springboot整合ActiveMQ(点对点和发布订阅)

本文介绍了ActiveMQ的基本概念和使用原因,包括系统解耦、异步调用和流量削峰。接着展示了如何在SpringBoot中整合ActiveMQ,提供了点对点(Queue)和发布订阅(Topic)两种消息传递模式的代码示例,详细解释了这两种模式的区别,并给出了项目目录结构、导入的包和关键组件。
摘要由CSDN通过智能技术生成

springboot整合ActiveMQ(点对点和发布订阅)

ActiveMQ是什么,为什么使用MQ

是基于 Java 中的 JMS 消息服务规范实现的一个消息中间件。

1.系统解耦

采用中间件之后,就可以完美解决上述中因为耦合可能导致的问题。系统 A 不用去

关心下层服务调用方的问题。

2. 异步调用

当一个请求处理需要经过 3 个系统的时候,A 和 B 系统处理时间 3ms 时间,这个是非

常快的,但是 C 系统可能需要 30s 才能处理完。这样整个业务处理时间因为 C 系统导

致非常慢。

比如我们在美团或者饿了吗下单,那么在下单的时候,后台需要通过后台处理:订单支

付->账户扣款->创建订单->通知商家准备菜品->安排骑手

这个时候我们对于扣款和创建订单来讲对于时效性要求强,处理效率也比较高。对于通

知商家准备菜品和安排骑手来讲时效性的要求不是很高,处理时间也可能会稍长。这个

时候就可以使用 mq 进行异步处理,先处理完前面的业务,然后反馈给用户,之后再通

过 mq 处理通知商家准备菜品和安排骑手

3.流量削峰

大部分时候,每秒几百请求,一台机器就足够了,但是为了抗那每天瞬时的高峰,硬是

部署了 10 台机器,每天就那半个小时有用,别的时候都是浪费资源的。

但是如果你就部署一台机器,那会导致瞬时高峰时,一下子压垮你的系统,因为绝对无

法抗住每秒几千的请求高峰。此时我们就可以用 MQ 中间件来进行流量削峰

所有机器前面部署一层 MQ,平时每秒几百请求大家都可以轻松接收消息。一旦到了瞬

时高峰期,一下涌入每秒几千的请求,就可以积压在 MQ 里面,然后那一台机器慢慢

的处理和消费。等高峰期过了,再消费一段时间,MQ 里积压的数据就消费完毕了。

转自王炬

知道了为什么要使用消息中间件,下面直接上代码了。

1:首先我们先打开ActiveMQ

在这里插入图片描述
在这里插入图片描述
打开网站输入:http://127.0.0.1:8161/ 出现以下画面,则启动成功在这里插入图片描述

代码我直接贴出(点对点和发布订阅)的整合模式

Queue与Topic 消息传递模式区别

1)点对点(point-to-point,简称PTP)Queue消息传递模型:
通过该消息传递模型,一个应用程序(即消息生产者)可以向另外一个应用程序(即消息消费者)发送消息。在此传递模型中,消息目的地类型是队列(即Destination接口实现类实例由Session接口实现类实例通过调用其createQueue方法并传入队列名称而创建)。消息首先被传送至消息服务器端特定的队列中,然后从此对列中将消息传送至对此队列进行监听的某个消费者。同一个队列可以关联多个消息生产者和消息消费者,但一条消息仅能传递给一个消息消费者。如果多个消息消费者正在监听队列上的消息,,JMS消息服务器将根据“先来者优先”的原则确定由哪个消息消费者接收下一条消息。如果没有消息消费者在监听队列,消息将保留在队列中,直至消息消费者连接到队列为止。这种消息传递模型是传统意义上的懒模型或轮询模型。在此模型中,消息不是自动推动给消息消费者的,而是要由消息消费者从队列中请求获得。
2)发布/订阅(publish/subscribe,简称pub/sub)Topic消息传递模型:
通过该消息传递模型,应用程序能够将一条消息发送给多个消息消费者。在此传送模型中,消息目的地类型是主题(即Destination接口实现类实例由Session接口实现类实例通过调用其createTopic方法并传入主题名称而创建)。消息首先由消息生产者发布至消息服务器中特定的主题中,然后由消息服务器将消息传送至所有已订阅此主题的消费者。主题目标也支持长期订阅。长期订阅表示消费者已注册了主题目标,但在消息到达目标时该消费者可以处于非活动状态。当消费者再次处于活动状态时,将会接收该消息。如果消费者均没有注册某个主题目标,该主题只保留注册了长期订阅的非活动消费者的消息。与PTP消息传递模型不同,pub/sub消息传递模型允许多个主题订阅者接收同一条消息。JMS一直保留消息,直至所有主题订阅者都接收到消息为止。pub/sub消息传递模型基本上是一个推模型。在该模型中,消息会自动广播,消息消费者无须通过主动请求或轮询主题的方法来获得新的消息。
转自我傲故我狂

项目目录

在这里插入图片描述

导入包

        <!--整合消息队列ActiveMQ-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <!--若配置线程池则加入-->
        <dependency>
            <groupId>org.messaginghub</groupId>
            <artifactId>pooled-jms</artifactId>
        </dependency>

Controller(生产者)

order点对点 topic 发布订阅
package cn.hp.springboot_07.controller;

import cn.hp.springboot_07.service.ProducerService;
import cn.hp.springboot_07.utils.JsonData;
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.RestController;

import javax.jms.Destination;


@RestController
@RequestMapping("/api")
public class OderController {

    @Autowired
    private ProducerService producerService;

    @RequestMapping("/order")
    public Object order(String msg) {
        Destination destination = new ActiveMQQueue("tlog.quetue");
        producerService.sendMag(destination,msg);
        return JsonData.buildSuccess();
    }
    @RequestMapping("/topic")
    public Object topic(String msg){
        producerService.publicMsg(msg);
        return JsonData.buildSuccess();
    }
}

jsm(消费者)

NewComsumer

注意@Component交给spring容器管理

package cn.hp.springboot_07.jsm;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

/**
 * 订阅模式的 消费者,可以支持多个消费者消费
 */
@Component
public class NewComsumer {
    @JmsListener(destination = "news.topic",containerFactory = "jmsListenerContainerTopic")
    public void comsumer(String msg){
        System.out.println("消费者1接收的报文"+msg);

    }

    @JmsListener(destination = "news.topic",containerFactory = "jmsListenerContainerTopic")
    public void comsumer2(String msg){
        System.out.println("消费者2接收的报文"+msg);

    }

    @JmsListener(destination = "news.topic",containerFactory = "jmsListenerContainerTopic")
    public void comsumer3(String msg){
        System.out.println("消费者3接收的报文"+msg);

    }
}

OrderConsumer

package cn.hp.springboot_07.jsm;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class OrderConsumer {

    /**
     * JmsListener消息监听(时时监听,只有发现有消息发送过来,会like消费)
     */
    @JmsListener(destination = "tlog.quetue")
    public void  consumerOrder(String msg){
        System.out.println("接收的报文"+msg);

    }
}

ProducerService

package cn.hp.springboot_07.service;


import javax.jms.Destination;

/**
 * 消息的产生或者提供者 服务
 */
public interface ProducerService {
    /**
     * 发送消息,destination 消息接收者(他也是一个队列)
     * @param destination
     * @param msg
     */
    public void sendMag(Destination destination, String msg);

    /**
     * 发送默认消息,由默认消息队列接收
     * @param msg
     */
    public void sendDefaultMsg(String msg);

    /**
     * 订阅模式
     * @param msg
     */
    void publicMsg(String msg);
}

ProducerServiceImp

package cn.hp.springboot_07.service.imp;

import cn.hp.springboot_07.service.ProducerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import javax.jms.Queue;
import javax.jms.Topic;

@Service
public class ProducerServiceImp implements ProducerService {
    @Autowired
    private Queue queue;

    @Autowired
    private JmsMessagingTemplate template; //jsm消息模板,此处用于消息发送

    @Override
    public void sendMag(javax.jms.Destination destination, String msg) {
        template.convertAndSend(destination,msg);

    }

    @Override
    public void sendDefaultMsg(String msg) {
        template.convertAndSend(queue,msg);
    }

    @Autowired
    private Topic topic;//注入topic主题(其实就是一个队列)

    @Override
    public void publicMsg(String msg) {
        template.convertAndSend(topic,msg);
    }
}

Uitl(JsonData)

链接
增加一下访问O(∩_∩)O哈哈~

Springboot07Application

package cn.hp.springboot_07;

import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;

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

@SpringBootApplication
@EnableJms //支持jms
public class Springboot07Application {

    //在当前类引入一个队列
    /**
     * @Bean是将当前方法注入到spring容器,当前方法返回对象作为一个bean对象使用
     * @Commpoment 是将当前类注入到spring容器,将当前类的对象作为1个bean对象使用
     * @return
     */
    @Bean
    public Queue queue(){
        return new ActiveMQQueue("tlog.quetue");
    }

    /**
     * 发布订阅模式
     * @param
     */
    @Bean
    public Topic topic(){
        return new ActiveMQTopic("news.topic");
    }

    /**
     * 配置支持 点对点 和 发布订阅
     * @param activeMQConnectionFactory
     * @return
     */
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) {
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setPubSubDomain(true);
        bean.setConnectionFactory(activeMQConnectionFactory);
        return bean;
    }


    public static void main(String[] args) {
        SpringApplication.run(Springboot07Application.class, args);
    }

}

application.properties

最后一个,(spring.jms.pub-sub-domain)
如果单单开启点对点则不需要
如果要开启订阅模式,则开启
如果要点对点,订阅模式都要开启则不需要

#整合jms测试,安装在别的机器,防火墙和端口号记得开放,若防火墙已关闭,此处可忽略
spring.activemq.broker-url=tcp://127.0.0.1:61616
#集群配置
#spring.activemq.broker-url=failover:(tcp://localhost:61616,tcp://localhost:61617)
spring.activemq.user=admin
spring.activemq.password=admin
#使用连接池
spring.activemq.pool.enabled=true
#连接池最大连接数
spring.activemq.pool.max-connections=100
#默认点对点,开启订阅模式
#spring.jms.pub-sub-domain=true

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值