Spring与消息队列
文章目录
一、SpringBoot使用JMS
1、什么是JMS
JMS是java的一个标准,定义了使用消息代理的通用API,相当于JDBC,让java使用基于消息的异步通讯更加简单。
2、使用ActiveMQ收发消息
控制台地址(http://localhost:8161/admin/)
producer端:
添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
编写配置:
spring:
#使用的消息队列类型
activemq:
#链接消息代理的协议ip和端口
broker-url: tcp://localhost:61616
#链接代理的用户名密码
user: admin
password: admin
#是否开启内存代理 如果不是同一个程序收发消息 则选择false默认true
in-memory: false
#jms设置
jms:
#模板设置
template:
#设置默认主题
default-destination: testmq
编写代码:
@RestController
public class producerController {
//依赖注入JmsTemplate
@Autowired
private JmsTemplate jmsTemplate;
@PostMapping(value = "/message")
public ResponseEntity<String> message(@RequestParam("msg") String msg){
//使用JmsTemplate的send方法发送消息
jmsTemplate.send((session)->{
return session.createObjectMessage(msg);
});
return ResponseEntity.ok(msg);
}
}
这里send方法有很多重载,使用默认的send方法则将消息发送到默认主题,也就是配置文件中配置的默认主题。也可以自行指定主题。
consumer端:
添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
编写配置:
spring:
activemq:
broker-url: tcp://localhost:61616
user: admin
password: admin
编写代码:
@Service
public class consumerService {
@JmsListener(destination = "testmq")
public void getMessage(String msg){
System.out.println("--->" + msg);
}
}
这里使用的是监听模式(推送模式)来收取消息,也可以编码手动接收(拉取模式)来接收消息,按照需求进行选择。拉去模式是消息驱动的,只需要在接收消息的方法上添加@JmsListener注解,设置感兴趣的topic即可。
3、遇到的问题
1、这里需要注意,如果监听的方法有返回值,则会抛出异常,无法寻找到主题。异常信息如下。
Failed to send reply with payload [test]; nested exception is javax.jms.InvalidDestinationException: Cannot determine response destination: Request message does not contain reply-to destination, and no default response destination set.
2、如果使用send方法发送领域对象,接收端需要手动进行转换,转换之前需要在容器中注入MessageConverter(springboot2.5.4中居然没有自动注入)。
3、使用SimpleMessageConverter进行转换时,转换的对象必须和发送时的对象全限定名一样,可以将领域对象打包发送到mvn仓库再进行引入。
4、如何使用send方法发送一个对象:
首先选择要使用的消息转换器并进行配置,这里使用MappingJackson2MessageConverter。
@Bean
public MappingJackson2MessageConverter messageConverter(){
//创建新的消息转换器
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
//设置标识类型的属性->也就是添加一个属性到mes