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;
}
没有什么意义的参考:
- 偶现访问 qyapi.weixin.qq.com被拒绝的情况?
- how-to-fix-java-net-connectexception-connection-refused-connect-in-java