<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
启动类:
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默认消费者并不消费订阅发布类型的消息,是因为springboot默认采用点对点的模式进行消息的监听
# 开启发布-订阅模式
spring.jms.pub-sub-domain=true
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);
}
// 发布订阅模式
@Autowired
private Topic topic;
public void publish(String msg){
this.jmsMessagingTemplate.convertAndSend(this.topic,msg);
}
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);
}
}
/**
* activemq发布订阅模式,需要指定topic!
* @return
*/
@Bean
public Topic topic(){
return new ActiveMQTopic("video.topic");
}
/**
* 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进行测试,控制台打印
在上面的例子中的写法,只支持发布订阅模式,如果两种模式都要支持,那么还需要做一些修改,在启动类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);
}
}