主页 > 手机  > 

OkHttp使用和源码分析学习(一)

OkHttp使用和源码分析学习(一)
使用 介绍

OkHttp 是一个高效的 HTTP 客户端,适用于 Android 和 Java 应用程序。它由 Square 公司开发,旨在简化网络请求的处理,并提供强大的功能,如连接池、GZIP 压缩、缓存、HTTP/2 支持等。 github地址: github /square/okhttp

核心特性 HTTP/2 支持:允许同一主机的请求共享一个 socket。连接池:减少请求延迟(如果 HTTP/2 不可用)。透明的 GZIP 压缩:自动压缩请求体,减少传输数据量。响应缓存:避免重复请求网络。同步和异步调用:支持同步阻塞调用和异步回调调用。WebSocket 支持:支持全双工通信。 核心组件 OkHttpClient:HTTP 客户端,用于发送请求和接收响应。通常设计为单例。Request:表示 HTTP 请求,包含 URL、方法、请求头、请求体等信息。Response:表示 HTTP 响应,包含状态码、响应头、响应体等信息。Call:表示一个已准备好执行的请求,可以同步或异步执行。Interceptor:拦截器,用于在请求和响应之间添加自定义逻辑(如日志、重试、缓存等)。 基本用法 步骤 添加依赖 在项目中引入 OkHttp 的依赖。如果你使用的是 Gradle,可以在 build.gradle 文件中添加以下依赖 implementation 'com.squareup.okhttp3:okhttp:4.9.3'

创建 OkHttpClient 实例 OkHttpClient 是 OkHttp 的核心类,用于发送 HTTP 请求和接收响应。通常将其设计为单例模式,以避免重复创建连接池和线程池。

构建 Request 对象 使用 Request.Builder 构建 HTTP 请求,设置 URL、请求方法(GET、POST 等)、请求头、请求体等。

发送请求

同步请求:使用 execute() 方法,阻塞当前线程直到收到响应。异步请求:使用 enqueue() 方法,在后台线程中执行请求,并通过回调处理响应。

处理响应 解析响应数据,检查状态码,获取响应体等。

