【问题标题】:Closing connection in GET request using Jersey Client 2.22.1使用 Jersey Client 2.22.1 关闭 GET 请求中的连接
【发布时间】:2016-02-08 08:52:31
【问题描述】:

我正在使用 Jersey 客户端从 Java 代码进行 REST 调用:

<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);  

我得到相同的输出。

这种情况下连接是自动关闭还是我需要手动关闭?

【问题讨论】:

    标签: jersey jersey-2.0 jersey-client


    【解决方案1】:

    简答

    考虑以下代码:

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

    在后台,如果请求成功,Jersey 会调用Response#readEntity(Class&lt;T&gt;),并且将为您关闭连接。 所以这种情况下不需要手动关闭连接。

    现在考虑以下代码:

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

    对于这种情况,您需要调用Response#close() 来关闭连接。或者调用 Response#readEntity(Class&lt;T&gt;) 让 Jersey 为你关闭连接。

    长答案

    documentation 中所述,如果您不使用read the entity,则需要通过调用Response#close() 手动关闭响应。

    更多详情,请查看 Jersey 的 documentation 关于如何关闭连接:

    5.7. Closing connections

    为每个请求打开和关闭底层连接 收到响应并处理实体后(实体为 读)。请参见以下示例:

    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 的阅读。 在这种情况下,InputStreamResponse 应该关闭 在阅读结束时手动从InputStream 读取。

    另外,看看JerseyInvocation source。下面引用了最重要的部分。

    translate(ClientResponse, RequestScope, Class&lt;T&gt;) 方法中,您会看到response.readEntity(Class&lt;T&gt;) 被调用。

    JerseyInvocation.Builder#get(Class&lt;T&gt;)

    为当前请求同步调用 HTTP GET 方法。

    @Override
    public <T> T get(final Class<T> responseType)
        throws ProcessingException, WebApplicationException {
    
        return method("GET", responseType);
    }
    

    JerseyInvocation.Builder#method(String, Class&lt;T&gt;)

    为当前请求同步调用任意方法。

    @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&lt;T&gt;)

    同步调用请求并接收回指定类型的响应。

    @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&lt;T&gt;)

    如果请求成功,则使用Response#readEntity(Class&lt;T&gt;)将响应实体作为指定Java类型的实例读取:

    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));
        }
    }
    

    【讨论】:

    • 我知道在我的问题中提到的readEntity() 之后连接将被关闭。我要Builder.get(String.class)
    • 你应该修改你的答案,因为当前的答案不能满足需要。
    猜你喜欢
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 2014-08-31
    • 2016-11-21
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    • 2014-09-27
    相关资源
    最近更新 更多