---恢复内容开始---

背景:

原来我准备是setDefaultDestinationName 设置队列的名称 发现 系统运行后  创建 的并不是队列 ,而是Topic  ,

自己看下源码,发现在创建时候,需要观察session的类型

JmsTemplate提供了3组*3,共计9个发送用的方法。
 
发送的方法有3组:
  1. 基本的发送
  2. 转换并发送
  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.

---恢复内容结束---

JmsTemplate 发送方式的更多相关文章

  1. spring-jms,spring-boot-starter-activemq JmsTemplate 发送方式

    spring-jms,spring-boot-starter-activemq JmsTemplate 发送方式 背景: 原来我准备是setDefaultDestinationName 设置队列的名称 ...

  2. HTML中发送方式(method)中get和post的比较

    get的方式是将表单控件的控件名name和取值value信息经过编码后,通过URL发送(可以在地址栏里看到).而post则将表单的内容通过http发送.一个 get通过URL传送变量,能传送的数据总量 ...

  3. post 发送方式

    /** * post 方式 解码 */ public static String getWebContentByPost(String urlString, String data, final St ...

  4. android handler ,message消息发送方式

    1.Message msg =  Message.obtain(mainHandler) msg.obj=obj;//添加你需要附加上去的内容 msg.what = what;//what消息处理的类 ...

  5. python实现邮件发送完整代码(带附件发送方式)

    实例一:利用SMTP与EMAIL实现邮件发送,带附件(完整代码) __author__ = 'Administrator'#coding=gb2312 from email.Header import ...

  6. Android为TV端助力 handler ,message消息发送方式

    1.Message msg =  Message.obtain(mainHandler) msg.obj=obj;//添加你需要附加上去的内容 msg.what = what;//what消息处理的类 ...

  7. activemq jmsTemplate 发送消息速度太慢

    http://activemq.apache.org/async-sends.html http://bbs.csdn.net/topics/370062485

  8. ActiveMQ学习总结(10)——ActiveMQ采用Spring注解方式发送和监听

    对于ActiveMQ消息的发送,原声的api操作繁琐,而且如果不进行二次封装,打开关闭会话以及各种创建操作也是够够的了.那么,Spring提供了一个很方便的去收发消息的框架,spring jms.整合 ...

  9. PHP通过XML报文格式的POST请求方式,与第三方接口交互(发送xml,获取XML,并解析xml步骤)

    开发者端:发送请求,并接收结果 <?php // 下面的demo,实现的功能如下: // 1-开发者需要判断一个用户是否存在,去请求第三方接口. // 2-与第三方接口的通信,是以xml格式传送 ...

随机推荐

  1. python exec和eval

    exec语句用来执行储存在字符串或文件中的Python语句.例如,我们可以在运行时生成一个包含Python代码的字符串,然后使用exec语句执行这些语句.下面是一个简单的例子. >>> ...

  2. Android-RelativeLayout布局技巧(一)

    如果有一个需求是这样的,在标题中的右上角有一个button <?xml version="1.0" encoding="utf-8"?> <L ...

  3. linux socket读数据错误解释

    EINTR 表示某种阻塞的操作,被接收到的信号中断,造成的一种错误返回值. EAGAIN   从字面上来看,是提示再试一次.这个错误经常出现在当应用程序进行一些非阻塞(non-blocking)操作( ...

  4. Oracle undo 表空间管理 (摘DAVID)

    Oracle 的Undo有两种方式: 一是使用undo 表空间,二是使用回滚段. 我们通过 undo_management 参数来控制使用哪种方式,如果设为auto,就使用UNDO 表空间,这时必须要 ...

  5. php中的可变变量、可变函数、匿名函数

    1.可变变量 简而言之:获取一个普通变量的值作为这个可变变量的变量名. 如: $a = "hello"; $$a = " world"; /* $a 的值为&q ...

  6. C语言学习笔记(五) 数组

    数组 数组的出现就是为了解决大量同类型数据的存储和使用的问题: 数组的分类:一维数组.二维数组. 一维数组:为多个变量连续分配存储控件:所有的变量的数据类型必须相同:所有变量所占的字节大小必须相等: ...

  7. Service(1)

    服务是一个应用组件,能够在后运行耗时的操作,不提供一个用户界面.(由于不提供界面,所以能够耗时运行,和活动最大的不同).还有一个应用组件能够启动一个服务,服务会继续在后台运行及时用户切换到还有一个应用 ...

  8. cadence原理图和PCB互联显示成功但是不能高亮和database

    问题现象:cadence原理图和PCB互联显示成功但是不能高亮我的问题 解决:尝试修复数据库试试,Tools->Database check 提醒:有一个封装非法命名,在原理图中修改后 再次保存 ...

  9. Sql语句查询XML - 小结

    --两种方式查询 DECLARE @varXML XML, @varXML1 XML --.xml数据源为属性方式 SET @varXML = '<PARAM> <Row FID = ...

  10. 手把手教你用git和SourceTree上传项目到github细解(转)

    尊重原创:https://blog.csdn.net/qq_32365567/article/details/52859166 一.引言 我想大家现在都很熟悉github了,也能运用github上开源 ...