【问题标题】:Adding custom HttpMessageConverter<T>添加自定义 HttpMessageConverter<T>
【发布时间】:2018-10-30 03:24:42
【问题描述】:

我正在尝试将自定义 HttpMessageConverter&lt;T&gt; 添加到我的(Spring 驱动的)REST API。

@Configuration
public class SpringWebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new BodyPrinterInterceptor());
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        final List<HttpMessageConverter> injectedConverters = new ArrayList<>();
        final SimpleModule module = new SimpleModule("module", new Version(1, 0, 0, null, null, null))
                .addSerializer(LocalDate.class, new LocalDateSerializer())
                .addDeserializer(LocalDate.class, new LocalDateDeserializer())
                .addSerializer(Type2_Numbers.class, new Type2_Numbers_Serializer())
                .addDeserializer(Type2_Numbers.class, new Type2_Numbers_Deserializer());

        final ObjectMapper objectMapper = new ObjectMapper()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .registerModule(module);
        final MappingJackson2HttpMessageConverter converter1 = new MappingJackson2HttpMessageConverter();
        converter1.setObjectMapper(objectMapper);
        injectedConverters.add(converter1);

        final XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.registerModule(module);
        xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
        final Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
        final MappingJackson2XmlHttpMessageConverter converter2 = new MappingJackson2XmlHttpMessageConverter(builder.build());
        converter2.setObjectMapper(xmlMapper);
        injectedConverters.add(converter2);

        for (HttpMessageConverter injectedConverter : injectedConverters) {
            converters.add(injectedConverter);
        }
    }
}

添加的转换器似乎不起作用。 (没有调用序列化器和反序列化器)

问题 如何正确添加 HttpMessageConverters?

【问题讨论】:

  • 这里没有问题
  • 添加明确的问题。

标签: java spring rest jackson spring-rest


【解决方案1】:

我相信您忘记在函数结束时调用super.configureMessageConverters(converters)

【讨论】:

  • 等等,我为什么要添加它?我的代码无需添加即可运行。
  • 在您的代码的原始版本中。不是你的 Utils 版本
【解决方案2】:

原因

在我的案例中导致问题的问题是,添加已存在于提供的 HttpMessageConverters 列表中的类型的自定义 HttpMessageConverter 不会导致添加新的 HttpMessageConverter 或更新相同类型的现有 HttpMessageConverter。

解决方案

如果现有的 HttpMessageConverter 对象与要添加的新自定义 HttpMessageConverter 对象的类型相同,则首先从列表中删除该对象,从而解决了该问题。然后添加新的自定义 HttpMessageConverter。

实施解决方案

Utils.java

public class Utils {
    public static void injectConverter(HttpMessageConverter converterToInject, List<HttpMessageConverter<?>> convertersList) {
        convertersList.removeIf(new Predicate<HttpMessageConverter<?>>() {
            @Override
            public boolean test(HttpMessageConverter<?> httpMessageConverter) {
                return converterToInject.getClass() == httpMessageConverter.getClass();
            }
        });
        convertersList.add(converterToInject);
    }
}

SpringWebConfig.java

@Configuration
public class SpringWebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new BodyPrinterInterceptor());
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        final List<HttpMessageConverter> injectedConverters = new ArrayList<>();
        final SimpleModule module = new SimpleModule("module", new Version(1, 0, 0, null, null, null))
                .addSerializer(LocalDate.class, new LocalDateSerializer())
                .addDeserializer(LocalDate.class, new LocalDateDeserializer())
                .addSerializer(Type2_Numbers.class, new Type2_Numbers_Serializer())
                .addDeserializer(Type2_Numbers.class, new Type2_Numbers_Deserializer());

        final ObjectMapper objectMapper = new ObjectMapper()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .registerModule(module);
        final MappingJackson2HttpMessageConverter converter1 = new MappingJackson2HttpMessageConverter();
        converter1.setObjectMapper(objectMapper);
        injectedConverters.add(converter1);

        final XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.registerModule(module);
        xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
        final Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
        final MappingJackson2XmlHttpMessageConverter converter2 = new MappingJackson2XmlHttpMessageConverter(builder.build());
        converter2.setObjectMapper(xmlMapper);
        injectedConverters.add(converter2);

        for (HttpMessageConverter injectedConverter : injectedConverters) {
            Utils.injectConverter(injectedConverter, converters);
        }

    }
}

【讨论】:

  • 我觉得有必要回答这个问题。因为这个特殊的问题花费了我很多时间和头发!
【解决方案3】:

建议使用以下

@Bean
public HttpMessageConverters additionalConverters() {
    return new HttpMessageConverters(new YourCustomHttpMsgConverter());
}

然后用GenericHttpMessageConverter扩展YourCustomHttpMsgConverter类

进一步编写覆盖方法 canRead、read、canWrite、write、canRead、canWrite、getSupportedMediaTypes 的实现

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-21
    • 2023-01-09
    • 2018-04-12
    • 2011-06-28
    • 2020-06-09
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    相关资源
    最近更新 更多