博客 / 詳情

返回

Servlet Filter 原理分析與實戰

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防刷 / 敏感詞過濾 / 資源訪問控制
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.