HttpUtils工具类(三)OKHttpClient使用详细教程

news/2024/9/18 14:53:10/ 标签: 网络, java

OkHttpClient 是一个由 Square 公司开发的 HTTP 客户端库,用于在 Android 和 Java 应用中进行网络请求。它支持同步和异步请求、连接池、超时设置、拦截器等功能,适合用于高性能网络请求,特别是在需要处理复杂的网络操作时。

一、OKHttpClient介绍

主要特点

  1. 同步和异步请求

    • 同步请求会在当前线程等待响应,适合不需要并发的简单请求。

    • 异步请求会将网络操作交由后台线程处理,不会阻塞主线程,适合需要并发处理或在 Android 等环境中使用。

  2. 连接池: OkHttp 默认会使用连接池来复用 HTTP 连接,从而提高性能,减少连接的建立和关闭的开销。

  3. 拦截器 (Interceptor): 拦截器允许在请求和响应时进行操作,例如可以在请求发送前添加认证信息,或在响应到达后进行日志记录。

  4. 自动处理 HTTP/2 和 SPDY: OkHttp 默认支持 HTTP/2 协议,可以提升多路复用性能,使多个请求共享一个 TCP 连接。

  5. 缓存机制: OkHttp 提供了默认的缓存机制,可以根据 HTTP 响应头自动缓存请求结果,减少重复网络请求。

  6. 超时控制: 可以对连接、读取和写入操作分别设置超时,避免长时间无响应的请求卡住应用。

二、在实际项目中的应用

(1)引入maven配置

<!-- ok的Http连接池 -->    
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.3</version>
</dependency>

(2)自定义HttpUtils工具类

