org.apache.http.NoHttpResponseException: 目标服务地址 failed to respond
在使用Httpclient去使用get请求去调用其他服务的时候出的这个错,但是我直接使用浏览器访问是可以正常返回结果的,百度了很多都是说的传输层的tcp协议问题,在四次挥手的时候服务端已经主动断开连接了,客户端持有无效的连接去访问服务端,造成无响应,建议的是增加重试机制,我试了,没用!!!
原来的工具类:说一下这里传进来的uri是完整的url,例如https://blog.csdn.net?name==xx&age=xx
/**
* 使用GET 方法发起http请求
*
* @param uri
* @return
* @throws IOException
*/
public static String get(String uri) throws IOException {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//创建客户端的时候设置默认的重试机制
// DefaultHttpRequestRetryHandler的构造方法会默认重试3次,也可自己指定
HttpClient httpClient = httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler()).build();
HttpGet httpGet = new HttpGet(uri);
/**
* 设置超时,设置请求和传输超时时间
*/
RequestConfig requestConfig = RequestConfig.custom().setRedirectsEnabled(true).setSocketTimeout(5000).setConnectTimeout(5000).build();
httpGet.setConfig(requestConfig);
HttpResponse response = null;
response = httpClient.execute(httpGet);
int code = response.getStatusLine().getStatusCode();
if (code != 200) {
log.warn("请求错误 错误码 {}", code);
}
return getContent(response.getEntity().getContent());
}
private static String getContent(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int i = -1;
while ((i = is.read()) != -1) {
baos.write(i);
}
is.close();
return ba
后面又想到get请求是不是参数不能这么放所以使用
// 定义请求的参数
URI uri1 = new URIBuilder("http://www.baidu.com/s").setParameter("name", "xx").build();
这个并没有尝试,不过个人觉得不是这个问题,最终也是创建出一个URL对象知识不用手动的去拼接
看了很多博客感觉都没说到点子上,后来看别人的工具类好像有个关流的操作,我的工具类里面并没有!!!,又想起之前的tcp协议是基于流的,有可能在返回数据的时候流出现了问题,但是httpclient对象没用close方法啊,看了一下这竟然是个接口,之前一直以为是类
又想了一下那些文章说的四次挥手,那么我有可能就是没关流导致的连接问题,找到问题了!!!
httpclient创建方式有很多种,和使用的版本有关系差别不大,刚开始蒙圈了,其实好像没什么区别,写出来大家看一下
创建HttpClient对象
3.X:
HttpClient httpClient = new DefaultHttpClient();
4.3:
CloseableHttpClient httpClient = HttpClients.createDefault();
这个好像是4.3之后的版本
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
HttpClient httpClient = httpClientBuilder.build();
我使用的是最后一种,查看了build()方法之后发现他返回的对象其实是一个CloseableHttpClient,可关闭的HttpClient,只不过用的接口接收,使用的多态,ok,现在明白了,只需要用实现类接收就可以调用close()方法了,不过需要注意关流需要在finally里面
现在代码:
public static String get1(String uri) throws IOException {
// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 创建Get请求
HttpGet httpGet = new HttpGet(uri);
// 响应模型
CloseableHttpResponse response = null;
// 配置信息
RequestConfig requestConfig = RequestConfig.custom()
// 设置连接超时时间(单位毫秒)
.setConnectTimeout(5000)
// 设置请求超时时间(单位毫秒)
.setConnectionRequestTimeout(5000)
// socket读写超时时间(单位毫秒)
.setSocketTimeout(5000)
// 设置是否允许重定向(默认为true)
.setRedirectsEnabled(true).build();
// 将上面的配置信息 运用到这个Get请求里
httpGet.setConfig(requestConfig);
String data = null;
try {
// 由客户端执行(发送)Get请求
response = httpClient.execute(httpGet);
// 从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
if (response.getStatusLine()== 200) {
data = EntityUtils.toString(responseEntity);
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + data);
}
} catch (
ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 释放资源
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return data;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
return data;
}
问题解决!!!