SpringMVC 总体流程
整体流程图:www.processon.com/view/link/6…
1.前端控制器DispatcherServlet 作用:接收请求,进行请求分发,处理响应结果
2.处理映射器HandlerMapping 作用:根据请求URL,找到对应Handler
3.处理适配器HandlerAdapter 作用:调用处理器(Handler | Controller)
4.处理器Handler(即Controller,由我们自己开发) 作用:接收用户请求数据,调用业务处理
5.视图解析器ViewResolver 作用:视图解析
6.视图View(由前端人员开发) 作用:将数据展现给用户
MVC三大组件
处理器映射器
HandlerMapping 在 SpringMVC 容器启动时就已经注入到容器中了,哪个 URL 对应的执行链路是什么,适配器是什么,容器启动时就确定了。调用getHandler(HttpServletRequest request)方法会返回处理器的执行链HandlerExecutionChain,该类有两个重要属性:处理器 Object handler和 拦截器数组 HandlerInterceptor[] interceptors
处理器适配器 HandlerAdapter
SpringMVC 使用适配器模式来适配调用 MVC 处理器 Handler。根据 Handler的不同种类采用不同的 Adapter。
| Handler类别 | 对应适配器 | 描述 | 使用 |
|---|---|---|---|
| Controller | SimpleControllerHandlerAdapter | 标准控制器,返回ModelAndView | 实现 Controller 接口 |
| HttpRequestHandler | HttpRequestHandlerAdapter | 业务自行处理请求,不返回ModeAndView | HttpRequestHandler 接口 |
| Servlet | SimpleServletHandlerAdapter | 基于标准的 servlet 处理 | |
| HandlerMethod | RequestMappingHandlerAdapter | 基于@requestMapping等注解对应方法处理 | 注解@Controller 配置控制器 |
视图解析器 ViewResolver
视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给用户。为了实现视图模型和具体实现技术的解耦,SpringMVC 定义了一个高度抽象的 View 接口(视图)。它是无状态的(每一个请求都会创建一个 View),不存在线程安全问题。SpringMVC 中常用的视图类型有:URL 视图、JSON 视图、文档类视图、XML 视图。
ViewResolver 负责将处理结果生成 View 视图,先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。视图解析器的作用是将逻辑视图转为物理视图,所有的视图解析器都必须实现 ViewResolver 接口。
当然,有的场景也不需要视图解析器
- 返回值是 String 类型,直接找到映射对应的 JSP,HTML,FreeMarker 或其他映射。默认请求是转发,也可以通过redirect 前缀指定为重定向
- void(无返回值) ,因为我们在控制器方法的参数中可以直接使用原始 SerlvetAPI 对象 HttpServletRequest 和 HttpServletResponse 对象,所以无论是转发还是重定向都可以轻松实现,而无需使用返回值
- ModeAndView 类型,不需要页面跳转,即基于 ajax 的异步请求,用 json 数据交互时,利用 @RequestBody 和 @ResponseBody 实现数据到 java 对象的绑定
参数获取
拦截器
SpringMVC 中实现拦截器只需要继承HandlerInterceptorAdapter类,它间接的实现了 HandlerInterceptor接口
原理: 拦截器是通过Java反射机制 + JDK动态代理来实现的,因此必须依赖接口(拦截实现接口的类),SpringMVC 会从执行链中拿到拦截器数组后遍历,拿到所有的 HandlerInterceptor,执行对应阶段的方法,成功返回true放行,失败返回false拦截
实现: Spring实现拦截器只需要继承HandlerInterceptorAdapter类,并重写对应的方法
应用场景: 未登录用户拦截、日志审计等
自定义拦截器中三个方法:
- preHandle => applyPreHandle(processedRequest, response) 控制器方法
handle()执行之前 - postHandle => applyPostHandle(processedRequest, response, mv) 在控制器方法
handle()执行之后,结果视图创建生成之前 - afterCompletion 结果视图创建生成之后,展示到浏览器之前。可以利用此方法进行清理操作
Spring整合SpringMVC注意事项
- Bean 被创建两次: Spring 的 IOC 容器不应该扫描 SpringMVC 中的 bean, 对应的 SpringMVC 的 IOC 容器不应该扫描 Spring 中的 bean,可以配置对应容器只扫描自己需要的 bean
- SpringIOC 容器与 SpringMVC 容器为父子关系,MVC 容器中能注入 IOC 容器的对象,反过来却不行 (例如:Controller 可以调 Service 但 Service 层不能注入 Controller)