- 项目有些地方需要用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");
}
}