Http請求-okhttp3基本用法

誰主沉浮oo7發表於2020-08-25

簡介

HTTP是現代應用常用的一種交換資料和媒體的網路方式,高效地使用HTTP能讓資源載入更快,節省頻寬。OkHttp是一個高效的HTTP客戶端,它有以下預設特性:

  • 支援HTTP/2,允許所有同一個主機地址的請求共享同一個socket連線
  • 連線池減少請求延時
  • 透明的GZIP壓縮減少響應資料的大小
  • 快取響應內容,避免一些完全重複的請求

原始碼:https://github.com/square/okhttp
說明:OkHttp支援Android 2.3及以上版本Android平臺,對於Java, JDK1.7及以上。
當網路出現問題的時候OkHttp依然堅守自己的職責,它會自動恢復一般的連線問題,如果你的服務有多個IP地址,當第一個IP請求失敗時,OkHttp會交替嘗試你配置的其他IP,OkHttp使用現代TLS技術(SNI, ALPN)初始化新的連線,當握手失敗時會回退到TLS 1.0。

簡單使用

引入maven依賴

<dependency>
   <groupId>com.squareup.okhttp3</groupId>
   <artifactId>okhttp</artifactId>
   <version>4.0.0-RC1</version>
</dependency>

請求方法

同步請求

就是執行請求的操作是阻塞式,直到 HTTP 響應返回。它對應 OKHTTP 中的 execute 方法。

GET請求

    /**
     * 同步get方式請求
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static String doGet(String url) throws IOException {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new IOException("Unexpected code " + response);
            }
        }
    }

POST請求

Json提交引數

/**
     * 同步post方式請求-json提交引數
     *
     * @param url
     * @param json
     * @return
     * @throws IOException
     */
    public static String doPost(String url, final String json) throws IOException {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new IOException("Unexpected code " + response);
            }
        }

    }

form表單提交引數

    /**
     * 同步post方式請求-form表單提交引數
     *
     * @param url
     * @param paramsMap
     * @return
     * @throws IOException
     */
    public static String doPost(String url, Map<String, String> paramsMap) throws IOException {
        OkHttpClient client = new OkHttpClient();
        FormBody.Builder builder = new FormBody.Builder();
        for (String key : paramsMap.keySet()) {
            builder.add(key, paramsMap.get(key));
        }
        RequestBody formBody = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new IOException("Unexpected code " + response);
            }
        }

    }

非同步請求

就是類似於非阻塞式的請求,它的執行結果一般都是通過介面回撥的方式告知呼叫者。它對應 OKHTTP 中的 enqueue 方法。

這是非同步請求,所以呼叫enqueue則無需再開啟子執行緒,enqueue方法會自動將網路請求部分放入子執行緒中執行。enqueue回撥方法onResponse與onFailure都執行在子執行緒中。
注意事項:

    1. 回撥介面的onFailure方法和onResponse執行在子執行緒。
    1. Response.code是http響應行中的code,如果訪問成功則返回200.這個不是伺服器設定的,而是http協議中自帶的。res中的code才是伺服器設定的。注意二者的區別。
    1. response.body().string()本質是輸入流的讀操作,所以它還是網路請求的一部分,所以這行程式碼必須放在子執行緒。
    1. response.body().string()只能呼叫一次,在第一次時有返回值,第二次再呼叫時將會返回null。原因是:response.body().string()的本質是輸入流的讀操作,必須有伺服器的輸出流的寫操作時客戶端的讀操作才能得到資料。而伺服器的寫操作只執行一次,所以客戶端的讀操作也只能執行一次,第二次將返回null。
    1. 再次強調,response.body().string()方法必須放在子執行緒中。當執行這行程式碼得到結果後,再跳轉到UI執行緒修改UI。

非同步請求自定義回撥函式

/**
     * okhttp 非同步呼叫回撥函式
     */
    static class OkHttpCallback implements Callback {
        @Override
        public void onFailure(@NotNull Call call, @NotNull IOException e) {
            log.error(e);
        }

        @Override
        public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
            if (response.isSuccessful()) {
                log.info("Successful data acquisition . . . ");
                log.info("response.code()==" + response.code());
                log.info("response.body().string()==" + response.body().string());
            }
        }
    }

