HttpMessageConverter<\T>是Spring的一个重要接口,负责将请求信息转换为一个对象(类型是T),将对象(类型T)输出为响应信息。
DispatcherServlet默认已经安装了RequestMappingHandlerAdapter作为HandlerAdapter的组件实现类:
#Spring 2.5中
//处理器适配器(3个)
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
在spring mvc 3.1中,对应变更为 :
DefaultAnnotationHandlerMapping 变更为 RequestMappingHandlerMapping
AnnotationMethodHandlerAdapter 变更为 RequestMappingHandlerAdapter
AnnotationMethodHandlerExceptionResolver 变更为 ExceptionHandlerExceptionResolver
HttpMessageConverter即由RequestMappingHandlerAdapter使用,将请求信息转换为对象,或将对象转换为响应信息。
Spring提供了HttpMessageConverter<\T>众多的实现类:
RequestMappingHandlerAdapter已经默认安装了四种HttpMessageConverter:
public RequestMappingHandlerAdapter() {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false);
this.messageConverters = new ArrayList(4);
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(stringHttpMessageConverter);
this.messageConverters.add(new SourceHttpMessageConverter());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}
如果需要装配其他的HttpMessageConverter,则可在Spring的web上下文中自行定义(也就是DispatcherServlet中定义的文件或默认文件spiter-servlet.xml):
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"
p:messageConverters-ref="messageConverters"/>
<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"/>
</util:list>
如果显式定义了一个RequestMappingHandlerAdapter,则SpringMVC将使用它覆盖默认的RequestMappingHandlerAdapter。
二、使用HttpMessageConverter<\T>
有两种方法将请求信息转换并绑定到处理方法的入参中,当控制器处理方法使用@RequestBody、@ResponseBody、HttpEntity<\T>、ResponseEntity<\T>时,SpringMVC才使用注册的HttpMessageConverter对请求响应消息进行处理,
Spring首先根据请求头或响应头的Content-Type(请求)或Accept(响应)属性选择匹配的HttpMessageConverter(可能会有很多个满足),然后根据参数类型或泛型类型的过滤得到匹配的HttpMessageConverter(选择一个合适的):
1、使用@RequestBody和@ResponseBody对处理方法进行标注,对请求体和响应体进行处理,并不需要成对出现。
//GET请求不能使用@RequestBody
@RequestMapping(value = "/hand41",method = RequestMethod.POST)
//将整个请求体参数进行转换,而不是报文头
//将请求报文头转换为字符串绑定到requestBody入参中
//如果请求没有指定Content-Type,会使用默认的application/x-www-form-urlencoded类型,再根据参数类型选择HttpMessageConverter(本例中是String类型,因此选择StringHttpMessageConverter)
public String hand41(@RequestBody String requestBody){
System.out.println(requestBody);
return "user/success";
}
}
在Postman中验证一下:
//@ResponseBody可以使用GET、POST请求
//没有设置Accept,默认是text/plain纯文本形式
//方法的返回类型是String,,会使用StringHttpMessageConverter对返回值进行处理。将返回值返回到客户端响应报文体中
@ResponseBody
@RequestMapping(value = "/hand42/{name}")
public String hand42(@PathVariable("name")String name){
return name;
}
2、使用HttpEntity<\T>和ResponseEntity<\T>对请求信息和响应信息进行转换
2.1、使用HttpEntity<\T>
//GET、POST请求都可以
@RequestMapping(value = "/handle43",method = RequestMethod.POST)
//泛型类型是String,所以使用StringHttpMessageConverter进行信息转换
public String handle43(HttpEntity<String> httpEntity){
//获取请求头的信息
long contentLen=httpEntity.getHeaders().getContentLength();
//获取报文体的信息
String requestBody=httpEntity.getBody();
return "user/success";
}
2.2、使用ResponseEntity<\T>
//返回值类型是ResponseEntity<String>,其中泛型类型是String,
@RequestMapping(value = "/hand44/{name}")
public ResponseEntity<String> hand44(@PathVariable("name") String name){
MultiValueMap<String,String> header=new LinkedMultiValueMap<String, String>();
header.add("Accept","text/plain");
//设置响应的body、head、状态
ResponseEntity<String> responseEntity=new ResponseEntity<String>(name,header, HttpStatus.OK);
return responseEntity;
}