Spring RestTemplate - 需要释放连接吗?

时间:2016-10-20 17:44:08

标签: spring httpclient resttemplate

这是我的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处理。如果我们需要照顾释放连接。

请有人解释/说明如何释放连接。

3 个答案:

答案 0 :(得分:10)

您应该将ClientHttpRequestFactory声明为bean。通过将它声明为bean,它将由Spring bean工厂管理,它将在应用程序关闭时调用工厂的destroy方法,或者bean超出范围。 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;
}

答案 1 :(得分:7)

您提出的问题: 我需要在上述调用之后释放连接,还是由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()

答案 2 :(得分:0)

我认为答案在这里: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();
        }
    }