黄沙百战穿金甲,不破楼兰终不还。这篇文章主要讲述Spring使用MappingJackson2MessageConverter发送接收ActiveMQ消息相关的知识,希望能为你提供帮助。
一、Spring使用JmsTemplate简化对JMS的访问在java对JMS队列访问中,使用默认的JMS支持将存在大量的检查型异常。通过Spring的支持,可以将所有的JMS的检查型异常转换为运行时非检查异常。以及在Spring中,通过配置JMSConnectionFactory的DefaultDestinationName指定发送和接收目的地。
下面是ActiveMQ的连接factory配置:
1@Bean 2public ActiveMQConnectionFactory getAMQFactory() { 3ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory(); 4mqConnectionFactory.setBrokerURL("tcp://59.110.231.87:61616"); 5mqConnectionFactory.setTrustedPackages(Arrays.asList("com.edoctor.bean")); 6return mqConnectionFactory; 7}
下面是JmsTemplate的配置:
1@Bean 2public JmsTemplate getJmsTemplate(ActiveMQConnectionFactory cf, MessageConverter messageConverter) { 3JmsTemplate jmsTemplate = new JmsTemplate(cf); 4jmsTemplate.setDefaultDestinationName("com.demo.testActiveMQ"); 5jmsTemplate.setMessageConverter(messageConverter); 6// pubSubDomain = true 为队列模式,false为订阅发布模式 7jmsTemplate.setPubSubDomain(false); 8return jmsTemplate; 9}
我是使用纯JAVA注解配置的Bean,基于xml的也类似,可以自行搜索。
上述字段含义如下:
setDefaultDestinationName:设置ActiveMQ的队列名称,当然如果下面的pubSubDomain为true,则为主题名称
setMessageConverter:设置ActiveMQ的消息转换器,默认不写的话是使用的Spring的SimpleMessageConverter
setPubSubDomain:值true代表该Template为队列,false为主题
二、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之间的相互转换 |
三、配置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 { 2private String name; 3private Integer age; 4private String email; 5 6public TestJMS() { 7} 8 9public TestJMS(String name, Integer age, String email) { 10this.name = name; 11this.age = age; 12this.email = email; 13} 14 15public String getName() { 16return name; 17} 18 19public void setName(String name) { 20this.name = name; 21} 22 23public Integer getAge() { 24return age; 25} 26 27public void setAge(Integer age) { 28this.age = age; 29} 30 31public String getEmail() { 32return email; 33} 34 35public void setEmail(String email) { 36this.email = email; 37} 38 39@Override 40public String toString() { 41return "TestJMS{" + 42"name=\'" + name + \'\\\'\' + 43", age=" + age + 44", email=\'" + email + \'\\\'\' + 45\'}\'; 46} 47 }
以及这是注入到JmsTemplate的MappingJackson2MessageConverter的Bean定义
1@Bean 2public MappingJackson2MessageConverter getJacksonMessageConverter() { 3MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 4converter.setTargetType(MessageType.TEXT); 5// 定义了typeId到Class的Map 6Map< String, Class< ?> > typeIdMap = new HashMap< > (); 7typeIdMap.put("TestJMS", TestJMS.class); 8converter.setTypeIdMappings(typeIdMap); 9// 设置发送到队列中的typeId的名称 10converter.setTypeIdPropertyName("TestJMS"); 11converter.setEncoding("UTF-8"); 12return converter; 13}
通过这样的注入,实现了Class Object格式无须序列化的对象发送与接受
【Spring使用MappingJackson2MessageConverter发送接收ActiveMQ消息】完整的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 18public ActiveMQConnectionFactory getAMQFactory() { 19ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory(); 20mqConnectionFactory.setBrokerURL("tcp://59.110.231.87:61616"); 21mqConnectionFactory.setTrustedPackages(Arrays.asList("com.edoctor.bean")); 22return mqConnectionFactory; 23} 24 25@Bean 26public JmsTemplate getJmsTemplate(ActiveMQConnectionFactory cf, MessageConverter messageConverter) { 27JmsTemplate jmsTemplate = new JmsTemplate(cf); 28jmsTemplate.setDefaultDestinationName("EDoctor.JMSTemplate.queue2"); 29jmsTemplate.setMessageConverter(messageConverter); 30// pubSubDomain = true 为队列模式,false为订阅发布模式 31jmsTemplate.setPubSubDomain(false); 32return jmsTemplate; 33} 34 35@Bean 36public MappingJackson2MessageConverter getJacksonMessageConverter() { 37MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 38converter.setTargetType(MessageType.TEXT); 39Map< String, Class< ?> > typeIdMap = new HashMap< > (); 40typeIdMap.put("TestJMS", TestJMS.class); 41converter.setTypeIdMappings(typeIdMap); 42converter.setTypeIdPropertyName("TestJMS"); 43converter.setEncoding("UTF-8"); 44return converter; 45} 46 47 }
四、总结
MappingJackson2MessageConverter可以很有效的实现MQ的发送和接受序列化,不需要将POJO手动序列化,实现Serializable接口。基于JSON的解析也顺应主流技术。因为踩了较多的坑,所以特地留此篇博客,如果不对的地方,还希望多多指出。
有疑问欢迎留言,谢谢!
推荐阅读
- Qt for Android 启动短暂的黑屏或白屏问题如何解决()
- pycharm运行Django发生AppRegistryNotReady: Apps aren't loaded yet.
- Lintcode364 Trapping Rain Water II solution 题解
- Android TextView数字增长动画效果
- 安卓的权限大全和动态使用安卓权限
- android——No matching client found for package错误处理
- android——Installation error: INSTALL_FAILED_CONFLICTING_PROVIDER 解决方案
- Android Surfaceflinger服务 ----- BufferQueue分析
- Spring中JdbcTemplate中使用RowMapper