SpringMVC完整执行流程
-
用户发送请求至前端控制器DispatcherServlet。
-
DispatcherServlet收到请求调用HandlerMapping处理器映射器。
-
处理器映射器找到具体的处理器(可以根据xml配置、注解等方式查找),生成HandlerExecutionChain(包含Handler及Handler拦截器)返回给DispatcherServlet。
-
DispatcherServlet调用HandlerAdapter处理器适配器。
-
HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
-
Controller执行完成返回ModelAndView。
-
HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
-
DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
-
ViewReslover解析后返回具体View。
-
DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
-
DispatcherServlet响应用户。
以上步骤中,DispatchServlet、HandlerMapping、HandlerAdapter和ViewResolver等对象协同工作,共同完成了SpringMVC请求–>响应的整个工作流程。但是这些对象和流程对于开发者来说都是不可见的,开发者并不需要关系这些对象时如何工作的,只需要在Handler(也就是Controller)中完成对请求的业务处理。
Spring-MVC组件解析
前端控制器:DispatcherServlet
- 用户请求到达DispatcherServlet,将由其进行分发,只分发不处理,它负责统一调度各个组件之间的调用,是整个请求响应的控制中心。DispatcherServlet降低了各个组件之间的耦合度
处理器映射器:HandlerMapping
-
HandlerMapping负责生成Handler。
-
DispatcherServlet解析请求的URL得到URI(请求资源标识符),然后根据URI调用处理器映射器(HandlerMapping)获得具体的Handler,以执行链(HandlerExecutionChain)的形式,将处理器对象(Handler)和处理器拦截器(HandlerInterceptor)返回给DispatcherServlet。
-
SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
处理器适配器:HandlerAdapter
-
DispatcherServlet根据获取的Handler,选择一个合适的HandlerAdapter。
-
HandlerAdapter是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
处理器:Handler
-
Handler就是要编写的具体业务控制器Controller。
-
提取Request中的模型数据,填充Handler入参,开始执行Handler;在填充Handler入参的过程中,根据配置Spring将做一些额外的工作:
- HttpMessageConveter:将请求消息(如Json、XML等数据)转换成一个对象,将对象转换为指定的响应消息;
- 数据转换:将请求消息进行数据转换。例如:String转换成Integer、Double等;
- 数据格式化:对请求消息进行数据格式化。例如:将字符串转换成格式化数字或格式化日期等;
- 数据验证:验证数据的有效性(长度、格式等),验证结果存储到BingdingResult或Error中;
视图解析器:ViewResolver
-
ViewResolver 负责将处理结果生成 View 视图。
-
Handler执行完成后,HandlerAdaptor向DispatcherServlet返回一个ModelAndView对象,其中view是视图名称,并不是真正的视图对象;根据ModelAndView选择一个合适的ViewResolver对象,ViewResolver对象把DispatcherServlet提供的ModelAndView解析成视图View对象(JSP)。
视图:View
-
最常见的视图View是Jsp
-
DispatcherServlet对视图View进行渲染(将模型数据填充到视图中),响应给用户。
-
SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jsp、jstlView、freemarkerView、pdfView等。
Spring-MVC注解
@RequestMapping
作用:用于建立请求 URL 和处理请求方法之间的对应关系
书写位置:
类上,请求URL 的第一级访问目录。此处不写的话,就相当于应用的根目录
方法上,请求 URL 的第二级访问目录,与类上的使用@ReqquestMapping标注的一级目录一起组成访问虚拟路径
属性:
value:用于指定请求的URL。它和path属性的作用是一样的
method:用于指定请求的方式,值为枚举类型
params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的key和value必须和配置的一模一样
例如:
params = {"accountName"},表示请求参数必须有accountName
params = {"moeny!100"},表示请求参数中money不能是100
@PostMapping
相当于@RequestMapping(method={RequestMethod.POST})
@GetMapping
相当于@RequestMapping(method={RequestMethod.GET})
@params 限定请求参数
// 有时候要求请求必须携带某个参数,比方说token,可以使用下属写法:
@RequestMapping(value = "test2_4",params = "token"){
//拿到token进行处理
}
// 这个时候如果请求参数里面没有token,请求将不会成功
@RequestHeader 限制请求头
做接口开发时,因为移动端可能是IOS,也有可能是Android,需要对不同设备做不同处理,
这个时候可以添加一个device_type(名字任意,见名知意即可)的请求头,写法如下:
public String test2_5(@RequestHeader String device_type,){
//获取设备类型进行判断处理
}
而且随着版本的更新,高版本可能会支持一些新特性,但是低版本支持不了,
这个时候也可以通过添加请求头的方式处理,写法如下:
//对于软件版本的请求头,老版本的app可能不支持,只需要在@RequestHeader内添加required = false即可,默认值为true。
public String test2_5(@RequestHeader String device_type,
@RequestHeader(required = false) String app_version){
//获取设备类型、软件版本进行判断处理
}
代码演示
<!-- 组件扫描。 -->
<context:component-scan base-package=“com.itheima.controller"/>
@Controller
@RequestMapping("/user")
public class QuickController {
//value的值用于表示访问地址值
//method的值用于限定请求的方式,常用的是get和post,分别用RequestMethod.GET和RequestMethod.post表示
//params可以对传递参数进行限制,params={"username"}用于要去请求参数必须含有username
@RequestMapping(value="/quick",method= RequestMethod.GET,params={"username"})
public String quickMethod(){
System.out.println("quickMethod running.....");
return "/success.jsp";
}
}
SpringMVC的XML配置解析
视图解析的请求转发和重定向
直接在Controller类中的方法中返回一个字符串,SpringMVC会帮助我们找到对应的视图资源,默认使用请求转发方式。
return "/index.jsp";
//上述代码相当于 return "forward:/index.jsp";
可以在字符串前添加redirect改为请求重定向。
return "redirect:/index.jsp";
内置资源视图解析器的前缀和后缀
可以在SpringMVC的配置文件中通过配置优化Controller返回的视图(视图名)
<bean class="org.srpingframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
上述配置其实就是配置了一个Bean,用配置的方式修改了这个Bean里面的两个属性值。
这样配置之后,Controller内方法最终返回的视图名称就是
//前缀prefix值+方法返回值+后缀suffix值 即:/pages/index.jsp
return "index";
重定向和内置资源视图解析器配合使用
如果想要同时使用重定向和内置资源视图解析器的前后缀,不能直接写成:
//SpringMVC没有这么智能,可以帮你截串之后再拼接成redirect:/pages/index.jsp
return "redirect:index";
如果想要让redirect生效,只能手动把路径写全,如下:
//手动添加了redirect或者forward后,内置资源视图解析器内置资源视图解析器不会再帮你补全路径,需要手动写全
return "redirect:/pages/index.jsp";
SpringMVC有默认组件配置,默认组件都是DispatcherServlet.properties配置文件中配置的,该配置文件地址org/springframework/web/servlet/DispatcherServlet.properties,该文件中配置了默认的视图解析器,如下:
org.springframework.web.servlet.ViewResolver =
org.springframework.web.servlet.view.InternalResourceViewResolver
翻看该解析器源码,可以看到该解析器的默认设置,如下:
REDIRECT_URL_PREFIX = "redirect:" --重定向前缀
FORWARD_URL_PREFIX = "forward:" --转发前缀(默认值)
prefix = ""; --视图名称前缀
suffix = ""; --视图名称后缀