文章目录

  • 一、简介
    • 1、特性
  • 二、导入依赖
  • 三、创建 get 请求
  • 四、创建 post 请求
  • 五、创建异步请求(MultipartBody 表单)
  • 六、FormBody 表单参数
  • 七、OkhttpConfig 配置类
  • 八、OkhttpUtil 工具类
  • 九、小结

一、简介

Square 公司开源的 OkHttp

okhttp 官网 https://square.github.io/okhttp/

  • 网络编程(含 UrlConnection 发送 HTTP 请求下载文件):https://blog.csdn.net/qq_41538097/article/details/118722718
  • Apache HttpComponents 简单使用:https://blog.csdn.net/qq_41538097/article/details/123719298
  • RestTemplate简单使用:https://blog.csdn.net/qq_41538097/article/details/123560238
  • okhttp3简单使用:https://blog.csdn.net/qq_41538097/article/details/123677614
  • HttpURLConnection 简单使用:https://blog.csdn.net/qq_41538097/article/details/123697432
1、特性

1)支持HTTP2,对一台机器的所有请求共享同一个socket连接(同域名下所有通信都在单个连接上完成,消除了因多个连接而带来的延时和内存消耗)。

2)内置连接池,支持连接复用,减少请求延迟

3)透明的GZIP压缩减少响应数据的大小

4)通过缓存避免重复请求

5)失败时自动重连,自动重定向

当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。

使用:OkHttp 是一个适用于 Android、Kotlin 和 Java 应用的 HTTP 和 HTTP/2 客户端,它的请求/响应 API 使用构造器模式 builders 来设计,它支持阻塞式的同步请求和带回调的异步请求。

如果你使用 OkHttpClient,你不用重写你的代码,okhttp-urlconnection 模块实现了 java.net.HttpURLConnection 中的API,okhttp-apache 模块实现了 HttpClient 中的API

<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.3</version>
</dependency>

持续更新,和上面的同版本更新

<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp-urlconnection</artifactId><version>4.9.3</version>
</dependency>

2016 停止更新

<dependency><groupId>com.squareup.okhttp</groupId><artifactId>okhttp-apache</artifactId><version>2.7.5</version>
</dependency>

二、导入依赖

        <dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.3</version></dependency>

三、创建 get 请求

因为是测试,OkHttpClient 是新建的对象,所以不需要配置类,如果需要 bean 工厂可以添加配置类步骤七,工具类步骤八

    @Testpublic void getUrlParams() throws IOException {OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间.readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间.build();String url = "http://127.0.0.1:8080/rest/get/url_path_params?name=admin&id=98";Request.Builder builder = new Request.Builder();Request request = builder.url(url).build();Response response = okHttpClient.newCall(request).execute();ResponseBody body = response.body();System.out.println(body.string());}

四、创建 post 请求

post 请求传递 json 数据 Content-Type:application/json; charset=utf-8

    @PostMapping("/post/params_json_list")public JSONObject postParamsJsonList(@RequestBody List<Map<String, Object>> list) {JSONObject jsonObject = JSON.parseObject("{\"message\":\"SUCCESS\",\"code\":200,\"type\":\"okhttp3\"}");jsonObject.put("body", list);return jsonObject;}

