美文网首页
OkHttp3 快速入门(一)

OkHttp3 快速入门(一)

作者: coding400 | 来源:发表于2020-05-10 16:24 被阅读0次
    okhttp.png

    OkHttp 是什么

    OkHttp 是一个 Http 客户端, 和 Apache Httpclient 类似, 但底层网络连接封装不一样, OkHttp 使用的是 okio, Httpclient 直接使用底层 Socket 来封装网络连接, 更多细节后面再研究, 这里主要记录 OkHttp 的使用方法

    提供了什么功能

    这里直接截取了官网的介绍

    1. HTTP/2 support allows all requests to the same host to share a socket.
    2. Connection pooling reduces request latency (if HTTP/2 isn’t available).
    3. Transparent GZIP shrinks download sizes.
    4. Response caching avoids the network completely for repeat requests.

    当然这里并非全部, 个人理解的是 连接池、异步、重试、异常处理等重要功能都有

    核心对象介绍

    Call

    该接口代表一个可向发起请求的对象(使用内部持有的 OkHttpClient 发送请求),包含了 request/response 流,可以被 canceled,只能被执行一次

    Request

    代表 http 请求中的 request 对象,通过该对象封装请求数据,如:method、request header、url、request body 等

    使用 Builder 建造者模式来封装请求

        Request request = new Request.Builder()
            .get()
            .url("http://www.baidu.com")
            .header("Accept", "application/json")
            .build();
    
    1. get() 使用 GET 方法,同样的还有 post()、head()、put() 等
    2. url() 请求路径
    3. header() 添加请求头

    OkHttpClient

    创建 Call 对象的工厂,可以被用来发送 http 请求并解析返回的 response。
    该对象应该在所有 http 调用者中共享,因为 OkHttpClient 对连接进行了缓存和复用,当所有 http 调用端共享该对象时,意味着同时共享了所有的 connection pool , 并且降低了延迟和内存开销。异步调用时,由于使用内部线程池来发送 http 请求,因此在异步调用过程中,共享 OkHttpClient 还共享了线程池

    创建方式
    1. 使用默认配置
    OkHttpClient okHttpClient = new OkHttpClient();
    
    1. 使用自定义配置
       OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .readTimeout(500, TimeUnit.MILLISECONDS)
            .build();
    
    1. 使用 execute 同步发送 GET 请求
        Request request = new Request.Builder()
            .get()
            .url("http://www.baidu.com")
            .header("Accept", "application/json")
            .build();
        try {
          Response response = okHttpClient.newCall(request).execute();
          System.out.println(response.body().string());
        } catch (IOException e) {
          e.printStackTrace();
        }
    
    1. 使用 execute 同步发送 POST 请求
        Request request = new Builder()
            .url("")
            // 设置 request header 或 response body 的 Content-Type 类型
            .post(RequestBody.create(MediaType.parse("application/json;charset=utf-8"), json))
            .build();
        try {
          Response response = okHttpClient.newCall(request).execute();
          System.out.println(response.body().string());
        } catch (IOException e) {
          e.printStackTrace();
        }
    
    1. 使用 enqueue 异步发送 GET 请求
        CountDownLatch latch = new CountDownLatch(1);
        okHttpClient.newCall(request).enqueue(new Callback() {
          @Override
          public void onFailure(Call call, IOException e) {
            System.out.println(e);
          }
    
          @Override
          public void onResponse(Call call, Response response) throws IOException {
            System.out.println(response.body().string());
            latch.countDown();
          }
        });
        latch.await();
    

    Interceptor

    Interceptor 为实现拦截器的标准接口,实现该接口之后,在 intercept(Chain chain) 中必须调用 chain.proceed(request) 方法,通过拦截器链模式来观察整个网络请求

    如:用该拦截器来记录每次请求时间,并将超过 500 毫秒的请求记录下来

    @Component
    @Slf4j
    public class TimeLogInterceptor implements Interceptor {
    
      @Override
      public Response intercept(Chain chain) throws IOException {
        Response response;
        Request rq = chain.request();
        long start = System.currentTimeMillis();
        try {
          response = chain.proceed(rq);
        } catch (Exception e) {
          log.error("error call request,cost>{},uri>{},e->{}", System.currentTimeMillis() - start,
              rq.url(), e);
          throw e;
        } finally {
          long end = System.currentTimeMillis();
          long cost = end - start;
          if (cost > 500) {
            log.warn("RestTemplate cost time exceed={} ms,uri={}", cost, rq.url());
          }
        }
    return response;
    }
    

    可通过 addInterceptor 或者 addNetworkInterceptor 添加,addInterceptor 添加的为全局拦截器,addNetworkInterceptor 添加的为网络拦截器,区别是:addInterceptor 只会调用一次,addNetworkInterceptor 随着网络请求的次数变化,如:当发生请求重试时,此时内部的拦截器将对 addNetworkInterceptor 中添加的拦截器进行多次调用

       OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .readTimeout(500, TimeUnit.MILLISECONDS)
            .addInterceptor(xxx)
            .addNetworkInterceptor(xx)
            .build();
    

    ConnectionPool

    该类用来管理 HTTP 和 HTTP/2 复用的连接,以便降低网络延迟。HTTP 请求通过同一请求地址来共用连接

       ConnectionPool connectionPool = new ConnectionPool(100, 1, TimeUnit.MINUTES);
       OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .readTimeout(500, TimeUnit.MILLISECONDS)
             .connectionPool(connectionPool)
            .build();
    

    构造方法接受 3 个参数,分别代表,最大闲置连接、最长闲置时间、闲置时间单位,默认的是最多 5 个连接,最长保持 5 分钟,关于如何设置闲置时间,需要根据被调用端的 KeepAlive 的时间

    相关文章

      网友评论

          本文标题:OkHttp3 快速入门(一)

          本文链接:https://www.haomeiwen.com/subject/lzmzwhtx.html