【问题标题】:Using JsonComponent with RabbitListener将 JsonComponent 与 RabbitListener 一起使用
【发布时间】:2021-07-13 15:16:29
【问题描述】:

我正在尝试使用自定义反序列化器:

@JsonComponent
class SuffixDeserializer extends JsonDeserializer<String> {

    private final String suffix;

    SuffixDeserializer(@Value("${suffix}") String suffix) {
        this.suffix = suffix;
    }

    @Override
    public String deserialize(JsonParser json, DeserializationContext ctx) 
            throws IOException {
        return json.getText() + suffix;
    }
}

对于 RabbitMQ 侦听器:

@Slf4j
@Service
class FooListener {

    @RabbitListener(queuesToDeclare = @Queue(name = "foo", durable = "true"))
    void foo(Message msg) {
        log.info("Received {}", msg);
    }

    @Data
    static class Message {
        @JsonDeserialize(using = SuffixDeserializer.class)
        private String field;
    }
}

我什至尝试显式注册JsonComponentModule

@Bean
public MessageConverter jsonConverter() {
    ObjectMapper mapper = new ObjectMapper()
            .registerModule(new JsonComponentModule());
    return new Jackson2JsonMessageConverter(mapper);
}

但是当我运行这段代码时,我得到了以下错误:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Class io.github.jjarzynski.jsoncomponentmq.SuffixDeserializer has no default (no arg) constructor
 at [Source: (String)"{"field": "bar"}"; line: 1, column: 1]

这意味着 Jackson 正在尝试创建自己的实例而不是使用 Spring Bean。

如何将自定义 Spring Bean 反序列化器应用于传入 RabbitMQ 消息中的字段?

【问题讨论】:

    标签: spring rabbitmq spring-amqp spring-rabbit jackson-databind


    【解决方案1】:

    我能够使用SuffixDeserializer bean 的唯一方法是通过以下方式注册它:

    @Bean
    MessageConverter jsonConverter(SuffixDeserializer deserializer) {
    
        SimpleModule jsonComponentModule = new JsonComponentModule()
                .addDeserializer(String.class, deserializer);
    
        ObjectMapper mapper = new ObjectMapper()
                .registerModule(jsonComponentModule);
    
        return new Jackson2JsonMessageConverter(mapper);
    }
    

    这表明@JsonComponent 扫描对 RabbitMQ 没有用处?我还不如用@Component注释SuffixDeserializer

    【讨论】:

      【解决方案2】:

      异常清楚地表明:

      SuffixDeserializer 在 [Source: (String)"{"field": "bar"}";行:1,列:1]

      所以你需要在 suffixDeserializer 类上放置一个默认构造函数,并且可能还需要设置后缀的 getter 和 setter。

      @JsonComponent
      class SuffixDeserializer extends JsonDeserializer<String> {
      
          private String suffix;
      
          SuffixDeserializer() {}
      
          SuffixDeserializer(@Value("suffix") String suffix) {
              this.suffix = suffix;
          }
      
          @Override
          public String deserialize(JsonParser json, DeserializationContext ctx) 
                  throws IOException {
              return json.getText() + suffix;
          }
      }
      

      【讨论】:

      • 添加无参数构造函数并将构造函数依赖注入更改为设置器依赖注入并不能解决问题。我最终得到空后缀值。 Jackson 正在独立于 Spring Bean 实例化自己的 SuffixDeserializer。
      猜你喜欢
      • 1970-01-01
      • 2016-01-19
      • 1970-01-01
      • 2017-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多