Spring3.1.0实现原理分析(十七).MVC请求处理方法参数解析器和返回值解析器

来源:互联网 发布:程序员的修炼之道 pdf 编辑:程序博客网 时间:2024/05/19 22:03
      大家好,通过我之前的分析可以知道一个request请求经过处理器映射对象(RequestMappingHandlerMapping)处理后,可以获得执行链对象,所谓执行链就是一堆拦截器加一个HandlerMethod对象。那么HandlerMethod是什么呢?它主要是对请求处理方法的封装,我们可以看下这个类的定义就能明白。
public class HandlerMethod {/** * 处理器 */private final Object bean;/** * 请求处理方法对象 */private final Method method;/** * 方法参数对象数组 */private MethodParameter[] parameters;......}

       所谓对request请求的处理,最终就是调用请求处理方法对象,那么这里就会涉及到两个问题。第一,请求处理方法可以定义哪些参数呢,参数值从何获取?第二请求处理方法的返回值作何用处?今天我们就分析下这两个问题,spring是通过方法参数解析器和方法返回值解析器来处理这两个问题的

       换句话说,通过今天的讲解你就能明白请求处理方法可以定义哪些类型的参数,参数值从何而来,可以定义哪些类型的方法返回值,spring如何使用返回值。


一. 方法参数解析器

 所有方法参数解析器都实现了HandlerMethodArgumentResolver接口,这个接口中定义了两个方法。

/** * 是否支持对该方法参数的解析 */boolean supportsParameter(MethodParameter parameter);/** * 获取参数值 */Object resolveArgument(MethodParameter parameter,    ModelAndViewContainer mavContainer,   NativeWebRequest webRequest,    WebDataBinderFactory binderFactory) throws Exception;


下面我介绍下这个接口最重要的几个实现类,它们都支持解析哪些类型的参数,参数值从何而来。

1. ServletRequestMethodArgumentResolver(请求相关对象解析器)

支持的参数类型:WebRequest, ServletRequest, MultipartRequest, HttpSession, Principal, Locale, InputStream, Reader 。

参数值来源:源于resolveArgument方法的第三个参数webRequest。


2. ServletResponseMethodArgumentResolver (应答相关对象解析器)

支持的参数类型:ServletResponse, OutputStream, Writer。

参数值来源:源于resolveArgument方法的第三个参数webRequest,从webRequest获取response。


3. SessionStatusMethodArgumentResolver (session处理状态解析器)

支持的参数类型:SessionStatus。

参数值来源:ModelAndViewContainer获取SessionStatus。spring在每次调用请求处理方法之前会创建ModelAndViewContainer对象,该对象持有SimpleSessionStatus对象,参数值就是SimpleSessionStatus。


4. UriComponentsBuilderMethodArgumentResolver (uri构造器对象解析器)

支持的参数类型:UriComponentsBuilder。

参数值来源:根据request.getServletPath()创建UriComponentsBuilder对象,至于UriComponentsBuilder对象有何用处,我没搞明白。


5. RequestParamMapMethodArgumentResolver (请求参数map解析器)

支持的参数类型:被@RequestParam注解的MultiValueMap或Map。

参数值来源:来自request.getParameterMap(),如果参数类型是MultiValueMap,对应值是LinkedMultiValueMap;如果参数类型是Map,对应值是LinkedHashMap,此时某个参数有多个值,只取第一个。


6. RequestHeaderMapMethodArgumentResolver (请求头字段map解析器)

支持的参数类型: 被@RequestHeader注解的Map。

参数值来源:来自request对象,如果参数类型是MultiValueMap,对应值类型是LinkedMultiValueMap;如果参数类型是Map,对应值类型是LinkedHashMap,此时某个头字段有多个值,只取第一个。


7. RedirectAttributesMethodArgumentResolver (重定向对象解析器)

支持的参数类型:RedirectAttributes。

参数值来源:参数解析器会创建全新的RedirectAttributesModelMap对象赋值给参数,并同时把它赋值给ModelAndViewContainer。


8. ModelMethodProcessor (模型对象解析器)

支持的参数类型:Model。

参数值来源:spring会把ModelAndViewContainer持有的BindingAwareModelMap赋值给参数。

补充说明:spring在每次调用请求处理方法之前都会创建ModelAndViewContainer对象(以下简称mavContainer),从它的名字我们也能理解mavContainer最重要的东西就是模型和视图,mavContainer默认持有的模型类型是BindingAwareModelMap。在创建了mavContainer之后,RequestMappingHandlerAdapter会对其模型执行初始化操作,如果暂不考虑闪属性的话(以后介绍),会往模型中填充三类数据。

a. 从request的session中获取所有被@SessionAttributes注解的属性值,置入模型(非覆盖)。

b. 调用被@ModelAttribute注解的方法列表,把方法返回值置入模型(非覆盖)。

c. 解析被@ModelAttribute注解的形参,同时该参数名称或类型被@SessionAttributes注解了,从session中获取参数值,把值添加到容器(非覆盖)。


9.ModelAttributeMethodProcessor(@ModelAttribute注解解析器)

支持的参数类型:参数必须被@ModelAttribute注解。@ModelAttribute这个注解并不太容器理解,它既可以注解方法又可以注解方法参数,还可以注解方法返回值。

参数值来源:这个过程比较复杂,我们详细分析下

 a. 首先它会根据参数名称从request请求路径模板变量中获取值,如果取不到再从请求参数中获取值。如果从上述两个地方获取到参数值了,则执行类型转换,因为参数类型不一定是String,可能是Integer也可能是一个用户类型。如果用户注册了自定义类型转换器,在这个地方就会被调用。

