HttpMessageConverter<T>是Spring3的一个重要接口,它负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息。
DispatcherServlet默认已安装了RequestMappingHandlerAdapter作为HandlerAdapter的组件实现类,HttpMessageConverter即由RequestMappingHandlerAdapter使用,将请求信息转换为对象,或将对象转换为响应信息。
HttpMessageConverter<T>接口定义以下几个方法:
/** * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses. */ public interface HttpMessageConverter<T> { /** * Indicates whether the given class can be read by this converter. */ boolean canRead(Class<?> clazz, MediaType mediaType); /** * Indicates whether the given class can be written by this converter. */ boolean canWrite(Class<?> clazz, MediaType mediaType); /** * Return the list of {@link MediaType} objects supported by this converter. */ List<MediaType> getSupportedMediaTypes(); /** * Read an object of the given type form the given input message, and returns it. */ T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; /** * Write an given object to the given output message. */ void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException; }
Spring为HttpMessageConverter提供了众多的实现类
RequestMappingHandlerAdapter默认已经注册了以下HttpMessageConverter:
private List<HttpMessageConverter<?>> messageConverters; public RequestMappingHandlerAdapter() { StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316 this.messageConverters = new ArrayList<HttpMessageConverter<?>>(4); this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(stringHttpMessageConverter); this.messageConverters.add(new SourceHttpMessageConverter<Source>()); this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); }
如果需要装配其他类型的HttpMessageConverter,可以在Spring的web容器(Spring子容器)上下文中自行定义一个RequestMappingHandlerAdapter,注册若干HttpMessageConverter。dispatcher-servlet.xml
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters" ref="messageConverters"/> </bean> <!--HttpMessageConverter列表--> <util:list id="messageConverters"> <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/> <bean class="org.springframework.http.converter.StringHttpMessageConverter"/> <bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/> </util:list>
如果在Spring web容器中显式定义了一个RequestMappingHandlerAdapter,则Spring MVC将使用它覆盖默认的AnnotationMethodHandlerAdapter(默认配置就没有了)。
如何使用 HttpMessageConverter<T> 将请求信息转换并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring MVC提供了两种途径:
1. 使用@RequestBody/@ResponseBody 对处理方法进行标注
2. 使用HttpEntity<T>/ResponseEntity<T> 作为处理方法的入参或返回值
示例1:
@RequestMapping(value = "/handle41")
public String handle41(@RequestBody String requestBody){
//将请求-报文体-转换为字符串绑定到requestBody入参中
}
@ResponseBody
@RequestMapping("/handle42")
public byte[] handle42(){
//
}
handle41()处Spring MVC将根据requestBody的类型(String)查找匹配的HttpMessageConverter,由于StringHttpMessageConverter的泛型类型对应String,所以StringHttpMessageConverter将会被Spring MVC选中,用它将请求体(POST)信息进行转换并且将结果绑定到requestBody入参上!
handle42()处,由于方法的返回值类型为byte[],所以Spring MVC根据类型匹配的查找规则将使用ByteArrayHttpMessageConverter对返回值进行处理。
和@RequestBody/@ResponseBody类似,HttpEntity<?>不但可以访问请求和响应报文头的数据,还可以访问请求和响应报文体的数据(也就是HttpEntity中不但有头数据还有体数据),Spring MVC根据HttpEntity的泛型类型查找对应的HttpMessageConverter。
在接收到一个http请求的时候,处理方法如何知道请求消息的格式,在处理完成之后又根据什么确定响应消息的格式?答案很简单,根据请求消息头的"Content-Type"及Accept属性确定。
Content-Type表示本次请求的报文内容格式。
Accept表示接受的MIME类型。
@ResponseBody
@RequestMapping( "/getEmployeesForJson")
public Collection<Employee> getEmployees() {
return employeeDao .getAll();
}