首页 > 代码库 > 解决Get content and status code from HttpResponse问题

解决Get content and status code from HttpResponse问题

在调用 apache的http处理jar包的时候,我们可能遇到过先判断返回的响应的状态是否正确,然后取值,这个时候就会在returnContent()的时候报异常

java.lang.IllegalStateException: Response content has been already consumed

	at org.apache.http.client.fluent.Response.assertNotConsumed(Response.java:56)
	at org.apache.http.client.fluent.Response.handleResponse(Response.java:88)
	at org.apache.http.client.fluent.Response.returnContent(Response.java:97)

 原因:

  在returnResponse()的finally中会把全局变量consumed置为true,returnContent()调用handleResponse中调用了dispose,dispose最后的finally中也将全局变量consumed置为true,而assertNotConsumed()是consumed为true就抛异常的,所以无论先调用哪一个都会出现异常。

    public HttpResponse returnResponse() throws IOException {
        assertNotConsumed();
        try {
            final HttpEntity entity = this.response.getEntity();
            if (entity != null) {
                final ByteArrayEntity byteArrayEntity = new ByteArrayEntity(
                        EntityUtils.toByteArray(entity));
                final ContentType contentType = ContentType.getOrDefault(entity);
                byteArrayEntity.setContentType(contentType.toString());
                this.response.setEntity(byteArrayEntity);
            }
            return this.response;
        } finally {
            this.consumed = true;
        }
    }
    public Content returnContent() throws ClientProtocolException, IOException {
        return handleResponse(new ContentResponseHandler());
    }

/**
     * Handles the response using the specified {@link ResponseHandler}
     */
    public <T> T handleResponse(
            final ResponseHandler<T> handler) throws ClientProtocolException, IOException {
        assertNotConsumed();
        try {
            return handler.handleResponse(this.response);
        } finally {
            dispose();
        }
    }

private void dispose() {
        if (this.consumed) {
            return;
        }
        try {
            final HttpEntity entity = this.response.getEntity();
            final InputStream content = entity.getContent();
            if (content != null) {
                content.close();
            }
        } catch (final Exception ignore) {
        } finally {
            this.consumed = true;
        }
    }
    private void assertNotConsumed() {
        if (this.consumed) {
            throw new IllegalStateException("Response content has been already consumed");
        }
    }

解决办法:

  在returnContent()中,先对Response的状态进行判断,状态值大于300的,会抛出对应的异常,然后调用EntityUtils.toString(entity)取值,所以可以先取HttpResponse,然后用

byte[] bytes = EntityUtils.toByteArray(httpResponse.getEntity());来取Content.
       public Content returnContent() throws ClientProtocolException, IOException {
        return handleResponse(new ContentResponseHandler());
    }
    public <T> T handleResponse(
            final ResponseHandler<T> handler) throws ClientProtocolException, IOException {
        assertNotConsumed();
        try {
            return handler.handleResponse(this.response);
        } finally {
            dispose();
        }
    }
    public T handleResponse(final HttpResponse response)
            throws HttpResponseException, IOException {
        final StatusLine statusLine = response.getStatusLine();
        final HttpEntity entity = response.getEntity();
        if (statusLine.getStatusCode() >= 300) {
            EntityUtils.consume(entity);
            throw new HttpResponseException(statusLine.getStatusCode(),
                    statusLine.getReasonPhrase());
        }
        return entity == null ? null : handleEntity(entity);
    }

 @Override
    public String handleEntity(final HttpEntity entity) throws IOException {
        return EntityUtils.toString(entity);
    }

 

解决Get content and status code from HttpResponse问题