Springboot——拦截器
作者:mmseoamin日期:2024-01-21

目录

一、拦截器概念

二、拦截器的使用

 2.1  拦截器的创建(preHandle实用性最强)

 2.2 将拦截器添加到容器当中

三、拦截器参数

3.1 获取请求头 request.getHeader

3.2 Object handler 是什么参数

         3.3 ModelAndView modelAndView

3.4 Exception ex

3.5 HttpServletRequest request

3.6 HttpServletResponse response

四、多拦截器执行顺序


一、拦截器概念

  拦截器(Interceptor):是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行(类似有保安拦截检查,正常才通过)

  作用:

  • 在指定的方法调用前后执行预先设定的代码(比如权限的校验就是在访问controller之前校验)
  • 阻止原始方法的执行(把原始的方法终止掉)

    Springboot——拦截器,第1张

    Springboot——拦截器,第2张

     Springboot——拦截器,第3张

    拦截器与过滤器的区别

    •  归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
    •  拦截器内容不同:Filter对所有访问进行增强(在Tomcat服务器进行配置),Interceptor仅针对SpringMVC的访问进行增强

      二、拦截器的使用

       2.1  拦截器的创建(preHandle实用性最强)

      /**
       * 登录检查
       * 1.配置到拦截器要拦截哪些请求
       * 2.把这些配置放在容器中
       *
       * 实现HandlerInterceptor接口
       */
      public class LoginInterceptor implements HandlerInterceptor {
          /**
           * 目标方法执行之前
           * 登录检查写在这里,如果没有登录,就不执行目标方法
           * @param request
           * @param response
           * @param handler
           * @return
           * @throws Exception
           */
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      //      获取进过拦截器的路径
              String requestURI = request.getRequestURI();
              //      登录检查逻辑
              HttpSession session = request.getSession();
              Object loginUser = session.getAttribute("loginUser");
              if(loginUser !=null){
      //          放行
                  return true;
              }
      //      拦截   就是未登录,自动跳转到登录页面,然后写拦截住的逻辑
              return false;
          }
          /**
           * 目标方法执行完成以后
           * @param request
           * @param response
           * @param handler
           * @param modelAndView
           * @throws Exception
           */
          @Override
          public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
              HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
          }
          /**
           * 页面渲染以后
           * @param request
           * @param response
           * @param handler
           * @param ex
           * @throws Exception
           */
          @Override
          public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
              HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
          }
      }
      

       2.2 将拦截器添加到容器当中

      @Configuration
      //定制SpringMVC的一些功能都使用WebMvcConfigurer
      public class AdminWebConfig implements WebMvcConfigurer {
          /**
           * 配置拦截器
           * @param registry 相当于拦截器的注册中心
           */
          @Override
          public void addInterceptors(InterceptorRegistry registry) {
      //       下面这句代码相当于添加一个拦截器   添加的拦截器就是我们刚刚创建的
               registry.addInterceptor(new LoginInterceptor())
      //       addPathPatterns()配置我们要拦截哪些路径 addPathPatterns("/**")表示拦截所有请求,包括我们的静态资源
                       .addPathPatterns()
      //       excludePathPatterns()表示我们要放行哪些(表示不用经过拦截器)
      //       excludePathPatterns("/","/login")表示放行“/”与“/login”请求
      //       如果有静态资源的时候可以在这个地方放行
                       .excludePathPatterns("/","/login");
          }
      }
      

      三、拦截器参数

      3.1 获取请求头 request.getHeader

          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              String contenType = request.getHeader("Content-Type");
              System.out.println("preHandle..."+contenType);
      //      放行
              return true;
          }
      

      Springboot——拦截器,第4张

       Springboot——拦截器,第5张

      3.2 Object handler 是什么参数

          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              String contenType = request.getHeader("Content-Type");
              System.out.println(handler);
              System.out.println("preHandle..."+contenType);
      //      放行
              return true;
          }
      

      使用PostMan发送请求后,控制台出现下面这个样子

      class org.springframework.web.method.HandlerMethod

      Springboot——拦截器,第6张

      这个参数有什么用?

         被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装

          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              String contenType = request.getHeader("Content-Type");
      //        System.out.println(handler);
              HandlerMethod hm = (HandlerMethod)handler;
      //        通过hm.getMethod()就可以拿到原始执行的对象,拿到这个对象就可以进行反射
               hm.getMethod();
              System.out.println("preHandle..."+contenType);
      //      放行
              return true;
          }

      Springboot——拦截器,第7张

      3.3 ModelAndView modelAndView

      封装了SpringMVC进行页面跳转的相关数据,但是我们现在都是反JSON,一般不会这么搞了

      3.4 Exception ex

      通过这个ex可以拿到原始的程序执行过程中出现的异常的

      假设controller层抛了异常,在这里是可以拿到异常对象的,但是我们有异常处理机制,所以这里就没有那么大的需求了

      如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理

      3.5 HttpServletRequest request

         request:请求对象

      3.6 HttpServletResponse response

        response:响应对象

      四、多拦截器执行顺序

       当配置多个拦截器时,形成拦截器链

       下图是第二个拦截器

      Springboot——拦截器,第8张

      @Configuration
      //定制SpringMVC的一些功能都使用WebMvcConfigurer
      public class AdminWebConfig implements WebMvcConfigurer {
          /**
           * 配置拦截器
           * @param registry 相当于拦截器的注册中心
           */
          @Override
          public void addInterceptors(InterceptorRegistry registry) {
      //       下面这句代码相当于添加一个拦截器   添加的拦截器就是我们刚刚创建的
               registry.addInterceptor(new LoginInterceptor())
      //       addPathPatterns()配置我们要拦截哪些路径 addPathPatterns("/**")表示拦截所有请求,包括我们的静态资源
                       .addPathPatterns()
      //       excludePathPatterns()表示我们要放行哪些(表示不用经过拦截器)
      //       excludePathPatterns("/","/login")表示放行“/”与“/login”请求
      //       如果有静态资源的时候可以在这个地方放行
                       .excludePathPatterns("/","/login");
      //       第二个拦截器
              registry.addInterceptor(new LoginInterceptor2()).addPathPatterns("/books");
          }
      }
      

      那当我们配置了两个拦截器以后,会有一个执行顺序

      拦截器链的运行顺序参照拦截器添加顺序为准,下面就是三个拦截器时的执行顺序

      Springboot——拦截器,第9张

       Springboot——拦截器,第10张