Java中的过滤器和拦截器
一.应用场景
拦截器应用场景
拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:
- 登录验证,判断用户是否登录。
- 权限验证,判断用户是否有权限访问资源,如校验token
- 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。
- 处理cookie、本地化、国际化、主题等。
- 性能监控,监控请求处理时长等。
- 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现)
过滤器应用场景
- 过滤敏感词汇(防止sql注入)
- 设置字符编码
- URL级别的权限访问控制
- 压缩响应信息
二.执行顺序
三.异同点
- 提供者
截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。过滤器需要在servlet容器中实现,拦截器可以适用于javaEE,javaSE等各种环境
2.触发时机
过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
3.实现方式
过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射。拦截器可以调用IOC容器中的各种依赖,而过滤器不能。
4.依赖
Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
5.执行方式
Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。过滤器可以修改request,而拦截器不能。过滤器只能在请求的前后使用,而拦截器可以详细到每个方法
6.生命周期
Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
总的来说
过滤器就是筛选出你要的东西,比如requeset中你要的那部分。拦截器在做安全方面用的比较多,比如终止一些流程
四.实现方法
过滤器
两种方式实现
- 使用spring boot提供的FilterRegistrationBean注册Filter
- 使用原生servlet注解定义Filter
package com.yfapi.api; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; /** * 自定义过滤器 */ @WebFilter({"/*"}) public class MyTokenAuthFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("do my filter"); chain.doFilter(request,response); } @Override public void destroy() { Filter.super.destroy(); } }
在application上添加自定义扫描器注解 @ServletComponentScan 或者 自己实现FilterRegistrationBean配置类
拦截器
自定义类实现接口HandlerInterceptor,重写preHandle方法。
package com.yfapi.api; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 自定义拦截器 */ public class MyTokenAuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("执行拦截器"); return HandlerInterceptor.super.preHandle(request, response, handler); } }
自定义拦截器注册类
package com.yfapi.api; import com.google.common.collect.Lists; import org.springframework.beans.factory.annotation.Autowired; 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 MyTokenAuthInterceptorConfigurer implements WebMvcConfigurer { @Autowired private MyTokenAuthInterceptor myTokenAuthInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { /** * 注册拦截器,除了common和authenticate接口其他的都要拦截判断token */ String[] excludePath = { "/api/authenticate/**", "/api/common/**" }; registry.addInterceptor(myTokenAuthInterceptor) .addPathPatterns("/**") .excludePathPatterns(Lists.newArrayList(excludePath)); WebMvcConfigurer.super.addInterceptors(registry); } }