【问题标题】:how can i specify the return type for asyncRabbitTemplate.convertSendAndReceiveAsType() at run time?如何在运行时指定 asyncRabbitTemplate.convertSendAndReceiveAsType() 的返回类型?
【发布时间】:2021-09-23 11:26:27
【问题描述】:

我一直在努力使用以下代码。并且不确定如何反序列化它甚至在运行时传递正确的类型。

代码是:


 @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')

提前致谢

解决方案:

所以我最终使用了以下内容:

@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<POJO> clazz

使用上面的代码:

WebsiteInfoResponse websiteInfoResponse = backendClient.sendAsync(new GetWebsiteInfoReq(createBusinessDetailsRequest.getWebsiteUrlId()), RabbitConstants.GET_WEBSITE_INFO_KEY, RabbitConstants.QR_EXCHANGE, WebsiteInfoResponse.class);

【问题讨论】:

    标签: java rabbitmq spring-rabbit java-16


    【解决方案1】:

    你不能。

    ParameterizedTypeReference&lt;Foo&gt; 的全部原因是告诉转换器你想要一个Foo;这必须在方法的编译时解决;你不能打电话给sendAsync()来接收不同的类型。

    不提供泛型类型意味着它将转换为Object(通常是映射)。

    即使new ParameterizedTypeReference&lt;R&gt;() { } 也不起作用,因为R 在编译时没有为泛型类型(sendAsync() 方法)解析。

    您必须自己进行转换。

    @SpringBootApplication
    public class So69299112Application {
    
        public static void main(String[] args) {
            SpringApplication.run(So69299112Application.class, args);
        }
    
        @Bean
        MessageConverter converter() {
            return new Jackson2JsonMessageConverter();
        }
    
        ObjectMapper mapper = new ObjectMapper();
    
        @Bean
        AsyncRabbitTemplate template(RabbitTemplate template) {
            template.setMessageConverter(new SimpleMessageConverter());
            return new AsyncRabbitTemplate(template);
        }
    
        @Bean
        ApplicationRunner runner(Service service) {
            return args -> {
                byte[] response = service.sendAsync("bar", "foo", "");
                Foo foo = this.mapper.readerFor(Foo.class).readValue(response);
                System.out.println(foo);
            };
        }
    
        @RabbitListener(queues = "foo")
        public Foo listen(String in) {
            return new Foo(in);
        }
    
        public static class Foo {
    
            String foo;
    
            public Foo() {
            }
    
            public Foo(String foo) {
                this.foo = foo;
            }
    
            public String getFoo() {
                return this.foo;
            }
    
            public void setFoo(String foo) {
                this.foo = foo;
            }
    
            @Override
            public String toString() {
                return "Foo [foo=" + this.foo + "]";
            }
    
        }
    
    }
    
    @Component
    class Service {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(Service.class);
    
        AsyncRabbitTemplate asyncRabbitTemplate;
    
        public Service(AsyncRabbitTemplate asyncRabbitTemplate) {
            this.asyncRabbitTemplate = asyncRabbitTemplate;
        }
    
        public byte[] sendAsync(Object payload, String routingKey, String exchangeName) {
    
            ListenableFuture<byte[]> listenableFuture = asyncRabbitTemplate.convertSendAndReceive(
                    exchangeName,
                    routingKey,
                    payload);
    
            try {
    
                return listenableFuture.get();
    
            }
            catch (InterruptedException | ExecutionException e) {
                LOGGER.error(" [x] Cannot get response.", e);
                return null;
            }
        }
    
    }
    

    【讨论】:

    • 听起来不错,谢谢分享
    • 感谢您对我的启发,请查看我的问题所附的解决方案。问候
    猜你喜欢
    • 2023-03-14
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    相关资源
    最近更新 更多