Filter介绍
什么是Filter?
-
Filter表示过滤器,是 JavaWeb三大组件(Servlet、Filter、Listener)之一。
-
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能
- 使用了过滤器之后,要想访问web服务器上的资源,必须先经过滤器,过滤器处理完毕之后,才可以访问对应的资源。
-
过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等。

下面我们通过Filter快速入门程序掌握过滤器的基本使用操作:
- 第1步,定义过滤器 :1.定义一个类,实现 Filter 接口,并重写其所有方法。
- 第2步,配置过滤器:Filter类上加 @WebFilter 注解,配置拦截资源的路径。引导类上加 @ServletComponentScan 开启Servlet组件支持。
- 直接演示过滤器结合Jwt令牌校验在实际登录过程中的应用
java
@Slf4j
@WebFilter(urlPatterns = "/*")
public class TokenFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 1. 获取请求url
String uri = request.getRequestURI();
// 2. 判断请求url中是否包含login,如果包含,说明是登录操作,放行
if (uri.contains("/login")) {
log.info("登录请求,直接放行");
chain.doFilter(request, response);
return;
}
// 3. 获取请求头中的令牌(token)
String token = request.getHeader("token");
// 4. 判断令牌是否存在,如果不存在,响应 401
if (StrUtil.isBlank(token)) {
response.setStatus(HttpStatus.HTTP_UNAUTHORIZED);
return;
}
// 5. 解析token,如果解析失败,响应 401
try {
JwtUtils.parseJWT(token);
// 6. 放行
chain.doFilter(request, response);
} catch (Exception e) {
response.setStatus(HttpStatus.HTTP_UNAUTHORIZED);
return;
}
}
}
当我们在Filter类上面加了@WebFilter注解之后,接下来我们还需要在启动类上面加上一个注解@ServletComponentScan
,通过这个@ServletComponentScan
注解来开启SpringBoot项目对于Servlet组件的支持。
less
@ServletComponentScan //开启对Servlet组件的支持
@SpringBootApplication
public class TliasManagementApplication {
public static void main(String[] args) {
SpringApplication.run(TliasManagementApplication.class, args);
}
}
注意事项: 在过滤器Filter中,如果不执行放行操作,将无法访问后面的资源。 放行操作:chain.doFilter(request, response);
2、Interceptor拦截器
Interceptor
什么是拦截器?
- 是一种动态拦截方法调用的机制,类似于过滤器。
- 拦截器是Spring框架中提供的,用来动态拦截控制器方法的执行。
- 拦截器的作用:拦截请求,在指定方法调用前后,根据业务需要执行预先设定的代码。

