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的解析也顺应主流技术。由于踩了较多的坑,因此特意留此篇博客,若是不对的地方,还但愿多多指出。有疑问欢迎留言,谢谢!
相关文章
相关标签/搜索