RequestBody 封装 body 参数

    @Testpublic void postParamsJson() throws IOException {OkHttpClient build = new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build();String json = "{\"name\": \"admin\",\"id\": 10}";String url = "http://127.0.0.1:8080/okhttp3/post/params_json";RequestBody requestBody = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8"));Request request = new Request.Builder().post(requestBody).url(url).build();Response execute = build.newCall(request).execute();ResponseBody responseBody = execute.body();assert responseBody != null;log.info(responseBody.string());}

五、创建异步请求(MultipartBody 表单)

form 表单上传表单(含文件)Content-Type:multipart/form-data;

@PostMapping("/post/params_from_async")public JSONObject postParamsFromAsync(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws InterruptedException, IOException, ServletException {TimeUnit.SECONDS.sleep(30);JSONObject jsonObject;TreeMap<String, Object> treeMap = new TreeMap<>();Collection<Part> parts = request.getParts();parts.forEach((part) -> {if (part.getContentType() == null) {treeMap.put(part.getName(), request.getParameter(part.getName()));}});String s = UUID.randomUUID().toString().replace("-", "").substring(0, 5) + Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().indexOf("."));try {file.transferTo(new File("I:\\spring\\spring-boot-aop-test\\file\\" + s));jsonObject = JSON.parseObject("{\"message\":\"文件下载成功\",\"code\":200,\"type\":\"okhttp3\"}");jsonObject.put("body", treeMap);} catch (IOException e) {e.printStackTrace();jsonObject = JSON.parseObject("{\"message\":\"文件下载失败\",\"code\":201,\"type\":\"okhttp3\"}");}return jsonObject;}

测试方法

    @Testpublic void postParamsFromAsync() throws IOException {String url = "http://127.0.0.1:8080/okhttp3/post/params_from_async";File file = new File("C:\\Users\\Administrator\\Pictures\\图标\\influxdb-studio.png");RequestBody multipartBody = MultipartBody.create(file, MediaType.parse("image/png"));MultipartBody body = new MultipartBody.Builder().addFormDataPart("file", "influxdb.png", multipartBody).addFormDataPart("age", "18").build();Request request = new Request.Builder().post(body).url(url).addHeader("Connection", "keep-alive").build();okHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {log.error("okhttp", "onFailure: " + e.getMessage());}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {log.info("okhttp", "onResponse: " + response.body().string());}});}

六、FormBody 表单参数

form 表单上传表单 Content-Type:application/x-www-form-urlencoded

    @PostMapping("/post/params_from")public JSONObject postParamsFrom(HttpServletRequest request) throws InterruptedException, IOException, ServletException {JSONObject jsonObject;Map<String, Object> treeMap = new TreeMap<>();Map<String, String[]> parameterMap = request.getParameterMap();parameterMap.forEach((key, value) -> {if (value.length == 1) {treeMap.put(key, value[0]);} else {treeMap.put(key, value);}});jsonObject = JSON.parseObject("{\"message\":\"表单读取成功\",\"code\":200,\"type\":\"okhttp3\"}");if (treeMap.keySet().size() > 0) {jsonObject.put("body", treeMap);}return jsonObject;}

测试方法

    @AutowiredOkHttpClient okHttpClient;@Testpublic void postParamsFrom() throws IOException {String url = "http://127.0.0.1:8080/okhttp3/post/params_from";LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();linkedHashMap.put("password", "123456");linkedHashMap.put("address", "西安");FormBody.Builder builder = new FormBody.Builder();builder.add("name", "admin");linkedHashMap.forEach((key, value) -> {builder.add(key, value);});RequestBody formBody = builder.build();Request request = new Request.Builder().post(formBody).url(url).addHeader("Connection", "keep-alive").build();Response response = okHttpClient.newCall(request).execute();log.info(response.body().string());}

七、OkhttpConfig 配置类

详细配置参考 https://www.freesion.com/article/3815946206/

@Configuration
@Slf4j
public class OkHttpConfig {@Beanpublic OkHttpClient okHttpClient() throws NoSuchAlgorithmException, KeyStoreException {// 详细配置可参考 https://www.freesion.com/article/3815946206/return new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS)      //设置连接超时.readTimeout(60, TimeUnit.SECONDS)         //设置读超时.writeTimeout(60, TimeUnit.SECONDS)        //设置写超时.retryOnConnectionFailure(true)                     //是否自动重连// 设置https配置,此处忽略了所有证书.sslSocketFactory(sslSocketFactory(), new EasyX509TrustManager(null))// 验证服务器的证书域名。在https握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口的实现程序来确定是否应该允许此连接.hostnameVerifier(new HostnameVerifier() {@Overridepublic boolean verify(String hostname, SSLSession session) {return true;}})// 拦截器日志记录.addInterceptor((Interceptor.Chain chain) -> {Request request = chain.request();log.info("intercept 接口地址:" + request.url()+ "\r\n接口参数):" + request.body().toString());return chain.proceed(chain.request());})// 添加证书,一般不要设置.certificatePinner(new CertificatePinner.Builder().add("test1.com", "sha1/sdfsdsdsdsdsdsdsdsdsdsdds=").add("test2.com", "sha1/sdsdsdsdsdsdsdsdsdssdssds=").build())//.connectionSpecs(...) // 设置连接的规格、TLS版本和密码套件等,最好不要去设置//.socketFactory(new SocketFactory() {...}) // 使用定制的用于http请求的套接字
/*                .authenticator(new Authenticator() { // 添加授权证书@Overridepublic Request authenticate(Route route, Response response) throws IOException {}}) */.cache(new Cache(new File("cache.tmp"), 10 * 1024 * 1024)) // 10M缓存// 定义连接池,最多有五个空闲连接,每个空闲连接最多保持6分钟.connectionPool(new ConnectionPool(5, 6, TimeUnit.MINUTES))// 指定分发器,即异步执行http请求时的线程池,http响应的回调也是在此线程池的线程中执行// .dispatcher(new Dispatcher(new ThreadPoolExecutor(...))).followRedirects(true)       // 允许http重定向.followSslRedirects(false)   // 截断https的重定向.pingInterval(30, TimeUnit.SECONDS) // 设置ping检测网络连通性的间隔。默认为0//.proxy(...) // 设置单个代理//.proxyAuthenticator(...)  // 设置代理验证//.proxySelector(...) // 为不同的链接设置不同的代理.build();}public class EasyX509TrustManager implements X509TrustManager {private X509TrustManager standardTrustManager = null;/*** Constructor for EasyX509TrustManager.*/public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException,KeyStoreException {super();TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());factory.init(keystore);TrustManager[] trustmanagers = factory.getTrustManagers();if (trustmanagers.length == 0) {throw new NoSuchAlgorithmException("no trust manager found");}this.standardTrustManager = (X509TrustManager) trustmanagers[0];}/*** @see X509TrustManager#checkClientTrusted(X509Certificate[],* String authType)*/public void checkClientTrusted(X509Certificate[] certificates, String authType)throws CertificateException {standardTrustManager.checkClientTrusted(certificates, authType);}/*** @see X509TrustManager#checkServerTrusted(X509Certificate[],* String authType)*/public void checkServerTrusted(X509Certificate[] certificates, String authType)throws CertificateException {if ((certificates != null) && (certificates.length == 1)) {certificates[0].checkValidity();} else {standardTrustManager.checkServerTrusted(certificates, authType);}}/*** @see X509TrustManager#getAcceptedIssuers()*/public X509Certificate[] getAcceptedIssuers() {return this.standardTrustManager.getAcceptedIssuers();}}public SSLSocketFactory sslSocketFactory() {try {//信任任何链接SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, new TrustManager[]{new EasyX509TrustManager(null)}, new SecureRandom());return sslContext.getSocketFactory();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (KeyManagementException e) {e.printStackTrace();} catch (KeyStoreException e) {e.printStackTrace();}return null;}
}

八、OkhttpUtil 工具类

@Slf4j
@Component
public class OkHttpUtil{private static OkHttpClient  okHttpClient;@Autowiredpublic OkHttpUtil(OkHttpClient  okHttpClient) {OkHttpUtil.okHttpClient= okHttpClient;}/*** get* @param url     请求的url* @param queries 请求的参数,在浏览器?后面的数据,没有可以传null*/public static  String get(String url, Map<String, String> queries) {String responseBody = "";StringBuffer sb = new StringBuffer(url);if (queries != null && queries.keySet().size() > 0) {boolean firstFlag = true;Iterator iterator = queries.entrySet().iterator();while (iterator.hasNext()) {Map.Entry entry = (Map.Entry<String, String>) iterator.next();if (firstFlag) {sb.append("?" + entry.getKey() + "=" + entry.getValue());firstFlag = false;} else {sb.append("&" + entry.getKey() + "=" + entry.getValue());}}}Request request = new Request.Builder().url(sb.toString()).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 put error >> ", e);} finally {if (response != null) {response.close();}}return responseBody;}/*** post** @param url    请求的url* @param params post form 提交的参数* @return*/public static String post(String url, Map<String, String> params) {String responseBody = "";FormBody.Builder builder = new FormBody.Builder();//添加参数if (params != null && params.keySet().size() > 0) {for (String key : params.keySet()) {builder.add(key, params.get(key));}}Request request = new Request.Builder().url(url).post(builder.build()).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post error >> ", e);} finally {if (response != null) {response.close();}}return responseBody;}/*** get* @param url     请求的url* @param queries 请求的参数,在浏览器?后面的数据,没有可以传null* @return*/public static String getForHeader(String url, Map<String, String> queries) {String responseBody = "";StringBuffer sb = new StringBuffer(url);if (queries != null && queries.keySet().size() > 0) {boolean firstFlag = true;Iterator iterator = queries.entrySet().iterator();while (iterator.hasNext()) {Map.Entry entry = (Map.Entry<String, String>) iterator.next();if (firstFlag) {sb.append("?" + entry.getKey() + "=" + entry.getValue());firstFlag = false;} else {sb.append("&" + entry.getKey() + "=" + entry.getValue());}}}Request request = new Request.Builder().addHeader("key", "value").url(sb.toString()).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 put error >> ", e);} finally {if (response != null) {response.close();}}return responseBody;}/*** Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"}* 参数一:请求Url* 参数二:请求的JSON* 参数三:请求回调*/public static String postJsonParams(String url, String jsonParams) {String responseBody = "";RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);Request request = new Request.Builder().url(url).post(requestBody).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post error >> ", e);} finally {if (response != null) {response.close();}}return responseBody;}/*** Post请求发送xml数据....* 参数一:请求Url* 参数二:请求的xmlString* 参数三:请求回调*/public static String postXmlParams(String url, String xml) {String responseBody = "";RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);Request request = new Request.Builder().url(url).post(requestBody).build();Response response = null;try {response = okHttpClient.newCall(request).execute();int status = response.code();if (response.isSuccessful()) {return response.body().string();}} catch (Exception e) {log.error("okhttp3 post error >> "+ e);} finally {if (response != null) {response.close();}}return responseBody;}
}

九、小结

okhttp 创建 request 请求常见的 body 类型

  • RequestBody 适合传一个参数,如:json (2 和 3 示例)
  • FormBody 表单参数(仅支持文本) (示例 6)
  • MultipartBody 表单(支持文本 和 文件)(示例 4)

创建 okhttp 请求,主要生成 request(包含 method、url、body、header),最后通过 OkHttpClient 执行同步(execute)异步(enqueue)方法

        Request request = new Request.Builder().post(formBody).url(url).addHeader("Connection", "keep-alive").build();Response response = okHttpClient.newCall(request).execute();

1、OkHttp3使用起来简单,但是实际上其原理代码十分复杂,这也使得OkHttp3功能很强大,包括缓存、gzip、长连接、重定向等。

2、OkHttp3原理复杂,但是它的主要功能就是网络访问,网络访问就是要完成读写功能,于是我们只需要好好把握HttpEngine中的sendRequest作用和readResponse作用即可,即sendRequest完成初始化,并通过Socket方式建立同服务器的网络连接,而readResponse通过Socket完成读写功能。

3、OkHttp3依赖于Okio,主要体现在网络访问数据放在okio.Buffer中,通过okio.Okio write方法写服务器数据,通过okio.Okio read方法读取服务器返回数据。

okhttp3简单使用相关推荐

  1. OkHttp3简单使用:请求和响应,post,get

    一,HTTP请求.响应报文格式 要弄明白网络框架,首先需要先掌握Http请求的,响应的报文格式. HTTP请求报文格式: HTTP请求报文主要由请求行.请求头部.请求正文3部分组成. request. ...

  2. OKhttp3 简单使用

    概述 okhttp 官网:https://square.github.io/okhttp/ HTTP是现代应用网络的方式.这就是我们交换数据和媒体的方式.有效地执行HTTP可以加快您的负载并节省带宽. ...

  3. Android网络框架okhttp3简单封装

    1:在demo得build文件中添加依赖(这里以3.8.1版本为例) dependencies {compile 'com.squareup.okhttp3:okhttp:3.8.1' } 2:对网络 ...

  4. 添加okhttp+android+studio,OKHTTP3 简单使用(一) 介绍及Android Studio集成

    HTTP是现代应用常用的一种交换数据和媒体的网络方式,高效地使用HTTP能让资源加载更快,节省带宽.OkHttp是一个高效的HTTP客户端,它有以下默认特性: 支持HTTP/2,允许所有同一个主机地址 ...

  5. 【OKHTTP3】OKHTTP3使用GET和POST

    一.参考资料 OKHTTP3 简单使用(三) POST方法 | JesseHu Blog 使用OKHTTP方式发送POST请求,获取返回的JSON串 - 简书 OkHttp工具类 - 风中追风_lon ...

  6. okHttp3连接池简单使用

    一.概述: HTTP是现代应用网络的方式.这就是我们交换数据和媒体的方式.有效地执行HTTP可以加快您的负载并节省带宽. OkHttp是一个默认有效的HTTP客户端: HTTP / 2支持允许对同一主 ...

  7. 安卓Okhttp3源码的简单分析

    前言:现在的Android项目基本上都是以OkHttp来进行网络通信的(retrofit也是基于okhttp的) 下面记录下okhttp3中的一些实现方式和原理. 工作流程 以这张图出发,说一下几个注 ...

  8. AutoCompleteTextView+Okhttp3+ListView实现简单的网络数据搜索展示

    首先用OKHttp3获取网络上的数据,并保存到Serializeable的Bean类集合 OkHttpClient client = new OkHttpClient();Request reques ...

  9. Android Banner(无限轮播图)控件的简单使用(网络数据OkHttp3)

    一言不合就上图 banner是第三方集成好的直接注入依赖就可以用 老套路先注入依赖: //banner这个版本才是王道(我的studio是2.3.3)compile 'com.youth.banner ...

最新文章

  1. Sql 删除不保留日志
  2. Docker学习(一)
  3. 网络:浏览器静态资源缓存机制
  4. 一个数据应用闭环(转载)
  5. idea中右侧的Maven框消失了
  6. leetcode51. N 皇后(回溯算法)
  7. 深入::first-letter的研究
  8. C++ primer 第12章 12.3 使用标准库:文本查询程序
  9. ajax实现一个前台的进度条,前台ajax实现上传文件并且有进度条
  10. pcs7服务器一直显示在同步,【征文】PCS7 诡异的时间同步问题
  11. 【秋招】拼多多_数据分析岗_面试题整理
  12. Excel中怎么添加批注
  13. 百度网盘会员怎么购买最便宜
  14. CSP 202203-2出行计划
  15. 前端JS获取当前日期
  16. iOS图片加载渲染的优化
  17. 卫星通信放大器系统市场现状研究分析与发展前景预测报告
  18. 印能捷服务器系统怎么装,Prinergy印能捷JTP全自动建立工具(32/64bit)
  19. jmap heap输出解析
  20. 【校园卡】校园卡最近消息:2020校园卡还未停售,更新最新海报

热门文章

  1. 这小伙子写的 Kafka 文章,有点厉害,看完觉得自愧不如!
  2. 台式计算机防盗锁怎么安装,笔记本防盗锁,小编教你笔记本防盗锁怎么用
  3. 手把手教你Vue项目实现本地Docker部署
  4. 与运行其他家庭计算机共享打印机,Win10系统电脑如何在局域网中共享打印机?...
  5. 云安全三大趋势:纵深防御、软件定义安全、设备虚拟化
  6. Linux系统上C语言程序编写与调试
  7. Python从入门到放弃?方法不对一切白费!
  8. android4.2 中文翻译
  9. 插上USB设备虚拟机不弹提示框
  10. 第三篇 第十章建筑灭火器配置(二)