- 在Java開發中,肯定會遇到構建HTTP請求的場景,常遇到的就是 GET 和 POST
- 以下總結三種常用的方法並實踐之:①HttpURLConnection ②HttpClient ③Hutool
- demo對應github地址:https://github.com/tyronczt/java-learn/blob/master/Tools/http-request
方法一、HttpURLConnection
HttpURLConnection 是 Java 的標準類,是 Java 比較原生的一種實現方式。
/**
* 發送get請求
*
* @param httpurl url地址
* @return
*/
public static String doGet(String httpurl) {
HttpURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = null;// 返回結果字符串
try {
// 創建遠程url連接對象
URL url = new URL(httpurl);
// 通過遠程url連接對象打開一個連接,強轉成httpURLConnection類
connection = (HttpURLConnection) url.openConnection();
// 設置連接方式:get
connection.setRequestMethod("GET");
// 設置連接主機服務器的超時時間:15000毫秒
connection.setConnectTimeout(15000);
// 設置讀取遠程返回的數據時間:60000毫秒
connection.setReadTimeout(60000);
// 發送請求
connection.connect();
// 通過connection連接,獲取輸入流
int responseCode = connection.getResponseCode();
if (responseCode == 200) {
is = connection.getInputStream();
// 封裝輸入流is,並指定字符集
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
// 存放數據
StringBuffer sbf = new StringBuffer();
String temp = null;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 關閉資源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
connection.disconnect();// 關閉遠程連接
}
return result;
}
/**
* Post請求
*
* @param httpUrl url地址
* @param param 參數
* @return 返回
*/
public static String doPost(String httpUrl, String param) {
HttpURLConnection connection = null;
InputStream is = null;
OutputStream os = null;
BufferedReader br = null;
String result = null;
try {
URL url = new URL(httpUrl);
// 通過遠程url連接對象打開連接
connection = (HttpURLConnection) url.openConnection();
// 設置連接請求方式
connection.setRequestMethod("POST");
// 設置連接主機服務器超時時間:15000毫秒
connection.setConnectTimeout(15000);
// 設置讀取主機服務器返回數據超時時間:60000毫秒
connection.setReadTimeout(60000);
// 默認值爲:false,當向遠程服務器傳送數據/寫數據時,需要設置爲true
connection.setDoOutput(true);
// 默認值爲:true,當前向遠程服務讀取數據時,設置爲true,該參數可有可無
connection.setDoInput(true);
// 請求參數判斷,帶問號的說明是String拼接,反之則爲json
if (param.contains("=")) {
// 設置傳入參數的格式:請求參數應該是 name1=value1&name2=value2 的形式。
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
} else {
//設置參數類型是json格式
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
}
// 通過連接對象獲取一個輸出流
os = connection.getOutputStream();
// 通過輸出流對象將參數寫出去/傳輸出去,它是通過字節數組寫出的,並設置utf-8,防止中文出錯
os.write(param.getBytes("utf-8"));
// 通過連接對象獲取一個輸入流,向遠程讀取
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
is = connection.getInputStream();
// 對輸入流對象進行包裝:charset根據工作項目組的要求來設置
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sbf = new StringBuffer();
String temp = null;
// 循環遍歷一行一行讀取數據
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
} else {
System.out.println("ResponseCode is an error code:" + connection.getResponseCode());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 關閉資源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != os) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 斷開與遠程地址url的連接
connection.disconnect();
}
return result;
}
main方法測試
public static void main(String[] args) {
System.out.println("通過HttpURLConnection的get方式:" + doGet("http://localhost:8080/getReq"));
Map<String, Object> map = new HashMap<>();
map.put("name", "tyron");
map.put("age", 18);
System.out.println("通過HttpURLConnection的POST方式,參數爲json形式:" +
doPost("http://localhost:8080/jsonPostReq", parseJson(map)));
String param = "name=tyron";
System.out.println("通過HttpURLConnection的POST方式,參數爲String形式:" +
doPost("http://localhost:8080/stringPostReq", param));
}
/**
* map轉string
*
* @param map map
* @return
*/
public static String parseJson(Map<String, Object> map) {
return JSONObject.toJSONString(map);
}
控制檯輸出
通過HttpURLConnection的get方式:hello get
通過HttpURLConnection的POST方式,參數爲json形式:用戶:tyron,年齡:18
通過HttpURLConnection的POST方式,參數爲String形式:hello:tyron
方法二:HttpClient4.5
HTTPClient 對 HTTP 的封裝性比較不錯,通過它基本上能夠滿足我們大部分的需求,HttpClient4.5 是 org.apache.http.client 下操作遠程 url 的工具包
<!-- 引入依賴 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
public static String doGet(String url) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = "";
try {
// 通過址默認配置創建一個httpClient實例
httpClient = HttpClients.createDefault();
// 創建httpGet遠程連接實例
HttpGet httpGet = new HttpGet(url);
// 設置請求頭信息,鑑權
// httpGet.setHeader("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
// 設置配置請求參數
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 連接主機服務超時時間
.setConnectionRequestTimeout(35000)// 請求超時時間
.setSocketTimeout(60000)// 數據讀取超時時間
.build();
// 爲httpGet實例設置配置
httpGet.setConfig(requestConfig);
// 執行get請求得到返回對象
response = httpClient.execute(httpGet);
// 通過返回對象獲取返回數據
HttpEntity entity = response.getEntity();
// 通過EntityUtils中的toString方法將結果轉換爲字符串
result = EntityUtils.toString(entity);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 關閉資源
if (null != response) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
public static String doPost(String url, Map<String, Object> paramMap) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse httpResponse = null;
String result = "";
// 創建httpClient實例
httpClient = HttpClients.createDefault();
// 創建httpPost遠程連接實例
HttpPost httpPost = new HttpPost(url);
// 配置請求參數實例
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 設置連接主機服務超時時間
.setConnectionRequestTimeout(35000)// 設置連接請求超時時間
.setSocketTimeout(60000)// 設置讀取數據連接超時時間
.build();
// 爲httpPost實例設置配置
httpPost.setConfig(requestConfig);
// 設置請求頭
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
// 封裝post請求參數
if (null != paramMap && paramMap.size() > 0) {
List<NameValuePair> nvps = new ArrayList<>();
// 通過map集成entrySet方法獲取entity
Set<Entry<String, Object>> entrySet = paramMap.entrySet();
// 循環遍歷,獲取迭代器
Iterator<Entry<String, Object>> iterator = entrySet.iterator();
while (iterator.hasNext()) {
Entry<String, Object> mapEntry = iterator.next();
nvps.add(new BasicNameValuePair(mapEntry.getKey(), mapEntry.getValue().toString()));
}
// 爲httpPost設置封裝好的請求參數
try {
httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
try {
// httpClient對象執行post請求,並返回響應參數對象
httpResponse = httpClient.execute(httpPost);
// 從響應對象中獲取響應內容
HttpEntity entity = httpResponse.getEntity();
result = EntityUtils.toString(entity);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 關閉資源
if (null != httpResponse) {
try {
httpResponse.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
main方法測試
public static void main(String[] args) {
System.out.println(doGet("http://localhost:8080/getReq"));
Map<String, Object> map = new HashMap<>();
map.put("name", "tyron");
System.out.println(doPost("http://localhost:8080/stringPostReq", map));
}
控制檯輸出
D:\soft\Java\jdk1.8.0_192\bin\java.exe "-javaagent:H:\Program Files\JetBrains\IntelliJ IDEA 2018.3.1\lib\idea_rt.jar=10427:H:\Program Files\JetBrains\IntelliJ IDEA 2018.3.1\bin" -Dfile.encoding=UTF-8 -classpath D:\soft\Java\jdk1.8.0_192\jre\lib\charsets.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\deploy.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\access-bridge-64.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\cldrdata.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\dnsns.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\jaccess.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\jfxrt.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\localedata.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\nashorn.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\sunec.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\sunjce_provider.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\sunmscapi.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\sunpkcs11.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\ext\zipfs.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\javaws.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\jce.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\jfr.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\jfxswt.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\jsse.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\management-agent.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\plugin.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\resources.jar;D:\soft\Java\jdk1.8.0_192\jre\lib\rt.jar;D:\idea_namespace\demo\target\classes;D:\maven\repository\org\springframework\boot\spring-boot-starter\2.1.4.RELEASE\spring-boot-starter-2.1.4.RELEASE.jar;D:\maven\repository\org\springframework\boot\spring-boot\2.1.4.RELEASE\spring-boot-2.1.4.RELEASE.jar;D:\maven\repository\org\springframework\spring-context\5.1.6.RELEASE\spring-context-5.1.6.RELEASE.jar;D:\maven\repository\org\springframework\boot\spring-boot-autoconfigure\2.1.4.RELEASE\spring-boot-autoconfigure-2.1.4.RELEASE.jar;D:\maven\repository\org\springframework\boot\spring-boot-starter-logging\2.1.4.RELEASE\spring-boot-starter-logging-2.1.4.RELEASE.jar;D:\maven\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\maven\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\maven\repository\org\apache\logging\log4j\log4j-to-slf4j\2.11.2\log4j-to-slf4j-2.11.2.jar;D:\maven\repository\org\apache\logging\log4j\log4j-api\2.11.2\log4j-api-2.11.2.jar;D:\maven\repository\org\slf4j\jul-to-slf4j\1.7.26\jul-to-slf4j-1.7.26.jar;D:\maven\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;D:\maven\repository\org\springframework\spring-core\5.1.6.RELEASE\spring-core-5.1.6.RELEASE.jar;D:\maven\repository\org\springframework\spring-jcl\5.1.6.RELEASE\spring-jcl-5.1.6.RELEASE.jar;D:\maven\repository\org\yaml\snakeyaml\1.23\snakeyaml-1.23.jar;D:\maven\repository\org\slf4j\slf4j-api\1.7.26\slf4j-api-1.7.26.jar;D:\maven\repository\org\springframework\boot\spring-boot-starter-web\2.1.4.RELEASE\spring-boot-starter-web-2.1.4.RELEASE.jar;D:\maven\repository\org\springframework\boot\spring-boot-starter-json\2.1.4.RELEASE\spring-boot-starter-json-2.1.4.RELEASE.jar;D:\maven\repository\com\fasterxml\jackson\core\jackson-databind\2.9.8\jackson-databind-2.9.8.jar;D:\maven\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;D:\maven\repository\com\fasterxml\jackson\core\jackson-core\2.9.8\jackson-core-2.9.8.jar;D:\maven\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.8\jackson-datatype-jdk8-2.9.8.jar;D:\maven\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.8\jackson-datatype-jsr310-2.9.8.jar;D:\maven\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.8\jackson-module-parameter-names-2.9.8.jar;D:\maven\repository\org\springframework\boot\spring-boot-starter-tomcat\2.1.4.RELEASE\spring-boot-starter-tomcat-2.1.4.RELEASE.jar;D:\maven\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.17\tomcat-embed-core-9.0.17.jar;D:\maven\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.17\tomcat-embed-el-9.0.17.jar;D:\maven\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.17\tomcat-embed-websocket-9.0.17.jar;D:\maven\repository\org\hibernate\validator\hibernate-validator\6.0.16.Final\hibernate-validator-6.0.16.Final.jar;D:\maven\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;D:\maven\repository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;D:\maven\repository\com\fasterxml\classmate\1.4.0\classmate-1.4.0.jar;D:\maven\repository\org\springframework\spring-web\5.1.6.RELEASE\spring-web-5.1.6.RELEASE.jar;D:\maven\repository\org\springframework\spring-beans\5.1.6.RELEASE\spring-beans-5.1.6.RELEASE.jar;D:\maven\repository\org\springframework\spring-webmvc\5.1.6.RELEASE\spring-webmvc-5.1.6.RELEASE.jar;D:\maven\repository\org\springframework\spring-aop\5.1.6.RELEASE\spring-aop-5.1.6.RELEASE.jar;D:\maven\repository\org\springframework\spring-expression\5.1.6.RELEASE\spring-expression-5.1.6.RELEASE.jar;D:\maven\repository\com\alibaba\fastjson\1.2.39\fastjson-1.2.39.jar;D:\maven\repository\org\apache\httpcomponents\httpclient\4.5.3\httpclient-4.5.3.jar;D:\maven\repository\org\apache\httpcomponents\httpcore\4.4.11\httpcore-4.4.11.jar;D:\maven\repository\commons-codec\commons-codec\1.11\commons-codec-1.11.jar;D:\maven\repository\cn\hutool\hutool-all\4.5.10\hutool-all-4.5.10.jar com.tyron.demo.http_client.Client_HttpClient4
DEBUG org.apache.http.client.protocol.RequestAddCookies - CookieSpec selected: default
DEBUG org.apache.http.client.protocol.RequestAuthCache - Auth cache not set in the context
DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection request: [route: {}->http://localhost:8080][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection leased: [id: 0][route: {}->http://localhost:8080][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
DEBUG org.apache.http.impl.execchain.MainClientExec - Opening connection {}->http://localhost:8080
DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connecting to localhost/127.0.0.1:8080
DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connection established 127.0.0.1:10432<->127.0.0.1:8080
DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-0: set socket timeout to 60000
DEBUG org.apache.http.impl.execchain.MainClientExec - Executing request GET /getReq HTTP/1.1
。。。省略
DEBUG org.apache.http.impl.execchain.MainClientExec - Connection can be kept alive indefinitely
DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection [id: 0][route: {}->http://localhost:8080] can be kept alive indefinitely
DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {}->http://localhost:8080][total kept alive: 1; route allocated: 1 of 2; total allocated: 1 of 20]
DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection manager is shutting down
DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-0: Close connection
DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection manager shut down
hello get
DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection request: [route: {}->http://localhost:8080][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection leased: [id: 1][route: {}->http://localhost:8080][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
DEBUG org.apache.http.impl.execchain.MainClientExec - Opening connection {}->http://localhost:8080
DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connecting to localhost/127.0.0.1:8080
DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connection established 127.0.0.1:10433<->127.0.0.1:8080
DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-1: set socket timeout to 60000
DEBUG org.apache.http.impl.execchain.MainClientExec - Executing request POST /stringPostReq HTTP/1.1
。。。省略
DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection manager shut down
hello:tyron
方法三、Hutool - HttpUtil
- A set of tools that keep Java sweet。Hutool是一個Java工具包,也只是一個工具包,它幫助我們簡化每一行代碼,減少每一個方法,讓Java語言也可以“甜甜的”。Hutool最初是我項目中“util”包的一個整理,後來慢慢積累並加入更多非業務相關功能,並廣泛學習其它開源項目精髓,經過自己整理修改,最終形成豐富的開源工具集。
- 此處使用的是 Http客戶端工具類 - HttpUtil
main方法測試
public static void main(String[] args) {
// 最簡單的HTTP請求,可以自動通過header等信息判斷編碼,不區分HTTP和HTTPS
String result1 = HttpUtil.get("http://localhost:8080/getReq");
System.out.println(result1);
// 當無法識別頁面編碼的時候,可以自定義請求頁面的編碼
String result2 = HttpUtil.get("http://localhost:8080/getReq", CharsetUtil.CHARSET_UTF_8);
System.out.println(result2);
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("name", "tyron");
String result = HttpUtil.post("http://localhost:8080/stringPostReq", paramMap);
System.out.println(result);
Map<String, Object> map = new HashMap<>();
map.put("name", "tyron");
map.put("age", 18);
System.out.println(HttpUtil.post("http://localhost:8080/jsonPostReq", JSONUtil.parseFromMap(map).toString()));
}
控制檯輸出
[main] DEBUG cn.hutool.log.LogFactory - Use [Slf4j] Logger As Default.
hello get
hello get
hello:tyron
用戶:tyron,年齡:18