GET請求

    /**
     * 非同步get方式請求
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static void doSyncGet(String url) {
        OkHttpClient okHttpClient = new OkHttpClient();
        final Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new OkHttpCallback());
    }

POST請求

Json提交引數

    /**
     * 非同步post方式請求-json提交引數
     *
     * @param url
     * @param json
     * @return
     * @throws IOException
     */
    public static void doSyncPost(String url, final String json) {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        client.newCall(request).enqueue(new OkHttpCallback());

    }

form表單提交引數

 /**
     * 非同步post方式請求-form表單提交引數
     *
     * @param url
     * @param paramsMap
     * @return
     * @throws IOException
     */
    public static void doSyncPost(String url, Map<String, String> paramsMap) {
        OkHttpClient client = new OkHttpClient();
        FormBody.Builder builder = new FormBody.Builder();
        for (String key : paramsMap.keySet()) {
            builder.add(key, paramsMap.get(key));
        }
        RequestBody formBody = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        client.newCall(request).enqueue(new OkHttpCallback());

    }

參考

示例程式碼

package com.ohaotian.feifz.style.study.utils;

import lombok.extern.log4j.Log4j2;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.util.Map;

/**
 * @author feifz
 * @version 1.0.0
 * @Description http工具類,基於okhttp3
 * @createTime 2019年06月06日 09:30:00
 */
@Log4j2
public class HttpUtil {

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


    /**
     * 同步get方式請求
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static String doGet(String url) throws IOException {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new IOException("Unexpected code " + response);
            }
        }
    }

    /**
     * 非同步get方式請求
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static void doSyncGet(String url) {
        OkHttpClient okHttpClient = new OkHttpClient();
        final Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new OkHttpCallback());
    }

    /**
     * 同步post方式請求-json提交引數
     *
     * @param url
     * @param json
     * @return
     * @throws IOException
     */
    public static String doPost(String url, final String json) throws IOException {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new IOException("Unexpected code " + response);
            }
        }

    }

    /**
     * 非同步post方式請求-json提交引數
     *
     * @param url
     * @param json
     * @return
     * @throws IOException
     */
    public static void doSyncPost(String url, final String json) {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        client.newCall(request).enqueue(new OkHttpCallback());

    }

    /**
     * 同步post方式請求-form表單提交引數
     *
     * @param url
     * @param paramsMap
     * @return
     * @throws IOException
     */
    public static String doPost(String url, Map<String, String> paramsMap) throws IOException {
        OkHttpClient client = new OkHttpClient();
        FormBody.Builder builder = new FormBody.Builder();
        for (String key : paramsMap.keySet()) {
            builder.add(key, paramsMap.get(key));
        }
        RequestBody formBody = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new IOException("Unexpected code " + response);
            }
        }

    }

    /**
     * 非同步post方式請求-form表單提交引數
     *
     * @param url
     * @param paramsMap
     * @return
     * @throws IOException
     */
    public static void doSyncPost(String url, Map<String, String> paramsMap) {
        OkHttpClient client = new OkHttpClient();
        FormBody.Builder builder = new FormBody.Builder();
        for (String key : paramsMap.keySet()) {
            builder.add(key, paramsMap.get(key));
        }
        RequestBody formBody = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        client.newCall(request).enqueue(new OkHttpCallback());

    }

    /**
     * okhttp 非同步呼叫回撥函式
     */
    static class OkHttpCallback implements Callback {
        @Override
        public void onFailure(@NotNull Call call, @NotNull IOException e) {
            log.error(e);
        }

        @Override
        public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
            if (response.isSuccessful()) {
                log.info("Successful data acquisition . . . ");
                log.info("response.code()==" + response.code());
                log.info("response.body().string()==" + response.body().string());
            }
        }
    }


}


結語

歡迎關注微信公眾號『碼仔zonE』,專注於分享Java、雲端計算相關內容,包括SpringBoot、SpringCloud、微服務、Docker、Kubernetes、Python等領域相關技術乾貨,期待與您相遇!

相關文章