内容参考自https://my.oschina.net/lichhao/blog/172562
在SpringMVC中,可以使用@RequestBody与@ResponseBody完成报文到对象、对象到报文的转换。这就是依靠Spring3.0引入的消息转换器机制实现的:
HttpMessageConverter
/** * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses. * * @author Arjen Poutsma * @author Juergen Hoeller * @since 3.0 * @param <T> the converted object type */ public interface HttpMessageConverter<T> { boolean canRead(Class<?> clazz, @Nullable MediaType mediaType); boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType); T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException; }在HttpServlet接口处理请求时会调用service()方法:
其中的参数ServletRequest与ServletResponse封装了请求和结果。
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest)req; response = (HttpServletResponse)res; } catch (ClassCastException var6) { throw new ServletException(lStrings.getString("http.non_http")); } this.service(request, response); }在ServletRequest接口中,通过getInputStream()获取请求信息。
ServletInputStream getInputStream() throws IOException;在ServletResponse接口中,通过getOutputStream()返回结果信息。
ServletOutputStream getOutputStream() throws IOException;可以理解成Http的交互就是流的交互,在SpringMVC中,对内部的流进行了抽象,顶层接口就是HttpMessage。他的子类分别是
public interface HttpOutputMessage extends HttpMessage { /** * Return the body of the message as an output stream. * @return the output stream body (never {@code null}) * @throws IOException in case of I/O errors */ OutputStream getBody() throws IOException; } public interface HttpInputMessage extends HttpMessage { /** * Return the body of the message as an input stream. * @return the input stream body (never {@code null}) * @throws IOException in case of I/O errors */ InputStream getBody() throws IOException; }一次http请求与返回跟SpringMVC的过程简述为下图
Http发送接收的是流,HttpMessageConverter操作的是HttpMessage,这整个过程用一个类完成,那就是RequestResponseBodyMethodProcessor。它同时负责请求的参数解析和返回值处理,判断是否有@RequestBody、@ResponseBody,然后调用converter(HttpMessageConverter的各种子类,比如StringHttpMessageConverter处理返回值是String的)进行读写。
@Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(RequestBody.class); } @Override public boolean supportsReturnType(MethodParameter returnType) { return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) || returnType.hasMethodAnnotation(ResponseBody.class)); } @Override public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { parameter = parameter.nestedIfOptional(); Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType()); String name = Conventions.getVariableNameForParameter(parameter); if (binderFactory != null) { WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name); if (arg != null) { validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { throw new MethodArgumentNotValidException(parameter, binder.getBindingResult()); } } if (mavContainer != null) { mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); } } return adaptArgumentIfNecessary(arg, parameter); } @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true); ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); // Try even with null return value. ResponseBodyAdvice could get involved. writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); }
