httpClient笔记

NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity

报错信息:org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity
解决方案:

public static InputStream getAsStream(String url) {
    try (CloseableHttpClient client = HttpClients.createDefault();
         CloseableHttpResponse response = client.execute(new HttpGet(url))) {
        HttpEntity httpEntity = response.getEntity();
        // 包装一层解决
        BufferedHttpEntity bhe = new BufferedHttpEntity(httpEntity);
        return bhe.getContent();
    } catch (IOException e) {
        LOGGER.error("doGet failed: " + e.getMessage());
    }
    return null;
}

参考:
stackoverflow

Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.

使用HttpClient,大量报出Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended的WARN日志,定位到HttpClient的源码如下:

public abstract class HttpMethodBase implements HttpMethod {
    public byte[] getResponseBody() throws IOException {
        if (responseBody == null) {
            InputStream instream = getResponseBodyAsStream();
            if (instream != null) {
                long contentLength = getResponseContentLength();
                if (contentLength > 2147483647L) {
                    throw new IOException("Content too large to be buffered: " + contentLength + " bytes");
                }
                int limit = getParams().getIntParameter("http.method.response.buffer.warnlimit", 1048576);
                if (contentLength == -1L || contentLength > (long) limit) {
                    LOG.warn("Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.");
                }
                LOG.debug("Buffering response body");
                ByteArrayOutputStream outstream = new ByteArrayOutputStream(contentLength <= 0L ? 4096: (int) contentLength);
                byte buffer[] = new byte[4096];
                int len;
                while ((len = instream.read(buffer)) > 0) {
                	outstream.write(buffer, 0, len);
                }
                outstream.close();
                setResponseStream(null);
                responseBody = outstream.toByteArray();
            }
        }
        return responseBody;
    }
}

报WARN的条件(contentLength == -1) || (contentLength > limit),即返回的HTTP头没有指定contentLength,或contentLength大于上限(默认1M)。如果能确定返回结果的大小对程序没有显著影响,这个WARN就可以忽略,可在日志配置中把HttpClient的日志级别调到ERROR。

不过这都是忽略潜在的问题,并没有解决问题。

HttpClient建议使用InputStream getResponseBodyAsStream()代替byte[] getResponseBody()。对于返回结果很大或无法预知的情况,使用InputStreamgetResponseBodyAsStream(),避免byte[] getResponseBody()可能带来的内存耗尽问题

解决方案,将stream转化为string:

private String convert(InputStream inputStream) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
    StringBuilder sb = new StringBuilder();
    String str;
    while ((str = br.readLine()) != null) {
        sb.append(str);
    }
    return sb.toString();
}

ConnectException: Connection refused

使用企业微信推送消息时遇到的问题,具体的报错信息:

java.lang.Exception: org.apache.http.conn.HttpHostConnectException: Connect to qyapi.weixin.qq.com:443 [qyapi.weixin.qq.com/81.69.87.29, qyapi.weixin.qq.com/81.69.54.213] failed: Connection refused
    报错行
	at com.xy.cloudiview.common.util.HttpUtil.doGet(HttpUtil.java:49)
	at com.xy.cloudiview.common.util.SendWeChatUtil.getToken(SendWeChatUtil.java:193)
	at com.xy.cloudiview.common.util.SendWeChatUtil.sendWeChat(SendWeChatUtil.java:57)
	at com.xy.cloudiview.datasetsubscript.business.service.impl.TableWarnServiceImpl.sendWeChat(TableWarnServiceImpl.java:330)
	at com.xy.cloudiview.datasetsubscript.business.service.impl.TableWarnServiceImpl.sendMsg(TableWarnServiceImpl.java:417)
	at com.xy.cloudiview.datasetsubscript.business.service.impl.TableWarnServiceImpl.executeTableWarnJob(TableWarnServiceImpl.java:99)
	at com.xy.cloudiview.datasetsubscript.business.xxljob.IviewTableWarnJobHandler.execute(IviewTableWarnJobHandler.java:45)
	at com.ppdai.job.core.thread.JobThread.run(JobThread.java:142)
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to qyapi.weixin.qq.com:443 [qyapi.weixin.qq.com/81.69.87.29, qyapi.weixin.qq.com/81.69.54.213] failed: Connection refused
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:156)
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
	at com.xy.cloudiview.common.util.HttpUtil.doGet(HttpUtil.java:39)
	... 7 common frames omitted
Caused by: java.net.ConnectException: Connection refused
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:368)
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
	... 17 common frames omitted

HttpUtil.doGet方法定义:

public static String doGet(String url) throws Exception {
    // 创建Httpclient对象
    CloseableHttpClient httpclient = HttpClients.createDefault();
    // 创建http GET请求
    HttpGet httpGet = new HttpGet(url);
    CloseableHttpResponse response = null;
    String content = "";
    try {
        // 执行请求
        response = httpclient.execute(httpGet);
        // 判断返回状态是否为200
        if (response.getStatusLine().getStatusCode() == 200) {
            //请求体内容
            content = EntityUtils.toString(response.getEntity(), "UTF-8");
        } else {
            log.error("doget error, url:{}, return code:{}", url,
                    response.getStatusLine().getStatusCode());
        }
    } catch (Exception e) {
    	// 报错行
        throw new Exception(e);
    } finally {
        if (response != null) {
            response.close();
        }
        //相当于关闭浏览器
        httpclient.close();
    }
    return content;
}

没有什么意义的参考:

参考

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

johnny233

晚饭能不能加鸡腿就靠你了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值