This is the multi-page printable view of this section.
Click here to print.
Return to the regular view of this page.
Filter
Filter分为RequestFilter和ResponseFilter两种,前者主要用于处理HttpRequest,在所有Interceptor对HttpRequest处理之后执行, 后者主要用于处理HttpResponse,在响应headers到达之后立即执行,此时所有拦截器对HttpResponse的处理均未开始执行。
与Interceptor的区别
- 执行顺序不同:
RequestFilter在所有拦截器对HttpRequest的处理之后才会执行,ResponseFilter在响应头接收到之后(响应body处理前)立即执行,此时所有拦截器对HttpResponse的处理均未执行。
- 关联性不同:
RequestFilter和ResponseFilter中均无法同时获取到请求和响应,因此也不能将两者关联起来,但是同一个请求将在RequestFilter和ResponseFilter中共享一个FilterContext实例,
因此可以通过该对象传递上下文参数。而Interceptor中可以获取HttpRequest经过处理后的HttpResponse,因此可以通过此种方式将请求和响应关联起来。
- 通过
RequestFilter或ResponseFilter无法替换原始的HttpRequest或HttpResponse,而通过Interceptor可以实现。
鉴于Filter和Interceptor的区别,下述场景更适合使用Filter:
- 只需要单独处理
HttpRequest或HttpResponse,如:对每个HttpRequest或HttpResponse添加固定的请求header。
HttpRequest处理过程中可能需要多次执行的逻辑,比如在发生重试、重定向时会发出多个网络请求,而这些请求均需要执行的逻辑。
Note
- 多个
Filter之间通过getOrder()方法返回值区分执行顺序,值越小,优先级越高
- 同一个
HttpRequest可以通过共享一个FitlerContext实例在多个RequestFilter和ResponseFilter实例间传递上下文参数
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放入指定的目录下即可。