SpringMVC

【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】

10 拦截器

文章目录

  • SpringMVC
  • 10 拦截器
  • 10.3 拦截器参数
  • 10.3.1 前置处理方法
  • 10.3.2 后置处理方法
  • 10.3.3 完成处理方法
  • 10.4 拦截器链配置
  • 10.4.1 配置多个拦截器

10.3 拦截器参数
10.3.1 前置处理方法

原始方法之前运行preHandle

preHandle拦截器多次读取HttpServletRequest 流数据_spring

  • request:请求对象
  • response:响应对象
  • handler:被调用的处理器对象,本质上是一个方法对象,对反射中的Method对象进行了再包装

使用request对象可以获取请求数据中的内容,如获取请求头的Content-Type

//原始方法调用前执行的内容
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String contentType = request.getHeader("Content-Type");
    System.out.println("preHandle..." + contentType);
    return true;
}

preHandle拦截器多次读取HttpServletRequest 流数据_开发语言_02

使用handler参数,可以获取方法的相关信息

//原始方法调用前执行的内容
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String contentType = request.getHeader("Content-Type");
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    String methodName = handlerMethod.getMethod().getName();
    System.out.println("preHandle..." + contentType + "  " + methodName);
    return true;
}

preHandle拦截器多次读取HttpServletRequest 流数据_servlet_03

10.3.2 后置处理方法

原始方法运行后运行,如果原始方法被拦截,则不执行

preHandle拦截器多次读取HttpServletRequest 流数据_spring_04

前三个参数和preHandle的是一致的

modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整

现在都是返回JSON 数据,所以这个参数的使用率不高

10.3.3 完成处理方法

拦截器最后执行的方法,无论原始方法是否执行

preHandle拦截器多次读取HttpServletRequest 流数据_开发语言_05

前三个参数与上面的是一致的。

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

有了全局异常处理器类,所以这个参数的使用率也不高

这三个方法中,最常用的是preHandle,在这个方法中可以通过返回值来决定是否要进行放行,开发者可以把业务逻辑放在该方法中,如果满足业务则返回true放行,不满足则返回false拦截。

10.4 拦截器链配置

目前,在项目中只添加了一个拦截器,如果有多个,该如何配置?配置多个后,执行顺序是什么?

10.4.1 配置多个拦截器

① 步骤1 创建拦截器类

实现接口,并重写接口中的方法

package com.dingjiaxiong.controller.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * ClassName: ProjectInterceptor2
 * date: 2022/9/19 18:14
 *
 * @author DingJiaxiong
 */

@Component
public class ProjectInterceptor2 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle...222");
        return true; //放行
    }

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

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

② 步骤2 配置拦截器类

package com.dingjiaxiong.config;

import com.dingjiaxiong.controller.interceptor.ProjectInterceptor;
import com.dingjiaxiong.controller.interceptor.ProjectInterceptor2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * ClassName: SpringMvcConfig
 * date: 2022/9/19 16:56
 *
 * @author DingJiaxiong
 */

@Configuration
@ComponentScan({"com.dingjiaxiong.controller"})
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {

    @Autowired
    private ProjectInterceptor projectInterceptor;

    @Autowired
    private ProjectInterceptor2 projectInterceptor2;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //配置多拦截器
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");

        registry.addInterceptor(projectInterceptor2).addPathPatterns("/books","/books/*");

    }
}

③ 运行程序,观察顺序

preHandle拦截器多次读取HttpServletRequest 流数据_java_06

可以看到拦截器执行的顺序是和配置顺序有关。【先进后出】

  • 当配置多个拦截器时,形成拦截器链
  • 拦截器链的运行顺序参照拦截器添加顺序为准
  • 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
  • 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作

preHandle拦截器多次读取HttpServletRequest 流数据_拦截器_07

  • preHandle:与配置顺序相同,必定运行
  • postHandle:与配置顺序相反,可能不运行
  • afterCompletion:与配置顺序相反,可能不运行

【以运行结果为准】