Spring 整合 JMS ( 基于ActiveMQ )

一. 消息中间件

  1. 什么是消息中间件

    消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。对于消息中间件,常见的角色大致也就有Producer(生产者)、Consumer(消费者)

  2. 常见的消息中间件产品
    常见的消息中间件产品

  3. 优势分析
    这里写图片描述

  4. 场景应用
    更新索引库

二. JMS

  1. 什么是 JMS

    JMS(Java Messaging Service)是 Java 平台上有关面向消息中间件的技术规范,它便于消息系统中的 Java 应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发。
    JMS 本身只定义了一系列的接口规范,是一种与厂商无关的 API,用来访问消息收发系统。

  2. 消息格式

    JMS 定义了五种不同的消息正文格式 :
    · TextMessage–一个字符串对象
    · MapMessage–一套名称-值对
    · ObjectMessage–一个序列化的 Java 对象
    · BytesMessage–一个字节的数据流
    · StreamMessage – Java 原始值的数据流

  3. JMS 消息传递类型
    a. 点对点
    这里写图片描述
    这里写图片描述
    b. 发布/ 订阅模式
    这里写图片描述
    这里写图片描述

三. ActiveMQ

这里写图片描述

四. JMS入门案例

  1. 准备工作
    • 1 引入坐标
<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-client</artifactId>
    <version>5.13.4</version>
</dependency>

点对点模式
  • 1 创建 QueueProducer
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQTextMessage;
import org.junit.Test;

import javax.jms.*;

public class QueueProducer {

    /**
     * 需求:发送消息
     * 模式:点对点模式
     */
    @Test
    public void sendMessage() throws Exception{
        //指定消息服务器发送地址
        String brokerURL = "tcp://192.168.66.66:61616";
        //创建消息连接工厂对象
        ConnectionFactory cf = new ActiveMQConnectionFactory(brokerURL);
        //从工厂中获取连接对象
        Connection connection = cf.createConnection();

        //开启连接
        connection.start();

        //从连接中获取消息回话对象session
        //参数1:
        // true: 表示使用的是消息事务确认提交模式 Session.SESSION_TRANSACTED
        // false: 消息自动确认模式
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建消息存储空间,且给这个空间起一个名称
        Queue queue = session.createQueue("myQueue");

        //创建消息发送者,且告知消息往哪儿发送
        MessageProducer producer = session.createProducer(queue);

        //创建消息对象
        TextMessage message = new ActiveMQTextMessage();
        message.setText("齐天大圣孙悟空,修炼了八九玄功?");

        //发送消息
        producer.send(message);

        producer.close();
        session.close();
        connection.close();

    }
}
  • 2 创建 QueueConsumer
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQTextMessage;
import org.aspectj.weaver.ast.Var;
import org.junit.Test;

import javax.jms.*;
import java.util.Map;

public class QueueConsumer {

    /**
     * 需求:接受消息
     * 模式:点对点模式
     */
    @Test
    public void receiveMessage() throws Exception{
        //指定消息服务器发送地址
        String brokerURL = "tcp://192.168.66.66:61616";
        //创建消息连接工厂对象
        ConnectionFactory cf = new ActiveMQConnectionFactory(brokerURL);
        //从工厂中获取连接对象
        Connection connection = cf.createConnection();

        //开启连接
        connection.start();

        //从连接中获取消息回话对象session
        //参数1:是否使用消息事务模式   参数2: 消息确认模式
        // true: 使用消息事务,  事务提交并确认模式 Session.SESSION_TRANSACTED
        // false: 不使用消息事务, 自动确认模式 Session.AUTO_ACKNOWLEDGE
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //指定消息存储空间,且给这个空间起一个名称
        Queue queue = session.createQueue("myQueue");

        //指定消息接受者,且指定从哪儿接受消息
        MessageConsumer consumer = session.createConsumer(queue);

        //监听接受
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {

               if(message instanceof TextMessage){
                    try {
                        TextMessage m = (TextMessage) message;
                        //获取消息
                        String text = m.getText();

                        System.out.println("接受消息:"+text);

                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }

            }
        });

        //等待输入,让端口阻塞,服务一直开启
        System.in.read();

        consumer.close();
        session.close();
        connection.close();

    }

}

上述代码中创建 session 的两个参数:
第 1 个参数 是否使用事务
第 2 个参数 消息的确认模式
 AUTO_ACKNOWLEDGE 自动确认
 CLIENT_ACKNOWLEDGE 客户端手动确认
 DUPS_OK_ACKNOWLEDGE 自动批量确认
 SESSION_TRANSACTED 事务提交并确认

发布/订阅模式
  • 1 创建 TopicProducer
//创建消息存储空间,且给这个空间起一个名称
//点对点:queue
//发布订阅:topic
//发布订阅和点对点根本区别在于发生消息数据结构不一样。
Topic topic = session.createTopic("myTopic");

//创建消息发送者,且告知消息往哪儿发送
MessageProducer producer = session.createProducer(topic);

和 [ 点对点模式 ] 的 Producer 代码相识度99% ,唯有上述两行不同

  • 2 创建 TopicConsumer
//从连接中获取消息回话对象session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//指定消息存储空间,且给这个空间起一个名称
Topic topic = session.createTopic("myTopic");
//指定消息接受者,且指定从哪儿接受消息
MessageConsumer consumer = session.createConsumer(topic);

和 [ 点对点模式 ] 的 Consumer 代码相识度99% ,唯有上述几行不同

