HttpClient使用詳解

前言:

在工作中我們會經常碰到調用別的系統接口的問題,如果是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位小夥伴在等你們啦,感興趣的就趕緊來點擊關注我把,哪裏不明白或有不同觀點的地方歡迎留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章