在拦截器当中,我们通常也是做一些通用性的操作,比如:我们可以通过拦截器来拦截前端发起的请求,将登录校验的逻辑全部编写在拦截器当中。在校验的过程当中,如发现用户登录了(携带JWT令牌且是合法令牌),就可以直接放行,去访问spring当中的资源。如果校验时发现并没有登录或是非法令牌,就可以直接给前端响应未登录的错误信息。 拦截器的使用步骤和过滤器类似,也分为两步:
- 定义拦截器
- 注册配置拦截器
1). 自定义拦截器
实现HandlerInterceptor接口,并重写其所有方法
java
//自定义拦截器
@Component
public class DemoInterceptor implements HandlerInterceptor {
//目标资源方法执行前执行。 返回true:放行 返回false:不放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle .... ");
return true; //true表示放行
}
//目标资源方法执行后执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle ... ");
}
//视图渲染完毕后执行,最后执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion .... ");
}
}
注意:
-
preHandle方法:目标资源方法执行前执行。 返回true:放行 返回false:不放行
-
postHandle方法:目标资源方法执行后执行
-
afterCompletion方法:视图渲染完毕后执行,最后执行
2). 注册配置拦截器
在 com.itheima
下创建一个包,然后创建一个配置类 WebConfig
, 实现 WebMvcConfigurer
接口,并重写 addInterceptors
方法
typescript
@Configuration
public class WebConfig implements WebMvcConfigurer {
//自定义的拦截器对象
@Autowired
private DemoInterceptor demoInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册自定义拦截器对象
registry.addInterceptor(demoInterceptor).addPathPatterns("/**");//设置拦截器拦截的请求路径( /** 表示拦截所有请求)
}
}
-
令牌校验Interceptor
讲解完了拦截器的基本操作之后,接下来我们需要完成最后一步操作:通过拦截器来完成案例当中的登录校验功能。
登录校验的业务逻辑以及操作步骤我们前面已经分析过了,和登录校验Filter过滤器当中的逻辑是完全一致的。现在我们只需要把这个技术方案由原来的过滤器换成拦截器interceptor就可以了。
1). Token和Interceptor
java
@Slf4j
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1. 获取请求url。
String uri = request.getRequestURI().toString();
//2. 判断请求url中是否包含login,如果包含,说明是登录操作,放行。
if(uri.contains("login")){ //登录请求
log.info("登录请求 , 直接放行");
return true;
}
//3. 获取请求头中的令牌(token)。
String jwt = request.getHeader("token");
//4. 判断令牌是否存在,如果不存在,返回错误结果(未登录)。
if(StringUtils.isBlank(jwt)){ //jwt为空
log.info("获取到jwt令牌为空, 返回错误结果");
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
return false;
}
//5. 解析token,如果解析失败,返回错误结果(未登录)。
try {
JwtUtils.parseJWT(jwt);
//6. 放行。
log.info("令牌合法, 放行");
return true;
} catch (Exception e) {
e.printStackTrace();
log.info("解析令牌失败, 返回错误结果");
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
return false;
}
}
}
2). 配置拦截器
typescript
@Configuration
public class WebConfig implements WebMvcConfigurer {
//拦截器对象
@Autowired
private TokenInterceptor tokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册自定义拦截器对象
registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
}
}
-
拦截路径
首先我们先来看拦截器的拦截路径的配置,在注册配置拦截器的时候,我们要指定拦截器的拦截路径,通过addPathPatterns("要拦截路径")
方法,就可以指定要拦截哪些资源。
在入门程序中我们配置的是/**
,表示拦截所有资源,而在配置拦截器时,不仅可以指定要拦截哪些资源,还可以指定不拦截哪些资源,只需要调用excludePathPatterns("不拦截路径")
方法,指定哪些资源不需要拦截。

typescript
@Configuration
public class WebConfig implements WebMvcConfigurer {
//拦截器对象
@Autowired
private DemoInterceptor demoInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册自定义拦截器对象
registry.addInterceptor(demoInterceptor)
.addPathPatterns("/**")//设置拦截器拦截的请求路径( /** 表示拦截所有请求)
.excludePathPatterns("/login");//设置不拦截的请求路径
}
}
3过滤器和拦截器的区别
在Java Web开发中,过滤器(Filter)和拦截器(Interceptor)都是常见的用于在请求和响应之间进行处理的组件。它们的主要区别如下:,
1、他们依赖的框架不同:过滤器是web的三大规范之一,不依赖任何框架,三大规范分别是Servlet、Filter和Listener。而拦截器是依赖于特定的框架而实现的,例如本文讲的基于spring框架实现的
2、功能不同:过滤器主要用于对请求进行预处理和过滤,例如设置字符集、登录验证、日志记录等操作;而拦截器则主要用于对请求进行流程控制,例如权限验证、参数注入、异常处理等操作。他们的拦截路径也有所区别,比如Filter中的/表示拦截全部的请求路径,Interceptor中的/ * 才表示拦截全部的请求路径。
3、触发时机也不同:请求的执行顺序是:请求进入容器 > 进入过滤器 > 进入 Servlet > 进入拦截器 > 执行控制器,所以过滤器和拦截器的执行时机也是不同的,过滤器会先执行,然后才会执行拦截器,最后才会进入真正的要调用的方法。过滤器通常是用来进行全局过滤的,而拦截器是用来实现某项业务拦截的。
图片来源:(juejin.cn/post/715506...)