標籤:gety 設定 obj 封裝 str factory ext ppi 讀取
一、Spring使用JmsTemplate簡化對JMS的訪問
在JAVA對JMS隊列訪問中,使用預設的JMS支援將存在大量的檢查型異常。通過Spring的支援,可以將所有的JMS的檢查型異常轉換為運行時非檢查異常。以及在Spring中,通過配置JMSConnectionFactory的DefaultDestinationName指定發送和接收目的地。
下面是ActiveMQ的串連factory配置:
1 @Bean2 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的配置:
1 @Bean2 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的也類似,可以自行搜尋。
上述欄位含義如下:
setDefaultDestinationName:設定ActiveMQ的隊列名稱,當然如果下面的pubSubDomain為true,則為主題名稱
setMessageConverter:設定ActiveMQ的訊息轉換器,預設不寫的話是使用的Spring的SimpleMessageConverter
setPubSubDomain:值true代表該Template為隊列,false為主題
2.Spring的訊息轉換器的種類
Spring內建的訊息轉換器可以大大簡化訊息的讀取以及寫入,所有的訊息轉換器都位於org.springframework.jms.support.converter包中。
訊息轉換器 |
功能 |
MappingJacksonMessageConverter |
使用Jackson JSON庫實現訊息與JSON格式之間的相互轉換 |
MappingJackson2MessageConverter |
使用Jackson 2 JSON庫實現訊息與JSON格式之間相互轉換 |
MarshallingMessageConverter |
使用JAXB庫實現訊息與XML格式之間的相互轉換 |
SimpleMessageConverter |
實現String與TextMessage之間的相互轉換,位元組數組與Bytes Message之間的相互轉換,Map與MapMessage之間的相互轉換 以及Serializable對象與ObjectMessage之間的相互轉換 |
預設情況下,JmsTemplate在convertAndSend()方法中會使用SimpleMessage Converter。但是通過將訊息轉換器聲明為bean並將其注入到JmsTemplate的messageConverter屬性中,我們可以重寫這種行為。例如,如果你想使用JSON訊息的話,那麼可以聲明一個MappingJackson2MessageConverter bean。
三、配置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 @Override40 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 @Configuration15 public class MQConfig {16 17 @Bean18 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 @Bean26 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 @Bean36 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的解析也順應主流技術。因為踩了較多的坑,所以特地留此篇部落格,如果不對的地方,還希望多多指出。
有疑問歡迎留言,謝謝!
Spring使用MappingJackson2MessageConverter發送接收ActiveMQ訊息