SpringMVC --- 拦截器

拦截器

在web开发中,拦截器是经常用到的功能。它可以帮我们验证是否登陆、预先设置数据以及统计方法的执行效率等等。

spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor

HandlerInterceptor是SpringMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。

SpringMVC 中的Interceptor拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式,第一种方式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口,或者是这个类继承实现了HandlerInterceptor 接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter ;第二种方式是实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。

1、拦截器类的编写

  1. 第一种方法,实现 HandlerInterceptor 接口,重写其中的方法(注意:是方法重写,因为HandlerInterceptor接口中的所有方法),HandlerInterceptor接口中有三个默认方法(default 修饰)
  2. 第二种方法:继承 HandlerInterceptorAdapter类(已过时,和HandlerInterceptor一样)
  3. 实现Spring的 WebRequestInterceptor 接口,或者是继承实现了WebRequestInterceptor的类。
public interface HandlerInterceptor {

   default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
   		throws Exception {

   	return true;
   }
   
   default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
   		@Nullable ModelAndView modelAndView) throws Exception {
   }

   default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
   		@Nullable Exception ex) throws Exception {
   }

}

2、拦截器的配置

SpringMVC中的拦截器用于拦截控制器方法的执行

SpringMVC中的拦截器需要实现 HandlerInterceptor

SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:

    <!--配置拦截器-->
    <!--所有的请求都会被拦截-->
    <mvc:interceptors>
        <!--第一种方式-->
       <!-- <bean class="com.atguigu.mvc.interceptors.FirstInterceptor"></bean>-->

        <!--第二种方式-->
        <!--<ref bean="firstInterceptor"></ref>-->
        
        <!--第三种方式-->
        <!--该方法能指定拦截规则,指定哪些拦截,哪些不拦截-->
        <!--拦截除主页面的所有请求-->
        <mvc:interceptor>
            <!--ant风格 /** -->
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/"/>
            <ref bean="firstInterceptor"/>
        </mvc:interceptor>
        
    </mvc:interceptors>
    <!-- 
    以上配置方式可以通过ref或bean标签设置拦截器,通过mvc:mapping设置需要拦截的请求,通过mvc:exclude-mapping设置需要排除的		 请求,即不需要拦截的请求
-->

3、拦截器的三个抽象方法

SpringMVC中的拦截器有三个抽象方法:

preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用 控制器方法;返回false表示拦截,即不调用控制器方法;
该方法在进入Handler(Controller)方法执行之前执行此方法
应用场景:如身份认证,身份授权。

postHandle:控制器方法执行之后执行postHandle()
该方法在进入Handler(Controller)方法之后,返回ModelAndView之前执行
应用场景从modelAndView出发,将公用模型数据(如菜单导航)在这里传到视图,也可以在这里统一制定视图

afterComplation:处理完视图和模型数据,渲染视图完毕之后执行afterComplation()
该方法在handler方法执行完之后执行
应用场景:统一日志处理,统一异常处理

4、多个拦截器的执行顺序

a> 若每个拦截器的preHandle()都返回true

此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:

preHandle()会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反序执行

b> 若某个拦截器的preHandle()返回了false

preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false的拦截器之前的拦截器的afterComplation()会执行

源码解读

img01
processDispatchResult 方法
img02
applyPreHandle(processedRequest, response) 方法:正序执行所有的preHandle方法
img03
applyPostHandle(processedRequest, response, mv) 方法,前提是所有 preHandle方法都返回true,才倒序执行所有的postHandle方法,否则一个不执行
img04
triggerAfterCompletion(request, response, null) 方法:是在processDispatchResult 方法调用,是倒序执行 preHandle 返回 false 之前的拦截器(不包括返回 false的拦截器)的 afterCompletion方法
img05

try {
	try {
		//所有 preHandle方法执行
		//如果存在 preHandle 返回 false,则返回false,则执行 return;挑出该层 try-catch
		
		//执行控制器方法
		
		//所有 postHandle方法倒序执行,如果有一个 preHandle 返回 false 则一个都不会执行
	} catch{
	} catch{
	}
	//processDispatchResult 方法执行,渲染视图和倒序执行preHandle返回false之前的 afterCompletion 方法
}catch{
}catch{
}finally{}

在DispatcherServlet 源码中,关于执行控制器方法的源码部分(在源码中1061 行上下,结构是以上述代码块的结构)
当有preHandle() 返回 false 时,里层 进入 if语句 执行 return; 所以 postHandle() 方法一个不会执行,而 afterCompletion() 方法会执行一部分,原因是 执行 afterCompletion() 方法是在 外层的 try - catch 中,而 preHandle() 结束的是里层的 try-catch,afterCompletion() 还是会执行到。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值