附上自己项目的配置文件:
text/html
application/json
application/javascript
text/plain
auto_detect
UTF-8
UTF-8
zh_CN
yyyy-MM-dd
HH:mm:ss
/spring.ftl as spring
yyyy-MM-dd HH:mm:ss
#
true
html_debug
com.dianping.emidas.merchant.**.domain
error/error-page
error/error-page
error/error-page
error/error-page
500
首先谈一下,mvc中对各种请求及返回类型的一些认识。(以下内容皆基于springmvc 4.0之后的版本)
项目中基本的使用情况,有以下几类
请求:
1、path、parameter,key/value形式绑定数据
2、requestBody,json格式字符串映射controller参数对象,只支持post请求,并且contentType需设置为contentType: "application/json"
返回:
1、freemarker、velocity基础请求返回基于模板引擎渲染的html页面
2、rest形式,返回json/jsonp/xml形式的对象,具体返回类型由请求头 accept与提供的messageconverter决定 accept与contentType概念参考
http://blog.csdn.net/z69183787/article/details/52313101
3、excel或pdf类文件流以供下载
text/html
application/json
application/javascript
text/plain
springmvc初始化时,会根据
中的配置项生成ContentNegotiationManager,并将对应策略mediaType的解析strategies注入
其中配置项ignoreAcceptHeader true:忽视请求头中的accept中的contentType,去除HeaderContentNegotiationStrategy策略;false为默认项
favorPathExtension标示启动后缀匹配mediaType,比如a.xml匹配excel
defaultContentType标识默认contentType,启动FixedContentNegotiationStrategy策略
当defaultContentType生效时,会忽略header中的accept,chrome中浏览器访问接口的 accept为
可以看到最后又 */*,该mediaType可以兼容任何响应mediaType。完。
接上,其中supportedMediaTypes指定了该转换器可以支持的响应contentType,当请求中的contentType与该转换器的支持类型匹配时,springmvc会选择该消息转换器进行消息响应及格式处理。
在项目中最常见的情况就是,浏览器直接访问请求,返回http406,就是因为当浏览器直接访问同时(ignoreAcceptHeader 为true)时,
当设置defaultContentType时即返回 默认contentType,若恰好设置的值无法与转换器中的匹配,比如设置为text/html ,返回requestedMediaTypes 为 text/html,
当json转换器中没有配置该mediaType时,即会返回406(无法处理该类请求)。
当未设置defaultContentType时 由于所有策略均无法解析,mediaType为空 ,返回requestedMediaTypes 为 */*,即可匹配所有messageConverter
当如下请求进入时,并有@ResponseBody注解时,
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/test")
public Test index(Test t) throws Exception {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(t.getA()));
return new Test();
}
由AbstractMessageConverterMethodProcessor的writeWithMessageConverters进行处理,其中有如下关键方法
Class> returnValueClass = getReturnValueType(returnValue, returnType);
HttpServletRequest servletRequest = inputMessage.getServletRequest();
List requestedMediaTypes = getAcceptableMediaTypes(servletRequest);
List producibleMediaTypes = getProducibleMediaTypes(servletRequest, returnValueClass);
List
关于messageConverter的其他内容可以参见:
http://blog.csdn.net/z69183787/article/details/52261274
http://blog.csdn.net/z69183787/article/details/52261238
http://blog.csdn.net/z69183787/article/details/52302172
之后对请求需要的与mvc提供的进行一个匹配,然后得到真实的messageConverter,并调用write方法进行json渲染。
以上是对响应消息时mvc的messageConverter处理模式。下面来看一下请求时的处理方式,这里使用@RequestBody直接接收json来调试,
RequestResponseBodyMethodProcessor负责处理
当如下请求进入时,@RequestBody请求必须为Post
@ResponseBody
@RequestMapping(method = RequestMethod.POST, value = "/test")
public Test index(@RequestBody Test t) throws Exception {
System.out.println(t);
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(t.getA()));
return new Test();
}
进入resolveArgument方法 对requestbody中的数据与参数的json对象进行绑定
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception
有一点需要注意,如果ajax传入的json字符串中的参数比实际接收java对象的参数多,那么会抛出转换失败的异常org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON
解决方案:http://blog.csdn.net/z69183787/article/details/52302323
http://blog.csdn.net/z69183787/article/details/52302392
http://blog.csdn.net/z69183787/article/details/52290014
http://blog.csdn.net/z69183787/article/details/52290032