Http客户端OkHttp的基本使用

Http客户端OkHttp的基本使用

okhttp是一款优秀的http客户端,支持异步,http2等等。

Github & Maven

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.14.0</version>
</dependency>

基本的组件

OkHttpClient

它类似于一个浏览器,在应用中应该全局唯一

Request

它表示一次Http请求,可以设置url地址,请求头等信息

RequestBody

它表示http请求体

Response

它表示一次Http响应,可以获取到响应体,响应头等信息

ResponseBody

它表示Http响应体

基本的流程

  1. 创建OkHttpClient客户端
  2. 创建请求体对象
  3. 创建请求对象,设置URL,Header信息
  4. 使用客户端对象执行请求,获取到Response对象
  5. 从Response对象获取到响应体
  6. 释放资源

GET 请求

基本的请求

OkHttpClient okHttpClient = new OkHttpClient();

Request request = new Request.Builder()
        .url("http://localhost:8081/")
        .addHeader("foo","bar") // http消息头
        .build();

Response response = okHttpClient.newCall(request).execute();

response.headers(); //响应头

ResponseBody responseBody = response.body();

responseBody.string(); // 响应体

文件下载

OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder().url("http://localhost:8081/down/demo.mp4").build();

Response response = client.newCall(request).execute();

// 从响应获取到InputStream
InputStream inputStream = response.body().byteStream();

POST请求

application/x-www-form-urlencoded

OkHttpClient client = new OkHttpClient();

// 表单请求体
RequestBody body = new FormBody.Builder()
        .add("name","KevinBlandy")          // 添加表单项
        .addEncoded("charset","utf-8")      // 添加表单项,使用URI编码
        .build();

Request request = new Request.Builder()
        .url("http://localhost:8081/user")
        .post(body).build();

Response response = client.newCall(request).execute();

response.body().string();

application/json

// 创建Content-Type头为JSON
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");

OkHttpClient client = new OkHttpClient();
JSONObject requestBody = new JSONObject();
requestBody.put("name","SpringBoot中文社区");

// 根据ContentType构建请求体
RequestBody body = RequestBody.create(mediaType, requestBody.toJSONString());

Request request = new Request.Builder()
        .url("http://localhost:8081/name")
        .post(body)  // 设置请求体
        .build();

Response response = client.newCall(request).execute();
response.body().string();

multipart/form-data

OkHttpClient client = new OkHttpClient();

// 需要上传的目标文件
File file = new File("D:\\demo.mp4");

// 创建Multipart表单体
RequestBody requestBody = new MultipartBody.Builder()

        .setType(MultipartBody.FORM) //设置ContentType为:multipart/form-data

        // 添加一个文件part,
        // part名称,文件名称,通过RequestBody构建请求体(文件的类型,目标文件)
        .addFormDataPart("file",file.getName(), RequestBody.create(MediaType.parse("image/png"), file))

        //RequestBody有N多重载方法,不仅仅可以基于本地磁盘构建表单项,还可以基于字节数据构建
        // .addFormDataPart("file",file.getName(), RequestBody.create(MediaType.parse("image/png"), new byte[]{}))

        // 添加一个普通的form-urlencoded part
        .addFormDataPart("name", "KevinBlandy")
        .build();

Request request = new Request.Builder()
        .url("http://localhost:8081/upload")
        .post(requestBody).build();

Response response = client.newCall(request).execute();
response.body().string();

其他的请求

基本上就是大同小异了,你可以通过阅读源码去进一步的了解

异步请求

可以通过回调的方式去处理服务端的响应结果

OkHttpClient okHttpClient = new OkHttpClient();

Request request = new Request.Builder()
        .url("http://localhost:8081/")
        .build();

Call call = okHttpClient.newCall(request);

// 该方法不会阻塞,通过设置回调方法来处理执行结果
call.enqueue(new Callback() {

    // 处理异常
    @Override
    public void onFailure(Call call, IOException e) {
        System.out.println(e.getMessage());
    }

    // 处理响应
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (response.isSuccessful()) {
            System.out.println(response.body().string());
        }
    }
});

尽量通过Builder来构建各个组件

如你所见,上面的Demo中。几乎处处都用到了工厂模式。Builder可以通过一系列的链式调用方法来设置属性,最后通过 build() 方法来创建我们需要组件。比起直接 new 出实例后,挨个设置要方便得多

OkHttpClient.Builder

其他的一些Builder就靠你自己去参阅源码或者文档了

OkHttpClient client = new OkHttpClient.Builder()
        .followRedirects(false)					//禁止OkHttp的重定向操作,自己处理重定向
        .followSslRedirects(false)				//禁止ssl重定向(80 -> 443)
        .cookieJar(new CookieJar() {			//cookie的序列化与反序列化接口,需要自己实现
            @Override
            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
            }
            @Override
            public List<Cookie> loadForRequest(HttpUrl url) {
                return null;
            }
        })
        .connectTimeout(Duration.ofMillis(2000))  // 设置连接超时时间
        // .... 还有很多配置(拦截器,SSL,缓存,事件监听器,代理.....),可以参阅文档或者源码
        .build();

在SpringBoot中使用OkHttp

最简单的整合就是把OkHttp的OkHttpClient 交给IOC管理,在需要的地方注入。

SpringBoot 也提供了一个非常不错的Http客户端。RestTemplate。而且在 SpringCloud 中都是靠它发起远程的rest调用。RestTemplate 可以设置一个 ClientHttpRequestFactory。它是一个接口,而且OkHttp提供了对它的实现:okHttp3ClientHttpRequestFactory

RestTemplate restTemplate = new RestTemplate();

OkHttpClient okHttpClient = new OkHttpClient();

// 实例化OkHttp工厂类
OkHttp3ClientHttpRequestFactory okHttp3ClientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory();

// 设置给RestTemplate
restTemplate.setRequestFactory(okHttp3ClientHttpRequestFactory);

看到这里,想必你在项目中使用Okhttp没问题了。

这个链接做的这么骚的吗

spirngboot注入配置的时候,需要配置https吗

看需求。如果不是SSL双向验证。客户端一般不需要配置证书。

嗯 确实骚啊?