当前位置: 首页 > news >正文

Filter 过滤器详解与使用指南

Filter 过滤器详解与使用指南

一、Filter 概述

1.1 什么是 Filter?

Filter(过滤器)是 Java Servlet 规范中定义的一种特殊组件,用于在请求到达 Servlet 之前或响应发送到客户端之前拦截和处理 HTTP 请求和响应。Filter 可以看作是一个"预处理-后处理"机制。

1.2 Filter 的作用

  • 预处理请求:在请求到达目标资源之前进行处理
  • 后处理响应:在响应发送到客户端之前进行处理
  • 链式处理:多个过滤器可以形成过滤链,依次处理请求和响应

1.3 Filter 的应用场景

  1. 身份认证和授权检查
  2. 请求日志记录和审计
  3. 数据压缩和加密
  4. 字符编码转换
  5. 输入验证和XSS防护
  6. 响应内容过滤和转换

二、Filter 的生命周期

Filter 的生命周期由 Web 容器管理,包含三个阶段:

  1. 初始化:Web 容器启动时,调用 init() 方法
  2. 过滤:每次请求时,调用 doFilter() 方法
  3. 销毁:Web 容器关闭时,调用 destroy() 方法

三、Filter 接口方法

public interface Filter {// 初始化方法,在Filter创建时调用一次void init(FilterConfig filterConfig) throws ServletException;// 过滤处理方法,每次请求都会调用void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;// 销毁方法,在Filter销毁时调用一次void destroy();
}

四、创建和配置 Filter

4.1 创建 Filter 类

// 方式1:实现Filter接口
public class MyFilter implements Filter {private FilterConfig filterConfig;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.filterConfig = filterConfig;System.out.println("MyFilter初始化完成");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 预处理逻辑System.out.println("请求预处理");// 调用过滤链中的下一个过滤器或目标资源chain.doFilter(request, response);// 后处理逻辑System.out.println("响应后处理");}@Overridepublic void destroy() {System.out.println("MyFilter被销毁");this.filterConfig = null;}
}

4.2 配置 Filter

