Skip to content

过滤器

Filter(过滤器)是Java Web中的一种拦截组件,运行在Servlet/JSP之前,用于对请求和响应进行统一预处理、后处理,而不修改业务逻辑本身。

主要用途

  • 统一设置 编码格式
  • 登录验证、权限控制
  • 请求日志、敏感词过滤
  • 对响应内容进行压缩、替换等

工作特点

  1. 请求先到Filter,再到Servlet/JSP
  2. 响应先从Servlet/JSP返回,再经过Filter
  3. 可配置多个,形成过滤链
  4. 基于 拦截—放行 机制,不侵入业务代码
flowchart LR Client[客户端浏览器]:::info --> Request[HTTP请求]:::success Request --> Filter1[过滤器1
Filter]:::warning Filter1 --> Filter2[过滤器2
Filter]:::warning Filter2 --> FilterN[过滤器N
Filter]:::warning FilterN --> Servlet[Servlet/JSP
处理请求]:::primary Servlet --> Response[响应数据]:::danger Response --> FilterN FilterN --> Filter2 Filter2 --> Filter1 Filter1 --> Client

过滤器生命周期

过滤器生命周期的各个阶段:

  • 实例化

  • 初始化

  • 过滤

  • 销毁

HelloFilter
@WebFilter("/*")
public class HelloFilter extends HttpFilter implements Filter {
  public HelloFilter() {
    super();
  }

  public void init(FilterConfig fConfig) throws ServletException {
  }

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    chain.doFilter(request, response);
  }

  public void destroy() {
  }
}
源代码
HelloFilter
import java.io.IOException;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpFilter;

@WebFilter("/*")
public class HelloFilter extends HttpFilter implements Filter {
  public HelloFilter() {
    super();
  }

  public void init(FilterConfig fConfig) throws ServletException {
  }

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    chain.doFilter(request, response);
  }

  public void destroy() {
  }
}

过滤器定义

创建Filter分两步:

  • 创建Filter类

    • 实现Filter业务功能
  • URL映射

    • 建立Filter业务类与URL地址之间的映射关系

创建Filter类

SimpleFilter1
@WebFilter("/*")
public class SimpleFilter2 extends HttpFilter implements Filter {
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    try {
      response.setContentType("text/html;charset=utf-8");
      PrintWriter out = response.getWriter();
      out.append("<p style='color: red;'>SimpleFilter2检查中...</p>");
      chain.doFilter(request, response);
      out.append("<p style='color: red;'>SimpleFilter2检查完成!</p>");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }
}
源代码
SimpleFilter1
import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpFilter;

public class SimpleFilter1 extends HttpFilter implements Filter {
  private FilterConfig filterConfig;

  public SimpleFilter1() {
    super();
  }

  public void init(FilterConfig fConfig) throws ServletException {
    this.filterConfig = fConfig;
  }

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    try {
      response.setContentType("text/html;charset=utf-8");
      PrintWriter out = response.getWriter();
      out.append("<p style='color: blue;'>SimpleFilter1检查中...</p>");
      chain.doFilter(request, response);
      out.append("<p style='color: red;'>SimpleFilter1检查中完成!</p>");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }

  public void destroy() {
  }
}

URL映射

Filter有两种映射方式:注解、web.xml

SimpleFilter2
1
2
3
@WebFilter("/*")
public class SimpleFilter2 extends HttpFilter implements Filter {
}
源代码
SimpleFilter2
import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpFilter;

@WebFilter("/*")
public class SimpleFilter2 extends HttpFilter implements Filter {
  private FilterConfig filterConfig;

  public SimpleFilter2() {
    super();
  }

  public void init(FilterConfig fConfig) throws ServletException {
    this.filterConfig = fConfig;
  }

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    try {
      response.setContentType("text/html;charset=utf-8");
      PrintWriter out = response.getWriter();
      out.append("<p style='color: red;'>SimpleFilter2检查中...</p>");
      chain.doFilter(request, response);
      out.append("<p style='color: red;'>SimpleFilter2检查完成!</p>");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }

  public void destroy() {
  }
}
WEB-INF/web.xml
1
2
3
4
5
6
7
8
9
<filter>
  <filter-name>SimpleFilter1</filter-name>  <!-- 过滤器名 -->
  <filter-class>SimpleFilter1</filter-class><!-- 业务类 -->
</filter>

