Filter

1.概念与作用

(1)Servlet 的核心是 “请求处理与流程控制”,但 Web 应用中存在大量通用功能(如权限校验、日志记录、字符编码转换),若直接在 Servlet 中实现这些功能,会导致代码冗余、耦合严重。Filter 可拦截请求 / 响应:在请求到达 Servlet 之前(预处理)或响应返回客户端之后(后处理)执行通用逻辑,将通用功能从 Servlet 中抽离(类似 Spring 框架的 AOP)为独立 Filter,通过配置即可全局生效,无需修改业务代码。
(2)Filter 是 Servlet2.3 规范新特性。Filter 拦截请求和响应,以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据。注意:Filter 不是 Servlet,它只是 Servlet 接收请求前的预处理器。
(3)Filter 与 Servlet 的关联由 Web 应用的配置描述文件来明确


2.Filter 主要应用场景


 (1)访问特定资源(Web 页、JSP 页、Servlet)时的身份验证,禁止非法用户访问
(2)访问资源的记录跟踪。
(3)字符编码转换


3.核心实现(1个接口,3个方法)

 一个 Filter 必须实现

javax.Servlet.Filter 接口
方法1:doFilter (ServletRequest, ServletResponse, FilterChain):用来实现过滤行为的方法。引入的 FilterChain 对象提供了后续 Filter 所要调用的信息
方法2:init(FilterConfig)
方法3:destroy()
  - 示例

@WebFilter("/*")
public class SimpleFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response,
                    FilterChain chain) throws IOException, ServletException {
    
    // 1. 处理请求前的逻辑
    System.out.println("请求到达");
    
    // 2. 必须调用这一行!
    chain.doFilter(request, response);// 放行到下一个 Filter
    
    // 3. 处理响应后的逻辑
    System.out.println("响应返回");
}
}


4.执行流程


请求流程:浏览器 -> Filter1(Before -> doFilter ())-> Filter2(Before -> doFilter ())-> Servlet -> Filter2(After)-> Filter1(After)-> 响应
 
 总结:
必须实现 Filter 接口

必须调用 chain.doFilter()(否则请求卡住)

常用注解 @WebFilter 配置

处理请求在 chain.doFilter() 之前

处理响应在 chain.doFilter() 之后


5.配置


 配置步骤
新建 Filter、指定过滤对象(可以是 URL 模式或逻辑名称),将信息添加到部署描述符(web.xml)


配置参数(新建 Filter 时需填写)
Name:如 TimingFilter、TimeTrackFilter
Description
Initialization parameters(Name、Value、Description)
Filter mappings:URL Pattern / Servlet Name、Dispatchers
Asynchronous Support

web.xml 配置片段

<filter>
<filter-name>TimeTrackFilter</filter-name>
<filter-class>com.servlet.TimeTrackFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TimeTrackFilter</filter-name>
<url-pattern>/Main</url-pattern>
</filter-mapping>


6.Filter 与 SSM 框架的关联


(1)SSM 框架可直接使用 Filter 解决通用问题,也允许通过自定义 Filter 扩展业务功能,二者协同实现请求全链路处理
(2)Spring 框架为简化开发,提供了多个开箱即用的 Filter,开发者可直接配置到 web.xml 或通过注解启用,无需重复编码。例如 Spring 提供的基础 Filter:CharacterEncodingFilter 可以统一请求 / 响应编码(解决中文乱码)


7.常用filter


7.1字符编码过滤器
 

@WebFilter("/*")
public class EncodingFilter implements Filter {
    private String encoding = "UTF-8";
    
    @Override
    public void init(FilterConfig config) {
        // 从配置读取编码
        String configEncoding = config.getInitParameter("encoding");
        if (configEncoding != null) {
            this.encoding = configEncoding;
        }
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                        FilterChain chain) throws IOException, ServletException {
        
        // 1. 设置请求编码(解决中文乱码)
        request.setCharacterEncoding(encoding);
        
        // 2. 设置响应编码
        response.setCharacterEncoding(encoding);
        response.setContentType("text/html;charset=" + encoding);
        
        // 3. 放行
        chain.doFilter(request, response);
    }
    
    @Override
    public void destroy() {
        // 清理资源(如果有的话)
    }
}


  7.2登录检查过滤器

@WebFilter({"/user/*", "/admin/*", "/cart/*"})  // 只过滤需要登录的路径
public class LoginFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp,
                        FilterChain chain) throws IOException, ServletException {
        
        // 转换为 HttpServlet 对象
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        
        // 获取 session
        HttpSession session = request.getSession(false);
        
        // 检查是否已登录
        if (session == null || session.getAttribute("user") == null) {
            // 未登录,重定向到登录页
            response.sendRedirect(request.getContextPath() + "/login.jsp");
            return;  // 重要:不调用 chain.doFilter()
        }
        
        // 已登录,放行
        chain.doFilter(request, response);
    }
}

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