import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import net.sf.json.JSONObject;
import java.nio.charset.Charset;
import java.util.UUID;
public class HttpClientUtil {
public static boolean httpPostWithJson(JSONObject jsonObj, String url, String appId) {
HttpPost post = null;
try {
HttpClient httpClient = new DefaultHttpClient();
// 1. 設置連接/讀取超時(毫秒)
httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 2000);
httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 2000);
post = new HttpPost(url);
// 2. 構造請求頭
post.setHeader("Content-type", "application/json; charset=utf-8");
post.setHeader("Connection", "Close");
post.setHeader("SessionId", generateSessionId());
post.setHeader("appid", appId);
// 3. 構建 JSON 請求體
StringEntity entity = new StringEntity(jsonObj.toString(), Charset.forName("UTF-8"));
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
post.setEntity(entity);
// 4. 執行請求
HttpResponse response = httpClient.execute(post);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
logError("HTTP 錯誤狀態碼: " + statusCode);
return false;
}
// 5. 解析響應頭業務碼
int retCode = 0;
String sessionId = "";
for (Header header : response.getAllHeaders()) {
if ("retcode".equals(header.getName()))
retCode = Integer.parseInt(header.getValue());
if ("SessionId".equals(header.getName()))
sessionId = header.getValue();
}
if (retCode != ErrorCodeHelper.IAS_SUCCESS) {
logError("業務錯誤碼: " + retCode + ", SessionId: " + sessionId);
return false;
}
return true;
} catch (Exception e) {
logError("請求異常: " + e.getMessage());
return false;
} finally {
// 6. 釋放連接資源
if (post != null) {
try {
post.releaseConnection();
Thread.sleep(500); // 避免連接過於頻繁
} catch (InterruptedException ignored) {}
}
}
}
// 生成簡短 SessionId
private static String generateSessionId() {
UUID uuid = UUID.randomUUID();
String s = uuid.toString();
return s.substring(0,8) + s.substring(9,13) + s.substring(14,18) + s.substring(19,23) + s.substring(24);
}
}
CONNECTION_TIMEOUT:建立 TCP 連接的最長等待時間SO_TIMEOUT:讀取數據(Socket read)的最長等待時間Charset.forName("UTF-8") 避免中文亂碼Content-Type 和 Content-EncodingStringEntity 而非 ByteArrayEntity,自動處理編碼許多內部 RPC 協議將業務狀態碼放在 Header 中(如 retcode、SessionId),而非 Body,需遍歷 response.getAllHeaders() 獲取。
java.lang.NoSuchFieldError: INSTANCE
at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<clinit>(...)
lib 目錄下的 JAR(如 httpclient-4.2.5.jar)httpclient-4.4.1.jar)被忽略INSTANCE 在 4.2.5 中不存在pom.xml 依賴降級/升級至 Hadoop 環境一致版本(如 4.2.5)maven-shade-plugin 將依賴重定向到私有包名,避免衝突
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.5</version> <!-- 與 Hadoop 環境一致 -->
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.2.5</version>
</dependency>
| 項目 | 4.x (Legacy) | 5.x (Modern) |
|---|---|---|
| 客戶端創建 | new DefaultHttpClient() | HttpClients.createDefault() |
| 請求構建 | new HttpPost(url) | HttpPost.METHOD_NAME, URI.create(url) |
| 執行方式 | client.execute(request) | client.execute(request, responseHandler) |
| 連接管理 | PoolingClientConnectionManager | PoolingHttpClientConnectionManager |
| 異步支持 | 無 | CloseableHttpAsyncClient |
新項目建議直接使用 5.x,API 更現代、支持響應式、連接池管理更完善。
HttpClient 實現 POST 請求核心流程:創建客戶端 → 設置超時 → 構造請求頭/體 → 執行 → 解析響應 → 釋放資源。生產環境務必關注: