SpringBoot与RabbitMQ的集成非常简单,不需要做任何的额外设置,只需要引入相关依赖并对application.properties进行配置即可
一、创建SpringBoot项目
这边直接通过IDEA建立两个SpringBoot项目即可,一个作为消费端一个作为生产端,由于后文中消费端需要实时监控队列,要开启web服务,所以创建消费端时可以先选择web依赖包免得后面再去导入。
二、项目结构整理
1.生产端
在com.rabbitmq目录下创建以下目录
- 数据库配置信息: config.database
- 常量: constant
- 实体类: entity
- 持久层: mapper
- xml配置: mapping
- 工具类: utils
- 服务层: service
- 生产者具体服务: producer
2.消费端
在com.rabbitmq目录下创建以下目录
- 实体类: entity
- 工具类: utils
- 消费者具体服务: consumer
三、引入依赖
- 在两个项目中都引入以下依赖
<!--rabbitMQ依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--工具类依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
四、配置
在application.properties文件中进行如下配置
- rabbitMQ基本配置(生产端、消费端)
spring.rabbitmq.addresses=192.168.11.81:5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#rabbitMQ默认虚拟主机为`/`
spring.rabbitmq.virtual-host=/
spring.rabbitmq.connection-timeout=15000s
- rabbitMQ消费端配置
#并发数
spring.rabbitmq.listener.simple.concurrency=5
spring.rabbitmq.listener.simple.max-concurrency=10
#签收模式,auto:自动,manual:手工
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#限流,即指定一个线程中同一时间接收处理的消息数量,防止挤爆
spring.rabbitmq.listener.simple.prefetch=1
- 项目相关
#项目路径前缀,可以不设,SpringBoot默认就是"/"
server.servlet.context-path=/
#项目端口,消费端跟生产端端口需不同
server.port=8080
spring.http.encoding.charset=UTF-8
#日期格式化
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
#不允许传递空值
spring.jackson.default-property-inclusion=NON_NULL
五、示例代码编写
1.生产端
- 创建实体类
public class Order implements Serializable {
private static final long serialVersionUID = -236444488241798054L;
private String id;
private String name;
/**存储消息发送的唯一标识*/
private String massageId;
public Order() {
}
public Order(String id, String name, String massageId) {
this.id = id;
this.name = name;
this.massageId = massageId;
}
getter、setter......
}
注意,实体对象必须实现Serializable
,因为实体类会经过序列化后通过网络传输到MQ上
- 创建发送服务类
@Component
public class OrderSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(Order order) throws Exception {
CorrelationData correlationData = new CorrelationData();
correlationData.setId(order.getMassageId());
/**
* convertAndSend参数解释
* 第一个参数: exchange,指定交换机名称,交换机和队列可以在rabbitMQ图形洁面上进行创建
* 第二个参数: routingKey, 指定路由key
* 第三个参数: 传输的对象
* 第四个参数: correlationData,指定消息唯一id
**/
rabbitTemplate.convertAndSend("order-exchange", "order.abcd", order, correlationData);
}
}
这里因为我们使用了SpringBoot,只要进行对应的依赖包导入和配置,就可以直接使用RabbitTemplate
,十分便利。
- 创建测试类进行发送测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitmqProducerApplicationTests {
@Autowired
private OrderSender orderSender;
@Test
public void testSend() throws Exception {
Order order = new Order("1", "orderOne", System.currentTimeMillis() + "#" + UUID.randomUUID().toString());
orderSender.send(order);
}
}
运行发送成功后,可以到RabbitMQ的管理界面的队列中点击getMassage进行查看,会看到一串序列化后的数据。注意,这里的getMassage不表示将队列中的数据消费掉,只是简单的查看。
2.消费端
-
创建实体类
这里的需要与生产者端保持一致,否则在序列化以及反序列化时会出现问题,直接从生产者端复制
Order
即可。 -
创建消费服务类
public class OrderReceiver { @RabbitListener(bindings = @QueueBinding( value = @Queue(value = "order-queue", durable = "true"), exchange = @Exchange(value = "order-exchange", durable = "true", type = "topic"), key = "order.#" ) ) @RabbitHandler public void orderMassage(@Payload Order order, @Headers Map<String, Object> headers, Channel channel) throws IOException { System.out.println("--------接收到消息,开始消费--------"); System.out.println("订单号为: " + order.getId()); //确认签收消息 Long delivery = (Long) headers.get(AmqpHeaders.DELIVERY_TAG); channel.basicAck(delivery, false); } }
- @RabbitListener: 该注解用于配置所监听的虚拟机和队列以及routingkey,如果配置的虚拟机和队列不存在则会自动创建。
- @RabbitHandler: RabbitMQ提供了
@RabbitHandler
注解来对指定函数进行消息监听,该注解用在指定的消息处理函数上。 - 函数的第一个参数为消息体,第二个参数为消息头,分别通过使用
@Payload
和@Headers
注解进行接收,第三个参数为Channel
是因为我们配置了消息手动签收模式,需要通过Channel
类的basicAck
方法来进行签收,该方法的第一个参数需要从消息头中获取,第二个参数为boolean值,指定是否支持批量签收。
-
测试,直接启动消费端的SpringBoot项目,然后从生产端发送信息即可,消费端会自动消费RabbitMQ接收到的信息。