spring:
rabbitmq:
publisher-confirm-type: correlated #前提要配置这个,注意版本
从2.1版本开始,CorrelationData对象有一个ListenableFuture,您可以使用它来获取结果,而不是在模板上使用ConfirmCallback。以下示例显示了如何配置CorrelationData实例:
import cn.hutool.core.util.IdUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.concurrent.ListenableFutureCallback;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class MainTest {
@Resource
RabbitTemplate template;
@Resource
private CachingConnectionFactory factory;
@Test
public void test() throws ExecutionException, InterruptedException, TimeoutException {
String traceId = IdUtil.randomUUID()+"RabbitTemplate_NON_PERSISTENT2";
//最麻烦版,这个设不设都没所谓
//factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
System.out.println("发布确认模式:" + factory.isPublisherConfirms());
final Message message = new Message(String.valueOf("sdfsdfsdfsdfsdf".getBytes(StandardCharsets.UTF_8));
//这个就是 ConfirmCallback
template.setConfirmCallback((correlationData, ack, cause) -> {
System.out.println("MyConfirmCallback:ack=" + ack);
System.out.println("MyConfirmCallback:cause=" + cause);
});
final CorrelationData cd = new CorrelationData(traceId);
//这个是2.1后才有,针对每个消息
cd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {
@Override
public void onFailure(Throwable ex) {
System.out.println("消息回调方法调用失败:"+ex.getMessage());
}
@Override
public void onSuccess(CorrelationData.Confirm result) {
System.out.println("CorrelationData-回执");
if(result.isAck()){
System.out.println("CorrelationData-成功 - ack");
} else {
System.out.println("CorrelationData-失败 - nack");
// 重发消息
// ...
}
}
});
template.send(
"sdfsdfsdfsdfsf",
"121123123123123123",
message
, cd
);
//最简版
final boolean ack = cd.getFuture().get(10, TimeUnit.SECONDS).isAck();
System.out.println("cd get:"+ack);
}
}
由于它是一个ListenableFuture<Confirm>,您可以在get()获取结果,也可以为异步回调添加监听器。Confirm对象是一个简单的bean,有2个属性:ack和reason(用于nack实例)。对于代理生成的nack实例,原因未填充。它是为框架生成的nack实例填充的(例如,在ack实例未完成时关闭连接)。
此外,当确认和返回都启用时,只要CorrelationData具有唯一的id,CorrelationData就会填充返回的消息;默认情况下,从2.3版本开始,情况总是如此。保证在用ack设置未来之前设置返回的消息。