前言
最近項目中涉及端對端接口的調用,由於實時性要求不是很高和一些其他原因,採用了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的兩個字段,可能是,抽空要再驗證下。
總結
感謝您的耐心閱讀,希望對您有些幫助!