Java框架之SpringMVC 05-拦截器-异常映射-Spring工作流程
SpringMVC
拦截器
Spring MVC也可以使用拦截器对请求进行拦截处理,可以自定义拦截器来实现特定的功能,自定义的拦截器可以实现HandlerInterceptor接口中的三个方法,也可以继承HandlerInterceptorAdapter 适配器类按照需要那个方法,就实现哪个方法
过滤器与拦截器区别
过滤器:过滤器在Servlet之前操作
拦截器:拦截器在Servlet之后,请求处理器(Controller)之前操作。
拦截器三个方法
① preHandle():这个方法在(Controller)处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。如果该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回 true;如果不需要再调用其他的组件去处理请求,则返回false。(如果返回false则后续操作都不再执行,类似于过滤器的 doFilter 所以正常情况下不要返回 false)
② postHandle():这个方法在(Controller)处理器处理完请求后,但是 DispatcherServlet 向客户端返回响应前(在视图渲染之前)被调用,在该方法中对用户请求request进行处理。
③ afterCompletion():这个方法在 DispatcherServlet 完全处理完请求后(转发|重定向 之后)被调用,可以在该方法中进行一些资源清理关闭的操作。
配置拦截器
<mvc:interceptors>
<!-- 为所有请求设置拦截器 也可用 ref 引用已经装配好的拦截器-->
<bean id="firstHandlerInterceptor" class="main.controller.FirstHandlerInterceptor"></bean>
<mvc:interceptor>
<!-- 表示指定拦截器只拦截/test/下的所有请求-->
<mvc:mapping path="/test/**/"/>
<!-- 表示访问/test/test.do的请求不会触发拦截器-->
<mvc:exclude-mapping path="/test/test.do"/>
<!-- 为指定的请求设置拦截器 也可用 ref 引用已经装配好的拦截器-->
<bean id="testInterceptor" class="main.controller.TestInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
程序执行顺序
1. preHandle():执行请求处理器的请求(Controller)方法之前执行。
2. 执行请求处理器的请求(Controller)方法
3. postHandle():执行请求处理器的请求(Controller)方法之后,在视图渲染之前。
4. 视图渲染
5. afterCompletion():视图渲染(转发|重定向)之后执行。
多个拦截器的执行流程
当存在多个拦截器时的执行顺序,由配置的先后顺序决定。(preHandle() 先配置,先执行)
preHandle():与拦截器配置的先后顺序一致。
postHandle():与拦截器配置的先后顺序相反。底层倒序循环调用的
afterCompletion():与拦截器配置的先后顺序相反。
preHandle()返回值为false时的工作原理
第一个拦截器的preHandle()的返回值为false:
只执行第一个拦截器的prehandle()方法,执行完,return;(后续的方法都不执行)
不是第一个拦截器的preHandle()的返回值为false:
当前拦截器之前的拦截器的afterCompletion()都会被执行。
当两个拦截器的 preHandle() 方法都返回 true 时,按照虚线路执行
当第二个拦截器 preHandle() 方法返回 false 时按照实现路线执行
异常处理
在SpringMVC中,无论请求控制器中是否存在异常,都会返回ModelAndView对象
Spring MVC 通过 HandlerExceptionResolver 处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常
DispatcherServlet 默认装配的 HandlerExceptionResolver 有 DefaultHandlerExceptionResolver 解析器会自动将标准的Spring MVC异常解析为HTTP错误状态码
使用 <mvc:annotation-driven/> 配置会装配Spring3.0后新增的异常解析器,实现更精细化处理。如果希望对所有异常进行统一处理或指定某一异常跳转页面,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为视图名,可实现跳转到指定页面,并报告异常.
配置异常解析器
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 为所有异常定义默认的处理页面,exceptionMappings未定义的,
value表示跳转页面,至于文件路径和后缀已经在 viewResolver 中指定-->
<property name="defaultErrorView" value="error"></property>
<!-- 定义异常处理页面用来获取异常信息的变量名,被存放到 request 域中-->
<property name="exceptionAttribute" value="exception"></property>
<!-- 需要特殊处理的异常,全类名作为key,异常页文件名作为值,可将不同的异常映射到不同的页面上-->
<property name="exceptionMappings">
<props>
<prop key="java.lang.NullPointerException">nullPointer</prop>
</props>
</property>
</bean>
<mvc:annotation-driven/>
是spring MVC为@Controllers分发请求所必须的,即启用注解驱动,解决了@Controller注解使用的前提配置。
同时它还提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB,读写JSON的支持(Jackson)。
它会自动为我们注册了很多的Bean,最重要的就是RequestMappingHandlerMapping和RequestMappingHandlerAdapter。
第一个是HandlerMapping的实现类,它会处理@RequestMapping 注解,并将其注册到请求映射表中。
第二个是HandlerAdapter的实现类,它是处理请求的适配器,说白了,就是确定调用哪个类的哪个方法,并且构造方法参数,返回值。
简单的说,用什么注解,就需要声明对应的BeanPostProcessor。而Spring为我们提供了一种极为方便注册这些BeanPostProcessor的方式,即使用各种标签来隐式地向 Spring 容器注册
Spring工作流程
相关类
HandlerMapping(请求处理器的映射对象):定义了一个所有请求和请求处理器对象之间的映射关系对象
HandlerExecutionChain(请求处理器执行链对象):定义了 当前请求处理器对象,和所有拦截器对象。
HandlerAdapter(请求处理器的适配器对象):调用当前请求处理器的请求方法。
执行流程对应下图理解
1)用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获
2)DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI):判断请求URI对应的映射
① 不存在:
再判断是否配置了 mvc:default-servlet-handler:
如果没配置,则控制台报映射查找不到,客户端展示404错误
如果有配置,则执行目标资源(一般为静态资源,如:JS,CSS,HTML)
② 存在:
执行下面流程
3)根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
4)DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。
5)如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法【正向】
6)提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
① HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
② 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
③ 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
④ 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
7)Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
8)此时将开始执行拦截器的postHandle(...)方法【逆向】
9)根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet,根据Model和View,来渲染视图
10)在返回给客户端时需要执行拦截器的AfterCompletion方法【逆向】
11)将渲染结果返回给客户端
Spring与SpringMVC
spring容器与springMVC容器对象的关系
springMVC容器对象,默认交个DispatcherServlet管理
spring容器对象,需要我们管理(交给Listener管理)
spring容器对象描述
Root WebApplicationContext: root of context hierarchy
springMVC容器对象描述
WebApplicationContext for namespace 'springDispatcherServlet-servlet':root of context hierarchy
spring容器对象是父,springMVC容器对象是子。子类可以直接调用父类方法。
SpringMVC 的 IOC 容器中的 bean 可以引用 Spring IOC 容器中的 bean.反之则不行.
在web应用下,获取spring容器对象方式
ServletContext servletContext = httpSession.getServletContext();
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
在web应用下,获取springMVC容器对象可直接通过装配属性的方式获取
@Autowired
private XmlWebApplicationContext context;
若 Spring 的 IOC 容器和 SpringMVC 的 IOC 容器扫描组件的包有重合的部分, 就会导致有的 bean 会被创建 2 次,可通过一个包含一个排除的方式解决
Java框架之SpringMVC 05-拦截器-异常映射-Spring工作流程的更多相关文章
- java框架之Struts2(4)-拦截器&标签库
拦截器 概述 Interceptor (拦截器):起到拦截客户端对 Action 请求的作用. Filter:过滤器,过滤客户端向服务器发送的请求. Interceptor:拦截器,拦截的是客户端对 ...
- java框架篇---struts实现拦截器
Struts2的拦截器和Servlet过滤器类似.在执行Action的execute方法之前,Struts2会首先执行在struts.xml中引用的拦截器,在执行完所有引用的拦截器的intercept ...
- springmvc中拦截器与springmvc全局异常处理器的问题
最近在做一个练手的小项目, 系统架构中用了springmvc的全局异常处理器, 做了系统的统一异常处理. 后来加入了springmvc的拦截器, 为了一些需求, 在拦截器中的 preHandle 方法 ...
- SpringMVC经典系列-14自己定义SpringMVC的拦截器---【LinusZhu】
注意:此文章是个人原创.希望有转载须要的朋友们标明文章出处.假设各位朋友们认为写的还好,就给个赞哈.你的鼓舞是我创作的最大动力,LinusZhu在此表示十分感谢,当然文章中如有纰漏,请联系linusz ...
- SpringMVC:拦截器
SpringMVC:拦截器 概述 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理.开发者可以自己定义一些拦截器来实现特定的功能. 过 ...
- springmvc的拦截器
什么是拦截器 java里的拦截器是动态拦截action调用的对象.它提供了一种机制可以使 ...
- Java虚拟机JVM学习05 类加载器的父委托机制
Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...
- SpringMVC利用拦截器防止SQL注入
引言 随着互联网的发展,人们在享受互联网带来的便捷的服务的时候,也面临着个人的隐私泄漏的问题.小到一个拥有用户系统的小型论坛,大到各个大型的银行机构,互联网安全问题都显得格外重要.而这些网站的背后,则 ...
- SpringMVC——实现拦截器
1. SpringMVC拦截器的概念与Struts2相同 2. 实现拦截器 (1) 项目结构 (2) 实现HandlerInterceptor接口 package com.zhengbin.contr ...
随机推荐
- 【codeforces 749B】Parallelogram is Back
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- JavaScript 判断对象中是否有某属性的常用方法
一.点(.)或方框号([ ]) var obj = { test: '123' } obj.test obj['test'] 二.in 运算符 var obj = { test: '123' } te ...
- PowerShell 通过 WMI 获取系统服务
本文告诉大家如何通过 WMI 获取系统服务 通过 Win32_Service 可以获取系统启动的服务 Get-WmiObject Win32_Service | Format-List Caption ...
- 运用NodeJs环境并依赖第三方库,框架等实现网站前后端分离报错问题及处理方法
运用NodeJs环境并依赖第三方库,框架等实现网站前后端分离报错问题及处理方法 问题一: SyntaxError: missing ) after argument list in .....\vie ...
- Checkpoint R77.30 web ui登录配置
R77.30默认只能使用微软内核的浏览器进行web ui的登陆,在专家模式下修改后chrome和firefox正常登录,步骤如下: [Expert@BJ-ZHX-FW:0]# cp /web/htdo ...
- JavaScript模块化演变 CommonJs,AMD, CMD, UMD(一)
原文链接:https://www.jianshu.com/p/33d53cce8237 原文系列2链接:https://www.jianshu.com/p/ad427d8879cb 前端完全手册: h ...
- 17.python文件处理
原文:https://www.cnblogs.com/linhaifeng/articles/5984922.html 文件处理流程: 1. 打开文件,得到文件句柄并赋值给一个变量2. 通过句柄对文件 ...
- Python之time模块和datatime模块
import time time.sleep(5) #休眠 time.time() #返回系统时间戳 utc时间秒数 time.ctime() #返回字符串时间格式,也可以传入参数转换为字符串时间ti ...
- 基于DDD的微服务设计和开发实战
你是否还在为微服务应该拆多小而争论不休?到底如何才能设计出收放自如的微服务?怎样才能保证业务领域模型与代码模型的一致性?或许本文能帮你找到答案. 本文是基于 DDD 的微服务设计和开发实战篇,通过借鉴 ...
- 斜率优化入门题题单$QwQ$
其实就是这一篇的那个例题帕的大部分题目的题解就写这儿辣,,, 因为都是些基础题不想专门给写题解,,,但是又掌握得差不得不写,,, 麻油办法就写一块儿好辣$QwQ$ 当然辣比较难的我就没放进来辣$QwQ ...