Java 关闭JAX-RS客户机/响应

Java 关闭JAX-RS客户机/响应,java,memory-leaks,jax-rs,Java,Memory Leaks,Jax Rs,不清楚是否必须关闭JAX RS客户机/响应实例。如果我必须,总是还是不 根据有关客户端类的信息: 调用此方法将有效地使所有资源目标无效 由客户端实例生成 WebTarget类没有任何invalidate()/close()方法,但响应类有。 根据: 关闭底层消息实体输入流(如果可用,并且 打开)以及释放与 响应(例如,缓冲消息实体数据) 。。。close()方法 应在包含未使用实体的所有实例上调用 输入流,以确保与实例关联的资源 正确清理并防止潜在的内存泄漏。这是 典型的客户端场景,其中应用程序

不清楚是否必须关闭JAX RS客户机/响应实例。如果我必须,总是还是不

根据有关客户端类的信息:

调用此方法将有效地使所有资源目标无效 由客户端实例生成

WebTarget类没有任何invalidate()/close()方法,但响应类有。 根据:

关闭底层消息实体输入流(如果可用,并且 打开)以及释放与 响应(例如,缓冲消息实体数据)

。。。close()方法 应在包含未使用实体的所有实例上调用 输入流,以确保与实例关联的资源 正确清理并防止潜在的内存泄漏。这是 典型的客户端场景,其中应用程序层代码 仅处理响应头并忽略响应实体

最后一段我不清楚。“未使用的实体输入流”是什么意思?如果我从响应中获得InputSteam或字符串,我是否应该显式关闭响应

我们可以在不访问响应实例的情况下获得响应结果:

Client client = ...;
WebTarget webTarget = ...;
Invocation.Builder builder = webTarget.request(MediaType.APPLICATION_JSON_TYPE);
Invocation invocation = builder.buildGet();
InputStream reso = invocation.invoke(InputStream.class);
我正在使用RESTeasy实现,我希望响应将在RESTeasy实现中关闭,但我找不到它。谁能告诉我为什么? 我知道
但即使知道,也会使用响应,而不关闭它。

根据文档,响应是幂等的

此操作是幂等的,也就是说,可以多次调用它,但效果相同,这也意味着对已关闭的消息实例调用close()方法是合法的,并且没有进一步的效果

因此,您可以自己安全地关闭
InputStream
,并且应该这样做

也就是说,我style wise不会执行
invocation.invoke(InputStream.class)
,因为
invoker(class)
用于执行实体转换。相反,如果您想要InputStream,您可能只需要调用
invocation.invoke()
并直接处理
响应
对象,因为在读取流之前您可能需要一些头信息。 处理响应
InputStream
时需要标题的原因很典型,因为您不关心主体,或者主体需要特殊的处理和大小考虑,这正是文档所指的(例如,
HEAD
对ping服务器的请求)

另见

从该方法返回的消息实例将被缓存,以便通过getEntity()进行后续检索。除非提供的实体类型是输入流,否则此方法会自动关闭未使用的原始响应实体数据流(如果打开)。如果实体数据已被缓冲,则将在使用缓冲数据之前重置缓冲区,以便在此响应上启用readEntity(…)方法的后续调用


因此,如果您选择的不是
InputStream
,您就不必关闭
响应
(但不管它作为幂等元是否安全)。

查看
resteasy客户端
源代码,
调用#调用(类)
只是调用
调用#调用()
和调用
调用#提取结果(GenericType responseType,Response Response,Annotation[]annotations)
响应中提取结果

@Override
public <T> T invoke(Class<T> responseType)
{
   Response response = invoke();
   if (Response.class.equals(responseType)) return (T)response;
   return extractResult(new GenericType<T>(responseType), response, null);
}
简而言之:调用close()或使用closeable with try with resources语句

  • 如果使用JAX-RS客户机引用,则在客户机上调用close()将关闭打开的套接字
  • 调用close-on-Response会释放连接,但不会释放任何打开的套接字
  • 无需调用close(),因为Resteasy将在封盖下释放连接。但若结果是一个InputStream,或者您正在处理响应结果,那个么应该这样做
资源/参考:

根据,应该对响应引用调用close()。 在第47.3节末尾,它指出

Resteasy将释放盖下的连接。唯一的 反例是指响应是 InputStream,必须显式关闭

另一方面,如果调用的结果是 响应,然后是响应。close()方法必须用于释放 连接

您可能应该在try/finally块中执行此操作。再一次, 释放连接只会使其可用于其他用途。信息技术 通常不关闭插座

请注意,如果ApacheHttpClient4Engine创建了自己的 HttpClient,无需等待finalize()关闭 插座。ClientHttpEngine接口对此有一个close()方法 目的

最后,如果您的javax.ws.rs.client.client类创建了 引擎自动为您启动,您应该呼叫客户端。关闭(),然后 这将清理所有插座连接


是的,我也发现在很多方面都严重缺乏文档。例如,线程安全,以及“快捷方式”方法是否实际关闭响应。例如
/**
 * Extracts result from response throwing an appropriate exception if not a successful response.
 *
 * @param responseType
 * @param response
 * @param annotations
 * @param <T>
 * @return
 */
public static <T> T extractResult(GenericType<T> responseType, Response response, Annotation[] annotations)
{
   int status = response.getStatus();
   if (status >= 200 && status < 300)
   {
      try
      {
         if (response.getMediaType() == null)
         {
            return null;
         }
         else
         {
            T rtn = response.readEntity(responseType, annotations);
            if (InputStream.class.isInstance(rtn)
                 || Reader.class.isInstance(rtn))
            {
               if (response instanceof ClientResponse)
               {
                  ClientResponse clientResponse = (ClientResponse)response;
                  clientResponse.noReleaseConnection();
               }
            }
            return rtn;

         }
      }
      catch (WebApplicationException wae)
      {
         try
         {
            response.close();
         }
         catch (Exception e)
         {

         }
         throw wae;
      }
      catch (Throwable throwable)
      {
         try
         {
            response.close();
         }
         catch (Exception e)
         {

         }
         throw new ResponseProcessingException(response, throwable);
      }
      finally
      {
         if (response.getMediaType() == null) response.close();
      }
   }
   try
   {
      // Buffer the entity for any exception thrown as the response may have any entity the user wants
      // We don't want to leave the connection open though.
      String s = String.class.cast(response.getHeaders().getFirst("resteasy.buffer.exception.entity"));
      if (s == null || Boolean.parseBoolean(s))
      {
         response.bufferEntity();
      }
      else
      {
         // close connection
         if (response instanceof ClientResponse)
         {
            try
            {
               ClientResponse.class.cast(response).releaseConnection();
            }
            catch (IOException e)
            {
               // Ignore
            }
         }
      }
      if (status >= 300 && status < 400) throw new RedirectionException(response);

      return handleErrorStatus(response);
   }
   finally
   {
      // close if no content
      if (response.getMediaType() == null) response.close();
   }

}