您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# SpringBoot Web中过滤器Filter的使用方法
## 目录
- [一、过滤器(Filter)概述](#一过滤器filter概述)
- [1.1 什么是过滤器](#11-什么是过滤器)
- [1.2 过滤器与拦截器的区别](#12-过滤器与拦截器的区别)
- [1.3 过滤器的应用场景](#13-过滤器的应用场景)
- [二、SpringBoot中Filter的实现方式](#二springboot中filter的实现方式)
- [2.1 实现Filter接口](#21-实现filter接口)
- [2.2 使用@WebFilter注解](#22-使用webfilter注解)
- [2.3 通过FilterRegistrationBean注册](#23-通过filterregistrationbean注册)
- [三、Filter的生命周期与核心方法](#三filter的生命周期与核心方法)
- [3.1 init()初始化方法](#31-init初始化方法)
- [3.2 doFilter()过滤逻辑](#32-dofilter过滤逻辑)
- [3.3 destroy()销毁方法](#33-destroy销毁方法)
- [四、Filter的配置详解](#四filter的配置详解)
- [4.1 URL模式匹配](#41-url模式匹配)
- [4.2 过滤器执行顺序](#42-过滤器执行顺序)
- [4.3 初始化参数配置](#43-初始化参数配置)
- [五、实战案例](#五实战案例)
- [5.1 请求日志记录过滤器](#51-请求日志记录过滤器)
- [5.2 权限验证过滤器](#52-权限验证过滤器)
- [5.3 XSS防护过滤器](#53-xss防护过滤器)
- [5.4 跨域处理过滤器](#54-跨域处理过滤器)
- [六、高级应用](#六高级应用)
- [6.1 过滤器链工作原理](#61-过滤器链工作原理)
- [6.2 异步请求处理](#62-异步请求处理)
- [6.3 异常处理机制](#63-异常处理机制)
- [七、常见问题与解决方案](#七常见问题与解决方案)
- [7.1 过滤器不生效问题](#71-过滤器不生效问题)
- [7.2 执行顺序问题](#72-执行顺序问题)
- [7.3 性能优化建议](#73-性能优化建议)
- [八、总结与最佳实践](#八总结与最佳实践)
## 一、过滤器(Filter)概述
### 1.1 什么是过滤器
过滤器(Filter)是Java Web开发中的核心组件之一,它可以在请求到达Servlet之前或响应返回客户端之前对HTTP请求和响应进行预处理和后处理。在Spring Boot应用中,过滤器仍然扮演着重要角色,主要用于处理与业务逻辑无关的横切关注点。
过滤器的主要特点包括:
- 在请求到达Controller前进行预处理
- 在响应返回客户端前进行后处理
- 可以拦截多个请求,实现代码复用
- 通过配置可以灵活控制过滤范围
### 1.2 过滤器与拦截器的区别
| 特性 | 过滤器(Filter) | 拦截器(Interceptor) |
|--------------|----------------------------------------|---------------------------------------|
| 作用范围 | Servlet规范,任何Web框架可用 | Spring MVC特有 |
| 执行时机 | 在DispatcherServlet之前 | 在DispatcherServlet之后,Controller之前|
| 依赖 | 依赖Servlet容器 | 依赖Spring框架 |
| 获取上下文 | 只能获取Servlet API对象 | 可以获取Spring上下文和业务对象 |
| 使用场景 | 字符编码、跨域处理、XSS防护等 | 权限验证、日志记录、参数预处理等 |
### 1.3 过滤器的应用场景
1. **安全相关**:XSS防护、CSRF防护、权限验证
2. **日志记录**:请求/响应日志、访问统计
3. **性能监控**:接口耗时统计、QPS监控
4. **编码处理**:统一字符编码设置
5. **跨域处理**:CORS跨域资源共享配置
6. **数据压缩**:响应内容GZIP压缩
7. **缓存控制**:HTTP缓存头设置
## 二、SpringBoot中Filter的实现方式
### 2.1 实现Filter接口
这是最基础的实现方式,创建一个类实现`javax.servlet.Filter`接口:
```java
import javax.servlet.*;
import java.io.IOException;
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化逻辑
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 前置处理
System.out.println("Before filter processing");
// 放行请求
chain.doFilter(request, response);
// 后置处理
System.out.println("After filter processing");
}
@Override
public void destroy() {
// 销毁逻辑
}
}
Spring Boot支持Servlet 3.0的@WebFilter
注解,可以简化配置:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*", filterName = "customFilter")
public class CustomFilter implements Filter {
// 实现方法同上
}
还需要在启动类添加@ServletComponentScan
注解:
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这是Spring Boot推荐的方式,提供了更灵活的配置:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<CustomFilter> customFilterRegistration() {
FilterRegistrationBean<CustomFilter> registration =
new FilterRegistrationBean<>();
registration.setFilter(new CustomFilter());
registration.addUrlPatterns("/*");
registration.setOrder(1); // 设置执行顺序
registration.setName("customFilter");
return registration;
}
}
init
方法在过滤器实例创建后立即执行,用于初始化操作:
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 获取初始化参数
String param = filterConfig.getInitParameter("paramName");
// 初始化资源
this.someResource = initResource();
log.info("Filter initialized with param: {}", param);
}
doFilter
是过滤器的核心方法,处理请求和响应:
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 1. 前置处理
long startTime = System.currentTimeMillis();
HttpServletRequest httpRequest = (HttpServletRequest) request;
// 2. 业务逻辑处理
if (shouldFilter(httpRequest)) {
// 可以修改请求或响应
CustomRequestWrapper wrappedRequest = new CustomRequestWrapper(httpRequest);
// 继续过滤器链
chain.doFilter(wrappedRequest, response);
} else {
chain.doFilter(request, response);
}
// 3. 后置处理
long duration = System.currentTimeMillis() - startTime;
log.info("Request {} processed in {} ms", httpRequest.getRequestURI(), duration);
}
destroy
在Web应用关闭时调用,用于释放资源:
@Override
public void destroy() {
// 释放资源
if (this.someResource != null) {
this.someResource.close();
}
log.info("Filter destroyed");
}
Spring Boot支持多种URL匹配模式:
registration.addUrlPatterns(
"/api/*", // 匹配/api路径下的所有请求
"*.html", // 匹配所有html文件
"/admin/**", // 匹配/admin及其子路径
"/public/resources/*.css" // 匹配特定资源
);
通过setOrder
方法控制执行顺序,值越小优先级越高:
@Bean
public FilterRegistrationBean<FilterA> filterA() {
FilterRegistrationBean<FilterA> reg = new FilterRegistrationBean<>();
reg.setOrder(1); // 最先执行
// ...
}
@Bean
public FilterRegistrationBean<FilterB> filterB() {
FilterRegistrationBean<FilterB> reg = new FilterRegistrationBean<>();
reg.setOrder(2); // 其次执行
// ...
}
可以通过两种方式配置初始化参数:
@WebFilter(
urlPatterns = "/*",
initParams = {
@WebInitParam(name = "param1", value = "value1"),
@WebInitParam(name = "param2", value = "value2")
}
)
registration.addInitParameter("param1", "value1");
registration.addInitParameter("param2", "value2");
在Filter中通过FilterConfig获取:
String value = filterConfig.getInitParameter("param1");
public class RequestLoggingFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// 记录请求信息
String requestURI = httpRequest.getRequestURI();
String method = httpRequest.getMethod();
String queryString = httpRequest.getQueryString();
String clientIP = httpRequest.getRemoteAddr();
log.info("Request: {} {}?{}, IP: {}", method, requestURI, queryString, clientIP);
long startTime = System.currentTimeMillis();
chain.doFilter(request, response);
long duration = System.currentTimeMillis() - startTime;
log.info("Response: {} completed in {} ms", requestURI, duration);
}
// init和destroy方法省略
}
public class AuthFilter implements Filter {
private List<String> excludeUrls = Arrays.asList("/login", "/public/");
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String path = httpRequest.getRequestURI().substring(
httpRequest.getContextPath().length());
// 排除不需要验证的URL
if (isExcluded(path)) {
chain.doFilter(request, response);
return;
}
// 检查认证信息
String token = httpRequest.getHeader("Authorization");
if (!validateToken(token)) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
return;
}
chain.doFilter(request, response);
}
private boolean isExcluded(String path) {
return excludeUrls.stream().anyMatch(path::startsWith);
}
private boolean validateToken(String token) {
// 实现token验证逻辑
return true;
}
}
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(new XssRequestWrapper((HttpServletRequest) request), response);
}
}
public class XssRequestWrapper extends HttpServletRequestWrapper {
public XssRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
return cleanXss(super.getParameter(name));
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null) return null;
return Arrays.stream(values).map(this::cleanXss).toArray(String[]::new);
}
private String cleanXss(String value) {
if (value == null) return null;
// 实现XSS清理逻辑
return value.replaceAll("<", "<").replaceAll(">", ">");
}
}
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
// 设置CORS头
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
httpResponse.setHeader("Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS");
httpResponse.setHeader("Access-Control-Max-Age", "3600");
httpResponse.setHeader("Access-Control-Allow-Headers",
"Content-Type, Authorization, X-Requested-With");
// 对OPTIONS请求直接返回
if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {
httpResponse.setStatus(HttpServletResponse.SC_OK);
return;
}
chain.doFilter(request, response);
}
}
Spring Boot中的过滤器链执行流程:
doFilter
方法被调用chain.doFilter()
进入Servlet对于异步请求,需要特殊处理:
public class AsyncFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (request.isAsyncSupported()) {
request.setAttribute("ASYNC_SUPPORTED", true);
}
// 包装响应以支持异步
AsyncResponseWrapper wrappedResponse = new AsyncResponseWrapper(
(HttpServletResponse) response);
try {
chain.doFilter(request, wrappedResponse);
} finally {
if (!request.isAsyncStarted()) {
wrappedResponse.finish();
}
}
}
}
过滤器中的异常处理策略:
public class ExceptionHandlingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (Exception e) {
handleException((HttpServletRequest) request,
(HttpServletResponse) response, e);
}
}
private void handleException(HttpServletRequest request,
HttpServletResponse response,
Exception ex) throws IOException {
// 根据异常类型返回不同的错误响应
if (ex instanceof AuthenticationException) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
} else {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Server error");
}
}
}
可能原因及解决方案:
未正确注册:
@Component
或@WebFilter
+@ServletComponentScan
FilterRegistrationBean
显式注册URL模式不匹配:
urlPatterns
是否包含目标路径/*
测试是否匹配所有请求顺序问题:
chain.doFilter()
控制执行顺序的方法:
使用@Order
注解:
@Component
@Order(1)
public class FilterA implements Filter { ... }
使用FilterRegistrationBean
的setOrder
方法:
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
实现Ordered
接口:
public class FilterB implements Filter, Ordered {
@Override
public int getOrder() { return 2; }
}
if (!needsFiltering(request)) {
chain.doFilter(request, response);
return;
}
适用场景:
实现方式对比:
方式 | 优点 | 缺点 |
---|---|---|
实现Filter接口 | 简单直接 | 配置不够灵活 |
@WebFilter注解 | 配置简洁 | 顺序控制有限 |
FilterRegistrationBean | 高度可配置,功能强大 | 代码量稍多 |
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。