Java 关闭JAX-RS客户机/响应
不清楚是否必须关闭JAX RS客户机/响应实例。如果我必须,总是还是不 根据有关客户端类的信息: 调用此方法将有效地使所有资源目标无效 由客户端实例生成 WebTarget类没有任何invalidate()/close()方法,但响应类有。 根据: 关闭底层消息实体输入流(如果可用,并且 打开)以及释放与 响应(例如,缓冲消息实体数据) 。。。close()方法 应在包含未使用实体的所有实例上调用 输入流,以确保与实例关联的资源 正确清理并防止潜在的内存泄漏。这是 典型的客户端场景,其中应用程序层代码 仅处理响应头并忽略响应实体 最后一段我不清楚。“未使用的实体输入流”是什么意思?如果我从响应中获得InputSteam或字符串,我是否应该显式关闭响应 我们可以在不访问响应实例的情况下获得响应结果:Java 关闭JAX-RS客户机/响应,java,memory-leaks,jax-rs,Java,Memory Leaks,Jax Rs,不清楚是否必须关闭JAX RS客户机/响应实例。如果我必须,总是还是不 根据有关客户端类的信息: 调用此方法将有效地使所有资源目标无效 由客户端实例生成 WebTarget类没有任何invalidate()/close()方法,但响应类有。 根据: 关闭底层消息实体输入流(如果可用,并且 打开)以及释放与 响应(例如,缓冲消息实体数据) 。。。close()方法 应在包含未使用实体的所有实例上调用 输入流,以确保与实例关联的资源 正确清理并防止潜在的内存泄漏。这是 典型的客户端场景,其中应用程序
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,或者您正在处理响应结果,那个么应该这样做
是的,我也发现在很多方面都严重缺乏文档。例如,线程安全,以及“快捷方式”方法是否实际关闭响应。例如
/**
* 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();
}
}