Java 調用http接口(基於OkHttp的Http工具類方法示例)


Java 調用http接口(基於OkHttp的Http工具類方法示例)

現在的互聯網項目中,自己單擼所有功能的時代已經過去了,有些功能往往有第三方或者公司其他團隊提供服務,你要做得僅僅就是和它們進行對接。對接一些大公司提供的服務時,它們往往會提供對應語言的SDK和說明文檔;而團隊與團隊之間的項目對接往往通過接口進行數據交互,往往都是HTTP JSON交互的形式。

本文介紹如何使用這些API,然后給出博主自己寫的一個工具列demo,需要的可以在此基礎上修改。

OkHttp3

一般來說,Java 直接調用HTTP接口常見的有三種方式,第一種是JDK原生的方式,第二種是apache 提供的HTTP工具,還有一種是本文着重介紹的OkHttp3工具

OkHttp3官方文檔介紹了它的4點優勢:

  • HTTP/2支持允許對同一主機的所有請求共享一個socket。
  • 連接池減少了請求延遲(如果HTTP/2不可用)。
  • 透明GZIP壓縮下載大小。
  • 響應緩存完全避免了網絡重復請求。

使用OkHttp很容易。它的請求/響應API設計為流暢的構建器和不變性。它同時支持同步阻塞調用和帶回調的異步調用。

下面介紹一下常見的GET方法和POST方法官方示例,首先添加依賴:

MAVEN依賴

<!--okhttp依賴-->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.0.0</version>
</dependency>

Http get操作示例

OkHttpClient client = new OkHttpClient();

String run(String url) throws IOException {
  Request request = new Request.Builder()
      .url(url)
      .build();

  try (Response response = client.newCall(request).execute()) {
    return response.body().string();
  }
}

Http Post操作示例

public static final MediaType JSON
    = MediaType.get("application/json; charset=utf-8");

OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException {
  RequestBody body = RequestBody.create(JSON, json);
  Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  try (Response response = client.newCall(request).execute()) {
    return response.body().string();
  }
}

Http 超時控制

當調用的對等方不可用時,超時使調用失敗。網絡可能是由於客戶機連接問題、服務器可用性問題或兩者之間的任何問題造成的。OkHttp支持連接、讀取和寫入超時。

private final OkHttpClient client;

public ConfigureTimeouts() throws Exception {
    client = new OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)
        .writeTimeout(10, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .build();
    }

public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
        .build();

    try (Response response = client.newCall(request).execute()) {
        System.out.println("Response completed: " + response);
    }
}

工具類示例

提供同步的GET和POST調用工具方法示例,提供了異步調用HTTP接口的demo

import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * @author axin
 * @since 2019-08-14
 */
public class OkHttpUtils {

    private static final Logger log = LoggerFactory.getLogger(OkHttpUtils.class);

    private static final String HTTP_JSON = "application/json; charset=utf-8";
    private static final String HTTP_FORM = "application/x-www-form-urlencoded; charset=utf-8";

    private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .connectTimeout(120, TimeUnit.SECONDS)
            .readTimeout(120, TimeUnit.SECONDS)
            .writeTimeout(120, TimeUnit.SECONDS)
            .build();


