spring中HttpMessageConverter详解

HttpMessageConverter 介绍

Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.

简单来说,HttpMessageConverter就是一个策略接口, 用来将http请求转为某个对象, 或许将http响应转为指定类型的对象。

HttpMessageConverter接口声明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public interface HttpMessageConverter<T> {

//检测参数clazz指定的类型是否可以被该转换器读取
trueboolean canRead(Class<?> clazz, MediaType mediaType);

//检测参数clazz指定的类型是否可以被该转换器写入
trueboolean canWrite(Class<?> clazz, MediaType mediaType);

//获取该转换器支持的媒体类型列表
trueList<MediaType> getSupportedMediaTypes();

//从输入信息中读取指定类型对象
trueT read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;

// 将指定的对象写入到输出
truevoid write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;

}

什么时候使用?

通常,我们在Controller里带有返回值得请求处理方法上加上注解@ResponseBody注解后,springMVC内部就会使用到HttpMessageConverter。 原理如下:

AnnotationMethodHandlerAdapter接口是专门用来处理加了@Controller注解的Controller的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
//省略
return invokeHandlerMethod(request, response, handler);
}
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
truetrue// 省略
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
truetrueModelAndView mav = methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
truetruemethodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
return mav;
}
@SuppressWarnings("unchecked")
truetruepublic ModelAndView getModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue,ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception {
// 省略
if (returnValue instanceof HttpEntity) {
handleHttpEntityResponse((HttpEntity<?>) returnValue, webRequest);
return null;
}
else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
handleResponseBody(returnValue, webRequest);
return null;
}
// 省略
}
private void handleResponseBody(Object returnValue, ServletWebRequest webRequest) throws Exception {
trueif (returnValue == null) {
truetruereturn;
true}
trueHttpInputMessage inputMessage = createHttpInputMessage(webRequest);
trueHttpOutputMessage outputMessage = createHttpOutputMessage(webRequest);
truewriteWithMessageConverters(returnValue, inputMessage, outputMessage);
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private void writeWithMessageConverters(Object returnValue,HttpInputMessage inputMessage, HttpOutputMessage outputMessage) throws IOException, HttpMediaTypeNotAcceptableException {
List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();
truetrueif (acceptedMediaTypes.isEmpty()) {
truetruetrueacceptedMediaTypes = Collections.singletonList(MediaType.ALL);
truetrue}
truetrueMediaType.sortByQualityValue(acceptedMediaTypes);
truetrueClass<?> returnValueType = returnValue.getClass();
truetrueList<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
truetrueif (getMessageConverters() != null) {
truetruetruefor (MediaType acceptedMediaType : acceptedMediaTypes) {
truetruetruetruefor (HttpMessageConverter messageConverter : getMessageConverters()) {
truetruetruetrue // 判断是否支持
truetruetruetruetrueif (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
truetruetruetruetrue // 写入输出
truetruetruetruetruetruemessageConverter.write(returnValue, acceptedMediaType, outputMessage);
truetruetruetruetruetrueif (logger.isDebugEnabled()) {
truetruetruetruetruetruetrueMediaType contentType = outputMessage.getHeaders().getContentType();
truetruetruetruetruetruetrueif (contentType == null) {
truetruetruetruetruetruetruetruecontentType = acceptedMediaType;
truetruetruetruetruetruetrue}
truetruetruetruetruetruetruelogger.debug("Written [" + returnValue + "] as \"" + contentType +
truetruetruetruetruetruetruetruetrue"\" using [" + messageConverter + "]");
truetruetruetruetruetrue}
truetruetruetruetruetruethis.responseArgumentUsed = true;
truetruetruetruetruetruereturn;
truetruetruetruetrue}
truetruetruetrue}
truetruetrue}
truetruetruefor (HttpMessageConverter messageConverter : messageConverters) {
truetruetruetrueallSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
truetruetrue}
truetrue}
truetruethrow new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
}

输出json

SpringMVC默认是使用Jackson(MappingJackson2HttpMessageConverter)来将返回对象转为json的。当然了,你也可以配置其它的类来实现Json的输出。

输出XML

具体的类是:MappingJackson2XmlHttpMessageConverter。 请求头Accept是”application/*+xml” 或 “application/xml”

输出feed

具体的类是:RssChannelHttpMessageConverter。 请求头Accept是:”application/rss+xml”

文章目录
  1. 1. HttpMessageConverter 介绍
  2. 2. 什么时候使用?
  3. 3. 输出json
  4. 4. 输出XML
  5. 5. 输出feed
|