同步 GET 请求 import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class SyncGetExample { public static void main(String[] args) throws Exception { // 创建 OkHttpClient 实例 OkHttpClient client = new OkHttpClient(); // 构建 Request 对象 Request request = new Request.Builder() .url(" jsonplaceholder.typicode /posts/1") .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { // 检查请求是否成功 if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 获取响应体并打印 System.out.println(response.body().string()); } } } 异步 GET 请求 import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import java.io.IOException; public class AsyncGetExample { public static void main(String[] args) { // 创建 OkHttpClient 实例 OkHttpClient client = new OkHttpClient(); // 构建 Request 对象 Request request = new Request.Builder() .url(" jsonplaceholder.typicode /posts/1") .build(); // 发送异步请求 client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 请求失败处理 e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { // 请求成功处理 if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 获取响应体并打印 System.out.println(response.body().string()); } }); } } POST 请求(提交表单) import okhttp3.FormBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; public class PostFormExample { public static void main(String[] args) throws Exception { // 创建 OkHttpClient 实例 OkHttpClient client = new OkHttpClient(); // 构建表单请求体 RequestBody formBody = new FormBody.Builder() .add("username", "testuser") .add("password", "testpassword") .build(); // 构建 Request 对象 Request request = new Request.Builder() .url(" example /login") .post(formBody) .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 获取响应体并打印 System.out.println(response.body().string()); } } } 文件上传(Multipart 请求) import okhttp3.*; import java.io.File; import java.io.IOException; public class FileUploadExample { public static void main(String[] args) throws Exception { // 创建 OkHttpClient 实例 OkHttpClient client = new OkHttpClient(); // 构建 Multipart 请求体 RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("title", "Square Logo") .addFormDataPart("image", "logo.png", RequestBody.create(new File("path/to/logo.png"), MediaType.parse("image/png"))) .build(); // 构建 Request 对象 Request request = new Request.Builder() .url(" example /upload") .post(requestBody) .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 获取响应体并打印 System.out.println(response.body().string()); } } } Head类型和添加 添加 使用Headers.Builder创建一个Headers对象,并添加需要的请求头 Headers.Builder headersBuilder = new Headers.Builder(); headersBuilder.add("Header-Name", "Header-Value"); Headers headers = headersBuilder.build(); 在创建Request对象时直接使用Request.Builder的addHeader方法添加头部信息 Request request = new Request.Builder() .url("http://example ") .addHeader("Header-Name1", "Header-Value1") .addHeader("Header-Name2", "Header-Value2") .build(); 头部类型 通用首部字段:适用于请求和响应消息,并提供一些通用信息。 名称说明Cache-Control用于指定缓存指令Connection控制当前事务完成后网络连接是否保持打开状态Date提供报文创建的日期和时间Transfer-Encoding对报文采用的编码方式Via显示报文经过的中间节点(代理、网关) 请求首部字段:提供关于请求本身的信息,如客户端的喜好和能力等。 名称说明Accept客户端告知服务器想要哪些媒体类型Accept-Charset客户端告知服务器想要哪些字符集Accept-Encoding客户端告知服务器想要哪些编码类型Accept-Language客户端告知服务器想要哪些语言Authorization包含用于服务器验证用户代理的凭据From提供客户端用户的E-mail地址Host指定服务器的域名和端口号Referer提供当前请求的URL来源User-Agent提供发送请求的应用程序的相关信息 响应首部字段:提供关于响应的信息,如资源的位置和状态等。 名称说明Location指示将页面重定向到的URLServer包含有关原始服务器用来处理请求的软件的信息Age对象已在代理缓存中的时间Expires响应被视为陈旧的日期/时间ETag标识资源版本的唯一字符串 实体首部字段:描述实体的元数据信息,如内容类型、长度和编码等。 名称说明Content-Type指示资源的媒体类型Content-Length表示发送给收件人的实体主体的大小Content-Encoding用于指定压缩算法Content-Language描述用于受众的语言Content-Location指示返回数据的备用位置 RequestBody 类型 表单数据(FormBody)

用于提交表单数据,内容类型为 application/x- -form-urlencoded。

import okhttp3.FormBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; public class FormBodyExample { public static void main(String[] args) throws Exception { OkHttpClient client = new OkHttpClient(); // 构建表单请求体 RequestBody formBody = new FormBody.Builder() .add("username", "testuser") .add("password", "testpassword") .build(); // 构建 Request 对象 Request request = new Request.Builder() .url(" example /login") .post(formBody) .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 打印响应体 System.out.println(response.body().string()); } } } JSON 数据(RequestBody.create)

用于提交 JSON 数据,内容类型为 application/json。

import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; public class JsonBodyExample { public static void main(String[] args) throws Exception { OkHttpClient client = new OkHttpClient(); // 定义 JSON 数据 String json = "{\"name\":\"John\", \"age\":30}"; MediaType JSON = MediaType.parse("application/json; charset=utf-8"); // 构建 JSON 请求体 RequestBody jsonBody = RequestBody.create(json, JSON); // 构建 Request 对象 Request request = new Request.Builder() .url(" example /api/user") .post(jsonBody) .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 打印响应体 System.out.println(response.body().string()); } } } 文件上传(MultipartBody)

用于上传文件或混合数据,内容类型为 multipart/form-data。

import okhttp3.*; import java.io.File; import java.io.IOException; public class MultipartBodyExample { public static void main(String[] args) throws Exception { OkHttpClient client = new OkHttpClient(); // 构建 Multipart 请求体 RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("title", "Square Logo") .addFormDataPart("image", "logo.png", RequestBody.create(new File("path/to/logo.png"), MediaType.parse("image/png"))) .build(); // 构建 Request 对象 Request request = new Request.Builder() .url(" example /upload") .post(requestBody) .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 打印响应体 System.out.println(response.body().string()); } } } 字符串数据(RequestBody.create)

用于提交纯文本数据,内容类型为 text/plain。

import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; public class StringBodyExample { public static void main(String[] args) throws Exception { OkHttpClient client = new OkHttpClient(); // 定义字符串数据 String text = "Hello, OkHttp!"; MediaType TEXT = MediaType.parse("text/plain; charset=utf-8"); // 构建字符串请求体 RequestBody textBody = RequestBody.create(text, TEXT); // 构建 Request 对象 Request request = new Request.Builder() .url(" example /api/text") .post(textBody) .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 打印响应体 System.out.println(response.body().string()); } } } 字节数组数据(RequestBody.create)

用于提交二进制数据。

import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; public class ByteArrayBodyExample { public static void main(String[] args) throws Exception { OkHttpClient client = new OkHttpClient(); // 定义字节数组数据 byte[] data = "Hello, OkHttp!".getBytes(); MediaType BINARY = MediaType.parse("application/octet-stream"); // 构建字节数组请求体 RequestBody byteBody = RequestBody.create(data, BINARY); // 构建 Request 对象 Request request = new Request.Builder() .url(" example /api/bytes") .post(byteBody) .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 打印响应体 System.out.println(response.body().string()); } } } 高级功能 拦截器

拦截器的作用:拦截器可以监控、修改请求和响应,用于在请求和响应之间插入自定义逻辑。

拦截器的类型:

应用拦截器:适用于全局逻辑处理。网络拦截器:适用于底层网络操作。

常见场景:

日志记录添加公共请求头重试机制修改请求或响应

拦截器可以自定义,实现步骤主要有如下几个:

实现 Interceptor 接口 创建一个类并实现 Interceptor 接口,重写 intercept() 方法。在 intercept() 方法中编写逻辑 在 intercept() 方法中,可以通过 Chain 对象获取请求和响应,并对其进行修改。将拦截器添加到 OkHttpClient 使用 OkHttpClient.Builder 的 addInterceptor() 或 addNetworkInterceptor() 方法添加拦截器。 日志拦截器

记录请求和响应的详细信息。

import okhttp3.*; import java.io.IOException; public class LoggingInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { // 获取请求 Request request = chain.request(); // 记录请求信息 long startTime = System.nanoTime(); System.out.println(String.format("发送请求: %s%n请求头: %s", request.url(), request.headers())); // 执行请求 Response response = chain.proceed(request); // 记录响应信息 long endTime = System.nanoTime(); System.out.println(String.format("收到响应: %s%n响应头: %s%n耗时: %.1fms", response.request().url(), response.headers(), (endTime - startTime) / 1e6d)); return response; } }

使用日志拦截器

import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class LoggingInterceptorExample { public static void main(String[] args) throws Exception { // 创建 OkHttpClient 并添加日志拦截器 OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new LoggingInterceptor()) .build(); // 构建 Request 对象 Request request = new Request.Builder() .url(" jsonplaceholder.typicode /posts/1") .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 打印响应体 System.out.println(response.body().string()); } } } 添加公共请求头拦截器

为所有请求添加统一的请求头(如认证信息)。

import okhttp3.*; import java.io.IOException; public class AuthInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { // 获取原始请求 Request originalRequest = chain.request(); // 添加公共请求头 Request newRequest = originalRequest.newBuilder() .header("Authorization", "Bearer token123") .header("User-Agent", "OkHttp Example") .build(); // 执行请求 return chain.proceed(newRequest); } }

使用公共请求头拦截器

import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class AuthInterceptorExample { public static void main(String[] args) throws Exception { // 创建 OkHttpClient 并添加拦截器 OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new AuthInterceptor()) .build(); // 构建 Request 对象 Request request = new Request.Builder() .url(" jsonplaceholder.typicode /posts/1") .build(); // 发送同步请求 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败,状态码: " + response.code()); } // 打印响应体 System.out.println(response.body().string()); } } } 缓存

OkHttp 支持 HTTP 缓存,可以通过设置缓存目录和大小来启用:

int cacheSize = 10 * 1024 * 1024; // 10 MB Cache cache = new Cache(new File("cacheDir"), cacheSize); OkHttpClient client = new OkHttpClient.Builder() .cache(cache) .build(); 超时设置 OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) // 连接超时 .readTimeout(10, TimeUnit.SECONDS) // 读取超时 .writeTimeout(10, TimeUnit.SECONDS) // 写入超时 .build(); WebSocket 支持

OkHttp 支持 WebSocket 协议,用于实现全双工通信:

OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("wss://echo.websocket.org") .build(); WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() { @Override public void onMessage(WebSocket webSocket, String text) { System.out.println("收到消息: " + text); } });
标签:

OkHttp使用和源码分析学习(一)由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“OkHttp使用和源码分析学习(一)