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.测试拦截器