【问题标题】:java.io.IOException: Attempted read from closed streamjava.io.IOException:尝试从关闭的流中读取
【发布时间】:2013-09-05 12:14:39
【问题描述】:

我正在使用 Apache HTTP 客户端进行 HTTPPost 调用,然后我尝试使用 Jackson 从响应中创建一个对象。 这是我的代码:

private static final Logger log = Logger.getLogger(ReportingAPICall.class);
ObjectMapper mapper = new ObjectMapper();

public void makePublisherApiCall(String jsonRequest)
{
    String url = ReaderUtility.readPropertyFile().getProperty("hosturl");
    DefaultHttpClient client = new DefaultHttpClient();
    try {
        HttpPost postRequest = new HttpPost(url);
        StringEntity entity = new StringEntity(jsonRequest);
        postRequest.addHeader("content-type", "application/json");
        log.info("pub id :"+ExcelReader.publisherId);
        postRequest.addHeader("accountId", ExcelReader.publisherId);
        postRequest.setEntity(entity);
        HttpResponse postResponse = client.execute(postRequest);
        log.info(EntityUtils.toString(postResponse.getEntity()));

    //  Response<PublisherReportResponse> response = mapper.readValue(postResponse.getEntity().getContent(), Response.class);
    //  log.info("Reponse "+response.toString());
    } catch (UnsupportedEncodingException ex) {
        log.error(ex.getMessage());
        log.error(ex);
        Assert.assertTrue(false, "Exception : UnsupportedEncodingException");
    } catch (ClientProtocolException ex) {
        log.error(ex.getMessage());
        log.error(ex);
        Assert.assertTrue(false, "Exception : ClientProtocolException");
    } catch (IOException ex) {
        log.error(ex.getMessage());
        log.error(ex);
        Assert.assertTrue(false, "Exception : IOException");
    }

方法 makePublisherApiCall() 将在一个循环中调用,该循环运行 100 次。 当我取消注释该行时基本上会出现问题:

//  Response<PublisherReportResponse> response = mapper.readValue(postResponse.getEntity().getContent(), Response.class);
//  log.info("Reponse "+response.toString());

取消注释后出现异常:

Attempted read from closed stream.
17:26:59,384 ERROR com.inmobi.reporting.automation.reportingmanager.ReportingAPICall - java.io.IOException: Attempted read from closed stream.

否则它工作正常。 有人可以让我知道我做错了什么。

【问题讨论】:

    标签: java jackson apache-httpclient-4.x


    【解决方案1】:

    EntityUtils.toString(postResponse.getEntity()) 对响应实体有什么作用?我怀疑它正在消耗实体的内容流。 HttpClient javadoc 声明,只有可重复的实体才能被多次使用。因此,如果实体不可重复,则无法再次将内容流提供给映射器。为避免这种情况,您应该只让映射器使用流 - 如果需要记录内容,请记录已解析的 Response 对象。

    【讨论】:

    • 但我认为这 2 行引起了问题。 // Response response = mapper.readValue(postResponse.getEntity().getContent(), Response.class); // log.info("响应"+response.toString());在评论这些程序后工作正常。
    • 是的。如果我是正确的,那么问题是您只能一次 使用实体的内容。我怀疑您通过日志记录和解析执行了两次。如果您想检查我的怀疑是否正确,请将log.info(EntityUtils.toString(postResponse.getEntity())); 注释掉并取消注释以下两行,然后再次检查它是否有效。
    【解决方案2】:

    我在这里找到了与 Spring RestTemplate 类似问题的答案:https://www.baeldung.com/spring-rest-template-interceptor

    如果我们希望我们的拦截器充当请求/响应记录器,那么我们需要读取它两次——第一次由拦截器读取,第二次由客户端读取。 默认实现只允许我们读取一次响应流。为了满足这样的特定场景,Spring 提供了一个特殊的类,称为 BufferingClientHttpRequestFactory。顾名思义,这个类会将请求/响应缓存在 JVM 内存中以供多次使用。

    下面是使用 BufferingClientHttpRequestFactory 初始化 RestTemplate 对象以启用请求/响应流缓存的方法:

    RestTemplate restTemplate = new RestTemplate( new BufferingClientHttpRequestFactory( new SimpleClientHttpRequestFactory() ) );
    

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题。确保您没有在 IDE 的“watch”或“inspect”部分使用实体的内容流。它在消耗(读取)后关闭。

      对不起我的英语。

      【讨论】:

      • 这给我带来了问题,我想知道为什么即使在第一次耗时时它也会抛出这个异常。然后我意识到我在变量手表中添加了“httpResponse.getEntity()”。感谢你的回答。这节省了我很多时间。
      【解决方案4】:

      我遇到了同样的问题。

      这个想法是,如果你使用 postResponse,那么你应该把它放在一个变量中,以便在不同的地方再次使用它。 否则,连接将关闭,您将无法再使用相同的响应。

      我曾经记录它(用于调试目的)并且总是失败。

      【讨论】:

        【解决方案5】:

        我遇到了同样的问题。

        就我而言,我需要通过AOP/获取响应内容

        【讨论】:

        • 欢迎来到 Stack Overflow。如果您详细说明您的答案我需要通过 AOP/ 进一步获取响应内容并提供更多详细信息,那就更好了。另请注意,您正在回答一个旧的且已回答的问题(带有绿色复选标记的答案),而您当前的答案更多的是评论而不是答案。 (Stack Overflow 的 Q/A 格式不适用于论坛式的讨论)。 – 请阅读How do I write a good answer? 并使用tour 了解 Stack Overflow 的工作原理。
        【解决方案6】:

        就我而言,这个问题与另一个原因有关, 我遇到这个问题是因为我没有使用

        closeableresponce=client.Getmethod(FinalUrl);

        在我的第一个 Test1 中,有人提到过,但是当我在 Test2 中错过时,我忘记输入此代码,这就是为什么流关闭消息显示...

        public void getapiwithheader() throws ParseException, IOException
        {
            client = new RestClient();
            closeableresponce=client.Getmethod(FinalUrl);
        
            HashMap<String, String> headermap = new HashMap<>();
            headermap.put("content-type", "application/json");
            //****************************************************************************    
            //Status code
            //****************************************************************************      
            int statuscode =closeableresponce.getStatusLine().getStatusCode();
            System.out.println("Status code "+statuscode);
            Assert.assertEquals(statuscode,RESPONSE_STATUS_CODE_200, "Status code is not 200");
        
        
            //****************************************************************************  
            // Json String
            //****************************************************************************      
            String responsestring=  EntityUtils.toString(closeableresponce.getEntity(),"UTF-8");
            JSONObject respjsonobj = new JSONObject(responsestring);
            System.out.println("Respose Json API"+respjsonobj);
        
            //****************************************************************************      
            // Verify the value of the JSON
            //****************************************************************************      
            String Email =TestUtil.getValueByJPath(respjsonobj,"/email");
            System.out.println("******************************************");
            System.out.println("Print the value of Email "+Email);
            Assert.assertEquals(Email, "johndoe@google.com");
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-02
          相关资源
          最近更新 更多