OkHttp 参考资料

github: https://github.com/square/okhttp

官方文档: https://square.github.io/okhttp/

官方 wiki 翻译: https://blog.csdn.net/jackingzheng/article/details/51778793

W3cschool okhttp 教程

okhttp 专栏: https://blog.csdn.net/lxk_1993/category_9367156.html

Retrofit 参考资料

github: https://github.com/square/retrofit

官网: https://square.github.io/retrofit/

[译] Retrofit官方文档最佳实践

Retrofit 2.0 使用教程

代码仓库

https://github.com/laolang2016/okhttp-study


测试用 api

### GET 请求
GET http://localhost:8090/product/category/list
Content-Type: application/json


### PUT 请求
PUT http://localhost:8090/product/category/add
Content-Type: application/json

{
    "parentId": 0,
    "name": "手机"
}


### POST 请求
POST http://localhost:8090/product/category/edit
Content-Type: application/json

{
    "id": 2,
    "parentId": 0,
    "name": "手机"
}

### DELETE 请求
DELETE http://localhost:8090/product/category/del/2
Content-Type: application/json

OkHttp 的基本使用

普通的同步请求

java 版

https://github.com/laolang2016/okhttp-study/blob/master/shop-boot/src/test/java/com/laolang/shop/okhttp/OkHttpBasicTest.java

package com.laolang.shop.okhttp;

import cn.hutool.json.JSONUtil;
import com.laolang.shop.modules.product.req.CategoryAddReq;
import com.laolang.shop.modules.product.req.CategoryEditReq;
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.testng.Assert;
import org.testng.annotations.Test;

@Slf4j
public class OkHttpBasicTest {

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

    @Test
    public void getTest() throws IOException {
        OkHttpClient client = new OkHttpClient();
        String url = "http://localhost:8090/product/category/list";
        Request request = new Request.Builder().url(url).method("GET", null).build();

        try (Response response = client.newCall(request).execute()) {

            Assert.assertNotNull(response.body());
            String json = response.body().string();
            log.info("request:{}", request);
            log.info("response:{}", response);
            log.info("code:{}", response.code());
            log.info("json:{}", json);
        }
    }

    @Test
    public void putTest() throws IOException {
        OkHttpClient client = new OkHttpClient();
        String url = "http://localhost:8090/product/category/add";
        CategoryAddReq req = new CategoryAddReq();
        req.setParentId(0L);
        req.setName("手机");
        RequestBody body = RequestBody.create(JSON, JSONUtil.toJsonStr(req));
        Request request = new Request.Builder()
                .url(url)
                .put(body)
                .build();

        try (Response response = client.newCall(request).execute()) {

            Assert.assertNotNull(response.body());
            String json = response.body().string();
            log.info("request:{}", request);
            log.info("response:{}", response);
            log.info("code:{}", response.code());
            log.info("json:{}", json);
        }
    }

    @Test
    public void postTest() throws IOException {
        OkHttpClient client = new OkHttpClient();
        String url = "http://localhost:8090/product/category/edit";
        CategoryEditReq req = new CategoryEditReq();
        req.setId(1L);
        req.setParentId(0L);
        req.setName("手机");
        RequestBody body = RequestBody.create(JSON, JSONUtil.toJsonStr(req));
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();

        try (Response response = client.newCall(request).execute()) {

            Assert.assertNotNull(response.body());
            String json = response.body().string();
            log.info("request:{}", request);
            log.info("response:{}", response);
            log.info("code:{}", response.code());
            log.info("json:{}", json);
        }
    }

    @Test
    public void deleteTest() throws IOException {
        OkHttpClient client = new OkHttpClient();
        String url = "http://localhost:8090/product/category/del/1";

        Request request = new Request.Builder().url(url).method("DELETE", null).build();

        try (Response response = client.newCall(request).execute()) {

            Assert.assertNotNull(response.body());
            String json = response.body().string();
            log.info("request:{}", request);
            log.info("response:{}", response);
            log.info("code:{}", response.code());
            log.info("json:{}", json);
        }
    }
}

