前言:
在工作中我們會經常碰到調用別的系統接口的問題,如果是http接口的話,我們一般會選擇使用HttpClient的來進行接口的調用。這篇文章就講解下如何使用HttpClient調用別人的接口,主要從兩個方面,第一種參數是map格式(post,get請求),第二種參數是json格式(psot,get請求)來展開講解。
正文:
一、什麼是HttpClient?
百度百科解釋:HttpClient 是Apache Jakarta Common 下的子項目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,並且它支持 HTTP 協議最新的版本和建議。
通俗的解釋:HttpClinet是以編程的方式(代碼方式)模擬瀏覽器對接口進行訪問從而進行數據的交互的工具包。
二、在什麼場景下需要使用HttpClient?
1.需要調用其他系統接口時,尤其是基於HTTP協議的接口(我個人這種場景下使用HttpClient最多)
2.調用WebService接口(個人覺得不是特別好用)
三、爲什麼要使用HttpClient?
HttpClient實際上是對Java提供方法的一些封裝,而HttpURLConnection是java的標準類,什麼也沒封裝,用起來太原始,不方便。例如:在HttpURLConnection中的輸入輸出流操作,但是在HttpClient被統一封裝成了HttpPost(HttpGet)和HttpResponse,這樣就就減少了操作的繁瑣性。可以類比,jdbc就相當於HttpURLConnection,MyBatis就相當於HttpClient。
四、怎麼使用HttpClient?
1.使用方法:
①創建 HttpClient 的實例
②創建請求方法的實例,並指定請求URL。如果需要發送GET請求,創建HttpGet對象;如果需要發送POST請求,創建HttpPost對象。
③如果需要發送請求參數,可調用HttpGet、HttpPost共同的setParams(HetpParams params)方法來添加請求參數;對於HttpPost對象而言,也可調用setEntity(HttpEntity entity)方法來設置請求參數。
④調用HttpClient對象的execute(HttpUriRequest request)發送請求,該方法返回一個HttpResponse。
⑤調用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取服務器的響應頭;調用HttpResponse的getEntity()方法可獲取HttpEntity對象,該對象包裝了服務器的響應內容。程序可通過該對象獲取服務器的響應內容。
⑥ 釋放連接。無論執行方法是否成功,都必須釋放連接
2.Demo1:HttpClient模擬瀏覽器get請求,請求接口,參數格式類似於form表單的get形式(這裏HttpClient版本是4.5.5)
maven依賴:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.5</version>
</dependency>
調用方代碼(封裝的HttpClient工具類的方法):
@Slf4j
public class HttpClientUtil {
private final static transient Log logger = LogFactory.getLog(HttpClientUtil.class);
public static final String CHARSET = "UTF-8";
public static final int CONNECT_TIMEOUT = 10 * 1000;
private static CloseableHttpClient httpClient;
static {
RequestConfig config = RequestConfig.custom()
.setConnectionRequestTimeout(CONNECT_TIMEOUT)//從連接池中獲取可用連接最大超時時間
.setConnectTimeout(CONNECT_TIMEOUT)//連接目標url最大超時
.setSocketTimeout(CONNECT_TIMEOUT).build();//等待響應(讀數據)最大超時
//創建HttpClient實例
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
}
public static String doGet(String url, Map<String, String> params,
String charset) {
if (StringUtils.isBlank(url)) {
return null;
}
try {//組裝參數和url
if (params != null && !params.isEmpty()) {
List<NameValuePair> pairs = new ArrayList<NameValuePair>(
params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
url += "?"
+ EntityUtils.toString(new UrlEncodedFormEntity(pairs,
charset));
}
HttpGet httpGet = new HttpGet(url);//創建HttpGET
CloseableHttpResponse response = httpClient.execute(httpGet);//執行HttpGet請求
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpGet.abort();
throw new RuntimeException("HttpClient,error status code :"
+ statusCode);
}
HttpEntity entity = response.getEntity();//獲取響應的結果
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");//格式化響應的結果
}
EntityUtils.consume(entity);
response.close();
return result;
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
return null;
}
public static void main(String[] args) {//測試的代碼
String url="http://172.16.172.128:8081/denglu/hello";
String chset="UTF-8";
HashMap<String, String> map = new HashMap<>();
map.put("name","dada1");
String s = doGet(url, map, chset);
System.out.println(s);
}
}
接口提供方代碼(封裝的HttpClient工具類中的方法):
@Controller
@RequestMapping(value = "/denglu")
public class UserController {
private final static transient Log logger = LogFactory.getLog(UserController.class);
@RequestMapping(value = "/hello",method = {RequestMethod.GET})//只能get方法訪問
public @ResponseBody String home(@RequestParam Map<String,String> map){
String name = map.get("name");
logger.info(name);
if (!"dada".equals(name)){
return "失敗";
}
logger.info(map.toString());
return "hello";
}
}
調用結果:
被調用方的入參:
Demo2:HttpClient模擬瀏覽器post請求,請求接口,參數格式類似於form表單的post形式(這裏HttpClient版本是4.5.5)
maven依賴:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.5</version>
</dependency>
調用方代碼:
public static String doPost(String url, Map<String, String> params,
String charset) {
if (StringUtils.isBlank(url)) {
return null;
}
try {//組裝參數
List<NameValuePair> pairs= new ArrayList<NameValuePair>(
params.size());
if (params != null && !params.isEmpty()) {
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
}
HttpEntity intoEntity = new UrlEncodedFormEntity(pairs, "utf-8");//格式化參數並設置編碼
HttpPost httpPost = new HttpPost(url);//創建HttpPost
httpPost.setEntity(intoEntity );//把參數放到請求體裏
CloseableHttpResponse response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpPost.abort();
throw new RuntimeException("HttpClient,error status code :"
+ statusCode);
}
HttpEntity entity = response.getEntity();//獲取返回參數
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
response.close();
return result;
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
return null;
}
public static void main(String[] args) {//測試代碼
String url="http://172.16.172.128:8081/denglu/hello";
String chset="UTF-8";
HashMap<String, String> map = new HashMap<>();
map.put("name","dada");
String s = doPost(url, map, chset);
System.out.println(s);
}
接口提供方代碼:
@Controller
@RequestMapping(value = "/denglu")
public class UserController {
private final static transient Log logger = LogFactory.getLog(UserController.class);
@RequestMapping(value = "/hello",method = {RequestMethod.POST})//只能post請求訪問
public @ResponseBody String home(@RequestParam Map<String,String> map){
String name = map.get("name");
logger.info(name);
if (!"dada".equals(name)){
return "失敗";
}
logger.info(map.toString());
return "hello";
}
}
調用結果:
被調用方的入參:
Demo3:HttpClient模擬瀏覽器post請求,請求接口,參數格式json格式(這裏HttpClient版本是4.5.5)
maven依賴:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.5</version>
</dependency>
調用方代碼(封裝的HttpClient工具類的方法):
public static String doPostJson(String url, String json) throws ClientProtocolException, IOException {
if (StringUtils.isBlank(url)) {
return null;
}
// 創建http POST請求
HttpPost httpPost = new HttpPost(url);
if (json != null) {
// 構造一個form表單式的實體
StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
// 將請求實體設置到httpPost對象中
httpPost.setEntity(stringEntity);
}
CloseableHttpResponse response = null;
try {
// 執行請求
response = httpClient.execute(httpPost);
log.info("POST 訪問url:" + url + " 狀態爲: " + response.getStatusLine().getStatusCode());
String re = EntityUtils.toString(response.getEntity(), "UTF-8");
log.info("返回結果爲: "+re);
return re;
} finally {
if (response != null) {
response.close();
}
}
}
public static void main(String[] args) throws IOException {//測試代碼
String url="http://172.16.172.128:8081/denglu/hello";
String str="{'name':'dada'}";
//字符串轉map
JSONObject jsonObject = JSONObject.parseObject(str);
Map<String,Object> map = (Map<String,Object>)jsonObject;// //json對象轉Map
//map轉字符串
String jsonString = JSON.toJSONString(map);
String s = doPostJson(url, jsonString);
System.out.println(s);
}
接口提供方代碼:
@RequestMapping(value = "/hello",method = {RequestMethod.POST})
public @ResponseBody String home(@RequestBody JSONObject object){
Map map = JSONObject.toJavaObject(object, Map.class);
String name = (String) map.get("name");
logger.info(name);
if (!"dada".equals(name)){
return "失敗";
}
logger.info(map.toString());
return "hello";
}
參考文章地址:
https://www.imooc.com/article/70192
http://www.cnblogs.com/langtianya/p/4001499.html
總結:
上面的三個demo比較簡單,但是主要讓大家熟悉封裝HttpClient工具類的思路,基本上按照開頭的6個步驟去寫代碼就不會有太大的問題,根據實際開發的需求可以靈活封裝HttpClient工具類的方法。我是阿達,一名喜歡分享知識的程序員,時不時的也會荒腔走板的聊一聊電影、電視劇、音樂、漫畫,這裏已經有17位小夥伴在等你們啦,感興趣的就趕緊來點擊關注我把,哪裏不明白或有不同觀點的地方歡迎留言。