You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在运行时指定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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 19:06:03