Spring Cloud 流与 RabbitMQ 发送任何日期,如 LocalDateTime 或 Instant

问题描述 投票:0回答:1

每当存在具有任何日期的对象(如

LocalDateTime
Instant
等)时,我都会遇到从 Rabbit 队列消费消息的问题。

这是我的设置:

Spring Boot应用程序

@SpringBootApplication
public class SpringCloudStreamProcessorApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringCloudStreamProcessorApplication.class, args);
    }
}

我的消费者设置:

@Component
public class ValueConsumer {

    @Bean
    public Consumer<StationExt> createStation() {
        return (value) -> {
            log.info("Received station {}", value);
        };
    }
}

我的实体表示

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StationExt {
    private String id;
    private String name;
    private LocalDate createdAt;
}

我的应用程序.yml

spring:
  cloud:
    function:
      definition: createStation
    stream:
      bindings:
        createStation-in-0:
          destination: created_station
          durableSubscription: true
          group: consumer

我的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.2</version>
        <relativePath/>
    </parent>


    <groupId>com.consumer</groupId>
    <artifactId>consumer-prototype</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Consumer Prototype</name>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream</artifactId>
            <version>3.2.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
            <version>3.1.4</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>



    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

当我通过 RabbitMQ 管理控制台在队列上发布此 JSON 消息时:

{
    "id": "ef19bf9b-99c0-4f1e-ab84-d5819a87002e",
    "name": "My Station Two",
    "createdAt": null
}

我在消费者中收到对象

StationExt

2022-08-23 19:24:36.759  INFO 382668 --- [ion.processor-1] c.consumer.prototyp.ValueConsumer: Received stationStationExt(id=ef19bf9b-99c0-4f1e-ab84-d5819a87002e, name=My Station Two, createdAt=null)

每当我使用任何日期值时

{
    "id": "ef19bf9b-99c0-4f1e-ab84-d5819a87002e",
    "name": "My Station Two",
    "createdAt": "2022-08-23"
}

抛出此异常:

2022-08-23 19:26:18.965 ERROR 382668 --- [ion.processor-1] o.s.integration.handler.LoggingHandler   : org.springframework.messaging.MessageHandlingException: error occurred in message handler [org.springframework.cloud.stream.function.FunctionConfiguration$FunctionToDestinationBinder$1@53ca55e1]; nested exception is java.lang.ClassCastException: class [B cannot be cast to class com.consumer.prototyp.StationExt ([B is in module java.base of loader 'bootstrap'; com.consumer.prototyp.processor.StationExt is in unnamed module of loader 'app'), failedMessage=GenericMessage [payload=byte[115], headers={amqp_receivedDeliveryMode=NON_PERSISTENT, amqp_receivedRoutingKey=created_station.processor, amqp_receivedExchange=, amqp_deliveryTag=8, deliveryAttempt=3, amqp_consumerQueue=created_station.processor, amqp_redelivered=false, id=76dd27c6-e3ea-06ff-b7d3-4dac62560611, amqp_consumerTag=amq.ctag-2eI4LcNYBLQONuGLGThIpg, sourceData=(Body:'[B@610afce2(byte[115])' MessageProperties [headers={}, contentLength=0, receivedDeliveryMode=NON_PERSISTENT, redelivered=false, receivedExchange=, receivedRoutingKey=created_station.processor, deliveryTag=8, consumerTag=amq.ctag-2eI4LcNYBLQONuGLGThIpg, consumerQueue=created_station.processor]), contentType=application/json, timestamp=1661275575944}]
    at org.springframework.integration.support.utils.IntegrationUtils.wrapInHandlingExceptionIfNecessary(IntegrationUtils.java:191)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:65)
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:115)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:133)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106)
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:72)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:317)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:272)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109)
    at org.springframework.integration.endpoint.MessageProducerSupport.sendMessage(MessageProducerSupport.java:216)
    at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter.access$1300(AmqpInboundChannelAdapter.java:69)
    at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter$Listener.lambda$onMessage$0(AmqpInboundChannelAdapter.java:374)
    at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329)
    at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:225)
    at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter$Listener.onMessage(AmqpInboundChannelAdapter.java:370)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1670)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1589)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1577)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1568)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1512)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:993)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:940)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:84)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1317)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1223)
    at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.ClassCastException: class [B cannot be cast to class com.consumer.prototyp.StationExt ([B is in module java.base of loader 'bootstrap'; com.consumer.prototyp.StationExt is in unnamed module of loader 'app')
    at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.invokeConsumer(SimpleFunctionRegistry.java:784)
    at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.doApply(SimpleFunctionRegistry.java:589)
    at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.apply(SimpleFunctionRegistry.java:435)
    at org.springframework.cloud.stream.function.PartitionAwareFunctionWrapper.apply(PartitionAwareFunctionWrapper.java:79)
    at org.springframework.cloud.stream.function.FunctionConfiguration$FunctionWrapper.apply(FunctionConfiguration.java:717)
    at org.springframework.cloud.stream.function.FunctionConfiguration$FunctionToDestinationBinder$1.handleMessageInternal(FunctionConfiguration.java:559)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:56)
    ... 27 more

我尝试过

Instant
OffsetDateTime
LocalDatetime
,但错误总是一样。

我尝试用

JsonFormat
注释 LocalDate,如下所示:

@JsonFormat(pattern = "dd-MM-yyyy", shape = JsonFormat.Shape.ANY)
    private LocalDate createdAt;

但错误始终保持不变。

尝试在 POM 中使用不同版本的

spring-cloud-stream
spring-cloud-stream-binder-rabbit

为什么这不起作用?

java spring spring-cloud-stream spring-rabbit
1个回答
1
投票

jackson-datatype-jsr310 添加到您的依赖项列表中。

另外将序列化器/反序列化器添加到您的日期字段

@JsonSerialize(using = LocalDateSerializer.class)
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonFormat(pattern = "dd-MM-yyyy")
private LocalDate createdAt;

@JsonDeserialize
指定使用哪个反序列化器将 String 映射到所需的类。如果没有
@JsonSerialize
,当你尝试将对象转换为 json 时,你会变得一团糟,就像

{"createdAt":{"nano":475000000,"dayOfYear":269,"dayOfWeek":"MONDAY","month":"SEPTEMBER","dayOfMonth":26 ...}...}
© www.soinside.com 2019 - 2024. All rights reserved.