Spring RestTemplate - 需要释放连接?

Spring RestTemplate - Need to release connection?

这是我的 Rest 模板配置,

    @Bean
    @Qualifier("myRestService")
    public RestTemplate createRestTemplate(@Value("${connection.timeout}") String maxConn) {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
         connectionManager.setMaxTotal(maxTotalConn);
         connectionManager.setDefaultMaxPerRoute(maxPerChannel);

        RequestConfig config = RequestConfig.custom().setConnectTimeout(100000).build();
        CloseableHttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager)
                .setDefaultRequestConfig(config).build();
        ClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);

        RestTemplate restTemplate = new RestTemplate(factory);

        restTemplate.setErrorHandler(new RestResponseErrorHandler());
         restTemplate.setMessageConverters(createMessageConverters());

        return restTemplate;
    }

我正在使用 PoolingHttpClientConnectionManager 来管理连接。

它被以下代码访问,

ResponseEntity<String> response = restClient.exchange( url, HttpMethod.GET, entity , String.class );

我需要在上述调用后释放连接还是由 RestTemplate 处理。如果我们需要注意释放连接。

请问有人explain/show如何释放连接。

您应该将 ClientHttpRequestFactory 声明为 bean。通过将其声明为 bean,它由 Spring bean 工厂管理,当应用程序关闭或 bean 超出范围时,它将调用工厂的 destroy 方法。 ClientHttpRequestFactory 的 destroy 方法将关闭底层 ClientConnectionManager 的连接池。您可以查看 Spring API 文档。

@Bean
public ClientHttpRequestFactory createRequestFactory(@Value("${connection.timeout}") String maxConn) {
    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
     connectionManager.setMaxTotal(maxTotalConn);
     connectionManager.setDefaultMaxPerRoute(maxPerChannel);

    RequestConfig config = RequestConfig.custom().setConnectTimeout(100000).build();
    CloseableHttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager)
            .setDefaultRequestConfig(config).build();
    return new HttpComponentsClientHttpRequestFactory(httpClient);
}

然后您可以使用这个 bean 来创建您的 RestTemplate:

@Bean
@Qualifier("myRestService")
public RestTemplate createRestTemplate(ClientHttpRequestFactory factory) {
    RestTemplate restTemplate = new RestTemplate(factory);

    restTemplate.setErrorHandler(new RestResponseErrorHandler());
    restTemplate.setMessageConverters(createMessageConverters());

    return restTemplate;
}

您提出的问题: 我需要在上述调用后释放连接还是由 RestTemplate 处理。如果我们需要注意释放连接。

不,如果您使用 resttemplate,则不需要在响应时关闭连接。

从 apache httpclient,您需要使用完整的响应 (EntityUtils.consume(HttpEntity) 并关闭响应。

这可以在 ClientConnectionRelease.java

中验证

但 RestTemplate 会为您完成此操作,以验证是否相同,请查看 RestTemplate.java

寻找方法

protected <T> T doExecute(URI url,...) {
 try {
        ClientHttpRequest request = this.createRequest(url, method);
        ...
        response = request.execute();
        ...
        if(responseExtractor != null) {
            var7 = responseExtractor.extractData(response);
            return var7;
        }
       ...
       ...
    } finally {
        if(response != null) {
            response.close();
        }

    }
}

响应提取器通过使用响应来为您完成工作 responseExtractor.extractData(响应);

在完全提取数据后,它也会关闭 response.close()

我想答案就在这里:org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor#doExecuteRequest

    @Override
    protected RemoteInvocationResult doExecuteRequest(
            HttpInvokerClientConfiguration config, ByteArrayOutputStream baos)
            throws IOException, ClassNotFoundException {

        HttpPost postMethod = createHttpPost(config);
        setRequestBody(config, postMethod, baos);
        try {
            HttpResponse response = executeHttpPost(config, getHttpClient(), postMethod);
            validateResponse(config, response);
            InputStream responseBody = getResponseBody(config, response);
            return readRemoteInvocationResult(responseBody, config.getCodebaseUrl());
        }
        finally {
            postMethod.releaseConnection();
        }
    }