OkHttp3簡單的使用說明(Cookie管理)

作者:Zyao89;轉載請保留此行,謝謝;


上一篇文章寫的是 Retrofit2.2說明-簡單使用,文中主要介紹的是Retrofit的簡單使用方法,具體涉及到的網絡請求方面的內容,在這里一并介紹。

Retrofit與okhttp共同出自于Square公司,retrofit就是對okhttp做了一層封裝。網絡請求依賴Okhttp,我們現在通過一些栗子,對OkHttp進行一定的了解。

首先說下OkHttp3是Java和Android都能用,Android還有一個著名網絡庫叫Volley,那個只有Android能用。

引入

    compile 'com.squareup.okhttp3:okhttp:3.6.0'

初始化

mOkHttpClient = new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .authenticator(new Authenticator()
                {
                    @Override
                    public Request authenticate(Route route, Response response) throws IOException
                    {//401,認證
                        String credential = Credentials.basic("zyao89", "password1");
                        return response.request().newBuilder().header("Authorization", credential).build();
                    }
                })
                .cookieJar(new CookieJar()
                {//這里可以做cookie傳遞,保存等操作
                    @Override
                    public void saveFromResponse(HttpUrl url, List<Cookie> cookies)
                    {//可以做保存cookies操作
                        System.out.println("cookies url: " + url.toString());
                        for (Cookie cookie : cookies)
                        {
                            System.out.println("cookies: " + cookie.toString());
                        }
                    }

                    @Override
                    public List<Cookie> loadForRequest(HttpUrl url)
                    {//加載新的cookies
                        ArrayList<Cookie> cookies = new ArrayList<>();
                        Cookie cookie = new Cookie.Builder()
                                .hostOnlyDomain(url.host())
                                .name("SESSION").value("zyao89")
                                .build();
                        cookies.add(cookie);
                        return cookies;
                    }
                })
                .build();
  • authenticator() 此方法可進行請求認證操作。
  • cookieJar () 次方法可進行cookies保留,和自定義cookies。(可用于存儲sessionID等信息,保存鏈接身份)

Get請求

  • 異步
public void get()
    {
        Request request = new Request.Builder()
                .url("http://200.200.200.182:9999/login")
                .build();

        Call call = mOkHttpClient.newCall(request);
        call.enqueue(getCallback());
    }
/**
     * 請求回調
     * @return
     */
    private Callback getCallback()
    {
        return new Callback()
        {//子線程回調
            @Override
            public void onResponse(Call call, Response response)
            {
                printLogCat("Code: " + response.code());
                printLogCat("Message: " + response.message());

                if (response.isSuccessful())
                {
                    try
                    {
                        printLogCat("Body: " + response.body().string());
                    }
                    catch (IOException e)
                    {
                        e.printStackTrace();
                        printLogCat("ERROR: " + "response'body is error");
                    }
                }
                else
                {
                    printLogCat("ERROR: " + "okHttp is request error");
                }
                printLogCat("");
            }

            @Override
            public void onFailure(Call call, IOException e)
            {
                printLogCat("ERROR: " + e.getMessage());
                printLogCat("");
            }
        };
    }
  • 同步
