Java ActiveMQ简介以及springboot集成activeMQ实现消息队列监听以及实现MQ延迟

来源:互联网 发布:淘宝上怎么购买呼死你 编辑:程序博客网 时间:2024/04/19 17:05

上篇文章我们提到了如何在Linux下安装activeMQ,环境已经准备好了。我们来学习如何将mq与java进行结合来实现功能。

1.简介

1.1 什么是ActiveMQ

ActiveMQ 是 Apache 出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个 完全支持 JMS1.1 和 J2EE 1.4 规范的 JMS Provider 实现,尽管 JMS 规范出台已经是很久的事 情了,但是 JMS 在当今的 J2EE 应用中间仍然扮演着特殊的地位。

1.2 JMS介绍

1.2.1 基本概念

JMS全称为Java Message Service 即Java消息服务。其API是一个消息服务的规范,JMS的客户端之间可以通过JMS服务进行异步的消息传输。

1.2.2 消息模型

模型分为两种,即 Point-to-Point(P2P)(点对点模型) 和 Publish/Subscribe(Pub/Sub)(发布订阅模型)

(1).P2P模型
<1> 模型图
这里写图片描述
<2> 概念

在P2P模型中涉及到的概念有 消息队列(Queue)、发送者(Sender)、接收者(Receiver),其过程为 每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。

<3> 特点

  1. 每个消息只有一个消费者(即消息一旦被消费者消费,消息就不再在消息队列中)
  2. 发送者发送了消息后,无论消费者是否在运行状态,都不会影响消息发送到队列中

(2).Pub/Sub模型
<1>模型图
这里写图片描述
<2> 概念

在Pub/Sub模型中涉及到的概念有 主题(Topic)、Publisher(发布者)、订阅者(Subscriber),其过程为 多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。

<3> 特点

每个消息可以有多个消费者

1.3 消息的消费

在JMS中,消息的产生和消息是异步的。对于消费来说,JMS的消息者可以通过两种方式来消费消息。
1. 同步
订阅者或接收者调用receive方法来接收消息,receive方法在能够接收到消息之前(或超时之前)将一直阻塞
2. 异步
订阅者或接收者可以注册为一个消息监听器。当消息到达之后,系统自动调用监听器的onMessage方法。

1.4 JMS消息基本组件

(1) ConnectionFactory(连接工厂)
创建Connection对象的工厂,针对两种不同的jms消息模型,分别有QueueConnectionFactory和TopicConnectionFactory两种。可以通过JNDI来查找ConnectionFactory对象。

(2) Destination(session创建出的消息队列或主题)
Destination的意思是消息生产者的消息发送目标或者说消息消费者的消息来源。对于消息生产者来说,它的Destination是某个队列(Queue)或某个主题(Topic);对于消息消费者来说,它的Destination也是某个队列或主题(即消息来源)。

所以,Destination实际上就是两种类型的对象:Queue、Topic可以通过JNDI来查找Destination。

(3) Connection(连接工厂创建出的连接)
Connection表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装)。Connection可以产生一个或多个Session。跟ConnectionFactory一样,Connection也有两种类型:QueueConnection和TopicConnection。

(4) Session(连接创建出的session)
Session是我们操作消息的接口。可以通过session创建生产者、消费者、消息等。Session提供了事务的功能。当我们需要使用session发送/接收多个消息时,可以将这些发送/接收动作放到一个事务中。同样,也分QueueSession和TopicSession。

(5) 消息的生产者
消息生产者由Session创建,并用于将消息发送到Destination。同样,消息生产者分两种类型:QueueSender和TopicPublisher。可以调用消息生产者的方法(send或publish方法)发送消息。

(6) 消息消费者
消息消费者由Session创建,用于接收被发送到Destination的消息。两种类型:QueueReceiver和TopicSubscriber。可分别通过session的createReceiver(Queue)或createSubscriber(Topic)来创建。当然,也可以session的creatDurableSubscriber方法来创建持久化的订阅者。

(7) MessageListener
消息监听器。如果注册了消息监听器,一旦消息到达,将自动调用监听器的onMessage方法。EJB中的MDB(Message-Driven Bean)就是一种MessageListener。

大概关系如下图所示
这里写图片描述