方式1:使用 web.xml 配置(传统方式)
<web-app><!-- 定义Filter --><filter><filter-name>MyFilter</filter-name><filter-class>com.example.MyFilter</filter-class><!-- 初始化参数 --><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><!-- 配置Filter映射 --><filter-mapping><filter-name>MyFilter</filter-name><!-- 匹配所有请求 --><url-pattern>/*</url-pattern><!-- 也可以指定Servlet名称 --><!-- <servlet-name>MyServlet</servlet-name> --><!-- 配置Dispatcher类型 --><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher></filter-mapping>
</web-app>
方式2:使用注解配置(Servlet 3.0+)
@WebFilter(filterName = "MyFilter",urlPatterns = {"/*"},initParams = {@WebInitParam(name = "encoding", value = "UTF-8")},dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD}
)
public class MyFilter implements Filter {// 实现代码同上
}

五、FilterChain 机制

FilterChain 代表一个过滤链,多个过滤器按照配置的顺序依次执行:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 1. 预处理代码(在chain.doFilter()之前执行)System.out.println("Filter1: 预处理");// 2. 将请求传递给下一个过滤器或目标资源chain.doFilter(request, response);// 3. 后处理代码(在chain.doFilter()之后执行)System.out.println("Filter1: 后处理");
}

六、常见 Filter 应用示例

6.1 字符编码过滤器

@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "encoding", value = "UTF-8")
})
public class CharacterEncodingFilter implements Filter {private String encoding;@Overridepublic void init(FilterConfig filterConfig) {this.encoding = filterConfig.getInitParameter("encoding");if (this.encoding == null) {this.encoding = "UTF-8";}}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 设置请求和响应编码request.setCharacterEncoding(encoding);response.setCharacterEncoding(encoding);response.setContentType("text/html;charset=" + encoding);chain.doFilter(request, response);}@Overridepublic void destroy() {// 清理资源}
}

6.2 身份认证过滤器

@WebFilter(urlPatterns = {"/admin/*", "/user/*"})
public class AuthenticationFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;HttpSession session = httpRequest.getSession(false);// 检查用户是否登录boolean isLoggedIn = (session != null && session.getAttribute("user") != null);if (!isLoggedIn) {// 未登录,重定向到登录页面httpResponse.sendRedirect(httpRequest.getContextPath() + "/login.jsp");return;}chain.doFilter(request, response);}
}

6.3 日志记录过滤器

@WebFilter("/*")
public class LoggingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;// 记录请求信息long startTime = System.currentTimeMillis();String requestURI = httpRequest.getRequestURI();String remoteAddr = httpRequest.getRemoteAddr();System.out.println("请求开始: " + requestURI + " from " + remoteAddr);chain.doFilter(request, response);// 记录响应信息long endTime = System.currentTimeMillis();long duration = endTime - startTime;System.out.println("请求完成: " + requestURI + " 耗时 " + duration + "ms");}
}

6.4 XSS 防护过滤器

@WebFilter("/*")
public class XSSFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 包装请求对象,对参数进行XSS过滤XSSRequestWrapper wrappedRequest = new XSSRequestWrapper((HttpServletRequest) request);chain.doFilter(wrappedRequest, response);}
}// XSS请求包装器
class XSSRequestWrapper extends HttpServletRequestWrapper {public XSSRequestWrapper(HttpServletRequest request) {super(request);}@Overridepublic String getParameter(String name) {String value = super.getParameter(name);return cleanXSS(value);}@Overridepublic String[] getParameterValues(String name) {String[] values = super.getParameterValues(name);if (values == null) return null;String[] cleanedValues = new String[values.length];for (int i = 0; i < values.length; i++) {cleanedValues[i] = cleanXSS(values[i]);}return cleanedValues;}private String cleanXSS(String value) {if (value == null) return null;// 简单的XSS过滤return value.replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&#x27;").replaceAll("/", "&#x2F;");}
}

七、Filter 执行顺序

7.1 执行顺序规则

  1. web.xml 配置:按照 <filter-mapping> 的配置顺序执行
  2. 注解配置:按照过滤器类名的字母顺序执行
  3. 混合配置:web.xml 配置的过滤器先于注解配置的过滤器执行

7.2 控制执行顺序

如果需要精确控制执行顺序,可以使用 web.xml 进行统一配置:

<filter-mapping><filter-name>Filter1</filter-name><url-pattern>/*</url-pattern>
</filter-mapping><filter-mapping><filter-name>Filter2</filter-name><url-pattern>/*</url-pattern>
</filter-mapping><filter-mapping><filter-name>Filter3</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

八、DispatcherType 详解

DispatcherType 用于控制过滤器在哪种类型的请求分发过程中被调用:

DispatcherType描述
REQUEST直接来自客户端的请求(默认)
FORWARD通过 RequestDispatcher.forward() 转发的请求
INCLUDE通过 RequestDispatcher.include() 包含的请求
ERROR通过错误页面机制转发的请求
ASYNC异步Servlet处理相关的请求

配置示例

<filter-mapping><filter-name>MyFilter</filter-name><url-pattern>/*</url-pattern><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher><dispatcher>ERROR</dispatcher>
</filter-mapping>

九、最佳实践

  1. 合理设计过滤链:将通用的、轻量级的过滤器放在前面
  2. 避免重复处理:通过请求属性标记已处理的请求
  3. 正确处理异常:在过滤器中捕获和处理异常
  4. 性能考虑:避免在过滤器中执行耗时操作
  5. 资源清理:在 destroy() 方法中释放资源
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {try {// 预处理// ...chain.doFilter(request, response);// 后处理// ...} catch (Exception e) {// 异常处理throw new ServletException("Filter处理异常", e);}
}

十、总结

Filter 是 Java Web 开发中非常重要的组件,它提供了强大的请求/响应预处理机制。通过合理使用 Filter,可以实现:

  1. 代码复用:将通用功能抽象为过滤器
  2. 职责分离:保持 Servlet 专注于业务逻辑
  3. 灵活配置:通过配置决定过滤器的应用范围和执行顺序
  4. 功能增强:在不修改现有代码的情况下增强系统功能

掌握 Filter 的使用是 Java Web 开发的基本技能,合理运用 Filter 可以大大提高应用程序的可维护性和扩展性。

http://www.dtcms.com/a/392278.html

相关文章:

  • 养成合成小游戏抖音快手微信小程序看广告流量主开源
  • 在 Ubuntu 系统下安装 Conda
  • ac8257 android 9 SYSTEM_LAST_KMSG
  • ARM 架构与嵌入式系统
  • ARM(14) - LCD(1)清屏和画图形
  • Linux第十九讲:传输层协议UDP
  • 计算机网络学习(四、网络层)
  • 开启科学计算之旅:《MATLAB程序设计》课程导览
  • MATLAB | 数学模型 | 传染病 SIR 模型的参数确定
  • MATLAB基本运算(2)
  • 小红书数据分析面试题及参考答案
  • SpringCloudStream:消息驱动组件
  • ret2text-CTFHub技能树
  • VirtualBox 7 虚拟机的硬盘如何扩大?
  • React新闻发布系统 权限列表开发
  • 23种设计模式之【策略模式】-核心原理与 Java 实践
  • 前端实战从零构建响应式井字棋游戏
  • Java中的equals()与hashCode()
  • 【绕过open_basedir】
  • 如何用户细分
  • 福彩双色球第2025109期篮球号码分析
  • 思考:客户端负载均衡和服务器负载均衡有什么区别?
  • 网络编程day04/05原始套接字
  • Yarn命令与npm命令的区别与联系(npm:Node.js的官方包管理工具;Yarn:Facebook开发的JavaScript包管理工具)
  • 【大语言模型 67】梯度压缩与稀疏通信
  • LeetCode第365题_水壶问题
  • OpenCV:DNN 模块实现图像风格迁移
  • 锤子助手插件功能六十四:禁用视频前置摄像头镜像
  • OpenHarmony NFC Tag驱动深度剖析:从HDF框架到NDEF读写全流程实战
  • 黑马头条_SpringCloud项目阶段四:多媒体短文章提交功能实现详解