我有一个带有默认AbstractJackson2HttpMessageConverter
的Spring Boot应用程序。绑定的杰克逊ObjectMapper
实例已注册自定义SimpleModule
,因此现在它支持Google Guava库中的Multimap
。
@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)
);
}
假设我的控制器中有以下方法:
@RequestMapping(method = POST)
@ResponseStatus(OK)
public Object post(
@RequestBody final Multimap<String, Object> multimap
) {
...
}
在这一步一切都很好。现在我必须验证multimap是否为空键或空键,如果在传入的multimap中找到任何无效键,则返回HTTP 400。这是一个简单的操作,可以轻松完成遍历传入的multimap并抛出异常以在控制器建议中处理。但这至少有下一个缺陷:
@Valid
,@ModelAttribute
之类的Spring MVC注释,但现在我并不真正关心这些,由于以下原因: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
) {
...
}
或者我对这种方法是错误的,它可以通过更多与Spring相关且更优雅的方式来实现?任何建议都非常感谢。提前谢谢!
答案 0 :(得分:4)
创建一个专门的章程,即@MultiMapRequestBody
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MultiMapRequestBody {
boolean required() default true;
然后创建一个知道该做什么的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
}
}
现在您可以自己处理身体转换和验证。您可能需要查看MappingJackson2HttpMessageConverter
,了解如何阅读和解析正文。或者可以扩展用于参数转换的abstract
类之一。
现在,在您的请求处理方法中,使用@MultiMapRequestBody
代替@RequestBody
注释。
@RequestMapping(method = POST)
@ResponseStatus(OK)
public Object post(
@MultiMapRequestBody final Multimap<String, Object> multimap
) {
...
}