RabbitMQのテンプレートメッセージ送信、現在の時刻より8時間後に日付型のフィールド

序文

遭遇した開発プロセスの問題のバーストの前にrabbitmq templateメッセージを送信し、時間内にメッセージ本体が8時間以下、現在の時間よりも、これは問題領域を見ています。

なぜそれについて話がです。

以下のように設定する前に、次のとおりです。

@Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);

        template.setMessageConverter(new Jackson2JsonMessageConverter());
        template.setMandatory(true);
      
        ...
        return template;
    }

VOメッセージに送り出さこれです:

@Data
public class TestVO {
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date testDate;
}

その後、問題は、メッセージ本文、現在の8時間の時間よりも短い時間です。

{ "testDate": "2019年12月27日午前5時45分26秒"}

理由

使用RabbitMQのテンプレートがあるように、我々は以下のとおりです。

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisRepository redisRepository;

    /**
     * 发送消息
     * @param exchange 交换机名称
     * @param routingKey 路由键
     * @param msgMbject 消息体,无需序列化,会自动序列化为json
     */
    public void send(String exchange, String routingKey, final Object msgMbject) {
        CorrelationData correlationData = new CorrelationData(GUID.generate());
        CachedMqMessageForConfirm cachedMqMessageForConfirm = new CachedMqMessageForConfirm(exchange, routingKey, msgMbject);
        redisRepository.saveCacheMessageForConfirms(correlationData,cachedMqMessageForConfirm);
        //核心代码:这里,发送出去的msgObject其实就是一个vo或者dto,rabbitmqTemplate会自动帮我们转为json
        rabbitTemplate.convertAndSend(exchange,routingKey,msgMbject,correlationData);
    }

私はコメントで説明し、変換がジャクソンは自動的に変換を行いますRabbitMQのです。

ソースは、調べるためにフォローアップすることができます:

org.springframework.amqp.rabbit.core.RabbitTemplate#convertAndSend
  
    @Override
    public void convertAndSend(String exchange, String routingKey, final Object object,
            @Nullable CorrelationData correlationData) throws AmqpException {
        // 这里调用了convertMessageIfNecessary(object)
        send(exchange, routingKey, convertMessageIfNecessary(object), correlationData);
    }

コールconvertMessageIfNessary:

protected Message convertMessageIfNecessary(final Object object) {
        if (object instanceof Message) {
            return (Message) object;
        }
        // 获取消息转换器
        return getRequiredMessageConverter().toMessage(object, new MessageProperties());
    }

メッセージコードコンバータを取得する次のとおりです。


    private MessageConverter getRequiredMessageConverter() throws IllegalStateException {
        MessageConverter converter = getMessageConverter();
        if (converter == null) {
            throw new AmqpIllegalStateException(
                    "No 'messageConverter' specified. Check configuration of RabbitTemplate.");
        }
        return converter;
    }

getMessageConverterは、フィールドrabbitmqTemplateクラスを取得することです。

    public MessageConverter getMessageConverter() {
        return this.messageConverter;
    }

それは割り当てを実行することができる場所を私たちは見るだけ。

その後、私はそれを考える、それが私たちのビジネスコードの割り当てであります:

@Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        // 下面这里赋值了。。。差点搞忘了
        template.setMessageConverter(new Jackson2JsonMessageConverter());
        template.setMandatory(true);

        return template;
    }

とにかく、それは、一般的には、送信する前に、当社のカスタムメッセージを変換messageConverter rabbitmqTemplateの使用です。

タイムゾーンの問題、良好な再現、ソースコード:

https://gitee.com/ckl111/all-simple-demo-in-work/tree/master/jackson-demo

@Data
public class TestVO {
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date testDate;
}

テストコード:


    @org.junit.Test
    public void normal() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        TestVO vo = new TestVO();
        vo.setTestDate(new Date());
        String value = mapper.writeValueAsString(vo);
        System.out.println(value);
    }

出力:

{ "testDate": "2019年12月27日午前5時45分26秒"}

ソリューション

  1. デフォルトゾーンの設定をする場合に指定

     @org.junit.Test
        public void specifyDefaultTimezone() throws JsonProcessingException {
            ObjectMapper mapper = new ObjectMapper();
            SerializationConfig oldSerializationConfig = mapper.getSerializationConfig();
            /**
             * 新的序列化配置,要配置时区
             */
            String timeZone = "GMT+8";
            SerializationConfig newSerializationConfig = oldSerializationConfig.with(TimeZone.getTimeZone(timeZone));
    
            mapper.setConfig(newSerializationConfig);
            TestVO vo = new TestVO();
            vo.setTestDate(new Date());
            String value = mapper.writeValueAsString(vo);
            System.out.println(value);
        }
  2. 注釈付きのフィールドで

    @Data
    public class TestVoWithTimeZone {
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        private Date testDate;
    }

    ここでは、追加のタイムゾーンは、手動でタイムゾーンの設定を指定します。

    テストコード:

    
        @org.junit.Test
        public void specifyTimezoneOnField() throws JsonProcessingException {
            ObjectMapper mapper = new ObjectMapper();
            TestVoWithTimeZone vo = new TestVoWithTimeZone();
            vo.setTestDate(new Date());
            String value = mapper.writeValueAsString(vo);
            System.out.println(value);
        }

2以上の出力が正しいです。

分析する一切のソースコードはありません、単に時間のシーケンスを見て、コンフィギュレーションのシーケンスがあるでしょう。この構成では、2つの部分から構成:デフォルトの設定+クラスのカスタム設定。カスタム設定はデフォルトの設定を上書きします。

私たちの第二の方法は、デフォルトの設定を変更することであり、第三の方法は、カスタム設定がデフォルトの設定を上書き使用することです。

jacksonかなり重要な、特にspring cloud家族のバケツ、feignまたこれで、restTemplateまた、同様に使用Spring MVCしてhttpmessageConverter、その下に、この場所で学生の興味、表情。

あなたが興味を持ってJsonFormat処理されている場合は、次のような場所を見ることができます:

com.fasterxml.jackson.annotation.JsonFormat.Value#値(com.fasterxml.jackson.annotation.JsonFormat)(ここで休憩を行い、その後、ここでテストを実行します)

概要

私はほとんど問題RabbitMQのテンプレートを忘れ、そして最終的に私たちのソリューションは以下のとおりです。

@Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);

        ObjectMapper mapper = new ObjectMapper();
        SerializationConfig oldSerializationConfig = mapper.getSerializationConfig();
        /**
         * 新的序列化配置,要配置时区
         */
        String timeZone = environment.getProperty(CadModuleConstants.SPRING_JACKSON_TIME_ZONE);
        SerializationConfig newSerializationConfig = oldSerializationConfig.with(TimeZone.getTimeZone(timeZone));

        mapper.setConfig(newSerializationConfig);

        Jackson2JsonMessageConverter messageConverter = new Jackson2JsonMessageConverter(mapper);

        template.setMessageConverter(messageConverter);
        template.setMandatory(true);
      
        ...设置callback啥的
        return template;
    }

その他の関連するソースコード:

https://gitee.com/ckl111/all-simple-demo-in-work/tree/master/jackson-demo

おすすめ

転載: www.cnblogs.com/grey-wolf/p/12107016.html