Spring MVC:是否可以将特定的HttpMessageConverter绑定到@RequestBody注释的参数?

Lyu*_*riv 1 java rest spring-mvc spring-boot

我有一个默认的Spring Boot应用程序AbstractJackson2HttpMessageConverter。界杰克逊ObjectMapper实例已SimpleModule注册了一个自定义,因此现在支持MultimapGoogle Guava库。

@Bean
public ObjectMapper objectMapper() {
    return new ObjectMapper()
            .setSerializationInclusion(NON_NULL)
            .configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
            .registerModule(new SimpleModule()
                    .addSerializer(multimapType, multimapDuplicateKeysSerializer)
                    .addDeserializer(multimapType, multimapJsonDeserializer)
            );
}
Run Code Online (Sandbox Code Playgroud)

并假设我的控制器中具有以下方法:

@RequestMapping(method = POST)
@ResponseStatus(OK)
public Object post(
    @RequestBody final Multimap<String, Object> multimap
) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

在这一步,一切都很好。现在,我必须验证多图是否为空键或空键,如果在传入的多图中发现任何无效键,则返回HTTP 400。这是一个微不足道的操作,可以轻松地遍历传入的多图并抛出异常,以在控制器建议中进行处理。但这至少具有以下缺陷:

  • 我不想直接在控制器或相关服务中的某处验证多图。
  • 如果有缺陷:我无法使其与Spring MVC注释一起使用 @Valid@ModelAttribute等等,但现在我真的不关心这些,因为以下的原因:
  • 我不希望在反序列化之后对multimap进行验证,因为我想在解析器级别的特定位置验证传入的请求正文HttpMessageConverter-我需要的验证纯粹是JSON流验证,即使对于大型多图,不需要在验证之前对整个多图进行反序列化。当然,如果可能的话。

是否可以仅将特定内容绑定HttpMessageConverter到特定内容@RequestBody?大概是这样的:

@RequestMapping(method = POST)
@ResponseStatus(OK)
public Object post(
    @SomeMagicSpringAnnotationHere("specificHttpMessageConverter") @RequestBody final Multimap<String, Object> multimap
    OR
    @AnotherMagicSpringAnnotationHere("specificObjectMapper") @RequestBody final Multimap<String, Object> multimap
    OR
    @WhateverMagicSpringAnnotationHere @RequestBody final Multimap<String, Object> multimap
) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

还是我对这种方法错误,可以通过与Spring相关且更优雅的方法来实现?任何建议都非常感谢。提前致谢!

M. *_*num 5

创建专门的注释,即 @MultiMapRequestBody

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MultiMapRequestBody {

    boolean required() default true;
Run Code Online (Sandbox Code Playgroud)

然后创建一个MultiMapRequestBodyMethodArgumentResolver知道该怎么做的。

public class MultiMapRequestBodyMethodArgumentResolver implements HandlerMethodArgumentResolver {

    public  boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(MultiMapRequestBody.class); // maybe check argument type too.
    }

    public  Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        // Logic for validation and converting using Jackson
        // Take a look at MappingJackson2HttpMessageConverter

    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以自己处理主体转换和验证。您可能想看看,以MappingJackson2HttpMessageConverter获取有关如何阅读和解析身体的一些启发。或者扩展其中之一abstract用于参数转换类。

现在,在您的请求处理方法中,使用@MultiMapRequestBody而不是@RequestBody注释。

@RequestMapping(method = POST)
@ResponseStatus(OK)
public Object post(
    @MultiMapRequestBody final Multimap<String, Object> multimap
) {
    ...
}
Run Code Online (Sandbox Code Playgroud)