1、docker-compose安装rabbitmq
version: '3'
services:
rabbitmq:
image: rabbitmq:management-alpine
container_name: rabbitmq
environment:
- RABBITMQ_DEFAULT_USER=admin
- RABBITMQ_DEFAULT_PASS=admin
restart: always
ports:
- "15672:15672"
- "5672:5672"
logging:
driver: "json-file"
options:
max-size: "200k"
max-file: "10"
2、maven配置文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ilovewl</groupId>
<artifactId>rabbitmq-demo</artifactId>
<version>1.0</version>
<name>rabbitmq-demo</name>
<description>rabbitmq Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3、重要的几个java类
RabbitmqConfig类
package com.ilovewl.rabbitmqdemo.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* rabbitMq 配置类
* @author liuchangrong
*/
@Configuration
public class RabbitmqConfig {
@Autowired
private CachingConnectionFactory connectionFactory;
/**
* 定义一个hello的队列
* Queue 可以有4个参数
* 1.队列名
* 2.durable 持久化消息队列 ,rabbitmq重启的时候不需要创建新的队列 默认true
* 3.auto-delete 表示消息队列没有在使用时将被自动删除 默认是false
* 4.exclusive 表示该消息队列是否只在当前connection生效,默认是false
*/
@Bean
public Queue helloQueue() {
return new Queue("queue-test");
}
/** ======================== 定制一些处理策略 =============================*/
/**
* 定制化amqp模版
*
* ConfirmCallback接口用于实现消息发送到RabbitMQ交换器后接收ack回调 即消息发送到exchange ack
* ReturnCallback接口用于实现消息发送到RabbitMQ 交换器,但无相应队列与交换器绑定时的回调 即消息发送不到任何一个队列中 ack
*/
@Bean
public RabbitTemplate rabbitTemplate() {
Logger log = LoggerFactory.getLogger(RabbitTemplate.class);
RabbitTemplate rabbitTemplate = new RabbitTemplate();
rabbitTemplate.setConnectionFactory(connectionFactory);
// 消息发送失败返回到队列中, yml需要配置 publisher-returns: true
rabbitTemplate.setMandatory(true);
// 消息返回, yml需要配置 publisher-returns: true
rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
String correlationId = message.getMessageProperties().getCorrelationId();
log.debug("消息:{} 发送失败, 应答码:{} 原因:{} 交换机: {} 路由键: {}", correlationId, replyCode, replyText, exchange, routingKey);
});
// 消息确认, yml需要配置 publisher-confirms: true
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
// log.debug("消息发送到exchange成功,id: {}", correlationData.getId());
} else {
log.debug("消息发送到exchange失败,原因: {}", cause);
}
});
return rabbitTemplate;
}
}
消费者类
package com.ilovewl.rabbitmqdemo.config;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
* @author liuchangrong
*/
@Component
public class Consumer {
private Logger log = LoggerFactory.getLogger(Consumer.class);
@RabbitListener(queues = "queue-test")
public void process(Message message, Channel channel) throws IOException {
// 采用手动应答模式, 手动确认应答更为安全稳定
channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
log.info("receive: " + new String(message.getBody()));
}
}
生产者类
package com.ilovewl.rabbitmqdemo.config;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author liuchangrong
*/
@Component
public class Producer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 给hello队列发送消息
*/
public void send() {
for (int i =0; i< 100; i++) {
String msg = "hello, 序号: " + i;
System.out.println("Producer, " + msg);
rabbitTemplate.convertAndSend("queue-test", msg);
}
}
}
4、配置文件application.properties
spring.rabbitmq.host=xxx.xxx.xxx.xxx
spring.rabbitmq.port=5672
#一般默认的密码是guest guest,因为在上面docker-compose安装的时候我指定了用户名和密码
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin
#消息发送到交换机确认机制,是否确认回调
spring.rabbitmq.publisher-confirms=true
#消息发送到交换机确认机制,是否返回回调
spring.rabbitmq.publisher-returns=true
#手动应答
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#指定最小的消费者数量
spring.rabbitmq.listener.simple.concurrency=1
#指定最小的消费者数量
spring.rabbitmq.listener.simple.max-concurrency=1
#是否支持重试
spring.rabbitmq.listener.simple.retry.enabled=true
5、启动程序即可看到控制台打印消息。
参考别人博客,原理还不是很清楚,消息确认机制是一脸懵,加油,要努力了。
end