rabbitMQ结合动态代理

使用动态代理实现消费端幂等性验证和消费确认(ack)
动态代理要求目标对象是实现接口的目标对象,所以先写一个消费接口
public interface BaseConsumer{
	void consumer(Message message, Channel channel);
}

实现类:

@Component
@Slf4j
public class MailConsumer implements BaseConsumer{
	    @Autowired
    private MailUtil mailUtil;
    @Override
    public void consumer(Message message, Channel channel) {
        Mail mail = MessageHelper.msgToObj(message, Mail.class);
        log.info("收到消息: {}", mail.toString());

        boolean success = mailUtil.send(mail);
        if (!success){
            throw new ServiceException("send mail error");
        }
    }
}

代理工厂:

public class BaseConsumerProxy{
	//被代理对象
	private Object target;
    private MsgLogService msgLogService;

    public BaseConsumerProxy(Object target, MsgLogService msgLogService) {
        this.target = target;
        this.msgLogService = msgLogService;
    }
    //Proxy.newProxyInstance
/*    ClassLoader loader,
    Class<?>[] interfaces,
    InvocationHandler h*/
    public Object getProxy(){
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        Object proxy = Proxy.newProxyInstance(classLoader,interfaces,(proxy1,method,args)->{
            Message message = (Message)args[0];
            Channel channel = (Channel)args[1];
            String correlationId = getCorrelationId(message);

            if (isConsumed(correlationId)) {// 消费幂等性, 防止消息被重复消费
                log.info("重复消费, correlationId: {}", correlationId);
                return null;
            }
            MessageProperties properties = message.getMessageProperties();
            long tag = properties.getDeliveryTag();
            try {
                Object result = method.invoke(target, args);
                msgLogService.updateStatus(correlationId, Constant.MsgLogStatus.CONSUMED_SUCCESS);
                channel.basicAck(tag,false);
                return result;
            }catch (Exception e){
                log.error("getProxy error", e);
                channel.basicNack(tag,false,true);
                return null;
            }
        });

        return proxy;
    }

    private String getCorrelationId(Message message){
        String correlationId = null;

        MessageProperties properties = message.getMessageProperties();
        Map<String, Object> headers = properties.getHeaders();
        for (Map.Entry<String, Object> entry : headers.entrySet()) {
            String key = (String) entry.getKey();
            String value = (String)entry.getValue();
            if (key.equals("spring_returned_message_correlation")){
                correlationId = value;
            }
        }
        return correlationId;
    }

    private boolean isConsumed(String correlationId) {
        MsgLog msgLog = msgLogService.selectByMsgId(correlationId);
        if (null == msgLog || msgLog.getStatus().equals(Constant.MsgLogStatus.CONSUMED_SUCCESS)) {
            return true;
        }
        return false;
    }
}

RabbitMQ监听类:

@Component
public class MailListener {
    @Autowired
    private MailConsumer mailConsumer;
    @Autowired
    private MsgLogService msgLogService;
	
	@RabbitListener(queues = RabbitConfig.MAIL_QUEUE_NAME)
	public class consumer(Message message, Channel channel){
		BaseConsumerProxy baseConsumerProxy = new BaseConsumerProxy();
		BaseConsumer proxy = (BaseConsumer)baseConsumerProxy.getProxy();
        if (null!=proxy){
            proxy.consumer(message,channel);
        }
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值