没有合适的资源?快使用搜索试试~ 我知道了~
资源详情
资源评论
资源推荐
络上对这个问题的分析及解决是很深,部分并能解决问题,且内容基本相同,拿来
主义,把内容放在的博客上!
报错原因可能有两种情况:
1.请求头中没有设置Content-Type参数,或Content-Type参数值是application/json;
2.请求头中正确设置Content-Type参数及参数值,但是在项jar依赖中(pom.xml或
build.gradle)没有添加处json字符的处类,如果SpringMVC框架在启动的时候,检查
com.fasterxml.jackson.databind.ObjectMapper和com.fasterxml.jackson.core.JsonGenerator有
个存在或能加载,则会注册MappingJackson2HttpMessageConverter,这个类使
Jackson将json请求参数转成相应的法参数;同样检查com.google.gson.Gson,如果存在或
能加载,则会注册GsonHttpMessageConverter,这个类使Gson将json请求参数转成相应
的法参数;如果依赖的Jackson和Gson都没有被添加或能加载,则SpringMVC将找到对应
的参数处类。
源码分析
在使SpringMVC的时候,都会添加<mvc:annotation-driven />注解,这个注解下有很多可以配
置的扩展参数,有兴趣的可以研究下。有这个注解,就必定有对应的注解解析,查看
NamespaceHandler接的实现类,发现有个MvcNamespaceHandler。
annotation-driven注解做么,直接看AnnotationDrivenBeanDefinitionParser类。这个类中主
要的就是parse法,这个法中做很多重要的事,如对些可扩展的参数进解析注册,这
些是本篇的重点,有兴趣的可以研究下,关注重点代码。
代码中的messageConverters是消息转换集合,包含对json、xml、atom、rss格式报
的转换。接着,把messageConverters添加到RequestMappingHandlerAdapter中,
RequestMappingHandlerAdapter是处@RequestMapping注解的HandlerAdapter,简单说就是
标注@RequestMapping注解的Controller,是经过RequestMappingHandlerAdapter进调
的。messageConverters是它的个属性,代码如下。
继续看AnnotationDrivenBeanDefinitionParser类,分析上图红框中的ManagedList<?>
messageConverters = getMessageConverters(element, source, parserContext),深这个
getMessageConverters法。
romePresent、jaxb2Present、jackson2Present、jackson2XmlPresent、gsonPresent为true则将
对应的转换包装成BeanDefinition,然后将其添加到messageConverters集合中。这个布尔变
的值在AnnotationDrivenBeanDefinitionParser类的开头处就赋值。
如果相应的实现类存在并且可以被加载,则对应的布尔变值为true,否则为false。也就是说,
如果SpringMVC框架在启动的时候,检查com.fasterxml.jackson.databind.ObjectMapper和
com.fasterxml.jackson.core.JsonGenerator有个存在或能加载,则会注册
MappingJackson2HttpMessageConverter,这个类使Jackson将json请求参数转成相应的法
参数;同样检查com.google.gson.Gson,如果存在或能加载,则会注册
GsonHttpMessageConverter,这个类使Gson将json请求参数转成相应的法参数;如果依赖
的Jackson和Gson都没有被添加或能加载,则SpringMVC将找到json参数转换类,也就没办
法处。
如果配置json参数转换处类,SpringMVC框架将根据请求头中的Content-Type参数遍历
messageConverters,选择匹配的转换类,进参数转换。如果Content-Type参数值类型是
messageConverters中持的,那么就没办法做转换。
总结:
先,SpringMVC框架在启动的时候会遍历Spring容中的所有bean,对标注@Controller或
@RequestMapping注解的类中法进遍历,将类和法上的@RequestMapping注解值进合
并,使@RequestMapping注解的相关参数值(如value、method等)封装个
RequestMappingInfo,将这个Controller实、法及法参数信息(类型、注解等)封装到
HandlerMethod中,然后以RequestMappingInfo为key,HandlerMethod为value存到个以Map
为结构的handlerMethods中。
接着,将@RequestMapping注解中的value(即请求径)值取出,即url,然后以url为key,以
RequestMappingInfo为value,存到个以Map为结构的urlMap属性中。
客户端发起请求的时候,根据请求的URL到urlMap中查找,找到RequestMappingInfo,然后根据
RequestMappingInfo到handlerMethods中查找,找到对应的HandlerMethod,接着将
HandlerMethod封装到HandlerExecutionChain;接着遍历容中所有HandlerAdapter实现类,
找到持这次请求的HandlerAdapter,如RequestMappingHandlerAdapter,然后执
SpringMVC拦截的前置法(preHandle法),然后对请求参数解析及转换,这主要根据
HandlerMethod中封装的参数信息(法参数上的注解)来遍历argumentResolvers(List结构,存储
HandlerMethodArgumentResolver接实现类,同实现类,实现对同注解参数的解析,如
RequestResponseBodyMethodProcessor可以实现对@RequestBody和@ResponseBody参数的
解析),找到持这个注解的HandlerMethodArgumentResolver实现类,然后解析请求参数。
插播下请求参数的解析及转换,下图是HandlerMethodArgumentResolver接的实现类。
从上图中可以看到很多常注解参数的解析类,这分析
RequestResponseBodyMethodProcessor,其它处类感兴趣的可以研究下。
RequestResponseBodyMethodProcessor会从请求头中获取Content-Type参数值,如
application/json,然后遍历messageConverters,查找能够处这种Content-Type的转换类,
如果messageConverters中有可以处application/json请求的处类,如Jackson或Gson,则使
Jackson或Gson对请求体中的参数进读取转换,转换成具体法参数类型,下是Jackson
具体的处代码。
如果messageConverters没有匹配的处类,那就会报415。
最后,(使反射)调具体Controller的对应法返回个ModelAndView对象,执拦截的后
置法(postHandle法),然后对返回的结果进处,最后执afterCompletion法。
BJWcn
- 粉丝: 28
- 资源: 295
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0