自从用了 OkHttp,别的都完全不想用了!

简介: Java封装OkHttp3工具类,适用于Java后端开发者说实在话,用过挺多网络请求工具,有过java原生的,HttpClient3和4,但是个人感觉用了OkHttp3之后,之前的那些完全不想再用了。怎么说呢,代码轻便,使用起来很很很灵活,响应快,比起HttpClient好用许多。当然,这些是我个人观点,不喜勿喷。
  • 准备工作
  • 工具类代码
  • 使用教程
  • 结语

Java封装OkHttp3工具类,适用于Java后端开发者

说实在话,用过挺多网络请求工具,有过java原生的,HttpClient3和4,但是个人感觉用了OkHttp3之后,之前的那些完全不想再用了。怎么说呢,代码轻便,使用起来很很很灵活,响应快,比起HttpClient好用许多。当然,这些是我个人观点,不喜勿喷。

准备工作

Maven项目在pom文件中引入jar包

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.10.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.60</version>
</dependency>

引入json是因为工具类中有些地方用到了,现在通信都流行使用json传输,也少不了要这个jar包

推荐下自己做的 Spring Boot 的实战项目:

https://github.com/YunaiV/ruoyi-vue-pro

工具类代码

import com.alibaba.fastjson.JSON;
import okhttp3.*;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class OkHttpUtils {
    private static volatile OkHttpClient okHttpClient = null;
    private static volatile Semaphore semaphore = null;
    private Map<String, String> headerMap;
    private Map<String, String> paramMap;
    private String url;
    private Request.Builder request;
    /**
     * 初始化okHttpClient,并且允许https访问
     */
    private OkHttpUtils() {
        if (okHttpClient == null) {
            synchronized (OkHttpUtils.class) {
                if (okHttpClient == null) {
                    TrustManager[] trustManagers = buildTrustManagers();
                    okHttpClient = new OkHttpClient.Builder()
                            .connectTimeout(15, TimeUnit.SECONDS)
                            .writeTimeout(20, TimeUnit.SECONDS)
                            .readTimeout(20, TimeUnit.SECONDS)
                            .sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager) trustManagers[0])
                            .hostnameVerifier((hostName, session) -> true)
                            .retryOnConnectionFailure(true)
                            .build();
                    addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
                }
            }
        }
    }
    /**
     * 用于异步请求时,控制访问线程数,返回结果
     *
     * @return
     */
    private static Semaphore getSemaphoreInstance() {
        //只能1个线程同时访问
        synchronized (OkHttpUtils.class) {
            if (semaphore == null) {
                semaphore = new Semaphore(0);
            }
        }
        return semaphore;
    }
    /**
     * 创建OkHttpUtils
     *
     * @return
     */
    public static OkHttpUtils builder() {
        return new OkHttpUtils();
    }
    /**
     * 添加url
     *
     * @param url
     * @return
     */
    public OkHttpUtils url(String url) {
        this.url = url;
        return this;
    }
    /**
     * 添加参数
     *
     * @param key   参数名
     * @param value 参数值
     * @return
     */
    public OkHttpUtils addParam(String key, String value) {
        if (paramMap == null) {
            paramMap = new LinkedHashMap<>(16);
        }
        paramMap.put(key, value);
        return this;
    }
    /**
     * 添加请求头
     *
     * @param key   参数名
     * @param value 参数值
     * @return
     */
    public OkHttpUtils addHeader(String key, String value) {
        if (headerMap == null) {
            headerMap = new LinkedHashMap<>(16);
        }
        headerMap.put(key, value);
        return this;
    }
    /**
     * 初始化get方法
     *
     * @return
     */
    public OkHttpUtils get() {
        request = new Request.Builder().get();
        StringBuilder urlBuilder = new StringBuilder(url);
        if (paramMap != null) {
            urlBuilder.append("?");
            try {
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    urlBuilder.append(URLEncoder.encode(entry.getKey(), "utf-8")).
                            append("=").
                            append(URLEncoder.encode(entry.getValue(), "utf-8")).
                            append("&");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            urlBuilder.deleteCharAt(urlBuilder.length() - 1);
        }
        request.url(urlBuilder.toString());
        return this;
    }
    /**
     * 初始化post方法
     *
     * @param isJsonPost true等于json的方式提交数据,类似postman里post方法的raw
     *                   false等于普通的表单提交
     * @return
     */
    public OkHttpUtils post(boolean isJsonPost) {
        RequestBody requestBody;
        if (isJsonPost) {
            String json = "";
            if (paramMap != null) {
                json = JSON.toJSONString(paramMap);
            }
            requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        } else {
            FormBody.Builder formBody = new FormBody.Builder();
            if (paramMap != null) {
                paramMap.forEach(formBody::add);
            }
            requestBody = formBody.build();
        }
        request = new Request.Builder().post(requestBody).url(url);
        return this;
    }
    /**
     * 同步请求
     *
     * @return
     */
    public String sync() {
        setHeader(request);
        try {
            Response response = okHttpClient.newCall(request.build()).execute();
            assert response.body() != null;
            return response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            return "请求失败:" + e.getMessage();
        }
    }
    /**
     * 异步请求,有返回值
     */
    public String async() {
        StringBuilder buffer = new StringBuilder("");
        setHeader(request);
        okHttpClient.newCall(request.build()).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                buffer.append("请求出错:").append(e.getMessage());
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                assert response.body() != null;
                buffer.append(response.body().string());
                getSemaphoreInstance().release();
            }
        });
        try {
            getSemaphoreInstance().acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return buffer.toString();
    }
    /**
     * 异步请求,带有接口回调
     *
     * @param callBack
     */
    public void async(ICallBack callBack) {
        setHeader(request);
        okHttpClient.newCall(request.build()).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callBack.onFailure(call, e.getMessage());
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                assert response.body() != null;
                callBack.onSuccessful(call, response.body().string());
            }
        });
    }
    /**
     * 为request添加请求头
     *
     * @param request
     */
    private void setHeader(Request.Builder request) {
        if (headerMap != null) {
            try {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    request.addHeader(entry.getKey(), entry.getValue());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 生成安全套接字工厂,用于https请求的证书跳过
     *
     * @return
     */
    private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {
        SSLSocketFactory ssfFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ssfFactory;
    }
    private static TrustManager[] buildTrustManagers() {
        return new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }
                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
        };
    }
    /**
     * 自定义一个接口回调
     */
    public interface ICallBack {
        void onSuccessful(Call call, String data);
        void onFailure(Call call, String errorMsg);
    }
}

推荐下自己做的 Spring Cloud 的实战项目:

https://github.com/YunaiV/onemall

使用教程

public static void main(String[] args) {
    // get请求,方法顺序按照这种方式,切记选择post/get一定要放在倒数第二,同步或者异步倒数第一,才会正确执行
    OkHttpUtils.builder().url("请求地址,http/https都可以")
            // 有参数的话添加参数,可多个
            .addParam("参数名", "参数值")
            .addParam("参数名", "参数值")
            // 也可以添加多个
            .addHeader("Content-Type", "application/json; charset=utf-8")
            .get()
            // 可选择是同步请求还是异步请求
            //.async();
            .sync();
    // post请求,分为两种,一种是普通表单提交,一种是json提交
    OkHttpUtils.builder().url("请求地址,http/https都可以")
            // 有参数的话添加参数,可多个
            .addParam("参数名", "参数值")
            .addParam("参数名", "参数值")
            // 也可以添加多个
            .addHeader("Content-Type", "application/json; charset=utf-8")
            // 如果是true的话,会类似于postman中post提交方式的raw,用json的方式提交,不是表单
            // 如果是false的话传统的表单提交
            .post(true)
            .sync();
    // 选择异步有两个方法,一个是带回调接口,一个是直接返回结果
    OkHttpUtils.builder().url("")
            .post(false)
            .async();
    OkHttpUtils.builder().url("").post(false).async(new OkHttpUtils.ICallBack() {
        @Override
        public void onSuccessful(Call call, String data) {
            // 请求成功后的处理
        }
        @Override
        public void onFailure(Call call, String errorMsg) {
            // 请求失败后的处理
        }
    });
}

结语

封装的明明白白,使用的简简单单,简单的几下就能做请求,用建造者模式是真的舒服

相关文章
|
人工智能
assert()函数(断言函数)
assert()函数(断言函数)
356 0
assert()函数(断言函数)
|
Java
Java如何实现证件照换底色| 背景换色
Java如何实现证件照换底色| 背景换色
859 1
|
存储 缓存 NoSQL
Spring-Boot实战|分布式缓存-JPA的二级缓存-Redis
以JPA为ORM框架的微服务,默认是二级缓存是关闭的。因为在分布式集群架构下,本地的二级缓存必然会带来多个微服务实例缓存不一致问题。将二级缓存移交给第三方中间件可以很好的解决缓存不一致问题。而Redis一款高性能的K-V存储中间件,在保证缓存一致性的同时,还能提供高性能,高可用的特性。本篇文章就是基于开源框架Hibernate-Redis,将Redis作为为JPA的二级缓存实现
5334 0
Spring-Boot实战|分布式缓存-JPA的二级缓存-Redis
|
Windows 计算机视觉 安全
流媒体技术学习笔记之(十三)Windows安装FFmpeg
一、下载地址: 网址:https://ffmpeg.org/ 选择Windows版本:https://ffmpeg.org/download.html#build-windows 二、解压安装: 下载并解压FFmpeg文件夹,它会生成一个类似名为“ffmpeg-20150504-git-eb9fb50-win32-static”的新文件夹:   打开你想安装的任意磁盘,例如:d盘。
4330 0
|
JavaScript 前端开发 安全
15个最佳的代码评审(Code Review)工具
  代码评审可以被看作是计算机源代码的测试,它的目的是查找和修复引入到开发阶段的应用程序的错误,提高软件的整体素质和开发者的技能。代码审查程序以各种形式,如结对编程,代码抽查等。在这个列表中,我们编制了15个最好的代码审查工具,这将有助于开发者节省代码审查时间。
4965 0
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第8天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建并配置 Spring Boot 项目,实现后端 API 和安全配置。接着,使用 Ant Design Pro Vue 脚手架创建前端项目,配置动态路由和菜单,并创建相应的页面组件。最后,通过具体实践心得,分享了版本兼容性、安全性、性能调优等注意事项,帮助读者快速搭建高效且易维护的应用框架。
280 3
|
算法 API 开发工具
ArcFace
ArcFace 是虹软公司开发的一款人脸识别 SDK,它具有高性能、高精度、高鲁棒性等特点,支持多种人脸检测、识别和跟踪技术,可用于多种场景,如手机解锁、身份认证、人脸支付等。
593 1
|
存储 人工智能 开发框架
认识什么是互联网数据中心(IDC)
互联网数据中心(IDC)拥有高速带宽、高性能网络与安全环境,提供服务器托管、租用等服务。它是数据存储与流通的核心,支持互联网内容提供商、企业和各类网站的大规模、高质量需求。机房维护涵盖多方面,确保设备稳定运行。中国IDC行业快速发展,机房按星级划分,从一星到五星,标准逐步提升,体现国家信息基础设施的进步与成熟。国际上,Uptime Institute的Tier等级进一步规范了数据中心的可用性与可靠性标准。
2608 6
|
存储 SQL Java
TDengine配置
【5月更文挑战第13天】TDengine配置
368 0
|
消息中间件 JavaScript 小程序
OkHttp完美封装,一行搞完外部请求
OkHttp完美封装,一行搞完外部请求