import com.alibaba.fastjson.JSONObject;
import com.yan.project.httpUtils.okHttp2.HttpRequestBody;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;@Slf4j
public class OkHttpUtils {private OkHttpUtils() {throw new IllegalArgumentException("Utility class");}private static final String MIME_JSON = "application/json; charset=utf-8";private static OkHttpClient httpClient = new OkHttpClient.Builder().connectTimeout(3, TimeUnit.SECONDS).writeTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).addInterceptor((Interceptor.Chain chain) -> {Request req = chain.request();try {Response res = chain.proceed(req);return res;} catch (Exception ex) {throw ex;}}).build();// GET-无参public static String getJson(String url) throws IOException {return basicGet(url, null);}// GET-有参public static String get(String url, Map<String, Object> paramMap) throws Exception {StringBuilder sb = new StringBuilder(url);if (paramMap != null && !paramMap.isEmpty()) {Set<String> keySet = paramMap.keySet();for (String key : keySet) {sb.append(sb.toString().contains("?") ? "&" : "?");sb.append(key).append("=").append(paramMap.get(key));}url = sb.toString();}return basicGet(url, null);}// GET-有参、有请求头public static String getWithHeades(String url, Map<String, Object> paramMap, Map<String, String> headers) throws Exception {StringBuilder sb = new StringBuilder(url);if (paramMap != null && !paramMap.isEmpty()) {Set<String> keySet = paramMap.keySet();for (String key : keySet) {sb.append(sb.toString().contains("?") ? "&" : "?");sb.append(key).append("=").append(paramMap.get(key));}url = sb.toString();}return basicGet(url, headers);}// GET-jsonpublic static String getJsonWithHeader(String url, Map<String, String> headerMap) throws IOException {Request.Builder request = new Request.Builder().url(url).get().header("Accept", MIME_JSON);if (headerMap != null) {headerMap.forEach(request::header);}try (Response response = httpClient.newCall(request.build()).execute()) {log.info("response_code:{}, response_body:{}", response.code(), response.body().string());return response.body().string();}}// POST-json传参public static String postJsonWithHeader(String url, Object reqBody, Map<String, String> headers) throws IOException {Request.Builder request = new Request.Builder().url(url).header("Accept", MIME_JSON).post(FormBody.create(MediaType.parse(MIME_JSON), JSONObject.toJSONString(reqBody)));// 遍历并添加 headerif (headers != null) {headers.forEach(request::header);}try (Response response = httpClient.newCall(request.build()).execute()) {log.info("response_code:{}, response_body:{}", response.code(), response.body().string());return response.body().string();}}// POST-param传参public static String postParamWithHeader(String url, Map<String, Object> paramMap, Map<String, String> headers) throws IOException {FormBody.Builder formBody = new FormBody.Builder();if (Objects.nonNull(paramMap)) {paramMap.forEach((k, v) -> formBody.add(k, (String) v));}Request.Builder request = new Request.Builder().url(url).header("Accept", MIME_JSON).post(formBody.build());// 遍历并添加 headerif (headers != null) {headers.forEach(request::header);}try (Response response = httpClient.newCall(request.build()).execute()) {log.info("response_code:{}, response_body:{}", response.code(), response.body().string());return response.body().string();}}public static final String octet_stream_str = "application/octet-stream";public static final MediaType octet_stream = MediaType.parse(octet_stream_str);public static void putStream(String url, InputStream inputStream, long contentLength) {Response response;try {RequestBody requestBody2 = new HttpRequestBody(inputStream, contentLength);Request request = new Request.Builder().url(url).addHeader("Content-Type", octet_stream_str).put(requestBody2).build();response = httpClient.newCall(request).execute();String result = response.body().string();if (response.code() != 200) {throw new Exception("Saturn SDK stream upload failed, url:" + url + "response.code():" + response.code() + ", msg:" + result);}} catch (Exception e) {e.printStackTrace();} finally {closeQuietly(inputStream);}}public static String putFile(String url, File file) throws Exception {RequestBody requestBody = RequestBody.create(octet_stream, file);Request request = new Request.Builder().url(url).addHeader("Content-Type", octet_stream_str).put(requestBody).build();Response response = httpClient.newCall(request).execute();String result = response.body().string();int code = response.code();log.info("putFile end, url:{}, response.code:{}, result:{}", url, code, result);if (code != 200) {throw new Exception("putFile failed, response.code():" + code + ", result:" + result);}return result;}private static String basicGet(String url, Map<String, String> headers) throws IOException {Request.Builder builder = new Request.Builder().url(url).get();// 遍历并添加 headerif (headers != null) {headers.forEach(builder::header);}try (Response response = httpClient.newCall(builder.build()).execute()) {return response.body().string();}}private static String basicDelete(String url, Headers headers) throws IOException {Request.Builder builder = new Request.Builder().url(url).delete();if (headers != null) {builder.headers(headers);}try (Response response = httpClient.newCall(builder.build()).execute()) {return response.body().string();}}public static void closeQuietly(Closeable is) {if (is != null) {try {is.close();} catch (Exception ex) {log.error("Resources encounter an exception when closing,ex:{}", ex.getMessage());}}}
}

这个 OkHttpUtils 类封装了 OkHttpClient 来进行 HTTP 请求,支持 GET、POST、PUT 等常见的 HTTP 方法,并提供了对参数、请求头、文件上传等功能的支持。以下是它的主要功能和使用方法的解释:

  1. OkHttpClient 实例

    • 使用 OkHttpClient.Builder() 创建,设置了超时时间(连接超时 3 秒,读写超时 5 秒),并添加了拦截器。

  2. 静态方法

    • getJson, get, getWithHeades, getJsonWithHeader:用于 GET 请求,支持无参、有参数和请求头的场景。

    • postJsonWithHeader, postParamWithHeader:用于 POST 请求,支持 JSON 数据或表单数据传递。

    • putStream, putFile:用于 PUT 请求,支持流和文件上传。

    • basicGet, basicDelete:内部通用方法,分别处理 GET 和 DELETE 请求。

三、拓展和使用建议

  • 增强错误处理:当前仅在拦截器中简单处理了异常,可以考虑在各个方法中增加详细的异常处理机制。
  • 连接池管理:默认情况下,OkHttp 使用连接池来提升性能,类内部也可以进一步定制连接池策略来优化并发性能。
  • 异步支持:所有请求均为同步请求,适合使用时可以考虑用 OkHttp 提供的 enqueue() 方法进行异步操作,防止阻塞主线程。

