Java中发送Http请求之OkHttpClient

Java中发送Http请求之OkHttpClient这是我参与11月更文挑战的第13天,活动详情查看:11月更文挑战 Java中Http请求的方式很多, OkHttpClient因其独特的特性,非常适合在常见的场景中使用

这是我参与11月更文挑战的第13天,活动详情查看:11月更文挑战

Java中Http请求的方式很多, OkHttpClient因其独特的特性,非常适合在常见的场景中使用.

1 OkHttpClient的简介

1 OkHttpClient说明

OkHttpClient是一个高效的HTTP客户端,其特性包含:

  • 支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
  • 连接池减少请求延时
  • 透明的GZIP压缩减少响应数据的大小
  • 缓存响应内容,避免一些完全重复的请求

2 OkHttpClient使用步骤

  • 创建OkHttpClient对象
  • 创建Request对象
  • 将Request 对象封装为Call
  • 通过Call 来执行同步或异步请求,调用execute方法同步执行,调用enqueue方法异步执行

3 OkHttpClient案例

@Slf4j
public class OkHttpDemo {

    // 创建OkHttpClient对象, 并设置超时时间 添加拦截器LoginInterceptor
    private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
        	.addInterceptor(new LoginInterceptor())
            .build();

    public static void main(String[] args) throws IOException {
        String url = "http://www.baidu.com";
        Request request = new Builder()
                .url(url)
                .get() // 不写,默认是GET请求
                .build();
		
        Call call = okHttpClient.newCall(request);
        // 异步调用
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                log.info("请求失败,异常信息为: {}", e.getMessage());
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response)
                    throws IOException {
                log.info("请求成功,返回信息为: {}", response.body().toString());
            }
        });
    }
}    

Interceptor拦截器

@Slf4j
public class LoginInterceptor implements Interceptor {

    /** * 统计登录接口完成时间 */
    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {

        Request request = chain.request();
        long begin = System.currentTimeMillis();
        Response  response = chain.proceed(request);
        long end = System.currentTimeMillis();

        // 请求路径中有/login 统计花费时间
        if (request.url().toString().contains("/login")) {
            log.info("接口处理总用时: {} ", end - begin);
        }

        return response;
    }
}

OkHttpClient对象

通过其内部类Builder的构造器模式,进行属性参数的初始化,常见的包括: 任务调度,协议,连接池,连接超时,读取超时等属性.

 public static final class Builder {
      @NotNull
      private Dispatcher dispatcher;
      @NotNull
      private ConnectionPool connectionPool;
      @NotNull
      private final List interceptors;
      private int callTimeout;
      private int connectTimeout;
      private int readTimeout;
      private int writeTimeout;
      private int pingInterval;
      private long minWebSocketMessageToCompress;
      @Nullable
      private RouteDatabase routeDatabase;
     
 }

Request对象

通过其内部类构造器模式,进行属性参数的初始化,常见的包括: 请求地址url,请求方式,请求头,请求体,标签参数等, 并且该构造中默认是GET请求.

  open class Builder {
    internal var url: HttpUrl? = null
    internal var method: String
    internal var headers: Headers.Builder
    internal var body: RequestBody? = null

    /** A mutable map of tags, or an immutable empty map if we don't have any. */
    internal var tags: MutableMap<Class<*>, Any> = mutableMapOf()

    constructor() {
      this.method = "GET"
      this.headers = Headers.Builder()
    }

    internal constructor(request: Request) {
      this.url = request.url
      this.method = request.method
      this.body = request.body
      this.tags = if (request.tags.isEmpty()) {
        mutableMapOf()
      } else {
        request.tags.toMutableMap()
      }
      this.headers = request.headers.newBuilder()
    }
  }

Call对象

通过OkHttpClient和Request对象构造Call对象,Call接口的唯一实现类RealCall. 其execute方法表示同步执行, enqueue方法表示异步执行.

    override fun execute(): Response {
    check(executed.compareAndSet(false, true)) { "Already Executed" }

    timeout.enter()
    callStart()
    try {
      client.dispatcher.executed(this)
      return getResponseWithInterceptorChain()
    } finally {
      client.dispatcher.finished(this)
    }
  }

   override fun enqueue(responseCallback: Callback) {
    check(executed.compareAndSet(false, true)) { "Already Executed" }

    callStart()
    client.dispatcher.enqueue(AsyncCall(responseCallback))
  }

Interceptor拦截器

Interceptor为所有拦截器的接口, 其实现类有 桥接拦截器BridgeInterceptor, 缓存拦截器CacheInterceptor, 服务拦截器CallServerInterceptor, 错误、重定向拦截器RetryAndFollowUpInterceptor, 连接拦截器ConnectInterceptor.

