Java調用第三方http接口的方式

1. 概述

在實際開發過程當中,咱們常常須要調用對方提供的接口或測試本身寫的接口是否合適。不少項目都會封裝規定好自己項目的接口規範,因此大多數須要去調用對方提供的接口或第三方接口(短信、天氣等)。html

在Java項目中調用第三方接口的方式有:java

①經過JDK網絡類Java.net.HttpURLConnection;git

②經過common封裝好的HttpClient;github

③經過Apache封裝好的CloseableHttpClient;web

④經過SpringBoot-RestTemplate;spring

2. Java調用第三方http接口的方式

2.1 經過JDK網絡類Java.net.HttpURLConnection

 比較原始的一種調用作法,這裏把get請求和post請求都統一放在一個方法裏面,直接上代碼:apache

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * @Author: Yang JianQiu
 * @Date: 2019/4/26 11:34
 * jdk類HttpURLConnection調用第三方http接口
 *
 * 一般分get和post兩種方式
 *
 * 參考資料:
 * http://www.cnblogs.com/angusbao/p/7727649.html
 */
public class HttpUrlConnectionToInterface {

    /**
     * 以post或get方式調用對方接口方法,
     * @param pathUrl
     */
    public static void doPostOrGet(String pathUrl, String data){
        OutputStreamWriter out = null;
        BufferedReader br = null;
        String result = "";
        try {
            URL url = new URL(pathUrl);
            //打開和url之間的鏈接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //請求方式
            conn.setRequestMethod("POST");
            //conn.setRequestMethod("GET");

            //設置通用的請求屬性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");

            //DoOutput設置是否向httpUrlConnection輸出,DoInput設置是否從httpUrlConnection讀入,此外發送post請求必須設置這兩個
            conn.setDoOutput(true);
            conn.setDoInput(true);

            /**
             * 下面的三句代碼,就是調用第三方http接口
             */
            //獲取URLConnection對象對應的輸出流
            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
            //發送請求參數即數據
            out.write(data);
            //flush輸出流的緩衝
            out.flush();

            /**
             * 下面的代碼至關於,獲取調用第三方http接口後返回的結果
             */
            //獲取URLConnection對象對應的輸入流
            InputStream is = conn.getInputStream();
            //構造一個字符流緩存
            br = new BufferedReader(new InputStreamReader(is));
            String str = "";
            while ((str = br.readLine()) != null){
                result += str;
            }
            System.out.println(result);
            //關閉流
            is.close();
            //斷開鏈接,disconnect是在底層tcp socket連接空閒時才切斷,若是正在被其餘線程使用就不切斷。
            conn.disconnect();

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (out != null){
                    out.close();
                }
                if (br != null){
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        /**
         *手機信息查詢接口:http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=手機號
     *      http://api.showji.com/Locating/www.showji.com.aspx?m=手機號&output=json&callback=querycallback
         */
        doPostOrGet("https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13026194071", "");
    }
}

2.2 經過apache common封裝好的HttpClient

httpClient的get或post請求方式步驟:json

  1. 生成一個HttpClient對象並設置相應的參數;
  2. 生成一個GetMethod對象或PostMethod並設置響應的參數;
  3. 用HttpClient生成的對象來執行GetMethod生成的Get方法;
  4. 處理響應狀態碼;
  5. 若響應正常,處理HTTP響應內容;
  6. 釋放鏈接。

導入以下jar包:api

        <!--HttpClient-->
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>

代碼以下:數組

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

import java.io.IOException;
import java.io.InputStream;

/**
 * @Author: Yang JianQiu
 * @Date: 2019/4/28 11:07
 *
 * HttpClient模擬get、post請求併發送請求參數(json等)
 * 【參考資料】
 * https://javasam.iteye.com/blog/2117845
 * https://blog.csdn.net/qq_28379809/article/details/82898792
 */
public class HttpClientToInterface {

    /**
     * httpClient的get請求方式
     * 使用GetMethod來訪問一個URL對應的網頁實現步驟:
     * 1.生成一個HttpClient對象並設置相應的參數;
     * 2.生成一個GetMethod對象並設置響應的參數;
     * 3.用HttpClient生成的對象來執行GetMethod生成的Get方法;
     * 4.處理響應狀態碼;
     * 5.若響應正常,處理HTTP響應內容;
     * 6.釋放鏈接。
     * @param url
     * @param charset
     * @return
     */
    public static String doGet(String url, String charset){
        /**
         * 1.生成HttpClient對象並設置參數
         */
        HttpClient httpClient = new HttpClient();
        //設置Http鏈接超時爲5秒
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);

        /**
         * 2.生成GetMethod對象並設置參數
         */
        GetMethod getMethod = new GetMethod(url);
        //設置get請求超時爲5秒
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);
        //設置請求重試處理,用的是默認的重試處理:請求三次
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());

