まず、JMSサービスを全員で確認します。
- メッセージサービス:2つまたは複数のプログラム間の結合を解決するために使用されるミドルウェアであり、最下層はJavaによって実装されます。
- 利点:非同期で信頼性が高い
- メッセージモデル:ポイントツーポイント、パブリッシュ/サブスクライブ
- JMSのオブジェクト
事前に説明してください:
ここでは、この設定ファイルについて説明します。上記の設定ファイルから理解できる場合は、スキップしてかまいません。学生は、ActiveMQ公式Webサイトでも表示できます。
ActiveMqのDTDの場合、関連する構成を宣言する前に、まずActiveMqにDTDをインポートする必要があります。そうしないと、Springはタグの意味を理解できません。
http://activemq.apache.org/schema/core/activemq-core-5.12.1.xsd
1 pom.xmlファイルのactivemqのバージョンを、ここでのバージョンに依存するように構成しました。これは、依存バージョンと同じである必要があります。そうでない場合、関連するdtdが見つかりません。
2. amq:connectionFactory:リンクファクトリのアドレスとユーザー名およびパスワードを構成するために使用される非常に単純な構成アイテム。ここでは、http接続ではなくtcp接続を選択することに注意する必要があります。
3. jmsTemplate:接続ファクトリが指定されている、より重要な構成、デフォルトのメッセージ送信先、接続期間、およびメッセージの公開方法
Mavenプロジェクトに依存関係を追加する
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- ActiveMQ依赖 -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
</dependency>
<!-- 加入spring-jms依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
</dependencies>
1.プロデューサーを作成します:applicationContext-activemq-topic-producer.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://xxx.xxx.xxx.xxx: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"/>
<!-- 订阅模式 -->
<property name="pubSubDomain" value="true"/>
</bean>
<!--订阅模式,一对多 -->
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="topic.item"/>
</bean>
</beans>
2つ目は、コンシューマー1のapplicationContext-activemq-topic-consumer1.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://xxx.xxx.xxx.xxx:61616"/>
</bean>
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
<!-- 消费者标识 -->
<property name="clientId" value="topic-consumer-a"/>
</bean>
<!--订阅模式,一对多的 -->
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="topic.item"/>
</bean>
<!-- messageListener实现类 -->
<bean id="topicMessageListener1" class="it.hehe.spring.topic.TopicMessageListener1"/>
<!-- 配置一个jms监听容器 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="topicDestination"/>
<property name="messageListener" ref="topicMessageListener1"/>
<!-- 消息持久化 -->
<property name="subscriptionDurable" value="true"/>
<!-- 消费者标识 -->
<property name="clientId" value="topic-consumer-a"/>
<!-- 订阅者标识(与消费者标识符可以不一样;默认为监听器全限定名) -->
<property name="durableSubscriptionName" value="topic-consumer-a"/>
<!-- 设置为发布/订阅模式 -->
<property name="pubSubDomain" value="true"/>
<!-- 是否开启事务 -->
<property name="sessionTransacted" value="false"/>
<!-- 客户端消息确认模式名称 -->
<property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/>
</bean>
</beans>
2つ目は、コンシューマー2のapplicationContext-activemq-topic-consumer2.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://xxx.xxx.xxx.xxx:61616"/>
</bean>
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
<!-- 消费者标识 -->
<property name="clientId" value="topic-consumer-b"/>
</bean>
<!--订阅模式,一对多的 -->
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="topic.item"/>
</bean>
<!-- messageListener实现类 -->
<bean id="topicMessageListener2" class="it
.hehe.spring.topic.TopicMessageListener2"/>
<!-- 配置一个jms监听容器 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="topicDestination"/>
<property name="messageListener" ref="topicMessageListener2"/>
<!-- 消息持久化 -->
<property name="subscriptionDurable" value="true"/>
<!-- 消费者标识 -->
<property name="clientId" value="topic-consumer-b"/>
<!-- 订阅者标识(与消费者标识符可以不一样;默认为监听器全限定名) -->
<property name="durableSubscriptionName" value="topic-consumer-b"/>
<!-- 设置为发布/订阅模式 -->
<property name="pubSubDomain" value="true"/>
<!-- 是否开启事务 -->
<property name="sessionTransacted" value="false"/>
<!-- 客户端消息确认模式名称 -->
<property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/>
</bean>
3、コンシューマー2リスナークラスを作成します
TopicMessageListener2.java
package cn.itcast.activemq.spring.topic;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener;
public class TopicMessageListener2 extends AbstractAdaptableMessageListener {
@Override
public void onMessage(Message message, Session session) throws JMSException {
// 判断消息类型是TextMessage
if (message instanceof TextMessage) {
// 如果是,则进行强转
TextMessage textMessage = (TextMessage) message;
try {
// 消费消息,打印消息内容
String text = textMessage.getText();
System.out.println("TopicMessageListener2-消费者2消息监听器接收到消息;消息内容为:" + text);
} catch (Exception e) {
e.printStackTrace();
}
/**
* 在spring的配置文件配置监听容器的时候如果 AcknowledgeMode配置为CLIENT_ACKNOWLEDGE的话:
* 那么在监听器代码中抛出异常或者执行session.recover();则会将信息重新发送6次(默认每秒发一个消息)
* 在重发6次后消息还是处理失败,那么消息将自动到DLQ-死信队列(Dead Letter Queue用来保存处理失败或者过期的消息;
* 默认在ActiveMQ队列里面的名称为:ActiveMQ.DLQ)
*/
session.recover();
/**
* 什么时候会重发:
* Messages are redelivered to a client when any of the following occurs:
A transacted session is used and rollback() is called.
A transacted session is closed before commit() is called.
A session is using CLIENT_ACKNOWLEDGE and Session.recover() is called.
*/
}
}
}
第4に、コンシューマー1リスナークラスを作成します
TopicMessageListener1.java
package cn.itcast.activemq.spring.topic;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener;
public class TopicMessageListener1 extends AbstractAdaptableMessageListener {
@Override
public void onMessage(Message message, Session session) throws JMSException {
// 判断消息类型是TextMessage
if (message instanceof TextMessage) {
// 如果是,则进行强转
TextMessage textMessage = (TextMessage) message;
try {
// 消费消息,打印消息内容
String text = textMessage.getText();
System.out.println("TopicMessageListener1-消费者1 消息监听器接收到消息;消息内容为:" + text);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
5、テストプロデューサークラスを作成します
Producer.java
package cn.itcast.activemq.spring.topic;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.command.ActiveMQTextMessage;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
public class Producer {
public static void main(String[] args) {
// 创建spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-activemq-topic-producer.xml");
// 从spring容器中获取JMSTemplate,这个对象是用于发送消息的
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
//创建消息模式
Destination destination = (Destination)context.getBean("topicDestination");
// 使用JMSTemplate发送消息
jmsTemplate.send(destination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage textMessage = new ActiveMQTextMessage();
textMessage.setText("。---spring-topic的方式发送。订阅主题的名称为:topic.item");
System.out.println("已发送消息...");
return textMessage;
}
});
}
}
6、消費者テストカテゴリ1、2をそれぞれ作成します
package cn.itcast.activemq.spring.topic;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Consumer1 {
public static void main(String[] args) {
// 创建spring容器
new ClassPathXmlApplicationContext("applicationContext-activemq-topic-consumer1.xml");
}
}
package cn.itcast.activemq.spring.topic;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Consumer2 {
public static void main(String[] args) {
// 创建spring容器
new ClassPathXmlApplicationContext("applicationContext-activemq-topic-consumer2.xml");
}
}
テスト効果: