1.拦截器介绍

Web开发中,可以用Filter(过滤器)和 HandlerInterceptor(拦截器) 来过滤web请求,都能对客户端发来的请求进行处理。

过滤器:是一个服务器端的组件,它可以截取用户端的请求和响应信息,并对这些信息过滤。

Spring MVC 中的拦截器(Interceptor)类似于 Servlet 开发中的过滤器 Filter,它主要用于拦截用户请求并作相应的处理,它也是 AOP 编程思想的体现,底层通过动态代理模式完成。听说:只有经过DispatcherServlet 的请求,才会走拦截器链,我们自定义的Servlet 请求是不会被拦截的

参考 Spring:过滤器filter、拦截器interceptor、和AOP的区别与联系

  • 原理
  • Filter:过滤器是基于函数回调。
  • HandlerInterceptor:拦截器是基于java的反射机制,使用代理模式
  • 作用域不同
  • Filter:过滤器依赖于servlet容器,只能在 servlet容器,web环境下使用。跟Spring没有关系
  • HandlerInterceptor:拦截器依赖于spring容器,可以在spring容器中调用,不管此时Spring处于什么环境
  • 过滤内容
  • Filter:过滤器可以对几乎所有的请求起作用(可以保护资源)
  • HandlerInterceptor:拦截器只能对action起作用
  • 细粒度的不同
  • Filter:过滤器的控制比较粗,只能在请求进来时进行处理,对请求和响应进行包装
  • HandlerInterceptor:拦截器提供更精细的控制,可以在controller对请求处理之前或之后被调用,也可以在渲染视图呈现给用户之后,以及request全部结束之后,都可以拦截到
  • 中断
  • Filter:过滤器比较复杂,需要处理请求和响应对象来引发中断,需要额外的动作,比如将用户重定向到错误页面
  • HandlerInterceptor:不能通过拦截器修改request内容,但是可以通过抛出异常或者preHandle方法内返回 false 进行中断来暂停request执行   
  • 小结
  • 如果过滤器和拦截器同时存在:执行顺序:过滤前-拦截前-Action处理-拦截后-过滤后
  • 替代:过滤器能做的,拦截器基本上都能做

2.新建拦截器 参考 Spring Boot 2.X(九):Spring MVC - 拦截器(Interceptor)

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

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

public class TokenInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// 在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理
		// 进行逻辑判断,如果ok就返回true,不行就返回false,返回false就不会处理请求
		System.out.println("this is before handler");
		Boolean flag = false;
		if (flag) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// 在业务处理器处理请求执行完成后,生成视图之前执行。
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// 在 DispatcherServlet 完全处理完请求后被调用,可用于清理资源等
	}

}

3.配置拦截器

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

	/*
	 * 拦截器配置
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {

		List<String> excludePath = new ArrayList<>();

		// 排除拦截路径
		excludePath.add("/test");
		excludePath.add("/user");

		// 注册自定义拦截器,添加拦截路径和排除拦截路径
		registry.addInterceptor(new TokenInterceptor())

				.addPathPatterns("/**")

				.excludePathPatterns(excludePath);
	}

}

4.测试拦截器