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

背景:

原来我准备是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. Android Exception 14(Activity has been destroyed)

    java.lang.IllegalStateException: Activity has been destroyed at android.app.FragmentManagerImpl.enqu ...

  2. C++ 和 java 使用 AES CBC 128 加解密

    Java 使用jce, code: import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax ...

  3. 9、Linux驱动的杂项设备

    杂项设备,是字符设备中的特殊,它的主设备号,是 10,不同的杂项设备,通过次设备号进行区分. 1.注册与注销 int misc_register(struct miscdevice * misc) 完 ...

  4. 你要相信你所做的一切对一个更美好的世界 Do have faith in what you are doing All for a better world

    http://www.nowamagic.net/librarys/veda/detail/2502 Do have faith in what you are doing. 先不要往下看,试试品尝上 ...

  5. 【MyBatis学习04】mapper代理方法开发dao

    上一篇博文总结了mybatis使用 原始dao的方法存在的一些弊端,我们肯定不会去用它,那么mybatis中该如何开发dao呢?如题所述,这篇博文主要来总结一下使用mapper代理的方法来开发dao的 ...

  6. php对象序列化和cookie的问题,反序列化false

    php对象序列化和cookie的问题,反序列化false $searchKeywords = array("羊奶","肥皂"); $searchKeywords ...

  7. sql语句优化技巧

    1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  8. Swift 烧脑体操一

    Swift 烧脑体操(一) - Optional 的嵌套   前言 Swift 其实比 Objective-C 复杂很多,相对于出生于上世纪 80 年代的 Objective-C 来说,Swift 融 ...

  9. Ubuntu vsftp复制文件到远端时错误,Permission denied

    Ubuntu 下复制文件到远端时错误,Permission denied 失败原因如下: (1)vsftp默认配置不允许上传文件 解决办法:修改配置文件 vi /etc/vsftpd.conf. 将& ...

  10. Oracle基础学习登陆SQLPLUS(一)

    SQLPLUS是ORACLE公司开发的非常简洁的管理工具,SQLPLUS是最好的,最核心的ORACLE管理工具.SQLPLUS简洁而高效,舍弃浮华,反璞归真.使用sqlplus,进入sqlplus并进 ...