Springboot使用RabbitMQ代码示例
示例说明
- 本示例使用slf4j-log4j12管理日志,需要排除spring-boot-start-amqp的logback-classic依赖以防止冲突。
- 消息队列几个要点
- 生产者:发送消息的程序
- 消费者:监听接收消费消息的程序
- 消息:一串二进制数据流
- 队列:消息的暂存区/存储区
- 转换器:消息的中转站,用于接收分发消息。其中有 fanout、direct、topic、headers 四种
- 路由:与转换器绑定即可路由消息到指定的队列!
依赖导入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<!--排除日志冲突-->
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
配置文件
spring:
rabbitmq:
host: 192.168.1.117
port: 5672
username: admin
password: admin
publisher-confirm-type: correlated #必须配置这个才会确认回调
publisher-returns: true
listener:
type: simple
simple:
acknowledge-mode: manual #手动确认
prefetch: 1 #限制每次发送一条数据。
concurrency: 3 #同一个队列启动几个消费者
max-concurrency: 3 #启动消费者最大数量
#重试策略相关配置
retry:
enabled: true #是否支持重试
max-attempts: 5
stateless: false
#时间策略乘数因子
multiplier: 1.0
initial-interval: 1000ms
max-interval: 10000ms
default-requeue-rejected: true
Bean配置类
@Configuration
public class RabbitMQConfig {
private static Logger log = LoggerFactory.getLogger(RabbitMQConfig.class);
@Autowired
private CachingConnectionFactory connectionFactory;
//目标转换器,需要哪种类型的转换器就创建哪种类型的转换器
@Bean
public DirectExchange exchangeHello(){
Map<String, Object> eArguments = new HashMap<>();
//备份交换器参数
eArguments.put("alternate-exchange", "exchange.ae");
return new DirectExchange("exchange.hello",true,false,eArguments);
}
//备份转换器
@Bean
public FanoutExchange exchangeAE(){
return new FanoutExchange("exchange.ae",true,false,null);
}
//死信转换器
@Bean
public TopicExchange exchangeDLX(){
return new TopicExchange("exchange.dlx",true,false,null);
}
//目标对列
@Bean
public Queue queueHello() {
Map<String, Object> args = new HashMap<>();
//声明死信交换器
args.put("x-dead-letter-exchange", "exchange.dlx");
//声明死信路由键
args.put("x-dead-letter-routing-key", "dlx.test" );
//声明队列消息过期时间 5000ms
args.put("x-message-ttl", 5000);
return new Queue("queue.hello",true,false,false,args);
}
//备份对列
@Bean
public Queue queueAE() {
return new Queue("queue.ae",true,false,false,null);
}
//死信对列
@Bean
public Queue queueDLX() {
return new Queue("queue.dlx",true,false,false,null);
}
//绑定目标对列
@Bean
public Binding bindingExchangeDirect(@Qualifier("queueHello")Queue queueHello, @Qualifier("exchangeHello") DirectExchange exchangeHello){
return BindingBuilder.bind(queueHello).to(exchangeHello).with("helloKey");
}
//绑定备份对列
@Bean
public Binding bindingExchangeAE(@Qualifier("queueAE")Queue queueAE, @Qualifier("exchangeAE") FanoutExchange exchangeAE){
return BindingBuilder.bind(queueAE).to(exchangeAE);
}
//绑定死信对列
@Bean
public Binding bindingExchangeDLX(@Qualifier("queueDLX")Queue queueAE, @Qualifier("exchangeDLX") TopicExchange exchangeDLX){
return BindingBuilder.bind(queueAE).to(exchangeDLX).with("dlx.*");
}
/**
* 如果需要在生产者需要消息发送后的回调,
* 需要对rabbitTemplate设置ConfirmCallback对象,
* 由于不同的生产者需要对应不同的ConfirmCallback,
* 如果rabbitTemplate设置为单例bean,
* 则所有的rabbitTemplate实际的ConfirmCallback为最后一次申明的ConfirmCallback。
* @return
*/
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
return template;
}
}
队列生产者
@Controller
public class HelloSender implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback{
private static Logger log = LoggerFactory.getLogger(HelloSender.class);
private RabbitTemplate rabbitTemplate;
//构造方法注入
@Autowired
public HelloSender(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
//这是是设置回调能收到发送到响应
rabbitTemplate.setConfirmCallback(this);
//如果设置备份队列则不起作用
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnCallback(this);
}
@RequestMapping("/send")
@ResponseBody
public void send() {
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
String sendMsg = "hello1 " + new Date();
System.out.println("Sender : " + sendMsg);
//convertAndSend(exchange:交换机名称,routingKey:路由关键字,object:发送的消息内容,correlationData:消息ID)
rabbitTemplate.convertAndSend("exchange.hello","helloKey", sendMsg,correlationId);
}
//回调确认
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if(ack){
log.info("消息发送成功:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
}else{
log.info("消息发送失败:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
}
}
//消息发送到转换器的时候没有对列,配置了备份对列该回调则不生效
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",exchange,routingKey,replyCode,replyText,message);
}
}
队列消费者
@Component
public class HelloConsumer {
private static Logger log = LoggerFactory.getLogger(HelloConsumer.class);
@RabbitHandler
@RabbitListener(queues = "queue.hello")
public void process(Message message, Channel channel) throws IOException {
log.info("receive: " + new String(message.getBody())+"《线程名:》"+Thread.currentThread().getName()+"《线程id:》"+Thread.currentThread().getId());
channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
}
}
启动类开启RabbitMQ
@EnableRabbit
@SpringBootApplication
public class RabbitmqApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitmqApplication.class,args);
}
}
来源:oschina
链接:https://my.oschina.net/u/4087795/blog/3218371