如何在运行时指定asyncRabbitTemplate.convertSendAndReceiveAsType的返回类型
RabbitMQ异步调用反序列化类型转换问题修复
问题描述
开发过程中实现RabbitMQ异步发送方法时,无法在运行时传递正确的返回值类型完成反序列化操作,抛出类转换异常。
原有方法实现
@Override public <T, R> R sendAsync(T payload, String routingKey, String exchangeName) { ListenableFuture<R> listenableFuture = asyncRabbitTemplate.convertSendAndReceiveAsType( exchangeName, routingKey, payload, new ParameterizedTypeReference<>() { } ); try { return listenableFuture.get(); } catch (InterruptedException | ExecutionException e) { LOGGER.error(" [x] Cannot get response.", e); return null; } }
方法调用示例
SaveImageResponse response = backendClient.sendAsync( new SaveImageRequest(createQRRequest.getOwner(), qr), RabbitConstants.CREATE_QR_IMAGE_KEY, RabbitConstants.CDN_EXCHANGE);
用到的POJO定义
public class SaveImageResponse { private String id; private String message; public SaveImageResponse() { } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "SaveImageResponse{" + "id='" + id + '\'' + ", message='" + message + '\'' + '}'; } }
报错信息
Caused by: java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class dev.yafatek.qr.api.responses.SaveImageResponse (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; dev.yafatek.qr.api.responses.SaveImageResponse is in unnamed module of loader 'app')
问题原因
Java泛型存在类型擦除机制,方法定义中的泛型参数R在运行时会被擦除为Object,直接创建匿名ParameterizedTypeReference无法获取到实际的返回类型,导致序列化框架默认将返回值反序列化为LinkedHashMap类型,强转自定义POJO时就会抛出类转换异常。
修复方案
修改后方法实现
@Override public <T, R> R sendAsync(T payload, String routingKey, String exchangeName, Class<R> clazz) { ListenableFuture<R> listenableFuture = asyncRabbitTemplate.convertSendAndReceiveAsType( exchangeName, routingKey, payload, new ParameterizedTypeReference<>() { } ); try { return objectMapper.convertValue(listenableFuture.get(), clazz); } catch (InterruptedException | ExecutionException e) { LOGGER.error(" [x] Cannot get response.", e); return null; } }
实现逻辑
在方法参数中新增Class<R> clazz参数,调用时传入目标返回POJO的类对象,引入Jackson的ObjectMapper调用convertValue方法,将默认反序列化得到的LinkedHashMap转换为指定类型的POJO。
新的调用示例
WebsiteInfoResponse websiteInfoResponse = backendClient.sendAsync(new GetWebsiteInfoReq(createBusinessDetailsRequest.getWebsiteUrlId()), RabbitConstants.GET_WEBSITE_INFO_KEY, RabbitConstants.QR_EXCHANGE, WebsiteInfoResponse.class);
内容的提问来源于stack exchange,提问作者Feras alawadi
相关产品推荐
相关产品推荐

