Filter过滤器

什么是Filter过滤器?

Filter是Java Servlet规范中的一部分,用于拦截和过滤请求与响应,通常用于在目标Servlet执行之前或之后执行特定逻辑。它可以在不改变目标资源逻辑的情况下,增强功能或添加通用处理逻辑。

常见用途包括:

  1. 权限校验:检查用户是否已登录或具备权限。
  2. 编码处理:解决请求和响应的字符编码问题。
  3. 日志记录:记录用户的请求信息、访问日志等。
  4. 防止重复提交:防止用户重复提交表单数据。
  5. 跨域支持:添加跨域资源共享(CORS)相关头信息。

Filter的基本结构

Filter必须实现jakarta.servlet.Filter接口,核心方法包括:

  1. init(FilterConfig filterConfig)
    初始化方法,在过滤器实例创建后调用一次。常用于初始化资源。

  2. doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    核心方法,每次拦截请求时调用。此方法中可以定义过滤逻辑,通过调用chain.doFilter(request, response)来放行请求。

  3. destroy()
    销毁方法,在过滤器被移除或服务器关闭时调用一次,用于释放资源。


Filter的配置

过滤器可以通过两种方式进行配置:

1. 在web.xml中配置

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.example.MyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

2. 使用注解配置

通过@WebFilter注解配置:

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
    // 实现方法
}

Filter的执行原理

  1. 当用户发起请求时,Servlet容器会根据请求路径匹配到相应的过滤器。
  2. 如果有多个过滤器匹配到同一个请求,按照配置的顺序依次执行。
  3. 在每个过滤器的doFilter方法中,是否执行目标Servlet取决于是否调用chain.doFilter(request, response)

Filter的生命周期

  1. 实例化:在服务器启动时,根据web.xml或注解配置创建Filter实例。
  2. 初始化:调用init方法,完成初始化操作。
  3. 请求过滤:每次请求调用doFilter方法。
  4. 销毁:在服务器关闭或应用程序卸载时,调用destroy方法释放资源。

Filter的匹配规则

精确匹配

匹配特定路径:

<url-pattern>/specificPath</url-pattern>

后缀匹配

匹配特定后缀:

<url-pattern>*.do</url-pattern>

前缀匹配

匹配路径前缀:

<url-pattern>/api/*</url-pattern>

全局匹配

匹配所有请求:

<url-pattern>/*</url-pattern>

Filter的优点

  1. 解耦合:将公共逻辑从Servlet中分离,便于维护。
  2. 复用性:公共逻辑只需编写一次,适用于多个Servlet。
  3. 灵活性:可以动态调整过滤器的顺序,实现运行时行为变化。

Filter在项目中的应用

场景1:用户登录校验

在OA项目中,所有的业务操作都要求用户先登录。可以通过Filter实现统一校验,避免每个Servlet重复编写代码。

示例代码:

@WebFilter(urlPatterns = "/*")
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 从Session中获取用户信息
        Object user = httpRequest.getSession().getAttribute("user");

        if (user == null) {
            // 未登录,重定向到登录页面
            httpResponse.sendRedirect(httpRequest.getContextPath() + "/login.jsp");
        } else {
            // 已登录,放行请求
            chain.doFilter(request, response);
        }
    }
}

场景2:统一编码设置

为了解决字符编码问题,可以在Filter中统一设置请求和响应的编码格式:

@WebFilter(urlPatterns = "/*")
public class EncodingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);
    }
}

场景3:记录请求日志

通过Filter记录用户的请求信息,便于后续分析和排查问题:

@WebFilter(urlPatterns = "/*")
public class LoggingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String uri = httpRequest.getRequestURI();
        String ip = request.getRemoteAddr();

        System.out.println("Request URI: " + uri + ", IP: " + ip);

        chain.doFilter(request, response);
    }
}

Filter的高级应用

责任链模式

Filter天然符合责任链设计模式:请求经过一系列过滤器处理,最终到达目标Servlet。可以动态调整过滤器的执行顺序,实现灵活扩展。

示例:多个过滤器处理请求

@WebFilter(urlPatterns = "/api/*")
public class FilterA implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("FilterA: Before");
        chain.doFilter(request, response);
        System.out.println("FilterA: After");
    }
}

@WebFilter(urlPatterns = "/api/*")
public class FilterB implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("FilterB: Before");
        chain.doFilter(request, response);
        System.out.println("FilterB: After");
    }
}

输出顺序:

FilterA: Before
FilterB: Before
FilterB: After
FilterA: After

改造OA项目的步骤

  1. 创建登录校验过滤器:验证用户是否登录,未登录则重定向到登录页面。
  2. 创建编码设置过滤器:统一设置请求和响应的字符编码。
  3. 配置过滤器顺序:确保登录校验过滤器先执行,编码过滤器后执行。
  4. 运行项目:通过访问不同模块验证过滤器功能。

总结

Filter是Java Web开发中的重要工具,提供了强大的拦截与增强功能。通过合理使用Filter,可以实现公共逻辑的复用、请求响应的统一处理以及动态扩展功能。在复杂项目中,Filter与责任链模式结合,可以极大提升系统的灵活性与可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值