HTTP 请求和响应的传输是字节流,意味着浏览器和服务器通过字节流进行通信。但是,使用 Spring,controller 类中的方法返回纯 String 类型或其他 Java 内建对象。如何将对象转换成字节流进行传输?
在报文到达SpringMVC和从SpringMVC出去,都存在一个字节流到java对象的转换问题。在SpringMVC中,它是由HttpMessageConverter来处理的。
当请求报文来到java中,它会被封装成为一个ServletInputStream的输入流,供我们读取报文。响应报文则是通过一个ServletOutputStream的输出流,来输出响应报文。
我们可以用下图来加深理解。
在Spring中,内置了大量的HttpMessageConverter。通过请求头信息中的MIME类型,选择相应的HttpMessageConverter。
// 数据转换器 -> 将数据转换成 requests 或 response 中的数据
public interface HttpMessageConverter
// 指定的 class 是否支持读取(MediaType 指数据的格式)
boolean canRead(Class<?> clazz, MediaType mediaType);
// 传入 class 与 MediaType -> 看 HttpMessageConverter 是否支持写数据到数据流中
boolean canWrite(Class<?> clazz, MediaType mediaType);
// 返回 HttpMessageConverter 支持的 MediaType
List<MediaType> getSupportedMediaTypes();
// 从 HttpInputMessage 中读取数据流, 并转化成 T 这站类型
T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
// 将 T 里面的数据信息写入到 HttpOutputMessage 的数据流中
void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
}
HttpMessageConverter接口的定义中出现了成对的canRead(),read()和canWrite(),write()方法。MediaType是对请求的Media Type属性的封装。
read方法中有一个HttpInputMessage,我们查看它的源码如下。
public interface HttpInputMessageextends HttpMessage {
InputStreamgetBody() throws IOException;
}
HttpInputMessage提供的接口就是将body中的数据转为输入流。
write方法中有一个HttpOutputMessage,我们查看它的源码如下。
public interface HttpOutputMessageextends HttpMessage {
OutputStreamgetBody() throws IOException;
}
HttpOutputMessage提供的接口就是将body中的数据转为输出流。
它们拥有相同的父接口HttpMessage。
public interface HttpMessage {
HttpHeadersgetHeaders();
}
HttpMessage提供的方法是读取头部中的信息。
1. FormHttpMessageConverter
支持 MultiValueMap 类型, 并且 MediaType 类型是 "multipart/form-data", 从 InputStream 里面读取数据, 并通过&符号分割, 最后转换成 MultiValueMap, 或 将 MultiValueMap转换成 & 符号连接的字符串, 最后转换成字节流, 输出到远端
HttpMessageConverter 在整个 SpringMVC 中起着根据 MediaType 类型将 HttpServletRequest 中的数据转换成 指定对象的转换器, 或将对象转换成指定格式的数据(PS: byte/String/xml/json 等);
1.通过继承 AbstractHttpMessageConverter自定义HttpMessageConverter
<!--视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/pages/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
手机扫一扫
移动阅读更方便
你可能感兴趣的文章