b. 其次spring会把参数值当做目标对象,创建数据绑定器,并执行绑定,绑定值来自request对象。所以我觉得最好别用@ModelAttribute注解基本类型,否则执行绑定的时候是会报错的,因为找不到setter和getter方法,当然这些错误不会被抛出。

c. 判断参数是否被@Valid注解了,注解了则执行校验操作。如果在验证过程中出现了验证错误,spring会判断当前参数的下个参数类型是否是Errors,如果不是则抛出异常。

d. 最后spring把参数值和参数值对应的绑定结果对象,置入mavContainer的模型。


10. MapMethodProcessor(map对象解析器)

支持的参数类型:Map

参数值来源:spring会把ModelAndViewContainer持有的BindingAwareModelMap赋值给参数。

11. ErrorsMethodArgumentResolver(错误对象解析器)

支持的参数类型:Errors。

参数值来源:从mavContainer的Model中获取BeanPropertyBindingResult赋值给参数。这个参数对位置有要求,必须跟在表单对象后面,也就是说必须跟在被@ModelAttribute注解的参数后面


12.ServletCookieValueMethodArgumentResolver (基于servlet的cookievalue解析器)

支持的参数类型:参数被@CookieValue注解了。

参数值来源:从request对象获取cookie值,如果被@CookieValue注解的参数类型是CookieValue,则直接把cookie对象赋值给参数;如果被@CookieValue注解的参数类型是字符串,则把cookie值赋值给参数。@CookieValue注解可以配置是否必须,默认值等。如果配置成了必须,但是从request获取不到cookie值,则返回默认值,如果未设置默认值,则spring抛出异常。


13.PathVariableMethodArgumentResolver (处理@PathVariable注解的参数解析器)

支持的参数类型:参数被@PathVariable注解了。

参数值来源:返回模板路径变量,如果获取不到,则返回null。


14. RequestHeaderMethodArgumentResolver (处理@RequestHeader注解的解析器)

支持的参数类型:参数被@RequestHeader注解了,并且被注解的参数类型不能是Map,通常被注解的参数类型应该是String或String[]。

参数值来源:从request获取请求头字段值。跟@CookieValue一样,这个注解也可以配置是否必须和默认值。


15.RequestParamMethodArgumentResolver (处理@RequestParam注解)

支持的参数类型:参数被@RequestParam注解了,如@RequestParam Stirng,@RequestParam String[]。

参数值来源:从request请求对象获取参数。


16. HttpEntityMethodProcessor (HttpEntity处理器)

支持的参数类型: HttpEntity<T>,如HttpEntity<String>等。

参数值来源:spring创建RequestMappingHandlerAdapter对象时,会为它的成员变量messageConverters设置一组默认的List<HttpMessageConverter<?>>。HttpMessageConverter的作用是负责request的body和对象直接的互转,比如StringHttpMessageConverter实现了body和String之间的互转。假设形参是HttpEntity<String>,则参数值就是StringHttpMessageConverter。


17.RequestResponseBodyMethodProcessor(RequestBody注解处理器)

支持的参数类型:被@RequestBody注解的参数,具体类型可以是某个HttpMessageConverter支持转换的类型。

参数值来源:调用支持该类型的HttpMessageConverter,把request的body转换成该类型。比如参数类型是String.class,则spring调用StringHttpMessageConverter把body转换成String后赋值给参数。


18. RequestPartMethodArgumentResolver (文件上传解析器)

支持的参数类型:@RequestPart(value="file") MultipartFile file,MultipartFile,List<MultipartFile>,javax.servlet.http.Part。

参数值来源:从文件上传请求对象MultipartHttpServletRequest获取参数值,关于spring的文件上传模块以后单户写篇博客分析,这里不展开了。


二. 方法返回值解析器

1. ViewNameMethodReturnValueHandler (视图名称方法返回值解析器)

支持的返回值类型:void,String。

如何处理返回值:如果返回值是null,不做任何处理;如果返回是字符串,把字符串当做视图名称;如果字符串中包含重定向字符,则设置ModelAndViewContainer的成员变量redirectModelScenario为true。


2. ViewMethodReturnValueHandler (View类型方法返回值解析器)

支持的返回值类型:View接口的实现类。

如何处理返回值:把view对象赋值给ModelAndViewContainer。


3. ModelMethodProcessor(模型对象处理器)

支持的返回值类型:Model接口的实现类。

如何处理返回值:把方法返回的Model中的键值对添加到ModelAndViewContainer持有的Model中。


4. ServletModelAttributeMethodProcessor(基于@ModelAttribute注解的处理器)

支持的返回值类型:返回值被@ModelAttribute注解了。

如何处理返回值:把返回值置入ModelAndViewContainer持有的Model中,可以通过@ModelAttribute的value指定key。


5. ModelAndViewMethodReturnValueHandler(ModelAndView返回值解析器)

支持的返回类型:ModelAndView。

如何处理返回值:把返回值ModelAndView持有的视图名称和ModelMap赋值给ModelAndViewContainer。


6.MapMethodProcessor(Map返回值处理器)

支持的返回类型:Map接口的实现类。

如何处理返回值:把Map中的键值对置入ModelAndViewContainer的Model。


7. HttpEntityMethodProcessor(HttpEntity返回值处理器)

支持的参数类型:HttpEntity 或 ResponseEntity。

如何处理返回值:从返回值获取结果码,头字段,body输出到Response对象。


8.RequestResponseBodyMethodProcessor(ResponseBody注解处理器)

支持的参数类型:返回值被@ResponseBody注解了。

如何处理返回值:把返回值通过HttpMessageConverter输出到Response的body。

阅读全文
0 0
原创粉丝点击