public void getSyc()
    {
        new Thread(new Runnable() {
            @Override
            public void run()
            {
                Request request = new Request.Builder()
                        .url("http://200.200.200.182:9999/login")
                        .build();
                Call call = mOkHttpClient.newCall(request);
                try
                {
                    Response response = call.execute();
                    sycCallback(response);
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }).start();
    }
private void sycCallback(Response response)
    {
        printLogCat("Code: " + response.code());
        printLogCat("Message: " + response.message());

        if (response.isSuccessful())
        {
            try
            {
                printLogCat("Body: " + response.body().string());
            }
            catch (IOException e)
            {
                e.printStackTrace();
                printLogCat("ERROR: " + "response'body is error");
            }
        }
        else
        {
            printLogCat("ERROR: " + "okHttp is request error");
        }
        printLogCat("");
    }

response的body有很多種輸出方法,string()只是其中之一,注意是string()不是toString()。如果是下載文件就是response.body().bytes()
另外可以根據response.code()獲取返回的狀態碼。

Post請求

同步異步都與get方法一致,后面提供異步栗子:

public void post()
    {
        String data = "{\"username\" : \"admin\", \"password\" : \"12345\"}";
        RequestBody requestBody = RequestBody.create(JSON, data);
        Request request = new Request.Builder()
                .url("http://200.200.200.182:9999/login")
                .post(requestBody)
                .build();

        Call call = mOkHttpClient.newCall(request);
        call.enqueue(getCallback());
    }

RequestBody的數據格式都要指定Content-Type,常見的有:

  • application/x-www-form-urlencoded 數據是個普通表單
  • multipart/form-data 數據里有文件
  • application/json 數據是個Json
  • text/x-markdown 文本MarkDown

除了RequestBody,也可用FormBody(繼承于RequestBody),如:

RequestBody formBody = new FormBody.Builder()
                .add("username", "admin2")
                .add("password", "12222333")
                .add("message", "zyao89")
                .build();

從源碼中可看到,FormBody中已指定Content-Type格式為application/x-www-form-urlencoded

private static final MediaType CONTENT_TYPE =
      MediaType.parse("application/x-www-form-urlencoded");

假如是個Json數據,則:

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

圖片文件數據,則:

public void postFile(File file)
    {
        MultipartBody multipartBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/png"), file))
                .build();
        Request request = new Request.Builder()
                .url("http://200.200.200.182:9999/file")
                .post(multipartBody)
                .build();

        Call call = mOkHttpClient.newCall(request);
        call.enqueue(getCallback());
    }

MultipartBody也是繼承了RequestBody,從源碼可知它適用于這五種Content-Type:

  public static final MediaType MIXED = MediaType.parse("multipart/mixed");

  public static final MediaType ALTERNATIVE = MediaType.parse("multipart/alternative");

  public static final MediaType DIGEST = MediaType.parse("multipart/digest");

  public static final MediaType PARALLEL = MediaType.parse("multipart/parallel");

  public static final MediaType FORM = MediaType.parse("multipart/form-data");

MediaType類型可參考W3Scholl MIME 參考手冊

PUT \ DELETE 等其它請求

這里只對PUT舉個栗子,其它類型差不多。

    public void put()
    {
        FormBody formBody = new FormBody.Builder()
                .add("username", "admin2")
                .add("password", "12222333")
                .add("message", "zyao89")
                .build();
        Request request = new Request.Builder()
                .url("http://200.200.200.182:9999/put")
                .header("Accept", "application/json; q=0.5")//添加請求頭,方式一
                .addHeader("Accept", "*")//添加請求頭,方式二
                .put(formBody)
                .build();

        Call call = mOkHttpClient.newCall(request);

        call.enqueue(getCallback());
    }

上面栗子中,Request在創建時,可自行增加header請求頭:

.header("Accept", "application/json; q=0.5")//添加請求頭,方式一
.addHeader("Accept", "*")//添加請求頭,方式二

客戶端Cookie 與 服務器Session 自動管理

業務中經常出現客戶端登錄請求結束后,服務端會返回一個帶有唯一登錄認證信息Session的Response,其中Session就藏在Cookie中,那么如何讓下一次Request請求創建時,可以將這個認證信息放入其中呢?

OkHttp為我們提供了簡便的管理方法,可自動攜帶,保存和更新Cookie信息;方法如下:

//cookie存儲
private ConcurrentHashMap<String, List<Cookie>> cookieStore = new ConcurrentHashMap<>();

mOkHttpClient = new OkHttpClient.Builder()
                .cookieJar(new CookieJar()
                {//這里可以做cookie傳遞,保存等操作
                    @Override
                    public void saveFromResponse(HttpUrl url, List<Cookie> cookies)
                    {//可以做保存cookies操作
                        cookieStore.put(url.host(), cookies);
                    }

                    @Override
                    public List<Cookie> loadForRequest(HttpUrl url)
                    {//加載新的cookies
                        List<Cookie> cookies = cookieStore.get(url.host());
                        return cookies != null ? cookies : new ArrayList<Cookie>();
                    }
                })
                .build();

如此設置后,在同一個域名地址情況下,發送Request都不用管理Cookie了,并且可以通過cookieStore獲取已存儲的Cookie,如此可達到自動管理。

Demo演示圖

測試Demo演示圖

Github項目地址:zyao89/DemoOkHttp

個人博客:http://zyao89.me

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容