JMS 消息服务
JMS(Java Messaging Service)是 Java 平台上有关面向消息中间件的技术规范,它便于消息系统中的Java 应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发。
JMS 定义了五种不同的消息正文格式,以及调用的消息类型,允许你发送并接收以一些不同形式的数据,提供现有消息格式的一些级别的兼容性。
· TextMessage–一个字符串对象
· MapMessage–一套名称-值对
· ObjectMessage–一个序列化的 Java 对象
· BytesMessage–一个字节的数据流
· StreamMessage – Java 原始值的数据流
消息中间件介绍
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题实现高性能,高可用,可伸缩和最终一致性[架构] 使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ
ActiveMQ:ActiveMQ 是 Apache 出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持 JMS1.1 和J2EE 1.4 规范的 JMS Provider 实现。我们在本次课程中介绍 ActiveMQ 的使用。
ActiveMQ的下载安装启动:
下载地址:https://activemq.apache.org/components/classic/download/
安装方式:直接解压即可
启动方式:找到D:\AcitveMQ\apache-activemq-5.15.9\bin\win64下的activemq.bat双击即可
方式一:JAVA原始方式
1.创建普通Maven(不选择骨架)工程,导入坐标
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.13.4</version>
</dependency>
</dependencies>
2.完整工程目录
3.点对点模式消息生产者QueueProducer.java
package com.demo;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class QueueProducer {
public static void main(String[] args) throws Exception {
//创建连接工厂
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.25.135:61616");
//获取连接
Connection connection = factory.createConnection();
//启动连接
connection.start();
/**
* 创建session(1.是否启动事务 2.消息确认模式
* AUTO_ACKNOWLEDGE = 1 自动确认
* CLIENT_ACKNOWLEDGE = 2 客户端手动确认
* DUPS_OK_ACKNOWLEDGE = 3 自动批量确认
* SESSION_TRANSACTED = 0 事务提交并确认
*/
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建队列对象
Queue queue = session.createQueue("queue");
//创建消息生产者
MessageProducer producer = session.createProducer(queue);
//创建消息
TextMessage textMessage = session.createTextMessage("欢迎来到德莱联盟");
//发送消息
producer.send(textMessage);
//关闭资源
producer.close();
session.close();
connection.close();
}
}
4.点对点模式消息消费者QueueConsumer.java
package com.demo;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class QueueConsumer {
public static void main(String[] args) throws Exception {
//创建连接工厂
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.25.135:61616");
//获取连接
Connection connection = factory.createConnection();
//启动连接
connection.start();
/**
* 创建session(1.是否启动事务 2.消息确认模式
* AUTO_ACKNOWLEDGE = 1 自动确认
* CLIENT_ACKNOWLEDGE = 2 客户端手动确认
* DUPS_OK_ACKNOWLEDGE = 3 自动批量确认
* SESSION_TRANSACTED = 0 事务提交并确认
*/
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建队列对象
Queue queue = session.createQueue("queue");
//创建消息消费者
MessageConsumer consumer = session.createConsumer(queue);
//手动获取消息
// TextMessage receive = (TextMessage) consumer.receive();
// System.out.println(receive.getText());
//监听获取消息
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
//等待键盘输入
System.in.read();
//关闭资源
consumer.close();
session.close();
connection.close();
}
}
5.发布/订阅模式消息生产者TopicProducer.java
package com.demo;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class TopicProducer {
public static void main(String[] args) throws Exception {
//创建连接工厂
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.25.135:61616");
//获取连接
Connection connection = factory.createConnection();
//启动连接
connection.start();
/**
* 创建session(1.是否启动事务 2.消息确认模式
* AUTO_ACKNOWLEDGE = 1 自动确认
* CLIENT_ACKNOWLEDGE = 2 客户端手动确认
* DUPS_OK_ACKNOWLEDGE = 3 自动批量确认
* SESSION_TRANSACTED = 0 事务提交并确认
*/
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建队列对象
Topic topic = session.createTopic("topic");
//创建消息生产者
MessageProducer producer = session.createProducer(topic);
//创建消息
TextMessage textMessage = session.createTextMessage("欢迎来到德莱联盟topic");
//发送消息
producer.send(textMessage);
//关闭资源
producer.close();
session.close();
connection.close();
}
}
6.发布/订阅模式消息消费者TopicProducer.java
package com.demo;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class TopicConsumer {
public static void main(String[] args) throws Exception {
//创建连接工厂
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.25.135:61616");
//获取连接
Connection connection = factory.createConnection();
//启动连接
connection.start();
/**
* 创建session(1.是否启动事务 2.消息确认模式
* AUTO_ACKNOWLEDGE = 1 自动确认
* CLIENT_ACKNOWLEDGE = 2 客户端手动确认
* DUPS_OK_ACKNOWLEDGE = 3 自动批量确认
* SESSION_TRANSACTED = 0 事务提交并确认
*/
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建队列对象
Topic topic = session.createTopic("topic");
//创建消息消费者
MessageConsumer consumer = session.createConsumer(topic);
//手动获取消息
// TextMessage receive = (TextMessage) consumer.receive();
// System.out.println(receive.getText());
//监听获取消息
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
//等待键盘输入
System.in.read();
//关闭资源
consumer.close();
session.close();
connection.close();
}
}
方式二:Spring整合JMS
1.创建普通Maven(不选择骨架)工程,导入坐标
<properties>
<spring.version>4.2.4.RELEASE</spring.version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.11.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
</dependencies>
2.完整工程目录
3.消息生产者配置文件applicationContext-producer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
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
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd">
<context:component-scan base-package="com.demo"/>
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.25.135:61616"/>
</bean>
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
</bean>
<!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
<!--这个是队列目的地,点对点的 文本信息-->
<bean id="queueTextDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="jms_queue"/>
</bean>
<!--这个是订阅模式 文本信息-->
<bean id="topicTextDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="jms_topic"/>
</bean>
</beans>
4.消息生产者类
QueueProducer.java
package com.demo;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
@Component
public class QueueProducer {
@Autowired
private JmsTemplate jmsTemplate;
@Autowired
private ActiveMQQueue queueTextDestination;
//发送文本消息
public void sendTextMessage(final String text) {
jmsTemplate.send(queueTextDestination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(text);
}
});
}
}
TopicProducer.java
package com.demo;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
@Component
public class TopicProducer {
@Autowired
private JmsTemplate jmsTemplate;
@Autowired
private ActiveMQTopic topicTextDestination;
//发送文本消息
public void sendTextMessage(final String text) {
jmsTemplate.send(topicTextDestination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(text);
}
});
}
}
5.消息生产测试类
QueueProducerTest.java
package com.test;
import com.demo.QueueProducer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-producer.xml")
public class QueueProducerTest {
@Autowired
private QueueProducer queueProducer;
@Test
public void testSend() {
queueProducer.sendTextMessage("SpringJms-Queue");
}
}
TopicProducerTest.java
package com.test;
import com.demo.TopicProducer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-producer.xml")
public class TopicProducerTest {
@Autowired
private TopicProducer topicProducer;
@Test
public void testSend() {
topicProducer.sendTextMessage("SpringJms-Topic");
}
}
6.消息消费者配置文件applicationContext-consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
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
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd">
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.25.135: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="queueTextDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="jms_queue"/>
</bean>
<!-- 我的监听类 -->
<bean id="myMessageListener" class="com.demo.MyMessageListener"/>
<!-- 消息监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="queueTextDestination"/>
<property name="messageListener" ref="myMessageListener"/>
</bean>
<!--==========================================-->
<!--这个是队列目的地,发布订阅的 文本信息-->
<bean id="topicTextDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="jms_topic"/>
</bean>
<!-- 我的监听类 -->
<bean id="myMessageListenerTopic" class="com.demo.MyMessageListenerTopic"/>
<!-- 消息监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="topicTextDestination"/>
<property name="messageListener" ref="myMessageListenerTopic"/>
</bean>
</beans>
7.消息消费者自定义监听类
MyMessageListener.java
package com.demo;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
public class MyMessageListener implements MessageListener {
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("接受到消息:" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
MyMessageListenerTopic.java
package com.demo;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
public class MyMessageListenerTopic implements MessageListener {
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("接受到消息:" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
8.消息消费者测试类
只开启一个就能同时监听queue/topic了
ListenerQueueTest.java
package com.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.io.IOException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-consumer.xml")
public class ListenerQueueTest {
@Test
public void test() {
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}