        String response = "";

        /**
         * 3.執行HTTP GET 請求
         */
        try {
            int statusCode = httpClient.executeMethod(getMethod);

            /**
             * 4.判斷訪問的狀態碼
             */
            if (statusCode != HttpStatus.SC_OK){
                System.err.println("請求出錯:" + getMethod.getStatusLine());
            }

            /**
             * 5.處理HTTP響應內容
             */
            //HTTP響應頭部信息,這裏簡單打印
            Header[] headers = getMethod.getResponseHeaders();
            for (Header h: headers){
                System.out.println(h.getName() + "---------------" + h.getValue());
            }
            //讀取HTTP響應內容,這裏簡單打印網頁內容
            //讀取爲字節數組
            byte[] responseBody = getMethod.getResponseBody();
            response = new String(responseBody, charset);
            System.out.println("-----------response:" + response);
            //讀取爲InputStream,在網頁內容數據量大時候推薦使用
            //InputStream response = getMethod.getResponseBodyAsStream();

        } catch (HttpException e) {
            //發生致命的異常,多是協議不對或者返回的內容有問題
            System.out.println("請檢查輸入的URL!");
            e.printStackTrace();
        } catch (IOException e){
            //發生網絡異常
            System.out.println("發生網絡異常!");
        }finally {
            /**
             * 6.釋放鏈接
             */
            getMethod.releaseConnection();
        }
        return response;
    }

    /**
     * post請求
     * @param url
     * @param json
     * @return
     */
    public static String doPost(String url, JSONObject json){
        HttpClient httpClient = new HttpClient();
        PostMethod postMethod = new PostMethod(url);

        postMethod.addRequestHeader("accept", "*/*");
        postMethod.addRequestHeader("connection", "Keep-Alive");
        //設置json格式傳送
        postMethod.addRequestHeader("Content-Type", "application/json;charset=utf-8");
        //必須設置下面這個Header
        postMethod.addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
        //添加請求參數
        postMethod.addParameter("commentId", json.getString("commentId"));

        String res = "";
        try {
            int code = httpClient.executeMethod(postMethod);
            if (code == 200){
                res = postMethod.getResponseBodyAsString();
                System.out.println(res);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return res;
    }

    public static void main(String[] args) {
        doGet("http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13026194071", "UTF-8");
        System.out.println("-----------分割線------------");
        System.out.println("-----------分割線------------");
        System.out.println("-----------分割線------------");

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("commentId", "13026194071");
        doPost("http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13026194071", jsonObject);
    }
}

2.3 經過Apache封裝好的CloseableHttpClient

 CloseableHttpClient是在HttpClient的基礎上修改更新而來的,這裏還涉及到請求頭token的設置(請求驗證),利用fastjson轉換請求或返回結果字符串爲json格式,固然上面兩種方式也是能夠設置請求頭token、json的,這裏只在下面說明。

導入以下jar包:

        <!--CloseableHttpClient-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.28</version>
        </dependency>

代碼以下:

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

/**
 * @Author: Yang JianQiu
 * @Date: 2019/4/26 11:41
 * Apache封裝好的CloseableHttpClient
 * 【參考資料】
 *  https://www.cnblogs.com/siv8/p/6222709.html
 *  https://blog.csdn.net/qq_35860138/article/details/82967727
 */
public class CloseableHttpClientToInterface {

    private static String tokenString = "";
    private static String AUTH_TOKEN_EXPIRED = "AUTH_TOKEN_EXPIRED";
    private static CloseableHttpClient httpClient = null;

    /**
     * 以get方式調用第三方接口
     * @param url
     * @return
     */
    public static String doGet(String url, String token){
        //建立HttpClient對象
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);

        try {
            if (tokenString != null && !tokenString.equals("")){
                tokenString = getToken();
            }
            //api_gateway_auth_token自定義header頭,用於token驗證使用
            get.addHeader("api_gateway_auth_token", tokenString);
            get.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
            HttpResponse response = httpClient.execute(get);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                //返回json格式
                String res = EntityUtils.toString(response.getEntity());
                return res;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 以post方式調用第三方接口
     * @param url
     * @param json
     * @return
     */
    public static String doPost(String url, JSONObject json){
        
        try {
            if (httpClient == null){
                httpClient = HttpClientBuilder.create().build();
            }

            HttpPost post = new HttpPost(url);
            
            if (tokenString != null && !tokenString.equals("")){
                tokenString = getToken();
            }
            
            //api_gateway_auth_token自定義header頭,用於token驗證使用
            post.addHeader("api_gateway_auth_token", tokenString);
            post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");

            StringEntity s = new StringEntity(json.toString());
            s.setContentEncoding("UTF-8");
            //發送json數據須要設置contentType
            s.setContentType("application/x-www-form-urlencoded");
            //設置請求參數
            post.setEntity(s);
            HttpResponse response = httpClient.execute(post);

            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                //返回json格式
                String res = EntityUtils.toString(response.getEntity());
                return res;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (httpClient != null){
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 獲取第三方接口的token
     */
    public static String getToken(){

        String token = "";

        JSONObject object = new JSONObject();
        object.put("appid", "appid");
        object.put("secretkey", "secretkey");

        try {
            if (httpClient == null){
                httpClient = HttpClientBuilder.create().build();
            }
            HttpPost post = new HttpPost("http://localhost/login");
            
            post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");

            StringEntity s = new StringEntity(object.toString());
            s.setContentEncoding("UTF-8");
            //發送json數據須要設置contentType
            s.setContentType("application/x-www-form-urlencoded");
            //設置請求參數
            post.setEntity(s);
            HttpResponse response = httpClient.execute(post);

            //這裏能夠把返回的結果按照自定義的返回數據結果,把string轉換成自定義類
            //ResultTokenBO result = JSONObject.parseObject(response, ResultTokenBO.class);

           //把response轉爲jsonObject
            JSONObject result = JSONObject.parseObject(response);
            if (result.containsKey("token")){
                token = result.getString("token");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return token;
    }

    /**
     * 測試
     */
    public static void test(String telephone){

        JSONObject object = new JSONObject();
        object.put("telephone", telephone);

        try {
            //首先獲取token
            tokenString = getToken();
            String response = doPost("http://localhost/searchUrl", object);

            //若是返回的結果是list形式的,須要使用JSONObject.parseArray轉換
            //List<Result> list = JSONObject.parseArray(response, Result.class);

            System.out.println(response);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        test("12345678910");
    }

}

2.4 經過SpringBoot-RestTemplate

 springBoot-RestTemple是上面三種方式的集大成者,代碼編寫更加簡單,目前能夠採用的調用第三方接口有:

  • delete() 在特定的URL上對資源執行HTTP DELETE操做
  • exchange() 在URL上執行特定的HTTP方法,返回包含對象的ResponseEntity,這個對象是從響應體中映射獲得的
  • execute() 在URL上執行特定的HTTP方法,返回一個從響應體映射獲得的對象
  • getForEntity() 發送一個HTTP GET請求,返回的ResponseEntity包含了響應體所映射成的對象
  • getForObject() 發送一個HTTP GET請求,返回的請求體將映射爲一個對象
  • postForEntity() POST 數據到一個URL,返回包含一個對象的ResponseEntity,這個對象是從響應體中映射獲得的
  • postForObject() POST 數據到一個URL,返回根據響應體匹配造成的對象
  • headForHeaders() 發送HTTP HEAD請求,返回包含特定資源URL的HTTP頭
  • optionsForAllow() 發送HTTP OPTIONS請求,返回對特定URL的Allow頭信息
  • postForLocation() POST 數據到一個URL,返回新建立資源的URL
  • put() PUT 資源到特定的URL

注意:目前標紅的爲經常使用的

首先導入springboot的web包

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
    </parent>

    <dependencies>
        <!--CloseableHttpClient-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>

        <!--spring restTemplate-->
        <!-- @ConfigurationProperties annotation processing (metadata for IDEs)
                生成spring-configuration-metadata.json類,須要引入此類-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

在啓動類同包下建立RestTemplateConfig.java類

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: Yang JianQiu
 * @Date: 2019/4/28 14:01
 */
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory){
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(15000);
        factory.setReadTimeout(5000);
        return factory;
    }
}

而後在Service類(RestTemplateToInterface )中注入使用

具體代碼以下:

import com.alibaba.fastjson.JSONObject;
import com.swordfall.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: Yang JianQiu
 * @Date: 2019/4/28 14:13
 *
 * 【參考資料】
 * https://blog.csdn.net/qq_15452971/article/details/79416469
 * https://blog.csdn.net/weixin_40461281/article/details/83540604
 */
@Service
public class RestTemplateToInterface {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 以get方式請求第三方http接口 getForEntity
     * @param url
     * @return
     */
    public User doGetWith1(String url){
        ResponseEntity<User> responseEntity = restTemplate.getForEntity(url, User.class);
        User user = responseEntity.getBody();
        return user;
    }

    /**
     * 以get方式請求第三方http接口 getForObject
     * 返回值返回的是響應體,省去了咱們再去getBody()
     * @param url
     * @return
     */
    public User doGetWith2(String url){
        User user  = restTemplate.getForObject(url, User.class);
        return user;
    }

    /**
     * 以post方式請求第三方http接口 postForEntity
     * @param url
     * @return
     */
    public String doPostWith1(String url){
        User user = new User("小白", 20);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, user, String.class);
        String body = responseEntity.getBody();
        return body;
    }

    /**
     * 以post方式請求第三方http接口 postForEntity
     * @param url
     * @return
     */
    public String doPostWith2(String url){
        User user = new User("小白", 20);
        String body = restTemplate.postForObject(url, user, String.class);
        return body;
    }

    /**
     * exchange
     * @return
     */
    public String doExchange(String url, Integer age, String name){
        //header參數
        HttpHeaders headers = new HttpHeaders();
        String token = "asdfaf2322";
        headers.add("authorization", token);
        headers.setContentType(MediaType.APPLICATION_JSON);

        //放入body中的json參數
        JSONObject obj = new JSONObject();
        obj.put("age", age);
        obj.put("name", name);

        //組裝
        HttpEntity<JSONObject> request = new HttpEntity<>(obj, headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
        String body = responseEntity.getBody();
        return body;
    }
}

總結

【github地址】

https://github.com/SwordfallYeung/JavaInvokingHttpInterface.git

【參考資料】

http://www.cnblogs.com/angusbao/p/7727649.html 純Java api HttpURLConnection

http://www.javashuo.com/article/p-aoyzgrip-dx.html 純Java api HttpURLConnection

http://www.javashuo.com/article/p-erqtyjxs-bd.html 封裝api HttpClient

http://www.javashuo.com/article/p-tsxxnixw-ca.html 

http://www.javashuo.com/article/p-tuxzgoxy-dw.html 封裝api HttpClient

http://www.javashuo.com/article/p-undzltcp-hk.html SpringBoot-RestTemplate

相關文章
相關標籤/搜索