activemq是一个非常常用的消息中间件,本节课进行SpringBoot2.0整合activemq队列模式的讲解,关于activemq基本介绍网上很多,这里就不进行详细讲解了。
SpringBoot关于activemq的官网:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-activemq,这里有对SpringBoot使用activemq详细讲解,下面直接上代码
一个依赖是activemq的,另外一个是activemq的线程池,类似于jdbc连接池
org.springframework.boot
spring-boot-starter-activemq
org.apache.activemq
activemq-pool
spring:
activemq:
broker-url: tcp://localhost:61616
user: admin
password: admin
#下列配置要增加依赖
pool.enabled: true
pool.max-connections: 100
在启动类中创建一个队列交给Spring管理,后续需要使用的时候直接依赖注入就行
package net.xdclass.base_project;
import org.apache.activemq.command.ActiveMQQueue;
import org.mybatis.spring.annotation.MapperScan;
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 //一个注解顶下面3个
@MapperScan("net.xdclass.base_project.mapper")
@EnableJms//开启支持jms
public class XdclassApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(XdclassApplication.class, args);
}
@Bean//创建一个bean,交给Spring管理
public Queue queue(){
return new ActiveMQQueue("testqueue");//new一个名字叫testqueue的队列
}
}
下面我们写消息生产者,这里有两种,先定义一个service:
package net.xdclass.base_project.service;
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);
}
实现类:
package net.xdclass.base_project.service.impl;
import net.xdclass.base_project.service.ProducerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
import javax.jms.Destination;
import javax.jms.Queue;
@Service
public class ProducerServiceImpl implements ProducerService {
@Autowired
private JmsMessagingTemplate jmsTemplate;
@Autowired
private Queue queue;
//发送消息,destination是发送到的队列,message是待发送的消息
@Override
public void sendMessage(Destination destination, String message) {
jmsTemplate.convertAndSend(destination,message);
}
//发送消息,destination是发送到的队列,message是待发送的消息
@Override
public void sendMessage(String message) {
jmsTemplate.convertAndSend(this.queue,message);
}
}
这里写一个控制器模拟微信支付完成的回调函数,调用我们的接口,然后进行消息的发送,这里order接口我们创建了一个order.queue的destination
package net.xdclass.base_project.controller;
import javax.jms.Destination;
import net.xdclass.base_project.domain.JsonData;
import net.xdclass.base_project.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;
/**
* 功能描述:模拟微信支付回调
*
*/
@RestController
@RequestMapping("/api/v1")
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();
}
}
启动项目,访问http://localhost:8080/api/v1/order?msg=123
查看activemq控制台,我们发现已经生成一个order.queue,并且里面有一条未消费的消息
下面我们写消费者进行消息的消费:
package net.xdclass.base_project.jms;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class OrderConsumer {
@JmsListener(destination = "order.queue")
public void receiveQueue(String text){
System.out.println("orderqueue的报文为:"+text);
}
}
server:
port: 8081
spring:
activemq:
broker-url: tcp://192.168.1.11:61616
user: admin
password: admin
#下列配置要增加依赖
pool.enabled: true
pool.max-connections: 100
#需要加入配置文件,支持发布订阅模型,默认只支持点对点
jms:
pub-sub-domain: true
与queue一样,在启动类中新增一个topic的bean,这样使用的时候直接注入就行了
@Bean
public Topic topic(){
return new ActiveMQTopic("video.topic");
}
Service:接着上面队列的消息生产这下面加入一个方法
package net.xdclass.base_project.service;
import javax.jms.Destination;
/**
* 功能描述:消息生产
*
* 创建时间:May 3, 2018 9:48:30 PM
*
*/
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);
}
ServiceImpl:注入刚刚创建的topic,然后调用发送的方法:
package net.xdclass.base_project.service.impl;
import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;
import net.xdclass.base_project.service.ProducerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
/**
* 功能描述:消息生产者
*
* 创建时间:May 2, 2018 11:29:47 PM
*
*/
@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( message);
}
//=======发布订阅相关代码=========
@Autowired
private Topic topic;
@Override
public void publish(String msg) {
this.jmsTemplate.convertAndSend(this.topic, msg);
}
}
下面在刚刚queue的控制器中写一个调用消息发布的接口:
/**
* 发布消息:生产者
* @param msg
* @return
*/
@GetMapping("common")
public Object common(String msg){
producerService.sendMessage(msg);
return JsonData.buildSuccess();
}
新建一个订阅者,订阅刚刚定义的发布者
package net.xdclass.base_project.jms;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@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);
}
}
发现已经访问成功,并且成功订阅,发布订阅模式消息不会被消费掉,他会一直在mq上。
这时候我们再返回前面发送一个队列的消息:
/**
* 同时支持topic与queue
* @param activeMQConnectionFactory
* @return
*/
@Bean
public JmsListenerContainerFactory> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) {
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
bean.setPubSubDomain(true);
bean.setConnectionFactory(activeMQConnectionFactory);
return bean;
}
@JmsListener(destination="video.topic",containerFactory = "jmsListenerContainerTopic")
public void receive1(String text){
System.out.println("video.topic 消费者:receive1="+text);
}
#需要加入配置文件,支持发布订阅模型,默认只支持点对点
# jms:
# pub-sub-domain: true
源码地址:https://gitee.com/xuxinsunqizheng/springboot_module.git