【SpringMVC】:拦截器

1、什么是拦截器

Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于对处理器进行预处理和后处理,同时也提供了一种可以提取处理器中可重用部分的方式。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

在一个项目中可以设置多个拦截器,这些拦截器按一定的顺序联结成一条链,这条链称为拦截器链(Interceptor Chain)。 在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用,拦截器也是AOP思想的具体实现。

2、过滤器和拦截器的区别

过滤器是 servlet 规范中的一部分,任何 Java Web 工程都可以使用,就算在SpringMVC中也可以使用不受限制。在 web.xml 中使用 url-pattern 配置了拦截地址之后,会对所有的访问所有改地址的资源进行拦截。

拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。并且拦截器只会拦截访问的控制器方法,不会拦截其他资源,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。

3、拦截器的实现方法

3.1、使用 HandlerInterceptor 接口实现

HandlerInterceptor 接口三个抽象方法,分别为preHandle()postHandle()afterCompletion(),其作用分别是:

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handle)方法:该方法在控制器(目标)的方法成功执行完成之前被执行

    该方法的返回值是布尔(Boolean)类型的,当它返回为false时,表示请求结束,后续的Interceptor和控制器(Controller)都不会再执行;当返回值为true时,就会继续调用下一个Interceptor的preHandle方法,如果已经是最后一个Interceptor的时候,就会是调用当前请求的控制器中的方法。

    Spring MVC 中的Interceptor是链式调用的,所以每个Interceptor的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor中的preHandle方法,在执行完所有InterceptorpreHandle方法之后才能执行控制器方法

  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法:该方法在控制器(目标)的方法成功执行完成之后,在DispatcherServlet进行视图返回渲染之前被执行

    先声明的 InterceptorpostHandle方法反而会后执行,在执行完所有InterceptorpreHandle方法之后才能执行之后的拦截器方法

  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)方法:在整个请求结束之后被执行,也就是在DispatcherServlet渲染了对应的视图之后执行

    需要当前对应的InterceptorpreHandle方法的返回值为true时才会执行,这个方法的主要作用是用于进行资源清理的工作。

我们可以通过复写这三个抽象方法来对用户的请求进行拦截处理的。在 SpringMVC 还提供了 HandlerInterceptor 接口的扩展类:

  1. AsyncHandlerInterceptor接口:继承HandlerInterceptor接口的同时,又声明了一个新的方法afterConcurrentHandlingStarted();
  2. HandlerInterceptorAdapter抽象类: 继承AsyncHandlerInterceptor接口的同时,又复写了preHandle方法。

当然在实际开发中,拦截器一般是通过实现 HandlerInterceptor 接口或者继承 HandlerInterceptorAdapter抽象类实现的。下面,我们就详细介绍这三个抽象方法:

那么我们定义两个拦截器模拟拦截器链:

//Demo1Interceptor第一个拦截器:
public class Demo1Interceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("这是第一个拦截器的 preHandle 方法");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("这是第一个拦截器的 postHandle 方法");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("这是第一个拦截器的 afterCompletion 方法");
    }
}
//Demo1Interceptor第二个拦截器:
public class Demo2Interceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("这是第二个拦截器的 preHandle 方法");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("这是第二个拦截器的 postHandle 方法");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("这是第二个拦截器的 afterCompletion 方法");
    }
}

3.2、使用 WebRequestInterceptor 接口实现

WebRequestInterceptor 接口中也定义了 3 个方法,同 HandlerInterceptor接口完全相同,我们也是通过复写这 3 个方法来对用户的请求进行拦截处理的。唯一不同的是传递参数不同,这 3 个方法都传递了同一个参数WebRequest,这个WebRequest是 Spring 中定义的一个接口,它里面的方法定义跟HttpServletRequest类似,在WebRequestInterceptor接口中对 WebRequest 进行的所有操作都将同步到HttpServletRequest中,然后在当前请求中依次传递。

  • preHandle(WebRequest request)方法:这个方法跟HandlerInterceptor接口中的preHandle相同,主要区别在于该方法的返回值是void类型。
  • postHandle(WebRequest request, ModelMap model)方法:该方法在请求处理之后,也就是在控制器中的方法调用之后被调用,但是会在视图返回被渲染之前被调用,所以可以在这个方法里面通过改变数据模型 ModelMap来改变数据的展示。
  • afterCompletion(WebRequest request, Exception ex)方法:Exception参数表示的是当前请求的异常对象,如果在控制器中抛出的异常已经被 Spring 的异常处理器给处理了的话,那么这个异常对象就是是null。
public class Demo3Interceptor implements WebRequestInterceptor {

    @Override
    public void preHandle(WebRequest request) throws Exception {
        System.out.println("这是WebRequestInterceptor 拦截器的 preHandle方法");
    }

    @Override
    public void postHandle(WebRequest request, ModelMap model) throws Exception {
        System.out.println("这是WebRequestInterceptor 拦截器的 postHandle方法");
    }

    @Override
    public void afterCompletion(WebRequest request, Exception ex) throws Exception {
        System.out.println("这是WebRequestInterceptor 拦截器的 afterCompletion 方法");
    }
}

4、配置拦截器

在定义玩拦截器之后,我们需要对拦截器进行配置,告诉 SpringMVC 我们有哪些拦截器,且这些拦截器拦截的路径。

在 Spring 的XML 配置文件中,我们可以通过mvc:interceptors标签声明一系列的拦截器,多个拦截器就构成了一个拦截器链,或者称之为拦截器栈。这些拦截器的执行顺序是按声明的先后顺序执行的,即:先声明的拦截器先执行,后声明的拦截器后执行。mvc:interceptors标签下声明interceptor标签主要有两种方式:

  1. 直接定义一个Interceptor实现类的bean对象,使用这种方式声明的Interceptor拦截器将会对所有的请求进行拦截;
  2. 使用mvc:interceptor标签进行声明,使用这种方式进行声明的Interceptor可以通过mvc:mapping子标签来定义需要进行拦截的请求路径,还可以通过mvc:exclude-mapping子标签来定义需要直接放行的请求路径。
<mvc:interceptors>
    <!-- 使用 bean 定义一个 Interceptor,直接定义在 mvc:interceptors 下面的 Interceptor 将拦截所有的请求 -->
    <bean class="Interc.Demo1Interceptor"/>
    <!-- 定义在 mvc:interceptor 下面的 Interceptor,表示对特定的请求进行拦截 -->
    <mvc:interceptor>
         <mvc:mapping path="/**"/>
         <mvc:exclude-mapping path="/user/"/>
         <bean class="Interc.Demo2Interceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
         <mvc:mapping path="/**"/>
         <bean class="Interc.Demo3Interceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

执行效果图:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值