Servlet Filter 原理分析与实战

Servlet Filter 使用责任链模式实现Filter的调度执行,通过FilterChain管理Filter的执行,实现了Filter之间的逻辑解耦。本文简化了Filter的扩展功能,可以清晰的看到责任链模式执行的骨架。

责任链模式

责任链目的:通过Chain封装调用链路,实现Filter解耦

Chain 里面维护了Filter集合,提供了Filter管理接口和调用下一个Filter的接口


class FilterChain {
    // Filter 集合
    List<Filter> filters = new ArrayList<>();
    // 下一个 Filter 的下标
    int idx;

    /** 管理接口 add / update / remove */
    public void addFilter(Filter filter) {
        filters.add(filter);
    }

    /** 调用 下一个 Filter.doFilter */
    public void doNextFilter() {
        if (idx == filters.size()) {return;}

        Filter filter = filters.get(idx++);

        filter.doFilter(this);
    }
}

Filter 只需要实现自己的逻辑,然后大喊 下一个 (chain.doNextFilter)

interface Filter {
    void doFilter(FilterChain chain);
}

class LogFilter implements Filter {
    @Override
    public void doFilter(FilterChain chain) {
        System.out.println(" log ------ start " );
        // 调用 下一个
        chain.doNextFilter();
        System.out.println(" log ------ end " );
    }
}

class AuthFilter implements Filter {
    @Override
    public void doFilter(FilterChain chain) {
        System.out.println(" auth ------ start " );
        // 调用 下一个
        chain.doNextFilter();
        System.out.println(" auth ------ end " );
    }
}

责任链 核心 在于链的调度管理[Chain]

多个Filter 串行执行 形成调用链

Filter:单个Filter,实现自身的逻辑,调用下一个Filter
FilterChain:Filter链 维护一串Filters,提供下一个Filter的调用

实战

@Component
@Order(2)
public class TransactionFilter implements Filter {

    @Autowired
    private HttpServletReqUtil reqUtil;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        final MyHttpServletRequestWrapper wrappedRequest = new MyHttpServletRequestWrapper(
                (HttpServletRequest) request);
        System.out.println("Inside Servlet Filter");
        System.out.println("User IP address: " + reqUtil.getRemoteAddress(wrappedRequest));
        System.out.println("Request Params: " + reqUtil.getRequestParams(wrappedRequest));
        System.out.println("Request Payload: " + reqUtil.getPayLoad(wrappedRequest));
        System.out.println("Exiting Servlet Filter");
        chain.doFilter(wrappedRequest, response);
    }
}

总结

  • Filter通过责任链进行调用,由FilterChain统一管理调度,目的是解耦Filter
  • Filter 适用场景:请求头Header处理/ IP防刷 / 敏感词过滤 / 资源访问控制

Echo
0 声望0 粉丝