【 <一> 炼丹初探:JavaWeb 的起源与基础】之 Servlet 过滤器:实现请求的预处理与后处理
<前文回顾>
<今日更新>
一、过滤器:Servlet 的“门神”
在 JavaWeb 开发里,Servlet 过滤器[1] 就像个“门神”,专门在请求进门前“查岗”,在响应出门前“把关”。它能对请求和响应进行“预处理”和“后处理”,比如权限验证、日志记录、字符编码啥的。过滤器虽然“低调”,但它的作用可不容小觑。
1. 过滤器的“三板斧”
过滤器的主要功能可以概括为“三板斧”:
- 预处理请求:在请求到达 Servlet 之前,对请求进行一些“加工”,比如设置字符编码、验证权限啥的。
- 拦截请求:根据条件决定是否放行请求,比如权限不足时直接返回错误页面。
- 后处理响应:在响应返回给客户端之前,对响应进行一些“修饰”,比如压缩内容、添加响应头啥的。
Java Code |
public class MyFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { // 预处理请求 req.setCharacterEncoding("UTF-8");
// 拦截请求 if (checkPermission(req)) { chain.doFilter(req, resp); // 放行请求 } else { ((HttpServletResponse) resp).sendError(HttpServletResponse.SC_FORBIDDEN, "权限不足"); }
// 后处理响应 resp.setContentType("text/html;charset=UTF-8"); }
private boolean checkPermission(ServletRequest req) { // 权限验证逻辑 return true; } } |
2. 过滤器的“生命周期”
过滤器的生命周期和 Servlet 差不多,主要分三步:init、doFilter、destroy。
- init:过滤器初始化时调用,通常用来加载配置、初始化资源啥的。
- doFilter:每次请求时调用,是过滤器的核心方法。
- destroy:过滤器销毁时调用,通常用来释放资源啥的。
Java Code |
public void init(FilterConfig config) throws ServletException { // 初始化代码 } public void destroy() { // 清理代码 } |
二、过滤器的“实际应用场景”
过滤器虽然“低调”,但它的应用场景可不少。比如权限验证、日志记录、字符编码啥的,都能用过滤器来实现。
1. 权限验证
权限验证是过滤器的“拿手好戏”。比如,用户访问某个页面时,过滤器可以“查岗”,看看用户有没有权限,没权限就直接“拦下”。
Java Code |
public class AuthFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpReq = (HttpServletRequest) req; HttpSession session = httpReq.getSession(); if (session.getAttribute("user") == null) { ((HttpServletResponse) resp).sendRedirect("login.jsp"); } else { chain.doFilter(req, resp); } } } |
2. 日志记录
日志记录是过滤器的“家常便饭”。比如,每次请求时,过滤器可以“记一笔”,把请求的 URL、参数啥的都记录下来。
Java Code |
public class LogFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpReq = (HttpServletRequest) req; System.out.println("请求 URL: " + httpReq.getRequestURL()); System.out.println("请求参数: " + httpReq.getQueryString()); chain.doFilter(req, resp); } } |
3. 字符编码
字符编码是过滤器的“基本功”。比如,每次请求时,过滤器可以“统一”设置字符编码,避免乱码问题。
Java Code |
public class EncodingFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); chain.doFilter(req, resp); } } |
三、过滤器的“历史”:从 Servlet 2.3 到 Servlet 4.0
过滤器从 Servlet 2.3 开始就有了,虽然现在 Servlet 4.0 已经“普及”了,但过滤器的“核心功能”依然没变。
1. Servlet 2.3:初代“门神”
Servlet 2.3 在 2001 年发布,过滤器是它的“初代门神”。虽然功能简单,但已经能满足大部分开发需求了。
2. Servlet 3.0:引入注解
Servlet 3.0 在 2009 年发布,引入了注解[2],让开发者能用注解配置过滤器,不用再写 web.xml 了。注解的引入,让过滤器的“玩法”更加方便。
Java Code |
@WebFilter("/admin/*") public class AuthFilter implements Filter { // 过滤器代码 } |
3. Servlet 4.0:支持 HTTP/2
Servlet 4.0 在 2017 年发布,支持 HTTP/2[3],让 Web 应用的性能更上一层楼。HTTP/2 的引入,让过滤器的“玩法”更加高效。
四、过滤器的“骚操作”
1. 请求压缩
过滤器不仅能“查岗”,还能“修饰”响应。比如,用过滤器压缩响应内容,减少传输数据量。
Java Code |
public class CompressionFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResp = (HttpServletResponse) resp; httpResp.setHeader("Content-Encoding", "gzip"); chain.doFilter(req, new GZIPResponseWrapper(httpResp)); } } |
2. 响应缓存
过滤器不仅能“修饰”响应,还能“缓存”响应。比如,用过滤器缓存响应内容,减少服务器压力。
Java Code |
public class CacheFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResp = (HttpServletResponse) resp; httpResp.setHeader("Cache-Control", "max-age=3600"); chain.doFilter(req, resp); } } |
3. 跨域处理
过滤器不仅能“缓存”响应,还能“处理”跨域。比如,用过滤器添加跨域响应头,支持跨域请求。
Java Code |
public class CorsFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResp = (HttpServletResponse) resp; httpResp.setHeader("Access-Control-Allow-Origin", "*"); httpResp.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); chain.doFilter(req, resp); } } |
专有名词解释
- Servlet 过滤器:一种用于在请求到达 Servlet 之前或响应返回客户端之前进行处理的组件。
- 注解:Annotation,一种用于配置过滤器的元数据。
- HTTP/2:HTTP 协议的第二个主要版本,支持多路复用、头部压缩等特性。