HttpMessageConverter

HttpMessageConverter<T>是Spring3的一个重要接口,它负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息。web

DispatcherServlet默认已安装RequestMappingHandlerAdapter做为HandlerAdapter的组件实现类,HttpMessageConverter即由RequestMappingHandlerAdapter使用,将请求信息转换为对象,或将对象转换为响应信息。spring

HttpMessageConverter<T>接口定义如下几个方法:json

/**
 * 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提供了众多的实现类mvc

RequestMappingHandlerAdapter默认已经注册了如下HttpMessageConverter:app

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.xmlthis

<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(默认配置就没有了)。spa

如何使用 HttpMessageConverter<T> 将请求信息转换并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring MVC提供了两种途径:code

1. 使用@RequestBody/@ResponseBody 对处理方法进行标注orm

2. 使用HttpEntity<T>/ResponseEntity<T> 做为处理方法的入参或返回值xml

示例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(); }
 请求时的目标类型:
方法的实际返回值为:Employee 的集合
SpringMVC 发现须要返回的是JSON类型,但实际返回的是Employee的集合。此时@ResponseBody查找有没有把结果转为JSON 的HttpMessageConverter,若是有,则调用其对应的方法,把结果转为JSON类型。
结论:
1.只有当处理器方法使用到@RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时,SpringMVC才使用注册的HttpMessageConverter 对请求响应消息进行处理。
2.当控制器处理方法使用到 @RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时,Spring 首先根据请求头或响应头的 Accept 属性选择匹配的 HttpMessageConverter, 而后根据参数类型或泛型类型的过滤获得匹配的 HttpMessageConverter, 若找不到可用的HttpMessageConverter 将报错
3.@RequestBody 和 @ResponseBody 不须要成对出现。若是方法入参使用到了@RequestBody,SpringMVC将会选择匹配的HttpMessageConverter 将请求信息转换并绑定到该入参中。若是处理方法标注了@ResponseBody,SpringMVC选择匹配的HttpMessageConverter 将方法返回值转换并输出响应消息。
相关文章
相关标签/搜索