- 生产者
- 创建一个SpringBoot项目springboot-producer,作为RabbitMQ的生产者。
- 在pom文件中引入相关的依赖坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- 在配置文件中加入RabbitMQ的相关配置项
spring.rabbitmq.host=127.0.01
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#虚拟机
spring.rabbitmq.virtual-host=/test
#连接超时时间
spring.rabbitmq.connection-timeout=1000ms
#producer
#confirmslistener 消息是否投递成功
spring.rabbitmq.publisher-confirms=true
#没有队列接收消息时,返回一个状态
spring.rabbitmq.publisher-returns=true
#true当消息无法被正常送达的时候被返回给生产者,false丢弃
spring.rabbitmq.template.mandatory=true
- 创建一个需要发送消息的实体类(必须实现Serializable接口)
package com.kangswx.rabbitmq.springboot.domain;
import java.io.Serializable;
public class Employee implements Serializable {
private String empno;
private String name;
private Integer age;
public Employee() {
}
public Employee(String empno, String name, Integer age) {
this.empno = empno;
this.name = name;
this.age = age;
}
public String getEmpno() {
return empno;
}
public void setEmpno(String empno) {
this.empno = empno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
- 创建一个发送消息的类,在类上面需要添加@Component注解。在没有启动消费者之前,如果没有创建对应的交换机,则会投递消息失败,此时需要手动创建交换机。
import com.kangswx.rabbitmq.springboot.domain.Employee;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
//创建一个消息是否投递成功的监听对象confirmCallback
RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
// 第一个参数, 消息的附加消息(自定义id),
// 第二个参数, 消息是否被Broker接收,isAck(true接收,false拒收),
// 第三个参数, 如果拒收,则返回拒收的原因
@Override
public void confirm(CorrelationData correlationData, boolean isAck, String s) {
System.out.println("======》correlationData: " + correlationData);
System.out.println("======》isAck: " + isAck);
if(!isAck){
System.err.println("======》s: "+s);
}
}
};
//创建一个处理消息是否被队列接收的监听对象,如果没有队列接收发出的消息,则会自动调用returnedMessage方法,进行后续的处理
RabbitTemplate.ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() {
// 第一个参数, 被退回的消息
// 第二个参数, 错误编码
// 第三个参数, 错误描述
// 第四个参数, 交换机的名字
// 第五个参数, 路由Key
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchangeName, String routingKey) {
System.err.println("-----returnedMessage++code: " + replyCode +", Text: " + replyText);
System.err.println("-----returnedMessage++exchangeName: " + exchangeName +", routingKey: " + routingKey);
System.err.println("-----returnedMessage++message: " + message);
}
};
public void sendMessage(Employee employee){
//CorrelationData作用是作为消息的附加消息传递,通常我们用它来保存消息的自定义id
CorrelationData correlationData = new CorrelationData(employee.getEmpno()+"-"+new Date().getTime());
//设置消息是否投递成功的监听对象
rabbitTemplate.setConfirmCallback(confirmCallback);
//设置消息是否被队列成功接收的监听对象
rabbitTemplate.setReturnCallback(returnCallback);
//如果没有创建交换机的话,在投递消息的时候会投递失败
//第一个参数,交换机的名称
//第二个参数,路由key值
//第三个参数,消息主题对应的类
//第四个参数,消息的附件消息
rabbitTemplate.convertAndSend("springboot-exchange", "hr.employee", employee, correlationData);
}
}
- 消费者
- 创建一个SpringBoot项目springboot-consumer作为消息队列的消费者
- 在pom文件中引入相关的依赖坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- 在application.properties中添加RabbitMQ的相关配置项
spring.rabbitmq.host=127.0.01
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#虚拟机
spring.rabbitmq.virtual-host=/test
#连接超时时间
spring.rabbitmq.connection-timeout=1000ms
#consumer
#简单配置,手动的
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#最小的消费者数量
spring.rabbitmq.listener.simple.concurrency=1
#最大的消费者数量
spring.rabbitmq.listener.simple.max-concurrency=5
- 创建一个需要发送消息的实体类(该类的包名和类名必须与生产者一致 且 必须实现Serializable接口)
import java.io.Serializable;
public class Employee implements Serializable {
private String empno;
private String name;
private Integer age;
public Employee() {
}
public Employee(String empno, String name, Integer age) {
this.empno = empno;
this.name = name;
this.age = age;
}
public String getEmpno() {
return empno;
}
public void setEmpno(String empno) {
this.empno = empno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
- 创建一个发送消息的类,在类上面需要添加@Component注解。在消费者中主要通过注解的方式完成相关的功能实现。当队列或交换机不存在的时候,会自动创建相关的队列或交换机,并进行绑定。消费者会一直处于等待状态,当有新的消息进来的时候,就会自动触发消费者的相关方法来处理消息。
package com.kangswx.rabbitmq.springboot;
import com.kangswx.rabbitmq.springboot.domain.Employee;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;
@Component
public class MessageConsumer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 用于接收消息的方法
* RabbitListener用于声明定义消息接收的队列与exchange绑定的信息,使消费者一直处于等待状态
* 在SpringBoot中消费者这端使用注解获取消息
*/
@RabbitListener(
bindings = @QueueBinding(
//队列的信息,当队列不存在的时候,会自动创建一个队列,并绑定下面的交换机
value = @Queue(value = "springboot-queue", durable = "true"),
//交换机的信息
exchange = @Exchange(value = "springboot-exchange", durable = "true", type = "topic"),
//路由规则
key = "#"
)
)
/**
* RabbitHandler注解,通知SpringBoot该方法用于接收消息,这个方法运行后将处于等待状态,
* 有新的消息进来就会自动触发该方法处理消息
*
* @param employee Payload将接收的消息反序列化后注入到Employee对象
* @param channel 用于接收消息后进行Ack处理
* @param headers headers获取辅助描述信息
*/
@RabbitHandler
public void handleMessage(@Payload Employee employee, Channel channel,
@Headers Map<String, Object> headers){
System.out.println("=====================");
System.out.println("empno: "+employee.getEmpno() + ", name:" + employee.getName() + ", age:" + employee.getAge());
long tag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
try {
//第一个参数,tag
//第二个参数,是否批量接收
channel.basicAck(tag, false);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("=====================");
}
}
- 生产者代码见 SpringBoot整合RabbitMQ生产者代码
- 消费者代码见 SpringBoot整合RabbitMQ消费者代码