kotlin 版

https://github.com/laolang2016/okhttp-study/blob/master/shopmobile/app/src/test/java/com/laolang/shopmobile/OkHttpBasicTest.kt

package com.laolang.shopmobile

import com.google.gson.Gson
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.junit.Test

class OkHttpBasicTest {

    private val mediaType = "application/json;charset=utf-8".toMediaTypeOrNull()

    @Test
    fun get_test() {
        val client = OkHttpClient.Builder().build()
        val url = "http://localhost:8090/product/category/list"
        val request = Request.Builder().url(url).build()
        val response = client.newCall(request).execute()
        val json = response.body?.string()

        println("request: $request")
        println("response: $response")
        println("code: ${response.code}")
        println("json: $json")
    }

    @Test
    fun put_test() {
        val client = OkHttpClient.Builder().build()
        val url = "http://localhost:8090/product/category/add"
        val req = Gson().toJson(mapOf(Pair("parentId", "0"), Pair("name", "手机")))
        val body: RequestBody = req.toRequestBody(mediaType)
        val request = Request.Builder()
            .url(url)
            .put(body)
            .build()
        val response = client.newCall(request).execute()
        val json = response.body?.string()

        println("request: $request")
        println("response: $response")
        println("code: ${response.code}")
        println("json: $json")
    }

    @Test
    fun post_test() {
        val client = OkHttpClient.Builder().build()
        val url = "http://localhost:8090/product/category/edit"
        val req = Gson().toJson(mapOf(Pair("id", "1"), Pair("parentId", "0"), Pair("name", "手机")))
        val body: RequestBody = req.toRequestBody(mediaType)
        val request = Request.Builder()
            .url(url)
            .post(body)
            .build()
        val response = client.newCall(request).execute()
        val json = response.body?.string()

        println("request: $request")
        println("response: $response")
        println("code: ${response.code}")
        println("json: $json")
    }

    @Test
    fun delete_test() {
        val client = OkHttpClient.Builder().build()
        val url = "http://localhost:8090/product/category/del/1"
        val request = Request.Builder().url(url).delete(null).build()
        val response = client.newCall(request).execute()
        val json = response.body?.string()

        println("request: $request")
        println("response: $response")
        println("code: ${response.code}")
        println("json: $json")
    }

}

自定义拦截器

一个简单的自定义拦截器

拦截器代码

package com.laolang.shop.okhttp;

import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

@Slf4j
public class LogInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        log.info("request:{}",request);
        Response response = chain.proceed(request);
        log.info("response:{}",response);
        return response;
    }
}

测试代码

package com.laolang.shop.okhttp;

import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.testng.Assert;
import org.testng.annotations.Test;

@Slf4j
public class OkHttpInterceptorTest {

    @Test
    public void test01() throws IOException {
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new LogInterceptor())
                .build();

        String url = "http://localhost:8090/product/category/list";
        Request request = new Request.Builder().url(url).method("GET", null).build();

        try (Response response = client.newCall(request).execute()) {

            Assert.assertNotNull(response.body());
            String json = response.body().string();
            log.info("code:{}", response.code());
            log.info("json:{}", json);
        }
    }
}

效果

LogInterceptor - request:Request{method=GET, url=http://localhost:8090/product/category/list, tags={}}
LogInterceptor - response:Response{protocol=http/1.1, code=200, message=, url=http://localhost:8090/product/category/list}
OkHttpInterceptorTest - code:200
OkHttpInterceptorTest - json:{"code":"200","success":true,"msg":"操作成功","body":[{"id":1,"parentId":0,"name":"分类-00"},{"id":2,"parentId":0,"name":"分类-01"},{"id":3,"parentId":0,"name":"分类-02"}],"extra":null}

关于拦截器中读取 response body

参考: 

Okhttp拦截器Interceptor学习和使用

Okhttp拦截器统一异常处理并多次读取response.body().string()