消息队列就改这么学(ActiveMQ)

ActiveMQ介绍

  1. MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。
  2. MQ的消费-生产者模型的一个典型的代表,一端往消息队列中不断的写入消息,而另一端则可以读取或者订阅队列中的消息。MQ和JMS类似
  3. JMS即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
  4. Message消息分为几种类型,它们分别携带:简单文本(TextMessage)、可序列化的对象 (ObjectMessage)、属性集合 (MapMessage)、字节流 (BytesMessage)、原始值流 (StreamMessage),还有无有效负载的消息 (Message)。
  5. JMS是一个用于提供消息服务的技术规范,它制定了在整个消息服务提供过程中的所有数据结构和交互流程。而MQ则是消息队列服务,是面向消息中间件(MOM)的最终实现,是真正的服务提供者;MQ的实现可以基于JMS,也可以基于其他规范或标准。
    支持JMS的开源MQ:目前选择的最多的是ActiveMQ。

ActiveMQ特点

  1. 多种语言和协议编写客户端。语言: Java, C, C++, C#, Ruby, Perl, Python, PHP。应用协议: OpenWire,Stomp REST,WSNotification,XMPP,AMQP
  2. 完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)
  3. 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性
  4. 通过了常见J2EE服务器(如 Geronimo,JBoss 4, GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上
  5. 支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
  6. 支持通过JDBC和journal提供高速的消息持久化
  7. 从设计上保证了高性能的集群,客户端-服务器,点对点
  8. 支持Ajax
  9. 支持与Axis的整合
  10. 可以很容易得调用内嵌JMS provider,进行测试
  11. ActiveMQ速度非常快;一般要比jbossMQ快10倍。
优点

是一个快速的开源消息组件(框架),支持集群,同等网络,自动检测,TCP,SSL,广播,持久化,XA,和J2EE1.4容器无缝结合,并且支持轻量级容器和大多数跨语言客户端上的Java虚拟机。消息异步接受,减少软件多系统集成的耦合度。消息可靠接收,确保消息在中间件可靠保存,多个消息也可以组成原子事务。

缺点

ActiveMQ默认的配置性能偏低,需要优化配置,但是配置文件复杂,ActiveMQ本身不提供管理工具;示例代码少;主页上的文档看上去比较全面,但是缺乏一种有效的组织方式,文档只有片段,用户很难由浅入深进行了解,二、文档整体的专业性太强。在研究阶段可以通过查maillist、看Javadoc、分析源代码来了解。

ActiveMQ应用场景

  1. 流量肖锋
  2. 任务异步处理
  3. 可以解耦合
  4. 消息通讯

SpringBoot集成ActiveMQ的使用demo(代码包含queue和topic两种使用方式)

  1. ActiveMQ配置信息application.properties文件
spring:
    activemq:
        user: admin
        password: admin
        broker-url: tcp://127.0.0.1:61616
        pool:     //连接池设置
            enabled: true     //是否开启连接池
            max-connections: 10     //最大连接数

  1. ActiveMQ配置信息类
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.jms.Queue;
import javax.jms.Topic;

@Component
public class ActiveMQConfig {
    @Bean
    public Queue queue () {
        return new ActiveMQQueue("queueTest"); //创建queue
    }

    @Bean
    public Topic topic () {
        return new ActiveMQTopic("topicTest"); //创建topic
    }
}

  1. producer类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;

@Component
@EnableScheduling //快速开启任务调度
public class ActiveMQProducer {

    Logger logger = LoggerFactory.getLogger(ActiveMQProducer.class);

    @Autowired
    private JmsTemplate jmsTemplate;

    @Autowired
    private Queue queue;

    @Autowired
    private Topic topic;


    public void sendByQueue () {
        System.out.println("ActiveMQ以 Queue 准备接受用户消息");
        logger.info("【sendByQueue start】ActiveMQ以 Queue 准备接受用户消息");
        jmsTemplate.convertAndSend(this.queue , "queue每三秒执行一次");
        logger.info("【sendByQueue success】ActiveMQ以 Queue 接受用户消息成功");
    }

    //@Scheduled(fixedDelay = 5000)   //每五秒执行一次该方法
    public void sendByQueue (Destination destination , String message) {
        System.out.println("ActiveMQ以 Queue 准备接受用户消息");
        logger.info("【sendByQueue start,destination is + " + destination + " ,message is " + message + "】ActiveMQ以 Queue 准备接受用户消息");
        logger.info("【sendByQueue start】ActiveMQ以 Queue 准备接受用户消息");
        this.jmsTemplate.convertAndSend(destination , message);
    }

    public void sendByTopic (Destination destination , String message) {
        System.out.println("ActiveMQ以 Topic 准备接受用户消息");
        logger.info("【sendByTopic start,destination is + " + destination + " ,message is " + message + "】ActiveMQ以 Topic 准备接受用户消息");
        logger.info("【sendByTopic start】ActiveMQ以 Topic 准备接受用户消息");
        this.jmsTemplate.convertAndSend(destination , message);
    }

}

  1. comsumer类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

import javax.jms.Queue;
import javax.jms.Topic;

@Component
@EnableScheduling
public class ActiveMQComsumer {

    Logger logger = LoggerFactory.getLogger(ActiveMQComsumer.class);

    @Autowired
    private JmsTemplate jmsTemplate;

    @Autowired
    private Queue queue;

    @Autowired
    private Topic topic;

    @JmsListener(destination = "queueTest")
    public void receiveByQueue (String message) {
        System.out.println("以Queue收到的消息为:" + message);
        logger.info("【receiveByQueue succeed】以 Queue 开始接受来自AvtiveMQ的消息");
    }

    @JmsListener(destination = "topicTest")
    public void receiveByTopic1 (String message) {
        System.out.println("receiveByTopic1以Topic收到消息:" + message);
        logger.info("【receiveByTopic1 succeed】以 Topic 成功接受来自AvtiveMQ的消息");
    }

    @JmsListener(destination = "topicTest")
    public void receiveByTopic2 (String message) {
        System.out.println("receiveByTopic1以Topic收到消息:" + message);
        logger.info("【receiveByTopic2 succeed】以 Topic 成功接受来自AvtiveMQ的消息");
    }
}

  1. Controller访问ActiveMQ
import com.ruider.common.Result;
import com.ruider.utils.ActiveMQ.ActiveMQProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.jms.Queue;
import javax.jms.Topic;

/**
 * ActiveMQ controller消息中间件
 */
@RestController
@RequestMapping("message")
public class ActiveMQController {
    private final Logger logger = LoggerFactory.getLogger(ActiveMQController.class);

    @Autowired
    private Queue queue;

    @Autowired
    private Topic topic;

    @Autowired
    private ActiveMQProducer activeMQProducerTest;

    @GetMapping("activeMQQueueProduce")
    public Result activeMQQueueProduce (String message) {
        Result result = new Result();
        try {
            activeMQProducerTest.sendByQueue(this.queue , message);
            result.setIsSuccess(true);
            result.setMessage("发送消息成功,MQ收到消息");
            logger.info("【activeMQQueueProduce success】发送消息成功,MQ Queue收到消息");
            return result;
        }
        catch(Exception e) {
            result.setIsSuccess(false);
            result.setCode(Result.EXCEPTION_CODE);
            result.setMessage("发送消息失败,MQ Queue未收到消息");
            logger.error("【activeMQQueueProduce fail】发送消息失败,MQ Queue未收到消息"+ e);
            return result;
        }
    }

    @GetMapping("activeMQTopicProduce")
    public Result activeMQTopicProduce (String message) {
        Result result = new Result();
        try {
            activeMQProducerTest.sendByTopic(this.topic , message);
            result.setIsSuccess(true);
            result.setMessage("发送消息成功,MQ Topic收到消息");
            logger.info("【activeMQTopicProduce success】发送消息成功,MQ Topic收到消息");
            return result;
        }
        catch(Exception e) {
            result.setIsSuccess(false);
            result.setCode(Result.EXCEPTION_CODE);
            result.setMessage("发送消息失败,MQ Topic未收到消息");
            logger.error("【activeMQTopicProduce fail】发送消息失败,MQ Topic未收到消息"+ e);
            return result;
        }
    }
}
  1. Controller类中使用到的Result类做前端与后台的交互

/**
 * Created by mahede on 2018/11/28.
 */
public class Result {

    public static final int ERROR_CODE = 100;

    public static final int ALREADY_SAVED = 110;

    public static final int FAIL_CODE = 120;

    public static final int SUCCESS_CODE = 140;

    public static final int EXCEPTION_CODE = 150;

    public static final int OVER_NUMBER = 160;

    public static final int OVER_TIME = 170;

    int code;

    String message;

    Object data;

    boolean isSuccess;

    public Result(){ this.code = SUCCESS_CODE;}

    public Result(int code, String message, Object data, boolean isSuccess) {
        this.code = code;
        this.message = message;
        this.data = data;
        this.isSuccess = isSuccess;
    }

    public Result(boolean isSuccess, Object data, String message) {
        this.message = message;
        this.data = data;
        this.isSuccess = isSuccess;
    }

    @Override
    public String toString() {
        return "Result{" +
                "code=" + code +
                ", message='" + message + '\'' +
                ", data=" + data +
                ", isSuccess=" + isSuccess +
                '}';
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public boolean getIsSuccess() {
        return isSuccess;
    }

    public void setIsSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值