安装rabbitMq
在Linux中安装docker-compose
安装教程
1.1 docker-compose安装rabbitMq
version: '3.0'
services:
rabbitmq:
image: rabbitmq:3.10-management
container_name: docker-rabbitmq
restart: always
hostname: rabbitmq_host
ports:
- 15672:15672 # web UI 管理接口
- 5672:5672 # 生产者和消费者连接使用的接口
volumes:
- ./log:/home/software/rabbitmq/logs #挂载 RabbitMQ日志
- ./data:/home/software/rabbitmq/data #挂载 RabbitMQ数据
environment:
- RABBITMQ_DEFAULT_USER=root
- RABBITMQ_DEFAULT_PASS=123456
然后启动rabbitmq
1.2 新建springboot项目
1.2.1 pom文件引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
1.2.2 application.yml文件
spring:
rabbitmq:
port: 5672
username: root
password: 123456
host: 192.168.222.135
listener:
simple:
prefetch: 1
acknowledge-mode: manual #指定消息确认模式为手动确认
retry:
enabled: true
max-attempts: 3 #重试次数
publisher-returns: true # 发送返回监听回调
publisher-confirm-type: correlated #配置消息发送到交换器之后是否触发回调方法
redis:
port: 6379
host: localhost
password:
database: 1
server:
port: 10001
创建order-client和order-server项目
定义常量池
public class StringConstant {
/**
* 电脑供应商
*/
public static final String QUEUE_COMPUTER_NAME = "order_computer";
/**
* 水果供应商
*/
public static final String QUEUE_FRUIT_NAME = "order_fruit";
/**
* Exchange名字
*/
public static final String ORDER_EXCHANGE_NAME = "order_exchange";
}
创建User类
@Data
public class User {
private String id;
private String name;
private Integer age;
private String phone;
}
1.2.3 定义队列
@Configuration
public class RabbitMQConfig {
@Bean("computerExchange")
public Exchange computerExchange() {
return ExchangeBuilder.topicExchange(StringConstant.ORDER_EXCHANGE_NAME).durable(true).build();
}
@Bean("computerQueue")
public Queue computerQueue() {
return QueueBuilder.durable(StringConstant.QUEUE_COMPUTER_NAME).build();
}
@Bean
public Binding computerBinding(@Qualifier("computerQueue") Queue queue ,@Qualifier("computerExchange") Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("order.computer").noargs();
}
@Bean
public Binding computerUserBinding(@Qualifier("computerQueue") Queue queue ,@Qualifier("computerExchange") Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("order.user.#").noargs();
}
@Bean("fruitExchange")
public Exchange fruitExchange() {
return ExchangeBuilder.topicExchange(StringConstant.ORDER_EXCHANGE_NAME).durable(true).build();
}
@Bean("fruitQueue")
public Queue fruitQueue() {
return QueueBuilder.durable(StringConstant.QUEUE_FRUIT_NAME).build();
}
@Bean
public Binding UserBinding(@Qualifier("fruitQueue") Queue queue ,@Qualifier("fruitExchange") Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("order.user.#").noargs();
}
@Bean
public Binding fruitBinding(@Qualifier("fruitQueue") Queue queue ,@Qualifier("fruitExchange") Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("order.fruit").noargs();
}
}
1.2.4 发送方
@RestController
@RequestMapping("/order")
public class OrderController {
@Resource
private RabbitTemplate rabbitTemplate;
@PostMapping("/testBind")
public String testBind(@RequestBody User user) {
rabbitTemplate.setConfirmCallback((correlationData, b, s) -> {
System.out.println(b);
});
System.out.println("我是testBind发送方");
rabbitTemplate.convertAndSend("order_exchange","",JsonUtil.JsonStr(user) ,message -> {
message.getMessageProperties().setMessageId(UUID.randomUUID().toString());
return message;
});
return "ok";
}
}
1.2.5 接收方
接收方ComputerReceiver
@Component
@Slf4j
public class ComputerReceiver {
@RabbitListener(queuesToDeclare = @Queue("order_computer"))
public void computerQueue(String msg, Channel channel ,Message message) throws Exception {
try {
Thread.sleep(1000);
List<User> userList = (List<User>) JsonUtil.fromJson(msg, new TypeReference<List<User>>() {
});
log.info("【ComputerReceiver】成功接收到消息 >>> {}", userList);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
} catch (Exception e) {
if (message.getMessageProperties().getRedelivered()) {
log.info("【ComputerReceiver】消息回滚过,拒绝接受消息 >>> {}", msg);
// 拒绝消息,并且不再重新进入队列
channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
} else {
log.info("【ComputerReceiver】消息即将返回到队列重新处理 >>> {}", msg);
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
}
e.printStackTrace();
}
}
}
接收方FruitReceiverTwo
@Component
@Slf4j
public class FruitReceiverTwo {
@RabbitListener(queuesToDeclare = @Queue("order_fruit"))
public void fruitQueue(String msg, Channel channel, Message message) throws Exception {
try {
Thread.sleep(1000);
List<User> user = (List<User>) JsonUtil.fromJson(msg, new TypeReference<List<User>>() {
});
log.info("【FruitReceiverTwo】成功接收到消息 >>> {}", user);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
} catch (Exception e) {
if (message.getMessageProperties().getRedelivered()) {
log.info("【FruitReceiverTwo】消息回滚过,拒绝接受消息 >>> {}", msg);
// 拒绝消息,并且不再重新进入队列
channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
} else {
log.info("【FruitReceiverTwo】消息即将返回到队列重新处理 >>> {}", msg);
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
}
e.printStackTrace();
}
}
}