springboot-13-2-springboot整合activemq

1. Springboot整合activemq点对点消息

  • 添加 springboot activemq的starter依赖
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-activemqartifactId>
dependency>
  <dependency>
            <groupId>org.messaginghubgroupId>
            <artifactId>pooled-jmsartifactId>
        dependency>
  • 消息队列配置
#activemq配置  61616 为 activeMQ 的默认端口,这里必须是tcp协议,端口需要在linux上开放
spring.activemq.broker-url=tcp://192.168.0.100:61616
#集群配置
#spring.activemq.broker-url=failover:(tcp://localhost:61616,tcp://localhost:61617)
spring.activemq.user=admin
spring.activemq.password=admin
#下列配置要增加activemq-pool依赖
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=100
  • 开放61616端口
    在这里插入图片描述
  • 编写代码

启动类:

package com.example.springbootdemo5;

import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import javax.jms.Queue;
/**
 * 主类
 */
@SpringBootApplication
@EnableJms // 开启jms支持
public class MQApplication {
    /**
     * 创建一个activemq消息队列,交给springboot管理
     *  common.queue 是队列的名字
     * @return
     */
    @Bean
    public Queue queue(){
        return new ActiveMQQueue("common.queue");
    }
    public static void main(String[] args) {
        SpringApplication.run(MQApplication.class, args);
    }
}

生产者接口定义

package com.example.springbootdemo5.service;
import javax.jms.Destination;

/**
 * 消息生产者,实际项目中,消息生产者是独立的项目
 */
public interface ProducerService {
    /**
     * 指定消息队列和消息
     * @param destination 发送到的消息队列
     * @param message 待发送的消息
     */
    void sendMessage(Destination destination, final String message);

    /**
     * 使用默认消息队列发送消息
     * @param message 待发送的消息
     */
    void sendMessage(final String message);
}

生产者的实现

package com.example.springbootdemo5.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import javax.jms.Destination;
import javax.jms.Queue;
/**
 *  消息生产者实现类
 */
@Service
public class ProducerServiceImpl implements ProducerService {
    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;
    @Autowired
    private Queue queue;

    @Override
    public void sendMessage(Destination destination, String message) {
        jmsMessagingTemplate.convertAndSend(destination,message);
    }
    @Override
    public void sendMessage(String message) {
        jmsMessagingTemplate.convertAndSend(this.queue,message);
    }
}

消费者:

package com.example.springbootdemo5.activemq.consumer;

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

/**
 * common.queue队列的消费者实时监听该消息队列,一有消息就直接进行消费
 */
@Component
public class CommonConsumer {
    /**
     * 监听并处理common.queue的队列消息
     * @param text
     */
    @JmsListener(destination = "common.queue")
    public void consumeMessage(String text){
        System.out.println("commonConsumer收到报文是:" + text);
    }
}
package com.example.springbootdemo5.activemq.consumer;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

/**
 * order.queue队列的消费者实时监听该消息队列,一有消息就直接进行消费
 */
@Component
public class OrderConsumer {

    @JmsListener(destination = "order.queue")
    public void consumeMessage(String text){
        System.out.println("orderConsumer收到报文是:" + text);
    }
}

Controller

package com.example.springbootdemo5.controller;
import com.example.springbootdemo5.service.ProducerService;
import org.apache.activemq.command.ActiveMQQueue;
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.Destination;

@RestController
@RequestMapping("/api/v1")
public class OrderController {
    @Autowired
    private ProducerService producerService;

    /**
     * 订单消息队列
     * http://localhost:8080//api/v1/order?msg=orderqueue%20test
     * @param msg
     * @return
     */
    @GetMapping("/order")
    public Object order(String msg){
        Destination destination = new ActiveMQQueue("order.queue");
        producerService.sendMessage(destination, msg);
        return "success";
    }

    /**
     * http://localhost:8080//api/v1/common?msg=common01
     * 发送消息到默认消息队列
     * @param msg
     * @return
     */
    @GetMapping("/common")
    public Object common(String msg){
        producerService.sendMessage(msg);
        return "success";
    }

}
  • 启动activemq,进行测试
    在这里插入图片描述
    控制台打印:
    在这里插入图片描述
    activemq管理台可以看到消息入队和消费的记录:
    springboot-13-2-springboot整合activemq_第1张图片

2. Springboot整合activemaq发布/订阅模式

  • 修改配置文件,开启发布订阅模式