通过这些封装,OkHttpUtils 能够方便地发送 HTTP 请求并处理响应。在实际项目中,你可以根据需要调整超时设置、缓存机制等配置。


http://www.ppmy.cn/news/1524197.html

相关文章

cell phone teardown 手机拆卸

tweezer 镊子 screwdriver 螺丝刀 opening tool 开口工具 repair 修理 battery 电池 rear panel 后盖 front and rear cameras 前后摄像头 volume button board 音量键线路板 headphone jack 耳机孔 a cracked screen 破裂屏 otherwise non-functional screen 其它坏屏 flex c…

Wni11 下 WSL 安装 CentOS

Wni11 下 WSL 安装 CentOS 方法一、安装包安装下载包安装安装打开 CentOS1. 从 Windows 终端 打开2. 从 PowerShell 打开 方法二、导入 CentOS 的 tar 文件进行安装0. 查看版本&#xff08;可选&#xff09;1. 导出 Docker 容器到 tar 文件2. 将 tar 文件导入 WSL2.1. 导入 tar…

【Linux 运维知识】Linux 编译后的内核镜像大小

Linux 内核镜像的大小取决于多个因素&#xff0c;包括内核的版本、启用的功能、模块的数量以及特定的编译配置。 以下是常见情况下不同内核镜像的大小范围&#xff1a; 1. 标准内核镜像大小 压缩后的内核镜像 (vmlinuz)&#xff1a; 压缩后的内核镜像文件&#xff0c;通常位于…

OpenCV视频处理练习案例-学习篇

需要实现的功能&#xff1a; 用OpenCV打开一段视频&#xff0c;将每一帧画面压缩成540p&#xff0c;对画面进行垂 直翻转&#xff0c;转为黑白&#xff0c;然后添加高斯噪声&#xff0c;把处理好的每一帧画面保存 成一个mp4文件保存到本地 Python代码如下&#xff1a; impor…

html 引入 css文档

1. 三种方法 html 引入 css文档有三种方式&#xff1a; 1.1 内部样式表 1.2 外部样式表 1.3 行内样式表

mysql数据库8.0小版本原地升级

mysql数据库8.0小版本原地升级 准备工作升级工作停库使用新版本软件启动数据库更新环境变量重启数据库 升级日志 OS release: CentOS 7.9升级前DB version: MySQL 8.0.30数据库升级安装包&#xff1a;mysql-8.0.36-linux-glibc2.12-x86_64.tar.xzMySQL Shell安装包&#xff1a;…

《自然语言处理 Transformer 模型详解》

一、引言 在自然语言处理领域&#xff0c;Transformer 模型的出现是一个重大的突破。它摒弃了传统的循环神经网络&#xff08;RNN&#xff09;和卷积神经网络&#xff08;CNN&#xff09;架构&#xff0c;完全基于注意力机制&#xff0c;在机器翻译、文本生成、问答系统等众多任…

(php伪随机数生成)[GWCTF 2019]枯燥的抽奖

审核源码发现加载check.php&#xff0c;审计发现使用了mt_rand()函数&#xff0c;这个函数生成的值是伪随机的 参考下面这篇文章 PHP mt_rand安全杂谈及应用场景详解 - FreeBuf网络安全行业门户 kali里面输入下载工具 git clone https://github.com/openwall/php_mt_seed.gi…

排序

一.排序概念及引用 1.排序概念 排序&#xff1a;使一串记录&#xff0c;按照其中某个或某些关键字大小&#xff0c;递增或递减排列起来的操作 稳定性&#xff1a;假定在待排序的序列中&#xff0c;存在多个相同的关键字&#xff0c;若经过排序&#xff0c;这些关键字的前后位…

漫谈设计模式 [12]:模板方法模式

引导性开场 菜鸟&#xff1a;老大&#xff0c;我最近在做一个项目&#xff0c;遇到了点麻烦。我们有很多相似的操作流程&#xff0c;但每个流程的细节又有些不同。我写了很多重复的代码&#xff0c;感觉很乱。你有啥好办法吗&#xff1f; 老鸟&#xff1a;嗯&#xff0c;听起…

