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

上篇文章我们提到了如何在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.8

repositories {
    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文件中添加
#activemq
spring.activemq.broker-url=tcp://192.168.47.128:61616
spring.activemq.user=admin
spring.activemq.password=admin
spring.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.
 */
@Component
public 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 .
 */
@Service
public 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.
 */
@Component
public 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 .
 */
@Service
public 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

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值