activemq默认消费者并不消费订阅发布类型的消息,是因为springboot默认采用点对点的模式进行消息的监听

# 开启发布-订阅模式
spring.jms.pub-sub-domain=true
  • ProducerService增加发布订阅模式生产者接口
package com.example.springbootdemo5.activemq.service;


import javax.jms.Destination;

/**
 * 消息生产者,实际项目中,消息生产者是独立的项目
 */
public interface ProducerService {
    /**
     * 指定消息队列和消息
     * @param destination 发送到的消息队列
     * @param message 待发送的消息
     */
    void sendMessage(Destination destination, final String message);

    /**
     * 使用默认消息队列发送消息
     * @param message 待发送的消息
     */
    void sendMessage(final String message);

    /**
     *  发布订阅模式-发布消息
     * @param message
     */
    void publish(final String message);
}
  • 实现类ProducerServiceImpl增加接口实现:
 // 发布订阅模式
    @Autowired
    private Topic topic;
    public void publish(String msg){
        this.jmsMessagingTemplate.convertAndSend(this.topic,msg);
    }
  • 定义三个消费者,都订阅video.topic这个主题 :
package com.example.springbootdemo5.activemq.consumer;

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

/**
 * 发布订阅模式消费者
 * 同一个消息,可以被不同的系统进行多次消费,处理不同的业务逻辑
 */
@Component
public class TopicConsumer {
    @JmsListener(destination = "video.topic")
    public void recive1(String text){
        System.out.println("consumer1-video.topic-message=" + text);
    }

    @JmsListener(destination = "video.topic")
    public void recive2(String text){
        System.out.println("consumer2-video.topic-message=" + text);
    }

    @JmsListener(destination = "video.topic")
    public void recive3(String text){
        System.out.println("consumer3-video.topic-message=" + text);
    }
}
  • 主启动类MQApplication 订阅topic:
 /**
     * activemq发布订阅模式,需要指定topic!
     * @return
     */
    @Bean
    public Topic topic(){
        return new ActiveMQTopic("video.topic");
    }
  • 测试controller增加:
 /**
     * http://localhost:8080/api/v1/publish?msg=pubsubtest
     * 发送消息到默认消息队列
     * @param msg
     * @return
     */
    @GetMapping("/publish")
    public Object publishMessage(String msg){
        producerService.publish(msg);
        return "success";
    }

在activemq管理台创建video.topic 这个topic, 浏览器输入http://localhost:8080/api/v1/publish?msg=pubsubtest进行测试,控制台打印
在这里插入图片描述
在这里插入图片描述

3. activemq同时支持点对点和发布订阅模式

在上面的例子中的写法,只支持发布订阅模式,如果两种模式都要支持,那么还需要做一些修改,在启动类MQApplication 给topic定义独立的JmsListenerContainer:

package com.example.springbootdemo5;

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 MQApplication {
    /**
     * 创建一个activemq消息队列,交给springboot管理
     *  common.queue 是队列的名字
     * @return
     */
    @Bean
    public Queue queue(){
        return new ActiveMQQueue("common.queue");
    }

    /**
     * activemq发布订阅模式,需要指定topic!
     * @return
     */
    @Bean
    public Topic topic(){
        return new ActiveMQTopic("video.topic");
    }

    /**
     * @JmsListener如果不指定独立的containerFactory的话只能消费queue消息,
     * 要同时支持点对点和发布订阅模式,需要给topic定义独立的JmsListenerContainer
     */
    @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(MQApplication.class, args);
    }
}

然后把配置文件中的spring.jms.pub-sub-domain=true 注释掉, 在消费者代码中,使用指定的containerFactory:(recive3不指定,就不会去消费消息了)

package com.example.springbootdemo5.activemq.consumer;

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

@Component
public class TopicConsumer {
    @JmsListener(destination = "video.topic",containerFactory = "jmsListenerContainerTopic")
    public void recive1(String text){
        System.out.println("consumer1-video.topic-message=" + text);
    }

    @JmsListener(destination = "video.topic", containerFactory = "jmsListenerContainerTopic")
    public void recive2(String text){
        System.out.println("consumer2-video.topic-message=" + text);
    }

    @JmsListener(destination = "video.topic")
    public void recive3(String text){
        System.out.println("consumer3-video.topic-message=" + text);
    }
}

你可能感兴趣的:(springboot)