This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Filter

Filter分为RequestFilterResponseFilter两种,前者主要用于处理HttpRequest,在所有InterceptorHttpRequest处理之后执行, 后者主要用于处理HttpResponse,在响应headers到达之后立即执行,此时所有拦截器对HttpResponse的处理均未开始执行。

Interceptor的区别

  1. 执行顺序不同:RequestFilter在所有拦截器对HttpRequest的处理之后才会执行,ResponseFilter在响应头接收到之后(响应body处理前)立即执行,此时所有拦截器对HttpResponse的处理均未执行。
  2. 关联性不同:RequestFilterResponseFilter中均无法同时获取到请求和响应,因此也不能将两者关联起来,但是同一个请求将在RequestFilterResponseFilter中共享一个FilterContext实例, 因此可以通过该对象传递上下文参数。而Interceptor中可以获取HttpRequest经过处理后的HttpResponse,因此可以通过此种方式将请求和响应关联起来。
  3. 通过RequestFilterResponseFilter无法替换原始的HttpRequestHttpResponse,而通过Interceptor可以实现。

鉴于FilterInterceptor的区别,下述场景更适合使用Filter

  1. 只需要单独处理HttpRequestHttpResponse,如:对每个HttpRequestHttpResponse添加固定的请求header。
  2. HttpRequest处理过程中可能需要多次执行的逻辑,比如在发生重试、重定向时会发出多个网络请求,而这些请求均需要执行的逻辑。

1 - 使用方式

HttpClient支持通过builder配置和SPI加载两种方式配置Filter

Builder配置

final HttpClient client = HttpClient.create().addRequestFilter((request, ctx) -> {  // 仅处理Request
    System.out.println("Request Filter");
    return CompletableFuture.completedFuture(null);
}).addResponseFilter((request, response, ctx) -> {   // 仅处理Response
    System.out.println("Response Filter");
    return CompletableFuture.completedFuture(null);
}).addFilter(new DuplexFilter() {   // 同时处理Request和Response
    @Override
    public CompletableFuture<Void> doFilter(HttpRequest request, FilterContext ctx) {
        System.out.println("Request Filter(Duplex)");
        return CompletableFuture.completedFuture(null);
    }

    @Override
    public CompletableFuture<Void> doFilter(HttpRequest request, HttpResponse response, FilterContext ctx) {
        System.out.println("Response Filter(Duplex)");
        return CompletableFuture.completedFuture(null);
    }
}).build();

SPI

HttpClient支持通过SPI的方式加载Filter,使用时,只需要按照Spi的加载规则将自定义的Filter放入指定的目录下即可。