本文是工作之余的随手记,记录在工作期间使用 RabbitMQ
的笔记。
文章目录
1、实现方式说明
SpringBoot 使用 spring-boot-starter-amqp 起步依赖实现 RabbitMQ 代码示例(一)
本文是承接上文,使用以下方式实现 RabbitMQ 功能。
- 发送消息有多种解决方式,本文使用注入
RabbitTemplate
,直接调用convertAndSend
方法发送消息,支持自动消息转换(如JSON
序列化)。 - 消费消息有多种解决方式,本文在方法上使用
@RabbitListener
注解监听队列,支持消息体自动反序列化为对象。
1、实现代码结构如下:
2、交换机
3、队列和路由键绑定
2、配置文件:application.yml
server:
port: 8089
#开发站
spring:
rabbitmq:
host: 10.106.18.54
port: 5672
username: root
password: 123456789
listener:
type: direct
direct:
prefetch: 250
concurrency: 16 # 消费线程池核心线程数
max-concurrency: 32 # 消费线程池最大线程数
acknowledge-mode: auto # 自动确认消息
exchangeRjwTest: 'sync.ex.rjw.test'
queueRjwTest: 'ha.queue.rjw.test'
routeRjwTest: 'route.rjw.test'
3、依赖文件:pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
4、配置类:RabbitMQConfig
package com.wen.rabbit.config;
import lombok.Data;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author : rjw
* @date : 2025-07-07
*/
@Configuration
@Data
public class RabbitMQConfig {
@Value("${spring.rabbitmq.exchangeRjwTest}")
private String exchangeRjwTest;
@Value("${spring.rabbitmq.queueRjwTest}")
private String queueRjwTest;
@Value("${spring.rabbitmq.routeRjwTest}")
private String routeRjwTest;
@Bean
public DirectExchange exchangeRjwTest() {
return new DirectExchange(exchangeRjwTest);
}
@Bean
public Queue queueRjwTest() {
return new Queue(queueRjwTest);
}
@Bean
public Binding bindingRjwTest01() {
return BindingBuilder.bind(queueRjwTest()).to(exchangeRjwTest()).with(routeRjwTest);
}
}
5、消息类:MQEntity
package com.wen.rabbit.model;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
/**
* @author : rjw
* @date : 2025-07-07
*/
@Data
public class MQEntity<T> {
private String type;
private long tm;
private int crmId;
private String who;
private boolean requeue;
private T data;
private JSONObject attachments;
}
6、消息类:TestEntity
package com.wen.rabbit.model;
import lombok.Data;
/**
* @author : rjw
* @date : 2025-07-07
*/
@Data
public class TestEntity {
private String name;
private Integer age;
private String sex;
}
7、MQ客户端:MQClient
package com.wen.rabbit.service;
import com.wen.rabbit.config.RabbitMQConfig;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
/**
* @author : rjw
* @date : 2025-07-07
*/
@Service
@Slf4j
public class MQClient {
@Resource
private RabbitTemplate rabbitTemplate;
@Resource
private RabbitMQConfig rabbitMQConfig;
public boolean send(String exchange, String routingKey, Object message) {
try {
rabbitTemplate.convertAndSend(exchange, routingKey, message);
return true;
} catch (AmqpException e) {
log.error("fail, exchange:{}, routingKey:{}, message:{}, exception:{}",
exchange, routingKey, message, e.toString());
return false;
}
}
}
8、事件抽象接口:MqEvent
package com.wen.rabbit.service;
import java.util.List;
/**
* @author : rjw
* @date : 2025-07-07
*/
public interface MqEvent<T> {
/**
* 获取MQ的路由主键
* @return
*/
public String getRoutingKey();
/**
* 获取数据
* @return
*/
public List<T> getData();
}
9、事件类:MqEventTest
package com.wen.rabbit.service;
import com.wen.rabbit.model.TestEntity;
import lombok.Getter;
import java.util.List;
/**
* @author : rjw
* @date : 2025-07-07
*/
@Getter
public class MqEventTest implements MqEvent {
private String routeKey;
private final List<TestEntity> data;
public MqEventTest(String routeKey, List<TestEntity> data) {
this.routeKey = routeKey;
this.data = data;
}
@Override
public String getRoutingKey() {
return this.routeKey;
}
@Override
public List<TestEntity> getData() {
return this.data;
}
}
10、发布者:MQPublisher
package com.wen.rabbit.service;
import com.alibaba.fastjson.JSON;
import com.wen.rabbit.config.RabbitMQConfig;
import com.wen.rabbit.model.MQEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author : rjw
* @date : 2025-07-07
*/
@Component
public class MQPublisher {
@Autowired
private MQClient mqClient;
@Autowired
private RabbitMQConfig mqConfig;
public void publish(MqEvent mqEvent) {
MQEntity<List> mqEntity = new MQEntity<>();
mqEntity.setTm(System.currentTimeMillis());
mqEntity.setData(mqEvent.getData());
mqEntity.setWho("one");
mqEntity.setRequeue(false);
mqClient.send(mqConfig.getExchangeRjwTest(), mqEvent.getRoutingKey(), JSON.toJSONBytes(mqEntity));
}
}
11、监听者(消费者):DataListener
package com.wen.rabbit;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.TypeReference;
import com.rabbitmq.client.Channel;
import com.wen.rabbit.model.MQEntity;
import com.wen.rabbit.model.TestEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author : rjw
* @date : 2025-07-07
*/
@Component
@Slf4j
public class DataListener {
@RabbitListener(queues = {"${spring.rabbitmq.queueRjwTest}"}, concurrency = "1", ackMode = "MANUAL")
public void dataListenerEvent(Message message, Channel channel) throws IOException {
long deliveryTag = message.getMessageProperties().getDeliveryTag();
String consumerQueue = message.getMessageProperties().getConsumerQueue();
try {
byte[] body = message.getBody();
String jsonBody = new String(body, StandardCharsets.UTF_8);
MQEntity<List<TestEntity>> mqEntity = JSON.parseObject(jsonBody, new TypeReference<>() {
});
log.info("接收到的MQ消息是: {}", mqEntity.toString());
channel.basicAck(deliveryTag, false);
} catch (JSONException e) {
log.error("parse mq msg exception, queue:{}, deliveryTag:{}", consumerQueue, deliveryTag, e);
channel.basicReject(deliveryTag, false);
} catch (RuntimeException e) {
log.error("handle mq msg exception, queue:{}, deliveryTag:{}", consumerQueue, deliveryTag, e);
channel.basicReject(deliveryTag, false); //为true会重新放回队列
}
}
}
12、生产者:DataProducer
package com.wen.rabbit;
import com.alibaba.fastjson.JSON;
import com.wen.rabbit.config.RabbitMQConfig;
import com.wen.rabbit.model.TestEntity;
import com.wen.rabbit.service.MQPublisher;
import com.wen.rabbit.service.MqEventTest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author : rjw
* @date : 2025-07-07
*/
@Slf4j
@Component
@EnableScheduling
public class DataProducer {
@Autowired
private MQPublisher publisher;
@Autowired
private RabbitMQConfig mqConfig;
@Scheduled(cron = "0 0/1 * * * ?")
public void createDataJob() {
log.info("生产者生成数据开始-----");
for (int i = 0; i < 20; i++) {
TestEntity testEntity = new TestEntity();
testEntity.setName("Jack" + i);
testEntity.setAge(20 + i);
testEntity.setSex(i % 2 == 0 ? "man" : "woman");
publisher.publish(new MqEventTest(mqConfig.getRouteRjwTest(), List.of(testEntity)));
log.info("消息数据:{}", JSON.toJSONString(new MqEventTest(mqConfig.getRouteRjwTest(), List.of(testEntity))));
}
log.info("生产者生成数据结束=====");
}
}
注意:本文是使用 SpringBoot 项目为核心进行开发,所使用的依赖和类都如上展示,可以应用于基本业务逻辑。