五. Spring 整合 JMS , ActiveMQ

这里写图片描述

准备

spring架构中已经整合了JMS, 故只需将ActiveMQ 交由spring-JMS 接管即可

– 引入 activemq-client 坐标

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-client</artifactId>
    <version>5.13.4</version>
</dependency>
生产者
  • 1 配置文件 applicationContext-mq-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" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--把activeMQ交给spring管理-->
    <bean id="targetConnnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <constructor-arg name="brokerURL" value="tcp://192.168.66.66:61616"></constructor-arg>
    </bean>

    <!--创建spring jms组件提供工厂对象,无缝接管activeMQ-->
    <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
        <property name="targetConnectionFactory" ref="targetConnnectionFactory"></property>
    </bean>

    <!--spring jms提供消息发送模板对象-->
    <bean class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory"></property>
    </bean>

    <!--点对点消息空间-->
    <bean class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="oneQueue"></constructor-arg>
    </bean>

    <!--发布订阅消息空间-->
    <bean class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg value="oneTopic"></constructor-arg>
    </bean>

</beans>
  • 2 生产者测试类 SpringJmsProducer
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-mq-producer.xml")
public class SpringJmsProducer {

    //注入消息发送模板对象
    @Autowired
    private JmsTemplate jmsTemplate;
    //注入消息目的地:点对点
    @Autowired
    private ActiveMQQueue activeMQQueue;

    //注入消息目的地:发布订阅
    @Autowired
    private ActiveMQTopic activeMQTopic;


    /**
     * 需求:点对点发送消息
     */
    @Test
    public  void sendMessageByP2P(){
        //使用模板发现消息
        jmsTemplate.send(activeMQQueue, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage("只要988!");
            }
        });
    }

    /**
     * 需求:发布订阅发送消息
     */
    @Test
    public  void sendMessageByPS(){
        //使用模板发现消息
        jmsTemplate.send(activeMQTopic, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage("只要988!hhhhhhh");
            }
        });
    }


}

消费者
  • 1 配置文件 applicationContext-mq-consumer.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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--把activeMQ添加到spring容器-->
    <bean id="targetConnnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <constructor-arg name="brokerURL" value="tcp://192.168.66.66:61616"></constructor-arg>
    </bean>

    <!--创建spring jms组件提供工厂对象,无缝接管activeMQ-->
    <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
        <property name="targetConnectionFactory" ref="targetConnnectionFactory"></property>
    </bean>

    <!--点对点消息空间-->
    <bean id="oneQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="oneQueue"></constructor-arg>
    </bean>

    <!--发布订阅消息空间-->
    <bean id="topic" class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg value="oneTopic"></constructor-arg>
    </bean>

    <!--自定义消息监听器01 处理点对点消息-->
    <bean id="queListener" class="com.pyg.search.listener.QueListener"></bean>

    <!--spring jms提供消息监听容器:自动触发监听器,自动实现消息接收-->
    <bean id="messageListenerContainer01"  class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <!--指定接受消息服务器-->
        <property name="connectionFactory" ref="connectionFactory"></property>
        <!--指定从消息服务器那个空间接受-->
        <property name="destination" ref="oneQueue"></property>
        <!--指定接受消息监听器-->
        <property name="messageListener" ref="queListener"></property>
    </bean>

    <!--自定义消息监听器02 处理订阅消息-->
    <bean id="topListener " class="com.pyg.search.listener.TopListener "></bean>

    <!--spring jms提供消息监听容器:自动触发监听器,自动实现消息接收-->
    <bean id="messageListenerContainer02"  class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <!--指定接受消息服务器-->
        <property name="connectionFactory" ref="connectionFactory"></property>
        <!--指定从消息服务器那个空间接受-->
        <property name="destination" ref="topic"></property>
        <!--指定接受消息监听器-->
        <property name="messageListener" ref="topListener "></property>
    </bean>

</beans>
  • 2 创建自定义监听类 QueListener, 处理点对点消息
import com.alibaba.fastjson.JSON;
import com.pyg.pojo.TbItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.solr.core.SolrTemplate;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import java.util.List;
import java.util.Map;

public class QueListener implements MessageListener{

    @Override
    public void onMessage(Message message) {

        if(message instanceof TextMessage){
             try {
                 TextMessage m = (TextMessage) message;
                 //获取消息
                 String text = m.getText();
                 System.out.println("接受消息:"+text);

             } catch (JMSException e) {
                 e.printStackTrace();
             }
        }

    }
}
  • 3 创建自定义监听类 TopListener , 处理订阅消息

import com.alibaba.fastjson.JSON;
import com.pyg.pojo.TbItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.solr.core.SolrTemplate;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import java.util.List;
import java.util.Map;

public class TopListener implements MessageListener{

    @Override
    public void onMessage(Message message) {

        if(message instanceof TextMessage){
             try {
                 TextMessage m = (TextMessage) message;
                 //获取消息
                 String text = m.getText();
                 System.out.println("接受消息:"+text);

             } catch (JMSException e) {
                 e.printStackTrace();
             }
        }

    }
}

无论是处理点对点, 还是订阅, 只要自定义一个监听类 implements MessageListener , 重写 onMessage(Message message) 方法就可以了, 服务器启动, 加载配置文件, 只要监听到消息, 自定义监听类会自动处理消息

猜你喜欢

转载自blog.csdn.net/qq_42806915/article/details/82219242
今日推荐