在JAVA對JMS隊列訪問中,使用默認的JMS支持將存在大量的檢查型異常。經過Spring的支持,能夠將全部的JMS的檢查型異常轉換爲運行時非檢查異常。以及在Spring中,經過配置JMSConnectionFactory的DefaultDestinationName指定發送和接收目的地。html
下面是ActiveMQ的鏈接factory配置:java
1 @Bean 2 public ActiveMQConnectionFactory getAMQFactory() { 3 ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory(); 4 mqConnectionFactory.setBrokerURL("tcp://59.110.231.87:61616"); 5 mqConnectionFactory.setTrustedPackages(Arrays.asList("com.edoctor.bean")); 6 return mqConnectionFactory; 7 }
下面是JmsTemplate的配置:spring
1 @Bean 2 public JmsTemplate getJmsTemplate(ActiveMQConnectionFactory cf, MessageConverter messageConverter) { 3 JmsTemplate jmsTemplate = new JmsTemplate(cf); 4 jmsTemplate.setDefaultDestinationName("com.demo.testActiveMQ"); 5 jmsTemplate.setMessageConverter(messageConverter); 6 // pubSubDomain = true 爲隊列模式,false爲訂閱發佈模式 7 jmsTemplate.setPubSubDomain(false); 8 return jmsTemplate; 9 }
我是使用純JAVA註解配置的Bean,基於xml的也相似,能夠自行搜索。apache
上述字段含義以下:json
setDefaultDestinationName:設置ActiveMQ的隊列名稱,固然若是下面的pubSubDomain爲true,則爲主題名稱api
setMessageConverter:設置ActiveMQ的消息轉換器,默認不寫的話是使用的Spring的SimpleMessageConverter數組
setPubSubDomain:值true表明該Template爲隊列,false爲主題app
Spring自帶的消息轉換器能夠大大簡化消息的讀取以及寫入,全部的消息轉換器都位於org.springframework.jms.support.converter包中。tcp
消息轉換器 | 功能 |
MappingJacksonMessageConverter | 使用Jackson JSON庫實現消息與JSON格式之間的相互轉換ide |
MappingJackson2MessageConverter | 使用Jackson 2 JSON庫實現消息與JSON格式之間相互轉換 |
MarshallingMessageConverter | 使用JAXB庫實現消息與XML格式之間的相互轉換 |
SimpleMessageConverter | 實現String與TextMessage之間的相互轉換,字節數組與Bytes |
默認狀況下,JmsTemplate在convertAndSend()方法中會使用SimpleMessage Converter。可是經過將消息轉換器聲明爲bean並將其注入到JmsTemplate的messageConverter屬性中,咱們能夠重寫這種行爲。例如,若是你想使用JSON消息的話,那麼能夠聲明一個MappingJackson2MessageConverter bean。
上文的JmsTemplate已經成功注入了ActiveMQConnectionFactory,下面就將注入咱們的MessageConverter。
因爲使用默認的SimpleMessageConverter若是是Object對象的話,必須將對象序列化,若是對象包含包裝類例如Integer將沒法實現序列化,所以,我打算使用基於json的MappingJackson2MessageConverter序列化對象發送以及接受,該配置會實現自動序列化。可是在網上查閱相關文檔,發現幾乎沒有中文介紹配置MappingJackson2MessageConverter的,所以,但願寫下這個配置幫助你們。
MappingJackson2MessageConverter在JavaDoc中的詳細配置:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/support/converter/MappingJackson2MessageConverter.html
對於文檔和介紹,上述連接有詳細說明,裏面主要提到一點:
意思是,若是須要在接受Object對象格式的消息的時候,須要配置這項屬性,以及這項屬性須要參考typeIdMappings。
咱們再看一下這個Map的說明:
這個Map以String爲key,Class爲值,而這裏的Key就是對應的typeId,Value就是你須要序列化的類。因此只須要構建這樣一個Map就能夠容許從MQ中接受類對象型的消息了。下面是個人POJO(注意該在MQ中發送接收的對象務必有無參構造函數)
1 public class TestJMS { 2 private String name; 3 private Integer age; 4 private String email; 5 6 public TestJMS() { 7 } 8 9 public TestJMS(String name, Integer age, String email) { 10 this.name = name; 11 this.age = age; 12 this.email = email; 13 } 14 15 public String getName() { 16 return name; 17 } 18 19 public void setName(String name) { 20 this.name = name; 21 } 22 23 public Integer getAge() { 24 return age; 25 } 26 27 public void setAge(Integer age) { 28 this.age = age; 29 } 30 31 public String getEmail() { 32 return email; 33 } 34 35 public void setEmail(String email) { 36 this.email = email; 37 } 38 39 @Override 40 public String toString() { 41 return "TestJMS{" + 42 "name='" + name + '\'' + 43 ", age=" + age + 44 ", email='" + email + '\'' + 45 '}'; 46 } 47 }
以及這是注入到JmsTemplate的MappingJackson2MessageConverter的Bean定義
1 @Bean 2 public MappingJackson2MessageConverter getJacksonMessageConverter() { 3 MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 4 converter.setTargetType(MessageType.TEXT); 5 // 定義了typeId到Class的Map 6 Map<String, Class<?>> typeIdMap = new HashMap<>(); 7 typeIdMap.put("TestJMS", TestJMS.class); 8 converter.setTypeIdMappings(typeIdMap); 9 // 設置發送到隊列中的typeId的名稱 10 converter.setTypeIdPropertyName("TestJMS"); 11 converter.setEncoding("UTF-8"); 12 return converter; 13 }
經過這樣的注入,實現了Class Object格式無須序列化的對象發送與接受
完整的ActiveMQ基於JAVA註解的配置代碼以下:
1 import com.test.bean.TestJMS; 2 import org.apache.activemq.ActiveMQConnectionFactory; 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.context.annotation.Configuration; 5 import org.springframework.jms.core.JmsTemplate; 6 import org.springframework.jms.support.converter.MappingJackson2MessageConverter; 7 import org.springframework.jms.support.converter.MessageConverter; 8 import org.springframework.jms.support.converter.MessageType; 9 10 import java.util.Arrays; 11 import java.util.HashMap; 12 import java.util.Map; 13 14 @Configuration 15 public class MQConfig { 16 17 @Bean 18 public ActiveMQConnectionFactory getAMQFactory() { 19 ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory(); 20 mqConnectionFactory.setBrokerURL("tcp://59.110.231.87:61616"); 21 mqConnectionFactory.setTrustedPackages(Arrays.asList("com.edoctor.bean")); 22 return mqConnectionFactory; 23 } 24 25 @Bean 26 public JmsTemplate getJmsTemplate(ActiveMQConnectionFactory cf, MessageConverter messageConverter) { 27 JmsTemplate jmsTemplate = new JmsTemplate(cf); 28 jmsTemplate.setDefaultDestinationName("EDoctor.JMSTemplate.queue2"); 29 jmsTemplate.setMessageConverter(messageConverter); 30 // pubSubDomain = true 爲隊列模式,false爲訂閱發佈模式 31 jmsTemplate.setPubSubDomain(false); 32 return jmsTemplate; 33 } 34 35 @Bean 36 public MappingJackson2MessageConverter getJacksonMessageConverter() { 37 MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 38 converter.setTargetType(MessageType.TEXT); 39 Map<String, Class<?>> typeIdMap = new HashMap<>(); 40 typeIdMap.put("TestJMS", TestJMS.class); 41 converter.setTypeIdMappings(typeIdMap); 42 converter.setTypeIdPropertyName("TestJMS"); 43 converter.setEncoding("UTF-8"); 44 return converter; 45 } 46 47 }
MappingJackson2MessageConverter能夠頗有效的實現MQ的發送和接受序列化,不須要將POJO手動序列化,實現Serializable接口。基於JSON的解析也順應主流技術。由於踩了較多的坑,因此特意留此篇博客,若是不對的地方,還但願多多指出。有疑問歡迎留言,謝謝!