生产者把消息发送到exchange 确认。通过实现 ConfirmCallback 接口,消息发送到 Broker 后触发回调,确认消息是否到达 Broker 服务器,也就是只确认是否正确到达 Exchange 中 implements RabbitTemplate.ConfirmCallback
看一下代码实现:
配置类:
package com.lwl.rabbitmq.config;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
public class RabbitConfig {
@Value("${spring.rabbitmq.host}")
private String addresses;
@Value("${spring.rabbitmq.port}")
private String port;
@Value("${spring.rabbitmq.username}")
private String username;
@Value("${spring.rabbitmq.password}")
private String password;
@Value("${spring.rabbitmq.virtual-host}")
private String virtualHost;
@Value("${spring.rabbitmq.publisher-confirms}")
private boolean publisherConfirms;
@Value("${spring.rabbitmq.publisher-returns}")
private boolean publisherReturns;
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses(addresses+":"+port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
/** 如果要进行消息回调,则这里必须要设置为true */
connectionFactory.setPublisherConfirms(publisherConfirms);
connectionFactory.setPublisherReturns(publisherReturns);
return connectionFactory;
}
@Bean
/** 因为要设置回调类,所以应是prototype类型,如果是singleton类型,则回调类为最后一次设置 */
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplatenew() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
return template;
}
}
package com.lwl.rabbitmq.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.lwl.rabbitmq.constant.Constants;
/**
* 发送消息 配置发送消息的队列queue
* @author lwl
* @create 2018年8月10日 下午2:37:38
* @version 1.0
*/
@Configuration
public class SendMessageConfig {
@Bean
public Queue topicQueue() {
return new Queue(Constants.TOPIC_QUEUE);
}
@Bean
TopicExchange exchange() {
return new TopicExchange(Constants.TOPIC_NAME);
}
/**
* 使用主题交换机,
* 将队列Constants.TOPIC_QUEUE与exchange绑定,binding_key为topic.queue.key,就是完全匹配
* @param topicQueue
* @param exchange
* @return
* @author lwl
* @create 2019年6月14日 上午10:51:21
*/
@Bean
Binding bindingExchangeMessage(Queue topicQueue, TopicExchange exchange) {
return BindingBuilder.bind(topicQueue).to(exchange).with(Constants.ROUTING_KEY);
}
}
配置文件:
# 配置rabbitmq
spring:
rabbitmq:
host: 192.168.3.66
port: 5672
username: lwl
password: 123456
publisher-confirms: true
publisher-returns: true
virtual-host: /
生产者:
package com.lwl.rabbitmq.producer;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import com.lwl.rabbitmq.constant.Constants;
/**
* 生成者
* @author lwl
* @create 2019年6月14日 上午10:56:41
* @version 1.0
*/
@Component
public class AckProducer implements RabbitTemplate.ConfirmCallback , RabbitTemplate.ReturnCallback{
@Autowired
private RabbitTemplate rabbitTemplatenew;
/**
* 使用主题交换机
* @param message
* @author lwl
* @create 2019年6月14日 上午10:54:54
*/
public void send(Object message){
rabbitTemplatenew.setConfirmCallback(this);
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
System.out.println();
System.out.println("callbackSender UUID: " + correlationData.getId());
System.out.println();
this.rabbitTemplatenew.convertAndSend(Constants.TOPIC_NAME,Constants.ROUTING_KEY, message, correlationData);
}
/**
*
* 通过实现 ConfirmCallback 接口,消息发送到 Broker 后触发回调,确认消息是否到达 Broker 服务器,也就是只确认是否正确到达 Exchange 中
* @param correlationData
* @param ack
* @param cause
* @author lwl
* @create 2019年6月17日 上午9:46:59
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
//
System.out.println();
System.out.println();
System.out.println("callbakck confirm: " + correlationData.getId());
System.out.println();
System.out.println();
}
/**
* 通过实现 ReturnCallback 接口,启动消息失败返回,比如路由不到队列时触发回调
* @param message
* @param replyCode
* @param replyText
* @param exchange
* @param routingKey
* @author lwl
* @create 2019年6月17日 上午10:01:47
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("消息主体 message : "+message);
System.out.println("消息主体 message : "+replyCode);
System.out.println("描述:"+replyText);
System.out.println("消息使用的交换器 exchange : "+exchange);
System.out.println("消息使用的路由键 routing : "+routingKey);
}
}
消费者:
package com.lwl.rabbitmq.consumer;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.lwl.rabbitmq.constant.Constants;
/**
* 消费者
* @author lwl
* @create 2019年6月14日 上午10:57:11
* @version 1.0
*/
@Component
@RabbitListener(queues = Constants.TOPIC_QUEUE)
public class TopicAckConsumer {
@RabbitHandler
public void process(String hello) {
System.out.println();
System.out.println("-----------------------客户端 3 收到数据 -----------------------");
System.out.println(Constants.TOPIC_QUEUE+ " --> Receiver3 : " + hello);
System.out.println();
}
}
测试用例:
package com.lwl.rabbitmq;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.lwl.rabbitmq.producer.AckProducer;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes={RabbitmqAckApplication.class})
@WebAppConfiguration
public class RabbitmqAckApplicationTests {
@Resource
private AckProducer ackProducer;
@Test
public void send() {
String message = " message with ack ";
ackProducer.send(message );
}
}
结果分析:
callbackSender UUID: 2c3a2573-fd21-4160-bb5d-f8f6cbe97cc3
callbakck confirm: 2c3a2573-fd21-4160-bb5d-f8f6cbe97cc3
消息发送到exchange之后,返回的uuid 和发送的uuid 是一样的