在自定义注解中实现@RequestBody 的功能

Implement functionality of @RequestBody in custom annotation

我创建了一个自定义注释 @JsonSchema,我在其中实现了 @RequestBody 的功能。我的注释将始终用于从 Web 请求中读取 JSON。但是我想在让它进一步传递之前根据模式验证 JSON 。为此,我有一个 class 实现 HandlerMethodArgumentResolver

最初,我的注释仅与 String 一起使用,因此我很容易从 RequestResponseBodyMethodProcessor#resolveArgument 获取通用对象,将其转换为字符串,对其进行验证,然后 return 它。但现在我也想将我的注释与自定义 classes 一起使用。

所以我想了解的是 @RequestBody 如何将 Web 请求正文中的绑定 JSON 转换为兼容 class。如果我了解这是怎么发生的,我可以首先将正文提取为字符串,进行验证,然后将正文绑定到具有我的注释和 return 的任何 class。

我目前的实施resolveArgument

@Override
public Object resolveArgument(MethodParameter parameter,
        ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
        WebDataBinderFactory binderFactory) throws Exception {
    Object value =  getRequestResponseBodyMethodProcessor()
            .resolveArgument(parameter, mavContainer, webRequest, binderFactory);
    return value;
//      return validateJson(value, parameter); I need to pass a String here

}

// Using message converters to read from body of web request. Can I parse the message earlier than it is cast to the required object type?
private RequestResponseBodyMethodProcessor getRequestResponseBodyMethodProcessor() {

    if (requestResponseBodyMethodProcessor == null) {
        List<HttpMessageConverter<?>> messageConverters = requestMappingHandlerAdapter().getMessageConverters();
        requestResponseBodyMethodProcessor = new RequestResponseBodyMethodProcessor(messageConverters);
    }
    return requestResponseBodyMethodProcessor;
}

经过一些研究,我遇到了一个叫做 HttpMessageConverter 的东西。消息转换器用于通过 HTTP 编组和解组 Java 对象到 JSON、XML 等。有一些默认转换器,其中 StringHttpMessageConverter 是其中之一。我们还可以添加自己的消息转换器。 Here 是一篇很好的文章,解释了如何做到这一点。

我通过调用 RequestMappingHandlerAdapter#getMessageConverters 获得了消息转换器的默认集合。我从中提取了 StringHTTPMEssageConverter 并调用了它的 read 方法来读取正文作为字符串。

代码如下:

if (requestResponseBodyMethodProcessor == null) {
        List<HttpMessageConverter<?>> messageConverters = requestMappingHandlerAdapter().getMessageConverters();
        requestResponseBodyMethodProcessor = new RequestResponseBodyMethodProcessor(messageConverters);
}

String body = null;
StringHttpMessageConverter stringHttpMessageConverter = null;
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
HttpInputMessage inputMessage = new ServletServerHttpRequest(servletRequest);
if (messageConverters.get(1) instanceof StringHttpMessageConverter)
        stringHttpMessageConverter = (StringHttpMessageConverter) messageConverters.get(1);

try {
        body = stringHttpMessageConverter.read(String.class, inputMessage);
} catch (IOException e) {
        e.printStackTrace();
}