自定义Spring HttpMessageConverter未被框架使用

时间:2017-10-31 15:43:04

标签: spring model-view-controller

我有一个Spring mvc @RestController类,其中method参数使用@RequestBody注释。像这样:

@RestController
@RequestMapping("/features")
public class FeatureController {

    @PostMapping
    public Feature createFeature(@RequestBody Feature feature) {
         ......
    }
}

我的Feature类有一个使用Builder模式构建的私有构造函数。因此,我创建了名为HttpMessageConverter的{​​{1}},并使用FeatureConverter正确注册了它。转换器使用Jackson解析JSON,然后使用extendMessageConverters创建Feature.Builder的实例。

我的问题是Spring在我的自定义Feature之前注册了MappingJackson2HttpMessageConverter的实例。因此,即使在FeatureConverter之前,MappingJackson2HttpMessageConverter也会尝试进行解析。由于构造函数是私有的,因此FeatureConverter失败。

我的问题是如何更改订单,以便在MappingJackson2HttpMessageConverter之前询问FeatureConverter。有没有正确的方法呢?

2 个答案:

答案 0 :(得分:1)

Spring MVC WebMvcConfigurerAdapter初始化HttpMessageConverters:

protected final List<HttpMessageConverter<?>> getMessageConverters() {
    if (this.messageConverters == null) {
        this.messageConverters = new ArrayList<HttpMessageConverter<?>>();
        configureMessageConverters(this.messageConverters);
        if (this.messageConverters.isEmpty()) {
            addDefaultHttpMessageConverters(this.messageConverters);
        }
        extendMessageConverters(this.messageConverters);
    }
    return this.messageConverters;
}

请参阅:Github - WebMvcConfigurationSupport

如您所见,有3种方法:

  1. configureMessageConverters,默认情况下为空,您可以在此处添加转换器
  2. addDefaultHttpMessageConverters,如名称所示,将创建所有默认转换器,在此处创建默认MappingJackson2HttpMessageConverter
  3. extendMessageConverters作为文档:
  4.   

    重写此方法以扩展或修改转换器列表   它已配置。例如,这可能是有用的   要注册的默认转换器然后插入自定义   转换器通过这种方法。

    在添加了所有默认转换器后想要修改列表时使用。

    要回答您的问题,如果您不需要默认转换器,则只需覆盖configureMessageConverters并添加它:

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new FeatureConverter());
    }
    

    如果您需要它们,您可以复制粘贴addDefaultHttpMessageConverters内容并将其添加到configureMessageConverters并按照初始化顺序播放(丑陋的解决方案)。

    否则,您可以使用extendMessageConverters在默认初始化后添加它并使用命令:

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(the_index_you_want, new FeatureConverter()); 
    }
    

答案 1 :(得分:0)

如果我理解正确,您希望使用# for specific class -keepclassmembers class FQNClassName { protected <fields>; } # for all classes -keepclassmembers class * { protected <fields>; } # other approach for default acl # be careful as method could have also native modifiers :) -keepclassmembers class * { !public !protected !private *; } Builder对象进行反序列化。 也许你可以使用杰克逊注释(没有Feature):

FeatureConverter

如果您使用import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; @JsonDeserialize(builder = Feature.FeatureBuilder.class) public class Feature { private final String name; public Feature(String name) { this.name = name; } public String getName() { return name; } /** * Builder */ @JsonPOJOBuilder(withPrefix = "") public static final class FeatureBuilder { private String name = ""; private FeatureBuilder() { } public static FeatureBuilder create() { return new FeatureBuilder(); } public FeatureBuilder name(String name) { this.name = name; return this; } /** * Build Feature object */ public Feature build() { Feature feature = new Feature(this.name); return feature; } } }

Lombok