【数据结构】顺序表的应用

基于动态顺序表实现通讯录 功能要求 1&#xff09;至少能够存储100个⼈的通讯信息 2&#xff09;能够保存用户信息&#xff1a;名字、性别、年龄、电话、地址等 3&#xff09;增加联系人信息 4&#xff09;删除指定联系人 5&#xff09;查找制定联系人 6&#xff09;修改指定…

集成电路学习:什么是MCU微控制器

一、MCU&#xff1a;微控制器 MCU&#xff0c;全称Microcontroller Unit&#xff0c;即微控制器&#xff0c;也常被称为单片机。它是一种集成了处理器&#xff08;CPU&#xff09;、存储器&#xff08;包括RAM和ROM&#xff09;、各种输入输出接口&#xff08;I/O&#xff09;、…

Meta:大语言模型可以通过自我批判取得大幅提升!

夕小瑶科技说 原创 作者 | 谢年年 论文的审稿模式想必大家都不会陌生&#xff0c;一篇论文除了分配多个评审&#xff0c;最后还将由PC综合评估各位审稿人的reviews撰写meta-review。 最近&#xff0c;来自Meta的研究团队将这一模式引进到大模型的对齐训练中。模型同时扮演 执…

《OpenCV计算机视觉》—— 身份证号码识别案例

文章目录 一、案例实现的整体思路二、代码实现1.首先定义两个函数2.模板图像中数字的定位处理3.身份证号码数字的定位处理4.使用模板匹配&#xff0c;计算匹配得分&#xff0c;找到正确结果 一、案例实现的整体思路 下面是一个数字0~9的模板图片 案例身份证如下&#xff1a; 对…

containerd二进制安装

文章目录 安装版本&#xff08;在2024年9月10日是新版&#xff09;方式1&#xff1a;yum安装&#xff08;不推荐&#xff09;设置主机名设置IP获取阿里YUM源查询containerd安装验证与启动服务测试命令 方式2&#xff1a;二进制安装&#xff08;推荐&#xff09;安装之前先了解c…

每周心赏|教师节“AI大礼包”:3款教学神器让你AI不释手

教师节“AI大礼包”真的来了&#xff01; 家人们谁懂啊&#xff0c;当学生时不想上课&#xff0c;当老师后不想上班…… 3款超会整活的教师必备AI神器&#xff0c;终于让我给挖到了&#xff1a;一键拥有金牌名师教学经验&#xff0c;助力撰写教案、高效赋能学生、总结工作成果…

流浪地球发动机

代码来自此处 if __name__ __main__:# 发动机的总个数, 计划手动启动的发动机总个数n, e map(int, input().split())# 记录每个发动机的最终启动时刻, 初始化为极大值&#xff0c;方便后面取最早启动时刻launches [1001] * nfor _ in range(e):# 发动机的手动启动时刻, 发动…

通信工程学习:什么是FDM频分复用、TDM时分复用、WDM波分复用、CDM码分复用

FDM频分复用、TDM时分复用、WDM波分复用、CDM码分复用 FDM频分复用、TDM时分复用、WDM波分复用、CDM码分复用是通信领域中常见的四种复用技术&#xff0c;它们各自具有不同的特点和应用场景。以下是对这四种复用技术的详细解释&#xff1a; 一、FDM频分复用&#xff08;Frequ…

Vue 中的 Vuex:全面解析与使用教程

什么是 Vuex&#xff1f; Vuex 是 Vue.js 官方提供的状态管理模式&#xff0c;专为 Vue.js 应用设计。它通过集中式存储管理应用中所有的组件状态&#xff0c;允许组件之间更方便地共享数据&#xff0c;并提供了一套规则来确保状态以可预测的方式发生变化。Vuex 对大型应用尤其…

Inspector里面可以编辑的变量相关

1.私有和保护变量无法在Inspector中编辑 2.给私有和保护变量加个特性[SerializeField]&#xff08;强制序列化字段特性&#xff09;就可以在inspector中看到和修改了 序列化就是把一个对象保存到一个文件或数据库字段中去 3.公共的也不让其显示编辑 给变量前加特性[HideInIn…