前言
代码什么的在我的仓库里都有https://gitee.com/song_mengyu/Example/tree/master/Project/rabbit-ack-test
一、 配置
<dependencies>
<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>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
一、发送确认
首先是 yml的配置
server:
port: 8081
spring:
application:
name: rabbit-server
rabbitmq:
port: 5673
host: 192.168.136.128
username: admin
password: admin
publisher-confirms: true
publisher-returns: true
对于这个发送确认只是做个简单的演示,所以我我们就只设置个队列即可
@Configuration
public class Config {
@Bean
public Queue MyQueue(){
return new Queue("myQueue", true);
}
}
然后是发送的逻辑
package com.mymy;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Sender {
@Autowired
RabbitTemplate rabbitTemplate;
public void send(){
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String s) {
if(ack){
System.out.println("发送成功");
}else {
System.out.println("发送失败");
}
}
});
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("消息内容是" + message.getBody().toString());
}
});
rabbitTemplate.convertAndSend("myQueue", "hello!");
}
}
最后是Controller
package com.mymy;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private Sender sender;
@GetMapping("/send")
public String send(){
sender.send();
return "okk";
}
}
上边的代码我们在测试时会发现当我们在发送一个请求时,就会报错
下面就是对代码的一些修改,同时再加上mandatory参数
三、上节的修改
首先先对mandatory参数介绍。当此参数为true时,交换器无法根据自身的类型和路由键找到一个符合的队列时将会把消息返回给生产者,如果为false,则直接丢弃掉。下面的代码参考了这个博主的文章https://blog.csdn.net/weixin_44929059/article/details/116303723
配置类如下
package com.mymy;
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.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.SerializerMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class Config {
@Bean
public Queue MyQueue(){
return new Queue("myQueue", true);
}
@Bean
public DirectExchange directExchange(){
return new DirectExchange("myExchange");
}
@Bean
public Binding binding(){
return BindingBuilder.bind(MyQueue()).to(directExchange()).with("myRouting");
}
@Bean
@Scope("prototype")
public RabbitTemplate crabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMandatory(true);
template.setMessageConverter(new SerializerMessageConverter());
return template;
}
}
Controller
package com.mymy;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
@RestController
public class Controller {
@Resource
RabbitTemplate rabbitTemplate;
//为该方法中的rabbitTemplate单独设置回调方法
@PostConstruct
public void init() {
rabbitTemplate.setMandatory(true);
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack) {
System.out.println("数据发送成功");
}else{
System.out.println("数据发送失败");
}
}
});
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("接受失败");
}
});
}
@GetMapping("/send")
public void send() {
rabbitTemplate.convertAndSend("myExchange","myRouting", "hello!");
}
}
三、消费者确认
yml配置
server:
port: 8080
spring:
application:
name: consumer
rabbitmq:
password: admin
username: admin
host: 192.168.136.128
port: 5673
listener:
simple:
acknowledge-mode: manual
Lisenner类的编写
package com.mymy;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
@Component
@RabbitListener(queues = {"myQueue"})
public class Listener {
@RabbitHandler
public void process(Map hello, Channel channel, Message message) throws IOException {
System.out.println("HelloReceiver收到 : " + hello.toString() +"收到时间"+new Date());
try {
//告诉服务器收到这条消息 已经被我消费了 可以在队列删掉 这样以后就不会再发了 否则消息服务器以为这条消息没处理掉 后续还会在发
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
System.out.println("receiver success");
} catch (IOException e) {
e.printStackTrace();
//丢弃这条消息
//channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);
System.out.println("receiver fail");
}
}
}