httpClient笔记

勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

导读:本篇文章讲解 httpClient笔记,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

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;
}

没有什么意义的参考:

参考

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/142251.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!