Spring使用MappingJackson2MessageConverter發送接收ActiveMQ消息

1、Spring使用JmsTemplate簡化對JMS的訪問

在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

 

2、Spring的消息轉換器的種類

Spring自帶的消息轉換器能夠大大簡化消息的讀取以及寫入,全部的消息轉換器都位於org.springframework.jms.support.converter包中。tcp

消息轉換器 功能
MappingJacksonMessageConverter

使用Jackson JSON庫實現消息與JSON格式之間的相互轉換ide

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。

 

3、配置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 }

 

4、總結

MappingJackson2MessageConverter能夠頗有效的實現MQ的發送和接受序列化,不須要將POJO手動序列化,實現Serializable接口。基於JSON的解析也順應主流技術。由於踩了較多的坑,因此特意留此篇博客,若是不對的地方,還但願多多指出。有疑問歡迎留言,謝謝!
相關文章
相關標籤/搜索