1、配置文件
#整合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
#下列配置要增加依赖。是否开启activemq连接池
spring.activemq.pool.enabled=true
#最大连接数
spring.activemq.pool.max-connections=100
#开启支持发布订阅模型,activemq默认只支持点对点
spring.jms.pub-sub-domain=true
2、启动类
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.jms.annotation.EnableJms;
import javax.jms.Queue;
import javax.jms.Topic;
@SpringBootApplication
@EnableJms //开启支持jms
public class FbiaoApplication {
@Bean //将主题对象交给spring管理
public Topic topic(){
return new ActiveMQTopic("video.topic");
}
@Bean //交给spring管理,方便后续注入
public Queue queue(){
//common.queue默认的消息队列
return new ActiveMQQueue("common.queue");
}
public static void main(String[] args) {
SpringApplication.run(FbiaoApplication.class, args);
}
}
3、发布生产者
import javax.jms.Destination;
/**
* 功能描述:消息生产
*/
public interface ProducerService {
/**
* 功能描述:指定消息队列,还有消息
* @param destination
* @param message
*/
public void sendMessage(Destination destination, final String message);
/**
* 功能描述:使用默认消息队列, 发送消息
* @param message
*/
public void sendMessage( final String message);
/**
* 功能描述:消息发布者
* @param msg
*/
public void publish(String msg);
}
import org.springframework.jms.core.JmsMessagingTemplate;
import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;
/**
* 功能描述:消息生产者
*/
@Service
public class ProducerServiceImpl implements ProducerService {
@Autowired
private Queue queue;
@Autowired
private JmsMessagingTemplate jmsTemplate; //用来发送消息到broker的对象
//发送消息,destination是发送到的队列,message是待发送的消息
@Override
public void sendMessage(Destination destination, String message) {
jmsTemplate.convertAndSend(destination, message);
}
//发送消息,destination是发送到的队列,message是待发送的消息
@Override
public void sendMessage(final String message) {
jmsTemplate.convertAndSend(this.queue,message);
}
//=======发布订阅相关代码=========
@Autowired
private Topic topic;
@Override
public void publish(String msg) {
this.jmsTemplate.convertAndSend(this.topic, msg);
}
}
4、测试发布订阅者
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class TopicSub {
@JmsListener(destination="video.topic")
public void receive1(String text){
System.out.println("video.topic 消费者:receive1="+text);
}
@JmsListener(destination="video.topic")
public void receive2(String text){
System.out.println("video.topic 消费者:receive2="+text);
}
@JmsListener(destination="video.topic")
public void receive3(String text){
System.out.println("video.topic 消费者:receive3="+text);
}
}
5、测试发布生产者消息接口
import javax.jms.Destination;
import org.apache.activemq.command.ActiveMQQueue;
/**
* 功能描述:模拟下单
*/
@RestController
@RequestMapping("/api/activemq")
public class OrderController {
@Autowired
private ProducerService producerService;
/**
* 功能描述:模拟下单
* @param msg 下单信息
* @return
*/
@GetMapping("order")
public Object order(String msg){
Destination destination = new ActiveMQQueue("order.queue");
producerService.sendMessage(destination, msg);
return JsonData.buildSuccess();
}
@GetMapping("common")
public Object common(String msg){
producerService.sendMessage(msg);
return JsonData.buildSuccess();
}
//消息发布
@GetMapping("topic")
public Object topic(String msg){
producerService.publish(msg);
return JsonData.buildSuccess();
}
}
6、测试发布生产者,订阅者
192.168.1.188:8080/api/activemq/topic?msg=发布订阅消息1
192.168.1.188:8080/api/activemq/common?msg=测试点对点默认消息队列
192.168.1.188:8080/api/activemq/order?msg=测试点对点指定消息队列
控制台并未打印出点对点的生产消费信息,但队列里有尚未消费的消息,消费者数量113
7、我们知道activemq默认只支持点对点模型,如何让它同时支持点对点和发布订阅模型呢?
7.1、解决办法
(1)默认消费者并不会消费订阅发布类型的消息,这是由于springboot默认采用的是p2p模式进行消息的监听
修改配置:spring.jms.pub-sub-domain=true使其支持发布订阅模型
(2)@JmsListener如果不指定独立的containerFactory的话是只能消费queue消息
修改订阅者container:containerFactory=“jmsListenerContainerTopic”
(3)需要给topic定义独立的JmsListenerContainer
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) {
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
bean.setPubSubDomain(true);
bean.setConnectionFactory(activeMQConnectionFactory);
return bean;
}
(4)在配置文件里面,注释掉 #spring.jms.pub-sub-domain=true
7.2、修改启动类
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 FbiaoApplication {
@Bean //将主题对象交给spring管理
public Topic topic(){
return new ActiveMQTopic("video.topic");
}
@Bean //交给spring管理,方便后续注入
public Queue queue(){
//common.queue默认的消息队列
return new ActiveMQQueue("common.queue");
}
public static void main(String[] args) {
SpringApplication.run(FbiaoApplication.class, args);
}
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) {
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
bean.setPubSubDomain(true);
bean.setConnectionFactory(activeMQConnectionFactory);
return bean;
}
}
7.3、修改订阅者
import org.springframework.jms.annotation.JmsListener;
@Component
public class TopicSub {
@JmsListener(destination="video.topic", containerFactory="jmsListenerContainerTopic")
public void receive1(String text){
System.out.println("video.topic 消费者:receive1="+text);
}
@JmsListener(destination="video.topic", containerFactory="jmsListenerContainerTopic")
public void receive2(String text){
System.out.println("video.topic 消费者:receive2="+text);
}
@JmsListener(destination="video.topic", containerFactory="jmsListenerContainerTopic")
public void receive3(String text){
System.out.println("video.topic 消费者:receive3="+text);
}
}
7.4在配置文件里面,注释掉
#spring.jms.pub-sub-domain=true
192.168.1.188:8080/api/activemq/topic?msg=发布订阅消息2
192.168.1.188:8080/api/activemq/common?msg=测试点对点默认消息队列1
192.168.1.188:8080/api/activemq/order?msg=测试点对点指定消息队列1