大概的一些关于mq的基本概念我们就聊到这里,下面我们开始创建一个springboot项目来进行java与mq的结合。

2. java与mq结合

2.1 创建Springboot项目

创建springboot项目的过程只进行简单的截图,如想了解细节,可看我之前的博客 java 搭建基于springboot的ssh(spring + springmvc + hibernate)的gradle项目(基础篇)

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

2.2 mq配置实现消息队列监听

好了,基本的springboot项目我们创建好了。现在我们开始进行项目结构改造以及文件的配置,代码解释我会以注释的形式写在代码中。请各位同学仔细阅读。

改造后的项目结构如下图所示
这里写图片描述

2.2.1 Gradle依赖配置

buildscript {    ext {        springBootVersion = '1.5.9.RELEASE'    }    repositories {        mavenCentral()    }    dependencies {        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")    }}apply plugin: 'java'apply plugin: 'eclipse'apply plugin: 'org.springframework.boot'group = 'com.beyondLi'version = '0.0.1-SNAPSHOT'sourceCompatibility = 1.8repositories {    mavenCentral()}dependencies {    //mq依赖jar包    compile('org.springframework.boot:spring-boot-starter-activemq')    compile('org.springframework.boot:spring-boot-starter-web')    compileOnly('org.projectlombok:lombok')    testCompile('org.springframework.boot:spring-boot-starter-test')}

2.2.2 application.properties文件中添加

#activemqspring.activemq.broker-url=tcp://192.168.47.128:61616spring.activemq.user=adminspring.activemq.password=adminspring.activemq.in-memory=true# 如果此处设置为true,需要加activemq-pool的依赖包,否则会自动配置失败,报JmsMessagingTemplate注入失败spring.activemq.pool.enabled=false

2.2.3 对mq进行封装

ActiveManager文件内容如下

package com.beyondli.common;import org.apache.activemq.ScheduledMessage;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jms.core.JmsMessagingTemplate;import org.springframework.stereotype.Component;import javax.jms.*;/** * Created by beyondLi on 2017/12/21. */@Componentpublic class ActiveManager {    @Autowired    JmsMessagingTemplate jmsMessagingTemplate;    /**     * @param data     * @desc 即时发送     */    public void send(Destination destination,String data) {        this.jmsMessagingTemplate.convertAndSend(destination, data);    }}

2.2.4 生产者(ProducerRest)

package com.beyondli.rest;import com.beyondli.common.ActiveManager;import org.apache.activemq.command.ActiveMQQueue;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import javax.jms.Destination;/** * Created by beyondLi * Date 2017/12/21 * Desc 生产者rest . */@RestController@RequestMapping(value = "/test/producer", produces = "application/json")public class ProducerRest {    /**     * 注入ActiveManager     */    @Autowired    ActiveManager activeManager;    /**     * 新增消息队列     */    @RequestMapping(value = "/add/queue", method = RequestMethod.GET)    public void addQueue() {        Destination destination = new ActiveMQQueue("beyondLiQueueTest");        //传入队列以及值        activeManager.send(destination, "success");    }}

2.2.5 消费者(CustomerRest)

package com.beyondli.rest;import org.springframework.jms.annotation.JmsListener;import org.springframework.stereotype.Service;/** * Created by beyondLi * Date 2017/12/21 * Desc 生产者rest . */@Servicepublic class CustomerRest {    /**     * 监听方     */    //监听注解    @JmsListener(destination = "beyondLiQueueTest")    public void getQueue(String info) {        System.out.println("成功监听beyondLiQueueTest消息队列,传来的值为:" + info);    }}

2.3 测试

我们来运行代码,进行测试,运行结果如下图所示。

首先启动项目后,我们会发现我们的消息队列已经成功添加到mq中(其实这个主要是因为启动的时候会先自动进行一次创建测试,所以会发现我们还没有调用方法就queue就已经创建出来了),如下图所示
这里写图片描述

现在我们访问生产者接口,看看消费者是否监听成功。如下图所示,我们监听方也成功监听到了我们的消息。
这里写图片描述

2.4 实现MQ延迟

其实所谓的MQ延迟说白了就是我要多少秒之后再去创建这个消息队列,从而达到多少秒之后自动调用某个接口的效果。
需求:例如我创建了一个秒杀活动,APP端有一个秒杀活动开启五分钟前自动给点击了”提醒我”的用户的手机发送短信的功能。
这个时候我们就会使用到mq的延迟功能,在秒杀活动开启前五分钟调用 查询所有点击了”提醒我”的会员的电话号码,给他们发送短信 功能的接口。

2.4.1 开启mq延迟功能

首先,上篇文章中我们有mq在linux下的安装过程,但是默认情况下mq的延迟功能是关闭的,所以首先我们需要将mq的延迟功能开启。

#切换目录/usr/local/apache-activemq-5.14.0/conf# 以vim查看配置文件vi activemq.xml# 在第40行添加 schedulerSupport="true" 如下图所示

这里写图片描述

修改完配置后,重新启动我们的mq。

2.4.2 在ActiveManager中添加延迟方法

package com.beyondli.common;import org.apache.activemq.ScheduledMessage;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jms.core.JmsMessagingTemplate;import org.springframework.stereotype.Component;import javax.jms.*;/** * Created by beyondLi on 2017/12/21. */@Componentpublic class ActiveManager {    @Autowired    JmsMessagingTemplate jmsMessagingTemplate;    /**     * @param data     * @desc 即时发送     */    public void send(Destination destination,String data) {        this.jmsMessagingTemplate.convertAndSend(destination, data);    }    /**     * @desc 延时发送     */    public void delaySend(String text, String queueName, Long time) {        //获取连接工厂        ConnectionFactory connectionFactory = this.jmsMessagingTemplate.getConnectionFactory();        try {            //获取连接            Connection connection = connectionFactory.createConnection();            connection.start();            //获取session            Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);            // 创建一个消息队列            Destination destination = session.createQueue(queueName);            MessageProducer producer = session.createProducer(destination);            producer.setDeliveryMode(DeliveryMode.PERSISTENT);            TextMessage message = session.createTextMessage(text);            //设置延迟时间            message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, time);            //发送            producer.send(message);            session.commit();            producer.close();            session.close();            connection.close();        } catch (Exception e) {            e.getMessage();        }    }}

2.4.3 生产者(ProducerRest)

package com.beyondli.rest;import com.beyondli.common.ActiveManager;import org.apache.activemq.command.ActiveMQQueue;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import javax.jms.Destination;import java.time.LocalDateTime;/** * Created by beyondLi * Date 2017/12/21 * Desc 生产者rest . */@RestController@RequestMapping(value = "/test/producer", produces = "application/json")public class ProducerRest {    /**     * 注入ActiveManager     */    @Autowired    ActiveManager activeManager;    /**     * 新增消息队列     */    @RequestMapping(value = "/add/queue", method = RequestMethod.GET)    public void addQueue() {        Destination destination = new ActiveMQQueue("beyondLiQueueTest");        //传入队列以及值        activeManager.send(destination, "success");    }    /**     * 新增消息队列(延迟)     */    @RequestMapping(value = "/add/delay/queue", method = RequestMethod.GET)    public void addDelayQueue() {        System.out.println(LocalDateTime.now());        activeManager.delaySend("success", "beyondLiDelayQueueTest", 5000L);    }}

2.4.4 消费者(CustomerRest)

package com.beyondli.rest;import org.springframework.jms.annotation.JmsListener;import org.springframework.stereotype.Service;import java.time.LocalDateTime;/** * Created by beyondLi * Date 2017/12/21 * Desc 生产者rest . */@Servicepublic class CustomerRest {    /**     * 监听方     */    //监听注解    @JmsListener(destination = "beyondLiQueueTest")    public void getQueue(String info) {        System.out.println("成功监听beyondLiQueue消息队列,传来的值为:" + info);    }    //    @JmsListener(destination = "beyondLiDelayQueueTest")    public void getDelayQueue(String info) {        System.out.println("成功监听beyondLiQueueTest消息队列,传来的值为:" + info + "当前时间为" + LocalDateTime.now());    }}

2.4.5 测试

运行项目,并调用接口,运行结果如下图所示,调用生产者后消费者5秒后自动执行,大功告成。
这里写图片描述

源码下载地址:http://download.csdn.net/download/liboyang71/10168685

原创粉丝点击