Закрытие соединения в GET-запросе с использованием Jersey Client 2.22.1

Я использую клиент Джерси для вызовов REST из кода Java:

<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>2.22.1</version>
</dependency> 

В моем запросе GET,

javax.ws.rs.client.Invocation.Builder builder = ClientBuilder.newClient().target(url).request(); 
builder.get().readEntity(String.class);

клиент будет автоматически закрыт после звонка readEntity(String.class),

Если я использую,

builder.get(String.class);  

Я получаю такой же вывод.

Соединение закрывается автоматически, или мне нужно закрыть его вручную в этом случае?

1 ответ

Решение

Короткий ответ

Рассмотрим следующий код:

Client client = ClientBuilder.newClient();
String result = client.target(url).request().get(String.class);

Под капотом Джерси призывает Response#readEntity(Class<T>) если запрос был успешным, и соединение будет закрыто для вас. Таким образом, соединение в этом случае не нужно закрывать вручную.

Теперь рассмотрим следующий код:

Client client = ClientBuilder.newClient();
Response response = client.target(url).request().get();

Для этой ситуации вам нужно вызвать Response#close() закрыть соединение. Или вызвать Response#readEntity(Class<T>) чтобы Джерси закрыл для вас связь.

Длинный ответ

Как указано в документации, если вы не читаете объект, вам нужно закрыть ответ вручную, вызвав Response#close(),

Для более подробной информации, посмотрите документацию Джерси о том, как закрыть соединения:

5,7. Закрытие соединения

Базовые соединения открываются для каждого запроса и закрываются после получения ответа и обработки объекта (объект считывается). Смотрите следующий пример:

final WebTarget target = ... some web target
Response response = target.path("resource").request().get();
System.out.println("Connection is still open.");
System.out.println("string response: " + response.readEntity(String.class));
System.out.println("Now the connection is closed.");

Если вы не читаете объект, то вам нужно вручную закрыть ответ response.close(),

Также, если объект читается в InputStream (от response.readEntity(InputStream.class)), соединение остается открытым, пока вы не закончите чтение из InputStream, В этом случае InputStreamили Response должен быть закрыт вручную в конце чтения из InputStream,

Кроме того, посмотрите на JerseyInvocation источник. Наиболее важные части приведены ниже.

в translate(ClientResponse, RequestScope, Class<T>) метод, который вы увидите, что response.readEntity(Class<T>) вызывается.

JerseyInvocation.Builder#get(Class<T>)

Вызывать HTTP GET Метод для текущего запроса синхронно.

@Override
public <T> T get(final Class<T> responseType)
    throws ProcessingException, WebApplicationException {

    return method("GET", responseType);
}

JerseyInvocation.Builder#method(String, Class<T>)

Вызовите произвольный метод для текущего запроса синхронно.

@Override
public <T> T method(final String name, final Class<T> responseType)
    throws ProcessingException, WebApplicationException {

    // responseType null check omitted for brevity

    requestContext.setMethod(name);
    return new JerseyInvocation(this).invoke(responseType);
}

JerseyInvocation#invoke(Class<T>)

Синхронно вызвать запрос и получить ответ указанного типа обратно.

@Override
public <T> T invoke(final Class<T> responseType)
    throws ProcessingException, WebApplicationException {

    // responseType null check omitted for brevity

    final ClientRuntime runtime = request().getClientRuntime();
    final RequestScope requestScope = runtime.getRequestScope();

    return requestScope.runInScope(new Producer<T>() {

        @Override
        public T call() throws ProcessingException {

            try {

                return translate(runtime.invoke(requestForCall(requestContext)), 
                                 requestScope, responseType);

            } catch (final ProcessingException ex) {
                // Exception handling omitted for brevity
            }
        }
    });
}

JerseyInvocation#translate(ClientResponse, RequestScope, Class<T>)

Если запрос выполнен успешно, объект ответа читается как экземпляр указанного типа Java с использованием Response#readEntity(Class<T>):

private <T> T translate(final ClientResponse response, final RequestScope scope, 
    final Class<T> responseType) throws ProcessingException {

    if (responseType == Response.class) {
        return responseType.cast(new InboundJaxrsResponse(response, scope));
    }

    if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) {

        try {

            return response.readEntity(responseType);

        } catch (final ProcessingException ex) {
            // Exception handling omitted for brevity
        }

    } else {
        throw convertToException(new InboundJaxrsResponse(response, scope));
    }
}
Другие вопросы по тегам