Call中execute方法调用的getResponseWithInterceptorChain()方法, 创建一个拦截器集合容器,首先添加用户自定义的拦截器, 错误、重定向拦截器,桥接拦截器,缓存拦截器,连接拦截器,服务拦截器.

整个拦截器执行链路,按照添加先后顺序执行,即先执行用户自定义拦截器.

  internal fun getResponseWithInterceptorChain(): Response {
    // Build a full stack of interceptors.
    val interceptors = mutableListOf<Interceptor>()
    interceptors += client.interceptors
    interceptors += RetryAndFollowUpInterceptor(client)
    interceptors += BridgeInterceptor(client.cookieJar)
    interceptors += CacheInterceptor(client.cache)
    interceptors += ConnectInterceptor
    if (!forWebSocket) {
      interceptors += client.networkInterceptors
    }
    interceptors += CallServerInterceptor(forWebSocket)

    val chain = RealInterceptorChain(
        call = this,
        interceptors = interceptors,
        index = 0,
        exchange = null,
        request = originalRequest,
        connectTimeoutMillis = client.connectTimeoutMillis,
        readTimeoutMillis = client.readTimeoutMillis,
        writeTimeoutMillis = client.writeTimeoutMillis
    )

    var calledNoMoreExchanges = false
    try {
      val response = chain.proceed(originalRequest)
      if (isCanceled()) {
        response.closeQuietly()
        throw IOException("Canceled")
      }
      return response
    } catch (e: IOException) {
      calledNoMoreExchanges = true
      throw noMoreExchanges(e) as Throwable
    } finally {
      if (!calledNoMoreExchanges) {
        noMoreExchanges(null)
      }
    }
  }

4 OkHttpClient常用工具类:

@Slf4j
public class OkHttpUtils {
    
        // 创建OkHttpClient对象, 并设置超时时间 
    private static final OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .build();

    /** * 同步GET请求 * * @param url 请求地址 */
    public static String getRequest(String url) {
        try {
            // 1 创建OkHttpClient对象 
            // 2 构建Request对象
            Request request = new Request.Builder()
                    .get()// 不写默认为GET请求
                    .url(url)
                    .build();
            // 3 发起请求获取响应值
            Response response = client.newCall(request).execute();
            // 4 根据响应结果判断
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new RuntimeException("请求异常,错误码为: " + response.code());
            }
        } catch (Exception e) {
            log.info("请求失败,错误信息为= {} ", e.getMessage());
        }
        return null;
    }
    
    /** * 同步POST请求 * * @param url 请求地址 * @param params 请求参数 */
    public static String postRequest(String url, Map<String, String> params) {

        try {
            // 1 创建OkHttpClient对象
            // 2 构建请求体
            MultipartBody body = new MultipartBody.Builder()
                    .setType(MediaType.parse("multipart/form-data"))
                    .addFormDataPart("username", params.get("username"))
                    .addFormDataPart("password", params.get("password"))
                    .build();
            // 3 构建Request对象
            Request request = new Request.Builder()
                    .post(body)
                    .url(url)
                    .build();
            // 4 发起请求获取响应值
            Response response = client.newCall(request).execute();

            // 5 根据响应结果判断
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new RuntimeException("请求异常,错误码为: " + response.code());
            }
        } catch (Exception e) {
            log.info("请求失败,错误信息为= {} ", e.getMessage());
        }
        return null;
    }
    
    
    /** * 同步GET请求 */
    public static String getRequest(String url) throws IOException {
        Request request = new Builder().url(url).build();
        Response response = execute(request);

        if (response.isSuccessful()) {
            return response.body().string();
        } else {
            throw new ArithmeticException("请求异常,错误码为: " + response.code());
        }

    }

    /** * 同步请求 */
    public static Response execute(Request request) throws IOException {
        return client.newCall(request).execute();
    }
    
    /** * 开启异步线程访问网络, 需要返回结果 */
    public static void enqueue(Request request, Callback callback) {
        client.newCall(request).enqueue(callback);
    }

    /** * 开启异步线程访问网络,不需要返回结果( Callback 返回为空) */
    public static void enqueue(Request request) {
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                log.info("请求失败,异常信息为: {} ", e.getMessage());
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response)
                    throws IOException {
                log.info("请求成功");
            }
        });
    }
    
}

参考资料:

blog.csdn.net/workingman_…

blog.csdn.net/weixin_4477…

blog.csdn.net/sinat_34241…

square.github.io/okhttp/3.x/…

今天的文章Java中发送Http请求之OkHttpClient分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/19780.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注