RabbitMq传递的实体修改引发阻塞

  • 项目有些地方需要用RabbitMq去实现队列,队列的相关代码如下:
/****传入队列*****/
rabbitTemplate.convertAndSend(CommonConstant.MEETING_STATUS_EXCHANGE, CommonConstant.MEETING_STATUS_ROUTING, new WSMessgeDTO(meeting, WSMessgeDTO.MeetingChangeType.CREATE));

/*****接收************/
@RabbitListener(queues = CommonConstant.MEETING_STATUS_QUEUE)
public void sendMessgeToWisdomScreen(@NotNull @Payload WSMessgeDTO wsMessgeDTO) {
    /**
    ···
    **/
}

这里在后续开发中改变WSMessgeDTO的数据结构时会出现一些问题:

如果修改了WSMessgeDTO实体,而队列中的数据还没有处理完,此时接收数据所需的WSMessgeDTO数据结构时修改后的,而队列中没有处理完的数据结构是修改前的,这就会导致数据不匹配引起数据接收失败产生报错,最终导致队列堵塞。

一般当我们需要服务在抛出异常后还能继续运行时,会把可能报错的代码块放在trycatch里,但是这里是接收数据的过程中产生报错,代码没有运行到方法体中,就没办法trycatch。

  • 解决方案如下:

不再直接传递WSMessgeDTO实体,在发送前将实体转成Json,接收时再转回来,这样传递过程中的数据类型始终是Json字符串,就不会出现数据接收失败的情况。即视数据类型前后不匹配,我们也可以将把Json反序列化成实体的代码块放到trycatch里,这样就不会导致服务堵塞了:

/***********发送*******************/
ObjectMapper objectMapper = new ObjectMapper();
String messageStr = objectMapper.writeValueAsString(new WSMessgeDTO(meeting, WSMessgeDTO.MeetingChangeType.CREATE));
rabbitTemplate.convertAndSend(CommonConstant.MEETING_STATUS_EXCHANGE, CommonConstant.MEETING_STATUS_ROUTING,messageStr );

/*************接收**********************/
@RabbitListener(queues = CommonConstant.MEETING_STATUS_QUEUE)
public void sendMessgeToWisdomScreen(@NotNull @Payload String messageStr) {
    ObjectMapper objectMapper = new ObjectMapper();
    WSMessgeDTO wsMessgeDTO = objectMapper.readValue(messageStr,WSMessgeDTO.class);
    /**
    ···
    **/
}

这里要用到的是ObjectMapper的readValue方法,readValue方法和convertValue方法区别如下:

readValue:将Json转成指定对象,eg:

ObjectMapper objectMapper = new ObjectMapper();
User user = new  User();
String userStr = objectMapper.writeValueAsString(user);
User result = objectMapper.readValue(userStr, User.class);

convertValue:将LinkedHashMap转成指定对象,eg:

/***********发送*******************/
ObjectMapper objectMapper = new ObjectMapper();
String messageStr = objectMapper.writeValueAsString(new WSMessgeDTO(meeting, WSMessgeDTO.MeetingChangeType.CREATE));
rabbitTemplate.convertAndSend(CommonConstant.MEETING_STATUS_EXCHANGE, CommonConstant.MEETING_STATUS_ROUTING,messageStr );

/*************接收**********************/
@RabbitListener(queues = CommonConstant.MEETING_STATUS_QUEUE)
public void sendMessgeToWisdomScreen(@NotNull @Payload String messageStr) {
    try{
   	    ObjectMapper objectMapper = new ObjectMapper();
        WSMessgeDTO wsMessgeDTO = objectMapper.readValue(messageStr,WSMessgeDTO.class);
        /**
        ···
        **/
    }catch(Exception e){
        log.error("message");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值