    /**
     * get請求
     * 對於小文檔,響應體上的string()方法非常方便和高效。
     * 但是,如果響應主體很大(大於1 MB),則應避免string(),
     * 因為它會將整個文檔加載到內存中。在這種情況下,將主體處理為流。
     *
     * @param url
     * @return
     */
    public static String httpGet(String url) {
        if (url == null || "".equals(url)) {
            log.error("url為null!");
            return "";
        }

        Request.Builder builder = new Request.Builder();
        Request request = builder.get().url(url).build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (response.code() == 200) {
                log.info("http GET 請求成功; [url={}]", url);
                return response.body().string();
            } else {
                log.warn("Http GET 請求失敗; [errorCode = {} , url={}]", response.code(), url);
            }
        } catch (IOException e) {
            throw new RuntimeException("同步http GET 請求失敗,url:" + url, e);
        }
        return null;
    }

    public static String httpGet(String url, Map<String, String> headers) {
        if (CollectionUtils.isEmpty(headers)) {
            return httpGet(url);
        }

        Request.Builder builder = new Request.Builder();
        headers.forEach((String key, String value) -> builder.header(key, value));
        Request request = builder.get().url(url).build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (response.code() == 200) {
                log.info("http GET 請求成功; [url={}]", url);
                return response.body().string();
            } else {
                log.warn("Http GET 請求失敗; [errorxxCode = {} , url={}]", response.code(), url);
            }
        } catch (IOException e) {
            throw new RuntimeException("同步http GET 請求失敗,url:" + url, e);
        }
        return null;
    }

    /**
     * 同步 POST調用 無Header
     *
     * @param url
     * @param json
     * @return
     */
    public static String httpPostJson(String url, String json) {
        if (url == null || "".equals(url)) {
            log.error("url為null!");
            return "";
        }

        MediaType JSON = MediaType.parse(HTTP_JSON);
        RequestBody body = RequestBody.create(JSON, json);
        Request.Builder requestBuilder = new Request.Builder().url(url);
        Request request = requestBuilder.post(body).build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (response.code() == 200) {
                log.info("http Post 請求成功; [url={}, requestContent={}]", url, json);
                return response.body().string();
            } else {
                log.warn("Http POST 請求失敗; [ errorCode = {}, url={}, param={}]", response.code(), url, json);
            }
        } catch (IOException e) {
            throw new RuntimeException("同步http請求失敗,url:" + url, e);
        }
        return null;
    }

    /**
     * 同步 POST調用 有Header
     *
     * @param url
     * @param headers
     * @param json
     * @return
     */
    public static String httpPostJson(String url, Map<String, String> headers, String json) {
        if (CollectionUtils.isEmpty(headers)) {
            httpPostJson(url, json);
        }

        MediaType JSON = MediaType.parse(HTTP_JSON);
        RequestBody body = RequestBody.create(JSON, json);
        Request.Builder requestBuilder = new Request.Builder().url(url);
        headers.forEach((k, v) -> requestBuilder.addHeader(k, v));
        Request request = requestBuilder.post(body).build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (response.code() == 200) {
                log.info("http Post 請求成功; [url={}, requestContent={}]", url, json);
                return response.body().string();
            } else {
                log.warn("Http POST 請求失敗; [ errorCode = {}, url={}, param={}]", response.code(), url, json);
            }
        } catch (IOException e) {
            throw new RuntimeException("同步http請求失敗,url:" + url, e);
        }
        return null;
    }

    /**
     * 提交表單
     * @param url
     * @param content
     * @param headers
     * @return
     */
    public static String postDataByForm(String url, String content, Map<String, String> headers) {
        MediaType JSON = MediaType.parse(HTTP_FORM);
        RequestBody body = RequestBody.create(JSON, content);

        Request.Builder requestBuilder = new Request.Builder().url(url);
        if (headers != null && headers.size() > 0) {
            headers.forEach((k, v) -> requestBuilder.addHeader(k, v));
        }
        Request request = requestBuilder
                .post(body)
                .build();

        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
            if (response.code() == 200) {
                log.info("postDataByForm; [postUrl={}, requestContent={}, responseCode={}]", url, content, response.code());
                return response.body().string();
            } else {
                log.warn("Http Post Form請求失敗,[url={}, param={}]", url, content);
            }
        } catch (IOException e) {
            log.error("Http Post Form請求失敗,[url={}, param={}]", url, content, e);
            throw new RuntimeException("Http Post Form請求失敗,url:" + url);
        }
        return null;
    }

    /**
     * 異步Http調用參考模板:Get、Post、Put
     * 需要異步調用的接口一般情況下你需要定制一個專門的Http方法
     *
     * @param httpMethod
     * @param url
     * @param content
     * @return
     */
    @Deprecated
    public static Future<Boolean> asyncHttpByJson(HttpMethod httpMethod, String url, Map<String, String> headers, String content) {
        MediaType JSON = MediaType.parse(HTTP_JSON);
        RequestBody body = RequestBody.create(JSON, content);

        Request.Builder requestBuilder = new Request.Builder()
                .url(url);

        if (!CollectionUtils.isEmpty(headers)) {
            headers.forEach((key, value) -> requestBuilder.header(key, value));
        }

        switch (httpMethod) {
            case GET:
                requestBuilder.get();
                break;
            case POST:
                requestBuilder.post(body);
                break;
            default:
        }

        Request request = requestBuilder.build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                log.error("異步http {} 請求失敗,[url={}, param={}]", httpMethod.name(), url, content);
                throw new RuntimeException("異步http請求失敗,url:" + url);
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                if (response.code() == 200) {
                    System.out.println("需要加入異步回調操作");
                } else {
                    log.error("異步http {} 請求失敗,錯誤碼為{},請求參數為[url={}, param={}]", httpMethod.name(), response.code(), url, content);
                }
            }
        });
        return new AsyncResult(true);
    }

    /**
     * lambda表達式異步調用http模板,不建議使用
     *
     * @param request
     * @param failure
     * @param respConsumer
     */
    public static void asyncCall(Request request, Consumer<Exception> failure, Consumer<Response> respConsumer) {
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                failure.accept(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                respConsumer.accept(response);
            }
        });
    }

    //test
    public static void main(String[] args) {
        String url = "http://www.baidu.com";
        System.out.println(httpGet(url));
    }

}

綜上,本文介紹了Okhttp3的使用,並給出了工具類的demo,要注意的是,對於異步調用http方法需要根據你們項目的具體業務進行改造,增加回調失敗與成功的業務邏輯。

文檔鏈接:OkHttp官網


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM