首先说一下什么是jms(java message service)java消息服务,Java消息服务指的是两个应用程序之间进行异步通信的API,它为标准消息协议和消息服务提供了一组通用接口,包括创建、发送、读取消息等,用于支持JAVA应用程序开发。在J2EE中,当两个应用程序使用JMS进行通信时,它们之间并不是直接相连的,而是通过一个共同的消息收发服务连接起来,可以达到解耦的效果,JMS天生就是异步的,客户端获取消息的时候,不需要主动发送请求,消息会自动发送给可用的客户端。(参考网上的)。
JMS对象模型有如下几种:
1. JMSConnectionFactory:JMS连接工厂,jms通过JDNI里面查找对应的连接工厂,然后通过连接工厂创建一个JMS连接。
2. JMS连接:很明显就是通过连接工厂创建的一个客户端和服务端的连接。
3. JMS会话:Session,表示连接客户端和服务器的回话连接,用该session可以创建不同的TextMessage类型,很重要,很重要,很重要。
4.JMS Destination: 也就说消息队列,准确的说应该是消息源。
5.JMS producer :消息的生产者,用来提供消息,这次的demo中我会使用JMSTemplate 模版来发送消息。
6. JMS consumer:消息的消费者,用来接收消息并消费消息,也是通过JMSTemplate receive()方法来接收消息。
JMS结构如下:
1. JMS provider:JMS提供者,例如(activeMQ,jbossMQ等)。
2. JMS客户:提供消息接收和发送的某一段程序,这个说起来有点抽象,就理解为一段代码就好了。
3. JMS 生产者,消费者,对应的就是消息的提供者和消息的使用者。
4. JMS消息队列:当然了包括了队列的基本性质,队头进入队尾取出,先进先出。
5. JMS Topic:就是消息的主题订阅,一次发布订阅,只要把连接对象设置为监听者,就能同时收到订阅消息。
6. JMS 消息对象:服务器和客户端进行传递的消息内容。
其中两种消息模型可用如下图表示(来自网络):
这幅图描述的是点对点的通信模型,主要有消息的发送者,消息队列,消息接收者,每个接收者只有一个消息队列,而且接收者和发送者之间没有绝对的时间依赖性,即使消息接收者不在运行,消息也能被收到,当接收者获得消息后,会再次发送一个消息确认通知给服务器。
图 1-1 点对点的通信队列模型
另一种则是消息的发布&订阅模型,是一种一对多的关系。通过系统中的主题topic来保存消息和传递消息,匿名用户也可用发送消息 ,发布者和订阅者有着很强的时间依赖性,只有当客户端订阅以后,并且在运行状态才可以接收到订阅信息,为了减少这种时间上的依赖性,JMS允许客户端创建一个可持久化的订阅,这样即使客户端没有激活(为运行)也可接收到订阅信息。
图 1-2 消息发布订阅模型
客户端在接收消息的时候有两种形式,一种是同步接收,另一种是异步接收,当订阅者使用receive方法接收,当消息未到达,该方法会阻塞,知道消息可用,另一种就是异步接收,客户端可创建一个消息监听器,当消息到达时,监听器会接收消息(方法为OnMessage()),并发送给订阅者。
测试部分结果如下:
测试topic:
请看代码:
1 pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>guo.mq.examples</groupId>
<artifactId>guo-mq02</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>guo-mq02</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.11.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
</dependencies>
</project>
2 spring配置文件
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.activemq.queue.*" annotation-config="true"/>
<!--连接工厂 创建连接-->
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<!--队列1-->
<bean id="queueDestination1" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>queue1</value>
</constructor-arg>
</bean>
<!--消息模版-->
<bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="queueDestination1"/>
<property name="receiveTimeout" value="10000"/>
</bean>
<!--queue消息 生产者 -->
<bean id="producerService" class="com.activemq.queue.ProduceServiceImpl">
<property name="jmsTemplate" ref="JmsTemplate"/>
</bean>
<!--queue消息 消费者 -->
<bean id="consumerService" class="com.activemq.queue.ConsumerServiceImpl">
<property name="jmsTemplate" ref="JmsTemplate"></property>
</bean>
<!--队列2-->
<bean id="queueDetination2" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>queue2</value>
</constructor-arg>
</bean>
<bean id="messageListener" class="com.activemq.queue.QueueMessageLIstener"></bean>
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="queueDetination2"/>
<property name="messageListener" ref="messageListener"/>
</bean>
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="topicDestionation"/>
</bean>
<bean id="topicJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="topicDestination"/>
<property name="pubSubDomain" value="true"/>
<property name="receiveTimeout" value="10000"/>
</bean>
<!--topic消息发布者 -->
<bean id="topicProvider" class="com.activemq.queue.TopicProvider">
<property name="topicJmstemplate" ref="topicJmsTemplate"></property>
</bean>
<!--topic消息监听者-->
<bean id="messageListener1" class="com.activemq.queue.TopicMessageListener"/>
<bean id="messageListener2" class="com.activemq.queue.TopicMessageListener2"/>
<!--topic消息监听容器-->
<bean id="topicJmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="topicDestination" />
<property name="messageListener" ref="messageListener1" />
</bean>
<!--topic消息监听容器-->
<bean id="topicJmsContainer2"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="topicDestination" />
<property name="messageListener" ref="messageListener2" />
</bean>
<!--session队列-->
<bean id="sessionAwateQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="sseionAwareDestinationQueue"/>
</bean>
<!--消费者会话监听器-->
<bean id="ConsumerSessionAwareListener" class="com.activemq.queue.ConsumerSessionAwareListener">
<property name="destination" ref="queueDestination1"/>
</bean>
<!--消息监听容器-->
<bean id="sessionAwareListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="sessionAwateQueue"/>
<property name="messageListener" ref="ConsumerSessionAwareListener"/>
</bean>
<bean id="adapterQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="adapterQueue"/>
</bean>
<!--消息监听适配器 自动回复消息-->
<bean id="jmsMessageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<property name="defaultListenerMethod" value="reveiverMessage"/>
<property name="delegate">
<bean class="com.activemq.queue.ConsumerListener"/>
</property>
</bean>
<!--消息是配置容器-->
<bean id="jmsMessageContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="destination" ref="adapterQueue"/>
<property name="connectionFactory" ref="connectionFactory"/>
<property name="messageListener" ref="jmsMessageListenerAdapter"/>
</bean>
</beans>
3 ConsumerListener:
@Component
public class ConsumerListener {
public String reveiverMessage(String message)
{
System.out.println("ConsumerListener接收到一个Text消息:\t" + message);
return "consumerListener 回复你了";
}
}
4 ConsumerServiceImpl:
@Component
public class ConsumerService {
private JmsTemplate jmsTemplate;
public void receive(Destination destination) throws JMSException {
TextMessage textMessage = (TextMessage) jmsTemplate.receive(destination);
System.out.println("ConsumerService从"+destination.toString()+"获取消息"+textMessage.getText());
}
}
5 ConsumerSessionAwareListener
@Component
public class ConsumerSessionAwareListener implements SessionAwareMessageListener<TextMessage> {
private Destination destination;
// session 可以用来回复消息
public void onMessage(TextMessage textMessage, Session session) throws JMSException {
System.out.println("ConsumerListner 收到消息" +textMessage.getText());
// 发送消息
MessageProducer producer = session.createProducer(destination);
TextMessage textMessage1 = session.createTextMessage("Consumer 收到消息后给你回复了一条");
producer.send(textMessage1);
}
public void setDestination(Destination destination) {
this.destination = destination;
}
}
6 ProduceServiceImpl
/**
1. Created by yangtianrui on 17/7/28.
*/
@Component
public class ProduceServiceImpl implements ProducerService {
private JmsTemplate jmsTemplate;
public void sendMessage(final String msg) {
final String destionation = jmsTemplate.getDefaultDestinationName();
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
System.out.println("ProducerService向队列" +destionation + "发送了消息:\t" + msg);
return session.createTextMessage(msg);
}
});
}
public void sendMessage(final Destination destination, final String msg) {
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
System.out.println("ProducerService向队列" +destination.toString() + "发送了消息:\t" + msg);
return session.createTextMessage(msg);
}
});
}
public void sendMessage(final Destination destination, final String msg, final Destination response) {
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
System.out.println("ProducerService向队列" + destination.toString() + "发送了消息:\t" + msg);
TextMessage textMessage = session.createTextMessage(msg);
textMessage.setJMSReplyTo(response);
return textMessage;
}
});
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
}
7 QueueMesageListener
@Component
public class QueueMessageLIstener implements MessageListener {
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("MessageListener监听器监听到了"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
9 TopicMessageListener
@Component
public class TopicMessageListener implements MessageListener{
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("TopicMessageListener收到了您发布的主题"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
10 TopicMessageListener2
@Component
public class TopicMessageListener2 implements MessageListener{
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("TopicMessageListener2收到了您发布的主题"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
11 TopicProvider
@Component
public class TopicProvider {
private JmsTemplate topicJmstemplate;
public void sendMessage(final Destination destination, final String msg)
{
topicJmstemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
System.out.println("ProcuderServiceTopic发布了主题"+destination.toString()+".........."+msg);
return session.createTextMessage(msg);
}
});
}
public void setTopicJmstemplate(JmsTemplate topicJmstemplate) {
this.topicJmstemplate = topicJmstemplate;
}
}
以下就是测试代码了:
import com.activemq.iqueue.ConsumerService;
import com.activemq.iqueue.ProducerService;
import com.activemq.queue.TopicMessageListener;
import com.activemq.queue.TopicMessageListener2;
import com.activemq.queue.TopicProvider;
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 javax.jms.Destination;
/**
* Created by yangtianrui on 17/7/28.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/spring-applicationcontext.xml")
public class SpringMq_Test {
@Autowired
private ConsumerService consumerService;
@Autowired
private ProducerService producerService;
@Autowired
private Destination queueDestination1;
@Autowired
private Destination queueDetination2;
@Autowired
private Destination topicDestination;
@Autowired
@Qualifier("topicProvider")
private TopicProvider topicProvide;
@Autowired
private TopicMessageListener topicMessageListener;
@Autowired
private TopicMessageListener2 topicMessageListener2;
@Autowired
private Destination sessionAwateQueue;
@Autowired
private Destination adapterQueue;
@Test
public void test_senMessage()
{
producerService.sendMessage("hello queue1");
}
@Test
public void testProduce() {
String msg = "Hello queue1 !";
producerService.sendMessage(msg);
}
@Test
public void test_receive()
{
consumerService.receive(queueDestination1);
}
@Test
public void test_topic()
{
topicProvide.sendMessage(topicDestination,"topic.......");
}
@Test
public void test_adapter()
{
//queueDestination1
producerService.sendMessage(adapterQueue,"通知队列1获取消息",queueDestination1);
consumerService.receive(queueDestination1);
}
@Test
public void test_session()
{
producerService.sendMessage(sessionAwateQueue,"请队列1队列接收消息");
consumerService.receive(queueDestination1);
}
}