22

我正在使用 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.

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

4

6 回答 6

51

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

于 2013-09-05T12:31:53.117 回答
11

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

对不起我的英语。

于 2017-01-03T20:29:54.307 回答
9

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

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

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

RestTemplate restTemplate = new RestTemplate( new BufferingClientHttpRequestFactory( new SimpleClientHttpRequestFactory() ) );
于 2020-08-07T10:17:18.713 回答
2

我有同样的问题。

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

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

于 2015-09-22T13:11:17.397 回答
0

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

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");
}
于 2018-08-08T11:57:09.323 回答
-1

我有同样的问题。

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

于 2020-08-30T06:26:15.797 回答