SpringMVC通过DispatcherServlet来处理请求信息,其中servlet-mapping配置指定了由Spring MVC 处理的请求的路径。下图中url-pattern被指定为/,这与/*有很大不同。

DispatcherServlet拦截请求路径
Tomcat在启动时会扫描web.xml文件,得到servlet的映射数据servletMappings,据此可以知道每个servlet处理的请求路径。通过分析源码,通常把路径4类:
1.以 /* 结尾的 path.endsWith("/*")
2.以 . 开头的 path.startsWith(".")
3.是否是 / path.equals("/")
4.以上3种之外的
上述4种映射处理后会被放入 wrapper中,这里Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收,其中4类servlet对应的wrapper如下:
1./* 对应的Servlet会放在wildcardWrappers中
2.*. 会被放到extensionWrappers中
3./ 会被放到defaultWrapper中(缺省)
4.其他的映射都被放到exactWrappers中(精确匹配某一路径)
用户的请求过来时,会对请求的url进行匹配,匹配规则的先后顺序如下:
1.精确匹配,使用contextVersion的exactWrappers
2.前缀匹配,使用contextVersion的wildcardWrappers
3.扩展名匹配,使用contextVersion的extensionWrappers
4.使用资源文件来处理servlet,使用contextVersion的welcomeResources属性,这个属性是个字符串数组
5.使用默认的servlet,使用contextVersion的defaultWrapper
DispatcherServlet处理过程
下面我们继续分析对于某个具体的请求(如http://ip:port/contextPath/path)
SpringMVC如何找到对应的Controller方法,即请求与Controller之间的映射关系。DispatcherServlet根据url得到对应的HandlerAdapter进行处理,处理过程中有几个重要的接口,HandlerMethodArgumentResolver、HandlerMethodReturnValueHandler。HandlerAdapter在处理每个请求时会实例化一个ServletInvocableHandlerMethod对象进行处理,处理请求时会根据ServletInvocableHandlerMethod的属性argumentResolvers(这个属性是它的父类InvocableHandlerMethod中定义的)进行处理,其中argumentResolvers属性是一个HandlerMethodArgumentResolverComposite类,这个类是实现了HandlerMethodArgumentResolver接口的类, 处理响应的时候,会根据ServletInvocableHandlerMethod的属性returnValueHandlers进行处理,returnValueHandlers属性是一HandlerMethodReturnValueHandlerComposite类,这个类是实现了HandlerMethodReturnValueHandler接口的类,这2个属性都在ServletInvocableHandlerMethod实例化的时候被赋值(通过HandlerAdapter的属性进行赋值),HandlerAdapter的相关属性是在HandlerAdapter进行实例化由Spring容量注入。
SpringMVC常见注解
常见的注解中,使用@ResponseBody注解的话最终返回值会被RequestResponseBodyMethodProcessor类处理,该类同时实现了HandlerMethodReturnValueHandler和HandlerMethodArgumentResolver这两个接口,所以它支持的请求类型是Controller方法参数中带有@RequestBody注解,支持的响应类型是Controller方法带有@ResponseBody注解,其他常用的HandlerMethodArgumentResolver实现类如下:
1.RequestParamMethodArgumentResolver
支持带有@RequestParam注解的参数或带有MultipartFile类型的参数
2.RequestParamMapMethodArgumentResolver
支持带有@RequestParam注解的参数 && @RequestParam注解的属性value存在 && 参数类型是实现Map接口的属性
3.PathVariableMethodArgumentResolver
支持带有@PathVariable注解的参数 且如果参数实现了Map接口,@PathVariable注解需带有value属性
4.MatrixVariableMethodArgumentResolver
支持带有@MatrixVariable注解的参数 且如果参数实现了Map接口,@MatrixVariable注解需带有value属性
5.RequestResponseBodyMethodProcessor
方法参数中带有@RequestBody注解
6.ServletRequestMethodArgumentResolver
参数类型是实现或继承或是WebRequest、ServletRequest、MultipartRequest、HttpSession、Principal、Locale、TimeZone、InputStream、Reader、HttpMethod这些类。
7.ServletResponseMethodArgumentResolver
参数类型是实现或继承或是ServletResponse、OutputStream、Writer这些类
8.RedirectAttributesMethodArgumentResolver
参数是实现了RedirectAttributes接口的类
9.HttpEntityMethodProcessor
参数类型是HttpEntity
常用的HandlerMethodReturnValueHandler实现类如下:
1.ModelAndViewMethodReturnValueHandler
返回值类型是ModelAndView或其子类
2.ModelMethodProcessor
返回值类型是Model或其子类
3.ViewMethodReturnValueHandler
返回值类型是View或其子类
4.HttpHeadersReturnValueHandler
返回值类型是HttpHeaders或其子类
5.ModelAttributeMethodProcessor
返回值有@ModelAttribute注解
6.ViewNameMethodReturnValueHandler
返回值是void或String
Controller常用注解
SpringMVC中将一个类添加@Controller以表示该类是一个controller,其他常用的注解如下:
1.@RequestMapping
用来标记请求的路径,它可以标记在类上面,也可以标记在方法上,当方法上和类上都标记了@RequestMapping的时候,那么对应的方法对应的Url就是类上的加方法上的。在RequestMapping中还可以指定一个属性method,其主要对应的值有RequestMethod.GET和RequestMethod.POST,@RequestMapping中还有一个属性params,可以通过该属性指定请求参数中必须包含某一参数,或必须不包含某一参数,或某参数的值必须是什么,以此来缩小指定的映射范围。
2.@PathVariable
可以标记在方法的参数上,利用它标记的参数可以利用请求路径传值,下面是一个具体的例子
|
|
3.@RequestParam
用来给参数传值的,但是它是从头request的参数里面取值,相当于request.getParameter(“参数名”)方法。它的取值规则跟@PathVariable是一样的,当没有指定的时候,默认是从request中取名称跟后面接的变量名同名的参数值,当要明确从request中取一个参数的时候使用@RequestParam(“参数名”)。
4.返回值
- 返回一个ModelAndView,其中Model是一个Map,里面存放的是一对对的键值对,其可以直接在页面上使用,View是一个字符串,表示的是某一个View的名称
- 返回一个字符串,这个时候如果需要给页面传值,可以给方法一个Map参数,该Map就相当于一个Model,往该Model里面存入键值对就可以在页面上进行访问了
- 返回一个Model也就是一个Map,这个时 返回一个Model也就是一个Map,这个时候将解析默认生成的view name
- 任何其他类型的对象。这个时候就会把该方法返回类型对象当做返回Model模型的一个属性返回给视图使用,这个属性名称可以通过在方法上给定@ModelAttribute注解来指定,否则将默认使用该返回类名称作为属性名称。
5.@SessionAttributes
只能声明在类上,而不能声明在方法上,表示模型对象的特定属性具有 Session 范围的作用域
如:@SessionAttributes(types = {User.class,Dept.class},value={“attr1”,“attr2”})