JmsTemplate发送消息

参考文章 https://www.cnblogs.com/java-synchronized/p/7750283.html

JmsTemplate提供了3组*3,共计9个发送用的方法。

发送的方法有3组:

基本的发送
转换并发送
转换、后处理再发送

必需的资源

javax.jms.ConnectionFactory

ConnectionFactory是客户端编程的开始,由它依次获取Connection、Session、Message、MessageProducer或MessageConsumer,从而做好了发送或接收的准备。

我们如何提供ConnectionFactory给JmsTemplate?凭借JmsTemplete提供的构造器或setter方法:

public JmsTemplate(ConnectionFactory connectionFactory)
public void setConnectionFactory(ConnectionFactory connectionFactory)

javax.jms.Destination

Destination是发送的目的地,或者接收的源。

我们如何提供Destination给JmsTemplate?

我们有两个机会做这件事,第一次是在初始化的时候提供一个默认的Destination,第二次是在发送的时候提供一个明确的Destination。相关的方法:

设置默认的Destination
public void setDefaultDestination(Destination destination)
将消息发送到指定的Destinatio
public void send(Destination destination, MessageCreator messageCreator)

以及MessageCreator接口用来提供创建消息的回调方法,后面再讲。

实际上,我们提供了上述的资源之后,我们就是做了这样的指令:让JmsTemplate连接到Destination,从我们提供的ConnectionFactory中获取连接资源。

DynamicDestinationResolver

JmsTemplate还提供了另一种获取Destination的方式:基于Destination解析器Destination类型Destination名字的获取。这里解析器默认为DynamicDestinationResolver

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");
        // 是否是发布订阅模式,决定了Destination类型是Topic还是Queue,默认为false
        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);
    }
}

你可以使用下面的代码来指定解析器、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提供了两个方法:

设置defaultDestination。这个方法和setDefaultDestination(Destination destination)做同样的事情,只是这个方法依赖于解析器和类型。
public void setDefaultDestinationName(String destinationName)
将消息发送到指定的Destination。这个方法和send(Destination destination, MessageCreator messageCreator)做同样的事情,只是这个方法依赖于解析器和类型
public void send(String destinationName, MessageCreator messageCreator)

如何根据destinationName创建Destination实例?
其实上面已经提到了,javax.jms.Session提供了两个方法,分别创建两种类型的Destination:

根据name创建Queue类型的Destination
Queue createQueue(java.lang.String queueName)
根据name创建Topic类型的Destination
Topic createTopic(java.lang.String topicName)

根据这份源码,可以帮助理解pubSubDomain的机制,以及将JMS的api和Spring的Destination解析器这两个知识点连接起来。

发送方法

使用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,它就会在合适的时候调用这个方法,并发送返回的消息。那么这个MessageCreator实例怎么来吗,我们可以自己简单实现,但通常使用JmsTemplate自带的匿名内部类实现,后面会有提到。

new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				return getRequiredMessageConverter().toMessage(message, session);
			}

1. 基本的发送方法

将消息发送到指定的Destination
public void send(Destination destination, MessageCreator messageCreator)
这个方法和上面做同样的事情,只是这个方法依赖于解析器和类型以解析Destination。
public void send(String destinationName, MessageCreator messageCreator)
将消息发送到defaultDestination。这个方法要求提前设置defaultDestination
public void send(MessageCreator messageCreator)

2. 转换并发送的方法

我们需要将数据装进JMS的Message,然后再发送。JMS的Message有5种具体的类型,不同的类型适合装载不同的数据。如果你不想做这段工作,而是希望能直接把数据丢给谁,然后由它来封装成Message,你只想准备数据,然后发送。那么接下来要介绍的方法,正适合你。

	public void convertAndSend(Destination destination, final Object message) throws JmsException {
		send(destination, new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				return getRequiredMessageConverter().toMessage(message, session);
			}
		});
	}

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 JmsTemplate() {
		initDefaultStrategies();
	}
	protected void initDefaultStrategies() {
		setMessageConverter(new SimpleMessageConverter());
	}

转换发送

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接口来创建消息。

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)

什么是消息 消息是一个用于在组件和应用程序之间通讯的的方法。消息之间的传递是点对点的。任何终端之间都可以相互接受和发送消息。并且每个终端都必须遵守如下的规则 -> 创建消息 -> 发送消息 -> 接收消息 -> 读取消息 为什么要使用消息 理由很简单,消息是一个分布式的低耦合通讯方案。A发送一个消息到一个agent ,B作为接受者去agent上获取消息。但是A,B不需要同时到agent上去注册。agent作为一个中转为A,B提供搞效率的通讯服务。 Java消息服务支持两种消息模型:Point-to-Point消息(P2P)和发布订阅消息(Publish Subscribe messaging,简称Pub/Sub)。JMS规范并不要求供应商同时支持这两种消息模型,但开发者应该熟悉这两种消息模型的优势与缺点。 企业消息产品(或者有时称为面向消息的中间件产品)正逐渐成为公司内操作集成的关 键组件。这些产品可以将分离的业务组件组合成一个可靠灵活的系统。 除了传统的 MOM 供应商,企业消息产品也可以由数据库供应商和许多与网络相关的公 司来提供。 Java 语言的客户端和 Java 语言的中间层服务必须能够使用这些消息系统。JMS 为 Java 语言程序提供了一个通用的方式来获取这些系统。 JMS 是一个接口和相关语义的集合,那些语义定义了 JMS 客户端如何获取企业消息产品 的功能。 由于消息是点对点的,所以 JMS 的所有用户都称为客户端(clients)。JMS 应用由定义 消息的应用和一系列与他们交互的客户端组成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值