Spring整合JMS(一)-基础篇

时间:2023-11-17 18:39:02

 1.基础知识

   Spring整合JMS(一)-基础篇

            图1   同步通信和异步通信通信过程示意图

  RMI使用的是同步通信,JMS使用的是异步通信。从图1可以看出异步通信的好处就是减少了不必要的等待,提高了效率。

  JMS中有两个主要的概念:消息代理(message broker)和目的地(destination)。

  消息代理指的概念:    发送者将消息发送到消息代理服务器,代理服务器收到消息后提示接收端去接收消息,消息代理就起了控制消息流转的作用,Apache 的activemq就是一种消息代理服务器。

  目的地指的概念:   消息发送的目标地址,也是消息接收者获取消息的目标地址,对应于queue和topic中的一种,并且要指定具体的名称。

  

  JMS通信又分为点对点和点对多2种形式。

  点对点通信形式如图12.3所示,采用javax.jms.Queue表示,点多多通信形式如图12.4所示,采用javax.jms.Topic表示。

  Spring整合JMS(一)-基础篇

  Spring整合JMS(一)-基础篇

Spring整合JMS(一)-基础篇

  同步通信的缺点,这也是使用JMS所能够解决的:

  Spring整合JMS(一)-基础篇    

2.Spring对JMS的支持

  为了消除重复冗余的JMS代码,如建立连接,异常处理等,我们应该使用Spring所提供的JmsTemplate来进行消息的发送与接收。

  和JDBCTemplate类似,JmsTemplate将捕获JMS所抛出的检查时异常,进行封装并以非检查时异常的形式进行抛出,我们就不必须对异常进行捕获。

  Spring整合JMS(一)-基础篇

3.示例代码

   JMS只是一种标准,Apache的activemq是其多种实现中的一种,下面将基于activemq来做示例。

   示例代码将分为发送端代码,接收端代码,XML配置和测试类4部分。

   首先要下载apache-activemq,运行apache-activemq-5.10.0-bin[1]\apache-activemq-5.10.0\bin\win32下面的activemq.bat启动JMS服务,确保已经正常启动,61616端口未被占用。

3.1 发送端代码

   发送消息的代码,注意要使用JmsTemplate:

@Component("producerServiceImpl")
public class ProducerServiceImpl implements ProducerService {
private JmsTemplate jmsTemplate;
public void sendMessage(Destination destination, final String message) {
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(message);
}
});
} public JmsTemplate getJmsTemplate() {
return jmsTemplate;
} @Resource
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
}

  Spring整合JMS(一)-基础篇

 3.2 接收端代码 

 Spring整合JMS(一)-基础篇

  使用EJB的消息驱动来处理消息的代码如下,这样onMessage方法不会阻塞,但是要绑定MessageListener接口:

  Spring整合JMS(一)-基础篇  

  使用Spring所支持JMS接收消息的配置如下,比使用JmsTemplate和集成MessageListener接口要好:

  Spring整合JMS(一)-基础篇

  需要在配置文件中做如下的配置:

 Spring整合JMS(一)-基础篇

    配置一个listener-container,将消息接收端的bean放在其中

 Spring整合JMS(一)-基础篇

3.3.XML配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd"> <context:component-scan base-package="com.tiantian" /> <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<property name="connectionFactory" ref="connectionFactory"/>
</bean> <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean> <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
</bean> <!--这个是队列目的地-->
<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>queue</value>
</constructor-arg>
</bean>
<!-- 消息监听器 -->
<bean id="consumerMessageListener" class="com.tiantian.springintejms.listener.ConsumerMessageListener"/>
<!-- 消息监听容器 -->
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="queueDestination" />
<property name="messageListener" ref="consumerMessageListener" />
</bean>
</beans>

3.4.测试类代码

  测试的代码如下所示:

import javax.jms.Destination;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.tiantian.springintejms.service.ProducerService; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")
public class ProducerConsumerTest { @Autowired
private ProducerService producerService;
@Autowired
@Qualifier("queueDestination")
private Destination destination; @Test
public void testSend() {
for (int i=0; i<2; i++) {
producerService.sendMessage(destination, "你好,生产者!这是消息:" + (i+1));
}
} }