spring-jms,spring-boot-starter-activemq JmsTemplate 发送方式
spring-jms,spring-boot-starter-activemq JmsTemplate 发送方式
背景:
原来我准备是setDefaultDestinationName 设置队列的名称 发现 系统运行后 创建 的并不是队列 ,而是Topic ,
自己看下源码,发现在创建时候,需要观察session的类型
JmsTemplate提供了3组*3,共计9个发送用的方法。
发送的方法有3组:
基本的发送
转换并发送
转换、后处理再发送
必需的资源
必需的资源有:
javax.jms.ConnectionFactory
ConnectionFactory是客户端编程的开始,由它依次获取Connection、Session、Message、MessageProducer或MessageConsumer,从而做好了发送或接收的准备。
javax.jms.Destination
Destination是发送的目的地,或者接收的源
实际上,我们提供了上述的资源之后,我们就是做了这样的指令:让JmsTemplate连接到Destination,从我们提供的ConnectionFactory中获取连接资源。
P.S.如果你不了客户端编程模型,建议参考02. JMS客户端编程模型。
1.ConnectionFactory资源
我们如何提供ConnectionFactory给JmsTemplate?凭借JmsTemplete提供的构造器或setter方法:
public JmsTemplate(ConnectionFactory connectionFactory)
public void setConnectionFactory(ConnectionFactory connectionFactory)
继承自org.springframework.jms.support.JmsAccessor
2.Destination资源
我们如何提供Destination给JmsTemplate?
我们有两个机会做这件事,第一次是在初始化的时候提供一个默认的Destination,第二次是在发送的时候提供一个明确的Destination。相关的方法:
public void setDefaultDestination(Destination destination)
设置默认的Destination
public void send(Destination destination, MessageCreator messageCreator)
将消息发送到指定的Destination
MessageCreator接口用来提供创建消息的回调方法,后面再讲。
JmsTemplate还提供了另一种获取Destination的方式:基于Destination解析器、Destination类型、Destination名字的获取。你可以使用下面的代码来指定解析器、Destination类型:
1 // jt is instance of JmsTemplate
2 jt.setDestinationResolver(new DynamicDestinationResolver()); // set Destination解析器
3 jt.setPubSubDomain(false); // set Destinantion类型
Destination解析器要实现org.springframework.jms.support.destination.DestinationResolver接口。解析器有默认的值,就是DynamicDestinationResolver,除非你要使用其他的解析器,否则不必调用setDestinationResolver。所以,第2行代码是多余的。
Destination类型有2个:false-Queue类型,true-Topic类型;默认为false。所以,第3行代码是多余的。
设置了解析器、类型,或者直接使用默认的值,之后,就可以设置destination的name。JmsTemplate提供了两个方法:
public void setDefaultDestinationName(String destinationName)
设置defaultDestination。这个方法和setDefaultDestination(Destination destination)做同样的事情,只是这个方法依赖于解析器和类型。
public void send(String destinationName, MessageCreator messageCreator)
将消息发送到指定的Destination。这个方法和send(Destination destination, MessageCreator messageCreator)做同样的事情,只是这个方法依赖于解析器和类型。
P.S.如何根据destinationName创建Destination实例?
javax.jms.Session提供了两个方法,分别创建两种类型的Destination:
Queue createQueue(java.lang.String queueName)
根据name创建Queue类型的Destination
Topic createTopic(java.lang.String topicName)
根据name创建Topic类型的Destination
复制代码
public class DynamicDestinationResolver implements DestinationResolver {
@Override
public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain)
throws JMSException {
Assert.notNull(session, "Session must not be null");
Assert.notNull(destinationName, "Destination name must not be null");
if (pubSubDomain) {
return resolveTopic(session, destinationName);
}
else {
return resolveQueue(session, destinationName);
}
}
protected Topic resolveTopic(Session session, String topicName) throws JMSException {
return session.createTopic(topicName);
}
protected Queue resolveQueue(Session session, String queueName) throws JMSException {
return session.createQueue(queueName);
}
}
复制代码
根据这份源码,可以帮助理解pubSubDomain的机制,以及将JMS的api和Spring的Destination解析器这两个知识点连接起来。
1.基本的发送方法
在前文我们已经接触了两个,它们都是在发送的同时指定Destination。现把它们和第3种一起介绍:
public void send(Destination destination, MessageCreator messageCreator)
将消息发送到指定的Destination
public void send(String destinationName, MessageCreator messageCreator)
将消息发送到指定的Destination。这个方法和send(Destination destination, MessageCreator messageCreator)做同样的事情,只是这个方法依赖于解析器和类型。
public void send(MessageCreator messageCreator)
将消息发送到defaultDestination。
这个方法要求提前设置defaultDestination,你可以调用setDefaultDestination(Destination destination)或者setDefaultDestinationName(String destinationName)来满足这个前提。
在3个基本的发送方法中,都使用MessageCreator来创建消息。
使用MessageCreator创建消息
jms中的Message,是以接口javax.jms.Message为首的接口家族,这个家族的图谱是这样的:
javax.jms.Message
|---- BytesMessage
|---- MapMessage
|---- ObjectMessage
|---- StreamMessage
|---- TextMessage
JMS将Message细分为5种类型,并在javax.jms.Session接口中分别定义了创建上述Message的多个方法,通常以create*Message为名,返回对应的Message类型。
在JMS的api中,只有javax.jms.Session能创建消息。
所以在Spring中,如果我们要创建Message,就要有Session。但是我们只有现成的ConnectionFactory,我们不应该走一遍从ConnectionFactory到Session的路,否则我们也不需要JmsTemplate帮我们发送了,因为剩下的工作也没多少了——关键是我们并没有从JMS的API中解脱出来。
所以有了MessageCreator的接口,它定义了一个回调的方法:
Message createMessage(Session session)
只要我们把MessageCreator的实例传给JmsTemplate,它就会在合适的时候调用这个方法,并发送返回的消息。
下面给一个例子:
复制代码
复制代码
1 jt.send(DESTINATION_NAME, new MessageCreator() {
2
3 public Message createMessage(Session session) throws JMSException {
4 String text = "A test for MessageCreator.";
5 Message message = session.createTextMessage(text);
6 return message;
7 }
8 });
复制代码
复制代码
2.转换并发送的方法
我们需要将数据装进JMS的Message,然后再发送。JMS的Message有5种具体的类型,不同的类型适合装载不同的数据。如果你不想做这段工作,而是希望能直接把数据丢给谁,然后由它来封装成Message——你只想准备数据,然后发送。那么接下来要介绍的方法,正适合你。
Spring为转换定义了一个接口:org.springframework.jms.support.converter.MessageConverter,这个接口定义了下面的两个方法:
Message toMessage(Object object, Session session)
发送时用到
Object fromMessage(Message message)
接收时用到
一般情况下,我们既不需要为MessageConverter提供实现,也不需要面向MessageConverter进行编程,所以我们实在没有必要关注上面的两个方法,扫一眼,有个大概的印象就够了。
说回JmsTemplate,它定义了下面的方法来设置Converter:
public void setMessageConverter(MessageConverter messageConverter)
而且在初始化的时候,会自动赋值一个SimpleMessageConverter类型的实例,所以我们甚至也不需要关心setMessageConverter方法了。
说了这不多,总结一下,如果要用到转换,我们需要多做什么工作?答案是不需要!
下面是具有转换功能的发送的方法,与基本的发送的方法进行对比:
转换发送 基本发送
public void convertAndSend(Destination destination, Object message)
将message转换成JMS的Message,并发送到指定的Destination
public void convertAndSend(String destinationName, Object message)
将message转换成JMS的Message,并发送到指定的Destination。
public void convertAndSend(Object message)
将message转换成JMS的Message,并发送到defaultDestination。
public void send(Destination destination, MessageCreator messageCreator)
将消息发送到指定的Destination
public void send(String destinationName, MessageCreator messageCreator)
将消息发送到指定的Destination。
public void send(MessageCreator messageCreator)
将消息发送到defaultDestination。
这两个系列的方法相似度很高,只是在创建消息的问题上有不同的处理:转换发送隐藏了消息的创建,基本发送需要实现MessageCreator接口来创建消息。
接下来是一个demo,我们将上面的demo也拿下来,做一个对比:
转换发送
1 String message = "a message for test convertAndSend.";
2 jt.convertAndSend(DESTINATION_NAME, message);
基本发送
复制代码
复制代码
1 jt.send(DESTINATION_NAME, new MessageCreator() {
2
3 public Message createMessage(Session session) throws JMSException {
4 String text = "A test for MessageCreator.";
5 Message message = session.createTextMessage(text);
6 return message;
7 }
8 });
复制代码
复制代码
2比8,这纯粹是数学问题了。
3.转换、后处理再发送的方法
javax.jms.Message定义了很多的方法用来为消息添加头部信息或属性。但是如果我们要用转换并发送的方法,我们就接触不到Message类型的消息了,自然也无法为其添加任何信息。JmsTemplate提供了另一套发送的方法,允许我们使用自动转换,还允许我们能接触到转换后的消息,以便我们能做些什么。之后我们会返回处理后的Message,交给JmsTemplate发送。
Spring定义了org.springframework.jms.core.MessagePostProcessor接口来做后处理的事,它定义了一个唯一的方法:
Message postProcessMessage(Message message)
对消息进行处理,并返回处理后的消息
让我们来看看这些方法,并与前文介绍的方法对比:
转换、后处理、发送 转换、发送
public void convertAndSend(Destination destination, Object message, MessagePostProcessor postProcessor)
public void convertAndSend(String destinationName, Object message, MessagePostProcessor postProcessor)
public void convertAndSend(Object message, MessagePostProcessor postProcessor)
public void convertAndSend(Destination destination, Object message)
将message转换成JMS的Message,并发送到指定的Destination
public void convertAndSend(String destinationName, Object message)
将message转换成JMS的Message,并发送到指定的Destination。
public void convertAndSend(Object message)
将message转换成JMS的Message,并发送到defaultDestination。
再来看看两个demo的对比:
转换、后处理、发送
复制代码
复制代码
1 String message = "a message for test convertProcessAndSend.";
2 jt.convertAndSend(DESTINATION_NAME, message,
3 new MessagePostProcessor() {
4 public Message postProcessMessage(Message message)
5 throws JMSException {
6 message.setIntProperty("order", 1);
7 return message;
8 }
9 });
复制代码
复制代码
转换、发送
1 String message = "a message for test convertAndSend.";
2 jt.convertAndSend(DESTINATION_NAME, message);
在转换、后处理、发送中,我们为Message设置了一个属性:order=1.
梦想一定要有,万一实现了!
spring-jms,spring-boot-starter-activemq JmsTemplate 发送方式的更多相关文章
- JmsTemplate 发送方式
---恢复内容开始--- 背景: 原来我准备是setDefaultDestinationName 设置队列的名称 发现 系统运行后 创建 的并不是队列 ,而是Topic , 自己看下源码,发现在创 ...
- activemq jmsTemplate 发送消息速度太慢
http://activemq.apache.org/async-sends.html http://bbs.csdn.net/topics/370062485
- Spring Boot (一): Spring Boot starter自定义
前些日子在公司接触了spring boot和spring cloud,有感于其大大简化了spring的配置过程,十分方便使用者快速构建项目,而且拥有丰富的starter供开发者使用.但是由于其自动化配 ...
- 使用Spring JMS轻松实现异步消息传递
异步进程通信是面向服务架构(SOA)一个重要的组成部分,因为企业里很多系统通信,特别是与外部组织间的通信,实质上都是异步的.Java消息服务(JMS)是用于编写使用异步消息传递的JEE应用程序的API ...
- 【ActiveMQ】Spring Jms集成ActiveMQ学习记录
Spring Jms集成ActiveMQ学习记录. 引入依赖包 无论生产者还是消费者均引入这些包: <properties> <spring.version>3.0.5.REL ...
- spring boot整合activemq消息中间件
spring boot整合activemq消息中间件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi ...
- ActiveMQ学习笔记(5)——使用Spring JMS收发消息
摘要 ActiveMQ学习笔记(四)http://my.oschina.net/xiaoxishan/blog/380446 中记录了如何使用原生的方式从ActiveMQ中收发消息.可以看出,每次 ...
- Spring JMS ActiveMQ整合(转)
转载自:http://my.oschina.net/xiaoxishan/blog/381209#comment-list ActiveMQ学习笔记(四)http://my.oschina.net/x ...
- ActiveMQ第二弹:使用Spring JMS与ActiveMQ通讯
本文章的完整代码可从我的github中下载:https://github.com/huangbowen521/SpringJMSSample.git 上一篇文章中介绍了如何安装和运行ActiveMQ. ...
随机推荐
- 鼠标右键点击弹出菜单(jQuery)
禁用浏览器默认事件,此处是兼容写法 $(document).contextmenu(function (e) { var event = e || window.event; if (event.pr ...
- django 使用mysql数据库
一 修改settings里面的配置文件 import pymysql # 一定要添加这两行!通过pip install pymysql! 或者pycharm 里面安装 pymysql.install_ ...
- 币种大写算法(js)
注意事项:小数精度处理问题,n*10出现精度误差,如1.88*10计算得18.799999999999997,实际想要的数据是18.8: 思路一:小数变成整数(通过字符串处理),计算后,变成小数: 思 ...
- NORDIC 修改MTU
https://www.cnblogs.com/jiangjiu/p/10063556.html 注意要修改RAM起始地址,因为MTU增大了
- 4.java JMS技术
1.什么是JMS JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间, 或分布式系统中发 ...
- 2.java多线程_synchronized(Lock)同步
1.synchronized同步关键词 线程安全是并发编程中的重要关注点,应该注意到的是,造成线程安全问题的主要诱因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同 操作共享数据.因此为 ...
- 1.Lucene简介
1.Lucene简介 Lucene是一个基于Java的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能 Lucene是开源项目,它是可扩展,高性能的库用于索引和搜 ...
- Tomcat 启动卡在 Root WebApplicationContext: initialization completed in
tomcat 启动一直卡在 Root WebApplicationContext: initialization completed in 重启了很多次,更换jdk版本,tomcat版本都不行. to ...
- Mysql索引类型分析
一.简介 MySQL目前主要有以下几种索引类型: 1.普通索引 2.唯一索引 3.主键索引 4.组合索引 5.全文索引 二.语句 CREATE TABLE table_na ...
- git撤销pull命令
1.运行git reflog命令查看你的历史变更记录 2.然后用git reset --hard HEAD@{n},(n是你要回退到的引用位置)回退. 比如上图可运行 git reset --hard ...