栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

拦截器的配置

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

拦截器的配置

文章目录
        • 拦截器简介
        • 实现一个拦截器
        • 拦截器的配置
        • 多个拦截器时的执行顺序

拦截器简介

过滤器可以拦截请求,拦截器也能拦截请求,那过滤器和拦截器有啥区别?看下面这张图就明白了。

拦截器有三个方法,分别是

  1. preHandle,发生在请求被控制器方法处理前。
    perHandle方法的返回值是boolean类型,true或false。
    true,表示放行,即调用控制器方法。
    false,表示拦截,即不调用控制器方法。
  2. postHandle,发生在请求被控制器方法处理后。
  3. afterCompletion,发生在视图渲染后。

为了更好地理解以上三个方法,可以查阅下DispatcherServlet的源码。

实现一个拦截器

现在来实现一个拦截器。
首先,新建一个基本的maven项目,这里不赘述,仅附上部分代码。




    
    Title


测试拦截器





    
    Title


success


package com.example.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TestController {
    @RequestMapping("/testInterceptor")
    public String testInterceptor(){
        return "success";
    }
}

然后,在java目录下新建Package:com.example.mvc.interceptors,在该包下新建类FirstInterceptor,内容如下,

package com.example.mvc.interceptors;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("FirstInterceptor-->preHandle");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("FirstInterceptor-->postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("FirstInterceptor-->afterCompletion");
    }
}

FirstInterceptor实现了接口HandlerInterceptor的perHandle、postHandle和afterCompletion方法。

接着,在配置文件springMVC.xml中配置拦截器,如下所示,


    

最后,启动应用。

IDEA控制器仅打印出:FirstInterceptor–>preHandle。这是因为preHandle的返回值是false,表示拦截,即不调用控制器方法,所以后面的postHandle、afterCompletion也不会对请求进行拦截处理。

不妨让preHandle返回true试试,如下,

IDEA控制台打印出的信息如下:

21:29:47.058 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
21:29:47.138 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/interceptor/", parameters={}
21:29:47.138 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped to ParameterizableViewController [view="index"]
FirstInterceptor-->preHandle
FirstInterceptor-->postHandle
FirstInterceptor-->afterCompletion
21:29:47.141 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
07-Dec-2021 21:29:52.964 信息 [Catalina-utility-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [D:tomcatwebappsmanager]
07-Dec-2021 21:29:53.017 信息 [Catalina-utility-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[D:tomcatwebappsmanager]的部署已在[52]毫秒内完成
21:29:56.724 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/interceptor/testInterceptor", parameters={}
21:29:56.736 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.example.mvc.controller.TestController#testInterceptor()
FirstInterceptor-->preHandle
FirstInterceptor-->postHandle
FirstInterceptor-->afterCompletion
21:29:56.782 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

即,访问根路径/时,IDEA控制台打印了:
FirstInterceptor–>preHandle
FirstInterceptor–>postHandle
FirstInterceptor–>afterCompletion。
访问/testInterceptor时,IDEA控制台也打印了:
FirstInterceptor–>preHandle
FirstInterceptor–>postHandle
FirstInterceptor–>afterCompletion。
也就是说,拦截器FirstInterceptor对所有的浏览器请求都进行了拦截。

拦截器的配置

拦截器的配置方法有三种。

  • 第一种,使用bean。

    

  • 第二种,使用ref。

首先,需要在拦截器的类上添加注解@Component,将该拦截器注册为IoC容器的bean,如下。

package com.example.mvc.interceptors;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("FirstInterceptor-->preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("FirstInterceptor-->postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("FirstInterceptor-->afterCompletion");
    }
}

同时,必须能够扫描到该拦截器,如下。


当然,也可以这样写,


最后,使用ref配置拦截器。


    

  • 第三种,使用interceptor。
    第一种、第二种方法,会对浏览器的所有请求进行拦截,不能指定拦截规则。
    使用interceptor时,可以设置拦截规则,指定拦截哪些请求路径,不拦截哪些请求路径。
    
        
            
            
            
        
    

,mapping表示要拦截,/**代表所有的请求路径,故拦截所有的请求路径。
,exclude-mapping,表示不要拦截,即不拦截根路径。

重启应用,IDEA控制台打印出如下信息:

21:50:23.901 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
21:50:23.978 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/interceptor/", parameters={}
21:50:23.978 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped to ParameterizableViewController [view="index"]
21:50:23.983 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
07-Dec-2021 21:50:29.323 信息 [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [D:tomcatwebappsmanager]
07-Dec-2021 21:50:29.378 信息 [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[D:tomcatwebappsmanager]的部署已在[54]毫秒内完成
21:50:33.199 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/interceptor/testInterceptor", parameters={}
21:50:33.211 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.example.mvc.controller.TestController#testInterceptor()
FirstInterceptor-->preHandle
FirstInterceptor-->postHandle
FirstInterceptor-->afterCompletion
21:50:33.254 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

访问根路径时,没有打印出信息。
访问/testInterceptor时,打印出如下信息:
FirstInterceptor–>preHandle
FirstInterceptor–>postHandle
FirstInterceptor–>afterCompletion。

多个拦截器时的执行顺序

先说结论:多个拦截器时,它们的执行顺序与SpringMVC配置文件中配置的顺序有关。

  • 情景1:所有的拦截器的preHandle都返回true
    preHandle按照配置的顺序正序执行;
    postHandle、afterCompletion按照配置的顺序反序执行。

看个例子。

package com.example.mvc.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("FirstInterceptor-->preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("FirstInterceptor-->postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("FirstInterceptor-->afterCompletion");
    }
}
package com.example.mvc.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SecondInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("SecondInterceptor-->preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("SecondInterceptor-->postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("SecondInterceptor-->afterCompletion");
    }
}

拦截器FirstInterceptor、拦截器SecondInterceptor的preHandle都返回true。


    
    

SpringMVC配置文件,配置拦截器的顺序为:FirstInterceptor->SecondInterceptor,即FirstInterceptor在先,SecondInterceptor在后。

启动应用,IDEA控制台打印出如下信息:

20:45:18.657 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
20:45:18.754 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/interceptor/", parameters={}
20:45:18.754 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped to ParameterizableViewController [view="index"]
FirstInterceptor-->preHandle
SecondInterceptor-->preHandle
SecondInterceptor-->postHandle
FirstInterceptor-->postHandle
SecondInterceptor-->afterCompletion
FirstInterceptor-->afterCompletion
  • 情景2:某个拦截器的preHandle返回false,假定为拦截器A
    拦截器A、A前面的拦截器的preHandle按照配置的顺序正序执行。
    所有拦截器的postHandle都不会执行。
    A前面的拦截器的afterCompletion按照配置的顺序反序执行。

看个例子。

package com.example.mvc.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("FirstInterceptor-->preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("FirstInterceptor-->postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("FirstInterceptor-->afterCompletion");
    }
}
package com.example.mvc.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SecondInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("SecondInterceptor-->preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("SecondInterceptor-->postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("SecondInterceptor-->afterCompletion");
    }
}
package com.example.mvc.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ThirdInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("ThirdInterceptor-->preHandle");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("ThirdInterceptor-->postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("ThirdInterceptor-->afterCompletion");
    }
}

拦截器FirstInterceptor、拦截器SecondInterceptor的preHandle都返回true,拦截器ThirdInterceptor的preHandle返回false。


    
    
    

SpringMVC配置文件中,配置的拦截器的先后顺序为:FirstInterceptor->SecondInterceptor->ThirdInterceptor。

启动应用,IDEA控制器打印出如下信息:

20:44:11.885 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
20:44:11.982 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/interceptor/", parameters={}
20:44:11.982 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped to ParameterizableViewController [view="index"]
FirstInterceptor-->preHandle
SecondInterceptor-->preHandle
ThirdInterceptor-->preHandle
SecondInterceptor-->afterCompletion
FirstInterceptor-->afterCompletion

多拦截器时执行顺序为什么结论如上?其实查阅下DispatcherServlet源码就明白了,不妨调试下。

视频1是针对情景1的调试。

视频1

视频2是针对情景2的调试。

视频2

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/642888.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号