【问题标题】:JERSEY : Error Trace : java.lang.IllegalStateException: Entity input stream has already been closedJERSEY:错误跟踪:java.lang.IllegalStateException:实体输入流已关闭
【发布时间】:2018-01-17 01:08:19
【问题描述】:

我正在使用 Jersey 2.x。

下面是我的控制器

@GET
@Path("{id}")
@Produces("application/json")
public Response getUser(@PathParam("id") int userId, @Context ContainerRequestContext containerRequestContext) {


        ContainerRequestContext requestContext = logRequest(containerRequestContext);

        //To further operations using requestContext

}

以下是我在同一个控制器类中记录请求的方法

private ContainerRequestContext logRequest(ContainerRequestContext requestContext) {

        JSONObject requestData = new JSONObject();
        try {

            Map bm = null;
            ContainerRequest cr = (ContainerRequest) requestContext;

            cr.bufferEntity();

            bm = cr.readEntity(Map.class);

            if (!String.valueOf(bm).equalsIgnoreCase("null")) {
                requestData.put("parameters", bm.toString());
            }

            requestData.put("uri", requestContext.getUriInfo().getRequestUri());
            requestData.put("ClientIp", requestContext.getProperty("requesterIp"));
            requestContext.setProperty("requestData", requestData);

        } catch (IOException | NumberFormatException | ProcessingException ex) {
            //Logging

        } catch (Exception ex) {
            //Logging
        }
        return requestContext;
    }

如您所见,我使用bufferEntity() 多次读取ContainerRequestContext。

当我在我的服务器上部署我的 API 时。

我正面临这个错误:

Error Trace : java.lang.IllegalStateException: Entity input stream has already been closed.

我在这里做错了什么。 如果有人可以向我解释这种行为,我将不胜感激。

【问题讨论】:

  • 可能是因为 Jersey 在调用资源方法之前读取了流。您可能想考虑改用 Filter,它在资源方法之前调用。
  • 可能是因为 Jersey 在调用资源方法之前读取了流。先生,您能否再解释一下,我想了解这种行为,您是绝对正确的,之前我在过滤器中使用了这种方法,我没有遇到这个问题。在我的新项目中,我将这部分代码移到了我的控制器级别。
  • 因为 Jersey 在调用你的资源方法之前,需要先读取流,以便在调用时将实体传递给你的方法。即使您没有实体参数,Jersey 似乎仍在读取流。
  • 另外,您正在使用 GET。这个请求还有正文吗?
  • 先生,我在所有方法 GET ,PUT,POST 中都遇到了这个异常。

标签: java jersey-2.0


【解决方案1】:

我也有类似的要求,我解决此问题的方法是在 Apache Commons 的 IOUtils 的帮助下“克隆”请求实体,如下面的代码 sn-p:

//--- Create a new InputStream with the original entity ---//
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(requestContext.getEntityStream(), baos);
InputStream originalEntity = new ByteArrayInputStream(baos.toByteArray()));

//--- Reasign the original entity to Request Context ---//
requestContext.setEntityStream(new ByteArrayInputStream(baos.toByteArray()));

//--- From this point onwards, you can do whatever you want with the original request entity ---//

. . .

//--- In my case, I am working with JsonObject as below (try/catch ommited for brevity) ---//
JsonReader jsonReader = Json.createReader(originalEntity);
JsonObject requestEntity = jsonReader.readObject();

. . .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 2022-12-12
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多