Web开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Spring提供的HandlerInterceptor(拦截器)。HandlerInterceptor 的功能跟过滤器类似,但是提供更精细的的控制能力:在request被响应之前、request被响应之后、视图渲染之前以及request全部结束之后。我们不能通过拦截器修改request内容,但是可以通过抛出异常(或者返回false)来暂停request的执行。
Spring Boot为什么提供了基础类WebMvcConfigurerAdapter ,我们只需要重写 addInterceptors方法添加注册拦截器。添加拦截器分为三个步骤:
- 创建我们自己的拦截器类并实现 HandlerInterceptor 接口或继承HandlerInterceptorAdapter。
- 创建一个Java类实现WebMvcConfigurer并重写 addInterceptors 方法。
- 实例化我们自定义的拦截器,然后将对像手动添加到拦截器链中(在addInterceptors方法中添加)。
1.创建拦截器
实现HandlerInterceptor 接口,创建拦截器:
public class MyInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("拦截器MyInterceptor------->1、请求之前调用,也就是Controller方法调用之前。");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
System.out.println("拦截器MyInterceptor------->2、请求之后调用,在视图渲染之前,也就是Controller方法调用之后");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
System.out.println("拦截器MyInterceptor------->3、请求结束之后被调用,主要用于清理工作。");
}
}
preHandle:在执行Handler方法前执行,也就是Controller方法调用之前。该方法返回值为bool类型,如果返回false,表示拦截请求,不再向下执行。如果返回true,表示放行,程序向下执行(如果后面没有其他Interceptor,就会直接执行Controller方法)。所以此方法可以对请求进行判断,觉得程序是否继续执行,或者执行一些前置初始化操作及对程序进行预处理。
postHandle:在执行Handler方法之后,返回ModelAndView之前执行。由于该方法会在DispatchServlet进行返回视图渲染之前被调用,所有从方法多被用于统一处理返回视图,例如将公用的模型数据(如菜单导航栏)添加到视图,或者根据其他情况指定公用视图。
afterCompletion:在执行完Handler之后执行。由于是在Controller方法执行完毕之后执行该方法,所以该方法适合进行统一的异常或者日志处理操作。
这三个方法都是相同的参数,Object handler参数可以转化成一个后端控制器对象,比如这里可以转换成LoginControl对象。
2.注册拦截器
WebMvcConfigurer是用来全局定制化Spring Boot的MVC特性。开发者需要通过WebMvcConfigurer接口来配置应用的MVC全局特性,这里面夜包含了拦截器,通过实现addInterceptors方法在里面添加我们自己定义的拦截器:
@Configuration
public class InterceptorConfigurerAdapter implements WebMvcConfigurer {
/**
* 该方法用于注册拦截器
* 可注册多个拦截器,多个拦截器组成一个拦截器链
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns 添加路径
// excludePathPatterns 排除路径
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/*.*");
}
}
运行工程访问页面查看控制台日志: