前言
最近项目中涉及端对端接口的调用,由于实时性要求不是很高和一些其他原因,采用了http协议的方式,使用HttpClient类来完成接口的调用,出现了一个非常奇怪的“fail to Respond”的问题。
正文
问题出现场景描述
本次采用的httpClient 类在之前项目中使用过,post 和 get 方法是可以完成顺利的接口调用的,本次调用的接口,用postman 调用是可以顺利调通的,但是在程序中用httpClient调用出现的问题却显得莫名其妙;
Postman 测试接口:显示调用正常
程序中调用部分代码:
Gson gson = new Gson();
// 设置接口参数
EntranceRecordCommand cmd =
EntranceRecordCloudCommand.builder().device_id(deviceId).data(cmdList).build();
String jsonParam = JSON.toJSONString(cmd);
log.info("Param-{}", jsonParam);
String result = null;
try {
// 接口调用
result = HttpUtils.doPost( "http://10.18.132.87:8090/report/temperature?key=x5bY2tM&signature=ng8h3prl0va9q",
jsonParam,
"utf-8");
log.info("result--{}",result);
} catch (Exception e) {
log.error("invoke exception!");
}
HttpUtils中部分代码:
public static String doPost(String url, String jsonStr, String charset) {
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try {
httpClient = acceptsUntrustedCertsHttpClient();
httpPost = new HttpPost(url);
StringEntity entity = new StringEntity(jsonStr);
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
if (response != null) {
HttpEntity resEntity = response.getEntity();
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
log.error("invoke fail");
return "";
}
if (resEntity != null) {
result = EntityUtils.toString(resEntity, charset);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return result;
}
Idea中控制台信息
httpclient org.apache.http.NoHttpResponseException: 10.18.132.87:8090 failed to respond
问题解决
尝试一
一开始还以为是传输的json 参数的问题,换用了fastjson 这一 Json对象转换工具类,发现还是同样的问题;
尝试二
百度了一下,好多文章都在说连接失效问题,是要调大超时时间,发现我这情况并不同,我这里就一个http 链接,而且还没有到默认超时时间,所以这个行不通;
尝试三
改了下httpClient类中doPost方法的一个参数,问题解决!
public static String doPost(String url, String jsonStr, String charset) {
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try {
httpClient = acceptsUntrustedCertsHttpClient();
httpPost = new HttpPost(url);
// 原来代码
StringEntity entity = new StringEntity(jsonStr);
// 修改后代码,加了一个ContentType.APPLICATION_JSON
StringEntity entity = new StringEntity(jsonStr, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
……
原因分析
因为doPost方法中第二个参数为接口需要的参数,是String 类型,而ContentType.APPLICATION_JSON 表明要发送到服务端的数据流主体是序列化的JSON字符串,所以要加一个contentType; 至于之前的为什么可以,我猜可能是跟这个接口有关,这个接口url 后面拼了requestParam的两个字段,可能是,抽空要再验证下。
总结
感谢您的耐心阅读,希望对您有些帮助!