<filter-mapping>
  <filter-name>SimpleFilter1</filter-name>  <!-- 过滤器名 -->
  <url-pattern>/*</url-pattern> <!-- 映射地址 -->
</filter-mapping>
源代码
WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>HelloFilter</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.jsp</welcome-file>
    <welcome-file>default.htm</welcome-file>
  </welcome-file-list>

  <filter>
    <filter-name>SimpleFilter1</filter-name>  <!-- 过滤器名 -->
    <filter-class>SimpleFilter1</filter-class><!-- 业务类 -->
  </filter>

  <filter-mapping>
    <filter-name>SimpleFilter1</filter-name>  <!-- 过滤器名 -->
    <url-pattern>/*</url-pattern> <!-- 映射地址 -->
  </filter-mapping>

</web-app>

过滤器链

过滤器链就是多个过滤器按配置顺序串联在一起,形成一条处理Web请求的链式调用流程

  1. 客户端请求到来时,按顺序依次经过每个过滤器
  2. 每个过滤器做完处理后,决定是否放行(doFilter)
  3. 全部放行后,请求才到达 Servlet/JSP
  4. 响应返回时,按相反顺序再次经过过滤器链
  5. 整个过程像流水线一样,统一处理编码、登录、日志、权限等
flowchart LR 客户端:::success --> 过滤器1:::danger --> 过滤器2:::danger --> etc[...]:::danger --> 过滤器n:::danger --> Servlet/JSP:::primary Servlet/JSP --> 过滤器n --> etc --> 过滤器2 --> 过滤器1 --> 客户端

示例

创建一个Servlet(DoSomethingServlet)接收客户端语法,创建一个客户端页面(hi_filter.html)发送Servlet请求,创建两个过滤器(SimpleFilter1SimpleFilter2)监听全部URL请求

DoSomethingServlet
1
2
3
4
5
6
7
8
9
@WebServlet("/DoSomthing")
public class DoSomethingServlet extends HttpServlet {
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    out.println("<p style='color:green;'>我做了一些事!<p>");
  }
}
源代码
DoSomethingServlet
import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.annotation.WebServlet;

@WebServlet("/DoSomthing")
public class DoSomethingServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public DoSomethingServlet() {
    super();
  }

  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    out.println("<p style='color:green;'>我做了一些事!<p>");
  }
}

demo/HelloFilter/src/main/webapp/hi_filter.html
<html>

<head>
  <meta charset="utf-8">
  <title> 新文档 </title>
</head>

<body>
  <h1>欢迎使用第一个过滤器示例</h1>
  <a href="/HelloFilter/DoSomthing">单击此处查看过滤器的效果</a>
</body>

</html>

SimpleFilter1
public class SimpleFilter1 extends HttpFilter implements Filter {
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    try {
      response.setContentType("text/html;charset=utf-8");
      PrintWriter out = response.getWriter();
      out.append("<p style='color: blue;'>SimpleFilter1检查中...</p>");
      chain.doFilter(request, response);
      out.append("<p style='color: red;'>SimpleFilter1检查中完成!</p>");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }
}
源代码
SimpleFilter1
import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpFilter;

public class SimpleFilter1 extends HttpFilter implements Filter {
  private FilterConfig filterConfig;

  public SimpleFilter1() {
    super();
  }

  public void init(FilterConfig fConfig) throws ServletException {
    this.filterConfig = fConfig;
  }

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    try {
      response.setContentType("text/html;charset=utf-8");
      PrintWriter out = response.getWriter();
      out.append("<p style='color: blue;'>SimpleFilter1检查中...</p>");
      chain.doFilter(request, response);
      out.append("<p style='color: red;'>SimpleFilter1检查中完成!</p>");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }

  public void destroy() {
  }
}
SimpleFilter2
@WebFilter("/*")
public class SimpleFilter2 extends HttpFilter implements Filter {
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    try {
      response.setContentType("text/html;charset=utf-8");
      PrintWriter out = response.getWriter();
      out.append("<p style='color: red;'>SimpleFilter2检查中...</p>");
      chain.doFilter(request, response);
      out.append("<p style='color: red;'>SimpleFilter2检查完成!</p>");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }
}
源代码
SimpleFilter2
import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpFilter;

@WebFilter("/*")
public class SimpleFilter2 extends HttpFilter implements Filter {
  private FilterConfig filterConfig;

  public SimpleFilter2() {
    super();
  }

  public void init(FilterConfig fConfig) throws ServletException {
    this.filterConfig = fConfig;
  }

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    try {
      response.setContentType("text/html;charset=utf-8");
      PrintWriter out = response.getWriter();
      out.append("<p style='color: red;'>SimpleFilter2检查中...</p>");
      chain.doFilter(request, response);
      out.append("<p style='color: red;'>SimpleFilter2检查完成!</p>");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }

  public void destroy() {
  }
}