【问题标题】:ClientHttpRequestInterceptor intercept method calling sequence?ClientHttpRequestInterceptor 拦截方法调用顺序?
【发布时间】:2021-12-26 11:27:59
【问题描述】:

ClientHttpRequestInterceptor的intercept方法是在从rest模板连接池获取连接之前调用还是之后调用?

【问题讨论】:

  • 你的意思是“线程池”而不是“连接池”吗?
  • 我的意思是具有 maxConnPerRoute 和 maxConnTotal 属性的其余连接池(PoolingHttpClientConnectionManager)

标签: java spring-boot resttemplate


【解决方案1】:

如果你在拦截器中什么都不做,那么就不会发起HTTP调用,也就意味着不会获取连接。

进行 HTTP 调用的代码在InterceptingClientHttpRequest

    private class InterceptingRequestExecution implements ClientHttpRequestExecution {

        private final Iterator<ClientHttpRequestInterceptor> iterator;

        public InterceptingRequestExecution() {
            this.iterator = interceptors.iterator();
        }

        @Override
        public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
            if (this.iterator.hasNext()) {
                ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
                return nextInterceptor.intercept(request, body, this);
            }
            else {
                HttpMethod method = request.getMethod();
                Assert.state(method != null, "No standard HTTP method");
                ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), method);
                request.getHeaders().forEach((key, value) -> delegate.getHeaders().addAll(key, value));
                if (body.length > 0) {
                    if (delegate instanceof StreamingHttpOutputMessage) {
                        StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) delegate;
                        streamingOutputMessage.setBody(outputStream -> StreamUtils.copy(body, outputStream));
                    }
                    else {
                        StreamUtils.copy(body, delegate.getBody());
                    }
                }
                return delegate.execute();
            }
        }
    }

如您所见,所有拦截器都被迭代以调用intercept

一般情况下,在您的intercept method 中,您需要执行请求(如果您不想阻止它)。

假设你有两个拦截器:

    RestTemplate rest = new RestTemplate();
    rest.setInterceptors(Arrays.asList(new ClientHttpRequestInterceptor() {
      @Override
      public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        System.out.println("first interceptor enter");
        ClientHttpResponse execute = execution.execute(request, body);
        System.out.println(execute.getStatusCode() + " In first interceptor");
        System.out.println("first interceptor exit");
        return execute;
      }
    }, new ClientHttpRequestInterceptor() {
      @Override
      public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        System.out.println("second interceptor enter");
        ClientHttpResponse execute = execution.execute(request, body);
        System.out.println(execute.getStatusCode() + " In second interceptor");
        System.out.println("second interceptor exit");
        return execute;
      }
    }));
    return rest.getForObject("https://stackoverflow.com/", String.class);

// output:
first interceptor enter
second interceptor enter
200 OK In second interceptor
second interceptor exit
200 OK In first interceptor
first interceptor exit

这里的流程是:

  1. 第一个拦截器(interceptor A)的拦截器方法被调用。
  2. interceptor A 执行execution.execute(request, body) 时,会调用第二个拦截器(interceptor A)。
  3. interceptor B执行execution.execute(request, body)时,由于没有拦截器,最终会通过requestFactory.createRequest(request.getURI(), method) 进行HTTP调用。 (在这种方法中,会如您所说的获取连接)。

【讨论】:

    猜你喜欢
    • 2014-10-11
    • 2012-04-01
    • 2021-09-16
    • 2015-08-14
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多