From 248d71e3b3fa0bf8f1da1fb08cd0aef30a0d654d Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 31 Mar 2020 09:43:45 +0800 Subject: [PATCH 001/924] Initial commit --- .gitee/ISSUE_TEMPLATE.zh-CN.md | 13 ++ .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md | 15 ++ LICENSE | 201 ++++++++++++++++++++++++++ README.en.md | 36 +++++ README.md | 37 +++++ 5 files changed, 302 insertions(+) create mode 100644 .gitee/ISSUE_TEMPLATE.zh-CN.md create mode 100644 .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md create mode 100644 LICENSE create mode 100644 README.en.md create mode 100644 README.md diff --git a/.gitee/ISSUE_TEMPLATE.zh-CN.md b/.gitee/ISSUE_TEMPLATE.zh-CN.md new file mode 100644 index 00000000..f09d98dd --- /dev/null +++ b/.gitee/ISSUE_TEMPLATE.zh-CN.md @@ -0,0 +1,13 @@ +### 该问题是怎么引起的? + + + +### �现步骤 + + + +### 报错信� + + + + diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md new file mode 100644 index 00000000..1e5b8d33 --- /dev/null +++ b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md @@ -0,0 +1,15 @@ +### 相关的Issue + + +### 原因(目的�解决的问题等) + + +### �述(�了什么,�更了什么) + + +### 测试用例 + + + + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.en.md b/README.en.md new file mode 100644 index 00000000..724a4724 --- /dev/null +++ b/README.en.md @@ -0,0 +1,36 @@ +# okhttps + +#### Description +OkHttp3 轻��装 ,功能力求开箱�用�设计力求优雅与纯粹,Java领域��端处Http问题的新选择。 + +#### Software Architecture +Software architecture description + +#### Installation + +1. xxxx +2. xxxx +3. xxxx + +#### Instructions + +1. xxxx +2. xxxx +3. xxxx + +#### Contribution + +1. Fork the repository +2. Create Feat_xxx branch +3. Commit your code +4. Create Pull Request + + +#### Gitee Feature + +1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md +2. Gitee blog [blog.gitee.com](https://blog.gitee.com) +3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) +4. The most valuable open source project [GVP](https://gitee.com/gvp) +5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) +6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md new file mode 100644 index 00000000..72dc1707 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# okhttps + +#### 介� +OkHttp3 轻��装 ,功能力求开箱�用�设计力求优雅与纯粹,Java领域��端处Http问题的新选择。 + +#### 软件架构 +软件架构说明 + + +#### 安装教程 + +1. xxxx +2. xxxx +3. xxxx + +#### 使用说明 + +1. xxxx +2. xxxx +3. xxxx + +#### �与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. �交代� +4. 新建 Pull Request + + +#### �云特技 + +1. 使用 Readme\_XXX.md �支���的语言,例如 Readme\_en.md, Readme\_zh.md +2. �云官方�客 [blog.gitee.com](https://blog.gitee.com) +3. 你�以 [https://gitee.com/explore](https://gitee.com/explore) 这个地��了解�云上的优秀开�项目 +4. [GVP](https://gitee.com/gvp) 全称是�云最有价值开�项目,是�云综�评定出的优秀开�项目 +5. �云官方�供的使用手册 [https://gitee.com/help](https://gitee.com/help) +6. �云��人物是一档用�展示�云会员风采的�目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) From 712eefa2e5723f40dae1b4cb32b55162fe84efef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 31 Mar 2020 14:18:33 +0800 Subject: [PATCH 002/924] clone from httputils --- .gitee/ISSUE_TEMPLATE.zh-CN.md | 13 - .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md | 15 - .gitignore | 7 + README.en.md | 36 - README.md | 789 +++++++++++++++++- pom.xml | 169 ++++ .../java/com/ejlchina/http/Configurator.java | 17 + .../java/com/ejlchina/http/DownListener.java | 19 + src/main/java/com/ejlchina/http/Download.java | 307 +++++++ src/main/java/com/ejlchina/http/HTTP.java | 70 ++ src/main/java/com/ejlchina/http/HttpCall.java | 28 + .../java/com/ejlchina/http/HttpResult.java | 282 +++++++ src/main/java/com/ejlchina/http/HttpTask.java | 710 ++++++++++++++++ .../java/com/ejlchina/http/HttpUtils.java | 105 +++ .../java/com/ejlchina/http/OnCallback.java | 11 + .../java/com/ejlchina/http/Preprocessor.java | 36 + src/main/java/com/ejlchina/http/Process.java | 31 + .../java/com/ejlchina/http/TaskListener.java | 20 + .../ejlchina/http/internal/AsyncHttpTask.java | 269 ++++++ .../ejlchina/http/internal/HttpClient.java | 445 ++++++++++ .../ejlchina/http/internal/HttpException.java | 21 + .../http/internal/ProcessInputStream.java | 53 ++ .../http/internal/ProcessRequestBody.java | 91 ++ .../http/internal/RealHttpResult.java | 134 +++ .../ejlchina/http/internal/RealProcess.java | 50 ++ .../ejlchina/http/internal/ResultBody.java | 323 +++++++ .../ejlchina/http/internal/SyncHttpTask.java | 92 ++ .../ejlchina/http/internal/TaskExecutor.java | 98 +++ src/test/java/com/ejlchina/test/HttpTest.java | 611 ++++++++++++++ src/test/java/com/ejlchina/test/User.java | 27 + 30 files changed, 4791 insertions(+), 88 deletions(-) delete mode 100644 .gitee/ISSUE_TEMPLATE.zh-CN.md delete mode 100644 .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md create mode 100644 .gitignore delete mode 100644 README.en.md create mode 100644 pom.xml create mode 100644 src/main/java/com/ejlchina/http/Configurator.java create mode 100644 src/main/java/com/ejlchina/http/DownListener.java create mode 100644 src/main/java/com/ejlchina/http/Download.java create mode 100644 src/main/java/com/ejlchina/http/HTTP.java create mode 100644 src/main/java/com/ejlchina/http/HttpCall.java create mode 100644 src/main/java/com/ejlchina/http/HttpResult.java create mode 100644 src/main/java/com/ejlchina/http/HttpTask.java create mode 100644 src/main/java/com/ejlchina/http/HttpUtils.java create mode 100644 src/main/java/com/ejlchina/http/OnCallback.java create mode 100644 src/main/java/com/ejlchina/http/Preprocessor.java create mode 100644 src/main/java/com/ejlchina/http/Process.java create mode 100644 src/main/java/com/ejlchina/http/TaskListener.java create mode 100644 src/main/java/com/ejlchina/http/internal/AsyncHttpTask.java create mode 100644 src/main/java/com/ejlchina/http/internal/HttpClient.java create mode 100644 src/main/java/com/ejlchina/http/internal/HttpException.java create mode 100644 src/main/java/com/ejlchina/http/internal/ProcessInputStream.java create mode 100644 src/main/java/com/ejlchina/http/internal/ProcessRequestBody.java create mode 100644 src/main/java/com/ejlchina/http/internal/RealHttpResult.java create mode 100644 src/main/java/com/ejlchina/http/internal/RealProcess.java create mode 100644 src/main/java/com/ejlchina/http/internal/ResultBody.java create mode 100644 src/main/java/com/ejlchina/http/internal/SyncHttpTask.java create mode 100644 src/main/java/com/ejlchina/http/internal/TaskExecutor.java create mode 100644 src/test/java/com/ejlchina/test/HttpTest.java create mode 100644 src/test/java/com/ejlchina/test/User.java diff --git a/.gitee/ISSUE_TEMPLATE.zh-CN.md b/.gitee/ISSUE_TEMPLATE.zh-CN.md deleted file mode 100644 index f09d98dd..00000000 --- a/.gitee/ISSUE_TEMPLATE.zh-CN.md +++ /dev/null @@ -1,13 +0,0 @@ -### 该问题是怎么引起的? - - - -### �现步骤 - - - -### 报错信� - - - - diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md deleted file mode 100644 index 1e5b8d33..00000000 --- a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md +++ /dev/null @@ -1,15 +0,0 @@ -### 相关的Issue - - -### 原因(目的�解决的问题等) - - -### �述(�了什么,�更了什么) - - -### 测试用例 - - - - - diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d848a362 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/target/ +/bin/ +/.settings/ +/.classpath +/.project +/.idea/** +*.iml \ No newline at end of file diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 724a4724..00000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# okhttps - -#### Description -OkHttp3 轻��装 ,功能力求开箱�用�设计力求优雅与纯粹,Java领域��端处Http问题的新选择。 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md index 72dc1707..b83e8387 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,778 @@ -# okhttps +# HttpUtils -#### 介� -OkHttp3 轻��装 ,功能力求开箱�用�设计力求优雅与纯粹,Java领域��端处Http问题的新选择。 +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/httputils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/httputils/) +[![License](https://img.shields.io/hexpm/l/plug.svg)](https://gitee.com/ejlchina-zhxu/httputils/blob/master/LICENSE) +[![Troy.Zhou](https://img.shields.io/badge/%E4%BD%9C%E8%80%85-ejlchina-orange.svg)](https://github.com/ejlchina) -#### 软件架构 -软件架构说明 +## 介� +  HttpUtils 是近期开�的对 OkHttp 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 -#### 安装教程 + * 链�调用,一点到底 + * BaseURL�URL��符�JSON自动�装与解� + * �步拦截器�异步预处�器�回调执行器 + * 文件上传下载(过程控制�进度监�) + * TCP连接池�Http2 -1. xxxx -2. xxxx -3. xxxx +### 当�文档版本[2.3.0](近期�布到中央仓库) +#### [查阅[2.1.x]点我](https://gitee.com/ejlchina-zhxu/httputils/blob/master/README-2.1.2.md) | [查阅[2.0.x]点我](https://gitee.com/ejlchina-zhxu/httputils/blob/master/README-2.0.0.md) | [查阅[1.0.x]点我](https://gitee.com/ejlchina-zhxu/httputils/blob/1.x/README.md) -#### 使用说明 +## 目录 -1. xxxx -2. xxxx -3. xxxx ++ [安装教程](#安装教程) + + [Maven](#maven) + + [Gradle](#gradle) ++ [使用说明](#使用说明) + + [1 简�示例](#1-简�示例) + - [1.1 构建HTTP](#11-构建-http) + - [1.2 �步请求](#12-�步请求) + - [1.3 异步请求](#13-异步请求) + + [2 请求方法(GET|POST|PUT|DELETE)](#2-请求方法getpostputdelete) + + [3 解�请求结果](#3-解�请求结果) + - [3.1 回调函数](#31-回调函数) + - [3.2 HttpResult](#32-HttpResult) + - [3.3 HttpCall](#33-HttpCall) + + [4 构建HTTP任务](#4-构建HTTP任务) + + [5 使用标签](#5-使用标签) + + [6 �置 HTTP](#65-�置-http) + - [6.1 设置 BaseUrl](#61-设置-baseurl) + - [6.2 回调执行器](#62-回调执行器) + - [6.3 �置 OkHttpClient](#63-�置-okhttpclient) + - [6.4 并行预处�器](#64-并行预处�器) + - [6.5 串行预处�器](#65-串行预处�器) + - [6.6 全局回调处�](#66-全局回调处�) + - [6.7 全局下载监�](#67-全局下载监�) + + [7 使用 HttpUtils 类](#7-使用-httputils-类) + + [8 文件下载](#8-文件下载) + - [8.1 下载进度监�](#81-下载进度监�) + - [8.2 下载过程控制](#82-下载过程控制) + - [8.3 实现断点续传](#83-实现断点续传) + - [8.4 实现分�下载](#84-实现分�下载) + + [9 文件上传](#9-文件上传) + - [9.1 上传进度监�](#91-上传进度监�) + - [9.2 上传过程控制](#92-上传过程控制) + + [10 执行线程自由切�(for Android)](#10-执行线程自由切�for-android) ++ [�考文档](#�考文档) ++ [�系方�](#�系方�) -#### �与贡献 +## 安装教程 + +### Maven + +``` + + com.ejlchina + httputils + 2.3.0 + +``` +### Gradle + +`compile 'com.ejlchina:httputils:2.3.0'` + +## 使用说明 + +### 1 简�示例 + +#### 1.1 构建 HTTP + +```java +HTTP http = HTTP.builder().build(); +``` +  以上代�构建了一个最简�的`HTTP`实例,它拥有以下三个方法: + +* `async(String url)` 开始一个异步HTTP任务 +* `sync(String url)` 开始一个�步HTTP任务 +* `cancel(String tag)` 根�标签批��消HTTP任务 + +  为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(请��[5.1 设置 BaseUrl](#51-设置-baseurl)): + +```java +HTTP http = HTTP.builder() + .baseUrl("http://api.demo.com") + .build(); +``` +  为了简化文档,下文中出现的`http`�是在构建时设置了`BaseUrl`的`HTTP`实例。 + +#### 1.2 �步请求 + +  使用方法`sync(String url)`开始一个�步请求: + +```java +List users = http.sync("/users") // http://api.demo.com/users + .get() // GET请求 + .getBody() // 获��应报文体 + .toList(User.class); // 得到目标数� +``` +  方法`sync`返回一个�步`HttpTask`,�链�使用。 + +#### 1.3 异步请求 + +  使用方法`async(String url)`开始一个异步请求: + +```java +http.async("/users/1") // http://api.demo.com/users/1 + .setOnResponse((HttpResult result) -> { + // 得到目标数� + User user = result.getBody().toBean(User.class); + }) + .get(); // GET请求 +``` +  方法`async`返回一个异步`HttpTask`,�链�使用。 + +### 2 请求方法(GET|POST|PUT|DELETE) + +  �步与异步的`HttpTask`都拥有`get`�`post`�`put`与`delete`方法。��的是:�步`HttpTask`的这些方法返回一个`HttpResult`,而异步`HttpTask`的这些方法返回一个`HttpCall`。 + +```java +HttpResult res1 = http.sync("/users").get(); // �步 GET +HttpResult res2 = http.sync("/users")post(); // �步 POST +HttpResult res3 = http.sync("/users/1").put(); // �步 PUT +HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE +HttpCall call1 = http.async("/users").get(); // 异步 GET +HttpCall call2 = http.async("/users").post(); // 异步 POST +HttpCall call3 = http.async("/users/1").put(); // 异步 PUT +HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE +``` +### 3 解�请求结果 + +#### 3.1 回调函数 + +  �有异步请求��以设置回调函数: + +```java +http.async("/users/{id}") // http://api.demo.com/users/1 + .addPathParam("id", 1) + .setOnResponse((HttpResult result) -> { + // �应回调 + }) + .setOnException((IOException e) -> { + // 异常回调 + }) + .setOnComplete((State state) -> { + // 完�回调,无论�功失败都会执行 + }) + .get(); +``` + +#### 3.2 HttpResult + +  `HttpResult`是HTTP请求执行完�的结果,它是�步请求方法( `get`�`post`�`put`�`delete`)的返回值,也是异步请求�应回调(`OnResponse`)的�数,它定义了如下方法: + +* `getState()` 得到请求执行状�枚举,它有以下�值: + * `State.CANCELED` 请求被�消 + * `State.RESPONSED` 已收到�应 + * `State.TIMEOUT` 请求超时 + * `State.NETWORK_ERROR` 网络错误 + * `State.EXCEPTION` 其它请求异常 +* `getStatus()` 得到HTTP状�� +* `isSuccessful()` 是��应�功,状��在 [200..300) 之间 +* `getHeaders()` 得到HTTP�应头 +* `getHeaders(String name)` 得到HTTP�应头 +* `getHeader(String name)` 得到HTTP�应头 +* `getBody()` 得到�应报文体`Body`实例,它定义了如下方法(对�一个`Body`实例,以下的`toXXX()`类方法�能使用一个且仅能调用一次): + * `toBytes()` 返回字节数组 + * `toByteStream()` 返回字节输入� + * `toCharStream()` 返回字符输入� + * `toString()` 返回字符串 + * `toJsonObject()` 返回Json对象 + * `toJsonArray()` 返回Json数组 + * `toBean(Class type)` 返回根�type自动json解��的JavaBean + * `toList(Class type)` 返回根�type自动json解��的JavaBean列表 + * `toFile(String filePath)` 下载到指定路径 + * `toFile(File file)` 下载到指定文件 + * `toFolder(String dirPath)` 下载到指定目录 + * `toFolder(File dir)` 下载到指定目录 + * `getContentType()` 返回报文体的媒体类型 + * `getContentLength()` 返回报文体的字节长度 + * `cache()` 缓存报文体,开�缓存����使用`toXXX()`类方法 + * `close()` 关闭报文体,未对报文体�任何消费时使用,比如�读�报文头 +* `getError()` 执行中�生的异常,自动�获执行请求是�生的 网络超时�网络错误 和 其它请求异常 +* `close()` 关闭报文,未对报文体�任何消费时使用,比如�读�长度 + +  示例,请求结果自动转Bean和List: + +```java +// 自动转Bean +Order order = http.sync("/orders/1") + .get().getBody().toBean(Order.class); + +// 自动转List +List orders = http.sync("/orders") + .get().getBody().toList(Order.class); +``` + +  示例,下载文件到指定目录: + +```java +String path = "D:/reports/2020-03-01.xlsx"; // 文件�存目录 + +// �步下载 +http.sync("/reports/2020-03-01.xlsx") + .get().getBody().toFile(path); + +// 异步下载 +http.async("/reports/2020-03-01.xlsx") + .setOnResponse((HttpResult result) -> { + result.getBody().toFile(path); + }) + .get(); +``` + +#### 3.3 HttpCall + +  `HttpCall`对象是异步请求方法(`get`�`post`�`put`�`delete`)的返回值,与`java`的`Future`接�很�,它有如下方法: + +* `cancel()` �消本次请求,返回�消结果 +* `isCanceled()` 返回请求是�被�消 +* `isDone()` 返回是�执行完�,包��消和失败 +* `getResult()` 返回执行结果`HttpResult`对象,若请求未执行完,则挂起当�线程直到执行完��返回 + +  �消一个异步请求示例: + +```java +HttpCall call = http.async("/users/1").get(); + +System.out.println(call.isCanceled()); // false + +boolean success = call.cancel(); // �消请求 + +System.out.println(success); // true +System.out.println(call.isCanceled()); // true +``` + +### 4 构建HTTP任务 + +  `HTTP`对象的`sync`与`async`方法返回一个`HttpTask`对象,该对象�供了�链�调用的`addXXX`与`setXXX`系列方法用于构建任务本身。 + +* `addHeader(String name, String value)` 添加请求头 +* `addHeader(Map headers)` 添加请求头 + +* `addPathParam(String name, Object value)` 添加路径�数:替�URL里的{name}��符 +* `addPathParam(Map params)` 添加路径�数:替�URL里的{name}��符 + +* `addUrlParam(String name, Object value)` 添加URL�数:拼接在URL的?之�(查询�数) +* `addUrlParam(Map params)` 添加URL�数:拼接在URL的?之�(查询�数) + +* `addBodyParam(String name, Object value)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) +* `addBodyParam(Map params)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) + +* `addJsonParam(String name, Object value)` 添加Json�数:请求体为Json(支�多层结构) +* `addJsonParam(Map params)` 添加Json�数:请求体为Json(支�多层结构) + +* `setRequestJson(Object json)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean +* `setRequestJson(Object bean, String dateFormat)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean + +* `addFileParam(String name, String filePath)` 上传文件 +* `addFileParam(String name, File file)` 上传文件 +* `addFileParam(String name, String type, InputStream inputStream)` 上传文件 +* `addFileParam(String name, String type, String fileName, InputStream input)` 上传文件 +* `addFileParam(String name, String type, byte[] content)` 上传文件 +* `addFileParam(String name, String type, String fileName, byte[] content)` 上传文件 + +* `setTag(String tag)` 为HTTP任务添加标签 +* `setRange(long rangeStart)` 设置Range头信�,用于断点续传 +* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,用于分�下载 +* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,用于分�下载 + +* `bind(Object object)` 绑定一个对象,�用于实现Android里的生命周期绑定 + +### 5 使用标签 + +  有时候我们想对HTTP任务加以分类,这时候�以使用标签功能: + +```java +http.async("/users") //(1) + .setTag("A").get(); + +http.async("/users") //(2) + .setTag("A.B").get(); + +http.async("/users") //(3) + .setTag("B").get(); + +http.async("/users") //(4) + .setTag("B.C").get(); + +http.async("/users") //(5) + .setTag("C").get(); +``` +  当使用标签�,就�以按标签批�的对HTTP任务进行�消: + +```java +int count = http.cancel("B"); //(2)(3)(4)被�消(�消标签包�"B"的任务) +System.out.println(count); // 输出 3 +``` +  �样的,�有异步HTTP任务��以被�消。标签除了�以用��消任务,在预处�器中它也�以�挥作用,请��[并行预处�器](#54-并行预处�器)与[串行预处�器](#55-串行预处�器)。 + +### 6 �置 HTTP + +#### 6.1 设置 BaseUrl + +```java +HTTP http = HTTP.builder() + .baseUrl("http://api.demo.com") // 设置 BaseUrl + .build(); +``` +  该�置全局生效,在�置了`BaseUrl`之�,具体的请求便�以�略`BaseUrl`部分,使得代�更加简�,例如: + +```java +http.sync("/users").get() // http://api.demo.com/users + +http.sync("/auth/signin") // http://api.demo.com/auth/signin + .addBodyParam("username", "Jackson") + .addBodyParam("password", "xxxxxx") + .post() // POST请求 +``` +  在�置了`BaseUrl`之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�: + +```java +http.sync("https://www.baidu.com").get() +``` + +#### 6.2 回调执行器 + +  如何想改�执行回调函数的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建`HTTP`时�置如下: + +```java +HTTP http = HTTP.builder() + .callbackExecutor((Runnable run) -> { + runOnUiThread(run); // 在UI线程执行 + }) + .build(); +``` +  该�置影�所有回调。 + +#### 6.3 �置 OkHttpClient + +  与其他�装 OkHttp 的框架��,HttpUtils 并�会�蔽 OkHttp 本身就很好用的功能,如下: + +```java +HTTP http = HTTP.builder() + .config((Builder builder) -> { + // �置连接池 最�10个连接(��置默认为 5) + builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES)); + // �置连接超时时间(默认10秒) + builder.connectTimeout(20, TimeUnit.SECONDS); + // �置拦截器 + builder.addInterceptor((Chain chain) -> { + Request request = chain.request(); + // 必须�步返回,拦截器内无法执行异步�作 + return chain.proceed(request); + }); + // 其它�置: SSL�缓存�代��事件监�... + }) + .build(); +``` + +#### 6.4 并行预处�器 + +  预处�器(`Preprocessor`)�以让我们在请求�出之�对请求本身�一些改�,但与`OkHttp`的拦截器(`Interceptor`)��:预处�器�以让我们**异步**处�这些问题。 + +  例如,当我们想为请求任务自动添加`Token`头信�,而`Token`�能通过异步方法`requestToken`获�时,这时使用`Interceptor`就很难处�了,但�以使用预处�器轻�解决: + +```java +HTTP http = HTTP.builder() + .addPreprocessor((PreChain chain) -> { + HttpTask task = chain.getTask();// 获得当�的HTTP任务 + if (!task.isTagged("Auth")) { // 根�标签判断该任务是�需�Token + return; + } + requestToken((String token) -> { // 异步获� Token + task.addHeader("Token", token);// 为任务添加头信� + chain.proceed(); // 继续当�的任务 + }); + }) + .build(); +``` +  和`Interceptor`一样,`Preprocessor`也�以添加多个。 + +#### 6.5 串行预处�器 + +  普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当`Token`过期时我们需�去刷新获�新`Token`,而刷新`Token`这个�作�能有一个任务去执行,因为如果`n`个任务�时执行的�,那么必有`n-1`个任务刚刷新得到的`Token`�能就立马失效了,而这是我们所�希望的。 + +  为了解决这个问题,HttpUtils �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器: + +```java +HTTP http = HTTP.builder() + .addSerialPreprocessor((PreChain chain) -> { + HttpTask task = chain.getTask(); + if (!task.isTagged("Auth")) { + return; + } + // 检查过期,若需�则刷新Token + requestTokenAndRefreshIfExpired((String token) -> { + task.addHeader("Token", token); + chain.proceed(); // 调用此方法�,�会有其它任务进入该处�器 + }); + }) + .build(); +``` +  串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程� + +#### 6.6 全局回调处� + +```java +HTTP http = HTTP.builder() + .responseListener((HttpTask task, HttpResult result) -> { + // 所有请求�应�都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行 + }) + .completeListener((HttpTask task, State state) -> { + // 所有请求执行完都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行 + }) + .exceptionListener((HttpTask task, IOException error) -> { + // 所有请求�生异常都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 + }) + .build(); +``` + +#### 6.7 全局下载监� + +```java +HTTP http = HTTP.builder() + .downloadListener((HttpTask task, Download download) -> { + // 所有下载在开始之�都会先走这里 + Ctrl ctrl = download.getCtrl(); // 下载控制器 + + }) + .build(); +``` + +### 7 使用 HttpUtils 类 + +  类`HttpUtils`本是 1.x 版本里的最��的核心类,由于在 2.x 版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。 + +  类`HttpUtils`共定义了四个��方法: + +* `async(String url)` 开始一个异步请求 (内容通过一个`HTTP`�例实现) +* `sync(String url)` 开始一个�步请求 (内容通过一个`HTTP`�例实现) +* `cancel(String tag)` 按标签�消请求(内容通过一个`HTTP`�例实现) +* `of(HTTP http)` �置`HttpUtils`�有的`HTTP`实例(�调用此方法�默认使用一个没有没有�过任何�置的`HTTP`懒实例) + +  也就是说,能使用`http`实例的地方,都�以使用`HttpUtils`类,例如: + +```java +// 在�置HTTP实例之�,�能使用全路径方� +List roles = HttpUtils.sync("http://api.demo.com/roles") + .get().getBody().toList(Role.class); + +// �置HTTP实例,全局生效 +HttpUtils.of(HTTP.builder() + .baseUrl("http://api.demo.com") + .build()); + +// 内部使用新的HTTP实例 +List users = HttpUtils.sync("/users") + .get().getBody().toList(User.class); +``` + +### 8 文件下载 + +  HttpUtils 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例: + +```java +http.sync("/download/test.zip") + .get() // 使用 GET 方法(其它方法也�以,看�务器支�) + .getBody() // 得到报文体 + .toFile("D:/download/test.zip") // 指定下载的目录,文件�将根�下载信�自动生� + .start(); // �动下载 +``` +  或使用异步连接方�: + +```java +http.async("/download/test.zip") + .setOnResponse((HttpResult result) -> { + result.getBody().toFile("D:/download/test.zip").start(); + }) + .get(); +``` +  这里�说明一下:`sync`与`async`的区别在于连接�务器并得到�应这个过程的�步与异步(这个过程的耗时在大文件下载中�比��),而`start`方法�动的下载过程则都是异步的。 + +#### 8.1 下载进度监� + +  就直接上代�啦,诸�一看便懂: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .setStepBytes(1024) // 设置�接收 1024 个字节执行一次进度回调(�设置默认为 8192) + // .setStepRate(0.01) // 设置�接收 1% 执行一次进度回调(�设置以 StepBytes 为准) + .setOnProcess((Process process) -> { // 下载进度回调 + long doneBytes = process.getDoneBytes(); // 已下载字节数 + long totalBytes = process.getTotalBytes(); // 总共的字节数 + double rate = process.getRate(); // 已下载的比例 + boolean isDone = process.isDone(); // 是�下载完� + }) + .toFolder("D:/download/") // 指定下载的目录,文件�将根�下载信�自动生� + // .toFile("D:/download/test.zip") // 指定下载的路径,若文件已存在则覆盖 + .setOnSuccess((File file) -> { // 下载�功回调 + + }) + .start(); +``` +  值得一�的是:由于 HttpUtils 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有`Content-Length`头),例如: + +```java +List users = http.sync("/users") + .get() + .getBody() + .setStepBytes(2) + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .toList(User.class); +``` + +#### 8.2 下载过程控制 + +  过于简�:还是直接上代�: + +```java +Ctrl ctrl = http.sync("/download/test.zip") + .get() + .getBody() + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .toFolder("D:/download/") + .start(); // 该方法返回一个下载过程控制器 + +ctrl.status(); // 下载状� +ctrl.pause(); // 暂�下载 +ctrl.resume(); // ��下载 +ctrl.cancel(); // �消下载(�时会删除文件,����) +``` +  无论是�步还是异步�起的下载请求,都�以�以上的控制: + +```java +http.async("/download/test.zip") + .setOnResponse((HttpResult result) -> { + // 拿到下载控制器 + Ctrl ctrl = result.getBody().toFolder("D:/download/").start(); + }) + .get(); +``` + +#### 8.3 实现断点续传 + +  HttpUtils 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,HttpUtils 通过一个失败回调拿到**断点**,便将��的问题�得简�: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .toFolder("D:/download/") + .setOnFailure((Failure failure) -> { // 下载失败回调,以便接收诸如网络错误等失败信� + IOException e = failure.getException(); // 具体的异常信� + long doneBytes = failure.getDoneBytes(); // 已下载的字节数(断点),需��存,用于断点续传 + File file = failure.getFile(); // 下载生�的文件,需��存 ,用于断点续传(��存路径也�以) + }) + .start(); +``` +  下�代�实现续传: + +```java +long doneBytes = ... // 拿到�存的断点 +File file = ... // 待续传的文件 + +http.sync("/download/test.zip") + .setRange(doneBytes) // 设置断点(已下载的字节数) + .get() + .getBody() + .toFile(file) // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + + }) + .setOnFailure((Failure failure) -> { + + }) + .start(); +``` + +#### 8.4 实现分�下载 + +  当文件很大时,有时候我们会考虑分�下载,与断点续传的�路是一样的,示例代�: + +```java +static String url = "http://api.demo.com/download/test.zip" + +public static void main(String[] args) { + long totalSize = HttpUtils.sync(url).get().getBody() + .close() // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); // 获得待下载文件的大�(由于未消费报文体,所以该请求�会消耗下载报文体的时间和网络��) + download(totalSize, 0); // 从第 0 �开始下载 + sleep(50000); // 等待下载完�(�然本例的主线程就结�啦) +} + +static void download(long totalSize, int index) { + long size = 3 * 1024 * 1024; // ��下载 3M + long start = index * size; + long end = Math.min(start + size, totalSize); + HttpUtils.sync(url) + .setRange(start, end) // 设置本次下载的范围 + .get().getBody() + .toFile("D:/download/test.zip") // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + if (end < totalSize) { // 若未下载完,则继续下载下一� + download(totalSize, index + 1); + } else { + System.out.println("下载完�"); + } + }) + .start(); +} +``` + +### 9 文件上传 + +  一个简�文件上传的示例: + +```java +http.sync("/upload") + .addFileParam("test", "D:/download/test.zip") + .post() // 上传�法一般使用 POST 或 PUT,看�务器支� +``` +  异步上传也是完全一样: + +```java +http.async("/upload") + .addFileParam("test", "D:/download/test.zip") + .post() +``` + +#### 9.1 上传进度监� + +  HttpUtils 的上传进度监�,监�的是所有请求报文体的��进度,示例代�: + +```java +http.sync("/upload") + .addBodyParam("name", "Jack") + .addBodyParam("age", 20) + .addFileParam("avatar", "D:/image/avatar.jpg") + .setStepBytes(1024) // 设置��� 1024 个字节执行一次进度回调(�设置默认为 8192) + // .setStepRate(0.01) // 设置��� 1% 执行一次进度回调(�设置以 StepBytes 为准) + .setOnProcess((Process process) -> { // 上传进度回调 + long doneBytes = process.getDoneBytes(); // 已��字节数 + long totalBytes = process.getTotalBytes(); // 总共的字节数 + double rate = process.getRate(); // 已��的比例 + boolean isDone = process.isDone(); // 是���完� + }) + .post() +``` +  咦�怎么感觉和下载的进度回调的一样?没错�HttpUtils 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在`get/post`方法之�使用这些API,下载是在`getBody`方法之�使用。很好�解:`get/post`之�是准备��请求时段,有上传的�义,而`getBody`之�,已是报文�应的时段,当然是下载。 + +#### 9.2 上传过程控制 + +  上传文件的过程控制就很简�,和常规请求一样,�有异步�起的上传�以�消: + +```java +HttpCall call = http.async("/upload") + .addFileParam("test", "D:/download/test.zip") + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .post() + +call.cancel(); // �消上传 +``` +  上传就没有暂�和继续这个功能啦,应该没人有这个需求�? + +### 10 执行线程自由切�(for Android) + +  在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。HttpUtils 为这类问题�供了良好的方案。 + +  在 **默认** 情况下,**所有回调** 函数都会 **在 IO 线程** 执行。为什么会设计如此呢?这是因为 HttpUtils �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。 + +  但是在 Android 里使用 HttpUtils 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器: + + ```java +HTTP http = HTTP.builder() + .callbackExecutor((Runnable run) -> { + // 实际编�中�以� Handler �出�,�需��次执行回调都�新创建 + new Handler(Looper.getMainLooper()).post(run); // 在主线程执行 + }) + .build(); +``` +  上述代�便实现了让 **所有** 的 **回调函数** 都在 **主线程** 执行的目的,如: + +```java +http.async("/users") + .addBodyParam("name", "Jack") + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .setOnResponse((HttpResult result) -> { + // 在主线程执行 + }) + .setOnException((Exception e) -> { + // 在主线程执行 + }) + .setOnComplete((State state) -> { + // 在主线程执行 + }) + .post(); +``` +  但是,如果�时还想让�些回调放在IO线程,实现 **自由切�**,怎么办呢?HttpUtils 给出了�常�活的方法,如下: + +```java +http.async("/users") + .addBodyParam("name", "Jack") + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnResponse((HttpResult result) -> { + // 在 IO 线程执行 + }) + .setOnException((Exception e) -> { + // 在主线程执行(没有指明 nextOnIO 则在回调执行器里执行) + }) + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnComplete((State state) -> { + // 在 IO 线程执行 + }) + .post(); +``` +  无论是哪一个回调,都�以使用`nextOnIO()`方法自由切�。�样,对于文件下载也是一样: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .toFolder("D:/download/") + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnSuccess((File file) -> { + // 在 IO 线程执行 + }) + .setOnFailure((Failure failure) -> { + // 在主线程执行 + }) + .start(); +``` + +## �考文档 + + + +## �系方� + +* 邮箱:zhou.xu@ejlchina.com + +## �与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. �交代� 4. 新建 Pull Request - - -#### �云特技 - -1. 使用 Readme\_XXX.md �支���的语言,例如 Readme\_en.md, Readme\_zh.md -2. �云官方�客 [blog.gitee.com](https://blog.gitee.com) -3. 你�以 [https://gitee.com/explore](https://gitee.com/explore) 这个地��了解�云上的优秀开�项目 -4. [GVP](https://gitee.com/gvp) 全称是�云最有价值开�项目,是�云综�评定出的优秀开�项目 -5. �云官方�供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. �云��人物是一档用�展示�云会员风采的�目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..f434d4c5 --- /dev/null +++ b/pom.xml @@ -0,0 +1,169 @@ + + 4.0.0 + + com.ejlchina + httputils + 2.3.0 + HttpUtils + + + 1.8 + UTF-8 + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + Troy + zhou.xu@ejlchina.com + ejlchina + http://www.ejlchina.com + + + + + scm:git://gitee.com/ejlchina-zhxu/httputils.git + scm:http://gitee.com/ejlchina-zhxu/httputils + https://gitee.com/ejlchina-zhxu/httputils + v2.2.0 + + + + + + junit + junit + 4.12 + test + + + + com.alibaba + fastjson + 1.2.67 + + + + com.squareup.okhttp3 + okhttp + 3.14.7 + + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + ${sonatypeOssDistMgmtSnapshotsUrl} + + + sonatype-nexus-staging + Nexus Release Repository + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + httputils + + + + org.apache.maven.plugins + maven-release-plugin + 2.1 + + forked-path + false + -Psonatype-oss-release + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java-version} + ${java-version} + ${project.build.sourceEncoding} + true + + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.7 + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.1 + + + sign-artifacts + verify + + sign + + + + + + + + + https://gitee.com/ejlchina-zhxu/httputils + Http工具包,�装 OkHttp,链�用法�支�异步�步��应JSON自动解�,回调线程切���置�活�支�URL��符�支�BaseUrl�外部�赖少�适用 JavaWeb 和 Android,教程全��简�易用 + + 江�一键�信�科技有�公� + http://www.ejlchina.com/ + + + https://gitee.com/ejlchina-zhxu/httputils/issues + + \ No newline at end of file diff --git a/src/main/java/com/ejlchina/http/Configurator.java b/src/main/java/com/ejlchina/http/Configurator.java new file mode 100644 index 00000000..c76a5a85 --- /dev/null +++ b/src/main/java/com/ejlchina/http/Configurator.java @@ -0,0 +1,17 @@ +package com.ejlchina.http; + +import okhttp3.OkHttpClient.Builder; + +/** + * Http �置器 + * + */ +public interface Configurator { + + /** + * 使用 builder �置 HttpClient + * @param builder OkHttpClient 构建器 + */ + void config(Builder builder); + +} diff --git a/src/main/java/com/ejlchina/http/DownListener.java b/src/main/java/com/ejlchina/http/DownListener.java new file mode 100644 index 00000000..7802013a --- /dev/null +++ b/src/main/java/com/ejlchina/http/DownListener.java @@ -0,0 +1,19 @@ +package com.ejlchina.http; + +/** + * 下载监�接� + * @author 15735 + * @since 2.3.0 + */ +public interface DownListener { + + + /** + * 全局下载监� + * @param task 所属的 HttpTask + * @param download 下载事件 + */ + void listen(HttpTask task, Download download); + + +} diff --git a/src/main/java/com/ejlchina/http/Download.java b/src/main/java/com/ejlchina/http/Download.java new file mode 100644 index 00000000..c7ef89bd --- /dev/null +++ b/src/main/java/com/ejlchina/http/Download.java @@ -0,0 +1,307 @@ +package com.ejlchina.http; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; + +import com.ejlchina.http.internal.HttpException; +import com.ejlchina.http.internal.TaskExecutor; + +import okhttp3.internal.Util; + +/** + * 文件下载 + * @author Troy.Zhou + * @since 2.2.0 + */ +public class Download { + + private File file; + private InputStream input; + private OnCallback onSuccess; + private OnCallback onFailure; + private TaskExecutor taskExecutor; + private long doneBytes; + private int buffSize = 0; + private long seekBytes = 0; + private boolean appended; + private volatile int status; + private Object lock = new Object(); + + protected boolean nextOnIO = false; + private boolean sOnIO; + private boolean fOnIO; + + private Ctrl ctrl; + + public Download(File file, InputStream input, TaskExecutor taskExecutor, long skipBytes) { + this.file = file; + this.input = input; + this.taskExecutor = taskExecutor; + this.seekBytes = skipBytes; + this.ctrl = new Ctrl(); + } + + /** + * 设置缓冲区大�,默认 2K(2048) + * @param buffSize 缓冲区大�(��:字节) + * @return Download + */ + public Download setBuffSize(int buffSize) { + if (buffSize > 0) { + this.buffSize = buffSize; + } + return this; + } + + /** + * 设置文件追加模� + * 用预断点续传和分�下载 + * @return Download + */ + public Download setAppended() { + this.appended = true; + return this; + } + + /** + * 设置文件指针,从文件的 seekBytes �置追加内容 + * @param seekBytes 跨越的字节数 + * @return Download + */ + public Download setFilePointer(long seekBytes) { + this.seekBytes = seekBytes; + return this; + } + + /** + * 在IO线程执行 + * @return Download + */ + public Download nextOnIO() { + nextOnIO = true; + return this; + } + + /** + * 设置下载�功回调 + * @param onSuccess �功回调函数 + * @return Download + */ + public Download setOnSuccess(OnCallback onSuccess) { + this.onSuccess = onSuccess; + sOnIO = nextOnIO; + nextOnIO = false; + return this; + } + + /** + * 设置下载失败回调 + * @param onFailure 失败回调函数 + * @return Download + */ + public Download setOnFailure(OnCallback onFailure) { + this.onFailure = onFailure; + fOnIO = nextOnIO; + nextOnIO = false; + return this; + } + + /** + * 开始下载 + * @return 下载控制器 + */ + public Ctrl start() { + if (buffSize == 0) { + buffSize = Process.DEFAULT_STEP_BYTES; + } + RandomAccessFile raFile = randomAccessFile(); + status = Ctrl.STATUS__DOWNLOADING; + taskExecutor.execute(() -> { + doDownload(raFile); + }, true); + return ctrl; + } + + /** + * 获�下载控制器 + * @return Ctrl + */ + public Ctrl getCtrl() { + return ctrl; + } + + public class Ctrl { + + /** + * 已�消 + */ + public static final int STATUS__CANCELED = -1; + + /** + * 下载中 + */ + public static final int STATUS__DOWNLOADING = 1; + + /** + * 已暂� + */ + public static final int STATUS__PAUSED = 2; + + /** + * 已完� + */ + public static final int STATUS__DONE = 3; + + /** + * 错误 + */ + public static final int STATUS__ERROR = 4; + + /** + * @see #STATUS__CANCELED + * @see #STATUS__DOWNLOADING + * @see #STATUS__PAUSED + * @see #STATUS__DONE + * @return 下载状� + */ + public int status() { + return status; + } + + /** + * 暂�下载任务 + */ + public void pause() { + synchronized (lock) { + if (status == STATUS__DOWNLOADING) { + status = STATUS__PAUSED; + } + } + } + + /** + * 继续下载任务 + */ + public void resume() { + synchronized (lock) { + if (status == STATUS__PAUSED) { + status = STATUS__DOWNLOADING; + } + } + } + + /** + * �消下载任务 + */ + public void cancel() { + synchronized (lock) { + if (status == STATUS__PAUSED || status == STATUS__DOWNLOADING) { + status = STATUS__CANCELED; + } + } + } + + } + + public class Failure { + + private IOException exception; + + Failure(IOException exception) { + this.exception = exception; + } + + /** + * @return 下载文件 + */ + public File getFile() { + return file; + } + + /** + * @return 已下载字节数 + */ + public long getDoneBytes() { + return doneBytes; + } + + /** + * @return 异常信� + */ + public IOException getException() { + return exception; + } + + } + + private RandomAccessFile randomAccessFile() { + try { + return new RandomAccessFile(file, "rw"); + } catch (FileNotFoundException e) { + status = Ctrl.STATUS__ERROR; + Util.closeQuietly(input); + throw new HttpException("无法获�文件[" + file.getAbsolutePath() + "]的输入�", e); + } + } + + private void doDownload(RandomAccessFile raFile) { + try { + if (appended && seekBytes > 0) { + long length = raFile.length(); + if (seekBytes <= length) { + raFile.seek(seekBytes); + doneBytes = seekBytes; + } else { + raFile.seek(length); + doneBytes = length; + } + } + while (status != Ctrl.STATUS__CANCELED && status != Ctrl.STATUS__DONE) { + if (status == Ctrl.STATUS__DOWNLOADING) { + byte[] buff = new byte[buffSize]; + int len = -1; + while ((len = input.read(buff)) != -1) { + raFile.write(buff, 0, len); + doneBytes += len; + if (status == Ctrl.STATUS__CANCELED + || status == Ctrl.STATUS__PAUSED) { + break; + } + } + if (len == -1) { + synchronized (lock) { + status = Ctrl.STATUS__DONE; + } + } + } + } + } catch (IOException e) { + synchronized (lock) { + status = Ctrl.STATUS__ERROR; + } + if (onFailure != null) { + taskExecutor.execute(() -> { + onFailure.on(new Failure(e)); + }, fOnIO); + } else { + throw new HttpException("�传输失败", e); + } + } finally { + Util.closeQuietly(raFile); + Util.closeQuietly(input); + if (status == Ctrl.STATUS__CANCELED) { + file.delete(); + } + } + if (status == Ctrl.STATUS__DONE + && onSuccess != null) { + taskExecutor.execute(() -> { + onSuccess.on(file); + }, sOnIO); + } + } + +} diff --git a/src/main/java/com/ejlchina/http/HTTP.java b/src/main/java/com/ejlchina/http/HTTP.java new file mode 100644 index 00000000..b8fc7c4b --- /dev/null +++ b/src/main/java/com/ejlchina/http/HTTP.java @@ -0,0 +1,70 @@ +package com.ejlchina.http; + +import com.ejlchina.http.internal.AsyncHttpTask; +import com.ejlchina.http.internal.SyncHttpTask; +import com.ejlchina.http.internal.TaskExecutor; +import com.ejlchina.http.internal.HttpClient.Builder; + +import okhttp3.Call; +import okhttp3.Request; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; + +/** + * HTTP 客户端接� + * @author 15735 + * + */ +public interface HTTP { + + /** + * 异步请求 + * @param url 请求地� + * @return 异步HTTP任务 + */ + AsyncHttpTask async(String url); + + /** + * �步请求 + * @param url 请求地� + * @return �步HTTP任务 + */ + SyncHttpTask sync(String url); + + /** + * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 + * @param tag 标签 + * @return 被�消的任务数� + */ + int cancel(String tag); + + /** + * OkHttp 原生请求 (该请求��过 预处�器) + * @param request 请求 + * @return Call + */ + Call request(Request request); + + /** + * Websocket(该请求��过 预处�器) + * @param request 请求 + * @param listener 监�器 + * @return + */ + WebSocket webSocket(Request request, WebSocketListener listener); + + /** + * 获�任务执行器 + * @return TaskExecutor + */ + TaskExecutor getExecutor(); + + /** + * HTTP 构建器 + * @return HTTP 构建器 + */ + static Builder builder() { + return new Builder(); + } + +} diff --git a/src/main/java/com/ejlchina/http/HttpCall.java b/src/main/java/com/ejlchina/http/HttpCall.java new file mode 100644 index 00000000..940d5749 --- /dev/null +++ b/src/main/java/com/ejlchina/http/HttpCall.java @@ -0,0 +1,28 @@ +package com.ejlchina.http; + +public interface HttpCall { + + /** + * �消 Http 请求 + * @return 是��消�功 + */ + boolean cancel(); + + /** + * @return 请求是�被�消 + */ + boolean isCanceled(); + + /** + * @return 请求是�执行完�,包��消和失败 + */ + boolean isDone(); + + /** + * Waits if necessary for the computation to complete, and then + * retrieves its result + * @return 请求执行结果,若请求未执行完,则阻塞当�线程直到请求执行完� + */ + HttpResult getResult(); + +} diff --git a/src/main/java/com/ejlchina/http/HttpResult.java b/src/main/java/com/ejlchina/http/HttpResult.java new file mode 100644 index 00000000..f1d67b8a --- /dev/null +++ b/src/main/java/com/ejlchina/http/HttpResult.java @@ -0,0 +1,282 @@ +package com.ejlchina.http; + +import java.io.File; +import java.io.InputStream; +import java.io.Reader; +import java.util.List; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ejlchina.http.internal.RealHttpResult; +import com.ejlchina.http.internal.TaskExecutor; + +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.Response; + + +/** + * Http 执行结果 + */ +public interface HttpResult { + + /** + * 构造一个 HttpResult + * 此方法构造的 HttpResult ��设置进度回调,��进行下载�作� + * 若需�,请使用方法: {@link #of(Response, TaskExecutor)} + * @param response Response + * @return HttpResult + */ + static HttpResult of(Response response) { + return of(response, null); + } + + /** + * 构造一个 HttpResult + * @param response Response + * @param taskExecutor 任务执行器, �通过方法 {@link HTTP#getExecutor()} 获得 + * @return HttpResult + */ + static HttpResult of(Response response, TaskExecutor taskExecutor) { + if (response != null) { + return new RealHttpResult(null, response, taskExecutor); + } + throw new IllegalArgumentException("response �能为空"); + } + + /** + * 获�所属的 Http请求任务 + * @return HttpTask + */ + HttpTask getTask(); + + + public enum State { + + /** + * 执行异常 + */ + EXCEPTION, + + /** + * 请求被�消 + */ + CANCELED, + + /** + * 请求已�应 + */ + RESPONSED, + + /** + * 网络超时 + */ + TIMEOUT, + + /** + * 网络出错 + */ + NETWORK_ERROR + + } + + /** + * HTTP�应报文体 + */ + public interface Body { + + /** + * @return 媒体类型 + */ + MediaType getContentType(); + + /** + * @return 报文体字节长度 + */ + long getContentLength(); + + /** + * 在IO线程执行 + * @return Body + */ + Body nextOnIO(); + + /** + * 设置报文体接收进度回调 + * @param onProcess 进度回调函数 + * @return Body + */ + Body setOnProcess(OnCallback onProcess); + + /** + * 设置进度回调的步进字节,默认 8K(8192) + * 表示�接收 stepBytes 个字节,执行一次进度回调 + * @param stepBytes 步进字节 + * @return Body + */ + Body setStepBytes(long stepBytes); + + /** + * 设置进度回调的步进比例 + * 表示�接收 stepRate 比例,执行一次进度回调 + * @param stepRate 步进比例 + * @return Body + */ + Body setStepRate(double stepRate); + + /** + * 设置进度回调忽略�应的Range头信�,�进度回调会从0开始 + * @return Body + */ + Body setRangeIgnored(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字节� + */ + InputStream toByteStream(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字节数组 + */ + byte[] toBytes(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字符� + */ + Reader toCharStream(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字符串 + */ + String toString(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转Json对象 + */ + JSONObject toJsonObject(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转Json数组 + */ + JSONArray toJsonArray(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean + */ + T toBean(Class type); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean列表 + */ + List toList(Class type); + + /** + * 下载到指定路径 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param filePath 目标路径 + * @return 下载过程 #Download + */ + Download toFile(String filePath); + + /** + * 下载到指定文件 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param file 目标文件 + * @return 下载过程 #Download + */ + Download toFile(File file); + + /** + * 下载到指定文件夹 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param dirPath 目标目录 + * @return 下载过程 #Download + */ + Download toFolder(String dirPath); + + /** + * 下载到指定文件夹 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param dir 目标目录 + * @return 下载过程 #Download + */ + Download toFolder(File dir); + + /** + * 缓存自己,缓存�� ��使用 toXXX 类方法 + * @return Body + */ + Body cache(); + + /** + * 关闭报文体 + * 未对报文体�任何消费时使用,比如�读�长度 + * @return Body + */ + Body close(); + + } + + + /** + * @return 执行状� + */ + State getState(); + + /** + * @return HTTP状�� + */ + int getStatus(); + + /** + * @return 是��应�功,状��在 [200..300) 之间 + */ + boolean isSuccessful(); + + /** + * @return �应头 + */ + Headers getHeaders(); + + /** + * @param name 头�称 + * @return �应头 + */ + List getHeaders(String name); + + /** + * @param name 头�称 + * @return �应头 + */ + String getHeader(String name); + + /** + * @return �应报文体 + */ + Body getBody(); + + /** + * @return 执行中�生的异常 + */ + Exception getError(); + + /** + * 关闭报文 + * 未对报文体�任何消费时使用,比如�读�报文头 + * @return HttpResult + */ + HttpResult close(); + +} diff --git a/src/main/java/com/ejlchina/http/HttpTask.java b/src/main/java/com/ejlchina/http/HttpTask.java new file mode 100644 index 00000000..04ccf72c --- /dev/null +++ b/src/main/java/com/ejlchina/http/HttpTask.java @@ -0,0 +1,710 @@ +package com.ejlchina.http; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; +import com.ejlchina.http.HttpResult.State; +import com.ejlchina.http.internal.HttpClient; +import com.ejlchina.http.internal.HttpException; +import com.ejlchina.http.internal.ProcessRequestBody; + +import okhttp3.Call; +import okhttp3.FormBody; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okhttp3.internal.Util; +import okio.Buffer; + + +/** + * Created by 周旭(Troy.Zhou) on 2020/3/11. + */ +@SuppressWarnings("unchecked") +public abstract class HttpTask> { + + private static final MediaType TYPE_JSON = MediaType.parse("application/json; charset=utf-8"); + private static String PATH_PARAM_REGEX = "[A-Za-z0-9_\\-/]*\\{[A-Za-z0-9_\\-]+\\}[A-Za-z0-9_\\-/]*"; + + protected HttpClient httpClient; + protected boolean nothrow; + protected String tag; + protected boolean nextOnIO = false; + + private String urlPath; + private Map headers; + private Map pathParams; + private Map urlParams; + private Map bodyParams; + private Map jsonParams; + private Map files; + private String requestJson; + private OnCallback onProcess; + private boolean pOnIO; + private long stepBytes = 0; + private double stepRate = -1; + + private Object object; + + + public HttpTask(HttpClient httpClient, String url) { + this.httpClient = httpClient; + this.urlPath = url; + } + + /** + * 获�请求任务的URL地� + * @return URL地� + */ + public String getUrl() { + return urlPath; + } + + /** + * 获�请求任务的标签 + * @return 标签 + */ + public String getTag() { + return tag; + } + + /** + * 标签匹� + * 判断任务标签与指定的标签是�匹�(包�指定的标签) + * @param tag 标签 + * @return 是�匹� + */ + public boolean isTagged(String tag) { + if (this.tag != null && tag != null) { + return this.tag.contains(tag); + } + return false; + } + + /** + * 获�请求任务的头信� + * @return 头信� + */ + public Map getHeaders() { + return headers; + } + + /** + * 获得被绑定的对象 + * @return Object + */ + public Object getBound() { + return object; + } + + /** + * 设置在�生异常时��上抛出,设置�: + * 异步请求�以在异常回调内�获异常,�步请求在返回结果中找到该异常 + * @return HttpTask 实例 + */ + public C nothrow() { + this.nothrow = true; + return (C) this; + } + + /** + * 为请求任务添加标签 + * @param tag 标签 + * @return HttpTask 实例 + */ + public C setTag(String tag) { + this.tag = tag; + return (C) this; + } + + /** + * 下一个回调在IO线程执行 + * @return HttpTask 实例 + */ + public C nextOnIO() { + nextOnIO = true; + return (C) this; + } + + /** + * 绑定一个对象 + * @return HttpTask 实例 + */ + public C bind(Object object) { + this.object = object; + return (C) this; + } + + /** + * 添加请求头 + * @param name 请求头� + * @param value 请求头值 + * @return HttpTask 实例 + */ + public C addHeader(String name, String value) { + if (name != null && value != null) { + if (headers == null) { + headers = new HashMap<>(); + } + headers.put(name, value); + } + return (C) this; + } + + /** + * 添加请求头 + * @param headers 请求头集� + * @return HttpTask 实例 + */ + public C addHeader(Map headers) { + if (headers != null) { + if (this.headers == null) { + this.headers = new HashMap<>(); + } + this.headers.putAll(headers); + } + return (C) this; + } + + /** + * 设置Range头信� + * 表示接收报文体时跳过的字节数,用于断点续传 + * @param rangeStart 表示从 rangeStart 个字节处开始接收,通常是已�下载的字节数,�上次的断点) + * @return HttpTask 实例 + */ + public C setRange(long rangeStart) { + return addHeader("Range", "bytes=" + rangeStart + "-"); + } + + /** + * 设置Range头信� + * 设置接收报文体时接收的范围,用于分�下载 + * @param rangeStart 表示从 rangeStart 个字节处开始接收 + * @param rangeEnd 表示接收到 rangeEnd 个字节处 + * @return HttpTask 实例 + */ + public C setRange(long rangeStart, long rangeEnd) { + return addHeader("Range", "bytes=" + rangeStart + "-" + rangeEnd); + } + + /** + * 设置报文体��进度回调 + * @param onProcess 进度回调函数 + * @return HttpTask 实例 + */ + public C setOnProcess(OnCallback onProcess) { + this.onProcess = onProcess; + pOnIO = nextOnIO; + nextOnIO = false; + return (C) this; + } + + /** + * 设置进度回调的步进字节,默认 8K(8192) + * 表示�接收 stepBytes 个字节,执行一次进度回调 + * @param stepBytes 步进字节 + * @return HttpTask 实例 + */ + public C setStepBytes(long stepBytes) { + this.stepBytes = stepBytes; + return (C) this; + } + + /** + * 设置进度回调的步进比例 + * 表示�接收 stepRate 比例,执行一次进度回调 + * @param stepRate 步进比例 + * @return HttpTask 实例 + */ + public C setStepRate(double stepRate) { + this.stepRate = stepRate; + return (C) this; + } + + /** + * 路径�数:替�URL里的{name} + * @param name �数� + * @param value �数值 + * @return HttpTask 实例 + **/ + public C addPathParam(String name, Object value) { + if (name != null && value != null) { + if (pathParams == null) { + pathParams = new HashMap<>(); + } + pathParams.put(name, value.toString()); + } + return (C) this; + } + + /** + * 路径�数:替�URL里的{name} + * @param params �数集� + * @return HttpTask 实例 + **/ + public C addPathParam(Map params) { + if (params != null) { + if (pathParams == null) { + pathParams = new HashMap<>(); + } + params.forEach((String name, Object value) -> { + if (name != null && value != null) { + pathParams.put(name, value.toString()); + } + }); + } + return (C) this; + } + + /** + * URL�数:拼接在URL�的�数 + * @param name �数� + * @param value �数值 + * @return HttpTask 实例 + **/ + public C addUrlParam(String name, Object value) { + if (name != null && value != null) { + if (urlParams == null) { + urlParams = new HashMap<>(); + } + urlParams.put(name, value.toString()); + } + return (C) this; + } + + /** + * URL�数:拼接在URL�的�数 + * @param params �数集� + * @return HttpTask 实例 + **/ + public C addUrlParam(Map params) { + if (params != null) { + if (urlParams == null) { + urlParams = new HashMap<>(); + } + params.forEach((String name, Object value) -> { + if (name != null && value != null) { + urlParams.put(name, value.toString()); + } + }); + } + return (C) this; + } + + /** + * Body�数:放在Body里的�数 + * @param name �数� + * @param value �数值 + * @return HttpTask 实例 + **/ + public C addBodyParam(String name, Object value) { + if (name != null && value != null) { + if (bodyParams == null) { + bodyParams = new HashMap<>(); + } + bodyParams.put(name, value.toString()); + } + return (C) this; + } + + /** + * Body�数:放在Body里的�数 + * @param params �数集� + * @return HttpTask 实例 + **/ + public C addBodyParam(Map params) { + if (params != null) { + if (bodyParams == null) { + bodyParams = new HashMap<>(); + } + params.forEach((String name, Object value) -> { + if (name != null && value != null) { + bodyParams.put(name, value.toString()); + } + }); + } + return (C) this; + } + + /** + * Json�数:请求体为Json,支�多层结构 + * @param name JSON键� + * @param value JSON键值 + * @return HttpTask 实例 + */ + public C addJsonParam(String name, Object value) { + if (name != null && value != null) { + if (jsonParams == null) { + jsonParams = new HashMap<>(); + } + jsonParams.put(name, value); + } + return (C) this; + } + + /** + * Json�数:请求体为Json,�支��层Json + * 若请求json为多层结构,请使用setRequestJson方法 + * @param params JSON键值集� + * @return HttpTask 实例 + */ + public C addJsonParam(Map params) { + if (params != null) { + if (jsonParams == null) { + jsonParams = new HashMap<>(); + } + jsonParams.putAll(params); + } + return (C) this; + } + + /** + * 设置 json 请求体 + * @param json JSON字符串 或 Java对象(将�� 对象的get方法�列化为 json 字符串) + * @return HttpTask 实例 + **/ + public C setRequestJson(Object json) { + return setRequestJson(json, null); + } + + /** + * 请求体为json + * @param json JSON字符串 或 Java对象,将跟� bean的get方法�列化程 json 字符串 + * @param dateFormat �列化json时对日期类型字段的处�格� + * @return HttpTask 实例 + **/ + public C setRequestJson(Object json, String dateFormat) { + if (json != null) { + if (json instanceof String) { + requestJson = json.toString(); + } else if (dateFormat != null) { + requestJson = JSON.toJSONStringWithDateFormat(json, dateFormat); + } else { + requestJson = JSON.toJSONString(json); + } + } + return (C) this; + } + + /** + * 添加文件�数 + * @param name �数� + * @param filePath 文件路径 + * @return HttpTask 实例 + */ + public C addFileParam(String name, String filePath) { + return addFileParam(name, new File(filePath)); + } + + /** + * 添加文件�数 + * @param name �数� + * @param file 文件 + * @return HttpTask 实例 + */ + public C addFileParam(String name, File file) { + if (name != null && file != null && file.exists()) { + String fileName = file.getName(); + String type = fileName.substring(fileName.lastIndexOf(".") + 1); + if (files == null) { + files = new HashMap<>(); + } + files.put(name, new FilePara(type, fileName, file)); + } + return (C) this; + } + + /** + * 添加文件�数 + * @param name �数� + * @param type 文件类型: 如 png�jpg�jpeg 等 + * @param inputStream 文件输入� + * @return HttpTask 实例 + */ + public C addFileParam(String name, String type, InputStream inputStream) { + return addFileParam(name, type, null, inputStream); + } + + /** + * 添加文件�数 + * @param name �数� + * @param type 文件类型: 如 png�jpg�jpeg 等 + * @param fileName 文件� + * @param input 文件输入� + * @return HttpTask 实例 + */ + public C addFileParam(String name, String type, String fileName, InputStream input) { + if (name != null && input != null) { + byte[] content = null; + try { + Buffer buffer = new Buffer(); + content = buffer.readFrom(input).readByteArray(); + buffer.close(); + } catch (IOException e) { + throw new HttpException("读�文件输入�出错:", e); + } finally { + Util.closeQuietly(input); + } + addFileParam(name, type, fileName, content); + } + return (C) this; + } + + /** + * 添加文件�数 + * @param name �数� + * @param type 文件类型: 如 png�jpg�jpeg 等 + * @param content 文件内容 + * @return HttpTask 实例 + */ + public C addFileParam(String name, String type, byte[] content) { + return addFileParam(name, type, null, content); + } + + /** + * 添加文件�数 + * @param name �数� + * @param type 文件类型: 如 png�jpg�jpeg 等 + * @param fileName 文件� + * @param content 文件内容 + * @return HttpTask 实例 + */ + public C addFileParam(String name, String type, String fileName, byte[] content) { + if (name != null && content != null) { + if (files == null) { + files = new HashMap<>(); + } + files.put(name, new FilePara(type, fileName, content)); + } + return (C) this; + } + + class FilePara { + + String type; + String fileName; + byte[] content; + File file; + + FilePara(String type, String fileName, byte[] content) { + this.type = type; + this.fileName = fileName; + this.content = content; + } + + FilePara(String type, String fileName, File file) { + this.type = type; + this.fileName = fileName; + this.file = file; + } + + } + + protected Call prepareCall(String method) { + assertNotConflict("GET".equals(method)); + Request.Builder builder = new Request.Builder() + .url(buildUrlPath()); + buildHeaders(builder); + RequestBody reqBody = null; + if (!"GET".equals(method)) { + reqBody = buildRequestBody(); + if (onProcess != null) { + long contentLength = contentLength(reqBody); + if (stepRate > 0 && stepRate <= 1) { + stepBytes = (long) (contentLength * stepRate); + } + if (stepBytes <= 0) { + stepBytes = Process.DEFAULT_STEP_BYTES; + } + reqBody = new ProcessRequestBody(reqBody, onProcess, + httpClient.getExecutor().getExecutor(pOnIO), + contentLength, stepBytes); + } + } + switch (method) { + case "GET": + builder.get(); + break; + case "POST": + builder.post(reqBody); + break; + case "PUT": + builder.put(reqBody); + break; + case "DELETE": + builder.delete(reqBody); + break; + } + return httpClient.request(builder.build()); + } + + private long contentLength(RequestBody reqBody) { + try { + return reqBody.contentLength(); + } catch (IOException e) { + throw new HttpException("无法获�请求体长度", e); + } + } + + + private void buildHeaders(Request.Builder builder) { + if (headers != null) { + for (String name : headers.keySet()) { + String value = headers.get(name); + if (value != null) { + builder.addHeader(name, value); + } + } + } + } + + + protected String toString(Response response) throws IOException { + String body = null; + ResponseBody rbody = response.body(); + if (rbody != null) { + body = rbody.string(); + } + return body; + } + + protected State toState(IOException e) { + if (e instanceof SocketTimeoutException) { + return State.TIMEOUT; + } else if (e instanceof UnknownHostException || e instanceof ConnectException) { + return State.NETWORK_ERROR; + } else if ("Canceled".equals(e.getMessage())) { + return State.CANCELED; + } + return State.EXCEPTION; + } + + + private RequestBody buildRequestBody() { + if (jsonParams != null) { + requestJson = JSON.toJSONString(jsonParams); + } + if (files != null) { + MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); + if (bodyParams != null) { + for (String name : bodyParams.keySet()) { + String value = bodyParams.get(name); + builder.addFormDataPart(name, value); + } + } + for (String name : files.keySet()) { + FilePara file = files.get(name); + MediaType type = httpClient.getMediaType(file.type); + RequestBody bodyPart; + if (file.file != null) { + bodyPart = RequestBody.create(type, file.file); + } else { + bodyPart = RequestBody.create(type, file.content); + } + builder.addFormDataPart(name, file.fileName, bodyPart); + } + return builder.build(); + } else if (requestJson != null) { + return RequestBody.create(TYPE_JSON, requestJson); + } else { + FormBody.Builder builder = new FormBody.Builder(); + if (bodyParams != null) { + for (String name : bodyParams.keySet()) { + String value = bodyParams.get(name); + builder.add(name, value); + } + } + return builder.build(); + } + } + + + + private String buildUrlPath() { + String url = urlPath; + if (url == null || url.trim().isEmpty()) { + throw new HttpException("url �能为空�"); + } + if (pathParams != null) { + for (String name : pathParams.keySet()) { + String target = "{" + name + "}"; + if (url.contains(target)) { + url = url.replace(target, pathParams.get(name)); + } else { + throw new HttpException("pathParameter [ " + name + " ] �存在于 url [ " + urlPath + " ]"); + } + } + } + if (url.matches(PATH_PARAM_REGEX)) { + throw new HttpException("url 里有 pathParameter 没有设置,你必须先调用 addPathParam 为其设置�"); + } + if (urlParams != null) { + if (url.contains("?")) { + if (!url.endsWith("?")) { + url = url.trim(); + if (url.lastIndexOf("=") < url.lastIndexOf("?") + 2) { + throw new HttpException("url 格�错误,'?' �没有�现 '='"); + } + if (!url.endsWith("&")) { + url += "&"; + } + } + } else { + url += "?"; + } + for (String name : urlParams.keySet()) { + url += name + "=" + urlParams.get(name) + "&"; + } + url = url.substring(0, url.length() - 1); + } + return url; + } + + + protected void assertNotConflict(boolean isGetRequest) { + if (isGetRequest) { + if (requestJson != null) { + throw new HttpException("GET 请求 �能调用 setRequestJson 方法�"); + } + if (jsonParams != null) { + throw new HttpException("GET 请求 �能调用 addJsonParam 方法�"); + } + if (bodyParams != null) { + throw new HttpException("GET 请求 �能调用 addBodyParam 方法�"); + } + if (files != null) { + throw new HttpException("GET 请求 �能调用 addFileParam 方法�"); + } + } + if (requestJson != null) { + if (jsonParams != null) { + throw new HttpException("方法 addJsonParam 与 setRequestJson �能�时调用�"); + } + if (bodyParams != null) { + throw new HttpException("方法 addBodyParam 与 setRequestJson �能�时调用�"); + } + if (files != null) { + throw new HttpException("方法 addFileParam 与 setRequestJson �能�时调用�"); + } + } + if (jsonParams != null) { + if (bodyParams != null) { + throw new HttpException("方法 addBodyParam 与 addJsonParam �能�时调用�"); + } + if (files != null) { + throw new HttpException("方法 addFileParam 与 addJsonParam �能�时调用�"); + } + } + } + +} diff --git a/src/main/java/com/ejlchina/http/HttpUtils.java b/src/main/java/com/ejlchina/http/HttpUtils.java new file mode 100644 index 00000000..f7b7ccb5 --- /dev/null +++ b/src/main/java/com/ejlchina/http/HttpUtils.java @@ -0,0 +1,105 @@ +package com.ejlchina.http; + +import com.ejlchina.http.internal.AsyncHttpTask; +import com.ejlchina.http.internal.SyncHttpTask; +import com.ejlchina.http.internal.TaskExecutor; + +import okhttp3.Call; +import okhttp3.Request; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; + +/** + * Http 工具类,�装 OkHttp + + * 特性: + * �步请求 + * 异步请求 + * Restfull路径 + * 文件上传 + * JSON自动解� + * TCP连接池 + * Http2 + * + * @author Troy.Zhou + */ +public class HttpUtils { + + + private static HTTP http; + + + /** + * �置HttpUtils�有的HTTP实例(�调用此方法�默认使用一个没有没有�过任何�置的HTTP懒实例) + * @param http HTTP实例 + */ + public static void of(HTTP http) { + if (http != null) { + HttpUtils.http = http; + } + } + + + static synchronized HTTP getHttp() { + if (http != null) { + return http; + } + http = HTTP.builder().build(); + return http; + } + + /** + * 异步请求 + * @param url 请求地� + * @return 异步 HttpTask + */ + public static AsyncHttpTask async(String url) { + return getHttp().async(url); + } + + /** + * �步请求 + * @param url 请求地� + * @return �步 HttpTask + */ + public static SyncHttpTask sync(String url) { + return getHttp().sync(url); + } + + /** + * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 + * @param tag 标签 + * @return 被�消的任务数� + */ + public static int cancel(String tag) { + return getHttp().cancel(tag); + } + + /** + * OkHttp 原生请求 (该请求��过 预处�器) + * @param request 请求 + * @return Call + */ + public static Call request(Request request) { + return getHttp().request(request); + } + + /** + * Websocket(该请求��过 预处�器) + * @param request 请求 + * @param listener 监�器 + * @return + */ + public static WebSocket webSocket(Request request, WebSocketListener listener) { + return getHttp().webSocket(request, listener); + } + + /** + * 获�任务执行器 + * @return TaskExecutor + */ + public static TaskExecutor getExecutor() { + return getHttp().getExecutor(); + } + +} diff --git a/src/main/java/com/ejlchina/http/OnCallback.java b/src/main/java/com/ejlchina/http/OnCallback.java new file mode 100644 index 00000000..32dd81e8 --- /dev/null +++ b/src/main/java/com/ejlchina/http/OnCallback.java @@ -0,0 +1,11 @@ +package com.ejlchina.http; + +/** + * 数�回调接� + * Created by 15735 on 2017/1/3. + */ +public interface OnCallback { + + void on(T data); + +} diff --git a/src/main/java/com/ejlchina/http/Preprocessor.java b/src/main/java/com/ejlchina/http/Preprocessor.java new file mode 100644 index 00000000..ee2f757c --- /dev/null +++ b/src/main/java/com/ejlchina/http/Preprocessor.java @@ -0,0 +1,36 @@ +package com.ejlchina.http; + +/** + * 预处�器,支�异步 + * 在HTTP请求任务正�开始之�执行 + * @author Troy.Zhou + */ +public interface Preprocessor { + + /** + * 在HTTP请求开始之�执行 + * @param chain 预处�器链 + */ + void doProcess(PreChain chain); + + + interface PreChain { + + /** + * @return 当�的请求任务 + */ + HttpTask getTask(); + + /** + * @return HTTP + */ + HTTP getHttp(); + + /** + * 继续HTTP请求任务 + */ + void proceed(); + + } + +} diff --git a/src/main/java/com/ejlchina/http/Process.java b/src/main/java/com/ejlchina/http/Process.java new file mode 100644 index 00000000..aff09bd3 --- /dev/null +++ b/src/main/java/com/ejlchina/http/Process.java @@ -0,0 +1,31 @@ +package com.ejlchina.http; + +/** + * 进度(上传或下载) + * @since 2.2.0 + */ +public interface Process { + + static final int DEFAULT_STEP_BYTES = 8192; + + /** + * @return 完�比例 + */ + double getRate(); + + /** + * @return 总 + */ + long getTotalBytes(); + + /** + * @return 已完�任务� + */ + long getDoneBytes(); + + /** + * @return 任务是�完� + */ + boolean isDone(); + +} diff --git a/src/main/java/com/ejlchina/http/TaskListener.java b/src/main/java/com/ejlchina/http/TaskListener.java new file mode 100644 index 00000000..90c2ada2 --- /dev/null +++ b/src/main/java/com/ejlchina/http/TaskListener.java @@ -0,0 +1,20 @@ +package com.ejlchina.http; + +/** + * 任务监�接� + * @author 15735 + * @since 2.3.0 + */ +public interface TaskListener { + + + /** + * 全局任务监� + * @param task 所属的 HttpTask + * @param data 监�内容 + * @return 是�继续执行 task 对应的回调函数 + */ + boolean listen(HttpTask task, T data); + + +} diff --git a/src/main/java/com/ejlchina/http/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/http/internal/AsyncHttpTask.java new file mode 100644 index 00000000..c55985a8 --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/AsyncHttpTask.java @@ -0,0 +1,269 @@ +package com.ejlchina.http.internal; + +import java.io.IOException; + +import com.ejlchina.http.HttpCall; +import com.ejlchina.http.HttpResult; +import com.ejlchina.http.HttpResult.State; +import com.ejlchina.http.HttpTask; +import com.ejlchina.http.OnCallback; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Response; + + +/** + * 异步 Http 请求任务 + * + * @author Troy.Zhou + * + */ +public class AsyncHttpTask extends HttpTask { + + + private OnCallback onResponse; + private OnCallback onException; + private OnCallback onComplete; + private boolean rOnIO; + private boolean eOnIO; + private boolean cOnIO; + + + public AsyncHttpTask(HttpClient client, String url) { + super(client, url); + } + + + /** + * 设置请求执行异常�的回调函数,设置�,相关异常将���上抛出 + * @param onException 请求异常回调 + * @return HttpTask 实例 + */ + public AsyncHttpTask setOnException(OnCallback onException) { + this.onException = onException; + eOnIO = nextOnIO; + nextOnIO = false; + return this; + } + + /** + * 设置请求执行完��的回调函数,无论�功|失败|异常 都会被执行 + * @param onComplete 请求完�回调 + * @return HttpTask 实例 + */ + public AsyncHttpTask setOnComplete(OnCallback onComplete) { + this.onComplete = onComplete; + cOnIO = nextOnIO; + nextOnIO = false; + return this; + } + + /** + * 设置请求得到�应�的回调函数 + * @param onResponse 请求�应回调 + * @return HttpTask 实例 + */ + public AsyncHttpTask setOnResponse(OnCallback onResponse) { + this.onResponse = onResponse; + rOnIO = nextOnIO; + nextOnIO = false; + return this; + } + + /** + * �起 GET 请求 + * @return HttpCall + */ + public HttpCall get() { + return request("GET"); + } + + /** + * �起 POST 请求 + * @return HttpCall + */ + public HttpCall post() { + return request("POST"); + } + + /** + * �起 PUT 请求 + * @return HttpCall + */ + public HttpCall put() { + return request("PUT"); + } + + /** + * �起 DELETE 请求 + * @return HttpCall + */ + public HttpCall delete() { + return request("DELETE"); + } + + private HttpCall request(String method) { + PreHttpCall call = new PreHttpCall(); + httpClient.preprocess(this, () -> { + synchronized (call) { + if (!call.isCanceled()) { + call.setCall(executeCall(prepareCall(method))); + } + } + }); + if (tag != null) { + httpClient.addTagCall(tag, call, this); + } + return call; + } + + + class PreHttpCall implements HttpCall { + + private boolean canceled = false; + private HttpCall call; + + @Override + public boolean cancel() { + boolean res = true; + synchronized (this) { + if (call != null) { + res = call.cancel(); + } else { + canceled = true; + } + notify(); + } + if (tag != null && call == null) { + httpClient.removeTagCall(AsyncHttpTask.this); + } + return res; + } + + @Override + public boolean isDone() { + if (call != null) { + return call.isDone(); + } + return canceled; + } + + @Override + public boolean isCanceled() { + if (call != null) { + return call.isCanceled(); + } + return canceled; + } + + public void setCall(HttpCall call) { + this.call = call; + notify(); + } + + @Override + public synchronized HttpResult getResult() { + if (canceled) { + return new RealHttpResult(AsyncHttpTask.this, State.CANCELED); + } + if (call == null) { + try { + wait(); + } catch (InterruptedException e) { + throw new HttpException(e.getMessage(), e); + } + } + if (call != null) { + return call.getResult(); + } + return new RealHttpResult(AsyncHttpTask.this, State.CANCELED); + } + + } + + class OkHttpCall implements HttpCall { + + private Call call; + private HttpResult result; + + public OkHttpCall(Call call) { + this.call = call; + } + + @Override + public boolean cancel() { + if (result == null) { + call.cancel(); + return true; + } + return false; + } + + @Override + public boolean isDone() { + return result != null; + } + + @Override + public boolean isCanceled() { + return call.isCanceled(); + } + + @Override + public synchronized HttpResult getResult() { + if (result == null) { + try { + wait(); + } catch (InterruptedException e) { + throw new HttpException(e.getMessage(), e); + } + } + return result; + } + + public void setResult(HttpResult result) { + synchronized (this) { + this.result = result; + notify(); + } + if (tag != null) { + httpClient.removeTagCall(AsyncHttpTask.this); + } + } + + } + + private HttpCall executeCall(Call call) { + OkHttpCall httpCall = new OkHttpCall(call); + call.enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException error) { + State state = toState(error); + if (state == State.CANCELED) { + httpCall.setResult(new RealHttpResult(AsyncHttpTask.this, state)); + } else { + TaskExecutor executor = httpClient.getExecutor(); + executor.executeOnComplete(AsyncHttpTask.this, onComplete, state, cOnIO); + if (!executor.executeOnException(AsyncHttpTask.this, onException, error, eOnIO) + && !nothrow) { + throw new HttpException(error.getMessage(), error); + } + httpCall.setResult(new RealHttpResult(AsyncHttpTask.this, state, error)); + } + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + TaskExecutor executor = httpClient.getExecutor(); + HttpResult result = new RealHttpResult(AsyncHttpTask.this, response, executor); + executor.executeOnComplete(AsyncHttpTask.this, onComplete, State.RESPONSED, cOnIO); + executor.executeOnResponse(AsyncHttpTask.this, onResponse, result, rOnIO); + httpCall.setResult(result); + } + + }); + return httpCall; + } + +} diff --git a/src/main/java/com/ejlchina/http/internal/HttpClient.java b/src/main/java/com/ejlchina/http/internal/HttpClient.java new file mode 100644 index 00000000..6d224c45 --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/HttpClient.java @@ -0,0 +1,445 @@ +package com.ejlchina.http.internal; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.Executor; + +import com.ejlchina.http.Configurator; +import com.ejlchina.http.DownListener; +import com.ejlchina.http.HTTP; +import com.ejlchina.http.HttpCall; +import com.ejlchina.http.HttpResult; +import com.ejlchina.http.HttpResult.State; +import com.ejlchina.http.HttpTask; +import com.ejlchina.http.Preprocessor; +import com.ejlchina.http.TaskListener; + +import okhttp3.Call; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; + +public class HttpClient implements HTTP { + + + private OkHttpClient client; + + private String baseUrl; + // 媒体类型 + private Map mediaTypes; + // 执行器 + private TaskExecutor executor; + // 预处�器 + private Preprocessor[] preprocessors; + + private List tagCalls; + + + private HttpClient(Builder builder) { + this.client = builder.client; + this.baseUrl = builder.baseUrl; + this.mediaTypes = builder.mediaTypes; + this.executor = new TaskExecutor(client.dispatcher().executorService(), + builder.mainExecutor, builder.downloadListener, + builder.responseListener, builder.exceptionListener, + builder.completeListener); + this.preprocessors = builder.preprocessors.toArray(new Preprocessor[builder.preprocessors.size()]); + this.tagCalls = Collections.synchronizedList(new LinkedList<>()); + } + + @Override + public AsyncHttpTask async(String url) { + return new AsyncHttpTask(this, urlPath(url)); + } + + @Override + public SyncHttpTask sync(String url) { + return new SyncHttpTask(this, urlPath(url)); + } + + @Override + public int cancel(String tag) { + if (tag == null) { + return 0; + } + int count = 0; + Iterator it = tagCalls.iterator(); + while (it.hasNext()) { + TagCall tagCall = it.next(); + // ��任务的标签包�指定的Tag就会被�消 + if (tagCall.tag.contains(tag)) { + if (tagCall.call.cancel()) { + count++; + } + it.remove(); + } + } + return count; + } + + @Override + public Call request(Request request) { + return client.newCall(request); + } + + @Override + public WebSocket webSocket(Request request, WebSocketListener listener) { + return client.newWebSocket(request, listener); + } + + public OkHttpClient getOkClient() { + return client; + } + + public int getTagCallCount() { + return tagCalls.size(); + } + + public void addTagCall(String tag, HttpCall call, HttpTask task) { + tagCalls.add(new TagCall(tag, call, task)); + } + + public void removeTagCall(HttpTask task) { + Iterator it = tagCalls.iterator(); + while (it.hasNext()) { + TagCall tagCall = it.next(); + if (tagCall.task == task) { + it.remove(); + break; + } + } + } + + class TagCall { + + String tag; + HttpCall call; + HttpTask task; + + public TagCall(String tag, HttpCall call, HttpTask task) { + this.tag = tag; + this.call = call; + this.task = task; + } + + } + + public MediaType getMediaType(String type) { + String mediaType = mediaTypes.get(type); + if (mediaType != null) { + return MediaType.parse(mediaType); + } + return MediaType.parse("application/octet-stream"); + } + + public TaskExecutor getExecutor() { + return executor; + } + + public void preprocess(HttpTask> httpTask, Runnable request) { + if (preprocessors.length > 0) { + RealPreChain process = new RealPreChain(preprocessors, + httpTask, request); + preprocessors[0].doProcess(process); + } else { + request.run(); + } + } + + /** + * 串行预处�器 + * @author Troy.Zhou + */ + static class SerialPreprocessor implements Preprocessor { + + // 预处�器 + private Preprocessor preprocessor; + // 待处�的任务队列 + private Queue pendings; + // 是�有任务正在执行 + private boolean running = false; + + SerialPreprocessor(Preprocessor preprocessor) { + this.preprocessor = preprocessor; + this.pendings = new LinkedList<>(); + } + + @Override + public void doProcess(PreChain process) { + boolean should = true; + synchronized (this) { + if (running) { + pendings.add(process); + should = false; + } else { + running = true; + } + } + if (should) { + preprocessor.doProcess(process); + } + } + + public void afterProcess() { + PreChain process = null; + synchronized (this) { + if (pendings.size() > 0) { + process = pendings.poll(); + } else { + running = false; + } + } + if (process != null) { + preprocessor.doProcess(process); + } + } + + } + + + class RealPreChain implements Preprocessor.PreChain { + + private int index; + + private Preprocessor[] preprocessors; + + private HttpTask httpTask; + + private Runnable request; + + public RealPreChain(Preprocessor[] preprocessors, + HttpTask httpTask, + Runnable request) { + this.index = 1; + this.preprocessors = preprocessors; + this.httpTask = httpTask; + this.request = request; + } + + @Override + public HttpTask getTask() { + return httpTask; + } + + @Override + public HTTP getHttp() { + return HttpClient.this; + } + + @Override + public void proceed() { + if (index > 0) { + Preprocessor last = preprocessors[index - 1]; + if (last instanceof SerialPreprocessor) { + ((SerialPreprocessor) last).afterProcess(); + } + } + if (index < preprocessors.length) { + preprocessors[index++].doProcess(this); + } else { + request.run(); + } + } + + } + + public Builder newBuilder() { + return new Builder(this); + } + + private String urlPath(String urlPath) { + boolean isFullPath = urlPath.startsWith("https://") + || urlPath.startsWith("http://"); + if (isFullPath) { + return urlPath; + } + if (baseUrl != null) { + return baseUrl + urlPath; + } + throw new HttpException("在设置 BaseUrl 之�,您必须使用全路径URL�起请求,当�URL为:" + urlPath); + } + + + public static class Builder { + + private OkHttpClient client; + + private String baseUrl; + + private Map mediaTypes; + + private Configurator configurator; + + private Executor mainExecutor; + + private List preprocessors; + + private DownListener downloadListener; + + private TaskListener responseListener; + + private TaskListener exceptionListener; + + private TaskListener completeListener; + + public Builder() { + mediaTypes = new HashMap<>(); + mediaTypes.put("*", "application/octet-stream"); + mediaTypes.put("png", "image/png"); + mediaTypes.put("jpg", "image/jpeg"); + mediaTypes.put("jpeg", "image/jpeg"); + mediaTypes.put("wav", "audio/wav"); + mediaTypes.put("mp3", "audio/mp3"); + mediaTypes.put("mp4", "video/mpeg4"); + mediaTypes.put("txt", "text/plain"); + mediaTypes.put("xls", "application/x-xls"); + mediaTypes.put("xml", "text/xml"); + mediaTypes.put("apk", "application/vnd.android.package-archive"); + mediaTypes.put("doc", "application/msword"); + mediaTypes.put("pdf", "application/pdf"); + mediaTypes.put("html", "text/html"); + preprocessors = new ArrayList<>(); + } + + private Builder(HttpClient hc) { + this.client = hc.client; + this.baseUrl = hc.baseUrl; + this.mediaTypes = hc.mediaTypes; + this.preprocessors = new ArrayList<>(); + Collections.addAll(this.preprocessors, hc.preprocessors); + } + + /** + * �置 OkHttpClient + * @param configurator �置器 + * @return Builder + */ + public Builder config(Configurator configurator) { + this.configurator = configurator; + return this; + } + + /** + * 设置 baseUrl + * @param baseUrl 全局URL�缀 + * @return Builder + */ + public Builder baseUrl(String baseUrl) { + this.baseUrl = baseUrl; + return this; + } + + /** + * �置媒体类型 + * @param mediaTypes 媒体类型 + * @return Builder + */ + public Builder mediaTypes(Map mediaTypes) { + this.mediaTypes.putAll(mediaTypes); + return this; + } + + /** + * �置媒体类型 + * @param key 媒体类型KEY + * @param value 媒体类型VALUE + * @return Builder + */ + public Builder mediaTypes(String key, String value) { + this.mediaTypes.put(key, value); + return this; + } + + /** + * 设置回调执行器,例如实现切�线程功能,�对异步请求有效 + * @param executor 回调执行器 + * @return Builder + */ + public Builder callbackExecutor(Executor executor) { + this.mainExecutor = executor; + return this; + } + + /** + * 添加�并行处�请求任务的预处�器 + * @param preprocessor 预处�器 + * @return Builder + */ + public Builder addPreprocessor(Preprocessor preprocessor) { + preprocessors.add(preprocessor); + return this; + } + + /** + * 添加预处�器 + * @param preprocessor 预处�器 + * @return Builder + */ + public Builder addSerialPreprocessor(Preprocessor preprocessor) { + preprocessors.add(new SerialPreprocessor(preprocessor)); + return this; + } + + /** + * 设置全局�应监� + * @param listener 监�器 + * @return Builder + */ + public Builder responseListener(TaskListener listener) { + this.responseListener = listener; + return this; + } + + /** + * 设置全局异常监� + * @param listener 监�器 + * @return Builder + */ + public Builder exceptionListener(TaskListener listener) { + this.exceptionListener = listener; + return this; + } + + /** + * 设置全局完�监� + * @param listener 监�器 + * @return Builder + */ + public Builder completeListener(TaskListener listener) { + this.completeListener = listener; + return this; + } + + /** + * 设置下载监�器 + * @param listener 监�器 + * @return Builder + */ + public Builder downloadListener(DownListener listener) { + this.downloadListener = listener; + return this; + } + + public HTTP build() { + if (configurator != null || client == null) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + if (configurator != null) { + configurator.config(builder); + } + client = builder.build(); + } + return new HttpClient(this); + } + + } + +} diff --git a/src/main/java/com/ejlchina/http/internal/HttpException.java b/src/main/java/com/ejlchina/http/internal/HttpException.java new file mode 100644 index 00000000..f78606cf --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/HttpException.java @@ -0,0 +1,21 @@ +package com.ejlchina.http.internal; + +/** + * Created by 周旭(Troy.Zhou) on 2016/8/30. + */ +public class HttpException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 8223484833265657324L; + + public HttpException(String detailMessage) { + super(detailMessage); + } + + public HttpException(String detailMessage, Throwable throwable) { + super(detailMessage, throwable); + } + +} diff --git a/src/main/java/com/ejlchina/http/internal/ProcessInputStream.java b/src/main/java/com/ejlchina/http/internal/ProcessInputStream.java new file mode 100644 index 00000000..779ddc30 --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/ProcessInputStream.java @@ -0,0 +1,53 @@ +package com.ejlchina.http.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.Executor; + +import com.ejlchina.http.OnCallback; +import com.ejlchina.http.Process; + +public class ProcessInputStream extends InputStream { + + private InputStream input; + private OnCallback onProcess; + private Executor callbackExecutor; + private long stepBytes; + private long step = 0; + private RealProcess process; + private boolean doneCalled = false; + + public ProcessInputStream(InputStream input, OnCallback onProcess, long totalBytes, long stepBytes, + long doneBytes, Executor callbackExecutor) { + this.input = input; + this.onProcess = onProcess; + this.stepBytes = stepBytes; + this.callbackExecutor = callbackExecutor; + this.process = new RealProcess(totalBytes, doneBytes); + this.step = doneBytes / stepBytes; + } + + + @Override + public int read() throws IOException { + int data = input.read(); + if (data > -1) { + process.increaseDoneBytes(); + } + if (process.notDoneOrReached(step * stepBytes)) { + return data; + } + if (process.isDone()) { + if (doneCalled) { + return data; + } + doneCalled = true; + } + step++; + callbackExecutor.execute(() -> { + onProcess.on(process); + }); + return data; + } + +} diff --git a/src/main/java/com/ejlchina/http/internal/ProcessRequestBody.java b/src/main/java/com/ejlchina/http/internal/ProcessRequestBody.java new file mode 100644 index 00000000..6f406b54 --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/ProcessRequestBody.java @@ -0,0 +1,91 @@ +package com.ejlchina.http.internal; + +import java.io.IOException; +import java.util.concurrent.Executor; + +import com.ejlchina.http.OnCallback; +import com.ejlchina.http.Process; + +import okhttp3.MediaType; +import okhttp3.RequestBody; +import okio.Buffer; +import okio.BufferedSink; +import okio.ForwardingSink; +import okio.Okio; + +public class ProcessRequestBody extends RequestBody { + + private RequestBody requestBody; + private OnCallback onProcess; + private Executor callbackExecutor; + private long stepBytes; + private long step = 0; + private RealProcess process; + private boolean doneCalled = false; + + public ProcessRequestBody(RequestBody requestBody, OnCallback onProcess, Executor callbackExecutor, + long contentLength, long stepBytes) { + this.requestBody = requestBody; + this.onProcess = onProcess; + this.callbackExecutor = callbackExecutor; + this.stepBytes = stepBytes; + this.process = new RealProcess(contentLength, 0); + } + + @Override + public long contentLength() throws IOException { + return process.getTotalBytes(); + } + + @Override + public boolean isDuplex() { + return requestBody.isDuplex(); + } + + @Override + public boolean isOneShot() { + return requestBody.isOneShot(); + } + + @Override + public MediaType contentType() { + return requestBody.contentType(); + } + + private BufferedSink bufferedSink; + + @Override + public void writeTo(BufferedSink sink) throws IOException { + if (bufferedSink == null) { + bufferedSink = Okio.buffer(new ForwardingSink(sink) { + + @Override + public void write(Buffer source, long byteCount) throws IOException { + //这个方法会循环调用,byteCount 是�次调用上传的字节数。 + super.write(source, byteCount); + process.addDoneBytes(byteCount); + if (process.notDoneOrReached(step * stepBytes)) { + return; + } + if (process.isDone()) { + if (doneCalled) { + return; + } + doneCalled = true; + } + step++; + callbackExecutor.execute(() -> { + onProcess.on(process); + }); + } + + }); + } + requestBody.writeTo(bufferedSink); + bufferedSink.flush(); + } + + + +} + diff --git a/src/main/java/com/ejlchina/http/internal/RealHttpResult.java b/src/main/java/com/ejlchina/http/internal/RealHttpResult.java new file mode 100644 index 00000000..697fd4a6 --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/RealHttpResult.java @@ -0,0 +1,134 @@ +package com.ejlchina.http.internal; + +import java.util.List; + +import com.ejlchina.http.HttpResult; +import com.ejlchina.http.HttpTask; + +import okhttp3.Headers; +import okhttp3.Response; + + +public class RealHttpResult implements HttpResult { + + private State state; + private Response response; + private Exception error; + private TaskExecutor taskExecutor; + private HttpTask httpTask; + + + public RealHttpResult(HttpTask httpTask, State state) { + this.httpTask = httpTask; + this.state = state; + } + + public RealHttpResult(HttpTask httpTask, Response response, TaskExecutor taskExecutor) { + this(httpTask, taskExecutor); + response(response); + } + + public RealHttpResult(HttpTask httpTask, TaskExecutor taskExecutor) { + this.httpTask = httpTask; + this.taskExecutor = taskExecutor; + } + + public RealHttpResult(HttpTask httpTask, State state, Exception error) { + this.httpTask = httpTask; + exception(state, error); + } + + + public void exception(State state, Exception error) { + this.state = state; + this.error = error; + } + + public void response(Response response) { + this.state = State.RESPONSED; + this.response = response; + } + + @Override + public HttpTask getTask() { + return httpTask; + } + + @Override + public State getState() { + return state; + } + + @Override + public int getStatus() { + if (response != null) { + return response.code(); + } + return 0; + } + + @Override + public boolean isSuccessful() { + if (response != null) { + return response.isSuccessful(); + } + return false; + } + + @Override + public Headers getHeaders() { + if (response != null) { + return response.headers(); + } + return null; + } + + @Override + public List getHeaders(String name) { + return response.headers(name); + } + + @Override + public String getHeader(String name) { + return response.header(name); + } + + @Override + public Body getBody() { + if (response != null) { + return new ResultBody(httpTask, response, taskExecutor); + } + return null; + } + + @Override + public Exception getError() { + return error; + } + + public Response getResponse() { + return response; + } + + + @Override + public String toString() { + Body body = getBody(); + String str = "HttpResult [\n state: " + state + ",\n status: " + getStatus() + + ",\n headers: " + getHeaders(); + if (body != null) { + str += ",\n contentType: " + body.getContentType() + + ",\n body: " + body.toString(); + } + return str + ",\n error: " + error + "\n]"; + } + + @Override + public HttpResult close() { + if (response != null) { + response.close(); + } + return this; + } + +} diff --git a/src/main/java/com/ejlchina/http/internal/RealProcess.java b/src/main/java/com/ejlchina/http/internal/RealProcess.java new file mode 100644 index 00000000..700d2895 --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/RealProcess.java @@ -0,0 +1,50 @@ +package com.ejlchina.http.internal; + +import com.ejlchina.http.Process; + +public class RealProcess implements Process { + + // 总字节数 + private long totalBytes; + // 已�完�字节数 + private long doneBytes; + + + public RealProcess(long totalBytes, long doneBytes) { + this.totalBytes = totalBytes; + this.doneBytes = doneBytes; + } + + @Override + public double getRate() { + return (double) doneBytes / totalBytes; + } + + @Override + public long getTotalBytes() { + return totalBytes; + } + + @Override + public long getDoneBytes() { + return doneBytes; + } + + @Override + public boolean isDone() { + return doneBytes >= totalBytes; + } + + public void addDoneBytes(long delt) { + doneBytes += delt; + } + + public void increaseDoneBytes() { + doneBytes++; + } + + public boolean notDoneOrReached(long bytes) { + return doneBytes < bytes && doneBytes < totalBytes; + } + +} diff --git a/src/main/java/com/ejlchina/http/internal/ResultBody.java b/src/main/java/com/ejlchina/http/internal/ResultBody.java new file mode 100644 index 00000000..aa827e75 --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/ResultBody.java @@ -0,0 +1,323 @@ +package com.ejlchina.http.internal; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.util.List; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ejlchina.http.Download; +import com.ejlchina.http.HttpTask; +import com.ejlchina.http.HttpResult.Body; +import com.ejlchina.http.OnCallback; +import com.ejlchina.http.Process; + +import okhttp3.MediaType; +import okhttp3.Response; +import okio.Buffer; + +public class ResultBody implements Body { + + private Response response; + private TaskExecutor taskExecutor; + private boolean onIO = false; + private OnCallback onProcess; + private long stepBytes = 0; + private double stepRate = -1; + private boolean rangeIgnored = false; + private HttpTask httpTask; + private boolean cached = false; + private byte[] data; + + ResultBody(HttpTask httpTask, Response response, TaskExecutor taskExecutor) { + this.httpTask = httpTask; + this.response = response; + this.taskExecutor = taskExecutor; + } + + @Override + public MediaType getContentType() { + return response.body().contentType(); + } + + @Override + public long getContentLength() { + return response.body().contentLength(); + } + + @Override + public Body nextOnIO() { + onIO = true; + return this; + } + + @Override + public Body setOnProcess(OnCallback onProcess) { + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor, ��设置下载进度回调�"); + } + if (cached) { + throw new IllegalStateException("开�缓存�,��设置下载进度回调�"); + } + this.onProcess = onProcess; + return this; + } + + @Override + public Body setStepBytes(long stepBytes) { + this.stepBytes = stepBytes; + return this; + } + + @Override + public Body setStepRate(double stepRate) { + this.stepRate = stepRate; + return this; + } + + @Override + public Body setRangeIgnored() { + this.rangeIgnored =true; + return this; + } + + @Override + public InputStream toByteStream() { + InputStream input; + if (cached) { + input = new ByteArrayInputStream(cacheBytes()); + } else { + input = response.body().byteStream(); + } + if (onProcess != null) { + long rangeStart = getRangeStart(); + long totalBytes = getContentLength(); + if (!rangeIgnored) { + totalBytes += rangeStart; + } + if (stepRate > 0 && stepRate <= 1) { + stepBytes = (long) (totalBytes * stepRate); + } + if (stepBytes <= 0) { + stepBytes = Process.DEFAULT_STEP_BYTES; + } + return new ProcessInputStream(input, onProcess, totalBytes, stepBytes, + rangeIgnored ? 0 : rangeStart, taskExecutor.getExecutor(onIO)); + } + return input; + } + + @Override + public byte[] toBytes() { + if (cached) { + return cacheBytes(); + } + return bodyToBytes(); + } + + @Override + public Reader toCharStream() { + if (cached || onProcess != null) { + return new InputStreamReader(toByteStream()); + } + return response.body().charStream(); + } + + @Override + public String toString() { + if (cached || onProcess != null) { + MediaType contentType = getContentType(); + Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8; + return new String(toBytes(), charset); + } + try { + return response.body().string(); + } catch (IOException e) { + throw new HttpException("报文体转化字符串出错", e); + } + } + + @Override + public JSONObject toJsonObject() { + return JSON.parseObject(toString()); + } + + @Override + public JSONArray toJsonArray() { + return JSON.parseArray(toString()); + } + + @Override + public T toBean(Class type) { + return JSON.parseObject(toString(), type); + } + + @Override + public List toList(Class type) { + return JSON.parseArray(toString(), type); + } + + @Override + public Download toFile(String filePath) { + return toFile(new File(filePath)); + } + + @Override + public Download toFile(File file) { + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor, ��进行下载�作�"); + } + if (!file.exists()) { + try { + File parent = file.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + file.createNewFile(); + } catch (IOException e) { + response.close(); + throw new HttpException( + "Cannot create file [" + file.getAbsolutePath() + "]", e); + } + } + return taskExecutor.download(httpTask, file, toByteStream(), + getRangeStart()); + } + + @Override + public Download toFolder(String dirPath) { + String fileName = resolveFileName(); + String filePath = resolveFilePath(dirPath, fileName); + int index = 0; + File file = new File(filePath); + while (file.exists()) { + String indexFileName = indexFileName(fileName, index++); + filePath = resolveFilePath(dirPath, indexFileName); + file = new File(filePath); + } + return toFile(file); + } + + @Override + public Download toFolder(File dir) { + if (dir.exists() && !dir.isDirectory()) { + response.close(); + throw new HttpException("文件下载失败:文件[" + dir.getAbsolutePath() + "]已存在,并且�是一个目录�"); + } + if (!dir.exists()) { + dir.mkdirs(); + } + return toFolder(dir.getAbsolutePath()); + } + + @Override + public Body cache() { + if (onProcess != null) { + throw new IllegalStateException("设置了下载进度回调,���开�缓存�"); + } + cached = true; + return this; + } + + @Override + public Body close() { + response.close(); + data = null; + return this; + } + + private byte[] cacheBytes() { + if (data == null) { + data = bodyToBytes(); + } + return data; + } + + private byte[] bodyToBytes() { + if (onProcess != null) { + Buffer buffer = new Buffer(); + try { + return buffer.readFrom(toByteStream()).readByteArray(); + } catch (IOException e) { + throw new HttpException("报文体转化字节数组出错", e); + } finally { + response.close(); + buffer.close(); + } + } + try { + return response.body().bytes(); + } catch (IOException e) { + throw new HttpException("报文体转化字节数组出错", e); + } + } + + private long getRangeStart() { + long rangeStart = 0; + if (response.code() != HttpURLConnection.HTTP_PARTIAL) { + return rangeStart; + } + String range = response.header("Content-Range"); + if (range != null && range.startsWith("bytes")) { + int index = range.indexOf('-'); + if (index > 5) { + String start = range.substring(5, index).trim(); + try { + rangeStart = Long.parseLong(start); + } catch (Exception ignore) {} + } + } + return rangeStart; + } + + private String resolveFilePath(String dirPath, String fileName) { + if (dirPath.endsWith("\\") || dirPath.endsWith("/")) { + return dirPath + fileName; + } + return dirPath + "\\" + fileName; + } + + private String indexFileName(String fileName, int index) { + int i = fileName.lastIndexOf('.'); + if (i < 0) { + return fileName + "(" + index + ")"; + } + String ext = fileName.substring(i); + if (i > 0) { + String name = fileName.substring(0, i); + return name + "(" + index + ")" + ext; + } + return "(" + index + ")" + ext; + } + + private String resolveFileName() { + String fileName = response.header("Content-Disposition"); + // 通过Content-Disposition获�文件�,这点跟�务器有关,需��活�通 + if (fileName == null || fileName.length() < 1) { + fileName = response.request().url().encodedPath(); + fileName = fileName.substring(fileName.lastIndexOf("/") + 1); + } else { + try { + fileName = URLDecoder.decode(fileName.substring( + fileName.indexOf("filename=") + 9), "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new HttpException("解�文件�失败", e); + } + // 有些文件�会被包�在""里�,所以�去掉,�然无法读�文件�缀 + fileName = fileName.replaceAll("\"", ""); + } + return fileName; + } + +} diff --git a/src/main/java/com/ejlchina/http/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/http/internal/SyncHttpTask.java new file mode 100644 index 00000000..8ff98b5b --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/SyncHttpTask.java @@ -0,0 +1,92 @@ +package com.ejlchina.http.internal; + +import java.io.IOException; + +import com.ejlchina.http.HttpResult; +import com.ejlchina.http.HttpResult.State; +import com.ejlchina.http.HttpTask; + +import okhttp3.Call; +import okhttp3.Response; + + +/** + * �步 Http 请求任务 + * + * @author Troy.Zhou + * + */ +public class SyncHttpTask extends HttpTask { + + public SyncHttpTask(HttpClient client, String url) { + super(client, url); + } + + /** + * �起 GET 请求 + * @return 请求结果 + */ + public HttpResult get() { + return request("GET"); + } + + /** + * �起 POST 请求 + * @return 请求结果 + */ + public HttpResult post() { + return request("POST"); + } + + /** + * �起 PUT 请求 + * @return 请求结果 + */ + public HttpResult put() { + return request("PUT"); + } + + /** + * �起 DELETE 请求 + * @return 请求结果 + */ + public HttpResult delete() { + return request("DELETE"); + } + + private HttpResult request(String method) { + RealHttpResult result = new RealHttpResult(this, httpClient.getExecutor()); + httpClient.preprocess(this, () -> { + Call call = prepareCall(method); + try { + Response response = call.execute(); + synchronized (SyncHttpTask.this) { + result.response(response); + SyncHttpTask.this.notify(); + } + } catch (IOException e) { + State state = toState(e); + synchronized (SyncHttpTask.this) { + result.exception(state, e); + SyncHttpTask.this.notify(); + } + } + }); + synchronized (this) { + if (result.getState() == null) { + try { + SyncHttpTask.this.wait(); + } catch (InterruptedException e) { + throw new HttpException("等待异常", e); + } + } + } + Exception e = result.getError(); + if (e != null && result.getState() != State.CANCELED + && !nothrow) { + throw new HttpException("请求执行异常", e); + } + return result; + } + +} diff --git a/src/main/java/com/ejlchina/http/internal/TaskExecutor.java b/src/main/java/com/ejlchina/http/internal/TaskExecutor.java new file mode 100644 index 00000000..419bc56c --- /dev/null +++ b/src/main/java/com/ejlchina/http/internal/TaskExecutor.java @@ -0,0 +1,98 @@ +package com.ejlchina.http.internal; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.Executor; + +import com.ejlchina.http.DownListener; +import com.ejlchina.http.Download; +import com.ejlchina.http.HttpResult; +import com.ejlchina.http.HttpResult.State; +import com.ejlchina.http.HttpTask; +import com.ejlchina.http.OnCallback; +import com.ejlchina.http.TaskListener; + +public class TaskExecutor { + + private Executor ioExecutor; + private Executor mainExecutor; + private DownListener downloadListener; + private TaskListener responseListener; + private TaskListener exceptionListener; + private TaskListener completeListener; + + public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, + TaskListener responseListener, TaskListener exceptionListener, + TaskListener completeListener) { + this.ioExecutor = ioExecutor; + this.mainExecutor = mainExecutor; + this.downloadListener = downloadListener; + this.responseListener = responseListener; + this.exceptionListener = exceptionListener; + this.completeListener = completeListener; + } + + public Executor getExecutor(boolean onIoThread) { + if (onIoThread || mainExecutor == null) { + return ioExecutor; + } + return mainExecutor; + } + + public Download download(HttpTask httpTask, File file, InputStream input, long skipBytes) { + Download download = new Download(file, input, this, skipBytes); + if (downloadListener != null) { + downloadListener.listen(httpTask, download); + } + return download; + } + + public void execute(Runnable command, boolean onIoThread) { + Executor executor = ioExecutor; + if (mainExecutor != null && !onIoThread) { + executor = mainExecutor; + } + executor.execute(command); + } + + public void executeOnResponse(HttpTask task, OnCallback onResponse, HttpResult result, boolean onIoThread) { + if (responseListener != null) { + execute(() -> { + if (responseListener.listen(task, result) && onResponse != null) { + onResponse.on(result); + } + }, onIoThread); + } else if (onResponse != null) { + execute(() -> { onResponse.on(result); }, onIoThread); + } + } + + public boolean executeOnException(HttpTask task, OnCallback onException, IOException error, boolean onIoThread) { + if (exceptionListener != null) { + execute(() -> { + if (exceptionListener.listen(task, error) && onException != null) { + onException.on(error); + } + }, onIoThread); + return true; + } else if (onException != null) { + execute(() -> { onException.on(error); }, onIoThread); + return true; + } + return false; + } + + public void executeOnComplete(HttpTask task, OnCallback onComplete, State state, boolean onIoThread) { + if (completeListener != null) { + execute(() -> { + if (completeListener.listen(task, state) && onComplete != null) { + onComplete.on(state); + } + }, onIoThread); + } else if (onComplete != null) { + execute(() -> { onComplete.on(state); }, onIoThread); + } + } + +} diff --git a/src/test/java/com/ejlchina/test/HttpTest.java b/src/test/java/com/ejlchina/test/HttpTest.java new file mode 100644 index 00000000..6573da97 --- /dev/null +++ b/src/test/java/com/ejlchina/test/HttpTest.java @@ -0,0 +1,611 @@ +package com.ejlchina.test; + + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import com.ejlchina.http.Download; +import com.ejlchina.http.Download.Ctrl; +import com.ejlchina.http.Download.Failure; +import com.ejlchina.http.HTTP; +import com.ejlchina.http.HttpCall; +import com.ejlchina.http.HttpResult; +import com.ejlchina.http.HttpResult.Body; +import com.ejlchina.http.HttpResult.State; +import com.ejlchina.http.HttpTask; +import com.ejlchina.http.HttpUtils; +import com.ejlchina.http.Preprocessor.PreChain; +import com.ejlchina.http.Process; +import com.ejlchina.http.internal.HttpClient; + +import okhttp3.ConnectionPool; +import okhttp3.Interceptor.Chain; +import okhttp3.OkHttpClient.Builder; +import okhttp3.Request; + + +public class HttpTest { + + + @Test + public void testCache() { + HTTP http = HTTP.builder().build(); + + Body body = http.sync("http://xxx.cdyun.vip/comm/provinces") + .get() + .getBody() + .cache() + ; + + + System.out.println("result = " + body.toString()); + System.out.println("result = " + body.toJsonArray()); + System.out.println("result = " + body.toBytes()); + + body.close(); + + System.out.println("result = " + body.toString()); + System.out.println("result = " + body.toJsonArray()); + System.out.println("result = " + body.toBytes()); + } + + + @Test + public void testGlobalCallback() { + HTTP http = HTTP.builder() + .responseListener((HttpTask task, HttpResult result) -> { + System.out.println("全局 onResponse: " + result.getStatus()); + return true; + }) + .completeListener((HttpTask task, State state) -> { + System.out.println("全局 onComplete: " + state); + return true; + }) + .exceptionListener((HttpTask task, IOException error) -> { + System.out.println("全局 onException: " + error.getMessage()); + return false; + }) + .build(); + + http.async("http://www.baidu.com") + .setOnResponse((HttpResult result) -> { + System.out.println("�例 onResponse: " + result.getStatus()); + }) + .setOnComplete((State state) -> { + System.out.println("�例 onComplete: " + state); + }) + .setOnException((IOException error) -> { + System.out.println("�例 onException: " + error.getMessage()); + }) + .get(); + + sleep(2000); + } + + @Test + public void testDownloadListener() { + HTTP http = HTTP.builder() + .downloadListener((HttpTask task, Download download) -> { + System.out.println("URL = " + task.getUrl()); + System.out.println("TAG = " + task.getTag()); + Ctrl ctrl = download.getCtrl(); + + new Thread(() -> { + sleep(3000); + ctrl.pause(); + sleep(3000); + ctrl.resume(); + sleep(3000); + ctrl.cancel(); + }).start(); + }) + .build(); + + String url = "https://download.cocos.com/CocosDashboard/v1.0.1/CocosDashboard-v1.0.1-win32-031816.exe"; + + long t0 = System.currentTimeMillis(); + + + http.sync(url) + .setTag("ASD") + .get() + .getBody() + .setOnProcess((Process process) -> { + print(t0, process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); + }) + .setStepRate(0.01) + .toFolder("D:/download/") + .nextOnIO() + .setOnSuccess((File file) -> { + print(t0, "下载�功:" + file.getAbsolutePath(), true); + }) + .setOnFailure((Failure failure) -> { + print(t0, "下载失败:" + failure.getDoneBytes() + ", path = " + failure.getFile().getAbsolutePath(), true); + }) + .start(); + + sleep(20000); + } + + @Test + public void testExecutor() { + HTTP http = HTTP.builder() + .callbackExecutor((Runnable command) -> { + System.out.println("主线程执行"); + command.run(); + }).build(); + + http.async("http://47.100.7.202/ejl-test.zip") + .addBodyParam("name", "Jack") +// .nextOnIO() + .setOnProcess((Process process) -> { + System.out.println("process: " + process.getRate()); + }) +// .nextOnIO() + .setOnResponse((HttpResult result) -> { + System.out.println("status: " + result.close().getStatus()); + }) + .nextOnIO() + .setOnComplete((State state) -> { + System.out.println("state: " + state); + }) + .post(); + + sleep(3000); + } + + + public static void main(String[] args) { + long totalSize = HttpUtils.sync("/download/test.zip").get().getBody() + .close() // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); + download(totalSize, 0); // 从第 0 �开始下载 + sleep(50000); // 等待下载完� + } + + static void download(long totalSize, int index) { + long size = 3 * 1024 * 1024; // ��下载 3M + long start = index * size; + long end = Math.min(start + size, totalSize); + HttpUtils.sync("/download/test.zip") + .setRange(start, end) // 设置本次下载的范围 + .get().getBody() + .toFile("D:/download/test.zip") // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + if (end < totalSize) { // 若未下载完,则继续下载下一� + download(totalSize, index + 1); + } else { + System.out.println("下载完�"); + } + }) + .start(); + } + + + @Test + public void testD() { + System.out.println(Long.parseLong("12")); + } + + + @Test + public void testUpload() { + String data = "0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz"; + + HTTP http = HTTP.builder().build(); + + long t0 = System.currentTimeMillis(); + + String res = http.sync("http://localhost:8080/test/index") + .addBodyParam("data", data) + .addFileParam("file", "D:\\WorkSpace\\download\\CocosDashboard-v1.0.1-win32-031816.exe") + .setStepRate(0.01) + .setOnProcess((Process process) -> { + print(t0, "上传:" + process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); + }) + .post() + .getBody() + .setStepBytes(5) + .setOnProcess((Process process) -> { + print(t0, "下载:" + process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); + }) + .toString(); + + System.out.println("�应:" + res); + } + + @Test + public void testDownload() { + HTTP http = HTTP.builder() + .config((Builder builder) -> { + builder.readTimeout(300, TimeUnit.MILLISECONDS); + }) + .build(); + + String url = "https://download.cocos.com/CocosDashboard/v1.0.1/CocosDashboard-v1.0.1-win32-031816.exe"; +// String url = "http://47.100.7.202/ejl-test.zip"; + + long t0 = System.currentTimeMillis(); + +// Ctrl ctrl = + http.sync(url) +// .setRange(24771214) + .bind(this) + .get() + .getBody() + .setOnProcess((Process process) -> { + print(t0, process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); + }) + .setStepRate(0.1) + .toFolder("D:/WorkSpace/download/") +// .toFile("D:\\WorkSpace\\download\\CocosDashboard-v1.0.1-win32-031816(9).exe") +// .setAppended() // �用 断点续传 + .nextOnIO() + .setOnSuccess((File file) -> { + print(t0, "下载�功:" + file.getAbsolutePath(), true); + }) + .setOnFailure((Failure failure) -> { + print(t0, "下载失败:" + failure.getDoneBytes() + ", path = " + failure.getFile().getAbsolutePath(), true); + }) + .start(); + + sleep(10000); + +// ctrl.status(); +// ctrl.pause(); +// System.out.println("暂�"); +// sleep(5000); +// +// ctrl.resume(); +// System.out.println("继续"); +// sleep(5000); +// +// ctrl.cancel(); +// System.out.println("�消"); + + +// + +// +// ctrl.pause(); +// System.out.println("暂�"); +// sleep(5000); +// +// ctrl.resume(); +// System.out.println("继续"); + sleep(5000); + + } + + void print(long t0, String str, boolean ln) { + long now = System.currentTimeMillis() - t0; + System.out.println((now) + "\t" + str); + if (ln) { + System.out.println(); + } + } + + long now(long t0) { + return System.currentTimeMillis() - t0; + } + + + @Test + public void testToList() { + long t0 = System.currentTimeMillis(); + + HTTP http = HTTP.builder() + .baseUrl("http://xxx.cdyun.vip/ejlchina") + .build(); + + HttpResult result = http.sync("/comm/provinces") + .setRange(0) + .get(); + + print(t0, "status: " + result.getStatus(), true); + print(t0, "headers: " + result.getHeaders(), true); + + Body body = result.getBody(); + + print(t0, "total: " + body.getContentLength(), true); + + List list = body.setStepRate(0.1) + .setOnProcess((Process process) -> { + print(t0, process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); + }) + .toList(User.class); + + print(t0, list.toString(), false); + } + + + @Test + public void testPreprocessor() { + + HTTP http = HTTP.builder() + .baseUrl("http://localhost:8080") + .addPreprocessor((PreChain chain) -> { + System.out.println("并行预处�-开始"); +// new Thread(() -> { + sleep(2000); + System.out.println("并行预处�-结�"); + chain.proceed(); +// }).start(); + }) + .addSerialPreprocessor((PreChain chain) -> { + System.out.println("串行预处�-开始"); + new Thread(() -> { + sleep(3000); + System.out.println("串行预处�-结�"); + chain.proceed(); + }).start(); + }) + .build(); + + new Thread(() -> { + System.out.println(http.sync("/user/show/1").get()); + }).start(); + + new Thread(() -> { + System.out.println(http.sync("/user/show/2").get()); + }).start(); + +// new Thread(() -> { +// http.async("/user/show/1") +// .setOnResponse((HttpResult result) -> { +// System.out.println(result); +// }) +// .get(); +// }).start(); +// +// new Thread(() -> { +// http.async("/user/show/2") +// .setOnResponse((HttpResult result) -> { +// System.out.println(result); +// }) +// .get(); +// }).start(); + + sleep(10000); + } + + + + @Test + public void testCancel() { + + HTTP http = HTTP.builder() + .baseUrl("http://localhost:8080") + .build(); + + http.async("/user/show/1") + .setOnResponse((HttpResult result) -> { + System.out.println(result); + }) + .setOnException((IOException e) -> { + System.out.println("异常�获:" + e.getMessage()); + }) + .setOnComplete((State state) -> { + System.out.println(state); + }) + .setTag("A") + .get(); + + System.out.println(((HttpClient) http).getTagCallCount()); + + http.async("/user/show/2") + .setOnResponse((HttpResult result) -> { + System.out.println(result); + }) + .setTag("A.B") + .get(); + + System.out.println(((HttpClient) http).getTagCallCount()); + + http.async("/user/show/3") + .setOnResponse((HttpResult result) -> { + System.out.println(result); + }) + .setTag("B.C") + .get(); + + System.out.println(((HttpClient) http).getTagCallCount()); + + http.async("/user/show/4") + .setOnResponse((HttpResult result) -> { + System.out.println(result); + }) + .setTag("C") + .get(); + + System.out.println(((HttpClient) http).getTagCallCount()); + + + System.out.println("标签�消:" + http.cancel("B")); + + System.out.println(((HttpClient) http).getTagCallCount()); + + sleep(5000); + + System.out.println(((HttpClient) http).getTagCallCount()); + + sleep(5000); + + System.out.println(((HttpClient) http).getTagCallCount()); + + sleep(5000); + + System.out.println(((HttpClient) http).getTagCallCount()); + +// System.out.println("isDone = " + call.isDone()); +// System.out.println("isCanceled = " + call.isCanceled()); +// +// System.out.println("�消结果 = " + call.cancel()); +// +// System.out.println("isDone = " + call.isDone()); +// System.out.println("isCanceled = " + call.isCanceled()); +// +// sleep(100); +// System.out.println("++++++++"); +// +// System.out.println("isDone = " + call.isDone()); +// System.out.println("isCanceled = " + call.isCanceled()); + } + + + + + private HTTP buildHttp() { + + return HTTP.builder() + .config((Builder builder) -> { + + // �置连接池 最�10个连接(��置默认为 5) + builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES)); + + // �置连接超时时间 + builder.connectTimeout(20, TimeUnit.SECONDS); + + builder.addInterceptor((Chain chain) -> { + + Request request = chain.request(); + + return chain.proceed(request); + }); + }) + .baseUrl("http://localhost:8080") + .callbackExecutor((Runnable run) -> { + runOnUiThread(run); + }) + .addPreprocessor((PreChain chain) -> { + new Thread(() -> { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + chain.getTask().addHeader("Token", "yyyyy"); + + chain.proceed(); + + }).start(); + }) + .addPreprocessor((PreChain chain) -> { + new Thread(() -> { + + chain.getTask().addUrlParam("actor", "Alice"); + + chain.proceed(); + + }).start(); + }) + .build(); + + } + + + @Test + public void syncHttpExample() { + + HTTP http = buildHttp(); + // �步请求 + HttpResult result = http.sync("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1584365400942&di=d9e7890f13b7bc4b76080fdd490ed5d5&imgtype=0&src=http%3A%2F%2Ft8.baidu.com%2Fit%2Fu%3D1484500186%2C1503043093%26fm%3D79%26app%3D86%26f%3DJPEG%3Fw%3D1280%26h%3D853") + .get(); + + result.getBody().toFile("E:/3.jpg"); +// // 得到状�� +// int status = result.getStatus(); +// +// // 得到返回头 +// Headers headers = result.getHeaders(); +// +// User user = result.getBody().toBean(User.class); +// // 得到目标数� +// +// +// System.out.println("status = " + status); +// System.out.println("headers = " + headers); +// System.out.println("user = " + user); + + System.out.println("status = " + result.getStatus()); + + } + + + @Test + public void syncJsonExample() { + HTTP http = buildHttp(); + // �步请求 + HttpResult result = http.sync("/user/save") + .addJsonParam("name", "Tom") + .addJsonParam("age", 23) + .post(); + + System.out.println("result = " + result); + + result = http.sync("/user/show/1").get(); + + System.out.println("result = " + result); + + System.out.println("isSuccessful = " + result.isSuccessful()); + } + + @Test + public void asyncHttpExample() throws InterruptedException { + HTTP http = buildHttp(); + // 异步请求 + // 最终路径 http://api.demo.com/users/2 + HttpCall call = http.async("/user/show/{id}") + // 设置路径�数 + .addPathParam("id", 2) + // 设置回调函数 + .setOnResponse((HttpResult result) -> { + System.out.println("000"); +// User user = result.getBody().toBean(User.class); +// System.out.println("user = " + user); + }) + .setOnException((IOException e) -> { + e.printStackTrace(); + }) + // �起 GET 请求 + .get(); + + Thread.sleep(150); + + System.out.println("是�完�: " + call.isDone()); + System.out.println("是��消: " + call.isCanceled()); + + call.cancel(); // �消请求 + + System.out.println("是��消: " + call.isCanceled()); + System.out.println("执行结果: " + call.getResult()); + System.out.println("是�完�: " + call.isDone()); +// + Thread.sleep(100); +// +// System.out.println("是�完�: " + call.isDone()); +// System.out.println("是��消: " + call.isCanceled()); +// System.out.println("执行状�: " + call.getResult()); + + } + + + private static void sleep(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + + static void runOnUiThread(Runnable run) { + run.run(); + } + +} diff --git a/src/test/java/com/ejlchina/test/User.java b/src/test/java/com/ejlchina/test/User.java new file mode 100644 index 00000000..bdf75c9d --- /dev/null +++ b/src/test/java/com/ejlchina/test/User.java @@ -0,0 +1,27 @@ +package com.ejlchina.test; + +public class User { + + int id; + String name; + + public void setId(int id) { + this.id = id; + } + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + public String getName() { + return name; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + "]"; + } + +} From b77323a58c6dfe593a0203ac2dc15018a220c6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 31 Mar 2020 14:27:16 +0800 Subject: [PATCH 003/924] =?UTF-8?q?=E6=8A=A5=E5=90=8D=E9=87=8D=E6=9E=84?= =?UTF-8?q?=EF=BC=9Acom.ejlchina.http=20->=20com.ejlchina.okhttps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{http => okhttps}/Configurator.java | 2 +- .../{http => okhttps}/DownListener.java | 2 +- .../ejlchina/{http => okhttps}/Download.java | 6 ++--- .../com/ejlchina/{http => okhttps}/HTTP.java | 10 +++---- .../ejlchina/{http => okhttps}/HttpCall.java | 2 +- .../{http => okhttps}/HttpResult.java | 6 ++--- .../ejlchina/{http => okhttps}/HttpTask.java | 10 +++---- .../ejlchina/{http => okhttps}/HttpUtils.java | 8 +++--- .../{http => okhttps}/OnCallback.java | 2 +- .../{http => okhttps}/Preprocessor.java | 2 +- .../ejlchina/{http => okhttps}/Process.java | 2 +- .../{http => okhttps}/TaskListener.java | 2 +- .../internal/AsyncHttpTask.java | 12 ++++----- .../internal/HttpClient.java | 20 +++++++------- .../internal/HttpException.java | 2 +- .../internal/ProcessInputStream.java | 6 ++--- .../internal/ProcessRequestBody.java | 6 ++--- .../internal/RealHttpResult.java | 6 ++--- .../internal/RealProcess.java | 4 +-- .../internal/ResultBody.java | 12 ++++----- .../internal/SyncHttpTask.java | 8 +++--- .../internal/TaskExecutor.java | 16 ++++++------ src/test/java/com/ejlchina/test/HttpTest.java | 26 +++++++++---------- 23 files changed, 86 insertions(+), 86 deletions(-) rename src/main/java/com/ejlchina/{http => okhttps}/Configurator.java (88%) rename src/main/java/com/ejlchina/{http => okhttps}/DownListener.java (89%) rename src/main/java/com/ejlchina/{http => okhttps}/Download.java (97%) rename src/main/java/com/ejlchina/{http => okhttps}/HTTP.java (84%) rename src/main/java/com/ejlchina/{http => okhttps}/HttpCall.java (94%) rename src/main/java/com/ejlchina/{http => okhttps}/HttpResult.java (97%) rename src/main/java/com/ejlchina/{http => okhttps}/HttpTask.java (98%) rename src/main/java/com/ejlchina/{http => okhttps}/HttpUtils.java (92%) rename src/main/java/com/ejlchina/{http => okhttps}/OnCallback.java (80%) rename src/main/java/com/ejlchina/{http => okhttps}/Preprocessor.java (94%) rename src/main/java/com/ejlchina/{http => okhttps}/Process.java (92%) rename src/main/java/com/ejlchina/{http => okhttps}/TaskListener.java (91%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/AsyncHttpTask.java (96%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/HttpClient.java (96%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/HttpException.java (91%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/ProcessInputStream.java (90%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/ProcessRequestBody.java (95%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/RealHttpResult.java (95%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/RealProcess.java (91%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/ResultBody.java (97%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/SyncHttpTask.java (92%) rename src/main/java/com/ejlchina/{http => okhttps}/internal/TaskExecutor.java (89%) diff --git a/src/main/java/com/ejlchina/http/Configurator.java b/src/main/java/com/ejlchina/okhttps/Configurator.java similarity index 88% rename from src/main/java/com/ejlchina/http/Configurator.java rename to src/main/java/com/ejlchina/okhttps/Configurator.java index c76a5a85..54f954ad 100644 --- a/src/main/java/com/ejlchina/http/Configurator.java +++ b/src/main/java/com/ejlchina/okhttps/Configurator.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; import okhttp3.OkHttpClient.Builder; diff --git a/src/main/java/com/ejlchina/http/DownListener.java b/src/main/java/com/ejlchina/okhttps/DownListener.java similarity index 89% rename from src/main/java/com/ejlchina/http/DownListener.java rename to src/main/java/com/ejlchina/okhttps/DownListener.java index 7802013a..53cbebed 100644 --- a/src/main/java/com/ejlchina/http/DownListener.java +++ b/src/main/java/com/ejlchina/okhttps/DownListener.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; /** * 下载监�接� diff --git a/src/main/java/com/ejlchina/http/Download.java b/src/main/java/com/ejlchina/okhttps/Download.java similarity index 97% rename from src/main/java/com/ejlchina/http/Download.java rename to src/main/java/com/ejlchina/okhttps/Download.java index c7ef89bd..87764862 100644 --- a/src/main/java/com/ejlchina/http/Download.java +++ b/src/main/java/com/ejlchina/okhttps/Download.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; import java.io.File; import java.io.FileNotFoundException; @@ -6,8 +6,8 @@ import java.io.InputStream; import java.io.RandomAccessFile; -import com.ejlchina.http.internal.HttpException; -import com.ejlchina.http.internal.TaskExecutor; +import com.ejlchina.okhttps.internal.HttpException; +import com.ejlchina.okhttps.internal.TaskExecutor; import okhttp3.internal.Util; diff --git a/src/main/java/com/ejlchina/http/HTTP.java b/src/main/java/com/ejlchina/okhttps/HTTP.java similarity index 84% rename from src/main/java/com/ejlchina/http/HTTP.java rename to src/main/java/com/ejlchina/okhttps/HTTP.java index b8fc7c4b..2f6a54df 100644 --- a/src/main/java/com/ejlchina/http/HTTP.java +++ b/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -1,9 +1,9 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; -import com.ejlchina.http.internal.AsyncHttpTask; -import com.ejlchina.http.internal.SyncHttpTask; -import com.ejlchina.http.internal.TaskExecutor; -import com.ejlchina.http.internal.HttpClient.Builder; +import com.ejlchina.okhttps.internal.AsyncHttpTask; +import com.ejlchina.okhttps.internal.SyncHttpTask; +import com.ejlchina.okhttps.internal.TaskExecutor; +import com.ejlchina.okhttps.internal.HttpClient.Builder; import okhttp3.Call; import okhttp3.Request; diff --git a/src/main/java/com/ejlchina/http/HttpCall.java b/src/main/java/com/ejlchina/okhttps/HttpCall.java similarity index 94% rename from src/main/java/com/ejlchina/http/HttpCall.java rename to src/main/java/com/ejlchina/okhttps/HttpCall.java index 940d5749..8a59cd14 100644 --- a/src/main/java/com/ejlchina/http/HttpCall.java +++ b/src/main/java/com/ejlchina/okhttps/HttpCall.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; public interface HttpCall { diff --git a/src/main/java/com/ejlchina/http/HttpResult.java b/src/main/java/com/ejlchina/okhttps/HttpResult.java similarity index 97% rename from src/main/java/com/ejlchina/http/HttpResult.java rename to src/main/java/com/ejlchina/okhttps/HttpResult.java index f1d67b8a..c3d51d96 100644 --- a/src/main/java/com/ejlchina/http/HttpResult.java +++ b/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; import java.io.File; import java.io.InputStream; @@ -7,8 +7,8 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.ejlchina.http.internal.RealHttpResult; -import com.ejlchina.http.internal.TaskExecutor; +import com.ejlchina.okhttps.internal.RealHttpResult; +import com.ejlchina.okhttps.internal.TaskExecutor; import okhttp3.Headers; import okhttp3.MediaType; diff --git a/src/main/java/com/ejlchina/http/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java similarity index 98% rename from src/main/java/com/ejlchina/http/HttpTask.java rename to src/main/java/com/ejlchina/okhttps/HttpTask.java index 04ccf72c..ae6067be 100644 --- a/src/main/java/com/ejlchina/http/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; import java.io.File; import java.io.IOException; @@ -10,10 +10,10 @@ import java.util.Map; import com.alibaba.fastjson.JSON; -import com.ejlchina.http.HttpResult.State; -import com.ejlchina.http.internal.HttpClient; -import com.ejlchina.http.internal.HttpException; -import com.ejlchina.http.internal.ProcessRequestBody; +import com.ejlchina.okhttps.HttpResult.State; +import com.ejlchina.okhttps.internal.HttpClient; +import com.ejlchina.okhttps.internal.HttpException; +import com.ejlchina.okhttps.internal.ProcessRequestBody; import okhttp3.Call; import okhttp3.FormBody; diff --git a/src/main/java/com/ejlchina/http/HttpUtils.java b/src/main/java/com/ejlchina/okhttps/HttpUtils.java similarity index 92% rename from src/main/java/com/ejlchina/http/HttpUtils.java rename to src/main/java/com/ejlchina/okhttps/HttpUtils.java index f7b7ccb5..96dca13d 100644 --- a/src/main/java/com/ejlchina/http/HttpUtils.java +++ b/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -1,8 +1,8 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; -import com.ejlchina.http.internal.AsyncHttpTask; -import com.ejlchina.http.internal.SyncHttpTask; -import com.ejlchina.http.internal.TaskExecutor; +import com.ejlchina.okhttps.internal.AsyncHttpTask; +import com.ejlchina.okhttps.internal.SyncHttpTask; +import com.ejlchina.okhttps.internal.TaskExecutor; import okhttp3.Call; import okhttp3.Request; diff --git a/src/main/java/com/ejlchina/http/OnCallback.java b/src/main/java/com/ejlchina/okhttps/OnCallback.java similarity index 80% rename from src/main/java/com/ejlchina/http/OnCallback.java rename to src/main/java/com/ejlchina/okhttps/OnCallback.java index 32dd81e8..bfeeaa3e 100644 --- a/src/main/java/com/ejlchina/http/OnCallback.java +++ b/src/main/java/com/ejlchina/okhttps/OnCallback.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; /** * 数�回调接� diff --git a/src/main/java/com/ejlchina/http/Preprocessor.java b/src/main/java/com/ejlchina/okhttps/Preprocessor.java similarity index 94% rename from src/main/java/com/ejlchina/http/Preprocessor.java rename to src/main/java/com/ejlchina/okhttps/Preprocessor.java index ee2f757c..d0f6f96c 100644 --- a/src/main/java/com/ejlchina/http/Preprocessor.java +++ b/src/main/java/com/ejlchina/okhttps/Preprocessor.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; /** * 预处�器,支�异步 diff --git a/src/main/java/com/ejlchina/http/Process.java b/src/main/java/com/ejlchina/okhttps/Process.java similarity index 92% rename from src/main/java/com/ejlchina/http/Process.java rename to src/main/java/com/ejlchina/okhttps/Process.java index aff09bd3..6f36f827 100644 --- a/src/main/java/com/ejlchina/http/Process.java +++ b/src/main/java/com/ejlchina/okhttps/Process.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; /** * 进度(上传或下载) diff --git a/src/main/java/com/ejlchina/http/TaskListener.java b/src/main/java/com/ejlchina/okhttps/TaskListener.java similarity index 91% rename from src/main/java/com/ejlchina/http/TaskListener.java rename to src/main/java/com/ejlchina/okhttps/TaskListener.java index 90c2ada2..54f734d1 100644 --- a/src/main/java/com/ejlchina/http/TaskListener.java +++ b/src/main/java/com/ejlchina/okhttps/TaskListener.java @@ -1,4 +1,4 @@ -package com.ejlchina.http; +package com.ejlchina.okhttps; /** * 任务监�接� diff --git a/src/main/java/com/ejlchina/http/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java similarity index 96% rename from src/main/java/com/ejlchina/http/internal/AsyncHttpTask.java rename to src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index c55985a8..cadc760c 100644 --- a/src/main/java/com/ejlchina/http/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -1,12 +1,12 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; import java.io.IOException; -import com.ejlchina.http.HttpCall; -import com.ejlchina.http.HttpResult; -import com.ejlchina.http.HttpResult.State; -import com.ejlchina.http.HttpTask; -import com.ejlchina.http.OnCallback; +import com.ejlchina.okhttps.HttpCall; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.OnCallback; +import com.ejlchina.okhttps.HttpResult.State; import okhttp3.Call; import okhttp3.Callback; diff --git a/src/main/java/com/ejlchina/http/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java similarity index 96% rename from src/main/java/com/ejlchina/http/internal/HttpClient.java rename to src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 6d224c45..cdc0c85e 100644 --- a/src/main/java/com/ejlchina/http/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -1,4 +1,4 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; import java.io.IOException; import java.util.ArrayList; @@ -11,15 +11,15 @@ import java.util.Queue; import java.util.concurrent.Executor; -import com.ejlchina.http.Configurator; -import com.ejlchina.http.DownListener; -import com.ejlchina.http.HTTP; -import com.ejlchina.http.HttpCall; -import com.ejlchina.http.HttpResult; -import com.ejlchina.http.HttpResult.State; -import com.ejlchina.http.HttpTask; -import com.ejlchina.http.Preprocessor; -import com.ejlchina.http.TaskListener; +import com.ejlchina.okhttps.Configurator; +import com.ejlchina.okhttps.DownListener; +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpCall; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.Preprocessor; +import com.ejlchina.okhttps.TaskListener; +import com.ejlchina.okhttps.HttpResult.State; import okhttp3.Call; import okhttp3.MediaType; diff --git a/src/main/java/com/ejlchina/http/internal/HttpException.java b/src/main/java/com/ejlchina/okhttps/internal/HttpException.java similarity index 91% rename from src/main/java/com/ejlchina/http/internal/HttpException.java rename to src/main/java/com/ejlchina/okhttps/internal/HttpException.java index f78606cf..c2bf3f37 100644 --- a/src/main/java/com/ejlchina/http/internal/HttpException.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpException.java @@ -1,4 +1,4 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; /** * Created by 周旭(Troy.Zhou) on 2016/8/30. diff --git a/src/main/java/com/ejlchina/http/internal/ProcessInputStream.java b/src/main/java/com/ejlchina/okhttps/internal/ProcessInputStream.java similarity index 90% rename from src/main/java/com/ejlchina/http/internal/ProcessInputStream.java rename to src/main/java/com/ejlchina/okhttps/internal/ProcessInputStream.java index 779ddc30..77cf2e91 100644 --- a/src/main/java/com/ejlchina/http/internal/ProcessInputStream.java +++ b/src/main/java/com/ejlchina/okhttps/internal/ProcessInputStream.java @@ -1,11 +1,11 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.Executor; -import com.ejlchina.http.OnCallback; -import com.ejlchina.http.Process; +import com.ejlchina.okhttps.OnCallback; +import com.ejlchina.okhttps.Process; public class ProcessInputStream extends InputStream { diff --git a/src/main/java/com/ejlchina/http/internal/ProcessRequestBody.java b/src/main/java/com/ejlchina/okhttps/internal/ProcessRequestBody.java similarity index 95% rename from src/main/java/com/ejlchina/http/internal/ProcessRequestBody.java rename to src/main/java/com/ejlchina/okhttps/internal/ProcessRequestBody.java index 6f406b54..c1f50f55 100644 --- a/src/main/java/com/ejlchina/http/internal/ProcessRequestBody.java +++ b/src/main/java/com/ejlchina/okhttps/internal/ProcessRequestBody.java @@ -1,10 +1,10 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; import java.io.IOException; import java.util.concurrent.Executor; -import com.ejlchina.http.OnCallback; -import com.ejlchina.http.Process; +import com.ejlchina.okhttps.OnCallback; +import com.ejlchina.okhttps.Process; import okhttp3.MediaType; import okhttp3.RequestBody; diff --git a/src/main/java/com/ejlchina/http/internal/RealHttpResult.java b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java similarity index 95% rename from src/main/java/com/ejlchina/http/internal/RealHttpResult.java rename to src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java index 697fd4a6..1218e4a0 100644 --- a/src/main/java/com/ejlchina/http/internal/RealHttpResult.java +++ b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java @@ -1,9 +1,9 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; import java.util.List; -import com.ejlchina.http.HttpResult; -import com.ejlchina.http.HttpTask; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; import okhttp3.Headers; import okhttp3.Response; diff --git a/src/main/java/com/ejlchina/http/internal/RealProcess.java b/src/main/java/com/ejlchina/okhttps/internal/RealProcess.java similarity index 91% rename from src/main/java/com/ejlchina/http/internal/RealProcess.java rename to src/main/java/com/ejlchina/okhttps/internal/RealProcess.java index 700d2895..895583e3 100644 --- a/src/main/java/com/ejlchina/http/internal/RealProcess.java +++ b/src/main/java/com/ejlchina/okhttps/internal/RealProcess.java @@ -1,6 +1,6 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; -import com.ejlchina.http.Process; +import com.ejlchina.okhttps.Process; public class RealProcess implements Process { diff --git a/src/main/java/com/ejlchina/http/internal/ResultBody.java b/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java similarity index 97% rename from src/main/java/com/ejlchina/http/internal/ResultBody.java rename to src/main/java/com/ejlchina/okhttps/internal/ResultBody.java index aa827e75..1123668e 100644 --- a/src/main/java/com/ejlchina/http/internal/ResultBody.java +++ b/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java @@ -1,4 +1,4 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; import static java.nio.charset.StandardCharsets.UTF_8; @@ -17,11 +17,11 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.ejlchina.http.Download; -import com.ejlchina.http.HttpTask; -import com.ejlchina.http.HttpResult.Body; -import com.ejlchina.http.OnCallback; -import com.ejlchina.http.Process; +import com.ejlchina.okhttps.Download; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.OnCallback; +import com.ejlchina.okhttps.Process; +import com.ejlchina.okhttps.HttpResult.Body; import okhttp3.MediaType; import okhttp3.Response; diff --git a/src/main/java/com/ejlchina/http/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java similarity index 92% rename from src/main/java/com/ejlchina/http/internal/SyncHttpTask.java rename to src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index 8ff98b5b..648c8357 100644 --- a/src/main/java/com/ejlchina/http/internal/SyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -1,10 +1,10 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; import java.io.IOException; -import com.ejlchina.http.HttpResult; -import com.ejlchina.http.HttpResult.State; -import com.ejlchina.http.HttpTask; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.HttpResult.State; import okhttp3.Call; import okhttp3.Response; diff --git a/src/main/java/com/ejlchina/http/internal/TaskExecutor.java b/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java similarity index 89% rename from src/main/java/com/ejlchina/http/internal/TaskExecutor.java rename to src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 419bc56c..fbb164b1 100644 --- a/src/main/java/com/ejlchina/http/internal/TaskExecutor.java +++ b/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -1,17 +1,17 @@ -package com.ejlchina.http.internal; +package com.ejlchina.okhttps.internal; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.Executor; -import com.ejlchina.http.DownListener; -import com.ejlchina.http.Download; -import com.ejlchina.http.HttpResult; -import com.ejlchina.http.HttpResult.State; -import com.ejlchina.http.HttpTask; -import com.ejlchina.http.OnCallback; -import com.ejlchina.http.TaskListener; +import com.ejlchina.okhttps.DownListener; +import com.ejlchina.okhttps.Download; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.OnCallback; +import com.ejlchina.okhttps.TaskListener; +import com.ejlchina.okhttps.HttpResult.State; public class TaskExecutor { diff --git a/src/test/java/com/ejlchina/test/HttpTest.java b/src/test/java/com/ejlchina/test/HttpTest.java index 6573da97..e8951dab 100644 --- a/src/test/java/com/ejlchina/test/HttpTest.java +++ b/src/test/java/com/ejlchina/test/HttpTest.java @@ -8,19 +8,19 @@ import org.junit.Test; -import com.ejlchina.http.Download; -import com.ejlchina.http.Download.Ctrl; -import com.ejlchina.http.Download.Failure; -import com.ejlchina.http.HTTP; -import com.ejlchina.http.HttpCall; -import com.ejlchina.http.HttpResult; -import com.ejlchina.http.HttpResult.Body; -import com.ejlchina.http.HttpResult.State; -import com.ejlchina.http.HttpTask; -import com.ejlchina.http.HttpUtils; -import com.ejlchina.http.Preprocessor.PreChain; -import com.ejlchina.http.Process; -import com.ejlchina.http.internal.HttpClient; +import com.ejlchina.okhttps.Download; +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpCall; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.HttpUtils; +import com.ejlchina.okhttps.Process; +import com.ejlchina.okhttps.Download.Ctrl; +import com.ejlchina.okhttps.Download.Failure; +import com.ejlchina.okhttps.HttpResult.Body; +import com.ejlchina.okhttps.HttpResult.State; +import com.ejlchina.okhttps.Preprocessor.PreChain; +import com.ejlchina.okhttps.internal.HttpClient; import okhttp3.ConnectionPool; import okhttp3.Interceptor.Chain; From 09b68905fe90b686572c5f7ed268062439663d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 31 Mar 2020 14:28:05 +0800 Subject: [PATCH 004/924] name: HttpUtils -> OkHttps, version: 1.0.0 --- pom.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index f434d4c5..c322c04d 100644 --- a/pom.xml +++ b/pom.xml @@ -2,9 +2,9 @@ 4.0.0 com.ejlchina - httputils - 2.3.0 - HttpUtils + okhttps + 1.0.0 + OkHttps 1.8 @@ -29,9 +29,9 @@ - scm:git://gitee.com/ejlchina-zhxu/httputils.git - scm:http://gitee.com/ejlchina-zhxu/httputils - https://gitee.com/ejlchina-zhxu/httputils + scm:git://gitee.com/ejlchina-zhxu/okhttps.git + scm:http://gitee.com/ejlchina-zhxu/okhttps + https://gitee.com/ejlchina-zhxu/okhttps v2.2.0 @@ -86,7 +86,7 @@ - httputils + okhttps @@ -157,13 +157,13 @@ - https://gitee.com/ejlchina-zhxu/httputils + https://gitee.com/ejlchina-zhxu/okhttps Http工具包,�装 OkHttp,链�用法�支�异步�步��应JSON自动解�,回调线程切���置�活�支�URL��符�支�BaseUrl�外部�赖少�适用 JavaWeb 和 Android,教程全��简�易用 江�一键�信�科技有�公� http://www.ejlchina.com/ - https://gitee.com/ejlchina-zhxu/httputils/issues + https://gitee.com/ejlchina-zhxu/okhttps/issues \ No newline at end of file From 5e2a49147a4924b39fdcc842d35bdac00d6d7eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 31 Mar 2020 14:32:38 +0800 Subject: [PATCH 005/924] =?UTF-8?q?HttpUtils=20of=20=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E4=B8=BA=E5=BC=82=E5=B8=B8=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/src/main/java/com/ejlchina/okhttps/HttpUtils.java index 96dca13d..a03e365f 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -36,6 +36,8 @@ public class HttpUtils { public static void of(HTTP http) { if (http != null) { HttpUtils.http = http; + } else { + throw new IllegalArgumentException("Parameter http can not be null!"); } } From 2940751fa88647554f9a5775409ad67266008e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 31 Mar 2020 15:13:42 +0800 Subject: [PATCH 006/924] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index b83e8387..fb708986 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# HttpUtils +# OkHttps -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/httputils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/httputils/) -[![License](https://img.shields.io/hexpm/l/plug.svg)](https://gitee.com/ejlchina-zhxu/httputils/blob/master/LICENSE) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/okhttps/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/okhttps/) +[![License](https://img.shields.io/hexpm/l/plug.svg)](https://gitee.com/ejlchina-zhxu/okhttps/blob/master/LICENSE) [![Troy.Zhou](https://img.shields.io/badge/%E4%BD%9C%E8%80%85-ejlchina-orange.svg)](https://github.com/ejlchina) ## 介� -  HttpUtils 是近期开�的对 OkHttp 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 +  OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 * 链�调用,一点到底 * BaseURL�URL��符�JSON自动�装与解� @@ -14,8 +14,7 @@ * 文件上传下载(过程控制�进度监�) * TCP连接池�Http2 -### 当�文档版本[2.3.0](近期�布到中央仓库) -#### [查阅[2.1.x]点我](https://gitee.com/ejlchina-zhxu/httputils/blob/master/README-2.1.2.md) | [查阅[2.0.x]点我](https://gitee.com/ejlchina-zhxu/httputils/blob/master/README-2.0.0.md) | [查阅[1.0.x]点我](https://gitee.com/ejlchina-zhxu/httputils/blob/1.x/README.md) +### 当�文档版本[1.0.0](近期�布到中央仓库) ## 目录 @@ -62,13 +61,13 @@ ``` com.ejlchina - httputils - 2.3.0 + okhttps + 1.0.0 ``` ### Gradle -`compile 'com.ejlchina:httputils:2.3.0'` +`compile 'com.ejlchina:okhttps:1.0.0'` ## 使用说明 @@ -345,7 +344,7 @@ HTTP http = HTTP.builder() #### 6.3 �置 OkHttpClient -  与其他�装 OkHttp 的框架��,HttpUtils 并�会�蔽 OkHttp 本身就很好用的功能,如下: +  与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下: ```java HTTP http = HTTP.builder() @@ -391,7 +390,7 @@ HTTP http = HTTP.builder()   普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当`Token`过期时我们需�去刷新获�新`Token`,而刷新`Token`这个�作�能有一个任务去执行,因为如果`n`个任务�时执行的�,那么必有`n-1`个任务刚刷新得到的`Token`�能就立马失效了,而这是我们所�希望的。 -  为了解决这个问题,HttpUtils �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器: +  为了解决这个问题,OkHttps �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器: ```java HTTP http = HTTP.builder() @@ -474,7 +473,7 @@ List users = HttpUtils.sync("/users") ### 8 文件下载 -  HttpUtils 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例: +  OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例: ```java http.sync("/download/test.zip") @@ -517,7 +516,7 @@ http.sync("/download/test.zip") }) .start(); ``` -  值得一�的是:由于 HttpUtils 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有`Content-Length`头),例如: +  值得一�的是:由于 OkHttps 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有`Content-Length`头),例如: ```java List users = http.sync("/users") @@ -562,7 +561,7 @@ http.async("/download/test.zip") #### 8.3 实现断点续传 -  HttpUtils 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,HttpUtils 通过一个失败回调拿到**断点**,便将��的问题�得简�: +  OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到**断点**,便将��的问题�得简�: ```java http.sync("/download/test.zip") @@ -651,7 +650,7 @@ http.async("/upload") #### 9.1 上传进度监� -  HttpUtils 的上传进度监�,监�的是所有请求报文体的��进度,示例代�: +  OkHttps 的上传进度监�,监�的是所有请求报文体的��进度,示例代�: ```java http.sync("/upload") @@ -668,7 +667,7 @@ http.sync("/upload") }) .post() ``` -  咦�怎么感觉和下载的进度回调的一样?没错�HttpUtils 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在`get/post`方法之�使用这些API,下载是在`getBody`方法之�使用。很好�解:`get/post`之�是准备��请求时段,有上传的�义,而`getBody`之�,已是报文�应的时段,当然是下载。 +  咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在`get/post`方法之�使用这些API,下载是在`getBody`方法之�使用。很好�解:`get/post`之�是准备��请求时段,有上传的�义,而`getBody`之�,已是报文�应的时段,当然是下载。 #### 9.2 上传过程控制 @@ -688,11 +687,11 @@ call.cancel(); // �消上传 ### 10 执行线程自由切�(for Android) -  在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。HttpUtils 为这类问题�供了良好的方案。 +  在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 -  在 **默认** 情况下,**所有回调** 函数都会 **在 IO 线程** 执行。为什么会设计如此呢?这是因为 HttpUtils �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。 +  在 **默认** 情况下,**所有回调** 函数都会 **在 IO 线程** 执行。为什么会设计如此呢?这是因为 OkHttps �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。 -  但是在 Android 里使用 HttpUtils 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器: +  但是在 Android 里使用 OkHttps 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器: ```java HTTP http = HTTP.builder() @@ -721,7 +720,7 @@ http.async("/users") }) .post(); ``` -  但是,如果�时还想让�些回调放在IO线程,实现 **自由切�**,怎么办呢?HttpUtils 给出了�常�活的方法,如下: +  但是,如果�时还想让�些回调放在IO线程,实现 **自由切�**,怎么办呢?OkHttps 给出了�常�活的方法,如下: ```java http.async("/users") From 869c2917f8366a61b996a09dc2f4aba18816201f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 31 Mar 2020 16:13:15 +0800 Subject: [PATCH 007/924] readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fb708986..975d597d 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ * 文件上传下载(过程控制�进度监�) * TCP连接池�Http2 +### �身:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.0](近期�布到中央仓库) ## 目录 From c37f31fa75868fb4ca5424a08431ffb0cfe6cc39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 31 Mar 2020 16:14:57 +0800 Subject: [PATCH 008/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 975d597d..6a00fcec 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ * 文件上传下载(过程控制�进度监�) * TCP连接池�Http2 -### �身:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) +### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.0](近期�布到中央仓库) ## 目录 From e53ca139c42b4252ab6232c9dfe1f6656b833bdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 31 Mar 2020 16:19:23 +0800 Subject: [PATCH 009/924] . --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a00fcec..bb89e92d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ * TCP连接池�Http2 ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) -### 当�文档版本[1.0.0](近期�布到中央仓库) +### 当�文档版本[1.0.0] ## 目录 From 3f0cfca90433208ae0deed9f3670533e0f64b4e3 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 7 Apr 2020 16:36:43 +0800 Subject: [PATCH 010/924] update README.md. --- README.md | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index bb89e92d..a8531e9d 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ http.async("/users/1") // http://api.demo.com/users/1 ```java HttpResult res1 = http.sync("/users").get(); // �步 GET -HttpResult res2 = http.sync("/users")post(); // �步 POST +HttpResult res2 = http.sync("/users").post(); // �步 POST HttpResult res3 = http.sync("/users/1").put(); // �步 PUT HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE HttpCall call1 = http.async("/users").get(); // 异步 GET @@ -202,21 +202,15 @@ List orders = http.sync("/orders") .get().getBody().toList(Order.class); ``` -  示例,下载文件到指定目录: +  示例,使用 cache 方法: ```java -String path = "D:/reports/2020-03-01.xlsx"; // 文件�存目录 +Body body = http.sync("/orders").get().getBody().cache(); -// �步下载 -http.sync("/reports/2020-03-01.xlsx") - .get().getBody().toFile(path); - -// 异步下载 -http.async("/reports/2020-03-01.xlsx") - .setOnResponse((HttpResult result) -> { - result.getBody().toFile(path); - }) - .get(); +// 使用 cache �,�以多次使用 toXXX() 方法 +System.out.println(body.toString()); +System.out.println(body.toJsonArray()); +System.out.println(body.toList(Order.class)); ``` #### 3.3 HttpCall From f56b83679bca4fbb4e9153e13c21a4da7d47784e Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 7 Apr 2020 16:45:34 +0800 Subject: [PATCH 011/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a8531e9d..80223ac7 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ http.async("/users/{id}") // http://api.demo.com/users/1 * `getHeaders()` 得到HTTP�应头 * `getHeaders(String name)` 得到HTTP�应头 * `getHeader(String name)` 得到HTTP�应头 -* `getBody()` 得到�应报文体`Body`实例,它定义了如下方法(对�一个`Body`实例,以下的`toXXX()`类方法�能使用一个且仅能调用一次): +* `getBody()` 得到�应报文体`Body`实例,它定义了如下方法(对�一个`Body`实例,以下的`toXXX()`类方法�能使用一个且仅能调用一次,除�先使用 cache 方法): * `toBytes()` 返回字节数组 * `toByteStream()` 返回字节输入� * `toCharStream()` 返回字符输入� From 7c75812ad7aa0853e7e08f84bc8fd3280d96071b Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 7 Apr 2020 16:53:36 +0800 Subject: [PATCH 012/924] update README.md. --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 80223ac7..57e94c78 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,20 @@ System.out.println(body.toJsonArray()); System.out.println(body.toList(Order.class)); ``` +  示例,获�下载文件的大�: + +```java +long size = http.sync("http://api.demo.com/download/test.zip") + .get().getBody() + .close() // �是想获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); // 获得待下载文件的大� + +// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络��) + +System.out.println("size = " + size); +``` + + #### 3.3 HttpCall   `HttpCall`对象是异步请求方法(`get`�`post`�`put`�`delete`)的返回值,与`java`的`Future`接�很�,它有如下方法: From 1a7b8db91141e3273a10ee1ed4779a1daefdbb36 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 7 Apr 2020 17:02:41 +0800 Subject: [PATCH 013/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57e94c78..7a9c954b 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ - [6.2 回调执行器](#62-回调执行器) - [6.3 �置 OkHttpClient](#63-�置-okhttpclient) - [6.4 并行预处�器](#64-并行预处�器) - - [6.5 串行预处�器](#65-串行预处�器) + - [6.5 串行预处�器(Token问题最优雅的解决方案)](#65-串行预处�器) - [6.6 全局回调处�](#66-全局回调处�) - [6.7 全局下载监�](#67-全局下载监�) + [7 使用 HttpUtils 类](#7-使用-httputils-类) From 0e2b9cd443d8c26de48a424a12fb54c5a07161f5 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 7 Apr 2020 22:37:21 +0800 Subject: [PATCH 014/924] update README.md. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7a9c954b..0b86c262 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.0] +### API文档:[https://apidoc.gitee.com/ejlchina-zhxu/okhttps](https://apidoc.gitee.com/ejlchina-zhxu/okhttps) ## 目录 From 0c14c2dfba96883de1069a27107e4e6e25469ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Tue, 7 Apr 2020 23:32:23 +0800 Subject: [PATCH 015/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=20HttpResult=20?= =?UTF-8?q?=E7=9A=84=E5=AE=9E=E7=8E=B0=EF=BC=8C=201=E3=80=81=E5=BD=93?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E7=8A=B6=E6=80=81=20!=3D=20State.RESPONSED?= =?UTF-8?q?=20=E6=97=B6=EF=BC=8C=E8=B0=83=E7=94=A8=20getHeaders=20?= =?UTF-8?q?=E7=AD=89=E6=96=B9=E6=B3=95=E6=97=B6=E4=B8=8D=E5=86=8D=E6=8A=9B?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=202=E3=80=81HttpResult.toString=20=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E7=A7=BB=E9=99=A4=E5=AF=B9=20Body.toString=20?= =?UTF-8?q?=E7=9A=84=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/internal/RealHttpResult.java | 274 +++++++++--------- 1 file changed, 140 insertions(+), 134 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java index 1218e4a0..c9326d36 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java +++ b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java @@ -1,134 +1,140 @@ -package com.ejlchina.okhttps.internal; - -import java.util.List; - -import com.ejlchina.okhttps.HttpResult; -import com.ejlchina.okhttps.HttpTask; - -import okhttp3.Headers; -import okhttp3.Response; - - -public class RealHttpResult implements HttpResult { - - private State state; - private Response response; - private Exception error; - private TaskExecutor taskExecutor; - private HttpTask httpTask; - - - public RealHttpResult(HttpTask httpTask, State state) { - this.httpTask = httpTask; - this.state = state; - } - - public RealHttpResult(HttpTask httpTask, Response response, TaskExecutor taskExecutor) { - this(httpTask, taskExecutor); - response(response); - } - - public RealHttpResult(HttpTask httpTask, TaskExecutor taskExecutor) { - this.httpTask = httpTask; - this.taskExecutor = taskExecutor; - } - - public RealHttpResult(HttpTask httpTask, State state, Exception error) { - this.httpTask = httpTask; - exception(state, error); - } - - - public void exception(State state, Exception error) { - this.state = state; - this.error = error; - } - - public void response(Response response) { - this.state = State.RESPONSED; - this.response = response; - } - - @Override - public HttpTask getTask() { - return httpTask; - } - - @Override - public State getState() { - return state; - } - - @Override - public int getStatus() { - if (response != null) { - return response.code(); - } - return 0; - } - - @Override - public boolean isSuccessful() { - if (response != null) { - return response.isSuccessful(); - } - return false; - } - - @Override - public Headers getHeaders() { - if (response != null) { - return response.headers(); - } - return null; - } - - @Override - public List getHeaders(String name) { - return response.headers(name); - } - - @Override - public String getHeader(String name) { - return response.header(name); - } - - @Override - public Body getBody() { - if (response != null) { - return new ResultBody(httpTask, response, taskExecutor); - } - return null; - } - - @Override - public Exception getError() { - return error; - } - - public Response getResponse() { - return response; - } - - - @Override - public String toString() { - Body body = getBody(); - String str = "HttpResult [\n state: " + state + ",\n status: " + getStatus() - + ",\n headers: " + getHeaders(); - if (body != null) { - str += ",\n contentType: " + body.getContentType() - + ",\n body: " + body.toString(); - } - return str + ",\n error: " + error + "\n]"; - } - - @Override - public HttpResult close() { - if (response != null) { - response.close(); - } - return this; - } - -} +package com.ejlchina.okhttps.internal; + +import java.util.Collections; +import java.util.List; + +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; + +import okhttp3.Headers; +import okhttp3.Response; + + +public class RealHttpResult implements HttpResult { + + private State state; + private Response response; + private Exception error; + private TaskExecutor taskExecutor; + private HttpTask httpTask; + private Body body; + + public RealHttpResult(HttpTask httpTask, State state) { + this.httpTask = httpTask; + this.state = state; + } + + public RealHttpResult(HttpTask httpTask, Response response, TaskExecutor taskExecutor) { + this(httpTask, taskExecutor); + response(response); + } + + public RealHttpResult(HttpTask httpTask, TaskExecutor taskExecutor) { + this.httpTask = httpTask; + this.taskExecutor = taskExecutor; + } + + public RealHttpResult(HttpTask httpTask, State state, Exception error) { + this.httpTask = httpTask; + exception(state, error); + } + + + public void exception(State state, Exception error) { + this.state = state; + this.error = error; + } + + public void response(Response response) { + this.state = State.RESPONSED; + this.response = response; + } + + @Override + public HttpTask getTask() { + return httpTask; + } + + @Override + public State getState() { + return state; + } + + @Override + public int getStatus() { + if (response != null) { + return response.code(); + } + return 0; + } + + @Override + public boolean isSuccessful() { + if (response != null) { + return response.isSuccessful(); + } + return false; + } + + @Override + public Headers getHeaders() { + if (response != null) { + return response.headers(); + } + return null; + } + + @Override + public List getHeaders(String name) { + if (response != null) { + return response.headers(name); + } + return Collections.emptyList(); + } + + @Override + public String getHeader(String name) { + if (response != null) { + return response.header(name); + } + return null; + } + + @Override + public Body getBody() { + if (body == null && response != null) { + body = new ResultBody(httpTask, response, taskExecutor); + } + return body; + } + + @Override + public Exception getError() { + return error; + } + + public Response getResponse() { + return response; + } + + + @Override + public String toString() { + Body body = getBody(); + String str = "HttpResult [\n state: " + state + ",\n status: " + getStatus() + + ",\n headers: " + getHeaders(); + if (body != null) { + str += ",\n contentType: " + body.getContentType(); + } + return str + ",\n error: " + error + "\n]"; + } + + @Override + public HttpResult close() { + if (response != null) { + response.close(); + } + return this; + } + +} From ed80e855c4a4c82ce4e289d23d6fc037910ac3cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Tue, 7 Apr 2020 23:45:30 +0800 Subject: [PATCH 016/924] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20HttpResult.getTask?= =?UTF-8?q?()=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpResult.java | 558 +++++++++--------- .../okhttps/internal/RealHttpResult.java | 5 - 2 files changed, 276 insertions(+), 287 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpResult.java b/src/main/java/com/ejlchina/okhttps/HttpResult.java index c3d51d96..63424db2 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpResult.java +++ b/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -1,282 +1,276 @@ -package com.ejlchina.okhttps; - -import java.io.File; -import java.io.InputStream; -import java.io.Reader; -import java.util.List; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.ejlchina.okhttps.internal.RealHttpResult; -import com.ejlchina.okhttps.internal.TaskExecutor; - -import okhttp3.Headers; -import okhttp3.MediaType; -import okhttp3.Response; - - -/** - * Http 执行结果 - */ -public interface HttpResult { - - /** - * 构造一个 HttpResult - * 此方法构造的 HttpResult ��设置进度回调,��进行下载�作� - * 若需�,请使用方法: {@link #of(Response, TaskExecutor)} - * @param response Response - * @return HttpResult - */ - static HttpResult of(Response response) { - return of(response, null); - } - - /** - * 构造一个 HttpResult - * @param response Response - * @param taskExecutor 任务执行器, �通过方法 {@link HTTP#getExecutor()} 获得 - * @return HttpResult - */ - static HttpResult of(Response response, TaskExecutor taskExecutor) { - if (response != null) { - return new RealHttpResult(null, response, taskExecutor); - } - throw new IllegalArgumentException("response �能为空"); - } - - /** - * 获�所属的 Http请求任务 - * @return HttpTask - */ - HttpTask getTask(); - - - public enum State { - - /** - * 执行异常 - */ - EXCEPTION, - - /** - * 请求被�消 - */ - CANCELED, - - /** - * 请求已�应 - */ - RESPONSED, - - /** - * 网络超时 - */ - TIMEOUT, - - /** - * 网络出错 - */ - NETWORK_ERROR - - } - - /** - * HTTP�应报文体 - */ - public interface Body { - - /** - * @return 媒体类型 - */ - MediaType getContentType(); - - /** - * @return 报文体字节长度 - */ - long getContentLength(); - - /** - * 在IO线程执行 - * @return Body - */ - Body nextOnIO(); - - /** - * 设置报文体接收进度回调 - * @param onProcess 进度回调函数 - * @return Body - */ - Body setOnProcess(OnCallback onProcess); - - /** - * 设置进度回调的步进字节,默认 8K(8192) - * 表示�接收 stepBytes 个字节,执行一次进度回调 - * @param stepBytes 步进字节 - * @return Body - */ - Body setStepBytes(long stepBytes); - - /** - * 设置进度回调的步进比例 - * 表示�接收 stepRate 比例,执行一次进度回调 - * @param stepRate 步进比例 - * @return Body - */ - Body setStepRate(double stepRate); - - /** - * 设置进度回调忽略�应的Range头信�,�进度回调会从0开始 - * @return Body - */ - Body setRangeIgnored(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转字节� - */ - InputStream toByteStream(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转字节数组 - */ - byte[] toBytes(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转字符� - */ - Reader toCharStream(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转字符串 - */ - String toString(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转Json对象 - */ - JSONObject toJsonObject(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转Json数组 - */ - JSONArray toJsonArray(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param 目标泛型 - * @param type 目标类型 - * @return 报文体Json文本转JavaBean - */ - T toBean(Class type); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param 目标泛型 - * @param type 目标类型 - * @return 报文体Json文本转JavaBean列表 - */ - List toList(Class type); - - /** - * 下载到指定路径 - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param filePath 目标路径 - * @return 下载过程 #Download - */ - Download toFile(String filePath); - - /** - * 下载到指定文件 - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param file 目标文件 - * @return 下载过程 #Download - */ - Download toFile(File file); - - /** - * 下载到指定文件夹 - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param dirPath 目标目录 - * @return 下载过程 #Download - */ - Download toFolder(String dirPath); - - /** - * 下载到指定文件夹 - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param dir 目标目录 - * @return 下载过程 #Download - */ - Download toFolder(File dir); - - /** - * 缓存自己,缓存�� ��使用 toXXX 类方法 - * @return Body - */ - Body cache(); - - /** - * 关闭报文体 - * 未对报文体�任何消费时使用,比如�读�长度 - * @return Body - */ - Body close(); - - } - - - /** - * @return 执行状� - */ - State getState(); - - /** - * @return HTTP状�� - */ - int getStatus(); - - /** - * @return 是��应�功,状��在 [200..300) 之间 - */ - boolean isSuccessful(); - - /** - * @return �应头 - */ - Headers getHeaders(); - - /** - * @param name 头�称 - * @return �应头 - */ - List getHeaders(String name); - - /** - * @param name 头�称 - * @return �应头 - */ - String getHeader(String name); - - /** - * @return �应报文体 - */ - Body getBody(); - - /** - * @return 执行中�生的异常 - */ - Exception getError(); - - /** - * 关闭报文 - * 未对报文体�任何消费时使用,比如�读�报文头 - * @return HttpResult - */ - HttpResult close(); - -} +package com.ejlchina.okhttps; + +import java.io.File; +import java.io.InputStream; +import java.io.Reader; +import java.util.List; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ejlchina.okhttps.internal.RealHttpResult; +import com.ejlchina.okhttps.internal.TaskExecutor; + +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.Response; + + +/** + * Http 执行结果 + */ +public interface HttpResult { + + /** + * 构造一个 HttpResult + * 此方法构造的 HttpResult ��设置进度回调,��进行下载�作� + * 若需�,请使用方法: {@link #of(Response, TaskExecutor)} + * @param response Response + * @return HttpResult + */ + static HttpResult of(Response response) { + return of(response, null); + } + + /** + * 构造一个 HttpResult + * @param response Response + * @param taskExecutor 任务执行器, �通过方法 {@link HTTP#getExecutor()} 获得 + * @return HttpResult + */ + static HttpResult of(Response response, TaskExecutor taskExecutor) { + if (response != null) { + return new RealHttpResult(null, response, taskExecutor); + } + throw new IllegalArgumentException("response �能为空"); + } + + + public enum State { + + /** + * 执行异常 + */ + EXCEPTION, + + /** + * 请求被�消 + */ + CANCELED, + + /** + * 请求已�应 + */ + RESPONSED, + + /** + * 网络超时 + */ + TIMEOUT, + + /** + * 网络出错 + */ + NETWORK_ERROR + + } + + /** + * HTTP�应报文体 + */ + public interface Body { + + /** + * @return 媒体类型 + */ + MediaType getContentType(); + + /** + * @return 报文体字节长度 + */ + long getContentLength(); + + /** + * 在IO线程执行 + * @return Body + */ + Body nextOnIO(); + + /** + * 设置报文体接收进度回调 + * @param onProcess 进度回调函数 + * @return Body + */ + Body setOnProcess(OnCallback onProcess); + + /** + * 设置进度回调的步进字节,默认 8K(8192) + * 表示�接收 stepBytes 个字节,执行一次进度回调 + * @param stepBytes 步进字节 + * @return Body + */ + Body setStepBytes(long stepBytes); + + /** + * 设置进度回调的步进比例 + * 表示�接收 stepRate 比例,执行一次进度回调 + * @param stepRate 步进比例 + * @return Body + */ + Body setStepRate(double stepRate); + + /** + * 设置进度回调忽略�应的Range头信�,�进度回调会从0开始 + * @return Body + */ + Body setRangeIgnored(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字节� + */ + InputStream toByteStream(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字节数组 + */ + byte[] toBytes(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字符� + */ + Reader toCharStream(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字符串 + */ + String toString(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转Json对象 + */ + JSONObject toJsonObject(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转Json数组 + */ + JSONArray toJsonArray(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean + */ + T toBean(Class type); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean列表 + */ + List toList(Class type); + + /** + * 下载到指定路径 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param filePath 目标路径 + * @return 下载过程 #Download + */ + Download toFile(String filePath); + + /** + * 下载到指定文件 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param file 目标文件 + * @return 下载过程 #Download + */ + Download toFile(File file); + + /** + * 下载到指定文件夹 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param dirPath 目标目录 + * @return 下载过程 #Download + */ + Download toFolder(String dirPath); + + /** + * 下载到指定文件夹 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param dir 目标目录 + * @return 下载过程 #Download + */ + Download toFolder(File dir); + + /** + * 缓存自己,缓存�� ��使用 toXXX 类方法 + * @return Body + */ + Body cache(); + + /** + * 关闭报文体 + * 未对报文体�任何消费时使用,比如�读�长度 + * @return Body + */ + Body close(); + + } + + + /** + * @return 执行状� + */ + State getState(); + + /** + * @return HTTP状�� + */ + int getStatus(); + + /** + * @return 是��应�功,状��在 [200..300) 之间 + */ + boolean isSuccessful(); + + /** + * @return �应头 + */ + Headers getHeaders(); + + /** + * @param name 头�称 + * @return �应头 + */ + List getHeaders(String name); + + /** + * @param name 头�称 + * @return �应头 + */ + String getHeader(String name); + + /** + * @return �应报文体 + */ + Body getBody(); + + /** + * @return 执行中�生的异常 + */ + Exception getError(); + + /** + * 关闭报文 + * 未对报文体�任何消费时使用,比如�读�报文头 + * @return HttpResult + */ + HttpResult close(); + +} diff --git a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java index c9326d36..4de88afd 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java +++ b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java @@ -50,11 +50,6 @@ public void response(Response response) { this.response = response; } - @Override - public HttpTask getTask() { - return httpTask; - } - @Override public State getState() { return state; From 7d0eba0676addbe57849a81063123126506e2354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Tue, 7 Apr 2020 23:58:22 +0800 Subject: [PATCH 017/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=20HttpCall.getResult?= =?UTF-8?q?()=20=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/internal/AsyncHttpTask.java | 4 ++-- src/main/java/com/ejlchina/okhttps/internal/HttpClient.java | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index cadc760c..44389f03 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -169,7 +169,7 @@ public synchronized HttpResult getResult() { } if (call == null) { try { - wait(); + wait(httpClient.totalTimeoutMillis()); } catch (InterruptedException e) { throw new HttpException(e.getMessage(), e); } @@ -214,7 +214,7 @@ public boolean isCanceled() { public synchronized HttpResult getResult() { if (result == null) { try { - wait(); + wait(httpClient.totalTimeoutMillis()); } catch (InterruptedException e) { throw new HttpException(e.getMessage(), e); } diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index cdc0c85e..15ab2fae 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -99,7 +99,11 @@ public WebSocket webSocket(Request request, WebSocketListener listener) { public OkHttpClient getOkClient() { return client; } - + + public int totalTimeoutMillis() { + return client.connectTimeoutMillis() + client.writeTimeoutMillis() + client.readTimeoutMillis(); + } + public int getTagCallCount() { return tagCalls.size(); } From 3c9c6bdbf48c1c6239fd70b662983bda2c985e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 09:10:37 +0800 Subject: [PATCH 018/924] README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0b86c262..d9644e66 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ - [6.2 回调执行器](#62-回调执行器) - [6.3 �置 OkHttpClient](#63-�置-okhttpclient) - [6.4 并行预处�器](#64-并行预处�器) - - [6.5 串行预处�器(Token问题最优雅的解决方案)](#65-串行预处�器) + - [6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器) - [6.6 全局回调处�](#66-全局回调处�) - [6.7 全局下载监�](#67-全局下载监�) + [7 使用 HttpUtils 类](#7-使用-httputils-类) @@ -396,7 +396,7 @@ HTTP http = HTTP.builder() ```   和`Interceptor`一样,`Preprocessor`也�以添加多个。 -#### 6.5 串行预处�器 +#### 6.5 串行预处�器(TOKEN问题最佳解决方案)   普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当`Token`过期时我们需�去刷新获�新`Token`,而刷新`Token`这个�作�能有一个任务去执行,因为如果`n`个任务�时执行的�,那么必有`n-1`个任务刚刷新得到的`Token`�能就立马失效了,而这是我们所�希望的。 From b15d21f266751f9b191e475b1e3d74ee732415b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 09:11:47 +0800 Subject: [PATCH 019/924] README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d9644e66..2fd5790a 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ - [6.2 回调执行器](#62-回调执行器) - [6.3 �置 OkHttpClient](#63-�置-okhttpclient) - [6.4 并行预处�器](#64-并行预处�器) - - [6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器) + - [6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案) - [6.6 全局回调处�](#66-全局回调处�) - [6.7 全局下载监�](#67-全局下载监�) + [7 使用 HttpUtils 类](#7-使用-httputils-类) From c530520a77ceab6e39a6f021f73f21773cee0d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 09:26:46 +0800 Subject: [PATCH 020/924] README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 2fd5790a..8f51efab 100644 --- a/README.md +++ b/README.md @@ -396,6 +396,11 @@ HTTP http = HTTP.builder() ```   和`Interceptor`一样,`Preprocessor`也�以添加多个。 +> 预处�器(Preprocessor)与拦截器(Interceptor)的区别: +> * 拦截器�能处��步�作,预处�器支�处�异步�作 +> * 拦截器都是并行处�请求,预处�支�串行处�(详�6.5章节) +> * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且预处�器先于拦截器执行 + #### 6.5 串行预处�器(TOKEN问题最佳解决方案)   普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当`Token`过期时我们需�去刷新获�新`Token`,而刷新`Token`这个�作�能有一个任务去执行,因为如果`n`个任务�时执行的�,那么必有`n-1`个任务刚刷新得到的`Token`�能就立马失效了,而这是我们所�希望的。 From 321db867f4c770b67433096a6ed133a07273ae7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 09:29:16 +0800 Subject: [PATCH 021/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f51efab..23016116 100644 --- a/README.md +++ b/README.md @@ -398,7 +398,7 @@ HTTP http = HTTP.builder() > 预处�器(Preprocessor)与拦截器(Interceptor)的区别: > * 拦截器�能处��步�作,预处�器支�处�异步�作 -> * 拦截器都是并行处�请求,预处�支�串行处�(详�6.5章节) +> * 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) > * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且预处�器先于拦截器执行 #### 6.5 串行预处�器(TOKEN问题最佳解决方案) From 084ce950ceac8ee5ff49ee545f65cab944b9cfc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 09:31:43 +0800 Subject: [PATCH 022/924] readme --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 23016116..e676ff36 100644 --- a/README.md +++ b/README.md @@ -394,9 +394,8 @@ HTTP http = HTTP.builder() }) .build(); ``` -  和`Interceptor`一样,`Preprocessor`也�以添加多个。 +  和`Interceptor`一样,`Preprocessor`也�以添加多个。他们之�的区别如下: -> 预处�器(Preprocessor)与拦截器(Interceptor)的区别: > * 拦截器�能处��步�作,预处�器支�处�异步�作 > * 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) > * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且预处�器先于拦截器执行 From 018bca1154087d99dd568b7760498e42bb6b46ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 09:43:54 +0800 Subject: [PATCH 023/924] readme --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e676ff36..d20d2cb2 100644 --- a/README.md +++ b/README.md @@ -398,7 +398,7 @@ HTTP http = HTTP.builder() > * 拦截器�能处��步�作,预处�器支�处�异步�作 > * 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) -> * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且预处�器先于拦截器执行 +> * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且预处�器先于拦截器执行。关于�应�,OkHttps还�供了全局回调机制(详�6.6章节) #### 6.5 串行预处�器(TOKEN问题最佳解决方案) @@ -429,22 +429,27 @@ HTTP http = HTTP.builder() HTTP http = HTTP.builder() .responseListener((HttpTask task, HttpResult result) -> { // 所有请求�应�都会走这里 - + return true; // 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行 }) .completeListener((HttpTask task, State state) -> { // 所有请求执行完都会走这里 - + return true; // 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行 }) .exceptionListener((HttpTask task, IOException error) -> { // 所有请求�生异常都会走这里 - + return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 }) .build(); ``` +  全局回调与拦截器的异�: +> * 处�时机都在请求的�应� +> * 拦截器�以添加多个,全局回调分三�,��最多添加一个 +> * 全局回调�以阻断�个请求的具体回调(在全局回调里返回 false),而拦截器�能 + #### 6.7 全局下载监� ```java From 64d3097464d766b1c1875e59e5e52001ebffbf75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 09:48:15 +0800 Subject: [PATCH 024/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d20d2cb2..f4f3b5e3 100644 --- a/README.md +++ b/README.md @@ -446,7 +446,7 @@ HTTP http = HTTP.builder() ```   全局回调与拦截器的异�: -> * 处�时机都在请求的�应� +> * 拦截器处�时机在请求�和�应�,全局回调�在�应� > * 拦截器�以添加多个,全局回调分三�,��最多添加一个 > * 全局回调�以阻断�个请求的具体回调(在全局回调里返回 false),而拦截器�能 From 0c7ff3b73c796aaf7d40f8c4385e6fbe8ebee578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 09:53:33 +0800 Subject: [PATCH 025/924] readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f4f3b5e3..40740da6 100644 --- a/README.md +++ b/README.md @@ -398,7 +398,7 @@ HTTP http = HTTP.builder() > * 拦截器�能处��步�作,预处�器支�处�异步�作 > * 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) -> * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且预处�器先于拦截器执行。关于�应�,OkHttps还�供了全局回调机制(详�6.6章节) +> * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调机制(详�6.6章节) #### 6.5 串行预处�器(TOKEN问题最佳解决方案) @@ -446,9 +446,9 @@ HTTP http = HTTP.builder() ```   全局回调与拦截器的异�: -> * 拦截器处�时机在请求�和�应�,全局回调�在�应� > * 拦截器�以添加多个,全局回调分三�,��最多添加一个 -> * 全局回调�以阻断�个请求的具体回调(在全局回调里返回 false),而拦截器�能 +> * 拦截器处的�时机在请求�和�应�,全局回调�在�应�,并且晚于拦截器 +> * 全局回调�以阻断(return false)�个请求的具体回调,而拦截器�能 #### 6.7 全局下载监� From c38c79ad2c9bb0dfa48d9313cbace733ab3b6337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 10:55:57 +0800 Subject: [PATCH 026/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/internal/AsyncHttpTask.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 44389f03..a0d798dc 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -169,7 +169,7 @@ public synchronized HttpResult getResult() { } if (call == null) { try { - wait(httpClient.totalTimeoutMillis()); + wait(httpClient.totalTimeoutMillis() * 10); } catch (InterruptedException e) { throw new HttpException(e.getMessage(), e); } @@ -214,7 +214,7 @@ public boolean isCanceled() { public synchronized HttpResult getResult() { if (result == null) { try { - wait(httpClient.totalTimeoutMillis()); + wait(httpClient.totalTimeoutMillis() * 10); } catch (InterruptedException e) { throw new HttpException(e.getMessage(), e); } From 9c2674392741d5bfef2c1e728f74e6500a0da20c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 11:22:05 +0800 Subject: [PATCH 027/924] V1.0.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c322c04d..1678b893 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.ejlchina okhttps - 1.0.0 + 1.0.1 OkHttps @@ -32,7 +32,7 @@ scm:git://gitee.com/ejlchina-zhxu/okhttps.git scm:http://gitee.com/ejlchina-zhxu/okhttps https://gitee.com/ejlchina-zhxu/okhttps - v2.2.0 + v1.0.1 From 1355d8e4aa8ac24600f5dbbb16999d6a0a9db749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 11:40:49 +0800 Subject: [PATCH 028/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 40740da6..79d44f92 100644 --- a/README.md +++ b/README.md @@ -369,7 +369,7 @@ HTTP http = HTTP.builder() // 必须�步返回,拦截器内无法执行异步�作 return chain.proceed(request); }); - // 其它�置: SSL�缓存�代��事件监�... + // 其它�置: CookieJar�SSL�缓存�代��事件监�... }) .build(); ``` From 8b2de164bd9d4867949f5142fe372d4c65fd1d4c Mon Sep 17 00:00:00 2001 From: ejlchina Date: Wed, 8 Apr 2020 12:13:18 +0800 Subject: [PATCH 029/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79d44f92..0067f8db 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ ``` ### Gradle -`compile 'com.ejlchina:okhttps:1.0.0'` +`implementation 'com.ejlchina:okhttps:1.0.0'` ## 使用说明 From fd60a1c2f6bbbcd7b8d2a228259ad67e1bdafc45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 12:14:23 +0800 Subject: [PATCH 030/924] readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0067f8db..27578d65 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ * TCP连接池�Http2 ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) -### 当�文档版本[1.0.0] +### 当�文档版本[1.0.1] ### API文档:[https://apidoc.gitee.com/ejlchina-zhxu/okhttps](https://apidoc.gitee.com/ejlchina-zhxu/okhttps) ## 目录 @@ -64,12 +64,12 @@ com.ejlchina okhttps - 1.0.0 + 1.0.1 ``` ### Gradle -`implementation 'com.ejlchina:okhttps:1.0.0'` +`implementation 'com.ejlchina:okhttps:1.0.1'` ## 使用说明 From e4f40b286e194f8e016959f9511a5367f07aef6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 12:36:02 +0800 Subject: [PATCH 031/924] readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 27578d65..b2d77eea 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ * BaseURL�URL��符�JSON自动�装与解� * �步拦截器�异步预处�器�回调执行器 * 文件上传下载(过程控制�进度监�) + * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) From 99200f3ccc04c49c54fffe8e476b1caf616e17e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 12:56:32 +0800 Subject: [PATCH 032/924] readme --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b2d77eea..f818d06e 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE #### 3.1 回调函数 -  �有异步请求��以设置回调函数: +  OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅: ```java http.async("/users/{id}") // http://api.demo.com/users/1 @@ -157,6 +157,9 @@ http.async("/users/{id}") // http://api.demo.com/users/1 .get(); ``` +>* �有异步请求��以设置这三�(�应|异常|完�)回调函数 +>* �步请求直接返回结果,无需使用回调 + #### 3.2 HttpResult   `HttpResult`是HTTP请求执行完�的结果,它是�步请求方法( `get`�`post`�`put`�`delete`)的返回值,也是异步请求�应回调(`OnResponse`)的�数,它定义了如下方法: From 0cec85b7a41021ade6e24393b1214e1e2dce7149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 12:57:31 +0800 Subject: [PATCH 033/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f818d06e..43b52cb3 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,7 @@ http.async("/users/{id}") // http://api.demo.com/users/1 .get(); ``` ->* �有异步请求��以设置这三�(�应|异常|完�)回调函数 +>* �有异步请求��以设置这三�(�应|异常|完�)回调 >* �步请求直接返回结果,无需使用回调 #### 3.2 HttpResult From b75664ed261a83c6292141b97952e3c204fa041a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 12:59:24 +0800 Subject: [PATCH 034/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 43b52cb3..9362b94d 100644 --- a/README.md +++ b/README.md @@ -221,7 +221,7 @@ System.out.println(body.toList(Order.class));   示例,获�下载文件的大�: ```java -long size = http.sync("http://api.demo.com/download/test.zip") +long size = http.sync("/download/test.zip") .get().getBody() .close() // �是想获得文件大�,�消费报文体,所以直接关闭 .getContentLength(); // 获得待下载文件的大� From 05620fd8f94062039d289b0f4bcbee667cef466b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 13:11:21 +0800 Subject: [PATCH 035/924] readme --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9362b94d..35c76a5e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ * �步拦截器�异步预处�器�回调执行器 * 文件上传下载(过程控制�进度监�) * �方法回调,充分利用 Lambda 表达� + * 全局监��回调阻断 * TCP连接池�Http2 ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) @@ -42,7 +43,7 @@ - [6.3 �置 OkHttpClient](#63-�置-okhttpclient) - [6.4 并行预处�器](#64-并行预处�器) - [6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案) - - [6.6 全局回调处�](#66-全局回调处�) + - [6.6 全局回调监�](#66-全局回调监�) - [6.7 全局下载监�](#67-全局下载监�) + [7 使用 HttpUtils 类](#7-使用-httputils-类) + [8 文件下载](#8-文件下载) @@ -402,7 +403,7 @@ HTTP http = HTTP.builder() > * 拦截器�能处��步�作,预处�器支�处�异步�作 > * 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) -> * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调机制(详�6.6章节) +> * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调监�(详�6.6章节) #### 6.5 串行预处�器(TOKEN问题最佳解决方案) @@ -427,7 +428,7 @@ HTTP http = HTTP.builder() ```   串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程� -#### 6.6 全局回调处� +#### 6.6 全局回调监� ```java HTTP http = HTTP.builder() @@ -449,10 +450,10 @@ HTTP http = HTTP.builder() .build(); ``` -  全局回调与拦截器的异�: -> * 拦截器�以添加多个,全局回调分三�,��最多添加一个 -> * 拦截器处的�时机在请求�和�应�,全局回调�在�应�,并且晚于拦截器 -> * 全局回调�以阻断(return false)�个请求的具体回调,而拦截器�能 +  全局回调监�与拦截器的异�: +> * 拦截器�以添加多个,全局回调监�分三�,��最多添加一个 +> * 拦截器处的�时机在请求�和�应�,全局回调监��在�应�,并且晚于拦截器 +> * 全局回调监��以阻断(return false)�个请求的具体回调,而拦截器�能 #### 6.7 全局下载监� From adf76e83aa4b6ae1feb726a75af81c75632c3597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 13:20:08 +0800 Subject: [PATCH 036/924] readme --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 35c76a5e..e2b9d6f7 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,9 @@ * 链�调用,一点到底 * BaseURL�URL��符�JSON自动�装与解� - * �步拦截器�异步预处�器�回调执行器 + * �步拦截器�异步预处�器�回调执行器�全局监��回调阻断 * 文件上传下载(过程控制�进度监�) * �方法回调,充分利用 Lambda 表达� - * 全局监��回调阻断 * TCP连接池�Http2 ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) From f6db912aad78d9576aa633f9f5578eeca5632721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 13:50:42 +0800 Subject: [PATCH 037/924] =?UTF-8?q?TaskExecutor=20=E6=96=B0=E5=A2=9E=20shu?= =?UTF-8?q?tdown=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ejlchina/okhttps/internal/TaskExecutor.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index fbb164b1..3abcc054 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import com.ejlchina.okhttps.DownListener; import com.ejlchina.okhttps.Download; @@ -95,4 +96,13 @@ public void executeOnComplete(HttpTask task, OnCallback onComplete, St } } + public void shutdown() { + if (ioExecutor != null && ioExecutor instanceof ExecutorService) { + ((ExecutorService) ioExecutor).shutdown(); + } + if (mainExecutor != null && mainExecutor instanceof ExecutorService) { + ((ExecutorService) mainExecutor).shutdown(); + } + } + } From e8f8c21f95f4dce4dd70e2fd472c266edff1271d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 13:54:21 +0800 Subject: [PATCH 038/924] =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 3abcc054..66ed7a85 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -96,6 +96,10 @@ public void executeOnComplete(HttpTask task, OnCallback onComplete, St } } + /** + * 关闭线程池 + * @since OkHttps V1.0.2 + */ public void shutdown() { if (ioExecutor != null && ioExecutor instanceof ExecutorService) { ((ExecutorService) ioExecutor).shutdown(); From f027d65d0b97b7b01a635e0ca76b5cb754b677d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 16:53:37 +0800 Subject: [PATCH 039/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2b9d6f7..3563ed0a 100644 --- a/README.md +++ b/README.md @@ -502,7 +502,7 @@ List users = HttpUtils.sync("/users") http.sync("/download/test.zip") .get() // 使用 GET 方法(其它方法也�以,看�务器支�) .getBody() // 得到报文体 - .toFile("D:/download/test.zip") // 指定下载的目录,文件�将根�下载信�自动生� + .toFile("D:/download/test.zip") // 下载到指定的路径 .start(); // �动下载 ```   或使用异步连接方�: From 9ba2d77b3710d6bcac171dec5db06f16a9212604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 16:55:37 +0800 Subject: [PATCH 040/924] readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3563ed0a..869edb2c 100644 --- a/README.md +++ b/README.md @@ -504,6 +504,10 @@ http.sync("/download/test.zip") .getBody() // 得到报文体 .toFile("D:/download/test.zip") // 下载到指定的路径 .start(); // �动下载 + +http.sync("/download/test.zip").get().getBody() + .toFolder("D:/download/") // 下载到指定的目录,文件�将根�下载信�自动生� + .start(); ```   或使用异步连接方�: From 3e08e59de5457d1930d9b014386c13282f766ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 16:56:58 +0800 Subject: [PATCH 041/924] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 869edb2c..354a69d2 100644 --- a/README.md +++ b/README.md @@ -506,7 +506,7 @@ http.sync("/download/test.zip") .start(); // �动下载 http.sync("/download/test.zip").get().getBody() - .toFolder("D:/download/") // 下载到指定的目录,文件�将根�下载信�自动生� + .toFolder("D:/download") // 下载到指定的目录,文件�将根�下载信�自动生� .start(); ```   或使用异步连接方�: @@ -514,7 +514,7 @@ http.sync("/download/test.zip").get().getBody() ```java http.async("/download/test.zip") .setOnResponse((HttpResult result) -> { - result.getBody().toFile("D:/download/test.zip").start(); + result.getBody().toFolder("D:/download").start(); }) .get(); ``` From e3e3e54b30c8508ddff40f00f2d717f0344200f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 8 Apr 2020 16:57:37 +0800 Subject: [PATCH 042/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 354a69d2..f844d1dc 100644 --- a/README.md +++ b/README.md @@ -506,7 +506,7 @@ http.sync("/download/test.zip") .start(); // �动下载 http.sync("/download/test.zip").get().getBody() - .toFolder("D:/download") // 下载到指定的目录,文件�将根�下载信�自动生� + .toFolder("D:/download") // 下载到指定的目录,文件�将根�下载信�自动生� .start(); ```   或使用异步连接方�: From 8794048f15cdbee2f7900b342096b2e524d64b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Wed, 8 Apr 2020 23:36:12 +0800 Subject: [PATCH 043/924] SimpleTests --- .../java/com/ejlchina/test/SimpleTests.java | 73 +++++++++++++++++++ src/test/java/com/ejlchina/test/User.java | 27 ------- 2 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 src/test/java/com/ejlchina/test/SimpleTests.java delete mode 100644 src/test/java/com/ejlchina/test/User.java diff --git a/src/test/java/com/ejlchina/test/SimpleTests.java b/src/test/java/com/ejlchina/test/SimpleTests.java new file mode 100644 index 00000000..f1e92e7e --- /dev/null +++ b/src/test/java/com/ejlchina/test/SimpleTests.java @@ -0,0 +1,73 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpResult; +import org.junit.Test; + +import java.util.List; + +public class SimpleTests { + + + HTTP http = HTTP.builder() + .baseUrl("http://localhost:8080") + .build(); + + /** + * �步请求示例 + */ + @Test + public void testSync() { + List users = http.sync("/users") // http://localhost:8080/users + .get() // GET请求 + .getBody() // 获��应报文体 + .toList(User.class); // 得到目标数� + System.out.println("users = " + users); + } + + /** + * 异步请求示例 + */ + @Test + public void testAsync() { + http.async("/users/1") // http://api.demo.com/users/1 + .setOnResponse((HttpResult result) -> { + // 得到目标数� + User user = result.getBody().toBean(User.class); + System.out.println("user = " + user); + }) + .get(); + sleep(5000); + } + + + void sleep(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} + + +class User { + + private int id; + private String name; + + public void setId(int id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + "]"; + } + +} \ No newline at end of file diff --git a/src/test/java/com/ejlchina/test/User.java b/src/test/java/com/ejlchina/test/User.java deleted file mode 100644 index bdf75c9d..00000000 --- a/src/test/java/com/ejlchina/test/User.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.ejlchina.test; - -public class User { - - int id; - String name; - - public void setId(int id) { - this.id = id; - } - public void setName(String name) { - this.name = name; - } - - public int getId() { - return id; - } - public String getName() { - return name; - } - - @Override - public String toString() { - return "User [id=" + id + ", name=" + name + "]"; - } - -} From d912448b9151afbe9690f6dc6abc87bf22850c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Wed, 8 Apr 2020 23:57:35 +0800 Subject: [PATCH 044/924] SimpleTests --- .../java/com/ejlchina/test/SimpleTests.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/test/java/com/ejlchina/test/SimpleTests.java b/src/test/java/com/ejlchina/test/SimpleTests.java index f1e92e7e..78f41c29 100644 --- a/src/test/java/com/ejlchina/test/SimpleTests.java +++ b/src/test/java/com/ejlchina/test/SimpleTests.java @@ -2,6 +2,7 @@ import com.ejlchina.okhttps.HTTP; import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpResult.Body; import org.junit.Test; import java.util.List; @@ -15,6 +16,7 @@ public class SimpleTests { /** * �步请求示例 + * �步请求直接得到结果,无需设置回调 */ @Test public void testSync() { @@ -27,6 +29,7 @@ public void testSync() { /** * 异步请求示例 + * 异步请求在OnResponse里接收请求结果 */ @Test public void testAsync() { @@ -41,6 +44,40 @@ public void testAsync() { } + /** + * �用 cache 示例 + */ + @Test + public void testCache() { + Body body = http.sync("/users").get().getBody() + .cache(); // �用 cache + // 使用 cache �,�以多次使用 toXXX() 方法 + System.out.println(body.toString()); + System.out.println(body.toJsonArray()); + System.out.println(body.toList(User.class)); + } + + + /** + * 获�文件大�示例 + */ + @Test + public void testContentLength() { + long t = System.currentTimeMillis(); + + long size = http.sync("https://download.cocos.com/CocosDashboard/v1.0.1/CocosDashboard-v1.0.1-win32-031816.exe") + .get().getBody() + .close() // �是想获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); // 获得待下载文件的大� + + t = System.currentTimeMillis() - t; + + // 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络��) + System.out.println("耗时:" + t + " 毫秒"); + System.out.println("size = " + (size / 1024) + " KB"); + } + + void sleep(int millis) { try { Thread.sleep(millis); From 062853b773871763317a195f1bcedaa368ae5cf7 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Thu, 9 Apr 2020 09:59:55 +0800 Subject: [PATCH 045/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f844d1dc..82ebb80f 100644 --- a/README.md +++ b/README.md @@ -728,7 +728,7 @@ HTTP http = HTTP.builder() }) .build(); ``` -  上述代�便实现了让 **所有** 的 **回调函数** 都在 **主线程** 执行的目的,如: +  上述代�便实现了让 **所有** 的 **回调函数** 都在 **主线程(UI线程)** 执行的目的,如: ```java http.async("/users") From a8ea604e618aef7008ceee2a90ed7a76581c49ea Mon Sep 17 00:00:00 2001 From: ejlchina Date: Thu, 9 Apr 2020 10:00:52 +0800 Subject: [PATCH 046/924] update README.md. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 82ebb80f..8ad48ef1 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ + [9 文件上传](#9-文件上传) - [9.1 上传进度监�](#91-上传进度监�) - [9.2 上传过程控制](#92-上传过程控制) - + [10 执行线程自由切�(for Android)](#10-执行线程自由切�for-android) + + [10 回调线程自由切�(for Android)](#10-回调线程自由切�for-android) + [�考文档](#�考文档) + [�系方�](#�系方�) @@ -712,7 +712,7 @@ call.cancel(); // �消上传 ```   上传就没有暂�和继续这个功能啦,应该没人有这个需求�? -### 10 执行线程自由切�(for Android) +### 10 回调线程自由切�(for Android)   在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 From 884a4d252ce90ef8704373380eacab2f5241569b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 10:12:40 +0800 Subject: [PATCH 047/924] readme --- README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8ad48ef1..8459860a 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,10 @@ + [9 文件上传](#9-文件上传) - [9.1 上传进度监�](#91-上传进度监�) - [9.2 上传过程控制](#92-上传过程控制) - + [10 回调线程自由切�(for Android)](#10-回调线程自由切�for-android) + + [10 异常处�](#10-异常处�) + - [10.1 �步方�](#101-�步方�) + - [10.2 异步方�](#102-异步方�) + + [11 回调线程自由切�(for Android)](#11-回调线程自由切�for-android) + [�考文档](#�考文档) + [�系方�](#�系方�) @@ -192,7 +195,7 @@ http.async("/users/{id}") // http://api.demo.com/users/1 * `getContentLength()` 返回报文体的字节长度 * `cache()` 缓存报文体,开�缓存����使用`toXXX()`类方法 * `close()` 关闭报文体,未对报文体�任何消费时使用,比如�读�报文头 -* `getError()` 执行中�生的异常,自动�获执行请求是�生的 网络超时�网络错误 和 其它请求异常 +* `getError()` 执行中�生的异常,自动�获执行请求时�生的 网络超时�网络错误 和 其它IO异常 * `close()` 关闭报文,未对报文体�任何消费时使用,比如�读�长度   示例,请求结果自动转Bean和List: @@ -712,7 +715,17 @@ call.cancel(); // �消上传 ```   上传就没有暂�和继续这个功能啦,应该没人有这个需求�? -### 10 回调线程自由切�(for Android) +### 10 异常处� + +#### 10.1 �步方� + +文档完善中... + +#### 10.2 异步方� + +文档完善中... + +### 11 回调线程自由切�(for Android)   在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 From b74e2fe706b4d5e63c38e0243e7f99910c5c05bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 10:16:36 +0800 Subject: [PATCH 048/924] readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8459860a..a2214606 100644 --- a/README.md +++ b/README.md @@ -717,6 +717,8 @@ call.cancel(); // �消上传 ### 10 异常处� +  相比其它的 HTTP 开�包,OkHttps �供了更多的异常处�方�,以满足��的异常处�需求。 + #### 10.1 �步方� 文档完善中... From 73ae5e3cc282b01cc67f1541e0ff0b1be36b12ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 10:17:46 +0800 Subject: [PATCH 049/924] readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a2214606..ff0d0045 100644 --- a/README.md +++ b/README.md @@ -717,13 +717,13 @@ call.cancel(); // �消上传 ### 10 异常处� -  相比其它的 HTTP 开�包,OkHttps �供了更多的异常处�方�,以满足��的异常处�需求。 +  相比其它的 HTTP 开�包,OkHttps �供了更多的异常处�方法,以满足��的异常处�需求。 -#### 10.1 �步方� +#### 10.1 �步请求的异常 文档完善中... -#### 10.2 异步方� +#### 10.2 异步请求的异常 文档完善中... From 90ed6c0e352ed02824393daee79260c4e705e545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 11:22:37 +0800 Subject: [PATCH 050/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=20HttpResult.getErro?= =?UTF-8?q?r()=20=E6=96=B9=E6=B3=95=E7=9A=84=E8=BF=94=E5=9B=9E=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=20Exception=20=E5=85=B7=E4=BD=93=E5=88=B0=20IOExcepti?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpResult.java | 3 ++- .../com/ejlchina/okhttps/internal/RealHttpResult.java | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpResult.java b/src/main/java/com/ejlchina/okhttps/HttpResult.java index 63424db2..88984b72 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpResult.java +++ b/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -1,6 +1,7 @@ package com.ejlchina.okhttps; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.util.List; @@ -264,7 +265,7 @@ public interface Body { /** * @return 执行中�生的异常 */ - Exception getError(); + IOException getError(); /** * 关闭报文 diff --git a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java index 4de88afd..f6eab345 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java +++ b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java @@ -1,5 +1,6 @@ package com.ejlchina.okhttps.internal; +import java.io.IOException; import java.util.Collections; import java.util.List; @@ -14,7 +15,7 @@ public class RealHttpResult implements HttpResult { private State state; private Response response; - private Exception error; + private IOException error; private TaskExecutor taskExecutor; private HttpTask httpTask; private Body body; @@ -34,13 +35,13 @@ public RealHttpResult(HttpTask httpTask, TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } - public RealHttpResult(HttpTask httpTask, State state, Exception error) { + public RealHttpResult(HttpTask httpTask, State state, IOException error) { this.httpTask = httpTask; exception(state, error); } - public void exception(State state, Exception error) { + public void exception(State state, IOException error) { this.state = state; this.error = error; } @@ -104,7 +105,7 @@ public Body getBody() { } @Override - public Exception getError() { + public IOException getError() { return error; } From e898b069d25c608ca6ccd3077e3c292df9b283b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 11:23:41 +0800 Subject: [PATCH 051/924] =?UTF-8?q?readme:=20=E5=90=8C=E6=AD=A5=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E7=9A=84=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ff0d0045..1ff3d618 100644 --- a/README.md +++ b/README.md @@ -721,7 +721,50 @@ call.cancel(); // �消上传 #### 10.1 �步请求的异常 -文档完善中... +  默认情况下,当请求执行异常时,会直接�外抛出,我们�以用 `try catch` ��获,例如: + +```java +try { + HttpResult result = http.sync("/users/1").get(); +} catch (HttpException e) { + Throwable cause = e.getCause(); // 得到异常原因 + if (cause instanceof ConnectException) { + // 当没网络时,会抛出连接异常 + } + if (cause instanceof SocketTimeoutException) { + // 当接�长时间未�应,会抛出超时异常 + } + if (cause instanceof UnknownHostException) { + // 当把域�或IP写错,会抛出 UnknownHost 异常 + } + // ... +} +``` +  这�传统的异常处�方�,当然�以解决问题,但是 OkHttps �供了更优雅的方案: + +``` +HttpResult result = http.sync("/users/1") + .nothrow() // 告诉 OkHttps �生异常时��直接�外抛出 + .get(); +State state = result.getState(); // 得到请求执行状� +if (state == State.RESPONSED) { + // 请求已正常�应 +} +if (state == State.CANCELED) { + // 请求已被�消 +} +if (state == State.NETWORK_ERROR) { + // 网络错误,说明用户没网了 +} +if (state == State.TIMEOUT) { + // 请求超时 +} +if (state == State.EXCEPTION) { + // 其它请求异常 +} +// 还�以获得具体的异常信� +Exception err = result.getError(); +``` #### 10.2 异步请求的异常 From c16276c1373c72794e2bd29042d24d6ba5c63c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 11:26:37 +0800 Subject: [PATCH 052/924] =?UTF-8?q?readme:=20=E5=90=8C=E6=AD=A5=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E7=9A=84=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1ff3d618..18be0c65 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ - [9.1 上传进度监�](#91-上传进度监�) - [9.2 上传过程控制](#92-上传过程控制) + [10 异常处�](#10-异常处�) - - [10.1 �步方�](#101-�步方�) - - [10.2 异步方�](#102-异步方�) + - [10.1 �步请求的异常](#101-�步请求的异常) + - [10.2 异步请求的异常](#102-异步请求的异常) + [11 回调线程自由切�(for Android)](#11-回调线程自由切�for-android) + [�考文档](#�考文档) + [�系方�](#�系方�) @@ -742,7 +742,7 @@ try { ```   这�传统的异常处�方�,当然�以解决问题,但是 OkHttps �供了更优雅的方案: -``` +```java HttpResult result = http.sync("/users/1") .nothrow() // 告诉 OkHttps �生异常时��直接�外抛出 .get(); From 999b12f137007aa985738fef8a45b716fff50d4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 11:35:37 +0800 Subject: [PATCH 053/924] =?UTF-8?q?readme:=20=E5=90=8C=E6=AD=A5=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E7=9A=84=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 +++++++++---------- .../java/com/ejlchina/test/SimpleTests.java | 1 - 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 18be0c65..17d7a247 100644 --- a/README.md +++ b/README.md @@ -746,24 +746,21 @@ try { HttpResult result = http.sync("/users/1") .nothrow() // 告诉 OkHttps �生异常时��直接�外抛出 .get(); -State state = result.getState(); // 得到请求执行状� -if (state == State.RESPONSED) { - // 请求已正常�应 -} -if (state == State.CANCELED) { - // 请求已被�消 -} -if (state == State.NETWORK_ERROR) { - // 网络错误,说明用户没网了 -} -if (state == State.TIMEOUT) { - // 请求超时 -} -if (state == State.EXCEPTION) { - // 其它请求异常 +// 判断执行状� +switch (result.getState()) { + case RESPONSED: // 请求已正常�应 + break; + case CANCELED: // 请求已被�消 + break; + case NETWORK_ERROR: // 网络错误,说明用户没网了 + break; + case TIMEOUT: // 请求超时 + break; + case EXCEPTION: // 其它异常 + break; } // 还�以获得具体的异常信� -Exception err = result.getError(); +Exception error = result.getError(); ``` #### 10.2 异步请求的异常 diff --git a/src/test/java/com/ejlchina/test/SimpleTests.java b/src/test/java/com/ejlchina/test/SimpleTests.java index 78f41c29..da3b3472 100644 --- a/src/test/java/com/ejlchina/test/SimpleTests.java +++ b/src/test/java/com/ejlchina/test/SimpleTests.java @@ -77,7 +77,6 @@ public void testContentLength() { System.out.println("size = " + (size / 1024) + " KB"); } - void sleep(int millis) { try { Thread.sleep(millis); From b14c3cbdbd628521e97e760ffb44b634de2ea25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 11:38:53 +0800 Subject: [PATCH 054/924] readme --- README.md | 5 +- .../com/ejlchina/test/ExceptionTests.java | 72 +++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/ejlchina/test/ExceptionTests.java diff --git a/README.md b/README.md index 17d7a247..7cdb00aa 100644 --- a/README.md +++ b/README.md @@ -743,9 +743,8 @@ try {   这�传统的异常处�方�,当然�以解决问题,但是 OkHttps �供了更优雅的方案: ```java -HttpResult result = http.sync("/users/1") - .nothrow() // 告诉 OkHttps �生异常时��直接�外抛出 - .get(); +// 使用 nothrow 方法告诉 OkHttps �生异常时��直接�外抛出 +HttpResult result = http.sync("/users/1").nothrow().get(); // 判断执行状� switch (result.getState()) { case RESPONSED: // 请求已正常�应 diff --git a/src/test/java/com/ejlchina/test/ExceptionTests.java b/src/test/java/com/ejlchina/test/ExceptionTests.java new file mode 100644 index 00000000..aeb31d5c --- /dev/null +++ b/src/test/java/com/ejlchina/test/ExceptionTests.java @@ -0,0 +1,72 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.internal.HttpException; +import org.junit.Test; + +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; + +public class ExceptionTests { + + HTTP http = HTTP.builder() + .baseUrl("http://localhost:8080") + .build(); + + @Test + public void testSync0() { + try { + HttpResult result = http.sync("/users/1").get(); + System.out.println("请求结果:" + result); + } catch (HttpException e) { + Throwable cause = e.getCause(); // 得到异常原因 + if (cause instanceof ConnectException) { + // 当没网络时,会抛出连接异常 + } + if (cause instanceof SocketTimeoutException) { + // 当接�长时间未�应,会抛出超时异常 + } + if (cause instanceof UnknownHostException) { + // 当把域�或IP写错,会抛出 UnknownHost 异常 + } + // ... + } + } + + @Test + public void testSync1() { + HttpResult result = http.sync("/users/1") + .nothrow() // 告诉 OkHttps �生异常时��直接�外抛出 + .get(); + // 判断执行状� + switch (result.getState()) { + case RESPONSED: // 请求已正常�应 + + break; + case CANCELED: // 请求已被�消 + + break; + case NETWORK_ERROR: // 网络错误,说明用户没网了 + + break; + case TIMEOUT: // 请求超时 + + break; + case EXCEPTION: // 其它异常 + + break; + } + // 还�以获得具体的异常信� + Exception error = result.getError(); + + + } + + @Test + public void testASync() { + + } + +} From 03fea6905fa627d2edebb7a102f2f3b7ca49bb28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 12:37:35 +0800 Subject: [PATCH 055/924] =?UTF-8?q?readme:=20=E5=BC=82=E6=AD=A5=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E7=9A=84=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 50 ++++++++++++++++++- .../com/ejlchina/test/ExceptionTests.java | 32 +++++++++++- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7cdb00aa..6cccea99 100644 --- a/README.md +++ b/README.md @@ -717,7 +717,7 @@ call.cancel(); // �消上传 ### 10 异常处� -  相比其它的 HTTP 开�包,OkHttps �供了更多的异常处�方法,以满足��的异常处�需求。 +  相比其它的 HTTP 开�包,OkHttps �外�供了一个特别的异常处�方�(`nothrow()`),以满足��的异常处�需求。 #### 10.1 �步请求的异常 @@ -764,7 +764,53 @@ Exception error = result.getError(); #### 10.2 异步请求的异常 -文档完善中... +  异步请求的使用最多的异常处�方�是设置一个异常回调: + +```java +http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .setOnException((IOException e) -> { + // 这里处�请求异常 + }) + .get(); +``` +  如果�设置`OnException`回调,�生异常时会在 **IO线程池** 中�上抛出,外层无法�获: + +```java +try { + http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .get(); +} catch (HttpException e) { + // 这�方�是�获�到异常的���� +} +``` +  但�使�设置`OnException`回调,�生异常时,�然会走`OnComplete`回调: + +```java +http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .setOnComplete((State state) -> { + // �生异常,会先执行这里,但执行完��然会在IO线程中�上抛出 + }) + .get(); +``` +  如果就是想 **�处�异常,也��上抛出**,�以�到�?�以�使用`nothrow()`方法: + +```java +http.async("/users/1") + .nothrow() // 告诉 OkHttps �生异常时��外抛出 + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .get(); +``` ### 11 回调线程自由切�(for Android) diff --git a/src/test/java/com/ejlchina/test/ExceptionTests.java b/src/test/java/com/ejlchina/test/ExceptionTests.java index aeb31d5c..aafeedf1 100644 --- a/src/test/java/com/ejlchina/test/ExceptionTests.java +++ b/src/test/java/com/ejlchina/test/ExceptionTests.java @@ -3,16 +3,24 @@ import com.ejlchina.okhttps.HTTP; import com.ejlchina.okhttps.HttpResult; import com.ejlchina.okhttps.internal.HttpException; +import okhttp3.OkHttpClient; import org.junit.Test; +import java.io.IOException; import java.net.ConnectException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; +import java.util.concurrent.TimeUnit; public class ExceptionTests { HTTP http = HTTP.builder() - .baseUrl("http://localhost:8080") + .config((OkHttpClient.Builder builder) -> { + builder.connectTimeout(2, TimeUnit.SECONDS); + builder.writeTimeout(2, TimeUnit.SECONDS); + builder.readTimeout(2, TimeUnit.SECONDS); + }) + .baseUrl("http://localhost:8081") .build(); @Test @@ -67,6 +75,28 @@ public void testSync1() { @Test public void testASync() { + http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + System.out.println(result); + }) + .setOnException((IOException e) -> { + // 这里处�请求异常 + System.out.println(e); + }) + .get(); + + sleep(10000); + } + + + + void sleep(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } From 889968a04470c19d3dba64c272ab70a0be7db172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 12:44:13 +0800 Subject: [PATCH 056/924] =?UTF-8?q?=E3=80=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6cccea99..602688e2 100644 --- a/README.md +++ b/README.md @@ -717,7 +717,7 @@ call.cancel(); // �消上传 ### 10 异常处� -  相比其它的 HTTP 开�包,OkHttps �外�供了一个特别的异常处�方�(`nothrow()`),以满足��的异常处�需求。 +  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还是�外�供了一个特别的处�方�(`nothrow()`),以满足��的异常处�需求。 #### 10.1 �步请求的异常 @@ -789,7 +789,7 @@ try { // 这�方�是�获�到异常的���� } ``` -  但�使�设置`OnException`回调,�生异常时,�然会走`OnComplete`回调: +  �使�设置`OnException`回调,�生异常时,�然会走`OnComplete`回调: ```java http.async("/users/1") @@ -797,7 +797,8 @@ http.async("/users/1") // 当�生异常时就�会走这里 }) .setOnComplete((State state) -> { - // �生异常,会先执行这里,但执行完��然会在IO线程中�上抛出 + // �生异常,会先执行这里,�以更加 state 判断�生了什么 + // 但执行完��然会在IO线程中�上抛出 }) .get(); ``` From 5cad02590cc06cf3cb3f8f41695217e2c5dad4c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 12:46:36 +0800 Subject: [PATCH 057/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 602688e2..ce385097 100644 --- a/README.md +++ b/README.md @@ -721,7 +721,7 @@ call.cancel(); // �消上传 #### 10.1 �步请求的异常 -  默认情况下,当请求执行异常时,会直接�外抛出,我们�以用 `try catch` ��获,例如: +  默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 `try catch` ��获,例如: ```java try { From ec54f5e680ccbebcd5e29376abbe2da6a215c27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:15:21 +0800 Subject: [PATCH 058/924] readme --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ce385097..9519bb9f 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ - [10.1 �步请求的异常](#101-�步请求的异常) - [10.2 异步请求的异常](#102-异步请求的异常) + [11 回调线程自由切�(for Android)](#11-回调线程自由切�for-android) + + [12 实现生命周期绑定(for Android)](#12-实现生命周期绑定for-android) + [�考文档](#�考文档) + [�系方�](#�系方�) @@ -357,7 +358,7 @@ HTTP http = HTTP.builder() }) .build(); ``` -  该�置影�所有回调。 +  该�置**影�所有回调**。 #### 6.3 �置 OkHttpClient @@ -888,9 +889,12 @@ http.sync("/download/test.zip") }) .start(); ``` +### 12 实现生命周期绑定(for Android) + +文档完善中,敬请期待... -## �考文档 +## �考文档 ## �系方� From f5a8569a3b66ceaaf475d37a596645961deb9154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:20:53 +0800 Subject: [PATCH 059/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9519bb9f..fd69be14 100644 --- a/README.md +++ b/README.md @@ -358,7 +358,7 @@ HTTP http = HTTP.builder() }) .build(); ``` -  该�置**影�所有回调**。 +  该�置默认 **影�所有回调**。 #### 6.3 �置 OkHttpClient From 31eae6de662479b19ca12614bd896cb8eee1ef88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:23:32 +0800 Subject: [PATCH 060/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fd69be14..d18d156f 100644 --- a/README.md +++ b/README.md @@ -349,7 +349,7 @@ http.sync("https://www.baidu.com").get() #### 6.2 回调执行器 -  如何想改�执行回调函数的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建`HTTP`时�置如下: +  OkHttps 默认所有回调都在 **IO线程** 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建`HTTP`时�置如下: ```java HTTP http = HTTP.builder() From 462bb08338ec57446fc96af40b2fa36290bf2a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:32:51 +0800 Subject: [PATCH 061/924] readme --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d18d156f..78a25dbc 100644 --- a/README.md +++ b/README.md @@ -260,7 +260,7 @@ System.out.println(call.isCanceled()); // true ### 4 构建HTTP任务 -  `HTTP`对象的`sync`与`async`方法返回一个`HttpTask`对象,该对象�供了�链�调用的`addXXX`与`setXXX`系列方法用于构建任务本身。 +  `HTTP`对象的`sync`与`async`方法返回一个`HttpTask`对象,该对象�供了�链�调用的`addXXX`与`setXXX`等系列方法用于构建任务本身。 * `addHeader(String name, String value)` 添加请求头 * `addHeader(Map headers)` 添加请求头 @@ -384,7 +384,7 @@ HTTP http = HTTP.builder() #### 6.4 并行预处�器 -  预处�器(`Preprocessor`)�以让我们在请求�出之�对请求本身�一些改�,但与`OkHttp`的拦截器(`Interceptor`)��:预处�器�以让我们**异步**处�这些问题。 +  预处�器(`Preprocessor`)�以让我们在请求�出之�对请求本身�一些改�,但与`OkHttp`的拦截器(`Interceptor`)��:预处�器�以让我们 **异步** 处�这些问题。   例如,当我们想为请求任务自动添加`Token`头信�,而`Token`�能通过异步方法`requestToken`获�时,这时使用`Interceptor`就很难处�了,但�以使用预处�器轻�解决: @@ -592,7 +592,7 @@ http.async("/download/test.zip") #### 8.3 实现断点续传 -  OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到**断点**,便将��的问题�得简�: +  OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到 **断点**,便将��的问题�得简�: ```java http.sync("/download/test.zip") @@ -718,7 +718,7 @@ call.cancel(); // �消上传 ### 10 异常处� -  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还是�外�供了一个特别的处�方�(`nothrow()`),以满足��的异常处�需求。 +  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还是�外�供了一个特别的处�方法(`nothrow()`),以满足��的异常处�需求。 #### 10.1 �步请求的异常 @@ -777,7 +777,7 @@ http.async("/users/1") }) .get(); ``` -  如果�设置`OnException`回调,�生异常时会在 **IO线程池** 中�上抛出,外层无法�获: +  如果�设置`OnException`回调,�生异常时会在 **IO 线程** 中�上抛出,外层无法�获: ```java try { @@ -787,7 +787,7 @@ try { }) .get(); } catch (HttpException e) { - // 这�方�是�获�到异常的���� + // 这�方�是�获�到异常的������ } ```   �使�设置`OnException`回调,�生异常时,�然会走`OnComplete`回调: @@ -798,12 +798,12 @@ http.async("/users/1") // 当�生异常时就�会走这里 }) .setOnComplete((State state) -> { - // �生异常,会先执行这里,�以更加 state 判断�生了什么 + // �生异常,会先执行这里,�以根� state 判断�生了什么 // 但执行完��然会在IO线程中�上抛出 }) .get(); ``` -  如果就是想 **�处�异常,也��上抛出**,�以�到�?�以�使用`nothrow()`方法: +  如果就是想 **�处�异常,也��上抛出**,�以�到�?�以�还是使用`nothrow()`方法: ```java http.async("/users/1") From f6bee7c6017d80df398357ad8bdef0283207a90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:34:29 +0800 Subject: [PATCH 062/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 78a25dbc..0d31e747 100644 --- a/README.md +++ b/README.md @@ -718,7 +718,7 @@ call.cancel(); // �消上传 ### 10 异常处� -  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还是�外�供了一个特别的处�方法(`nothrow()`),以满足��的异常处�需求。 +  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还是�供了一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 #### 10.1 �步请求的异常 From b34d4fdd43b315511ad26404294c72a92e5061c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:34:52 +0800 Subject: [PATCH 063/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d31e747..83676cca 100644 --- a/README.md +++ b/README.md @@ -718,7 +718,7 @@ call.cancel(); // �消上传 ### 10 异常处� -  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还是�供了一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 +  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还�供了一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 #### 10.1 �步请求的异常 From 29f7472d2c351f7be021943c0433bf537ac7c2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:36:11 +0800 Subject: [PATCH 064/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 83676cca..4453bbb4 100644 --- a/README.md +++ b/README.md @@ -741,7 +741,7 @@ try { // ... } ``` -  这�传统的异常处�方�,当然�以解决问题,但是 OkHttps �供了更优雅的方案: +  这�传统的异常处�方�,当然�以解决问题,但是 OkHttps 有更佳的方案: ```java // 使用 nothrow 方法告诉 OkHttps �生异常时��直接�外抛出 From 77d4c3b58dc32c86bf4bea11ae093cd4b7bd73d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:39:02 +0800 Subject: [PATCH 065/924] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4453bbb4..b27a2624 100644 --- a/README.md +++ b/README.md @@ -765,7 +765,7 @@ Exception error = result.getError(); #### 10.2 异步请求的异常 -  异步请求的使用最多的异常处�方�是设置一个异常回调: +  异步请求最常用的异常处�方�就是设置一个异常回调: ```java http.async("/users/1") @@ -803,7 +803,7 @@ http.async("/users/1") }) .get(); ``` -  如果就是想 **�处�异常,也��上抛出**,�以�到�?�以�还是使用`nothrow()`方法: +  如果就是想 **�处�异常,也��上抛出**,�生错误完全无视,�以�到�?�以�还是使用`nothrow()`方法: ```java http.async("/users/1") From c5303b41e6a97145f266bc837106a0f4be3c1f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:48:12 +0800 Subject: [PATCH 066/924] readme --- README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b27a2624..50c17a75 100644 --- a/README.md +++ b/README.md @@ -777,7 +777,18 @@ http.async("/users/1") }) .get(); ``` -  如果�设置`OnException`回调,�生异常时会在 **IO 线程** 中�上抛出,外层无法�获: +  当然,还有一个全局异常监�(`ExceptionListener`): + +```java +HTTP http = HTTP.builder() + .exceptionListener((HttpTask task, IOException error) -> { + // 所有请求�生异常都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 + }) + .build(); +``` +  如果�设置`OnException`回调,也没有`ExceptionListener`,�生异常时会在 **IO 线程** 中�上抛出,外层无法�获: ```java try { @@ -790,7 +801,7 @@ try { // 这�方�是�获�到异常的������ } ``` -  �使�设置`OnException`回调,�生异常时,�然会走`OnComplete`回调: +  �使没有`OnException`回调,�生异常时,�然会走`OnComplete`回调,如果设置了的�: ```java http.async("/users/1") From 89d64a6adc5c9a367997591af86c053e9431d7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 13:53:25 +0800 Subject: [PATCH 067/924] readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 50c17a75..11da4a26 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,7 @@ http.async("/users/{id}") // http://api.demo.com/users/1 }) .setOnComplete((State state) -> { // 完�回调,无论�功失败都会执行 + // 并且在 �应|异常回调 之�执行 }) .get(); ``` From d4b6c4e5e9d577480983cbd1610e63fa0a8cd122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:02:17 +0800 Subject: [PATCH 068/924] .. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 11da4a26..54e390fc 100644 --- a/README.md +++ b/README.md @@ -719,7 +719,7 @@ call.cancel(); // �消上传 ### 10 异常处� -  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还�供了一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 +  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 #### 10.1 �步请求的异常 From c27b3ecb1b875eb4b01d2ee58ddbc20157d75000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:19:03 +0800 Subject: [PATCH 069/924] readme --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 54e390fc..621db2f4 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 +> 1. OkHttps �常轻�,自身代�在 2000 行左� +> 2. OkHttps 有较高的编�质�,sonarqube 结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) + ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.1] ### API文档:[https://apidoc.gitee.com/ejlchina-zhxu/okhttps](https://apidoc.gitee.com/ejlchina-zhxu/okhttps) @@ -58,8 +61,8 @@ - [10.2 异步请求的异常](#102-异步请求的异常) + [11 回调线程自由切�(for Android)](#11-回调线程自由切�for-android) + [12 实现生命周期绑定(for Android)](#12-实现生命周期绑定for-android) -+ [�考文档](#�考文档) + [�系方�](#�系方�) ++ [�与贡献](#�与贡献) ## 安装教程 @@ -906,8 +909,6 @@ http.sync("/download/test.zip") 文档完善中,敬请期待... -## �考文档 - ## �系方� From ea7f08ac05a38cef32bc3b99b1a089a827a2887d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:19:43 +0800 Subject: [PATCH 070/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 621db2f4..a33f49ea 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ * TCP连接池�Http2 > 1. OkHttps �常轻�,自身代�在 2000 行左� -> 2. OkHttps 有较高的编�质�,sonarqube 结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) +> 2. OkHttps 有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.1] From 1229d3a61e61c2a87076a1688e94e471355e7860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:21:49 +0800 Subject: [PATCH 071/924] readme --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index a33f49ea..98ca90d1 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,7 @@ * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 -> 1. OkHttps �常轻�,自身代�在 2000 行左� -> 2. OkHttps 有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) +> OkHttps �常轻�,自身代�在 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.1] From cf3cf94d230936aeef2ffe0e1249244264a1e960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:30:07 +0800 Subject: [PATCH 072/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98ca90d1..bdc34adf 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 -> OkHttps �常轻�,自身代�在 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) +> OkHttps �常轻�,自身代�在 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.1] From 311f24197307a5a877be9dd370d6d5bce5ec1d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:40:05 +0800 Subject: [PATCH 073/924] =?UTF-8?q?=E9=85=8D=E7=BD=AE=20sonar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index 1678b893..95b384e4 100644 --- a/pom.xml +++ b/pom.xml @@ -10,6 +10,9 @@ 1.8 UTF-8 https://oss.sonatype.org/content/repositories/snapshots/ + + src/main/java/com/ejlchina/okhttps/Preprocessor + From 377a0e3ba4739a089f68605b3c1efa33e24d84ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:41:45 +0800 Subject: [PATCH 074/924] =?UTF-8?q?=E9=85=8D=E7=BD=AE=20sonar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 95b384e4..c9d4cbcc 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ UTF-8 https://oss.sonatype.org/content/repositories/snapshots/ - src/main/java/com/ejlchina/okhttps/Preprocessor + src/main/java/com/ejlchina/okhttps/Preprocessor.java From 269f587dd8bbe349f75643afc495602401492b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:47:00 +0800 Subject: [PATCH 075/924] .. --- pom.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pom.xml b/pom.xml index c9d4cbcc..1678b893 100644 --- a/pom.xml +++ b/pom.xml @@ -10,9 +10,6 @@ 1.8 UTF-8 https://oss.sonatype.org/content/repositories/snapshots/ - - src/main/java/com/ejlchina/okhttps/Preprocessor.java - From dbff8b6d9dad9ad9cd9bca048170e019f55adedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:55:53 +0800 Subject: [PATCH 076/924] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81:=20HttpTask.toString(Response=20response)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index ae6067be..7469ef9b 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -568,16 +568,6 @@ private void buildHeaders(Request.Builder builder) { } } - - protected String toString(Response response) throws IOException { - String body = null; - ResponseBody rbody = response.body(); - if (rbody != null) { - body = rbody.string(); - } - return body; - } - protected State toState(IOException e) { if (e instanceof SocketTimeoutException) { return State.TIMEOUT; From 0e0f57b0f7bd977c20036d4e38ef4f930a7da5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 14:57:58 +0800 Subject: [PATCH 077/924] remove unused imports --- .../java/com/ejlchina/okhttps/HttpTask.java | 32 ++++++------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 7469ef9b..392484d5 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -1,5 +1,14 @@ package com.ejlchina.okhttps; +import com.alibaba.fastjson.JSON; +import com.ejlchina.okhttps.HttpResult.State; +import com.ejlchina.okhttps.internal.HttpClient; +import com.ejlchina.okhttps.internal.HttpException; +import com.ejlchina.okhttps.internal.ProcessRequestBody; +import okhttp3.*; +import okhttp3.internal.Util; +import okio.Buffer; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -9,23 +18,6 @@ import java.util.HashMap; import java.util.Map; -import com.alibaba.fastjson.JSON; -import com.ejlchina.okhttps.HttpResult.State; -import com.ejlchina.okhttps.internal.HttpClient; -import com.ejlchina.okhttps.internal.HttpException; -import com.ejlchina.okhttps.internal.ProcessRequestBody; - -import okhttp3.Call; -import okhttp3.FormBody; -import okhttp3.MediaType; -import okhttp3.MultipartBody; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okhttp3.ResponseBody; -import okhttp3.internal.Util; -import okio.Buffer; - /** * Created by 周旭(Troy.Zhou) on 2020/3/11. @@ -555,8 +547,7 @@ private long contentLength(RequestBody reqBody) { throw new HttpException("无法获�请求体长度", e); } } - - + private void buildHeaders(Request.Builder builder) { if (headers != null) { for (String name : headers.keySet()) { @@ -579,7 +570,6 @@ protected State toState(IOException e) { return State.EXCEPTION; } - private RequestBody buildRequestBody() { if (jsonParams != null) { requestJson = JSON.toJSONString(jsonParams); @@ -618,8 +608,6 @@ private RequestBody buildRequestBody() { } } - - private String buildUrlPath() { String url = urlPath; if (url == null || url.trim().isEmpty()) { From e8436350146cf095fdf05b51fd96948155af899b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 15:13:13 +0800 Subject: [PATCH 078/924] =?UTF-8?q?HTTP=20=E6=8E=A5=E5=8F=A3=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=96=B9=E6=B3=95=EF=BC=9AcancelAll()=20=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E6=89=80=E6=9C=89=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HTTP.java | 7 ++++++- .../ejlchina/okhttps/internal/HttpClient.java | 21 ++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HTTP.java b/src/main/java/com/ejlchina/okhttps/HTTP.java index 2f6a54df..3ac7124b 100644 --- a/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -37,7 +37,12 @@ public interface HTTP { * @return 被�消的任务数� */ int cancel(String tag); - + + /** + * �消所有HTTP任务,包括�步和异步 + */ + void cancelAll(); + /** * OkHttp 原生请求 (该请求��过 预处�器) * @param request 请求 diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 15ab2fae..99660120 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -30,18 +30,18 @@ public class HttpClient implements HTTP { + + final OkHttpClient client; - private OkHttpClient client; - - private String baseUrl; + final String baseUrl; // 媒体类型 - private Map mediaTypes; + final Map mediaTypes; // 执行器 - private TaskExecutor executor; + final TaskExecutor executor; // 预处�器 - private Preprocessor[] preprocessors; + final Preprocessor[] preprocessors; - private List tagCalls; + final List tagCalls; private HttpClient(Builder builder) { @@ -85,7 +85,12 @@ public int cancel(String tag) { } return count; } - + + @Override + public void cancelAll() { + client.dispatcher().cancelAll(); + } + @Override public Call request(Request request) { return client.newCall(request); From f2f5cf13d2d585f935b98a5da383545217b9b503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 15:48:24 +0800 Subject: [PATCH 079/924] =?UTF-8?q?=E6=8A=BD=E8=B1=A1=20Cancelable=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=EF=BC=8C=E4=BD=BF=E5=BE=97=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E4=BB=BB=E5=8A=A1=20=E4=B9=9F=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E6=8C=89=20=E6=A0=87=E7=AD=BE=E5=8F=96=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/Cancelable.java | 11 ++++ src/main/java/com/ejlchina/okhttps/HTTP.java | 2 + .../java/com/ejlchina/okhttps/HttpCall.java | 2 +- .../okhttps/internal/AsyncHttpTask.java | 6 +-- .../ejlchina/okhttps/internal/HttpClient.java | 53 ++++++++----------- .../okhttps/internal/SyncHttpTask.java | 35 +++++++++++- src/test/java/com/ejlchina/test/HttpTest.java | 16 +++--- 7 files changed, 82 insertions(+), 43 deletions(-) create mode 100644 src/main/java/com/ejlchina/okhttps/Cancelable.java diff --git a/src/main/java/com/ejlchina/okhttps/Cancelable.java b/src/main/java/com/ejlchina/okhttps/Cancelable.java new file mode 100644 index 00000000..0c81a7ac --- /dev/null +++ b/src/main/java/com/ejlchina/okhttps/Cancelable.java @@ -0,0 +1,11 @@ +package com.ejlchina.okhttps; + +public interface Cancelable { + + /** + * �消 + * @return �消是��功 + */ + boolean cancel(); + +} diff --git a/src/main/java/com/ejlchina/okhttps/HTTP.java b/src/main/java/com/ejlchina/okhttps/HTTP.java index 3ac7124b..5252ff53 100644 --- a/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -33,12 +33,14 @@ public interface HTTP { /** * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 + * 从 v1.0.2 开始支��消�步请求 * @param tag 标签 * @return 被�消的任务数� */ int cancel(String tag); /** + * @since 1.0.2 * �消所有HTTP任务,包括�步和异步 */ void cancelAll(); diff --git a/src/main/java/com/ejlchina/okhttps/HttpCall.java b/src/main/java/com/ejlchina/okhttps/HttpCall.java index 8a59cd14..a7543a7b 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpCall.java +++ b/src/main/java/com/ejlchina/okhttps/HttpCall.java @@ -1,6 +1,6 @@ package com.ejlchina.okhttps; -public interface HttpCall { +public interface HttpCall extends Cancelable { /** * �消 Http 请求 diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index a0d798dc..7969fc11 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -113,7 +113,7 @@ private HttpCall request(String method) { } }); if (tag != null) { - httpClient.addTagCall(tag, call, this); + httpClient.addTagTask(tag, call, this); } return call; } @@ -136,7 +136,7 @@ public boolean cancel() { notify(); } if (tag != null && call == null) { - httpClient.removeTagCall(AsyncHttpTask.this); + httpClient.removeTagTask(AsyncHttpTask.this); } return res; } @@ -228,7 +228,7 @@ public void setResult(HttpResult result) { notify(); } if (tag != null) { - httpClient.removeTagCall(AsyncHttpTask.this); + httpClient.removeTagTask(AsyncHttpTask.this); } } diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 99660120..15e69497 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -11,14 +11,7 @@ import java.util.Queue; import java.util.concurrent.Executor; -import com.ejlchina.okhttps.Configurator; -import com.ejlchina.okhttps.DownListener; -import com.ejlchina.okhttps.HTTP; -import com.ejlchina.okhttps.HttpCall; -import com.ejlchina.okhttps.HttpResult; -import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.Preprocessor; -import com.ejlchina.okhttps.TaskListener; +import com.ejlchina.okhttps.*; import com.ejlchina.okhttps.HttpResult.State; import okhttp3.Call; @@ -30,9 +23,9 @@ public class HttpClient implements HTTP { - + // OkHttpClient final OkHttpClient client; - + // 根URL final String baseUrl; // 媒体类型 final Map mediaTypes; @@ -40,8 +33,8 @@ public class HttpClient implements HTTP { final TaskExecutor executor; // 预处�器 final Preprocessor[] preprocessors; - - final List tagCalls; + // �有标签的任务 + final List tagTasks; private HttpClient(Builder builder) { @@ -52,8 +45,8 @@ private HttpClient(Builder builder) { builder.mainExecutor, builder.downloadListener, builder.responseListener, builder.exceptionListener, builder.completeListener); - this.preprocessors = builder.preprocessors.toArray(new Preprocessor[builder.preprocessors.size()]); - this.tagCalls = Collections.synchronizedList(new LinkedList<>()); + this.preprocessors = builder.preprocessors.toArray(new Preprocessor[0]); + this.tagTasks = Collections.synchronizedList(new LinkedList<>()); } @Override @@ -72,12 +65,12 @@ public int cancel(String tag) { return 0; } int count = 0; - Iterator it = tagCalls.iterator(); + Iterator it = tagTasks.iterator(); while (it.hasNext()) { - TagCall tagCall = it.next(); + TagTask tagCall = it.next(); // ��任务的标签包�指定的Tag就会被�消 if (tagCall.tag.contains(tag)) { - if (tagCall.call.cancel()) { + if (tagCall.canceler.cancel()) { count++; } it.remove(); @@ -109,18 +102,18 @@ public int totalTimeoutMillis() { return client.connectTimeoutMillis() + client.writeTimeoutMillis() + client.readTimeoutMillis(); } - public int getTagCallCount() { - return tagCalls.size(); + public int getTagTaskCount() { + return tagTasks.size(); } - public void addTagCall(String tag, HttpCall call, HttpTask task) { - tagCalls.add(new TagCall(tag, call, task)); + public void addTagTask(String tag, Cancelable canceler, HttpTask task) { + tagTasks.add(new TagTask(tag, canceler, task)); } - public void removeTagCall(HttpTask task) { - Iterator it = tagCalls.iterator(); + public void removeTagTask(HttpTask task) { + Iterator it = tagTasks.iterator(); while (it.hasNext()) { - TagCall tagCall = it.next(); + TagTask tagCall = it.next(); if (tagCall.task == task) { it.remove(); break; @@ -128,15 +121,15 @@ public void removeTagCall(HttpTask task) { } } - class TagCall { - + static class TagTask { + String tag; - HttpCall call; + Cancelable canceler; HttpTask task; - - public TagCall(String tag, HttpCall call, HttpTask task) { + + public TagTask(String tag, Cancelable canceler, HttpTask task) { this.tag = tag; - this.call = call; + this.canceler = canceler; this.task = task; } diff --git a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index 648c8357..cbb9cdd4 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -2,6 +2,7 @@ import java.io.IOException; +import com.ejlchina.okhttps.Cancelable; import com.ejlchina.okhttps.HttpResult; import com.ejlchina.okhttps.HttpTask; import com.ejlchina.okhttps.HttpResult.State; @@ -53,13 +54,45 @@ public HttpResult put() { public HttpResult delete() { return request("DELETE"); } - + + static class SyncCall implements Cancelable { + + final Call call; + boolean done = false; + + public SyncCall(Call call) { + this.call = call; + } + + @Override + public boolean cancel() { + if (done) { + return false; + } + call.cancel(); + return true; + } + + public void setDone(boolean done) { + this.done = done; + } + + } + private HttpResult request(String method) { RealHttpResult result = new RealHttpResult(this, httpClient.getExecutor()); httpClient.preprocess(this, () -> { Call call = prepareCall(method); + SyncCall syncCall = null; + if (tag != null) { + syncCall = new SyncCall(call); + httpClient.addTagTask(tag, syncCall, this); + } try { Response response = call.execute(); + if (syncCall != null) { + syncCall.setDone(true); + } synchronized (SyncHttpTask.this) { result.response(response); SyncHttpTask.this.notify(); diff --git a/src/test/java/com/ejlchina/test/HttpTest.java b/src/test/java/com/ejlchina/test/HttpTest.java index e8951dab..c638d69d 100644 --- a/src/test/java/com/ejlchina/test/HttpTest.java +++ b/src/test/java/com/ejlchina/test/HttpTest.java @@ -396,7 +396,7 @@ public void testCancel() { .setTag("A") .get(); - System.out.println(((HttpClient) http).getTagCallCount()); + System.out.println(((HttpClient) http).getTagTaskCount()); http.async("/user/show/2") .setOnResponse((HttpResult result) -> { @@ -405,7 +405,7 @@ public void testCancel() { .setTag("A.B") .get(); - System.out.println(((HttpClient) http).getTagCallCount()); + System.out.println(((HttpClient) http).getTagTaskCount()); http.async("/user/show/3") .setOnResponse((HttpResult result) -> { @@ -414,7 +414,7 @@ public void testCancel() { .setTag("B.C") .get(); - System.out.println(((HttpClient) http).getTagCallCount()); + System.out.println(((HttpClient) http).getTagTaskCount()); http.async("/user/show/4") .setOnResponse((HttpResult result) -> { @@ -423,24 +423,24 @@ public void testCancel() { .setTag("C") .get(); - System.out.println(((HttpClient) http).getTagCallCount()); + System.out.println(((HttpClient) http).getTagTaskCount()); System.out.println("标签�消:" + http.cancel("B")); - System.out.println(((HttpClient) http).getTagCallCount()); + System.out.println(((HttpClient) http).getTagTaskCount()); sleep(5000); - System.out.println(((HttpClient) http).getTagCallCount()); + System.out.println(((HttpClient) http).getTagTaskCount()); sleep(5000); - System.out.println(((HttpClient) http).getTagCallCount()); + System.out.println(((HttpClient) http).getTagTaskCount()); sleep(5000); - System.out.println(((HttpClient) http).getTagCallCount()); + System.out.println(((HttpClient) http).getTagTaskCount()); // System.out.println("isDone = " + call.isDone()); // System.out.println("isCanceled = " + call.isCanceled()); From 52f628cbe023cbbaef4d2b3cd3631a264fec7548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 16:01:01 +0800 Subject: [PATCH 080/924] . --- src/main/java/com/ejlchina/okhttps/Preprocessor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/Preprocessor.java b/src/main/java/com/ejlchina/okhttps/Preprocessor.java index d0f6f96c..a1fdd173 100644 --- a/src/main/java/com/ejlchina/okhttps/Preprocessor.java +++ b/src/main/java/com/ejlchina/okhttps/Preprocessor.java @@ -19,8 +19,9 @@ interface PreChain { /** * @return 当�的请求任务 */ + @SuppressWarnings("") HttpTask getTask(); - + /** * @return HTTP */ From 7dfe92f4607b76ff2b4ef33635ea64cb4e7acc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 16:04:38 +0800 Subject: [PATCH 081/924] . --- src/main/java/com/ejlchina/okhttps/Preprocessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/Preprocessor.java b/src/main/java/com/ejlchina/okhttps/Preprocessor.java index a1fdd173..c090c56e 100644 --- a/src/main/java/com/ejlchina/okhttps/Preprocessor.java +++ b/src/main/java/com/ejlchina/okhttps/Preprocessor.java @@ -19,7 +19,7 @@ interface PreChain { /** * @return 当�的请求任务 */ - @SuppressWarnings("") + @SuppressWarnings("all") HttpTask getTask(); /** From 5d2429baab904735ea320c3409b21fa2096940d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 16:10:01 +0800 Subject: [PATCH 082/924] . --- src/main/java/com/ejlchina/okhttps/Preprocessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/Preprocessor.java b/src/main/java/com/ejlchina/okhttps/Preprocessor.java index c090c56e..12454e6e 100644 --- a/src/main/java/com/ejlchina/okhttps/Preprocessor.java +++ b/src/main/java/com/ejlchina/okhttps/Preprocessor.java @@ -19,7 +19,7 @@ interface PreChain { /** * @return 当�的请求任务 */ - @SuppressWarnings("all") + @SuppressWarnings("rawtypes") HttpTask getTask(); /** From 38d09fe668ed359dcd4fd2c0aeff1f29ad3e3c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 16:13:42 +0800 Subject: [PATCH 083/924] . --- README.md | 2 +- src/main/java/com/ejlchina/okhttps/Preprocessor.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bdc34adf..98ca90d1 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 -> OkHttps �常轻�,自身代�在 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A +> OkHttps �常轻�,自身代�在 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.1] diff --git a/src/main/java/com/ejlchina/okhttps/Preprocessor.java b/src/main/java/com/ejlchina/okhttps/Preprocessor.java index 12454e6e..c090c56e 100644 --- a/src/main/java/com/ejlchina/okhttps/Preprocessor.java +++ b/src/main/java/com/ejlchina/okhttps/Preprocessor.java @@ -19,7 +19,7 @@ interface PreChain { /** * @return 当�的请求任务 */ - @SuppressWarnings("rawtypes") + @SuppressWarnings("all") HttpTask getTask(); /** From a399222d077f3a5d0d10b3a143716011be2c7638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 16:51:52 +0800 Subject: [PATCH 084/924] V1.0.2 ^_^ --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1678b893..b8e2b970 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.ejlchina okhttps - 1.0.1 + 1.0.2 OkHttps @@ -32,7 +32,7 @@ scm:git://gitee.com/ejlchina-zhxu/okhttps.git scm:http://gitee.com/ejlchina-zhxu/okhttps https://gitee.com/ejlchina-zhxu/okhttps - v1.0.1 + v1.0.2 From 15c74c7b1f14d77ad6c4d47465faf9e470ccc350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 17:21:04 +0800 Subject: [PATCH 085/924] Tests --- src/test/java/com/ejlchina/test/BaseTest.java | 49 ++ .../java/com/ejlchina/test/CacheTests.java | 27 + .../java/com/ejlchina/test/CancelTests.java | 97 +++ .../java/com/ejlchina/test/DownloadTests.java | 140 ++++ .../com/ejlchina/test/ExceptionTests.java | 18 +- .../java/com/ejlchina/test/ExecutorTests.java | 39 ++ src/test/java/com/ejlchina/test/HttpTest.java | 611 ------------------ .../java/com/ejlchina/test/JsonTests.java | 61 ++ .../java/com/ejlchina/test/ListenerTests.java | 94 +++ .../com/ejlchina/test/PreprocessorTests.java | 60 ++ .../java/com/ejlchina/test/SimpleTests.java | 28 +- .../java/com/ejlchina/test/UploadTests.java | 36 ++ 12 files changed, 610 insertions(+), 650 deletions(-) create mode 100644 src/test/java/com/ejlchina/test/BaseTest.java create mode 100644 src/test/java/com/ejlchina/test/CacheTests.java create mode 100644 src/test/java/com/ejlchina/test/CancelTests.java create mode 100644 src/test/java/com/ejlchina/test/DownloadTests.java create mode 100644 src/test/java/com/ejlchina/test/ExecutorTests.java delete mode 100644 src/test/java/com/ejlchina/test/HttpTest.java create mode 100644 src/test/java/com/ejlchina/test/JsonTests.java create mode 100644 src/test/java/com/ejlchina/test/ListenerTests.java create mode 100644 src/test/java/com/ejlchina/test/PreprocessorTests.java create mode 100644 src/test/java/com/ejlchina/test/UploadTests.java diff --git a/src/test/java/com/ejlchina/test/BaseTest.java b/src/test/java/com/ejlchina/test/BaseTest.java new file mode 100644 index 00000000..bd96497b --- /dev/null +++ b/src/test/java/com/ejlchina/test/BaseTest.java @@ -0,0 +1,49 @@ +package com.ejlchina.test; + +public class BaseTest { + + public static void sleep(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public static void println() { + System.out.println(); + } + + public static void println(Object x) { + System.out.println(x); + } + + public static void println(long t0, String str) { + System.out.println(now() - t0 + "\t" + str); + } + + public static long now() { + return System.currentTimeMillis(); + } + + public static class User { + + private int id; + private String name; + + public void setId(int id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + "]"; + } + + } + +} diff --git a/src/test/java/com/ejlchina/test/CacheTests.java b/src/test/java/com/ejlchina/test/CacheTests.java new file mode 100644 index 00000000..baa95483 --- /dev/null +++ b/src/test/java/com/ejlchina/test/CacheTests.java @@ -0,0 +1,27 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpResult; +import org.junit.Test; + +public class CacheTests extends BaseTest { + + @Test + public void testCache() { + HTTP http = HTTP.builder().build(); + + HttpResult.Body body = http.sync("http://xxx.cdyun.vip/comm/provinces") + .get() + .getBody() + .cache(); + + println("result = " + body.toString()); + println("result = " + body.toJsonArray()); + + body.close(); + + println("result = " + body.toString()); + println("result = " + body.toJsonArray()); + } + +} diff --git a/src/test/java/com/ejlchina/test/CancelTests.java b/src/test/java/com/ejlchina/test/CancelTests.java new file mode 100644 index 00000000..ebd5aaa0 --- /dev/null +++ b/src/test/java/com/ejlchina/test/CancelTests.java @@ -0,0 +1,97 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.internal.HttpClient; +import org.junit.Test; + +import java.io.IOException; + +/** + * 测试�消 + */ +public class CancelTests extends BaseTest { + + + @Test + public void testCancel() { + + HTTP http = HTTP.builder() + .baseUrl("http://localhost:8080") + .build(); + + http.async("/user/show/1") + .setOnResponse((HttpResult result) -> { + println(result); + }) + .setOnException((IOException e) -> { + println("异常�获:" + e.getMessage()); + }) + .setOnComplete((HttpResult.State state) -> { + println(state); + }) + .setTag("A") + .get(); + + println(((HttpClient) http).getTagTaskCount()); + + http.async("/user/show/2") + .setOnResponse((HttpResult result) -> { + println(result); + }) + .setTag("A.B") + .get(); + + println(((HttpClient) http).getTagTaskCount()); + + http.async("/user/show/3") + .setOnResponse((HttpResult result) -> { + println(result); + }) + .setTag("B.C") + .get(); + + println(((HttpClient) http).getTagTaskCount()); + + http.async("/user/show/4") + .setOnResponse((HttpResult result) -> { + println(result); + }) + .setTag("C") + .get(); + + println(((HttpClient) http).getTagTaskCount()); + + + println("标签�消:" + http.cancel("B")); + + println(((HttpClient) http).getTagTaskCount()); + + sleep(5000); + + println(((HttpClient) http).getTagTaskCount()); + + sleep(5000); + + println(((HttpClient) http).getTagTaskCount()); + + sleep(5000); + + println(((HttpClient) http).getTagTaskCount()); + +// println("isDone = " + call.isDone()); +// println("isCanceled = " + call.isCanceled()); +// +// println("�消结果 = " + call.cancel()); +// +// println("isDone = " + call.isDone()); +// println("isCanceled = " + call.isCanceled()); +// +// sleep(100); +// println("++++++++"); +// +// println("isDone = " + call.isDone()); +// println("isCanceled = " + call.isCanceled()); + } + +} diff --git a/src/test/java/com/ejlchina/test/DownloadTests.java b/src/test/java/com/ejlchina/test/DownloadTests.java new file mode 100644 index 00000000..12113de8 --- /dev/null +++ b/src/test/java/com/ejlchina/test/DownloadTests.java @@ -0,0 +1,140 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.*; +import com.ejlchina.okhttps.Process; +import okhttp3.OkHttpClient; +import org.junit.Test; + +import java.io.File; +import java.util.concurrent.TimeUnit; + +public class DownloadTests extends BaseTest { + + + /** + * 分�下载测试 + * @param args + */ + public static void main(String[] args) { + long totalSize = HttpUtils.sync("/download/test.zip").get().getBody() + .close() // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); + download(totalSize, 0); // 从第 0 �开始下载 + sleep(50000); // 等待下载完� + } + + static void download(long totalSize, int index) { + long size = 3 * 1024 * 1024; // ��下载 3M + long start = index * size; + long end = Math.min(start + size, totalSize); + HttpUtils.sync("/download/test.zip") + .setRange(start, end) // 设置本次下载的范围 + .get().getBody() + .toFile("D:/download/test.zip") // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + if (end < totalSize) { // 若未下载完,则继续下载下一� + download(totalSize, index + 1); + } else { + println("下载完�"); + } + }) + .start(); + } + + + + @Test + public void testDownload() { + HTTP http = HTTP.builder() + .config((OkHttpClient.Builder builder) -> { + builder.readTimeout(300, TimeUnit.MILLISECONDS); + }) + .build(); + + String url = "https://download.cocos.com/CocosDashboard/v1.0.1/CocosDashboard-v1.0.1-win32-031816.exe"; +// String url = "http://47.100.7.202/ejl-test.zip"; + + long t0 = now(); + +// Ctrl ctrl = + http.sync(url) +// .setRange(24771214) + .bind(this) + .get() + .getBody() + .setOnProcess((Process process) -> { + println(t0, process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate()); + }) + .setStepRate(0.1) + .toFolder("D:/WorkSpace/download/") +// .toFile("D:\\WorkSpace\\download\\CocosDashboard-v1.0.1-win32-031816(9).exe") +// .setAppended() // �用 断点续传 + .nextOnIO() + .setOnSuccess((File file) -> { + println(t0, "下载�功:" + file.getAbsolutePath()); + println(); + }) + .setOnFailure((Download.Failure failure) -> { + println(t0, "下载失败:" + failure.getDoneBytes() + ", path = " + failure.getFile().getAbsolutePath()); + println(); + }) + .start(); + + sleep(10000); + +// ctrl.status(); +// ctrl.pause(); +// println("暂�"); +// sleep(5000); +// +// ctrl.resume(); +// println("继续"); +// sleep(5000); +// +// ctrl.cancel(); +// println("�消"); + + +// + +// +// ctrl.pause(); +// println("暂�"); +// sleep(5000); +// +// ctrl.resume(); +// println("继续"); + sleep(5000); + + } + + + @Test + public void syncHttpExample() { + + HTTP http = HTTP.builder().build(); + // �步请求 + HttpResult result = http.sync("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1584365400942&di=d9e7890f13b7bc4b76080fdd490ed5d5&imgtype=0&src=http%3A%2F%2Ft8.baidu.com%2Fit%2Fu%3D1484500186%2C1503043093%26fm%3D79%26app%3D86%26f%3DJPEG%3Fw%3D1280%26h%3D853") + .get(); + + result.getBody().toFile("E:/3.jpg"); +// // 得到状�� +// int status = result.getStatus(); +// +// // 得到返回头 +// Headers headers = result.getHeaders(); +// +// User user = result.getBody().toBean(User.class); +// // 得到目标数� +// +// +// println("status = " + status); +// println("headers = " + headers); +// println("user = " + user); + + println("status = " + result.getStatus()); + + } + +} diff --git a/src/test/java/com/ejlchina/test/ExceptionTests.java b/src/test/java/com/ejlchina/test/ExceptionTests.java index aafeedf1..7cee825b 100644 --- a/src/test/java/com/ejlchina/test/ExceptionTests.java +++ b/src/test/java/com/ejlchina/test/ExceptionTests.java @@ -12,7 +12,10 @@ import java.net.UnknownHostException; import java.util.concurrent.TimeUnit; -public class ExceptionTests { +/** + * 测试异常处� + */ +public class ExceptionTests extends BaseTest { HTTP http = HTTP.builder() .config((OkHttpClient.Builder builder) -> { @@ -78,11 +81,11 @@ public void testASync() { http.async("/users/1") .setOnResponse((HttpResult result) -> { // 当�生异常时就�会走这里 - System.out.println(result); + println(result); }) .setOnException((IOException e) -> { // 这里处�请求异常 - System.out.println(e); + println(e); }) .get(); @@ -90,13 +93,4 @@ public void testASync() { } - - void sleep(int millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } diff --git a/src/test/java/com/ejlchina/test/ExecutorTests.java b/src/test/java/com/ejlchina/test/ExecutorTests.java new file mode 100644 index 00000000..8f82422b --- /dev/null +++ b/src/test/java/com/ejlchina/test/ExecutorTests.java @@ -0,0 +1,39 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.Process; +import org.junit.Test; + +public class ExecutorTests extends BaseTest { + + + @Test + public void testExecutor() { + HTTP http = HTTP.builder() + .callbackExecutor((Runnable command) -> { + println("主线程执行"); + command.run(); + }).build(); + + http.async("http://47.100.7.202/ejl-test.zip") + .addBodyParam("name", "Jack") +// .nextOnIO() + .setOnProcess((Process process) -> { + println("process: " + process.getRate()); + }) +// .nextOnIO() + .setOnResponse((HttpResult result) -> { + println("status: " + result.close().getStatus()); + }) + .nextOnIO() + .setOnComplete((HttpResult.State state) -> { + println("state: " + state); + }) + .post(); + + sleep(3000); + } + + +} diff --git a/src/test/java/com/ejlchina/test/HttpTest.java b/src/test/java/com/ejlchina/test/HttpTest.java deleted file mode 100644 index c638d69d..00000000 --- a/src/test/java/com/ejlchina/test/HttpTest.java +++ /dev/null @@ -1,611 +0,0 @@ -package com.ejlchina.test; - - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -import com.ejlchina.okhttps.Download; -import com.ejlchina.okhttps.HTTP; -import com.ejlchina.okhttps.HttpCall; -import com.ejlchina.okhttps.HttpResult; -import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.HttpUtils; -import com.ejlchina.okhttps.Process; -import com.ejlchina.okhttps.Download.Ctrl; -import com.ejlchina.okhttps.Download.Failure; -import com.ejlchina.okhttps.HttpResult.Body; -import com.ejlchina.okhttps.HttpResult.State; -import com.ejlchina.okhttps.Preprocessor.PreChain; -import com.ejlchina.okhttps.internal.HttpClient; - -import okhttp3.ConnectionPool; -import okhttp3.Interceptor.Chain; -import okhttp3.OkHttpClient.Builder; -import okhttp3.Request; - - -public class HttpTest { - - - @Test - public void testCache() { - HTTP http = HTTP.builder().build(); - - Body body = http.sync("http://xxx.cdyun.vip/comm/provinces") - .get() - .getBody() - .cache() - ; - - - System.out.println("result = " + body.toString()); - System.out.println("result = " + body.toJsonArray()); - System.out.println("result = " + body.toBytes()); - - body.close(); - - System.out.println("result = " + body.toString()); - System.out.println("result = " + body.toJsonArray()); - System.out.println("result = " + body.toBytes()); - } - - - @Test - public void testGlobalCallback() { - HTTP http = HTTP.builder() - .responseListener((HttpTask task, HttpResult result) -> { - System.out.println("全局 onResponse: " + result.getStatus()); - return true; - }) - .completeListener((HttpTask task, State state) -> { - System.out.println("全局 onComplete: " + state); - return true; - }) - .exceptionListener((HttpTask task, IOException error) -> { - System.out.println("全局 onException: " + error.getMessage()); - return false; - }) - .build(); - - http.async("http://www.baidu.com") - .setOnResponse((HttpResult result) -> { - System.out.println("�例 onResponse: " + result.getStatus()); - }) - .setOnComplete((State state) -> { - System.out.println("�例 onComplete: " + state); - }) - .setOnException((IOException error) -> { - System.out.println("�例 onException: " + error.getMessage()); - }) - .get(); - - sleep(2000); - } - - @Test - public void testDownloadListener() { - HTTP http = HTTP.builder() - .downloadListener((HttpTask task, Download download) -> { - System.out.println("URL = " + task.getUrl()); - System.out.println("TAG = " + task.getTag()); - Ctrl ctrl = download.getCtrl(); - - new Thread(() -> { - sleep(3000); - ctrl.pause(); - sleep(3000); - ctrl.resume(); - sleep(3000); - ctrl.cancel(); - }).start(); - }) - .build(); - - String url = "https://download.cocos.com/CocosDashboard/v1.0.1/CocosDashboard-v1.0.1-win32-031816.exe"; - - long t0 = System.currentTimeMillis(); - - - http.sync(url) - .setTag("ASD") - .get() - .getBody() - .setOnProcess((Process process) -> { - print(t0, process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); - }) - .setStepRate(0.01) - .toFolder("D:/download/") - .nextOnIO() - .setOnSuccess((File file) -> { - print(t0, "下载�功:" + file.getAbsolutePath(), true); - }) - .setOnFailure((Failure failure) -> { - print(t0, "下载失败:" + failure.getDoneBytes() + ", path = " + failure.getFile().getAbsolutePath(), true); - }) - .start(); - - sleep(20000); - } - - @Test - public void testExecutor() { - HTTP http = HTTP.builder() - .callbackExecutor((Runnable command) -> { - System.out.println("主线程执行"); - command.run(); - }).build(); - - http.async("http://47.100.7.202/ejl-test.zip") - .addBodyParam("name", "Jack") -// .nextOnIO() - .setOnProcess((Process process) -> { - System.out.println("process: " + process.getRate()); - }) -// .nextOnIO() - .setOnResponse((HttpResult result) -> { - System.out.println("status: " + result.close().getStatus()); - }) - .nextOnIO() - .setOnComplete((State state) -> { - System.out.println("state: " + state); - }) - .post(); - - sleep(3000); - } - - - public static void main(String[] args) { - long totalSize = HttpUtils.sync("/download/test.zip").get().getBody() - .close() // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭 - .getContentLength(); - download(totalSize, 0); // 从第 0 �开始下载 - sleep(50000); // 等待下载完� - } - - static void download(long totalSize, int index) { - long size = 3 * 1024 * 1024; // ��下载 3M - long start = index * size; - long end = Math.min(start + size, totalSize); - HttpUtils.sync("/download/test.zip") - .setRange(start, end) // 设置本次下载的范围 - .get().getBody() - .toFile("D:/download/test.zip") // 下载到�一个文件里 - .setAppended() // 开�文件追加模� - .setOnSuccess((File file) -> { - if (end < totalSize) { // 若未下载完,则继续下载下一� - download(totalSize, index + 1); - } else { - System.out.println("下载完�"); - } - }) - .start(); - } - - - @Test - public void testD() { - System.out.println(Long.parseLong("12")); - } - - - @Test - public void testUpload() { - String data = "0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz"; - - HTTP http = HTTP.builder().build(); - - long t0 = System.currentTimeMillis(); - - String res = http.sync("http://localhost:8080/test/index") - .addBodyParam("data", data) - .addFileParam("file", "D:\\WorkSpace\\download\\CocosDashboard-v1.0.1-win32-031816.exe") - .setStepRate(0.01) - .setOnProcess((Process process) -> { - print(t0, "上传:" + process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); - }) - .post() - .getBody() - .setStepBytes(5) - .setOnProcess((Process process) -> { - print(t0, "下载:" + process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); - }) - .toString(); - - System.out.println("�应:" + res); - } - - @Test - public void testDownload() { - HTTP http = HTTP.builder() - .config((Builder builder) -> { - builder.readTimeout(300, TimeUnit.MILLISECONDS); - }) - .build(); - - String url = "https://download.cocos.com/CocosDashboard/v1.0.1/CocosDashboard-v1.0.1-win32-031816.exe"; -// String url = "http://47.100.7.202/ejl-test.zip"; - - long t0 = System.currentTimeMillis(); - -// Ctrl ctrl = - http.sync(url) -// .setRange(24771214) - .bind(this) - .get() - .getBody() - .setOnProcess((Process process) -> { - print(t0, process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); - }) - .setStepRate(0.1) - .toFolder("D:/WorkSpace/download/") -// .toFile("D:\\WorkSpace\\download\\CocosDashboard-v1.0.1-win32-031816(9).exe") -// .setAppended() // �用 断点续传 - .nextOnIO() - .setOnSuccess((File file) -> { - print(t0, "下载�功:" + file.getAbsolutePath(), true); - }) - .setOnFailure((Failure failure) -> { - print(t0, "下载失败:" + failure.getDoneBytes() + ", path = " + failure.getFile().getAbsolutePath(), true); - }) - .start(); - - sleep(10000); - -// ctrl.status(); -// ctrl.pause(); -// System.out.println("暂�"); -// sleep(5000); -// -// ctrl.resume(); -// System.out.println("继续"); -// sleep(5000); -// -// ctrl.cancel(); -// System.out.println("�消"); - - -// - -// -// ctrl.pause(); -// System.out.println("暂�"); -// sleep(5000); -// -// ctrl.resume(); -// System.out.println("继续"); - sleep(5000); - - } - - void print(long t0, String str, boolean ln) { - long now = System.currentTimeMillis() - t0; - System.out.println((now) + "\t" + str); - if (ln) { - System.out.println(); - } - } - - long now(long t0) { - return System.currentTimeMillis() - t0; - } - - - @Test - public void testToList() { - long t0 = System.currentTimeMillis(); - - HTTP http = HTTP.builder() - .baseUrl("http://xxx.cdyun.vip/ejlchina") - .build(); - - HttpResult result = http.sync("/comm/provinces") - .setRange(0) - .get(); - - print(t0, "status: " + result.getStatus(), true); - print(t0, "headers: " + result.getHeaders(), true); - - Body body = result.getBody(); - - print(t0, "total: " + body.getContentLength(), true); - - List list = body.setStepRate(0.1) - .setOnProcess((Process process) -> { - print(t0, process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate(), false); - }) - .toList(User.class); - - print(t0, list.toString(), false); - } - - - @Test - public void testPreprocessor() { - - HTTP http = HTTP.builder() - .baseUrl("http://localhost:8080") - .addPreprocessor((PreChain chain) -> { - System.out.println("并行预处�-开始"); -// new Thread(() -> { - sleep(2000); - System.out.println("并行预处�-结�"); - chain.proceed(); -// }).start(); - }) - .addSerialPreprocessor((PreChain chain) -> { - System.out.println("串行预处�-开始"); - new Thread(() -> { - sleep(3000); - System.out.println("串行预处�-结�"); - chain.proceed(); - }).start(); - }) - .build(); - - new Thread(() -> { - System.out.println(http.sync("/user/show/1").get()); - }).start(); - - new Thread(() -> { - System.out.println(http.sync("/user/show/2").get()); - }).start(); - -// new Thread(() -> { -// http.async("/user/show/1") -// .setOnResponse((HttpResult result) -> { -// System.out.println(result); -// }) -// .get(); -// }).start(); -// -// new Thread(() -> { -// http.async("/user/show/2") -// .setOnResponse((HttpResult result) -> { -// System.out.println(result); -// }) -// .get(); -// }).start(); - - sleep(10000); - } - - - - @Test - public void testCancel() { - - HTTP http = HTTP.builder() - .baseUrl("http://localhost:8080") - .build(); - - http.async("/user/show/1") - .setOnResponse((HttpResult result) -> { - System.out.println(result); - }) - .setOnException((IOException e) -> { - System.out.println("异常�获:" + e.getMessage()); - }) - .setOnComplete((State state) -> { - System.out.println(state); - }) - .setTag("A") - .get(); - - System.out.println(((HttpClient) http).getTagTaskCount()); - - http.async("/user/show/2") - .setOnResponse((HttpResult result) -> { - System.out.println(result); - }) - .setTag("A.B") - .get(); - - System.out.println(((HttpClient) http).getTagTaskCount()); - - http.async("/user/show/3") - .setOnResponse((HttpResult result) -> { - System.out.println(result); - }) - .setTag("B.C") - .get(); - - System.out.println(((HttpClient) http).getTagTaskCount()); - - http.async("/user/show/4") - .setOnResponse((HttpResult result) -> { - System.out.println(result); - }) - .setTag("C") - .get(); - - System.out.println(((HttpClient) http).getTagTaskCount()); - - - System.out.println("标签�消:" + http.cancel("B")); - - System.out.println(((HttpClient) http).getTagTaskCount()); - - sleep(5000); - - System.out.println(((HttpClient) http).getTagTaskCount()); - - sleep(5000); - - System.out.println(((HttpClient) http).getTagTaskCount()); - - sleep(5000); - - System.out.println(((HttpClient) http).getTagTaskCount()); - -// System.out.println("isDone = " + call.isDone()); -// System.out.println("isCanceled = " + call.isCanceled()); -// -// System.out.println("�消结果 = " + call.cancel()); -// -// System.out.println("isDone = " + call.isDone()); -// System.out.println("isCanceled = " + call.isCanceled()); -// -// sleep(100); -// System.out.println("++++++++"); -// -// System.out.println("isDone = " + call.isDone()); -// System.out.println("isCanceled = " + call.isCanceled()); - } - - - - - private HTTP buildHttp() { - - return HTTP.builder() - .config((Builder builder) -> { - - // �置连接池 最�10个连接(��置默认为 5) - builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES)); - - // �置连接超时时间 - builder.connectTimeout(20, TimeUnit.SECONDS); - - builder.addInterceptor((Chain chain) -> { - - Request request = chain.request(); - - return chain.proceed(request); - }); - }) - .baseUrl("http://localhost:8080") - .callbackExecutor((Runnable run) -> { - runOnUiThread(run); - }) - .addPreprocessor((PreChain chain) -> { - new Thread(() -> { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - chain.getTask().addHeader("Token", "yyyyy"); - - chain.proceed(); - - }).start(); - }) - .addPreprocessor((PreChain chain) -> { - new Thread(() -> { - - chain.getTask().addUrlParam("actor", "Alice"); - - chain.proceed(); - - }).start(); - }) - .build(); - - } - - - @Test - public void syncHttpExample() { - - HTTP http = buildHttp(); - // �步请求 - HttpResult result = http.sync("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1584365400942&di=d9e7890f13b7bc4b76080fdd490ed5d5&imgtype=0&src=http%3A%2F%2Ft8.baidu.com%2Fit%2Fu%3D1484500186%2C1503043093%26fm%3D79%26app%3D86%26f%3DJPEG%3Fw%3D1280%26h%3D853") - .get(); - - result.getBody().toFile("E:/3.jpg"); -// // 得到状�� -// int status = result.getStatus(); -// -// // 得到返回头 -// Headers headers = result.getHeaders(); -// -// User user = result.getBody().toBean(User.class); -// // 得到目标数� -// -// -// System.out.println("status = " + status); -// System.out.println("headers = " + headers); -// System.out.println("user = " + user); - - System.out.println("status = " + result.getStatus()); - - } - - - @Test - public void syncJsonExample() { - HTTP http = buildHttp(); - // �步请求 - HttpResult result = http.sync("/user/save") - .addJsonParam("name", "Tom") - .addJsonParam("age", 23) - .post(); - - System.out.println("result = " + result); - - result = http.sync("/user/show/1").get(); - - System.out.println("result = " + result); - - System.out.println("isSuccessful = " + result.isSuccessful()); - } - - @Test - public void asyncHttpExample() throws InterruptedException { - HTTP http = buildHttp(); - // 异步请求 - // 最终路径 http://api.demo.com/users/2 - HttpCall call = http.async("/user/show/{id}") - // 设置路径�数 - .addPathParam("id", 2) - // 设置回调函数 - .setOnResponse((HttpResult result) -> { - System.out.println("000"); -// User user = result.getBody().toBean(User.class); -// System.out.println("user = " + user); - }) - .setOnException((IOException e) -> { - e.printStackTrace(); - }) - // �起 GET 请求 - .get(); - - Thread.sleep(150); - - System.out.println("是�完�: " + call.isDone()); - System.out.println("是��消: " + call.isCanceled()); - - call.cancel(); // �消请求 - - System.out.println("是��消: " + call.isCanceled()); - System.out.println("执行结果: " + call.getResult()); - System.out.println("是�完�: " + call.isDone()); -// - Thread.sleep(100); -// -// System.out.println("是�完�: " + call.isDone()); -// System.out.println("是��消: " + call.isCanceled()); -// System.out.println("执行状�: " + call.getResult()); - - } - - - private static void sleep(int millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - - static void runOnUiThread(Runnable run) { - run.run(); - } - -} diff --git a/src/test/java/com/ejlchina/test/JsonTests.java b/src/test/java/com/ejlchina/test/JsonTests.java new file mode 100644 index 00000000..4e936e02 --- /dev/null +++ b/src/test/java/com/ejlchina/test/JsonTests.java @@ -0,0 +1,61 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.Process; +import org.junit.Test; + +import java.util.List; + +public class JsonTests extends BaseTest { + + @Test + public void syncJsonExample() { + HTTP http = HTTP.builder().build(); + // �步请求 + HttpResult result = http.sync("/user/save") + .addJsonParam("name", "Tom") + .addJsonParam("age", 23) + .post(); + + println("result = " + result); + + result = http.sync("/user/show/1").get(); + + println("result = " + result); + + println("isSuccessful = " + result.isSuccessful()); + } + + + @Test + public void testToList() { + long t0 = System.currentTimeMillis(); + + HTTP http = HTTP.builder() + .baseUrl("http://xxx.cdyun.vip/ejlchina") + .build(); + + HttpResult result = http.sync("/comm/provinces") + .setRange(0) + .get(); + + println(t0, "status: " + result.getStatus()); + println(); + println(t0, "headers: " + result.getHeaders()); + println(); + HttpResult.Body body = result.getBody(); + + println(t0, "total: " + body.getContentLength()); + println(); + List list = body.setStepRate(0.1) + .setOnProcess((Process process) -> { + println(t0, process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate()); + }) + .toList(User.class); + + println(t0, list.toString()); + } + + +} diff --git a/src/test/java/com/ejlchina/test/ListenerTests.java b/src/test/java/com/ejlchina/test/ListenerTests.java new file mode 100644 index 00000000..5a0ad8ac --- /dev/null +++ b/src/test/java/com/ejlchina/test/ListenerTests.java @@ -0,0 +1,94 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.Download; +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.Process; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +public class ListenerTests extends BaseTest { + + @Test + public void testGlobalCallback() { + HTTP http = HTTP.builder() + .responseListener((HttpTask task, HttpResult result) -> { + println("全局 onResponse: " + result.getStatus()); + return true; + }) + .completeListener((HttpTask task, HttpResult.State state) -> { + println("全局 onComplete: " + state); + return true; + }) + .exceptionListener((HttpTask task, IOException error) -> { + println("全局 onException: " + error.getMessage()); + return false; + }) + .build(); + + http.async("http://www.baidu.com") + .setOnResponse((HttpResult result) -> { + println("�例 onResponse: " + result.getStatus()); + }) + .setOnComplete((HttpResult.State state) -> { + println("�例 onComplete: " + state); + }) + .setOnException((IOException error) -> { + println("�例 onException: " + error.getMessage()); + }) + .get(); + + sleep(2000); + } + + @Test + public void testDownloadListener() { + HTTP http = HTTP.builder() + .downloadListener((HttpTask task, Download download) -> { + println("URL = " + task.getUrl()); + println("TAG = " + task.getTag()); + Download.Ctrl ctrl = download.getCtrl(); + + new Thread(() -> { + sleep(3000); + ctrl.pause(); + sleep(3000); + ctrl.resume(); + sleep(3000); + ctrl.cancel(); + }).start(); + }) + .build(); + + String url = "https://download.cocos.com/CocosDashboard/v1.0.1/CocosDashboard-v1.0.1-win32-031816.exe"; + + long t0 = now(); + + + http.sync(url) + .setTag("ASD") + .get() + .getBody() + .setOnProcess((Process process) -> { + println(t0, process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate()); + }) + .setStepRate(0.01) + .toFolder("D:/download/") + .nextOnIO() + .setOnSuccess((File file) -> { + println(t0, "下载�功:" + file.getAbsolutePath()); + println(); + }) + .setOnFailure((Download.Failure failure) -> { + println(t0, "下载失败:" + failure.getDoneBytes() + ", path = " + failure.getFile().getAbsolutePath()); + println(); + }) + .start(); + + sleep(20000); + } + +} diff --git a/src/test/java/com/ejlchina/test/PreprocessorTests.java b/src/test/java/com/ejlchina/test/PreprocessorTests.java new file mode 100644 index 00000000..f20fe559 --- /dev/null +++ b/src/test/java/com/ejlchina/test/PreprocessorTests.java @@ -0,0 +1,60 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.Preprocessor; +import org.junit.Test; + +public class PreprocessorTests extends BaseTest { + + + @Test + public void testPreprocessor() { + + HTTP http = HTTP.builder() + .baseUrl("http://localhost:8080") + .addPreprocessor((Preprocessor.PreChain chain) -> { + println("并行预处�-开始"); +// new Thread(() -> { + sleep(2000); + println("并行预处�-结�"); + chain.proceed(); +// }).start(); + }) + .addSerialPreprocessor((Preprocessor.PreChain chain) -> { + println("串行预处�-开始"); + new Thread(() -> { + sleep(3000); + println("串行预处�-结�"); + chain.proceed(); + }).start(); + }) + .build(); + + new Thread(() -> { + println(http.sync("/user/show/1").get()); + }).start(); + + new Thread(() -> { + println(http.sync("/user/show/2").get()); + }).start(); + +// new Thread(() -> { +// http.async("/user/show/1") +// .setOnResponse((HttpResult result) -> { +// println(result); +// }) +// .get(); +// }).start(); +// +// new Thread(() -> { +// http.async("/user/show/2") +// .setOnResponse((HttpResult result) -> { +// println(result); +// }) +// .get(); +// }).start(); + + sleep(10000); + } + +} diff --git a/src/test/java/com/ejlchina/test/SimpleTests.java b/src/test/java/com/ejlchina/test/SimpleTests.java index da3b3472..4a6d8a34 100644 --- a/src/test/java/com/ejlchina/test/SimpleTests.java +++ b/src/test/java/com/ejlchina/test/SimpleTests.java @@ -7,7 +7,7 @@ import java.util.List; -public class SimpleTests { +public class SimpleTests extends BaseTest { HTTP http = HTTP.builder() @@ -77,33 +77,7 @@ public void testContentLength() { System.out.println("size = " + (size / 1024) + " KB"); } - void sleep(int millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } } -class User { - - private int id; - private String name; - - public void setId(int id) { - this.id = id; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return "User [id=" + id + ", name=" + name + "]"; - } - -} \ No newline at end of file diff --git a/src/test/java/com/ejlchina/test/UploadTests.java b/src/test/java/com/ejlchina/test/UploadTests.java new file mode 100644 index 00000000..dc1728f5 --- /dev/null +++ b/src/test/java/com/ejlchina/test/UploadTests.java @@ -0,0 +1,36 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.Process; +import org.junit.Test; + +public class UploadTests extends BaseTest { + + @Test + public void testUpload() { + String data = "0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz0123456789abcdefghijklmnopqrstuvwsyz"; + + HTTP http = HTTP.builder().build(); + + long t0 = System.currentTimeMillis(); + + String res = http.sync("http://localhost:8080/test/index") + .addBodyParam("data", data) + .addFileParam("file", "D:\\WorkSpace\\download\\CocosDashboard-v1.0.1-win32-031816.exe") + .setStepRate(0.01) + .setOnProcess((Process process) -> { + println(t0, "上传:" + process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate()); + }) + .post() + .getBody() + .setStepBytes(5) + .setOnProcess((Process process) -> { + println(t0, "下载:" + process.getDoneBytes() + "/" + process.getTotalBytes() + "\t" + process.getRate()); + }) + .toString(); + + println("�应:" + res); + } + + +} From 90696dcf6a7b412ecfacaedab1187339e22ff6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 18:26:16 +0800 Subject: [PATCH 086/924] Tests --- src/test/java/com/ejlchina/test/CancelTests.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/test/java/com/ejlchina/test/CancelTests.java b/src/test/java/com/ejlchina/test/CancelTests.java index ebd5aaa0..45ec2707 100644 --- a/src/test/java/com/ejlchina/test/CancelTests.java +++ b/src/test/java/com/ejlchina/test/CancelTests.java @@ -13,6 +13,16 @@ public class CancelTests extends BaseTest { + public void testCancelAll() { + HTTP http = HTTP.builder() + .baseUrl("http://localhost:8080") + .build(); + + + + + } + @Test public void testCancel() { From ee6d276c6b3a601e2c2797306b633caefbd8efc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 20:37:19 +0800 Subject: [PATCH 087/924] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=AF=B9=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E8=AF=B7=E6=B1=82=E8=BF=9B=E8=A1=8C=E5=8F=96=E6=B6=88?= =?UTF-8?q?=E6=97=B6=EF=BC=8COkHttp=20=E5=BA=95=E5=B1=82=E6=8A=9B=E5=87=BA?= =?UTF-8?q?=20SocketException=20=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 8 ++++++-- .../java/com/ejlchina/okhttps/internal/AsyncHttpTask.java | 2 +- .../java/com/ejlchina/okhttps/internal/SyncHttpTask.java | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 392484d5..ae8f96fd 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.ConnectException; +import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.util.HashMap; @@ -559,12 +560,15 @@ private void buildHeaders(Request.Builder builder) { } } - protected State toState(IOException e) { + protected State toState(IOException e, boolean sync) { if (e instanceof SocketTimeoutException) { return State.TIMEOUT; } else if (e instanceof UnknownHostException || e instanceof ConnectException) { return State.NETWORK_ERROR; - } else if ("Canceled".equals(e.getMessage())) { + } + String msg = e.getMessage(); + if (msg != null && ("Canceled".equals(msg) || e instanceof SocketException + && msg.startsWith("Socket operation on nonsocket"))) { return State.CANCELED; } return State.EXCEPTION; diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 7969fc11..49be51ff 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -239,7 +239,7 @@ private HttpCall executeCall(Call call) { call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException error) { - State state = toState(error); + State state = toState(error, false); if (state == State.CANCELED) { httpCall.setResult(new RealHttpResult(AsyncHttpTask.this, state)); } else { diff --git a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index cbb9cdd4..4c3696dc 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -98,7 +98,7 @@ private HttpResult request(String method) { SyncHttpTask.this.notify(); } } catch (IOException e) { - State state = toState(e); + State state = toState(e, true); synchronized (SyncHttpTask.this) { result.exception(state, e); SyncHttpTask.this.notify(); @@ -114,7 +114,7 @@ private HttpResult request(String method) { } } } - Exception e = result.getError(); + IOException e = result.getError(); if (e != null && result.getState() != State.CANCELED && !nothrow) { throw new HttpException("请求执行异常", e); From 94043a090bd88fb33e42ab71944f541be1653231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 20:51:35 +0800 Subject: [PATCH 088/924] V1.0.2 ^_^ --- .../java/com/ejlchina/test/CancelTests.java | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/ejlchina/test/CancelTests.java b/src/test/java/com/ejlchina/test/CancelTests.java index 45ec2707..e69dfa2b 100644 --- a/src/test/java/com/ejlchina/test/CancelTests.java +++ b/src/test/java/com/ejlchina/test/CancelTests.java @@ -2,6 +2,7 @@ import com.ejlchina.okhttps.HTTP; import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpResult.State; import com.ejlchina.okhttps.internal.HttpClient; import org.junit.Test; @@ -13,14 +14,39 @@ public class CancelTests extends BaseTest { - public void testCancelAll() { + @Test + public void testCancelByTag() { HTTP http = HTTP.builder() - .baseUrl("http://localhost:8080") + .baseUrl("http://tst-api-mini.cdyun.vip") .build(); - - - + new Thread(() -> { + sleep(50); +// http.cancelAll(); +// int count = http.cancel("A"); +// println("count = " + count); + }).start(); + + http.async("/ejlchina/comm/provinces") + .setTag("A") + .setOnResponse((HttpResult result) -> { + println("异步:result = " + result); + }) + .setOnComplete((State state) -> { + println("异步:state = " + state); + }) + .get(); + + try { + HttpResult result = http.sync("/ejlchina/comm/provinces") + .setTag("A") + .get(); + + println("�步:result = " + result); + } catch (Exception e) { + e.printStackTrace(); + } + sleep(5000); } @Test From aa10838a97df402636a0845cc866e007872ec2ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 9 Apr 2020 21:04:48 +0800 Subject: [PATCH 089/924] V1.0.2 ^_^ --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 98ca90d1..31067378 100644 --- a/README.md +++ b/README.md @@ -87,11 +87,12 @@ ```java HTTP http = HTTP.builder().build(); ``` -  以上代�构建了一个最简�的`HTTP`实例,它拥有以下三个方法: +  以上代�构建了一个最简�的`HTTP`实例,它拥有以下方法: * `async(String url)` 开始一个异步HTTP任务 * `sync(String url)` 开始一个�步HTTP任务 * `cancel(String tag)` 根�标签批��消HTTP任务 +* `cancelAll()` �消所有任务(since v1.0.2)   为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(请��[5.1 设置 BaseUrl](#51-设置-baseurl)): @@ -323,7 +324,7 @@ http.async("/users") //(5) int count = http.cancel("B"); //(2)(3)(4)被�消(�消标签包�"B"的任务) System.out.println(count); // 输出 3 ``` -  �样的,�有异步HTTP任务��以被�消。标签除了�以用��消任务,在预处�器中它也�以�挥作用,请��[并行预处�器](#54-并行预处�器)与[串行预处�器](#55-串行预处�器)。 +  标签除了�以用��消任务,在预处�器中它也�以�挥作用,请��[并行预处�器](#54-并行预处�器)与[串行预处�器](#55-串行预处�器)。 ### 6 �置 HTTP From 261c2e8c3585e5934b2c192a0dd8bf413545fdee Mon Sep 17 00:00:00 2001 From: ejlchina Date: Fri, 10 Apr 2020 00:21:48 +0800 Subject: [PATCH 090/924] V1.0.2 ^_^ --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 31067378..d4e29534 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 -> OkHttps �常轻�,自身代�在 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) +> OkHttps �常轻�,自身代�仅 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.1] From 0956cec8e7ee74f69c1643f7cedf38d5c522b745 Mon Sep 17 00:00:00 2001 From: richenli <719583022@qq.com> Date: Fri, 10 Apr 2020 10:47:32 +0800 Subject: [PATCH 091/924] =?UTF-8?q?1.=E5=85=81=E8=AE=B8sync()=E5=92=8Casyn?= =?UTF-8?q?c()=E7=A9=BA=E5=8F=82=E4=BC=A0=E5=85=A5=20=E5=8E=9F=E5=9B=A0:?= =?UTF-8?q?=E9=83=A8=E5=88=86=E9=A1=B9=E7=9B=AE=E7=9A=84=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E6=94=BE=E5=9C=A8json=E5=BD=93=E4=B8=AD?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E4=BB=A5url=E4=B8=BA=E4=B8=BB=202.=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=E8=B6=85=E6=97=B6=E6=97=B6=E9=97=B4=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=20HTTP=20http=20=3D=20HTTP.builder().builderTimeOut(3,3,=20Tim?= =?UTF-8?q?eUnit.SECONDS).build();=203.=E4=BC=98=E5=8C=96HttpTask=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HTTP.java | 13 ++++ .../java/com/ejlchina/okhttps/HttpTask.java | 59 ++++++++----------- .../java/com/ejlchina/okhttps/HttpUtils.java | 16 +++++ .../ejlchina/okhttps/internal/HttpClient.java | 38 +++++++++++- 4 files changed, 91 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HTTP.java b/src/main/java/com/ejlchina/okhttps/HTTP.java index 5252ff53..22232f1e 100644 --- a/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -24,12 +24,25 @@ public interface HTTP { */ AsyncHttpTask async(String url); + /** + * 异步请求 + * @param url 请求地� + * @return 异步HTTP任务 + */ + AsyncHttpTask async(); + /** * �步请求 * @param url 请求地� * @return �步HTTP任务 */ SyncHttpTask sync(String url); + + /** + * �步请求 + * @return �步HTTP任务 + */ + SyncHttpTask sync(); /** * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index ae8f96fd..4d6038d7 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -18,6 +18,7 @@ import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; /** @@ -33,7 +34,6 @@ public abstract class HttpTask> { protected boolean nothrow; protected String tag; protected boolean nextOnIO = false; - private String urlPath; private Map headers; private Map pathParams; @@ -246,19 +246,10 @@ public C addPathParam(String name, Object value) { * @return HttpTask 实例 **/ public C addPathParam(Map params) { - if (params != null) { - if (pathParams == null) { - pathParams = new HashMap<>(); - } - params.forEach((String name, Object value) -> { - if (name != null && value != null) { - pathParams.put(name, value.toString()); - } - }); - } + addParams(params,this.pathParams); return (C) this; } - + /** * URL�数:拼接在URL�的�数 * @param name �数� @@ -281,16 +272,7 @@ public C addUrlParam(String name, Object value) { * @return HttpTask 实例 **/ public C addUrlParam(Map params) { - if (params != null) { - if (urlParams == null) { - urlParams = new HashMap<>(); - } - params.forEach((String name, Object value) -> { - if (name != null && value != null) { - urlParams.put(name, value.toString()); - } - }); - } + addParams(params,this.urlParams); return (C) this; } @@ -316,19 +298,26 @@ public C addBodyParam(String name, Object value) { * @return HttpTask 实例 **/ public C addBodyParam(Map params) { - if (params != null) { - if (bodyParams == null) { - bodyParams = new HashMap<>(); + addParams(params,this.bodyParams); + return (C) this; + } + private void addParams(Map params,Map addParam){ + if (params != null) { + if (addParam == null) { + addParam = new HashMap<>(); + } +// params.forEach((String name, Object value) -> { +// if (name != null && value != null) { +// addParam.put(name, value.toString()); +// } +// }); + for (Map.Entry stringEntry : params.entrySet()) { + if (stringEntry.getKey() != null && stringEntry.getValue() != null) { + addParam.put(stringEntry.getKey(), stringEntry.getValue().toString()); + } } - params.forEach((String name, Object value) -> { - if (name != null && value != null) { - bodyParams.put(name, value.toString()); - } - }); } - return (C) this; } - /** * Json�数:请求体为Json,支�多层结构 * @param name JSON键� @@ -504,6 +493,10 @@ class FilePara { } protected Call prepareCall(String method) { +// OkHttpClient client = new OkHttpClient.Builder() +// .connectTimeout(connectTimeout,timeUnit) // 设置连接超时时间 +// .readTimeout(readTimeout,timeUnit) // 设置读�超时时间 +// .build(); assertNotConflict("GET".equals(method)); Request.Builder builder = new Request.Builder() .url(buildUrlPath()); @@ -526,7 +519,7 @@ protected Call prepareCall(String method) { } switch (method) { case "GET": - builder.get(); + builder.get().build(); break; case "POST": builder.post(reqBody); diff --git a/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/src/main/java/com/ejlchina/okhttps/HttpUtils.java index a03e365f..e2a8e0af 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -59,6 +59,14 @@ public static AsyncHttpTask async(String url) { return getHttp().async(url); } + /** + * 异步请求 + * @return 异步 HttpTask + */ + public static AsyncHttpTask async() { + return getHttp().async(); + } + /** * �步请求 * @param url 请求地� @@ -68,6 +76,14 @@ public static SyncHttpTask sync(String url) { return getHttp().sync(url); } + /** + * �步请求 + * @return �步 HttpTask + */ + public static SyncHttpTask sync() { + return getHttp().sync(); + } + /** * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 * @param tag 标签 diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 15e69497..5a1ad119 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -10,6 +10,7 @@ import java.util.Map; import java.util.Queue; import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; import com.ejlchina.okhttps.*; import com.ejlchina.okhttps.HttpResult.State; @@ -58,7 +59,17 @@ public AsyncHttpTask async(String url) { public SyncHttpTask sync(String url) { return new SyncHttpTask(this, urlPath(url)); } - + + @Override + public AsyncHttpTask async() { + return new AsyncHttpTask(this, urlPath()); + } + + @Override + public SyncHttpTask sync() { + return new SyncHttpTask(this, urlPath()); + } + @Override public int cancel(String tag) { if (tag == null) { @@ -86,6 +97,7 @@ public void cancelAll() { @Override public Call request(Request request) { + return client.newCall(request); } @@ -269,6 +281,13 @@ private String urlPath(String urlPath) { } throw new HttpException("在设置 BaseUrl 之�,您必须使用全路径URL�起请求,当�URL为:" + urlPath); } + + private String urlPath() { + if (baseUrl != null) { + return baseUrl; + } + throw new HttpException("在设置 BaseUrl 之�,您必须使用全路径URL�起请求,当�URL为:" + baseUrl); + } public static class Builder { @@ -430,7 +449,22 @@ public Builder downloadListener(DownListener listener) { this.downloadListener = listener; return this; } - + + /** + * 设置超时时间 + * @param connectTimeout 连接时间 + * @param readTimeout 读�时间 + * @param timeUnit + * @return + */ + public Builder builderTimeOut(long connectTimeout, long readTimeout, TimeUnit timeUnit) { + this.client= new OkHttpClient.Builder() + .connectTimeout(connectTimeout,timeUnit) // 设置连接超时时间 + .readTimeout(readTimeout,timeUnit) // 设置读�超时时间 + .build(); + return this; + } + public HTTP build() { if (configurator != null || client == null) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); From 82eb2ea1c97f1033916a7b5b10bb57c9d4207018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 10 Apr 2020 11:42:47 +0800 Subject: [PATCH 092/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=88=A4=E6=96=AD=20?= =?UTF-8?q?Cancel=20=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index ae8f96fd..51d69a98 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -567,7 +567,8 @@ protected State toState(IOException e, boolean sync) { return State.NETWORK_ERROR; } String msg = e.getMessage(); - if (msg != null && ("Canceled".equals(msg) || e instanceof SocketException + if (msg != null && ("Canceled".equals(msg) + || sync && e instanceof SocketException && msg.startsWith("Socket operation on nonsocket"))) { return State.CANCELED; } From f63c0ac50db00a665703a9852594701dd3e813a5 Mon Sep 17 00:00:00 2001 From: richenli <719583022@qq.com> Date: Fri, 10 Apr 2020 12:20:25 +0800 Subject: [PATCH 093/924] =?UTF-8?q?1.=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E9=97=AE=E9=A2=98=E4=BB=A5=E5=8F=8A=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HTTP.java | 82 +- .../java/com/ejlchina/okhttps/HttpTask.java | 511 ++++++----- .../ejlchina/okhttps/internal/HttpClient.java | 852 +++++++++--------- 3 files changed, 743 insertions(+), 702 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HTTP.java b/src/main/java/com/ejlchina/okhttps/HTTP.java index 22232f1e..acb1fbd2 100644 --- a/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -12,79 +12,87 @@ /** * HTTP 客户端接� - * @author 15735 * + * @author 15735 */ public interface HTTP { - /** - * 异步请求 - * @param url 请求地� - * @return 异步HTTP任务 - */ + /** + * 异步请求 + * + * @param url 请求地� + * @return 异步HTTP任务 + */ AsyncHttpTask async(String url); - /** - * 异步请求 - * @param url 请求地� - * @return 异步HTTP任务 - */ - AsyncHttpTask async(); + /** + * 异步请求 + * + * @return 异步HTTP任务 + */ + AsyncHttpTask async(); - /** - * �步请求 - * @param url 请求地� - * @return �步HTTP任务 - */ + /** + * �步请求 + * + * @param url 请求地� + * @return �步HTTP任务 + */ SyncHttpTask sync(String url); - /** - * �步请求 - * @return �步HTTP任务 - */ - SyncHttpTask sync(); - + /** + * �步请求 + * + * @return �步HTTP任务 + */ + SyncHttpTask sync(); + /** * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 - * 从 v1.0.2 开始支��消�步请求 + * 从 v1.0.2 开始支��消�步请求 + * * @param tag 标签 * @return 被�消的任务数� */ int cancel(String tag); - /** - * @since 1.0.2 - * �消所有HTTP任务,包括�步和异步 - */ - void cancelAll(); + /** + * @since 1.0.2 + * �消所有HTTP任务,包括�步和异步 + */ + void cancelAll(); /** * OkHttp 原生请求 (该请求��过 预处�器) + * * @param request 请求 * @return Call */ Call request(Request request); - + /** * Websocket(该请求��过 预处�器) - * @param request 请求 + * + * @param request 请求 * @param listener 监�器 * @return */ WebSocket webSocket(Request request, WebSocketListener listener); - + /** * 获�任务执行器 + * * @return TaskExecutor */ TaskExecutor getExecutor(); - + /** * HTTP 构建器 + * * @return HTTP 构建器 */ - static Builder builder() { - return new Builder(); - } - + static Builder builder() { + return new Builder(); + } + } diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 4d6038d7..002fe663 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -44,273 +44,297 @@ public abstract class HttpTask> { private String requestJson; private OnCallback onProcess; private boolean pOnIO; - private long stepBytes = 0; - private double stepRate = -1; - - private Object object; - - + private long stepBytes = 0; + private double stepRate = -1; + + private Object object; + + public HttpTask(HttpClient httpClient, String url) { - this.httpClient = httpClient; - this.urlPath = url; + this.httpClient = httpClient; + this.urlPath = url; } /** * 获�请求任务的URL地� + * * @return URL地� */ public String getUrl() { - return urlPath; + return urlPath; } - + /** * 获�请求任务的标签 + * * @return 标签 */ public String getTag() { - return tag; - } - + return tag; + } + /** * 标签匹� * 判断任务标签与指定的标签是�匹�(包�指定的标签) + * * @param tag 标签 * @return 是�匹� */ public boolean isTagged(String tag) { - if (this.tag != null && tag != null) { - return this.tag.contains(tag); - } - return false; + if (this.tag != null && tag != null) { + return this.tag.contains(tag); + } + return false; } - + /** * 获�请求任务的头信� + * * @return 头信� */ public Map getHeaders() { - return headers; - } - + return headers; + } + /** * 获得被绑定的对象 + * * @return Object */ public Object getBound() { - return object; + return object; } - /** + /** * 设置在�生异常时��上抛出,设置�: * 异步请求�以在异常回调内�获异常,�步请求在返回结果中找到该异常 + * * @return HttpTask 实例 */ public C nothrow() { - this.nothrow = true; - return (C) this; + this.nothrow = true; + return (C) this; } - + /** * 为请求任务添加标签 + * * @param tag 标签 * @return HttpTask 实例 */ public C setTag(String tag) { - this.tag = tag; - return (C) this; + this.tag = tag; + return (C) this; } /** * 下一个回调在IO线程执行 + * * @return HttpTask 实例 */ public C nextOnIO() { - nextOnIO = true; - return (C) this; + nextOnIO = true; + return (C) this; } - + /** * 绑定一个对象 + * * @return HttpTask 实例 */ public C bind(Object object) { - this.object = object; - return (C) this; + this.object = object; + return (C) this; } - - /** + + /** * 添加请求头 - * @param name 请求头� + * + * @param name 请求头� * @param value 请求头值 * @return HttpTask 实例 */ - public C addHeader(String name, String value) { - if (name != null && value != null) { - if (headers == null) { + public C addHeader(String name, String value) { + if (name != null && value != null) { + if (headers == null) { headers = new HashMap<>(); } headers.put(name, value); - } + } return (C) this; } /** * 添加请求头 + * * @param headers 请求头集� * @return HttpTask 实例 */ public C addHeader(Map headers) { - if (headers != null) { - if (this.headers == null) { - this.headers = new HashMap<>(); + if (headers != null) { + if (this.headers == null) { + this.headers = new HashMap<>(); } this.headers.putAll(headers); - } + } return (C) this; } - + /** * 设置Range头信� * 表示接收报文体时跳过的字节数,用于断点续传 + * * @param rangeStart 表示从 rangeStart 个字节处开始接收,通常是已�下载的字节数,�上次的断点) * @return HttpTask 实例 */ public C setRange(long rangeStart) { - return addHeader("Range", "bytes=" + rangeStart + "-"); + return addHeader("Range", "bytes=" + rangeStart + "-"); } - + /** * 设置Range头信� * 设置接收报文体时接收的范围,用于分�下载 + * * @param rangeStart 表示从 rangeStart 个字节处开始接收 - * @param rangeEnd 表示接收到 rangeEnd 个字节处 + * @param rangeEnd 表示接收到 rangeEnd 个字节处 * @return HttpTask 实例 */ public C setRange(long rangeStart, long rangeEnd) { - return addHeader("Range", "bytes=" + rangeStart + "-" + rangeEnd); - } - - /** - * 设置报文体��进度回调 - * @param onProcess 进度回调函数 - * @return HttpTask 实例 - */ - public C setOnProcess(OnCallback onProcess) { - this.onProcess = onProcess; - pOnIO = nextOnIO; - nextOnIO = false; - return (C) this; - } - - /** - * 设置进度回调的步进字节,默认 8K(8192) - * 表示�接收 stepBytes 个字节,执行一次进度回调 - * @param stepBytes 步进字节 - * @return HttpTask 实例 - */ - public C setStepBytes(long stepBytes) { - this.stepBytes = stepBytes; - return (C) this; - } - - /** - * 设置进度回调的步进比例 - * 表示�接收 stepRate 比例,执行一次进度回调 - * @param stepRate 步进比例 - * @return HttpTask 实例 - */ - public C setStepRate(double stepRate) { - this.stepRate = stepRate; - return (C) this; - } - + return addHeader("Range", "bytes=" + rangeStart + "-" + rangeEnd); + } + + /** + * 设置报文体��进度回调 + * + * @param onProcess 进度回调函数 + * @return HttpTask 实例 + */ + public C setOnProcess(OnCallback onProcess) { + this.onProcess = onProcess; + pOnIO = nextOnIO; + nextOnIO = false; + return (C) this; + } + + /** + * 设置进度回调的步进字节,默认 8K(8192) + * 表示�接收 stepBytes 个字节,执行一次进度回调 + * + * @param stepBytes 步进字节 + * @return HttpTask 实例 + */ + public C setStepBytes(long stepBytes) { + this.stepBytes = stepBytes; + return (C) this; + } + + /** + * 设置进度回调的步进比例 + * 表示�接收 stepRate 比例,执行一次进度回调 + * + * @param stepRate 步进比例 + * @return HttpTask 实例 + */ + public C setStepRate(double stepRate) { + this.stepRate = stepRate; + return (C) this; + } + /** * 路径�数:替�URL里的{name} - * @param name �数� + * + * @param name �数� * @param value �数值 * @return HttpTask 实例 **/ public C addPathParam(String name, Object value) { - if (name != null && value != null) { - if (pathParams == null) { - pathParams = new HashMap<>(); - } - pathParams.put(name, value.toString()); - } + if (name != null && value != null) { + if (pathParams == null) { + pathParams = new HashMap<>(); + } + pathParams.put(name, value.toString()); + } return (C) this; } /** * 路径�数:替�URL里的{name} + * * @param params �数集� * @return HttpTask 实例 **/ public C addPathParam(Map params) { - addParams(params,this.pathParams); + addParams(params, this.pathParams); return (C) this; } /** * URL�数:拼接在URL�的�数 - * @param name �数� + * + * @param name �数� * @param value �数值 * @return HttpTask 实例 **/ public C addUrlParam(String name, Object value) { - if (name != null && value != null) { - if (urlParams == null) { - urlParams = new HashMap<>(); - } - urlParams.put(name, value.toString()); - } + if (name != null && value != null) { + if (urlParams == null) { + urlParams = new HashMap<>(); + } + urlParams.put(name, value.toString()); + } return (C) this; } /** * URL�数:拼接在URL�的�数 + * * @param params �数集� * @return HttpTask 实例 **/ public C addUrlParam(Map params) { - addParams(params,this.urlParams); + addParams(params, this.urlParams); return (C) this; } /** * Body�数:放在Body里的�数 - * @param name �数� + * + * @param name �数� * @param value �数值 * @return HttpTask 实例 **/ public C addBodyParam(String name, Object value) { - if (name != null && value != null) { - if (bodyParams == null) { - bodyParams = new HashMap<>(); - } - bodyParams.put(name, value.toString()); - } + if (name != null && value != null) { + if (bodyParams == null) { + bodyParams = new HashMap<>(); + } + bodyParams.put(name, value.toString()); + } return (C) this; } /** * Body�数:放在Body里的�数 + * * @param params �数集� * @return HttpTask 实例 **/ public C addBodyParam(Map params) { - addParams(params,this.bodyParams); + addParams(params, this.bodyParams); return (C) this; } - private void addParams(Map params,Map addParam){ + + /** + * 批�添加�数 + * + * @param params + * @param addParam + */ + private void addParams(Map params, Map addParam) { if (params != null) { if (addParam == null) { addParam = new HashMap<>(); } -// params.forEach((String name, Object value) -> { -// if (name != null && value != null) { -// addParam.put(name, value.toString()); -// } -// }); for (Map.Entry stringEntry : params.entrySet()) { if (stringEntry.getKey() != null && stringEntry.getValue() != null) { addParam.put(stringEntry.getKey(), stringEntry.getValue().toString()); @@ -318,32 +342,35 @@ private void addParams(Map params,Map addParam){ } } } + /** * Json�数:请求体为Json,支�多层结构 - * @param name JSON键� + * + * @param name JSON键� * @param value JSON键值 * @return HttpTask 实例 */ public C addJsonParam(String name, Object value) { - if (name != null && value != null) { - if (jsonParams == null) { - jsonParams = new HashMap<>(); - } - jsonParams.put(name, value); - } + if (name != null && value != null) { + if (jsonParams == null) { + jsonParams = new HashMap<>(); + } + jsonParams.put(name, value); + } return (C) this; } /** * Json�数:请求体为Json,�支��层Json * 若请求json为多层结构,请使用setRequestJson方法 + * * @param params JSON键值集� * @return HttpTask 实例 */ public C addJsonParam(Map params) { - if (params != null) { + if (params != null) { if (jsonParams == null) { - jsonParams = new HashMap<>(); + jsonParams = new HashMap<>(); } jsonParams.putAll(params); } @@ -352,6 +379,7 @@ public C addJsonParam(Map params) { /** * 设置 json 请求体 + * * @param json JSON字符串 或 Java对象(将�� 对象的get方法�列化为 json 字符串) * @return HttpTask 实例 **/ @@ -361,26 +389,28 @@ public C setRequestJson(Object json) { /** * 请求体为json - * @param json JSON字符串 或 Java对象,将跟� bean的get方法�列化程 json 字符串 + * + * @param json JSON字符串 或 Java对象,将跟� bean的get方法�列化程 json 字符串 * @param dateFormat �列化json时对日期类型字段的处�格� * @return HttpTask 实例 **/ public C setRequestJson(Object json, String dateFormat) { if (json != null) { - if (json instanceof String) { - requestJson = json.toString(); - } else if (dateFormat != null) { - requestJson = JSON.toJSONStringWithDateFormat(json, dateFormat); - } else { - requestJson = JSON.toJSONString(json); - } + if (json instanceof String) { + requestJson = json.toString(); + } else if (dateFormat != null) { + requestJson = JSON.toJSONStringWithDateFormat(json, dateFormat); + } else { + requestJson = JSON.toJSONString(json); + } } return (C) this; } - + /** * 添加文件�数 - * @param name �数� + * + * @param name �数� * @param filePath 文件路径 * @return HttpTask 实例 */ @@ -390,6 +420,7 @@ public C addFileParam(String name, String filePath) { /** * 添加文件�数 + * * @param name �数� * @param file 文件 * @return HttpTask 实例 @@ -408,57 +439,61 @@ public C addFileParam(String name, File file) { /** * 添加文件�数 - * @param name �数� - * @param type 文件类型: 如 png�jpg�jpeg 等 + * + * @param name �数� + * @param type 文件类型: 如 png�jpg�jpeg 等 * @param inputStream 文件输入� * @return HttpTask 实例 */ public C addFileParam(String name, String type, InputStream inputStream) { - return addFileParam(name, type, null, inputStream); + return addFileParam(name, type, null, inputStream); } - + /** * 添加文件�数 - * @param name �数� - * @param type 文件类型: 如 png�jpg�jpeg 等 + * + * @param name �数� + * @param type 文件类型: 如 png�jpg�jpeg 等 * @param fileName 文件� - * @param input 文件输入� + * @param input 文件输入� * @return HttpTask 实例 */ public C addFileParam(String name, String type, String fileName, InputStream input) { if (name != null && input != null) { byte[] content = null; - try { - Buffer buffer = new Buffer(); - content = buffer.readFrom(input).readByteArray(); - buffer.close(); - } catch (IOException e) { - throw new HttpException("读�文件输入�出错:", e); - } finally { - Util.closeQuietly(input); - } + try { + Buffer buffer = new Buffer(); + content = buffer.readFrom(input).readByteArray(); + buffer.close(); + } catch (IOException e) { + throw new HttpException("读�文件输入�出错:", e); + } finally { + Util.closeQuietly(input); + } addFileParam(name, type, fileName, content); } return (C) this; } - + /** * 添加文件�数 - * @param name �数� - * @param type 文件类型: 如 png�jpg�jpeg 等 + * + * @param name �数� + * @param type 文件类型: 如 png�jpg�jpeg 等 * @param content 文件内容 * @return HttpTask 实例 */ public C addFileParam(String name, String type, byte[] content) { - return addFileParam(name, type, null, content); + return addFileParam(name, type, null, content); } - + /** * 添加文件�数 - * @param name �数� - * @param type 文件类型: 如 png�jpg�jpeg 等 + * + * @param name �数� + * @param type 文件类型: 如 png�jpg�jpeg 等 * @param fileName 文件� - * @param content 文件内容 + * @param content 文件内容 * @return HttpTask 实例 */ public C addFileParam(String name, String type, String fileName, byte[] content) { @@ -472,75 +507,75 @@ public C addFileParam(String name, String type, String fileName, byte[] content) } class FilePara { - - String type; - String fileName; - byte[] content; - File file; - - FilePara(String type, String fileName, byte[] content) { - this.type = type; - this.fileName = fileName; - this.content = content; - } - - FilePara(String type, String fileName, File file) { - this.type = type; - this.fileName = fileName; - this.file = file; - } - - } - + + String type; + String fileName; + byte[] content; + File file; + + FilePara(String type, String fileName, byte[] content) { + this.type = type; + this.fileName = fileName; + this.content = content; + } + + FilePara(String type, String fileName, File file) { + this.type = type; + this.fileName = fileName; + this.file = file; + } + + } + protected Call prepareCall(String method) { // OkHttpClient client = new OkHttpClient.Builder() // .connectTimeout(connectTimeout,timeUnit) // 设置连接超时时间 // .readTimeout(readTimeout,timeUnit) // 设置读�超时时间 // .build(); - assertNotConflict("GET".equals(method)); + assertNotConflict("GET".equals(method)); Request.Builder builder = new Request.Builder() - .url(buildUrlPath()); + .url(buildUrlPath()); buildHeaders(builder); - RequestBody reqBody = null; - if (!"GET".equals(method)) { - reqBody = buildRequestBody(); - if (onProcess != null) { - long contentLength = contentLength(reqBody); - if (stepRate > 0 && stepRate <= 1) { - stepBytes = (long) (contentLength * stepRate); - } - if (stepBytes <= 0) { - stepBytes = Process.DEFAULT_STEP_BYTES; - } - reqBody = new ProcessRequestBody(reqBody, onProcess, - httpClient.getExecutor().getExecutor(pOnIO), - contentLength, stepBytes); - } - } - switch (method) { - case "GET": - builder.get().build(); - break; - case "POST": - builder.post(reqBody); - break; - case "PUT": - builder.put(reqBody); - break; - case "DELETE": - builder.delete(reqBody); - break; + RequestBody reqBody = null; + if (!"GET".equals(method)) { + reqBody = buildRequestBody(); + if (onProcess != null) { + long contentLength = contentLength(reqBody); + if (stepRate > 0 && stepRate <= 1) { + stepBytes = (long) (contentLength * stepRate); + } + if (stepBytes <= 0) { + stepBytes = Process.DEFAULT_STEP_BYTES; + } + reqBody = new ProcessRequestBody(reqBody, onProcess, + httpClient.getExecutor().getExecutor(pOnIO), + contentLength, stepBytes); + } + } + switch (method) { + case "GET": + builder.get().build(); + break; + case "POST": + builder.post(reqBody); + break; + case "PUT": + builder.put(reqBody); + break; + case "DELETE": + builder.delete(reqBody); + break; } - return httpClient.request(builder.build()); - } + return httpClient.request(builder.build()); + } - private long contentLength(RequestBody reqBody) { - try { - return reqBody.contentLength(); - } catch (IOException e) { - throw new HttpException("无法获�请求体长度", e); - } - } + private long contentLength(RequestBody reqBody) { + try { + return reqBody.contentLength(); + } catch (IOException e) { + throw new HttpException("无法获�请求体长度", e); + } + } private void buildHeaders(Request.Builder builder) { if (headers != null) { @@ -553,19 +588,19 @@ private void buildHeaders(Request.Builder builder) { } } - protected State toState(IOException e, boolean sync) { - if (e instanceof SocketTimeoutException) { - return State.TIMEOUT; - } else if (e instanceof UnknownHostException || e instanceof ConnectException) { - return State.NETWORK_ERROR; - } - String msg = e.getMessage(); - if (msg != null && ("Canceled".equals(msg) || e instanceof SocketException + protected State toState(IOException e, boolean sync) { + if (e instanceof SocketTimeoutException) { + return State.TIMEOUT; + } else if (e instanceof UnknownHostException || e instanceof ConnectException) { + return State.NETWORK_ERROR; + } + String msg = e.getMessage(); + if (msg != null && ("Canceled".equals(msg) || e instanceof SocketException && msg.startsWith("Socket operation on nonsocket"))) { - return State.CANCELED; - } - return State.EXCEPTION; - } + return State.CANCELED; + } + return State.EXCEPTION; + } private RequestBody buildRequestBody() { if (jsonParams != null) { @@ -584,11 +619,11 @@ private RequestBody buildRequestBody() { MediaType type = httpClient.getMediaType(file.type); RequestBody bodyPart; if (file.file != null) { - bodyPart = RequestBody.create(type, file.file); + bodyPart = RequestBody.create(type, file.file); } else { - bodyPart = RequestBody.create(type, file.content); + bodyPart = RequestBody.create(type, file.content); } - builder.addFormDataPart(name, file.fileName, bodyPart); + builder.addFormDataPart(name, file.fileName, bodyPart); } return builder.build(); } else if (requestJson != null) { @@ -596,17 +631,17 @@ private RequestBody buildRequestBody() { } else { FormBody.Builder builder = new FormBody.Builder(); if (bodyParams != null) { - for (String name : bodyParams.keySet()) { - String value = bodyParams.get(name); - builder.add(name, value); - } + for (String name : bodyParams.keySet()) { + String value = bodyParams.get(name); + builder.add(name, value); + } } return builder.build(); } } private String buildUrlPath() { - String url = urlPath; + String url = urlPath; if (url == null || url.trim().isEmpty()) { throw new HttpException("url �能为空�"); } diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 5a1ad119..62d48d69 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -24,130 +24,130 @@ public class HttpClient implements HTTP { - // OkHttpClient - final OkHttpClient client; - // 根URL - final String baseUrl; - // 媒体类型 - final Map mediaTypes; - // 执行器 - final TaskExecutor executor; - // 预处�器 - final Preprocessor[] preprocessors; - // �有标签的任务 - final List tagTasks; - - - private HttpClient(Builder builder) { - this.client = builder.client; - this.baseUrl = builder.baseUrl; - this.mediaTypes = builder.mediaTypes; - this.executor = new TaskExecutor(client.dispatcher().executorService(), - builder.mainExecutor, builder.downloadListener, - builder.responseListener, builder.exceptionListener, - builder.completeListener); - this.preprocessors = builder.preprocessors.toArray(new Preprocessor[0]); - this.tagTasks = Collections.synchronizedList(new LinkedList<>()); - } - - @Override + // OkHttpClient + final OkHttpClient client; + // 根URL + final String baseUrl; + // 媒体类型 + final Map mediaTypes; + // 执行器 + final TaskExecutor executor; + // 预处�器 + final Preprocessor[] preprocessors; + // �有标签的任务 + final List tagTasks; + + + private HttpClient(Builder builder) { + this.client = builder.client; + this.baseUrl = builder.baseUrl; + this.mediaTypes = builder.mediaTypes; + this.executor = new TaskExecutor(client.dispatcher().executorService(), + builder.mainExecutor, builder.downloadListener, + builder.responseListener, builder.exceptionListener, + builder.completeListener); + this.preprocessors = builder.preprocessors.toArray(new Preprocessor[0]); + this.tagTasks = Collections.synchronizedList(new LinkedList<>()); + } + + @Override public AsyncHttpTask async(String url) { return new AsyncHttpTask(this, urlPath(url)); } - @Override + @Override public SyncHttpTask sync(String url) { return new SyncHttpTask(this, urlPath(url)); } - @Override - public AsyncHttpTask async() { - return new AsyncHttpTask(this, urlPath()); - } - - @Override - public SyncHttpTask sync() { - return new SyncHttpTask(this, urlPath()); - } - - @Override - public int cancel(String tag) { - if (tag == null) { - return 0; - } - int count = 0; - Iterator it = tagTasks.iterator(); - while (it.hasNext()) { - TagTask tagCall = it.next(); - // ��任务的标签包�指定的Tag就会被�消 - if (tagCall.tag.contains(tag)) { - if (tagCall.canceler.cancel()) { - count++; - } - it.remove(); - } - } - return count; - } - - @Override - public void cancelAll() { - client.dispatcher().cancelAll(); - } - - @Override - public Call request(Request request) { - - return client.newCall(request); + @Override + public AsyncHttpTask async() { + return new AsyncHttpTask(this, urlPath()); + } + + @Override + public SyncHttpTask sync() { + return new SyncHttpTask(this, urlPath()); + } + + @Override + public int cancel(String tag) { + if (tag == null) { + return 0; + } + int count = 0; + Iterator it = tagTasks.iterator(); + while (it.hasNext()) { + TagTask tagCall = it.next(); + // ��任务的标签包�指定的Tag就会被�消 + if (tagCall.tag.contains(tag)) { + if (tagCall.canceler.cancel()) { + count++; + } + it.remove(); + } + } + return count; + } + + @Override + public void cancelAll() { + client.dispatcher().cancelAll(); + } + + @Override + public Call request(Request request) { + + return client.newCall(request); } - - @Override - public WebSocket webSocket(Request request, WebSocketListener listener) { - return client.newWebSocket(request, listener); - } - - public OkHttpClient getOkClient() { - return client; - } - - public int totalTimeoutMillis() { - return client.connectTimeoutMillis() + client.writeTimeoutMillis() + client.readTimeoutMillis(); - } - - public int getTagTaskCount() { - return tagTasks.size(); - } - - public void addTagTask(String tag, Cancelable canceler, HttpTask task) { - tagTasks.add(new TagTask(tag, canceler, task)); - } - - public void removeTagTask(HttpTask task) { - Iterator it = tagTasks.iterator(); - while (it.hasNext()) { - TagTask tagCall = it.next(); - if (tagCall.task == task) { - it.remove(); - break; - } - } - } - - static class TagTask { - - String tag; - Cancelable canceler; - HttpTask task; - - public TagTask(String tag, Cancelable canceler, HttpTask task) { - this.tag = tag; - this.canceler = canceler; - this.task = task; - } - - } - - public MediaType getMediaType(String type) { + + @Override + public WebSocket webSocket(Request request, WebSocketListener listener) { + return client.newWebSocket(request, listener); + } + + public OkHttpClient getOkClient() { + return client; + } + + public int totalTimeoutMillis() { + return client.connectTimeoutMillis() + client.writeTimeoutMillis() + client.readTimeoutMillis(); + } + + public int getTagTaskCount() { + return tagTasks.size(); + } + + public void addTagTask(String tag, Cancelable canceler, HttpTask task) { + tagTasks.add(new TagTask(tag, canceler, task)); + } + + public void removeTagTask(HttpTask task) { + Iterator it = tagTasks.iterator(); + while (it.hasNext()) { + TagTask tagCall = it.next(); + if (tagCall.task == task) { + it.remove(); + break; + } + } + } + + static class TagTask { + + String tag; + Cancelable canceler; + HttpTask task; + + public TagTask(String tag, Cancelable canceler, HttpTask task) { + this.tag = tag; + this.canceler = canceler; + this.task = task; + } + + } + + public MediaType getMediaType(String type) { String mediaType = mediaTypes.get(type); if (mediaType != null) { return MediaType.parse(mediaType); @@ -155,327 +155,325 @@ public MediaType getMediaType(String type) { return MediaType.parse("application/octet-stream"); } - public TaskExecutor getExecutor() { - return executor; - } - - public void preprocess(HttpTask> httpTask, Runnable request) { - if (preprocessors.length > 0) { - RealPreChain process = new RealPreChain(preprocessors, - httpTask, request); - preprocessors[0].doProcess(process); - } else { - request.run(); - } + public TaskExecutor getExecutor() { + return executor; + } + + public void preprocess(HttpTask> httpTask, Runnable request) { + if (preprocessors.length > 0) { + RealPreChain process = new RealPreChain(preprocessors, + httpTask, request); + preprocessors[0].doProcess(process); + } else { + request.run(); + } } - + /** * 串行预处�器 + * * @author Troy.Zhou */ static class SerialPreprocessor implements Preprocessor { - - // 预处�器 - private Preprocessor preprocessor; - // 待处�的任务队列 - private Queue pendings; - // 是�有任务正在执行 - private boolean running = false; - - SerialPreprocessor(Preprocessor preprocessor) { - this.preprocessor = preprocessor; - this.pendings = new LinkedList<>(); - } - - @Override - public void doProcess(PreChain process) { - boolean should = true; - synchronized (this) { - if (running) { - pendings.add(process); - should = false; - } else { - running = true; - } - } - if (should) { - preprocessor.doProcess(process); - } - } - - public void afterProcess() { - PreChain process = null; - synchronized (this) { - if (pendings.size() > 0) { - process = pendings.poll(); - } else { - running = false; - } - } - if (process != null) { - preprocessor.doProcess(process); - } - } - + + // 预处�器 + private Preprocessor preprocessor; + // 待处�的任务队列 + private Queue pendings; + // 是�有任务正在执行 + private boolean running = false; + + SerialPreprocessor(Preprocessor preprocessor) { + this.preprocessor = preprocessor; + this.pendings = new LinkedList<>(); + } + + @Override + public void doProcess(PreChain process) { + boolean should = true; + synchronized (this) { + if (running) { + pendings.add(process); + should = false; + } else { + running = true; + } + } + if (should) { + preprocessor.doProcess(process); + } + } + + public void afterProcess() { + PreChain process = null; + synchronized (this) { + if (pendings.size() > 0) { + process = pendings.poll(); + } else { + running = false; + } + } + if (process != null) { + preprocessor.doProcess(process); + } + } + } - - + + class RealPreChain implements Preprocessor.PreChain { - private int index; - - private Preprocessor[] preprocessors; - - private HttpTask httpTask; - - private Runnable request; - - public RealPreChain(Preprocessor[] preprocessors, - HttpTask httpTask, - Runnable request) { - this.index = 1; - this.preprocessors = preprocessors; - this.httpTask = httpTask; - this.request = request; - } - - @Override - public HttpTask getTask() { - return httpTask; - } - - @Override - public HTTP getHttp() { - return HttpClient.this; - } - - @Override - public void proceed() { - if (index > 0) { - Preprocessor last = preprocessors[index - 1]; - if (last instanceof SerialPreprocessor) { - ((SerialPreprocessor) last).afterProcess(); - } - } - if (index < preprocessors.length) { - preprocessors[index++].doProcess(this); - } else { - request.run(); - } - } + private int index; + + private Preprocessor[] preprocessors; + + private HttpTask httpTask; + + private Runnable request; + + public RealPreChain(Preprocessor[] preprocessors, + HttpTask httpTask, + Runnable request) { + this.index = 1; + this.preprocessors = preprocessors; + this.httpTask = httpTask; + this.request = request; + } + + @Override + public HttpTask getTask() { + return httpTask; + } + + @Override + public HTTP getHttp() { + return HttpClient.this; + } + + @Override + public void proceed() { + if (index > 0) { + Preprocessor last = preprocessors[index - 1]; + if (last instanceof SerialPreprocessor) { + ((SerialPreprocessor) last).afterProcess(); + } + } + if (index < preprocessors.length) { + preprocessors[index++].doProcess(this); + } else { + request.run(); + } + } + + } + + public Builder newBuilder() { + return new Builder(this); + } + + private String urlPath(String urlPath) { + boolean isFullPath = urlPath.startsWith("https://") + || urlPath.startsWith("http://"); + if (isFullPath) { + return urlPath; + } + if (baseUrl != null) { + return baseUrl + urlPath; + } + throw new HttpException("在设置 BaseUrl 之�,您必须使用全路径URL�起请求,当�URL为:" + urlPath); + } + + private String urlPath() { + if (baseUrl != null) { + return baseUrl; + } + throw new HttpException("在设置 BaseUrl 之�,您必须使用全路径URL�起请求,当�URL为:" + baseUrl); + } + + + public static class Builder { + + private OkHttpClient client; + + private String baseUrl; + + private Map mediaTypes; + + private Configurator configurator; + + private Executor mainExecutor; + + private List preprocessors; + + private DownListener downloadListener; + + private TaskListener responseListener; + + private TaskListener exceptionListener; + + private TaskListener completeListener; + + public Builder() { + mediaTypes = new HashMap<>(); + mediaTypes.put("*", "application/octet-stream"); + mediaTypes.put("png", "image/png"); + mediaTypes.put("jpg", "image/jpeg"); + mediaTypes.put("jpeg", "image/jpeg"); + mediaTypes.put("wav", "audio/wav"); + mediaTypes.put("mp3", "audio/mp3"); + mediaTypes.put("mp4", "video/mpeg4"); + mediaTypes.put("txt", "text/plain"); + mediaTypes.put("xls", "application/x-xls"); + mediaTypes.put("xml", "text/xml"); + mediaTypes.put("apk", "application/vnd.android.package-archive"); + mediaTypes.put("doc", "application/msword"); + mediaTypes.put("pdf", "application/pdf"); + mediaTypes.put("html", "text/html"); + preprocessors = new ArrayList<>(); + } + + private Builder(HttpClient hc) { + this.client = hc.client; + this.baseUrl = hc.baseUrl; + this.mediaTypes = hc.mediaTypes; + this.preprocessors = new ArrayList<>(); + Collections.addAll(this.preprocessors, hc.preprocessors); + } + + /** + * �置 OkHttpClient + * + * @param configurator �置器 + * @return Builder + */ + public Builder config(Configurator configurator) { + this.configurator = configurator; + return this; + } + + /** + * 设置 baseUrl + * + * @param baseUrl 全局URL�缀 + * @return Builder + */ + public Builder baseUrl(String baseUrl) { + this.baseUrl = baseUrl; + return this; + } + + /** + * �置媒体类型 + * + * @param mediaTypes 媒体类型 + * @return Builder + */ + public Builder mediaTypes(Map mediaTypes) { + this.mediaTypes.putAll(mediaTypes); + return this; + } + + /** + * �置媒体类型 + * + * @param key 媒体类型KEY + * @param value 媒体类型VALUE + * @return Builder + */ + public Builder mediaTypes(String key, String value) { + this.mediaTypes.put(key, value); + return this; + } + + /** + * 设置回调执行器,例如实现切�线程功能,�对异步请求有效 + * + * @param executor 回调执行器 + * @return Builder + */ + public Builder callbackExecutor(Executor executor) { + this.mainExecutor = executor; + return this; + } + + /** + * 添加�并行处�请求任务的预处�器 + * + * @param preprocessor 预处�器 + * @return Builder + */ + public Builder addPreprocessor(Preprocessor preprocessor) { + preprocessors.add(preprocessor); + return this; + } + + /** + * 添加预处�器 + * + * @param preprocessor 预处�器 + * @return Builder + */ + public Builder addSerialPreprocessor(Preprocessor preprocessor) { + preprocessors.add(new SerialPreprocessor(preprocessor)); + return this; + } + + /** + * 设置全局�应监� + * + * @param listener 监�器 + * @return Builder + */ + public Builder responseListener(TaskListener listener) { + this.responseListener = listener; + return this; + } + + /** + * 设置全局异常监� + * + * @param listener 监�器 + * @return Builder + */ + public Builder exceptionListener(TaskListener listener) { + this.exceptionListener = listener; + return this; + } + + /** + * 设置全局完�监� + * + * @param listener 监�器 + * @return Builder + */ + public Builder completeListener(TaskListener listener) { + this.completeListener = listener; + return this; + } + + /** + * 设置下载监�器 + * + * @param listener 监�器 + * @return Builder + */ + public Builder downloadListener(DownListener listener) { + this.downloadListener = listener; + return this; + } + + + public HTTP build() { + if (configurator != null || client == null) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + if (configurator != null) { + configurator.config(builder); + } + client = builder.build(); + } + return new HttpClient(this); + } } - - public Builder newBuilder() { - return new Builder(this); - } - - private String urlPath(String urlPath) { - boolean isFullPath = urlPath.startsWith("https://") - || urlPath.startsWith("http://"); - if (isFullPath) { - return urlPath; - } - if (baseUrl != null) { - return baseUrl + urlPath; - } - throw new HttpException("在设置 BaseUrl 之�,您必须使用全路径URL�起请求,当�URL为:" + urlPath); - } - - private String urlPath() { - if (baseUrl != null) { - return baseUrl; - } - throw new HttpException("在设置 BaseUrl 之�,您必须使用全路径URL�起请求,当�URL为:" + baseUrl); - } - - - public static class Builder { - - private OkHttpClient client; - - private String baseUrl; - - private Map mediaTypes; - - private Configurator configurator; - - private Executor mainExecutor; - - private List preprocessors; - - private DownListener downloadListener; - - private TaskListener responseListener; - - private TaskListener exceptionListener; - - private TaskListener completeListener; - - public Builder() { - mediaTypes = new HashMap<>(); - mediaTypes.put("*", "application/octet-stream"); - mediaTypes.put("png", "image/png"); - mediaTypes.put("jpg", "image/jpeg"); - mediaTypes.put("jpeg", "image/jpeg"); - mediaTypes.put("wav", "audio/wav"); - mediaTypes.put("mp3", "audio/mp3"); - mediaTypes.put("mp4", "video/mpeg4"); - mediaTypes.put("txt", "text/plain"); - mediaTypes.put("xls", "application/x-xls"); - mediaTypes.put("xml", "text/xml"); - mediaTypes.put("apk", "application/vnd.android.package-archive"); - mediaTypes.put("doc", "application/msword"); - mediaTypes.put("pdf", "application/pdf"); - mediaTypes.put("html", "text/html"); - preprocessors = new ArrayList<>(); - } - - private Builder(HttpClient hc) { - this.client = hc.client; - this.baseUrl = hc.baseUrl; - this.mediaTypes = hc.mediaTypes; - this.preprocessors = new ArrayList<>(); - Collections.addAll(this.preprocessors, hc.preprocessors); - } - - /** - * �置 OkHttpClient - * @param configurator �置器 - * @return Builder - */ - public Builder config(Configurator configurator) { - this.configurator = configurator; - return this; - } - - /** - * 设置 baseUrl - * @param baseUrl 全局URL�缀 - * @return Builder - */ - public Builder baseUrl(String baseUrl) { - this.baseUrl = baseUrl; - return this; - } - - /** - * �置媒体类型 - * @param mediaTypes 媒体类型 - * @return Builder - */ - public Builder mediaTypes(Map mediaTypes) { - this.mediaTypes.putAll(mediaTypes); - return this; - } - - /** - * �置媒体类型 - * @param key 媒体类型KEY - * @param value 媒体类型VALUE - * @return Builder - */ - public Builder mediaTypes(String key, String value) { - this.mediaTypes.put(key, value); - return this; - } - - /** - * 设置回调执行器,例如实现切�线程功能,�对异步请求有效 - * @param executor 回调执行器 - * @return Builder - */ - public Builder callbackExecutor(Executor executor) { - this.mainExecutor = executor; - return this; - } - - /** - * 添加�并行处�请求任务的预处�器 - * @param preprocessor 预处�器 - * @return Builder - */ - public Builder addPreprocessor(Preprocessor preprocessor) { - preprocessors.add(preprocessor); - return this; - } - - /** - * 添加预处�器 - * @param preprocessor 预处�器 - * @return Builder - */ - public Builder addSerialPreprocessor(Preprocessor preprocessor) { - preprocessors.add(new SerialPreprocessor(preprocessor)); - return this; - } - - /** - * 设置全局�应监� - * @param listener 监�器 - * @return Builder - */ - public Builder responseListener(TaskListener listener) { - this.responseListener = listener; - return this; - } - - /** - * 设置全局异常监� - * @param listener 监�器 - * @return Builder - */ - public Builder exceptionListener(TaskListener listener) { - this.exceptionListener = listener; - return this; - } - - /** - * 设置全局完�监� - * @param listener 监�器 - * @return Builder - */ - public Builder completeListener(TaskListener listener) { - this.completeListener = listener; - return this; - } - - /** - * 设置下载监�器 - * @param listener 监�器 - * @return Builder - */ - public Builder downloadListener(DownListener listener) { - this.downloadListener = listener; - return this; - } - - /** - * 设置超时时间 - * @param connectTimeout 连接时间 - * @param readTimeout 读�时间 - * @param timeUnit - * @return - */ - public Builder builderTimeOut(long connectTimeout, long readTimeout, TimeUnit timeUnit) { - this.client= new OkHttpClient.Builder() - .connectTimeout(connectTimeout,timeUnit) // 设置连接超时时间 - .readTimeout(readTimeout,timeUnit) // 设置读�超时时间 - .build(); - return this; - } - - public HTTP build() { - if (configurator != null || client == null) { - OkHttpClient.Builder builder = new OkHttpClient.Builder(); - if (configurator != null) { - configurator.config(builder); - } - client = builder.build(); - } - return new HttpClient(this); - } - - } - + } From dbef39a0ad6d3dec0a98e1c74e64ea897b34d7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 10 Apr 2020 14:14:51 +0800 Subject: [PATCH 094/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=20build=20url=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 7e251013..59b57d93 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -474,7 +474,7 @@ public C addFileParam(String name, String type, String fileName, byte[] content) return (C) this; } - class FilePara { + static class FilePara { String type; String fileName; @@ -624,27 +624,31 @@ private String buildUrlPath() { throw new HttpException("url 里有 pathParameter 没有设置,你必须先调用 addPathParam 为其设置�"); } if (urlParams != null) { - if (url.contains("?")) { - if (!url.endsWith("?")) { - url = url.trim(); - if (url.lastIndexOf("=") < url.lastIndexOf("?") + 2) { - throw new HttpException("url 格�错误,'?' �没有�现 '='"); - } - if (!url.endsWith("&")) { - url += "&"; - } - } - } else { - url += "?"; - } - for (String name : urlParams.keySet()) { - url += name + "=" + urlParams.get(name) + "&"; - } - url = url.substring(0, url.length() - 1); + url = buildUrl(url.trim()); } return url; } + private String buildUrl(String url) { + StringBuilder sb = new StringBuilder(url); + if (url.contains("?")) { + if (!url.endsWith("?")) { + if (url.lastIndexOf("=") < url.lastIndexOf("?") + 2) { + throw new HttpException("url 格�错误,'?' �没有�现 '='"); + } + if (!url.endsWith("&")) { + sb.append('&'); + } + } + } else { + sb.append('?'); + } + for (String name : urlParams.keySet()) { + sb.append(name).append('=').append(urlParams.get(name)).append('&'); + } + sb.delete(sb.length() - 1, sb.length()); + return sb.toString(); + } protected void assertNotConflict(boolean isGetRequest) { if (isGetRequest) { From 76ff2e19f24e0fce9c93551879141d8193a985c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 10 Apr 2020 15:52:25 +0800 Subject: [PATCH 095/924] V1.0.2 ^_^ --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d4e29534..1270a5f8 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ > OkHttps �常轻�,自身代�仅 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) -### 当�文档版本[1.0.1] +### 当�文档版本[1.0.2] ### API文档:[https://apidoc.gitee.com/ejlchina-zhxu/okhttps](https://apidoc.gitee.com/ejlchina-zhxu/okhttps) ## 目录 @@ -71,12 +71,12 @@ com.ejlchina okhttps - 1.0.1 + 1.0.2 ``` ### Gradle -`implementation 'com.ejlchina:okhttps:1.0.1'` +`implementation 'com.ejlchina:okhttps:1.0.2'` ## 使用说明 @@ -91,8 +91,10 @@ HTTP http = HTTP.builder().build(); * `async(String url)` 开始一个异步HTTP任务 * `sync(String url)` 开始一个�步HTTP任务 +* `async()` 开始一个异步HTTP任务,使用该方法必须在构建时设置 BaseUrl +* `sync()` 开始一个�步HTTP任务,使用该方法必须在构建时设置 BaseUrl * `cancel(String tag)` 根�标签批��消HTTP任务 -* `cancelAll()` �消所有任务(since v1.0.2) +* `cancelAll()` �消所有任务   为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(请��[5.1 设置 BaseUrl](#51-设置-baseurl)): From cc6127c2aeb8a174f961ebcec42c1cd411839a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 10 Apr 2020 16:14:46 +0800 Subject: [PATCH 096/924] V1.0.2 ^_^ --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1270a5f8..2d99971c 100644 --- a/README.md +++ b/README.md @@ -462,7 +462,7 @@ HTTP http = HTTP.builder()   全局回调监�与拦截器的异�: > * 拦截器�以添加多个,全局回调监�分三�,��最多添加一个 > * 拦截器处的�时机在请求�和�应�,全局回调监��在�应�,并且晚于拦截器 -> * 全局回调监��以阻断(return false)�个请求的具体回调,而拦截器�能 +> * 全局回调监��以 **阻断**(return false)�个请求的具体回调,而拦截器�能 #### 6.7 全局下载监� @@ -750,7 +750,7 @@ try {   这�传统的异常处�方�,当然�以解决问题,但是 OkHttps 有更佳的方案: ```java -// 使用 nothrow 方法告诉 OkHttps �生异常时��直接�外抛出 +// 方法 nothrow() 让异常�直接抛出 HttpResult result = http.sync("/users/1").nothrow().get(); // 判断执行状� switch (result.getState()) { @@ -766,7 +766,7 @@ switch (result.getState()) { break; } // 还�以获得具体的异常信� -Exception error = result.getError(); +IOException error = result.getError(); ``` #### 10.2 异步请求的异常 From 741d214c654d93d2bd186df7d7d4f83d21ecbec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Fri, 10 Apr 2020 23:35:08 +0800 Subject: [PATCH 097/924] =?UTF-8?q?=E6=B2=A1=E6=9C=89=E5=85=B3=E8=81=94=20?= =?UTF-8?q?httpTask=20=E7=9A=84=20HttpResult=20=E6=89=A7=E8=A1=8C=20Downlo?= =?UTF-8?q?ad=20=E7=9A=84=E6=97=B6=E5=80=99=20=E4=B8=8D=E8=B5=B0=20?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E4=B8=8B=E8=BD=BD=E7=9B=91=E5=90=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/internal/TaskExecutor.java | 224 +++++++++--------- 1 file changed, 112 insertions(+), 112 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 66ed7a85..cb8c5d1c 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -1,112 +1,112 @@ -package com.ejlchina.okhttps.internal; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; - -import com.ejlchina.okhttps.DownListener; -import com.ejlchina.okhttps.Download; -import com.ejlchina.okhttps.HttpResult; -import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.OnCallback; -import com.ejlchina.okhttps.TaskListener; -import com.ejlchina.okhttps.HttpResult.State; - -public class TaskExecutor { - - private Executor ioExecutor; - private Executor mainExecutor; - private DownListener downloadListener; - private TaskListener responseListener; - private TaskListener exceptionListener; - private TaskListener completeListener; - - public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, - TaskListener responseListener, TaskListener exceptionListener, - TaskListener completeListener) { - this.ioExecutor = ioExecutor; - this.mainExecutor = mainExecutor; - this.downloadListener = downloadListener; - this.responseListener = responseListener; - this.exceptionListener = exceptionListener; - this.completeListener = completeListener; - } - - public Executor getExecutor(boolean onIoThread) { - if (onIoThread || mainExecutor == null) { - return ioExecutor; - } - return mainExecutor; - } - - public Download download(HttpTask httpTask, File file, InputStream input, long skipBytes) { - Download download = new Download(file, input, this, skipBytes); - if (downloadListener != null) { - downloadListener.listen(httpTask, download); - } - return download; - } - - public void execute(Runnable command, boolean onIoThread) { - Executor executor = ioExecutor; - if (mainExecutor != null && !onIoThread) { - executor = mainExecutor; - } - executor.execute(command); - } - - public void executeOnResponse(HttpTask task, OnCallback onResponse, HttpResult result, boolean onIoThread) { - if (responseListener != null) { - execute(() -> { - if (responseListener.listen(task, result) && onResponse != null) { - onResponse.on(result); - } - }, onIoThread); - } else if (onResponse != null) { - execute(() -> { onResponse.on(result); }, onIoThread); - } - } - - public boolean executeOnException(HttpTask task, OnCallback onException, IOException error, boolean onIoThread) { - if (exceptionListener != null) { - execute(() -> { - if (exceptionListener.listen(task, error) && onException != null) { - onException.on(error); - } - }, onIoThread); - return true; - } else if (onException != null) { - execute(() -> { onException.on(error); }, onIoThread); - return true; - } - return false; - } - - public void executeOnComplete(HttpTask task, OnCallback onComplete, State state, boolean onIoThread) { - if (completeListener != null) { - execute(() -> { - if (completeListener.listen(task, state) && onComplete != null) { - onComplete.on(state); - } - }, onIoThread); - } else if (onComplete != null) { - execute(() -> { onComplete.on(state); }, onIoThread); - } - } - - /** - * 关闭线程池 - * @since OkHttps V1.0.2 - */ - public void shutdown() { - if (ioExecutor != null && ioExecutor instanceof ExecutorService) { - ((ExecutorService) ioExecutor).shutdown(); - } - if (mainExecutor != null && mainExecutor instanceof ExecutorService) { - ((ExecutorService) mainExecutor).shutdown(); - } - } - -} +package com.ejlchina.okhttps.internal; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; + +import com.ejlchina.okhttps.DownListener; +import com.ejlchina.okhttps.Download; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.OnCallback; +import com.ejlchina.okhttps.TaskListener; +import com.ejlchina.okhttps.HttpResult.State; + +public class TaskExecutor { + + private Executor ioExecutor; + private Executor mainExecutor; + private DownListener downloadListener; + private TaskListener responseListener; + private TaskListener exceptionListener; + private TaskListener completeListener; + + public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, + TaskListener responseListener, TaskListener exceptionListener, + TaskListener completeListener) { + this.ioExecutor = ioExecutor; + this.mainExecutor = mainExecutor; + this.downloadListener = downloadListener; + this.responseListener = responseListener; + this.exceptionListener = exceptionListener; + this.completeListener = completeListener; + } + + public Executor getExecutor(boolean onIoThread) { + if (onIoThread || mainExecutor == null) { + return ioExecutor; + } + return mainExecutor; + } + + public Download download(HttpTask httpTask, File file, InputStream input, long skipBytes) { + Download download = new Download(file, input, this, skipBytes); + if (httpTask != null && downloadListener != null) { + downloadListener.listen(httpTask, download); + } + return download; + } + + public void execute(Runnable command, boolean onIoThread) { + Executor executor = ioExecutor; + if (mainExecutor != null && !onIoThread) { + executor = mainExecutor; + } + executor.execute(command); + } + + public void executeOnResponse(HttpTask task, OnCallback onResponse, HttpResult result, boolean onIoThread) { + if (responseListener != null) { + execute(() -> { + if (responseListener.listen(task, result) && onResponse != null) { + onResponse.on(result); + } + }, onIoThread); + } else if (onResponse != null) { + execute(() -> { onResponse.on(result); }, onIoThread); + } + } + + public boolean executeOnException(HttpTask task, OnCallback onException, IOException error, boolean onIoThread) { + if (exceptionListener != null) { + execute(() -> { + if (exceptionListener.listen(task, error) && onException != null) { + onException.on(error); + } + }, onIoThread); + return true; + } else if (onException != null) { + execute(() -> { onException.on(error); }, onIoThread); + return true; + } + return false; + } + + public void executeOnComplete(HttpTask task, OnCallback onComplete, State state, boolean onIoThread) { + if (completeListener != null) { + execute(() -> { + if (completeListener.listen(task, state) && onComplete != null) { + onComplete.on(state); + } + }, onIoThread); + } else if (onComplete != null) { + execute(() -> { onComplete.on(state); }, onIoThread); + } + } + + /** + * 关闭线程池 + * @since OkHttps V1.0.2 + */ + public void shutdown() { + if (ioExecutor != null && ioExecutor instanceof ExecutorService) { + ((ExecutorService) ioExecutor).shutdown(); + } + if (mainExecutor != null && mainExecutor instanceof ExecutorService) { + ((ExecutorService) mainExecutor).shutdown(); + } + } + +} From d906c6d1bea9bf2052663dd80b68f6d7536ca5e4 Mon Sep 17 00:00:00 2001 From: zhxu_china <1573555987@qq.com> Date: Sat, 11 Apr 2020 12:01:39 +0800 Subject: [PATCH 098/924] =?UTF-8?q?!3=20=E6=9B=B4=E6=96=B0=E6=96=87?= =?UTF-8?q?=E6=A1=A3=20*=20Merge=20branch=20'master'=20of=20https://gitee.?= =?UTF-8?q?com/zhxu/okhttps.git=20*=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d99971c..21ae7bb1 100644 --- a/README.md +++ b/README.md @@ -747,7 +747,7 @@ try { // ... } ``` -  这�传统的异常处�方�,当然�以解决问题,但是 OkHttps 有更佳的方案: +  这�传统的异常处�方�,当然�以解决问题,但 OkHttps 有更佳的方案: ```java // 方法 nothrow() 让异常�直接抛出 From c0ca210c0714145236ba63bef7d853e00623b1af Mon Sep 17 00:00:00 2001 From: yejunxiang Date: Sat, 11 Apr 2020 16:22:57 +0800 Subject: [PATCH 099/924] =?UTF-8?q?!4=20=E4=BC=98=E5=8C=96HttpUtils?= =?UTF-8?q?=E5=B9=B6=E5=AE=8C=E5=96=84README=E6=96=87=E6=A1=A3=20*=20?= =?UTF-8?q?=E5=AE=8C=E5=96=84README=20*=20HttpUtils=E5=A2=9E=E5=8A=A0cance?= =?UTF-8?q?lAll()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 26 ++++++++++++------- .../java/com/ejlchina/okhttps/HttpUtils.java | 8 ++++++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 21ae7bb1..15d42ce6 100644 --- a/README.md +++ b/README.md @@ -89,12 +89,14 @@ HTTP http = HTTP.builder().build(); ```   以上代�构建了一个最简�的`HTTP`实例,它拥有以下方法: -* `async(String url)` 开始一个异步HTTP任务 -* `sync(String url)` 开始一个�步HTTP任务 -* `async()` 开始一个异步HTTP任务,使用该方法必须在构建时设置 BaseUrl -* `sync()` 开始一个�步HTTP任务,使用该方法必须在构建时设置 BaseUrl -* `cancel(String tag)` 根�标签批��消HTTP任务 -* `cancelAll()` �消所有任务 +* `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) +* `async()` 开始一个异步HTTP任务,使用该方法必须在构建时设置 BaseUrl +* `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) +* `sync()` 开始一个�步HTTP任务,使用该方法必须在构建时设置 BaseUrl +* `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) +* `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) +* `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) +* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯   为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(请��[5.1 设置 BaseUrl](#51-设置-baseurl)): @@ -482,11 +484,15 @@ HTTP http = HTTP.builder()   类`HttpUtils`共定义了四个��方法: -* `async(String url)` 开始一个异步请求 (内容通过一个`HTTP`�例实现) -* `sync(String url)` 开始一个�步请求 (内容通过一个`HTTP`�例实现) -* `cancel(String tag)` 按标签�消请求(内容通过一个`HTTP`�例实现) * `of(HTTP http)` �置`HttpUtils`�有的`HTTP`实例(�调用此方法�默认使用一个没有没有�过任何�置的`HTTP`懒实例) - +* `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) +* `async()` 开始一个异步HTTP任务,使用该方法必须在构建时设置 BaseUrl +* `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) +* `sync()` 开始一个�步HTTP任务,使用该方法必须在构建时设置 BaseUrl +* `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) +* `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) +* `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) +* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯   也就是说,能使用`http`实例的地方,都�以使用`HttpUtils`类,例如: ```java diff --git a/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/src/main/java/com/ejlchina/okhttps/HttpUtils.java index e2a8e0af..965ac96f 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -93,6 +93,14 @@ public static int cancel(String tag) { return getHttp().cancel(tag); } + /** + * @since 1.0.3 + * �消所有HTTP任务,包括�步和异步 + */ + public void cancelAll() { + getHttp().cancelAll(); + } + /** * OkHttp 原生请求 (该请求��过 预处�器) * @param request 请求 From 7d647757b795a8fc265866ed07be8d3cffd632ac Mon Sep 17 00:00:00 2001 From: Funny Date: Sat, 11 Apr 2020 16:39:31 +0800 Subject: [PATCH 100/924] =?UTF-8?q?!5=20=E6=9B=B4=E6=96=B0=20README:=20?= =?UTF-8?q?=E5=90=8E=E6=9C=9F=E5=BC=80=E5=8F=91=E8=AE=A1=E5=88=92=20*=20up?= =?UTF-8?q?date=20README.md.=20*=20update=20README.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 15d42ce6..1964fd0a 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ - [10.2 异步请求的异常](#102-异步请求的异常) + [11 回调线程自由切�(for Android)](#11-回调线程自由切�for-android) + [12 实现生命周期绑定(for Android)](#12-实现生命周期绑定for-android) ++ [�期计划(v1.1.0)](#�期计划v110) + [�系方�](#�系方�) + [�与贡献](#�与贡献) @@ -916,7 +917,11 @@ http.sync("/download/test.zip") 文档完善中,敬请期待... +## �期计划(v1.1.0) +* 简化 WebSocket 编程:�直接�� JavaBean 对象消� +* 简化 WebSocket 编程:�直接接收 JavaBean 对象消� +* 简化 WebSocket 编程:�使用 Lambda 表达�进行 WebSocket 编程 ## �系方� From b3cf9fb759c005d92e05b1bf40dfa840ec365fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 19:01:53 +0800 Subject: [PATCH 101/924] =?UTF-8?q?=E7=BA=A6=E6=9D=9F=20HttpTask.setTag=20?= =?UTF-8?q?=E5=8F=AA=E8=83=BD=E8=B0=83=E7=94=A8=E4=B8=80=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 59b57d93..ac7cadca 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -116,6 +116,10 @@ public C nothrow() { * @return HttpTask 实例 */ public C setTag(String tag) { + if (this.tag != null) { + // 标签�动�修改会带�许多��控的问题 + throw new IllegalStateException("该任务的标签已�存在,��以在更改�"); + } this.tag = tag; return (C) this; } From bdbfa126e33099ae1599b57eff48c7a6991108dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 19:05:28 +0800 Subject: [PATCH 102/924] =?UTF-8?q?fix=20bug:=20=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E6=97=B6=EF=BC=8C=E5=A6=82=E6=9E=9C=E5=8F=91?= =?UTF-8?q?=E7=94=9F=E5=BC=82=E5=B8=B8=E4=B8=8D=E6=8D=95=E8=8E=B7=E5=A4=84?= =?UTF-8?q?=E7=90=86=EF=BC=8C=E5=88=99=E6=A0=87=E7=AD=BE=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E4=B8=80=E7=9B=B4=E4=B8=8D=E4=BC=9A=E5=89=94=E9=99=A4=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/internal/AsyncHttpTask.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 49be51ff..d574bac1 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -243,13 +243,13 @@ public void onFailure(Call call, IOException error) { if (state == State.CANCELED) { httpCall.setResult(new RealHttpResult(AsyncHttpTask.this, state)); } else { + httpCall.setResult(new RealHttpResult(AsyncHttpTask.this, state, error)); TaskExecutor executor = httpClient.getExecutor(); executor.executeOnComplete(AsyncHttpTask.this, onComplete, state, cOnIO); if (!executor.executeOnException(AsyncHttpTask.this, onException, error, eOnIO) && !nothrow) { throw new HttpException(error.getMessage(), error); } - httpCall.setResult(new RealHttpResult(AsyncHttpTask.this, state, error)); } } @@ -257,9 +257,9 @@ public void onFailure(Call call, IOException error) { public void onResponse(Call call, Response response) throws IOException { TaskExecutor executor = httpClient.getExecutor(); HttpResult result = new RealHttpResult(AsyncHttpTask.this, response, executor); + httpCall.setResult(result); executor.executeOnComplete(AsyncHttpTask.this, onComplete, State.RESPONSED, cOnIO); executor.executeOnResponse(AsyncHttpTask.this, onResponse, result, rOnIO); - httpCall.setResult(result); } }); From 2f37c7dbc80b179399a0ba86ca1d799685264235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 19:18:42 +0800 Subject: [PATCH 103/924] exception message --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index ac7cadca..944540f8 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -118,7 +118,7 @@ public C nothrow() { public C setTag(String tag) { if (this.tag != null) { // 标签�动�修改会带�许多��控的问题 - throw new IllegalStateException("该任务的标签已�存在,��以在更改�"); + throw new IllegalStateException("the task's tag already exists, canot modify again!"); } this.tag = tag; return (C) this; From d434e0d912bdd0ca1e8eb2191a0703376a09c953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 19:21:33 +0800 Subject: [PATCH 104/924] exception message --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 944540f8..447913ec 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -118,7 +118,7 @@ public C nothrow() { public C setTag(String tag) { if (this.tag != null) { // 标签�动�修改会带�许多��控的问题 - throw new IllegalStateException("the task's tag already exists, canot modify again!"); + throw new IllegalStateException("the tag[" + this.tag + "] of task[" + urlPath + "] already exists, canot modify again!"); } this.tag = tag; return (C) this; From ef622d77a218fc376574d90e86ea7c8322ba1745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 19:38:02 +0800 Subject: [PATCH 105/924] V_1.0.3 ^_^ --- src/test/java/com/ejlchina/test/TagTests.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/test/java/com/ejlchina/test/TagTests.java diff --git a/src/test/java/com/ejlchina/test/TagTests.java b/src/test/java/com/ejlchina/test/TagTests.java new file mode 100644 index 00000000..f2c9f8f3 --- /dev/null +++ b/src/test/java/com/ejlchina/test/TagTests.java @@ -0,0 +1,41 @@ +package com.ejlchina.test; + +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.internal.HttpClient; +import okhttp3.OkHttpClient; +import org.junit.Test; + +import java.util.concurrent.TimeUnit; + +public class TagTests extends BaseTest { + + @Test + public void testTag() { + HttpClient http = (HttpClient) HTTP.builder() + .config((OkHttpClient.Builder builder) -> { + builder.connectTimeout(1, TimeUnit.SECONDS); + builder.writeTimeout(1, TimeUnit.SECONDS); + builder.readTimeout(1, TimeUnit.SECONDS); + }) + .build(); + + http.async("http://www.baidu.com") + .setTag("AA") + .setOnResponse((HttpResult result) -> { + throw new RuntimeException("我是一个异常"); + }) + .get(); + + println("taskCount = " + http.getTagTaskCount()); + sleep(1000); + println("taskCount = " + http.getTagTaskCount()); + sleep(1000); + println("taskCount = " + http.getTagTaskCount()); + sleep(5000); + println("taskCount = " + http.getTagTaskCount()); + + } + + +} From f2b497629c87d978683ed0f17770ab6849511d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 20:06:44 +0800 Subject: [PATCH 106/924] =?UTF-8?q?Tag=20=E5=8F=AF=E4=BB=A5=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E4=BF=AE=E6=94=B9=EF=BC=8C=E5=8F=AA=E6=98=AF=E4=B8=8D?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E4=BF=AE=E6=94=B9=E4=B8=BA=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 447913ec..82e44717 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -116,11 +116,9 @@ public C nothrow() { * @return HttpTask 实例 */ public C setTag(String tag) { - if (this.tag != null) { - // 标签�动�修改会带�许多��控的问题 - throw new IllegalStateException("the tag[" + this.tag + "] of task[" + urlPath + "] already exists, canot modify again!"); + if (tag != null) { + this.tag = tag; } - this.tag = tag; return (C) this; } From 10c4bab9e5b11d5fee75be72c6b34ec8096d5275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 20:47:58 +0800 Subject: [PATCH 107/924] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E6=B7=BB=E5=8A=A0=E6=A0=87=E7=AD=BE=E6=97=B6?= =?UTF-8?q?=20tagTask=20=E6=B2=A1=E6=9C=89=E7=A7=BB=E9=99=A4=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/internal/SyncHttpTask.java | 69 ++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index 4c3696dc..bc80b721 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -1,6 +1,7 @@ package com.ejlchina.okhttps.internal; import java.io.IOException; +import java.util.concurrent.CountDownLatch; import com.ejlchina.okhttps.Cancelable; import com.ejlchina.okhttps.HttpResult; @@ -57,19 +58,23 @@ public HttpResult delete() { static class SyncCall implements Cancelable { - final Call call; + private Call call; boolean done = false; + boolean canceled = false; - public SyncCall(Call call) { + public void setCall(Call call) { this.call = call; } @Override - public boolean cancel() { + public synchronized boolean cancel() { if (done) { return false; } - call.cancel(); + if (call != null) { + call.cancel(); + } + canceled = true; return true; } @@ -81,39 +86,39 @@ public void setDone(boolean done) { private HttpResult request(String method) { RealHttpResult result = new RealHttpResult(this, httpClient.getExecutor()); + SyncCall syncCall = new SyncCall(); + if (tag != null) { + httpClient.addTagTask(tag, syncCall, this); + } + CountDownLatch latch = new CountDownLatch(1); httpClient.preprocess(this, () -> { - Call call = prepareCall(method); - SyncCall syncCall = null; - if (tag != null) { - syncCall = new SyncCall(call); - httpClient.addTagTask(tag, syncCall, this); + synchronized (syncCall) { + if (syncCall.canceled) { + result.exception(State.CANCELED, null); + latch.countDown(); + return; + } + syncCall.setCall(prepareCall(method)); } try { - Response response = call.execute(); - if (syncCall != null) { - syncCall.setDone(true); - } - synchronized (SyncHttpTask.this) { - result.response(response); - SyncHttpTask.this.notify(); - } + result.response(syncCall.call.execute()); + syncCall.setDone(true); } catch (IOException e) { - State state = toState(e, true); - synchronized (SyncHttpTask.this) { - result.exception(state, e); - SyncHttpTask.this.notify(); - } - } + result.exception(toState(e, true), e); + } finally { + latch.countDown(); + } }); - synchronized (this) { - if (result.getState() == null) { - try { - SyncHttpTask.this.wait(); - } catch (InterruptedException e) { - throw new HttpException("等待异常", e); - } - } - } + if (result.getState() == null) { + try { + latch.await(); + } catch (InterruptedException e) { + throw new HttpException("等待异常", e); + } + } + if (tag != null) { + httpClient.removeTagTask(this); + } IOException e = result.getError(); if (e != null && result.getState() != State.CANCELED && !nothrow) { From e6de40da124083e370bed615afe5b6bc44a8399b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 20:49:09 +0800 Subject: [PATCH 108/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E5=BD=93?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E4=BB=BB=E5=8A=A1=E5=A4=84=E4=BA=8E=E9=A2=84?= =?UTF-8?q?=E5=A4=84=E7=90=86=E6=9C=9F=E9=97=B4=EF=BC=8C=E4=B9=9F=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E8=A2=AB=E6=8C=89=E6=A0=87=E7=AD=BE=E5=8F=96=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/internal/AsyncHttpTask.java | 6 +++--- .../java/com/ejlchina/okhttps/internal/RealHttpResult.java | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index d574bac1..7d8fe373 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -105,6 +105,9 @@ public HttpCall delete() { private HttpCall request(String method) { PreHttpCall call = new PreHttpCall(); + if (tag != null) { + httpClient.addTagTask(tag, call, this); + } httpClient.preprocess(this, () -> { synchronized (call) { if (!call.isCanceled()) { @@ -112,9 +115,6 @@ private HttpCall request(String method) { } } }); - if (tag != null) { - httpClient.addTagTask(tag, call, this); - } return call; } diff --git a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java index f6eab345..15c27ab2 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java +++ b/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java @@ -39,8 +39,7 @@ public RealHttpResult(HttpTask httpTask, State state, IOException error) { this.httpTask = httpTask; exception(state, error); } - - + public void exception(State state, IOException error) { this.state = state; this.error = error; From 4d2b8d5453e9f0700dea7fe3dba5c5f70af059df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 21:10:29 +0800 Subject: [PATCH 109/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E8=AF=B7=E6=B1=82=E6=A0=87=E7=AD=BE=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/internal/AsyncHttpTask.java | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 7d8fe373..a65cc445 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -105,14 +105,14 @@ public HttpCall delete() { private HttpCall request(String method) { PreHttpCall call = new PreHttpCall(); - if (tag != null) { - httpClient.addTagTask(tag, call, this); - } + registeTagTask(call); httpClient.preprocess(this, () -> { synchronized (call) { - if (!call.isCanceled()) { - call.setCall(executeCall(prepareCall(method))); - } + if (call.isCanceled()) { + removeTagTask(); + } else { + call.setCall(executeCall(prepareCall(method))); + } } }); return call; @@ -125,20 +125,10 @@ class PreHttpCall implements HttpCall { private HttpCall call; @Override - public boolean cancel() { - boolean res = true; - synchronized (this) { - if (call != null) { - res = call.cancel(); - } else { - canceled = true; - } - notify(); - } - if (tag != null && call == null) { - httpClient.removeTagTask(AsyncHttpTask.this); - } - return res; + public synchronized boolean cancel() { + canceled = call == null || call.cancel(); + notify(); + return canceled; } @Override @@ -151,9 +141,6 @@ public boolean isDone() { @Override public boolean isCanceled() { - if (call != null) { - return call.isCanceled(); - } return canceled; } @@ -227,9 +214,7 @@ public void setResult(HttpResult result) { this.result = result; notify(); } - if (tag != null) { - httpClient.removeTagTask(AsyncHttpTask.this); - } + removeTagTask(); } } From 022d3126fa50bd76d9a528f4ed2645d2baa8c3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 21:11:38 +0800 Subject: [PATCH 110/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E8=AF=B7=E6=B1=82=E6=A0=87=E7=AD=BE=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 82e44717..51443ac8 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -497,6 +497,18 @@ static class FilePara { } + protected void registeTagTask(Cancelable canceler) { + if (tag != null) { + httpClient.addTagTask(tag, canceler, this); + } + } + + protected void removeTagTask() { + if (tag != null) { + httpClient.removeTagTask(this); + } + } + protected Call prepareCall(String method) { assertNotConflict("GET".equals(method)); Request.Builder builder = new Request.Builder() From 4001ce5af28c0e8d834e12886748e0e3ce520ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 21:52:00 +0800 Subject: [PATCH 111/924] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20CountDownLatch=20?= =?UTF-8?q?=E7=AE=80=E5=8C=96=E5=90=8C=E6=AD=A5=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 13 +++++- .../okhttps/internal/AsyncHttpTask.java | 44 +++++++------------ .../okhttps/internal/SyncHttpTask.java | 19 +++----- 3 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 51443ac8..24b926a5 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -18,6 +18,8 @@ import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** @@ -31,10 +33,10 @@ public abstract class HttpTask> { protected HttpClient httpClient; protected boolean nothrow; - protected String tag; protected boolean nextOnIO = false; private String urlPath; + private String tag; private Map headers; private Map pathParams; private Map urlParams; @@ -700,4 +702,13 @@ protected void assertNotConflict(boolean isGetRequest) { } } + protected void timeoutAwait(CountDownLatch latch) { + try { + latch.await(httpClient.totalTimeoutMillis() * 10, + TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new HttpException("超时", e); + } + } + } diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index a65cc445..9fa9a686 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -1,6 +1,7 @@ package com.ejlchina.okhttps.internal; import java.io.IOException; +import java.util.concurrent.CountDownLatch; import com.ejlchina.okhttps.HttpCall; import com.ejlchina.okhttps.HttpResult; @@ -108,7 +109,7 @@ private HttpCall request(String method) { registeTagTask(call); httpClient.preprocess(this, () -> { synchronized (call) { - if (call.isCanceled()) { + if (call.canceled) { removeTagTask(); } else { call.setCall(executeCall(prepareCall(method))); @@ -123,11 +124,12 @@ class PreHttpCall implements HttpCall { private boolean canceled = false; private HttpCall call; - + final CountDownLatch latch = new CountDownLatch(1); + @Override public synchronized boolean cancel() { canceled = call == null || call.cancel(); - notify(); + latch.countDown(); return canceled; } @@ -146,33 +148,25 @@ public boolean isCanceled() { public void setCall(HttpCall call) { this.call = call; - notify(); + latch.countDown(); } @Override - public synchronized HttpResult getResult() { - if (canceled) { + public HttpResult getResult() { + timeoutAwait(latch); + if (canceled || call == null) { return new RealHttpResult(AsyncHttpTask.this, State.CANCELED); } - if (call == null) { - try { - wait(httpClient.totalTimeoutMillis() * 10); - } catch (InterruptedException e) { - throw new HttpException(e.getMessage(), e); - } - } - if (call != null) { - return call.getResult(); - } - return new RealHttpResult(AsyncHttpTask.this, State.CANCELED); + return call.getResult(); } } - + class OkHttpCall implements HttpCall { private Call call; private HttpResult result; + final CountDownLatch latch = new CountDownLatch(1); public OkHttpCall(Call call) { this.call = call; @@ -198,22 +192,16 @@ public boolean isCanceled() { } @Override - public synchronized HttpResult getResult() { + public HttpResult getResult() { if (result == null) { - try { - wait(httpClient.totalTimeoutMillis() * 10); - } catch (InterruptedException e) { - throw new HttpException(e.getMessage(), e); - } + timeoutAwait(latch); } return result; } public void setResult(HttpResult result) { - synchronized (this) { - this.result = result; - notify(); - } + this.result = result; + latch.countDown(); removeTagTask(); } diff --git a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index bc80b721..69de2342 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -9,7 +9,6 @@ import com.ejlchina.okhttps.HttpResult.State; import okhttp3.Call; -import okhttp3.Response; /** @@ -87,9 +86,8 @@ public void setDone(boolean done) { private HttpResult request(String method) { RealHttpResult result = new RealHttpResult(this, httpClient.getExecutor()); SyncCall syncCall = new SyncCall(); - if (tag != null) { - httpClient.addTagTask(tag, syncCall, this); - } + // 注册标签任务 + registeTagTask(syncCall); CountDownLatch latch = new CountDownLatch(1); httpClient.preprocess(this, () -> { synchronized (syncCall) { @@ -110,19 +108,14 @@ private HttpResult request(String method) { } }); if (result.getState() == null) { - try { - latch.await(); - } catch (InterruptedException e) { - throw new HttpException("等待异常", e); - } - } - if (tag != null) { - httpClient.removeTagTask(this); + timeoutAwait(latch); } + // 移除标签任务 + removeTagTask(); IOException e = result.getError(); if (e != null && result.getState() != State.CANCELED && !nothrow) { - throw new HttpException("请求执行异常", e); + throw new HttpException("执行异常", e); } return result; } From 2122183f5d7e9ed5a88e73ab4172874f8e5f23b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 22:59:57 +0800 Subject: [PATCH 112/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpCall.java | 10 +--- .../okhttps/internal/AsyncHttpTask.java | 58 +++++++++++-------- .../okhttps/internal/HttpException.java | 13 +++++ .../okhttps/internal/SyncHttpTask.java | 5 +- 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpCall.java b/src/main/java/com/ejlchina/okhttps/HttpCall.java index a7543a7b..11df025a 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpCall.java +++ b/src/main/java/com/ejlchina/okhttps/HttpCall.java @@ -3,16 +3,10 @@ public interface HttpCall extends Cancelable { /** - * �消 Http 请求 - * @return 是��消�功 - */ - boolean cancel(); - - /** - * @return 请求是�被�消 + * @return 是�被�消 */ boolean isCanceled(); - + /** * @return 请求是�执行完�,包��消和失败 */ diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 9fa9a686..7801409b 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -3,10 +3,7 @@ import java.io.IOException; import java.util.concurrent.CountDownLatch; -import com.ejlchina.okhttps.HttpCall; -import com.ejlchina.okhttps.HttpResult; -import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.OnCallback; +import com.ejlchina.okhttps.*; import com.ejlchina.okhttps.HttpResult.State; import okhttp3.Call; @@ -164,16 +161,16 @@ public HttpResult getResult() { class OkHttpCall implements HttpCall { - private Call call; - private HttpResult result; + final Call call; final CountDownLatch latch = new CountDownLatch(1); + private HttpResult result; public OkHttpCall(Call call) { this.call = call; } @Override - public boolean cancel() { + public synchronized boolean cancel() { if (result == null) { call.cancel(); return true; @@ -202,7 +199,6 @@ public HttpResult getResult() { public void setResult(HttpResult result) { this.result = result; latch.countDown(); - removeTagTask(); } } @@ -212,31 +208,43 @@ private HttpCall executeCall(Call call) { call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException error) { - State state = toState(error, false); - if (state == State.CANCELED) { - httpCall.setResult(new RealHttpResult(AsyncHttpTask.this, state)); - } else { - httpCall.setResult(new RealHttpResult(AsyncHttpTask.this, state, error)); - TaskExecutor executor = httpClient.getExecutor(); - executor.executeOnComplete(AsyncHttpTask.this, onComplete, state, cOnIO); - if (!executor.executeOnException(AsyncHttpTask.this, onException, error, eOnIO) - && !nothrow) { - throw new HttpException(error.getMessage(), error); - } - } + State state = toState(error, false); + HttpResult result = new RealHttpResult(AsyncHttpTask.this, state, error); + doCallback(httpCall, result, () -> { + TaskExecutor executor = httpClient.getExecutor(); + executor.executeOnComplete(AsyncHttpTask.this, onComplete, state, cOnIO); + if (!executor.executeOnException(AsyncHttpTask.this, onException, error, eOnIO) + && !nothrow) { + throw new HttpException(state, error.getMessage(), error); + } + }); } @Override public void onResponse(Call call, Response response) throws IOException { TaskExecutor executor = httpClient.getExecutor(); - HttpResult result = new RealHttpResult(AsyncHttpTask.this, response, executor); - httpCall.setResult(result); - executor.executeOnComplete(AsyncHttpTask.this, onComplete, State.RESPONSED, cOnIO); - executor.executeOnResponse(AsyncHttpTask.this, onResponse, result, rOnIO); + HttpResult result = new RealHttpResult(AsyncHttpTask.this, response, executor); + doCallback(httpCall, result, () -> { + executor.executeOnComplete(AsyncHttpTask.this, onComplete, State.RESPONSED, cOnIO); + executor.executeOnResponse(AsyncHttpTask.this, onResponse, result, rOnIO); + }); } - + }); return httpCall; } + private void doCallback(OkHttpCall httpCall, HttpResult result, Runnable runnable) { + //noinspection SynchronizationOnLocalVariableOrMethodParameter + synchronized (httpCall) { + removeTagTask(); + if (httpCall.isCanceled() || result.getState() == State.CANCELED) { + httpCall.setResult(new RealHttpResult(AsyncHttpTask.this, State.CANCELED)); + return; + } + httpCall.setResult(result); + runnable.run(); + } + } + } diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpException.java b/src/main/java/com/ejlchina/okhttps/internal/HttpException.java index c2bf3f37..f7a8a0d6 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpException.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpException.java @@ -1,5 +1,7 @@ package com.ejlchina.okhttps.internal; +import com.ejlchina.okhttps.HttpResult; + /** * Created by 周旭(Troy.Zhou) on 2016/8/30. */ @@ -10,6 +12,8 @@ public class HttpException extends RuntimeException { */ private static final long serialVersionUID = 8223484833265657324L; + private HttpResult.State state; + public HttpException(String detailMessage) { super(detailMessage); } @@ -18,4 +22,13 @@ public HttpException(String detailMessage, Throwable throwable) { super(detailMessage, throwable); } + public HttpException(HttpResult.State state, String detailMessage, Throwable throwable) { + super(detailMessage, throwable); + this.state = state; + } + + public HttpResult.State getState() { + return state; + } + } diff --git a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index 69de2342..8e5b5053 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -113,9 +113,10 @@ private HttpResult request(String method) { // 移除标签任务 removeTagTask(); IOException e = result.getError(); - if (e != null && result.getState() != State.CANCELED + State state = result.getState(); + if (e != null && state != State.CANCELED && !nothrow) { - throw new HttpException("执行异常", e); + throw new HttpException(state, "执行异常", e); } return result; } From ee9b36c5500288d1e1adc5be40a717b931b53054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 23:15:29 +0800 Subject: [PATCH 113/924] =?UTF-8?q?=E6=A0=87=E7=AD=BE=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E9=98=9F=E5=88=97=E6=96=B0=E5=A2=9E=E8=BF=87=E6=9C=9F=E6=B8=85?= =?UTF-8?q?=E7=90=86=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ejlchina/okhttps/internal/HttpClient.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 6de2ac77..4f0998dd 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -72,6 +72,8 @@ public int cancel(String tag) { count++; } it.remove(); + } else if (tagCall.isExpired()) { + it.remove(); } } return count; @@ -116,19 +118,29 @@ public void removeTagTask(HttpTask task) { it.remove(); break; } + if (tagCall.isExpired()) { + it.remove(); + } } } - static class TagTask { + class TagTask { String tag; Cancelable canceler; HttpTask task; + long createAt; - public TagTask(String tag, Cancelable canceler, HttpTask task) { + TagTask(String tag, Cancelable canceler, HttpTask task) { this.tag = tag; this.canceler = canceler; this.task = task; + this.createAt = System.nanoTime(); + } + + boolean isExpired() { + // 生存时间大于10�的总超时�值 + return System.nanoTime() - createAt > 10_000_000 * totalTimeoutMillis(); } } From 3873c418e34c24e0ff76b9b1e441f455586c6609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 23:24:08 +0800 Subject: [PATCH 114/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/internal/AsyncHttpTask.java | 26 +++++++++---------- .../okhttps/internal/SyncHttpTask.java | 14 +++------- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 7801409b..3688a9ae 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -119,9 +119,9 @@ private HttpCall request(String method) { class PreHttpCall implements HttpCall { - private boolean canceled = false; - private HttpCall call; - final CountDownLatch latch = new CountDownLatch(1); + HttpCall call; + boolean canceled = false; + CountDownLatch latch = new CountDownLatch(1); @Override public synchronized boolean cancel() { @@ -143,7 +143,7 @@ public boolean isCanceled() { return canceled; } - public void setCall(HttpCall call) { + void setCall(HttpCall call) { this.call = call; latch.countDown(); } @@ -161,11 +161,11 @@ public HttpResult getResult() { class OkHttpCall implements HttpCall { - final Call call; - final CountDownLatch latch = new CountDownLatch(1); - private HttpResult result; - - public OkHttpCall(Call call) { + Call call; + HttpResult result; + CountDownLatch latch = new CountDownLatch(1); + + OkHttpCall(Call call) { this.call = call; } @@ -196,7 +196,7 @@ public HttpResult getResult() { return result; } - public void setResult(HttpResult result) { + void setResult(HttpResult result) { this.result = result; latch.countDown(); } @@ -210,7 +210,7 @@ private HttpCall executeCall(Call call) { public void onFailure(Call call, IOException error) { State state = toState(error, false); HttpResult result = new RealHttpResult(AsyncHttpTask.this, state, error); - doCallback(httpCall, result, () -> { + onCallback(httpCall, result, () -> { TaskExecutor executor = httpClient.getExecutor(); executor.executeOnComplete(AsyncHttpTask.this, onComplete, state, cOnIO); if (!executor.executeOnException(AsyncHttpTask.this, onException, error, eOnIO) @@ -224,7 +224,7 @@ public void onFailure(Call call, IOException error) { public void onResponse(Call call, Response response) throws IOException { TaskExecutor executor = httpClient.getExecutor(); HttpResult result = new RealHttpResult(AsyncHttpTask.this, response, executor); - doCallback(httpCall, result, () -> { + onCallback(httpCall, result, () -> { executor.executeOnComplete(AsyncHttpTask.this, onComplete, State.RESPONSED, cOnIO); executor.executeOnResponse(AsyncHttpTask.this, onResponse, result, rOnIO); }); @@ -234,7 +234,7 @@ public void onResponse(Call call, Response response) throws IOException { return httpCall; } - private void doCallback(OkHttpCall httpCall, HttpResult result, Runnable runnable) { + private void onCallback(OkHttpCall httpCall, HttpResult result, Runnable runnable) { //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (httpCall) { removeTagTask(); diff --git a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index 8e5b5053..d40a7855 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -57,14 +57,10 @@ public HttpResult delete() { static class SyncCall implements Cancelable { - private Call call; + Call call; boolean done = false; boolean canceled = false; - public void setCall(Call call) { - this.call = call; - } - @Override public synchronized boolean cancel() { if (done) { @@ -77,10 +73,6 @@ public synchronized boolean cancel() { return true; } - public void setDone(boolean done) { - this.done = done; - } - } private HttpResult request(String method) { @@ -96,11 +88,11 @@ private HttpResult request(String method) { latch.countDown(); return; } - syncCall.setCall(prepareCall(method)); + syncCall.call = prepareCall(method); } try { result.response(syncCall.call.execute()); - syncCall.setDone(true); + syncCall.done = true; } catch (IOException e) { result.exception(toState(e, true), e); } finally { From 176eaa4f1287d05091db24efb905cce06070f023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 11 Apr 2020 23:34:17 +0800 Subject: [PATCH 115/924] V1.0.3 ^_^ --- src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 3688a9ae..c0d28ca7 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -234,8 +234,8 @@ public void onResponse(Call call, Response response) throws IOException { return httpCall; } + @SuppressWarnings("all") private void onCallback(OkHttpCall httpCall, HttpResult result, Runnable runnable) { - //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (httpCall) { removeTagTask(); if (httpCall.isCanceled() || result.getState() == State.CANCELED) { From bb03c83b1dd611b46252e0cab5c1ad0fc01206f2 Mon Sep 17 00:00:00 2001 From: hake <15735559897@qq.com> Date: Sun, 12 Apr 2020 09:09:51 +0800 Subject: [PATCH 116/924] =?UTF-8?q?=E5=8F=96=E6=B6=88=E6=89=80=E6=9C=89?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E4=BB=BB=E5=8A=A1=E6=97=B6=EF=BC=8C=E6=B8=85?= =?UTF-8?q?=E7=A9=BA=20tagTasks=20=E9=98=9F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/internal/HttpClient.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 4f0998dd..ff6645ef 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -82,6 +82,7 @@ public int cancel(String tag) { @Override public void cancelAll() { client.dispatcher().cancelAll(); + tagTasks.clear(); } @Override From cc6745cf6c6ee1b0d70d6e3aceba0bf14d13a306 Mon Sep 17 00:00:00 2001 From: hake <15735559897@qq.com> Date: Sun, 12 Apr 2020 09:12:11 +0800 Subject: [PATCH 117/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8F=98=E9=87=8F?= =?UTF-8?q?=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ejlchina/okhttps/internal/HttpClient.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index ff6645ef..e935d604 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -160,9 +160,9 @@ public TaskExecutor getExecutor() { public void preprocess(HttpTask> httpTask, Runnable request) { if (preprocessors.length > 0) { - RealPreChain process = new RealPreChain(preprocessors, + RealPreChain chain = new RealPreChain(preprocessors, httpTask, request); - preprocessors[0].doProcess(process); + preprocessors[0].doProcess(chain); } else { request.run(); } @@ -187,32 +187,32 @@ static class SerialPreprocessor implements Preprocessor { } @Override - public void doProcess(PreChain process) { + public void doProcess(PreChain chain) { boolean should = true; synchronized (this) { if (running) { - pendings.add(process); + pendings.add(chain); should = false; } else { running = true; } } if (should) { - preprocessor.doProcess(process); + preprocessor.doProcess(chain); } } public void afterProcess() { - PreChain process = null; + PreChain chain = null; synchronized (this) { if (pendings.size() > 0) { - process = pendings.poll(); + chain = pendings.poll(); } else { running = false; } } - if (process != null) { - preprocessor.doProcess(process); + if (chain != null) { + preprocessor.doProcess(chain); } } From 54eb8fa82a8e6297d75ca2b2cdd02637d74ef4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 12 Apr 2020 09:38:43 +0800 Subject: [PATCH 118/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=20tagTasks=20?= =?UTF-8?q?=E9=98=9F=E5=88=97=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/internal/HttpClient.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index e935d604..32553f1c 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -34,7 +34,7 @@ private HttpClient(Builder builder) { builder.responseListener, builder.exceptionListener, builder.completeListener); this.preprocessors = builder.preprocessors.toArray(new Preprocessor[0]); - this.tagTasks = Collections.synchronizedList(new LinkedList<>()); + this.tagTasks = new LinkedList<>(); } @Override @@ -58,7 +58,7 @@ public SyncHttpTask sync(String url) { } @Override - public int cancel(String tag) { + public synchronized int cancel(String tag) { if (tag == null) { return 0; } @@ -80,7 +80,7 @@ public int cancel(String tag) { } @Override - public void cancelAll() { + public synchronized void cancelAll() { client.dispatcher().cancelAll(); tagTasks.clear(); } @@ -107,11 +107,11 @@ public int getTagTaskCount() { return tagTasks.size(); } - public void addTagTask(String tag, Cancelable canceler, HttpTask task) { + public synchronized void addTagTask(String tag, Cancelable canceler, HttpTask task) { tagTasks.add(new TagTask(tag, canceler, task)); } - public void removeTagTask(HttpTask task) { + public synchronized void removeTagTask(HttpTask task) { Iterator it = tagTasks.iterator(); while (it.hasNext()) { TagTask tagCall = it.next(); From 32e491e2390b4638cae2511b357f74efa8f534b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 12 Apr 2020 09:39:29 +0800 Subject: [PATCH 119/924] V1.0.3 ^_^ --- pom.xml | 336 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 168 insertions(+), 168 deletions(-) diff --git a/pom.xml b/pom.xml index b8e2b970..1c69b7d4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,169 +1,169 @@ - - 4.0.0 - - com.ejlchina - okhttps - 1.0.2 - OkHttps - - - 1.8 - UTF-8 - https://oss.sonatype.org/content/repositories/snapshots/ - - - - - The Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - - Troy - zhou.xu@ejlchina.com - ejlchina - http://www.ejlchina.com - - - - - scm:git://gitee.com/ejlchina-zhxu/okhttps.git - scm:http://gitee.com/ejlchina-zhxu/okhttps - https://gitee.com/ejlchina-zhxu/okhttps - v1.0.2 - - - - - - junit - junit - 4.12 - test - - - - com.alibaba - fastjson - 1.2.67 - - - - com.squareup.okhttp3 - okhttp - 3.14.7 - - - - - - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - ${sonatypeOssDistMgmtSnapshotsUrl} - - - sonatype-nexus-staging - Nexus Release Repository - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - okhttps - - - - org.apache.maven.plugins - maven-release-plugin - 2.1 - - forked-path - false - -Psonatype-oss-release - - - - - org.apache.maven.plugins - maven-compiler-plugin - - ${java-version} - ${java-version} - ${project.build.sourceEncoding} - true - - - - - org.apache.maven.plugins - maven-source-plugin - 2.1.2 - - - attach-sources - - jar-no-fork - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.7 - - - attach-javadocs - - jar - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.1 - - - sign-artifacts - verify - - sign - - - - - - - - - https://gitee.com/ejlchina-zhxu/okhttps - Http工具包,�装 OkHttp,链�用法�支�异步�步��应JSON自动解�,回调线程切���置�活�支�URL��符�支�BaseUrl�外部�赖少�适用 JavaWeb 和 Android,教程全��简�易用 - - 江�一键�信�科技有�公� - http://www.ejlchina.com/ - - - https://gitee.com/ejlchina-zhxu/okhttps/issues - + + 4.0.0 + + com.ejlchina + okhttps + 1.0.3 + OkHttps + + + 1.8 + UTF-8 + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + Troy + zhou.xu@ejlchina.com + ejlchina + http://www.ejlchina.com + + + + + scm:git://gitee.com/ejlchina-zhxu/okhttps.git + scm:http://gitee.com/ejlchina-zhxu/okhttps + https://gitee.com/ejlchina-zhxu/okhttps + v1.0.3 + + + + + + junit + junit + 4.12 + test + + + + com.alibaba + fastjson + 1.2.67 + + + + com.squareup.okhttp3 + okhttp + 3.14.7 + + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + ${sonatypeOssDistMgmtSnapshotsUrl} + + + sonatype-nexus-staging + Nexus Release Repository + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + okhttps + + + + org.apache.maven.plugins + maven-release-plugin + 2.1 + + forked-path + false + -Psonatype-oss-release + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java-version} + ${java-version} + ${project.build.sourceEncoding} + true + + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.7 + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.1 + + + sign-artifacts + verify + + sign + + + + + + + + + https://gitee.com/ejlchina-zhxu/okhttps + Http工具包,�装 OkHttp,链�用法�支�异步�步��应JSON自动解�,回调线程切���置�活�支�URL��符�支�BaseUrl�外部�赖少�适用 JavaWeb 和 Android,教程全��简�易用 + + 江�一键�信�科技有�公� + http://www.ejlchina.com/ + + + https://gitee.com/ejlchina-zhxu/okhttps/issues + \ No newline at end of file From 910b19b6c83443a6004c77a10fe6371971fbad2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 12 Apr 2020 21:21:08 +0800 Subject: [PATCH 120/924] V1.0.3 ^_^ --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1964fd0a..01bf4e9a 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ > OkHttps �常轻�,自身代�仅 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) -### 当�文档版本[1.0.2] +### 当�文档版本[1.0.3] ### API文档:[https://apidoc.gitee.com/ejlchina-zhxu/okhttps](https://apidoc.gitee.com/ejlchina-zhxu/okhttps) ## 目录 @@ -72,12 +72,12 @@ com.ejlchina okhttps - 1.0.2 + 1.0.3 ``` ### Gradle -`implementation 'com.ejlchina:okhttps:1.0.2'` +`implementation 'com.ejlchina:okhttps:1.0.3'` ## 使用说明 From eabf562b90bdcdc58668fee5c3e63f9cff96c9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 13 Apr 2020 11:53:53 +0800 Subject: [PATCH 121/924] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20mockserver=20?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8C=96=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index b8e2b970..59a5257c 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,9 @@ 1.8 + 3.14.7 + 1.2.67 + 4.12 UTF-8 https://oss.sonatype.org/content/repositories/snapshots/ @@ -36,24 +39,31 @@ - - - junit - junit - 4.12 - test + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} - - - com.alibaba + + + com.alibaba fastjson - 1.2.67 + ${fastjson.version} - + com.squareup.okhttp3 - okhttp - 3.14.7 + mockwebserver + ${okhttp.version} + test + + + + junit + junit + ${junit.version} + test From 62c8027fede491a1054fb656aa8d5332aa1b1d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 13 Apr 2020 14:25:17 +0800 Subject: [PATCH 122/924] =?UTF-8?q?HttpTask=20=E6=96=B0=E5=A2=9E=20appendT?= =?UTF-8?q?ag=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 24b926a5..eb858d0c 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -124,6 +124,22 @@ public C setTag(String tag) { return (C) this; } + /** + * 为请求任务追加标签 + * @param tag 标签 + * @return HttpTask 实例 + */ + public C appendTag(String tag) { + if (tag != null) { + if (this.tag != null) { + this.tag = this.tag + "." + tag; + } else { + this.tag = tag; + } + } + return (C) this; + } + /** * 下一个回调在IO线程执行 * @return HttpTask 实例 @@ -576,7 +592,7 @@ protected State toState(IOException e, boolean sync) { } String msg = e.getMessage(); if (msg != null && ("Canceled".equals(msg) - || sync && e instanceof SocketException + || sync && e instanceof SocketException && msg.startsWith("Socket operation on nonsocket"))) { return State.CANCELED; } From cac4d90250b5d4768e5e56e643c937767c3912e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 13 Apr 2020 14:33:51 +0800 Subject: [PATCH 123/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=20TagTask=20?= =?UTF-8?q?=E9=98=9F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ejlchina/okhttps/internal/HttpClient.java | 62 +++++++++++-------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 32553f1c..e43affd4 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -58,31 +58,35 @@ public SyncHttpTask sync(String url) { } @Override - public synchronized int cancel(String tag) { + public int cancel(String tag) { if (tag == null) { return 0; } int count = 0; - Iterator it = tagTasks.iterator(); - while (it.hasNext()) { - TagTask tagCall = it.next(); - // ��任务的标签包�指定的Tag就会被�消 - if (tagCall.tag.contains(tag)) { - if (tagCall.canceler.cancel()) { - count++; + synchronized (tagTasks) { + Iterator it = tagTasks.iterator(); + while (it.hasNext()) { + TagTask tagCall = it.next(); + // ��任务的标签包�指定的Tag就会被�消 + if (tagCall.tag.contains(tag)) { + if (tagCall.canceler.cancel()) { + count++; + } + it.remove(); + } else if (tagCall.isExpired()) { + it.remove(); } - it.remove(); - } else if (tagCall.isExpired()) { - it.remove(); } } return count; } @Override - public synchronized void cancelAll() { + public void cancelAll() { client.dispatcher().cancelAll(); - tagTasks.clear(); + synchronized (tagTasks) { + tagTasks.clear(); + } } @Override @@ -107,22 +111,28 @@ public int getTagTaskCount() { return tagTasks.size(); } - public synchronized void addTagTask(String tag, Cancelable canceler, HttpTask task) { - tagTasks.add(new TagTask(tag, canceler, task)); + public TagTask addTagTask(String tag, Cancelable canceler, HttpTask task) { + TagTask tagTask = new TagTask(tag, canceler, task); + synchronized (tagTasks) { + tagTasks.add(tagTask); + } + return tagTask; } - public synchronized void removeTagTask(HttpTask task) { - Iterator it = tagTasks.iterator(); - while (it.hasNext()) { - TagTask tagCall = it.next(); - if (tagCall.task == task) { - it.remove(); - break; - } - if (tagCall.isExpired()) { - it.remove(); + public void removeTagTask(HttpTask task) { + synchronized (tagTasks) { + Iterator it = tagTasks.iterator(); + while (it.hasNext()) { + TagTask tagCall = it.next(); + if (tagCall.task == task) { + it.remove(); + break; + } + if (tagCall.isExpired()) { + it.remove(); + } } - } + } } class TagTask { From 90b848b278a1512e8dd7b6061bc52f6946411d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 13 Apr 2020 20:31:46 +0800 Subject: [PATCH 124/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=20HttpTask=EF=BC=9A?= =?UTF-8?q?=201=E3=80=81=E8=8B=A5=E8=B0=83=E7=94=A8=E5=A4=9A=E6=AC=A1=20se?= =?UTF-8?q?tTag=EF=BC=8C=E4=BB=BB=E5=8A=A1=E5=B0=86=E8=A2=AB=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=A4=9A=E4=B8=AA=E6=A0=87=E7=AD=BE=202=E3=80=81?= =?UTF-8?q?=E8=8B=A5=E6=A0=87=E7=AD=BE=E4=BB=BB=E5=8A=A1=E5=B7=B2=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=EF=BC=8C=E5=88=99=E4=BF=AE=E6=94=B9=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=B0=86=E6=9B=B4=E6=96=B0=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=203=E3=80=81=E4=BC=98=E5=8C=96=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=9AaddJsonParam(Map=20params)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 45 ++++++++++--------- .../ejlchina/okhttps/internal/HttpClient.java | 6 ++- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index eb858d0c..8f4c2453 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSON; import com.ejlchina.okhttps.HttpResult.State; import com.ejlchina.okhttps.internal.HttpClient; +import com.ejlchina.okhttps.internal.HttpClient.TagTask; import com.ejlchina.okhttps.internal.HttpException; import com.ejlchina.okhttps.internal.ProcessRequestBody; import okhttp3.*; @@ -50,6 +51,9 @@ public abstract class HttpTask> { private double stepRate = -1; private Object object; + + private TagTask tagTask; + private Cancelable canceler; public HttpTask(HttpClient httpClient, String url) { @@ -114,28 +118,18 @@ public C nothrow() { /** * 为请求任务添加标签 + * v1.0.4 之�,若 set 多次,标签将连接在一起 * @param tag 标签 * @return HttpTask 实例 */ public C setTag(String tag) { if (tag != null) { - this.tag = tag; - } - return (C) this; - } - - /** - * 为请求任务追加标签 - * @param tag 标签 - * @return HttpTask 实例 - */ - public C appendTag(String tag) { - if (tag != null) { - if (this.tag != null) { - this.tag = this.tag + "." + tag; - } else { - this.tag = tag; - } + if (this.tag != null) { + this.tag = this.tag + "." + tag; + } else { + this.tag = tag; + } + updateTagTask(); } return (C) this; } @@ -363,7 +357,7 @@ public C addJsonParam(String name, Object value) { * @param params JSON键值集� * @return HttpTask 实例 */ - public C addJsonParam(Map params) { + public C addJsonParam(Map params) { if (params != null) { if (jsonParams == null) { jsonParams = new HashMap<>(); @@ -514,13 +508,23 @@ static class FilePara { } } - + protected void registeTagTask(Cancelable canceler) { if (tag != null) { - httpClient.addTagTask(tag, canceler, this); + tagTask = httpClient.addTagTask(tag, canceler, this); } + this.canceler = canceler; } + private void updateTagTask() { + if (tagTask != null) { + tagTask.setTag(tag); + } else + if (canceler != null) { + registeTagTask(canceler); + } + } + protected void removeTagTask() { if (tag != null) { httpClient.removeTagTask(this); @@ -719,6 +723,7 @@ protected void assertNotConflict(boolean isGetRequest) { } protected void timeoutAwait(CountDownLatch latch) { + // TODO: 超时�会异常� try { latch.await(httpClient.totalTimeoutMillis() * 10, TimeUnit.MILLISECONDS); diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index e43affd4..c6902eb6 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -135,7 +135,7 @@ public void removeTagTask(HttpTask task) { } } - class TagTask { + public class TagTask { String tag; Cancelable canceler; @@ -154,6 +154,10 @@ boolean isExpired() { return System.nanoTime() - createAt > 10_000_000 * totalTimeoutMillis(); } + public void setTag(String tag) { + this.tag = tag; + } + } public MediaType getMediaType(String type) { From a2f8522cab00d86d3e7279ab1f36c58d7933719a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 13 Apr 2020 21:29:44 +0800 Subject: [PATCH 125/924] Test --- src/test/java/com/ejlchina/test/BaseTest.java | 49 +++++- .../java/com/ejlchina/test/SimpleTests.java | 142 +++++++++++------- 2 files changed, 134 insertions(+), 57 deletions(-) diff --git a/src/test/java/com/ejlchina/test/BaseTest.java b/src/test/java/com/ejlchina/test/BaseTest.java index bd96497b..e920abda 100644 --- a/src/test/java/com/ejlchina/test/BaseTest.java +++ b/src/test/java/com/ejlchina/test/BaseTest.java @@ -31,19 +31,64 @@ public static class User { private int id; private String name; - public void setId(int id) { + + public User() { + } + + public User(int id, String name) { + this.id = id; + this.name = name; + } + + public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } + + public int getId() { + return id; + } + + public String getName() { + return name; + } - @Override + @Override public String toString() { return "User [id=" + id + ", name=" + name + "]"; } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + } } diff --git a/src/test/java/com/ejlchina/test/SimpleTests.java b/src/test/java/com/ejlchina/test/SimpleTests.java index 4a6d8a34..4b0ef9ef 100644 --- a/src/test/java/com/ejlchina/test/SimpleTests.java +++ b/src/test/java/com/ejlchina/test/SimpleTests.java @@ -1,17 +1,25 @@ package com.ejlchina.test; -import com.ejlchina.okhttps.HTTP; -import com.ejlchina.okhttps.HttpResult; -import com.ejlchina.okhttps.HttpResult.Body; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import java.util.Arrays; import java.util.List; +import org.junit.Test; + +import com.alibaba.fastjson.JSON; +import com.ejlchina.okhttps.HTTP; + +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + public class SimpleTests extends BaseTest { + MockWebServer server = new MockWebServer(); + HTTP http = HTTP.builder() - .baseUrl("http://localhost:8080") + .baseUrl("http://" + server.getHostName() + ":" + server.getPort()) .build(); /** @@ -19,63 +27,87 @@ public class SimpleTests extends BaseTest { * �步请求直接得到结果,无需设置回调 */ @Test - public void testSync() { - List users = http.sync("/users") // http://localhost:8080/users + public void testSyncToBean() { + User u1 = new User(1, "Jack"); + server.enqueue(new MockResponse().setBody(JSON.toJSONString(u1))); + + User user = http.sync("/users") // http://localhost:8080/users .get() // GET请求 .getBody() // 获��应报文体 - .toList(User.class); // 得到目标数� - System.out.println("users = " + users); - } - - /** - * 异步请求示例 - * 异步请求在OnResponse里接收请求结果 - */ - @Test - public void testAsync() { - http.async("/users/1") // http://api.demo.com/users/1 - .setOnResponse((HttpResult result) -> { - // 得到目标数� - User user = result.getBody().toBean(User.class); - System.out.println("user = " + user); - }) - .get(); - sleep(5000); + .toBean(User.class); // 得到目标数� + + assertEquals(u1, user); } - - + /** - * �用 cache 示例 - */ - @Test - public void testCache() { - Body body = http.sync("/users").get().getBody() - .cache(); // �用 cache - // 使用 cache �,�以多次使用 toXXX() 方法 - System.out.println(body.toString()); - System.out.println(body.toJsonArray()); - System.out.println(body.toList(User.class)); - } - - - /** - * 获�文件大�示例 + * �步请求示例 + * �步请求直接得到结果,无需设置回调 */ @Test - public void testContentLength() { - long t = System.currentTimeMillis(); - - long size = http.sync("https://download.cocos.com/CocosDashboard/v1.0.1/CocosDashboard-v1.0.1-win32-031816.exe") - .get().getBody() - .close() // �是想获得文件大�,�消费报文体,所以直接关闭 - .getContentLength(); // 获得待下载文件的大� - - t = System.currentTimeMillis() - t; - - // 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络��) - System.out.println("耗时:" + t + " 毫秒"); - System.out.println("size = " + (size / 1024) + " KB"); + public void testSyncToList() { + User u1 = new User(1, "Jack"); + User u2 = new User(2, "Tom"); + List list = Arrays.asList(u1, u2); + server.enqueue(new MockResponse().setBody(JSON.toJSONString(list))); + + List users = http.sync("/users") // http://localhost:8080/users + .get() // GET请求 + .getBody() // 获��应报文体 + .toList(User.class); // 得到目标数� + + assertEquals(u1, users.get(0)); + assertEquals(u2, users.get(1)); } +// +// /** +// * 异步请求示例 +// * 异步请求在OnResponse里接收请求结果 +// */ +// @Test +// public void testAsync() { +// http.async("/users/1") // http://api.demo.com/users/1 +// .setOnResponse((HttpResult result) -> { +// // 得到目标数� +// User user = result.getBody().toBean(User.class); +// System.out.println("user = " + user); +// }) +// .get(); +// sleep(5000); +// } +// +// +// /** +// * �用 cache 示例 +// */ +// @Test +// public void testCache() { +// Body body = http.sync("/users").get().getBody() +// .cache(); // �用 cache +// // 使用 cache �,�以多次使用 toXXX() 方法 +// System.out.println(body.toString()); +// System.out.println(body.toJsonArray()); +// System.out.println(body.toList(User.class)); +// } +// +// +// /** +// * 获�文件大�示例 +// */ +// @Test +// public void testContentLength() { +// long t = System.currentTimeMillis(); +// +// long size = http.sync("https://download.cocos.com/CocosDashboard/v1.0.1/CocosDashboard-v1.0.1-win32-031816.exe") +// .get().getBody() +// .close() // �是想获得文件大�,�消费报文体,所以直接关闭 +// .getContentLength(); // 获得待下载文件的大� +// +// t = System.currentTimeMillis() - t; +// +// // 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络��) +// System.out.println("耗时:" + t + " 毫秒"); +// System.out.println("size = " + (size / 1024) + " KB"); +// } } From fd69399a57a074d22f0e69ac929429f25342018f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Mon, 13 Apr 2020 23:19:36 +0800 Subject: [PATCH 126/924] =?UTF-8?q?HttpTask=20=E5=AE=9E=E7=8E=B0=20Cancela?= =?UTF-8?q?ble=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 8f4c2453..2b8d6289 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -27,7 +27,7 @@ * Created by 周旭(Troy.Zhou) on 2020/3/11. */ @SuppressWarnings("unchecked") -public abstract class HttpTask> { +public abstract class HttpTask> implements Cancelable { private static final MediaType TYPE_JSON = MediaType.parse("application/json; charset=utf-8"); private static String PATH_PARAM_REGEX = "[A-Za-z0-9_\\-/]*\\{[A-Za-z0-9_\\-]+\\}[A-Za-z0-9_\\-/]*"; @@ -488,6 +488,14 @@ public C addFileParam(String name, String type, String fileName, byte[] content) return (C) this; } + @Override + public boolean cancel() { + if (canceler != null) { + return canceler.cancel(); + } + return false; + } + static class FilePara { String type; From dbcc2006623efd08ad2519fc762fcfc046b44da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Mon, 13 Apr 2020 23:21:01 +0800 Subject: [PATCH 127/924] v1.0.4 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 553da5e8..1cf524f8 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.ejlchina okhttps - 1.0.3 + 1.0.4 OkHttps @@ -35,7 +35,7 @@ scm:git://gitee.com/ejlchina-zhxu/okhttps.git scm:http://gitee.com/ejlchina-zhxu/okhttps https://gitee.com/ejlchina-zhxu/okhttps - v1.0.3 + v1.0.4 From 8cf9fe917d59b06d0b335807284836cec153d844 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 14 Apr 2020 00:14:59 +0800 Subject: [PATCH 128/924] update README.md. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 01bf4e9a..f59bdeda 100644 --- a/README.md +++ b/README.md @@ -926,6 +926,8 @@ http.sync("/download/test.zip") ## �系方� * 邮箱:zhou.xu@ejlchina.com +* 微信: + ## �与贡献 From 8653bac3f828621083cb3384737ddcaa18b268e1 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 14 Apr 2020 00:15:50 +0800 Subject: [PATCH 129/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f59bdeda..97190bb9 100644 --- a/README.md +++ b/README.md @@ -927,7 +927,7 @@ http.sync("/download/test.zip") * 邮箱:zhou.xu@ejlchina.com * 微信: - + ## �与贡献 From 78280d980b1a07229b9685d29eba5e8e51337cc5 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 14 Apr 2020 00:20:47 +0800 Subject: [PATCH 130/924] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E4=BA=A4=E6=B5=81?= =?UTF-8?q?=E7=BE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 97190bb9..c17e12cb 100644 --- a/README.md +++ b/README.md @@ -927,7 +927,9 @@ http.sync("/download/test.zip") * 邮箱:zhou.xu@ejlchina.com * 微信: - +
+ +
## �与贡献 From ecc3df352a3347d11d9e06475f38a85cc0f01b22 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 14 Apr 2020 00:21:51 +0800 Subject: [PATCH 131/924] update README.md. --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index c17e12cb..936c1532 100644 --- a/README.md +++ b/README.md @@ -926,10 +926,7 @@ http.sync("/download/test.zip") ## �系方� * 邮箱:zhou.xu@ejlchina.com -* 微信: -
- -
+* 微信: ## �与贡献 From 7b9cfa98fb8fd97d001214e204827b5cce3fe1cb Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 14 Apr 2020 00:25:34 +0800 Subject: [PATCH 132/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 936c1532..21f09e94 100644 --- a/README.md +++ b/README.md @@ -926,7 +926,7 @@ http.sync("/download/test.zip") ## �系方� * 邮箱:zhou.xu@ejlchina.com -* 微信: +* 微信: ## �与贡献 From 5fc7163580796f1cb4cbecb67f8f89d443f2686f Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 14 Apr 2020 00:30:38 +0800 Subject: [PATCH 133/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21f09e94..ff35cc34 100644 --- a/README.md +++ b/README.md @@ -925,8 +925,8 @@ http.sync("/download/test.zip") ## �系方� +* 微信: * 邮箱:zhou.xu@ejlchina.com -* 微信: ## �与贡献 From c0b95e5dcbfe23b95c43ec57e4ffd72b5b238c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 14 Apr 2020 14:04:45 +0800 Subject: [PATCH 134/924] =?UTF-8?q?=E9=A2=84=E5=A4=84=E7=90=86=E5=99=A8?= =?UTF-8?q?=E8=B6=85=E6=97=B6=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 43 +++++++++++++------ .../okhttps/internal/AsyncHttpTask.java | 11 ++++- .../okhttps/internal/HttpException.java | 5 +++ .../okhttps/internal/SyncHttpTask.java | 23 ++++++---- 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 2b8d6289..0d8c3ecb 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -1,15 +1,5 @@ package com.ejlchina.okhttps; -import com.alibaba.fastjson.JSON; -import com.ejlchina.okhttps.HttpResult.State; -import com.ejlchina.okhttps.internal.HttpClient; -import com.ejlchina.okhttps.internal.HttpClient.TagTask; -import com.ejlchina.okhttps.internal.HttpException; -import com.ejlchina.okhttps.internal.ProcessRequestBody; -import okhttp3.*; -import okhttp3.internal.Util; -import okio.Buffer; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -22,6 +12,23 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import com.alibaba.fastjson.JSON; +import com.ejlchina.okhttps.HttpResult.State; +import com.ejlchina.okhttps.internal.HttpClient; +import com.ejlchina.okhttps.internal.HttpClient.TagTask; +import com.ejlchina.okhttps.internal.HttpException; +import com.ejlchina.okhttps.internal.ProcessRequestBody; +import com.ejlchina.okhttps.internal.RealHttpResult; + +import okhttp3.Call; +import okhttp3.FormBody; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.internal.Util; +import okio.Buffer; + /** * Created by 周旭(Troy.Zhou) on 2020/3/11. @@ -730,14 +737,24 @@ protected void assertNotConflict(boolean isGetRequest) { } } - protected void timeoutAwait(CountDownLatch latch) { - // TODO: 超时�会异常� + /** + * @param latch CountDownLatch + * @return 是�未超时:false 表示已超时 + */ + protected boolean timeoutAwait(CountDownLatch latch) { try { - latch.await(httpClient.totalTimeoutMillis() * 10, + return latch.await(httpClient.totalTimeoutMillis() * 10, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new HttpException("超时", e); } } + protected HttpResult timeoutResult() { + if (nothrow) { + return new RealHttpResult(this, State.TIMEOUT); + } + throw new HttpException(State.TIMEOUT, "执行超时"); + } + } diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index c0d28ca7..d22f433b 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -150,7 +150,10 @@ void setCall(HttpCall call) { @Override public HttpResult getResult() { - timeoutAwait(latch); + if (!timeoutAwait(latch)) { + cancel(); + return timeoutResult(); + } if (canceled || call == null) { return new RealHttpResult(AsyncHttpTask.this, State.CANCELED); } @@ -191,7 +194,10 @@ public boolean isCanceled() { @Override public HttpResult getResult() { if (result == null) { - timeoutAwait(latch); + if (!timeoutAwait(latch)) { + cancel(); + return timeoutResult(); + } } return result; } @@ -202,6 +208,7 @@ void setResult(HttpResult result) { } } + private HttpCall executeCall(Call call) { OkHttpCall httpCall = new OkHttpCall(call); diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpException.java b/src/main/java/com/ejlchina/okhttps/internal/HttpException.java index f7a8a0d6..60dc6539 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpException.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpException.java @@ -27,6 +27,11 @@ public HttpException(HttpResult.State state, String detailMessage, Throwable thr this.state = state; } + public HttpException(HttpResult.State state, String detailMessage) { + super(detailMessage); + this.state = state; + } + public HttpResult.State getState() { return state; } diff --git a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index d40a7855..ef3d16a6 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -55,7 +55,7 @@ public HttpResult delete() { return request("DELETE"); } - static class SyncCall implements Cancelable { + static class SyncHttpCall implements Cancelable { Call call; boolean done = false; @@ -77,33 +77,38 @@ public synchronized boolean cancel() { private HttpResult request(String method) { RealHttpResult result = new RealHttpResult(this, httpClient.getExecutor()); - SyncCall syncCall = new SyncCall(); + SyncHttpCall httpCall = new SyncHttpCall(); // 注册标签任务 - registeTagTask(syncCall); + registeTagTask(httpCall); CountDownLatch latch = new CountDownLatch(1); httpClient.preprocess(this, () -> { - synchronized (syncCall) { - if (syncCall.canceled) { + synchronized (httpCall) { + if (httpCall.canceled) { result.exception(State.CANCELED, null); latch.countDown(); return; } - syncCall.call = prepareCall(method); + httpCall.call = prepareCall(method); } try { - result.response(syncCall.call.execute()); - syncCall.done = true; + result.response(httpCall.call.execute()); + httpCall.done = true; } catch (IOException e) { result.exception(toState(e, true), e); } finally { latch.countDown(); } }); + boolean timeout = false; if (result.getState() == null) { - timeoutAwait(latch); + timeout = !timeoutAwait(latch); } // 移除标签任务 removeTagTask(); + if (timeout) { + httpCall.cancel(); + return timeoutResult(); + } IOException e = result.getError(); State state = result.getState(); if (e != null && state != State.CANCELED From dd3e672d0e32d5116a54128dfeb7ea2f1c19599f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 14 Apr 2020 20:33:57 +0800 Subject: [PATCH 135/924] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HTTP.java | 2 +- src/main/java/com/ejlchina/okhttps/HttpTask.java | 1 + src/main/java/com/ejlchina/okhttps/HttpUtils.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HTTP.java b/src/main/java/com/ejlchina/okhttps/HTTP.java index 7b768f6f..f5c67a8e 100644 --- a/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -69,7 +69,7 @@ public interface HTTP { * * @param request 请求 * @param listener 监�器 - * @return + * @return Websocket */ WebSocket webSocket(Request request, WebSocketListener listener); diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 0d8c3ecb..3eb3932a 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -152,6 +152,7 @@ public C nextOnIO() { /** * 绑定一个对象 + * @param object 对象 * @return HttpTask 实例 */ public C bind(Object object) { diff --git a/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/src/main/java/com/ejlchina/okhttps/HttpUtils.java index 965ac96f..ae36b8f2 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -114,7 +114,7 @@ public static Call request(Request request) { * Websocket(该请求��过 预处�器) * @param request 请求 * @param listener 监�器 - * @return + * @return WebSocket */ public static WebSocket webSocket(Request request, WebSocketListener listener) { return getHttp().webSocket(request, listener); From e5da47c0e3740f5671e6b2e8b5b2a4418fb16289 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Wed, 15 Apr 2020 14:55:54 +0800 Subject: [PATCH 136/924] update README.md. --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ff35cc34..4089aa46 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,9 @@ + [10 异常处�](#10-异常处�) - [10.1 �步请求的异常](#101-�步请求的异常) - [10.2 异步请求的异常](#102-异步请求的异常) - + [11 回调线程自由切�(for Android)](#11-回调线程自由切�for-android) - + [12 实现生命周期绑定(for Android)](#12-实现生命周期绑定for-android) + + [11 请求的�消](#11-请求的�消) + + [12 回调线程自由切�(for Android)](#12-回调线程自由切�for-android) + + [13 实现生命周期绑定(for Android)](#13-实现生命周期绑定for-android) + [�期计划(v1.1.0)](#�期计划v110) + [�系方�](#�系方�) + [�与贡献](#�与贡献) @@ -72,12 +73,12 @@ com.ejlchina okhttps - 1.0.3 + 1.0.4 ``` ### Gradle -`implementation 'com.ejlchina:okhttps:1.0.3'` +`implementation 'com.ejlchina:okhttps:1.0.4'` ## 使用说明 @@ -837,8 +838,9 @@ http.async("/users/1") }) .get(); ``` +### 11 请求的�消 -### 11 回调线程自由切�(for Android) +### 12 回调线程自由切�(for Android)   在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 @@ -913,7 +915,7 @@ http.sync("/download/test.zip") }) .start(); ``` -### 12 实现生命周期绑定(for Android) +### 13 实现生命周期绑定(for Android) 文档完善中,敬请期待... From ff72a2db7f12699562a297ea7f74105196b83bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 15:13:55 +0800 Subject: [PATCH 137/924] =?UTF-8?q?read=20me:=20=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E7=9A=84=E5=8F=96=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 4089aa46..40890e12 100644 --- a/README.md +++ b/README.md @@ -840,6 +840,13 @@ http.async("/users/1") ``` ### 11 请求的�消 +  在 OkHttps 里�消�个请求有多�方�: + +* 使用`HttpCall#cancel()`�消请求(适用于异步请求) +* 使用`HttpTask#cancel()`�消请求(适用于所有请求)(since v1.0.4) +* 使用`HTTP.cancel(String tag)`批��消请求(适用于所有请求) +* 使用`HTTP.cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) + ### 12 回调线程自由切�(for Android)   在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 From 9f092750ea0b91ed47a9d872f58d448e4d48be2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 15:15:13 +0800 Subject: [PATCH 138/924] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 40890e12..25b6b71d 100644 --- a/README.md +++ b/README.md @@ -842,8 +842,8 @@ http.async("/users/1")   在 OkHttps 里�消�个请求有多�方�: -* 使用`HttpCall#cancel()`�消请求(适用于异步请求) -* 使用`HttpTask#cancel()`�消请求(适用于所有请求)(since v1.0.4) +* 使用`HttpCall#cancel()`�消�个请求(适用于异步请求) +* 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) * 使用`HTTP.cancel(String tag)`批��消请求(适用于所有请求) * 使用`HTTP.cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) From 5b02073b581037af2ed9e1aeb2afd33ea3c17c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 15:18:21 +0800 Subject: [PATCH 139/924] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 25b6b71d..a0bfae18 100644 --- a/README.md +++ b/README.md @@ -844,8 +844,8 @@ http.async("/users/1") * 使用`HttpCall#cancel()`�消�个请求(适用于异步请求) * 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) -* 使用`HTTP.cancel(String tag)`批��消请求(适用于所有请求) -* 使用`HTTP.cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) +* 使用`HTTP#cancel(String tag)`批��消请求(适用于所有请求) +* 使用`HTTP#cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) ### 12 回调线程自由切�(for Android) From 0577b4c14ea9d5770e5cf15bc6e84dd8d689b1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 15:29:50 +0800 Subject: [PATCH 140/924] readme --- README.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0bfae18..4bfb6422 100644 --- a/README.md +++ b/README.md @@ -842,11 +842,35 @@ http.async("/users/1")   在 OkHttps 里�消�个请求有多�方�: -* 使用`HttpCall#cancel()`�消�个请求(适用于异步请求) +* 使用`HttpCall#cancel()`�消�个请求(适用于异步请求,[详� 3.3 章节](#33-httpcall)) * 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) -* 使用`HTTP#cancel(String tag)`批��消请求(适用于所有请求) + +```java +HttpTask task = http.async("/users") + .setOnResponse((HttpResult result) -> { + // �应回调 + }); + +task.get(); // �起 GET 请求 + +// �消请求,并返回是��消�功 +boolean canceled = task.cancel(); +``` + +* 使用`HTTP#cancel(String tag)`批��消请求(适用于所有请求,[详�第 5 章节](#5-使用标签)) * 使用`HTTP#cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) +```java +http.async("/users") + .setOnResponse((HttpResult result) -> { + + }) + .get(); + +// �消所有请求 +http.cancelAll(); +``` + ### 12 回调线程自由切�(for Android)   在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 From db9e1c03f064bcd7eb0e6c89b95b30ef279cdd3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 15:31:45 +0800 Subject: [PATCH 141/924] readme --- README.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4bfb6422..b2234441 100644 --- a/README.md +++ b/README.md @@ -857,18 +857,11 @@ task.get(); // �起 GET 请求 boolean canceled = task.cancel(); ``` -* 使用`HTTP#cancel(String tag)`批��消请求(适用于所有请求,[详�第 5 章节](#5-使用标签)) +* 使用`HTTP#cancel(String tag)`按标签批��消请求(适用于所有请求,[详�第 5 章节](#5-使用标签)) * 使用`HTTP#cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) ```java -http.async("/users") - .setOnResponse((HttpResult result) -> { - - }) - .get(); - -// �消所有请求 -http.cancelAll(); +http.cancelAll(); // �消所有请求 ``` ### 12 回调线程自由切�(for Android) From 5156ddaccc817dddfc5fcffa2335b4021ed80139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 15:37:15 +0800 Subject: [PATCH 142/924] readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b2234441..439d6bc5 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ + [10 异常处�](#10-异常处�) - [10.1 �步请求的异常](#101-�步请求的异常) - [10.2 异步请求的异常](#102-异步请求的异常) - + [11 请求的�消](#11-请求的�消) + + [11 �消请求的4�方�](#11-�消请求的4�方�) + [12 回调线程自由切�(for Android)](#12-回调线程自由切�for-android) + [13 实现生命周期绑定(for Android)](#13-实现生命周期绑定for-android) + [�期计划(v1.1.0)](#�期计划v110) @@ -838,9 +838,9 @@ http.async("/users/1") }) .get(); ``` -### 11 请求的�消 +### 11 �消请求的4�方� -  在 OkHttps 里�消�个请求有多�方�: +  在 OkHttps 里�消请求共有 4 �方�: * 使用`HttpCall#cancel()`�消�个请求(适用于异步请求,[详� 3.3 章节](#33-httpcall)) * 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) From 7853a5019a484b0d7b2d31fa398f3f8858dc6228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 15:38:09 +0800 Subject: [PATCH 143/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 439d6bc5..796bb0a4 100644 --- a/README.md +++ b/README.md @@ -840,7 +840,7 @@ http.async("/users/1") ``` ### 11 �消请求的4�方� -  在 OkHttps 里�消请求共有 4 �方�: +  在 OkHttps 里�消请求共有 **4 �** 方�: * 使用`HttpCall#cancel()`�消�个请求(适用于异步请求,[详� 3.3 章节](#33-httpcall)) * 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) From 99c4d099feaa79fae503c5a80a77592dc45117aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 15:45:20 +0800 Subject: [PATCH 144/924] =?UTF-8?q?readme=EF=BC=9A=E7=94=9F=E5=91=BD?= =?UTF-8?q?=E5=91=A8=E6=9C=9F=E7=BB=91=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 796bb0a4..6d28a19b 100644 --- a/README.md +++ b/README.md @@ -840,7 +840,7 @@ http.async("/users/1") ``` ### 11 �消请求的4�方� -  在 OkHttps 里�消请求共有 **4 �** 方�: +  在 OkHttps 里�消请求共有 **4 �** 方��选: * 使用`HttpCall#cancel()`�消�个请求(适用于异步请求,[详� 3.3 章节](#33-httpcall)) * 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) @@ -941,6 +941,11 @@ http.sync("/download/test.zip") ``` ### 13 实现生命周期绑定(for Android) +  由于 OkHttps 并��赖于 Android,所以它并没有直接�供关于生命周期绑定的实现,但它的一些扩展机制让我们很容易就�以实现这个功能。 + + + + 文档完善中,敬请期待... ## �期计划(v1.1.0) From 56d120e654fe1401d35d4a43f0efcfa5876d80eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 15:55:26 +0800 Subject: [PATCH 145/924] readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d28a19b..367e03c0 100644 --- a/README.md +++ b/README.md @@ -941,8 +941,9 @@ http.sync("/download/test.zip") ``` ### 13 实现生命周期绑定(for Android) -  由于 OkHttps 并��赖于 Android,所以它并没有直接�供关于生命周期绑定的实现,但它的一些扩展机制让我们很容易就�以实现这个功能。 +  由于 OkHttps 并��赖于 Android,所以它并没有直接�供关于生命周期绑定的实现,但它的一些扩展机制让我们很容易就�以实现这个功能。在开始之�,我们首先��解何为生命周期绑定: +> 所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� From 7d9dacd8962324d277b844c7fd1686c68b17759d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 16:08:26 +0800 Subject: [PATCH 146/924] =?UTF-8?q?readme:=20=E7=94=9F=E5=91=BD=E5=91=A8?= =?UTF-8?q?=E6=9C=9F=E7=BB=91=E5=AE=9A=EF=BC=88for=20Android=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 367e03c0..0aa61aed 100644 --- a/README.md +++ b/README.md @@ -941,10 +941,22 @@ http.sync("/download/test.zip") ``` ### 13 实现生命周期绑定(for Android) -  由于 OkHttps 并��赖于 Android,所以它并没有直接�供关于生命周期绑定的实现,但它的一些扩展机制让我们很容易就�以实现这个功能。在开始之�,我们首先��解何为生命周期绑定: +  由于 OkHttps 并��赖于 Android,所以它并没有�供关于生命周期绑定的直接实现,但它的一些扩展机制让我们很容易就�以实现这个需求。在开始之�,我们首先��解何为生命周期绑定: > 所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� +  现在我们需�手写一个工具类,这个工具类具有生命周期绑定的功能,�设我们把它���`OkHttps`,在 androidx 的开�环境里,它的使用效果如下: + +```java +// 在 Activity 或 Fragment 内�起请求 +OkHttps.async("http://www.baidu.com") + .bind(getLifecycle()) // 绑定Activity 或 Fragment 的生命周期,getLifecycle()是Activity 或 Fragment 自带的方法 + .setOnResponse((HttpResult result) -> { + Log.i("FirstFragment", "收到请求:" + result.toString()); + }) + .get(); +``` + 文档完善中,敬请期待... From 8b02d424d5310c10a4ba5d3c67d1d78e28f1c120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 16:09:20 +0800 Subject: [PATCH 147/924] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0aa61aed..6c2887e6 100644 --- a/README.md +++ b/README.md @@ -948,9 +948,9 @@ http.sync("/download/test.zip")   现在我们需�手写一个工具类,这个工具类具有生命周期绑定的功能,�设我们把它���`OkHttps`,在 androidx 的开�环境里,它的使用效果如下: ```java -// 在 Activity 或 Fragment 内�起请求 +// 在 Activity 或 Fragment 内�起请,getLifecycle()是Activity 或 Fragment 自带的方法 OkHttps.async("http://www.baidu.com") - .bind(getLifecycle()) // 绑定Activity 或 Fragment 的生命周期,getLifecycle()是Activity 或 Fragment 自带的方法 + .bind(getLifecycle()) // 绑定Activity 或 Fragment 的生命周期 .setOnResponse((HttpResult result) -> { Log.i("FirstFragment", "收到请求:" + result.toString()); }) From c806ebb8c044a776878d7e864a3bc97be543db2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 18:11:45 +0800 Subject: [PATCH 148/924] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6c2887e6..a5a70c21 100644 --- a/README.md +++ b/README.md @@ -945,11 +945,11 @@ http.sync("/download/test.zip") > 所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� -  现在我们需�手写一个工具类,这个工具类具有生命周期绑定的功能,�设我们把它���`OkHttps`,在 androidx 的开�环境里,它的使用效果如下: +  现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在 androidx 的开�环境里,它的使用效果如下: ```java // 在 Activity 或 Fragment 内�起请,getLifecycle()是Activity 或 Fragment 自带的方法 -OkHttps.async("http://www.baidu.com") +http.async("http://www.baidu.com") .bind(getLifecycle()) // 绑定Activity 或 Fragment 的生命周期 .setOnResponse((HttpResult result) -> { Log.i("FirstFragment", "收到请求:" + result.toString()); From 16cb05f778c24bbdc5a498d426d78ac71d1245e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 19:11:36 +0800 Subject: [PATCH 149/924] readme --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a5a70c21..6bf6b4ab 100644 --- a/README.md +++ b/README.md @@ -945,17 +945,19 @@ http.sync("/download/test.zip") > 所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� -  现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在 androidx 的开�环境里,它的使用效果如下: +  现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在`androidx`的开�环境里,它的使用效果如下: ```java -// 在 Activity 或 Fragment 内�起请,getLifecycle()是Activity 或 Fragment 自带的方法 +// 在 Activity 或 Fragment 内�起请,getLifecycle() 是 Activity 或 Fragment 自带的方法 http.async("http://www.baidu.com") - .bind(getLifecycle()) // 绑定Activity 或 Fragment 的生命周期 + .bind(getLifecycle()) // 绑定生命周期 .setOnResponse((HttpResult result) -> { Log.i("FirstFragment", "收到请求:" + result.toString()); }) .get(); ``` +  上述代�中的`getLifecycle()`是`androidx`中`Activity`或`Fragment`自带的方法,而`bind()`是`HttpTask`的现有方法。在�置好`HTTP`实例�,上述代��起的请求便�以感知`Activity`或`Fragment`的生命周期。 +  那`HTTP`实例到底该如何�置呢? From 8d109beb477b40753aa7f3ca610aebe8b7825e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 19:12:00 +0800 Subject: [PATCH 150/924] radme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6bf6b4ab..e77a4135 100644 --- a/README.md +++ b/README.md @@ -957,6 +957,7 @@ http.async("http://www.baidu.com") .get(); ```   上述代�中的`getLifecycle()`是`androidx`中`Activity`或`Fragment`自带的方法,而`bind()`是`HttpTask`的现有方法。在�置好`HTTP`实例�,上述代��起的请求便�以感知`Activity`或`Fragment`的生命周期。 +   那`HTTP`实例到底该如何�置呢? From 29bfd74523c6685ba406f2a92387335ca0bbcf9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 19:23:16 +0800 Subject: [PATCH 151/924] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/README.md b/README.md index e77a4135..5482ae61 100644 --- a/README.md +++ b/README.md @@ -960,6 +960,69 @@ http.async("http://www.baidu.com")   那`HTTP`实例到底该如何�置呢? +#### 第一步:�置预处�器 + +```java +HTTP http = HTTP.builder() + ... // �略其它�置项 + .addPreprocessor((Preprocessor.PreChain chain) -> { + HttpTask task = chain.getTask(); + Object bound = task.getBound(); + // 判断 task 是�绑定了 Lifecycle 对象 + if (bound instanceof Lifecycle) { + // �新绑定一个 生命周期监视器(LCObserver),它的定义�下一步 + task.bind(new LCObserver(task, (Lifecycle) bound)); + } + chain.proceed(); + }) + ... // �略其它�置项 + .build(); +``` + +#### 第二步:定义生命周期监视器 + +```java +public class LCObserver implements LifecycleObserver { + + HttpTask task; + Lifecycle lifecycle; + + LCObserver(HttpTask task, Lifecycle lifecycle) { + this.task = task; + this.lifecycle = lifecycle; + lifecycle.addObserver(this); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + public void onStop() { + task.cancel(); // 在 ON_STOP 事件中,�消对应的 HTTP 任务 + } + + void unbind() { + lifecycle.removeObserver(this); + } + +} +``` + +#### 第三步:�置全局回调监� + +```java +HTTP http = HTTP.builder() + ... // �略其它�置项 + .completeListener((HttpTask task, HttpResult.State state) -> { + Object bound = task.getBound(); + // 判断 task 是�绑定了生命周期监视器(LCObserver)对象 + if (bound instanceof LCObserver) { + // 解绑监视器 + ((LCObserver) bound).unbind(); + } + return true; + }) + ... // �略其它�置项 + .build(); +``` + 文档完善中,敬请期待... From fdaf567d221518b1a741c37fa197175b5d35c8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 19:40:16 +0800 Subject: [PATCH 152/924] =?UTF-8?q?README=EF=BC=9AAndroid=E4=B8=AD?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E7=94=9F=E5=91=BD=E5=91=A8=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5482ae61..a7390596 100644 --- a/README.md +++ b/README.md @@ -1007,6 +1007,8 @@ public class LCObserver implements LifecycleObserver { #### 第三步:�置全局回调监� +  以上两步其实已�实现了生命周期绑定的功能,但是在请求完�之�,我们需�移除生命周期监视器(LCObserver)对象: + ```java HTTP http = HTTP.builder() ... // �略其它�置项 @@ -1023,9 +1025,12 @@ HTTP http = HTTP.builder() .build(); ``` +#### 以上三步便在Android中实现了生命周期与HTTP请求绑定的功能 + +  �常简�,懒得敲代�的�学还�以 [点这里 OkHttps.java](https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java) 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。 +  有需�的�学,�以直接下载下�使用,还�以�其上�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考[6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案)。 -文档完善中,敬请期待... ## �期计划(v1.1.0) From 2122c5cb2875be70562c3e8b4de69d50f86b2e10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 20:01:56 +0800 Subject: [PATCH 153/924] readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a7390596..0dca2155 100644 --- a/README.md +++ b/README.md @@ -970,7 +970,7 @@ HTTP http = HTTP.builder() Object bound = task.getBound(); // 判断 task 是�绑定了 Lifecycle 对象 if (bound instanceof Lifecycle) { - // �新绑定一个 生命周期监视器(LCObserver),它的定义�下一步 + // �新绑定一个 生命周期监视器(LCObserver)对象,它的定义�下一步 task.bind(new LCObserver(task, (Lifecycle) bound)); } chain.proceed(); @@ -1007,7 +1007,7 @@ public class LCObserver implements LifecycleObserver { #### 第三步:�置全局回调监� -  以上两步其实已�实现了生命周期绑定的功能,但是在请求完�之�,我们需�移除生命周期监视器(LCObserver)对象: +  以上两步其实已�实现了生命周期绑定的功能,但是在请求完�之�,我们需�在`lifecycle`中移除`LCObserver`对象: ```java HTTP http = HTTP.builder() @@ -1029,7 +1029,7 @@ HTTP http = HTTP.builder()   �常简�,懒得敲代�的�学还�以 [点这里 OkHttps.java](https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java) 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。 -  有需�的�学,�以直接下载下�使用,还�以�其上�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考[6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案)。 +  有需�的�学,�以直接下载下�使用,还�以基于它�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考[6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案)。 ## �期计划(v1.1.0) From aea6951c85cfc2f2dc4d1ef4972a100ff8a76421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 15 Apr 2020 20:05:35 +0800 Subject: [PATCH 154/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0dca2155..4713d05c 100644 --- a/README.md +++ b/README.md @@ -240,7 +240,7 @@ long size = http.sync("/download/test.zip") .close() // �是想获得文件大�,�消费报文体,所以直接关闭 .getContentLength(); // 获得待下载文件的大� -// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络��) +// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络�� System.out.println("size = " + size); ``` From 07293f4e2d4e3793d615c8020132bfc5f80c516a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 16 Apr 2020 09:12:05 +0800 Subject: [PATCH 155/924] readme --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4713d05c..2ae9958f 100644 --- a/README.md +++ b/README.md @@ -310,19 +310,25 @@ System.out.println(call.isCanceled()); // true ```java http.async("/users") //(1) - .setTag("A").get(); + .setTag("A") + .get(); http.async("/users") //(2) - .setTag("A.B").get(); + .setTag("A.B") + .get(); http.async("/users") //(3) - .setTag("B").get(); + .setTag("B") + .get(); http.async("/users") //(4) - .setTag("B.C").get(); + .setTag("B") + .setTag("C") // since v1.0.4, 标签将以追加模�添加 + .get(); http.async("/users") //(5) - .setTag("C").get(); + .setTag("C") + .get(); ```   当使用标签�,就�以按标签批�的对HTTP任务进行�消: From 54f13169289ac8f9e3798b68af8574f66366188a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 16 Apr 2020 09:19:14 +0800 Subject: [PATCH 156/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ae9958f..a0660d7a 100644 --- a/README.md +++ b/README.md @@ -954,7 +954,7 @@ http.sync("/download/test.zip")   现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在`androidx`的开�环境里,它的使用效果如下: ```java -// 在 Activity 或 Fragment 内�起请,getLifecycle() 是 Activity 或 Fragment 自带的方法 +// 在 Activity 或 Fragment 内�起请求 http.async("http://www.baidu.com") .bind(getLifecycle()) // 绑定生命周期 .setOnResponse((HttpResult result) -> { From 3b136584c6b2f4d97293a6ebdbdfcdc36f7ea9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 16 Apr 2020 09:22:14 +0800 Subject: [PATCH 157/924] readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a0660d7a..96b5bc53 100644 --- a/README.md +++ b/README.md @@ -1004,7 +1004,8 @@ public class LCObserver implements LifecycleObserver { task.cancel(); // 在 ON_STOP 事件中,�消对应的 HTTP 任务 } - void unbind() { + public void unbind() { + // 在请求完�之�移除监视器 lifecycle.removeObserver(this); } From 9b86ebedd8fda8015267c73bec66cb2143120c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 16 Apr 2020 09:23:42 +0800 Subject: [PATCH 158/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 96b5bc53..9c8de12e 100644 --- a/README.md +++ b/README.md @@ -1032,7 +1032,7 @@ HTTP http = HTTP.builder() .build(); ``` -#### 以上三步便在Android中实现了生命周期与HTTP请求绑定的功能 +**以上三步便在Android中实现了生命周期与HTTP请求绑定的功能**   �常简�,懒得敲代�的�学还�以 [点这里 OkHttps.java](https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java) 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。 From 6d46a28665923b813936d55feea880ad641d4871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 16 Apr 2020 09:26:35 +0800 Subject: [PATCH 159/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c8de12e..55245b38 100644 --- a/README.md +++ b/README.md @@ -1036,7 +1036,7 @@ HTTP http = HTTP.builder()   �常简�,懒得敲代�的�学还�以 [点这里 OkHttps.java](https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java) 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。 -  有需�的�学,�以直接下载下�使用,还�以基于它�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考[6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案)。 +  有需�的�学,�以直接下载下�使用,还�以基于它�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考[6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案),�比如扩展实现生命周期与下载事件绑定的功能,都�常简�。 ## �期计划(v1.1.0) From 0acd3a35cda92308e52904b79e5221469f6a1340 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Thu, 16 Apr 2020 10:14:45 +0800 Subject: [PATCH 160/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 55245b38..f47cc19e 100644 --- a/README.md +++ b/README.md @@ -1047,7 +1047,7 @@ HTTP http = HTTP.builder() ## �系方� -* 微信: +* 微信: * 邮箱:zhou.xu@ejlchina.com ## �与贡献 From bf1c874683189899ad8b490656e83bfefbac0dc9 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Thu, 16 Apr 2020 10:15:32 +0800 Subject: [PATCH 161/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f47cc19e..9f6d4060 100644 --- a/README.md +++ b/README.md @@ -1047,7 +1047,7 @@ HTTP http = HTTP.builder() ## �系方� -* 微信: +* 微信: * 邮箱:zhou.xu@ejlchina.com ## �与贡献 From 46bd05ed0269493bc2ddcd0361ccb9d1b1831d71 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Thu, 16 Apr 2020 10:18:52 +0800 Subject: [PATCH 162/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f6d4060..f41cd94b 100644 --- a/README.md +++ b/README.md @@ -1047,7 +1047,7 @@ HTTP http = HTTP.builder() ## �系方� -* 微信: +* 微信: * 邮箱:zhou.xu@ejlchina.com ## �与贡献 From ce8b3a671acfdf3b41b33790db1170b14429385b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Thu, 16 Apr 2020 10:23:44 +0800 Subject: [PATCH 163/924] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f41cd94b..c142298f 100644 --- a/README.md +++ b/README.md @@ -1047,7 +1047,7 @@ HTTP http = HTTP.builder() ## �系方� -* 微信: +* 微信: * 邮箱:zhou.xu@ejlchina.com ## �与贡献 From cf58ca8b4a964d0dd987af3851b53f1440a112ec Mon Sep 17 00:00:00 2001 From: ejlchina Date: Thu, 16 Apr 2020 12:19:31 +0800 Subject: [PATCH 164/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c142298f..6675dd0c 100644 --- a/README.md +++ b/README.md @@ -1047,7 +1047,7 @@ HTTP http = HTTP.builder() ## �系方� -* 微信: +* 微信: * 邮箱:zhou.xu@ejlchina.com ## �与贡献 From efe5a5b6199dac0f88ce1e7eba56cf30e901caf9 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Sat, 18 Apr 2020 10:56:34 +0800 Subject: [PATCH 165/924] update README.md. --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6675dd0c..ddaee286 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ ### Maven -``` +```xml com.ejlchina okhttps @@ -80,6 +80,18 @@ `implementation 'com.ejlchina:okhttps:1.0.4'` +安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��: + +```groovy +android { + // �略其它�置.. + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } +} +``` + ## 使用说明 ### 1 简�示例 From a8c95ae3c2305419b56d6b2085e1e9b3ba27bf90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 20 Apr 2020 09:11:37 +0800 Subject: [PATCH 166/924] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c142298f..ce55f903 100644 --- a/README.md +++ b/README.md @@ -951,7 +951,7 @@ http.sync("/download/test.zip") > 所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� -  现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在`androidx`的开�环境里,它的使用效果如下: +  现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在`Activity`或`Fragment`里,它的使用效果如下: ```java // 在 Activity 或 Fragment 内�起请求 @@ -962,7 +962,7 @@ http.async("http://www.baidu.com") }) .get(); ``` -  上述代�中的`getLifecycle()`是`androidx`中`Activity`或`Fragment`自带的方法,而`bind()`是`HttpTask`的现有方法。在�置好`HTTP`实例�,上述代��起的请求便�以感知`Activity`或`Fragment`的生命周期。 +  上述代�中的`getLifecycle()`是`Activity`或`Fragment`自带的方法,而`bind()`是`HttpTask`的现有方法。在�置好`HTTP`实例�,上述代��起的请求便�以感知`Activity`或`Fragment`的生命周期。   那`HTTP`实例到底该如何�置呢? From 2995122cd81187d8980d22d37e569ef81b8f8640 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Tue, 21 Apr 2020 20:30:00 +0800 Subject: [PATCH 167/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dcb3ddc1..bc4f67ef 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ > OkHttps �常轻�,自身代�仅 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) ### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) -### 当�文档版本[1.0.3] +### 当�文档版本[1.0.4] ### API文档:[https://apidoc.gitee.com/ejlchina-zhxu/okhttps](https://apidoc.gitee.com/ejlchina-zhxu/okhttps) ## 目录 From 34ea363e3a4d7e4d625c971a079f7b1b0cb916da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 22 Apr 2020 13:02:53 +0800 Subject: [PATCH 168/924] update readme --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bc4f67ef..3a35714f 100644 --- a/README.md +++ b/README.md @@ -311,8 +311,7 @@ System.out.println(call.isCanceled()); // true * `setTag(String tag)` 为HTTP任务添加标签 * `setRange(long rangeStart)` 设置Range头信�,用于断点续传 -* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,用于分�下载 -* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,用于分�下载 +* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,�用于分�下载 * `bind(Object object)` 绑定一个对象,�用于实现Android里的生命周期绑定 @@ -430,7 +429,7 @@ HTTP http = HTTP.builder() }) .build(); ``` -  和`Interceptor`一样,`Preprocessor`也�以添加多个。他们之�的区别如下: +  和`Interceptor`一样,`Preprocessor`也�以添加多个。他们之间的区别如下: > * 拦截器�能处��步�作,预处�器支�处�异步�作 > * 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) From b3a69a80fe817ce639734aa37d6fc633885f13bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 22 Apr 2020 20:37:42 +0800 Subject: [PATCH 169/924] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3a35714f..7004426a 100644 --- a/README.md +++ b/README.md @@ -334,7 +334,7 @@ http.async("/users") //(3) http.async("/users") //(4) .setTag("B") - .setTag("C") // since v1.0.4, 标签将以追加模�添加 + .setTag("C") // 从 v1.0.4 标签将以追加模�添加,等效于 setTag("B.C") .get(); http.async("/users") //(5) @@ -499,7 +499,7 @@ HTTP http = HTTP.builder() ### 7 使用 HttpUtils 类 -  类`HttpUtils`本是 1.x 版本里的最��的核心类,由于在 2.x 版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。 +  类`HttpUtils`本是 [�身 HttpUtils](https://gitee.com/ejlchina-zhxu/httputils) 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。   类`HttpUtils`共定义了四个��方法: From 6b8981cd1d346a1ee26b3a7ec04711902b98ef7c Mon Sep 17 00:00:00 2001 From: ejlchina Date: Thu, 23 Apr 2020 11:35:19 +0800 Subject: [PATCH 170/924] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7004426a..f8606ccd 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ > OkHttps �常轻�,自身代�仅 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) -### �世:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) +### �身:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.4] ### API文档:[https://apidoc.gitee.com/ejlchina-zhxu/okhttps](https://apidoc.gitee.com/ejlchina-zhxu/okhttps) From 09269cb9fefeeccc56707f8ba8b895d680c1a398 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Thu, 23 Apr 2020 17:05:00 +0800 Subject: [PATCH 171/924] =?UTF-8?q?update=20README.md.=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=BE=AE=E4=BF=A1=E7=BE=A4=E4=BA=8C=E7=BB=B4=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8606ccd..d9df88ee 100644 --- a/README.md +++ b/README.md @@ -1058,7 +1058,7 @@ HTTP http = HTTP.builder() ## �系方� -* 微信: +* 微信: * 邮箱:zhou.xu@ejlchina.com ## �与贡献 From 188214d94f1f32e896142e981146fda9098a99c4 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Fri, 24 Apr 2020 12:17:47 +0800 Subject: [PATCH 172/924] update README.md. --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d9df88ee..84f77c0c 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,10 @@ * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 -> OkHttps �常轻�,自身代�仅 2000 行左�,且有较高的编�质�,sonarqube 分�结果为 3A,[查看报告](https://gitee.com/ejlchina-zhxu/okhttps/quality_analyses?platform=sonar_qube) +> 1. OkHttps �常轻�(59Kb),是 Retrofit(124Kb)的一�,并且更加的开箱�用,API 也更加自然和语义化。 +> 2. OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit �� +> 3. OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。 + ### �身:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) ### 当�文档版本[1.0.4] From c8dc1284def6c8cceb3d95ebdb75735da44c6154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sun, 26 Apr 2020 17:25:18 +0800 Subject: [PATCH 173/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ejlchina/okhttps/HttpTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 3eb3932a..848df563 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -526,7 +526,7 @@ static class FilePara { } protected void registeTagTask(Cancelable canceler) { - if (tag != null) { + if (tag != null && tagTask == null) { tagTask = httpClient.addTagTask(tag, canceler, this); } this.canceler = canceler; From d1497bf3b886e7d20ada45d3c87778ed423b0de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 27 Apr 2020 11:27:57 +0800 Subject: [PATCH 174/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=EF=BC=9AHttpTask#doAddParams=20=E5=85=BC=E5=AE=B9=E4=BD=8E?= =?UTF-8?q?=E7=89=88=E6=9C=ACAndroid=EF=BC=8823=E5=8F=8A=E4=BB=A5=E4=B8=8B?= =?UTF-8?q?=EF=BC=89=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 848df563..369ecc38 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -8,6 +8,7 @@ import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -131,12 +132,12 @@ public C nothrow() { */ public C setTag(String tag) { if (tag != null) { - if (this.tag != null) { - this.tag = this.tag + "." + tag; - } else { - this.tag = tag; - } - updateTagTask(); + if (this.tag != null) { + this.tag = this.tag + "." + tag; + } else { + this.tag = tag; + } + updateTagTask(); } return (C) this; } @@ -335,11 +336,14 @@ public C addBodyParam(Map params) { private void doAddParams(Map taskParams, Map params) { if (params != null) { - params.forEach((String name, Object value) -> { + Iterator it = params.keySet().iterator(); + while (it.hasNext()) { + String name = it.next(); + Object value = params.get(name); if (name != null && value != null) { taskParams.put(name, value.toString()); } - }); + } } } @@ -527,17 +531,17 @@ static class FilePara { protected void registeTagTask(Cancelable canceler) { if (tag != null && tagTask == null) { - tagTask = httpClient.addTagTask(tag, canceler, this); + tagTask = httpClient.addTagTask(tag, canceler, this); } this.canceler = canceler; } private void updateTagTask() { if (tagTask != null) { - tagTask.setTag(tag); + tagTask.setTag(tag); } else if (canceler != null) { - registeTagTask(canceler); + registeTagTask(canceler); } } @@ -751,11 +755,11 @@ protected boolean timeoutAwait(CountDownLatch latch) { } } - protected HttpResult timeoutResult() { - if (nothrow) { - return new RealHttpResult(this, State.TIMEOUT); - } - throw new HttpException(State.TIMEOUT, "执行超时"); - } + protected HttpResult timeoutResult() { + if (nothrow) { + return new RealHttpResult(this, State.TIMEOUT); + } + throw new HttpException(State.TIMEOUT, "执行超时"); + } } From bb6953d9c77b1048b6259a26fb20eda24f7d29f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 27 Apr 2020 11:37:00 +0800 Subject: [PATCH 175/924] . --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 1cf524f8..ea76c2a4 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.ejlchina okhttps - 1.0.4 + 1.0.5 OkHttps @@ -35,7 +35,7 @@ scm:git://gitee.com/ejlchina-zhxu/okhttps.git scm:http://gitee.com/ejlchina-zhxu/okhttps https://gitee.com/ejlchina-zhxu/okhttps - v1.0.4 + v1.0.5 @@ -168,7 +168,7 @@ https://gitee.com/ejlchina-zhxu/okhttps - Http工具包,�装 OkHttp,链�用法�支�异步�步��应JSON自动解�,回调线程切���置�活�支�URL��符�支�BaseUrl�外部�赖少�适用 JavaWeb 和 Android,教程全��简�易用 + 比 Retrofit 更好用的网络框架� OkHttp3 轻��装 ,开箱�用�Java领域��端处� Http问题的新选择。 江�一键�信�科技有�公� http://www.ejlchina.com/ From de0191fbd0b175f571cb4570ec01689043d83115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 27 Apr 2020 12:22:18 +0800 Subject: [PATCH 176/924] V1.0.5 ^_^ --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 84f77c0c..bbbd68dc 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ ### �身:[HttpUtils, V2.3.0 之��命�为 OkHttps](https://gitee.com/ejlchina-zhxu/httputils) -### 当�文档版本[1.0.4] +### 当�文档版本[1.0.5] ### API文档:[https://apidoc.gitee.com/ejlchina-zhxu/okhttps](https://apidoc.gitee.com/ejlchina-zhxu/okhttps) ## 目录 @@ -76,12 +76,12 @@ com.ejlchina okhttps - 1.0.4 + 1.0.5 ``` ### Gradle -`implementation 'com.ejlchina:okhttps:1.0.4'` +`implementation 'com.ejlchina:okhttps:1.0.5'` 安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��: From 252d7aa32a78ae5ec5105da22ed7c7b2f14a343e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 27 Apr 2020 21:10:06 +0800 Subject: [PATCH 177/924] =?UTF-8?q?=E7=BD=91=E7=AB=99=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vuepress/config.js | 7 ++++++ docs/.vuepress/public/favicon.png | Bin 0 -> 3471 bytes docs/README.md | 38 ++++++++++++++++++++++++++++++ package.json | 6 +++++ 4 files changed, 51 insertions(+) create mode 100644 docs/.vuepress/config.js create mode 100644 docs/.vuepress/public/favicon.png create mode 100644 docs/README.md create mode 100644 package.json diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js new file mode 100644 index 00000000..d9a899ba --- /dev/null +++ b/docs/.vuepress/config.js @@ -0,0 +1,7 @@ +module.exports = { + title: 'OkHttps', + description: 'OkHttps 官网', + head: [ + ['link', { rel: 'icon', href: '/favicon.png' }] + ] +} \ No newline at end of file diff --git a/docs/.vuepress/public/favicon.png b/docs/.vuepress/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..74f9ae7340d0f02d65ab922cfc31f7f80d9c8b36 GIT binary patch literal 3471 zcmV;A4RG>_P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 zVoOIv00000008+zyMF)x010qNS#tmY3labT3lag+-G2N401Wd z$A26Ss2rn>P!&*wq=^+PGGf89wXxWWRAwlCGEx^;j zGQii`|Ex%R6b3{oZ#-}nFdvvuq!C)Q8F(02qP4%Jhz8^iL@7@J3xLaj;YHkZ1nmc& z0PfM+e=W}o=LW=pSPXnW&l^lZD}Y~IKx==07Iw=7h*I8UU@0&y=BfLD=aEs*>a6}7mGZ^`=KzqK;wf|PyZA%r1QrX)BSD%s)mqa|}Entq;{yUvsyJH|qdD9UCA046i8^Cp1`+x8Bx_L+` z?_0nFz|;uEw*nVv?XU0TnxzgKJPUY{a2R`mMZmPd0s}y6|0U$TvJluEQv7J(MPrl1 zO58(~@-9T?e+~&L`a19vt^MxQEtaE{^1cfE5l|sT_X3w{?XOI7okTsv{1-%l@q1v# zV21&qwZ9QK19&i`=pn$eq&+2e4>9kI7lFeZ#XbdornUcYF4oFfN_q2;Nyrh7V!MH} z;=WU20WqVgS8=~HJ_at<+JB)KbLAuR!e0S=$x&=8a7LWbS7adOJ7YcWq3w3yT&?{L zg<2~oDdn94tOdq6ioFd?kNTYw=^bLez?TpXW7bfC0id=22C}lb-BIi$;1OfPP(^*I zUyJ(-{A1ue)4(Am^Rk}>eB>xL7qMZeLaCXr)(zO_ralF}r?tPPXyX(q^G;cV{YAeA z`3`eVNIH9nnL=NRd!q2#p$-FjKO*NliW~|oH8!;>?2&aH?kV(#wDun=+86^xTKh|Z z-#Us+L)M6_vH~$HeYZQ#?E-#Yv=IiN76AWr9KX%jHc+k}awqnczP-qF$ljvwexONf ze;;r;_PMW7h;0KE_&hTk5`O2n?#){Je=7Rs2da8{-rX^F?1VkYYGja39Xocy%ATHg zd)g1!ddOnO^}2z3^SZf8wJ}h)3WezbWF^$5KpTHy*sGK`HKd}mwf5I$eK(bAV-|2f za0>7ta7VpX{%yj#eu_;09}m0++)%HTGrtF=yl)~~R&6@1eUUDxhb(kduqr1Q7Xr^A zFhI8Q)GF1+T?y*C3wit=Z+@BzJZG+vsm#*!Q;s4F+JEQ=L@Dn$WJjS*H)nkl#!$-% z{=m914ir=N#(+a3faQ5WL2PE*1aVpWh^xJaT#0>q=QCNafrr3oDiRb2jHYsdV!q6m zTMiFL_BZ#c7l_$~?)uWq^hF*KMpI5G5nwcxS5LXmacsV^JzU9jynI4RbvyvXsRES1TdP)qo=r5PkU|OJM2}; zdyimenFer-*8a}4Ti79tR^4s>CV|naPl37hS~<}M1(%fajzEU*K@+uGwDyk!(?g6K znQeaMg#ux0M>ZCOZ5_Iia2V@>(-Ds;n=b3GZU=HC>Tv`vDQ?Hdb0B2DU6u>pzG#mPWoardII?Wcvgz*MIy;j~uawtt0|21{} zo8q86=QwsI^Z}V^DfBO`{mp5$CJBtD5<=+*qouAwplI!X2)t=IJQJW~{J?Fl$9`Ik z=>$eoF`@Jj0HdX@qI$|JmfuG!uEM4_=|EY)Xlf8c+2}Ynsf5H13DOQTc21-$ zVKg-up=j;z0zR-Do>)QxxdbWk=qe8wO$|mUz<(^ik1HWQ-9g%#-5y1e7N# z)rMseBk*Mq0Dg=hzO+wJW{DPj*Vk0 zWG{4(MwSwsWYc$m!yU)tyfZGg{63xZpoDtZMuaj7_gr8sb>#F}kkW)Q;N${wM9jL@ z04}GLF~HhNwQ)*>y23W$r2!>$7Q0eydp zS0TZ{*K6flU6sawF|S@LFN@ILSO4x_DQ6e)0 z8DJ&pLAi+(pqRQg)@$Xz)obMsT;*cIcr1yHkXT+p+F3$EsRk)=9K?YNB}_TN064+& z`}-v%I$MxNn}zvA8f;MVf}xam7%VxilHzB5TlX+Wt| z8>4_#^tl$e^`b8aV6P5B(i#pv2lolA@j&aFAC`G|g$~y-8 zd-)aUn>ulM`J^^+2Fai#gwa$#C(0(LRU$6QB(b|6x$t+{jZCN%RLZL*0(NdQU zN?tt!#Add^#1riqAcEG^UGC3wI*r^MMFz^b^v$#N0M$4!TI#w939r{&_vr@C%L9f9 zt>OBPyQlq!VU~*ij6F3`H=wlkI~l4T@KVYvBMw8h$NUPd{U5adXxnw-T5~>`j9>5v zh_1sOmORkL)(<76yrtOlM(qVo*V^yMUEx5LQr?M3L?v7F??<)v=LH>b?aNw(>^Tb3 zA;4owd10~Nhn$r1Mj}D`Z7_D>@a(bzF>ilY^q(oX13nH_-3y%NIR0x_ZmqDbr1v8+ zdu_T#Des!1Eih1Ig7murgKj_~%~^FYka9}OC6F@o#(Q!_nHvE-rIdGi(MBmsCMf?3 z+{*|Hqomo3y8Hb>>_NCd_NxBXG;B!8WZqeeJ8i|2geQUl4yLQC^O- zRk$;@H5+*gaNl5?B{s9R*CXp1VfVQkNx_;p*!02FtL}TtJ@x9rIT=YNHZA6<`;gcsPXnu6)6^Zd zZye&0dx`lwGG-MUfO%2ors66SAm*lrBg>e#V^5tFrj5uZvUSMtxjXKoK`E~SOh!DH zrX&6tljGFUqFu-u(fwNc`xDmTRAxY03^E?cxpYORbs23#996d=F5REd7yMuZGE;CA z;(B}n3EjH`^eC_>t6tkw=0KV`9G-Z;Rcu2~Ii*S24WuYy|sBRhH zw{CncLWKiqm&p<^8;ONJ6MG24q}qWvSiX!5t-Cs`FI5dVAnh`t(5E0fCMO|bZO0)a xsnLA#8)6?~^qt6l-c3lfif*9GxPcE?{U0r~qwQ(G{XhT!002ovPDHLkV1n9jU1$IR literal 0 HcmV?d00001 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..92e32024 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,38 @@ +--- +home: true +heroText: OkHttps +tagline: 安�和Java领域开箱�用的 HTTP 客户端 +actionText: 快速上手 → +actionLink: /zh/guide/ +features: +- title: 轻�纯粹优雅 + details: OkHttps �常轻�,体积仅是 Retrofit 的一��到,并且��赖于特定平�,API 语义简�舒适。 +- title: 开箱�用的功能 + details: 异步预处�器�回调执行器�全局监�器�回调阻断机制�文件上传下载�过程控制�进度监�。 +- title: 更多实用特性 + details: URL ��符�Lambda 回调�JSON自动�装解��OkHttp 的特性:拦截器�连接池�CookieJar 等。 + +footer: Apache Licensed | Copyright © 2020-present Troy Zhou +--- + + +```java +// 构建 HTTP +HTTP http = HTTP.builder() + .baseUrl("http://api.demo.com") + .build(); + +// �步请求 +List users = http.sync("/users") // http://api.demo.com/users + .get() // GET请求 + .getBody() // 获��应报文体 + .toList(User.class); // 得到目标数� + +// 异步请求 +http.async("/users/jack") // http://api.demo.com/users/jack + .setOnResponse((HttpResult result) -> { + // 得到目标数� + User jack = result.getBody().toBean(User.class); + }) + .get(); // GET请求 +``` diff --git a/package.json b/package.json new file mode 100644 index 00000000..2a6dea1b --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "scripts": { + "dev": "vuepress dev docs", + "build": "vuepress build docs" + } +} \ No newline at end of file From e6ffe1f09fd4dcbf2428cbb94cda83cc2cb0e440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Tue, 28 Apr 2020 00:10:23 +0800 Subject: [PATCH 178/924] docs --- docs/.vuepress/config.js | 16 +- docs/README.md | 7 +- docs/guide/README.md | 93 ++++ docs/guide/getting-start.md | 920 ++++++++++++++++++++++++++++++++++++ 4 files changed, 1031 insertions(+), 5 deletions(-) create mode 100644 docs/guide/README.md create mode 100644 docs/guide/getting-start.md diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index d9a899ba..78f5aa65 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -2,6 +2,18 @@ module.exports = { title: 'OkHttps', description: 'OkHttps 官网', head: [ - ['link', { rel: 'icon', href: '/favicon.png' }] - ] + // ['link', { rel: 'icon', href: '/favicon.png' }] + ], + themeConfig: { + // logo: '/favicon.png', + nav: [ + { text: '教程', link: '/guide/' }, + { text: 'Gitee', link: 'https://gitee.com/ejlchina-zhxu/okhttps' }, + { text: 'GitHub', link: 'https://github.com/ejlchina/okhttps' } + ], + sidebar: [ + ['/guide/', '起步'], + '/guide/getting-start' + ] + } } \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 92e32024..3cd3c901 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,9 +1,10 @@ --- home: true + heroText: OkHttps -tagline: 安�和Java领域开箱�用的 HTTP 客户端 +tagline: JAVA 中超级好用的 HTTP 客户端 actionText: 快速上手 → -actionLink: /zh/guide/ +actionLink: /guide/ features: - title: 轻�纯粹优雅 details: OkHttps �常轻�,体积仅是 Retrofit 的一��到,并且��赖于特定平�,API 语义简�舒适。 @@ -19,7 +20,7 @@ footer: Apache Licensed | Copyright © 2020-present Troy Zhou ```java // 构建 HTTP HTTP http = HTTP.builder() - .baseUrl("http://api.demo.com") + .baseUrl("https://api.demo.com") .build(); // �步请求 diff --git a/docs/guide/README.md b/docs/guide/README.md new file mode 100644 index 00000000..e05d40b8 --- /dev/null +++ b/docs/guide/README.md @@ -0,0 +1,93 @@ +## 介� + +  OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 + + * 链�调用,一点到底 + * BaseURL�URL��符�JSON自动�装与解� + * �步拦截器�异步预处�器�回调执行器�全局监��回调阻断 + * 文件上传下载(过程控制�进度监�) + * �方法回调,充分利用 Lambda 表达� + * TCP连接池�Http2 + +> 1. OkHttps �常轻�(59Kb),是 Retrofit(124Kb)的一�,并且更加的开箱�用,API 也更加自然和语义化。 +> 2. OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit �� +> 3. OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。 + + +## 安装 + +### Maven + +```xml + + com.ejlchina + okhttps + 1.0.5 + +``` +### Gradle + +`implementation 'com.ejlchina:okhttps:1.0.5'` + +安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��: + +```groovy +android { + // �略其它�置.. + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } +} +``` + +## 使用 + +### 构建 HTTP + +```java +HTTP http = HTTP.builder().build(); +``` +  以上代�构建了一个最简�的`HTTP`实例,它拥有以下方法: + +* `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) +* `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) +* `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) +* `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) +* `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) +* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 + +  为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(请��[5.1 设置 BaseUrl](#51-设置-baseurl)): + +```java +HTTP http = HTTP.builder() + .baseUrl("http://api.demo.com") + .build(); +``` +  为了简化文档,下文中出现的`http`�是在构建时设置了`BaseUrl`的`HTTP`实例。 + +#### �步请求 + +  使用方法`sync(String url)`开始一个�步请求: + +```java +List users = http.sync("/users") // http://api.demo.com/users + .get() // GET请求 + .getBody() // 获��应报文体 + .toList(User.class); // 得到目标数� +``` +  方法`sync`返回一个�步`HttpTask`,�链�使用。 + +#### 异步请求 + +  使用方法`async(String url)`开始一个异步请求: + +```java +http.async("/users/1") // http://api.demo.com/users/1 + .setOnResponse((HttpResult result) -> { + // 得到目标数� + User user = result.getBody().toBean(User.class); + }) + .get(); // GET请求 +``` +  方法`async`返回一个异步`HttpTask`,�链�使用。 diff --git a/docs/guide/getting-start.md b/docs/guide/getting-start.md new file mode 100644 index 00000000..fda88cae --- /dev/null +++ b/docs/guide/getting-start.md @@ -0,0 +1,920 @@ +### 2 请求方法(GET|POST|PUT|DELETE) + +  �步与异步的`HttpTask`都拥有`get`�`post`�`put`与`delete`方法。��的是:�步`HttpTask`的这些方法返回一个`HttpResult`,而异步`HttpTask`的这些方法返回一个`HttpCall`。 + +```java +HttpResult res1 = http.sync("/users").get(); // �步 GET +HttpResult res2 = http.sync("/users").post(); // �步 POST +HttpResult res3 = http.sync("/users/1").put(); // �步 PUT +HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE +HttpCall call1 = http.async("/users").get(); // 异步 GET +HttpCall call2 = http.async("/users").post(); // 异步 POST +HttpCall call3 = http.async("/users/1").put(); // 异步 PUT +HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE +``` +### 3 解�请求结果 + +#### 3.1 回调函数 + +  OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅: + +```java +http.async("/users/{id}") // http://api.demo.com/users/1 + .addPathParam("id", 1) + .setOnResponse((HttpResult result) -> { + // �应回调 + }) + .setOnException((IOException e) -> { + // 异常回调 + }) + .setOnComplete((State state) -> { + // 完�回调,无论�功失败都会执行 + // 并且在 �应|异常回调 之�执行 + }) + .get(); +``` + +>* �有异步请求��以设置这三�(�应|异常|完�)回调 +>* �步请求直接返回结果,无需使用回调 + +#### 3.2 HttpResult + +  `HttpResult`是HTTP请求执行完�的结果,它是�步请求方法( `get`�`post`�`put`�`delete`)的返回值,也是异步请求�应回调(`OnResponse`)的�数,它定义了如下方法: + +* `getState()` 得到请求执行状�枚举,它有以下�值: + * `State.CANCELED` 请求被�消 + * `State.RESPONSED` 已收到�应 + * `State.TIMEOUT` 请求超时 + * `State.NETWORK_ERROR` 网络错误 + * `State.EXCEPTION` 其它请求异常 +* `getStatus()` 得到HTTP状�� +* `isSuccessful()` 是��应�功,状��在 [200..300) 之间 +* `getHeaders()` 得到HTTP�应头 +* `getHeaders(String name)` 得到HTTP�应头 +* `getHeader(String name)` 得到HTTP�应头 +* `getBody()` 得到�应报文体`Body`实例,它定义了如下方法(对�一个`Body`实例,以下的`toXXX()`类方法�能使用一个且仅能调用一次,除�先使用 cache 方法): + * `toBytes()` 返回字节数组 + * `toByteStream()` 返回字节输入� + * `toCharStream()` 返回字符输入� + * `toString()` 返回字符串 + * `toJsonObject()` 返回Json对象 + * `toJsonArray()` 返回Json数组 + * `toBean(Class type)` 返回根�type自动json解��的JavaBean + * `toList(Class type)` 返回根�type自动json解��的JavaBean列表 + * `toFile(String filePath)` 下载到指定路径 + * `toFile(File file)` 下载到指定文件 + * `toFolder(String dirPath)` 下载到指定目录 + * `toFolder(File dir)` 下载到指定目录 + * `getContentType()` 返回报文体的媒体类型 + * `getContentLength()` 返回报文体的字节长度 + * `cache()` 缓存报文体,开�缓存����使用`toXXX()`类方法 + * `close()` 关闭报文体,未对报文体�任何消费时使用,比如�读�报文头 +* `getError()` 执行中�生的异常,自动�获执行请求时�生的 网络超时�网络错误 和 其它IO异常 +* `close()` 关闭报文,未对报文体�任何消费时使用,比如�读�长度 + +  示例,请求结果自动转Bean和List: + +```java +// 自动转Bean +Order order = http.sync("/orders/1") + .get().getBody().toBean(Order.class); + +// 自动转List +List orders = http.sync("/orders") + .get().getBody().toList(Order.class); +``` + +  示例,使用 cache 方法: + +```java +Body body = http.sync("/orders").get().getBody().cache(); + +// 使用 cache �,�以多次使用 toXXX() 方法 +System.out.println(body.toString()); +System.out.println(body.toJsonArray()); +System.out.println(body.toList(Order.class)); +``` + +  示例,获�下载文件的大�: + +```java +long size = http.sync("/download/test.zip") + .get().getBody() + .close() // �是想获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); // 获得待下载文件的大� + +// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络�� + +System.out.println("size = " + size); +``` + + +#### 3.3 HttpCall + +  `HttpCall`对象是异步请求方法(`get`�`post`�`put`�`delete`)的返回值,与`java`的`Future`接�很�,它有如下方法: + +* `cancel()` �消本次请求,返回�消结果 +* `isCanceled()` 返回请求是�被�消 +* `isDone()` 返回是�执行完�,包��消和失败 +* `getResult()` 返回执行结果`HttpResult`对象,若请求未执行完,则挂起当�线程直到执行完��返回 + +  �消一个异步请求示例: + +```java +HttpCall call = http.async("/users/1").get(); + +System.out.println(call.isCanceled()); // false + +boolean success = call.cancel(); // �消请求 + +System.out.println(success); // true +System.out.println(call.isCanceled()); // true +``` + +### 4 构建HTTP任务 + +  `HTTP`对象的`sync`与`async`方法返回一个`HttpTask`对象,该对象�供了�链�调用的`addXXX`与`setXXX`等系列方法用于构建任务本身。 + +* `addHeader(String name, String value)` 添加请求头 +* `addHeader(Map headers)` 添加请求头 + +* `addPathParam(String name, Object value)` 添加路径�数:替�URL里的{name}��符 +* `addPathParam(Map params)` 添加路径�数:替�URL里的{name}��符 + +* `addUrlParam(String name, Object value)` 添加URL�数:拼接在URL的?之�(查询�数) +* `addUrlParam(Map params)` 添加URL�数:拼接在URL的?之�(查询�数) + +* `addBodyParam(String name, Object value)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) +* `addBodyParam(Map params)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) + +* `addJsonParam(String name, Object value)` 添加Json�数:请求体为Json(支�多层结构) +* `addJsonParam(Map params)` 添加Json�数:请求体为Json(支�多层结构) + +* `setRequestJson(Object json)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean +* `setRequestJson(Object bean, String dateFormat)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean + +* `addFileParam(String name, String filePath)` 上传文件 +* `addFileParam(String name, File file)` 上传文件 +* `addFileParam(String name, String type, InputStream inputStream)` 上传文件 +* `addFileParam(String name, String type, String fileName, InputStream input)` 上传文件 +* `addFileParam(String name, String type, byte[] content)` 上传文件 +* `addFileParam(String name, String type, String fileName, byte[] content)` 上传文件 + +* `setTag(String tag)` 为HTTP任务添加标签 +* `setRange(long rangeStart)` 设置Range头信�,用于断点续传 +* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,�用于分�下载 + +* `bind(Object object)` 绑定一个对象,�用于实现Android里的生命周期绑定 + +### 5 使用标签 + +  有时候我们想对HTTP任务加以分类,这时候�以使用标签功能: + +```java +http.async("/users") //(1) + .setTag("A") + .get(); + +http.async("/users") //(2) + .setTag("A.B") + .get(); + +http.async("/users") //(3) + .setTag("B") + .get(); + +http.async("/users") //(4) + .setTag("B") + .setTag("C") // 从 v1.0.4 标签将以追加模�添加,等效于 setTag("B.C") + .get(); + +http.async("/users") //(5) + .setTag("C") + .get(); +``` +  当使用标签�,就�以按标签批�的对HTTP任务进行�消: + +```java +int count = http.cancel("B"); //(2)(3)(4)被�消(�消标签包�"B"的任务) +System.out.println(count); // 输出 3 +``` +  标签除了�以用��消任务,在预处�器中它也�以�挥作用,请��[并行预处�器](#54-并行预处�器)与[串行预处�器](#55-串行预处�器)。 + +### 6 �置 HTTP + +#### 6.1 设置 BaseUrl + +```java +HTTP http = HTTP.builder() + .baseUrl("http://api.demo.com") // 设置 BaseUrl + .build(); +``` +  该�置全局生效,在�置了`BaseUrl`之�,具体的请求便�以�略`BaseUrl`部分,使得代�更加简�,例如: + +```java +http.sync("/users").get() // http://api.demo.com/users + +http.sync("/auth/signin") // http://api.demo.com/auth/signin + .addBodyParam("username", "Jackson") + .addBodyParam("password", "xxxxxx") + .post() // POST请求 +``` +  在�置了`BaseUrl`之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�: + +```java +http.sync("https://www.baidu.com").get() +``` + +#### 6.2 回调执行器 + +  OkHttps 默认所有回调都在 **IO线程** 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建`HTTP`时�置如下: + +```java +HTTP http = HTTP.builder() + .callbackExecutor((Runnable run) -> { + runOnUiThread(run); // 在UI线程执行 + }) + .build(); +``` +  该�置默认 **影�所有回调**。 + +#### 6.3 �置 OkHttpClient + +  与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下: + +```java +HTTP http = HTTP.builder() + .config((Builder builder) -> { + // �置连接池 最�10个连接(��置默认为 5) + builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES)); + // �置连接超时时间(默认10秒) + builder.connectTimeout(20, TimeUnit.SECONDS); + // �置拦截器 + builder.addInterceptor((Chain chain) -> { + Request request = chain.request(); + // 必须�步返回,拦截器内无法执行异步�作 + return chain.proceed(request); + }); + // 其它�置: CookieJar�SSL�缓存�代��事件监�... + }) + .build(); +``` + +#### 6.4 并行预处�器 + +  预处�器(`Preprocessor`)�以让我们在请求�出之�对请求本身�一些改�,但与`OkHttp`的拦截器(`Interceptor`)��:预处�器�以让我们 **异步** 处�这些问题。 + +  例如,当我们想为请求任务自动添加`Token`头信�,而`Token`�能通过异步方法`requestToken`获�时,这时使用`Interceptor`就很难处�了,但�以使用预处�器轻�解决: + +```java +HTTP http = HTTP.builder() + .addPreprocessor((PreChain chain) -> { + HttpTask task = chain.getTask();// 获得当�的HTTP任务 + if (!task.isTagged("Auth")) { // 根�标签判断该任务是�需�Token + return; + } + requestToken((String token) -> { // 异步获� Token + task.addHeader("Token", token);// 为任务添加头信� + chain.proceed(); // 继续当�的任务 + }); + }) + .build(); +``` +  和`Interceptor`一样,`Preprocessor`也�以添加多个。他们之间的区别如下: + +> * 拦截器�能处��步�作,预处�器支�处�异步�作 +> * 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) +> * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调监�(详�6.6章节) + +#### 6.5 串行预处�器(TOKEN问题最佳解决方案) + +  普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当`Token`过期时我们需�去刷新获�新`Token`,而刷新`Token`这个�作�能有一个任务去执行,因为如果`n`个任务�时执行的�,那么必有`n-1`个任务刚刷新得到的`Token`�能就立马失效了,而这是我们所�希望的。 + +  为了解决这个问题,OkHttps �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器: + +```java +HTTP http = HTTP.builder() + .addSerialPreprocessor((PreChain chain) -> { + HttpTask task = chain.getTask(); + if (!task.isTagged("Auth")) { + return; + } + // 检查过期,若需�则刷新Token + requestTokenAndRefreshIfExpired((String token) -> { + task.addHeader("Token", token); + chain.proceed(); // 调用此方法�,�会有其它任务进入该处�器 + }); + }) + .build(); +``` +  串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程� + +#### 6.6 全局回调监� + +```java +HTTP http = HTTP.builder() + .responseListener((HttpTask task, HttpResult result) -> { + // 所有请求�应�都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行 + }) + .completeListener((HttpTask task, State state) -> { + // 所有请求执行完都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行 + }) + .exceptionListener((HttpTask task, IOException error) -> { + // 所有请求�生异常都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 + }) + .build(); +``` + +  全局回调监�与拦截器的异�: +> * 拦截器�以添加多个,全局回调监�分三�,��最多添加一个 +> * 拦截器处的�时机在请求�和�应�,全局回调监��在�应�,并且晚于拦截器 +> * 全局回调监��以 **阻断**(return false)�个请求的具体回调,而拦截器�能 + +#### 6.7 全局下载监� + +```java +HTTP http = HTTP.builder() + .downloadListener((HttpTask task, Download download) -> { + // 所有下载在开始之�都会先走这里 + Ctrl ctrl = download.getCtrl(); // 下载控制器 + + }) + .build(); +``` + +### 7 使用 HttpUtils 类 + +  类`HttpUtils`本是 [�身 HttpUtils](https://gitee.com/ejlchina-zhxu/httputils) 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。 + +  类`HttpUtils`共定义了四个��方法: + +* `of(HTTP http)` �置`HttpUtils`�有的`HTTP`实例(�调用此方法�默认使用一个没有没有�过任何�置的`HTTP`懒实例) +* `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) +* `async()` 开始一个异步HTTP任务,使用该方法必须在构建时设置 BaseUrl +* `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) +* `sync()` 开始一个�步HTTP任务,使用该方法必须在构建时设置 BaseUrl +* `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) +* `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) +* `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) +* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 +  也就是说,能使用`http`实例的地方,都�以使用`HttpUtils`类,例如: + +```java +// 在�置HTTP实例之�,�能使用全路径方� +List roles = HttpUtils.sync("http://api.demo.com/roles") + .get().getBody().toList(Role.class); + +// �置HTTP实例,全局生效 +HttpUtils.of(HTTP.builder() + .baseUrl("http://api.demo.com") + .build()); + +// 内部使用新的HTTP实例 +List users = HttpUtils.sync("/users") + .get().getBody().toList(User.class); +``` + +### 8 文件下载 + +  OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例: + +```java +http.sync("/download/test.zip") + .get() // 使用 GET 方法(其它方法也�以,看�务器支�) + .getBody() // 得到报文体 + .toFile("D:/download/test.zip") // 下载到指定的路径 + .start(); // �动下载 + +http.sync("/download/test.zip").get().getBody() + .toFolder("D:/download") // 下载到指定的目录,文件�将根�下载信�自动生� + .start(); +``` +  或使用异步连接方�: + +```java +http.async("/download/test.zip") + .setOnResponse((HttpResult result) -> { + result.getBody().toFolder("D:/download").start(); + }) + .get(); +``` +  这里�说明一下:`sync`与`async`的区别在于连接�务器并得到�应这个过程的�步与异步(这个过程的耗时在大文件下载中�比��),而`start`方法�动的下载过程则都是异步的。 + +#### 8.1 下载进度监� + +  就直接上代�啦,诸�一看便懂: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .setStepBytes(1024) // 设置�接收 1024 个字节执行一次进度回调(�设置默认为 8192) + // .setStepRate(0.01) // 设置�接收 1% 执行一次进度回调(�设置以 StepBytes 为准) + .setOnProcess((Process process) -> { // 下载进度回调 + long doneBytes = process.getDoneBytes(); // 已下载字节数 + long totalBytes = process.getTotalBytes(); // 总共的字节数 + double rate = process.getRate(); // 已下载的比例 + boolean isDone = process.isDone(); // 是�下载完� + }) + .toFolder("D:/download/") // 指定下载的目录,文件�将根�下载信�自动生� + // .toFile("D:/download/test.zip") // 指定下载的路径,若文件已存在则覆盖 + .setOnSuccess((File file) -> { // 下载�功回调 + + }) + .start(); +``` +  值得一�的是:由于 OkHttps 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有`Content-Length`头),例如: + +```java +List users = http.sync("/users") + .get() + .getBody() + .setStepBytes(2) + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .toList(User.class); +``` + +#### 8.2 下载过程控制 + +  过于简�:还是直接上代�: + +```java +Ctrl ctrl = http.sync("/download/test.zip") + .get() + .getBody() + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .toFolder("D:/download/") + .start(); // 该方法返回一个下载过程控制器 + +ctrl.status(); // 下载状� +ctrl.pause(); // 暂�下载 +ctrl.resume(); // ��下载 +ctrl.cancel(); // �消下载(�时会删除文件,����) +``` +  无论是�步还是异步�起的下载请求,都�以�以上的控制: + +```java +http.async("/download/test.zip") + .setOnResponse((HttpResult result) -> { + // 拿到下载控制器 + Ctrl ctrl = result.getBody().toFolder("D:/download/").start(); + }) + .get(); +``` + +#### 8.3 实现断点续传 + +  OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到 **断点**,便将��的问题�得简�: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .toFolder("D:/download/") + .setOnFailure((Failure failure) -> { // 下载失败回调,以便接收诸如网络错误等失败信� + IOException e = failure.getException(); // 具体的异常信� + long doneBytes = failure.getDoneBytes(); // 已下载的字节数(断点),需��存,用于断点续传 + File file = failure.getFile(); // 下载生�的文件,需��存 ,用于断点续传(��存路径也�以) + }) + .start(); +``` +  下�代�实现续传: + +```java +long doneBytes = ... // 拿到�存的断点 +File file = ... // 待续传的文件 + +http.sync("/download/test.zip") + .setRange(doneBytes) // 设置断点(已下载的字节数) + .get() + .getBody() + .toFile(file) // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + + }) + .setOnFailure((Failure failure) -> { + + }) + .start(); +``` + +#### 8.4 实现分�下载 + +  当文件很大时,有时候我们会考虑分�下载,与断点续传的�路是一样的,示例代�: + +```java +static String url = "http://api.demo.com/download/test.zip" + +public static void main(String[] args) { + long totalSize = HttpUtils.sync(url).get().getBody() + .close() // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); // 获得待下载文件的大�(由于未消费报文体,所以该请求�会消耗下载报文体的时间和网络��) + download(totalSize, 0); // 从第 0 �开始下载 + sleep(50000); // 等待下载完�(�然本例的主线程就结�啦) +} + +static void download(long totalSize, int index) { + long size = 3 * 1024 * 1024; // ��下载 3M + long start = index * size; + long end = Math.min(start + size, totalSize); + HttpUtils.sync(url) + .setRange(start, end) // 设置本次下载的范围 + .get().getBody() + .toFile("D:/download/test.zip") // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + if (end < totalSize) { // 若未下载完,则继续下载下一� + download(totalSize, index + 1); + } else { + System.out.println("下载完�"); + } + }) + .start(); +} +``` + +### 9 文件上传 + +  一个简�文件上传的示例: + +```java +http.sync("/upload") + .addFileParam("test", "D:/download/test.zip") + .post() // 上传�法一般使用 POST 或 PUT,看�务器支� +``` +  异步上传也是完全一样: + +```java +http.async("/upload") + .addFileParam("test", "D:/download/test.zip") + .post() +``` + +#### 9.1 上传进度监� + +  OkHttps 的上传进度监�,监�的是所有请求报文体的��进度,示例代�: + +```java +http.sync("/upload") + .addBodyParam("name", "Jack") + .addBodyParam("age", 20) + .addFileParam("avatar", "D:/image/avatar.jpg") + .setStepBytes(1024) // 设置��� 1024 个字节执行一次进度回调(�设置默认为 8192) + // .setStepRate(0.01) // 设置��� 1% 执行一次进度回调(�设置以 StepBytes 为准) + .setOnProcess((Process process) -> { // 上传进度回调 + long doneBytes = process.getDoneBytes(); // 已��字节数 + long totalBytes = process.getTotalBytes(); // 总共的字节数 + double rate = process.getRate(); // 已��的比例 + boolean isDone = process.isDone(); // 是���完� + }) + .post() +``` +  咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在`get/post`方法之�使用这些API,下载是在`getBody`方法之�使用。很好�解:`get/post`之�是准备��请求时段,有上传的�义,而`getBody`之�,已是报文�应的时段,当然是下载。 + +#### 9.2 上传过程控制 + +  上传文件的过程控制就很简�,和常规请求一样,�有异步�起的上传�以�消: + +```java +HttpCall call = http.async("/upload") + .addFileParam("test", "D:/download/test.zip") + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .post() + +call.cancel(); // �消上传 +``` +  上传就没有暂�和继续这个功能啦,应该没人有这个需求�? + +### 10 异常处� + +  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 + +#### 10.1 �步请求的异常 + +  默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 `try catch` ��获,例如: + +```java +try { + HttpResult result = http.sync("/users/1").get(); +} catch (HttpException e) { + Throwable cause = e.getCause(); // 得到异常原因 + if (cause instanceof ConnectException) { + // 当没网络时,会抛出连接异常 + } + if (cause instanceof SocketTimeoutException) { + // 当接�长时间未�应,会抛出超时异常 + } + if (cause instanceof UnknownHostException) { + // 当把域�或IP写错,会抛出 UnknownHost 异常 + } + // ... +} +``` +  这�传统的异常处�方�,当然�以解决问题,但 OkHttps 有更佳的方案: + +```java +// 方法 nothrow() 让异常�直接抛出 +HttpResult result = http.sync("/users/1").nothrow().get(); +// 判断执行状� +switch (result.getState()) { + case RESPONSED: // 请求已正常�应 + break; + case CANCELED: // 请求已被�消 + break; + case NETWORK_ERROR: // 网络错误,说明用户没网了 + break; + case TIMEOUT: // 请求超时 + break; + case EXCEPTION: // 其它异常 + break; +} +// 还�以获得具体的异常信� +IOException error = result.getError(); +``` + +#### 10.2 异步请求的异常 + +  异步请求最常用的异常处�方�就是设置一个异常回调: + +```java +http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .setOnException((IOException e) -> { + // 这里处�请求异常 + }) + .get(); +``` +  当然,还有一个全局异常监�(`ExceptionListener`): + +```java +HTTP http = HTTP.builder() + .exceptionListener((HttpTask task, IOException error) -> { + // 所有请求�生异常都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 + }) + .build(); +``` +  如果�设置`OnException`回调,也没有`ExceptionListener`,�生异常时会在 **IO 线程** 中�上抛出,外层无法�获: + +```java +try { + http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .get(); +} catch (HttpException e) { + // 这�方�是�获�到异常的������ +} +``` +  �使没有`OnException`回调,�生异常时,�然会走`OnComplete`回调,如果设置了的�: + +```java +http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .setOnComplete((State state) -> { + // �生异常,会先执行这里,�以根� state 判断�生了什么 + // 但执行完��然会在IO线程中�上抛出 + }) + .get(); +``` +  如果就是想 **�处�异常,也��上抛出**,�生错误完全无视,�以�到�?�以�还是使用`nothrow()`方法: + +```java +http.async("/users/1") + .nothrow() // 告诉 OkHttps �生异常时��外抛出 + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .get(); +``` +### 11 �消请求的4�方� + +  在 OkHttps 里�消请求共有 **4 �** 方��选: + +* 使用`HttpCall#cancel()`�消�个请求(适用于异步请求,[详� 3.3 章节](#33-httpcall)) +* 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) + +```java +HttpTask task = http.async("/users") + .setOnResponse((HttpResult result) -> { + // �应回调 + }); + +task.get(); // �起 GET 请求 + +// �消请求,并返回是��消�功 +boolean canceled = task.cancel(); +``` + +* 使用`HTTP#cancel(String tag)`按标签批��消请求(适用于所有请求,[详�第 5 章节](#5-使用标签)) +* 使用`HTTP#cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) + +```java +http.cancelAll(); // �消所有请求 +``` + +### 12 回调线程自由切�(for Android) + +  在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 + +  在 **默认** 情况下,**所有回调** 函数都会 **在 IO 线程** 执行。为什么会设计如此呢?这是因为 OkHttps �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。 + +  但是在 Android 里使用 OkHttps 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器: + + ```java +HTTP http = HTTP.builder() + .callbackExecutor((Runnable run) -> { + // 实际编�中�以� Handler �出�,�需��次执行回调都�新创建 + new Handler(Looper.getMainLooper()).post(run); // 在主线程执行 + }) + .build(); +``` +  上述代�便实现了让 **所有** 的 **回调函数** 都在 **主线程(UI线程)** 执行的目的,如: + +```java +http.async("/users") + .addBodyParam("name", "Jack") + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .setOnResponse((HttpResult result) -> { + // 在主线程执行 + }) + .setOnException((Exception e) -> { + // 在主线程执行 + }) + .setOnComplete((State state) -> { + // 在主线程执行 + }) + .post(); +``` +  但是,如果�时还想让�些回调放在IO线程,实现 **自由切�**,怎么办呢?OkHttps 给出了�常�活的方法,如下: + +```java +http.async("/users") + .addBodyParam("name", "Jack") + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnResponse((HttpResult result) -> { + // 在 IO 线程执行 + }) + .setOnException((Exception e) -> { + // 在主线程执行(没有指明 nextOnIO 则在回调执行器里执行) + }) + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnComplete((State state) -> { + // 在 IO 线程执行 + }) + .post(); +``` +  无论是哪一个回调,都�以使用`nextOnIO()`方法自由切�。�样,对于文件下载也是一样: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .toFolder("D:/download/") + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnSuccess((File file) -> { + // 在 IO 线程执行 + }) + .setOnFailure((Failure failure) -> { + // 在主线程执行 + }) + .start(); +``` +### 13 实现生命周期绑定(for Android) + +  由于 OkHttps 并��赖于 Android,所以它并没有�供关于生命周期绑定的直接实现,但它的一些扩展机制让我们很容易就�以实现这个需求。在开始之�,我们首先��解何为生命周期绑定: + +> 所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� + +  现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在`Activity`或`Fragment`里,它的使用效果如下: + +```java +// 在 Activity 或 Fragment 内�起请求 +http.async("http://www.baidu.com") + .bind(getLifecycle()) // 绑定生命周期 + .setOnResponse((HttpResult result) -> { + Log.i("FirstFragment", "收到请求:" + result.toString()); + }) + .get(); +``` +  上述代�中的`getLifecycle()`是`Activity`或`Fragment`自带的方法,而`bind()`是`HttpTask`的现有方法。在�置好`HTTP`实例�,上述代��起的请求便�以感知`Activity`或`Fragment`的生命周期。 + +  那`HTTP`实例到底该如何�置呢? + +#### 第一步:�置预处�器 + +```java +HTTP http = HTTP.builder() + ... // �略其它�置项 + .addPreprocessor((Preprocessor.PreChain chain) -> { + HttpTask task = chain.getTask(); + Object bound = task.getBound(); + // 判断 task 是�绑定了 Lifecycle 对象 + if (bound instanceof Lifecycle) { + // �新绑定一个 生命周期监视器(LCObserver)对象,它的定义�下一步 + task.bind(new LCObserver(task, (Lifecycle) bound)); + } + chain.proceed(); + }) + ... // �略其它�置项 + .build(); +``` + +#### 第二步:定义生命周期监视器 + +```java +public class LCObserver implements LifecycleObserver { + + HttpTask task; + Lifecycle lifecycle; + + LCObserver(HttpTask task, Lifecycle lifecycle) { + this.task = task; + this.lifecycle = lifecycle; + lifecycle.addObserver(this); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + public void onStop() { + task.cancel(); // 在 ON_STOP 事件中,�消对应的 HTTP 任务 + } + + public void unbind() { + // 在请求完�之�移除监视器 + lifecycle.removeObserver(this); + } + +} +``` + +#### 第三步:�置全局回调监� + +  以上两步其实已�实现了生命周期绑定的功能,但是在请求完�之�,我们需�在`lifecycle`中移除`LCObserver`对象: + +```java +HTTP http = HTTP.builder() + ... // �略其它�置项 + .completeListener((HttpTask task, HttpResult.State state) -> { + Object bound = task.getBound(); + // 判断 task 是�绑定了生命周期监视器(LCObserver)对象 + if (bound instanceof LCObserver) { + // 解绑监视器 + ((LCObserver) bound).unbind(); + } + return true; + }) + ... // �略其它�置项 + .build(); +``` + +**以上三步便在Android中实现了生命周期与HTTP请求绑定的功能** + +  �常简�,懒得敲代�的�学还�以 [点这里 OkHttps.java](https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java) 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。 + +  有需�的�学,�以直接下载下�使用,还�以基于它�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考[6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案),�比如扩展实现生命周期与下载事件绑定的功能,都�常简�。 + + +## �期计划(v1.1.0) + +* 简化 WebSocket 编程:�直接�� JavaBean 对象消� +* 简化 WebSocket 编程:�直接接收 JavaBean 对象消� +* 简化 WebSocket 编程:�使用 Lambda 表达�进行 WebSocket 编程 + +## �系方� + +* 微信: +* 邮箱:zhou.xu@ejlchina.com + +## �与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. �交代� +4. 新建 Pull Request From 02b6e548e37a5946dc0516c8bff227cb765d0d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 11:23:24 +0800 Subject: [PATCH 179/924] docs --- docs/.vuepress/config.js | 10 +- docs/.vuepress/public/logo.png | Bin 0 -> 5800 bytes docs/.vuepress/styles/index.styl | 3 + docs/README.md | 6 +- docs/guide/README.md | 34 ++- docs/guide/android.md | 168 ++++++++++++ docs/guide/getting-start.md | 455 ++----------------------------- docs/guide/updown.md | 218 +++++++++++++++ 8 files changed, 444 insertions(+), 450 deletions(-) create mode 100644 docs/.vuepress/public/logo.png create mode 100644 docs/.vuepress/styles/index.styl create mode 100644 docs/guide/android.md create mode 100644 docs/guide/updown.md diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 78f5aa65..7f15ba16 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -2,10 +2,10 @@ module.exports = { title: 'OkHttps', description: 'OkHttps 官网', head: [ - // ['link', { rel: 'icon', href: '/favicon.png' }] + ['link', { rel: 'icon', href: '/logo.png' }] ], themeConfig: { - // logo: '/favicon.png', + logo: '/logo.png', nav: [ { text: '教程', link: '/guide/' }, { text: 'Gitee', link: 'https://gitee.com/ejlchina-zhxu/okhttps' }, @@ -13,7 +13,9 @@ module.exports = { ], sidebar: [ ['/guide/', '起步'], - '/guide/getting-start' - ] + ['/guide/getting-start', '一探究竟'], + ['/guide/android', '安�'], + ], + sidebarDepth: 2 } } \ No newline at end of file diff --git a/docs/.vuepress/public/logo.png b/docs/.vuepress/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..3b3b2845420b470e4b091e3862ff98653c4b1cb0 GIT binary patch literal 5800 zcmX9?c|2768$RclVT^4s*_RpXRMuoG%P?dtA*m#L(n8lZmMhEHm&71ZWGfe4Wi5Ng zo~ww;5;4j}cES*5ese#+KhEcUKi~Izp69He_j%rATWd2Oq!=R5sxYDrp^2IMU_Bh0y>E*~O>!|ph0Kd1zw>qt@EFdT#`V|KkDr5H~Vx$ zx)qN}Ap!Ni=LJ%~4KJ^GhuGQh?bUZ0gP6bYt%j3+HhGK!?l=fvsUG{UYoE##$O+3L zcXJaDBgO*^4X}+3<@1HV`X40nk{wF!_t4kKDi{!MFP%L1P(CCI|9baxI_?ea=Cg%nKp+fbIeFs4TS`T<+@j9@WN^=z+q2S+UuVX zJ08S5nc@z=+e|L71(Fns;bfH}MHahx5{!0&1nRSZk5wOCfttxuth$gLL|cTK2_TWX zJy=EO-aO=tH^Tv(ESk4IyZSS_H|=cFbqDUos}!-J$@LBeU)J`r0{1d~(0R95-6|8PJ$uBxn)R!h`R!oGVeOt8Zk_3mb8P&Qx~Rsl$qY?5ZAR znd`p}FIl_Y?L7>yjD{#egzxhQ3HK8`fNlA7fprdau?sC9x7N+c=0Kh5hbjX-cSBk5zHwMB>BZEb<@Y z#2oE^)g|o!thYh_Z;NtWb_uo_kjDYZHRbcd(KoHQObKGM#7!0I1t3$N^xf+9EksGM zz?0D8jd%BiBi@wHzh0B1_YHj>Y?_S8X^cUb zTq`U5d{K4O=DM?QvY|!LDG|$HEbx7t?<{v@;!>kx#Y(ZOkz;*$>fvdxVN|z5unN_^ z7MEEG1A3I{iHB8-FNL@29d9r3-{^=)az0HG`5CAjSoYZouLY5F>IW*@lf8N^Wi(RH z{B|h5FO9jW?j%szc+R+*C`>Ws1-!>?Aclo6flubmOR+fP_uX!ZROPR~3 z>&xdOdw%#Y&a|+q|54hu?xvMe08=F)FO{0>0~y8X^3X&JSpr7wv^LPdf?nq5FZhgS z1Q7X6G53V=AR@7pg4rFJP!LN*w>lgzL3pl00TWzm;*DIkDT(**ymB-uZ)}JZlrbfM zTG2t+NqtCn6`pieaHjVxF|K05tP@;AnNIgZuXCSTVIvKyUVtiYTlKhpnuhs>ESA`%fNPm-I6&ic%!=cur zrJu^WpyGwoakaA%#V_8iIN{gscF?P>Zrz=~S6x0o?5faZP378&T(l-2G^Tm>&jzwE za-bhZt7erF%l||?uO^@^2^t($@Vz$^*f zO!9d7+0I9N0Tuo6&uD!s==x;pjaeu~kj&nNHQMlW5Ql_x(H`;kMAYCpJ*JWqz6PTC z3`No@)D-046&)>w6zin}1SY({gvc>mi1Yomph7dPCZi7H%pSkLSr8~mfJW({t+$c|! zwfYLT1unZ0tEFO%{e;EICSCD-`_S54$mr^ioaZY6tsYi<7McJh%w@_`fy6ez4qs+iXK0=H;rm!}>Ft77(PG9d`cPmaL6)z%?%Es&N zYmVB55_lBv-*LGe@#bL>kV^F<7JW?)<@Q64VYvVJIh3dWcER)d*0?Qj&ZBWP_xG%v zol>$%*HYBj@kR`nEdX^`cgvZE>V;xbLu9=4tVWGN1mgQzo?d?3bBF+7MFc45A^_o0 z-<9U5=;6Va0K{PAs)J>00<~O67pAlR_z0SipC%<=!U6oVvvS>H+@MSh&slEHB+*3x z?MB2`;z8TE#4OZZ5eQd{7Kqbp3s!PTohEQ8W$Kaub~iYm8fV-1I?v8=nM4n-dPTlPzo<##cHv9x+IN=y@JUN$W1QHR!G781TfE+uY zA{NVv2m&O4MB+WD;AxKA_6dW_zHXB>aYcX#2ix2I8m%9`GC#Y_Em)Y`;|CVAw&yu( z_4DO~alkq1DD5A&of!ua0g(i#2$6Oy&z)AL_o<|i(xJ^Xz*yK=^j ze&#qwJMKeqX{7`@4*DqAO0hXr^{t`1B`fS7Yl5*FY!P%Z={-2JG3No|0LfXJHc01( zC1CL!I(r{zfhuJV5m>MYsHb-L@}}VNB9IUESw~dzmS>_@iSCMprw&U;QP~B=4;RW! zTB%#lmzyKgB=7ScanLuiEKFrh-Q>_@O{=Afs$%#o=bndotMZ?3|bMG$hPhg%6nwsV*iVcjh-QaCd;cW>uUxQTywg9 zpL?QlGH7#rCzLF0*%a5J_oUJg4UmNo-V@_zj%kTXUQP4md2^iBf8$Au5{vxhC;{n3D+ zf7IoLWm)&Viwje(tWuk)rlDPHJAwD-#aGZ0FWmt?*xSfPF@0;A z7Q-w^fCg`*KIL)xDlC*iV^0YHa*qsCL(O>^JUAWD;J)U=dB9^37C!r?dJg7cBwU@~ z0R!ryD%qveb@wKt5mOIHP0p1j6nTpPpvH>~r~ehgVZ5(4^6w&a8D|X03^K0VdSVpD zYAK23X%D?ZD&UTrjWH7V${(enem#CKh$q=dpyfjuKwW8{@Jf@9<4c%2`vNSjI@F01 zB6p{6+kKM1`DnA~55wMhtdtJY!VggQVwPyp5rY5zSrKVW@Kgq>!$$PigzFizc-#hl z@6_4FE4F$~XUQUbkL%1s(`4je_l1EgWPr#w*f(`YOe*f;NXuS|FpyIRP#KmX`!~MZ z@ZJ`-4Hu!E3IRso()ma5Vy>jF1`USK2;W%vGfw-qedmznw2|H90gWGj3!6FAW;ymM zzdfNgxk}9n``tvlANaO>UOPUL?#5m)JC?5->T`ixCV#|OIkNShotY8!{l&6DkaI|1N`ax|&rZ7l z?z&&4G?ri$mD#tosdTvUP}h)WiuU>bJ3$BElSJgJCR-JSCM0=|ps9Xvoopb`+AT?t z!Tc%R!roPI%To~u&COJ9|1uECzuvd#>t+m-i359@$r6&}xh}mimjknKsb3GDo<&LA zm5Xl}*8|{1(l6=^r_NW2?oZDAel)p1O?TPbj2g>2U_bMd7)kHh<#<?7jM!H4`$P+ zY#7^p;vDS@E$v6m2U%_UAE(dUFpKe)_+0OhbPL;r)OS(bI{=pp8nc`y< z9)=!JU3<7XJ}i%Y3vrEV8!#MOdoC+a6*KG3!aYZCBbQ3b-~VW6!1}Jx(Z( zK3@Be+DY);;lt_CXu1t^YiNigz?HF}-R^JL-WbZb$;I_A%x#!QPrit4F)i3Ee{_`^ z3A8giIEG$^UupH;n>b*OYi5*xldc}0e`+^}1MIHe`LZXdvHs&t)PgC^HENTK&KNTE zD-8erv-j#ZMc$+KO+!hq$ixZPYe2V&P9VK8L*iP@e%yo!jcySvw)PM9&5t*uKMo$Z z^>gmEK?8a5?DNR_yl5Q-uq*2s8){Oml`qE|?p>50I|KCdzV%8Q3`Vt@YPNG~tIZ$kt;NT+`hR=gEYMzO6ZD|2Hyu^ewRy6Dkv$++c^3 zFseFe(-b91|8kMr5^X(VT5SmM34NLBoGm*sw*)+QU5Q1X>Z^WpGufAxVQnJx?T+4n z1W;M&>2DVQIQgBd*dN)B&=lpD7p9-1<+?f_MclzZL#e~y_^-U9gnT&u>#n1t?9j2F z9~n{S zIU&?_t)>S{gj3M=QTl~!vkvwNF5sa-Z`iszA$nNCOegYCpxB+&KANFEKad-KPOYM> z4v}owcXM0D6an0Uo@Yh#76Vt{VKJ4=BScPf%4tzKg82f}{dIFkC3rT27vqz1qd%R; z_s`44A|N$#Uqpo(_)o0TWCzXg0gA5ex9eJ5pB3%V1Tc-qtdMU4B;5O}X4P{TE`Q;` zq!s87DyJ=Ml*P)pI+aFhI(gaWRati(c>NDrF`^QTWwJbxl=`l#jXy*_7M&YG!$Fof zZiZzqBk%YQi8ekND$b7!4x)0=o);9DN*xx6-ei729|wr+`bpsv=V0&iPolUGGq=0r zTw~(}ADqAVg3YfwzD6L1Co+h3+q}nkT(($!uWI~t#Z#rpm=Ji~=Ec&1gCkCkrmq+0 z^bTv6&ssG24ZSP=>#yUEz|@%PQpR`7FgX9aJAuf!9f!u^1+CT{Rh7?T#;+EjZTEzW zB#&$Mi4_jb?ym=N|tg2236iIFNRu<^P(9?`q#FJX_mht! z3WEcbZDH>_I;2rZJO>U^Xf)22=7_@QvMqv_IhITWy^eR48ekWJFme$6=$&$p#e#&X zfy5#75#;W6nDBe$`Awq(LX-L3WZ(1WaGJUi(h)3|)Y*#n3&&nG9gyZgvJ|huSS4z`Y`R zf2Y_2aYl(#k2@4(9Y3y#$3Q4fWXG>)!|TVZlyN}Daa+XT@EC<{27?CVt3CW~HGUa& zuvXhJ3py@SYYRLynrTCNP=0T@2ckos{>Cbn;z2doW!@9{K3ORuP9*|cxuQqgEN27v z_(+=jrY)qP^yrLW;73JP@8YLujJqy<6(7JlX*nmV(?mbrguyZH800-v++ST);? +heroImage: /logo.png heroText: OkHttps -tagline: JAVA 中超级好用的 HTTP 客户端 +tagline: 基于 OkHttp 的 Java HTTP 客户端 actionText: 快速上手 → actionLink: /guide/ features: @@ -37,3 +37,5 @@ http.async("/users/jack") // http://api.demo.com/users/jack }) .get(); // GET请求 ``` + +**
就这么简�,你已学会 OkHttps 90% 的用法�
** \ No newline at end of file diff --git a/docs/guide/README.md b/docs/guide/README.md index e05d40b8..f2cda81c 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -43,18 +43,18 @@ android { ## 使用 -### 构建 HTTP +### 构建实例 ```java HTTP http = HTTP.builder().build(); ```   以上代�构建了一个最简�的`HTTP`实例,它拥有以下方法: -* `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) -* `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) -* `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) -* `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) -* `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) +* `async(String url)` 开始一个异步请求 +* `sync(String url)` 开始一个�步请求 +* `cancel(String tag)` 按标签�消请求 +* `cancelAll()` �消所有HTTP任务,包括�步和异步 +* `request(Request request)` OkHttp 原生请求 * `webSocket(Request request, WebSocketListener listener)` WebSocket通讯   为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(请��[5.1 设置 BaseUrl](#51-设置-baseurl)): @@ -66,7 +66,7 @@ HTTP http = HTTP.builder() ```   为了简化文档,下文中出现的`http`�是在构建时设置了`BaseUrl`的`HTTP`实例。 -#### �步请求 +### �步请求   使用方法`sync(String url)`开始一个�步请求: @@ -78,7 +78,7 @@ List users = http.sync("/users") // http://api.demo.com/users ```   方法`sync`返回一个�步`HttpTask`,�链�使用。 -#### 异步请求 +### 异步请求   使用方法`async(String url)`开始一个异步请求: @@ -91,3 +91,21 @@ http.async("/users/1") // http://api.demo.com/users/1 .get(); // GET请求 ```   方法`async`返回一个异步`HttpTask`,�链�使用。 + + +### 请求方法 + +  �步与异步的`HttpTask`都拥有`get`�`post`�`put`与`delete`方法。��的是:�步`HttpTask`的这些方法返回一个`HttpResult`,而异步`HttpTask`的这些方法返回一个`HttpCall`。 + +```java +HttpResult res1 = http.sync("/users").get(); // �步 GET +HttpResult res2 = http.sync("/users").post(); // �步 POST +HttpResult res3 = http.sync("/users/1").put(); // �步 PUT +HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE +HttpCall call1 = http.async("/users").get(); // 异步 GET +HttpCall call2 = http.async("/users").post(); // 异步 POST +HttpCall call3 = http.async("/users/1").put(); // 异步 PUT +HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE +``` + +**至此,你已轻�学会了 OkHttps 95% 的常规用法�但别急,��还有更精彩的。** \ No newline at end of file diff --git a/docs/guide/android.md b/docs/guide/android.md new file mode 100644 index 00000000..0ec1dbbf --- /dev/null +++ b/docs/guide/android.md @@ -0,0 +1,168 @@ +## 回调线程切� + +  在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 + +  在 **默认** 情况下,**所有回调** 函数都会 **在 IO 线程** 执行。为什么会设计如此呢?这是因为 OkHttps �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。 + +  但是在 Android 里使用 OkHttps 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器: + + ```java +HTTP http = HTTP.builder() + .callbackExecutor((Runnable run) -> { + // 实际编�中�以� Handler �出�,�需��次执行回调都�新创建 + new Handler(Looper.getMainLooper()).post(run); // 在主线程执行 + }) + .build(); +``` +  上述代�便实现了让 **所有** 的 **回调函数** 都在 **主线程(UI线程)** 执行的目的,如: + +```java +http.async("/users") + .addBodyParam("name", "Jack") + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .setOnResponse((HttpResult result) -> { + // 在主线程执行 + }) + .setOnException((Exception e) -> { + // 在主线程执行 + }) + .setOnComplete((State state) -> { + // 在主线程执行 + }) + .post(); +``` +  但是,如果�时还想让�些回调放在IO线程,实现 **自由切�**,怎么办呢?OkHttps 给出了�常�活的方法,如下: + +```java +http.async("/users") + .addBodyParam("name", "Jack") + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnResponse((HttpResult result) -> { + // 在 IO 线程执行 + }) + .setOnException((Exception e) -> { + // 在主线程执行(没有指明 nextOnIO 则在回调执行器里执行) + }) + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnComplete((State state) -> { + // 在 IO 线程执行 + }) + .post(); +``` +  无论是哪一个回调,都�以使用`nextOnIO()`方法自由切�。�样,对于文件下载也是一样: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .toFolder("D:/download/") + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnSuccess((File file) -> { + // 在 IO 线程执行 + }) + .setOnFailure((Failure failure) -> { + // 在主线程执行 + }) + .start(); +``` + +## 生命周期绑定 + +  由于 OkHttps 并��赖于 Android,所以它并没有�供关于生命周期绑定的直接实现,但它的一些扩展机制让我们很容易就�以实现这个需求。在开始之�,我们首先��解何为生命周期绑定: + +> 所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� + +  现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在`Activity`或`Fragment`里,它的使用效果如下: + +```java +// 在 Activity 或 Fragment 内�起请求 +http.async("http://www.baidu.com") + .bind(getLifecycle()) // 绑定生命周期 + .setOnResponse((HttpResult result) -> { + Log.i("FirstFragment", "收到请求:" + result.toString()); + }) + .get(); +``` +  上述代�中的`getLifecycle()`是`Activity`或`Fragment`自带的方法,而`bind()`是`HttpTask`的现有方法。在�置好`HTTP`实例�,上述代��起的请求便�以感知`Activity`或`Fragment`的生命周期。 + +  那`HTTP`实例到底该如何�置呢? + +### 第一步:�置预处�器 + +```java +HTTP http = HTTP.builder() + ... // �略其它�置项 + .addPreprocessor((Preprocessor.PreChain chain) -> { + HttpTask task = chain.getTask(); + Object bound = task.getBound(); + // 判断 task 是�绑定了 Lifecycle 对象 + if (bound instanceof Lifecycle) { + // �新绑定一个 生命周期监视器(LCObserver)对象,它的定义�下一步 + task.bind(new LCObserver(task, (Lifecycle) bound)); + } + chain.proceed(); + }) + ... // �略其它�置项 + .build(); +``` + +### 第二步:定义生命周期监视器 + +```java +public class LCObserver implements LifecycleObserver { + + HttpTask task; + Lifecycle lifecycle; + + LCObserver(HttpTask task, Lifecycle lifecycle) { + this.task = task; + this.lifecycle = lifecycle; + lifecycle.addObserver(this); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + public void onStop() { + task.cancel(); // 在 ON_STOP 事件中,�消对应的 HTTP 任务 + } + + public void unbind() { + // 在请求完�之�移除监视器 + lifecycle.removeObserver(this); + } + +} +``` + +### 第三步:�置全局回调监� + +  以上两步其实已�实现了生命周期绑定的功能,但是在请求完�之�,我们需�在`lifecycle`中移除`LCObserver`对象: + +```java +HTTP http = HTTP.builder() + ... // �略其它�置项 + .completeListener((HttpTask task, HttpResult.State state) -> { + Object bound = task.getBound(); + // 判断 task 是�绑定了生命周期监视器(LCObserver)对象 + if (bound instanceof LCObserver) { + // 解绑监视器 + ((LCObserver) bound).unbind(); + } + return true; + }) + ... // �略其它�置项 + .build(); +``` + +**以上三步便在Android中实现了生命周期与HTTP请求绑定的功能** + +  �常简�,懒得敲代�的�学还�以 [点这里 OkHttps.java](https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java) 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。 + +  有需�的�学,�以直接下载下�使用,还�以基于它�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考[6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案),�比如扩展实现生命周期与下载事件绑定的功能,都�常简�。 diff --git a/docs/guide/getting-start.md b/docs/guide/getting-start.md index fda88cae..9d9bb495 100644 --- a/docs/guide/getting-start.md +++ b/docs/guide/getting-start.md @@ -1,20 +1,7 @@ -### 2 请求方法(GET|POST|PUT|DELETE) -  �步与异步的`HttpTask`都拥有`get`�`post`�`put`与`delete`方法。��的是:�步`HttpTask`的这些方法返回一个`HttpResult`,而异步`HttpTask`的这些方法返回一个`HttpCall`。 +## 解�请求结果 -```java -HttpResult res1 = http.sync("/users").get(); // �步 GET -HttpResult res2 = http.sync("/users").post(); // �步 POST -HttpResult res3 = http.sync("/users/1").put(); // �步 PUT -HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE -HttpCall call1 = http.async("/users").get(); // 异步 GET -HttpCall call2 = http.async("/users").post(); // 异步 POST -HttpCall call3 = http.async("/users/1").put(); // 异步 PUT -HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE -``` -### 3 解�请求结果 - -#### 3.1 回调函数 +### 回调函数   OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅: @@ -37,7 +24,7 @@ http.async("/users/{id}") // http://api.demo.com/users/1 >* �有异步请求��以设置这三�(�应|异常|完�)回调 >* �步请求直接返回结果,无需使用回调 -#### 3.2 HttpResult +### HttpResult   `HttpResult`是HTTP请求执行完�的结果,它是�步请求方法( `get`�`post`�`put`�`delete`)的返回值,也是异步请求�应回调(`OnResponse`)的�数,它定义了如下方法: @@ -109,7 +96,7 @@ System.out.println("size = " + size); ``` -#### 3.3 HttpCall +### HttpCall   `HttpCall`对象是异步请求方法(`get`�`post`�`put`�`delete`)的返回值,与`java`的`Future`接�很�,它有如下方法: @@ -131,7 +118,7 @@ System.out.println(success); // true System.out.println(call.isCanceled()); // true ``` -### 4 构建HTTP任务 +## 构建HTTP任务   `HTTP`对象的`sync`与`async`方法返回一个`HttpTask`对象,该对象�供了�链�调用的`addXXX`与`setXXX`等系列方法用于构建任务本身。 @@ -166,7 +153,7 @@ System.out.println(call.isCanceled()); // true * `bind(Object object)` 绑定一个对象,�用于实现Android里的生命周期绑定 -### 5 使用标签 +## 使用标签   有时候我们想对HTTP任务加以分类,这时候�以使用标签功能: @@ -200,9 +187,9 @@ System.out.println(count); // 输出 3 ```   标签除了�以用��消任务,在预处�器中它也�以�挥作用,请��[并行预处�器](#54-并行预处�器)与[串行预处�器](#55-串行预处�器)。 -### 6 �置 HTTP +## �置 HTTP -#### 6.1 设置 BaseUrl +### 设置 BaseUrl ```java HTTP http = HTTP.builder() @@ -225,7 +212,7 @@ http.sync("/auth/signin") // http://api.demo.com/auth/signin http.sync("https://www.baidu.com").get() ``` -#### 6.2 回调执行器 +### 回调执行器   OkHttps 默认所有回调都在 **IO线程** 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建`HTTP`时�置如下: @@ -238,7 +225,7 @@ HTTP http = HTTP.builder() ```   该�置默认 **影�所有回调**。 -#### 6.3 �置 OkHttpClient +### �置 OkHttpClient   与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下: @@ -260,7 +247,7 @@ HTTP http = HTTP.builder() .build(); ``` -#### 6.4 并行预处�器 +### 并行预处�器   预处�器(`Preprocessor`)�以让我们在请求�出之�对请求本身�一些改�,但与`OkHttp`的拦截器(`Interceptor`)��:预处�器�以让我们 **异步** 处�这些问题。 @@ -286,7 +273,7 @@ HTTP http = HTTP.builder() > * 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) > * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调监�(详�6.6章节) -#### 6.5 串行预处�器(TOKEN问题最佳解决方案) +### 串行预处�器(TOKEN问题最佳解决方案)   普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当`Token`过期时我们需�去刷新获�新`Token`,而刷新`Token`这个�作�能有一个任务去执行,因为如果`n`个任务�时执行的�,那么必有`n-1`个任务刚刷新得到的`Token`�能就立马失效了,而这是我们所�希望的。 @@ -309,7 +296,7 @@ HTTP http = HTTP.builder() ```   串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程� -#### 6.6 全局回调监� +### 全局回调监� ```java HTTP http = HTTP.builder() @@ -336,7 +323,7 @@ HTTP http = HTTP.builder() > * 拦截器处的�时机在请求�和�应�,全局回调监��在�应�,并且晚于拦截器 > * 全局回调监��以 **阻断**(return false)�个请求的具体回调,而拦截器�能 -#### 6.7 全局下载监� +### 全局下载监� ```java HTTP http = HTTP.builder() @@ -348,7 +335,7 @@ HTTP http = HTTP.builder() .build(); ``` -### 7 使用 HttpUtils 类 +## 使用 HttpUtils 类   类`HttpUtils`本是 [�身 HttpUtils](https://gitee.com/ejlchina-zhxu/httputils) 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。 @@ -380,229 +367,12 @@ List users = HttpUtils.sync("/users") .get().getBody().toList(User.class); ``` -### 8 文件下载 - -  OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例: - -```java -http.sync("/download/test.zip") - .get() // 使用 GET 方法(其它方法也�以,看�务器支�) - .getBody() // 得到报文体 - .toFile("D:/download/test.zip") // 下载到指定的路径 - .start(); // �动下载 - -http.sync("/download/test.zip").get().getBody() - .toFolder("D:/download") // 下载到指定的目录,文件�将根�下载信�自动生� - .start(); -``` -  或使用异步连接方�: - -```java -http.async("/download/test.zip") - .setOnResponse((HttpResult result) -> { - result.getBody().toFolder("D:/download").start(); - }) - .get(); -``` -  这里�说明一下:`sync`与`async`的区别在于连接�务器并得到�应这个过程的�步与异步(这个过程的耗时在大文件下载中�比��),而`start`方法�动的下载过程则都是异步的。 - -#### 8.1 下载进度监� - -  就直接上代�啦,诸�一看便懂: - -```java -http.sync("/download/test.zip") - .get() - .getBody() - .setStepBytes(1024) // 设置�接收 1024 个字节执行一次进度回调(�设置默认为 8192) - // .setStepRate(0.01) // 设置�接收 1% 执行一次进度回调(�设置以 StepBytes 为准) - .setOnProcess((Process process) -> { // 下载进度回调 - long doneBytes = process.getDoneBytes(); // 已下载字节数 - long totalBytes = process.getTotalBytes(); // 总共的字节数 - double rate = process.getRate(); // 已下载的比例 - boolean isDone = process.isDone(); // 是�下载完� - }) - .toFolder("D:/download/") // 指定下载的目录,文件�将根�下载信�自动生� - // .toFile("D:/download/test.zip") // 指定下载的路径,若文件已存在则覆盖 - .setOnSuccess((File file) -> { // 下载�功回调 - - }) - .start(); -``` -  值得一�的是:由于 OkHttps 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有`Content-Length`头),例如: - -```java -List users = http.sync("/users") - .get() - .getBody() - .setStepBytes(2) - .setOnProcess((Process process) -> { - System.out.println(process.getRate()); - }) - .toList(User.class); -``` - -#### 8.2 下载过程控制 - -  过于简�:还是直接上代�: - -```java -Ctrl ctrl = http.sync("/download/test.zip") - .get() - .getBody() - .setOnProcess((Process process) -> { - System.out.println(process.getRate()); - }) - .toFolder("D:/download/") - .start(); // 该方法返回一个下载过程控制器 - -ctrl.status(); // 下载状� -ctrl.pause(); // 暂�下载 -ctrl.resume(); // ��下载 -ctrl.cancel(); // �消下载(�时会删除文件,����) -``` -  无论是�步还是异步�起的下载请求,都�以�以上的控制: - -```java -http.async("/download/test.zip") - .setOnResponse((HttpResult result) -> { - // 拿到下载控制器 - Ctrl ctrl = result.getBody().toFolder("D:/download/").start(); - }) - .get(); -``` - -#### 8.3 实现断点续传 - -  OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到 **断点**,便将��的问题�得简�: - -```java -http.sync("/download/test.zip") - .get() - .getBody() - .toFolder("D:/download/") - .setOnFailure((Failure failure) -> { // 下载失败回调,以便接收诸如网络错误等失败信� - IOException e = failure.getException(); // 具体的异常信� - long doneBytes = failure.getDoneBytes(); // 已下载的字节数(断点),需��存,用于断点续传 - File file = failure.getFile(); // 下载生�的文件,需��存 ,用于断点续传(��存路径也�以) - }) - .start(); -``` -  下�代�实现续传: - -```java -long doneBytes = ... // 拿到�存的断点 -File file = ... // 待续传的文件 - -http.sync("/download/test.zip") - .setRange(doneBytes) // 设置断点(已下载的字节数) - .get() - .getBody() - .toFile(file) // 下载到�一个文件里 - .setAppended() // 开�文件追加模� - .setOnSuccess((File file) -> { - - }) - .setOnFailure((Failure failure) -> { - - }) - .start(); -``` - -#### 8.4 实现分�下载 - -  当文件很大时,有时候我们会考虑分�下载,与断点续传的�路是一样的,示例代�: - -```java -static String url = "http://api.demo.com/download/test.zip" - -public static void main(String[] args) { - long totalSize = HttpUtils.sync(url).get().getBody() - .close() // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭 - .getContentLength(); // 获得待下载文件的大�(由于未消费报文体,所以该请求�会消耗下载报文体的时间和网络��) - download(totalSize, 0); // 从第 0 �开始下载 - sleep(50000); // 等待下载完�(�然本例的主线程就结�啦) -} - -static void download(long totalSize, int index) { - long size = 3 * 1024 * 1024; // ��下载 3M - long start = index * size; - long end = Math.min(start + size, totalSize); - HttpUtils.sync(url) - .setRange(start, end) // 设置本次下载的范围 - .get().getBody() - .toFile("D:/download/test.zip") // 下载到�一个文件里 - .setAppended() // 开�文件追加模� - .setOnSuccess((File file) -> { - if (end < totalSize) { // 若未下载完,则继续下载下一� - download(totalSize, index + 1); - } else { - System.out.println("下载完�"); - } - }) - .start(); -} -``` - -### 9 文件上传 -  一个简�文件上传的示例: - -```java -http.sync("/upload") - .addFileParam("test", "D:/download/test.zip") - .post() // 上传�法一般使用 POST 或 PUT,看�务器支� -``` -  异步上传也是完全一样: - -```java -http.async("/upload") - .addFileParam("test", "D:/download/test.zip") - .post() -``` - -#### 9.1 上传进度监� - -  OkHttps 的上传进度监�,监�的是所有请求报文体的��进度,示例代�: - -```java -http.sync("/upload") - .addBodyParam("name", "Jack") - .addBodyParam("age", 20) - .addFileParam("avatar", "D:/image/avatar.jpg") - .setStepBytes(1024) // 设置��� 1024 个字节执行一次进度回调(�设置默认为 8192) - // .setStepRate(0.01) // 设置��� 1% 执行一次进度回调(�设置以 StepBytes 为准) - .setOnProcess((Process process) -> { // 上传进度回调 - long doneBytes = process.getDoneBytes(); // 已��字节数 - long totalBytes = process.getTotalBytes(); // 总共的字节数 - double rate = process.getRate(); // 已��的比例 - boolean isDone = process.isDone(); // 是���完� - }) - .post() -``` -  咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在`get/post`方法之�使用这些API,下载是在`getBody`方法之�使用。很好�解:`get/post`之�是准备��请求时段,有上传的�义,而`getBody`之�,已是报文�应的时段,当然是下载。 - -#### 9.2 上传过程控制 - -  上传文件的过程控制就很简�,和常规请求一样,�有异步�起的上传�以�消: - -```java -HttpCall call = http.async("/upload") - .addFileParam("test", "D:/download/test.zip") - .setOnProcess((Process process) -> { - System.out.println(process.getRate()); - }) - .post() - -call.cancel(); // �消上传 -``` -  上传就没有暂�和继续这个功能啦,应该没人有这个需求�? - -### 10 异常处� +## 异常处�   使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 -#### 10.1 �步请求的异常 +### �步请求的异常   默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 `try catch` ��获,例如: @@ -645,7 +415,7 @@ switch (result.getState()) { IOException error = result.getError(); ``` -#### 10.2 异步请求的异常 +### 异步请求的异常   异步请求最常用的异常处�方�就是设置一个异常回调: @@ -706,7 +476,7 @@ http.async("/users/1") }) .get(); ``` -### 11 �消请求的4�方� +## �消请求的4�方�   在 OkHttps 里�消请求共有 **4 �** 方��选: @@ -731,190 +501,3 @@ boolean canceled = task.cancel(); ```java http.cancelAll(); // �消所有请求 ``` - -### 12 回调线程自由切�(for Android) - -  在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 - -  在 **默认** 情况下,**所有回调** 函数都会 **在 IO 线程** 执行。为什么会设计如此呢?这是因为 OkHttps �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。 - -  但是在 Android 里使用 OkHttps 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器: - - ```java -HTTP http = HTTP.builder() - .callbackExecutor((Runnable run) -> { - // 实际编�中�以� Handler �出�,�需��次执行回调都�新创建 - new Handler(Looper.getMainLooper()).post(run); // 在主线程执行 - }) - .build(); -``` -  上述代�便实现了让 **所有** 的 **回调函数** 都在 **主线程(UI线程)** 执行的目的,如: - -```java -http.async("/users") - .addBodyParam("name", "Jack") - .setOnProcess((Process process) -> { - // 在主线程执行 - }) - .setOnResponse((HttpResult result) -> { - // 在主线程执行 - }) - .setOnException((Exception e) -> { - // 在主线程执行 - }) - .setOnComplete((State state) -> { - // 在主线程执行 - }) - .post(); -``` -  但是,如果�时还想让�些回调放在IO线程,实现 **自由切�**,怎么办呢?OkHttps 给出了�常�活的方法,如下: - -```java -http.async("/users") - .addBodyParam("name", "Jack") - .setOnProcess((Process process) -> { - // 在主线程执行 - }) - .nextOnIO() // 指定下一个回调在 IO 线程执行 - .setOnResponse((HttpResult result) -> { - // 在 IO 线程执行 - }) - .setOnException((Exception e) -> { - // 在主线程执行(没有指明 nextOnIO 则在回调执行器里执行) - }) - .nextOnIO() // 指定下一个回调在 IO 线程执行 - .setOnComplete((State state) -> { - // 在 IO 线程执行 - }) - .post(); -``` -  无论是哪一个回调,都�以使用`nextOnIO()`方法自由切�。�样,对于文件下载也是一样: - -```java -http.sync("/download/test.zip") - .get() - .getBody() - .setOnProcess((Process process) -> { - // 在主线程执行 - }) - .toFolder("D:/download/") - .nextOnIO() // 指定下一个回调在 IO 线程执行 - .setOnSuccess((File file) -> { - // 在 IO 线程执行 - }) - .setOnFailure((Failure failure) -> { - // 在主线程执行 - }) - .start(); -``` -### 13 实现生命周期绑定(for Android) - -  由于 OkHttps 并��赖于 Android,所以它并没有�供关于生命周期绑定的直接实现,但它的一些扩展机制让我们很容易就�以实现这个需求。在开始之�,我们首先��解何为生命周期绑定: - -> 所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� - -  现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在`Activity`或`Fragment`里,它的使用效果如下: - -```java -// 在 Activity 或 Fragment 内�起请求 -http.async("http://www.baidu.com") - .bind(getLifecycle()) // 绑定生命周期 - .setOnResponse((HttpResult result) -> { - Log.i("FirstFragment", "收到请求:" + result.toString()); - }) - .get(); -``` -  上述代�中的`getLifecycle()`是`Activity`或`Fragment`自带的方法,而`bind()`是`HttpTask`的现有方法。在�置好`HTTP`实例�,上述代��起的请求便�以感知`Activity`或`Fragment`的生命周期。 - -  那`HTTP`实例到底该如何�置呢? - -#### 第一步:�置预处�器 - -```java -HTTP http = HTTP.builder() - ... // �略其它�置项 - .addPreprocessor((Preprocessor.PreChain chain) -> { - HttpTask task = chain.getTask(); - Object bound = task.getBound(); - // 判断 task 是�绑定了 Lifecycle 对象 - if (bound instanceof Lifecycle) { - // �新绑定一个 生命周期监视器(LCObserver)对象,它的定义�下一步 - task.bind(new LCObserver(task, (Lifecycle) bound)); - } - chain.proceed(); - }) - ... // �略其它�置项 - .build(); -``` - -#### 第二步:定义生命周期监视器 - -```java -public class LCObserver implements LifecycleObserver { - - HttpTask task; - Lifecycle lifecycle; - - LCObserver(HttpTask task, Lifecycle lifecycle) { - this.task = task; - this.lifecycle = lifecycle; - lifecycle.addObserver(this); - } - - @OnLifecycleEvent(Lifecycle.Event.ON_STOP) - public void onStop() { - task.cancel(); // 在 ON_STOP 事件中,�消对应的 HTTP 任务 - } - - public void unbind() { - // 在请求完�之�移除监视器 - lifecycle.removeObserver(this); - } - -} -``` - -#### 第三步:�置全局回调监� - -  以上两步其实已�实现了生命周期绑定的功能,但是在请求完�之�,我们需�在`lifecycle`中移除`LCObserver`对象: - -```java -HTTP http = HTTP.builder() - ... // �略其它�置项 - .completeListener((HttpTask task, HttpResult.State state) -> { - Object bound = task.getBound(); - // 判断 task 是�绑定了生命周期监视器(LCObserver)对象 - if (bound instanceof LCObserver) { - // 解绑监视器 - ((LCObserver) bound).unbind(); - } - return true; - }) - ... // �略其它�置项 - .build(); -``` - -**以上三步便在Android中实现了生命周期与HTTP请求绑定的功能** - -  �常简�,懒得敲代�的�学还�以 [点这里 OkHttps.java](https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java) 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。 - -  有需�的�学,�以直接下载下�使用,还�以基于它�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考[6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案),�比如扩展实现生命周期与下载事件绑定的功能,都�常简�。 - - -## �期计划(v1.1.0) - -* 简化 WebSocket 编程:�直接�� JavaBean 对象消� -* 简化 WebSocket 编程:�直接接收 JavaBean 对象消� -* 简化 WebSocket 编程:�使用 Lambda 表达�进行 WebSocket 编程 - -## �系方� - -* 微信: -* 邮箱:zhou.xu@ejlchina.com - -## �与贡献 - -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. �交代� -4. 新建 Pull Request diff --git a/docs/guide/updown.md b/docs/guide/updown.md new file mode 100644 index 00000000..c1fffee4 --- /dev/null +++ b/docs/guide/updown.md @@ -0,0 +1,218 @@ + +## 文件下载 + +  OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例: + +```java +http.sync("/download/test.zip") + .get() // 使用 GET 方法(其它方法也�以,看�务器支�) + .getBody() // 得到报文体 + .toFile("D:/download/test.zip") // 下载到指定的路径 + .start(); // �动下载 + +http.sync("/download/test.zip").get().getBody() + .toFolder("D:/download") // 下载到指定的目录,文件�将根�下载信�自动生� + .start(); +``` +  或使用异步连接方�: + +```java +http.async("/download/test.zip") + .setOnResponse((HttpResult result) -> { + result.getBody().toFolder("D:/download").start(); + }) + .get(); +``` +  这里�说明一下:`sync`与`async`的区别在于连接�务器并得到�应这个过程的�步与异步(这个过程的耗时在大文件下载中�比��),而`start`方法�动的下载过程则都是异步的。 + +### 下载进度监� + +  就直接上代�啦,诸�一看便懂: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .setStepBytes(1024) // 设置�接收 1024 个字节执行一次进度回调(�设置默认为 8192) + // .setStepRate(0.01) // 设置�接收 1% 执行一次进度回调(�设置以 StepBytes 为准) + .setOnProcess((Process process) -> { // 下载进度回调 + long doneBytes = process.getDoneBytes(); // 已下载字节数 + long totalBytes = process.getTotalBytes(); // 总共的字节数 + double rate = process.getRate(); // 已下载的比例 + boolean isDone = process.isDone(); // 是�下载完� + }) + .toFolder("D:/download/") // 指定下载的目录,文件�将根�下载信�自动生� + // .toFile("D:/download/test.zip") // 指定下载的路径,若文件已存在则覆盖 + .setOnSuccess((File file) -> { // 下载�功回调 + + }) + .start(); +``` +  值得一�的是:由于 OkHttps 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有`Content-Length`头),例如: + +```java +List users = http.sync("/users") + .get() + .getBody() + .setStepBytes(2) + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .toList(User.class); +``` + +### 下载过程控制 + +  过于简�:还是直接上代�: + +```java +Ctrl ctrl = http.sync("/download/test.zip") + .get() + .getBody() + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .toFolder("D:/download/") + .start(); // 该方法返回一个下载过程控制器 + +ctrl.status(); // 下载状� +ctrl.pause(); // 暂�下载 +ctrl.resume(); // ��下载 +ctrl.cancel(); // �消下载(�时会删除文件,����) +``` +  无论是�步还是异步�起的下载请求,都�以�以上的控制: + +```java +http.async("/download/test.zip") + .setOnResponse((HttpResult result) -> { + // 拿到下载控制器 + Ctrl ctrl = result.getBody().toFolder("D:/download/").start(); + }) + .get(); +``` + +### 实现断点续传 + +  OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到 **断点**,便将��的问题�得简�: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .toFolder("D:/download/") + .setOnFailure((Failure failure) -> { // 下载失败回调,以便接收诸如网络错误等失败信� + IOException e = failure.getException(); // 具体的异常信� + long doneBytes = failure.getDoneBytes(); // 已下载的字节数(断点),需��存,用于断点续传 + File file = failure.getFile(); // 下载生�的文件,需��存 ,用于断点续传(��存路径也�以) + }) + .start(); +``` +  下�代�实现续传: + +```java +long doneBytes = ... // 拿到�存的断点 +File file = ... // 待续传的文件 + +http.sync("/download/test.zip") + .setRange(doneBytes) // 设置断点(已下载的字节数) + .get() + .getBody() + .toFile(file) // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + + }) + .setOnFailure((Failure failure) -> { + + }) + .start(); +``` + +### 实现分�下载 + +  当文件很大时,有时候我们会考虑分�下载,与断点续传的�路是一样的,示例代�: + +```java +static String url = "http://api.demo.com/download/test.zip" + +public static void main(String[] args) { + long totalSize = HttpUtils.sync(url).get().getBody() + .close() // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); // 获得待下载文件的大�(由于未消费报文体,所以该请求�会消耗下载报文体的时间和网络��) + download(totalSize, 0); // 从第 0 �开始下载 + sleep(50000); // 等待下载完�(�然本例的主线程就结�啦) +} + +static void download(long totalSize, int index) { + long size = 3 * 1024 * 1024; // ��下载 3M + long start = index * size; + long end = Math.min(start + size, totalSize); + HttpUtils.sync(url) + .setRange(start, end) // 设置本次下载的范围 + .get().getBody() + .toFile("D:/download/test.zip") // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + if (end < totalSize) { // 若未下载完,则继续下载下一� + download(totalSize, index + 1); + } else { + System.out.println("下载完�"); + } + }) + .start(); +} +``` + +## 文件上传 + +  一个简�文件上传的示例: + +```java +http.sync("/upload") + .addFileParam("test", "D:/download/test.zip") + .post() // 上传�法一般使用 POST 或 PUT,看�务器支� +``` +  异步上传也是完全一样: + +```java +http.async("/upload") + .addFileParam("test", "D:/download/test.zip") + .post() +``` + +### 上传进度监� + +  OkHttps 的上传进度监�,监�的是所有请求报文体的��进度,示例代�: + +```java +http.sync("/upload") + .addBodyParam("name", "Jack") + .addBodyParam("age", 20) + .addFileParam("avatar", "D:/image/avatar.jpg") + .setStepBytes(1024) // 设置��� 1024 个字节执行一次进度回调(�设置默认为 8192) + // .setStepRate(0.01) // 设置��� 1% 执行一次进度回调(�设置以 StepBytes 为准) + .setOnProcess((Process process) -> { // 上传进度回调 + long doneBytes = process.getDoneBytes(); // 已��字节数 + long totalBytes = process.getTotalBytes(); // 总共的字节数 + double rate = process.getRate(); // 已��的比例 + boolean isDone = process.isDone(); // 是���完� + }) + .post() +``` +  咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在`get/post`方法之�使用这些API,下载是在`getBody`方法之�使用。很好�解:`get/post`之�是准备��请求时段,有上传的�义,而`getBody`之�,已是报文�应的时段,当然是下载。 + +### 上传过程控制 + +  上传文件的过程控制就很简�,和常规请求一样,�有异步�起的上传�以�消: + +```java +HttpCall call = http.async("/upload") + .addFileParam("test", "D:/download/test.zip") + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .post() + +call.cancel(); // �消上传 +``` +  上传就没有暂�和继续这个功能啦,应该没人有这个需求�? \ No newline at end of file From 636cd57228cc689fe8b40fbcec211e8dd202db62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 14:08:29 +0800 Subject: [PATCH 180/924] docs --- docs/.vuepress/config.js | 8 +- docs/README.md | 4 +- docs/guide/README.md | 32 +-- docs/guide/android.md | 9 +- docs/guide/configuration.md | 150 +++++++++++ docs/guide/features.md | 164 ++++++++++++ docs/guide/foundation.md | 203 +++++++++++++++ docs/guide/getting-start.md | 503 ------------------------------------ 8 files changed, 544 insertions(+), 529 deletions(-) create mode 100644 docs/guide/configuration.md create mode 100644 docs/guide/features.md create mode 100644 docs/guide/foundation.md delete mode 100644 docs/guide/getting-start.md diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 7f15ba16..cb8d6db8 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -13,9 +13,15 @@ module.exports = { ], sidebar: [ ['/guide/', '起步'], - ['/guide/getting-start', '一探究竟'], + ['/guide/foundation', '基础'], + ['/guide/configuration', '�置'], + ['/guide/features', '特色'], + ['/guide/updown', '上传下载'], ['/guide/android', '安�'], ], sidebarDepth: 2 + }, + markdown: { + lineNumbers: true } } \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 09bbef40..fcb54b8f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ features: - title: 更多实用特性 details: URL ��符�Lambda 回调�JSON自动�装解��OkHttp 的特性:拦截器�连接池�CookieJar 等。 -footer: Apache Licensed | Copyright © 2020-present Troy Zhou +footer: Apache Licensed | Copyright © 2020-present ejlchina --- @@ -38,4 +38,4 @@ http.async("/users/jack") // http://api.demo.com/users/jack .get(); // GET请求 ``` -**
就这么简�,你已学会 OkHttps 90% 的用法�
** \ No newline at end of file +**
就这么简�,你已学会了 90% 的用法�
** \ No newline at end of file diff --git a/docs/guide/README.md b/docs/guide/README.md index f2cda81c..0725a00d 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -9,10 +9,11 @@ * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 -> 1. OkHttps �常轻�(59Kb),是 Retrofit(124Kb)的一�,并且更加的开箱�用,API 也更加自然和语义化。 -> 2. OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit �� -> 3. OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。 - +::: tip +* OkHttps �常轻�(59Kb),仅是 Retrofit(124Kb)的一�,并且更加的开箱�用,API 也更加自然和语义化。 +* OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit �� +* OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。 +::: ## 安装 @@ -27,7 +28,9 @@ ``` ### Gradle -`implementation 'com.ejlchina:okhttps:1.0.5'` +```groovy +implementation 'com.ejlchina:okhttps:1.0.5' +``` 安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��: @@ -50,14 +53,14 @@ HTTP http = HTTP.builder().build(); ```   以上代�构建了一个最简�的`HTTP`实例,它拥有以下方法: -* `async(String url)` 开始一个异步请求 * `sync(String url)` 开始一个�步请求 +* `async(String url)` 开始一个异步请求 * `cancel(String tag)` 按标签�消请求 * `cancelAll()` �消所有HTTP任务,包括�步和异步 * `request(Request request)` OkHttp 原生请求 * `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 -  为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(请��[5.1 设置 BaseUrl](#51-设置-baseurl)): +  为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(详� [设置 BaseUrl](/guide/configuration.html#设置-baseurl)): ```java HTTP http = HTTP.builder() @@ -93,19 +96,4 @@ http.async("/users/1") // http://api.demo.com/users/1   方法`async`返回一个异步`HttpTask`,�链�使用。 -### 请求方法 - -  �步与异步的`HttpTask`都拥有`get`�`post`�`put`与`delete`方法。��的是:�步`HttpTask`的这些方法返回一个`HttpResult`,而异步`HttpTask`的这些方法返回一个`HttpCall`。 - -```java -HttpResult res1 = http.sync("/users").get(); // �步 GET -HttpResult res2 = http.sync("/users").post(); // �步 POST -HttpResult res3 = http.sync("/users/1").put(); // �步 PUT -HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE -HttpCall call1 = http.async("/users").get(); // 异步 GET -HttpCall call2 = http.async("/users").post(); // 异步 POST -HttpCall call3 = http.async("/users/1").put(); // 异步 PUT -HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE -``` - **至此,你已轻�学会了 OkHttps 95% 的常规用法�但别急,��还有更精彩的。** \ No newline at end of file diff --git a/docs/guide/android.md b/docs/guide/android.md index 0ec1dbbf..534edb64 100644 --- a/docs/guide/android.md +++ b/docs/guide/android.md @@ -4,6 +4,8 @@   在 **默认** 情况下,**所有回调** 函数都会 **在 IO 线程** 执行。为什么会设计如此呢?这是因为 OkHttps �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。 +### �置 +   但是在 Android 里使用 OkHttps 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器: ```java @@ -14,6 +16,9 @@ HTTP http = HTTP.builder() }) .build(); ``` + +### 用例 +   上述代�便实现了让 **所有** 的 **回调函数** 都在 **主线程(UI线程)** 执行的目的,如: ```java @@ -78,7 +83,9 @@ http.sync("/download/test.zip")   由于 OkHttps 并��赖于 Android,所以它并没有�供关于生命周期绑定的直接实现,但它的一些扩展机制让我们很容易就�以实现这个需求。在开始之�,我们首先��解何为生命周期绑定: -> 所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� +::: tip HTTP 请求的生命周期绑定 +所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� +:::   现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在`Activity`或`Fragment`里,它的使用效果如下: diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md new file mode 100644 index 00000000..8d8fbba8 --- /dev/null +++ b/docs/guide/configuration.md @@ -0,0 +1,150 @@ +## 设置 BaseUrl + +```java +HTTP http = HTTP.builder() + .baseUrl("http://api.demo.com") // 设置 BaseUrl + .build(); +``` +  该�置全局生效,在�置了`BaseUrl`之�,具体的请求便�以�略`BaseUrl`部分,使得代�更加简�,例如: + +```java +http.sync("/users").get() // http://api.demo.com/users + +http.sync("/auth/signin") // http://api.demo.com/auth/signin + .addBodyParam("username", "Jackson") + .addBodyParam("password", "xxxxxx") + .post() // POST请求 +``` +  在�置了`BaseUrl`之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�: + +```java +http.sync("https://www.baidu.com").get() +``` + +## 回调执行器 + +  OkHttps 默认所有回调都在 **IO线程** 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建`HTTP`时�置如下: + +```java +HTTP http = HTTP.builder() + .callbackExecutor((Runnable run) -> { + runOnUiThread(run); // 在UI线程执行 + }) + .build(); +``` +  该�置默认 **影�所有回调**。 + +## �置 OkHttpClient + +  与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下: + +```java +HTTP http = HTTP.builder() + .config((Builder builder) -> { + // �置连接池 最�10个连接(��置默认为 5) + builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES)); + // �置连接超时时间(默认10秒) + builder.connectTimeout(20, TimeUnit.SECONDS); + // �置拦截器 + builder.addInterceptor((Chain chain) -> { + Request request = chain.request(); + // 必须�步返回,拦截器内无法执行异步�作 + return chain.proceed(request); + }); + // 其它�置: CookieJar�SSL�缓存�代��事件监�... + }) + .build(); +``` + +## 并行预处�器 + +  预处�器(`Preprocessor`)�以让我们在请求�出之�对请求本身�一些改�,但与`OkHttp`的拦截器(`Interceptor`)��:预处�器�以让我们 **异步** 处�这些问题。 + +  例如,当我们想为请求任务自动添加`Token`头信�,而`Token`�能通过异步方法`requestToken`获�时,这时使用`Interceptor`就很难处�了,但�以使用预处�器轻�解决: + +```java +HTTP http = HTTP.builder() + .addPreprocessor((PreChain chain) -> { + HttpTask task = chain.getTask();// 获得当�的HTTP任务 + if (!task.isTagged("Auth")) { // 根�标签判断该任务是�需�Token + return; + } + requestToken((String token) -> { // 异步获� Token + task.addHeader("Token", token);// 为任务添加头信� + chain.proceed(); // 继续当�的任务 + }); + }) + .build(); +``` +  和`Interceptor`一样,`Preprocessor`也�以添加多个。他们之间的区别如下: + +::: tip 拦截器与预处�器的区别 +* 拦截器�能处��步�作,预处�器支�处�异步�作 +* 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) +* 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调监�(详�6.6章节) +::: + +## 串行预处�器(TOKEN问题最佳解决方案) + +  普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当`Token`过期时我们需�去刷新获�新`Token`,而刷新`Token`这个�作�能有一个任务去执行,因为如果`n`个任务�时执行的�,那么必有`n-1`个任务刚刷新得到的`Token`�能就立马失效了,而这是我们所�希望的。 + +  为了解决这个问题,OkHttps �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器: + +```java +HTTP http = HTTP.builder() + .addSerialPreprocessor((PreChain chain) -> { + HttpTask task = chain.getTask(); + if (!task.isTagged("Auth")) { + return; + } + // 检查过期,若需�则刷新Token + requestTokenAndRefreshIfExpired((String token) -> { + task.addHeader("Token", token); + chain.proceed(); // 调用此方法�,�会有其它任务进入该处�器 + }); + }) + .build(); +``` +  串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程� + +## 全局回调监� + +  全局回调是实际开�中�常需�的功能,比如对�务器�应的状��进行统一处�等,�时 OkHttps 的全局回调还具有 **回调阻断** 的功能: + +```java +HTTP http = HTTP.builder() + .responseListener((HttpTask task, HttpResult result) -> { + // 所有请求�应�都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行 + }) + .completeListener((HttpTask task, State state) -> { + // 所有请求执行完都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行 + }) + .exceptionListener((HttpTask task, IOException error) -> { + // 所有请求�生异常都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 + }) + .build(); +``` + +::: tip 全局回调监�与拦截器的异�: +* 拦截器�以添加多个,全局回调监�分三�,��最多添加一个 +* 拦截器处的�时机在请求�和�应�,全局回调监��在�应�,并且晚于拦截器 +* 全局回调监��以 **阻断**(return false)�个请求的具体回调,而拦截器�能 +::: + +## 全局下载监� + +```java +HTTP http = HTTP.builder() + .downloadListener((HttpTask task, Download download) -> { + // 所有下载在开始之�都会先走这里 + Ctrl ctrl = download.getCtrl(); // 下载控制器 + + }) + .build(); +``` \ No newline at end of file diff --git a/docs/guide/features.md b/docs/guide/features.md new file mode 100644 index 00000000..fedc980f --- /dev/null +++ b/docs/guide/features.md @@ -0,0 +1,164 @@ +## 使用 HttpUtils 类 + +  类`HttpUtils`本是 [�身 HttpUtils](https://gitee.com/ejlchina-zhxu/httputils) 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。 + +  类`HttpUtils`共定义了四个��方法: + +* `of(HTTP http)` �置`HttpUtils`�有的`HTTP`实例(�调用此方法�默认使用一个没有没有�过任何�置的`HTTP`懒实例) +* `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) +* `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) +* `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) +* `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) +* `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) +* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 +  也就是说,能使用`http`实例的地方,都�以使用`HttpUtils`类,例如: + +```java +// 在�置HTTP实例之�,�能使用全路径方� +List roles = HttpUtils.sync("http://api.demo.com/roles") + .get().getBody().toList(Role.class); + +// �置HTTP实例,全局生效 +HttpUtils.of(HTTP.builder() + .baseUrl("http://api.demo.com") + .build()); + +// 内部使用新的HTTP实例 +List users = HttpUtils.sync("/users") + .get().getBody().toList(User.class); +``` + +## 异常处� + +  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 + +### �步请求的异常 + +  默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 `try catch` ��获,例如: + +```java +try { + HttpResult result = http.sync("/users/1").get(); +} catch (HttpException e) { + Throwable cause = e.getCause(); // 得到异常原因 + if (cause instanceof ConnectException) { + // 当没网络时,会抛出连接异常 + } + if (cause instanceof SocketTimeoutException) { + // 当接�长时间未�应,会抛出超时异常 + } + if (cause instanceof UnknownHostException) { + // 当把域�或IP写错,会抛出 UnknownHost 异常 + } + // ... +} +``` +  这�传统的异常处�方�,当然�以解决问题,但 OkHttps 有更佳的方案: + +```java +// 方法 nothrow() 让异常�直接抛出 +HttpResult result = http.sync("/users/1").nothrow().get(); +// 判断执行状� +switch (result.getState()) { + case RESPONSED: // 请求已正常�应 + break; + case CANCELED: // 请求已被�消 + break; + case NETWORK_ERROR: // 网络错误,说明用户没网了 + break; + case TIMEOUT: // 请求超时 + break; + case EXCEPTION: // 其它异常 + break; +} +// 还�以获得具体的异常信� +IOException error = result.getError(); +``` + +### 异步请求的异常 + +  异步请求最常用的异常处�方�就是设置一个异常回调: + +```java +http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .setOnException((IOException e) -> { + // 这里处�请求异常 + }) + .get(); +``` +  当然,还有一个全局异常监�(`ExceptionListener`): + +```java +HTTP http = HTTP.builder() + .exceptionListener((HttpTask task, IOException error) -> { + // 所有请求�生异常都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 + }) + .build(); +``` +  如果�设置`OnException`回调,也没有`ExceptionListener`,�生异常时会在 **IO 线程** 中�上抛出,外层无法�获: + +```java +try { + http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .get(); +} catch (HttpException e) { + // 这�方�是�获�到异常的������ +} +``` +  �使没有`OnException`回调,�生异常时,�然会走`OnComplete`回调,如果设置了的�: + +```java +http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .setOnComplete((State state) -> { + // �生异常,会先执行这里,�以根� state 判断�生了什么 + // 但执行完��然会在IO线程中�上抛出 + }) + .get(); +``` +  如果就是想 **�处�异常,也��上抛出**,�生错误完全无视,�以�到�?�以�还是使用`nothrow()`方法: + +```java +http.async("/users/1") + .nothrow() // 告诉 OkHttps �生异常时��外抛出 + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .get(); +``` + +## �消请求 + +  在 OkHttps 里�消请求共有 **4 �** 方��选: + +* 使用`HttpCall#cancel()`�消�个请求(适用于异步请求,[详� 3.3 章节](#33-httpcall)) +* 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) + +```java +HttpTask task = http.async("/users") + .setOnResponse((HttpResult result) -> { + // �应回调 + }); + +task.get(); // �起 GET 请求 + +// �消请求,并返回是��消�功 +boolean canceled = task.cancel(); +``` + +* 使用`HTTP#cancel(String tag)`按标签批��消请求(适用于所有请求,[详�第 5 章节](#5-使用标签)) +* 使用`HTTP#cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) + +```java +http.cancelAll(); // �消所有请求 +``` \ No newline at end of file diff --git a/docs/guide/foundation.md b/docs/guide/foundation.md new file mode 100644 index 00000000..b0a3b173 --- /dev/null +++ b/docs/guide/foundation.md @@ -0,0 +1,203 @@ +## 请求方法 + +  �步与异步的`HttpTask`都拥有`get`�`post`�`put`与`delete`方法。��的是:�步`HttpTask`的这些方法返回一个`HttpResult`,而异步`HttpTask`的这些方法返回一个`HttpCall`。 + +```java +HttpResult res1 = http.sync("/users").get(); // �步 GET +HttpResult res2 = http.sync("/users").post(); // �步 POST +HttpResult res3 = http.sync("/users/1").put(); // �步 PUT +HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE +HttpCall call1 = http.async("/users").get(); // 异步 GET +HttpCall call2 = http.async("/users").post(); // 异步 POST +HttpCall call3 = http.async("/users/1").put(); // 异步 PUT +HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE +``` + +## 回调函数 + +  OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅: + +```java +http.async("/users/{id}") // http://api.demo.com/users/1 + .addPathParam("id", 1) + .setOnResponse((HttpResult result) -> { + // �应回调 + }) + .setOnException((IOException e) -> { + // 异常回调 + }) + .setOnComplete((State state) -> { + // 完�回调,无论�功失败都会执行 + // 并且在 �应|异常回调 之�执行 + }) + .get(); +``` + +  OkHttps �时还支� **全局回调** 和 **回调阻断** 机制,详� [全局回调监�](/guide/configuration.html#全局回调监�)。 + +::: tip +* �有异步请求��以设置这三�(�应|异常|完�)回调 +* �步请求直接返回结果,无需使用回调 +::: + +## HttpResult + +  `HttpResult`是HTTP请求执行完�的结果,它是�步请求方法( `get`�`post`�`put`�`delete`)的返回值,也是异步请求�应回调(`OnResponse`)的�数,它定义了如下方法: + +* `getState()` 得到请求执行状�枚举,它有以下�值: + * `State.CANCELED` 请求被�消 + * `State.RESPONSED` 已收到�应 + * `State.TIMEOUT` 请求超时 + * `State.NETWORK_ERROR` 网络错误 + * `State.EXCEPTION` 其它请求异常 +* `getStatus()` 得到HTTP状�� +* `isSuccessful()` 是��应�功,状��在 [200..300) 之间 +* `getHeaders()` 得到HTTP�应头 +* `getHeaders(String name)` 得到HTTP�应头 +* `getHeader(String name)` 得到HTTP�应头 +* `getBody()` 得到�应报文体`Body`实例,它定义了如下方法(对�一个`Body`实例,以下的`toXXX()`类方法�能使用一个且仅能调用一次,除�先使用 cache 方法): + * `toBytes()` 返回字节数组 + * `toByteStream()` 返回字节输入� + * `toCharStream()` 返回字符输入� + * `toString()` 返回字符串 + * `toJsonObject()` 返回Json对象 + * `toJsonArray()` 返回Json数组 + * `toBean(Class type)` 返回根�type自动json解��的JavaBean + * `toList(Class type)` 返回根�type自动json解��的JavaBean列表 + * `toFile(String filePath)` 下载到指定路径 + * `toFile(File file)` 下载到指定文件 + * `toFolder(String dirPath)` 下载到指定目录 + * `toFolder(File dir)` 下载到指定目录 + * `getContentType()` 返回报文体的媒体类型 + * `getContentLength()` 返回报文体的字节长度 + * `cache()` 缓存报文体,开�缓存����使用`toXXX()`类方法 + * `close()` 关闭报文体,未对报文体�任何消费时使用,比如�读�报文头 +* `getError()` 执行中�生的异常,自动�获执行请求时�生的 网络超时�网络错误 和 其它IO异常 +* `close()` 关闭报文,未对报文体�任何消费时使用,比如�读�长度 + +  示例,请求结果自动转Bean和List: + +```java +// 自动转Bean +Order order = http.sync("/orders/1") + .get().getBody().toBean(Order.class); + +// 自动转List +List orders = http.sync("/orders") + .get().getBody().toList(Order.class); +``` + +  示例,使用 cache 方法: + +```java +Body body = http.sync("/orders").get().getBody().cache(); + +// 使用 cache �,�以多次使用 toXXX() 方法 +System.out.println(body.toString()); +System.out.println(body.toJsonArray()); +System.out.println(body.toList(Order.class)); +``` + +  示例,获�下载文件的大�: + +```java +long size = http.sync("/download/test.zip") + .get().getBody() + .close() // �是想获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); // 获得待下载文件的大� + +// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络�� + +System.out.println("size = " + size); +``` + +## HttpCall + +  `HttpCall`对象是异步请求方法(`get`�`post`�`put`�`delete`)的返回值,与`java`的`Future`接�很�,它有如下方法: + +* `cancel()` �消本次请求,返回�消结果 +* `isCanceled()` 返回请求是�被�消 +* `isDone()` 返回是�执行完�,包��消和失败 +* `getResult()` 返回执行结果`HttpResult`对象,若请求未执行完,则挂起当�线程直到执行完��返回 + +  �消一个异步请求示例: + +```java +HttpCall call = http.async("/users/1").get(); + +System.out.println(call.isCanceled()); // false + +boolean success = call.cancel(); // �消请求 + +System.out.println(success); // true +System.out.println(call.isCanceled()); // true +``` + +## 构建HTTP任务 + +  `HTTP`对象的`sync`与`async`方法返回一个`HttpTask`对象,该对象�供了�链�调用的`addXXX`与`setXXX`等系列方法用于构建任务本身。 + +* `addHeader(String name, String value)` 添加请求头 +* `addHeader(Map headers)` 添加请求头 + +* `addPathParam(String name, Object value)` 添加路径�数:替�URL里的{name}��符 +* `addPathParam(Map params)` 添加路径�数:替�URL里的{name}��符 + +* `addUrlParam(String name, Object value)` 添加URL�数:拼接在URL的?之�(查询�数) +* `addUrlParam(Map params)` 添加URL�数:拼接在URL的?之�(查询�数) + +* `addBodyParam(String name, Object value)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) +* `addBodyParam(Map params)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) + +* `addJsonParam(String name, Object value)` 添加Json�数:请求体为Json(支�多层结构) +* `addJsonParam(Map params)` 添加Json�数:请求体为Json(支�多层结构) + +* `setRequestJson(Object json)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean +* `setRequestJson(Object bean, String dateFormat)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean + +* `addFileParam(String name, String filePath)` 上传文件 +* `addFileParam(String name, File file)` 上传文件 +* `addFileParam(String name, String type, InputStream inputStream)` 上传文件 +* `addFileParam(String name, String type, String fileName, InputStream input)` 上传文件 +* `addFileParam(String name, String type, byte[] content)` 上传文件 +* `addFileParam(String name, String type, String fileName, byte[] content)` 上传文件 + +* `setTag(String tag)` 为HTTP任务添加标签 +* `setRange(long rangeStart)` 设置Range头信�,用于[断点续传](/guide/updown.html#实现断点续传) +* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,�用于[分�下载](/guide/updown.html#实现分�下载) + +* `bind(Object object)` 绑定一个对象,�用于实现Android里的[生命周期绑定](/guide/android.html#生命周期绑定) + +## 使用标签 + +  有时候我们想对HTTP任务加以分类,这时候�以使用标签功能: + +```java +http.async("/users") //(1) + .setTag("A") + .get(); + +http.async("/users") //(2) + .setTag("A.B") + .get(); + +http.async("/users") //(3) + .setTag("B") + .get(); + +http.async("/users") //(4) + .setTag("B") + .setTag("C") // 从 v1.0.4 标签将以追加模�添加,等效于 setTag("B.C") + .get(); + +http.async("/users") //(5) + .setTag("C") + .get(); +``` +  当使用标签�,就�以按标签批�的对HTTP任务进行�消: + +```java +int count = http.cancel("B"); //(2)(3)(4)被�消(�消标签包�"B"的任务) +System.out.println(count); // 输出 3 +``` +  标签除了�以用��消任务,在预处�器中它也�以�挥作用,请�� [并行预处�器](/guide/configuration.html#并行预处�器) 与 [串行预处�器(token问题最佳解决方案)](/guide/configuration.html#串行预处�器(token问题最佳解决方案))。 diff --git a/docs/guide/getting-start.md b/docs/guide/getting-start.md deleted file mode 100644 index 9d9bb495..00000000 --- a/docs/guide/getting-start.md +++ /dev/null @@ -1,503 +0,0 @@ - -## 解�请求结果 - -### 回调函数 - -  OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅: - -```java -http.async("/users/{id}") // http://api.demo.com/users/1 - .addPathParam("id", 1) - .setOnResponse((HttpResult result) -> { - // �应回调 - }) - .setOnException((IOException e) -> { - // 异常回调 - }) - .setOnComplete((State state) -> { - // 完�回调,无论�功失败都会执行 - // 并且在 �应|异常回调 之�执行 - }) - .get(); -``` - ->* �有异步请求��以设置这三�(�应|异常|完�)回调 ->* �步请求直接返回结果,无需使用回调 - -### HttpResult - -  `HttpResult`是HTTP请求执行完�的结果,它是�步请求方法( `get`�`post`�`put`�`delete`)的返回值,也是异步请求�应回调(`OnResponse`)的�数,它定义了如下方法: - -* `getState()` 得到请求执行状�枚举,它有以下�值: - * `State.CANCELED` 请求被�消 - * `State.RESPONSED` 已收到�应 - * `State.TIMEOUT` 请求超时 - * `State.NETWORK_ERROR` 网络错误 - * `State.EXCEPTION` 其它请求异常 -* `getStatus()` 得到HTTP状�� -* `isSuccessful()` 是��应�功,状��在 [200..300) 之间 -* `getHeaders()` 得到HTTP�应头 -* `getHeaders(String name)` 得到HTTP�应头 -* `getHeader(String name)` 得到HTTP�应头 -* `getBody()` 得到�应报文体`Body`实例,它定义了如下方法(对�一个`Body`实例,以下的`toXXX()`类方法�能使用一个且仅能调用一次,除�先使用 cache 方法): - * `toBytes()` 返回字节数组 - * `toByteStream()` 返回字节输入� - * `toCharStream()` 返回字符输入� - * `toString()` 返回字符串 - * `toJsonObject()` 返回Json对象 - * `toJsonArray()` 返回Json数组 - * `toBean(Class type)` 返回根�type自动json解��的JavaBean - * `toList(Class type)` 返回根�type自动json解��的JavaBean列表 - * `toFile(String filePath)` 下载到指定路径 - * `toFile(File file)` 下载到指定文件 - * `toFolder(String dirPath)` 下载到指定目录 - * `toFolder(File dir)` 下载到指定目录 - * `getContentType()` 返回报文体的媒体类型 - * `getContentLength()` 返回报文体的字节长度 - * `cache()` 缓存报文体,开�缓存����使用`toXXX()`类方法 - * `close()` 关闭报文体,未对报文体�任何消费时使用,比如�读�报文头 -* `getError()` 执行中�生的异常,自动�获执行请求时�生的 网络超时�网络错误 和 其它IO异常 -* `close()` 关闭报文,未对报文体�任何消费时使用,比如�读�长度 - -  示例,请求结果自动转Bean和List: - -```java -// 自动转Bean -Order order = http.sync("/orders/1") - .get().getBody().toBean(Order.class); - -// 自动转List -List orders = http.sync("/orders") - .get().getBody().toList(Order.class); -``` - -  示例,使用 cache 方法: - -```java -Body body = http.sync("/orders").get().getBody().cache(); - -// 使用 cache �,�以多次使用 toXXX() 方法 -System.out.println(body.toString()); -System.out.println(body.toJsonArray()); -System.out.println(body.toList(Order.class)); -``` - -  示例,获�下载文件的大�: - -```java -long size = http.sync("/download/test.zip") - .get().getBody() - .close() // �是想获得文件大�,�消费报文体,所以直接关闭 - .getContentLength(); // 获得待下载文件的大� - -// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络�� - -System.out.println("size = " + size); -``` - - -### HttpCall - -  `HttpCall`对象是异步请求方法(`get`�`post`�`put`�`delete`)的返回值,与`java`的`Future`接�很�,它有如下方法: - -* `cancel()` �消本次请求,返回�消结果 -* `isCanceled()` 返回请求是�被�消 -* `isDone()` 返回是�执行完�,包��消和失败 -* `getResult()` 返回执行结果`HttpResult`对象,若请求未执行完,则挂起当�线程直到执行完��返回 - -  �消一个异步请求示例: - -```java -HttpCall call = http.async("/users/1").get(); - -System.out.println(call.isCanceled()); // false - -boolean success = call.cancel(); // �消请求 - -System.out.println(success); // true -System.out.println(call.isCanceled()); // true -``` - -## 构建HTTP任务 - -  `HTTP`对象的`sync`与`async`方法返回一个`HttpTask`对象,该对象�供了�链�调用的`addXXX`与`setXXX`等系列方法用于构建任务本身。 - -* `addHeader(String name, String value)` 添加请求头 -* `addHeader(Map headers)` 添加请求头 - -* `addPathParam(String name, Object value)` 添加路径�数:替�URL里的{name}��符 -* `addPathParam(Map params)` 添加路径�数:替�URL里的{name}��符 - -* `addUrlParam(String name, Object value)` 添加URL�数:拼接在URL的?之�(查询�数) -* `addUrlParam(Map params)` 添加URL�数:拼接在URL的?之�(查询�数) - -* `addBodyParam(String name, Object value)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) -* `addBodyParam(Map params)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) - -* `addJsonParam(String name, Object value)` 添加Json�数:请求体为Json(支�多层结构) -* `addJsonParam(Map params)` 添加Json�数:请求体为Json(支�多层结构) - -* `setRequestJson(Object json)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean -* `setRequestJson(Object bean, String dateFormat)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean - -* `addFileParam(String name, String filePath)` 上传文件 -* `addFileParam(String name, File file)` 上传文件 -* `addFileParam(String name, String type, InputStream inputStream)` 上传文件 -* `addFileParam(String name, String type, String fileName, InputStream input)` 上传文件 -* `addFileParam(String name, String type, byte[] content)` 上传文件 -* `addFileParam(String name, String type, String fileName, byte[] content)` 上传文件 - -* `setTag(String tag)` 为HTTP任务添加标签 -* `setRange(long rangeStart)` 设置Range头信�,用于断点续传 -* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,�用于分�下载 - -* `bind(Object object)` 绑定一个对象,�用于实现Android里的生命周期绑定 - -## 使用标签 - -  有时候我们想对HTTP任务加以分类,这时候�以使用标签功能: - -```java -http.async("/users") //(1) - .setTag("A") - .get(); - -http.async("/users") //(2) - .setTag("A.B") - .get(); - -http.async("/users") //(3) - .setTag("B") - .get(); - -http.async("/users") //(4) - .setTag("B") - .setTag("C") // 从 v1.0.4 标签将以追加模�添加,等效于 setTag("B.C") - .get(); - -http.async("/users") //(5) - .setTag("C") - .get(); -``` -  当使用标签�,就�以按标签批�的对HTTP任务进行�消: - -```java -int count = http.cancel("B"); //(2)(3)(4)被�消(�消标签包�"B"的任务) -System.out.println(count); // 输出 3 -``` -  标签除了�以用��消任务,在预处�器中它也�以�挥作用,请��[并行预处�器](#54-并行预处�器)与[串行预处�器](#55-串行预处�器)。 - -## �置 HTTP - -### 设置 BaseUrl - -```java -HTTP http = HTTP.builder() - .baseUrl("http://api.demo.com") // 设置 BaseUrl - .build(); -``` -  该�置全局生效,在�置了`BaseUrl`之�,具体的请求便�以�略`BaseUrl`部分,使得代�更加简�,例如: - -```java -http.sync("/users").get() // http://api.demo.com/users - -http.sync("/auth/signin") // http://api.demo.com/auth/signin - .addBodyParam("username", "Jackson") - .addBodyParam("password", "xxxxxx") - .post() // POST请求 -``` -  在�置了`BaseUrl`之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�: - -```java -http.sync("https://www.baidu.com").get() -``` - -### 回调执行器 - -  OkHttps 默认所有回调都在 **IO线程** 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建`HTTP`时�置如下: - -```java -HTTP http = HTTP.builder() - .callbackExecutor((Runnable run) -> { - runOnUiThread(run); // 在UI线程执行 - }) - .build(); -``` -  该�置默认 **影�所有回调**。 - -### �置 OkHttpClient - -  与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下: - -```java -HTTP http = HTTP.builder() - .config((Builder builder) -> { - // �置连接池 最�10个连接(��置默认为 5) - builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES)); - // �置连接超时时间(默认10秒) - builder.connectTimeout(20, TimeUnit.SECONDS); - // �置拦截器 - builder.addInterceptor((Chain chain) -> { - Request request = chain.request(); - // 必须�步返回,拦截器内无法执行异步�作 - return chain.proceed(request); - }); - // 其它�置: CookieJar�SSL�缓存�代��事件监�... - }) - .build(); -``` - -### 并行预处�器 - -  预处�器(`Preprocessor`)�以让我们在请求�出之�对请求本身�一些改�,但与`OkHttp`的拦截器(`Interceptor`)��:预处�器�以让我们 **异步** 处�这些问题。 - -  例如,当我们想为请求任务自动添加`Token`头信�,而`Token`�能通过异步方法`requestToken`获�时,这时使用`Interceptor`就很难处�了,但�以使用预处�器轻�解决: - -```java -HTTP http = HTTP.builder() - .addPreprocessor((PreChain chain) -> { - HttpTask task = chain.getTask();// 获得当�的HTTP任务 - if (!task.isTagged("Auth")) { // 根�标签判断该任务是�需�Token - return; - } - requestToken((String token) -> { // 异步获� Token - task.addHeader("Token", token);// 为任务添加头信� - chain.proceed(); // 继续当�的任务 - }); - }) - .build(); -``` -  和`Interceptor`一样,`Preprocessor`也�以添加多个。他们之间的区别如下: - -> * 拦截器�能处��步�作,预处�器支�处�异步�作 -> * 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) -> * 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调监�(详�6.6章节) - -### 串行预处�器(TOKEN问题最佳解决方案) - -  普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当`Token`过期时我们需�去刷新获�新`Token`,而刷新`Token`这个�作�能有一个任务去执行,因为如果`n`个任务�时执行的�,那么必有`n-1`个任务刚刷新得到的`Token`�能就立马失效了,而这是我们所�希望的。 - -  为了解决这个问题,OkHttps �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器: - -```java -HTTP http = HTTP.builder() - .addSerialPreprocessor((PreChain chain) -> { - HttpTask task = chain.getTask(); - if (!task.isTagged("Auth")) { - return; - } - // 检查过期,若需�则刷新Token - requestTokenAndRefreshIfExpired((String token) -> { - task.addHeader("Token", token); - chain.proceed(); // 调用此方法�,�会有其它任务进入该处�器 - }); - }) - .build(); -``` -  串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程� - -### 全局回调监� - -```java -HTTP http = HTTP.builder() - .responseListener((HttpTask task, HttpResult result) -> { - // 所有请求�应�都会走这里 - - return true; // 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行 - }) - .completeListener((HttpTask task, State state) -> { - // 所有请求执行完都会走这里 - - return true; // 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行 - }) - .exceptionListener((HttpTask task, IOException error) -> { - // 所有请求�生异常都会走这里 - - return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 - }) - .build(); -``` - -  全局回调监�与拦截器的异�: -> * 拦截器�以添加多个,全局回调监�分三�,��最多添加一个 -> * 拦截器处的�时机在请求�和�应�,全局回调监��在�应�,并且晚于拦截器 -> * 全局回调监��以 **阻断**(return false)�个请求的具体回调,而拦截器�能 - -### 全局下载监� - -```java -HTTP http = HTTP.builder() - .downloadListener((HttpTask task, Download download) -> { - // 所有下载在开始之�都会先走这里 - Ctrl ctrl = download.getCtrl(); // 下载控制器 - - }) - .build(); -``` - -## 使用 HttpUtils 类 - -  类`HttpUtils`本是 [�身 HttpUtils](https://gitee.com/ejlchina-zhxu/httputils) 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。 - -  类`HttpUtils`共定义了四个��方法: - -* `of(HTTP http)` �置`HttpUtils`�有的`HTTP`实例(�调用此方法�默认使用一个没有没有�过任何�置的`HTTP`懒实例) -* `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) -* `async()` 开始一个异步HTTP任务,使用该方法必须在构建时设置 BaseUrl -* `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) -* `sync()` 开始一个�步HTTP任务,使用该方法必须在构建时设置 BaseUrl -* `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) -* `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) -* `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) -* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 -  也就是说,能使用`http`实例的地方,都�以使用`HttpUtils`类,例如: - -```java -// 在�置HTTP实例之�,�能使用全路径方� -List roles = HttpUtils.sync("http://api.demo.com/roles") - .get().getBody().toList(Role.class); - -// �置HTTP实例,全局生效 -HttpUtils.of(HTTP.builder() - .baseUrl("http://api.demo.com") - .build()); - -// 内部使用新的HTTP实例 -List users = HttpUtils.sync("/users") - .get().getBody().toList(User.class); -``` - - -## 异常处� - -  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 - -### �步请求的异常 - -  默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 `try catch` ��获,例如: - -```java -try { - HttpResult result = http.sync("/users/1").get(); -} catch (HttpException e) { - Throwable cause = e.getCause(); // 得到异常原因 - if (cause instanceof ConnectException) { - // 当没网络时,会抛出连接异常 - } - if (cause instanceof SocketTimeoutException) { - // 当接�长时间未�应,会抛出超时异常 - } - if (cause instanceof UnknownHostException) { - // 当把域�或IP写错,会抛出 UnknownHost 异常 - } - // ... -} -``` -  这�传统的异常处�方�,当然�以解决问题,但 OkHttps 有更佳的方案: - -```java -// 方法 nothrow() 让异常�直接抛出 -HttpResult result = http.sync("/users/1").nothrow().get(); -// 判断执行状� -switch (result.getState()) { - case RESPONSED: // 请求已正常�应 - break; - case CANCELED: // 请求已被�消 - break; - case NETWORK_ERROR: // 网络错误,说明用户没网了 - break; - case TIMEOUT: // 请求超时 - break; - case EXCEPTION: // 其它异常 - break; -} -// 还�以获得具体的异常信� -IOException error = result.getError(); -``` - -### 异步请求的异常 - -  异步请求最常用的异常处�方�就是设置一个异常回调: - -```java -http.async("/users/1") - .setOnResponse((HttpResult result) -> { - // 当�生异常时就�会走这里 - }) - .setOnException((IOException e) -> { - // 这里处�请求异常 - }) - .get(); -``` -  当然,还有一个全局异常监�(`ExceptionListener`): - -```java -HTTP http = HTTP.builder() - .exceptionListener((HttpTask task, IOException error) -> { - // 所有请求�生异常都会走这里 - - return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 - }) - .build(); -``` -  如果�设置`OnException`回调,也没有`ExceptionListener`,�生异常时会在 **IO 线程** 中�上抛出,外层无法�获: - -```java -try { - http.async("/users/1") - .setOnResponse((HttpResult result) -> { - // 当�生异常时就�会走这里 - }) - .get(); -} catch (HttpException e) { - // 这�方�是�获�到异常的������ -} -``` -  �使没有`OnException`回调,�生异常时,�然会走`OnComplete`回调,如果设置了的�: - -```java -http.async("/users/1") - .setOnResponse((HttpResult result) -> { - // 当�生异常时就�会走这里 - }) - .setOnComplete((State state) -> { - // �生异常,会先执行这里,�以根� state 判断�生了什么 - // 但执行完��然会在IO线程中�上抛出 - }) - .get(); -``` -  如果就是想 **�处�异常,也��上抛出**,�生错误完全无视,�以�到�?�以�还是使用`nothrow()`方法: - -```java -http.async("/users/1") - .nothrow() // 告诉 OkHttps �生异常时��外抛出 - .setOnResponse((HttpResult result) -> { - // 当�生异常时就�会走这里 - }) - .get(); -``` -## �消请求的4�方� - -  在 OkHttps 里�消请求共有 **4 �** 方��选: - -* 使用`HttpCall#cancel()`�消�个请求(适用于异步请求,[详� 3.3 章节](#33-httpcall)) -* 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) - -```java -HttpTask task = http.async("/users") - .setOnResponse((HttpResult result) -> { - // �应回调 - }); - -task.get(); // �起 GET 请求 - -// �消请求,并返回是��消�功 -boolean canceled = task.cancel(); -``` - -* 使用`HTTP#cancel(String tag)`按标签批��消请求(适用于所有请求,[详�第 5 章节](#5-使用标签)) -* 使用`HTTP#cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) - -```java -http.cancelAll(); // �消所有请求 -``` From 872cda2fe0e5a3b990d84ba7629dd74288484bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 14:46:50 +0800 Subject: [PATCH 181/924] docs --- docs/.vuepress/config.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index cb8d6db8..782afe3f 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -8,6 +8,7 @@ module.exports = { logo: '/logo.png', nav: [ { text: '教程', link: '/guide/' }, + { text: '历�版本', link: 'https://gitee.com/ejlchina-zhxu/okhttps/releases' }, { text: 'Gitee', link: 'https://gitee.com/ejlchina-zhxu/okhttps' }, { text: 'GitHub', link: 'https://github.com/ejlchina/okhttps' } ], @@ -19,7 +20,13 @@ module.exports = { ['/guide/updown', '上传下载'], ['/guide/android', '安�'], ], - sidebarDepth: 2 + sidebarDepth: 2, + smoothScroll: true, + lastUpdated: '上次更新', + repo: 'https://gitee.com/ejlchina-zhxu/okhttps', + repoLabel: '查看��', + docsBranch: 'dev', + editLinks: true, }, markdown: { lineNumbers: true From ef09094bda963b55fb038a9dcde92ddb70dad194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 18:48:08 +0800 Subject: [PATCH 182/924] docs --- .gitignore | 4 +++- docs/.vuepress/config.js | 17 ++++++++++++----- docs/README.md | 29 +++++++++++++++++++++++++++++ docs/guide/README.md | 2 +- docs/guide/android.md | 2 ++ docs/guide/configuration.md | 2 ++ docs/guide/features.md | 2 ++ docs/guide/foundation.md | 2 ++ docs/guide/updown.md | 1 + package.json | 13 +++++++++++-- 10 files changed, 65 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index d848a362..535469d5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ /.classpath /.project /.idea/** -*.iml \ No newline at end of file +*.iml +/package-lock.json +/node_modules/ \ No newline at end of file diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 782afe3f..e004f65c 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -9,8 +9,7 @@ module.exports = { nav: [ { text: '教程', link: '/guide/' }, { text: '历�版本', link: 'https://gitee.com/ejlchina-zhxu/okhttps/releases' }, - { text: 'Gitee', link: 'https://gitee.com/ejlchina-zhxu/okhttps' }, - { text: 'GitHub', link: 'https://github.com/ejlchina/okhttps' } + { text: '�云', link: 'https://gitee.com/ejlchina-zhxu/okhttps' } ], sidebar: [ ['/guide/', '起步'], @@ -23,12 +22,20 @@ module.exports = { sidebarDepth: 2, smoothScroll: true, lastUpdated: '上次更新', - repo: 'https://gitee.com/ejlchina-zhxu/okhttps', - repoLabel: '查看��', + repo: 'ejlchina/okhttps', + repoLabel: 'Github', docsBranch: 'dev', + docsDir: 'docs', editLinks: true, + editLinkText: '在 GitHub 上编辑此页' }, + // 若全局使用 vuepress,back-to-top 就会失效 + plugins: [ + '@vuepress/back-to-top', 'code-switcher', + ['smartlook', {id: "309988eea09b54d04d69edf5864d0414949892f4"}], + ['seo', { /* options */ }] + ], markdown: { lineNumbers: true } -} \ No newline at end of file +} diff --git a/docs/README.md b/docs/README.md index fcb54b8f..4ca82a7b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,6 +16,8 @@ features: footer: Apache Licensed | Copyright © 2020-present ejlchina --- + ```java // 构建 HTTP @@ -38,4 +40,31 @@ http.async("/users/jack") // http://api.demo.com/users/jack .get(); // GET请求 ``` + + **
就这么简�,你已学会了 90% 的用法�
** \ No newline at end of file diff --git a/docs/guide/README.md b/docs/guide/README.md index 0725a00d..3a847547 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -1,4 +1,4 @@ -## 介� +# 起步   OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 diff --git a/docs/guide/android.md b/docs/guide/android.md index 534edb64..e9b163b5 100644 --- a/docs/guide/android.md +++ b/docs/guide/android.md @@ -1,3 +1,5 @@ +# 安� + ## 回调线程切�   在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 8d8fbba8..6f4983f7 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -1,3 +1,5 @@ +# �置 + ## 设置 BaseUrl ```java diff --git a/docs/guide/features.md b/docs/guide/features.md index fedc980f..637059be 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -1,3 +1,5 @@ +# 特色 + ## 使用 HttpUtils 类   类`HttpUtils`本是 [�身 HttpUtils](https://gitee.com/ejlchina-zhxu/httputils) 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。 diff --git a/docs/guide/foundation.md b/docs/guide/foundation.md index b0a3b173..4ec4ecdc 100644 --- a/docs/guide/foundation.md +++ b/docs/guide/foundation.md @@ -1,3 +1,5 @@ +# 基础 + ## 请求方法   �步与异步的`HttpTask`都拥有`get`�`post`�`put`与`delete`方法。��的是:�步`HttpTask`的这些方法返回一个`HttpResult`,而异步`HttpTask`的这些方法返回一个`HttpCall`。 diff --git a/docs/guide/updown.md b/docs/guide/updown.md index c1fffee4..df02d78b 100644 --- a/docs/guide/updown.md +++ b/docs/guide/updown.md @@ -1,3 +1,4 @@ +# 上传下载 ## 文件下载 diff --git a/package.json b/package.json index 2a6dea1b..b60f3866 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,15 @@ { "scripts": { - "dev": "vuepress dev docs", + "dev": "vuepress dev docs --no-cache", "build": "vuepress build docs" + }, + "devDependencies": { + "@vuepress/plugin-back-to-top": "^1.4.1", + "vuepress": "^1.4.1", + "vuepress-plugin-seo": "^0.1.2" + }, + "dependencies": { + "vuepress-plugin-code-switcher": "^1.0.3", + "vuepress-plugin-smartlook": "0.0.6" } -} \ No newline at end of file +} From 0e188be7882ab6ccc901c8553e52833174c09c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 19:52:32 +0800 Subject: [PATCH 183/924] docs --- .gitignore | 7 ++++--- docs/.vuepress/config.js | 10 +++++++--- docs/.vuepress/public/favicon.png | Bin 3471 -> 0 bytes docs/guide/README.md | 4 ++++ docs/guide/android.md | 4 ++++ docs/guide/configuration.md | 4 ++++ docs/guide/features.md | 4 ++++ docs/guide/foundation.md | 4 ++++ docs/guide/updown.md | 4 ++++ 9 files changed, 35 insertions(+), 6 deletions(-) delete mode 100644 docs/.vuepress/public/favicon.png diff --git a/.gitignore b/.gitignore index 535469d5..bc295ba2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,8 @@ /.settings/ /.classpath /.project -/.idea/** -*.iml +/.idea/ /package-lock.json -/node_modules/ \ No newline at end of file +/node_modules/ +/docs/.vuepress/dist/ +*.iml \ No newline at end of file diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index e004f65c..9bb0dd2f 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -1,6 +1,6 @@ module.exports = { title: 'OkHttps', - description: 'OkHttps 官网', + description: 'OkHttps 官网 比 Retrofit 更好用的网络框架� OkHttp3 轻��装 ,开箱�用�Java领域��端处� Http问题的新选择。', head: [ ['link', { rel: 'icon', href: '/logo.png' }] ], @@ -27,13 +27,17 @@ module.exports = { docsBranch: 'dev', docsDir: 'docs', editLinks: true, - editLinkText: '在 GitHub 上编辑此页' + editLinkText: '在 GitHub 上编辑此页', + author: 'Troy Zhou' }, // 若全局使用 vuepress,back-to-top 就会失效 plugins: [ '@vuepress/back-to-top', 'code-switcher', ['smartlook', {id: "309988eea09b54d04d69edf5864d0414949892f4"}], - ['seo', { /* options */ }] + ['seo', { + description: $page => $page.frontmatter.description, + tags: $page => $page.frontmatter.tags + }] ], markdown: { lineNumbers: true diff --git a/docs/.vuepress/public/favicon.png b/docs/.vuepress/public/favicon.png deleted file mode 100644 index 74f9ae7340d0f02d65ab922cfc31f7f80d9c8b36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3471 zcmV;A4RG>_P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 zVoOIv00000008+zyMF)x010qNS#tmY3labT3lag+-G2N401Wd z$A26Ss2rn>P!&*wq=^+PGGf89wXxWWRAwlCGEx^;j zGQii`|Ex%R6b3{oZ#-}nFdvvuq!C)Q8F(02qP4%Jhz8^iL@7@J3xLaj;YHkZ1nmc& z0PfM+e=W}o=LW=pSPXnW&l^lZD}Y~IKx==07Iw=7h*I8UU@0&y=BfLD=aEs*>a6}7mGZ^`=KzqK;wf|PyZA%r1QrX)BSD%s)mqa|}Entq;{yUvsyJH|qdD9UCA046i8^Cp1`+x8Bx_L+` z?_0nFz|;uEw*nVv?XU0TnxzgKJPUY{a2R`mMZmPd0s}y6|0U$TvJluEQv7J(MPrl1 zO58(~@-9T?e+~&L`a19vt^MxQEtaE{^1cfE5l|sT_X3w{?XOI7okTsv{1-%l@q1v# zV21&qwZ9QK19&i`=pn$eq&+2e4>9kI7lFeZ#XbdornUcYF4oFfN_q2;Nyrh7V!MH} z;=WU20WqVgS8=~HJ_at<+JB)KbLAuR!e0S=$x&=8a7LWbS7adOJ7YcWq3w3yT&?{L zg<2~oDdn94tOdq6ioFd?kNTYw=^bLez?TpXW7bfC0id=22C}lb-BIi$;1OfPP(^*I zUyJ(-{A1ue)4(Am^Rk}>eB>xL7qMZeLaCXr)(zO_ralF}r?tPPXyX(q^G;cV{YAeA z`3`eVNIH9nnL=NRd!q2#p$-FjKO*NliW~|oH8!;>?2&aH?kV(#wDun=+86^xTKh|Z z-#Us+L)M6_vH~$HeYZQ#?E-#Yv=IiN76AWr9KX%jHc+k}awqnczP-qF$ljvwexONf ze;;r;_PMW7h;0KE_&hTk5`O2n?#){Je=7Rs2da8{-rX^F?1VkYYGja39Xocy%ATHg zd)g1!ddOnO^}2z3^SZf8wJ}h)3WezbWF^$5KpTHy*sGK`HKd}mwf5I$eK(bAV-|2f za0>7ta7VpX{%yj#eu_;09}m0++)%HTGrtF=yl)~~R&6@1eUUDxhb(kduqr1Q7Xr^A zFhI8Q)GF1+T?y*C3wit=Z+@BzJZG+vsm#*!Q;s4F+JEQ=L@Dn$WJjS*H)nkl#!$-% z{=m914ir=N#(+a3faQ5WL2PE*1aVpWh^xJaT#0>q=QCNafrr3oDiRb2jHYsdV!q6m zTMiFL_BZ#c7l_$~?)uWq^hF*KMpI5G5nwcxS5LXmacsV^JzU9jynI4RbvyvXsRES1TdP)qo=r5PkU|OJM2}; zdyimenFer-*8a}4Ti79tR^4s>CV|naPl37hS~<}M1(%fajzEU*K@+uGwDyk!(?g6K znQeaMg#ux0M>ZCOZ5_Iia2V@>(-Ds;n=b3GZU=HC>Tv`vDQ?Hdb0B2DU6u>pzG#mPWoardII?Wcvgz*MIy;j~uawtt0|21{} zo8q86=QwsI^Z}V^DfBO`{mp5$CJBtD5<=+*qouAwplI!X2)t=IJQJW~{J?Fl$9`Ik z=>$eoF`@Jj0HdX@qI$|JmfuG!uEM4_=|EY)Xlf8c+2}Ynsf5H13DOQTc21-$ zVKg-up=j;z0zR-Do>)QxxdbWk=qe8wO$|mUz<(^ik1HWQ-9g%#-5y1e7N# z)rMseBk*Mq0Dg=hzO+wJW{DPj*Vk0 zWG{4(MwSwsWYc$m!yU)tyfZGg{63xZpoDtZMuaj7_gr8sb>#F}kkW)Q;N${wM9jL@ z04}GLF~HhNwQ)*>y23W$r2!>$7Q0eydp zS0TZ{*K6flU6sawF|S@LFN@ILSO4x_DQ6e)0 z8DJ&pLAi+(pqRQg)@$Xz)obMsT;*cIcr1yHkXT+p+F3$EsRk)=9K?YNB}_TN064+& z`}-v%I$MxNn}zvA8f;MVf}xam7%VxilHzB5TlX+Wt| z8>4_#^tl$e^`b8aV6P5B(i#pv2lolA@j&aFAC`G|g$~y-8 zd-)aUn>ulM`J^^+2Fai#gwa$#C(0(LRU$6QB(b|6x$t+{jZCN%RLZL*0(NdQU zN?tt!#Add^#1riqAcEG^UGC3wI*r^MMFz^b^v$#N0M$4!TI#w939r{&_vr@C%L9f9 zt>OBPyQlq!VU~*ij6F3`H=wlkI~l4T@KVYvBMw8h$NUPd{U5adXxnw-T5~>`j9>5v zh_1sOmORkL)(<76yrtOlM(qVo*V^yMUEx5LQr?M3L?v7F??<)v=LH>b?aNw(>^Tb3 zA;4owd10~Nhn$r1Mj}D`Z7_D>@a(bzF>ilY^q(oX13nH_-3y%NIR0x_ZmqDbr1v8+ zdu_T#Des!1Eih1Ig7murgKj_~%~^FYka9}OC6F@o#(Q!_nHvE-rIdGi(MBmsCMf?3 z+{*|Hqomo3y8Hb>>_NCd_NxBXG;B!8WZqeeJ8i|2geQUl4yLQC^O- zRk$;@H5+*gaNl5?B{s9R*CXp1VfVQkNx_;p*!02FtL}TtJ@x9rIT=YNHZA6<`;gcsPXnu6)6^Zd zZye&0dx`lwGG-MUfO%2ors66SAm*lrBg>e#V^5tFrj5uZvUSMtxjXKoK`E~SOh!DH zrX&6tljGFUqFu-u(fwNc`xDmTRAxY03^E?cxpYORbs23#996d=F5REd7yMuZGE;CA z;(B}n3EjH`^eC_>t6tkw=0KV`9G-Z;Rcu2~Ii*S24WuYy|sBRhH zw{CncLWKiqm&p<^8;ONJ6MG24q}qWvSiX!5t-Cs`FI5dVAnh`t(5E0fCMO|bZO0)a xsnLA#8)6?~^qt6l-c3lfif*9GxPcE?{U0r~qwQ(G{XhT!002ovPDHLkV1n9jU1$IR diff --git a/docs/guide/README.md b/docs/guide/README.md index 3a847547..ea0465f7 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -1,3 +1,7 @@ +--- +description: OkHttps 安装 构建实例 HTTP build �步请求 异步请求 sync async BaseUrl request webSocket gradle maven ejlchina +--- + # 起步   OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 diff --git a/docs/guide/android.md b/docs/guide/android.md index e9b163b5..73c7fde5 100644 --- a/docs/guide/android.md +++ b/docs/guide/android.md @@ -1,3 +1,7 @@ +--- +description: OkHttps 安� 生命周期 UI线程 主线程 IO线程 自由 �活 切� 生命周期绑定 �置预处�器 定义生命周期监视器 �置全局回调监� +--- + # 安� ## 回调线程切� diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 6f4983f7..f828e5a1 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -1,3 +1,7 @@ +--- +description: OkHttps �置 BaseUrl 回调执行器 主线程 UI线程 OkHttpClient 预处�器 TOKEN问题最佳解决方案 刷新TOKEN 全局 回调监� 下载监� 回调阻断 拦截器 CookieJar�SSL�缓存�代��事件监� +--- + # �置 ## 设置 BaseUrl diff --git a/docs/guide/features.md b/docs/guide/features.md index 637059be..56771574 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -1,3 +1,7 @@ +--- +description: OkHttps 使用 HttpUtils 类 WebSocket 异常处� nothrow 异常回调 多�方� �消请求 标签 批��消 cancelAll +--- + # 特色 ## 使用 HttpUtils 类 diff --git a/docs/guide/foundation.md b/docs/guide/foundation.md index 4ec4ecdc..4cccf799 100644 --- a/docs/guide/foundation.md +++ b/docs/guide/foundation.md @@ -1,3 +1,7 @@ +--- +description: OkHttps 请求方法 回调函数 HttpResult cache 多次 消费报文体 HttpCall 构建HTTP任务 请求�数 JSON 使用标签 �起请求 �消请求 +--- + # 基础 ## 请求方法 diff --git a/docs/guide/updown.md b/docs/guide/updown.md index df02d78b..14290b57 100644 --- a/docs/guide/updown.md +++ b/docs/guide/updown.md @@ -1,3 +1,7 @@ +--- +description: OkHttps 文件 上传 下载 进度监� 过程控制 断点续传 分�下载 +--- + # 上传下载 ## 文件下载 From 332644fe7be3f61b8650736036eaccf34594e205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 20:51:59 +0800 Subject: [PATCH 184/924] update README --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bbbd68dc..4fba4996 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,13 @@ -# OkHttps - +

+ + logo + +

+

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/okhttps/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/okhttps/) [![License](https://img.shields.io/hexpm/l/plug.svg)](https://gitee.com/ejlchina-zhxu/okhttps/blob/master/LICENSE) [![Troy.Zhou](https://img.shields.io/badge/%E4%BD%9C%E8%80%85-ejlchina-orange.svg)](https://github.com/ejlchina) +

## 介� From 3b9e9a7bf8d7b5d2af01064e80badbd46bcde36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 20:54:34 +0800 Subject: [PATCH 185/924] update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4fba4996..3e3969ac 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@

-[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/okhttps/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.ejlchina/okhttps/) -[![License](https://img.shields.io/hexpm/l/plug.svg)](https://gitee.com/ejlchina-zhxu/okhttps/blob/master/LICENSE) -[![Troy.Zhou](https://img.shields.io/badge/%E4%BD%9C%E8%80%85-ejlchina-orange.svg)](https://github.com/ejlchina) + + +

## 介� From 50c767b6c4e5e28d76644500b9382845d2fce3ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 20:56:47 +0800 Subject: [PATCH 186/924] update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3e3969ac..d11d76e5 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@

- - - + Maven Central + License + Troy.Zhou

## 介� From 897d0876866aff5b42546aeeda386cd036765352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 21:00:09 +0800 Subject: [PATCH 187/924] update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index d11d76e5..a8d14c73 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,10 @@ Troy.Zhou

+## Documentation + +Check out our docs at http://okhttps.ejlchina.com/. + ## 介�   OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 From 3bdec153c3706bc5ca2a48c3fa03e1c92e73eaf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 21:03:23 +0800 Subject: [PATCH 188/924] update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a8d14c73..a8369c32 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- logo + logo

From 9638a33e6e3e2397600e8e1920dea45818a63643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 21:05:06 +0800 Subject: [PATCH 189/924] update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a8369c32..edb85cd9 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ## Documentation -Check out our docs at http://okhttps.ejlchina.com/. +官网 http://okhttps.ejlchina.com/ ## 介� From 15613c6f80a894831305af59b5b61336e42da8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 28 Apr 2020 21:27:15 +0800 Subject: [PATCH 190/924] docs --- docs/.vuepress/config.js | 6 +----- package.json | 1 + 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 9bb0dd2f..e45e3dda 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -32,12 +32,8 @@ module.exports = { }, // 若全局使用 vuepress,back-to-top 就会失效 plugins: [ - '@vuepress/back-to-top', 'code-switcher', + '@vuepress/back-to-top', 'code-switcher', 'baidu-autopush', 'seo', ['smartlook', {id: "309988eea09b54d04d69edf5864d0414949892f4"}], - ['seo', { - description: $page => $page.frontmatter.description, - tags: $page => $page.frontmatter.tags - }] ], markdown: { lineNumbers: true diff --git a/package.json b/package.json index b60f3866..cfbe1cec 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "devDependencies": { "@vuepress/plugin-back-to-top": "^1.4.1", "vuepress": "^1.4.1", + "vuepress-plugin-baidu-autopush": "^1.0.1", "vuepress-plugin-seo": "^0.1.2" }, "dependencies": { From 9614aa145669ead94036a1a9ea579ae7c3594ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 29 Apr 2020 15:40:19 +0800 Subject: [PATCH 191/924] docs --- docs/README.md | 7 ++++--- docs/guide/configuration.md | 4 ++-- docs/guide/updown.md | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/README.md b/docs/README.md index 4ca82a7b..e7ab259a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,8 +2,8 @@ home: true heroImage: /logo.png heroText: OkHttps -tagline: 基于 OkHttp 的 Java HTTP 客户端 -actionText: 快速上手 → +tagline: 基于 OkHttp 增强版 HTTP 客户端 +actionText: �速上手 → actionLink: /guide/ features: - title: 轻�纯粹优雅 @@ -67,4 +67,5 @@ http.async("/users/jack") // http://api.demo.com/users/jack --> -**

就这么简�,你已学会了 90% 的用法�
** \ No newline at end of file +**
竟然�到 15 秒,你已学会 90% 的精髓�
** +
[**了解更多**](/guide/)
\ No newline at end of file diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index f828e5a1..ad0bb551 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -19,12 +19,12 @@ http.sync("/users").get() // http://api.demo.com/users http.sync("/auth/signin") // http://api.demo.com/auth/signin .addBodyParam("username", "Jackson") .addBodyParam("password", "xxxxxx") - .post() // POST请求 + .post(); // POST请求 ```   在�置了`BaseUrl`之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�: ```java -http.sync("https://www.baidu.com").get() +http.sync("https://www.baidu.com").get(); ``` ## 回调执行器 diff --git a/docs/guide/updown.md b/docs/guide/updown.md index 14290b57..7f29e5c1 100644 --- a/docs/guide/updown.md +++ b/docs/guide/updown.md @@ -182,7 +182,7 @@ http.sync("/upload") ```java http.async("/upload") .addFileParam("test", "D:/download/test.zip") - .post() + .post(); ``` ### 上传进度监� @@ -202,7 +202,7 @@ http.sync("/upload") double rate = process.getRate(); // 已��的比例 boolean isDone = process.isDone(); // 是���完� }) - .post() + .post(); ```   咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在`get/post`方法之�使用这些API,下载是在`getBody`方法之�使用。很好�解:`get/post`之�是准备��请求时段,有上传的�义,而`getBody`之�,已是报文�应的时段,当然是下载。 @@ -216,7 +216,7 @@ HttpCall call = http.async("/upload") .setOnProcess((Process process) -> { System.out.println(process.getRate()); }) - .post() + .post(); call.cancel(); // �消上传 ``` From bb08f8dcbc4353d44f8373360290087607870df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 29 Apr 2020 15:43:06 +0800 Subject: [PATCH 192/924] docs --- docs/guide/updown.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/updown.md b/docs/guide/updown.md index 7f29e5c1..73486bac 100644 --- a/docs/guide/updown.md +++ b/docs/guide/updown.md @@ -175,7 +175,7 @@ static void download(long totalSize, int index) { ```java http.sync("/upload") .addFileParam("test", "D:/download/test.zip") - .post() // 上传�法一般使用 POST 或 PUT,看�务器支� + .post(); // 上传�法一般使用 POST 或 PUT,看�务器支� ```   异步上传也是完全一样: From fd6ab20bfd7986c539372d093b747565accebac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 29 Apr 2020 16:33:13 +0800 Subject: [PATCH 193/924] =?UTF-8?q?HttpTask=20=E6=9A=B4=E9=9C=B2=20=20requ?= =?UTF-8?q?est(String=20method)=20=E6=96=B9=E6=B3=95=EF=BC=8C=E5=BD=93?= =?UTF-8?q?=E9=A2=84=E5=AE=9A=E4=B9=89=E7=9A=84=20GET|POST|PUT|DELETE?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E4=B8=8D=E5=A4=9F=E7=94=A8=E6=98=AF=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=8F=AF=E4=BB=A5=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=85=B6=E5=AE=83=E8=AF=B7=E6=B1=82=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 2 + .../okhttps/internal/AsyncHttpTask.java | 10 +++- .../okhttps/internal/SyncHttpTask.java | 51 +++++++++++-------- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 369ecc38..3e48bc02 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -585,6 +585,8 @@ protected Call prepareCall(String method) { case "DELETE": builder.delete(reqBody); break; + default: + builder.method(method, reqBody); } return httpClient.request(builder.build()); } diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index d22f433b..7f894429 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -101,7 +101,15 @@ public HttpCall delete() { return request("DELETE"); } - private HttpCall request(String method) { + /** + * �起 HTTP 请求 + * @param method 请求方法 + * @return HttpCall + */ + public HttpCall request(String method) { + if (method == null || method.isEmpty()) { + throw new IllegalArgumentException("HTTP 请求方法 method ��为空�"); + } PreHttpCall call = new PreHttpCall(); registeTagTask(call); httpClient.preprocess(this, () -> { diff --git a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index ef3d16a6..666c0a90 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -55,27 +55,15 @@ public HttpResult delete() { return request("DELETE"); } - static class SyncHttpCall implements Cancelable { - - Call call; - boolean done = false; - boolean canceled = false; - - @Override - public synchronized boolean cancel() { - if (done) { - return false; - } - if (call != null) { - call.cancel(); - } - canceled = true; - return true; - } - - } - - private HttpResult request(String method) { + /** + * �起 HTTP 请求 + * @param method + * @return 请求结果 + */ + public HttpResult request(String method) { + if (method == null || method.isEmpty()) { + throw new IllegalArgumentException("HTTP 请求方法 method ��为空�"); + } RealHttpResult result = new RealHttpResult(this, httpClient.getExecutor()); SyncHttpCall httpCall = new SyncHttpCall(); // 注册标签任务 @@ -117,5 +105,26 @@ private HttpResult request(String method) { } return result; } + + + static class SyncHttpCall implements Cancelable { + + Call call; + boolean done = false; + boolean canceled = false; + + @Override + public synchronized boolean cancel() { + if (done) { + return false; + } + if (call != null) { + call.cancel(); + } + canceled = true; + return true; + } + + } } From 1dd855998e569aaeabaed774b5fe50d6ea0254e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 29 Apr 2020 21:10:21 +0800 Subject: [PATCH 194/924] websocket --- src/main/java/com/ejlchina/okhttps/HTTP.java | 8 + .../java/com/ejlchina/okhttps/HttpTask.java | 11 +- .../java/com/ejlchina/okhttps/WebSocket.java | 49 +++++ .../ejlchina/okhttps/internal/HttpClient.java | 6 + .../okhttps/internal/WebSocketTask.java | 208 ++++++++++++++++++ 5 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/ejlchina/okhttps/WebSocket.java create mode 100644 src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java diff --git a/src/main/java/com/ejlchina/okhttps/HTTP.java b/src/main/java/com/ejlchina/okhttps/HTTP.java index f5c67a8e..5e534549 100644 --- a/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -3,6 +3,7 @@ import com.ejlchina.okhttps.internal.AsyncHttpTask; import com.ejlchina.okhttps.internal.SyncHttpTask; import com.ejlchina.okhttps.internal.TaskExecutor; +import com.ejlchina.okhttps.internal.WebSocketTask; import com.ejlchina.okhttps.internal.HttpClient.Builder; import okhttp3.Call; @@ -43,6 +44,13 @@ public interface HTTP { */ SyncHttpTask sync(); + /** + * Websocket 连接 + * @param url 连接地� + * @return WebSocket 任务 + */ + WebSocketTask webSocket(String url); + /** * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 * 从 v1.0.2 开始支��消�步请求 diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/src/main/java/com/ejlchina/okhttps/HttpTask.java index 3e48bc02..04824ed9 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -553,7 +553,12 @@ protected void removeTagTask() { protected Call prepareCall(String method) { assertNotConflict("GET".equals(method)); - Request.Builder builder = new Request.Builder() + Request request = prepareRequest(method); + return httpClient.request(request); + } + + protected Request prepareRequest(String method) { + Request.Builder builder = new Request.Builder() .url(buildUrlPath()); buildHeaders(builder); RequestBody reqBody = null; @@ -588,8 +593,8 @@ protected Call prepareCall(String method) { default: builder.method(method, reqBody); } - return httpClient.request(builder.build()); - } + return builder.build(); + } private long contentLength(RequestBody reqBody) { try { diff --git a/src/main/java/com/ejlchina/okhttps/WebSocket.java b/src/main/java/com/ejlchina/okhttps/WebSocket.java new file mode 100644 index 00000000..015d46cb --- /dev/null +++ b/src/main/java/com/ejlchina/okhttps/WebSocket.java @@ -0,0 +1,49 @@ +package com.ejlchina.okhttps; + +import okio.ByteString; + +public interface WebSocket extends Cancelable { + + + public interface Listener { + + void on(WebSocket ws, T data); + + } + + + /** + * � {@link okhttp3.WebSocket#queueSize()} + */ + long queueSize(); + + /** + * � {@link okhttp3.WebSocket#send(String)} + */ + boolean send(String text); + + /** + * � {@link okhttp3.WebSocket#send(ByteString)} + */ + boolean send(ByteString bytes); + + /** + * 以JSON文本格���对象消� + * @param bean 待��的对象 + * @return 如果连接已断开 返回 false + */ + public boolean send(Object bean); + + /** + * ��字节� + * @param data 待��的数� + * @return 如果连接已断开 返回 false + */ + public boolean send(byte[] data); + + /** + * � {@link okhttp3.WebSocket#close(int, String)} + */ + boolean close(int code, String reason); + +} diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index c6902eb6..160d795a 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -3,6 +3,7 @@ import com.ejlchina.okhttps.*; import com.ejlchina.okhttps.HttpResult.State; import okhttp3.*; +import okhttp3.WebSocket; import java.io.IOException; import java.util.*; @@ -57,6 +58,11 @@ public SyncHttpTask sync(String url) { return new SyncHttpTask(this, urlPath(url)); } + @Override + public WebSocketTask webSocket(String url) { + return new WebSocketTask(this, urlPath(url)); + } + @Override public int cancel(String tag) { if (tag == null) { diff --git a/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java new file mode 100644 index 00000000..c0897e38 --- /dev/null +++ b/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -0,0 +1,208 @@ +package com.ejlchina.okhttps.internal; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.fastjson.JSON; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.WebSocket; +import com.ejlchina.okhttps.WebSocket.Listener; + +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.WebSocketListener; +import okio.ByteString; + + +public class WebSocketTask extends HttpTask { + + + private Listener onOnen; + private Listener onException; + + + public WebSocketTask(HttpClient httpClient, String url) { + super(httpClient, url); + } + + + public WebSocket listen() { + WebSocketImpl socket = new WebSocketImpl(); + registeTagTask(socket); + httpClient.preprocess(this, () -> { + synchronized (socket) { + if (socket.cancelOrClosed) { + removeTagTask(); + } else { + Request request = prepareRequest("GET"); + MessageListener listener = new MessageListener(socket); + socket.setWebSocket(httpClient.webSocket(request, listener)); + } + } + }); + return socket; + } + + + class MessageListener extends WebSocketListener { + + WebSocket webSocket; + + public MessageListener(WebSocket webSocket) { + this.webSocket = webSocket; + } + + @Override + public void onOpen(okhttp3.WebSocket webSocket, Response response) { + if (onOnen != null) { + HttpResult result = new RealHttpResult(WebSocketTask.this, response, httpClient.executor); + onOnen.on(this.webSocket, result); + } + } + + @Override + public void onMessage(okhttp3.WebSocket webSocket, String text) { + // TODO Auto-generated method stub + } + + @Override + public void onMessage(okhttp3.WebSocket webSocket, ByteString bytes) { + // TODO Auto-generated method stub + } + + @Override + public void onClosing(okhttp3.WebSocket webSocket, int code, String reason) { + // TODO Auto-generated method stub + } + + @Override + public void onClosed(okhttp3.WebSocket webSocket, int code, String reason) { + // TODO Auto-generated method stub + } + + @Override + public void onFailure(okhttp3.WebSocket webSocket, Throwable t, Response response) { + if (onException != null) { +// onException.on(this.webSocket, t); + } + } + + } + + + static class WebSocketImpl implements WebSocket { + + boolean cancelOrClosed; + + okhttp3.WebSocket webSocket; + + List queues = new ArrayList<>(); + + @Override + public synchronized boolean cancel() { + if (webSocket != null) { + webSocket.cancel(); + } + cancelOrClosed = true; + return true; + } + + @Override + public synchronized boolean close(int code, String reason) { + if (webSocket != null) { + webSocket.close(code, reason); + } + cancelOrClosed = true; + return true; + } + + @Override + public long queueSize() { + if (webSocket != null) { + return webSocket.queueSize(); + } + return 0; + } + + @Override + public boolean send(String text) { + if (webSocket != null) { + return webSocket.send(text); + } + queueMsgToSend(text); + return true; + } + + @Override + public boolean send(ByteString bytes) { + if (webSocket != null) { + return webSocket.send(bytes); + } + queueMsgToSend(bytes); + return true; + } + + @Override + public boolean send(Object bean) { + if (webSocket != null) { + return send(webSocket, bean); + } + queueMsgToSend(bean); + return true; + } + + @Override + public boolean send(byte[] data) { + if (webSocket != null) { + return send(webSocket, data); + } + queueMsgToSend(data); + return true; + } + + void queueMsgToSend(Object msg) { + if (msg == null) { + return; + } + synchronized (queues) { + if (queues != null) { + queues.add(msg); + } else if (webSocket != null) { + send(webSocket, msg); + } else { + throw new IllegalStateException(); + } + } + } + + void setWebSocket(okhttp3.WebSocket webSocket) { + synchronized (queues) { + for (Object msg: queues) { + send(webSocket, msg); + } + this.webSocket = webSocket; + queues = null; + } + } + + boolean send(okhttp3.WebSocket webSocket, Object msg) { + if (msg == null) { + return false; + } + if (msg instanceof String) { + return webSocket.send((String) msg); + } + if (msg instanceof ByteString) { + return webSocket.send((ByteString) msg); + } + if (msg instanceof byte[]) { + return webSocket.send(ByteString.of((byte[]) msg)); + } + return webSocket.send(JSON.toJSONString(msg)); + } + + } + +} From 71c6465d88a81a88bc7e0ce767e9dccc194c6778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sat, 2 May 2020 01:03:08 +0800 Subject: [PATCH 195/924] docs --- docs/.vuepress/config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index e45e3dda..573c7d19 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -9,6 +9,7 @@ module.exports = { nav: [ { text: '教程', link: '/guide/' }, { text: '历�版本', link: 'https://gitee.com/ejlchina-zhxu/okhttps/releases' }, + { text: 'Grails 中文', link: 'http://grails.ejlchina.com' }, { text: '�云', link: 'https://gitee.com/ejlchina-zhxu/okhttps' } ], sidebar: [ From 5fb309ac5b376f0a728c75a8d7d7d226b9839996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 3 May 2020 20:26:28 +0800 Subject: [PATCH 196/924] add-vuepress-plugin-baidu-tongji --- docs/.vuepress/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 573c7d19..3e22cadd 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -34,7 +34,7 @@ module.exports = { // 若全局使用 vuepress,back-to-top 就会失效 plugins: [ '@vuepress/back-to-top', 'code-switcher', 'baidu-autopush', 'seo', - ['smartlook', {id: "309988eea09b54d04d69edf5864d0414949892f4"}], + ['baidu-tongji', {hm: '6eb41c0ab450d5a4ae8769682ecb0ab2'}], ], markdown: { lineNumbers: true From 4de968fe00b554791e7006e50db89eeb4c6c42bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 13:17:34 +0800 Subject: [PATCH 197/924] doc --- docs/guide/configuration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index ad0bb551..30bf60e9 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -73,6 +73,7 @@ HTTP http = HTTP.builder() .addPreprocessor((PreChain chain) -> { HttpTask task = chain.getTask();// 获得当�的HTTP任务 if (!task.isTagged("Auth")) { // 根�标签判断该任务是�需�Token + chain.proceed(); return; } requestToken((String token) -> { // 异步获� Token @@ -101,6 +102,7 @@ HTTP http = HTTP.builder() .addSerialPreprocessor((PreChain chain) -> { HttpTask task = chain.getTask(); if (!task.isTagged("Auth")) { + chain.proceed(); return; } // 检查过期,若需�则刷新Token From 23d78efa629e63cc3d6cd1231ad0a95e2f80a14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 13:26:48 +0800 Subject: [PATCH 198/924] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 +- okhttps/.gitignore | 1 + pom.xml => okhttps/pom.xml | 0 .../java/com/ejlchina/okhttps/Cancelable.java | 0 .../com/ejlchina/okhttps/Configurator.java | 0 .../com/ejlchina/okhttps/DownListener.java | 0 .../java/com/ejlchina/okhttps/Download.java | 0 .../main/java/com/ejlchina/okhttps/HTTP.java | 0 .../java/com/ejlchina/okhttps/HttpCall.java | 0 .../java/com/ejlchina/okhttps/HttpResult.java | 554 +++++++++--------- .../java/com/ejlchina/okhttps/HttpTask.java | 0 .../java/com/ejlchina/okhttps/HttpUtils.java | 0 .../java/com/ejlchina/okhttps/OnCallback.java | 0 .../com/ejlchina/okhttps/Preprocessor.java | 0 .../java/com/ejlchina/okhttps/Process.java | 0 .../com/ejlchina/okhttps/TaskListener.java | 0 .../java/com/ejlchina/okhttps/WebSocket.java | 0 .../okhttps/internal/AsyncHttpTask.java | 0 .../ejlchina/okhttps/internal/HttpClient.java | 0 .../okhttps/internal/HttpException.java | 0 .../okhttps/internal/ProcessInputStream.java | 0 .../okhttps/internal/ProcessRequestBody.java | 0 .../okhttps/internal/RealHttpResult.java | 270 ++++----- .../okhttps/internal/RealProcess.java | 0 .../ejlchina/okhttps/internal/ResultBody.java | 0 .../okhttps/internal/SyncHttpTask.java | 0 .../okhttps/internal/TaskExecutor.java | 224 +++---- .../okhttps/internal/WebSocketTask.java | 0 .../test/java/com/ejlchina/test/BaseTest.java | 0 .../java/com/ejlchina/test/CacheTests.java | 0 .../java/com/ejlchina/test/CancelTests.java | 0 .../java/com/ejlchina/test/DownloadTests.java | 0 .../com/ejlchina/test/ExceptionTests.java | 2 +- .../java/com/ejlchina/test/ExecutorTests.java | 0 .../java/com/ejlchina/test/JsonTests.java | 0 .../java/com/ejlchina/test/ListenerTests.java | 0 .../com/ejlchina/test/PreprocessorTests.java | 0 .../java/com/ejlchina/test/SimpleTests.java | 0 .../test/java/com/ejlchina/test/TagTests.java | 0 .../java/com/ejlchina/test/UploadTests.java | 0 40 files changed, 529 insertions(+), 528 deletions(-) create mode 100644 okhttps/.gitignore rename pom.xml => okhttps/pom.xml (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/Cancelable.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/Configurator.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/DownListener.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/Download.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/HTTP.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/HttpCall.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/HttpResult.java (95%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/HttpTask.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/HttpUtils.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/OnCallback.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/Preprocessor.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/Process.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/TaskListener.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/WebSocket.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/HttpClient.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/HttpException.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/ProcessInputStream.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/ProcessRequestBody.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java (95%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/RealProcess.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/ResultBody.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java (100%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java (97%) rename {src => okhttps/src}/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/BaseTest.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/CacheTests.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/CancelTests.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/DownloadTests.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/ExceptionTests.java (98%) rename {src => okhttps/src}/test/java/com/ejlchina/test/ExecutorTests.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/JsonTests.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/ListenerTests.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/PreprocessorTests.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/SimpleTests.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/TagTests.java (100%) rename {src => okhttps/src}/test/java/com/ejlchina/test/UploadTests.java (100%) diff --git a/.gitignore b/.gitignore index bc295ba2..5a255776 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ /target/ /bin/ -/.settings/ -/.classpath -/.project +/*/.settings/ +/*/.classpath +/*/.project /.idea/ /package-lock.json /node_modules/ diff --git a/okhttps/.gitignore b/okhttps/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/okhttps/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/pom.xml b/okhttps/pom.xml similarity index 100% rename from pom.xml rename to okhttps/pom.xml diff --git a/src/main/java/com/ejlchina/okhttps/Cancelable.java b/okhttps/src/main/java/com/ejlchina/okhttps/Cancelable.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/Cancelable.java rename to okhttps/src/main/java/com/ejlchina/okhttps/Cancelable.java diff --git a/src/main/java/com/ejlchina/okhttps/Configurator.java b/okhttps/src/main/java/com/ejlchina/okhttps/Configurator.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/Configurator.java rename to okhttps/src/main/java/com/ejlchina/okhttps/Configurator.java diff --git a/src/main/java/com/ejlchina/okhttps/DownListener.java b/okhttps/src/main/java/com/ejlchina/okhttps/DownListener.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/DownListener.java rename to okhttps/src/main/java/com/ejlchina/okhttps/DownListener.java diff --git a/src/main/java/com/ejlchina/okhttps/Download.java b/okhttps/src/main/java/com/ejlchina/okhttps/Download.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/Download.java rename to okhttps/src/main/java/com/ejlchina/okhttps/Download.java diff --git a/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/HTTP.java rename to okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java diff --git a/src/main/java/com/ejlchina/okhttps/HttpCall.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpCall.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/HttpCall.java rename to okhttps/src/main/java/com/ejlchina/okhttps/HttpCall.java diff --git a/src/main/java/com/ejlchina/okhttps/HttpResult.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java similarity index 95% rename from src/main/java/com/ejlchina/okhttps/HttpResult.java rename to okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java index 88984b72..c3d31928 100644 --- a/src/main/java/com/ejlchina/okhttps/HttpResult.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -1,277 +1,277 @@ -package com.ejlchina.okhttps; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.util.List; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.ejlchina.okhttps.internal.RealHttpResult; -import com.ejlchina.okhttps.internal.TaskExecutor; - -import okhttp3.Headers; -import okhttp3.MediaType; -import okhttp3.Response; - - -/** - * Http 执行结果 - */ -public interface HttpResult { - - /** - * 构造一个 HttpResult - * 此方法构造的 HttpResult ��设置进度回调,��进行下载�作� - * 若需�,请使用方法: {@link #of(Response, TaskExecutor)} - * @param response Response - * @return HttpResult - */ - static HttpResult of(Response response) { - return of(response, null); - } - - /** - * 构造一个 HttpResult - * @param response Response - * @param taskExecutor 任务执行器, �通过方法 {@link HTTP#getExecutor()} 获得 - * @return HttpResult - */ - static HttpResult of(Response response, TaskExecutor taskExecutor) { - if (response != null) { - return new RealHttpResult(null, response, taskExecutor); - } - throw new IllegalArgumentException("response �能为空"); - } - - - public enum State { - - /** - * 执行异常 - */ - EXCEPTION, - - /** - * 请求被�消 - */ - CANCELED, - - /** - * 请求已�应 - */ - RESPONSED, - - /** - * 网络超时 - */ - TIMEOUT, - - /** - * 网络出错 - */ - NETWORK_ERROR - - } - - /** - * HTTP�应报文体 - */ - public interface Body { - - /** - * @return 媒体类型 - */ - MediaType getContentType(); - - /** - * @return 报文体字节长度 - */ - long getContentLength(); - - /** - * 在IO线程执行 - * @return Body - */ - Body nextOnIO(); - - /** - * 设置报文体接收进度回调 - * @param onProcess 进度回调函数 - * @return Body - */ - Body setOnProcess(OnCallback onProcess); - - /** - * 设置进度回调的步进字节,默认 8K(8192) - * 表示�接收 stepBytes 个字节,执行一次进度回调 - * @param stepBytes 步进字节 - * @return Body - */ - Body setStepBytes(long stepBytes); - - /** - * 设置进度回调的步进比例 - * 表示�接收 stepRate 比例,执行一次进度回调 - * @param stepRate 步进比例 - * @return Body - */ - Body setStepRate(double stepRate); - - /** - * 设置进度回调忽略�应的Range头信�,�进度回调会从0开始 - * @return Body - */ - Body setRangeIgnored(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转字节� - */ - InputStream toByteStream(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转字节数组 - */ - byte[] toBytes(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转字符� - */ - Reader toCharStream(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转字符串 - */ - String toString(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转Json对象 - */ - JSONObject toJsonObject(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @return 报文体转Json数组 - */ - JSONArray toJsonArray(); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param 目标泛型 - * @param type 目标类型 - * @return 报文体Json文本转JavaBean - */ - T toBean(Class type); - - /** - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param 目标泛型 - * @param type 目标类型 - * @return 报文体Json文本转JavaBean列表 - */ - List toList(Class type); - - /** - * 下载到指定路径 - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param filePath 目标路径 - * @return 下载过程 #Download - */ - Download toFile(String filePath); - - /** - * 下载到指定文件 - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param file 目标文件 - * @return 下载过程 #Download - */ - Download toFile(File file); - - /** - * 下载到指定文件夹 - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param dirPath 目标目录 - * @return 下载过程 #Download - */ - Download toFolder(String dirPath); - - /** - * 下载到指定文件夹 - * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 - * @param dir 目标目录 - * @return 下载过程 #Download - */ - Download toFolder(File dir); - - /** - * 缓存自己,缓存�� ��使用 toXXX 类方法 - * @return Body - */ - Body cache(); - - /** - * 关闭报文体 - * 未对报文体�任何消费时使用,比如�读�长度 - * @return Body - */ - Body close(); - - } - - - /** - * @return 执行状� - */ - State getState(); - - /** - * @return HTTP状�� - */ - int getStatus(); - - /** - * @return 是��应�功,状��在 [200..300) 之间 - */ - boolean isSuccessful(); - - /** - * @return �应头 - */ - Headers getHeaders(); - - /** - * @param name 头�称 - * @return �应头 - */ - List getHeaders(String name); - - /** - * @param name 头�称 - * @return �应头 - */ - String getHeader(String name); - - /** - * @return �应报文体 - */ - Body getBody(); - - /** - * @return 执行中�生的异常 - */ - IOException getError(); - - /** - * 关闭报文 - * 未对报文体�任何消费时使用,比如�读�报文头 - * @return HttpResult - */ - HttpResult close(); - -} +package com.ejlchina.okhttps; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.List; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ejlchina.okhttps.internal.RealHttpResult; +import com.ejlchina.okhttps.internal.TaskExecutor; + +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.Response; + + +/** + * Http 执行结果 + */ +public interface HttpResult { + + /** + * 构造一个 HttpResult + * 此方法构造的 HttpResult ��设置进度回调,��进行下载�作� + * 若需�,请使用方法: {@link #of(Response, TaskExecutor)} + * @param response Response + * @return HttpResult + */ + static HttpResult of(Response response) { + return of(response, null); + } + + /** + * 构造一个 HttpResult + * @param response Response + * @param taskExecutor 任务执行器, �通过方法 {@link HTTP#getExecutor()} 获得 + * @return HttpResult + */ + static HttpResult of(Response response, TaskExecutor taskExecutor) { + if (response != null) { + return new RealHttpResult(null, response, taskExecutor); + } + throw new IllegalArgumentException("response �能为空"); + } + + + public enum State { + + /** + * 执行异常 + */ + EXCEPTION, + + /** + * 请求被�消 + */ + CANCELED, + + /** + * 请求已�应 + */ + RESPONSED, + + /** + * 网络超时 + */ + TIMEOUT, + + /** + * 网络出错 + */ + NETWORK_ERROR + + } + + /** + * HTTP�应报文体 + */ + public interface Body { + + /** + * @return 媒体类型 + */ + MediaType getContentType(); + + /** + * @return 报文体字节长度 + */ + long getContentLength(); + + /** + * 在IO线程执行 + * @return Body + */ + Body nextOnIO(); + + /** + * 设置报文体接收进度回调 + * @param onProcess 进度回调函数 + * @return Body + */ + Body setOnProcess(OnCallback onProcess); + + /** + * 设置进度回调的步进字节,默认 8K(8192) + * 表示�接收 stepBytes 个字节,执行一次进度回调 + * @param stepBytes 步进字节 + * @return Body + */ + Body setStepBytes(long stepBytes); + + /** + * 设置进度回调的步进比例 + * 表示�接收 stepRate 比例,执行一次进度回调 + * @param stepRate 步进比例 + * @return Body + */ + Body setStepRate(double stepRate); + + /** + * 设置进度回调忽略�应的Range头信�,�进度回调会从0开始 + * @return Body + */ + Body setRangeIgnored(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字节� + */ + InputStream toByteStream(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字节数组 + */ + byte[] toBytes(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字符� + */ + Reader toCharStream(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转字符串 + */ + String toString(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转Json对象 + */ + JSONObject toJsonObject(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @return 报文体转Json数组 + */ + JSONArray toJsonArray(); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean + */ + T toBean(Class type); + + /** + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean列表 + */ + List toList(Class type); + + /** + * 下载到指定路径 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param filePath 目标路径 + * @return 下载过程 #Download + */ + Download toFile(String filePath); + + /** + * 下载到指定文件 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param file 目标文件 + * @return 下载过程 #Download + */ + Download toFile(File file); + + /** + * 下载到指定文件夹 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param dirPath 目标目录 + * @return 下载过程 #Download + */ + Download toFolder(String dirPath); + + /** + * 下载到指定文件夹 + * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 + * @param dir 目标目录 + * @return 下载过程 #Download + */ + Download toFolder(File dir); + + /** + * 缓存自己,缓存�� ��使用 toXXX 类方法 + * @return Body + */ + Body cache(); + + /** + * 关闭报文体 + * 未对报文体�任何消费时使用,比如�读�长度 + * @return Body + */ + Body close(); + + } + + + /** + * @return 执行状� + */ + State getState(); + + /** + * @return HTTP状�� + */ + int getStatus(); + + /** + * @return 是��应�功,状��在 [200..300) 之间 + */ + boolean isSuccessful(); + + /** + * @return �应头 + */ + Headers getHeaders(); + + /** + * @param name 头�称 + * @return �应头 + */ + List getHeaders(String name); + + /** + * @param name 头�称 + * @return �应头 + */ + String getHeader(String name); + + /** + * @return �应报文体 + */ + Body getBody(); + + /** + * @return 执行中�生的异常 + */ + IOException getError(); + + /** + * 关闭报文 + * 未对报文体�任何消费时使用,比如�读�报文头 + * @return HttpResult + */ + HttpResult close(); + +} diff --git a/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/HttpTask.java rename to okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java diff --git a/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/HttpUtils.java rename to okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java diff --git a/src/main/java/com/ejlchina/okhttps/OnCallback.java b/okhttps/src/main/java/com/ejlchina/okhttps/OnCallback.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/OnCallback.java rename to okhttps/src/main/java/com/ejlchina/okhttps/OnCallback.java diff --git a/src/main/java/com/ejlchina/okhttps/Preprocessor.java b/okhttps/src/main/java/com/ejlchina/okhttps/Preprocessor.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/Preprocessor.java rename to okhttps/src/main/java/com/ejlchina/okhttps/Preprocessor.java diff --git a/src/main/java/com/ejlchina/okhttps/Process.java b/okhttps/src/main/java/com/ejlchina/okhttps/Process.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/Process.java rename to okhttps/src/main/java/com/ejlchina/okhttps/Process.java diff --git a/src/main/java/com/ejlchina/okhttps/TaskListener.java b/okhttps/src/main/java/com/ejlchina/okhttps/TaskListener.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/TaskListener.java rename to okhttps/src/main/java/com/ejlchina/okhttps/TaskListener.java diff --git a/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/WebSocket.java rename to okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java diff --git a/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/internal/HttpClient.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java diff --git a/src/main/java/com/ejlchina/okhttps/internal/HttpException.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpException.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/internal/HttpException.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpException.java diff --git a/src/main/java/com/ejlchina/okhttps/internal/ProcessInputStream.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ProcessInputStream.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/internal/ProcessInputStream.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/ProcessInputStream.java diff --git a/src/main/java/com/ejlchina/okhttps/internal/ProcessRequestBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ProcessRequestBody.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/internal/ProcessRequestBody.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/ProcessRequestBody.java diff --git a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java similarity index 95% rename from src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java index 15c27ab2..aa4974fc 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java @@ -1,135 +1,135 @@ -package com.ejlchina.okhttps.internal; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; - -import com.ejlchina.okhttps.HttpResult; -import com.ejlchina.okhttps.HttpTask; - -import okhttp3.Headers; -import okhttp3.Response; - - -public class RealHttpResult implements HttpResult { - - private State state; - private Response response; - private IOException error; - private TaskExecutor taskExecutor; - private HttpTask httpTask; - private Body body; - - public RealHttpResult(HttpTask httpTask, State state) { - this.httpTask = httpTask; - this.state = state; - } - - public RealHttpResult(HttpTask httpTask, Response response, TaskExecutor taskExecutor) { - this(httpTask, taskExecutor); - response(response); - } - - public RealHttpResult(HttpTask httpTask, TaskExecutor taskExecutor) { - this.httpTask = httpTask; - this.taskExecutor = taskExecutor; - } - - public RealHttpResult(HttpTask httpTask, State state, IOException error) { - this.httpTask = httpTask; - exception(state, error); - } - - public void exception(State state, IOException error) { - this.state = state; - this.error = error; - } - - public void response(Response response) { - this.state = State.RESPONSED; - this.response = response; - } - - @Override - public State getState() { - return state; - } - - @Override - public int getStatus() { - if (response != null) { - return response.code(); - } - return 0; - } - - @Override - public boolean isSuccessful() { - if (response != null) { - return response.isSuccessful(); - } - return false; - } - - @Override - public Headers getHeaders() { - if (response != null) { - return response.headers(); - } - return null; - } - - @Override - public List getHeaders(String name) { - if (response != null) { - return response.headers(name); - } - return Collections.emptyList(); - } - - @Override - public String getHeader(String name) { - if (response != null) { - return response.header(name); - } - return null; - } - - @Override - public Body getBody() { - if (body == null && response != null) { - body = new ResultBody(httpTask, response, taskExecutor); - } - return body; - } - - @Override - public IOException getError() { - return error; - } - - public Response getResponse() { - return response; - } - - - @Override - public String toString() { - Body body = getBody(); - String str = "HttpResult [\n state: " + state + ",\n status: " + getStatus() - + ",\n headers: " + getHeaders(); - if (body != null) { - str += ",\n contentType: " + body.getContentType(); - } - return str + ",\n error: " + error + "\n]"; - } - - @Override - public HttpResult close() { - if (response != null) { - response.close(); - } - return this; - } - -} +package com.ejlchina.okhttps.internal; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; + +import okhttp3.Headers; +import okhttp3.Response; + + +public class RealHttpResult implements HttpResult { + + private State state; + private Response response; + private IOException error; + private TaskExecutor taskExecutor; + private HttpTask httpTask; + private Body body; + + public RealHttpResult(HttpTask httpTask, State state) { + this.httpTask = httpTask; + this.state = state; + } + + public RealHttpResult(HttpTask httpTask, Response response, TaskExecutor taskExecutor) { + this(httpTask, taskExecutor); + response(response); + } + + public RealHttpResult(HttpTask httpTask, TaskExecutor taskExecutor) { + this.httpTask = httpTask; + this.taskExecutor = taskExecutor; + } + + public RealHttpResult(HttpTask httpTask, State state, IOException error) { + this.httpTask = httpTask; + exception(state, error); + } + + public void exception(State state, IOException error) { + this.state = state; + this.error = error; + } + + public void response(Response response) { + this.state = State.RESPONSED; + this.response = response; + } + + @Override + public State getState() { + return state; + } + + @Override + public int getStatus() { + if (response != null) { + return response.code(); + } + return 0; + } + + @Override + public boolean isSuccessful() { + if (response != null) { + return response.isSuccessful(); + } + return false; + } + + @Override + public Headers getHeaders() { + if (response != null) { + return response.headers(); + } + return null; + } + + @Override + public List getHeaders(String name) { + if (response != null) { + return response.headers(name); + } + return Collections.emptyList(); + } + + @Override + public String getHeader(String name) { + if (response != null) { + return response.header(name); + } + return null; + } + + @Override + public Body getBody() { + if (body == null && response != null) { + body = new ResultBody(httpTask, response, taskExecutor); + } + return body; + } + + @Override + public IOException getError() { + return error; + } + + public Response getResponse() { + return response; + } + + + @Override + public String toString() { + Body body = getBody(); + String str = "HttpResult [\n state: " + state + ",\n status: " + getStatus() + + ",\n headers: " + getHeaders(); + if (body != null) { + str += ",\n contentType: " + body.getContentType(); + } + return str + ",\n error: " + error + "\n]"; + } + + @Override + public HttpResult close() { + if (response != null) { + response.close(); + } + return this; + } + +} diff --git a/src/main/java/com/ejlchina/okhttps/internal/RealProcess.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/RealProcess.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/internal/RealProcess.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/RealProcess.java diff --git a/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/internal/ResultBody.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java diff --git a/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java diff --git a/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java similarity index 97% rename from src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index cb8c5d1c..42d2e19e 100644 --- a/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -1,112 +1,112 @@ -package com.ejlchina.okhttps.internal; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; - -import com.ejlchina.okhttps.DownListener; -import com.ejlchina.okhttps.Download; -import com.ejlchina.okhttps.HttpResult; -import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.OnCallback; -import com.ejlchina.okhttps.TaskListener; -import com.ejlchina.okhttps.HttpResult.State; - -public class TaskExecutor { - - private Executor ioExecutor; - private Executor mainExecutor; - private DownListener downloadListener; - private TaskListener responseListener; - private TaskListener exceptionListener; - private TaskListener completeListener; - - public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, - TaskListener responseListener, TaskListener exceptionListener, - TaskListener completeListener) { - this.ioExecutor = ioExecutor; - this.mainExecutor = mainExecutor; - this.downloadListener = downloadListener; - this.responseListener = responseListener; - this.exceptionListener = exceptionListener; - this.completeListener = completeListener; - } - - public Executor getExecutor(boolean onIoThread) { - if (onIoThread || mainExecutor == null) { - return ioExecutor; - } - return mainExecutor; - } - - public Download download(HttpTask httpTask, File file, InputStream input, long skipBytes) { - Download download = new Download(file, input, this, skipBytes); - if (httpTask != null && downloadListener != null) { - downloadListener.listen(httpTask, download); - } - return download; - } - - public void execute(Runnable command, boolean onIoThread) { - Executor executor = ioExecutor; - if (mainExecutor != null && !onIoThread) { - executor = mainExecutor; - } - executor.execute(command); - } - - public void executeOnResponse(HttpTask task, OnCallback onResponse, HttpResult result, boolean onIoThread) { - if (responseListener != null) { - execute(() -> { - if (responseListener.listen(task, result) && onResponse != null) { - onResponse.on(result); - } - }, onIoThread); - } else if (onResponse != null) { - execute(() -> { onResponse.on(result); }, onIoThread); - } - } - - public boolean executeOnException(HttpTask task, OnCallback onException, IOException error, boolean onIoThread) { - if (exceptionListener != null) { - execute(() -> { - if (exceptionListener.listen(task, error) && onException != null) { - onException.on(error); - } - }, onIoThread); - return true; - } else if (onException != null) { - execute(() -> { onException.on(error); }, onIoThread); - return true; - } - return false; - } - - public void executeOnComplete(HttpTask task, OnCallback onComplete, State state, boolean onIoThread) { - if (completeListener != null) { - execute(() -> { - if (completeListener.listen(task, state) && onComplete != null) { - onComplete.on(state); - } - }, onIoThread); - } else if (onComplete != null) { - execute(() -> { onComplete.on(state); }, onIoThread); - } - } - - /** - * 关闭线程池 - * @since OkHttps V1.0.2 - */ - public void shutdown() { - if (ioExecutor != null && ioExecutor instanceof ExecutorService) { - ((ExecutorService) ioExecutor).shutdown(); - } - if (mainExecutor != null && mainExecutor instanceof ExecutorService) { - ((ExecutorService) mainExecutor).shutdown(); - } - } - -} +package com.ejlchina.okhttps.internal; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; + +import com.ejlchina.okhttps.DownListener; +import com.ejlchina.okhttps.Download; +import com.ejlchina.okhttps.HttpResult; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.OnCallback; +import com.ejlchina.okhttps.TaskListener; +import com.ejlchina.okhttps.HttpResult.State; + +public class TaskExecutor { + + private Executor ioExecutor; + private Executor mainExecutor; + private DownListener downloadListener; + private TaskListener responseListener; + private TaskListener exceptionListener; + private TaskListener completeListener; + + public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, + TaskListener responseListener, TaskListener exceptionListener, + TaskListener completeListener) { + this.ioExecutor = ioExecutor; + this.mainExecutor = mainExecutor; + this.downloadListener = downloadListener; + this.responseListener = responseListener; + this.exceptionListener = exceptionListener; + this.completeListener = completeListener; + } + + public Executor getExecutor(boolean onIoThread) { + if (onIoThread || mainExecutor == null) { + return ioExecutor; + } + return mainExecutor; + } + + public Download download(HttpTask httpTask, File file, InputStream input, long skipBytes) { + Download download = new Download(file, input, this, skipBytes); + if (httpTask != null && downloadListener != null) { + downloadListener.listen(httpTask, download); + } + return download; + } + + public void execute(Runnable command, boolean onIoThread) { + Executor executor = ioExecutor; + if (mainExecutor != null && !onIoThread) { + executor = mainExecutor; + } + executor.execute(command); + } + + public void executeOnResponse(HttpTask task, OnCallback onResponse, HttpResult result, boolean onIoThread) { + if (responseListener != null) { + execute(() -> { + if (responseListener.listen(task, result) && onResponse != null) { + onResponse.on(result); + } + }, onIoThread); + } else if (onResponse != null) { + execute(() -> { onResponse.on(result); }, onIoThread); + } + } + + public boolean executeOnException(HttpTask task, OnCallback onException, IOException error, boolean onIoThread) { + if (exceptionListener != null) { + execute(() -> { + if (exceptionListener.listen(task, error) && onException != null) { + onException.on(error); + } + }, onIoThread); + return true; + } else if (onException != null) { + execute(() -> { onException.on(error); }, onIoThread); + return true; + } + return false; + } + + public void executeOnComplete(HttpTask task, OnCallback onComplete, State state, boolean onIoThread) { + if (completeListener != null) { + execute(() -> { + if (completeListener.listen(task, state) && onComplete != null) { + onComplete.on(state); + } + }, onIoThread); + } else if (onComplete != null) { + execute(() -> { onComplete.on(state); }, onIoThread); + } + } + + /** + * 关闭线程池 + * @since OkHttps V1.0.2 + */ + public void shutdown() { + if (ioExecutor != null && ioExecutor instanceof ExecutorService) { + ((ExecutorService) ioExecutor).shutdown(); + } + if (mainExecutor != null && mainExecutor instanceof ExecutorService) { + ((ExecutorService) mainExecutor).shutdown(); + } + } + +} diff --git a/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java similarity index 100% rename from src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java diff --git a/src/test/java/com/ejlchina/test/BaseTest.java b/okhttps/src/test/java/com/ejlchina/test/BaseTest.java similarity index 100% rename from src/test/java/com/ejlchina/test/BaseTest.java rename to okhttps/src/test/java/com/ejlchina/test/BaseTest.java diff --git a/src/test/java/com/ejlchina/test/CacheTests.java b/okhttps/src/test/java/com/ejlchina/test/CacheTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/CacheTests.java rename to okhttps/src/test/java/com/ejlchina/test/CacheTests.java diff --git a/src/test/java/com/ejlchina/test/CancelTests.java b/okhttps/src/test/java/com/ejlchina/test/CancelTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/CancelTests.java rename to okhttps/src/test/java/com/ejlchina/test/CancelTests.java diff --git a/src/test/java/com/ejlchina/test/DownloadTests.java b/okhttps/src/test/java/com/ejlchina/test/DownloadTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/DownloadTests.java rename to okhttps/src/test/java/com/ejlchina/test/DownloadTests.java diff --git a/src/test/java/com/ejlchina/test/ExceptionTests.java b/okhttps/src/test/java/com/ejlchina/test/ExceptionTests.java similarity index 98% rename from src/test/java/com/ejlchina/test/ExceptionTests.java rename to okhttps/src/test/java/com/ejlchina/test/ExceptionTests.java index 7cee825b..7fd25505 100644 --- a/src/test/java/com/ejlchina/test/ExceptionTests.java +++ b/okhttps/src/test/java/com/ejlchina/test/ExceptionTests.java @@ -71,7 +71,7 @@ public void testSync1() { } // 还�以获得具体的异常信� Exception error = result.getError(); - + System.out.println(error); } diff --git a/src/test/java/com/ejlchina/test/ExecutorTests.java b/okhttps/src/test/java/com/ejlchina/test/ExecutorTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/ExecutorTests.java rename to okhttps/src/test/java/com/ejlchina/test/ExecutorTests.java diff --git a/src/test/java/com/ejlchina/test/JsonTests.java b/okhttps/src/test/java/com/ejlchina/test/JsonTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/JsonTests.java rename to okhttps/src/test/java/com/ejlchina/test/JsonTests.java diff --git a/src/test/java/com/ejlchina/test/ListenerTests.java b/okhttps/src/test/java/com/ejlchina/test/ListenerTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/ListenerTests.java rename to okhttps/src/test/java/com/ejlchina/test/ListenerTests.java diff --git a/src/test/java/com/ejlchina/test/PreprocessorTests.java b/okhttps/src/test/java/com/ejlchina/test/PreprocessorTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/PreprocessorTests.java rename to okhttps/src/test/java/com/ejlchina/test/PreprocessorTests.java diff --git a/src/test/java/com/ejlchina/test/SimpleTests.java b/okhttps/src/test/java/com/ejlchina/test/SimpleTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/SimpleTests.java rename to okhttps/src/test/java/com/ejlchina/test/SimpleTests.java diff --git a/src/test/java/com/ejlchina/test/TagTests.java b/okhttps/src/test/java/com/ejlchina/test/TagTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/TagTests.java rename to okhttps/src/test/java/com/ejlchina/test/TagTests.java diff --git a/src/test/java/com/ejlchina/test/UploadTests.java b/okhttps/src/test/java/com/ejlchina/test/UploadTests.java similarity index 100% rename from src/test/java/com/ejlchina/test/UploadTests.java rename to okhttps/src/test/java/com/ejlchina/test/UploadTests.java From f780ad7885b408652aba3542ca66d61766c8e462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 13:31:53 +0800 Subject: [PATCH 199/924] =?UTF-8?q?=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 16 +- .../docs}/.vuepress/config.js | 0 okhttps-doc/docs/.vuepress/dist/404.html | 19 ++ .../dist/assets/css/0.styles.86d9e6f9.css | 1 + .../dist/assets/img/search.83621669.svg | 1 + .../.vuepress/dist/assets/js/10.bc5e580e.js | 1 + .../.vuepress/dist/assets/js/11.152d132f.js | 1 + .../.vuepress/dist/assets/js/12.92e24a16.js | 1 + .../.vuepress/dist/assets/js/13.d857e269.js | 1 + .../.vuepress/dist/assets/js/2.16cbe9f2.js | 1 + .../.vuepress/dist/assets/js/3.972ca2ed.js | 1 + .../.vuepress/dist/assets/js/4.fe3bf0b0.js | 1 + .../.vuepress/dist/assets/js/5.93d38f11.js | 1 + .../.vuepress/dist/assets/js/6.fd474f39.js | 1 + .../.vuepress/dist/assets/js/7.51e5642d.js | 1 + .../.vuepress/dist/assets/js/8.d296d289.js | 1 + .../.vuepress/dist/assets/js/9.bff804f8.js | 1 + .../.vuepress/dist/assets/js/app.1e2fa6f5.js | 13 ++ .../docs/.vuepress/dist/guide/android.html | 161 +++++++++++++++ .../.vuepress/dist/guide/configuration.html | 137 ++++++++++++ .../docs/.vuepress/dist/guide/features.html | 150 ++++++++++++++ .../docs/.vuepress/dist/guide/foundation.html | 130 ++++++++++++ .../docs/.vuepress/dist/guide/index.html | 79 +++++++ .../docs/.vuepress/dist/guide/updown.html | 195 ++++++++++++++++++ okhttps-doc/docs/.vuepress/dist/index.html | 72 +++++++ .../docs/.vuepress/dist}/logo.png | Bin okhttps-doc/docs/.vuepress/public/logo.png | Bin 0 -> 5800 bytes .../docs}/.vuepress/styles/index.styl | 0 {docs => okhttps-doc/docs}/README.md | 0 {docs => okhttps-doc/docs}/guide/README.md | 0 {docs => okhttps-doc/docs}/guide/android.md | 0 .../docs}/guide/configuration.md | 0 {docs => okhttps-doc/docs}/guide/features.md | 0 .../docs}/guide/foundation.md | 0 {docs => okhttps-doc/docs}/guide/updown.md | 0 package.json => okhttps-doc/package.json | 0 36 files changed, 979 insertions(+), 7 deletions(-) rename {docs => okhttps-doc/docs}/.vuepress/config.js (100%) create mode 100644 okhttps-doc/docs/.vuepress/dist/404.html create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/css/0.styles.86d9e6f9.css create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/img/search.83621669.svg create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/10.bc5e580e.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/11.152d132f.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/12.92e24a16.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/13.d857e269.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/2.16cbe9f2.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/3.972ca2ed.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/4.fe3bf0b0.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/5.93d38f11.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/6.fd474f39.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/7.51e5642d.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/8.d296d289.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/9.bff804f8.js create mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/app.1e2fa6f5.js create mode 100644 okhttps-doc/docs/.vuepress/dist/guide/android.html create mode 100644 okhttps-doc/docs/.vuepress/dist/guide/configuration.html create mode 100644 okhttps-doc/docs/.vuepress/dist/guide/features.html create mode 100644 okhttps-doc/docs/.vuepress/dist/guide/foundation.html create mode 100644 okhttps-doc/docs/.vuepress/dist/guide/index.html create mode 100644 okhttps-doc/docs/.vuepress/dist/guide/updown.html create mode 100644 okhttps-doc/docs/.vuepress/dist/index.html rename {docs/.vuepress/public => okhttps-doc/docs/.vuepress/dist}/logo.png (100%) create mode 100644 okhttps-doc/docs/.vuepress/public/logo.png rename {docs => okhttps-doc/docs}/.vuepress/styles/index.styl (100%) rename {docs => okhttps-doc/docs}/README.md (100%) rename {docs => okhttps-doc/docs}/guide/README.md (100%) rename {docs => okhttps-doc/docs}/guide/android.md (100%) rename {docs => okhttps-doc/docs}/guide/configuration.md (100%) rename {docs => okhttps-doc/docs}/guide/features.md (100%) rename {docs => okhttps-doc/docs}/guide/foundation.md (100%) rename {docs => okhttps-doc/docs}/guide/updown.md (100%) rename package.json => okhttps-doc/package.json (100%) diff --git a/.gitignore b/.gitignore index 5a255776..d39f4879 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,12 @@ -/target/ -/bin/ +/*/target/ +/*/bin/ /*/.settings/ /*/.classpath /*/.project -/.idea/ -/package-lock.json -/node_modules/ -/docs/.vuepress/dist/ -*.iml \ No newline at end of file +/*/.idea/ +/*/package-lock.json +/*/node_modules/ +/*/.vuepress/dist/* +/*/*.iml +*.iml +/.idea/ \ No newline at end of file diff --git a/docs/.vuepress/config.js b/okhttps-doc/docs/.vuepress/config.js similarity index 100% rename from docs/.vuepress/config.js rename to okhttps-doc/docs/.vuepress/config.js diff --git a/okhttps-doc/docs/.vuepress/dist/404.html b/okhttps-doc/docs/.vuepress/dist/404.html new file mode 100644 index 00000000..8d2b3afc --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/404.html @@ -0,0 +1,19 @@ + + + + + + OkHttps + + + + + + + +

404

That's a Four-Oh-Four.
+ Take me home. +
+ + + diff --git a/okhttps-doc/docs/.vuepress/dist/assets/css/0.styles.86d9e6f9.css b/okhttps-doc/docs/.vuepress/dist/assets/css/0.styles.86d9e6f9.css new file mode 100644 index 00000000..355d531c --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/css/0.styles.86d9e6f9.css @@ -0,0 +1 @@ +#nprogress{pointer-events:none}#nprogress .bar{background:#3eaf7c;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #3eaf7c,0 0 5px #3eaf7c;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border-color:#3eaf7c transparent transparent #3eaf7c;border-style:solid;border-width:2px;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}html{scroll-behavior:smooth}.go-to-top[data-v-5fd4ef0c]{cursor:pointer;position:fixed;bottom:2rem;right:2.5rem;width:2rem;color:#3eaf7c;z-index:1}.go-to-top[data-v-5fd4ef0c]:hover{color:#72cda4}@media (max-width:959px){.go-to-top[data-v-5fd4ef0c]{display:none}}.fade-enter-active[data-v-5fd4ef0c],.fade-leave-active[data-v-5fd4ef0c]{transition:opacity .3s}.fade-enter[data-v-5fd4ef0c],.fade-leave-to[data-v-5fd4ef0c]{opacity:0}.code-switcher div[class*=language-]:before{content:""}.code-switcher .tab-header ul{padding:0;text-align:right;margin-bottom:-5px;margin-top:20px}.code-switcher .tab-header li{display:inline-block;padding:0 10px;cursor:pointer;border-radius:4px;border:2px solid #eaecef;margin-left:5px;font-size:80%}.code-switcher .tab-header li.active{border-color:#3eaf7c}.icon.outbound{color:#aaa;display:inline-block;vertical-align:middle;position:relative;top:-1px}.home{padding:3.6rem 2rem 0;max-width:960px;margin:0 auto;display:block}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.8rem auto}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:#6a8bad}.home .hero .action-button{display:inline-block;font-size:1.2rem;color:#fff;background-color:#3eaf7c;padding:.8rem 1.6rem;border-radius:4px;transition:background-color .1s ease;box-sizing:border-box;border-bottom:1px solid #389d70}.home .hero .action-button:hover{background-color:#4abf8a}.home .features{border-top:1px solid #eaecef;padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:#3a5169}.home .feature p{color:#4e6e8e}.home .footer{padding:2.5rem;border-top:1px solid #eaecef;text-align:center;color:#4e6e8e}@media (max-width:719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width:419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.search-box{display:inline-block;position:relative;margin-right:1rem}.search-box input{cursor:text;width:10rem;height:2rem;color:#4e6e8e;display:inline-block;border:1px solid #cfd4db;border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:none;transition:all .2s ease;background:#fff url(/assets/img/search.83621669.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:#3eaf7c}.search-box .suggestions{background:#fff;width:20rem;position:absolute;top:2rem;border:1px solid #cfd4db;border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestions.align-right{right:0}.search-box .suggestion{line-height:1.4;padding:.4rem .6rem;border-radius:4px;cursor:pointer}.search-box .suggestion a{white-space:normal;color:#5d82a6}.search-box .suggestion a .page-title{font-weight:600}.search-box .suggestion a .header{font-size:.9em;margin-left:.25em}.search-box .suggestion.focused{background-color:#f3f4f5}.search-box .suggestion.focused a{color:#3eaf7c}@media (max-width:959px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (-ms-high-contrast:none){.search-box input{height:2rem}}@media (max-width:959px) and (min-width:719px){.search-box .suggestions{left:0}}@media (max-width:719px){.search-box{margin-right:0}.search-box input{left:1rem}.search-box .suggestions{right:0}}@media (max-width:419px){.search-box .suggestions{width:calc(100vw - 4rem)}.search-box input:focus{width:8rem}}.sidebar-button{cursor:pointer;display:none;width:1.25rem;height:1.25rem;position:absolute;padding:.6rem;top:.6rem;left:1rem}.sidebar-button .icon{display:block;width:1.25rem;height:1.25rem}@media (max-width:719px){.sidebar-button{display:block}}.dropdown-enter,.dropdown-leave-to{height:0!important}.dropdown-wrapper{cursor:pointer}.dropdown-wrapper .dropdown-title{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:transparent;border:none;font-weight:500;color:#2c3e50;pointer-events:none}.dropdown-wrapper .dropdown-title:hover{border-color:transparent}.dropdown-wrapper .dropdown-title .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.dropdown-wrapper .nav-dropdown .dropdown-item{color:inherit;line-height:1.7rem}.dropdown-wrapper .nav-dropdown .dropdown-item h4{margin:.45rem 0 0;border-top:1px solid #eee;padding:.45rem 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper{padding:0;list-style:none}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper .dropdown-subitem{font-size:.9em}.dropdown-wrapper .nav-dropdown .dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active,.dropdown-wrapper .nav-dropdown .dropdown-item a:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid #3eaf7c;border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.dropdown-wrapper .nav-dropdown .dropdown-item:first-child h4{margin-top:0;padding-top:0;border-top:0}@media (max-width:719px){.dropdown-wrapper.open .dropdown-title{margin-bottom:.5rem}.dropdown-wrapper .dropdown-title{font-weight:600;font-size:inherit}.dropdown-wrapper .dropdown-title:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown{transition:height .1s ease-out;overflow:hidden}.dropdown-wrapper .nav-dropdown .dropdown-item h4{border-top:0;margin-top:0;padding-top:0}.dropdown-wrapper .nav-dropdown .dropdown-item>a,.dropdown-wrapper .nav-dropdown .dropdown-item h4{font-size:15px;line-height:2rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width:719px){.dropdown-wrapper{height:1.8rem}.dropdown-wrapper.open .nav-dropdown,.dropdown-wrapper:hover .nav-dropdown{display:block!important}.dropdown-wrapper.open:blur{display:none}.dropdown-wrapper .dropdown-title .arrow{border-left:4px solid transparent;border-right:4px solid transparent;border-top:6px solid #ccc;border-bottom:0}.dropdown-wrapper .nav-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:#fff;padding:.6rem 0;border:1px solid;border-color:#ddd #ddd #ccc;text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}}.nav-links{display:inline-block}.nav-links a{line-height:1.4rem;color:inherit}.nav-links a.router-link-active,.nav-links a:hover{color:#3eaf7c}.nav-links .nav-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:2rem}.nav-links .nav-item:first-child{margin-left:0}.nav-links .repo-link{margin-left:1.5rem}@media (max-width:719px){.nav-links .nav-item,.nav-links .repo-link{margin-left:0}}@media (min-width:719px){.nav-links a.router-link-active,.nav-links a:hover{color:#2c3e50}.nav-item>a:not(.external).router-link-active,.nav-item>a:not(.external):hover{margin-bottom:-2px;border-bottom:2px solid #46bd87}}.navbar{padding:.7rem 1.5rem;line-height:2.2rem}.navbar a,.navbar img,.navbar span{display:inline-block}.navbar .logo{height:2.2rem;min-width:2.2rem;margin-right:.8rem;vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:#2c3e50;position:relative}.navbar .links{padding-left:1.5rem;box-sizing:border-box;background-color:#fff;white-space:nowrap;font-size:.9rem;position:absolute;right:1.5rem;top:.7rem;display:flex}.navbar .links .search-box{flex:0 0 auto;vertical-align:top}@media (max-width:719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .links{padding-left:1.5rem}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.page-edit{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-edit{padding:2rem}}@media (max-width:419px){.page-edit{padding:1.5rem}}.page-edit{padding-top:1rem;padding-bottom:1rem;overflow:auto}.page-edit .edit-link{display:inline-block}.page-edit .edit-link a{color:#4e6e8e;margin-right:.25rem}.page-edit .last-updated{float:right;font-size:.9em}.page-edit .last-updated .prefix{font-weight:500;color:#4e6e8e}.page-edit .last-updated .time{font-weight:400;color:#aaa}@media (max-width:719px){.page-edit .edit-link{margin-bottom:.5rem}.page-edit .last-updated{font-size:.8em;float:none;text-align:left}}.page-nav{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-nav{padding:2rem}}@media (max-width:419px){.page-nav{padding:1.5rem}}.page-nav{padding-top:1rem;padding-bottom:0}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid #eaecef;padding-top:1rem;overflow:auto}.page-nav .next{float:right}.page{padding-bottom:2rem;display:block}.sidebar-group .sidebar-group{padding-left:.5em}.sidebar-group:not(.collapsable) .sidebar-heading:not(.clickable){cursor:auto;color:inherit}.sidebar-group.is-sub-group{padding-left:0}.sidebar-group.is-sub-group>.sidebar-heading{font-size:.95em;line-height:1.4;font-weight:400;padding-left:2rem}.sidebar-group.is-sub-group>.sidebar-heading:not(.clickable){opacity:.5}.sidebar-group.is-sub-group>.sidebar-group-items{padding-left:1rem}.sidebar-group.is-sub-group>.sidebar-group-items>li>.sidebar-link{font-size:.95em;border-left:none}.sidebar-group.depth-2>.sidebar-heading{border-left:none}.sidebar-heading{color:#2c3e50;transition:color .15s ease;cursor:pointer;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0;border-left:.25rem solid transparent}.sidebar-heading.open,.sidebar-heading:hover{color:inherit}.sidebar-heading .arrow{position:relative;top:-.12em;left:.5em}.sidebar-heading.clickable.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-heading.clickable:hover{color:#3eaf7c}.sidebar-group-items{transition:height .1s ease-out;font-size:.95em;overflow:hidden}.sidebar .sidebar-sub-headers{padding-left:1rem;font-size:.95em}a.sidebar-link{font-size:1em;font-weight:400;display:inline-block;color:#2c3e50;border-left:.25rem solid transparent;padding:.35rem 1rem .35rem 1.25rem;line-height:1.4;width:100%;box-sizing:border-box}a.sidebar-link:hover{color:#3eaf7c}a.sidebar-link.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-group a.sidebar-link{padding-left:2rem}.sidebar-sub-headers a.sidebar-link{padding-top:.25rem;padding-bottom:.25rem;border-left:none}.sidebar-sub-headers a.sidebar-link.active{font-weight:500}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .nav-links{display:none;border-bottom:1px solid #eaecef;padding:.5rem 0 .75rem}.sidebar .nav-links a{font-weight:600}.sidebar .nav-links .nav-item,.sidebar .nav-links .repo-link{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar>.sidebar-links{padding:1.5rem 0}.sidebar>.sidebar-links>li>a.sidebar-link{font-size:1.1em;line-height:1.7;font-weight:700}.sidebar>.sidebar-links>li:not(:first-child){margin-top:.75rem}@media (max-width:719px){.sidebar .nav-links{display:block}.sidebar .nav-links .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar>.sidebar-links{padding:1rem 0}}code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}.theme-default-content code{color:#476582;padding:.25rem .5rem;margin:0;font-size:.85em;background-color:rgba(27,31,35,.05);border-radius:3px}.theme-default-content code .token.deleted{color:#ec5975}.theme-default-content code .token.inserted{color:#3eaf7c}.theme-default-content pre,.theme-default-content pre[class*=language-]{line-height:1.4;padding:1.25rem 1.5rem;margin:.85rem 0;background-color:#282c34;border-radius:6px;overflow:auto}.theme-default-content pre[class*=language-] code,.theme-default-content pre code{color:#fff;padding:0;background-color:transparent;border-radius:0}div[class*=language-]{position:relative;background-color:#282c34;border-radius:6px}div[class*=language-] .highlight-lines{-webkit-user-select:none;-ms-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlighted{background-color:rgba(0,0,0,.66)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:transparent;position:relative;z-index:1}div[class*=language-]:before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:hsla(0,0%,100%,.4)}div[class*=language-]:not(.line-numbers-mode) .line-numbers-wrapper{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlighted{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlighted:before{content:" ";position:absolute;z-index:3;left:0;top:0;display:block;width:3.5rem;height:100%;background-color:rgba(0,0,0,.66)}div[class*=language-].line-numbers-mode pre{padding-left:4.5rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers-wrapper{position:absolute;top:0;width:3.5rem;text-align:center;color:hsla(0,0%,100%,.3);padding:1.25rem 0;line-height:1.4}div[class*=language-].line-numbers-mode .line-numbers-wrapper br{-webkit-user-select:none;-ms-user-select:none;user-select:none}div[class*=language-].line-numbers-mode .line-numbers-wrapper .line-number{position:relative;z-index:4;-webkit-user-select:none;-ms-user-select:none;user-select:none;font-size:.85em}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;z-index:2;top:0;left:0;width:3.5rem;height:100%;border-radius:6px 0 0 6px;border-right:1px solid rgba(0,0,0,.66);background-color:#282c34}div[class~=language-js]:before{content:"js"}div[class~=language-ts]:before{content:"ts"}div[class~=language-html]:before{content:"html"}div[class~=language-md]:before{content:"md"}div[class~=language-vue]:before{content:"vue"}div[class~=language-css]:before{content:"css"}div[class~=language-sass]:before{content:"sass"}div[class~=language-scss]:before{content:"scss"}div[class~=language-less]:before{content:"less"}div[class~=language-stylus]:before{content:"stylus"}div[class~=language-go]:before{content:"go"}div[class~=language-java]:before{content:"java"}div[class~=language-c]:before{content:"c"}div[class~=language-sh]:before{content:"sh"}div[class~=language-yaml]:before{content:"yaml"}div[class~=language-py]:before{content:"py"}div[class~=language-docker]:before{content:"docker"}div[class~=language-dockerfile]:before{content:"dockerfile"}div[class~=language-makefile]:before{content:"makefile"}div[class~=language-javascript]:before{content:"js"}div[class~=language-typescript]:before{content:"ts"}div[class~=language-markup]:before{content:"html"}div[class~=language-markdown]:before{content:"md"}div[class~=language-json]:before{content:"json"}div[class~=language-ruby]:before{content:"rb"}div[class~=language-python]:before{content:"py"}div[class~=language-bash]:before{content:"sh"}div[class~=language-php]:before{content:"php"}.custom-block .custom-block-title{font-weight:600;margin-bottom:-.4rem}.custom-block.danger,.custom-block.tip,.custom-block.warning{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-block.tip{background-color:#f3f5f7;border-color:#42b983}.custom-block.warning{background-color:rgba(255,229,100,.3);border-color:#e7c000;color:#6b5900}.custom-block.warning .custom-block-title{color:#b29400}.custom-block.warning a{color:#2c3e50}.custom-block.danger{background-color:#ffe6e6;border-color:#c00;color:#4d0000}.custom-block.danger .custom-block-title{color:#900}.custom-block.danger a{color:#2c3e50}.custom-block.details{display:block;position:relative;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:#eee}.custom-block.details h4{margin-top:0}.custom-block.details figure:last-child,.custom-block.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-block.details summary{outline:none;cursor:pointer}.arrow{display:inline-block;width:0;height:0}.arrow.up{border-bottom:6px solid #ccc}.arrow.down,.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent}.arrow.down{border-top:6px solid #ccc}.arrow.right{border-left:6px solid #ccc}.arrow.left,.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent}.arrow.left{border-right:6px solid #ccc}.theme-default-content:not(.custom){max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.theme-default-content:not(.custom){padding:2rem}}@media (max-width:419px){.theme-default-content:not(.custom){padding:1.5rem}}.table-of-contents .badge{vertical-align:middle}body,html{padding:0;margin:0;background-color:#fff}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;color:#2c3e50}.page{padding-left:20rem}.navbar{z-index:20;right:0;height:3.6rem;background-color:#fff;box-sizing:border-box;border-bottom:1px solid #eaecef}.navbar,.sidebar-mask{position:fixed;top:0;left:0}.sidebar-mask{z-index:9;width:100vw;height:100vh;display:none}.sidebar{font-size:16px;background-color:#fff;width:20rem;position:fixed;z-index:10;margin:0;top:3.6rem;left:0;bottom:0;box-sizing:border-box;border-right:1px solid #eaecef;overflow-y:auto}.theme-default-content:not(.custom)>:first-child{margin-top:3.6rem}.theme-default-content:not(.custom) a:hover{text-decoration:underline}.theme-default-content:not(.custom) p.demo{padding:1rem 1.5rem;border:1px solid #ddd;border-radius:4px}.theme-default-content:not(.custom) img{max-width:100%}.theme-default-content.custom{padding:0;margin:0}.theme-default-content.custom img{max-width:100%}a{font-weight:500;text-decoration:none}a,p a code{color:#3eaf7c}p a code{font-weight:400}kbd{background:#eee;border:.15rem solid #ddd;border-bottom:.25rem solid #ddd;border-radius:.15rem;padding:0 .15em}blockquote{font-size:1rem;color:#999;border-left:.2rem solid #dfe2e5;margin:1rem 0;padding:.25rem 0 .25rem 1rem}blockquote>p{margin:0}ol,ul{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}.theme-default-content:not(.custom)>h1,.theme-default-content:not(.custom)>h2,.theme-default-content:not(.custom)>h3,.theme-default-content:not(.custom)>h4,.theme-default-content:not(.custom)>h5,.theme-default-content:not(.custom)>h6{margin-top:-3.1rem;padding-top:4.6rem;margin-bottom:0}.theme-default-content:not(.custom)>h1:first-child,.theme-default-content:not(.custom)>h2:first-child,.theme-default-content:not(.custom)>h3:first-child,.theme-default-content:not(.custom)>h4:first-child,.theme-default-content:not(.custom)>h5:first-child,.theme-default-content:not(.custom)>h6:first-child{margin-top:-1.5rem;margin-bottom:1rem}.theme-default-content:not(.custom)>h1:first-child+.custom-block,.theme-default-content:not(.custom)>h1:first-child+p,.theme-default-content:not(.custom)>h1:first-child+pre,.theme-default-content:not(.custom)>h2:first-child+.custom-block,.theme-default-content:not(.custom)>h2:first-child+p,.theme-default-content:not(.custom)>h2:first-child+pre,.theme-default-content:not(.custom)>h3:first-child+.custom-block,.theme-default-content:not(.custom)>h3:first-child+p,.theme-default-content:not(.custom)>h3:first-child+pre,.theme-default-content:not(.custom)>h4:first-child+.custom-block,.theme-default-content:not(.custom)>h4:first-child+p,.theme-default-content:not(.custom)>h4:first-child+pre,.theme-default-content:not(.custom)>h5:first-child+.custom-block,.theme-default-content:not(.custom)>h5:first-child+p,.theme-default-content:not(.custom)>h5:first-child+pre,.theme-default-content:not(.custom)>h6:first-child+.custom-block,.theme-default-content:not(.custom)>h6:first-child+p,.theme-default-content:not(.custom)>h6:first-child+pre{margin-top:2rem}h1:hover .header-anchor,h2:hover .header-anchor,h3:hover .header-anchor,h4:hover .header-anchor,h5:hover .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid #eaecef}h3{font-size:1.35rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0}a.header-anchor:hover{text-decoration:none}.line-number,code,kbd{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}ol,p,ul{line-height:1.7}hr{border:0;border-top:1px solid #eaecef}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto}tr{border-top:1px solid #dfe2e5}tr:nth-child(2n){background-color:#f6f8fa}td,th{border:1px solid #dfe2e5;padding:.6em 1em}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.no-navbar .theme-default-content:not(.custom)>h1,.theme-container.no-navbar h2,.theme-container.no-navbar h3,.theme-container.no-navbar h4,.theme-container.no-navbar h5,.theme-container.no-navbar h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .sidebar{top:0}@media (min-width:720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}@media (max-width:959px){.sidebar{font-size:15px;width:16.4rem}.page{padding-left:16.4rem}}@media (max-width:719px){.sidebar{top:0;padding-top:3.6rem;transform:translateX(-100%);transition:transform .2s ease}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translateX(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width:419px){h1{font-size:1.9rem}.theme-default-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}.home .hero img{height:200px}.badge[data-v-15b7b770]{display:inline-block;font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:#fff}.badge.green[data-v-15b7b770],.badge.tip[data-v-15b7b770],.badge[data-v-15b7b770]{background-color:#42b983}.badge.error[data-v-15b7b770]{background-color:#da5961}.badge.warn[data-v-15b7b770],.badge.warning[data-v-15b7b770],.badge.yellow[data-v-15b7b770]{background-color:#e7c000}.badge+.badge[data-v-15b7b770]{margin-left:5px} \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/img/search.83621669.svg b/okhttps-doc/docs/.vuepress/dist/assets/img/search.83621669.svg new file mode 100644 index 00000000..03d83913 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/img/search.83621669.svg @@ -0,0 +1 @@ + diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/10.bc5e580e.js b/okhttps-doc/docs/.vuepress/dist/assets/js/10.bc5e580e.js new file mode 100644 index 00000000..8f8cfd50 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/10.bc5e580e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{333:function(s,t,a){"use strict";a.r(t);var n=a(19),e=Object(n.a)({},(function(){var s=this,t=s.$createElement,a=s._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[a("h1",{attrs:{id:"特色"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#特色"}},[s._v("#")]),s._v(" 特色")]),s._v(" "),a("h2",{attrs:{id:"使用-httputils-类"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用-httputils-类"}},[s._v("#")]),s._v(" 使用 HttpUtils 类")]),s._v(" "),a("p",[s._v("类"),a("code",[s._v("HttpUtils")]),s._v("本是 "),a("a",{attrs:{href:"https://gitee.com/ejlchina-zhxu/httputils",target:"_blank",rel:"noopener noreferrer"}},[s._v("�身 HttpUtils"),a("OutboundLink")],1),s._v(" 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了"),a("code",[s._v("HTTP")]),s._v("接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。")]),s._v(" "),a("p",[s._v("类"),a("code",[s._v("HttpUtils")]),s._v("共定义了四个��方法:")]),s._v(" "),a("ul",[a("li",[a("code",[s._v("of(HTTP http)")]),s._v(" �置"),a("code",[s._v("HttpUtils")]),s._v("�有的"),a("code",[s._v("HTTP")]),s._v("实例(�调用此方法�默认使用一个没有没有�过任何�置的"),a("code",[s._v("HTTP")]),s._v("懒实例)")]),s._v(" "),a("li",[a("code",[s._v("sync(String url)")]),s._v(" 开始一个�步请求 (内部通过一个"),a("code",[s._v("HTTP")]),s._v("�例实现)")]),s._v(" "),a("li",[a("code",[s._v("async(String url)")]),s._v(" 开始一个异步请求 (内部通过一个"),a("code",[s._v("HTTP")]),s._v("�例实现)")]),s._v(" "),a("li",[a("code",[s._v("cancel(String tag)")]),s._v(" 按标签�消请求(内部通过一个"),a("code",[s._v("HTTP")]),s._v("�例实现)")]),s._v(" "),a("li",[a("code",[s._v("cancelAll()")]),s._v(" �消所有HTTP任务,包括�步和异步(内部通过一个"),a("code",[s._v("HTTP")]),s._v("�例实现)")]),s._v(" "),a("li",[a("code",[s._v("request(Request request)")]),s._v(" OkHttp 原生请求 (该请求��过 预处�器)")]),s._v(" "),a("li",[a("code",[s._v("webSocket(Request request, WebSocketListener listener)")]),s._v(" WebSocket通讯\n  也就是说,能使用"),a("code",[s._v("http")]),s._v("实例的地方,都�以使用"),a("code",[s._v("HttpUtils")]),s._v("类,例如:")])]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在�置HTTP实例之�,�能使用全路径方�")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Role")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" roles "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"http://api.demo.com/roles"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Role")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �置HTTP实例,全局生效")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("of")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("baseUrl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"http://api.demo.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 内部使用新的HTTP实例")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" users "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br")])]),a("h2",{attrs:{id:"异常处�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#异常处�"}},[s._v("#")]),s._v(" 异常处�")]),s._v(" "),a("p",[s._v("使用 OkHttps 时,"),a("strong",[s._v("异常处��是必须的")]),s._v(",但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:"),a("code",[s._v("nothrow()")]),s._v(",以满足��的异常处�需求。")]),s._v(" "),a("h3",{attrs:{id:"�步请求的异常"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�步请求的异常"}},[s._v("#")]),s._v(" �步请求的异常")]),s._v(" "),a("p",[s._v("默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 "),a("code",[s._v("try catch")]),s._v(" ��获,例如:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("try")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("catch")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpException")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Throwable")]),s._v(" cause "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getCause")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到异常原因")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cause "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("ConnectException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当没网络时,会抛出连接异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cause "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("SocketTimeoutException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当接�长时间未�应,会抛出超时异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cause "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("UnknownHostException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当把域�或IP写错,会抛出 UnknownHost 异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// ...")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br")])]),a("p",[s._v("这�传统的异常处�方�,当然�以解决问题,但 OkHttps 有更佳的方案:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 方法 nothrow() 让异常�直接抛出")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nothrow")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 判断执行状�")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("switch")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" RESPONSED"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 请求已正常�应")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" CANCELED"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 请求已被�消")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" NETWORK_ERROR"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 网络错误,说明用户没网了")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" TIMEOUT"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 请求超时")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" EXCEPTION"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 其它异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 还�以获得具体的异常信�")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("IOException")]),s._v(" error "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getError")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br"),a("span",{staticClass:"line-number"},[s._v("16")]),a("br"),a("span",{staticClass:"line-number"},[s._v("17")]),a("br")])]),a("h3",{attrs:{id:"异步请求的异常"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#异步请求的异常"}},[s._v("#")]),s._v(" 异步请求的异常")]),s._v(" "),a("p",[s._v("异步请求最常用的异常处�方�就是设置一个异常回调:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当�生异常时就�会走这里")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("IOException")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 这里处�请求异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br")])]),a("p",[s._v("当然,还有一个全局异常监�("),a("code",[s._v("ExceptionListener")]),s._v("):")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("exceptionListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("IOException")]),s._v(" error"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 所有请求�生异常都会走这里")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("return")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br")])]),a("p",[s._v("如果�设置"),a("code",[s._v("OnException")]),s._v("回调,也没有"),a("code",[s._v("ExceptionListener")]),s._v(",�生异常时会在 "),a("strong",[s._v("IO 线程")]),s._v(" 中�上抛出,外层无法�获:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("try")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当�生异常时就�会走这里")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("catch")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpException")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 这�方�是�获�到异常的������")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br")])]),a("p",[s._v("�使没有"),a("code",[s._v("OnException")]),s._v("回调,�生异常时,�然会走"),a("code",[s._v("OnComplete")]),s._v("回调,如果设置了的�:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当�生异常时就�会走这里")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnComplete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("State")]),s._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �生异常,会先执行这里,�以根� state 判断�生了什么")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 但执行完��然会在IO线程中�上抛出")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br")])]),a("p",[s._v("如果就是想 "),a("strong",[s._v("�处�异常,也��上抛出")]),s._v(",�生错误完全无视,�以�到�?�以�还是使用"),a("code",[s._v("nothrow()")]),s._v("方法:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nothrow")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 告诉 OkHttps �生异常时��外抛出")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当�生异常时就�会走这里")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br")])]),a("h2",{attrs:{id:"�消请求"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�消请求"}},[s._v("#")]),s._v(" �消请求")]),s._v(" "),a("p",[s._v("在 OkHttps 里�消请求共有 "),a("strong",[s._v("4 �")]),s._v(" 方��选:")]),s._v(" "),a("ul",[a("li",[s._v("使用"),a("code",[s._v("HttpCall#cancel()")]),s._v("�消�个请求(适用于异步请求,"),a("a",{attrs:{href:"#33-httpcall"}},[s._v("详� 3.3 章节")]),s._v(")")]),s._v(" "),a("li",[s._v("使用"),a("code",[s._v("HttpTask#cancel()")]),s._v("�消�个请求(适用于所有请求)(since v1.0.4)")])]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �应回调")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\ntask"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �起 GET 请求")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �消请求,并返回是��消�功")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("boolean")]),s._v(" canceled "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" \n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br")])]),a("ul",[a("li",[s._v("使用"),a("code",[s._v("HTTP#cancel(String tag)")]),s._v("按标签批��消请求(适用于所有请求,"),a("a",{attrs:{href:"#5-%E4%BD%BF%E7%94%A8%E6%A0%87%E7%AD%BE"}},[s._v("详�第 5 章节")]),s._v(")")]),s._v(" "),a("li",[s._v("使用"),a("code",[s._v("HTTP#cancelAll()")]),s._v("�消所有请求(适用于所有请求)(since v1.0.2)")])]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("cancelAll")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �消所有请求")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br")])])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/11.152d132f.js b/okhttps-doc/docs/.vuepress/dist/assets/js/11.152d132f.js new file mode 100644 index 00000000..4ce64ac2 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/11.152d132f.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{335:function(t,s,a){"use strict";a.r(s);var n=a(19),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"基础"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#基础"}},[t._v("#")]),t._v(" 基础")]),t._v(" "),a("h2",{attrs:{id:"请求方法"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#请求方法"}},[t._v("#")]),t._v(" 请求方法")]),t._v(" "),a("p",[t._v("�步与异步的"),a("code",[t._v("HttpTask")]),t._v("都拥有"),a("code",[t._v("get")]),t._v("�"),a("code",[t._v("post")]),t._v("�"),a("code",[t._v("put")]),t._v("与"),a("code",[t._v("delete")]),t._v("方法。��的是:�步"),a("code",[t._v("HttpTask")]),t._v("的这些方法返回一个"),a("code",[t._v("HttpResult")]),t._v(",而异步"),a("code",[t._v("HttpTask")]),t._v("的这些方法返回一个"),a("code",[t._v("HttpCall")]),t._v("。")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" res1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �步 GET")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" res2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �步 POST")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" res3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("put")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �步 PUT")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" res4 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("delete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �步 DELETE")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步 GET")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步 POST")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("put")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步 PUT")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call4 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("delete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步 DELETE")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("h2",{attrs:{id:"回调函数"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#回调函数"}},[t._v("#")]),t._v(" 回调函数")]),t._v(" "),a("p",[t._v("OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/{id}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// http://api.demo.com/users/1")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addPathParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �应回调")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IOException")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异常回调")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnComplete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),t._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 完�回调,无论�功失败都会执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 并且在 �应|异常回调 之�执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br")])]),a("p",[t._v("OkHttps �时还支� "),a("strong",[t._v("全局回调")]),t._v(" 和 "),a("strong",[t._v("回调阻断")]),t._v(" 机制,详� "),a("RouterLink",{attrs:{to:"/guide/configuration.html#全局回调监�"}},[t._v("全局回调监�")]),t._v("。")],1),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("ul",[a("li",[t._v("�有异步请求��以设置这三�(�应|异常|完�)回调")]),t._v(" "),a("li",[t._v("�步请求直接返回结果,无需使用回调")])])]),t._v(" "),a("h2",{attrs:{id:"httpresult"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#httpresult"}},[t._v("#")]),t._v(" HttpResult")]),t._v(" "),a("p",[a("code",[t._v("HttpResult")]),t._v("是HTTP请求执行完�的结果,它是�步请求方法( "),a("code",[t._v("get")]),t._v("�"),a("code",[t._v("post")]),t._v("�"),a("code",[t._v("put")]),t._v("�"),a("code",[t._v("delete")]),t._v(")的返回值,也是异步请求�应回调("),a("code",[t._v("OnResponse")]),t._v(")的�数,它定义了如下方法:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("getState()")]),t._v(" 得到请求执行状�枚举,它有以下�值:\n"),a("ul",[a("li",[a("code",[t._v("State.CANCELED")]),t._v(" 请求被�消")]),t._v(" "),a("li",[a("code",[t._v("State.RESPONSED")]),t._v(" 已收到�应")]),t._v(" "),a("li",[a("code",[t._v("State.TIMEOUT")]),t._v(" 请求超时")]),t._v(" "),a("li",[a("code",[t._v("State.NETWORK_ERROR")]),t._v(" 网络错误")]),t._v(" "),a("li",[a("code",[t._v("State.EXCEPTION")]),t._v(" 其它请求异常")])])]),t._v(" "),a("li",[a("code",[t._v("getStatus()")]),t._v(" 得到HTTP状��")]),t._v(" "),a("li",[a("code",[t._v("isSuccessful()")]),t._v(" 是��应�功,状��在 [200..300) 之间")]),t._v(" "),a("li",[a("code",[t._v("getHeaders()")]),t._v(" 得到HTTP�应头")]),t._v(" "),a("li",[a("code",[t._v("getHeaders(String name)")]),t._v(" 得到HTTP�应头")]),t._v(" "),a("li",[a("code",[t._v("getHeader(String name)")]),t._v(" 得到HTTP�应头")]),t._v(" "),a("li",[a("code",[t._v("getBody()")]),t._v(" 得到�应报文体"),a("code",[t._v("Body")]),t._v("实例,它定义了如下方法(对�一个"),a("code",[t._v("Body")]),t._v("实例,以下的"),a("code",[t._v("toXXX()")]),t._v("类方法�能使用一个且仅能调用一次,除�先使用 cache 方法):\n"),a("ul",[a("li",[a("code",[t._v("toBytes()")]),t._v(" 返回字节数组")]),t._v(" "),a("li",[a("code",[t._v("toByteStream()")]),t._v(" 返回字节输入�")]),t._v(" "),a("li",[a("code",[t._v("toCharStream()")]),t._v(" 返回字符输入�")]),t._v(" "),a("li",[a("code",[t._v("toString()")]),t._v(" 返回字符串")]),t._v(" "),a("li",[a("code",[t._v("toJsonObject()")]),t._v(" 返回Json对象")]),t._v(" "),a("li",[a("code",[t._v("toJsonArray()")]),t._v(" 返回Json数组")]),t._v(" "),a("li",[a("code",[t._v("toBean(Class type)")]),t._v(" 返回根�type自动json解��的JavaBean")]),t._v(" "),a("li",[a("code",[t._v("toList(Class type)")]),t._v(" 返回根�type自动json解��的JavaBean列表")]),t._v(" "),a("li",[a("code",[t._v("toFile(String filePath)")]),t._v(" 下载到指定路径")]),t._v(" "),a("li",[a("code",[t._v("toFile(File file)")]),t._v(" 下载到指定文件")]),t._v(" "),a("li",[a("code",[t._v("toFolder(String dirPath)")]),t._v(" 下载到指定目录")]),t._v(" "),a("li",[a("code",[t._v("toFolder(File dir)")]),t._v(" 下载到指定目录")]),t._v(" "),a("li",[a("code",[t._v("getContentType()")]),t._v(" 返回报文体的媒体类型")]),t._v(" "),a("li",[a("code",[t._v("getContentLength()")]),t._v(" 返回报文体的字节长度")]),t._v(" "),a("li",[a("code",[t._v("cache()")]),t._v(" 缓存报文体,开�缓存����使用"),a("code",[t._v("toXXX()")]),t._v("类方法")]),t._v(" "),a("li",[a("code",[t._v("close()")]),t._v(" 关闭报文体,未对报文体�任何消费时使用,比如�读�报文头")])])]),t._v(" "),a("li",[a("code",[t._v("getError()")]),t._v(" 执行中�生的异常,自动�获执行请求时�生的 网络超时�网络错误 和 其它IO异常")]),t._v(" "),a("li",[a("code",[t._v("close()")]),t._v(" 关闭报文,未对报文体�任何消费时使用,比如�读�长度")])]),t._v(" "),a("p",[t._v("示例,请求结果自动转Bean和List:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 自动转Bean")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),t._v(" order "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/orders/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 自动转List")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" orders "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/orders"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br")])]),a("p",[t._v("示例,使用 cache 方法:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Body")]),t._v(" body "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/orders"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cache")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用 cache �,�以多次使用 toXXX() 方法")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toJsonArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br")])]),a("p",[t._v("示例,获�下载文件的大�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" size "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �是想获得文件大�,�消费报文体,所以直接关闭")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getContentLength")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获得待下载文件的大�")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络��")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"size = "')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" size"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("h2",{attrs:{id:"httpcall"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#httpcall"}},[t._v("#")]),t._v(" HttpCall")]),t._v(" "),a("p",[a("code",[t._v("HttpCall")]),t._v("对象是异步请求方法("),a("code",[t._v("get")]),t._v("�"),a("code",[t._v("post")]),t._v("�"),a("code",[t._v("put")]),t._v("�"),a("code",[t._v("delete")]),t._v(")的返回值,与"),a("code",[t._v("java")]),t._v("的"),a("code",[t._v("Future")]),t._v("接�很�,它有如下方法:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("cancel()")]),t._v(" �消本次请求,返回�消结果")]),t._v(" "),a("li",[a("code",[t._v("isCanceled()")]),t._v(" 返回请求是�被�消")]),t._v(" "),a("li",[a("code",[t._v("isDone()")]),t._v(" 返回是�执行完�,包��消和失败")]),t._v(" "),a("li",[a("code",[t._v("getResult()")]),t._v(" 返回执行结果"),a("code",[t._v("HttpResult")]),t._v("对象,若请求未执行完,则挂起当�线程直到执行完��返回")])]),t._v(" "),a("p",[t._v("�消一个异步请求示例:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("call"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isCanceled")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// false")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("boolean")]),t._v(" success "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" call"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �消请求")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("call"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isCanceled")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("h2",{attrs:{id:"构建http任务"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#构建http任务"}},[t._v("#")]),t._v(" 构建HTTP任务")]),t._v(" "),a("p",[a("code",[t._v("HTTP")]),t._v("对象的"),a("code",[t._v("sync")]),t._v("与"),a("code",[t._v("async")]),t._v("方法返回一个"),a("code",[t._v("HttpTask")]),t._v("对象,该对象�供了�链�调用的"),a("code",[t._v("addXXX")]),t._v("与"),a("code",[t._v("setXXX")]),t._v("等系列方法用于构建任务本身。")]),t._v(" "),a("ul",[a("li",[a("p",[a("code",[t._v("addHeader(String name, String value)")]),t._v(" 添加请求头")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addHeader(Map headers)")]),t._v(" 添加请求头")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addPathParam(String name, Object value)")]),t._v(" 添加路径�数:替�URL里的{name}��符")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addPathParam(Map params)")]),t._v(" 添加路径�数:替�URL里的{name}��符")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addUrlParam(String name, Object value)")]),t._v(" 添加URL�数:拼接在URL的?之�(查询�数)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addUrlParam(Map params)")]),t._v(" 添加URL�数:拼接在URL的?之�(查询�数)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addBodyParam(String name, Object value)")]),t._v(" 添加Body�数:以表�key=value&的形�放在报文体内(表��数)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addBodyParam(Map params)")]),t._v(" 添加Body�数:以表�key=value&的形�放在报文体内(表��数)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addJsonParam(String name, Object value)")]),t._v(" 添加Json�数:请求体为Json(支�多层结构)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addJsonParam(Map params)")]),t._v(" 添加Json�数:请求体为Json(支�多层结构)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("setRequestJson(Object json)")]),t._v(" 设置请求体的Json字符串 或待转�为 Json的 JavaBean")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("setRequestJson(Object bean, String dateFormat)")]),t._v(" 设置请求体的Json字符串 或待转�为 Json的 JavaBean")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String filePath)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, File file)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String type, InputStream inputStream)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String type, String fileName, InputStream input)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String type, byte[] content)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String type, String fileName, byte[] content)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("setTag(String tag)")]),t._v(" 为HTTP任务添加标签")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("setRange(long rangeStart)")]),t._v(" 设置Range头信�,用于"),a("RouterLink",{attrs:{to:"/guide/updown.html#实现断点续传"}},[t._v("断点续传")])],1)]),t._v(" "),a("li",[a("p",[a("code",[t._v("setRange(long rangeStart, long rangeEnd)")]),t._v(" 设置Range头信�,�用于"),a("RouterLink",{attrs:{to:"/guide/updown.html#实现分�下载"}},[t._v("分�下载")])],1)]),t._v(" "),a("li",[a("p",[a("code",[t._v("bind(Object object)")]),t._v(" 绑定一个对象,�用于实现Android里的"),a("RouterLink",{attrs:{to:"/guide/android.html#生命周期绑定"}},[t._v("生命周期绑定")])],1)])]),t._v(" "),a("h2",{attrs:{id:"使用标签"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用标签"}},[t._v("#")]),t._v(" 使用标签")]),t._v(" "),a("p",[t._v("有时候我们想对HTTP任务加以分类,这时候�以使用标签功能:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(1)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(2)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A.B"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(3)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"B"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(4)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"B"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"C"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// 从 v1.0.4 标签将以追加模�添加,等效于 setTag("B.C")')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(5)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"C"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br"),a("span",{staticClass:"line-number"},[t._v("17")]),a("br"),a("span",{staticClass:"line-number"},[t._v("18")]),a("br"),a("span",{staticClass:"line-number"},[t._v("19")]),a("br"),a("span",{staticClass:"line-number"},[t._v("20")]),a("br")])]),a("p",[t._v("当使用标签�,就�以按标签批�的对HTTP任务进行�消:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("int")]),t._v(" count "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"B"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('//(2)(3)(4)被�消(�消标签包�"B"的任务)')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("count"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 输出 3")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br")])]),a("p",[t._v("标签除了�以用��消任务,在预处�器中它也�以�挥作用,请�� "),a("RouterLink",{attrs:{to:"/guide/configuration.html#并行预处�器"}},[t._v("并行预处�器")]),t._v(" 与 "),a("RouterLink",{attrs:{to:"/guide/configuration.html#串行预处�器(token问题最佳解决方案)"}},[t._v("串行预处�器(token问题最佳解决方案)")]),t._v("。")],1)])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/12.92e24a16.js b/okhttps-doc/docs/.vuepress/dist/assets/js/12.92e24a16.js new file mode 100644 index 00000000..e954337f --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/12.92e24a16.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{332:function(t,s,a){"use strict";a.r(s);var n=a(19),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"上传下载"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#上传下载"}},[t._v("#")]),t._v(" 上传下载")]),t._v(" "),a("h2",{attrs:{id:"文件下载"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#文件下载"}},[t._v("#")]),t._v(" 文件下载")]),t._v(" "),a("p",[t._v("OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用 GET 方法(其它方法也�以,看�务器支�)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 得到报文体")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载到指定的路径")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �动下载")]),t._v("\n\nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载到指定的目录,文件�将根�下载信�自动生�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br")])]),a("p",[t._v("或使用异步连接方�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br")])]),a("p",[t._v("这里�说明一下:"),a("code",[t._v("sync")]),t._v("与"),a("code",[t._v("async")]),t._v("的区别在于连接�务器并得到�应这个过程的�步与异步(这个过程的耗时在大文件下载中�比��),而"),a("code",[t._v("start")]),t._v("方法�动的下载过程则都是异步的。")]),t._v(" "),a("h3",{attrs:{id:"下载进度监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#下载进度监�"}},[t._v("#")]),t._v(" 下载进度监�")]),t._v(" "),a("p",[t._v("就直接上代�啦,诸�一看便懂:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setStepBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1024")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置�接收 1024 个字节执行一次进度回调(�设置默认为 8192) ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// .setStepRate(0.01) // 设置�接收 1% 执行一次进度回调(�设置以 StepBytes 为准) ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载进度回调")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" doneBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDoneBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已下载字节数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" totalBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTotalBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 总共的字节数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("double")]),t._v(" rate "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已下载的比例")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("boolean")]),t._v(" isDone "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isDone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 是�下载完�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 指定下载的目录,文件�将根�下载信�自动生�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// .toFile("D:/download/test.zip") // 指定下载的路径,若文件已存在则覆盖')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnSuccess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载�功回调")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br"),a("span",{staticClass:"line-number"},[t._v("17")]),a("br")])]),a("p",[t._v("值得一�的是:由于 OkHttps 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有"),a("code",[t._v("Content-Length")]),t._v("头),例如:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" users "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setStepBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("h3",{attrs:{id:"下载过程控制"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#下载过程控制"}},[t._v("#")]),t._v(" 下载过程控制")]),t._v(" "),a("p",[t._v("过于简�:还是直接上代�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ctrl")]),t._v(" ctrl "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 该方法返回一个下载过程控制器")]),t._v("\n \nctrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载状�")]),t._v("\nctrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("pause")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 暂�下载")]),t._v("\nctrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("resume")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ��下载")]),t._v("\nctrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �消下载(�时会删除文件,����)")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br")])]),a("p",[t._v("无论是�步还是异步�起的下载请求,都�以�以上的控制:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 拿到下载控制器")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ctrl")]),t._v(" ctrl "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br")])]),a("h3",{attrs:{id:"实现断点续传"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#实现断点续传"}},[t._v("#")]),t._v(" 实现断点续传")]),t._v(" "),a("p",[t._v("OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到 "),a("strong",[t._v("断点")]),t._v(",便将��的问题�得简�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnFailure")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Failure")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载失败回调,以便接收诸如网络错误等失败信�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IOException")]),t._v(" e "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 具体的异常信�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" doneBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDoneBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已下载的字节数(断点),需��存,用于断点续传")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载生�的文件,需��存 ,用于断点续传(��存路径也�以)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br")])]),a("p",[t._v("下�代�实现续传:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" doneBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 拿到�存的断点")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 待续传的文件")]),t._v("\n\nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setRange")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("doneBytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置断点(已下载的字节数)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载到�一个文件里")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setAppended")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 开�文件追加模�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnSuccess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnFailure")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Failure")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br")])]),a("h3",{attrs:{id:"实现分�下载"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#实现分�下载"}},[t._v("#")]),t._v(" 实现分�下载")]),t._v(" "),a("p",[t._v("当文件很大时,有时候我们会考虑分�下载,与断点续传的�路是一样的,示例代�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" url "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://api.demo.com/download/test.zip"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" totalSize "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getContentLength")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获得待下载文件的大�(由于未消费报文体,所以该请求�会消耗下载报文体的时间和网络��)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("download")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 从第 0 �开始下载")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sleep")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("50000")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 等待下载完�(�然本例的主线程就结�啦)")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("download")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("int")]),t._v(" index"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" size "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1024")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1024")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ��下载 3M ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" start "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" index "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" size"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" end "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Math")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("min")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("start "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" size"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setRange")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("start"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" end"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置本次下载的范围")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载到�一个文件里")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setAppended")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 开�文件追加模�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnSuccess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("end "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若未下载完,则继续下载下一�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("download")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" index "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"下载完�"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br"),a("span",{staticClass:"line-number"},[t._v("17")]),a("br"),a("span",{staticClass:"line-number"},[t._v("18")]),a("br"),a("span",{staticClass:"line-number"},[t._v("19")]),a("br"),a("span",{staticClass:"line-number"},[t._v("20")]),a("br"),a("span",{staticClass:"line-number"},[t._v("21")]),a("br"),a("span",{staticClass:"line-number"},[t._v("22")]),a("br"),a("span",{staticClass:"line-number"},[t._v("23")]),a("br"),a("span",{staticClass:"line-number"},[t._v("24")]),a("br"),a("span",{staticClass:"line-number"},[t._v("25")]),a("br"),a("span",{staticClass:"line-number"},[t._v("26")]),a("br"),a("span",{staticClass:"line-number"},[t._v("27")]),a("br"),a("span",{staticClass:"line-number"},[t._v("28")]),a("br")])]),a("h2",{attrs:{id:"文件上传"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#文件上传"}},[t._v("#")]),t._v(" 文件上传")]),t._v(" "),a("p",[t._v("一个简�文件上传的示例:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addFileParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 上传�法一般使用 POST 或 PUT,看�务器支�")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br")])]),a("p",[t._v("异步上传也是完全一样:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addFileParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br")])]),a("h3",{attrs:{id:"上传进度监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#上传进度监�"}},[t._v("#")]),t._v(" 上传进度监�")]),t._v(" "),a("p",[t._v("OkHttps 的上传进度监�,监�的是所有请求报文体的��进度,示例代�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Jack"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addFileParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"avatar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/image/avatar.jpg"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setStepBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1024")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置��� 1024 个字节执行一次进度回调(�设置默认为 8192) ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// .setStepRate(0.01) // 设置��� 1% 执行一次进度回调(�设置以 StepBytes 为准) ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 上传进度回调")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" doneBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDoneBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已��字节数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" totalBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTotalBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 总共的字节数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("double")]),t._v(" rate "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已��的比例")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("boolean")]),t._v(" isDone "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isDone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 是���完�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br")])]),a("p",[t._v("咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在"),a("code",[t._v("get/post")]),t._v("方法之�使用这些API,下载是在"),a("code",[t._v("getBody")]),t._v("方法之�使用。很好�解:"),a("code",[t._v("get/post")]),t._v("之�是准备��请求时段,有上传的�义,而"),a("code",[t._v("getBody")]),t._v("之�,已是报文�应的时段,当然是下载。")]),t._v(" "),a("h3",{attrs:{id:"上传过程控制"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#上传过程控制"}},[t._v("#")]),t._v(" 上传过程控制")]),t._v(" "),a("p",[t._v("上传文件的过程控制就很简�,和常规请求一样,�有异步�起的上传�以�消:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addFileParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\ncall"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �消上传")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("p",[t._v("上传就没有暂�和继续这个功能啦,应该没人有这个需求�?")])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/13.d857e269.js b/okhttps-doc/docs/.vuepress/dist/assets/js/13.d857e269.js new file mode 100644 index 00000000..126a94c9 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/13.d857e269.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{281:function(n,w,o){}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/2.16cbe9f2.js b/okhttps-doc/docs/.vuepress/dist/assets/js/2.16cbe9f2.js new file mode 100644 index 00000000..7e02b99a --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/2.16cbe9f2.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{282:function(t,e,n){"use strict";n.d(e,"d",(function(){return i})),n.d(e,"a",(function(){return a})),n.d(e,"i",(function(){return s})),n.d(e,"f",(function(){return u})),n.d(e,"g",(function(){return c})),n.d(e,"h",(function(){return l})),n.d(e,"b",(function(){return h})),n.d(e,"e",(function(){return f})),n.d(e,"k",(function(){return p})),n.d(e,"l",(function(){return d})),n.d(e,"c",(function(){return g})),n.d(e,"j",(function(){return v}));n(20),n(84),n(143),n(298),n(145),n(57),n(25),n(283),n(58),n(148),n(88);var i=/#.*$/,r=/\.(md|html)$/,a=/\/$/,s=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(i,"").replace(r,"")}function u(t){return s.test(t)}function c(t){return/^mailto:/.test(t)}function l(t){return/^tel:/.test(t)}function h(t){if(u(t))return t;var e=t.match(i),n=e?e[0]:"",r=o(t);return a.test(r)?t:r+".html"+n}function f(t,e){var n=decodeURIComponent(t.hash),r=function(t){var e=t.match(i);if(e)return e[0]}(e);return(!r||n===r)&&o(t.path)===o(e)}function p(t,e,n){if(u(e))return{type:"external",path:e};n&&(e=function(t,e,n){var i=t.charAt(0);if("/"===i)return t;if("?"===i||"#"===i)return e+t;var r=e.split("/");n&&r[r.length-1]||r.pop();for(var a=t.replace(/^\//,"").split("/"),s=0;s3&&void 0!==arguments[3]?arguments[3]:1;if("string"==typeof e)return p(n,e,i);if(Array.isArray(e))return Object.assign(p(n,e[0],i),{title:e[1]});var a=e.children||[];return 0===a.length&&e.path?Object.assign(p(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,children:a.map((function(e){return t(e,n,i,r+1)})),collapsable:!1!==e.collapsable}}(t,r,c)})):[]}return[]}function g(t){var e;return(t=t.map((function(t){return Object.assign({},t)}))).forEach((function(t){2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)})),t.filter((function(t){return 2===t.level}))}function v(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},283:function(t,e,n){"use strict";var i=n(89),r=n(8),a=n(14),s=n(13),o=n(90),u=n(91);i("match",1,(function(t,e,n){return[function(e){var n=s(this),i=null==e?void 0:e[t];return void 0!==i?i.call(e,n):new RegExp(e)[t](String(n))},function(t){var i=n(e,t,this);if(i.done)return i.value;var s=r(t),c=String(this);if(!s.global)return u(s,c);var l=s.unicode;s.lastIndex=0;for(var h,f=[],p=0;null!==(h=u(s,c));){var d=String(h[0]);f[p]=d,""===d&&(s.lastIndex=o(c,a(s.lastIndex),l)),p++}return 0===p?null:f}]}))},284:function(t,e,n){},285:function(t,e,n){},286:function(t,e,n){},287:function(t,e,n){},288:function(t,e,n){},289:function(t,e,n){},290:function(t,e,n){},291:function(t,e,n){},292:function(t,e,n){},293:function(t,e,n){},294:function(t,e,n){},295:function(t,e,n){},296:function(t,e,n){},298:function(t,e,n){n(0)({target:"Array",stat:!0},{isArray:n(40)})},299:function(t,e,n){"use strict";var i=n(0),r=n(146).trim;i({target:"String",proto:!0,forced:n(311)("trim")},{trim:function(){return r(this)}})},300:function(t,e,n){var i=n(6),r=n(3),a=n(82),s=n(155),o=n(7).f,u=n(39).f,c=n(86),l=n(144),h=n(150),f=n(21),p=n(1),d=n(37).set,g=n(312),v=n(2)("match"),m=r.RegExp,b=m.prototype,k=/a/g,_=/a/g,x=new m(k)!==k,C=h.UNSUPPORTED_Y;if(i&&a("RegExp",!x||C||p((function(){return _[v]=!1,m(k)!=k||m(_)==_||"/a/i"!=m(k,"i")})))){for(var $=function(t,e){var n,i=this instanceof $,r=c(t),a=void 0===e;if(!i&&r&&t.constructor===$&&a)return t;x?r&&!a&&(t=t.source):t instanceof $&&(a&&(e=l.call(t)),t=t.source),C&&(n=!!e&&e.indexOf("y")>-1)&&(e=e.replace(/y/g,""));var o=s(x?new m(t,e):m(t,e),i?this:b,$);return C&&n&&d(o,{sticky:n}),o},L=function(t){t in $||o($,t,{configurable:!0,get:function(){return m[t]},set:function(e){m[t]=e}})},y=u(m),w=0;y.length>w;)L(y[w++]);b.constructor=$,$.prototype=b,f(r,"RegExp",$)}g("RegExp")},301:function(t,e,n){"use strict";var i=n(21),r=n(8),a=n(1),s=n(144),o=RegExp.prototype,u=o.toString,c=a((function(){return"/a/b"!=u.call({source:"a",flags:"b"})})),l="toString"!=u.name;(c||l)&&i(RegExp.prototype,"toString",(function(){var t=r(this),e=String(t.source),n=t.flags;return"/"+e+"/"+String(void 0===n&&t instanceof RegExp&&!("flags"in o)?s.call(t):n)}),{unsafe:!0})},302:function(t,e){t.exports=function(t){return null==t}},303:function(t,e,n){"use strict";n.r(e);n(142);var i=n(282),r={name:"SidebarGroup",components:{DropdownTransition:n(304).a},props:["item","open","collapsable","depth"],beforeCreate:function(){this.$options.components.SidebarLinks=n(303).default},methods:{isActive:i.e}},a=(n(324),n(19)),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{staticClass:"sidebar-group",class:[{collapsable:t.collapsable,"is-sub-group":0!==t.depth},"depth-"+t.depth]},[t.item.path?n("RouterLink",{staticClass:"sidebar-heading clickable",class:{open:t.open,active:t.isActive(t.$route,t.item.path)},attrs:{to:t.item.path},nativeOn:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]):n("p",{staticClass:"sidebar-heading",class:{open:t.open},on:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]),t._v(" "),n("DropdownTransition",[t.open||!t.collapsable?n("SidebarLinks",{staticClass:"sidebar-group-items",attrs:{items:t.item.children,"sidebar-depth":t.item.sidebarDepth,depth:t.depth+1}}):t._e()],1)],1)}),[],!1,null,null,null).exports;n(325),n(57);function o(t,e,n,i,r){var a={props:{to:e,activeClass:"",exactActiveClass:""},class:{active:i,"sidebar-link":!0}};return r>2&&(a.style={"padding-left":r+"rem"}),t("RouterLink",a,n)}function u(t,e,n,r,a){var s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:1;return!e||s>a?null:t("ul",{class:"sidebar-sub-headers"},e.map((function(e){var c=Object(i.e)(r,n+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[o(t,n+"#"+e.slug,e.title,c,e.level-1),u(t,e.children,n,r,a,s+1)])})))}var c={functional:!0,props:["item","sidebarDepth"],render:function(t,e){var n=e.parent,r=n.$page,a=(n.$site,n.$route),s=n.$themeConfig,c=n.$themeLocaleConfig,l=e.props,h=l.item,f=l.sidebarDepth,p=Object(i.e)(a,h.path),d="auto"===h.type?p||h.children.some((function(t){return Object(i.e)(a,h.basePath+"#"+t.slug)})):p,g="external"===h.type?function(t,e,n){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[n,t("OutboundLink")])}(t,h.path,h.title||h.path):o(t,h.path,h.title||h.path,d),v=[r.frontmatter.sidebarDepth,f,c.sidebarDepth,s.sidebarDepth,1].find((function(t){return void 0!==t})),m=c.displayAllHeaders||s.displayAllHeaders;return"auto"===h.type?[g,u(t,h.children,h.basePath,a,v)]:(d||m)&&h.headers&&!i.d.test(h.path)?[g,u(t,Object(i.c)(h.headers),h.path,a,v)]:g}};n(326);function l(t,e){return"group"===e.type&&e.children.some((function(e){return"group"===e.type?l(t,e):"page"===e.type&&Object(i.e)(t,e.path)}))}var h={name:"SidebarLinks",components:{SidebarGroup:s,SidebarLink:Object(a.a)(c,void 0,void 0,!1,null,null,null).exports},props:["items","depth","sidebarDepth"],data:function(){return{openGroupIndex:0}},watch:{$route:function(){this.refreshIndex()}},created:function(){this.refreshIndex()},methods:{refreshIndex:function(){var t=function(t,e){for(var n=0;n-1&&(this.openGroupIndex=t)},toggleGroup:function(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive:function(t){return Object(i.e)(this.$route,t.regularPath)}}},f=Object(a.a)(h,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.items.length?n("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(e,i){return n("li",{key:i},["group"===e.type?n("SidebarGroup",{attrs:{item:e,open:i===t.openGroupIndex,collapsable:e.collapsable||e.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(i)}}}):n("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:e}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=f.exports},304:function(t,e,n){"use strict";var i={name:"DropdownTransition",methods:{setHeight:function(t){t.style.height=t.scrollHeight+"px"},unsetHeight:function(t){t.style.height=""}}},r=(n(316),n(19)),a=Object(r.a)(i,(function(){var t=this.$createElement;return(this._self._c||t)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.a=a.exports},305:function(t,e,n){"use strict";var i=n(0),r=n(306);i({target:"String",proto:!0,forced:n(307)("link")},{link:function(t){return r(this,"a","href",t)}})},306:function(t,e,n){var i=n(13),r=/"/g;t.exports=function(t,e,n,a){var s=String(i(t)),o="<"+e;return""!==n&&(o+=" "+n+'="'+String(a).replace(r,""")+'"'),o+">"+s+""}},307:function(t,e,n){var i=n(1);t.exports=function(t){return i((function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}))}},308:function(t,e,n){"use strict";var i=n(284);n.n(i).a},309:function(t,e,n){var i=n(0),r=n(310);i({global:!0,forced:parseInt!=r},{parseInt:r})},310:function(t,e,n){var i=n(3),r=n(146).trim,a=n(147),s=i.parseInt,o=/^[+-]?0[Xx]/,u=8!==s(a+"08")||22!==s(a+"0x16");t.exports=u?function(t,e){var n=r(String(t));return s(n,e>>>0||(o.test(n)?16:10))}:s},311:function(t,e,n){var i=n(1),r=n(147);t.exports=function(t){return i((function(){return!!r[t]()||"​…᠎"!="​…᠎"[t]()||r[t].name!==t}))}},312:function(t,e,n){"use strict";var i=n(38),r=n(7),a=n(2),s=n(6),o=a("species");t.exports=function(t){var e=i(t),n=r.f;s&&e&&!e[o]&&n(e,o,{configurable:!0,get:function(){return this}})}},313:function(t,e,n){"use strict";var i,r=n(0),a=n(22).f,s=n(14),o=n(85),u=n(13),c=n(87),l=n(26),h="".endsWith,f=Math.min,p=c("endsWith");r({target:"String",proto:!0,forced:!!(l||p||(i=a(String.prototype,"endsWith"),!i||i.writable))&&!p},{endsWith:function(t){var e=String(u(this));o(t);var n=arguments.length>1?arguments[1]:void 0,i=s(e.length),r=void 0===n?i:f(s(n),i),a=String(t);return h?h.call(e,a,r):e.slice(r-a.length,r)===a}})},314:function(t,e,n){"use strict";var i=n(285);n.n(i).a},315:function(t,e,n){"use strict";var i=n(286);n.n(i).a},316:function(t,e,n){"use strict";var i=n(287);n.n(i).a},317:function(t,e,n){"use strict";var i=n(288);n.n(i).a},318:function(t,e,n){"use strict";var i=n(289);n.n(i).a},319:function(t,e,n){"use strict";var i=n(290);n.n(i).a},320:function(t,e,n){"use strict";var i=n(291);n.n(i).a},321:function(t,e,n){var i=n(28),r=n(10),a=n(23);t.exports=function(t){return"string"==typeof t||!r(t)&&a(t)&&"[object String]"==i(t)}},322:function(t,e,n){"use strict";var i=n(292);n.n(i).a},323:function(t,e,n){"use strict";var i=n(293);n.n(i).a},324:function(t,e,n){"use strict";var i=n(294);n.n(i).a},325:function(t,e,n){"use strict";var i=n(0),r=n(27).find,a=n(83),s=n(15),o=!0,u=s("find");"find"in[]&&Array(1).find((function(){o=!1})),i({target:"Array",proto:!0,forced:o||!u},{find:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),a("find")},326:function(t,e,n){"use strict";var i=n(295);n.n(i).a},327:function(t,e,n){"use strict";var i=n(296);n.n(i).a},329:function(t,e,n){"use strict";n.r(e);n(142),n(81),n(305);var i=n(282),r={name:"NavLink",props:{item:{required:!0}},computed:{link:function(){return Object(i.b)(this.item.link)},exact:function(){var t=this;return this.$site.locales?Object.keys(this.$site.locales).some((function(e){return e===t.link})):"/"===this.link},isNonHttpURI:function(){return Object(i.g)(this.link)||Object(i.h)(this.link)},isBlankTarget:function(){return"_blank"===this.target},isInternal:function(){return!Object(i.f)(this.link)&&!this.isBlankTarget},target:function(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(i.f)(this.link)?"_blank":""},rel:function(){return this.isNonHttpURI?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":""}},methods:{focusoutAction:function(){this.$emit("focusout")}}},a=n(19),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isInternal?n("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction(e)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):n("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?n("OutboundLink"):t._e()],1)}),[],!1,null,null,null).exports,o={name:"Home",components:{NavLink:s},computed:{data:function(){return this.$page.frontmatter},actionLink:function(){return{link:this.data.actionLink,text:this.data.actionText}}}},u=(n(308),Object(a.a)(o,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("main",{staticClass:"home",attrs:{"aria-labelledby":"main-title"}},[n("header",{staticClass:"hero"},[t.data.heroImage?n("img",{attrs:{src:t.$withBase(t.data.heroImage),alt:t.data.heroAlt||"hero"}}):t._e(),t._v(" "),null!==t.data.heroText?n("h1",{attrs:{id:"main-title"}},[t._v("\n "+t._s(t.data.heroText||t.$title||"Hello")+"\n ")]):t._e(),t._v(" "),null!==t.data.tagline?n("p",{staticClass:"description"},[t._v("\n "+t._s(t.data.tagline||t.$description||"Welcome to your VuePress site")+"\n ")]):t._e(),t._v(" "),t.data.actionText&&t.data.actionLink?n("p",{staticClass:"action"},[n("NavLink",{staticClass:"action-button",attrs:{item:t.actionLink}})],1):t._e()]),t._v(" "),t.data.features&&t.data.features.length?n("div",{staticClass:"features"},t._l(t.data.features,(function(e,i){return n("div",{key:i,staticClass:"feature"},[n("h2",[t._v(t._s(e.title))]),t._v(" "),n("p",[t._v(t._s(e.details))])])})),0):t._e(),t._v(" "),n("Content",{staticClass:"theme-default-content custom"}),t._v(" "),t.data.footer?n("div",{staticClass:"footer"},[t._v("\n "+t._s(t.data.footer)+"\n ")]):t._e()],1)}),[],!1,null,null,null).exports),c=(n(309),n(20),n(149),n(143),n(298),n(25),n(151),n(283),n(299),n(145),n(57),n(300),n(301),n(313),n(58),n(148),n(153)),l=n.n(c),h=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,i=l()(e,"title","");return l()(e,"frontmatter.tags")&&(i+=" ".concat(e.frontmatter.tags.join(" "))),n&&(i+=" ".concat(n)),f(t,i)},f=function(t,e){var n=function(t){return t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")},i=new RegExp("[^\0-]"),r=t.split(/\s+/g).map((function(t){return t.trim()})).filter((function(t){return!!t}));if(i.test(t))return r.some((function(t){return e.toLowerCase().indexOf(t)>-1}));var a=t.endsWith(" ");return new RegExp(r.map((function(t,e){return r.length!==e+1||a?"(?=.*\\b".concat(n(t),"\\b)"):"(?=.*\\b".concat(n(t),")")})).join("")+".+","gi").test(e)},p={name:"SearchBox",data:function(){return{query:"",focused:!1,focusIndex:0,placeholder:void 0}},computed:{showSuggestions:function(){return this.focused&&this.suggestions&&this.suggestions.length},suggestions:function(){var t=this.query.trim().toLowerCase();if(t){for(var e=this.$site.pages,n=this.$site.themeConfig.searchMaxSuggestions||5,i=this.$localePath,r=[],a=0;a=n);a++){var s=e[a];if(this.getPageLocalePath(s)===i&&this.isSearchable(s))if(h(t,s))r.push(s);else if(s.headers)for(var o=0;o=n);o++){var u=s.headers[o];u.title&&h(t,s,u.title)&&r.push(Object.assign({},s,{path:s.path+"#"+u.slug,header:u}))}}return r}},alignRight:function(){return(this.$site.themeConfig.nav||[]).length+(this.$site.repo?1:0)<=2}},mounted:function(){this.placeholder=this.$site.themeConfig.searchPlaceholder||"",document.addEventListener("keydown",this.onHotkey)},beforeDestroy:function(){document.removeEventListener("keydown",this.onHotkey)},methods:{getPageLocalePath:function(t){for(var e in this.$site.locales||{})if("/"!==e&&0===t.path.indexOf(e))return e;return"/"},isSearchable:function(t){var e=null;return null===e||(e=Array.isArray(e)?e:new Array(e)).filter((function(e){return t.path.match(e)})).length>0},onHotkey:function(t){t.srcElement===document.body&&["s","/"].includes(t.key)&&(this.$refs.input.focus(),t.preventDefault())},onUp:function(){this.showSuggestions&&(this.focusIndex>0?this.focusIndex--:this.focusIndex=this.suggestions.length-1)},onDown:function(){this.showSuggestions&&(this.focusIndex "+t._s(e.header.title))]):t._e()])])})),0):t._e()])}),[],!1,null,null,null).exports),g=(n(315),Object(a.a)({},(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"sidebar-button",on:{click:function(e){return t.$emit("toggle-sidebar")}}},[n("svg",{staticClass:"icon",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img",viewBox:"0 0 448 512"}},[n("path",{attrs:{fill:"currentColor",d:"M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"}})])])}),[],!1,null,null,null).exports),v=(n(152),n(35)),m=n(304),b=n(154),k=n.n(b),_={name:"DropdownLink",components:{NavLink:s,DropdownTransition:m.a},props:{item:{required:!0}},data:function(){return{open:!1}},computed:{dropdownAriaLabel:function(){return this.item.ariaLabel||this.item.text}},watch:{$route:function(){this.open=!1}},methods:{setOpen:function(t){this.open=t},isLastItemOfArray:function(t,e){return k()(e)===t}}},x=(n(317),{name:"NavLinks",components:{NavLink:s,DropdownLink:Object(a.a)(_,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[n("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[n("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),n("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),n("DropdownTransition",[n("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(e,i){return n("li",{key:e.link||i,staticClass:"dropdown-item"},["links"===e.type?n("h4",[t._v("\n "+t._s(e.text)+"\n ")]):t._e(),t._v(" "),"links"===e.type?n("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(e.items,(function(i){return n("li",{key:i.link,staticClass:"dropdown-subitem"},[n("NavLink",{attrs:{item:i},on:{focusout:function(n){t.isLastItemOfArray(i,e.items)&&t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0):n("NavLink",{attrs:{item:e},on:{focusout:function(n){t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null).exports},computed:{userNav:function(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav:function(){var t=this,e=this.$site.locales;if(e&&Object.keys(e).length>1){var n=this.$page.path,i=this.$router.options.routes,r=this.$site.themeConfig.locales||{},a={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(e).map((function(a){var s,o=e[a],u=r[a]&&r[a].label||o.lang;return o.lang===t.$lang?s=n:(s=n.replace(t.$localeConfig.path,a),i.some((function(t){return t.path===s}))||(s=a)),{text:u,link:s}}))};return[].concat(Object(v.a)(this.userNav),[a])}return this.userNav},userLinks:function(){return(this.nav||[]).map((function(t){return Object.assign(Object(i.j)(t),{items:(t.items||[]).map(i.j)})}))},repoLink:function(){var t=this.$site.themeConfig.repo;return t?/^https?:/.test(t)?t:"https://github.com/".concat(t):null},repoLabel:function(){if(this.repoLink){if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;for(var t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"],n=0;nMath.abs(n)&&Math.abs(e)>40&&(e>0&&this.touchStart.x<=80?this.toggleSidebar(!0):this.toggleSidebar(!1))}}}),B=Object(a.a)(W,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"theme-container",class:t.pageClasses,on:{touchstart:t.onTouchStart,touchend:t.onTouchEnd}},[t.shouldShowNavbar?n("Navbar",{on:{"toggle-sidebar":t.toggleSidebar}}):t._e(),t._v(" "),n("div",{staticClass:"sidebar-mask",on:{click:function(e){return t.toggleSidebar(!1)}}}),t._v(" "),n("Sidebar",{attrs:{items:t.sidebarItems},on:{"toggle-sidebar":t.toggleSidebar},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("sidebar-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("sidebar-bottom")]},proxy:!0}],null,!0)}),t._v(" "),t.$page.frontmatter.home?n("Home"):n("Page",{attrs:{"sidebar-items":t.sidebarItems},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("page-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("page-bottom")]},proxy:!0}],null,!0)})],1)}),[],!1,null,null,null);e.default=B.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/3.972ca2ed.js b/okhttps-doc/docs/.vuepress/dist/assets/js/3.972ca2ed.js new file mode 100644 index 00000000..1f8e660f --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/3.972ca2ed.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{297:function(t,e,n){},328:function(t,e,n){"use strict";var i=n(297);n.n(i).a},334:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(328),n(19)),a=Object(r.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=a.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/4.fe3bf0b0.js b/okhttps-doc/docs/.vuepress/dist/assets/js/4.fe3bf0b0.js new file mode 100644 index 00000000..6c638411 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/4.fe3bf0b0.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{331:function(t,e,s){"use strict";s.r(e);var n=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],o={methods:{getMsg:function(){return n[Math.floor(Math.random()*n.length)]}}},i=s(19),h=Object(i.a)(o,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"theme-container"},[e("div",{staticClass:"theme-default-content"},[e("h1",[this._v("404")]),this._v(" "),e("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),e("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])}),[],!1,null,null,null);e.default=h.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/5.93d38f11.js b/okhttps-doc/docs/.vuepress/dist/assets/js/5.93d38f11.js new file mode 100644 index 00000000..8b93dda2 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/5.93d38f11.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{330:function(e,t,a){"use strict";a.r(t);a(143),a(92),a(81);var n={props:{name:{type:String,default:"default"},isolated:{type:Boolean,default:!1},languages:Object},data:function(){return{selectedLanguage:Object.keys(this.languages)[0]}},computed:{root:function(){for(var e,t=this;e=t.$parent;)t=e;return t},localStorageKey:function(){return"vuepress-plugin-code-switcher@".concat(this.name)}},methods:{switchLanguage:function(e){if(this.isolated)return this.selectedLanguage=e;"undefined"!=typeof localStorage&&localStorage.setItem(this.localStorageKey,e),this.root.$emit("change",{name:this.name,value:e})}},created:function(){var e=this;if(!this.isolated){if("undefined"!=typeof localStorage){var t=localStorage.getItem(this.localStorageKey);t&&-1!==Object.keys(this.languages).indexOf(t)&&(this.selectedLanguage=t)}this.root.$on("change",(function(t){var a=t.name,n=t.value;a===e.name&&(e.selectedLanguage=n)}))}}},s=a(19),i=Object(s.a)(n,(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"code-switcher"},[a("div",{staticClass:"tab-header"},[a("ul",e._l(e.languages,(function(t,n){return a("li",{key:n,class:{active:e.selectedLanguage===n},on:{click:function(t){return e.switchLanguage(n)}}},[e._v(" "+e._s(t)+"\n ")])})),0)]),e._v(" "),e._l(e.languages,(function(t,n){return a("div",{directives:[{name:"show",rawName:"v-show",value:n===e.selectedLanguage,expression:"shorthand === selectedLanguage"}],key:n,staticClass:"tab-content"},[e._t(n)],2)}))],2)}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/6.fd474f39.js b/okhttps-doc/docs/.vuepress/dist/assets/js/6.fd474f39.js new file mode 100644 index 00000000..66342655 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/6.fd474f39.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{337:function(s,t,n){"use strict";n.r(t);var a=n(19),e=Object(a.a)({},(function(){var s=this,t=s.$createElement,n=s._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[n("div",{staticClass:"language-java line-numbers-mode"},[n("pre",{pre:!0,attrs:{class:"language-java"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 构建 HTTP")]),s._v("\n"),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),n("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("baseUrl")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[s._v('"https://api.demo.com"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �步请求")]),s._v("\n"),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("List")]),n("span",{pre:!0,attrs:{class:"token generics"}},[n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" users "),n("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// http://api.demo.com/users")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// GET请求")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 获��应报文体")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("toList")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到目标数�")]),s._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 异步请求")]),s._v("\nhttp"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/jack"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// http://api.demo.com/users/jack")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到目标数�")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),s._v(" jack "),n("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("toBean")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// GET请求")]),s._v("\n")])]),s._v(" "),n("div",{staticClass:"line-numbers-wrapper"},[n("span",{staticClass:"line-number"},[s._v("1")]),n("br"),n("span",{staticClass:"line-number"},[s._v("2")]),n("br"),n("span",{staticClass:"line-number"},[s._v("3")]),n("br"),n("span",{staticClass:"line-number"},[s._v("4")]),n("br"),n("span",{staticClass:"line-number"},[s._v("5")]),n("br"),n("span",{staticClass:"line-number"},[s._v("6")]),n("br"),n("span",{staticClass:"line-number"},[s._v("7")]),n("br"),n("span",{staticClass:"line-number"},[s._v("8")]),n("br"),n("span",{staticClass:"line-number"},[s._v("9")]),n("br"),n("span",{staticClass:"line-number"},[s._v("10")]),n("br"),n("span",{staticClass:"line-number"},[s._v("11")]),n("br"),n("span",{staticClass:"line-number"},[s._v("12")]),n("br"),n("span",{staticClass:"line-number"},[s._v("13")]),n("br"),n("span",{staticClass:"line-number"},[s._v("14")]),n("br"),n("span",{staticClass:"line-number"},[s._v("15")]),n("br"),n("span",{staticClass:"line-number"},[s._v("16")]),n("br"),n("span",{staticClass:"line-number"},[s._v("17")]),n("br"),n("span",{staticClass:"line-number"},[s._v("18")]),n("br")])]),s._v(" "),n("p",[n("strong",[n("center",[s._v("竟然�到 "),n("font",{attrs:{size:"5"}},[s._v("15")]),s._v(" 秒,你已学会 "),n("font",{attrs:{size:"6"}},[s._v("90")]),s._v("% 的精髓�")],1)],1),s._v(" "),n("center",[n("RouterLink",{attrs:{to:"/guide/"}},[n("strong",[s._v("了解更多")])])],1)],1)])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/7.51e5642d.js b/okhttps-doc/docs/.vuepress/dist/assets/js/7.51e5642d.js new file mode 100644 index 00000000..c76c8a33 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/7.51e5642d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{338:function(s,t,a){"use strict";a.r(t);var n=a(19),e=Object(n.a)({},(function(){var s=this,t=s.$createElement,a=s._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[a("h1",{attrs:{id:"起步"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#起步"}},[s._v("#")]),s._v(" 起步")]),s._v(" "),a("p",[s._v("OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。")]),s._v(" "),a("ul",[a("li",[s._v("链�调用,一点到底")]),s._v(" "),a("li",[s._v("BaseURL�URL��符�JSON自动�装与解�")]),s._v(" "),a("li",[s._v("�步拦截器�异步预处�器�回调执行器�全局监��回调阻断")]),s._v(" "),a("li",[s._v("文件上传下载(过程控制�进度监�)")]),s._v(" "),a("li",[s._v("�方法回调,充分利用 Lambda 表达�")]),s._v(" "),a("li",[s._v("TCP连接池�Http2")])]),s._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[s._v("TIP")]),s._v(" "),a("ul",[a("li",[s._v("OkHttps �常轻�(59Kb),仅是 Retrofit(124Kb)的一�,并且更加的开箱�用,API 也更加自然和语义化。")]),s._v(" "),a("li",[s._v("OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit ��")]),s._v(" "),a("li",[s._v("OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。")])])]),s._v(" "),a("h2",{attrs:{id:"安装"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#安装"}},[s._v("#")]),s._v(" 安装")]),s._v(" "),a("h3",{attrs:{id:"maven"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#maven"}},[s._v("#")]),s._v(" Maven")]),s._v(" "),a("div",{staticClass:"language-xml line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-xml"}},[a("code",[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),s._v("dependency")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),s._v("groupId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v("com.ejlchina"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("")])]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),s._v("artifactId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v("okhttps"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("")])]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),s._v("version")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v("1.0.5"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("")])]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("")])]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br")])]),a("h3",{attrs:{id:"gradle"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#gradle"}},[s._v("#")]),s._v(" Gradle")]),s._v(" "),a("div",{staticClass:"language-groovy line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-groovy"}},[a("code",[s._v("implementation "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'com.ejlchina:okhttps:1.0.5'")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br")])]),a("p",[s._v("安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��:")]),s._v(" "),a("div",{staticClass:"language-groovy line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-groovy"}},[a("code",[s._v("android "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置..")]),s._v("\n compileOptions "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n sourceCompatibility "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("1.8")]),s._v("\n targetCompatibility "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("1.8")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br")])]),a("h2",{attrs:{id:"使用"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用"}},[s._v("#")]),s._v(" 使用")]),s._v(" "),a("h3",{attrs:{id:"构建实例"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#构建实例"}},[s._v("#")]),s._v(" 构建实例")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br")])]),a("p",[s._v("以上代�构建了一个最简�的"),a("code",[s._v("HTTP")]),s._v("实例,它拥有以下方法:")]),s._v(" "),a("ul",[a("li",[a("code",[s._v("sync(String url)")]),s._v(" 开始一个�步请求")]),s._v(" "),a("li",[a("code",[s._v("async(String url)")]),s._v(" 开始一个异步请求")]),s._v(" "),a("li",[a("code",[s._v("cancel(String tag)")]),s._v(" 按标签�消请求")]),s._v(" "),a("li",[a("code",[s._v("cancelAll()")]),s._v(" �消所有HTTP任务,包括�步和异步")]),s._v(" "),a("li",[a("code",[s._v("request(Request request)")]),s._v(" OkHttp 原生请求")]),s._v(" "),a("li",[a("code",[s._v("webSocket(Request request, WebSocketListener listener)")]),s._v(" WebSocket通讯")])]),s._v(" "),a("p",[s._v("为了使用方便,在构建的时候,我们更愿�指定一个"),a("code",[s._v("BaseUrl")]),s._v("(详� "),a("RouterLink",{attrs:{to:"/guide/configuration.html#设置-baseurl"}},[s._v("设置 BaseUrl")]),s._v("):")],1),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("baseUrl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"http://api.demo.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br")])]),a("p",[s._v("为了简化文档,下文中出现的"),a("code",[s._v("http")]),s._v("�是在构建时设置了"),a("code",[s._v("BaseUrl")]),s._v("的"),a("code",[s._v("HTTP")]),s._v("实例。")]),s._v(" "),a("h3",{attrs:{id:"�步请求"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�步请求"}},[s._v("#")]),s._v(" �步请求")]),s._v(" "),a("p",[s._v("使用方法"),a("code",[s._v("sync(String url)")]),s._v("开始一个�步请求:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" users "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// http://api.demo.com/users")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// GET请求")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 获��应报文体")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到目标数�")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br")])]),a("p",[s._v("方法"),a("code",[s._v("sync")]),s._v("返回一个�步"),a("code",[s._v("HttpTask")]),s._v(",�链�使用。")]),s._v(" "),a("h3",{attrs:{id:"异步请求"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#异步请求"}},[s._v("#")]),s._v(" 异步请求")]),s._v(" "),a("p",[s._v("使用方法"),a("code",[s._v("async(String url)")]),s._v("开始一个异步请求:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// http://api.demo.com/users/1")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到目标数�")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),s._v(" user "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toBean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// GET请求")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br")])]),a("p",[s._v("方法"),a("code",[s._v("async")]),s._v("返回一个异步"),a("code",[s._v("HttpTask")]),s._v(",�链�使用。")]),s._v(" "),a("p",[a("strong",[s._v("至此,你已轻�学会了 OkHttps 95% 的常规用法�但别急,��还有更精彩的。")])])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/8.d296d289.js b/okhttps-doc/docs/.vuepress/dist/assets/js/8.d296d289.js new file mode 100644 index 00000000..791bf3d0 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/8.d296d289.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{336:function(s,t,a){"use strict";a.r(t);var n=a(19),e=Object(n.a)({},(function(){var s=this,t=s.$createElement,a=s._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[a("h1",{attrs:{id:"安�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#安�"}},[s._v("#")]),s._v(" 安�")]),s._v(" "),a("h2",{attrs:{id:"回调线程切�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#回调线程切�"}},[s._v("#")]),s._v(" 回调线程切�")]),s._v(" "),a("p",[s._v("在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。")]),s._v(" "),a("p",[s._v("在 "),a("strong",[s._v("默认")]),s._v(" 情况下,"),a("strong",[s._v("所有回调")]),s._v(" 函数都会 "),a("strong",[s._v("在 IO 线程")]),s._v(" 执行。为什么会设计如此呢?这是因为 OkHttps �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。")]),s._v(" "),a("h3",{attrs:{id:"�置"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�置"}},[s._v("#")]),s._v(" �置")]),s._v(" "),a("p",[s._v("但是在 Android 里使用 OkHttps 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("callbackExecutor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Runnable")]),s._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 实际编�中�以� Handler �出�,�需��次执行回调都�新创建")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("new")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Handler")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Looper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getMainLooper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br")])]),a("h3",{attrs:{id:"用例"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#用例"}},[s._v("#")]),s._v(" 用例")]),s._v(" "),a("p",[s._v("上述代�便实现了让 "),a("strong",[s._v("所有")]),s._v(" 的 "),a("strong",[s._v("回调函数")]),s._v(" 都在 "),a("strong",[s._v("主线程(UI线程)")]),s._v(" 执行的目的,如:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"Jack"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Process")]),s._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Exception")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnComplete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("State")]),s._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br")])]),a("p",[s._v("但是,如果�时还想让�些回调放在IO线程,实现 "),a("strong",[s._v("自由切�")]),s._v(",怎么办呢?OkHttps 给出了�常�活的方法,如下:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"Jack"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Process")]),s._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nextOnIO")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 指定下一个回调在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Exception")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行(没有指明 nextOnIO 则在回调执行器里执行)")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nextOnIO")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 指定下一个回调在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnComplete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("State")]),s._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br"),a("span",{staticClass:"line-number"},[s._v("16")]),a("br"),a("span",{staticClass:"line-number"},[s._v("17")]),a("br")])]),a("p",[s._v("无论是哪一个回调,都�以使用"),a("code",[s._v("nextOnIO()")]),s._v("方法自由切�。�样,对于文件下载也是一样:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Process")]),s._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nextOnIO")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 指定下一个回调在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnSuccess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("File")]),s._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnFailure")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Failure")]),s._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br")])]),a("h2",{attrs:{id:"生命周期绑定"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#生命周期绑定"}},[s._v("#")]),s._v(" 生命周期绑定")]),s._v(" "),a("p",[s._v("由于 OkHttps 并��赖于 Android,所以它并没有�供关于生命周期绑定的直接实现,但它的一些扩展机制让我们很容易就�以实现这个需求。在开始之�,我们首先��解何为生命周期绑定:")]),s._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[s._v("HTTP 请求的生命周期绑定")]),s._v(" "),a("p",[s._v("所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错�")])]),s._v(" "),a("p",[s._v("现在我们需�对"),a("code",[s._v("HTTP")]),s._v("实例进行�置,�置�的"),a("code",[s._v("HTTP")]),s._v("实例具有生命周期绑定的功能,在"),a("code",[s._v("Activity")]),s._v("或"),a("code",[s._v("Fragment")]),s._v("里,它的使用效果如下:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 Activity 或 Fragment 内�起请求")]),s._v("\nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"http://www.baidu.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("bind")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getLifecycle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 绑定生命周期")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("i")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"FirstFragment"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"收到请求:"')]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("+")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br")])]),a("p",[s._v("上述代�中的"),a("code",[s._v("getLifecycle()")]),s._v("是"),a("code",[s._v("Activity")]),s._v("或"),a("code",[s._v("Fragment")]),s._v("自带的方法,而"),a("code",[s._v("bind()")]),s._v("是"),a("code",[s._v("HttpTask")]),s._v("的现有方法。在�置好"),a("code",[s._v("HTTP")]),s._v("实例�,上述代��起的请求便�以感知"),a("code",[s._v("Activity")]),s._v("或"),a("code",[s._v("Fragment")]),s._v("的生命周期。")]),s._v(" "),a("p",[s._v("那"),a("code",[s._v("HTTP")]),s._v("实例到底该如何�置呢?")]),s._v(" "),a("h3",{attrs:{id:"第一步:�置预处�器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第一步:�置预处�器"}},[s._v("#")]),s._v(" 第一步:�置预处�器")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置项")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("addPreprocessor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Preprocessor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("PreChain")]),s._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getTask")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Object")]),s._v(" bound "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 判断 task 是�绑定了 Lifecycle 对象")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("bound "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �新绑定一个 生命周期监视器(LCObserver)对象,它的定义�下一步")]),s._v("\n task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("bind")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("new")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" bound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置项")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br")])]),a("h3",{attrs:{id:"第二步:定义生命周期监视器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第二步:定义生命周期监视器"}},[s._v("#")]),s._v(" 第二步:定义生命周期监视器")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("public")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("implements")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LifecycleObserver")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),s._v(" lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),s._v(" lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("task "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("lifecycle "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("addObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[s._v("@OnLifecycleEvent")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("ON_STOP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("public")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("void")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("onStop")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 ON_STOP 事件中,�消对应的 HTTP 任务")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("public")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("void")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("unbind")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在请求完�之�移除监视器")]),s._v("\n lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("removeObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br"),a("span",{staticClass:"line-number"},[s._v("16")]),a("br"),a("span",{staticClass:"line-number"},[s._v("17")]),a("br"),a("span",{staticClass:"line-number"},[s._v("18")]),a("br"),a("span",{staticClass:"line-number"},[s._v("19")]),a("br"),a("span",{staticClass:"line-number"},[s._v("20")]),a("br"),a("span",{staticClass:"line-number"},[s._v("21")]),a("br"),a("span",{staticClass:"line-number"},[s._v("22")]),a("br")])]),a("h3",{attrs:{id:"第三步:�置全局回调监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第三步:�置全局回调监�"}},[s._v("#")]),s._v(" 第三步:�置全局回调监�")]),s._v(" "),a("p",[s._v("以上两步其实已�实现了生命周期绑定的功能,但是在请求完�之�,我们需�在"),a("code",[s._v("lifecycle")]),s._v("中移除"),a("code",[s._v("LCObserver")]),s._v("对象:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置项")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("completeListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("State")]),s._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Object")]),s._v(" bound "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 判断 task 是�绑定了生命周期监视器(LCObserver)对象")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("bound "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 解绑监视器")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" bound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("unbind")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("return")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置项")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br")])]),a("p",[a("strong",[s._v("以上三步便在Android中实现了生命周期与HTTP请求绑定的功能")])]),s._v(" "),a("p",[s._v("�常简�,懒得敲代�的�学还�以 "),a("a",{attrs:{href:"https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java",target:"_blank",rel:"noopener noreferrer"}},[s._v("点这里 OkHttps.java"),a("OutboundLink")],1),s._v(" 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。")]),s._v(" "),a("p",[s._v("有需�的�学,�以直接下载下�使用,还�以基于它�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考"),a("a",{attrs:{href:"#65-%E4%B8%B2%E8%A1%8C%E9%A2%84%E5%A4%84%E7%90%86%E5%99%A8token%E9%97%AE%E9%A2%98%E6%9C%80%E4%BD%B3%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88"}},[s._v("6.5 串行预处�器(TOKEN问题最佳解决方案)")]),s._v(",�比如扩展实现生命周期与下载事件绑定的功能,都�常简�。")])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/9.bff804f8.js b/okhttps-doc/docs/.vuepress/dist/assets/js/9.bff804f8.js new file mode 100644 index 00000000..2dae5b30 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/9.bff804f8.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{339:function(t,s,a){"use strict";a.r(s);var n=a(19),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"�置"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�置"}},[t._v("#")]),t._v(" �置")]),t._v(" "),a("h2",{attrs:{id:"设置-baseurl"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#设置-baseurl"}},[t._v("#")]),t._v(" 设置 BaseUrl")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("baseUrl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://api.demo.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置 BaseUrl")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br")])]),a("p",[t._v("该�置全局生效,在�置了"),a("code",[t._v("BaseUrl")]),t._v("之�,具体的请求便�以�略"),a("code",[t._v("BaseUrl")]),t._v("部分,使得代�更加简�,例如:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// http://api.demo.com/users")]),t._v("\n\nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/auth/signin"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// http://api.demo.com/auth/signin")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"username"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Jackson"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"xxxxxx"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// POST请求")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br")])]),a("p",[t._v("在�置了"),a("code",[t._v("BaseUrl")]),t._v("之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://www.baidu.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br")])]),a("h2",{attrs:{id:"回调执行器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#回调执行器"}},[t._v("#")]),t._v(" 回调执行器")]),t._v(" "),a("p",[t._v("OkHttps 默认所有回调都在 "),a("strong",[t._v("IO线程")]),t._v(" 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建"),a("code",[t._v("HTTP")]),t._v("时�置如下:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("callbackExecutor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Runnable")]),t._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("runOnUiThread")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在UI线程执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br")])]),a("p",[t._v("该�置默认 "),a("strong",[t._v("影�所有回调")]),t._v("。")]),t._v(" "),a("h2",{attrs:{id:"�置-okhttpclient"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�置-okhttpclient"}},[t._v("#")]),t._v(" �置 OkHttpClient")]),t._v(" "),a("p",[t._v("与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("config")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),t._v(" builder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �置连接池 最�10个连接(��置默认为 5)")]),t._v("\n builder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("connectionPool")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConnectionPool")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TimeUnit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("MINUTES"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �置连接超时时间(默认10秒)")]),t._v("\n builder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("connectTimeout")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TimeUnit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SECONDS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �置拦截器")]),t._v("\n builder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addInterceptor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Chain")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Request")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("request")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 必须�步返回,拦截器内无法执行异步�作")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 其它�置: CookieJar�SSL�缓存�代��事件监�...")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br")])]),a("h2",{attrs:{id:"并行预处�器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#并行预处�器"}},[t._v("#")]),t._v(" 并行预处�器")]),t._v(" "),a("p",[t._v("预处�器("),a("code",[t._v("Preprocessor")]),t._v(")�以让我们在请求�出之�对请求本身�一些改�,但与"),a("code",[t._v("OkHttp")]),t._v("的拦截器("),a("code",[t._v("Interceptor")]),t._v(")��:预处�器�以让我们 "),a("strong",[t._v("异步")]),t._v(" 处�这些问题。")]),t._v(" "),a("p",[t._v("例如,当我们想为请求任务自动添加"),a("code",[t._v("Token")]),t._v("头信�,而"),a("code",[t._v("Token")]),t._v("�能通过异步方法"),a("code",[t._v("requestToken")]),t._v("获�时,这时使用"),a("code",[t._v("Interceptor")]),t._v("就很难处�了,但�以使用预处�器轻�解决:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addPreprocessor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PreChain")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTask")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获得当�的HTTP任务")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isTagged")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Auth"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 根�标签判断该任务是�需�Token")]),t._v("\n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("requestToken")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步获� Token")]),t._v("\n task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addHeader")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Token"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 为任务添加头信�")]),t._v("\n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 继续当�的任务")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br")])]),a("p",[t._v("和"),a("code",[t._v("Interceptor")]),t._v("一样,"),a("code",[t._v("Preprocessor")]),t._v("也�以添加多个。他们之间的区别如下:")]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("拦截器与预处�器的区别")]),t._v(" "),a("ul",[a("li",[t._v("拦截器�能处��步�作,预处�器支�处�异步�作")]),t._v(" "),a("li",[t._v("拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节)")]),t._v(" "),a("li",[t._v("拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调监�(详�6.6章节)")])])]),t._v(" "),a("h2",{attrs:{id:"串行预处�器(token问题最佳解决方案)"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#串行预处�器(token问题最佳解决方案)"}},[t._v("#")]),t._v(" 串行预处�器(TOKEN问题最佳解决方案)")]),t._v(" "),a("p",[t._v("普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当"),a("code",[t._v("Token")]),t._v("过期时我们需�去刷新获�新"),a("code",[t._v("Token")]),t._v(",而刷新"),a("code",[t._v("Token")]),t._v("这个�作�能有一个任务去执行,因为如果"),a("code",[t._v("n")]),t._v("个任务�时执行的�,那么必有"),a("code",[t._v("n-1")]),t._v("个任务刚刷新得到的"),a("code",[t._v("Token")]),t._v("�能就立马失效了,而这是我们所�希望的。")]),t._v(" "),a("p",[t._v("为了解决这个问题,OkHttps �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addSerialPreprocessor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PreChain")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTask")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isTagged")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Auth"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 检查过期,若需�则刷新Token")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("requestTokenAndRefreshIfExpired")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addHeader")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Token"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" \n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 调用此方法�,�会有其它任务进入该处�器")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br")])]),a("p",[t._v("串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程�")]),t._v(" "),a("h2",{attrs:{id:"全局回调监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#全局回调监�"}},[t._v("#")]),t._v(" 全局回调监�")]),t._v(" "),a("p",[t._v("全局回调是实际开�中�常需�的功能,比如对�务器�应的状��进行统一处�等,�时 OkHttps 的全局回调还具有 "),a("strong",[t._v("回调阻断")]),t._v(" 的功能:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("responseListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所有请求�应�都会走这里")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("completeListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),t._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所有请求执行完都会走这里")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("exceptionListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IOException")]),t._v(" error"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所有请求�生异常都会走这里")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br"),a("span",{staticClass:"line-number"},[t._v("17")]),a("br")])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("全局回调监�与拦截器的异�:")]),t._v(" "),a("ul",[a("li",[t._v("拦截器�以添加多个,全局回调监�分三�,��最多添加一个")]),t._v(" "),a("li",[t._v("拦截器处的�时机在请求�和�应�,全局回调监��在�应�,并且晚于拦截器")]),t._v(" "),a("li",[t._v("全局回调监��以 "),a("strong",[t._v("阻断")]),t._v("(return false)�个请求的具体回调,而拦截器�能")])])]),t._v(" "),a("h2",{attrs:{id:"全局下载监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#全局下载监�"}},[t._v("#")]),t._v(" 全局下载监�")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("downloadListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Download")]),t._v(" download"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所有下载在开始之�都会先走这里")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ctrl")]),t._v(" ctrl "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" download"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getCtrl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载控制器")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/app.1e2fa6f5.js b/okhttps-doc/docs/.vuepress/dist/assets/js/app.1e2fa6f5.js new file mode 100644 index 00000000..4a930851 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/assets/js/app.1e2fa6f5.js @@ -0,0 +1,13 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,c=e[0],u=e[1],s=e[2],l=0,p=[];l0?o(r(t),9007199254740991):0}},function(t,e,n){var r=n(6),o=n(1),i=n(4),a=Object.defineProperty,c={},u=function(t){throw t};t.exports=function(t,e){if(i(c,t))return c[t];e||(e={});var n=[][t],s=!!i(e,"ACCESSORS")&&e.ACCESSORS,f=i(e,0)?e[0]:u,l=i(e,1)?e[1]:void 0;return c[t]=!!n&&!o((function(){if(s&&!r)return!0;var t={length:-1};s?a(t,1,{enumerable:!0,get:u}):t[1]=1,n.call(t,f,l)}))}},function(t,e,n){var r=n(13);t.exports=function(t){return Object(r(t))}},function(t,e,n){var r=n(67),o=n(21),i=n(160);r||o(Object.prototype,"toString",i,{unsafe:!0})},function(t,e,n){var r=n(193),o=n(196);t.exports=function(t,e){var n=o(t,e);return r(n)?n:void 0}},function(t,e,n){"use strict";function r(t,e,n,r,o,i,a,c){var u,s="function"==typeof t?t.options:t;if(e&&(s.render=e,s.staticRenderFns=n,s._compiled=!0),r&&(s.functional=!0),i&&(s._scopeId="data-v-"+i),a?(u=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},s._ssrRegister=u):o&&(u=c?function(){o.call(this,this.$root.$options.shadowRoot)}:o),u)if(s.functional){s._injectStyles=u;var f=s.render;s.render=function(t,e){return u.call(e),f(t,e)}}else{var l=s.beforeCreate;s.beforeCreate=l?[].concat(l,u):[u]}return{exports:t,options:s}}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";var r=n(0),o=n(27).filter,i=n(45),a=n(15),c=i("filter"),u=a("filter");r({target:"Array",proto:!0,forced:!c||!u},{filter:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}})},function(t,e,n){var r=n(3),o=n(9),i=n(4),a=n(59),c=n(96),u=n(37),s=u.get,f=u.enforce,l=String(String).split("String");(t.exports=function(t,e,n,c){var u=!!c&&!!c.unsafe,s=!!c&&!!c.enumerable,p=!!c&&!!c.noTargetGet;"function"==typeof n&&("string"!=typeof e||i(n,"name")||o(n,"name",e),f(n).source=l.join("string"==typeof e?e:"")),t!==r?(u?!p&&t[e]&&(s=!0):delete t[e],s?t[e]=n:o(t,e,n)):s?t[e]=n:a(e,n)})(Function.prototype,"toString",(function(){return"function"==typeof this&&s(this).source||c(this)}))},function(t,e,n){var r=n(6),o=n(93),i=n(29),a=n(11),c=n(30),u=n(4),s=n(94),f=Object.getOwnPropertyDescriptor;e.f=r?f:function(t,e){if(t=a(t),e=c(e,!0),s)try{return f(t,e)}catch(t){}if(u(t,e))return i(!o.f.call(t,e),t[e])}},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e,n){"use strict";var r=n(0),o=n(46);r({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},function(t,e){t.exports=!1},function(t,e,n){var r=n(158),o=n(41),i=n(16),a=n(14),c=n(104),u=[].push,s=function(t){var e=1==t,n=2==t,s=3==t,f=4==t,l=6==t,p=5==t||l;return function(d,h,v,y){for(var m,g,b=i(d),_=o(b),x=r(h,v,3),w=a(_.length),O=0,S=y||c,j=e?S(d,w):n?S(d,0):void 0;w>O;O++)if((p||O in _)&&(g=x(m=_[O],O,b),t))if(e)j[O]=g;else if(g)switch(t){case 3:return!0;case 5:return m;case 6:return O;case 2:u.call(j,m)}else if(f)return!1;return l?-1:s||f?f:j}};t.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6)}},function(t,e,n){var r=n(34),o=n(178),i=n(179),a=r?r.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":a&&a in Object(t)?o(t):i(t)}},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var r=n(5);t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},function(t,e){t.exports={}},function(t,e,n){var r,o=n(8),i=n(163),a=n(62),c=n(31),u=n(164),s=n(95),f=n(42),l=f("IE_PROTO"),p=function(){},d=function(t){return" + + diff --git a/okhttps-doc/docs/.vuepress/dist/guide/configuration.html b/okhttps-doc/docs/.vuepress/dist/guide/configuration.html new file mode 100644 index 00000000..0564067a --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/guide/configuration.html @@ -0,0 +1,137 @@ + + + + + + �置 | OkHttps + + + + + + + + + + + + + + + + + + +

# �置

# 设置 BaseUrl

HTTP http = HTTP.builder()
+        .baseUrl("http://api.demo.com")    // 设置 BaseUrl
+        .build();
+
1
2
3

该�置全局生效,在�置了BaseUrl之�,具体的请求便�以�略BaseUrl部分,使得代�更加简�,例如:

http.sync("/users").get()                  // http://api.demo.com/users
+
+http.sync("/auth/signin")                  // http://api.demo.com/auth/signin
+        .addBodyParam("username", "Jackson")
+        .addBodyParam("password", "xxxxxx")
+        .post();                           // POST请求
+
1
2
3
4
5
6

在�置了BaseUrl之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�:

http.sync("https://www.baidu.com").get();
+
1

# 回调执行器

OkHttps 默认所有回调都在 IO线程 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建HTTP时�置如下:

HTTP http = HTTP.builder()
+        .callbackExecutor((Runnable run) -> {
+            runOnUiThread(run);            // 在UI线程执行
+        })
+        .build();
+
1
2
3
4
5

该�置默认 影�所有回调。

# �置 OkHttpClient

与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下:

HTTP http = HTTP.builder()
+    .config((Builder builder) -> {
+        // �置连接池 最�10个连接(��置默认为 5)
+        builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES));
+        // �置连接超时时间(默认10秒)
+        builder.connectTimeout(20, TimeUnit.SECONDS);
+        // �置拦截器
+        builder.addInterceptor((Chain chain) -> {
+            Request request = chain.request();
+            // 必须�步返回,拦截器内无法执行异步�作
+            return chain.proceed(request);
+        });
+        // 其它�置: CookieJar�SSL�缓存�代��事件监�...
+    })
+    .build();
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 并行预处�器

预处�器(Preprocessor)�以让我们在请求�出之�对请求本身�一些改�,但与OkHttp的拦截器(Interceptor)��:预处�器�以让我们 异步 处�这些问题。

例如,当我们想为请求任务自动添加Token头信�,而Token�能通过异步方法requestToken获�时,这时使用Interceptor就很难处�了,但�以使用预处�器轻�解决:

HTTP http = HTTP.builder()
+        .addPreprocessor((PreChain chain) -> {
+            HttpTask<?> task = chain.getTask();// 获得当�的HTTP任务
+            if (!task.isTagged("Auth")) {      // 根�标签判断该任务是�需�Token
+                chain.proceed();
+                return;
+            }
+            requestToken((String token) -> {   // 异步获� Token
+                task.addHeader("Token", token);// 为任务添加头信�
+                chain.proceed();               // 继续当�的任务
+            });
+        })
+        .build();
+
1
2
3
4
5
6
7
8
9
10
11
12
13

和Interceptor一样,Preprocessor也�以添加多个。他们之间的区别如下:

拦截器与预处�器的区别

  • 拦截器å�ªèƒ½å¤„ç�†å�Œæ­¥æ“�作,预处ç�†å™¨æ”¯æŒ�处ç�†å¼‚æ­¥æ“�作
  • 拦截器都是并行处ç�†è¯·æ±‚,预处ç�†å™¨æ”¯æŒ�串行处ç�†ï¼ˆè¯¦è§�6.5章节)
  • 拦截器处ç�†æ—¶æœºåœ¨è¯·æ±‚å‰�å’Œå“�应å�Žï¼Œé¢„处ç�†å™¨å�ªåœ¨è¯·æ±‚å‰�,并且先于拦截器执行。关于å“�应å�Žï¼ŒOkHttps还æ��供了全局回调监å�¬ï¼ˆè¯¦è§�6.6章节)

# 串行预处�器(TOKEN问题最佳解决方案)

普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当Token过期时我们需�去刷新获�新Token,而刷新Token这个�作�能有一个任务去执行,因为如果n个任务�时执行的�,那么必有n-1个任务刚刷新得到的Token�能就立马失效了,而这是我们所�希望的。

为了解决这个问题,OkHttps �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器:

HTTP http = HTTP.builder()
+        .addSerialPreprocessor((PreChain chain) -> {
+            HttpTask<?> task = chain.getTask();
+            if (!task.isTagged("Auth")) {
+                chain.proceed();
+                return;
+            }
+            // 检查过期,若需�则刷新Token
+            requestTokenAndRefreshIfExpired((String token) -> {
+                task.addHeader("Token", token);            
+                chain.proceed();               // 调用此方法�,�会有其它任务进入该处�器
+            });
+        })
+        .build();
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14

串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程�

# 全局回调监�

全局回调是实际开�中�常需�的功能,比如对�务器�应的状��进行统一处�等,�时 OkHttps 的全局回调还具有 回调阻断 的功能:

HTTP http = HTTP.builder()
+        .responseListener((HttpTask<?> task, HttpResult result) -> {
+            // 所有请求�应�都会走这里
+
+            return true; // 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行
+        })
+        .completeListener((HttpTask<?> task, State state) -> {
+            // 所有请求执行完都会走这里
+
+            return true; // 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行
+        })
+        .exceptionListener((HttpTask<?> task, IOException error) -> {
+            // 所有请求�生异常都会走这里
+
+            return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行
+        })
+        .build();
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

全局回调监�与拦截器的异�:

  • 拦截器å�¯ä»¥æ·»åŠ å¤šä¸ªï¼Œå…¨å±€å›žè°ƒç›‘å�¬åˆ†ä¸‰ç§�,æ¯�ç§�最多添加一个
  • 拦截器处的ç�†æ—¶æœºåœ¨è¯·æ±‚å‰�å’Œå“�应å�Žï¼Œå…¨å±€å›žè°ƒç›‘å�¬å�ªåœ¨å“�应å�Žï¼Œå¹¶ä¸”晚于拦截器
  • 全局回调监å�¬å�¯ä»¥ 阻断(return false)æŸ�个请求的具体回调,而拦截器ä¸�能

# 全局下载监�

HTTP http = HTTP.builder()
+        .downloadListener((HttpTask<?> task, Download download) -> {
+            // 所有下载在开始之�都会先走这里
+            Ctrl ctrl = download.getCtrl();         // 下载控制器
+            
+        })
+        .build();
+
1
2
3
4
5
6
7
+ + + diff --git a/okhttps-doc/docs/.vuepress/dist/guide/features.html b/okhttps-doc/docs/.vuepress/dist/guide/features.html new file mode 100644 index 00000000..23771675 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/guide/features.html @@ -0,0 +1,150 @@ + + + + + + 特色 | OkHttps + + + + + + + + + + + + + + + + + + +

# 特色

# 使用 HttpUtils 类

类HttpUtils本是 �身 HttpUtils 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了HTTP接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。

类HttpUtils共定义了四个��方法:

  • of(HTTP http) é…�ç½®HttpUtilsæŒ�有的HTTP实例(ä¸�调用此方法å‰�默认使用一个没有没有ç»�过任何é…�置的HTTP懒实例)
  • sync(String url) 开始一个å�Œæ­¥è¯·æ±‚ (内部通过一个HTTPå�•例实现)
  • async(String url) 开始一个异步请求 (内部通过一个HTTPå�•例实现)
  • cancel(String tag) 按标签å�–消请求(内部通过一个HTTPå�•例实现)
  • cancelAll() å�–消所有HTTP任务,包括å�Œæ­¥å’Œå¼‚步(内部通过一个HTTPå�•例实现)
  • request(Request request) OkHttp 原生请求 (该请求ä¸�ç»�过 预处ç�†å™¨ï¼‰
  • webSocket(Request request, WebSocketListener listener) WebSocket通讯 +  也就是说,能使用http实例的地方,都å�¯ä»¥ä½¿ç”¨HttpUtils类,例如:
// 在�置HTTP实例之�,�能使用全路径方�
+List<Role> roles = HttpUtils.sync("http://api.demo.com/roles")
+        .get().getBody().toList(Role.class);
+
+// �置HTTP实例,全局生效
+HttpUtils.of(HTTP.builder()
+        .baseUrl("http://api.demo.com")
+        .build());
+
+// 内部使用新的HTTP实例
+List<User> users = HttpUtils.sync("/users")
+        .get().getBody().toList(User.class);
+
1
2
3
4
5
6
7
8
9
10
11
12

# 异常处�

使用 OkHttps 时,异常处��是必须的,但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:nothrow(),以满足��的异常处�需求。

# �步请求的异常

默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 try catch ��获,例如:

try {
+    HttpResult result = http.sync("/users/1").get();
+} catch (HttpException e) {
+    Throwable cause = e.getCause(); // 得到异常原因
+    if (cause instanceof ConnectException) {
+        // 当没网络时,会抛出连接异常
+    }
+    if (cause instanceof SocketTimeoutException) {
+        // 当接�长时间未�应,会抛出超时异常
+    }
+    if (cause instanceof UnknownHostException) {
+        // 当把域�或IP写错,会抛出 UnknownHost 异常
+    }
+    // ...
+}
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这�传统的异常处�方�,当然�以解决问题,但 OkHttps 有更佳的方案:

// 方法  nothrow() 让异常�直接抛出
+HttpResult result = http.sync("/users/1").nothrow().get();
+// 判断执行状�
+switch (result.getState()) {
+    case RESPONSED:     // 请求已正常�应
+        break;
+    case CANCELED:      // 请求已被�消
+        break;
+    case NETWORK_ERROR: // 网络错误,说明用户没网了
+        break;
+    case TIMEOUT:       // 请求超时
+        break;
+    case EXCEPTION:     // 其它异常
+        break;
+}
+// 还�以获得具体的异常信�
+IOException error = result.getError();
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 异步请求的异常

异步请求最常用的异常处�方�就是设置一个异常回调:

http.async("/users/1")
+        .setOnResponse((HttpResult result) -> {
+            // 当�生异常时就�会走这里
+        })
+        .setOnException((IOException e) -> {
+            // 这里处�请求异常
+        })
+        .get();
+
1
2
3
4
5
6
7
8

当然,还有一个全局异常监�(ExceptionListener):

HTTP http = HTTP.builder()
+        .exceptionListener((HttpTask<?> task, IOException error) -> {
+            // 所有请求�生异常都会走这里
+
+            return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行
+        })
+        .build();
+
1
2
3
4
5
6
7

如果�设置OnException回调,也没有ExceptionListener,�生异常时会在 IO 线程 中�上抛出,外层无法�获:

try {
+    http.async("/users/1")
+            .setOnResponse((HttpResult result) -> {
+                // 当�生异常时就�会走这里
+            })
+            .get();
+} catch (HttpException e) {
+    // 这�方�是�获�到异常的������
+}
+
1
2
3
4
5
6
7
8
9

�使没有OnException回调,�生异常时,�然会走OnComplete回调,如果设置了的�:

http.async("/users/1")
+        .setOnResponse((HttpResult result) -> {
+            // 当�生异常时就�会走这里
+        })
+        .setOnComplete((State state) -> {
+            // �生异常,会先执行这里,�以根� state 判断�生了什么
+            // 但执行完��然会在IO线程中�上抛出
+        })
+        .get();
+
1
2
3
4
5
6
7
8
9

如果就是想 �处�异常,也��上抛出,�生错误完全无视,�以�到�?�以�还是使用nothrow()方法:

http.async("/users/1")
+        .nothrow()  // 告诉 OkHttps �生异常时��外抛出
+        .setOnResponse((HttpResult result) -> {
+            // 当�生异常时就�会走这里
+        })
+        .get();
+
1
2
3
4
5
6

# �消请求

在 OkHttps 里�消请求共有 4 � 方��选:

  • 使用HttpCall#cancel()å�–消å�•个请求(适用于异步请求,详è§� 3.3 章节)
  • 使用HttpTask#cancel()å�–消å�•个请求(适用于所有请求)(since v1.0.4)
HttpTask<?> task = http.async("/users")
+        .setOnResponse((HttpResult result) -> {
+            // �应回调
+        });
+
+task.get(); // �起 GET 请求
+
+// �消请求,并返回是��消�功
+boolean canceled = task.cancel();   
+
1
2
3
4
5
6
7
8
9
  • 使用HTTP#cancel(String tag)按标签批é‡�å�–消请求(适用于所有请求,详è§�第 5 章节)
  • 使用HTTP#cancelAll()å�–消所有请求(适用于所有请求)(since v1.0.2)
http.cancelAll();   // �消所有请求
+
1
+ + + diff --git a/okhttps-doc/docs/.vuepress/dist/guide/foundation.html b/okhttps-doc/docs/.vuepress/dist/guide/foundation.html new file mode 100644 index 00000000..54bfdf7b --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/guide/foundation.html @@ -0,0 +1,130 @@ + + + + + + 基础 | OkHttps + + + + + + + + + + + + + + + + + + +

# 基础

# 请求方法

�步与异步的HttpTask都拥有get�post�put与delete方法。��的是:�步HttpTask的这些方法返回一个HttpResult,而异步HttpTask的这些方法返回一个HttpCall。

HttpResult res1 = http.sync("/users").get();     // �步 GET
+HttpResult res2 = http.sync("/users").post();    // �步 POST
+HttpResult res3 = http.sync("/users/1").put();   // �步 PUT
+HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE
+HttpCall call1 = http.async("/users").get();     // 异步 GET
+HttpCall call2 = http.async("/users").post();    // 异步 POST
+HttpCall call3 = http.async("/users/1").put();   // 异步 PUT
+HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE
+
1
2
3
4
5
6
7
8

# 回调函数

OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅:

http.async("/users/{id}")             // http://api.demo.com/users/1
+        .addPathParam("id", 1)
+        .setOnResponse((HttpResult result) -> {
+            // �应回调
+        })
+        .setOnException((IOException e) -> {
+            // 异常回调
+        })
+        .setOnComplete((State state) -> {
+            // 完�回调,无论�功失败都会执行
+            // 并且在 �应|异常回调 之�执行
+        })
+        .get();
+
1
2
3
4
5
6
7
8
9
10
11
12
13

OkHttps �时还支� 全局回调 和 回调阻断 机制,详� 全局回调监�。

TIP

  • å�ªæœ‰å¼‚步请求æ‰�å�¯ä»¥è®¾ç½®è¿™ä¸‰ç§�(å“�应|异常|完æˆ�)回调
  • å�Œæ­¥è¯·æ±‚直接返回结果,无需使用回调

# HttpResult

HttpResult是HTTP请求执行完�的结果,它是�步请求方法( get�post�put�delete)的返回值,也是异步请求�应回调(OnResponse)的�数,它定义了如下方法:

  • getState() 得到请求执行状æ€�枚举,它有以下å�–值: +
    • State.CANCELED 请求被å�–消
    • State.RESPONSED 已收到å“�应
    • State.TIMEOUT 请求超时
    • State.NETWORK_ERROR 网络错误
    • State.EXCEPTION 其它请求异常
  • getStatus() 得到HTTP状æ€�ç �
  • isSuccessful() 是å�¦å“�应æˆ�功,状æ€�ç �在 [200..300) 之间
  • getHeaders() 得到HTTPå“�应头
  • getHeaders(String name) 得到HTTPå“�应头
  • getHeader(String name) 得到HTTPå“�应头
  • getBody() 得到å“�应报文体Body实例,它定义了如下方法(对å�Œä¸€ä¸ªBody实例,以下的toXXX()类方法å�ªèƒ½ä½¿ç”¨ä¸€ä¸ªä¸”仅能调用一次,除é�žå…ˆä½¿ç”¨ cache 方法): +
    • toBytes() 返回字节数组
    • toByteStream() 返回字节输入æµ�
    • toCharStream() 返回字符输入æµ�
    • toString() 返回字符串
    • toJsonObject() 返回Json对象
    • toJsonArray() 返回Json数组
    • toBean(Class<T> type) 返回根æ�®type自动jsonè§£æž�å�Žçš„JavaBean
    • toList(Class<T> type) 返回根æ�®type自动jsonè§£æž�å�Žçš„JavaBean列表
    • toFile(String filePath) 下载到指定路径
    • toFile(File file) 下载到指定文件
    • toFolder(String dirPath) 下载到指定目录
    • toFolder(File dir) 下载到指定目录
    • getContentType() 返回报文体的媒体类型
    • getContentLength() 返回报文体的字节长度
    • cache() 缓存报文体,开å�¯ç¼“å­˜å�Žå�¯é‡�å¤�使用toXXX()类方法
    • close() 关闭报文体,未对报文体å�šä»»ä½•消费时使用,比如å�ªè¯»å�–报文头
  • getError() 执行中å�‘生的异常,自动æ�•获执行请求时å�‘生的 网络超时ã€�网络错误 å’Œ 其它IO异常
  • close() 关闭报文,未对报文体å�šä»»ä½•消费时使用,比如å�ªè¯»å�–长度

示例,请求结果自动转Bean和List:

// 自动转Bean
+Order order = http.sync("/orders/1")
+        .get().getBody().toBean(Order.class);
+        
+// 自动转List
+List<Order> orders = http.sync("/orders")
+        .get().getBody().toList(Order.class);
+
1
2
3
4
5
6
7

示例,使用 cache 方法:

Body body = http.sync("/orders").get().getBody().cache();
+
+// 使用 cache �,�以多次使用 toXXX() 方法
+System.out.println(body.toString());
+System.out.println(body.toJsonArray());
+System.out.println(body.toList(Order.class));
+
1
2
3
4
5
6

示例,获�下载文件的大�:

long size = http.sync("/download/test.zip")
+            .get().getBody()
+            .close()             // �是想获得文件大�,�消费报文体,所以直接关闭
+            .getContentLength(); // 获得待下载文件的大�
+
+// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络��
+
+System.out.println("size = " + size);
+
1
2
3
4
5
6
7
8

# HttpCall

HttpCall对象是异步请求方法(get�post�put�delete)的返回值,与java的Future接�很�,它有如下方法:

  • cancel() å�–消本次请求,返回å�–消结果
  • isCanceled() 返回请求是å�¦è¢«å�–消
  • isDone() 返回是å�¦æ‰§è¡Œå®Œæˆ�,包å�«å�–消和失败
  • getResult() 返回执行结果HttpResult对象,若请求未执行完,则挂起当å‰�线程直到执行完æˆ�å†�返回

�消一个异步请求示例:

HttpCall call = http.async("/users/1").get();
+
+System.out.println(call.isCanceled());     // false
+
+boolean success = call.cancel();           // �消请求
+
+System.out.println(success);               // true
+System.out.println(call.isCanceled());     // true
+
1
2
3
4
5
6
7
8

# 构建HTTP任务

HTTP对象的sync与async方法返回一个HttpTask对象,该对象�供了�链�调用的addXXX与setXXX等系列方法用于构建任务本身。

  • addHeader(String name, String value) 添加请求头

  • addHeader(Map<String, String> headers) 添加请求头

  • addPathParam(String name, Object value) 添加路径å�‚数:替æ�¢URL里的{name}å� ä½�符

  • addPathParam(Map<String, ?> params) 添加路径å�‚数:替æ�¢URL里的{name}å� ä½�符

  • addUrlParam(String name, Object value) 添加URLå�‚数:拼接在URLçš„?之å�Žï¼ˆæŸ¥è¯¢å�‚数)

  • addUrlParam(Map<String, ?> params) 添加URLå�‚数:拼接在URLçš„?之å�Žï¼ˆæŸ¥è¯¢å�‚数)

  • addBodyParam(String name, Object value) 添加Bodyå�‚数:以表å�•key=value&的形å¼�放在报文体内(表å�•å�‚数)

  • addBodyParam(Map<String, ?> params) 添加Bodyå�‚数:以表å�•key=value&的形å¼�放在报文体内(表å�•å�‚数)

  • addJsonParam(String name, Object value) 添加Jsonå�‚数:请求体为Json(支æŒ�多层结构)

  • addJsonParam(Map<String, ?> params) 添加Jsonå�‚数:请求体为Json(支æŒ�多层结构)

  • setRequestJson(Object json) 设置请求体的Json字符串 或待转æ�¢ä¸º Jsonçš„ JavaBean

  • setRequestJson(Object bean, String dateFormat) 设置请求体的Json字符串 或待转æ�¢ä¸º Jsonçš„ JavaBean

  • addFileParam(String name, String filePath) 上传文件

  • addFileParam(String name, File file) 上传文件

  • addFileParam(String name, String type, InputStream inputStream) 上传文件

  • addFileParam(String name, String type, String fileName, InputStream input) 上传文件

  • addFileParam(String name, String type, byte[] content) 上传文件

  • addFileParam(String name, String type, String fileName, byte[] content) 上传文件

  • setTag(String tag) 为HTTP任务添加标签

  • setRange(long rangeStart) 设置Range头信æ�¯ï¼Œç”¨äºŽæ–­ç‚¹ç»­ä¼ 

  • setRange(long rangeStart, long rangeEnd) 设置Range头信æ�¯ï¼Œå�¯ç”¨äºŽåˆ†å�—下载

  • bind(Object object) 绑定一个对象,å�¯ç”¨äºŽå®žçްAndroid里的生命周期绑定

# 使用标签

有时候我们想对HTTP任务加以分类,这时候�以使用标签功能:

http.async("/users")    //(1)
+        .setTag("A")
+        .get();
+        
+http.async("/users")    //(2)
+        .setTag("A.B")
+        .get();
+        
+http.async("/users")    //(3)
+        .setTag("B")
+        .get();
+        
+http.async("/users")    //(4)
+        .setTag("B")
+        .setTag("C")    // 从 v1.0.4 标签将以追加模�添加,等效于 setTag("B.C")
+        .get();
+        
+http.async("/users")    //(5)
+        .setTag("C")
+        .get();
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

当使用标签�,就�以按标签批�的对HTTP任务进行�消:

int count = http.cancel("B");              //(2)(3)(4)被�消(�消标签包�"B"的任务)
+System.out.println(count);                 // 输出 3
+
1
2

标签除了�以用��消任务,在预处�器中它也�以�挥作用,请�� 并行预处�器 与 串行预处�器(token问题最佳解决方案)。

+ + + diff --git a/okhttps-doc/docs/.vuepress/dist/guide/index.html b/okhttps-doc/docs/.vuepress/dist/guide/index.html new file mode 100644 index 00000000..9b6c66b0 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/guide/index.html @@ -0,0 +1,79 @@ + + + + + + èµ·æ­¥ | OkHttps + + + + + + + + + + + + + + + + + + +

# èµ·æ­¥

OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。

  • 链å¼�调用,一点到底
  • BaseURLã€�URLå� ä½�符ã€�JSON自动å°�装与解æž�
  • å�Œæ­¥æ‹¦æˆªå™¨ã€�异步预处ç�†å™¨ã€�回调执行器ã€�全局监å�¬ã€�回调阻断
  • 文件上传下载(过程控制ã€�进度监å�¬ï¼‰
  • å�•方法回调,充分利用 Lambda 表达å¼�
  • TCP连接池ã€�Http2

TIP

  • OkHttps é�žå¸¸è½»é‡�(59Kb),仅是 Retrofit(124Kb)的一å�Šï¼Œå¹¶ä¸”更加的开箱å�³ç”¨ï¼ŒAPI 也更加自然和语义化。
  • OkHttps 是一个纯粹的 Java 网络开å�‘包,并ä¸�ä¾�èµ– Android,这一点和 Retrofit ä¸�å�Œ
  • OkHttps 用起æ�¥å¾ˆä¼˜ç¾Žï¼Œå�¯ä»¥åƒ� RxJava 那样链å¼�用,å�´æ¯” RxJava 更简å�•。

# 安装

# Maven

<dependency>
+     <groupId>com.ejlchina</groupId>
+     <artifactId>okhttps</artifactId>
+     <version>1.0.5</version>
+</dependency>
+
1
2
3
4
5

# Gradle

implementation 'com.ejlchina:okhttps:1.0.5'
+
1

安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��:

android {
+    // �略其它�置..
+    compileOptions {
+        sourceCompatibility = 1.8
+        targetCompatibility = 1.8
+    }
+}
+
1
2
3
4
5
6
7

# 使用

# 构建实例

HTTP http = HTTP.builder().build();
+
1

以上代�构建了一个最简�的HTTP实例,它拥有以下方法:

  • sync(String url) 开始一个å�Œæ­¥è¯·æ±‚
  • async(String url) 开始一个异步请求
  • cancel(String tag) 按标签å�–消请求
  • cancelAll() å�–消所有HTTP任务,包括å�Œæ­¥å’Œå¼‚æ­¥
  • request(Request request) OkHttp 原生请求
  • webSocket(Request request, WebSocketListener listener) WebSocket通讯

为了使用方便,在构建的时候,我们更愿�指定一个BaseUrl(详� 设置 BaseUrl):

HTTP http = HTTP.builder()
+        .baseUrl("http://api.demo.com")
+        .build();
+
1
2
3

为了简化文档,下文中出现的http�是在构建时设置了BaseUrl的HTTP实例。

# �步请求

使用方法sync(String url)开始一个�步请求:

List<User> users = http.sync("/users") // http://api.demo.com/users
+        .get()                         // GET请求
+        .getBody()                     // 获��应报文体
+        .toList(User.class);           // 得到目标数�
+
1
2
3
4

方法sync返回一个�步HttpTask,�链�使用。

# 异步请求

使用方法async(String url)开始一个异步请求:

http.async("/users/1")                //  http://api.demo.com/users/1
+        .setOnResponse((HttpResult result) -> {
+            // 得到目标数�
+            User user = result.getBody().toBean(User.class);
+        })
+        .get();                       // GET请求
+
1
2
3
4
5
6

方法async返回一个异步HttpTask,�链�使用。

至此,你已轻�学会了 OkHttps 95% 的常规用法�但别急,��还有更精彩的。

+ + + diff --git a/okhttps-doc/docs/.vuepress/dist/guide/updown.html b/okhttps-doc/docs/.vuepress/dist/guide/updown.html new file mode 100644 index 00000000..32ad8f39 --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/guide/updown.html @@ -0,0 +1,195 @@ + + + + + + 上传下载 | OkHttps + + + + + + + + + + + + + + + + + + +

# 上传下载

# 文件下载

OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例:

http.sync("/download/test.zip")
+        .get()                           // 使用 GET 方法(其它方法也�以,看�务器支�)
+        .getBody()                       // 得到报文体
+        .toFile("D:/download/test.zip")  // 下载到指定的路径
+        .start();                        // �动下载
+
+http.sync("/download/test.zip").get().getBody()                  
+        .toFolder("D:/download")         // 下载到指定的目录,文件�将根�下载信�自动生�
+        .start();
+
1
2
3
4
5
6
7
8
9

或使用异步连接方�:

http.async("/download/test.zip")
+        .setOnResponse((HttpResult result) -> {
+            result.getBody().toFolder("D:/download").start();
+        })
+        .get();
+
1
2
3
4
5

这里�说明一下:sync与async的区别在于连接�务器并得到�应这个过程的�步与异步(这个过程的耗时在大文件下载中�比��),而start方法�动的下载过程则都是异步的。

# 下载进度监�

就直接上代�啦,诸�一看便懂:

http.sync("/download/test.zip")
+        .get()
+        .getBody()
+        .setStepBytes(1024)   // 设置�接收 1024 个字节执行一次进度回调(�设置默认为 8192)  
+ //     .setStepRate(0.01)    // 设置�接收 1% 执行一次进度回调(�设置以 StepBytes 为准)  
+        .setOnProcess((Process process) -> {           // 下载进度回调
+            long doneBytes = process.getDoneBytes();   // 已下载字节数
+            long totalBytes = process.getTotalBytes(); // 总共的字节数
+            double rate = process.getRate();           // 已下载的比例
+            boolean isDone = process.isDone();         // 是�下载完�
+        })
+        .toFolder("D:/download/")        // 指定下载的目录,文件�将根�下载信�自动生�
+ //     .toFile("D:/download/test.zip")  // 指定下载的路径,若文件已存在则覆盖
+        .setOnSuccess((File file) -> {   // 下载�功回调
+            
+        })
+        .start();
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

值得一�的是:由于 OkHttps 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有Content-Length头),例如:

List<User> users = http.sync("/users")
+        .get()
+        .getBody()
+        .setStepBytes(2)
+        .setOnProcess((Process process) -> {
+            System.out.println(process.getRate());
+        })
+        .toList(User.class);
+
1
2
3
4
5
6
7
8

# 下载过程控制

过于简�:还是直接上代�:

Ctrl ctrl = http.sync("/download/test.zip")
+        .get()
+        .getBody()
+        .setOnProcess((Process process) -> {
+            System.out.println(process.getRate());
+        })
+        .toFolder("D:/download/")
+        .start();   // 该方法返回一个下载过程控制器
+ 
+ctrl.status();      // 下载状�
+ctrl.pause();       // 暂�下载
+ctrl.resume();      // ��下载
+ctrl.cancel();      // �消下载(�时会删除文件,����)
+
1
2
3
4
5
6
7
8
9
10
11
12
13

无论是�步还是异步�起的下载请求,都�以�以上的控制:

http.async("/download/test.zip")
+        .setOnResponse((HttpResult result) -> {
+            // 拿到下载控制器
+            Ctrl ctrl = result.getBody().toFolder("D:/download/").start();
+        })
+        .get();
+
1
2
3
4
5
6

# 实现断点续传

OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到 断点,便将��的问题�得简�:

http.sync("/download/test.zip")
+        .get()
+        .getBody()
+        .toFolder("D:/download/")
+        .setOnFailure((Failure failure) -> {         // 下载失败回调,以便接收诸如网络错误等失败信�
+            IOException e = failure.getException();  // 具体的异常信�
+            long doneBytes = failure.getDoneBytes(); // 已下载的字节数(断点),需��存,用于断点续传
+            File file = failure.getFile();           // 下载生�的文件,需��存 ,用于断点续传(��存路径也�以)
+        })
+        .start();
+
1
2
3
4
5
6
7
8
9
10

下�代�实现续传:

long doneBytes = ...    // 拿到�存的断点
+File file =  ...        // 待续传的文件
+
+http.sync("/download/test.zip")
+        .setRange(doneBytes)                         // 设置断点(已下载的字节数)
+        .get()
+        .getBody()
+        .toFile(file)                                // 下载到�一个文件里
+        .setAppended()                               // 开�文件追加模�
+        .setOnSuccess((File file) -> {
+
+        })
+        .setOnFailure((Failure failure) -> {
+        
+        })
+        .start();
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 实现分�下载

当文件很大时,有时候我们会考虑分�下载,与断点续传的�路是一样的,示例代�:

static String url = "http://api.demo.com/download/test.zip"
+
+public static void main(String[] args) {
+    long totalSize = HttpUtils.sync(url).get().getBody()
+            .close()             // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭
+            .getContentLength(); // 获得待下载文件的大�(由于未消费报文体,所以该请求�会消耗下载报文体的时间和网络��)
+    download(totalSize, 0);      // 从第 0 �开始下载
+    sleep(50000);                // 等待下载完�(�然本例的主线程就结�啦)
+}
+
+static void download(long totalSize, int index) {
+    long size = 3 * 1024 * 1024;                 // ��下载 3M  
+    long start = index * size;
+    long end = Math.min(start + size, totalSize);
+    HttpUtils.sync(url)
+            .setRange(start, end)                // 设置本次下载的范围
+            .get().getBody()
+            .toFile("D:/download/test.zip")      // 下载到�一个文件里
+            .setAppended()                       // 开�文件追加模�
+            .setOnSuccess((File file) -> {
+                if (end < totalSize) {           // 若未下载完,则继续下载下一�
+                    download(totalSize, index + 1); 
+                } else {
+                    System.out.println("下载完�");
+                }
+            })
+            .start();
+}
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 文件上传

一个简�文件上传的示例:

http.sync("/upload")
+        .addFileParam("test", "D:/download/test.zip")
+        .post();     // 上传�法一般使用 POST 或 PUT,看�务器支�
+
1
2
3

异步上传也是完全一样:

http.async("/upload")
+        .addFileParam("test", "D:/download/test.zip")
+        .post();
+
1
2
3

# 上传进度监�

OkHttps 的上传进度监�,监�的是所有请求报文体的��进度,示例代�:

http.sync("/upload")
+        .addBodyParam("name", "Jack")
+        .addBodyParam("age", 20)
+        .addFileParam("avatar", "D:/image/avatar.jpg")
+        .setStepBytes(1024)   // 设置��� 1024 个字节执行一次进度回调(�设置默认为 8192)  
+ //     .setStepRate(0.01)    // 设置��� 1% 执行一次进度回调(�设置以 StepBytes 为准)  
+        .setOnProcess((Process process) -> {           // 上传进度回调
+            long doneBytes = process.getDoneBytes();   // 已��字节数
+            long totalBytes = process.getTotalBytes(); // 总共的字节数
+            double rate = process.getRate();           // 已��的比例
+            boolean isDone = process.isDone();         // 是���完�
+        })
+        .post();
+
1
2
3
4
5
6
7
8
9
10
11
12
13

咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在get/post方法之�使用这些API,下载是在getBody方法之�使用。很好�解:get/post之�是准备��请求时段,有上传的�义,而getBody之�,已是报文�应的时段,当然是下载。

# 上传过程控制

上传文件的过程控制就很简�,和常规请求一样,�有异步�起的上传�以�消:

HttpCall call = http.async("/upload")
+        .addFileParam("test", "D:/download/test.zip")
+        .setOnProcess((Process process) -> {
+            System.out.println(process.getRate());
+        })
+        .post();
+
+call.cancel();  // �消上传
+
1
2
3
4
5
6
7
8

上传就没有暂�和继续这个功能啦,应该没人有这个需求�?

+ + + diff --git a/okhttps-doc/docs/.vuepress/dist/index.html b/okhttps-doc/docs/.vuepress/dist/index.html new file mode 100644 index 00000000..3d0605ad --- /dev/null +++ b/okhttps-doc/docs/.vuepress/dist/index.html @@ -0,0 +1,72 @@ + + + + + + OkHttps + + + + + + + + + + + + + + + + +
hero

+ OkHttps +

+ 基于 OkHttp 增强版 HTTP 客户端 +

+ �速上手 → +

轻�纯粹优雅

OkHttps �常轻�,体积仅是 Retrofit 的一��到,并且��赖于特定平�,API 语义简�舒适。

开箱�用的功能

异步预处�器�回调执行器�全局监�器�回调阻断机制�文件上传下载�过程控制�进度监�。

更多实用特性

URL ��符�Lambda 回调�JSON自动�装解��OkHttp 的特性:拦截器�连接池�CookieJar 等。

// 构建 HTTP
+HTTP http = HTTP.builder()
+        .baseUrl("https://api.demo.com")
+        .build();
+
+// �步请求
+List<User> users = http.sync("/users")  // http://api.demo.com/users
+        .get()                          // GET请求
+        .getBody()                      // 获��应报文体
+        .toList(User.class);            // 得到目标数�
+
+// 异步请求
+http.async("/users/jack")               //  http://api.demo.com/users/jack
+        .setOnResponse((HttpResult result) -> {
+            // 得到目标数�
+            User jack = result.getBody().toBean(User.class);
+        })
+        .get();                         // GET请求
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

竟然�到 15 秒,你已学会 90% 的精髓�
了解更多

+ + + diff --git a/docs/.vuepress/public/logo.png b/okhttps-doc/docs/.vuepress/dist/logo.png similarity index 100% rename from docs/.vuepress/public/logo.png rename to okhttps-doc/docs/.vuepress/dist/logo.png diff --git a/okhttps-doc/docs/.vuepress/public/logo.png b/okhttps-doc/docs/.vuepress/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..3b3b2845420b470e4b091e3862ff98653c4b1cb0 GIT binary patch literal 5800 zcmX9?c|2768$RclVT^4s*_RpXRMuoG%P?dtA*m#L(n8lZmMhEHm&71ZWGfe4Wi5Ng zo~ww;5;4j}cES*5ese#+KhEcUKi~Izp69He_j%rATWd2Oq!=R5sxYDrp^2IMU_Bh0y>E*~O>!|ph0Kd1zw>qt@EFdT#`V|KkDr5H~Vx$ zx)qN}Ap!Ni=LJ%~4KJ^GhuGQh?bUZ0gP6bYt%j3+HhGK!?l=fvsUG{UYoE##$O+3L zcXJaDBgO*^4X}+3<@1HV`X40nk{wF!_t4kKDi{!MFP%L1P(CCI|9baxI_?ea=Cg%nKp+fbIeFs4TS`T<+@j9@WN^=z+q2S+UuVX zJ08S5nc@z=+e|L71(Fns;bfH}MHahx5{!0&1nRSZk5wOCfttxuth$gLL|cTK2_TWX zJy=EO-aO=tH^Tv(ESk4IyZSS_H|=cFbqDUos}!-J$@LBeU)J`r0{1d~(0R95-6|8PJ$uBxn)R!h`R!oGVeOt8Zk_3mb8P&Qx~Rsl$qY?5ZAR znd`p}FIl_Y?L7>yjD{#egzxhQ3HK8`fNlA7fprdau?sC9x7N+c=0Kh5hbjX-cSBk5zHwMB>BZEb<@Y z#2oE^)g|o!thYh_Z;NtWb_uo_kjDYZHRbcd(KoHQObKGM#7!0I1t3$N^xf+9EksGM zz?0D8jd%BiBi@wHzh0B1_YHj>Y?_S8X^cUb zTq`U5d{K4O=DM?QvY|!LDG|$HEbx7t?<{v@;!>kx#Y(ZOkz;*$>fvdxVN|z5unN_^ z7MEEG1A3I{iHB8-FNL@29d9r3-{^=)az0HG`5CAjSoYZouLY5F>IW*@lf8N^Wi(RH z{B|h5FO9jW?j%szc+R+*C`>Ws1-!>?Aclo6flubmOR+fP_uX!ZROPR~3 z>&xdOdw%#Y&a|+q|54hu?xvMe08=F)FO{0>0~y8X^3X&JSpr7wv^LPdf?nq5FZhgS z1Q7X6G53V=AR@7pg4rFJP!LN*w>lgzL3pl00TWzm;*DIkDT(**ymB-uZ)}JZlrbfM zTG2t+NqtCn6`pieaHjVxF|K05tP@;AnNIgZuXCSTVIvKyUVtiYTlKhpnuhs>ESA`%fNPm-I6&ic%!=cur zrJu^WpyGwoakaA%#V_8iIN{gscF?P>Zrz=~S6x0o?5faZP378&T(l-2G^Tm>&jzwE za-bhZt7erF%l||?uO^@^2^t($@Vz$^*f zO!9d7+0I9N0Tuo6&uD!s==x;pjaeu~kj&nNHQMlW5Ql_x(H`;kMAYCpJ*JWqz6PTC z3`No@)D-046&)>w6zin}1SY({gvc>mi1Yomph7dPCZi7H%pSkLSr8~mfJW({t+$c|! zwfYLT1unZ0tEFO%{e;EICSCD-`_S54$mr^ioaZY6tsYi<7McJh%w@_`fy6ez4qs+iXK0=H;rm!}>Ft77(PG9d`cPmaL6)z%?%Es&N zYmVB55_lBv-*LGe@#bL>kV^F<7JW?)<@Q64VYvVJIh3dWcER)d*0?Qj&ZBWP_xG%v zol>$%*HYBj@kR`nEdX^`cgvZE>V;xbLu9=4tVWGN1mgQzo?d?3bBF+7MFc45A^_o0 z-<9U5=;6Va0K{PAs)J>00<~O67pAlR_z0SipC%<=!U6oVvvS>H+@MSh&slEHB+*3x z?MB2`;z8TE#4OZZ5eQd{7Kqbp3s!PTohEQ8W$Kaub~iYm8fV-1I?v8=nM4n-dPTlPzo<##cHv9x+IN=y@JUN$W1QHR!G781TfE+uY zA{NVv2m&O4MB+WD;AxKA_6dW_zHXB>aYcX#2ix2I8m%9`GC#Y_Em)Y`;|CVAw&yu( z_4DO~alkq1DD5A&of!ua0g(i#2$6Oy&z)AL_o<|i(xJ^Xz*yK=^j ze&#qwJMKeqX{7`@4*DqAO0hXr^{t`1B`fS7Yl5*FY!P%Z={-2JG3No|0LfXJHc01( zC1CL!I(r{zfhuJV5m>MYsHb-L@}}VNB9IUESw~dzmS>_@iSCMprw&U;QP~B=4;RW! zTB%#lmzyKgB=7ScanLuiEKFrh-Q>_@O{=Afs$%#o=bndotMZ?3|bMG$hPhg%6nwsV*iVcjh-QaCd;cW>uUxQTywg9 zpL?QlGH7#rCzLF0*%a5J_oUJg4UmNo-V@_zj%kTXUQP4md2^iBf8$Au5{vxhC;{n3D+ zf7IoLWm)&Viwje(tWuk)rlDPHJAwD-#aGZ0FWmt?*xSfPF@0;A z7Q-w^fCg`*KIL)xDlC*iV^0YHa*qsCL(O>^JUAWD;J)U=dB9^37C!r?dJg7cBwU@~ z0R!ryD%qveb@wKt5mOIHP0p1j6nTpPpvH>~r~ehgVZ5(4^6w&a8D|X03^K0VdSVpD zYAK23X%D?ZD&UTrjWH7V${(enem#CKh$q=dpyfjuKwW8{@Jf@9<4c%2`vNSjI@F01 zB6p{6+kKM1`DnA~55wMhtdtJY!VggQVwPyp5rY5zSrKVW@Kgq>!$$PigzFizc-#hl z@6_4FE4F$~XUQUbkL%1s(`4je_l1EgWPr#w*f(`YOe*f;NXuS|FpyIRP#KmX`!~MZ z@ZJ`-4Hu!E3IRso()ma5Vy>jF1`USK2;W%vGfw-qedmznw2|H90gWGj3!6FAW;ymM zzdfNgxk}9n``tvlANaO>UOPUL?#5m)JC?5->T`ixCV#|OIkNShotY8!{l&6DkaI|1N`ax|&rZ7l z?z&&4G?ri$mD#tosdTvUP}h)WiuU>bJ3$BElSJgJCR-JSCM0=|ps9Xvoopb`+AT?t z!Tc%R!roPI%To~u&COJ9|1uECzuvd#>t+m-i359@$r6&}xh}mimjknKsb3GDo<&LA zm5Xl}*8|{1(l6=^r_NW2?oZDAel)p1O?TPbj2g>2U_bMd7)kHh<#<?7jM!H4`$P+ zY#7^p;vDS@E$v6m2U%_UAE(dUFpKe)_+0OhbPL;r)OS(bI{=pp8nc`y< z9)=!JU3<7XJ}i%Y3vrEV8!#MOdoC+a6*KG3!aYZCBbQ3b-~VW6!1}Jx(Z( zK3@Be+DY);;lt_CXu1t^YiNigz?HF}-R^JL-WbZb$;I_A%x#!QPrit4F)i3Ee{_`^ z3A8giIEG$^UupH;n>b*OYi5*xldc}0e`+^}1MIHe`LZXdvHs&t)PgC^HENTK&KNTE zD-8erv-j#ZMc$+KO+!hq$ixZPYe2V&P9VK8L*iP@e%yo!jcySvw)PM9&5t*uKMo$Z z^>gmEK?8a5?DNR_yl5Q-uq*2s8){Oml`qE|?p>50I|KCdzV%8Q3`Vt@YPNG~tIZ$kt;NT+`hR=gEYMzO6ZD|2Hyu^ewRy6Dkv$++c^3 zFseFe(-b91|8kMr5^X(VT5SmM34NLBoGm*sw*)+QU5Q1X>Z^WpGufAxVQnJx?T+4n z1W;M&>2DVQIQgBd*dN)B&=lpD7p9-1<+?f_MclzZL#e~y_^-U9gnT&u>#n1t?9j2F z9~n{S zIU&?_t)>S{gj3M=QTl~!vkvwNF5sa-Z`iszA$nNCOegYCpxB+&KANFEKad-KPOYM> z4v}owcXM0D6an0Uo@Yh#76Vt{VKJ4=BScPf%4tzKg82f}{dIFkC3rT27vqz1qd%R; z_s`44A|N$#Uqpo(_)o0TWCzXg0gA5ex9eJ5pB3%V1Tc-qtdMU4B;5O}X4P{TE`Q;` zq!s87DyJ=Ml*P)pI+aFhI(gaWRati(c>NDrF`^QTWwJbxl=`l#jXy*_7M&YG!$Fof zZiZzqBk%YQi8ekND$b7!4x)0=o);9DN*xx6-ei729|wr+`bpsv=V0&iPolUGGq=0r zTw~(}ADqAVg3YfwzD6L1Co+h3+q}nkT(($!uWI~t#Z#rpm=Ji~=Ec&1gCkCkrmq+0 z^bTv6&ssG24ZSP=>#yUEz|@%PQpR`7FgX9aJAuf!9f!u^1+CT{Rh7?T#;+EjZTEzW zB#&$Mi4_jb?ym=N|tg2236iIFNRu<^P(9?`q#FJX_mht! z3WEcbZDH>_I;2rZJO>U^Xf)22=7_@QvMqv_IhITWy^eR48ekWJFme$6=$&$p#e#&X zfy5#75#;W6nDBe$`Awq(LX-L3WZ(1WaGJUi(h)3|)Y*#n3&&nG9gyZgvJ|huSS4z`Y`R zf2Y_2aYl(#k2@4(9Y3y#$3Q4fWXG>)!|TVZlyN}Daa+XT@EC<{27?CVt3CW~HGUa& zuvXhJ3py@SYYRLynrTCNP=0T@2ckos{>Cbn;z2doW!@9{K3ORuP9*|cxuQqgEN27v z_(+=jrY)qP^yrLW;73JP@8YLujJqy<6(7JlX*nmV(?mbrguyZH800-v++ST);? Date: Fri, 8 May 2020 13:34:11 +0800 Subject: [PATCH 200/924] update_README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index edb85cd9..ed3a8f1c 100644 --- a/README.md +++ b/README.md @@ -432,6 +432,7 @@ HTTP http = HTTP.builder() .addPreprocessor((PreChain chain) -> { HttpTask task = chain.getTask();// 获得当�的HTTP任务 if (!task.isTagged("Auth")) { // 根�标签判断该任务是�需�Token + chain.proceed(); return; } requestToken((String token) -> { // 异步获� Token @@ -458,6 +459,7 @@ HTTP http = HTTP.builder() .addSerialPreprocessor((PreChain chain) -> { HttpTask task = chain.getTask(); if (!task.isTagged("Auth")) { + chain.proceed(); return; } // 检查过期,若需�则刷新Token From b74c1e5292c5f9b8e052d1be5c0bde2d951299df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 14:27:48 +0800 Subject: [PATCH 201/924] =?UTF-8?q?=E5=AD=90=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps-fastjson/pom.xml | 17 +++++ okhttps-gson/pom.xml | 17 +++++ okhttps-jackson/pom.xml | 17 +++++ okhttps-kotlin/pom.xml | 17 +++++ okhttps/pom.xml | 158 ++------------------------------------- 5 files changed, 75 insertions(+), 151 deletions(-) create mode 100644 okhttps-fastjson/pom.xml create mode 100644 okhttps-gson/pom.xml create mode 100644 okhttps-jackson/pom.xml create mode 100644 okhttps-kotlin/pom.xml diff --git a/okhttps-fastjson/pom.xml b/okhttps-fastjson/pom.xml new file mode 100644 index 00000000..bdf2ab35 --- /dev/null +++ b/okhttps-fastjson/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + + okhttps-fastjson + OkHttps Fastjson + jar + + + com.ejlchina + okhttps-parent + 1.0.5 + + + + okhttps-fastjson + + \ No newline at end of file diff --git a/okhttps-gson/pom.xml b/okhttps-gson/pom.xml new file mode 100644 index 00000000..c595205b --- /dev/null +++ b/okhttps-gson/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + + okhttps-gson + OkHttps Gson + jar + + + com.ejlchina + okhttps-parent + 1.0.5 + + + + okhttps-gson + + \ No newline at end of file diff --git a/okhttps-jackson/pom.xml b/okhttps-jackson/pom.xml new file mode 100644 index 00000000..ad226219 --- /dev/null +++ b/okhttps-jackson/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + + okhttps-jackson + OkHttps Jackson + jar + + + com.ejlchina + okhttps-parent + 1.0.5 + + + + okhttps-jackson + + \ No newline at end of file diff --git a/okhttps-kotlin/pom.xml b/okhttps-kotlin/pom.xml new file mode 100644 index 00000000..acbaf2e6 --- /dev/null +++ b/okhttps-kotlin/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + + okhttps-kotlin + OkHttps Kotlin + jar + + + com.ejlchina + okhttps-parent + 1.0.5 + + + + okhttps-kotlin + + \ No newline at end of file diff --git a/okhttps/pom.xml b/okhttps/pom.xml index ea76c2a4..c2cd72c2 100644 --- a/okhttps/pom.xml +++ b/okhttps/pom.xml @@ -1,51 +1,18 @@ 4.0.0 - com.ejlchina okhttps - 1.0.5 OkHttps - - - 1.8 - 3.14.7 - 1.2.67 - 4.12 - UTF-8 - https://oss.sonatype.org/content/repositories/snapshots/ - - - - - The Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - - Troy - zhou.xu@ejlchina.com - ejlchina - http://www.ejlchina.com - - - - - scm:git://gitee.com/ejlchina-zhxu/okhttps.git - scm:http://gitee.com/ejlchina-zhxu/okhttps - https://gitee.com/ejlchina-zhxu/okhttps - v1.0.5 - + jar + + + com.ejlchina + okhttps-parent + 1.0.5 + - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - - com.alibaba fastjson @@ -59,121 +26,10 @@ test - - junit - junit - ${junit.version} - test - - - - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - ${sonatypeOssDistMgmtSnapshotsUrl} - - - sonatype-nexus-staging - Nexus Release Repository - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - okhttps - - - - org.apache.maven.plugins - maven-release-plugin - 2.1 - - forked-path - false - -Psonatype-oss-release - - - - - org.apache.maven.plugins - maven-compiler-plugin - - ${java-version} - ${java-version} - ${project.build.sourceEncoding} - true - - - - - org.apache.maven.plugins - maven-source-plugin - 2.1.2 - - - attach-sources - - jar-no-fork - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.7 - - - attach-javadocs - - jar - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.1 - - - sign-artifacts - verify - - sign - - - - - - - https://gitee.com/ejlchina-zhxu/okhttps - 比 Retrofit 更好用的网络框架� OkHttp3 轻��装 ,开箱�用�Java领域��端处� Http问题的新选择。 - - 江�一键�信�科技有�公� - http://www.ejlchina.com/ - - - https://gitee.com/ejlchina-zhxu/okhttps/issues - \ No newline at end of file From defe4ce5f4edd6435f2b0720afc5b480936432d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 14:28:58 +0800 Subject: [PATCH 202/924] gitignore --- .gitignore | 5 +- pom.xml | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore index d39f4879..5a66362c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,7 @@ /*/.vuepress/dist/* /*/*.iml *.iml -/.idea/ \ No newline at end of file +/.idea/ +.settings/ +.classpath +.project \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..d342656e --- /dev/null +++ b/pom.xml @@ -0,0 +1,176 @@ + + 4.0.0 + + com.ejlchina + okhttps-parent + 1.0.5 + OkHttps + + pom + + + okhttps + okhttps-fastjson + okhttps-gson + okhttps-jackson + okhttps-kotlin + + + + 1.8 + 3.14.7 + 1.2.67 + 4.12 + UTF-8 + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + Troy + zhou.xu@ejlchina.com + ejlchina + http://www.ejlchina.com + + + + + scm:git://gitee.com/ejlchina-zhxu/okhttps.git + scm:http://gitee.com/ejlchina-zhxu/okhttps + https://gitee.com/ejlchina-zhxu/okhttps + v1.0.5 + + + + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + + + junit + junit + ${junit.version} + test + + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + ${sonatypeOssDistMgmtSnapshotsUrl} + + + sonatype-nexus-staging + Nexus Release Repository + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + okhttps + + + + org.apache.maven.plugins + maven-release-plugin + 2.1 + + forked-path + false + -Psonatype-oss-release + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java-version} + ${java-version} + ${project.build.sourceEncoding} + true + + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.7 + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.1 + + + sign-artifacts + verify + + sign + + + + + + + + + https://gitee.com/ejlchina-zhxu/okhttps + 比 Retrofit 更好用的网络框架� OkHttp3 轻��装 ,开箱�用�Java领域��端处� Http问题的新选择。 + + 江�一键�信�科技有�公� + http://www.ejlchina.com/ + + + https://gitee.com/ejlchina-zhxu/okhttps/issues + + \ No newline at end of file From 011d970987394585f1dfc1e6409bdaadf914f3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 16:41:27 +0800 Subject: [PATCH 203/924] =?UTF-8?q?HttpTask=20=E6=96=B0=E5=A2=9E=20=20noPr?= =?UTF-8?q?eprocess()=20=E5=92=8C=20noSerialPreprocess()=20=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=8C=E7=94=A8=E4=BA=8E=E8=B7=B3=E8=BF=87=20?= =?UTF-8?q?=E9=A2=84=E5=A4=84=E7=90=86=E5=99=A8=20=E5=92=8C=20=E4=B8=B2?= =?UTF-8?q?=E8=A1=8C=E9=A2=84=E5=A4=84=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 25 +++++++++- .../okhttps/internal/AsyncHttpTask.java | 2 +- .../ejlchina/okhttps/internal/HttpClient.java | 50 +++++++++++++------ .../okhttps/internal/SyncHttpTask.java | 2 +- .../okhttps/internal/WebSocketTask.java | 9 ++-- 5 files changed, 65 insertions(+), 23 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 04824ed9..2d7b8b17 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -63,7 +63,10 @@ public abstract class HttpTask> implements Cancelable { private TagTask tagTask; private Cancelable canceler; - + protected boolean noPreprocess = false; + protected boolean noSerialPreprocess = false; + + public HttpTask(HttpClient httpClient, String url) { this.httpClient = httpClient; this.urlPath = url; @@ -124,6 +127,24 @@ public C nothrow() { return (C) this; } + /** + * 指定该请求��过任何预处�器 + * @return HttpTask 实例 + */ + public C noPreprocess() { + this.noPreprocess = true; + return (C) this; + } + + /** + * 指定该请求��过并行预处�器 + * @return HttpTask 实例 + */ + public C noSerialPreprocess() { + this.noSerialPreprocess = true; + return (C) this; + } + /** * 为请求任务添加标签 * v1.0.4 之�,若 set 多次,标签将连接在一起 @@ -161,7 +182,7 @@ public C bind(Object object) { return (C) this; } - /** + /** * 添加请求头 * @param name 请求头� * @param value 请求头值 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 7f894429..2fb42b88 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -120,7 +120,7 @@ public HttpCall request(String method) { call.setCall(executeCall(prepareCall(method))); } } - }); + }, noPreprocess, noSerialPreprocess); return call; } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 160d795a..511bca79 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -178,14 +178,27 @@ public TaskExecutor getExecutor() { return executor; } - public void preprocess(HttpTask> httpTask, Runnable request) { - if (preprocessors.length > 0) { - RealPreChain chain = new RealPreChain(preprocessors, - httpTask, request); - preprocessors[0].doProcess(chain); - } else { - request.run(); - } + public void preprocess(HttpTask> httpTask, Runnable request, + boolean noPreprocess, boolean noSerialPreprocess) { + if (preprocessors.length == 0 || noPreprocess) { + request.run(); + return; + } + int index = 0; + if (noSerialPreprocess) { + while (index < preprocessors.length + && preprocessors[index] instanceof SerialPreprocessor) { + index++; + } + } + if (index < preprocessors.length) { + RealPreChain chain = new RealPreChain(preprocessors, + httpTask, request, index + 1, + noSerialPreprocess); + preprocessors[index].doProcess(chain); + } else { + request.run(); + } } /** @@ -249,13 +262,15 @@ class RealPreChain implements Preprocessor.PreChain { private Runnable request; - public RealPreChain(Preprocessor[] preprocessors, - HttpTask httpTask, - Runnable request) { - this.index = 1; + private boolean noSerialPreprocess; + + public RealPreChain(Preprocessor[] preprocessors, HttpTask httpTask, Runnable request, + int index, boolean noSerialPreprocess) { + this.index = index; // index 大于等于 1 this.preprocessors = preprocessors; this.httpTask = httpTask; this.request = request; + this.noSerialPreprocess = noSerialPreprocess; } @Override @@ -270,12 +285,17 @@ public HTTP getHttp() { @Override public void proceed() { - if (index > 0) { - Preprocessor last = preprocessors[index - 1]; + if (noSerialPreprocess) { + while (index < preprocessors.length + && preprocessors[index] instanceof SerialPreprocessor) { + index++; + } + } else { + Preprocessor last = preprocessors[index - 1]; if (last instanceof SerialPreprocessor) { ((SerialPreprocessor) last).afterProcess(); } - } + } if (index < preprocessors.length) { preprocessors[index++].doProcess(this); } else { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index 666c0a90..ba931fce 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -86,7 +86,7 @@ public HttpResult request(String method) { } finally { latch.countDown(); } - }); + }, noPreprocess, noSerialPreprocess); boolean timeout = false; if (result.getState() == null) { timeout = !timeoutAwait(latch); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index c0897e38..e083716e 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -1,6 +1,5 @@ package com.ejlchina.okhttps.internal; -import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -20,7 +19,7 @@ public class WebSocketTask extends HttpTask { private Listener onOnen; - private Listener onException; + private Listener onException; public WebSocketTask(HttpClient httpClient, String url) { @@ -41,7 +40,7 @@ public WebSocket listen() { socket.setWebSocket(httpClient.webSocket(request, listener)); } } - }); + }, noPreprocess, noSerialPreprocess); return socket; } @@ -85,7 +84,9 @@ public void onClosed(okhttp3.WebSocket webSocket, int code, String reason) { @Override public void onFailure(okhttp3.WebSocket webSocket, Throwable t, Response response) { if (onException != null) { -// onException.on(this.webSocket, t); + onException.on(this.webSocket, t); + } else if (!nothrow) { + throw new HttpException("WebSockt 异常", t); } } From 360098c16cac30b148e177fe8555989f6bfd581c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 16:45:22 +0800 Subject: [PATCH 204/924] V2.0.0 --- okhttps-fastjson/pom.xml | 2 +- okhttps-gson/pom.xml | 2 +- okhttps-jackson/pom.xml | 2 +- okhttps-kotlin/pom.xml | 2 +- okhttps/pom.xml | 2 +- pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/okhttps-fastjson/pom.xml b/okhttps-fastjson/pom.xml index bdf2ab35..330d0843 100644 --- a/okhttps-fastjson/pom.xml +++ b/okhttps-fastjson/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 1.0.5 + 2.0.0 diff --git a/okhttps-gson/pom.xml b/okhttps-gson/pom.xml index c595205b..31755f32 100644 --- a/okhttps-gson/pom.xml +++ b/okhttps-gson/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 1.0.5 + 2.0.0 diff --git a/okhttps-jackson/pom.xml b/okhttps-jackson/pom.xml index ad226219..da562191 100644 --- a/okhttps-jackson/pom.xml +++ b/okhttps-jackson/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 1.0.5 + 2.0.0 diff --git a/okhttps-kotlin/pom.xml b/okhttps-kotlin/pom.xml index acbaf2e6..75144398 100644 --- a/okhttps-kotlin/pom.xml +++ b/okhttps-kotlin/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 1.0.5 + 2.0.0 diff --git a/okhttps/pom.xml b/okhttps/pom.xml index c2cd72c2..93fbdada 100644 --- a/okhttps/pom.xml +++ b/okhttps/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 1.0.5 + 2.0.0 diff --git a/pom.xml b/pom.xml index d342656e..77da9d24 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.ejlchina okhttps-parent - 1.0.5 + 2.0.0 OkHttps pom From 3f248e84e835b73dba8881814efd92e5cba66c72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 17:31:54 +0800 Subject: [PATCH 205/924] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20JsonObj=20?= =?UTF-8?q?=E5=92=8C=20JsonArr=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/JsonArr.java | 93 +++++++++++++++ .../java/com/ejlchina/okhttps/JsonObj.java | 111 ++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java create mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java new file mode 100644 index 00000000..f297a2d5 --- /dev/null +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java @@ -0,0 +1,93 @@ +package com.ejlchina.okhttps; + +public interface JsonArr { + + /** + * @return JSON 的键值对数� + */ + int size(); + + /** + * @return 是�为空 + */ + boolean isEmpty(); + + /** + * @param index 元素下标 + * @return � JsonObj + */ + JsonObj getJsonOjb(int index); + + /** + * @param index 元素下标 + * @return � JsonArr + */ + JsonArr getJsonArr(int index); + + /** + * @param index 元素下标 + * @return Boolean 值 + */ + Boolean getBool(int index); + + /** + * @param index 元素下标 + * @return boolean 值 + */ + boolean getBoolVal(int index); + + /** + * @param index 元素下标 + * @return Integer 值 + */ + Integer getInt(int index); + + /** + * @param index 元素下标 + * @return int 值 + */ + int getIntVal(int index); + + /** + * @param index 元素下标 + * @return Short 值 + */ + Short getShort(int index); + + /** + * @param index 元素下标 + * @return short 值 + */ + short getShortVal(int index); + + /** + * @param index 元素下标 + * @return Float 值 + */ + Float getFloat(int index); + + /** + * @param index 元素下标 + * @return float 值 + */ + float getFloatVal(int index); + + /** + * @param index 元素下标 + * @return Double 值 + */ + Double getDouble(int index); + + /** + * @param index 元素下标 + * @return double 值 + */ + double getDoubleVal(int index); + + /** + * @param index 元素下标 + * @return String 值 + */ + String getString(int index); + +} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java new file mode 100644 index 00000000..609dabee --- /dev/null +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java @@ -0,0 +1,111 @@ +package com.ejlchina.okhttps; + +import java.util.Set; + +/** + * JSON 对象 + * @author 15735 + * + */ +public interface JsonObj { + + /** + * @return JSON 的键值对数� + */ + public int size(); + + /** + * @return 是�为空 + */ + boolean isEmpty(); + + /** + * @param key 键� + * @return � JsonObj + */ + JsonObj getJsonOjb(String key); + + /** + * @param key 键� + * @return � JsonArr + */ + JsonArr getJsonArr(String key); + + /** + * @param key 键� + * @return Boolean 值 + */ + Boolean getBool(String key); + + /** + * @param key 键� + * @return boolean 值 + */ + boolean getBoolVal(String key); + + /** + * @param key 键� + * @return Integer 值 + */ + Integer getInt(String key); + + /** + * @param key 键� + * @return int 值 + */ + int getIntVal(String key); + + /** + * @param key 键� + * @return Short 值 + */ + Short getShort(String key); + + /** + * @param key 键� + * @return short 值 + */ + short getShortVal(String key); + + /** + * @param key 键� + * @return Float 值 + */ + Float getFloat(String key); + + /** + * @param key 键� + * @return float 值 + */ + float getFloatVal(String key); + + /** + * @param key 键� + * @return Double 值 + */ + Double getDouble(String key); + + /** + * @param key 键� + * @return double 值 + */ + double getDoubleVal(String key); + + /** + * @param key 键� + * @return String 值 + */ + String getString(String key); + + /** + * @param key 键� + * @return 是�有该键 + */ + boolean has(String key); + + /** + * @return JSON 的键集� + */ + public Set keySet(); + +} From c54019aa42ffdb52733cacd8854f0c971323395c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 18:39:23 +0800 Subject: [PATCH 206/924] =?UTF-8?q?okhttps=20=E4=B8=8E=20fastjson=20?= =?UTF-8?q?=E8=A7=A3=E8=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps-fastjson/pom.xml | 11 ++++ okhttps-gson/pom.xml | 10 +++ .../com/ejlchina/okhttps/gson/TestCase.java | 12 ++++ okhttps-jackson/pom.xml | 10 +++ okhttps/pom.xml | 6 -- .../java/com/ejlchina/okhttps/HttpResult.java | 6 +- .../java/com/ejlchina/okhttps/HttpTask.java | 12 ++-- .../com/ejlchina/okhttps/JsonFactory.java | 57 +++++++++++++++++ .../java/com/ejlchina/okhttps/WebSocket.java | 8 +++ .../ejlchina/okhttps/internal/HttpClient.java | 20 +++++- .../ejlchina/okhttps/internal/ResultBody.java | 31 ++++++--- .../okhttps/internal/TaskExecutor.java | 24 ++++--- .../okhttps/internal/WebSocketTask.java | 24 ++++--- .../java/com/ejlchina/test/CacheTests.java | 4 +- .../java/com/ejlchina/test/SimpleTests.java | 63 ++++++++----------- 15 files changed, 220 insertions(+), 78 deletions(-) create mode 100644 okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java create mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java diff --git a/okhttps-fastjson/pom.xml b/okhttps-fastjson/pom.xml index 330d0843..e69a9497 100644 --- a/okhttps-fastjson/pom.xml +++ b/okhttps-fastjson/pom.xml @@ -11,6 +11,17 @@ 2.0.0 + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + okhttps-fastjson diff --git a/okhttps-gson/pom.xml b/okhttps-gson/pom.xml index 31755f32..f78670ea 100644 --- a/okhttps-gson/pom.xml +++ b/okhttps-gson/pom.xml @@ -11,6 +11,16 @@ 2.0.0 + + + + com.google.code.gson + gson + 2.8.6 + + + + okhttps-gson diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java new file mode 100644 index 00000000..9611f79c --- /dev/null +++ b/okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java @@ -0,0 +1,12 @@ +package com.ejlchina.okhttps.gson; + +import org.junit.Test; + +public class TestCase { + + @Test + public void test() { + + } + +} diff --git a/okhttps-jackson/pom.xml b/okhttps-jackson/pom.xml index da562191..e149b9a5 100644 --- a/okhttps-jackson/pom.xml +++ b/okhttps-jackson/pom.xml @@ -11,6 +11,16 @@ 2.0.0 + + + + com.fasterxml.jackson.core + jackson-core + 2.11.0 + + + + okhttps-jackson diff --git a/okhttps/pom.xml b/okhttps/pom.xml index 93fbdada..ebffcd88 100644 --- a/okhttps/pom.xml +++ b/okhttps/pom.xml @@ -13,12 +13,6 @@ - - com.alibaba - fastjson - ${fastjson.version} - - com.squareup.okhttp3 mockwebserver diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java index c3d31928..6a1ae528 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -6,8 +6,6 @@ import java.io.Reader; import java.util.List; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; import com.ejlchina.okhttps.internal.RealHttpResult; import com.ejlchina.okhttps.internal.TaskExecutor; @@ -153,13 +151,13 @@ public interface Body { * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 * @return 报文体转Json对象 */ - JSONObject toJsonObject(); + JsonObj toJsonObj(); /** * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 * @return 报文体转Json数组 */ - JSONArray toJsonArray(); + JsonArr toJsonArr(); /** * �一个 Body 对象的 toXXX 类方法��使用一个并且�能调用一次 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 2d7b8b17..68b78b1b 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -13,7 +13,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import com.alibaba.fastjson.JSON; import com.ejlchina.okhttps.HttpResult.State; import com.ejlchina.okhttps.internal.HttpClient; import com.ejlchina.okhttps.internal.HttpClient.TagTask; @@ -420,9 +419,13 @@ public C setRequestJson(Object json, String dateFormat) { if (json instanceof String) { requestJson = json.toString(); } else if (dateFormat != null) { - requestJson = JSON.toJSONStringWithDateFormat(json, dateFormat); + requestJson = httpClient.getExecutor() + .getJsonFactoryNotNull() + .toJsonStr(json, dateFormat); } else { - requestJson = JSON.toJSONString(json); + requestJson = httpClient.getExecutor() + .getJsonFactoryNotNull() + .toJsonStr(json); } } return (C) this; @@ -653,7 +656,8 @@ protected State toState(IOException e, boolean sync) { private RequestBody buildRequestBody() { if (jsonParams != null) { - requestJson = JSON.toJSONString(jsonParams); + requestJson = httpClient.getExecutor().getJsonFactoryNotNull() + .toJsonStr(jsonParams); } if (files != null) { MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java new file mode 100644 index 00000000..b9c4e3e2 --- /dev/null +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java @@ -0,0 +1,57 @@ +package com.ejlchina.okhttps; + +import java.util.List; + + +public interface JsonFactory { + + + /** + * 将 json 文本解�为 JsonObj + * @param json 文本 + * @return JsonObj + */ + JsonObj newJsonObj(String json); + + /** + * 将 json 文本解�为 JsonArr + * @param json 文本 + * @return JsonArr + */ + JsonArr newJsonArr(String json); + + /** + * 将 Java 对象�列化为 Json 字符串 + * @param bean Java Bean + * @return Json 字符串 + */ + String toJsonStr(Object bean); + + /** + * 将 Java 对象�列化为 Json 字符串 + * @param bean Java Bean + * @param dateFormat 日期类的处�格� + * @return Json 字符串 + */ + String toJsonStr(Object bean, String dateFormat); + + /** + * 将 json 文本 解�为 Java Bean + * @param 目标泛型 + * @param type 目标类型 + * @param json 文本 + * @return Java Bean + */ + T jsonToBean(Class type, String json); + + /** + * 将 json 文本 解�为 Java List + * @param 目标泛型 + * @param type 目标类型 + * @param json 文本 + * @return Java List + */ + List jsonToList(Class type, String json); + + +} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java index 015d46cb..f8cb6e39 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java @@ -34,6 +34,14 @@ public interface Listener { */ public boolean send(Object bean); + /** + * 以JSON文本格���对象消� + * @param bean 待��的对象 + * @param dateFormat 日期类型字段的处�格� + * @return 如果连接已断开 返回 false + */ + public boolean send(Object bean, String dateFormat); + /** * ��字节� * @param data 待��的数� diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 511bca79..2174e816 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -33,7 +33,7 @@ private HttpClient(Builder builder) { this.executor = new TaskExecutor(client.dispatcher().executorService(), builder.mainExecutor, builder.downloadListener, builder.responseListener, builder.exceptionListener, - builder.completeListener); + builder.completeListener, builder.jsonFactory); this.preprocessors = builder.preprocessors.toArray(new Preprocessor[0]); this.tagTasks = new LinkedList<>(); } @@ -349,6 +349,8 @@ public static class Builder { private TaskListener completeListener; + private JsonFactory jsonFactory; + public Builder() { mediaTypes = new HashMap<>(); mediaTypes.put("*", "application/octet-stream"); @@ -374,6 +376,11 @@ private Builder(HttpClient hc) { this.mediaTypes = hc.mediaTypes; this.preprocessors = new ArrayList<>(); Collections.addAll(this.preprocessors, hc.preprocessors); + this.downloadListener = hc.executor.downloadListener; + this.responseListener = hc.executor.responseListener; + this.exceptionListener = hc.executor.exceptionListener; + this.completeListener = hc.executor.completeListener; + this.jsonFactory = hc.executor.jsonFactory; } /** @@ -498,6 +505,17 @@ public Builder downloadListener(DownListener listener) { return this; } + /** + * 设置 JSON 工厂 + * @param jsonFactory JSON 工厂 + * @return Builder + */ + public Builder jsonFactory(JsonFactory jsonFactory) { + this.jsonFactory = jsonFactory; + return this; + } + + public HTTP build() { if (configurator != null || client == null) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java index 1123668e..03d51e3c 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java @@ -14,14 +14,13 @@ import java.nio.charset.Charset; import java.util.List; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; import com.ejlchina.okhttps.Download; +import com.ejlchina.okhttps.HttpResult.Body; import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.JsonArr; +import com.ejlchina.okhttps.JsonObj; import com.ejlchina.okhttps.OnCallback; import com.ejlchina.okhttps.Process; -import com.ejlchina.okhttps.HttpResult.Body; import okhttp3.MediaType; import okhttp3.Response; @@ -149,23 +148,35 @@ public String toString() { } @Override - public JSONObject toJsonObject() { - return JSON.parseObject(toString()); + public JsonObj toJsonObj() { + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); + } + return taskExecutor.getJsonFactoryNotNull().newJsonObj(toString()); } @Override - public JSONArray toJsonArray() { - return JSON.parseArray(toString()); + public JsonArr toJsonArr() { + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); + } + return taskExecutor.getJsonFactoryNotNull().newJsonArr(toString()); } @Override public T toBean(Class type) { - return JSON.parseObject(toString(), type); + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); + } + return taskExecutor.getJsonFactoryNotNull().jsonToBean(type, toString()); } @Override public List toList(Class type) { - return JSON.parseArray(toString(), type); + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); + } + return taskExecutor.getJsonFactoryNotNull().jsonToList(type, toString()); } @Override diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 42d2e19e..1df24b71 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -10,28 +10,31 @@ import com.ejlchina.okhttps.Download; import com.ejlchina.okhttps.HttpResult; import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.JsonFactory; import com.ejlchina.okhttps.OnCallback; import com.ejlchina.okhttps.TaskListener; import com.ejlchina.okhttps.HttpResult.State; public class TaskExecutor { - private Executor ioExecutor; - private Executor mainExecutor; - private DownListener downloadListener; - private TaskListener responseListener; - private TaskListener exceptionListener; - private TaskListener completeListener; + Executor ioExecutor; + Executor mainExecutor; + DownListener downloadListener; + TaskListener responseListener; + TaskListener exceptionListener; + TaskListener completeListener; + JsonFactory jsonFactory; public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, TaskListener responseListener, TaskListener exceptionListener, - TaskListener completeListener) { + TaskListener completeListener, JsonFactory jsonFactory) { this.ioExecutor = ioExecutor; this.mainExecutor = mainExecutor; this.downloadListener = downloadListener; this.responseListener = responseListener; this.exceptionListener = exceptionListener; this.completeListener = completeListener; + this.jsonFactory = jsonFactory; } public Executor getExecutor(boolean onIoThread) { @@ -96,6 +99,13 @@ public void executeOnComplete(HttpTask task, OnCallback onComplete, St } } + public JsonFactory getJsonFactoryNotNull() { + if (jsonFactory != null) { + return jsonFactory; + } + throw new IllegalStateException("没有设置 JsonFactory,��� Json �作�"); + } + /** * 关闭线程池 * @since OkHttps V1.0.2 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index e083716e..9a3726be 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.List; -import com.alibaba.fastjson.JSON; import com.ejlchina.okhttps.HttpResult; import com.ejlchina.okhttps.HttpTask; import com.ejlchina.okhttps.WebSocket; @@ -28,7 +27,7 @@ public WebSocketTask(HttpClient httpClient, String url) { public WebSocket listen() { - WebSocketImpl socket = new WebSocketImpl(); + WebSocketImpl socket = new WebSocketImpl(httpClient.executor); registeTagTask(socket); httpClient.preprocess(this, () -> { synchronized (socket) { @@ -101,6 +100,12 @@ static class WebSocketImpl implements WebSocket { List queues = new ArrayList<>(); + TaskExecutor taskExecutor; + + public WebSocketImpl(TaskExecutor taskExecutor) { + this.taskExecutor = taskExecutor; + } + @Override public synchronized boolean cancel() { if (webSocket != null) { @@ -147,13 +152,14 @@ public boolean send(ByteString bytes) { @Override public boolean send(Object bean) { - if (webSocket != null) { - return send(webSocket, bean); - } - queueMsgToSend(bean); - return true; + return send(taskExecutor.getJsonFactoryNotNull().toJsonStr(bean)); } + @Override + public boolean send(Object bean, String dateFormat) { + return send(taskExecutor.getJsonFactoryNotNull().toJsonStr(bean, dateFormat)); + } + @Override public boolean send(byte[] data) { if (webSocket != null) { @@ -163,6 +169,8 @@ public boolean send(byte[] data) { return true; } + + void queueMsgToSend(Object msg) { if (msg == null) { return; @@ -201,7 +209,7 @@ boolean send(okhttp3.WebSocket webSocket, Object msg) { if (msg instanceof byte[]) { return webSocket.send(ByteString.of((byte[]) msg)); } - return webSocket.send(JSON.toJSONString(msg)); + return webSocket.send(taskExecutor.getJsonFactoryNotNull().toJsonStr(msg)); } } diff --git a/okhttps/src/test/java/com/ejlchina/test/CacheTests.java b/okhttps/src/test/java/com/ejlchina/test/CacheTests.java index baa95483..962eebb8 100644 --- a/okhttps/src/test/java/com/ejlchina/test/CacheTests.java +++ b/okhttps/src/test/java/com/ejlchina/test/CacheTests.java @@ -16,12 +16,12 @@ public void testCache() { .cache(); println("result = " + body.toString()); - println("result = " + body.toJsonArray()); + println("result = " + body.toJsonArr()); body.close(); println("result = " + body.toString()); - println("result = " + body.toJsonArray()); + println("result = " + body.toJsonArr()); } } diff --git a/okhttps/src/test/java/com/ejlchina/test/SimpleTests.java b/okhttps/src/test/java/com/ejlchina/test/SimpleTests.java index 4b0ef9ef..0f54880a 100644 --- a/okhttps/src/test/java/com/ejlchina/test/SimpleTests.java +++ b/okhttps/src/test/java/com/ejlchina/test/SimpleTests.java @@ -1,16 +1,7 @@ package com.ejlchina.test; -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.List; - -import org.junit.Test; - -import com.alibaba.fastjson.JSON; import com.ejlchina.okhttps.HTTP; -import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; public class SimpleTests extends BaseTest { @@ -26,38 +17,38 @@ public class SimpleTests extends BaseTest { * �步请求示例 * �步请求直接得到结果,无需设置回调 */ - @Test - public void testSyncToBean() { - User u1 = new User(1, "Jack"); - server.enqueue(new MockResponse().setBody(JSON.toJSONString(u1))); - - User user = http.sync("/users") // http://localhost:8080/users - .get() // GET请求 - .getBody() // 获��应报文体 - .toBean(User.class); // 得到目标数� - - assertEquals(u1, user); - } +// @Test +// public void testSyncToBean() { +// User u1 = new User(1, "Jack"); +// server.enqueue(new MockResponse().setBody(JSON.toJSONString(u1))); +// +// User user = http.sync("/users") // http://localhost:8080/users +// .get() // GET请求 +// .getBody() // 获��应报文体 +// .toBean(User.class); // 得到目标数� +// +// assertEquals(u1, user); +// } /** * �步请求示例 * �步请求直接得到结果,无需设置回调 */ - @Test - public void testSyncToList() { - User u1 = new User(1, "Jack"); - User u2 = new User(2, "Tom"); - List list = Arrays.asList(u1, u2); - server.enqueue(new MockResponse().setBody(JSON.toJSONString(list))); - - List users = http.sync("/users") // http://localhost:8080/users - .get() // GET请求 - .getBody() // 获��应报文体 - .toList(User.class); // 得到目标数� - - assertEquals(u1, users.get(0)); - assertEquals(u2, users.get(1)); - } +// @Test +// public void testSyncToList() { +// User u1 = new User(1, "Jack"); +// User u2 = new User(2, "Tom"); +// List list = Arrays.asList(u1, u2); +// server.enqueue(new MockResponse().setBody(JSON.toJSONString(list))); +// +// List users = http.sync("/users") // http://localhost:8080/users +// .get() // GET请求 +// .getBody() // 获��应报文体 +// .toList(User.class); // 得到目标数� +// +// assertEquals(u1, users.get(0)); +// assertEquals(u2, users.get(1)); +// } // // /** // * 异步请求示例 From 00738199dec55f5bef79b2895f0e90878a87b8a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 20:15:11 +0800 Subject: [PATCH 207/924] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps-fastjson/pom.xml | 9 ++++++--- okhttps-gson/pom.xml | 9 ++++++--- okhttps-jackson/pom.xml | 9 ++++++--- okhttps-kotlin/pom.xml | 10 +++++++++- pom.xml | 3 ++- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/okhttps-fastjson/pom.xml b/okhttps-fastjson/pom.xml index e69a9497..a68e2685 100644 --- a/okhttps-fastjson/pom.xml +++ b/okhttps-fastjson/pom.xml @@ -8,17 +8,20 @@ com.ejlchina okhttps-parent - 2.0.0 + ${okhttps.version} - + + com.ejlchina + okhttps + ${okhttps.version} + com.alibaba fastjson ${fastjson.version} - diff --git a/okhttps-gson/pom.xml b/okhttps-gson/pom.xml index f78670ea..8add3318 100644 --- a/okhttps-gson/pom.xml +++ b/okhttps-gson/pom.xml @@ -8,17 +8,20 @@ com.ejlchina okhttps-parent - 2.0.0 + ${okhttps.version} - + + com.ejlchina + okhttps + ${okhttps.version} + com.google.code.gson gson 2.8.6 - diff --git a/okhttps-jackson/pom.xml b/okhttps-jackson/pom.xml index e149b9a5..f0129540 100644 --- a/okhttps-jackson/pom.xml +++ b/okhttps-jackson/pom.xml @@ -8,17 +8,20 @@ com.ejlchina okhttps-parent - 2.0.0 + ${okhttps.version} - + + com.ejlchina + okhttps + ${okhttps.version} + com.fasterxml.jackson.core jackson-core 2.11.0 - diff --git a/okhttps-kotlin/pom.xml b/okhttps-kotlin/pom.xml index 75144398..48cdb7ed 100644 --- a/okhttps-kotlin/pom.xml +++ b/okhttps-kotlin/pom.xml @@ -8,9 +8,17 @@ com.ejlchina okhttps-parent - 2.0.0 + ${okhttps.version} + + + com.ejlchina + okhttps + ${okhttps.version} + + + okhttps-kotlin diff --git a/pom.xml b/pom.xml index 77da9d24..7b815fe3 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.ejlchina okhttps-parent - 2.0.0 + ${okhttps.version} OkHttps pom @@ -17,6 +17,7 @@ + 2.0.0 1.8 3.14.7 1.2.67 From a3120aea77c809b14a768c9bf37155b177c41ddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 20:48:44 +0800 Subject: [PATCH 208/924] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20okhttps-fastjson?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ejlchina/okhttps/FastJsonArr.java | 97 +++++++++++++++ .../com/ejlchina/okhttps/FastJsonObj.java | 111 ++++++++++++++++++ .../com/ejlchina/okhttps/FastjsonFactory.java | 39 ++++++ 3 files changed, 247 insertions(+) create mode 100644 okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java create mode 100644 okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java create mode 100644 okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonFactory.java diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java new file mode 100644 index 00000000..68218a13 --- /dev/null +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java @@ -0,0 +1,97 @@ +package com.ejlchina.okhttps; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +public class FastJsonArr implements JsonArr { + + private JSONArray json; + + public FastJsonArr(JSONArray json) { + this.json = json; + } + + @Override + public int size() { + return json.size(); + } + + @Override + public boolean isEmpty() { + return json.isEmpty(); + } + + @Override + public JsonObj getJsonOjb(int index) { + JSONObject subJson = json.getJSONObject(index); + if (subJson != null) { + return new FastJsonObj(subJson); + } + return null; + } + + @Override + public JsonArr getJsonArr(int index) { + JSONArray subJson = json.getJSONArray(index); + if (subJson != null) { + return new FastJsonArr(subJson); + } + return null; + } + + @Override + public Boolean getBool(int index) { + return json.getBoolean(index); + } + + @Override + public boolean getBoolVal(int index) { + return json.getBooleanValue(index); + } + + @Override + public Integer getInt(int index) { + return json.getInteger(index); + } + + @Override + public int getIntVal(int index) { + return json.getIntValue(index); + } + + @Override + public Short getShort(int index) { + return json.getShort(index); + } + + @Override + public short getShortVal(int index) { + return json.getShortValue(index); + } + + @Override + public Float getFloat(int index) { + return json.getFloat(index); + } + + @Override + public float getFloatVal(int index) { + return json.getFloatValue(index); + } + + @Override + public Double getDouble(int index) { + return json.getDouble(index); + } + + @Override + public double getDoubleVal(int index) { + return json.getDoubleValue(index); + } + + @Override + public String getString(int index) { + return json.getString(index); + } + +} diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java new file mode 100644 index 00000000..217147b6 --- /dev/null +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java @@ -0,0 +1,111 @@ +package com.ejlchina.okhttps; + +import java.util.Set; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +public class FastJsonObj implements JsonObj { + + + private JSONObject json; + + + public FastJsonObj(JSONObject json) { + this.json = json; + } + + @Override + public int size() { + return json.size(); + } + + @Override + public boolean isEmpty() { + return json.isEmpty(); + } + + @Override + public JsonObj getJsonOjb(String key) { + JSONObject subJson = json.getJSONObject(key); + if (subJson != null) { + return new FastJsonObj(subJson); + } + return null; + } + + @Override + public JsonArr getJsonArr(String key) { + JSONArray subJson = json.getJSONArray(key); + if (subJson != null) { + return new FastJsonArr(subJson); + } + return null; + } + + @Override + public Boolean getBool(String key) { + return json.getBoolean(key); + } + + @Override + public boolean getBoolVal(String key) { + return json.getBooleanValue(key); + } + + @Override + public Integer getInt(String key) { + return json.getInteger(key); + } + + @Override + public int getIntVal(String key) { + return json.getIntValue(key); + } + + @Override + public Short getShort(String key) { + return json.getShort(key); + } + + @Override + public short getShortVal(String key) { + return json.getShortValue(key); + } + + @Override + public Float getFloat(String key) { + return json.getFloat(key); + } + + @Override + public float getFloatVal(String key) { + return json.getFloatValue(key); + } + + @Override + public Double getDouble(String key) { + return json.getDouble(key); + } + + @Override + public double getDoubleVal(String key) { + return json.getDoubleValue(key); + } + + @Override + public String getString(String key) { + return json.getString(key); + } + + @Override + public boolean has(String key) { + return json.containsKey(key); + } + + @Override + public Set keySet() { + return json.keySet(); + } + +} diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonFactory.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonFactory.java new file mode 100644 index 00000000..a725fc4e --- /dev/null +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonFactory.java @@ -0,0 +1,39 @@ +package com.ejlchina.okhttps; + +import java.util.List; + +import com.alibaba.fastjson.JSON; + +public class FastjsonFactory implements JsonFactory { + + @Override + public JsonObj newJsonObj(String json) { + return new FastJsonObj(JSON.parseObject(json)); + } + + @Override + public JsonArr newJsonArr(String json) { + return new FastJsonArr(JSON.parseArray(json)); + } + + @Override + public String toJsonStr(Object bean) { + return JSON.toJSONString(bean); + } + + @Override + public String toJsonStr(Object bean, String dateFormat) { + return JSON.toJSONStringWithDateFormat(bean, dateFormat); + } + + @Override + public T jsonToBean(Class type, String json) { + return JSON.parseObject(json, type); + } + + @Override + public List jsonToList(Class type, String json) { + return JSON.parseArray(json, type); + } + +} From 75866b255443c0bc8ae20c54f65f63ae76d7ac11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 20:53:59 +0800 Subject: [PATCH 209/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/{FastjsonFactory.java => FastJsonFactory.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename okhttps-fastjson/src/main/java/com/ejlchina/okhttps/{FastjsonFactory.java => FastJsonFactory.java} (93%) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonFactory.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java similarity index 93% rename from okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonFactory.java rename to okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java index a725fc4e..925be7b0 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonFactory.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java @@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSON; -public class FastjsonFactory implements JsonFactory { +public class FastJsonFactory implements JsonFactory { @Override public JsonObj newJsonObj(String json) { From 41f962bd59dd1128fe1bb15b7f3f35bfcc92d566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Fri, 8 May 2020 22:30:18 +0800 Subject: [PATCH 210/924] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20okhttps-fastjson?= =?UTF-8?q?=20=E4=B8=8E=20okhttps-gson?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ejlchina/okhttps/FastJsonArr.java | 14 ++ .../com/ejlchina/okhttps/FastJsonFactory.java | 20 +- .../com/ejlchina/okhttps/FastJsonObj.java | 14 +- .../java/com/ejlchina/okhttps/GsonArr.java | 162 ++++++++++++++++ .../com/ejlchina/okhttps/GsonFactory.java | 83 +++++++++ .../java/com/ejlchina/okhttps/GsonObj.java | 173 ++++++++++++++++++ .../com/ejlchina/okhttps/gson/TestCase.java | 121 ++++++++++++ .../java/com/ejlchina/okhttps/JsonArr.java | 15 ++ .../java/com/ejlchina/okhttps/JsonObj.java | 14 ++ 9 files changed, 610 insertions(+), 6 deletions(-) create mode 100644 okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java create mode 100644 okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java create mode 100644 okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java index 68218a13..81c178bb 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java @@ -1,5 +1,8 @@ package com.ejlchina.okhttps; +import java.math.BigDecimal; +import java.math.BigInteger; + import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -94,4 +97,15 @@ public String getString(int index) { return json.getString(index); } + @Override + public BigDecimal getBigDecimal(int index) { + // TODO Auto-generated method stub + return json.getBigDecimal(index); + } + + @Override + public BigInteger getBigInteger(int index) { + return json.getBigInteger(index); + } + } diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java index 925be7b0..26fd8b4f 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java @@ -8,12 +8,18 @@ public class FastJsonFactory implements JsonFactory { @Override public JsonObj newJsonObj(String json) { - return new FastJsonObj(JSON.parseObject(json)); + if (json != null) { + return new FastJsonObj(JSON.parseObject(json)); + } + return null; } @Override public JsonArr newJsonArr(String json) { - return new FastJsonArr(JSON.parseArray(json)); + if (json != null) { + return new FastJsonArr(JSON.parseArray(json)); + } + return null; } @Override @@ -28,12 +34,18 @@ public String toJsonStr(Object bean, String dateFormat) { @Override public T jsonToBean(Class type, String json) { - return JSON.parseObject(json, type); + if (json != null) { + return JSON.parseObject(json, type); + } + return null; } @Override public List jsonToList(Class type, String json) { - return JSON.parseArray(json, type); + if (json != null) { + return JSON.parseArray(json, type); + } + return null; } } diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java index 217147b6..2eb401b9 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java @@ -1,5 +1,7 @@ package com.ejlchina.okhttps; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Set; import com.alibaba.fastjson.JSONArray; @@ -7,10 +9,8 @@ public class FastJsonObj implements JsonObj { - private JSONObject json; - public FastJsonObj(JSONObject json) { this.json = json; } @@ -98,6 +98,16 @@ public String getString(String key) { return json.getString(key); } + @Override + public BigDecimal getBigDecimal(String key) { + return json.getBigDecimal(key); + } + + @Override + public BigInteger getBigInteger(String key) { + return json.getBigInteger(key); + } + @Override public boolean has(String key) { return json.containsKey(key); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java new file mode 100644 index 00000000..8d77e4bb --- /dev/null +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java @@ -0,0 +1,162 @@ +package com.ejlchina.okhttps; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; + +public class GsonArr implements JsonArr { + + private JsonArray json; + + public GsonArr(JsonArray json) { + this.json = json; + } + + @Override + public int size() { + return json.size(); + } + + @Override + public boolean isEmpty() { + return json.size() == 0; + } + + @Override + public JsonObj getJsonOjb(int index) { + JsonElement subJson = json.get(index); + if (subJson != null) { + return new GsonObj(subJson.getAsJsonObject()); + } + return null; + } + + @Override + public JsonArr getJsonArr(int index) { + JsonElement subJson = json.get(index); + if (subJson != null) { + return new GsonArr(subJson.getAsJsonArray()); + } + return null; + } + + @Override + public Boolean getBool(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsBoolean(); + } + return null; + } + + @Override + public boolean getBoolVal(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsBoolean(); + } + return false; + } + + @Override + public Integer getInt(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsInt(); + } + return null; + } + + @Override + public int getIntVal(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsInt(); + } + return 0; + } + + @Override + public Short getShort(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsShort(); + } + return null; + } + + @Override + public short getShortVal(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsShort(); + } + return 0; + } + + @Override + public Float getFloat(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsFloat(); + } + return null; + } + + @Override + public float getFloatVal(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsFloat(); + } + return 0; + } + + @Override + public Double getDouble(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsDouble(); + } + return null; + } + + @Override + public double getDoubleVal(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsDouble(); + } + return 0; + } + + @Override + public String getString(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsString(); + } + return null; + } + + @Override + public BigDecimal getBigDecimal(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsBigDecimal(); + } + return null; + } + + @Override + public BigInteger getBigInteger(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsBigInteger(); + } + return null; + } + +} diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java new file mode 100644 index 00000000..5a581534 --- /dev/null +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java @@ -0,0 +1,83 @@ +package com.ejlchina.okhttps; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; + +public class GsonFactory implements JsonFactory { + + private final Gson gson; + + public GsonFactory() { + this(new Gson()); + } + + public GsonFactory(Gson gson) { + this.gson = gson; + } + + @Override + public JsonObj newJsonObj(String json) { + if (json != null) { + return new GsonObj(gson.fromJson(json, JsonObject.class)); + } + return null; + } + + @Override + public JsonArr newJsonArr(String json) { + if (json != null) { + return new GsonArr(gson.fromJson(json, JsonArray.class)); + } + return null; + } + + @Override + public String toJsonStr(Object bean) { + return gson.toJson(bean); + } + + @Override + public String toJsonStr(Object bean, String dateFormat) { + return gson.newBuilder().setDateFormat(dateFormat).create().toJson(bean); + } + + @Override + public T jsonToBean(Class type, String json) { + if (json != null) { + return gson.fromJson(json, type); + } + return null; + } + + @Override + public List jsonToList(Class type, String json) { + if (json != null) { + T[] beans = gson.fromJson(json, TypeToken.getArray(type).getType()); + List list = new ArrayList<>(); + Collections.addAll(list, beans); + return list; + } + return null; + } + +} + + + + + + + + + + + + + + diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java new file mode 100644 index 00000000..744c6aa5 --- /dev/null +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java @@ -0,0 +1,173 @@ +package com.ejlchina.okhttps; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Set; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class GsonObj implements JsonObj { + + private JsonObject json; + + public GsonObj(JsonObject json) { + this.json = json; + } + + @Override + public int size() { + return json.size(); + } + + @Override + public boolean isEmpty() { + return json.size() == 0; + } + + @Override + public JsonObj getJsonOjb(String key) { + JsonElement subJson = json.get(key); + if (subJson != null) { + return new GsonObj(subJson.getAsJsonObject()); + } + return null; + } + + @Override + public JsonArr getJsonArr(String key) { + JsonElement subJson = json.get(key); + if (subJson != null) { + return new GsonArr(subJson.getAsJsonArray()); + } + return null; + } + + @Override + public Boolean getBool(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsBoolean(); + } + return null; + } + + @Override + public boolean getBoolVal(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsBoolean(); + } + return false; + } + + @Override + public Integer getInt(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsInt(); + } + return null; + } + + @Override + public int getIntVal(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsInt(); + } + return 0; + } + + @Override + public Short getShort(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsShort(); + } + return null; + } + + @Override + public short getShortVal(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsShort(); + } + return 0; + } + + @Override + public Float getFloat(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsFloat(); + } + return null; + } + + @Override + public float getFloatVal(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsFloat(); + } + return 0; + } + + @Override + public Double getDouble(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsDouble(); + } + return null; + } + + @Override + public double getDoubleVal(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsDouble(); + } + return 0; + } + + @Override + public String getString(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsString(); + } + return null; + } + + @Override + public BigDecimal getBigDecimal(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsBigDecimal(); + } + return null; + } + + @Override + public BigInteger getBigInteger(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsBigInteger(); + } + return null; + } + + @Override + public boolean has(String key) { + return json.has(key); + } + + @Override + public Set keySet() { + return json.keySet(); + } + +} diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java index 9611f79c..beb3d645 100644 --- a/okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java +++ b/okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java @@ -1,12 +1,133 @@ package com.ejlchina.okhttps.gson; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + import org.junit.Test; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; + public class TestCase { + + Gson gson = new Gson(); + @Test public void test() { + + User u1 = new User(1, "Tom"); + User u2 = new User(2, "Jack"); + List list = new ArrayList<>(); + list.add(u1); + list.add(u2); + + String json = gson.toJson(list); + + System.out.println("json = " + json); + +// User[] users = gson.fromJson(json, TypeToken.getArray(User.class).getType()); + + List users = jsonToList(User.class, json); + + System.out.println(users.get(0)); + System.out.println(users.get(0)); + } + + @Test + public void test2() { + User u1 = new User(1, "Tom"); + System.out.println(toJsonStr(u1, "yyyy-MM-dd HH:mm:ss")); + } + + @Test + public void test3() { + User u1 = new User(1, "Tom"); + String json = gson.toJson(u1); + System.out.println(json); + + JsonObject jsonObj = gson.fromJson(json, JsonObject.class); + + System.out.println(jsonObj); + System.out.println(jsonObj.get("id").getAsInt()); + System.out.println(jsonObj.get("name").getAsString()); + } + + @Test + public void test4() { + User u1 = new User(1, "Tom"); + User u2 = new User(2, "Jack"); + List list = new ArrayList<>(); + list.add(u1); + list.add(u2); + + String json = gson.toJson(list); + + JsonArray jsonArr = gson.fromJson(json, JsonArray.class); + + System.out.println(jsonArr); + System.out.println(jsonArr.get(0)); + System.out.println(jsonArr.get(1)); + } + + public List jsonToList(Class type, String json) { + T[] objs = gson.fromJson(json, TypeToken.getArray(type).getType()); + List list = new ArrayList<>(); + Collections.addAll(list, objs); + return list; + } + + + public String toJsonStr(Object bean, String dateFormat) { + return gson.newBuilder().setDateFormat(dateFormat).create().toJson(bean); + } + + + public static class User { + + private int id; + private String name; + private Date date = new Date(); + + public User() { + } + + public User(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + public void setId(int id) { + this.id = id; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + ", date=" + date + "]"; + } + } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java index f297a2d5..0f2ecbe0 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java @@ -1,5 +1,8 @@ package com.ejlchina.okhttps; +import java.math.BigDecimal; +import java.math.BigInteger; + public interface JsonArr { /** @@ -90,4 +93,16 @@ public interface JsonArr { */ String getString(int index); + /** + * @param key 键� + * @return BigDecimal 值 + */ + BigDecimal getBigDecimal(int index); + + /** + * @param key 键� + * @return BigInteger 值 + */ + BigInteger getBigInteger(int index); + } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java index 609dabee..0eecbac5 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java @@ -1,5 +1,7 @@ package com.ejlchina.okhttps; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Set; /** @@ -97,6 +99,18 @@ public interface JsonObj { */ String getString(String key); + /** + * @param key 键� + * @return BigDecimal 值 + */ + BigDecimal getBigDecimal(String key); + + /** + * @param key 键� + * @return BigInteger 值 + */ + BigInteger getBigInteger(String key); + /** * @param key 键� * @return 是�有该键 From 650bafb236652c47e6a7bf757da66fee8f419c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 00:04:50 +0800 Subject: [PATCH 211/924] =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps-gson/pom.xml | 2 +- okhttps-jackson/pom.xml | 6 +++--- pom.xml | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/okhttps-gson/pom.xml b/okhttps-gson/pom.xml index 8add3318..7d511711 100644 --- a/okhttps-gson/pom.xml +++ b/okhttps-gson/pom.xml @@ -20,7 +20,7 @@ com.google.code.gson gson - 2.8.6 + ${gson.version} diff --git a/okhttps-jackson/pom.xml b/okhttps-jackson/pom.xml index f0129540..381ca8d1 100644 --- a/okhttps-jackson/pom.xml +++ b/okhttps-jackson/pom.xml @@ -17,10 +17,10 @@ okhttps ${okhttps.version} - + com.fasterxml.jackson.core - jackson-core - 2.11.0 + jackson-databind + ${jackson.version} diff --git a/pom.xml b/pom.xml index 7b815fe3..59c0f71d 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,9 @@ 2.0.0 1.8 3.14.7 + 2.8.6 1.2.67 + 2.11.0 4.12 UTF-8 https://oss.sonatype.org/content/repositories/snapshots/ From e86855674e93f043daa5dd69745ce6a56af88759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 00:05:10 +0800 Subject: [PATCH 212/924] =?UTF-8?q?=E9=9B=86=E6=88=90=20Jackson?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ejlchina/okhttps/{gson => }/TestCase.java | 2 +- .../java/com/ejlchina/okhttps/JacksonArr.java | 110 ++++++++++++++++ .../com/ejlchina/okhttps/JacksonFactory.java | 83 ++++++++++++ .../java/com/ejlchina/okhttps/JacksonObj.java | 123 ++++++++++++++++++ .../java/com/ejlchina/okhttps/TestCase.java | 117 +++++++++++++++++ 5 files changed, 434 insertions(+), 1 deletion(-) rename okhttps-gson/src/test/java/com/ejlchina/okhttps/{gson => }/TestCase.java (98%) create mode 100644 okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java create mode 100644 okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java create mode 100644 okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java create mode 100644 okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java similarity index 98% rename from okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java rename to okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java index beb3d645..232d096b 100644 --- a/okhttps-gson/src/test/java/com/ejlchina/okhttps/gson/TestCase.java +++ b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java @@ -1,4 +1,4 @@ -package com.ejlchina.okhttps.gson; +package com.ejlchina.okhttps; import java.util.ArrayList; import java.util.Collections; diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java new file mode 100644 index 00000000..c33a19a7 --- /dev/null +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java @@ -0,0 +1,110 @@ +package com.ejlchina.okhttps; + +import java.math.BigDecimal; +import java.math.BigInteger; + +public class JacksonArr implements JsonArr { + + @Override + public int size() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean isEmpty() { + // TODO Auto-generated method stub + return false; + } + + @Override + public JsonObj getJsonOjb(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public JsonArr getJsonArr(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Boolean getBool(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean getBoolVal(int index) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Integer getInt(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getIntVal(int index) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Short getShort(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public short getShortVal(int index) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Float getFloat(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public float getFloatVal(int index) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Double getDouble(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public double getDoubleVal(int index) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getString(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public BigDecimal getBigDecimal(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public BigInteger getBigInteger(int index) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java new file mode 100644 index 00000000..93fbb78d --- /dev/null +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java @@ -0,0 +1,83 @@ +package com.ejlchina.okhttps; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +import com.ejlchina.okhttps.internal.HttpException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.type.CollectionType; + +public class JacksonFactory implements JsonFactory { + + private ObjectMapper objectMapper; + + public JacksonFactory() { + this(new ObjectMapper()); + } + + public JacksonFactory(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + @Override + public JsonObj newJsonObj(String json) { + // TODO Auto-generated method stub + return null; + } + + @Override + public JsonArr newJsonArr(String json) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String toJsonStr(Object bean) { + try { + return objectMapper.writeValueAsString(bean); + } catch (JsonProcessingException e) { + throw new HttpException("Java Bean [" + bean + "] Jackson �列化异常", e); + } + } + + @Override + public String toJsonStr(Object bean, String dateFormat) { + ObjectMapper mapper = objectMapper.copy(); + mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + mapper.setDateFormat(new SimpleDateFormat(dateFormat)); + try { + return mapper.writeValueAsString(bean); + } catch (JsonProcessingException e) { + throw new HttpException("Java Bean [" + bean + "] Jackson �列化异常", e); + } + } + + @Override + public T jsonToBean(Class type, String json) { + if (json != null) { + try { + return objectMapper.readValue(json, type); + } catch (JsonProcessingException e) { + throw new HttpException("Jackson 解�异常:" + json, e); + } + } + return null; + } + + @Override + public List jsonToList(Class type, String json) { + if (json != null) { + CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type); + try { + return objectMapper.readValue(json, javaType); + } catch (JsonProcessingException e) { + throw new HttpException("Jackson 解�异常:" + json, e); + } + } + return null; + } + +} diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java new file mode 100644 index 00000000..fed71eea --- /dev/null +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java @@ -0,0 +1,123 @@ +package com.ejlchina.okhttps; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Set; + +public class JacksonObj implements JsonObj { + + @Override + public int size() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean isEmpty() { + // TODO Auto-generated method stub + return false; + } + + @Override + public JsonObj getJsonOjb(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public JsonArr getJsonArr(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Boolean getBool(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean getBoolVal(String key) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Integer getInt(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getIntVal(String key) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Short getShort(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public short getShortVal(String key) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Float getFloat(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public float getFloatVal(String key) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Double getDouble(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public double getDoubleVal(String key) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getString(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public BigDecimal getBigDecimal(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public BigInteger getBigInteger(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean has(String key) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Set keySet() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java new file mode 100644 index 00000000..41d7dfce --- /dev/null +++ b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java @@ -0,0 +1,117 @@ +package com.ejlchina.okhttps; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.junit.Test; + +import com.ejlchina.okhttps.internal.HttpException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.type.CollectionType; + +public class TestCase { + + + ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void test() throws JsonProcessingException { + + User u1 = new User(1, "Tom"); + + ObjectMapper mapper = objectMapper.copy(); + + mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + + mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + + String json = mapper.writeValueAsString(u1); + + System.out.println("json = " + json); + + json = objectMapper.writeValueAsString(u1); + + System.out.println("json = " + json); + } + + + @Test + public void test1() throws JsonProcessingException { + + User u1 = new User(1, "Tom"); + User u2 = new User(2, "Jack"); + List list = new ArrayList<>(); + list.add(u1); + list.add(u2); + + String json = objectMapper.writeValueAsString(list); + + System.out.println("json = " + json); + + List nlist = jsonToList(User.class, json); + + System.out.println(nlist); + } + + + + public List jsonToList(Class type, String json) { + if (json != null) { + CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type); + try { + return objectMapper.readValue(json, javaType); + } catch (JsonProcessingException e) { + throw new HttpException("Jackson 解�异常:" + json, e); + } + } + return null; + } + + + public static class User { + + private int id; + private String name; + private Date date = new Date(); + + public User() { + } + + public User(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + public void setId(int id) { + this.id = id; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + ", date=" + date + "]"; + } + + } + +} From 60e598056e608bd8dc975c7c442be310b8e99d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 11:49:09 +0800 Subject: [PATCH 213/924] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20okhttp-jackson?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ejlchina/okhttps/FastJsonArr.java | 39 +----- .../com/ejlchina/okhttps/FastJsonFactory.java | 61 ++++++--- .../com/ejlchina/okhttps/FastJsonObj.java | 38 +----- .../java/com/ejlchina/okhttps/GsonArr.java | 62 +-------- .../com/ejlchina/okhttps/GsonFactory.java | 46 ++++--- .../java/com/ejlchina/okhttps/GsonObj.java | 62 +-------- .../java/com/ejlchina/okhttps/JacksonArr.java | 105 ++++++++-------- .../com/ejlchina/okhttps/JacksonFactory.java | 73 +++++++---- .../java/com/ejlchina/okhttps/JacksonObj.java | 118 +++++++++--------- .../java/com/ejlchina/okhttps/JsonArr.java | 44 +------ .../com/ejlchina/okhttps/JsonFactory.java | 25 ++-- .../java/com/ejlchina/okhttps/JsonObj.java | 44 +------ .../ejlchina/okhttps/internal/ResultBody.java | 8 +- 13 files changed, 269 insertions(+), 456 deletions(-) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java index 81c178bb..e116c378 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java @@ -43,52 +43,22 @@ public JsonArr getJsonArr(int index) { } @Override - public Boolean getBool(int index) { - return json.getBoolean(index); - } - - @Override - public boolean getBoolVal(int index) { + public boolean getBool(int index) { return json.getBooleanValue(index); } @Override - public Integer getInt(int index) { - return json.getInteger(index); - } - - @Override - public int getIntVal(int index) { + public int getInt(int index) { return json.getIntValue(index); } @Override - public Short getShort(int index) { - return json.getShort(index); - } - - @Override - public short getShortVal(int index) { - return json.getShortValue(index); - } - - @Override - public Float getFloat(int index) { - return json.getFloat(index); - } - - @Override - public float getFloatVal(int index) { + public float getFloat(int index) { return json.getFloatValue(index); } @Override - public Double getDouble(int index) { - return json.getDouble(index); - } - - @Override - public double getDoubleVal(int index) { + public double getDouble(int index) { return json.getDoubleValue(index); } @@ -99,7 +69,6 @@ public String getString(int index) { @Override public BigDecimal getBigDecimal(int index) { - // TODO Auto-generated method stub return json.getBigDecimal(index); } diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java index 26fd8b4f..bfbcc84f 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java @@ -1,25 +1,36 @@ package com.ejlchina.okhttps; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.List; import com.alibaba.fastjson.JSON; +import com.ejlchina.okhttps.internal.HttpException; + +import okio.Okio; public class FastJsonFactory implements JsonFactory { + private Charset charset; + + public FastJsonFactory() { + this(StandardCharsets.UTF_8); + } + + public FastJsonFactory(Charset charset) { + this.charset = charset; + } + @Override - public JsonObj newJsonObj(String json) { - if (json != null) { - return new FastJsonObj(JSON.parseObject(json)); - } - return null; + public JsonObj newJsonObj(InputStream in) { + return new FastJsonObj(JSON.parseObject(toString(in))); } @Override - public JsonArr newJsonArr(String json) { - if (json != null) { - return new FastJsonArr(JSON.parseArray(json)); - } - return null; + public JsonArr newJsonArr(InputStream in) { + return new FastJsonArr(JSON.parseArray(toString(in))); } @Override @@ -33,19 +44,33 @@ public String toJsonStr(Object bean, String dateFormat) { } @Override - public T jsonToBean(Class type, String json) { - if (json != null) { - return JSON.parseObject(json, type); + public T jsonToBean(Class type, InputStream in) { + try { + return JSON.parseObject(in, type); + } catch (IOException e) { + throw new HttpException("读�文本异常", e); } - return null; } @Override - public List jsonToList(Class type, String json) { - if (json != null) { - return JSON.parseArray(json, type); + public List jsonToList(Class type, InputStream in) { + return JSON.parseArray(toString(in), type); + } + + private String toString(InputStream in) { + try { + return Okio.buffer(Okio.source(in)).readString(charset); + } catch (IOException e) { + throw new HttpException("读�文本异常", e); } - return null; + } + + public Charset getCharset() { + return charset; + } + + public void setCharset(Charset charset) { + this.charset = charset; } } diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java index 2eb401b9..484b32c9 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java @@ -44,52 +44,22 @@ public JsonArr getJsonArr(String key) { } @Override - public Boolean getBool(String key) { - return json.getBoolean(key); - } - - @Override - public boolean getBoolVal(String key) { + public boolean getBool(String key) { return json.getBooleanValue(key); } @Override - public Integer getInt(String key) { - return json.getInteger(key); - } - - @Override - public int getIntVal(String key) { + public int getInt(String key) { return json.getIntValue(key); } @Override - public Short getShort(String key) { - return json.getShort(key); - } - - @Override - public short getShortVal(String key) { - return json.getShortValue(key); - } - - @Override - public Float getFloat(String key) { - return json.getFloat(key); - } - - @Override - public float getFloatVal(String key) { + public float getFloat(String key) { return json.getFloatValue(key); } @Override - public Double getDouble(String key) { - return json.getDouble(key); - } - - @Override - public double getDoubleVal(String key) { + public double getDouble(String key) { return json.getDoubleValue(key); } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java index 8d77e4bb..a63c3e67 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java @@ -43,16 +43,7 @@ public JsonArr getJsonArr(int index) { } @Override - public Boolean getBool(int index) { - JsonElement val = json.get(index); - if (val != null) { - return val.getAsBoolean(); - } - return null; - } - - @Override - public boolean getBoolVal(int index) { + public boolean getBool(int index) { JsonElement val = json.get(index); if (val != null) { return val.getAsBoolean(); @@ -61,52 +52,16 @@ public boolean getBoolVal(int index) { } @Override - public Integer getInt(int index) { + public int getInt(int index) { JsonElement val = json.get(index); if (val != null) { return val.getAsInt(); } - return null; - } - - @Override - public int getIntVal(int index) { - JsonElement val = json.get(index); - if (val != null) { - return val.getAsInt(); - } - return 0; - } - - @Override - public Short getShort(int index) { - JsonElement val = json.get(index); - if (val != null) { - return val.getAsShort(); - } - return null; - } - - @Override - public short getShortVal(int index) { - JsonElement val = json.get(index); - if (val != null) { - return val.getAsShort(); - } return 0; } @Override - public Float getFloat(int index) { - JsonElement val = json.get(index); - if (val != null) { - return val.getAsFloat(); - } - return null; - } - - @Override - public float getFloatVal(int index) { + public float getFloat(int index) { JsonElement val = json.get(index); if (val != null) { return val.getAsFloat(); @@ -115,16 +70,7 @@ public float getFloatVal(int index) { } @Override - public Double getDouble(int index) { - JsonElement val = json.get(index); - if (val != null) { - return val.getAsDouble(); - } - return null; - } - - @Override - public double getDoubleVal(int index) { + public double getDouble(int index) { JsonElement val = json.get(index); if (val != null) { return val.getAsDouble(); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java index 5a581534..17f464e0 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java @@ -1,5 +1,7 @@ package com.ejlchina.okhttps; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -11,7 +13,7 @@ public class GsonFactory implements JsonFactory { - private final Gson gson; + private Gson gson; public GsonFactory() { this(new Gson()); @@ -22,19 +24,13 @@ public GsonFactory(Gson gson) { } @Override - public JsonObj newJsonObj(String json) { - if (json != null) { - return new GsonObj(gson.fromJson(json, JsonObject.class)); - } - return null; + public JsonObj newJsonObj(InputStream in) { + return new GsonObj(gson.fromJson(new InputStreamReader(in), JsonObject.class)); } @Override - public JsonArr newJsonArr(String json) { - if (json != null) { - return new GsonArr(gson.fromJson(json, JsonArray.class)); - } - return null; + public JsonArr newJsonArr(InputStream in) { + return new GsonArr(gson.fromJson(new InputStreamReader(in), JsonArray.class)); } @Override @@ -48,22 +44,24 @@ public String toJsonStr(Object bean, String dateFormat) { } @Override - public T jsonToBean(Class type, String json) { - if (json != null) { - return gson.fromJson(json, type); - } - return null; + public T jsonToBean(Class type, InputStream in) { + return gson.fromJson(new InputStreamReader(in), type); } @Override - public List jsonToList(Class type, String json) { - if (json != null) { - T[] beans = gson.fromJson(json, TypeToken.getArray(type).getType()); - List list = new ArrayList<>(); - Collections.addAll(list, beans); - return list; - } - return null; + public List jsonToList(Class type, InputStream in) { + T[] beans = gson.fromJson(new InputStreamReader(in), TypeToken.getArray(type).getType()); + List list = new ArrayList<>(); + Collections.addAll(list, beans); + return list; + } + + public Gson getGson() { + return gson; + } + + public void setGson(Gson gson) { + this.gson = gson; } } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java index 744c6aa5..5441ce81 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java @@ -44,16 +44,7 @@ public JsonArr getJsonArr(String key) { } @Override - public Boolean getBool(String key) { - JsonElement val = json.get(key); - if (val != null) { - return val.getAsBoolean(); - } - return null; - } - - @Override - public boolean getBoolVal(String key) { + public boolean getBool(String key) { JsonElement val = json.get(key); if (val != null) { return val.getAsBoolean(); @@ -62,52 +53,16 @@ public boolean getBoolVal(String key) { } @Override - public Integer getInt(String key) { + public int getInt(String key) { JsonElement val = json.get(key); if (val != null) { return val.getAsInt(); } - return null; - } - - @Override - public int getIntVal(String key) { - JsonElement val = json.get(key); - if (val != null) { - return val.getAsInt(); - } - return 0; - } - - @Override - public Short getShort(String key) { - JsonElement val = json.get(key); - if (val != null) { - return val.getAsShort(); - } - return null; - } - - @Override - public short getShortVal(String key) { - JsonElement val = json.get(key); - if (val != null) { - return val.getAsShort(); - } return 0; } @Override - public Float getFloat(String key) { - JsonElement val = json.get(key); - if (val != null) { - return val.getAsFloat(); - } - return null; - } - - @Override - public float getFloatVal(String key) { + public float getFloat(String key) { JsonElement val = json.get(key); if (val != null) { return val.getAsFloat(); @@ -116,16 +71,7 @@ public float getFloatVal(String key) { } @Override - public Double getDouble(String key) { - JsonElement val = json.get(key); - if (val != null) { - return val.getAsDouble(); - } - return null; - } - - @Override - public double getDoubleVal(String key) { + public double getDouble(String key) { JsonElement val = json.get(key); if (val != null) { return val.getAsDouble(); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java index c33a19a7..ae519f91 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java @@ -3,107 +3,106 @@ import java.math.BigDecimal; import java.math.BigInteger; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + public class JacksonArr implements JsonArr { + private ArrayNode json; + + public JacksonArr(ArrayNode json) { + this.json = json; + } + @Override public int size() { - // TODO Auto-generated method stub - return 0; + return json.size(); } @Override public boolean isEmpty() { - // TODO Auto-generated method stub - return false; + return json.isEmpty(); } @Override public JsonObj getJsonOjb(int index) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(index); + if (subJson != null && subJson.isObject()) { + return new JacksonObj((ObjectNode) subJson); + } return null; } @Override public JsonArr getJsonArr(int index) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Boolean getBool(int index) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(index); + if (subJson != null && subJson.isArray()) { + return new JacksonArr((ArrayNode) subJson); + } return null; } @Override - public boolean getBoolVal(int index) { - // TODO Auto-generated method stub + public boolean getBool(int index) { + JsonNode subJson = json.get(index); + if (subJson != null && subJson.asBoolean()) { + return subJson.asBoolean(); + } return false; } @Override - public Integer getInt(int index) { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getIntVal(int index) { - // TODO Auto-generated method stub - return 0; - } - - @Override - public Short getShort(int index) { - // TODO Auto-generated method stub - return null; - } - - @Override - public short getShortVal(int index) { - // TODO Auto-generated method stub + public int getInt(int index) { + JsonNode subJson = json.get(index); + if (subJson != null && subJson.isNumber()) { + return subJson.intValue(); + } return 0; } @Override - public Float getFloat(int index) { - // TODO Auto-generated method stub - return null; - } - - @Override - public float getFloatVal(int index) { - // TODO Auto-generated method stub + public float getFloat(int index) { + JsonNode subJson = json.get(index); + if (subJson != null && subJson.isNumber()) { + return subJson.floatValue(); + } return 0; } @Override - public Double getDouble(int index) { - // TODO Auto-generated method stub - return null; - } - - @Override - public double getDoubleVal(int index) { - // TODO Auto-generated method stub + public double getDouble(int index) { + JsonNode subJson = json.get(index); + if (subJson != null && subJson.isNumber()) { + return subJson.doubleValue(); + } return 0; } @Override public String getString(int index) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(index); + if (subJson != null) { + return subJson.asText(); + } return null; } @Override public BigDecimal getBigDecimal(int index) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(index); + if (subJson != null && subJson.isNumber()) { + return subJson.decimalValue(); + } return null; } @Override public BigInteger getBigInteger(int index) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(index); + if (subJson != null && subJson.isNumber()) { + return subJson.bigIntegerValue(); + } return null; } diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java index 93fbb78d..8fa0e7c2 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java @@ -1,13 +1,18 @@ package com.ejlchina.okhttps; +import java.io.IOException; +import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import com.ejlchina.okhttps.internal.HttpException; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.type.CollectionType; public class JacksonFactory implements JsonFactory { @@ -23,15 +28,35 @@ public JacksonFactory(ObjectMapper objectMapper) { } @Override - public JsonObj newJsonObj(String json) { - // TODO Auto-generated method stub - return null; + public JsonObj newJsonObj(InputStream in) { + try { + JsonNode json = objectMapper.readTree(in); + if (json.isObject()) { + return new JacksonObj((ObjectNode) json); + } + if (json.isNull() || json.isMissingNode()) { + return null; + } + throw new HttpException("�是 一个 json 对象:" + json); + } catch (IOException e) { + throw new HttpException("Jackson 解�异常", e); + } } @Override - public JsonArr newJsonArr(String json) { - // TODO Auto-generated method stub - return null; + public JsonArr newJsonArr(InputStream in) { + try { + JsonNode json = objectMapper.readTree(in); + if (json.isArray()) { + return new JacksonArr((ArrayNode) json); + } + if (json.isNull() || json.isMissingNode()) { + return null; + } + throw new HttpException("�是 一个 json 数组:" + json); + } catch (IOException e) { + throw new HttpException("Jackson 解�异常", e); + } } @Override @@ -56,28 +81,30 @@ public String toJsonStr(Object bean, String dateFormat) { } @Override - public T jsonToBean(Class type, String json) { - if (json != null) { - try { - return objectMapper.readValue(json, type); - } catch (JsonProcessingException e) { - throw new HttpException("Jackson 解�异常:" + json, e); - } + public T jsonToBean(Class type, InputStream in) { + try { + return objectMapper.readValue(in, type); + } catch (IOException e) { + throw new HttpException("Jackson 解�异常", e); } - return null; } @Override - public List jsonToList(Class type, String json) { - if (json != null) { - CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type); - try { - return objectMapper.readValue(json, javaType); - } catch (JsonProcessingException e) { - throw new HttpException("Jackson 解�异常:" + json, e); - } + public List jsonToList(Class type, InputStream in) { + CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type); + try { + return objectMapper.readValue(in, javaType); + } catch (IOException e) { + throw new HttpException("Jackson 解�异常", e); } - return null; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; } } diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java index fed71eea..6ff76c67 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java @@ -2,122 +2,126 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.util.HashSet; +import java.util.Iterator; import java.util.Set; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + public class JacksonObj implements JsonObj { + private ObjectNode json; + + public JacksonObj(ObjectNode json) { + this.json = json; + } + @Override public int size() { - // TODO Auto-generated method stub - return 0; + return json.size(); } @Override public boolean isEmpty() { - // TODO Auto-generated method stub - return false; + return json.isEmpty(); } @Override public JsonObj getJsonOjb(String key) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(key); + if (subJson != null && subJson.isObject()) { + return new JacksonObj((ObjectNode) subJson); + } return null; } @Override public JsonArr getJsonArr(String key) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Boolean getBool(String key) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(key); + if (subJson != null && subJson.isArray()) { + return new JacksonArr((ArrayNode) subJson); + } return null; } @Override - public boolean getBoolVal(String key) { - // TODO Auto-generated method stub + public boolean getBool(String key) { + JsonNode subJson = json.get(key); + if (subJson != null && subJson.asBoolean()) { + return subJson.asBoolean(); + } return false; } @Override - public Integer getInt(String key) { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getIntVal(String key) { - // TODO Auto-generated method stub + public int getInt(String key) { + JsonNode subJson = json.get(key); + if (subJson != null && subJson.isNumber()) { + return subJson.intValue(); + } return 0; } @Override - public Short getShort(String key) { - // TODO Auto-generated method stub - return null; - } - - @Override - public short getShortVal(String key) { - // TODO Auto-generated method stub + public float getFloat(String key) { + JsonNode subJson = json.get(key); + if (subJson != null && subJson.isNumber()) { + return subJson.floatValue(); + } return 0; } @Override - public Float getFloat(String key) { - // TODO Auto-generated method stub - return null; - } - - @Override - public float getFloatVal(String key) { - // TODO Auto-generated method stub - return 0; - } - - @Override - public Double getDouble(String key) { - // TODO Auto-generated method stub - return null; - } - - @Override - public double getDoubleVal(String key) { - // TODO Auto-generated method stub + public double getDouble(String key) { + JsonNode subJson = json.get(key); + if (subJson != null && subJson.isNumber()) { + return subJson.doubleValue(); + } return 0; } @Override public String getString(String key) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(key); + if (subJson != null) { + return subJson.asText(); + } return null; } @Override public BigDecimal getBigDecimal(String key) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(key); + if (subJson != null && subJson.isNumber()) { + return subJson.decimalValue(); + } return null; } @Override public BigInteger getBigInteger(String key) { - // TODO Auto-generated method stub + JsonNode subJson = json.get(key); + if (subJson != null && subJson.isNumber()) { + return subJson.bigIntegerValue(); + } return null; } @Override public boolean has(String key) { - // TODO Auto-generated method stub - return false; + return json.has(key); } @Override public Set keySet() { - // TODO Auto-generated method stub - return null; + Iterator it = json.fieldNames(); + Set set = new HashSet<>(); + while (it.hasNext()) { + set.add(it.next()); + } + return set; } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java index 0f2ecbe0..97c1fe43 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java @@ -27,65 +27,29 @@ public interface JsonArr { */ JsonArr getJsonArr(int index); - /** - * @param index 元素下标 - * @return Boolean 值 - */ - Boolean getBool(int index); - /** * @param index 元素下标 * @return boolean 值 */ - boolean getBoolVal(int index); - - /** - * @param index 元素下标 - * @return Integer 值 - */ - Integer getInt(int index); + boolean getBool(int index); /** * @param index 元素下标 * @return int 值 */ - int getIntVal(int index); - - /** - * @param index 元素下标 - * @return Short 值 - */ - Short getShort(int index); - - /** - * @param index 元素下标 - * @return short 值 - */ - short getShortVal(int index); - - /** - * @param index 元素下标 - * @return Float 值 - */ - Float getFloat(int index); + int getInt(int index); /** * @param index 元素下标 * @return float 值 */ - float getFloatVal(int index); - - /** - * @param index 元素下标 - * @return Double 值 - */ - Double getDouble(int index); + float getFloat(int index); /** * @param index 元素下标 * @return double 值 */ - double getDoubleVal(int index); + double getDouble(int index); /** * @param index 元素下标 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java index b9c4e3e2..0ffcb9d9 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java @@ -1,5 +1,6 @@ package com.ejlchina.okhttps; +import java.io.InputStream; import java.util.List; @@ -7,18 +8,18 @@ public interface JsonFactory { /** - * 将 json 文本解�为 JsonObj - * @param json 文本 + * 解� JsonObj + * @param in 输入� * @return JsonObj */ - JsonObj newJsonObj(String json); + JsonObj newJsonObj(InputStream in); /** - * 将 json 文本解�为 JsonArr - * @param json 文本 + * 解� JsonArr + * @param in 输入� * @return JsonArr */ - JsonArr newJsonArr(String json); + JsonArr newJsonArr(InputStream in); /** * 将 Java 对象�列化为 Json 字符串 @@ -36,22 +37,22 @@ public interface JsonFactory { String toJsonStr(Object bean, String dateFormat); /** - * 将 json 文本 解�为 Java Bean + * 解� Java Bean * @param 目标泛型 * @param type 目标类型 - * @param json 文本 + * @param in 输入� * @return Java Bean */ - T jsonToBean(Class type, String json); + T jsonToBean(Class type, InputStream in); /** - * 将 json 文本 解�为 Java List + * 解�为 Java List * @param 目标泛型 * @param type 目标类型 - * @param json 文本 + * @param in 输入� * @return Java List */ - List jsonToList(Class type, String json); + List jsonToList(Class type, InputStream in); } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java index 0eecbac5..aa54d343 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java @@ -33,65 +33,29 @@ public interface JsonObj { */ JsonArr getJsonArr(String key); - /** - * @param key 键� - * @return Boolean 值 - */ - Boolean getBool(String key); - /** * @param key 键� * @return boolean 值 */ - boolean getBoolVal(String key); - - /** - * @param key 键� - * @return Integer 值 - */ - Integer getInt(String key); + boolean getBool(String key); /** * @param key 键� * @return int 值 */ - int getIntVal(String key); - - /** - * @param key 键� - * @return Short 值 - */ - Short getShort(String key); - - /** - * @param key 键� - * @return short 值 - */ - short getShortVal(String key); - - /** - * @param key 键� - * @return Float 值 - */ - Float getFloat(String key); + int getInt(String key); /** * @param key 键� * @return float 值 */ - float getFloatVal(String key); - - /** - * @param key 键� - * @return Double 值 - */ - Double getDouble(String key); + float getFloat(String key); /** * @param key 键� * @return double 值 */ - double getDoubleVal(String key); + double getDouble(String key); /** * @param key 键� diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java index 03d51e3c..df84faa1 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java @@ -152,7 +152,7 @@ public JsonObj toJsonObj() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.getJsonFactoryNotNull().newJsonObj(toString()); + return taskExecutor.getJsonFactoryNotNull().newJsonObj(toByteStream()); } @Override @@ -160,7 +160,7 @@ public JsonArr toJsonArr() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.getJsonFactoryNotNull().newJsonArr(toString()); + return taskExecutor.getJsonFactoryNotNull().newJsonArr(toByteStream()); } @Override @@ -168,7 +168,7 @@ public T toBean(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.getJsonFactoryNotNull().jsonToBean(type, toString()); + return taskExecutor.getJsonFactoryNotNull().jsonToBean(type, toByteStream()); } @Override @@ -176,7 +176,7 @@ public List toList(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.getJsonFactoryNotNull().jsonToList(type, toString()); + return taskExecutor.getJsonFactoryNotNull().jsonToList(type, toByteStream()); } @Override From 6f0da36194b10dd2141d5d527afc6b74371db072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 11:56:23 +0800 Subject: [PATCH 214/924] =?UTF-8?q?Json=20=E8=A7=A3=E8=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java | 6 ++++++ okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java index 97c1fe43..063fb7fe 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java @@ -39,6 +39,12 @@ public interface JsonArr { */ int getInt(int index); + /** + * @param index 元素下标 + * @return long 值 + */ + long getLong(int index); + /** * @param index 元素下标 * @return float 值 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java index aa54d343..5a8cd48a 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java @@ -45,6 +45,12 @@ public interface JsonObj { */ int getInt(String key); + /** + * @param key 键� + * @return long 值 + */ + long getLong(String key); + /** * @param key 键� * @return float 值 From 6c99c5e3b60da64bf1023941f2a4d0e08e10ca90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 11:56:56 +0800 Subject: [PATCH 215/924] =?UTF-8?q?=E9=9B=86=E6=88=90=20fastjaon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/ejlchina/okhttps/FastJsonArr.java | 5 +++++ .../src/main/java/com/ejlchina/okhttps/FastJsonObj.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java index e116c378..2ea27798 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java @@ -52,6 +52,11 @@ public int getInt(int index) { return json.getIntValue(index); } + @Override + public long getLong(int index) { + return json.getLongValue(index); + } + @Override public float getFloat(int index) { return json.getFloatValue(index); diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java index 484b32c9..7d4ebd0b 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java @@ -53,6 +53,11 @@ public int getInt(String key) { return json.getIntValue(key); } + @Override + public long getLong(String key) { + return json.getLongValue(key); + } + @Override public float getFloat(String key) { return json.getFloatValue(key); From 60fc2a3fcd90fdca1f83667d423444a878da6936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 11:57:12 +0800 Subject: [PATCH 216/924] =?UTF-8?q?=E9=9B=86=E6=88=90=20gson?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/ejlchina/okhttps/GsonArr.java | 9 +++++++++ .../src/main/java/com/ejlchina/okhttps/GsonObj.java | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java index a63c3e67..de121c95 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java @@ -60,6 +60,15 @@ public int getInt(int index) { return 0; } + @Override + public long getLong(int index) { + JsonElement val = json.get(index); + if (val != null) { + return val.getAsLong(); + } + return 0; + } + @Override public float getFloat(int index) { JsonElement val = json.get(index); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java index 5441ce81..9b7c0d7c 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java @@ -61,6 +61,15 @@ public int getInt(String key) { return 0; } + @Override + public long getLong(String key) { + JsonElement val = json.get(key); + if (val != null) { + return val.getAsLong(); + } + return 0; + } + @Override public float getFloat(String key) { JsonElement val = json.get(key); From d0583764e9d9b6c636cbfe4e59a91b23c7f5ba58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 11:57:25 +0800 Subject: [PATCH 217/924] =?UTF-8?q?=E9=9B=86=E6=88=90=20jackson?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/ejlchina/okhttps/JacksonArr.java | 9 +++++++++ .../src/main/java/com/ejlchina/okhttps/JacksonObj.java | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java index ae519f91..c6870240 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java @@ -61,6 +61,15 @@ public int getInt(int index) { return 0; } + @Override + public long getLong(int index) { + JsonNode subJson = json.get(index); + if (subJson != null && subJson.isNumber()) { + return subJson.longValue(); + } + return 0; + } + @Override public float getFloat(int index) { JsonNode subJson = json.get(index); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java index 6ff76c67..79c5b0cf 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java @@ -64,6 +64,15 @@ public int getInt(String key) { return 0; } + @Override + public long getLong(String key) { + JsonNode subJson = json.get(key); + if (subJson != null && subJson.isNumber()) { + return subJson.longValue(); + } + return 0; + } + @Override public float getFloat(String key) { JsonNode subJson = json.get(key); From bdb9e5cff69de9e5442c46c3af1ae29f229e0e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 12:05:42 +0800 Subject: [PATCH 218/924] json toString --- .../src/main/java/com/ejlchina/okhttps/FastJsonArr.java | 5 +++++ .../src/main/java/com/ejlchina/okhttps/FastJsonObj.java | 5 +++++ okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java | 5 +++++ okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java | 5 +++++ .../src/main/java/com/ejlchina/okhttps/JacksonArr.java | 5 +++++ .../src/main/java/com/ejlchina/okhttps/JacksonObj.java | 5 +++++ 6 files changed, 30 insertions(+) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java index 2ea27798..829fcb50 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java @@ -82,4 +82,9 @@ public BigInteger getBigInteger(int index) { return json.getBigInteger(index); } + @Override + public String toString() { + return json.toJSONString(); + } + } diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java index 7d4ebd0b..dfddd9c6 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java @@ -93,4 +93,9 @@ public Set keySet() { return json.keySet(); } + @Override + public String toString() { + return json.toJSONString(); + } + } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java index de121c95..85ae0620 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java @@ -114,4 +114,9 @@ public BigInteger getBigInteger(int index) { return null; } + @Override + public String toString() { + return json.toString(); + } + } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java index 9b7c0d7c..88d3afbf 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java @@ -125,4 +125,9 @@ public Set keySet() { return json.keySet(); } + @Override + public String toString() { + return json.toString(); + } + } diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java index c6870240..3d65cf0b 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java @@ -115,4 +115,9 @@ public BigInteger getBigInteger(int index) { return null; } + @Override + public String toString() { + return json.toString(); + } + } diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java index 79c5b0cf..f67a1d2a 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java @@ -133,4 +133,9 @@ public Set keySet() { return set; } + @Override + public String toString() { + return json.toString(); + } + } From abefa818487b0e0b567ca56f202773858d9b6ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 12:17:25 +0800 Subject: [PATCH 219/924] gitignore --- okhttps-fastjson/.gitignore | 1 + okhttps-gson/.gitignore | 1 + okhttps-jackson/.gitignore | 1 + 3 files changed, 3 insertions(+) create mode 100644 okhttps-fastjson/.gitignore create mode 100644 okhttps-gson/.gitignore create mode 100644 okhttps-jackson/.gitignore diff --git a/okhttps-fastjson/.gitignore b/okhttps-fastjson/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/okhttps-fastjson/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/okhttps-gson/.gitignore b/okhttps-gson/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/okhttps-gson/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/okhttps-jackson/.gitignore b/okhttps-jackson/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/okhttps-jackson/.gitignore @@ -0,0 +1 @@ +/target/ From d080050f1b93ef6c73c7ef298164f2cc381f81ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 13:13:08 +0800 Subject: [PATCH 220/924] =?UTF-8?q?HTTP=20=E6=8E=A5=E5=8F=A3=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20newBuilder=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index 5e534549..12218242 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -87,6 +87,12 @@ public interface HTTP { */ TaskExecutor getExecutor(); + /** + * 新的构建器 + * @return Builder + */ + Builder newBuilder(); + /** * HTTP 构建器 * @return HTTP 构建器 From c9e2502f9531559e5a80a3423ba9cf696bda6280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 13:16:39 +0800 Subject: [PATCH 221/924] refactor: JsonFactory -> JsonService --- ...FastJsonFactory.java => FastJsonService.java} | 6 +++--- .../{GsonFactory.java => GsonService.java} | 6 +++--- .../{JacksonFactory.java => JacksonService.java} | 6 +++--- .../main/java/com/ejlchina/okhttps/HttpTask.java | 6 +++--- .../{JsonFactory.java => JsonService.java} | 3 +-- .../ejlchina/okhttps/internal/HttpClient.java | 16 +++++++++------- .../ejlchina/okhttps/internal/ResultBody.java | 8 ++++---- .../ejlchina/okhttps/internal/TaskExecutor.java | 16 ++++++++-------- .../ejlchina/okhttps/internal/WebSocketTask.java | 6 +++--- 9 files changed, 37 insertions(+), 36 deletions(-) rename okhttps-fastjson/src/main/java/com/ejlchina/okhttps/{FastJsonFactory.java => FastJsonService.java} (92%) rename okhttps-gson/src/main/java/com/ejlchina/okhttps/{GsonFactory.java => GsonService.java} (92%) rename okhttps-jackson/src/main/java/com/ejlchina/okhttps/{JacksonFactory.java => JacksonService.java} (95%) rename okhttps/src/main/java/com/ejlchina/okhttps/{JsonFactory.java => JsonService.java} (96%) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java similarity index 92% rename from okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java rename to okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java index bfbcc84f..d1678548 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonFactory.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java @@ -11,15 +11,15 @@ import okio.Okio; -public class FastJsonFactory implements JsonFactory { +public class FastJsonService implements JsonService { private Charset charset; - public FastJsonFactory() { + public FastJsonService() { this(StandardCharsets.UTF_8); } - public FastJsonFactory(Charset charset) { + public FastJsonService(Charset charset) { this.charset = charset; } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java similarity index 92% rename from okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java rename to okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java index 17f464e0..87b0b741 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonFactory.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java @@ -11,15 +11,15 @@ import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; -public class GsonFactory implements JsonFactory { +public class GsonService implements JsonService { private Gson gson; - public GsonFactory() { + public GsonService() { this(new Gson()); } - public GsonFactory(Gson gson) { + public GsonService(Gson gson) { this.gson = gson; } diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java similarity index 95% rename from okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java rename to okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java index 8fa0e7c2..764b9f53 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonFactory.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java @@ -15,15 +15,15 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.type.CollectionType; -public class JacksonFactory implements JsonFactory { +public class JacksonService implements JsonService { private ObjectMapper objectMapper; - public JacksonFactory() { + public JacksonService() { this(new ObjectMapper()); } - public JacksonFactory(ObjectMapper objectMapper) { + public JacksonService(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 68b78b1b..ae2ea2c7 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -420,11 +420,11 @@ public C setRequestJson(Object json, String dateFormat) { requestJson = json.toString(); } else if (dateFormat != null) { requestJson = httpClient.getExecutor() - .getJsonFactoryNotNull() + .jsonServiceNotNull() .toJsonStr(json, dateFormat); } else { requestJson = httpClient.getExecutor() - .getJsonFactoryNotNull() + .jsonServiceNotNull() .toJsonStr(json); } } @@ -656,7 +656,7 @@ protected State toState(IOException e, boolean sync) { private RequestBody buildRequestBody() { if (jsonParams != null) { - requestJson = httpClient.getExecutor().getJsonFactoryNotNull() + requestJson = httpClient.getExecutor().jsonServiceNotNull() .toJsonStr(jsonParams); } if (files != null) { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java similarity index 96% rename from okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java rename to okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java index 0ffcb9d9..c4108c8b 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonFactory.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java @@ -4,9 +4,8 @@ import java.util.List; -public interface JsonFactory { +public interface JsonService { - /** * 解� JsonObj * @param in 输入� diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 2174e816..96dca4ef 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -33,7 +33,7 @@ private HttpClient(Builder builder) { this.executor = new TaskExecutor(client.dispatcher().executorService(), builder.mainExecutor, builder.downloadListener, builder.responseListener, builder.exceptionListener, - builder.completeListener, builder.jsonFactory); + builder.completeListener, builder.jsonService); this.preprocessors = builder.preprocessors.toArray(new Preprocessor[0]); this.tagTasks = new LinkedList<>(); } @@ -174,6 +174,7 @@ public MediaType getMediaType(String type) { return MediaType.parse("application/octet-stream"); } + @Override public TaskExecutor getExecutor() { return executor; } @@ -305,6 +306,7 @@ public void proceed() { } + @Override public Builder newBuilder() { return new Builder(this); } @@ -349,7 +351,7 @@ public static class Builder { private TaskListener completeListener; - private JsonFactory jsonFactory; + private JsonService jsonService; public Builder() { mediaTypes = new HashMap<>(); @@ -380,7 +382,7 @@ private Builder(HttpClient hc) { this.responseListener = hc.executor.responseListener; this.exceptionListener = hc.executor.exceptionListener; this.completeListener = hc.executor.completeListener; - this.jsonFactory = hc.executor.jsonFactory; + this.jsonService = hc.executor.jsonService; } /** @@ -506,12 +508,12 @@ public Builder downloadListener(DownListener listener) { } /** - * 设置 JSON 工厂 - * @param jsonFactory JSON 工厂 + * 设置 JSON �务 + * @param jsonService JSON �务 * @return Builder */ - public Builder jsonFactory(JsonFactory jsonFactory) { - this.jsonFactory = jsonFactory; + public Builder jsonService(JsonService jsonService) { + this.jsonService = jsonService; return this; } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java index df84faa1..14e7725a 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java @@ -152,7 +152,7 @@ public JsonObj toJsonObj() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.getJsonFactoryNotNull().newJsonObj(toByteStream()); + return taskExecutor.jsonServiceNotNull().newJsonObj(toByteStream()); } @Override @@ -160,7 +160,7 @@ public JsonArr toJsonArr() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.getJsonFactoryNotNull().newJsonArr(toByteStream()); + return taskExecutor.jsonServiceNotNull().newJsonArr(toByteStream()); } @Override @@ -168,7 +168,7 @@ public T toBean(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.getJsonFactoryNotNull().jsonToBean(type, toByteStream()); + return taskExecutor.jsonServiceNotNull().jsonToBean(type, toByteStream()); } @Override @@ -176,7 +176,7 @@ public List toList(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.getJsonFactoryNotNull().jsonToList(type, toByteStream()); + return taskExecutor.jsonServiceNotNull().jsonToList(type, toByteStream()); } @Override diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 1df24b71..1381006d 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -10,7 +10,7 @@ import com.ejlchina.okhttps.Download; import com.ejlchina.okhttps.HttpResult; import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.JsonFactory; +import com.ejlchina.okhttps.JsonService; import com.ejlchina.okhttps.OnCallback; import com.ejlchina.okhttps.TaskListener; import com.ejlchina.okhttps.HttpResult.State; @@ -23,18 +23,18 @@ public class TaskExecutor { TaskListener responseListener; TaskListener exceptionListener; TaskListener completeListener; - JsonFactory jsonFactory; + JsonService jsonService; public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, TaskListener responseListener, TaskListener exceptionListener, - TaskListener completeListener, JsonFactory jsonFactory) { + TaskListener completeListener, JsonService jsonService) { this.ioExecutor = ioExecutor; this.mainExecutor = mainExecutor; this.downloadListener = downloadListener; this.responseListener = responseListener; this.exceptionListener = exceptionListener; this.completeListener = completeListener; - this.jsonFactory = jsonFactory; + this.jsonService = jsonService; } public Executor getExecutor(boolean onIoThread) { @@ -99,11 +99,11 @@ public void executeOnComplete(HttpTask task, OnCallback onComplete, St } } - public JsonFactory getJsonFactoryNotNull() { - if (jsonFactory != null) { - return jsonFactory; + public JsonService jsonServiceNotNull() { + if (jsonService != null) { + return jsonService; } - throw new IllegalStateException("没有设置 JsonFactory,��� Json �作�"); + throw new IllegalStateException("没有设置 JsonService,��� Json �作�"); } /** diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 9a3726be..7a36e24a 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -152,12 +152,12 @@ public boolean send(ByteString bytes) { @Override public boolean send(Object bean) { - return send(taskExecutor.getJsonFactoryNotNull().toJsonStr(bean)); + return send(taskExecutor.jsonServiceNotNull().toJsonStr(bean)); } @Override public boolean send(Object bean, String dateFormat) { - return send(taskExecutor.getJsonFactoryNotNull().toJsonStr(bean, dateFormat)); + return send(taskExecutor.jsonServiceNotNull().toJsonStr(bean, dateFormat)); } @Override @@ -209,7 +209,7 @@ boolean send(okhttp3.WebSocket webSocket, Object msg) { if (msg instanceof byte[]) { return webSocket.send(ByteString.of((byte[]) msg)); } - return webSocket.send(taskExecutor.getJsonFactoryNotNull().toJsonStr(msg)); + return webSocket.send(taskExecutor.jsonServiceNotNull().toJsonStr(msg)); } } From c372871cffd97953a7444d43a2d5b8b0f9ccab15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 13:59:57 +0800 Subject: [PATCH 222/924] refactor --- .../java/com/ejlchina/okhttps/FastJsonService.java | 4 ++-- .../main/java/com/ejlchina/okhttps/GsonService.java | 4 ++-- .../java/com/ejlchina/okhttps/JacksonService.java | 4 ++-- .../main/java/com/ejlchina/okhttps/JsonService.java | 12 ++++++------ .../com/ejlchina/okhttps/internal/ResultBody.java | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java index d1678548..7cd6436a 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java @@ -24,12 +24,12 @@ public FastJsonService(Charset charset) { } @Override - public JsonObj newJsonObj(InputStream in) { + public JsonObj toJsonObj(InputStream in) { return new FastJsonObj(JSON.parseObject(toString(in))); } @Override - public JsonArr newJsonArr(InputStream in) { + public JsonArr toJsonArr(InputStream in) { return new FastJsonArr(JSON.parseArray(toString(in))); } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java index 87b0b741..1b25c59e 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java @@ -24,12 +24,12 @@ public GsonService(Gson gson) { } @Override - public JsonObj newJsonObj(InputStream in) { + public JsonObj toJsonObj(InputStream in) { return new GsonObj(gson.fromJson(new InputStreamReader(in), JsonObject.class)); } @Override - public JsonArr newJsonArr(InputStream in) { + public JsonArr toJsonArr(InputStream in) { return new GsonArr(gson.fromJson(new InputStreamReader(in), JsonArray.class)); } diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java index 764b9f53..301d5a73 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java @@ -28,7 +28,7 @@ public JacksonService(ObjectMapper objectMapper) { } @Override - public JsonObj newJsonObj(InputStream in) { + public JsonObj toJsonObj(InputStream in) { try { JsonNode json = objectMapper.readTree(in); if (json.isObject()) { @@ -44,7 +44,7 @@ public JsonObj newJsonObj(InputStream in) { } @Override - public JsonArr newJsonArr(InputStream in) { + public JsonArr toJsonArr(InputStream in) { try { JsonNode json = objectMapper.readTree(in); if (json.isArray()) { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java index c4108c8b..094d60d4 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java @@ -8,17 +8,17 @@ public interface JsonService { /** * 解� JsonObj - * @param in 输入� + * @param in JSON 输入� * @return JsonObj */ - JsonObj newJsonObj(InputStream in); + JsonObj toJsonObj(InputStream in); /** * 解� JsonArr - * @param in 输入� + * @param in JSON 输入� * @return JsonArr */ - JsonArr newJsonArr(InputStream in); + JsonArr toJsonArr(InputStream in); /** * 将 Java 对象�列化为 Json 字符串 @@ -39,7 +39,7 @@ public interface JsonService { * 解� Java Bean * @param 目标泛型 * @param type 目标类型 - * @param in 输入� + * @param in JSON 输入� * @return Java Bean */ T jsonToBean(Class type, InputStream in); @@ -48,7 +48,7 @@ public interface JsonService { * 解�为 Java List * @param 目标泛型 * @param type 目标类型 - * @param in 输入� + * @param in JSON 输入� * @return Java List */ List jsonToList(Class type, InputStream in); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java index 14e7725a..44df2806 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java @@ -152,7 +152,7 @@ public JsonObj toJsonObj() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.jsonServiceNotNull().newJsonObj(toByteStream()); + return taskExecutor.jsonServiceNotNull().toJsonObj(toByteStream()); } @Override @@ -160,7 +160,7 @@ public JsonArr toJsonArr() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); } - return taskExecutor.jsonServiceNotNull().newJsonArr(toByteStream()); + return taskExecutor.jsonServiceNotNull().toJsonArr(toByteStream()); } @Override From 41a9f7951e88b3802b338bffeb171853bb96877f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 15:48:21 +0800 Subject: [PATCH 223/924] TestCases --- .../java/com/ejlchina/okhttps/DateBean.java | 40 ++++++ .../java/com/ejlchina/okhttps/TestCases.java | 88 ++++++++++++ .../test/java/com/ejlchina/okhttps/User.java | 66 +++++++++ .../java/com/ejlchina/okhttps/DateBean.java | 40 ++++++ .../java/com/ejlchina/okhttps/TestCase.java | 133 ------------------ .../java/com/ejlchina/okhttps/TestCases.java | 88 ++++++++++++ .../test/java/com/ejlchina/okhttps/User.java | 66 +++++++++ .../java/com/ejlchina/okhttps/DateBean.java | 40 ++++++ .../java/com/ejlchina/okhttps/TestCase.java | 117 --------------- .../java/com/ejlchina/okhttps/TestCases.java | 88 ++++++++++++ .../test/java/com/ejlchina/okhttps/User.java | 66 +++++++++ 11 files changed, 582 insertions(+), 250 deletions(-) create mode 100644 okhttps-fastjson/src/test/java/com/ejlchina/okhttps/DateBean.java create mode 100644 okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java create mode 100644 okhttps-fastjson/src/test/java/com/ejlchina/okhttps/User.java create mode 100644 okhttps-gson/src/test/java/com/ejlchina/okhttps/DateBean.java delete mode 100644 okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java create mode 100644 okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java create mode 100644 okhttps-gson/src/test/java/com/ejlchina/okhttps/User.java create mode 100644 okhttps-jackson/src/test/java/com/ejlchina/okhttps/DateBean.java delete mode 100644 okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java create mode 100644 okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java create mode 100644 okhttps-jackson/src/test/java/com/ejlchina/okhttps/User.java diff --git a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/DateBean.java b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/DateBean.java new file mode 100644 index 00000000..2e016c80 --- /dev/null +++ b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/DateBean.java @@ -0,0 +1,40 @@ +package com.ejlchina.okhttps; + +import java.util.Date; + +public class DateBean { + + private int id; + private Date date; + + + public DateBean() { + } + + public DateBean(int id, Date date) { + this.id = id; + this.date = date; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + @Override + public String toString() { + return "DateBean [id=" + id + ", date=" + date + "]"; + } + +} diff --git a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java new file mode 100644 index 00000000..c5657995 --- /dev/null +++ b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java @@ -0,0 +1,88 @@ +package com.ejlchina.okhttps; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + + +public class TestCases { + + JsonService jsonService = new FastJsonService(); + + @Test + public void testToJsonObj() { + String json = "{\"id\":1,\"name\":\"Jack\"}"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + JsonObj jsonObj = jsonService.toJsonObj(in); + Set keys = jsonObj.keySet(); + Assert.assertTrue(keys.size() == 2); + Assert.assertTrue(keys.contains("id")); + Assert.assertTrue(keys.contains("name")); + Assert.assertTrue(!jsonObj.isEmpty()); + Assert.assertTrue(2 == jsonObj.size()); + Assert.assertTrue(1 == jsonObj.getInt("id")); + Assert.assertTrue(!jsonObj.has("age")); + Assert.assertTrue(0 == jsonObj.getInt("age")); + Assert.assertEquals("Jack", jsonObj.getString("name")); + } + + @Test + public void testToJsonArr() { + String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + JsonArr jsonObj = jsonService.toJsonArr(in); + Assert.assertTrue(!jsonObj.isEmpty()); + Assert.assertTrue(jsonObj.size() == 2); + JsonObj json1 = jsonObj.getJsonOjb(0); + JsonObj json2 = jsonObj.getJsonOjb(1); + Assert.assertEquals(1, json1.getInt("id")); + Assert.assertEquals("Jack", json1.getString("name")); + Assert.assertEquals(2, json2.getInt("id")); + Assert.assertEquals("Tom", json2.getString("name")); + } + + @Test + public void testToJsonStr() { + String json = jsonService.toJsonStr(new User(1, "Jack")); + Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); + } + + @Test + public void testToJsonStrWithDateFormat() throws ParseException { + String dataFormat = "yyyy-MM-dd HH:mm:ss"; + SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); + String date = "2020-05-09 12:30:15"; + String json = jsonService.toJsonStr(new DateBean(1, sdf.parse(date)), dataFormat); + Assert.assertTrue(json.contains(date)); + } + + @Test + public void testJsonToBean() { + String json = "{\"id\":1,\"name\":\"Jack\"}"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + User user = jsonService.jsonToBean(User.class, in); + Assert.assertEquals(1, user.getId()); + Assert.assertEquals("Jack", user.getName()); + } + + @Test + public void testJsonToList() { + String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + List users = jsonService.jsonToList(User.class, in); + Assert.assertTrue(2 == users.size()); + User u1 = users.get(0); + User u2 = users.get(1); + Assert.assertEquals(1, u1.getId()); + Assert.assertEquals("Jack", u1.getName()); + Assert.assertEquals(2, u2.getId()); + Assert.assertEquals("Tom", u2.getName()); + } + +} diff --git a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/User.java b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/User.java new file mode 100644 index 00000000..1fcb6484 --- /dev/null +++ b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/User.java @@ -0,0 +1,66 @@ +package com.ejlchina.okhttps; + +public class User { + + private int id; + private String name; + + + public User() { + } + + public User(int id, String name) { + this.id = id; + this.name = name; + } + + public void setId(int id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + +} diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/DateBean.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/DateBean.java new file mode 100644 index 00000000..2e016c80 --- /dev/null +++ b/okhttps-gson/src/test/java/com/ejlchina/okhttps/DateBean.java @@ -0,0 +1,40 @@ +package com.ejlchina.okhttps; + +import java.util.Date; + +public class DateBean { + + private int id; + private Date date; + + + public DateBean() { + } + + public DateBean(int id, Date date) { + this.id = id; + this.date = date; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + @Override + public String toString() { + return "DateBean [id=" + id + ", date=" + date + "]"; + } + +} diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java deleted file mode 100644 index 232d096b..00000000 --- a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.ejlchina.okhttps; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -import org.junit.Test; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.reflect.TypeToken; - -public class TestCase { - - - Gson gson = new Gson(); - - @Test - public void test() { - - - User u1 = new User(1, "Tom"); - User u2 = new User(2, "Jack"); - List list = new ArrayList<>(); - list.add(u1); - list.add(u2); - - String json = gson.toJson(list); - - System.out.println("json = " + json); - -// User[] users = gson.fromJson(json, TypeToken.getArray(User.class).getType()); - - List users = jsonToList(User.class, json); - - System.out.println(users.get(0)); - System.out.println(users.get(0)); - } - - @Test - public void test2() { - User u1 = new User(1, "Tom"); - System.out.println(toJsonStr(u1, "yyyy-MM-dd HH:mm:ss")); - } - - @Test - public void test3() { - User u1 = new User(1, "Tom"); - String json = gson.toJson(u1); - System.out.println(json); - - JsonObject jsonObj = gson.fromJson(json, JsonObject.class); - - System.out.println(jsonObj); - System.out.println(jsonObj.get("id").getAsInt()); - System.out.println(jsonObj.get("name").getAsString()); - } - - @Test - public void test4() { - User u1 = new User(1, "Tom"); - User u2 = new User(2, "Jack"); - List list = new ArrayList<>(); - list.add(u1); - list.add(u2); - - String json = gson.toJson(list); - - JsonArray jsonArr = gson.fromJson(json, JsonArray.class); - - System.out.println(jsonArr); - System.out.println(jsonArr.get(0)); - System.out.println(jsonArr.get(1)); - } - - public List jsonToList(Class type, String json) { - T[] objs = gson.fromJson(json, TypeToken.getArray(type).getType()); - List list = new ArrayList<>(); - Collections.addAll(list, objs); - return list; - } - - - public String toJsonStr(Object bean, String dateFormat) { - return gson.newBuilder().setDateFormat(dateFormat).create().toJson(bean); - } - - - public static class User { - - private int id; - private String name; - private Date date = new Date(); - - public User() { - } - - public User(int id, String name) { - this.id = id; - this.name = name; - } - - public int getId() { - return id; - } - public void setId(int id) { - this.id = id; - } - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - @Override - public String toString() { - return "User [id=" + id + ", name=" + name + ", date=" + date + "]"; - } - - } - -} diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java new file mode 100644 index 00000000..ebf03180 --- /dev/null +++ b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java @@ -0,0 +1,88 @@ +package com.ejlchina.okhttps; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + + +public class TestCases { + + JsonService jsonService = new GsonService(); + + @Test + public void testToJsonObj() { + String json = "{\"id\":1,\"name\":\"Jack\"}"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + JsonObj jsonObj = jsonService.toJsonObj(in); + Set keys = jsonObj.keySet(); + Assert.assertTrue(keys.size() == 2); + Assert.assertTrue(keys.contains("id")); + Assert.assertTrue(keys.contains("name")); + Assert.assertTrue(!jsonObj.isEmpty()); + Assert.assertTrue(2 == jsonObj.size()); + Assert.assertTrue(1 == jsonObj.getInt("id")); + Assert.assertTrue(!jsonObj.has("age")); + Assert.assertTrue(0 == jsonObj.getInt("age")); + Assert.assertEquals("Jack", jsonObj.getString("name")); + } + + @Test + public void testToJsonArr() { + String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + JsonArr jsonObj = jsonService.toJsonArr(in); + Assert.assertTrue(!jsonObj.isEmpty()); + Assert.assertTrue(jsonObj.size() == 2); + JsonObj json1 = jsonObj.getJsonOjb(0); + JsonObj json2 = jsonObj.getJsonOjb(1); + Assert.assertEquals(1, json1.getInt("id")); + Assert.assertEquals("Jack", json1.getString("name")); + Assert.assertEquals(2, json2.getInt("id")); + Assert.assertEquals("Tom", json2.getString("name")); + } + + @Test + public void testToJsonStr() { + String json = jsonService.toJsonStr(new User(1, "Jack")); + Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); + } + + @Test + public void testToJsonStrWithDateFormat() throws ParseException { + String dataFormat = "yyyy-MM-dd HH:mm:ss"; + SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); + String date = "2020-05-09 12:30:15"; + String json = jsonService.toJsonStr(new DateBean(1, sdf.parse(date)), dataFormat); + Assert.assertTrue(json.contains(date)); + } + + @Test + public void testJsonToBean() { + String json = "{\"id\":1,\"name\":\"Jack\"}"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + User user = jsonService.jsonToBean(User.class, in); + Assert.assertEquals(1, user.getId()); + Assert.assertEquals("Jack", user.getName()); + } + + @Test + public void testJsonToList() { + String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + List users = jsonService.jsonToList(User.class, in); + Assert.assertTrue(2 == users.size()); + User u1 = users.get(0); + User u2 = users.get(1); + Assert.assertEquals(1, u1.getId()); + Assert.assertEquals("Jack", u1.getName()); + Assert.assertEquals(2, u2.getId()); + Assert.assertEquals("Tom", u2.getName()); + } + +} diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/User.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/User.java new file mode 100644 index 00000000..1fcb6484 --- /dev/null +++ b/okhttps-gson/src/test/java/com/ejlchina/okhttps/User.java @@ -0,0 +1,66 @@ +package com.ejlchina.okhttps; + +public class User { + + private int id; + private String name; + + + public User() { + } + + public User(int id, String name) { + this.id = id; + this.name = name; + } + + public void setId(int id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + +} diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/DateBean.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/DateBean.java new file mode 100644 index 00000000..2e016c80 --- /dev/null +++ b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/DateBean.java @@ -0,0 +1,40 @@ +package com.ejlchina.okhttps; + +import java.util.Date; + +public class DateBean { + + private int id; + private Date date; + + + public DateBean() { + } + + public DateBean(int id, Date date) { + this.id = id; + this.date = date; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + @Override + public String toString() { + return "DateBean [id=" + id + ", date=" + date + "]"; + } + +} diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java deleted file mode 100644 index 41d7dfce..00000000 --- a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.ejlchina.okhttps; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.junit.Test; - -import com.ejlchina.okhttps.internal.HttpException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.type.CollectionType; - -public class TestCase { - - - ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void test() throws JsonProcessingException { - - User u1 = new User(1, "Tom"); - - ObjectMapper mapper = objectMapper.copy(); - - mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - - mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); - - String json = mapper.writeValueAsString(u1); - - System.out.println("json = " + json); - - json = objectMapper.writeValueAsString(u1); - - System.out.println("json = " + json); - } - - - @Test - public void test1() throws JsonProcessingException { - - User u1 = new User(1, "Tom"); - User u2 = new User(2, "Jack"); - List list = new ArrayList<>(); - list.add(u1); - list.add(u2); - - String json = objectMapper.writeValueAsString(list); - - System.out.println("json = " + json); - - List nlist = jsonToList(User.class, json); - - System.out.println(nlist); - } - - - - public List jsonToList(Class type, String json) { - if (json != null) { - CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type); - try { - return objectMapper.readValue(json, javaType); - } catch (JsonProcessingException e) { - throw new HttpException("Jackson 解�异常:" + json, e); - } - } - return null; - } - - - public static class User { - - private int id; - private String name; - private Date date = new Date(); - - public User() { - } - - public User(int id, String name) { - this.id = id; - this.name = name; - } - - public int getId() { - return id; - } - public void setId(int id) { - this.id = id; - } - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - @Override - public String toString() { - return "User [id=" + id + ", name=" + name + ", date=" + date + "]"; - } - - } - -} diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java new file mode 100644 index 00000000..63953de4 --- /dev/null +++ b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java @@ -0,0 +1,88 @@ +package com.ejlchina.okhttps; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + + +public class TestCases { + + JsonService jsonService = new JacksonService(); + + @Test + public void testToJsonObj() { + String json = "{\"id\":1,\"name\":\"Jack\"}"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + JsonObj jsonObj = jsonService.toJsonObj(in); + Set keys = jsonObj.keySet(); + Assert.assertTrue(keys.size() == 2); + Assert.assertTrue(keys.contains("id")); + Assert.assertTrue(keys.contains("name")); + Assert.assertTrue(!jsonObj.isEmpty()); + Assert.assertTrue(2 == jsonObj.size()); + Assert.assertTrue(1 == jsonObj.getInt("id")); + Assert.assertTrue(!jsonObj.has("age")); + Assert.assertTrue(0 == jsonObj.getInt("age")); + Assert.assertEquals("Jack", jsonObj.getString("name")); + } + + @Test + public void testToJsonArr() { + String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + JsonArr jsonObj = jsonService.toJsonArr(in); + Assert.assertTrue(!jsonObj.isEmpty()); + Assert.assertTrue(jsonObj.size() == 2); + JsonObj json1 = jsonObj.getJsonOjb(0); + JsonObj json2 = jsonObj.getJsonOjb(1); + Assert.assertEquals(1, json1.getInt("id")); + Assert.assertEquals("Jack", json1.getString("name")); + Assert.assertEquals(2, json2.getInt("id")); + Assert.assertEquals("Tom", json2.getString("name")); + } + + @Test + public void testToJsonStr() { + String json = jsonService.toJsonStr(new User(1, "Jack")); + Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); + } + + @Test + public void testToJsonStrWithDateFormat() throws ParseException { + String dataFormat = "yyyy-MM-dd HH:mm:ss"; + SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); + String date = "2020-05-09 12:30:15"; + String json = jsonService.toJsonStr(new DateBean(1, sdf.parse(date)), dataFormat); + Assert.assertTrue(json.contains(date)); + } + + @Test + public void testJsonToBean() { + String json = "{\"id\":1,\"name\":\"Jack\"}"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + User user = jsonService.jsonToBean(User.class, in); + Assert.assertEquals(1, user.getId()); + Assert.assertEquals("Jack", user.getName()); + } + + @Test + public void testJsonToList() { + String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; + InputStream in = new ByteArrayInputStream(json.getBytes()); + List users = jsonService.jsonToList(User.class, in); + Assert.assertTrue(2 == users.size()); + User u1 = users.get(0); + User u2 = users.get(1); + Assert.assertEquals(1, u1.getId()); + Assert.assertEquals("Jack", u1.getName()); + Assert.assertEquals(2, u2.getId()); + Assert.assertEquals("Tom", u2.getName()); + } + +} diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/User.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/User.java new file mode 100644 index 00000000..1fcb6484 --- /dev/null +++ b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/User.java @@ -0,0 +1,66 @@ +package com.ejlchina.okhttps; + +public class User { + + private int id; + private String name; + + + public User() { + } + + public User(int id, String name) { + this.id = id; + this.name = name; + } + + public void setId(int id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + +} From e2bdada67bfc3bdc25f3df1abc5d6000db678aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 16:19:34 +0800 Subject: [PATCH 224/924] =?UTF-8?q?HTTP.builder()=20=E6=96=B0=E5=A2=9E=20p?= =?UTF-8?q?reprocTimeoutTimes=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 2 +- .../ejlchina/okhttps/internal/HttpClient.java | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index ae2ea2c7..d16e775c 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -780,7 +780,7 @@ protected void assertNotConflict(boolean isGetRequest) { */ protected boolean timeoutAwait(CountDownLatch latch) { try { - return latch.await(httpClient.totalTimeoutMillis() * 10, + return latch.await(httpClient.preprocTimeoutMillis(), TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new HttpException("超时", e); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 96dca4ef..c622552e 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -24,7 +24,8 @@ public class HttpClient implements HTTP { final Preprocessor[] preprocessors; // �有标签的任务 final List tagTasks; - + // 最大预处�时间�数(相对于普通请求的超时时间) + final int preprocTimeoutTimes; private HttpClient(Builder builder) { this.client = builder.client; @@ -35,6 +36,7 @@ private HttpClient(Builder builder) { builder.responseListener, builder.exceptionListener, builder.completeListener, builder.jsonService); this.preprocessors = builder.preprocessors.toArray(new Preprocessor[0]); + this.preprocTimeoutTimes = builder.preprocTimeoutTimes; this.tagTasks = new LinkedList<>(); } @@ -109,8 +111,10 @@ public OkHttpClient getOkClient() { return client; } - public int totalTimeoutMillis() { - return client.connectTimeoutMillis() + client.writeTimeoutMillis() + client.readTimeoutMillis(); + public int preprocTimeoutMillis() { + return preprocTimeoutTimes * (client.connectTimeoutMillis() + + client.writeTimeoutMillis() + + client.readTimeoutMillis()); } public int getTagTaskCount() { @@ -157,7 +161,7 @@ public class TagTask { boolean isExpired() { // 生存时间大于10�的总超时�值 - return System.nanoTime() - createAt > 10_000_000 * totalTimeoutMillis(); + return System.nanoTime() - createAt > 1_000_000 * preprocTimeoutMillis(); } public void setTag(String tag) { @@ -353,6 +357,8 @@ public static class Builder { private JsonService jsonService; + private int preprocTimeoutTimes = 10; + public Builder() { mediaTypes = new HashMap<>(); mediaTypes.put("*", "application/octet-stream"); @@ -383,6 +389,7 @@ private Builder(HttpClient hc) { this.exceptionListener = hc.executor.exceptionListener; this.completeListener = hc.executor.completeListener; this.jsonService = hc.executor.jsonService; + this.preprocTimeoutTimes = hc.preprocTimeoutTimes; } /** @@ -462,6 +469,19 @@ public Builder addSerialPreprocessor(Preprocessor preprocessor) { preprocessors.add(new SerialPreprocessor(preprocessor)); return this; } + + /** + * 最大预处�时间(�数,相当普通请求的超时时间) + * + * @param times 普通超时时间的�数,默认为 10 + * @return + */ + public Builder preprocTimeoutTimes(int times) { + if (times > 0) { + this.preprocTimeoutTimes = times; + } + return this; + } /** * 设置全局�应监� From 153f4b4fed97d5ba58b94efe1907ea7c08f8f102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 16:28:19 +0800 Subject: [PATCH 225/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ejlchina/okhttps/HttpTask.java | 16 ++++++++-------- .../ejlchina/okhttps/internal/AsyncHttpTask.java | 2 +- .../ejlchina/okhttps/internal/HttpClient.java | 8 ++++---- .../ejlchina/okhttps/internal/SyncHttpTask.java | 2 +- .../ejlchina/okhttps/internal/WebSocketTask.java | 3 +-- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index d16e775c..10a6060e 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -62,8 +62,8 @@ public abstract class HttpTask> implements Cancelable { private TagTask tagTask; private Cancelable canceler; - protected boolean noPreprocess = false; - protected boolean noSerialPreprocess = false; + protected boolean skipPreproc = false; + protected boolean skipSerialPreproc = false; public HttpTask(HttpClient httpClient, String url) { @@ -127,20 +127,20 @@ public C nothrow() { } /** - * 指定该请求��过任何预处�器 + * 指定该请求跳过任何预处�器(包括串行和并行) * @return HttpTask 实例 */ - public C noPreprocess() { - this.noPreprocess = true; + public C skipPreproc() { + this.skipPreproc = true; return (C) this; } /** - * 指定该请求��过并行预处�器 + * 指定该请求跳过任何串行预处�器 * @return HttpTask 实例 */ - public C noSerialPreprocess() { - this.noSerialPreprocess = true; + public C skipSerialPreproc() { + this.skipSerialPreproc = true; return (C) this; } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 2fb42b88..8fd8c0ec 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -120,7 +120,7 @@ public HttpCall request(String method) { call.setCall(executeCall(prepareCall(method))); } } - }, noPreprocess, noSerialPreprocess); + }, skipPreproc, skipSerialPreproc); return call; } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index c622552e..958a841f 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -184,13 +184,13 @@ public TaskExecutor getExecutor() { } public void preprocess(HttpTask> httpTask, Runnable request, - boolean noPreprocess, boolean noSerialPreprocess) { - if (preprocessors.length == 0 || noPreprocess) { + boolean skipPreproc, boolean skipSerialPreproc) { + if (preprocessors.length == 0 || skipPreproc) { request.run(); return; } int index = 0; - if (noSerialPreprocess) { + if (skipSerialPreproc) { while (index < preprocessors.length && preprocessors[index] instanceof SerialPreprocessor) { index++; @@ -199,7 +199,7 @@ public void preprocess(HttpTask> httpTask, Runnable reques if (index < preprocessors.length) { RealPreChain chain = new RealPreChain(preprocessors, httpTask, request, index + 1, - noSerialPreprocess); + skipSerialPreproc); preprocessors[index].doProcess(chain); } else { request.run(); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index ba931fce..f93f4a96 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -86,7 +86,7 @@ public HttpResult request(String method) { } finally { latch.countDown(); } - }, noPreprocess, noSerialPreprocess); + }, skipPreproc, skipSerialPreproc); boolean timeout = false; if (result.getState() == null) { timeout = !timeoutAwait(latch); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 7a36e24a..3f901785 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -39,7 +39,7 @@ public WebSocket listen() { socket.setWebSocket(httpClient.webSocket(request, listener)); } } - }, noPreprocess, noSerialPreprocess); + }, skipPreproc, skipSerialPreproc); return socket; } @@ -169,7 +169,6 @@ public boolean send(byte[] data) { return true; } - void queueMsgToSend(Object msg) { if (msg == null) { From dbf9bf56362fdad0a3146b5c746310573fc5cb6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 17:11:21 +0800 Subject: [PATCH 226/924] =?UTF-8?q?=E5=85=BC=E5=AE=B9=20fastjson=20android?= =?UTF-8?q?=20=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/ejlchina/okhttps/FastJsonService.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java index 7cd6436a..8f0c57fe 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java @@ -45,11 +45,7 @@ public String toJsonStr(Object bean, String dateFormat) { @Override public T jsonToBean(Class type, InputStream in) { - try { - return JSON.parseObject(in, type); - } catch (IOException e) { - throw new HttpException("读�文本异常", e); - } + return JSON.parseObject(toString(in), type); } @Override From f9493085205c30361f3197fcf0bd59b6872f657a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 19:42:58 +0800 Subject: [PATCH 227/924] =?UTF-8?q?=E7=AE=80=E5=8C=96=20WebSocekt=20?= =?UTF-8?q?=E7=BC=96=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/WebSocket.java | 103 +++++++++++++++++- .../okhttps/internal/AbstractBody.java | 53 +++++++++ .../okhttps/internal/MessageBody.java | 81 ++++++++++++++ .../ejlchina/okhttps/internal/ResultBody.java | 40 +------ .../okhttps/internal/WebSocketTask.java | 71 ++++++++++-- 5 files changed, 300 insertions(+), 48 deletions(-) create mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java create mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java index f8cb6e39..1aee7154 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java @@ -1,19 +1,118 @@ package com.ejlchina.okhttps; +import java.io.InputStream; +import java.io.Reader; +import java.util.List; + import okio.ByteString; public interface WebSocket extends Cancelable { + public interface Message { + + /** + * 判断是文本消�还是二进制消� + * @return 是�是文本消� + */ + boolean isText(); + + /** + * @return 消�体转字节� + */ + InputStream toByteStream(); + + /** + * @return 消�体转字节数组 + */ + byte[] toBytes(); + + /** + * @return ByteString + */ + ByteString toByteString(); + + /** + * @return 消�体转字符� + */ + Reader toCharStream(); + + /** + * @return 消�体转字符串 + */ + String toString(); + + /** + * @return 消�体转Json对象 + */ + JsonObj toJsonObj(); + + /** + * @return 消�体转Json数组 + */ + JsonArr toJsonArr(); + + /** + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean + */ + T toBean(Class type); + + /** + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean列表 + */ + List toList(Class type); + + } + + + public static class Close { + + private int code; + private String reason; + + public Close(int code, String reason) { + this.code = code; + this.reason = reason; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + @Override + public String toString() { + return "Close [code=" + code + ", reason=" + reason + "]"; + } + } + + public interface Listener { void on(WebSocket ws, T data); } - /** - * � {@link okhttp3.WebSocket#queueSize()} + * 若连接已打开,则: + * � {@link okhttp3.WebSocket#queueSize()},返回排�消�的字节数 + * �则: + * 返回排队消�的数� */ long queueSize(); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java new file mode 100644 index 00000000..d3a0a78e --- /dev/null +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java @@ -0,0 +1,53 @@ +package com.ejlchina.okhttps.internal; + +import java.io.InputStream; +import java.util.List; + +import com.ejlchina.okhttps.JsonArr; +import com.ejlchina.okhttps.JsonObj; + +public abstract class AbstractBody { + + + protected TaskExecutor taskExecutor; + + + public AbstractBody(TaskExecutor taskExecutor) { + this.taskExecutor = taskExecutor; + } + + public abstract InputStream toByteStream(); + + + public JsonObj toJsonObj() { + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); + } + return taskExecutor.jsonServiceNotNull().toJsonObj(toByteStream()); + } + + + public JsonArr toJsonArr() { + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); + } + return taskExecutor.jsonServiceNotNull().toJsonArr(toByteStream()); + } + + + public T toBean(Class type) { + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); + } + return taskExecutor.jsonServiceNotNull().jsonToBean(type, toByteStream()); + } + + + public List toList(Class type) { + if (taskExecutor == null) { + throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); + } + return taskExecutor.jsonServiceNotNull().jsonToList(type, toByteStream()); + } + +} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java new file mode 100644 index 00000000..b3a9e2aa --- /dev/null +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java @@ -0,0 +1,81 @@ +package com.ejlchina.okhttps.internal; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +import com.ejlchina.okhttps.WebSocket.Message; + +import okio.ByteString; + +public class MessageBody extends AbstractBody implements Message { + + private String text; + private ByteString bytes; + + + public MessageBody(String text, TaskExecutor taskExecutor) { + super(taskExecutor); + this.text = text; + } + + public MessageBody(ByteString bytes, TaskExecutor taskExecutor) { + super(taskExecutor); + this.bytes = bytes; + } + + @Override + public boolean isText() { + return text != null; + } + + @Override + public byte[] toBytes() { + if (text != null) { + return text.getBytes(StandardCharsets.UTF_8); + } + if (bytes != null) { + return bytes.toByteArray(); + } + return null; + } + + @Override + public ByteString toByteString() { + if (text != null) { + return ByteString.encodeUtf8(text); + } + return bytes; + } + + @Override + public Reader toCharStream() { + return new InputStreamReader(toByteStream()); + } + + @Override + public InputStream toByteStream() { + if (text != null) { + return new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)); + } + if (bytes != null) { + ByteBuffer buffer = bytes.asByteBuffer(); + return new InputStream() { + + @Override + public int read() throws IOException { + if (buffer.hasRemaining()) { + return buffer.get(); + } + return -1; + } + }; + } + return null; + } + +} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java index 44df2806..9bafee28 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java @@ -12,13 +12,10 @@ import java.net.HttpURLConnection; import java.net.URLDecoder; import java.nio.charset.Charset; -import java.util.List; import com.ejlchina.okhttps.Download; import com.ejlchina.okhttps.HttpResult.Body; import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.JsonArr; -import com.ejlchina.okhttps.JsonObj; import com.ejlchina.okhttps.OnCallback; import com.ejlchina.okhttps.Process; @@ -26,10 +23,9 @@ import okhttp3.Response; import okio.Buffer; -public class ResultBody implements Body { +public class ResultBody extends AbstractBody implements Body { private Response response; - private TaskExecutor taskExecutor; private boolean onIO = false; private OnCallback onProcess; private long stepBytes = 0; @@ -40,9 +36,9 @@ public class ResultBody implements Body { private byte[] data; ResultBody(HttpTask httpTask, Response response, TaskExecutor taskExecutor) { + super(taskExecutor); this.httpTask = httpTask; this.response = response; - this.taskExecutor = taskExecutor; } @Override @@ -147,38 +143,6 @@ public String toString() { } } - @Override - public JsonObj toJsonObj() { - if (taskExecutor == null) { - throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); - } - return taskExecutor.jsonServiceNotNull().toJsonObj(toByteStream()); - } - - @Override - public JsonArr toJsonArr() { - if (taskExecutor == null) { - throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); - } - return taskExecutor.jsonServiceNotNull().toJsonArr(toByteStream()); - } - - @Override - public T toBean(Class type) { - if (taskExecutor == null) { - throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); - } - return taskExecutor.jsonServiceNotNull().jsonToBean(type, toByteStream()); - } - - @Override - public List toList(Class type) { - if (taskExecutor == null) { - throw new IllegalStateException("没有 taskExecutor,��� Json 转��"); - } - return taskExecutor.jsonServiceNotNull().jsonToList(type, toByteStream()); - } - @Override public Download toFile(String filePath) { return toFile(new File(filePath)); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 3f901785..1edd2010 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -6,7 +6,9 @@ import com.ejlchina.okhttps.HttpResult; import com.ejlchina.okhttps.HttpTask; import com.ejlchina.okhttps.WebSocket; +import com.ejlchina.okhttps.WebSocket.Close; import com.ejlchina.okhttps.WebSocket.Listener; +import com.ejlchina.okhttps.WebSocket.Message; import okhttp3.Request; import okhttp3.Response; @@ -17,8 +19,11 @@ public class WebSocketTask extends HttpTask { - private Listener onOnen; + private Listener onOpen; private Listener onException; + private Listener onMessage; + private Listener onClosing; + private Listener onClosed; public WebSocketTask(HttpClient httpClient, String url) { @@ -54,30 +59,40 @@ public MessageListener(WebSocket webSocket) { @Override public void onOpen(okhttp3.WebSocket webSocket, Response response) { - if (onOnen != null) { + if (onOpen != null) { HttpResult result = new RealHttpResult(WebSocketTask.this, response, httpClient.executor); - onOnen.on(this.webSocket, result); + onOpen.on(this.webSocket, result); } } + // 接收文本数� 仅当 websocket 消�中的 opcode == 1 时 @Override public void onMessage(okhttp3.WebSocket webSocket, String text) { - // TODO Auto-generated method stub + if (onMessage != null) { + onMessage.on(this.webSocket, new MessageBody(text, httpClient.executor)); + } } + // 接收二进制数� 仅当 websocket 消�中的 opcode == 2 时 @Override public void onMessage(okhttp3.WebSocket webSocket, ByteString bytes) { - // TODO Auto-generated method stub + if (onMessage != null) { + onMessage.on(this.webSocket, new MessageBody(bytes, httpClient.executor)); + } } @Override public void onClosing(okhttp3.WebSocket webSocket, int code, String reason) { - // TODO Auto-generated method stub + if (onClosing != null) { + onClosing.on(this.webSocket, new Close(code, reason)); + } } @Override public void onClosed(okhttp3.WebSocket webSocket, int code, String reason) { - // TODO Auto-generated method stub + if (onClosed != null) { + onClosed.on(this.webSocket, new Close(code, reason)); + } } @Override @@ -129,7 +144,7 @@ public long queueSize() { if (webSocket != null) { return webSocket.queueSize(); } - return 0; + return queues.size(); } @Override @@ -213,4 +228,44 @@ boolean send(okhttp3.WebSocket webSocket, Object msg) { } + /** + * 连接打开监� + * @param onOpen 监�器 + */ + public void setOnOpen(Listener onOpen) { + this.onOpen = onOpen; + } + + /** + * 连接异常监� + * @param onException 监�器 + */ + public void setOnException(Listener onException) { + this.onException = onException; + } + + /** + * 消�监� + * @param onTextMessage 监�器 + */ + public void setOnTextMessage(Listener onMessage) { + this.onMessage = onMessage; + } + + /** + * 正在关闭监� + * @param onClosing 监�器 + */ + public void setOnClosing(Listener onClosing) { + this.onClosing = onClosing; + } + + /** + * 已关闭监� + * @param onClosed 监�器 + */ + public void setOnClosed(Listener onClosed) { + this.onClosed = onClosed; + } + } From 43b149afab6c0b41891a7939dbd84445d1154d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 19:46:17 +0800 Subject: [PATCH 228/924] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/internal/WebSocketTask.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 1edd2010..ea88a090 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -30,7 +30,10 @@ public WebSocketTask(HttpClient httpClient, String url) { super(httpClient, url); } - + /** + * �动 WebSocket 监� + * @return WebSocket + */ public WebSocket listen() { WebSocketImpl socket = new WebSocketImpl(httpClient.executor); registeTagTask(socket); From 74bf97cd4541a0db46349bcc17478f15e25cc2fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 19:59:06 +0800 Subject: [PATCH 229/924] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=20HTTP#sync()=20?= =?UTF-8?q?=E5=92=8C=20HTTP#async()=20=E6=96=B9=E6=B3=95=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=20HTTP#sync(null)=20=E5=92=8C=20HTTP#async(n?= =?UTF-8?q?ull)=20=E4=BB=A3=E6=9B=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ejlchina/okhttps/HTTP.java | 26 +++++-------------- .../java/com/ejlchina/okhttps/HttpUtils.java | 16 ------------ .../ejlchina/okhttps/internal/HttpClient.java | 18 +++++-------- 3 files changed, 14 insertions(+), 46 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index 12218242..93aec89c 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -18,31 +18,19 @@ */ public interface HTTP { - /** - * 异步请求 - * @param url 请求地� - * @return 异步HTTP任务 - */ - AsyncHttpTask async(String url); - - /** - * 异步请求 - * @return 异步HTTP任务 - */ - AsyncHttpTask async(); - /** * �步请求 * @param url 请求地� * @return �步HTTP任务 */ SyncHttpTask sync(String url); - + /** - * �步请求 - * @return �步HTTP任务 + * 异步请求 + * @param url 请求地� + * @return 异步HTTP任务 */ - SyncHttpTask sync(); + AsyncHttpTask async(String url); /** * Websocket 连接 @@ -66,14 +54,14 @@ public interface HTTP { void cancelAll(); /** - * OkHttp 原生请求 (该请求��过 预处�器) + * OkHttp 的 HTTP 原生请求 (该请求��过 预处�器) * @param request 请求 * @return Call */ Call request(Request request); /** - * Websocket(该请求��过 预处�器) + * OkHttp 的 Websocket 原生请求(该请求��过 预处�器) * * @param request 请求 * @param listener 监�器 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java index ae36b8f2..99936b22 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -59,14 +59,6 @@ public static AsyncHttpTask async(String url) { return getHttp().async(url); } - /** - * 异步请求 - * @return 异步 HttpTask - */ - public static AsyncHttpTask async() { - return getHttp().async(); - } - /** * �步请求 * @param url 请求地� @@ -76,14 +68,6 @@ public static SyncHttpTask sync(String url) { return getHttp().sync(url); } - /** - * �步请求 - * @return �步 HttpTask - */ - public static SyncHttpTask sync() { - return getHttp().sync(); - } - /** * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 * @param tag 标签 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 958a841f..2502ab72 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -40,21 +40,11 @@ private HttpClient(Builder builder) { this.tagTasks = new LinkedList<>(); } - @Override - public AsyncHttpTask async() { - return async(null); - } - @Override public AsyncHttpTask async(String url) { return new AsyncHttpTask(this, urlPath(url)); } - @Override - public SyncHttpTask sync() { - return sync(null); - } - @Override public SyncHttpTask sync(String url) { return new SyncHttpTask(this, urlPath(url)); @@ -62,7 +52,13 @@ public SyncHttpTask sync(String url) { @Override public WebSocketTask webSocket(String url) { - return new WebSocketTask(this, urlPath(url)); + String path = urlPath(url); + if (path.startsWith("https://")) { + path = path.replace("https://", "wss://"); + } else if (path.startsWith("http://")) { + path = path.replace("http://", "ws://"); + } + return new WebSocketTask(this, path); } @Override From 8786fe23032166e57a0f185c22331685e8eb420e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 23:00:34 +0800 Subject: [PATCH 230/924] =?UTF-8?q?=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps-fastjson/pom.xml | 2 +- okhttps-gson/pom.xml | 2 +- okhttps-jackson/pom.xml | 2 +- okhttps-kotlin/pom.xml | 2 +- .../java/com/ejlchina/okhttps/JsonArr.java | 4 ++-- .../java/com/ejlchina/okhttps/WebSocket.java | 4 ++++ .../ejlchina/okhttps/internal/HttpClient.java | 2 +- .../okhttps/internal/SyncHttpTask.java | 2 +- .../okhttps/internal/WebSocketTask.java | 22 ++++++++++++++----- pom.xml | 3 ++- 10 files changed, 30 insertions(+), 15 deletions(-) diff --git a/okhttps-fastjson/pom.xml b/okhttps-fastjson/pom.xml index a68e2685..2ce76aa4 100644 --- a/okhttps-fastjson/pom.xml +++ b/okhttps-fastjson/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - ${okhttps.version} + 2.0.0 diff --git a/okhttps-gson/pom.xml b/okhttps-gson/pom.xml index 7d511711..3fefaaf1 100644 --- a/okhttps-gson/pom.xml +++ b/okhttps-gson/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - ${okhttps.version} + 2.0.0 diff --git a/okhttps-jackson/pom.xml b/okhttps-jackson/pom.xml index 381ca8d1..62d867ec 100644 --- a/okhttps-jackson/pom.xml +++ b/okhttps-jackson/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - ${okhttps.version} + 2.0.0 diff --git a/okhttps-kotlin/pom.xml b/okhttps-kotlin/pom.xml index 48cdb7ed..799eef8c 100644 --- a/okhttps-kotlin/pom.xml +++ b/okhttps-kotlin/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - ${okhttps.version} + 2.0.0 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java index 063fb7fe..e9782b66 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java @@ -64,13 +64,13 @@ public interface JsonArr { String getString(int index); /** - * @param key 键� + * @param index 元素下标 * @return BigDecimal 值 */ BigDecimal getBigDecimal(int index); /** - * @param key 键� + * @param index 元素下标 * @return BigInteger 值 */ BigInteger getBigInteger(int index); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java index 1aee7154..fad33e60 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java @@ -118,11 +118,15 @@ public interface Listener { /** * � {@link okhttp3.WebSocket#send(String)} + * @param text 文本数� + * @return 是��以�� */ boolean send(String text); /** * � {@link okhttp3.WebSocket#send(ByteString)} + * @param bytes 二进制数� + * @return 是��以�� */ boolean send(ByteString bytes); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 2502ab72..923b470e 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -470,7 +470,7 @@ public Builder addSerialPreprocessor(Preprocessor preprocessor) { * 最大预处�时间(�数,相当普通请求的超时时间) * * @param times 普通超时时间的�数,默认为 10 - * @return + * @return Builder */ public Builder preprocTimeoutTimes(int times) { if (times > 0) { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index f93f4a96..f574880f 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -57,7 +57,7 @@ public HttpResult delete() { /** * �起 HTTP 请求 - * @param method + * @param method 请求方法 * @return 请求结果 */ public HttpResult request(String method) { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index ea88a090..b0da5adc 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -234,41 +234,51 @@ boolean send(okhttp3.WebSocket webSocket, Object msg) { /** * 连接打开监� * @param onOpen 监�器 + * @return WebSocketTask */ - public void setOnOpen(Listener onOpen) { + public WebSocketTask setOnOpen(Listener onOpen) { this.onOpen = onOpen; + return this; } /** * 连接异常监� * @param onException 监�器 + * @return WebSocketTask */ - public void setOnException(Listener onException) { + public WebSocketTask setOnException(Listener onException) { this.onException = onException; + return this; } /** * 消�监� - * @param onTextMessage 监�器 + * @param onMessage 监�器 + * @return WebSocketTask */ - public void setOnTextMessage(Listener onMessage) { + public WebSocketTask setOnTextMessage(Listener onMessage) { this.onMessage = onMessage; + return this; } /** * 正在关闭监� * @param onClosing 监�器 + * @return WebSocketTask */ - public void setOnClosing(Listener onClosing) { + public WebSocketTask setOnClosing(Listener onClosing) { this.onClosing = onClosing; + return this; } /** * 已关闭监� * @param onClosed 监�器 + * @return WebSocketTask */ - public void setOnClosed(Listener onClosed) { + public WebSocketTask setOnClosed(Listener onClosed) { this.onClosed = onClosed; + return this; } } diff --git a/pom.xml b/pom.xml index 59c0f71d..9975fd79 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.ejlchina okhttps-parent - ${okhttps.version} + 2.0.0 OkHttps pom @@ -113,6 +113,7 @@ org.apache.maven.plugins maven-compiler-plugin + 3.8.1 ${java-version} ${java-version} From a04a03df8ea65bc4cb7562acf1d884c8160baabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 23:03:42 +0800 Subject: [PATCH 231/924] ignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5a66362c..ea5b62f4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ /*/node_modules/ /*/.vuepress/dist/* /*/*.iml +**.versionsBackup +/target/ *.iml /.idea/ .settings/ From 3051ae2a22faa266f3e5bdb376153c3f5338a00e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 23:04:48 +0800 Subject: [PATCH 232/924] delete kotlin --- okhttps-kotlin/pom.xml | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 okhttps-kotlin/pom.xml diff --git a/okhttps-kotlin/pom.xml b/okhttps-kotlin/pom.xml deleted file mode 100644 index 799eef8c..00000000 --- a/okhttps-kotlin/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - 4.0.0 - - okhttps-kotlin - OkHttps Kotlin - jar - - - com.ejlchina - okhttps-parent - 2.0.0 - - - - - com.ejlchina - okhttps - ${okhttps.version} - - - - - okhttps-kotlin - - \ No newline at end of file From 696b2acad9d02ca3c76ef372b4e32721ea99becf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Sat, 9 May 2020 23:05:05 +0800 Subject: [PATCH 233/924] modules --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9975fd79..5440f01d 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,6 @@ okhttps-fastjson okhttps-gson okhttps-jackson - okhttps-kotlin From e69bd8c94a0f700d1019f60db90e42b265cef49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 00:48:17 +0800 Subject: [PATCH 234/924] baidu-tongji --- okhttps-doc/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/okhttps-doc/package.json b/okhttps-doc/package.json index cfbe1cec..f9d1f6a9 100644 --- a/okhttps-doc/package.json +++ b/okhttps-doc/package.json @@ -7,6 +7,7 @@ "@vuepress/plugin-back-to-top": "^1.4.1", "vuepress": "^1.4.1", "vuepress-plugin-baidu-autopush": "^1.0.1", + "vuepress-plugin-baidu-tongji": "^1.0.1", "vuepress-plugin-seo": "^0.1.2" }, "dependencies": { From 4f795193ba3ceb4d4157f85eded9766f6bf03240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 13:45:28 +0800 Subject: [PATCH 235/924] =?UTF-8?q?MessageBody=20=E5=AE=9E=E7=8E=B0=20toSt?= =?UTF-8?q?ring=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ejlchina/okhttps/internal/MessageBody.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java index b3a9e2aa..4da07e39 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java @@ -44,6 +44,17 @@ public byte[] toBytes() { return null; } + @Override + public String toString() { + if (text != null) { + return text; + } + if (bytes != null) { + return bytes.utf8(); + } + return null; + } + @Override public ByteString toByteString() { if (text != null) { From 565c8a9b0eab923ca0caf1acfbd1a60ea6a487b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 13:45:55 +0800 Subject: [PATCH 236/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ejlchina/okhttps/internal/HttpClient.java | 44 +++++++++++-------- .../okhttps/internal/WebSocketTask.java | 2 +- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 923b470e..75e9de3d 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -42,23 +42,17 @@ private HttpClient(Builder builder) { @Override public AsyncHttpTask async(String url) { - return new AsyncHttpTask(this, urlPath(url)); + return new AsyncHttpTask(this, urlPath(url, false)); } @Override public SyncHttpTask sync(String url) { - return new SyncHttpTask(this, urlPath(url)); + return new SyncHttpTask(this, urlPath(url, false)); } @Override public WebSocketTask webSocket(String url) { - String path = urlPath(url); - if (path.startsWith("https://")) { - path = path.replace("https://", "wss://"); - } else if (path.startsWith("http://")) { - path = path.replace("http://", "ws://"); - } - return new WebSocketTask(this, path); + return new WebSocketTask(this, urlPath(url, true)); } @Override @@ -311,22 +305,34 @@ public Builder newBuilder() { return new Builder(this); } - private String urlPath(String urlPath) { + private String urlPath(String urlPath, boolean websocket) { + String fullUrl; if (urlPath == null) { if (baseUrl != null) { - return baseUrl; + fullUrl = baseUrl; + } else { + throw new HttpException("在设置 BaseUrl 之�,您必须指定具体路径�能�起请求�"); + } + } else { + boolean isFullPath = urlPath.startsWith("https://") + || urlPath.startsWith("http://") + || urlPath.startsWith("wss://") + || urlPath.startsWith("ws://"); + if (isFullPath) { + fullUrl = urlPath; + } else if (baseUrl != null) { + fullUrl = baseUrl + urlPath; + } else { + throw new HttpException("在设置 BaseUrl 之�,您必须使用全路径URL�起请求,当�URL为:" + urlPath); } - throw new HttpException("在设置 BaseUrl 之�,您必须指定具体路径�能�起请求�"); } - boolean isFullPath = urlPath.startsWith("https://") - || urlPath.startsWith("http://"); - if (isFullPath) { - return urlPath; + if (websocket && fullUrl.startsWith("http")) { + return fullUrl.replaceFirst("http", "ws"); } - if (baseUrl != null) { - return baseUrl + urlPath; + if (!websocket && fullUrl.startsWith("ws")) { + return fullUrl.replaceFirst("ws", "http"); } - throw new HttpException("在设置 BaseUrl 之�,您必须使用全路径URL�起请求,当�URL为:" + urlPath); + return fullUrl; } public static class Builder { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index b0da5adc..c4a31090 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -256,7 +256,7 @@ public WebSocketTask setOnException(Listener onException) { * @param onMessage 监�器 * @return WebSocketTask */ - public WebSocketTask setOnTextMessage(Listener onMessage) { + public WebSocketTask setOnMessage(Listener onMessage) { this.onMessage = onMessage; return this; } From b44acebc946de32c67edfa1a8cc31bd063fcefc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 14:24:19 +0800 Subject: [PATCH 237/924] =?UTF-8?q?HttpUtils=20=E8=87=AA=E5=8A=A8=E5=AF=BB?= =?UTF-8?q?=E6=89=BE=20JsonService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpUtils.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java index 99936b22..9aac93b5 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -46,10 +46,32 @@ static synchronized HTTP getHttp() { if (http != null) { return http; } - http = HTTP.builder().build(); + http = HTTP.builder().jsonService(findJsonService(new String[] { + "com.ejlchina.okhttps.GsonService", + "com.ejlchina.okhttps.FastJsonService", + "com.ejlchina.okhttps.JacksonService" + }, 0)).build(); return http; } + static JsonService findJsonService(String[] classes, int index) { + if (index >= classes.length) { + return null; + } + Class clazz = null; + try { + clazz = Class.forName(classes[0]); + } catch (Exception ignore) {} + if (clazz == null || !JsonService.class.isAssignableFrom(clazz)) { + return findJsonService(classes, index + 1); + } + try { + return (JsonService) clazz.getDeclaredConstructor().newInstance(); + } catch (Exception ignore) { + return null; + } + } + /** * 异步请求 * @param url 请求地� From e321ed3dbca91f4f1737324407d35e2089097d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 14:34:03 +0800 Subject: [PATCH 238/924] . --- okhttps-doc/.gitignore | 5 + okhttps-doc/docs/.vuepress/dist/404.html | 19 -- .../dist/assets/css/0.styles.86d9e6f9.css | 1 - .../dist/assets/img/search.83621669.svg | 1 - .../.vuepress/dist/assets/js/10.bc5e580e.js | 1 - .../.vuepress/dist/assets/js/11.152d132f.js | 1 - .../.vuepress/dist/assets/js/12.92e24a16.js | 1 - .../.vuepress/dist/assets/js/13.d857e269.js | 1 - .../.vuepress/dist/assets/js/2.16cbe9f2.js | 1 - .../.vuepress/dist/assets/js/3.972ca2ed.js | 1 - .../.vuepress/dist/assets/js/4.fe3bf0b0.js | 1 - .../.vuepress/dist/assets/js/5.93d38f11.js | 1 - .../.vuepress/dist/assets/js/6.fd474f39.js | 1 - .../.vuepress/dist/assets/js/7.51e5642d.js | 1 - .../.vuepress/dist/assets/js/8.d296d289.js | 1 - .../.vuepress/dist/assets/js/9.bff804f8.js | 1 - .../.vuepress/dist/assets/js/app.1e2fa6f5.js | 13 -- .../docs/.vuepress/dist/guide/android.html | 161 --------------- .../.vuepress/dist/guide/configuration.html | 137 ------------ .../docs/.vuepress/dist/guide/features.html | 150 -------------- .../docs/.vuepress/dist/guide/foundation.html | 130 ------------ .../docs/.vuepress/dist/guide/index.html | 79 ------- .../docs/.vuepress/dist/guide/updown.html | 195 ------------------ okhttps-doc/docs/.vuepress/dist/index.html | 72 ------- okhttps-doc/docs/.vuepress/dist/logo.png | Bin 5800 -> 0 bytes .../java/com/ejlchina/test/SimpleTests.java | 16 +- .../com/ejlchina/test/WebSocketTests.java | 50 +++++ 27 files changed, 64 insertions(+), 977 deletions(-) create mode 100644 okhttps-doc/.gitignore delete mode 100644 okhttps-doc/docs/.vuepress/dist/404.html delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/css/0.styles.86d9e6f9.css delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/img/search.83621669.svg delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/10.bc5e580e.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/11.152d132f.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/12.92e24a16.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/13.d857e269.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/2.16cbe9f2.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/3.972ca2ed.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/4.fe3bf0b0.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/5.93d38f11.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/6.fd474f39.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/7.51e5642d.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/8.d296d289.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/9.bff804f8.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/assets/js/app.1e2fa6f5.js delete mode 100644 okhttps-doc/docs/.vuepress/dist/guide/android.html delete mode 100644 okhttps-doc/docs/.vuepress/dist/guide/configuration.html delete mode 100644 okhttps-doc/docs/.vuepress/dist/guide/features.html delete mode 100644 okhttps-doc/docs/.vuepress/dist/guide/foundation.html delete mode 100644 okhttps-doc/docs/.vuepress/dist/guide/index.html delete mode 100644 okhttps-doc/docs/.vuepress/dist/guide/updown.html delete mode 100644 okhttps-doc/docs/.vuepress/dist/index.html delete mode 100644 okhttps-doc/docs/.vuepress/dist/logo.png create mode 100644 okhttps/src/test/java/com/ejlchina/test/WebSocketTests.java diff --git a/okhttps-doc/.gitignore b/okhttps-doc/.gitignore new file mode 100644 index 00000000..e2a59199 --- /dev/null +++ b/okhttps-doc/.gitignore @@ -0,0 +1,5 @@ +/package-lock.json +/node_modules/ +/docs/.vuepress/dist/ +/docs/.vuepress/dist/* +docs/.vuepress/dist/* \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/404.html b/okhttps-doc/docs/.vuepress/dist/404.html deleted file mode 100644 index 8d2b3afc..00000000 --- a/okhttps-doc/docs/.vuepress/dist/404.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - OkHttps - - - - - - - -

404

That's a Four-Oh-Four.
- Take me home. -
- - - diff --git a/okhttps-doc/docs/.vuepress/dist/assets/css/0.styles.86d9e6f9.css b/okhttps-doc/docs/.vuepress/dist/assets/css/0.styles.86d9e6f9.css deleted file mode 100644 index 355d531c..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/css/0.styles.86d9e6f9.css +++ /dev/null @@ -1 +0,0 @@ -#nprogress{pointer-events:none}#nprogress .bar{background:#3eaf7c;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #3eaf7c,0 0 5px #3eaf7c;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border-color:#3eaf7c transparent transparent #3eaf7c;border-style:solid;border-width:2px;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}html{scroll-behavior:smooth}.go-to-top[data-v-5fd4ef0c]{cursor:pointer;position:fixed;bottom:2rem;right:2.5rem;width:2rem;color:#3eaf7c;z-index:1}.go-to-top[data-v-5fd4ef0c]:hover{color:#72cda4}@media (max-width:959px){.go-to-top[data-v-5fd4ef0c]{display:none}}.fade-enter-active[data-v-5fd4ef0c],.fade-leave-active[data-v-5fd4ef0c]{transition:opacity .3s}.fade-enter[data-v-5fd4ef0c],.fade-leave-to[data-v-5fd4ef0c]{opacity:0}.code-switcher div[class*=language-]:before{content:""}.code-switcher .tab-header ul{padding:0;text-align:right;margin-bottom:-5px;margin-top:20px}.code-switcher .tab-header li{display:inline-block;padding:0 10px;cursor:pointer;border-radius:4px;border:2px solid #eaecef;margin-left:5px;font-size:80%}.code-switcher .tab-header li.active{border-color:#3eaf7c}.icon.outbound{color:#aaa;display:inline-block;vertical-align:middle;position:relative;top:-1px}.home{padding:3.6rem 2rem 0;max-width:960px;margin:0 auto;display:block}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.8rem auto}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:#6a8bad}.home .hero .action-button{display:inline-block;font-size:1.2rem;color:#fff;background-color:#3eaf7c;padding:.8rem 1.6rem;border-radius:4px;transition:background-color .1s ease;box-sizing:border-box;border-bottom:1px solid #389d70}.home .hero .action-button:hover{background-color:#4abf8a}.home .features{border-top:1px solid #eaecef;padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:#3a5169}.home .feature p{color:#4e6e8e}.home .footer{padding:2.5rem;border-top:1px solid #eaecef;text-align:center;color:#4e6e8e}@media (max-width:719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width:419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.search-box{display:inline-block;position:relative;margin-right:1rem}.search-box input{cursor:text;width:10rem;height:2rem;color:#4e6e8e;display:inline-block;border:1px solid #cfd4db;border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:none;transition:all .2s ease;background:#fff url(/assets/img/search.83621669.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:#3eaf7c}.search-box .suggestions{background:#fff;width:20rem;position:absolute;top:2rem;border:1px solid #cfd4db;border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestions.align-right{right:0}.search-box .suggestion{line-height:1.4;padding:.4rem .6rem;border-radius:4px;cursor:pointer}.search-box .suggestion a{white-space:normal;color:#5d82a6}.search-box .suggestion a .page-title{font-weight:600}.search-box .suggestion a .header{font-size:.9em;margin-left:.25em}.search-box .suggestion.focused{background-color:#f3f4f5}.search-box .suggestion.focused a{color:#3eaf7c}@media (max-width:959px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (-ms-high-contrast:none){.search-box input{height:2rem}}@media (max-width:959px) and (min-width:719px){.search-box .suggestions{left:0}}@media (max-width:719px){.search-box{margin-right:0}.search-box input{left:1rem}.search-box .suggestions{right:0}}@media (max-width:419px){.search-box .suggestions{width:calc(100vw - 4rem)}.search-box input:focus{width:8rem}}.sidebar-button{cursor:pointer;display:none;width:1.25rem;height:1.25rem;position:absolute;padding:.6rem;top:.6rem;left:1rem}.sidebar-button .icon{display:block;width:1.25rem;height:1.25rem}@media (max-width:719px){.sidebar-button{display:block}}.dropdown-enter,.dropdown-leave-to{height:0!important}.dropdown-wrapper{cursor:pointer}.dropdown-wrapper .dropdown-title{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:transparent;border:none;font-weight:500;color:#2c3e50;pointer-events:none}.dropdown-wrapper .dropdown-title:hover{border-color:transparent}.dropdown-wrapper .dropdown-title .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.dropdown-wrapper .nav-dropdown .dropdown-item{color:inherit;line-height:1.7rem}.dropdown-wrapper .nav-dropdown .dropdown-item h4{margin:.45rem 0 0;border-top:1px solid #eee;padding:.45rem 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper{padding:0;list-style:none}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper .dropdown-subitem{font-size:.9em}.dropdown-wrapper .nav-dropdown .dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active,.dropdown-wrapper .nav-dropdown .dropdown-item a:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid #3eaf7c;border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.dropdown-wrapper .nav-dropdown .dropdown-item:first-child h4{margin-top:0;padding-top:0;border-top:0}@media (max-width:719px){.dropdown-wrapper.open .dropdown-title{margin-bottom:.5rem}.dropdown-wrapper .dropdown-title{font-weight:600;font-size:inherit}.dropdown-wrapper .dropdown-title:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown{transition:height .1s ease-out;overflow:hidden}.dropdown-wrapper .nav-dropdown .dropdown-item h4{border-top:0;margin-top:0;padding-top:0}.dropdown-wrapper .nav-dropdown .dropdown-item>a,.dropdown-wrapper .nav-dropdown .dropdown-item h4{font-size:15px;line-height:2rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width:719px){.dropdown-wrapper{height:1.8rem}.dropdown-wrapper.open .nav-dropdown,.dropdown-wrapper:hover .nav-dropdown{display:block!important}.dropdown-wrapper.open:blur{display:none}.dropdown-wrapper .dropdown-title .arrow{border-left:4px solid transparent;border-right:4px solid transparent;border-top:6px solid #ccc;border-bottom:0}.dropdown-wrapper .nav-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:#fff;padding:.6rem 0;border:1px solid;border-color:#ddd #ddd #ccc;text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}}.nav-links{display:inline-block}.nav-links a{line-height:1.4rem;color:inherit}.nav-links a.router-link-active,.nav-links a:hover{color:#3eaf7c}.nav-links .nav-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:2rem}.nav-links .nav-item:first-child{margin-left:0}.nav-links .repo-link{margin-left:1.5rem}@media (max-width:719px){.nav-links .nav-item,.nav-links .repo-link{margin-left:0}}@media (min-width:719px){.nav-links a.router-link-active,.nav-links a:hover{color:#2c3e50}.nav-item>a:not(.external).router-link-active,.nav-item>a:not(.external):hover{margin-bottom:-2px;border-bottom:2px solid #46bd87}}.navbar{padding:.7rem 1.5rem;line-height:2.2rem}.navbar a,.navbar img,.navbar span{display:inline-block}.navbar .logo{height:2.2rem;min-width:2.2rem;margin-right:.8rem;vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:#2c3e50;position:relative}.navbar .links{padding-left:1.5rem;box-sizing:border-box;background-color:#fff;white-space:nowrap;font-size:.9rem;position:absolute;right:1.5rem;top:.7rem;display:flex}.navbar .links .search-box{flex:0 0 auto;vertical-align:top}@media (max-width:719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .links{padding-left:1.5rem}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.page-edit{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-edit{padding:2rem}}@media (max-width:419px){.page-edit{padding:1.5rem}}.page-edit{padding-top:1rem;padding-bottom:1rem;overflow:auto}.page-edit .edit-link{display:inline-block}.page-edit .edit-link a{color:#4e6e8e;margin-right:.25rem}.page-edit .last-updated{float:right;font-size:.9em}.page-edit .last-updated .prefix{font-weight:500;color:#4e6e8e}.page-edit .last-updated .time{font-weight:400;color:#aaa}@media (max-width:719px){.page-edit .edit-link{margin-bottom:.5rem}.page-edit .last-updated{font-size:.8em;float:none;text-align:left}}.page-nav{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-nav{padding:2rem}}@media (max-width:419px){.page-nav{padding:1.5rem}}.page-nav{padding-top:1rem;padding-bottom:0}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid #eaecef;padding-top:1rem;overflow:auto}.page-nav .next{float:right}.page{padding-bottom:2rem;display:block}.sidebar-group .sidebar-group{padding-left:.5em}.sidebar-group:not(.collapsable) .sidebar-heading:not(.clickable){cursor:auto;color:inherit}.sidebar-group.is-sub-group{padding-left:0}.sidebar-group.is-sub-group>.sidebar-heading{font-size:.95em;line-height:1.4;font-weight:400;padding-left:2rem}.sidebar-group.is-sub-group>.sidebar-heading:not(.clickable){opacity:.5}.sidebar-group.is-sub-group>.sidebar-group-items{padding-left:1rem}.sidebar-group.is-sub-group>.sidebar-group-items>li>.sidebar-link{font-size:.95em;border-left:none}.sidebar-group.depth-2>.sidebar-heading{border-left:none}.sidebar-heading{color:#2c3e50;transition:color .15s ease;cursor:pointer;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0;border-left:.25rem solid transparent}.sidebar-heading.open,.sidebar-heading:hover{color:inherit}.sidebar-heading .arrow{position:relative;top:-.12em;left:.5em}.sidebar-heading.clickable.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-heading.clickable:hover{color:#3eaf7c}.sidebar-group-items{transition:height .1s ease-out;font-size:.95em;overflow:hidden}.sidebar .sidebar-sub-headers{padding-left:1rem;font-size:.95em}a.sidebar-link{font-size:1em;font-weight:400;display:inline-block;color:#2c3e50;border-left:.25rem solid transparent;padding:.35rem 1rem .35rem 1.25rem;line-height:1.4;width:100%;box-sizing:border-box}a.sidebar-link:hover{color:#3eaf7c}a.sidebar-link.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-group a.sidebar-link{padding-left:2rem}.sidebar-sub-headers a.sidebar-link{padding-top:.25rem;padding-bottom:.25rem;border-left:none}.sidebar-sub-headers a.sidebar-link.active{font-weight:500}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .nav-links{display:none;border-bottom:1px solid #eaecef;padding:.5rem 0 .75rem}.sidebar .nav-links a{font-weight:600}.sidebar .nav-links .nav-item,.sidebar .nav-links .repo-link{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar>.sidebar-links{padding:1.5rem 0}.sidebar>.sidebar-links>li>a.sidebar-link{font-size:1.1em;line-height:1.7;font-weight:700}.sidebar>.sidebar-links>li:not(:first-child){margin-top:.75rem}@media (max-width:719px){.sidebar .nav-links{display:block}.sidebar .nav-links .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar>.sidebar-links{padding:1rem 0}}code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}.theme-default-content code{color:#476582;padding:.25rem .5rem;margin:0;font-size:.85em;background-color:rgba(27,31,35,.05);border-radius:3px}.theme-default-content code .token.deleted{color:#ec5975}.theme-default-content code .token.inserted{color:#3eaf7c}.theme-default-content pre,.theme-default-content pre[class*=language-]{line-height:1.4;padding:1.25rem 1.5rem;margin:.85rem 0;background-color:#282c34;border-radius:6px;overflow:auto}.theme-default-content pre[class*=language-] code,.theme-default-content pre code{color:#fff;padding:0;background-color:transparent;border-radius:0}div[class*=language-]{position:relative;background-color:#282c34;border-radius:6px}div[class*=language-] .highlight-lines{-webkit-user-select:none;-ms-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlighted{background-color:rgba(0,0,0,.66)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:transparent;position:relative;z-index:1}div[class*=language-]:before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:hsla(0,0%,100%,.4)}div[class*=language-]:not(.line-numbers-mode) .line-numbers-wrapper{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlighted{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlighted:before{content:" ";position:absolute;z-index:3;left:0;top:0;display:block;width:3.5rem;height:100%;background-color:rgba(0,0,0,.66)}div[class*=language-].line-numbers-mode pre{padding-left:4.5rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers-wrapper{position:absolute;top:0;width:3.5rem;text-align:center;color:hsla(0,0%,100%,.3);padding:1.25rem 0;line-height:1.4}div[class*=language-].line-numbers-mode .line-numbers-wrapper br{-webkit-user-select:none;-ms-user-select:none;user-select:none}div[class*=language-].line-numbers-mode .line-numbers-wrapper .line-number{position:relative;z-index:4;-webkit-user-select:none;-ms-user-select:none;user-select:none;font-size:.85em}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;z-index:2;top:0;left:0;width:3.5rem;height:100%;border-radius:6px 0 0 6px;border-right:1px solid rgba(0,0,0,.66);background-color:#282c34}div[class~=language-js]:before{content:"js"}div[class~=language-ts]:before{content:"ts"}div[class~=language-html]:before{content:"html"}div[class~=language-md]:before{content:"md"}div[class~=language-vue]:before{content:"vue"}div[class~=language-css]:before{content:"css"}div[class~=language-sass]:before{content:"sass"}div[class~=language-scss]:before{content:"scss"}div[class~=language-less]:before{content:"less"}div[class~=language-stylus]:before{content:"stylus"}div[class~=language-go]:before{content:"go"}div[class~=language-java]:before{content:"java"}div[class~=language-c]:before{content:"c"}div[class~=language-sh]:before{content:"sh"}div[class~=language-yaml]:before{content:"yaml"}div[class~=language-py]:before{content:"py"}div[class~=language-docker]:before{content:"docker"}div[class~=language-dockerfile]:before{content:"dockerfile"}div[class~=language-makefile]:before{content:"makefile"}div[class~=language-javascript]:before{content:"js"}div[class~=language-typescript]:before{content:"ts"}div[class~=language-markup]:before{content:"html"}div[class~=language-markdown]:before{content:"md"}div[class~=language-json]:before{content:"json"}div[class~=language-ruby]:before{content:"rb"}div[class~=language-python]:before{content:"py"}div[class~=language-bash]:before{content:"sh"}div[class~=language-php]:before{content:"php"}.custom-block .custom-block-title{font-weight:600;margin-bottom:-.4rem}.custom-block.danger,.custom-block.tip,.custom-block.warning{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-block.tip{background-color:#f3f5f7;border-color:#42b983}.custom-block.warning{background-color:rgba(255,229,100,.3);border-color:#e7c000;color:#6b5900}.custom-block.warning .custom-block-title{color:#b29400}.custom-block.warning a{color:#2c3e50}.custom-block.danger{background-color:#ffe6e6;border-color:#c00;color:#4d0000}.custom-block.danger .custom-block-title{color:#900}.custom-block.danger a{color:#2c3e50}.custom-block.details{display:block;position:relative;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:#eee}.custom-block.details h4{margin-top:0}.custom-block.details figure:last-child,.custom-block.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-block.details summary{outline:none;cursor:pointer}.arrow{display:inline-block;width:0;height:0}.arrow.up{border-bottom:6px solid #ccc}.arrow.down,.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent}.arrow.down{border-top:6px solid #ccc}.arrow.right{border-left:6px solid #ccc}.arrow.left,.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent}.arrow.left{border-right:6px solid #ccc}.theme-default-content:not(.custom){max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.theme-default-content:not(.custom){padding:2rem}}@media (max-width:419px){.theme-default-content:not(.custom){padding:1.5rem}}.table-of-contents .badge{vertical-align:middle}body,html{padding:0;margin:0;background-color:#fff}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;color:#2c3e50}.page{padding-left:20rem}.navbar{z-index:20;right:0;height:3.6rem;background-color:#fff;box-sizing:border-box;border-bottom:1px solid #eaecef}.navbar,.sidebar-mask{position:fixed;top:0;left:0}.sidebar-mask{z-index:9;width:100vw;height:100vh;display:none}.sidebar{font-size:16px;background-color:#fff;width:20rem;position:fixed;z-index:10;margin:0;top:3.6rem;left:0;bottom:0;box-sizing:border-box;border-right:1px solid #eaecef;overflow-y:auto}.theme-default-content:not(.custom)>:first-child{margin-top:3.6rem}.theme-default-content:not(.custom) a:hover{text-decoration:underline}.theme-default-content:not(.custom) p.demo{padding:1rem 1.5rem;border:1px solid #ddd;border-radius:4px}.theme-default-content:not(.custom) img{max-width:100%}.theme-default-content.custom{padding:0;margin:0}.theme-default-content.custom img{max-width:100%}a{font-weight:500;text-decoration:none}a,p a code{color:#3eaf7c}p a code{font-weight:400}kbd{background:#eee;border:.15rem solid #ddd;border-bottom:.25rem solid #ddd;border-radius:.15rem;padding:0 .15em}blockquote{font-size:1rem;color:#999;border-left:.2rem solid #dfe2e5;margin:1rem 0;padding:.25rem 0 .25rem 1rem}blockquote>p{margin:0}ol,ul{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}.theme-default-content:not(.custom)>h1,.theme-default-content:not(.custom)>h2,.theme-default-content:not(.custom)>h3,.theme-default-content:not(.custom)>h4,.theme-default-content:not(.custom)>h5,.theme-default-content:not(.custom)>h6{margin-top:-3.1rem;padding-top:4.6rem;margin-bottom:0}.theme-default-content:not(.custom)>h1:first-child,.theme-default-content:not(.custom)>h2:first-child,.theme-default-content:not(.custom)>h3:first-child,.theme-default-content:not(.custom)>h4:first-child,.theme-default-content:not(.custom)>h5:first-child,.theme-default-content:not(.custom)>h6:first-child{margin-top:-1.5rem;margin-bottom:1rem}.theme-default-content:not(.custom)>h1:first-child+.custom-block,.theme-default-content:not(.custom)>h1:first-child+p,.theme-default-content:not(.custom)>h1:first-child+pre,.theme-default-content:not(.custom)>h2:first-child+.custom-block,.theme-default-content:not(.custom)>h2:first-child+p,.theme-default-content:not(.custom)>h2:first-child+pre,.theme-default-content:not(.custom)>h3:first-child+.custom-block,.theme-default-content:not(.custom)>h3:first-child+p,.theme-default-content:not(.custom)>h3:first-child+pre,.theme-default-content:not(.custom)>h4:first-child+.custom-block,.theme-default-content:not(.custom)>h4:first-child+p,.theme-default-content:not(.custom)>h4:first-child+pre,.theme-default-content:not(.custom)>h5:first-child+.custom-block,.theme-default-content:not(.custom)>h5:first-child+p,.theme-default-content:not(.custom)>h5:first-child+pre,.theme-default-content:not(.custom)>h6:first-child+.custom-block,.theme-default-content:not(.custom)>h6:first-child+p,.theme-default-content:not(.custom)>h6:first-child+pre{margin-top:2rem}h1:hover .header-anchor,h2:hover .header-anchor,h3:hover .header-anchor,h4:hover .header-anchor,h5:hover .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid #eaecef}h3{font-size:1.35rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0}a.header-anchor:hover{text-decoration:none}.line-number,code,kbd{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}ol,p,ul{line-height:1.7}hr{border:0;border-top:1px solid #eaecef}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto}tr{border-top:1px solid #dfe2e5}tr:nth-child(2n){background-color:#f6f8fa}td,th{border:1px solid #dfe2e5;padding:.6em 1em}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.no-navbar .theme-default-content:not(.custom)>h1,.theme-container.no-navbar h2,.theme-container.no-navbar h3,.theme-container.no-navbar h4,.theme-container.no-navbar h5,.theme-container.no-navbar h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .sidebar{top:0}@media (min-width:720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}@media (max-width:959px){.sidebar{font-size:15px;width:16.4rem}.page{padding-left:16.4rem}}@media (max-width:719px){.sidebar{top:0;padding-top:3.6rem;transform:translateX(-100%);transition:transform .2s ease}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translateX(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width:419px){h1{font-size:1.9rem}.theme-default-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}.home .hero img{height:200px}.badge[data-v-15b7b770]{display:inline-block;font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:#fff}.badge.green[data-v-15b7b770],.badge.tip[data-v-15b7b770],.badge[data-v-15b7b770]{background-color:#42b983}.badge.error[data-v-15b7b770]{background-color:#da5961}.badge.warn[data-v-15b7b770],.badge.warning[data-v-15b7b770],.badge.yellow[data-v-15b7b770]{background-color:#e7c000}.badge+.badge[data-v-15b7b770]{margin-left:5px} \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/img/search.83621669.svg b/okhttps-doc/docs/.vuepress/dist/assets/img/search.83621669.svg deleted file mode 100644 index 03d83913..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/img/search.83621669.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/10.bc5e580e.js b/okhttps-doc/docs/.vuepress/dist/assets/js/10.bc5e580e.js deleted file mode 100644 index 8f8cfd50..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/10.bc5e580e.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{333:function(s,t,a){"use strict";a.r(t);var n=a(19),e=Object(n.a)({},(function(){var s=this,t=s.$createElement,a=s._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[a("h1",{attrs:{id:"特色"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#特色"}},[s._v("#")]),s._v(" 特色")]),s._v(" "),a("h2",{attrs:{id:"使用-httputils-类"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用-httputils-类"}},[s._v("#")]),s._v(" 使用 HttpUtils 类")]),s._v(" "),a("p",[s._v("类"),a("code",[s._v("HttpUtils")]),s._v("本是 "),a("a",{attrs:{href:"https://gitee.com/ejlchina-zhxu/httputils",target:"_blank",rel:"noopener noreferrer"}},[s._v("�身 HttpUtils"),a("OutboundLink")],1),s._v(" 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了"),a("code",[s._v("HTTP")]),s._v("接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。")]),s._v(" "),a("p",[s._v("类"),a("code",[s._v("HttpUtils")]),s._v("共定义了四个��方法:")]),s._v(" "),a("ul",[a("li",[a("code",[s._v("of(HTTP http)")]),s._v(" �置"),a("code",[s._v("HttpUtils")]),s._v("�有的"),a("code",[s._v("HTTP")]),s._v("实例(�调用此方法�默认使用一个没有没有�过任何�置的"),a("code",[s._v("HTTP")]),s._v("懒实例)")]),s._v(" "),a("li",[a("code",[s._v("sync(String url)")]),s._v(" 开始一个�步请求 (内部通过一个"),a("code",[s._v("HTTP")]),s._v("�例实现)")]),s._v(" "),a("li",[a("code",[s._v("async(String url)")]),s._v(" 开始一个异步请求 (内部通过一个"),a("code",[s._v("HTTP")]),s._v("�例实现)")]),s._v(" "),a("li",[a("code",[s._v("cancel(String tag)")]),s._v(" 按标签�消请求(内部通过一个"),a("code",[s._v("HTTP")]),s._v("�例实现)")]),s._v(" "),a("li",[a("code",[s._v("cancelAll()")]),s._v(" �消所有HTTP任务,包括�步和异步(内部通过一个"),a("code",[s._v("HTTP")]),s._v("�例实现)")]),s._v(" "),a("li",[a("code",[s._v("request(Request request)")]),s._v(" OkHttp 原生请求 (该请求��过 预处�器)")]),s._v(" "),a("li",[a("code",[s._v("webSocket(Request request, WebSocketListener listener)")]),s._v(" WebSocket通讯\n  也就是说,能使用"),a("code",[s._v("http")]),s._v("实例的地方,都�以使用"),a("code",[s._v("HttpUtils")]),s._v("类,例如:")])]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在�置HTTP实例之�,�能使用全路径方�")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Role")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" roles "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"http://api.demo.com/roles"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Role")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �置HTTP实例,全局生效")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("of")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("baseUrl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"http://api.demo.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 内部使用新的HTTP实例")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" users "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br")])]),a("h2",{attrs:{id:"异常处�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#异常处�"}},[s._v("#")]),s._v(" 异常处�")]),s._v(" "),a("p",[s._v("使用 OkHttps 时,"),a("strong",[s._v("异常处��是必须的")]),s._v(",但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:"),a("code",[s._v("nothrow()")]),s._v(",以满足��的异常处�需求。")]),s._v(" "),a("h3",{attrs:{id:"�步请求的异常"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�步请求的异常"}},[s._v("#")]),s._v(" �步请求的异常")]),s._v(" "),a("p",[s._v("默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 "),a("code",[s._v("try catch")]),s._v(" ��获,例如:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("try")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("catch")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpException")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Throwable")]),s._v(" cause "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getCause")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到异常原因")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cause "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("ConnectException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当没网络时,会抛出连接异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cause "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("SocketTimeoutException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当接�长时间未�应,会抛出超时异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("cause "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("UnknownHostException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当把域�或IP写错,会抛出 UnknownHost 异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// ...")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br")])]),a("p",[s._v("这�传统的异常处�方�,当然�以解决问题,但 OkHttps 有更佳的方案:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 方法 nothrow() 让异常�直接抛出")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nothrow")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 判断执行状�")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("switch")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" RESPONSED"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 请求已正常�应")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" CANCELED"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 请求已被�消")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" NETWORK_ERROR"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 网络错误,说明用户没网了")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" TIMEOUT"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 请求超时")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("case")]),s._v(" EXCEPTION"),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v(":")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 其它异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("break")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 还�以获得具体的异常信�")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("IOException")]),s._v(" error "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getError")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br"),a("span",{staticClass:"line-number"},[s._v("16")]),a("br"),a("span",{staticClass:"line-number"},[s._v("17")]),a("br")])]),a("h3",{attrs:{id:"异步请求的异常"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#异步请求的异常"}},[s._v("#")]),s._v(" 异步请求的异常")]),s._v(" "),a("p",[s._v("异步请求最常用的异常处�方�就是设置一个异常回调:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当�生异常时就�会走这里")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("IOException")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 这里处�请求异常")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br")])]),a("p",[s._v("当然,还有一个全局异常监�("),a("code",[s._v("ExceptionListener")]),s._v("):")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("exceptionListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("IOException")]),s._v(" error"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 所有请求�生异常都会走这里")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("return")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br")])]),a("p",[s._v("如果�设置"),a("code",[s._v("OnException")]),s._v("回调,也没有"),a("code",[s._v("ExceptionListener")]),s._v(",�生异常时会在 "),a("strong",[s._v("IO 线程")]),s._v(" 中�上抛出,外层无法�获:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("try")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当�生异常时就�会走这里")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("catch")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpException")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 这�方�是�获�到异常的������")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br")])]),a("p",[s._v("�使没有"),a("code",[s._v("OnException")]),s._v("回调,�生异常时,�然会走"),a("code",[s._v("OnComplete")]),s._v("回调,如果设置了的�:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当�生异常时就�会走这里")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnComplete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("State")]),s._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �生异常,会先执行这里,�以根� state 判断�生了什么")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 但执行完��然会在IO线程中�上抛出")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br")])]),a("p",[s._v("如果就是想 "),a("strong",[s._v("�处�异常,也��上抛出")]),s._v(",�生错误完全无视,�以�到�?�以�还是使用"),a("code",[s._v("nothrow()")]),s._v("方法:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nothrow")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 告诉 OkHttps �生异常时��外抛出")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 当�生异常时就�会走这里")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br")])]),a("h2",{attrs:{id:"�消请求"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�消请求"}},[s._v("#")]),s._v(" �消请求")]),s._v(" "),a("p",[s._v("在 OkHttps 里�消请求共有 "),a("strong",[s._v("4 �")]),s._v(" 方��选:")]),s._v(" "),a("ul",[a("li",[s._v("使用"),a("code",[s._v("HttpCall#cancel()")]),s._v("�消�个请求(适用于异步请求,"),a("a",{attrs:{href:"#33-httpcall"}},[s._v("详� 3.3 章节")]),s._v(")")]),s._v(" "),a("li",[s._v("使用"),a("code",[s._v("HttpTask#cancel()")]),s._v("�消�个请求(适用于所有请求)(since v1.0.4)")])]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �应回调")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\ntask"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �起 GET 请求")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �消请求,并返回是��消�功")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("boolean")]),s._v(" canceled "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" \n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br")])]),a("ul",[a("li",[s._v("使用"),a("code",[s._v("HTTP#cancel(String tag)")]),s._v("按标签批��消请求(适用于所有请求,"),a("a",{attrs:{href:"#5-%E4%BD%BF%E7%94%A8%E6%A0%87%E7%AD%BE"}},[s._v("详�第 5 章节")]),s._v(")")]),s._v(" "),a("li",[s._v("使用"),a("code",[s._v("HTTP#cancelAll()")]),s._v("�消所有请求(适用于所有请求)(since v1.0.2)")])]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("cancelAll")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �消所有请求")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br")])])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/11.152d132f.js b/okhttps-doc/docs/.vuepress/dist/assets/js/11.152d132f.js deleted file mode 100644 index 4ce64ac2..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/11.152d132f.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{335:function(t,s,a){"use strict";a.r(s);var n=a(19),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"基础"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#基础"}},[t._v("#")]),t._v(" 基础")]),t._v(" "),a("h2",{attrs:{id:"请求方法"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#请求方法"}},[t._v("#")]),t._v(" 请求方法")]),t._v(" "),a("p",[t._v("�步与异步的"),a("code",[t._v("HttpTask")]),t._v("都拥有"),a("code",[t._v("get")]),t._v("�"),a("code",[t._v("post")]),t._v("�"),a("code",[t._v("put")]),t._v("与"),a("code",[t._v("delete")]),t._v("方法。��的是:�步"),a("code",[t._v("HttpTask")]),t._v("的这些方法返回一个"),a("code",[t._v("HttpResult")]),t._v(",而异步"),a("code",[t._v("HttpTask")]),t._v("的这些方法返回一个"),a("code",[t._v("HttpCall")]),t._v("。")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" res1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �步 GET")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" res2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �步 POST")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" res3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("put")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �步 PUT")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" res4 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("delete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �步 DELETE")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步 GET")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步 POST")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("put")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步 PUT")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call4 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("delete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步 DELETE")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("h2",{attrs:{id:"回调函数"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#回调函数"}},[t._v("#")]),t._v(" 回调函数")]),t._v(" "),a("p",[t._v("OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/{id}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// http://api.demo.com/users/1")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addPathParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �应回调")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IOException")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异常回调")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnComplete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),t._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 完�回调,无论�功失败都会执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 并且在 �应|异常回调 之�执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br")])]),a("p",[t._v("OkHttps �时还支� "),a("strong",[t._v("全局回调")]),t._v(" 和 "),a("strong",[t._v("回调阻断")]),t._v(" 机制,详� "),a("RouterLink",{attrs:{to:"/guide/configuration.html#全局回调监�"}},[t._v("全局回调监�")]),t._v("。")],1),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("ul",[a("li",[t._v("�有异步请求��以设置这三�(�应|异常|完�)回调")]),t._v(" "),a("li",[t._v("�步请求直接返回结果,无需使用回调")])])]),t._v(" "),a("h2",{attrs:{id:"httpresult"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#httpresult"}},[t._v("#")]),t._v(" HttpResult")]),t._v(" "),a("p",[a("code",[t._v("HttpResult")]),t._v("是HTTP请求执行完�的结果,它是�步请求方法( "),a("code",[t._v("get")]),t._v("�"),a("code",[t._v("post")]),t._v("�"),a("code",[t._v("put")]),t._v("�"),a("code",[t._v("delete")]),t._v(")的返回值,也是异步请求�应回调("),a("code",[t._v("OnResponse")]),t._v(")的�数,它定义了如下方法:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("getState()")]),t._v(" 得到请求执行状�枚举,它有以下�值:\n"),a("ul",[a("li",[a("code",[t._v("State.CANCELED")]),t._v(" 请求被�消")]),t._v(" "),a("li",[a("code",[t._v("State.RESPONSED")]),t._v(" 已收到�应")]),t._v(" "),a("li",[a("code",[t._v("State.TIMEOUT")]),t._v(" 请求超时")]),t._v(" "),a("li",[a("code",[t._v("State.NETWORK_ERROR")]),t._v(" 网络错误")]),t._v(" "),a("li",[a("code",[t._v("State.EXCEPTION")]),t._v(" 其它请求异常")])])]),t._v(" "),a("li",[a("code",[t._v("getStatus()")]),t._v(" 得到HTTP状��")]),t._v(" "),a("li",[a("code",[t._v("isSuccessful()")]),t._v(" 是��应�功,状��在 [200..300) 之间")]),t._v(" "),a("li",[a("code",[t._v("getHeaders()")]),t._v(" 得到HTTP�应头")]),t._v(" "),a("li",[a("code",[t._v("getHeaders(String name)")]),t._v(" 得到HTTP�应头")]),t._v(" "),a("li",[a("code",[t._v("getHeader(String name)")]),t._v(" 得到HTTP�应头")]),t._v(" "),a("li",[a("code",[t._v("getBody()")]),t._v(" 得到�应报文体"),a("code",[t._v("Body")]),t._v("实例,它定义了如下方法(对�一个"),a("code",[t._v("Body")]),t._v("实例,以下的"),a("code",[t._v("toXXX()")]),t._v("类方法�能使用一个且仅能调用一次,除�先使用 cache 方法):\n"),a("ul",[a("li",[a("code",[t._v("toBytes()")]),t._v(" 返回字节数组")]),t._v(" "),a("li",[a("code",[t._v("toByteStream()")]),t._v(" 返回字节输入�")]),t._v(" "),a("li",[a("code",[t._v("toCharStream()")]),t._v(" 返回字符输入�")]),t._v(" "),a("li",[a("code",[t._v("toString()")]),t._v(" 返回字符串")]),t._v(" "),a("li",[a("code",[t._v("toJsonObject()")]),t._v(" 返回Json对象")]),t._v(" "),a("li",[a("code",[t._v("toJsonArray()")]),t._v(" 返回Json数组")]),t._v(" "),a("li",[a("code",[t._v("toBean(Class type)")]),t._v(" 返回根�type自动json解��的JavaBean")]),t._v(" "),a("li",[a("code",[t._v("toList(Class type)")]),t._v(" 返回根�type自动json解��的JavaBean列表")]),t._v(" "),a("li",[a("code",[t._v("toFile(String filePath)")]),t._v(" 下载到指定路径")]),t._v(" "),a("li",[a("code",[t._v("toFile(File file)")]),t._v(" 下载到指定文件")]),t._v(" "),a("li",[a("code",[t._v("toFolder(String dirPath)")]),t._v(" 下载到指定目录")]),t._v(" "),a("li",[a("code",[t._v("toFolder(File dir)")]),t._v(" 下载到指定目录")]),t._v(" "),a("li",[a("code",[t._v("getContentType()")]),t._v(" 返回报文体的媒体类型")]),t._v(" "),a("li",[a("code",[t._v("getContentLength()")]),t._v(" 返回报文体的字节长度")]),t._v(" "),a("li",[a("code",[t._v("cache()")]),t._v(" 缓存报文体,开�缓存����使用"),a("code",[t._v("toXXX()")]),t._v("类方法")]),t._v(" "),a("li",[a("code",[t._v("close()")]),t._v(" 关闭报文体,未对报文体�任何消费时使用,比如�读�报文头")])])]),t._v(" "),a("li",[a("code",[t._v("getError()")]),t._v(" 执行中�生的异常,自动�获执行请求时�生的 网络超时�网络错误 和 其它IO异常")]),t._v(" "),a("li",[a("code",[t._v("close()")]),t._v(" 关闭报文,未对报文体�任何消费时使用,比如�读�长度")])]),t._v(" "),a("p",[t._v("示例,请求结果自动转Bean和List:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 自动转Bean")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),t._v(" order "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/orders/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 自动转List")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" orders "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/orders"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br")])]),a("p",[t._v("示例,使用 cache 方法:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Body")]),t._v(" body "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/orders"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cache")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用 cache �,�以多次使用 toXXX() 方法")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toJsonArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br")])]),a("p",[t._v("示例,获�下载文件的大�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" size "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �是想获得文件大�,�消费报文体,所以直接关闭")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getContentLength")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获得待下载文件的大�")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络��")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"size = "')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" size"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("h2",{attrs:{id:"httpcall"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#httpcall"}},[t._v("#")]),t._v(" HttpCall")]),t._v(" "),a("p",[a("code",[t._v("HttpCall")]),t._v("对象是异步请求方法("),a("code",[t._v("get")]),t._v("�"),a("code",[t._v("post")]),t._v("�"),a("code",[t._v("put")]),t._v("�"),a("code",[t._v("delete")]),t._v(")的返回值,与"),a("code",[t._v("java")]),t._v("的"),a("code",[t._v("Future")]),t._v("接�很�,它有如下方法:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("cancel()")]),t._v(" �消本次请求,返回�消结果")]),t._v(" "),a("li",[a("code",[t._v("isCanceled()")]),t._v(" 返回请求是�被�消")]),t._v(" "),a("li",[a("code",[t._v("isDone()")]),t._v(" 返回是�执行完�,包��消和失败")]),t._v(" "),a("li",[a("code",[t._v("getResult()")]),t._v(" 返回执行结果"),a("code",[t._v("HttpResult")]),t._v("对象,若请求未执行完,则挂起当�线程直到执行完��返回")])]),t._v(" "),a("p",[t._v("�消一个异步请求示例:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("call"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isCanceled")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// false")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("boolean")]),t._v(" success "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" call"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �消请求")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("call"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isCanceled")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("h2",{attrs:{id:"构建http任务"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#构建http任务"}},[t._v("#")]),t._v(" 构建HTTP任务")]),t._v(" "),a("p",[a("code",[t._v("HTTP")]),t._v("对象的"),a("code",[t._v("sync")]),t._v("与"),a("code",[t._v("async")]),t._v("方法返回一个"),a("code",[t._v("HttpTask")]),t._v("对象,该对象�供了�链�调用的"),a("code",[t._v("addXXX")]),t._v("与"),a("code",[t._v("setXXX")]),t._v("等系列方法用于构建任务本身。")]),t._v(" "),a("ul",[a("li",[a("p",[a("code",[t._v("addHeader(String name, String value)")]),t._v(" 添加请求头")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addHeader(Map headers)")]),t._v(" 添加请求头")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addPathParam(String name, Object value)")]),t._v(" 添加路径�数:替�URL里的{name}��符")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addPathParam(Map params)")]),t._v(" 添加路径�数:替�URL里的{name}��符")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addUrlParam(String name, Object value)")]),t._v(" 添加URL�数:拼接在URL的?之�(查询�数)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addUrlParam(Map params)")]),t._v(" 添加URL�数:拼接在URL的?之�(查询�数)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addBodyParam(String name, Object value)")]),t._v(" 添加Body�数:以表�key=value&的形�放在报文体内(表��数)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addBodyParam(Map params)")]),t._v(" 添加Body�数:以表�key=value&的形�放在报文体内(表��数)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addJsonParam(String name, Object value)")]),t._v(" 添加Json�数:请求体为Json(支�多层结构)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addJsonParam(Map params)")]),t._v(" 添加Json�数:请求体为Json(支�多层结构)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("setRequestJson(Object json)")]),t._v(" 设置请求体的Json字符串 或待转�为 Json的 JavaBean")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("setRequestJson(Object bean, String dateFormat)")]),t._v(" 设置请求体的Json字符串 或待转�为 Json的 JavaBean")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String filePath)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, File file)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String type, InputStream inputStream)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String type, String fileName, InputStream input)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String type, byte[] content)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("addFileParam(String name, String type, String fileName, byte[] content)")]),t._v(" 上传文件")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("setTag(String tag)")]),t._v(" 为HTTP任务添加标签")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("setRange(long rangeStart)")]),t._v(" 设置Range头信�,用于"),a("RouterLink",{attrs:{to:"/guide/updown.html#实现断点续传"}},[t._v("断点续传")])],1)]),t._v(" "),a("li",[a("p",[a("code",[t._v("setRange(long rangeStart, long rangeEnd)")]),t._v(" 设置Range头信�,�用于"),a("RouterLink",{attrs:{to:"/guide/updown.html#实现分�下载"}},[t._v("分�下载")])],1)]),t._v(" "),a("li",[a("p",[a("code",[t._v("bind(Object object)")]),t._v(" 绑定一个对象,�用于实现Android里的"),a("RouterLink",{attrs:{to:"/guide/android.html#生命周期绑定"}},[t._v("生命周期绑定")])],1)])]),t._v(" "),a("h2",{attrs:{id:"使用标签"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用标签"}},[t._v("#")]),t._v(" 使用标签")]),t._v(" "),a("p",[t._v("有时候我们想对HTTP任务加以分类,这时候�以使用标签功能:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(1)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(2)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A.B"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(3)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"B"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(4)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"B"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"C"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// 从 v1.0.4 标签将以追加模�添加,等效于 setTag("B.C")')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(5)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setTag")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"C"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br"),a("span",{staticClass:"line-number"},[t._v("17")]),a("br"),a("span",{staticClass:"line-number"},[t._v("18")]),a("br"),a("span",{staticClass:"line-number"},[t._v("19")]),a("br"),a("span",{staticClass:"line-number"},[t._v("20")]),a("br")])]),a("p",[t._v("当使用标签�,就�以按标签批�的对HTTP任务进行�消:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("int")]),t._v(" count "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"B"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('//(2)(3)(4)被�消(�消标签包�"B"的任务)')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("count"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 输出 3")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br")])]),a("p",[t._v("标签除了�以用��消任务,在预处�器中它也�以�挥作用,请�� "),a("RouterLink",{attrs:{to:"/guide/configuration.html#并行预处�器"}},[t._v("并行预处�器")]),t._v(" 与 "),a("RouterLink",{attrs:{to:"/guide/configuration.html#串行预处�器(token问题最佳解决方案)"}},[t._v("串行预处�器(token问题最佳解决方案)")]),t._v("。")],1)])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/12.92e24a16.js b/okhttps-doc/docs/.vuepress/dist/assets/js/12.92e24a16.js deleted file mode 100644 index e954337f..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/12.92e24a16.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{332:function(t,s,a){"use strict";a.r(s);var n=a(19),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"上传下载"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#上传下载"}},[t._v("#")]),t._v(" 上传下载")]),t._v(" "),a("h2",{attrs:{id:"文件下载"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#文件下载"}},[t._v("#")]),t._v(" 文件下载")]),t._v(" "),a("p",[t._v("OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用 GET 方法(其它方法也�以,看�务器支�)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 得到报文体")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载到指定的路径")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �动下载")]),t._v("\n\nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载到指定的目录,文件�将根�下载信�自动生�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br")])]),a("p",[t._v("或使用异步连接方�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br")])]),a("p",[t._v("这里�说明一下:"),a("code",[t._v("sync")]),t._v("与"),a("code",[t._v("async")]),t._v("的区别在于连接�务器并得到�应这个过程的�步与异步(这个过程的耗时在大文件下载中�比��),而"),a("code",[t._v("start")]),t._v("方法�动的下载过程则都是异步的。")]),t._v(" "),a("h3",{attrs:{id:"下载进度监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#下载进度监�"}},[t._v("#")]),t._v(" 下载进度监�")]),t._v(" "),a("p",[t._v("就直接上代�啦,诸�一看便懂:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setStepBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1024")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置�接收 1024 个字节执行一次进度回调(�设置默认为 8192) ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// .setStepRate(0.01) // 设置�接收 1% 执行一次进度回调(�设置以 StepBytes 为准) ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载进度回调")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" doneBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDoneBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已下载字节数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" totalBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTotalBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 总共的字节数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("double")]),t._v(" rate "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已下载的比例")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("boolean")]),t._v(" isDone "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isDone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 是�下载完�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 指定下载的目录,文件�将根�下载信�自动生�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// .toFile("D:/download/test.zip") // 指定下载的路径,若文件已存在则覆盖')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnSuccess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载�功回调")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br"),a("span",{staticClass:"line-number"},[t._v("17")]),a("br")])]),a("p",[t._v("值得一�的是:由于 OkHttps 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有"),a("code",[t._v("Content-Length")]),t._v("头),例如:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" users "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setStepBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("h3",{attrs:{id:"下载过程控制"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#下载过程控制"}},[t._v("#")]),t._v(" 下载过程控制")]),t._v(" "),a("p",[t._v("过于简�:还是直接上代�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ctrl")]),t._v(" ctrl "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 该方法返回一个下载过程控制器")]),t._v("\n \nctrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载状�")]),t._v("\nctrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("pause")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 暂�下载")]),t._v("\nctrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("resume")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ��下载")]),t._v("\nctrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �消下载(�时会删除文件,����)")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br")])]),a("p",[t._v("无论是�步还是异步�起的下载请求,都�以�以上的控制:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 拿到下载控制器")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ctrl")]),t._v(" ctrl "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br")])]),a("h3",{attrs:{id:"实现断点续传"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#实现断点续传"}},[t._v("#")]),t._v(" 实现断点续传")]),t._v(" "),a("p",[t._v("OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到 "),a("strong",[t._v("断点")]),t._v(",便将��的问题�得简�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnFailure")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Failure")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载失败回调,以便接收诸如网络错误等失败信�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IOException")]),t._v(" e "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 具体的异常信�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" doneBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDoneBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已下载的字节数(断点),需��存,用于断点续传")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载生�的文件,需��存 ,用于断点续传(��存路径也�以)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br")])]),a("p",[t._v("下�代�实现续传:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" doneBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 拿到�存的断点")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 待续传的文件")]),t._v("\n\nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setRange")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("doneBytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置断点(已下载的字节数)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载到�一个文件里")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setAppended")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 开�文件追加模�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnSuccess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnFailure")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Failure")]),t._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br")])]),a("h3",{attrs:{id:"实现分�下载"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#实现分�下载"}},[t._v("#")]),t._v(" 实现分�下载")]),t._v(" "),a("p",[t._v("当文件很大时,有时候我们会考虑分�下载,与断点续传的�路是一样的,示例代�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" url "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://api.demo.com/download/test.zip"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" totalSize "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getContentLength")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获得待下载文件的大�(由于未消费报文体,所以该请求�会消耗下载报文体的时间和网络��)")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("download")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 从第 0 �开始下载")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sleep")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("50000")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 等待下载完�(�然本例的主线程就结�啦)")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("download")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("int")]),t._v(" index"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" size "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1024")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1024")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ��下载 3M ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" start "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" index "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" size"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" end "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Math")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("min")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("start "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" size"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setRange")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("start"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" end"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置本次下载的范围")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载到�一个文件里")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setAppended")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 开�文件追加模�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnSuccess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),t._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("end "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若未下载完,则继续下载下一�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("download")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("totalSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" index "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"下载完�"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br"),a("span",{staticClass:"line-number"},[t._v("17")]),a("br"),a("span",{staticClass:"line-number"},[t._v("18")]),a("br"),a("span",{staticClass:"line-number"},[t._v("19")]),a("br"),a("span",{staticClass:"line-number"},[t._v("20")]),a("br"),a("span",{staticClass:"line-number"},[t._v("21")]),a("br"),a("span",{staticClass:"line-number"},[t._v("22")]),a("br"),a("span",{staticClass:"line-number"},[t._v("23")]),a("br"),a("span",{staticClass:"line-number"},[t._v("24")]),a("br"),a("span",{staticClass:"line-number"},[t._v("25")]),a("br"),a("span",{staticClass:"line-number"},[t._v("26")]),a("br"),a("span",{staticClass:"line-number"},[t._v("27")]),a("br"),a("span",{staticClass:"line-number"},[t._v("28")]),a("br")])]),a("h2",{attrs:{id:"文件上传"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#文件上传"}},[t._v("#")]),t._v(" 文件上传")]),t._v(" "),a("p",[t._v("一个简�文件上传的示例:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addFileParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 上传�法一般使用 POST 或 PUT,看�务器支�")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br")])]),a("p",[t._v("异步上传也是完全一样:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addFileParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br")])]),a("h3",{attrs:{id:"上传进度监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#上传进度监�"}},[t._v("#")]),t._v(" 上传进度监�")]),t._v(" "),a("p",[t._v("OkHttps 的上传进度监�,监�的是所有请求报文体的��进度,示例代�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Jack"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addFileParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"avatar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/image/avatar.jpg"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setStepBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1024")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置��� 1024 个字节执行一次进度回调(�设置默认为 8192) ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// .setStepRate(0.01) // 设置��� 1% 执行一次进度回调(�设置以 StepBytes 为准) ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 上传进度回调")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" doneBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDoneBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已��字节数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("long")]),t._v(" totalBytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTotalBytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 总共的字节数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("double")]),t._v(" rate "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 已��的比例")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("boolean")]),t._v(" isDone "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isDone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 是���完�")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br")])]),a("p",[t._v("咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在"),a("code",[t._v("get/post")]),t._v("方法之�使用这些API,下载是在"),a("code",[t._v("getBody")]),t._v("方法之�使用。很好�解:"),a("code",[t._v("get/post")]),t._v("之�是准备��请求时段,有上传的�义,而"),a("code",[t._v("getBody")]),t._v("之�,已是报文�应的时段,当然是下载。")]),t._v(" "),a("h3",{attrs:{id:"上传过程控制"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#上传过程控制"}},[t._v("#")]),t._v(" 上传过程控制")]),t._v(" "),a("p",[t._v("上传文件的过程控制就很简�,和常规请求一样,�有异步�起的上传�以�消:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpCall")]),t._v(" call "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addFileParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"D:/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Process")]),t._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\ncall"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �消上传")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br")])]),a("p",[t._v("上传就没有暂�和继续这个功能啦,应该没人有这个需求�?")])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/13.d857e269.js b/okhttps-doc/docs/.vuepress/dist/assets/js/13.d857e269.js deleted file mode 100644 index 126a94c9..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/13.d857e269.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{281:function(n,w,o){}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/2.16cbe9f2.js b/okhttps-doc/docs/.vuepress/dist/assets/js/2.16cbe9f2.js deleted file mode 100644 index 7e02b99a..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/2.16cbe9f2.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{282:function(t,e,n){"use strict";n.d(e,"d",(function(){return i})),n.d(e,"a",(function(){return a})),n.d(e,"i",(function(){return s})),n.d(e,"f",(function(){return u})),n.d(e,"g",(function(){return c})),n.d(e,"h",(function(){return l})),n.d(e,"b",(function(){return h})),n.d(e,"e",(function(){return f})),n.d(e,"k",(function(){return p})),n.d(e,"l",(function(){return d})),n.d(e,"c",(function(){return g})),n.d(e,"j",(function(){return v}));n(20),n(84),n(143),n(298),n(145),n(57),n(25),n(283),n(58),n(148),n(88);var i=/#.*$/,r=/\.(md|html)$/,a=/\/$/,s=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(i,"").replace(r,"")}function u(t){return s.test(t)}function c(t){return/^mailto:/.test(t)}function l(t){return/^tel:/.test(t)}function h(t){if(u(t))return t;var e=t.match(i),n=e?e[0]:"",r=o(t);return a.test(r)?t:r+".html"+n}function f(t,e){var n=decodeURIComponent(t.hash),r=function(t){var e=t.match(i);if(e)return e[0]}(e);return(!r||n===r)&&o(t.path)===o(e)}function p(t,e,n){if(u(e))return{type:"external",path:e};n&&(e=function(t,e,n){var i=t.charAt(0);if("/"===i)return t;if("?"===i||"#"===i)return e+t;var r=e.split("/");n&&r[r.length-1]||r.pop();for(var a=t.replace(/^\//,"").split("/"),s=0;s3&&void 0!==arguments[3]?arguments[3]:1;if("string"==typeof e)return p(n,e,i);if(Array.isArray(e))return Object.assign(p(n,e[0],i),{title:e[1]});var a=e.children||[];return 0===a.length&&e.path?Object.assign(p(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,children:a.map((function(e){return t(e,n,i,r+1)})),collapsable:!1!==e.collapsable}}(t,r,c)})):[]}return[]}function g(t){var e;return(t=t.map((function(t){return Object.assign({},t)}))).forEach((function(t){2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)})),t.filter((function(t){return 2===t.level}))}function v(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},283:function(t,e,n){"use strict";var i=n(89),r=n(8),a=n(14),s=n(13),o=n(90),u=n(91);i("match",1,(function(t,e,n){return[function(e){var n=s(this),i=null==e?void 0:e[t];return void 0!==i?i.call(e,n):new RegExp(e)[t](String(n))},function(t){var i=n(e,t,this);if(i.done)return i.value;var s=r(t),c=String(this);if(!s.global)return u(s,c);var l=s.unicode;s.lastIndex=0;for(var h,f=[],p=0;null!==(h=u(s,c));){var d=String(h[0]);f[p]=d,""===d&&(s.lastIndex=o(c,a(s.lastIndex),l)),p++}return 0===p?null:f}]}))},284:function(t,e,n){},285:function(t,e,n){},286:function(t,e,n){},287:function(t,e,n){},288:function(t,e,n){},289:function(t,e,n){},290:function(t,e,n){},291:function(t,e,n){},292:function(t,e,n){},293:function(t,e,n){},294:function(t,e,n){},295:function(t,e,n){},296:function(t,e,n){},298:function(t,e,n){n(0)({target:"Array",stat:!0},{isArray:n(40)})},299:function(t,e,n){"use strict";var i=n(0),r=n(146).trim;i({target:"String",proto:!0,forced:n(311)("trim")},{trim:function(){return r(this)}})},300:function(t,e,n){var i=n(6),r=n(3),a=n(82),s=n(155),o=n(7).f,u=n(39).f,c=n(86),l=n(144),h=n(150),f=n(21),p=n(1),d=n(37).set,g=n(312),v=n(2)("match"),m=r.RegExp,b=m.prototype,k=/a/g,_=/a/g,x=new m(k)!==k,C=h.UNSUPPORTED_Y;if(i&&a("RegExp",!x||C||p((function(){return _[v]=!1,m(k)!=k||m(_)==_||"/a/i"!=m(k,"i")})))){for(var $=function(t,e){var n,i=this instanceof $,r=c(t),a=void 0===e;if(!i&&r&&t.constructor===$&&a)return t;x?r&&!a&&(t=t.source):t instanceof $&&(a&&(e=l.call(t)),t=t.source),C&&(n=!!e&&e.indexOf("y")>-1)&&(e=e.replace(/y/g,""));var o=s(x?new m(t,e):m(t,e),i?this:b,$);return C&&n&&d(o,{sticky:n}),o},L=function(t){t in $||o($,t,{configurable:!0,get:function(){return m[t]},set:function(e){m[t]=e}})},y=u(m),w=0;y.length>w;)L(y[w++]);b.constructor=$,$.prototype=b,f(r,"RegExp",$)}g("RegExp")},301:function(t,e,n){"use strict";var i=n(21),r=n(8),a=n(1),s=n(144),o=RegExp.prototype,u=o.toString,c=a((function(){return"/a/b"!=u.call({source:"a",flags:"b"})})),l="toString"!=u.name;(c||l)&&i(RegExp.prototype,"toString",(function(){var t=r(this),e=String(t.source),n=t.flags;return"/"+e+"/"+String(void 0===n&&t instanceof RegExp&&!("flags"in o)?s.call(t):n)}),{unsafe:!0})},302:function(t,e){t.exports=function(t){return null==t}},303:function(t,e,n){"use strict";n.r(e);n(142);var i=n(282),r={name:"SidebarGroup",components:{DropdownTransition:n(304).a},props:["item","open","collapsable","depth"],beforeCreate:function(){this.$options.components.SidebarLinks=n(303).default},methods:{isActive:i.e}},a=(n(324),n(19)),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{staticClass:"sidebar-group",class:[{collapsable:t.collapsable,"is-sub-group":0!==t.depth},"depth-"+t.depth]},[t.item.path?n("RouterLink",{staticClass:"sidebar-heading clickable",class:{open:t.open,active:t.isActive(t.$route,t.item.path)},attrs:{to:t.item.path},nativeOn:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]):n("p",{staticClass:"sidebar-heading",class:{open:t.open},on:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]),t._v(" "),n("DropdownTransition",[t.open||!t.collapsable?n("SidebarLinks",{staticClass:"sidebar-group-items",attrs:{items:t.item.children,"sidebar-depth":t.item.sidebarDepth,depth:t.depth+1}}):t._e()],1)],1)}),[],!1,null,null,null).exports;n(325),n(57);function o(t,e,n,i,r){var a={props:{to:e,activeClass:"",exactActiveClass:""},class:{active:i,"sidebar-link":!0}};return r>2&&(a.style={"padding-left":r+"rem"}),t("RouterLink",a,n)}function u(t,e,n,r,a){var s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:1;return!e||s>a?null:t("ul",{class:"sidebar-sub-headers"},e.map((function(e){var c=Object(i.e)(r,n+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[o(t,n+"#"+e.slug,e.title,c,e.level-1),u(t,e.children,n,r,a,s+1)])})))}var c={functional:!0,props:["item","sidebarDepth"],render:function(t,e){var n=e.parent,r=n.$page,a=(n.$site,n.$route),s=n.$themeConfig,c=n.$themeLocaleConfig,l=e.props,h=l.item,f=l.sidebarDepth,p=Object(i.e)(a,h.path),d="auto"===h.type?p||h.children.some((function(t){return Object(i.e)(a,h.basePath+"#"+t.slug)})):p,g="external"===h.type?function(t,e,n){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[n,t("OutboundLink")])}(t,h.path,h.title||h.path):o(t,h.path,h.title||h.path,d),v=[r.frontmatter.sidebarDepth,f,c.sidebarDepth,s.sidebarDepth,1].find((function(t){return void 0!==t})),m=c.displayAllHeaders||s.displayAllHeaders;return"auto"===h.type?[g,u(t,h.children,h.basePath,a,v)]:(d||m)&&h.headers&&!i.d.test(h.path)?[g,u(t,Object(i.c)(h.headers),h.path,a,v)]:g}};n(326);function l(t,e){return"group"===e.type&&e.children.some((function(e){return"group"===e.type?l(t,e):"page"===e.type&&Object(i.e)(t,e.path)}))}var h={name:"SidebarLinks",components:{SidebarGroup:s,SidebarLink:Object(a.a)(c,void 0,void 0,!1,null,null,null).exports},props:["items","depth","sidebarDepth"],data:function(){return{openGroupIndex:0}},watch:{$route:function(){this.refreshIndex()}},created:function(){this.refreshIndex()},methods:{refreshIndex:function(){var t=function(t,e){for(var n=0;n-1&&(this.openGroupIndex=t)},toggleGroup:function(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive:function(t){return Object(i.e)(this.$route,t.regularPath)}}},f=Object(a.a)(h,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.items.length?n("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(e,i){return n("li",{key:i},["group"===e.type?n("SidebarGroup",{attrs:{item:e,open:i===t.openGroupIndex,collapsable:e.collapsable||e.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(i)}}}):n("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:e}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=f.exports},304:function(t,e,n){"use strict";var i={name:"DropdownTransition",methods:{setHeight:function(t){t.style.height=t.scrollHeight+"px"},unsetHeight:function(t){t.style.height=""}}},r=(n(316),n(19)),a=Object(r.a)(i,(function(){var t=this.$createElement;return(this._self._c||t)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.a=a.exports},305:function(t,e,n){"use strict";var i=n(0),r=n(306);i({target:"String",proto:!0,forced:n(307)("link")},{link:function(t){return r(this,"a","href",t)}})},306:function(t,e,n){var i=n(13),r=/"/g;t.exports=function(t,e,n,a){var s=String(i(t)),o="<"+e;return""!==n&&(o+=" "+n+'="'+String(a).replace(r,""")+'"'),o+">"+s+""}},307:function(t,e,n){var i=n(1);t.exports=function(t){return i((function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}))}},308:function(t,e,n){"use strict";var i=n(284);n.n(i).a},309:function(t,e,n){var i=n(0),r=n(310);i({global:!0,forced:parseInt!=r},{parseInt:r})},310:function(t,e,n){var i=n(3),r=n(146).trim,a=n(147),s=i.parseInt,o=/^[+-]?0[Xx]/,u=8!==s(a+"08")||22!==s(a+"0x16");t.exports=u?function(t,e){var n=r(String(t));return s(n,e>>>0||(o.test(n)?16:10))}:s},311:function(t,e,n){var i=n(1),r=n(147);t.exports=function(t){return i((function(){return!!r[t]()||"​…᠎"!="​…᠎"[t]()||r[t].name!==t}))}},312:function(t,e,n){"use strict";var i=n(38),r=n(7),a=n(2),s=n(6),o=a("species");t.exports=function(t){var e=i(t),n=r.f;s&&e&&!e[o]&&n(e,o,{configurable:!0,get:function(){return this}})}},313:function(t,e,n){"use strict";var i,r=n(0),a=n(22).f,s=n(14),o=n(85),u=n(13),c=n(87),l=n(26),h="".endsWith,f=Math.min,p=c("endsWith");r({target:"String",proto:!0,forced:!!(l||p||(i=a(String.prototype,"endsWith"),!i||i.writable))&&!p},{endsWith:function(t){var e=String(u(this));o(t);var n=arguments.length>1?arguments[1]:void 0,i=s(e.length),r=void 0===n?i:f(s(n),i),a=String(t);return h?h.call(e,a,r):e.slice(r-a.length,r)===a}})},314:function(t,e,n){"use strict";var i=n(285);n.n(i).a},315:function(t,e,n){"use strict";var i=n(286);n.n(i).a},316:function(t,e,n){"use strict";var i=n(287);n.n(i).a},317:function(t,e,n){"use strict";var i=n(288);n.n(i).a},318:function(t,e,n){"use strict";var i=n(289);n.n(i).a},319:function(t,e,n){"use strict";var i=n(290);n.n(i).a},320:function(t,e,n){"use strict";var i=n(291);n.n(i).a},321:function(t,e,n){var i=n(28),r=n(10),a=n(23);t.exports=function(t){return"string"==typeof t||!r(t)&&a(t)&&"[object String]"==i(t)}},322:function(t,e,n){"use strict";var i=n(292);n.n(i).a},323:function(t,e,n){"use strict";var i=n(293);n.n(i).a},324:function(t,e,n){"use strict";var i=n(294);n.n(i).a},325:function(t,e,n){"use strict";var i=n(0),r=n(27).find,a=n(83),s=n(15),o=!0,u=s("find");"find"in[]&&Array(1).find((function(){o=!1})),i({target:"Array",proto:!0,forced:o||!u},{find:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),a("find")},326:function(t,e,n){"use strict";var i=n(295);n.n(i).a},327:function(t,e,n){"use strict";var i=n(296);n.n(i).a},329:function(t,e,n){"use strict";n.r(e);n(142),n(81),n(305);var i=n(282),r={name:"NavLink",props:{item:{required:!0}},computed:{link:function(){return Object(i.b)(this.item.link)},exact:function(){var t=this;return this.$site.locales?Object.keys(this.$site.locales).some((function(e){return e===t.link})):"/"===this.link},isNonHttpURI:function(){return Object(i.g)(this.link)||Object(i.h)(this.link)},isBlankTarget:function(){return"_blank"===this.target},isInternal:function(){return!Object(i.f)(this.link)&&!this.isBlankTarget},target:function(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(i.f)(this.link)?"_blank":""},rel:function(){return this.isNonHttpURI?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":""}},methods:{focusoutAction:function(){this.$emit("focusout")}}},a=n(19),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isInternal?n("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction(e)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):n("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?n("OutboundLink"):t._e()],1)}),[],!1,null,null,null).exports,o={name:"Home",components:{NavLink:s},computed:{data:function(){return this.$page.frontmatter},actionLink:function(){return{link:this.data.actionLink,text:this.data.actionText}}}},u=(n(308),Object(a.a)(o,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("main",{staticClass:"home",attrs:{"aria-labelledby":"main-title"}},[n("header",{staticClass:"hero"},[t.data.heroImage?n("img",{attrs:{src:t.$withBase(t.data.heroImage),alt:t.data.heroAlt||"hero"}}):t._e(),t._v(" "),null!==t.data.heroText?n("h1",{attrs:{id:"main-title"}},[t._v("\n "+t._s(t.data.heroText||t.$title||"Hello")+"\n ")]):t._e(),t._v(" "),null!==t.data.tagline?n("p",{staticClass:"description"},[t._v("\n "+t._s(t.data.tagline||t.$description||"Welcome to your VuePress site")+"\n ")]):t._e(),t._v(" "),t.data.actionText&&t.data.actionLink?n("p",{staticClass:"action"},[n("NavLink",{staticClass:"action-button",attrs:{item:t.actionLink}})],1):t._e()]),t._v(" "),t.data.features&&t.data.features.length?n("div",{staticClass:"features"},t._l(t.data.features,(function(e,i){return n("div",{key:i,staticClass:"feature"},[n("h2",[t._v(t._s(e.title))]),t._v(" "),n("p",[t._v(t._s(e.details))])])})),0):t._e(),t._v(" "),n("Content",{staticClass:"theme-default-content custom"}),t._v(" "),t.data.footer?n("div",{staticClass:"footer"},[t._v("\n "+t._s(t.data.footer)+"\n ")]):t._e()],1)}),[],!1,null,null,null).exports),c=(n(309),n(20),n(149),n(143),n(298),n(25),n(151),n(283),n(299),n(145),n(57),n(300),n(301),n(313),n(58),n(148),n(153)),l=n.n(c),h=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,i=l()(e,"title","");return l()(e,"frontmatter.tags")&&(i+=" ".concat(e.frontmatter.tags.join(" "))),n&&(i+=" ".concat(n)),f(t,i)},f=function(t,e){var n=function(t){return t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")},i=new RegExp("[^\0-]"),r=t.split(/\s+/g).map((function(t){return t.trim()})).filter((function(t){return!!t}));if(i.test(t))return r.some((function(t){return e.toLowerCase().indexOf(t)>-1}));var a=t.endsWith(" ");return new RegExp(r.map((function(t,e){return r.length!==e+1||a?"(?=.*\\b".concat(n(t),"\\b)"):"(?=.*\\b".concat(n(t),")")})).join("")+".+","gi").test(e)},p={name:"SearchBox",data:function(){return{query:"",focused:!1,focusIndex:0,placeholder:void 0}},computed:{showSuggestions:function(){return this.focused&&this.suggestions&&this.suggestions.length},suggestions:function(){var t=this.query.trim().toLowerCase();if(t){for(var e=this.$site.pages,n=this.$site.themeConfig.searchMaxSuggestions||5,i=this.$localePath,r=[],a=0;a=n);a++){var s=e[a];if(this.getPageLocalePath(s)===i&&this.isSearchable(s))if(h(t,s))r.push(s);else if(s.headers)for(var o=0;o=n);o++){var u=s.headers[o];u.title&&h(t,s,u.title)&&r.push(Object.assign({},s,{path:s.path+"#"+u.slug,header:u}))}}return r}},alignRight:function(){return(this.$site.themeConfig.nav||[]).length+(this.$site.repo?1:0)<=2}},mounted:function(){this.placeholder=this.$site.themeConfig.searchPlaceholder||"",document.addEventListener("keydown",this.onHotkey)},beforeDestroy:function(){document.removeEventListener("keydown",this.onHotkey)},methods:{getPageLocalePath:function(t){for(var e in this.$site.locales||{})if("/"!==e&&0===t.path.indexOf(e))return e;return"/"},isSearchable:function(t){var e=null;return null===e||(e=Array.isArray(e)?e:new Array(e)).filter((function(e){return t.path.match(e)})).length>0},onHotkey:function(t){t.srcElement===document.body&&["s","/"].includes(t.key)&&(this.$refs.input.focus(),t.preventDefault())},onUp:function(){this.showSuggestions&&(this.focusIndex>0?this.focusIndex--:this.focusIndex=this.suggestions.length-1)},onDown:function(){this.showSuggestions&&(this.focusIndex "+t._s(e.header.title))]):t._e()])])})),0):t._e()])}),[],!1,null,null,null).exports),g=(n(315),Object(a.a)({},(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"sidebar-button",on:{click:function(e){return t.$emit("toggle-sidebar")}}},[n("svg",{staticClass:"icon",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img",viewBox:"0 0 448 512"}},[n("path",{attrs:{fill:"currentColor",d:"M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"}})])])}),[],!1,null,null,null).exports),v=(n(152),n(35)),m=n(304),b=n(154),k=n.n(b),_={name:"DropdownLink",components:{NavLink:s,DropdownTransition:m.a},props:{item:{required:!0}},data:function(){return{open:!1}},computed:{dropdownAriaLabel:function(){return this.item.ariaLabel||this.item.text}},watch:{$route:function(){this.open=!1}},methods:{setOpen:function(t){this.open=t},isLastItemOfArray:function(t,e){return k()(e)===t}}},x=(n(317),{name:"NavLinks",components:{NavLink:s,DropdownLink:Object(a.a)(_,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[n("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[n("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),n("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),n("DropdownTransition",[n("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(e,i){return n("li",{key:e.link||i,staticClass:"dropdown-item"},["links"===e.type?n("h4",[t._v("\n "+t._s(e.text)+"\n ")]):t._e(),t._v(" "),"links"===e.type?n("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(e.items,(function(i){return n("li",{key:i.link,staticClass:"dropdown-subitem"},[n("NavLink",{attrs:{item:i},on:{focusout:function(n){t.isLastItemOfArray(i,e.items)&&t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0):n("NavLink",{attrs:{item:e},on:{focusout:function(n){t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null).exports},computed:{userNav:function(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav:function(){var t=this,e=this.$site.locales;if(e&&Object.keys(e).length>1){var n=this.$page.path,i=this.$router.options.routes,r=this.$site.themeConfig.locales||{},a={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(e).map((function(a){var s,o=e[a],u=r[a]&&r[a].label||o.lang;return o.lang===t.$lang?s=n:(s=n.replace(t.$localeConfig.path,a),i.some((function(t){return t.path===s}))||(s=a)),{text:u,link:s}}))};return[].concat(Object(v.a)(this.userNav),[a])}return this.userNav},userLinks:function(){return(this.nav||[]).map((function(t){return Object.assign(Object(i.j)(t),{items:(t.items||[]).map(i.j)})}))},repoLink:function(){var t=this.$site.themeConfig.repo;return t?/^https?:/.test(t)?t:"https://github.com/".concat(t):null},repoLabel:function(){if(this.repoLink){if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;for(var t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"],n=0;nMath.abs(n)&&Math.abs(e)>40&&(e>0&&this.touchStart.x<=80?this.toggleSidebar(!0):this.toggleSidebar(!1))}}}),B=Object(a.a)(W,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"theme-container",class:t.pageClasses,on:{touchstart:t.onTouchStart,touchend:t.onTouchEnd}},[t.shouldShowNavbar?n("Navbar",{on:{"toggle-sidebar":t.toggleSidebar}}):t._e(),t._v(" "),n("div",{staticClass:"sidebar-mask",on:{click:function(e){return t.toggleSidebar(!1)}}}),t._v(" "),n("Sidebar",{attrs:{items:t.sidebarItems},on:{"toggle-sidebar":t.toggleSidebar},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("sidebar-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("sidebar-bottom")]},proxy:!0}],null,!0)}),t._v(" "),t.$page.frontmatter.home?n("Home"):n("Page",{attrs:{"sidebar-items":t.sidebarItems},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("page-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("page-bottom")]},proxy:!0}],null,!0)})],1)}),[],!1,null,null,null);e.default=B.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/3.972ca2ed.js b/okhttps-doc/docs/.vuepress/dist/assets/js/3.972ca2ed.js deleted file mode 100644 index 1f8e660f..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/3.972ca2ed.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{297:function(t,e,n){},328:function(t,e,n){"use strict";var i=n(297);n.n(i).a},334:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(328),n(19)),a=Object(r.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=a.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/4.fe3bf0b0.js b/okhttps-doc/docs/.vuepress/dist/assets/js/4.fe3bf0b0.js deleted file mode 100644 index 6c638411..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/4.fe3bf0b0.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{331:function(t,e,s){"use strict";s.r(e);var n=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],o={methods:{getMsg:function(){return n[Math.floor(Math.random()*n.length)]}}},i=s(19),h=Object(i.a)(o,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"theme-container"},[e("div",{staticClass:"theme-default-content"},[e("h1",[this._v("404")]),this._v(" "),e("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),e("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])}),[],!1,null,null,null);e.default=h.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/5.93d38f11.js b/okhttps-doc/docs/.vuepress/dist/assets/js/5.93d38f11.js deleted file mode 100644 index 8b93dda2..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/5.93d38f11.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{330:function(e,t,a){"use strict";a.r(t);a(143),a(92),a(81);var n={props:{name:{type:String,default:"default"},isolated:{type:Boolean,default:!1},languages:Object},data:function(){return{selectedLanguage:Object.keys(this.languages)[0]}},computed:{root:function(){for(var e,t=this;e=t.$parent;)t=e;return t},localStorageKey:function(){return"vuepress-plugin-code-switcher@".concat(this.name)}},methods:{switchLanguage:function(e){if(this.isolated)return this.selectedLanguage=e;"undefined"!=typeof localStorage&&localStorage.setItem(this.localStorageKey,e),this.root.$emit("change",{name:this.name,value:e})}},created:function(){var e=this;if(!this.isolated){if("undefined"!=typeof localStorage){var t=localStorage.getItem(this.localStorageKey);t&&-1!==Object.keys(this.languages).indexOf(t)&&(this.selectedLanguage=t)}this.root.$on("change",(function(t){var a=t.name,n=t.value;a===e.name&&(e.selectedLanguage=n)}))}}},s=a(19),i=Object(s.a)(n,(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"code-switcher"},[a("div",{staticClass:"tab-header"},[a("ul",e._l(e.languages,(function(t,n){return a("li",{key:n,class:{active:e.selectedLanguage===n},on:{click:function(t){return e.switchLanguage(n)}}},[e._v(" "+e._s(t)+"\n ")])})),0)]),e._v(" "),e._l(e.languages,(function(t,n){return a("div",{directives:[{name:"show",rawName:"v-show",value:n===e.selectedLanguage,expression:"shorthand === selectedLanguage"}],key:n,staticClass:"tab-content"},[e._t(n)],2)}))],2)}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/6.fd474f39.js b/okhttps-doc/docs/.vuepress/dist/assets/js/6.fd474f39.js deleted file mode 100644 index 66342655..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/6.fd474f39.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{337:function(s,t,n){"use strict";n.r(t);var a=n(19),e=Object(a.a)({},(function(){var s=this,t=s.$createElement,n=s._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[n("div",{staticClass:"language-java line-numbers-mode"},[n("pre",{pre:!0,attrs:{class:"language-java"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 构建 HTTP")]),s._v("\n"),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),n("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("baseUrl")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[s._v('"https://api.demo.com"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �步请求")]),s._v("\n"),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("List")]),n("span",{pre:!0,attrs:{class:"token generics"}},[n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" users "),n("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// http://api.demo.com/users")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// GET请求")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 获��应报文体")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("toList")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到目标数�")]),s._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 异步请求")]),s._v("\nhttp"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/jack"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// http://api.demo.com/users/jack")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到目标数�")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),s._v(" jack "),n("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("toBean")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// GET请求")]),s._v("\n")])]),s._v(" "),n("div",{staticClass:"line-numbers-wrapper"},[n("span",{staticClass:"line-number"},[s._v("1")]),n("br"),n("span",{staticClass:"line-number"},[s._v("2")]),n("br"),n("span",{staticClass:"line-number"},[s._v("3")]),n("br"),n("span",{staticClass:"line-number"},[s._v("4")]),n("br"),n("span",{staticClass:"line-number"},[s._v("5")]),n("br"),n("span",{staticClass:"line-number"},[s._v("6")]),n("br"),n("span",{staticClass:"line-number"},[s._v("7")]),n("br"),n("span",{staticClass:"line-number"},[s._v("8")]),n("br"),n("span",{staticClass:"line-number"},[s._v("9")]),n("br"),n("span",{staticClass:"line-number"},[s._v("10")]),n("br"),n("span",{staticClass:"line-number"},[s._v("11")]),n("br"),n("span",{staticClass:"line-number"},[s._v("12")]),n("br"),n("span",{staticClass:"line-number"},[s._v("13")]),n("br"),n("span",{staticClass:"line-number"},[s._v("14")]),n("br"),n("span",{staticClass:"line-number"},[s._v("15")]),n("br"),n("span",{staticClass:"line-number"},[s._v("16")]),n("br"),n("span",{staticClass:"line-number"},[s._v("17")]),n("br"),n("span",{staticClass:"line-number"},[s._v("18")]),n("br")])]),s._v(" "),n("p",[n("strong",[n("center",[s._v("竟然�到 "),n("font",{attrs:{size:"5"}},[s._v("15")]),s._v(" 秒,你已学会 "),n("font",{attrs:{size:"6"}},[s._v("90")]),s._v("% 的精髓�")],1)],1),s._v(" "),n("center",[n("RouterLink",{attrs:{to:"/guide/"}},[n("strong",[s._v("了解更多")])])],1)],1)])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/7.51e5642d.js b/okhttps-doc/docs/.vuepress/dist/assets/js/7.51e5642d.js deleted file mode 100644 index c76c8a33..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/7.51e5642d.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{338:function(s,t,a){"use strict";a.r(t);var n=a(19),e=Object(n.a)({},(function(){var s=this,t=s.$createElement,a=s._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[a("h1",{attrs:{id:"起步"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#起步"}},[s._v("#")]),s._v(" 起步")]),s._v(" "),a("p",[s._v("OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。")]),s._v(" "),a("ul",[a("li",[s._v("链�调用,一点到底")]),s._v(" "),a("li",[s._v("BaseURL�URL��符�JSON自动�装与解�")]),s._v(" "),a("li",[s._v("�步拦截器�异步预处�器�回调执行器�全局监��回调阻断")]),s._v(" "),a("li",[s._v("文件上传下载(过程控制�进度监�)")]),s._v(" "),a("li",[s._v("�方法回调,充分利用 Lambda 表达�")]),s._v(" "),a("li",[s._v("TCP连接池�Http2")])]),s._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[s._v("TIP")]),s._v(" "),a("ul",[a("li",[s._v("OkHttps �常轻�(59Kb),仅是 Retrofit(124Kb)的一�,并且更加的开箱�用,API 也更加自然和语义化。")]),s._v(" "),a("li",[s._v("OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit ��")]),s._v(" "),a("li",[s._v("OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。")])])]),s._v(" "),a("h2",{attrs:{id:"安装"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#安装"}},[s._v("#")]),s._v(" 安装")]),s._v(" "),a("h3",{attrs:{id:"maven"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#maven"}},[s._v("#")]),s._v(" Maven")]),s._v(" "),a("div",{staticClass:"language-xml line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-xml"}},[a("code",[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),s._v("dependency")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),s._v("groupId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v("com.ejlchina"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("")])]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),s._v("artifactId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v("okhttps"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("")])]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),s._v("version")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v("1.0.5"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("")])]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("")])]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br")])]),a("h3",{attrs:{id:"gradle"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#gradle"}},[s._v("#")]),s._v(" Gradle")]),s._v(" "),a("div",{staticClass:"language-groovy line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-groovy"}},[a("code",[s._v("implementation "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v("'com.ejlchina:okhttps:1.0.5'")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br")])]),a("p",[s._v("安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��:")]),s._v(" "),a("div",{staticClass:"language-groovy line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-groovy"}},[a("code",[s._v("android "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置..")]),s._v("\n compileOptions "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n sourceCompatibility "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("1.8")]),s._v("\n targetCompatibility "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[s._v("1.8")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br")])]),a("h2",{attrs:{id:"使用"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用"}},[s._v("#")]),s._v(" 使用")]),s._v(" "),a("h3",{attrs:{id:"构建实例"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#构建实例"}},[s._v("#")]),s._v(" 构建实例")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br")])]),a("p",[s._v("以上代�构建了一个最简�的"),a("code",[s._v("HTTP")]),s._v("实例,它拥有以下方法:")]),s._v(" "),a("ul",[a("li",[a("code",[s._v("sync(String url)")]),s._v(" 开始一个�步请求")]),s._v(" "),a("li",[a("code",[s._v("async(String url)")]),s._v(" 开始一个异步请求")]),s._v(" "),a("li",[a("code",[s._v("cancel(String tag)")]),s._v(" 按标签�消请求")]),s._v(" "),a("li",[a("code",[s._v("cancelAll()")]),s._v(" �消所有HTTP任务,包括�步和异步")]),s._v(" "),a("li",[a("code",[s._v("request(Request request)")]),s._v(" OkHttp 原生请求")]),s._v(" "),a("li",[a("code",[s._v("webSocket(Request request, WebSocketListener listener)")]),s._v(" WebSocket通讯")])]),s._v(" "),a("p",[s._v("为了使用方便,在构建的时候,我们更愿�指定一个"),a("code",[s._v("BaseUrl")]),s._v("(详� "),a("RouterLink",{attrs:{to:"/guide/configuration.html#设置-baseurl"}},[s._v("设置 BaseUrl")]),s._v("):")],1),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("baseUrl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"http://api.demo.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br")])]),a("p",[s._v("为了简化文档,下文中出现的"),a("code",[s._v("http")]),s._v("�是在构建时设置了"),a("code",[s._v("BaseUrl")]),s._v("的"),a("code",[s._v("HTTP")]),s._v("实例。")]),s._v(" "),a("h3",{attrs:{id:"�步请求"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�步请求"}},[s._v("#")]),s._v(" �步请求")]),s._v(" "),a("p",[s._v("使用方法"),a("code",[s._v("sync(String url)")]),s._v("开始一个�步请求:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" users "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// http://api.demo.com/users")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// GET请求")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 获��应报文体")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到目标数�")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br")])]),a("p",[s._v("方法"),a("code",[s._v("sync")]),s._v("返回一个�步"),a("code",[s._v("HttpTask")]),s._v(",�链�使用。")]),s._v(" "),a("h3",{attrs:{id:"异步请求"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#异步请求"}},[s._v("#")]),s._v(" 异步请求")]),s._v(" "),a("p",[s._v("使用方法"),a("code",[s._v("async(String url)")]),s._v("开始一个异步请求:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users/1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// http://api.demo.com/users/1")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 得到目标数�")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),s._v(" user "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toBean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("User")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// GET请求")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br")])]),a("p",[s._v("方法"),a("code",[s._v("async")]),s._v("返回一个异步"),a("code",[s._v("HttpTask")]),s._v(",�链�使用。")]),s._v(" "),a("p",[a("strong",[s._v("至此,你已轻�学会了 OkHttps 95% 的常规用法�但别急,��还有更精彩的。")])])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/8.d296d289.js b/okhttps-doc/docs/.vuepress/dist/assets/js/8.d296d289.js deleted file mode 100644 index 791bf3d0..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/8.d296d289.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{336:function(s,t,a){"use strict";a.r(t);var n=a(19),e=Object(n.a)({},(function(){var s=this,t=s.$createElement,a=s._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[a("h1",{attrs:{id:"安�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#安�"}},[s._v("#")]),s._v(" 安�")]),s._v(" "),a("h2",{attrs:{id:"回调线程切�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#回调线程切�"}},[s._v("#")]),s._v(" 回调线程切�")]),s._v(" "),a("p",[s._v("在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。")]),s._v(" "),a("p",[s._v("在 "),a("strong",[s._v("默认")]),s._v(" 情况下,"),a("strong",[s._v("所有回调")]),s._v(" 函数都会 "),a("strong",[s._v("在 IO 线程")]),s._v(" 执行。为什么会设计如此呢?这是因为 OkHttps �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。")]),s._v(" "),a("h3",{attrs:{id:"�置"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�置"}},[s._v("#")]),s._v(" �置")]),s._v(" "),a("p",[s._v("但是在 Android 里使用 OkHttps 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("callbackExecutor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Runnable")]),s._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 实际编�中�以� Handler �出�,�需��次执行回调都�新创建")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("new")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Handler")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Looper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getMainLooper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br")])]),a("h3",{attrs:{id:"用例"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#用例"}},[s._v("#")]),s._v(" 用例")]),s._v(" "),a("p",[s._v("上述代�便实现了让 "),a("strong",[s._v("所有")]),s._v(" 的 "),a("strong",[s._v("回调函数")]),s._v(" 都在 "),a("strong",[s._v("主线程(UI线程)")]),s._v(" 执行的目的,如:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"Jack"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Process")]),s._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Exception")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnComplete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("State")]),s._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br")])]),a("p",[s._v("但是,如果�时还想让�些回调放在IO线程,实现 "),a("strong",[s._v("自由切�")]),s._v(",怎么办呢?OkHttps 给出了�常�活的方法,如下:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"Jack"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Process")]),s._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nextOnIO")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 指定下一个回调在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Exception")]),s._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行(没有指明 nextOnIO 则在回调执行器里执行)")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nextOnIO")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 指定下一个回调在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnComplete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("State")]),s._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br"),a("span",{staticClass:"line-number"},[s._v("16")]),a("br"),a("span",{staticClass:"line-number"},[s._v("17")]),a("br")])]),a("p",[s._v("无论是哪一个回调,都�以使用"),a("code",[s._v("nextOnIO()")]),s._v("方法自由切�。�样,对于文件下载也是一样:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[s._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"/download/test.zip"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBody")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnProcess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Process")]),s._v(" process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toFolder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"D:/download/"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("nextOnIO")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 指定下一个回调在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnSuccess")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("File")]),s._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 IO 线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnFailure")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Failure")]),s._v(" failure"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在主线程执行")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("start")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br")])]),a("h2",{attrs:{id:"生命周期绑定"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#生命周期绑定"}},[s._v("#")]),s._v(" 生命周期绑定")]),s._v(" "),a("p",[s._v("由于 OkHttps 并��赖于 Android,所以它并没有�供关于生命周期绑定的直接实现,但它的一些扩展机制让我们很容易就�以实现这个需求。在开始之�,我们首先��解何为生命周期绑定:")]),s._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[s._v("HTTP 请求的生命周期绑定")]),s._v(" "),a("p",[s._v("所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错�")])]),s._v(" "),a("p",[s._v("现在我们需�对"),a("code",[s._v("HTTP")]),s._v("实例进行�置,�置�的"),a("code",[s._v("HTTP")]),s._v("实例具有生命周期绑定的功能,在"),a("code",[s._v("Activity")]),s._v("或"),a("code",[s._v("Fragment")]),s._v("里,它的使用效果如下:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 Activity 或 Fragment 内�起请求")]),s._v("\nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("async")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"http://www.baidu.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("bind")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getLifecycle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 绑定生命周期")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("setOnResponse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("i")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"FirstFragment"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[s._v('"收到请求:"')]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("+")]),s._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br")])]),a("p",[s._v("上述代�中的"),a("code",[s._v("getLifecycle()")]),s._v("是"),a("code",[s._v("Activity")]),s._v("或"),a("code",[s._v("Fragment")]),s._v("自带的方法,而"),a("code",[s._v("bind()")]),s._v("是"),a("code",[s._v("HttpTask")]),s._v("的现有方法。在�置好"),a("code",[s._v("HTTP")]),s._v("实例�,上述代��起的请求便�以感知"),a("code",[s._v("Activity")]),s._v("或"),a("code",[s._v("Fragment")]),s._v("的生命周期。")]),s._v(" "),a("p",[s._v("那"),a("code",[s._v("HTTP")]),s._v("实例到底该如何�置呢?")]),s._v(" "),a("h3",{attrs:{id:"第一步:�置预处�器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第一步:�置预处�器"}},[s._v("#")]),s._v(" 第一步:�置预处�器")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置项")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("addPreprocessor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Preprocessor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("PreChain")]),s._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getTask")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Object")]),s._v(" bound "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 判断 task 是�绑定了 Lifecycle 对象")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("bound "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �新绑定一个 生命周期监视器(LCObserver)对象,它的定义�下一步")]),s._v("\n task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("bind")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("new")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" bound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置项")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br")])]),a("h3",{attrs:{id:"第二步:定义生命周期监视器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第二步:定义生命周期监视器"}},[s._v("#")]),s._v(" 第二步:定义生命周期监视器")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("public")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("class")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("implements")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LifecycleObserver")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),s._v(" lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),s._v(" lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("task "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("lifecycle "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("addObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[s._v("@OnLifecycleEvent")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Lifecycle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v("ON_STOP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("public")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("void")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("onStop")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("cancel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在 ON_STOP 事件中,�消对应的 HTTP 任务")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("public")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("void")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("unbind")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 在请求完�之�移除监视器")]),s._v("\n lifecycle"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("removeObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br"),a("span",{staticClass:"line-number"},[s._v("14")]),a("br"),a("span",{staticClass:"line-number"},[s._v("15")]),a("br"),a("span",{staticClass:"line-number"},[s._v("16")]),a("br"),a("span",{staticClass:"line-number"},[s._v("17")]),a("br"),a("span",{staticClass:"line-number"},[s._v("18")]),a("br"),a("span",{staticClass:"line-number"},[s._v("19")]),a("br"),a("span",{staticClass:"line-number"},[s._v("20")]),a("br"),a("span",{staticClass:"line-number"},[s._v("21")]),a("br"),a("span",{staticClass:"line-number"},[s._v("22")]),a("br")])]),a("h3",{attrs:{id:"第三步:�置全局回调监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第三步:�置全局回调监�"}},[s._v("#")]),s._v(" 第三步:�置全局回调监�")]),s._v(" "),a("p",[s._v("以上两步其实已�实现了生命周期绑定的功能,但是在请求完�之�,我们需�在"),a("code",[s._v("lifecycle")]),s._v("中移除"),a("code",[s._v("LCObserver")]),s._v("对象:")]),s._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HTTP")]),s._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置项")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("completeListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(">")])]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("HttpResult")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("State")]),s._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("->")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("Object")]),s._v(" bound "),a("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("getBound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 判断 task 是�绑定了生命周期监视器(LCObserver)对象")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("if")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("bound "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("instanceof")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("{")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// 解绑监视器")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[s._v("LCObserver")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" bound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("unbind")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("return")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),s._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[s._v("// �略其它�置项")]),s._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[s._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])]),s._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[s._v("1")]),a("br"),a("span",{staticClass:"line-number"},[s._v("2")]),a("br"),a("span",{staticClass:"line-number"},[s._v("3")]),a("br"),a("span",{staticClass:"line-number"},[s._v("4")]),a("br"),a("span",{staticClass:"line-number"},[s._v("5")]),a("br"),a("span",{staticClass:"line-number"},[s._v("6")]),a("br"),a("span",{staticClass:"line-number"},[s._v("7")]),a("br"),a("span",{staticClass:"line-number"},[s._v("8")]),a("br"),a("span",{staticClass:"line-number"},[s._v("9")]),a("br"),a("span",{staticClass:"line-number"},[s._v("10")]),a("br"),a("span",{staticClass:"line-number"},[s._v("11")]),a("br"),a("span",{staticClass:"line-number"},[s._v("12")]),a("br"),a("span",{staticClass:"line-number"},[s._v("13")]),a("br")])]),a("p",[a("strong",[s._v("以上三步便在Android中实现了生命周期与HTTP请求绑定的功能")])]),s._v(" "),a("p",[s._v("�常简�,懒得敲代�的�学还�以 "),a("a",{attrs:{href:"https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java",target:"_blank",rel:"noopener noreferrer"}},[s._v("点这里 OkHttps.java"),a("OutboundLink")],1),s._v(" 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。")]),s._v(" "),a("p",[s._v("有需�的�学,�以直接下载下�使用,还�以基于它�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考"),a("a",{attrs:{href:"#65-%E4%B8%B2%E8%A1%8C%E9%A2%84%E5%A4%84%E7%90%86%E5%99%A8token%E9%97%AE%E9%A2%98%E6%9C%80%E4%BD%B3%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88"}},[s._v("6.5 串行预处�器(TOKEN问题最佳解决方案)")]),s._v(",�比如扩展实现生命周期与下载事件绑定的功能,都�常简�。")])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/9.bff804f8.js b/okhttps-doc/docs/.vuepress/dist/assets/js/9.bff804f8.js deleted file mode 100644 index 2dae5b30..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/9.bff804f8.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{339:function(t,s,a){"use strict";a.r(s);var n=a(19),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"�置"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�置"}},[t._v("#")]),t._v(" �置")]),t._v(" "),a("h2",{attrs:{id:"设置-baseurl"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#设置-baseurl"}},[t._v("#")]),t._v(" 设置 BaseUrl")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("baseUrl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://api.demo.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 设置 BaseUrl")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br")])]),a("p",[t._v("该�置全局生效,在�置了"),a("code",[t._v("BaseUrl")]),t._v("之�,具体的请求便�以�略"),a("code",[t._v("BaseUrl")]),t._v("部分,使得代�更加简�,例如:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// http://api.demo.com/users")]),t._v("\n\nhttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/auth/signin"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// http://api.demo.com/auth/signin")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"username"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Jackson"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addBodyParam")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"xxxxxx"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// POST请求")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br")])]),a("p",[t._v("在�置了"),a("code",[t._v("BaseUrl")]),t._v("之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://www.baidu.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br")])]),a("h2",{attrs:{id:"回调执行器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#回调执行器"}},[t._v("#")]),t._v(" 回调执行器")]),t._v(" "),a("p",[t._v("OkHttps 默认所有回调都在 "),a("strong",[t._v("IO线程")]),t._v(" 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建"),a("code",[t._v("HTTP")]),t._v("时�置如下:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("callbackExecutor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Runnable")]),t._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("runOnUiThread")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在UI线程执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br")])]),a("p",[t._v("该�置默认 "),a("strong",[t._v("影�所有回调")]),t._v("。")]),t._v(" "),a("h2",{attrs:{id:"�置-okhttpclient"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#�置-okhttpclient"}},[t._v("#")]),t._v(" �置 OkHttpClient")]),t._v(" "),a("p",[t._v("与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("config")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),t._v(" builder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �置连接池 最�10个连接(��置默认为 5)")]),t._v("\n builder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("connectionPool")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConnectionPool")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TimeUnit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("MINUTES"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �置连接超时时间(默认10秒)")]),t._v("\n builder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("connectTimeout")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TimeUnit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SECONDS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// �置拦截器")]),t._v("\n builder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addInterceptor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Chain")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Request")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("request")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 必须�步返回,拦截器内无法执行异步�作")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 其它�置: CookieJar�SSL�缓存�代��事件监�...")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br")])]),a("h2",{attrs:{id:"并行预处�器"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#并行预处�器"}},[t._v("#")]),t._v(" 并行预处�器")]),t._v(" "),a("p",[t._v("预处�器("),a("code",[t._v("Preprocessor")]),t._v(")�以让我们在请求�出之�对请求本身�一些改�,但与"),a("code",[t._v("OkHttp")]),t._v("的拦截器("),a("code",[t._v("Interceptor")]),t._v(")��:预处�器�以让我们 "),a("strong",[t._v("异步")]),t._v(" 处�这些问题。")]),t._v(" "),a("p",[t._v("例如,当我们想为请求任务自动添加"),a("code",[t._v("Token")]),t._v("头信�,而"),a("code",[t._v("Token")]),t._v("�能通过异步方法"),a("code",[t._v("requestToken")]),t._v("获�时,这时使用"),a("code",[t._v("Interceptor")]),t._v("就很难处�了,但�以使用预处�器轻�解决:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addPreprocessor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PreChain")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTask")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获得当�的HTTP任务")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isTagged")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Auth"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 根�标签判断该任务是�需�Token")]),t._v("\n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("requestToken")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 异步获� Token")]),t._v("\n task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addHeader")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Token"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 为任务添加头信�")]),t._v("\n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 继续当�的任务")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br")])]),a("p",[t._v("和"),a("code",[t._v("Interceptor")]),t._v("一样,"),a("code",[t._v("Preprocessor")]),t._v("也�以添加多个。他们之间的区别如下:")]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("拦截器与预处�器的区别")]),t._v(" "),a("ul",[a("li",[t._v("拦截器�能处��步�作,预处�器支�处�异步�作")]),t._v(" "),a("li",[t._v("拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节)")]),t._v(" "),a("li",[t._v("拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调监�(详�6.6章节)")])])]),t._v(" "),a("h2",{attrs:{id:"串行预处�器(token问题最佳解决方案)"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#串行预处�器(token问题最佳解决方案)"}},[t._v("#")]),t._v(" 串行预处�器(TOKEN问题最佳解决方案)")]),t._v(" "),a("p",[t._v("普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当"),a("code",[t._v("Token")]),t._v("过期时我们需�去刷新获�新"),a("code",[t._v("Token")]),t._v(",而刷新"),a("code",[t._v("Token")]),t._v("这个�作�能有一个任务去执行,因为如果"),a("code",[t._v("n")]),t._v("个任务�时执行的�,那么必有"),a("code",[t._v("n-1")]),t._v("个任务刚刷新得到的"),a("code",[t._v("Token")]),t._v("�能就立马失效了,而这是我们所�希望的。")]),t._v(" "),a("p",[t._v("为了解决这个问题,OkHttps �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addSerialPreprocessor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PreChain")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTask")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isTagged")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Auth"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 检查过期,若需�则刷新Token")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("requestTokenAndRefreshIfExpired")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addHeader")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Token"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" \n chain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("proceed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 调用此方法�,�会有其它任务进入该处�器")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br")])]),a("p",[t._v("串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程�")]),t._v(" "),a("h2",{attrs:{id:"全局回调监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#全局回调监�"}},[t._v("#")]),t._v(" 全局回调监�")]),t._v(" "),a("p",[t._v("全局回调是实际开�中�常需�的功能,比如对�务器�应的状��进行统一处�等,�时 OkHttps 的全局回调还具有 "),a("strong",[t._v("回调阻断")]),t._v(" 的功能:")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("responseListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpResult")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所有请求�应�都会走这里")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("completeListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),t._v(" state"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所有请求执行完都会走这里")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("exceptionListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IOException")]),t._v(" error"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所有请求�生异常都会走这里")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br"),a("span",{staticClass:"line-number"},[t._v("8")]),a("br"),a("span",{staticClass:"line-number"},[t._v("9")]),a("br"),a("span",{staticClass:"line-number"},[t._v("10")]),a("br"),a("span",{staticClass:"line-number"},[t._v("11")]),a("br"),a("span",{staticClass:"line-number"},[t._v("12")]),a("br"),a("span",{staticClass:"line-number"},[t._v("13")]),a("br"),a("span",{staticClass:"line-number"},[t._v("14")]),a("br"),a("span",{staticClass:"line-number"},[t._v("15")]),a("br"),a("span",{staticClass:"line-number"},[t._v("16")]),a("br"),a("span",{staticClass:"line-number"},[t._v("17")]),a("br")])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("全局回调监�与拦截器的异�:")]),t._v(" "),a("ul",[a("li",[t._v("拦截器�以添加多个,全局回调监�分三�,��最多添加一个")]),t._v(" "),a("li",[t._v("拦截器处的�时机在请求�和�应�,全局回调监��在�应�,并且晚于拦截器")]),t._v(" "),a("li",[t._v("全局回调监��以 "),a("strong",[t._v("阻断")]),t._v("(return false)�个请求的具体回调,而拦截器�能")])])]),t._v(" "),a("h2",{attrs:{id:"全局下载监�"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#全局下载监�"}},[t._v("#")]),t._v(" 全局下载监�")]),t._v(" "),a("div",{staticClass:"language-java line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTTP")]),t._v(" http "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HTTP"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("downloadListener")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HttpTask")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Download")]),t._v(" download"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所有下载在开始之�都会先走这里")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ctrl")]),t._v(" ctrl "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" download"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getCtrl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 下载控制器")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])]),t._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[t._v("1")]),a("br"),a("span",{staticClass:"line-number"},[t._v("2")]),a("br"),a("span",{staticClass:"line-number"},[t._v("3")]),a("br"),a("span",{staticClass:"line-number"},[t._v("4")]),a("br"),a("span",{staticClass:"line-number"},[t._v("5")]),a("br"),a("span",{staticClass:"line-number"},[t._v("6")]),a("br"),a("span",{staticClass:"line-number"},[t._v("7")]),a("br")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/okhttps-doc/docs/.vuepress/dist/assets/js/app.1e2fa6f5.js b/okhttps-doc/docs/.vuepress/dist/assets/js/app.1e2fa6f5.js deleted file mode 100644 index 4a930851..00000000 --- a/okhttps-doc/docs/.vuepress/dist/assets/js/app.1e2fa6f5.js +++ /dev/null @@ -1,13 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,c=e[0],u=e[1],s=e[2],l=0,p=[];l0?o(r(t),9007199254740991):0}},function(t,e,n){var r=n(6),o=n(1),i=n(4),a=Object.defineProperty,c={},u=function(t){throw t};t.exports=function(t,e){if(i(c,t))return c[t];e||(e={});var n=[][t],s=!!i(e,"ACCESSORS")&&e.ACCESSORS,f=i(e,0)?e[0]:u,l=i(e,1)?e[1]:void 0;return c[t]=!!n&&!o((function(){if(s&&!r)return!0;var t={length:-1};s?a(t,1,{enumerable:!0,get:u}):t[1]=1,n.call(t,f,l)}))}},function(t,e,n){var r=n(13);t.exports=function(t){return Object(r(t))}},function(t,e,n){var r=n(67),o=n(21),i=n(160);r||o(Object.prototype,"toString",i,{unsafe:!0})},function(t,e,n){var r=n(193),o=n(196);t.exports=function(t,e){var n=o(t,e);return r(n)?n:void 0}},function(t,e,n){"use strict";function r(t,e,n,r,o,i,a,c){var u,s="function"==typeof t?t.options:t;if(e&&(s.render=e,s.staticRenderFns=n,s._compiled=!0),r&&(s.functional=!0),i&&(s._scopeId="data-v-"+i),a?(u=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},s._ssrRegister=u):o&&(u=c?function(){o.call(this,this.$root.$options.shadowRoot)}:o),u)if(s.functional){s._injectStyles=u;var f=s.render;s.render=function(t,e){return u.call(e),f(t,e)}}else{var l=s.beforeCreate;s.beforeCreate=l?[].concat(l,u):[u]}return{exports:t,options:s}}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";var r=n(0),o=n(27).filter,i=n(45),a=n(15),c=i("filter"),u=a("filter");r({target:"Array",proto:!0,forced:!c||!u},{filter:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}})},function(t,e,n){var r=n(3),o=n(9),i=n(4),a=n(59),c=n(96),u=n(37),s=u.get,f=u.enforce,l=String(String).split("String");(t.exports=function(t,e,n,c){var u=!!c&&!!c.unsafe,s=!!c&&!!c.enumerable,p=!!c&&!!c.noTargetGet;"function"==typeof n&&("string"!=typeof e||i(n,"name")||o(n,"name",e),f(n).source=l.join("string"==typeof e?e:"")),t!==r?(u?!p&&t[e]&&(s=!0):delete t[e],s?t[e]=n:o(t,e,n)):s?t[e]=n:a(e,n)})(Function.prototype,"toString",(function(){return"function"==typeof this&&s(this).source||c(this)}))},function(t,e,n){var r=n(6),o=n(93),i=n(29),a=n(11),c=n(30),u=n(4),s=n(94),f=Object.getOwnPropertyDescriptor;e.f=r?f:function(t,e){if(t=a(t),e=c(e,!0),s)try{return f(t,e)}catch(t){}if(u(t,e))return i(!o.f.call(t,e),t[e])}},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e,n){"use strict";var r=n(0),o=n(46);r({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},function(t,e){t.exports=!1},function(t,e,n){var r=n(158),o=n(41),i=n(16),a=n(14),c=n(104),u=[].push,s=function(t){var e=1==t,n=2==t,s=3==t,f=4==t,l=6==t,p=5==t||l;return function(d,h,v,y){for(var m,g,b=i(d),_=o(b),x=r(h,v,3),w=a(_.length),O=0,S=y||c,j=e?S(d,w):n?S(d,0):void 0;w>O;O++)if((p||O in _)&&(g=x(m=_[O],O,b),t))if(e)j[O]=g;else if(g)switch(t){case 3:return!0;case 5:return m;case 6:return O;case 2:u.call(j,m)}else if(f)return!1;return l?-1:s||f?f:j}};t.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6)}},function(t,e,n){var r=n(34),o=n(178),i=n(179),a=r?r.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":a&&a in Object(t)?o(t):i(t)}},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var r=n(5);t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},function(t,e){t.exports={}},function(t,e,n){var r,o=n(8),i=n(163),a=n(62),c=n(31),u=n(164),s=n(95),f=n(42),l=f("IE_PROTO"),p=function(){},d=function(t){return" - - diff --git a/okhttps-doc/docs/.vuepress/dist/guide/configuration.html b/okhttps-doc/docs/.vuepress/dist/guide/configuration.html deleted file mode 100644 index 0564067a..00000000 --- a/okhttps-doc/docs/.vuepress/dist/guide/configuration.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - �置 | OkHttps - - - - - - - - - - - - - - - - - - -

# �置

# 设置 BaseUrl

HTTP http = HTTP.builder()
-        .baseUrl("http://api.demo.com")    // 设置 BaseUrl
-        .build();
-
1
2
3

该�置全局生效,在�置了BaseUrl之�,具体的请求便�以�略BaseUrl部分,使得代�更加简�,例如:

http.sync("/users").get()                  // http://api.demo.com/users
-
-http.sync("/auth/signin")                  // http://api.demo.com/auth/signin
-        .addBodyParam("username", "Jackson")
-        .addBodyParam("password", "xxxxxx")
-        .post();                           // POST请求
-
1
2
3
4
5
6

在�置了BaseUrl之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�:

http.sync("https://www.baidu.com").get();
-
1

# 回调执行器

OkHttps 默认所有回调都在 IO线程 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建HTTP时�置如下:

HTTP http = HTTP.builder()
-        .callbackExecutor((Runnable run) -> {
-            runOnUiThread(run);            // 在UI线程执行
-        })
-        .build();
-
1
2
3
4
5

该�置默认 影�所有回调。

# �置 OkHttpClient

与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下:

HTTP http = HTTP.builder()
-    .config((Builder builder) -> {
-        // �置连接池 最�10个连接(��置默认为 5)
-        builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES));
-        // �置连接超时时间(默认10秒)
-        builder.connectTimeout(20, TimeUnit.SECONDS);
-        // �置拦截器
-        builder.addInterceptor((Chain chain) -> {
-            Request request = chain.request();
-            // 必须�步返回,拦截器内无法执行异步�作
-            return chain.proceed(request);
-        });
-        // 其它�置: CookieJar�SSL�缓存�代��事件监�...
-    })
-    .build();
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 并行预处�器

预处�器(Preprocessor)�以让我们在请求�出之�对请求本身�一些改�,但与OkHttp的拦截器(Interceptor)��:预处�器�以让我们 异步 处�这些问题。

例如,当我们想为请求任务自动添加Token头信�,而Token�能通过异步方法requestToken获�时,这时使用Interceptor就很难处�了,但�以使用预处�器轻�解决:

HTTP http = HTTP.builder()
-        .addPreprocessor((PreChain chain) -> {
-            HttpTask<?> task = chain.getTask();// 获得当�的HTTP任务
-            if (!task.isTagged("Auth")) {      // 根�标签判断该任务是�需�Token
-                chain.proceed();
-                return;
-            }
-            requestToken((String token) -> {   // 异步获� Token
-                task.addHeader("Token", token);// 为任务添加头信�
-                chain.proceed();               // 继续当�的任务
-            });
-        })
-        .build();
-
1
2
3
4
5
6
7
8
9
10
11
12
13

和Interceptor一样,Preprocessor也�以添加多个。他们之间的区别如下:

拦截器与预处�器的区别

  • 拦截器å�ªèƒ½å¤„ç�†å�Œæ­¥æ“�作,预处ç�†å™¨æ”¯æŒ�处ç�†å¼‚æ­¥æ“�作
  • 拦截器都是并行处ç�†è¯·æ±‚,预处ç�†å™¨æ”¯æŒ�串行处ç�†ï¼ˆè¯¦è§�6.5章节)
  • 拦截器处ç�†æ—¶æœºåœ¨è¯·æ±‚å‰�å’Œå“�应å�Žï¼Œé¢„处ç�†å™¨å�ªåœ¨è¯·æ±‚å‰�,并且先于拦截器执行。关于å“�应å�Žï¼ŒOkHttps还æ��供了全局回调监å�¬ï¼ˆè¯¦è§�6.6章节)

# 串行预处�器(TOKEN问题最佳解决方案)

普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当Token过期时我们需�去刷新获�新Token,而刷新Token这个�作�能有一个任务去执行,因为如果n个任务�时执行的�,那么必有n-1个任务刚刷新得到的Token�能就立马失效了,而这是我们所�希望的。

为了解决这个问题,OkHttps �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器:

HTTP http = HTTP.builder()
-        .addSerialPreprocessor((PreChain chain) -> {
-            HttpTask<?> task = chain.getTask();
-            if (!task.isTagged("Auth")) {
-                chain.proceed();
-                return;
-            }
-            // 检查过期,若需�则刷新Token
-            requestTokenAndRefreshIfExpired((String token) -> {
-                task.addHeader("Token", token);            
-                chain.proceed();               // 调用此方法�,�会有其它任务进入该处�器
-            });
-        })
-        .build();
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14

串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程�

# 全局回调监�

全局回调是实际开�中�常需�的功能,比如对�务器�应的状��进行统一处�等,�时 OkHttps 的全局回调还具有 回调阻断 的功能:

HTTP http = HTTP.builder()
-        .responseListener((HttpTask<?> task, HttpResult result) -> {
-            // 所有请求�应�都会走这里
-
-            return true; // 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行
-        })
-        .completeListener((HttpTask<?> task, State state) -> {
-            // 所有请求执行完都会走这里
-
-            return true; // 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行
-        })
-        .exceptionListener((HttpTask<?> task, IOException error) -> {
-            // 所有请求�生异常都会走这里
-
-            return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行
-        })
-        .build();
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

全局回调监�与拦截器的异�:

  • 拦截器å�¯ä»¥æ·»åŠ å¤šä¸ªï¼Œå…¨å±€å›žè°ƒç›‘å�¬åˆ†ä¸‰ç§�,æ¯�ç§�最多添加一个
  • 拦截器处的ç�†æ—¶æœºåœ¨è¯·æ±‚å‰�å’Œå“�应å�Žï¼Œå…¨å±€å›žè°ƒç›‘å�¬å�ªåœ¨å“�应å�Žï¼Œå¹¶ä¸”晚于拦截器
  • 全局回调监å�¬å�¯ä»¥ 阻断(return false)æŸ�个请求的具体回调,而拦截器ä¸�能

# 全局下载监�

HTTP http = HTTP.builder()
-        .downloadListener((HttpTask<?> task, Download download) -> {
-            // 所有下载在开始之�都会先走这里
-            Ctrl ctrl = download.getCtrl();         // 下载控制器
-            
-        })
-        .build();
-
1
2
3
4
5
6
7
- - - diff --git a/okhttps-doc/docs/.vuepress/dist/guide/features.html b/okhttps-doc/docs/.vuepress/dist/guide/features.html deleted file mode 100644 index 23771675..00000000 --- a/okhttps-doc/docs/.vuepress/dist/guide/features.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - 特色 | OkHttps - - - - - - - - - - - - - - - - - - -

# 特色

# 使用 HttpUtils 类

类HttpUtils本是 �身 HttpUtils 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了HTTP接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。

类HttpUtils共定义了四个��方法:

  • of(HTTP http) é…�ç½®HttpUtilsæŒ�有的HTTP实例(ä¸�调用此方法å‰�默认使用一个没有没有ç»�过任何é…�置的HTTP懒实例)
  • sync(String url) 开始一个å�Œæ­¥è¯·æ±‚ (内部通过一个HTTPå�•例实现)
  • async(String url) 开始一个异步请求 (内部通过一个HTTPå�•例实现)
  • cancel(String tag) 按标签å�–消请求(内部通过一个HTTPå�•例实现)
  • cancelAll() å�–消所有HTTP任务,包括å�Œæ­¥å’Œå¼‚步(内部通过一个HTTPå�•例实现)
  • request(Request request) OkHttp 原生请求 (该请求ä¸�ç»�过 预处ç�†å™¨ï¼‰
  • webSocket(Request request, WebSocketListener listener) WebSocket通讯 -  也就是说,能使用http实例的地方,都å�¯ä»¥ä½¿ç”¨HttpUtils类,例如:
// 在�置HTTP实例之�,�能使用全路径方�
-List<Role> roles = HttpUtils.sync("http://api.demo.com/roles")
-        .get().getBody().toList(Role.class);
-
-// �置HTTP实例,全局生效
-HttpUtils.of(HTTP.builder()
-        .baseUrl("http://api.demo.com")
-        .build());
-
-// 内部使用新的HTTP实例
-List<User> users = HttpUtils.sync("/users")
-        .get().getBody().toList(User.class);
-
1
2
3
4
5
6
7
8
9
10
11
12

# 异常处�

使用 OkHttps 时,异常处��是必须的,但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:nothrow(),以满足��的异常处�需求。

# �步请求的异常

默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 try catch ��获,例如:

try {
-    HttpResult result = http.sync("/users/1").get();
-} catch (HttpException e) {
-    Throwable cause = e.getCause(); // 得到异常原因
-    if (cause instanceof ConnectException) {
-        // 当没网络时,会抛出连接异常
-    }
-    if (cause instanceof SocketTimeoutException) {
-        // 当接�长时间未�应,会抛出超时异常
-    }
-    if (cause instanceof UnknownHostException) {
-        // 当把域�或IP写错,会抛出 UnknownHost 异常
-    }
-    // ...
-}
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这�传统的异常处�方�,当然�以解决问题,但 OkHttps 有更佳的方案:

// 方法  nothrow() 让异常�直接抛出
-HttpResult result = http.sync("/users/1").nothrow().get();
-// 判断执行状�
-switch (result.getState()) {
-    case RESPONSED:     // 请求已正常�应
-        break;
-    case CANCELED:      // 请求已被�消
-        break;
-    case NETWORK_ERROR: // 网络错误,说明用户没网了
-        break;
-    case TIMEOUT:       // 请求超时
-        break;
-    case EXCEPTION:     // 其它异常
-        break;
-}
-// 还�以获得具体的异常信�
-IOException error = result.getError();
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 异步请求的异常

异步请求最常用的异常处�方�就是设置一个异常回调:

http.async("/users/1")
-        .setOnResponse((HttpResult result) -> {
-            // 当�生异常时就�会走这里
-        })
-        .setOnException((IOException e) -> {
-            // 这里处�请求异常
-        })
-        .get();
-
1
2
3
4
5
6
7
8

当然,还有一个全局异常监�(ExceptionListener):

HTTP http = HTTP.builder()
-        .exceptionListener((HttpTask<?> task, IOException error) -> {
-            // 所有请求�生异常都会走这里
-
-            return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行
-        })
-        .build();
-
1
2
3
4
5
6
7

如果�设置OnException回调,也没有ExceptionListener,�生异常时会在 IO 线程 中�上抛出,外层无法�获:

try {
-    http.async("/users/1")
-            .setOnResponse((HttpResult result) -> {
-                // 当�生异常时就�会走这里
-            })
-            .get();
-} catch (HttpException e) {
-    // 这�方�是�获�到异常的������
-}
-
1
2
3
4
5
6
7
8
9

�使没有OnException回调,�生异常时,�然会走OnComplete回调,如果设置了的�:

http.async("/users/1")
-        .setOnResponse((HttpResult result) -> {
-            // 当�生异常时就�会走这里
-        })
-        .setOnComplete((State state) -> {
-            // �生异常,会先执行这里,�以根� state 判断�生了什么
-            // 但执行完��然会在IO线程中�上抛出
-        })
-        .get();
-
1
2
3
4
5
6
7
8
9

如果就是想 �处�异常,也��上抛出,�生错误完全无视,�以�到�?�以�还是使用nothrow()方法:

http.async("/users/1")
-        .nothrow()  // 告诉 OkHttps �生异常时��外抛出
-        .setOnResponse((HttpResult result) -> {
-            // 当�生异常时就�会走这里
-        })
-        .get();
-
1
2
3
4
5
6

# �消请求

在 OkHttps 里�消请求共有 4 � 方��选:

  • 使用HttpCall#cancel()å�–消å�•个请求(适用于异步请求,详è§� 3.3 章节)
  • 使用HttpTask#cancel()å�–消å�•个请求(适用于所有请求)(since v1.0.4)
HttpTask<?> task = http.async("/users")
-        .setOnResponse((HttpResult result) -> {
-            // �应回调
-        });
-
-task.get(); // �起 GET 请求
-
-// �消请求,并返回是��消�功
-boolean canceled = task.cancel();   
-
1
2
3
4
5
6
7
8
9
  • 使用HTTP#cancel(String tag)按标签批é‡�å�–消请求(适用于所有请求,详è§�第 5 章节)
  • 使用HTTP#cancelAll()å�–消所有请求(适用于所有请求)(since v1.0.2)
http.cancelAll();   // �消所有请求
-
1
- - - diff --git a/okhttps-doc/docs/.vuepress/dist/guide/foundation.html b/okhttps-doc/docs/.vuepress/dist/guide/foundation.html deleted file mode 100644 index 54bfdf7b..00000000 --- a/okhttps-doc/docs/.vuepress/dist/guide/foundation.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - 基础 | OkHttps - - - - - - - - - - - - - - - - - - -

# 基础

# 请求方法

�步与异步的HttpTask都拥有get�post�put与delete方法。��的是:�步HttpTask的这些方法返回一个HttpResult,而异步HttpTask的这些方法返回一个HttpCall。

HttpResult res1 = http.sync("/users").get();     // �步 GET
-HttpResult res2 = http.sync("/users").post();    // �步 POST
-HttpResult res3 = http.sync("/users/1").put();   // �步 PUT
-HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE
-HttpCall call1 = http.async("/users").get();     // 异步 GET
-HttpCall call2 = http.async("/users").post();    // 异步 POST
-HttpCall call3 = http.async("/users/1").put();   // 异步 PUT
-HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE
-
1
2
3
4
5
6
7
8

# 回调函数

OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅:

http.async("/users/{id}")             // http://api.demo.com/users/1
-        .addPathParam("id", 1)
-        .setOnResponse((HttpResult result) -> {
-            // �应回调
-        })
-        .setOnException((IOException e) -> {
-            // 异常回调
-        })
-        .setOnComplete((State state) -> {
-            // 完�回调,无论�功失败都会执行
-            // 并且在 �应|异常回调 之�执行
-        })
-        .get();
-
1
2
3
4
5
6
7
8
9
10
11
12
13

OkHttps �时还支� 全局回调 和 回调阻断 机制,详� 全局回调监�。

TIP

  • å�ªæœ‰å¼‚步请求æ‰�å�¯ä»¥è®¾ç½®è¿™ä¸‰ç§�(å“�应|异常|完æˆ�)回调
  • å�Œæ­¥è¯·æ±‚直接返回结果,无需使用回调

# HttpResult

HttpResult是HTTP请求执行完�的结果,它是�步请求方法( get�post�put�delete)的返回值,也是异步请求�应回调(OnResponse)的�数,它定义了如下方法:

  • getState() 得到请求执行状æ€�枚举,它有以下å�–值: -
    • State.CANCELED 请求被å�–消
    • State.RESPONSED 已收到å“�应
    • State.TIMEOUT 请求超时
    • State.NETWORK_ERROR 网络错误
    • State.EXCEPTION 其它请求异常
  • getStatus() 得到HTTP状æ€�ç �
  • isSuccessful() 是å�¦å“�应æˆ�功,状æ€�ç �在 [200..300) 之间
  • getHeaders() 得到HTTPå“�应头
  • getHeaders(String name) 得到HTTPå“�应头
  • getHeader(String name) 得到HTTPå“�应头
  • getBody() 得到å“�应报文体Body实例,它定义了如下方法(对å�Œä¸€ä¸ªBody实例,以下的toXXX()类方法å�ªèƒ½ä½¿ç”¨ä¸€ä¸ªä¸”仅能调用一次,除é�žå…ˆä½¿ç”¨ cache 方法): -
    • toBytes() 返回字节数组
    • toByteStream() 返回字节输入æµ�
    • toCharStream() 返回字符输入æµ�
    • toString() 返回字符串
    • toJsonObject() 返回Json对象
    • toJsonArray() 返回Json数组
    • toBean(Class<T> type) 返回根æ�®type自动jsonè§£æž�å�Žçš„JavaBean
    • toList(Class<T> type) 返回根æ�®type自动jsonè§£æž�å�Žçš„JavaBean列表
    • toFile(String filePath) 下载到指定路径
    • toFile(File file) 下载到指定文件
    • toFolder(String dirPath) 下载到指定目录
    • toFolder(File dir) 下载到指定目录
    • getContentType() 返回报文体的媒体类型
    • getContentLength() 返回报文体的字节长度
    • cache() 缓存报文体,开å�¯ç¼“å­˜å�Žå�¯é‡�å¤�使用toXXX()类方法
    • close() 关闭报文体,未对报文体å�šä»»ä½•消费时使用,比如å�ªè¯»å�–报文头
  • getError() 执行中å�‘生的异常,自动æ�•获执行请求时å�‘生的 网络超时ã€�网络错误 å’Œ 其它IO异常
  • close() 关闭报文,未对报文体å�šä»»ä½•消费时使用,比如å�ªè¯»å�–长度

示例,请求结果自动转Bean和List:

// 自动转Bean
-Order order = http.sync("/orders/1")
-        .get().getBody().toBean(Order.class);
-        
-// 自动转List
-List<Order> orders = http.sync("/orders")
-        .get().getBody().toList(Order.class);
-
1
2
3
4
5
6
7

示例,使用 cache 方法:

Body body = http.sync("/orders").get().getBody().cache();
-
-// 使用 cache �,�以多次使用 toXXX() 方法
-System.out.println(body.toString());
-System.out.println(body.toJsonArray());
-System.out.println(body.toList(Order.class));
-
1
2
3
4
5
6

示例,获�下载文件的大�:

long size = http.sync("/download/test.zip")
-            .get().getBody()
-            .close()             // �是想获得文件大�,�消费报文体,所以直接关闭
-            .getContentLength(); // 获得待下载文件的大�
-
-// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络��
-
-System.out.println("size = " + size);
-
1
2
3
4
5
6
7
8

# HttpCall

HttpCall对象是异步请求方法(get�post�put�delete)的返回值,与java的Future接�很�,它有如下方法:

  • cancel() å�–消本次请求,返回å�–消结果
  • isCanceled() 返回请求是å�¦è¢«å�–消
  • isDone() 返回是å�¦æ‰§è¡Œå®Œæˆ�,包å�«å�–消和失败
  • getResult() 返回执行结果HttpResult对象,若请求未执行完,则挂起当å‰�线程直到执行完æˆ�å†�返回

�消一个异步请求示例:

HttpCall call = http.async("/users/1").get();
-
-System.out.println(call.isCanceled());     // false
-
-boolean success = call.cancel();           // �消请求
-
-System.out.println(success);               // true
-System.out.println(call.isCanceled());     // true
-
1
2
3
4
5
6
7
8

# 构建HTTP任务

HTTP对象的sync与async方法返回一个HttpTask对象,该对象�供了�链�调用的addXXX与setXXX等系列方法用于构建任务本身。

  • addHeader(String name, String value) 添加请求头

  • addHeader(Map<String, String> headers) 添加请求头

  • addPathParam(String name, Object value) 添加路径å�‚数:替æ�¢URL里的{name}å� ä½�符

  • addPathParam(Map<String, ?> params) 添加路径å�‚数:替æ�¢URL里的{name}å� ä½�符

  • addUrlParam(String name, Object value) 添加URLå�‚数:拼接在URLçš„?之å�Žï¼ˆæŸ¥è¯¢å�‚数)

  • addUrlParam(Map<String, ?> params) 添加URLå�‚数:拼接在URLçš„?之å�Žï¼ˆæŸ¥è¯¢å�‚数)

  • addBodyParam(String name, Object value) 添加Bodyå�‚数:以表å�•key=value&的形å¼�放在报文体内(表å�•å�‚数)

  • addBodyParam(Map<String, ?> params) 添加Bodyå�‚数:以表å�•key=value&的形å¼�放在报文体内(表å�•å�‚数)

  • addJsonParam(String name, Object value) 添加Jsonå�‚数:请求体为Json(支æŒ�多层结构)

  • addJsonParam(Map<String, ?> params) 添加Jsonå�‚数:请求体为Json(支æŒ�多层结构)

  • setRequestJson(Object json) 设置请求体的Json字符串 或待转æ�¢ä¸º Jsonçš„ JavaBean

  • setRequestJson(Object bean, String dateFormat) 设置请求体的Json字符串 或待转æ�¢ä¸º Jsonçš„ JavaBean

  • addFileParam(String name, String filePath) 上传文件

  • addFileParam(String name, File file) 上传文件

  • addFileParam(String name, String type, InputStream inputStream) 上传文件

  • addFileParam(String name, String type, String fileName, InputStream input) 上传文件

  • addFileParam(String name, String type, byte[] content) 上传文件

  • addFileParam(String name, String type, String fileName, byte[] content) 上传文件

  • setTag(String tag) 为HTTP任务添加标签

  • setRange(long rangeStart) 设置Range头信æ�¯ï¼Œç”¨äºŽæ–­ç‚¹ç»­ä¼ 

  • setRange(long rangeStart, long rangeEnd) 设置Range头信æ�¯ï¼Œå�¯ç”¨äºŽåˆ†å�—下载

  • bind(Object object) 绑定一个对象,å�¯ç”¨äºŽå®žçްAndroid里的生命周期绑定

# 使用标签

有时候我们想对HTTP任务加以分类,这时候�以使用标签功能:

http.async("/users")    //(1)
-        .setTag("A")
-        .get();
-        
-http.async("/users")    //(2)
-        .setTag("A.B")
-        .get();
-        
-http.async("/users")    //(3)
-        .setTag("B")
-        .get();
-        
-http.async("/users")    //(4)
-        .setTag("B")
-        .setTag("C")    // 从 v1.0.4 标签将以追加模�添加,等效于 setTag("B.C")
-        .get();
-        
-http.async("/users")    //(5)
-        .setTag("C")
-        .get();
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

当使用标签�,就�以按标签批�的对HTTP任务进行�消:

int count = http.cancel("B");              //(2)(3)(4)被�消(�消标签包�"B"的任务)
-System.out.println(count);                 // 输出 3
-
1
2

标签除了�以用��消任务,在预处�器中它也�以�挥作用,请�� 并行预处�器 与 串行预处�器(token问题最佳解决方案)。

- - - diff --git a/okhttps-doc/docs/.vuepress/dist/guide/index.html b/okhttps-doc/docs/.vuepress/dist/guide/index.html deleted file mode 100644 index 9b6c66b0..00000000 --- a/okhttps-doc/docs/.vuepress/dist/guide/index.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - èµ·æ­¥ | OkHttps - - - - - - - - - - - - - - - - - - -

# èµ·æ­¥

OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。

  • 链å¼�调用,一点到底
  • BaseURLã€�URLå� ä½�符ã€�JSON自动å°�装与解æž�
  • å�Œæ­¥æ‹¦æˆªå™¨ã€�异步预处ç�†å™¨ã€�回调执行器ã€�全局监å�¬ã€�回调阻断
  • 文件上传下载(过程控制ã€�进度监å�¬ï¼‰
  • å�•方法回调,充分利用 Lambda 表达å¼�
  • TCP连接池ã€�Http2

TIP

  • OkHttps é�žå¸¸è½»é‡�(59Kb),仅是 Retrofit(124Kb)的一å�Šï¼Œå¹¶ä¸”更加的开箱å�³ç”¨ï¼ŒAPI 也更加自然和语义化。
  • OkHttps 是一个纯粹的 Java 网络开å�‘包,并ä¸�ä¾�èµ– Android,这一点和 Retrofit ä¸�å�Œ
  • OkHttps 用起æ�¥å¾ˆä¼˜ç¾Žï¼Œå�¯ä»¥åƒ� RxJava 那样链å¼�用,å�´æ¯” RxJava 更简å�•。

# 安装

# Maven

<dependency>
-     <groupId>com.ejlchina</groupId>
-     <artifactId>okhttps</artifactId>
-     <version>1.0.5</version>
-</dependency>
-
1
2
3
4
5

# Gradle

implementation 'com.ejlchina:okhttps:1.0.5'
-
1

安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��:

android {
-    // �略其它�置..
-    compileOptions {
-        sourceCompatibility = 1.8
-        targetCompatibility = 1.8
-    }
-}
-
1
2
3
4
5
6
7

# 使用

# 构建实例

HTTP http = HTTP.builder().build();
-
1

以上代�构建了一个最简�的HTTP实例,它拥有以下方法:

  • sync(String url) 开始一个å�Œæ­¥è¯·æ±‚
  • async(String url) 开始一个异步请求
  • cancel(String tag) 按标签å�–消请求
  • cancelAll() å�–消所有HTTP任务,包括å�Œæ­¥å’Œå¼‚æ­¥
  • request(Request request) OkHttp 原生请求
  • webSocket(Request request, WebSocketListener listener) WebSocket通讯

为了使用方便,在构建的时候,我们更愿�指定一个BaseUrl(详� 设置 BaseUrl):

HTTP http = HTTP.builder()
-        .baseUrl("http://api.demo.com")
-        .build();
-
1
2
3

为了简化文档,下文中出现的http�是在构建时设置了BaseUrl的HTTP实例。

# �步请求

使用方法sync(String url)开始一个�步请求:

List<User> users = http.sync("/users") // http://api.demo.com/users
-        .get()                         // GET请求
-        .getBody()                     // 获��应报文体
-        .toList(User.class);           // 得到目标数�
-
1
2
3
4

方法sync返回一个�步HttpTask,�链�使用。

# 异步请求

使用方法async(String url)开始一个异步请求:

http.async("/users/1")                //  http://api.demo.com/users/1
-        .setOnResponse((HttpResult result) -> {
-            // 得到目标数�
-            User user = result.getBody().toBean(User.class);
-        })
-        .get();                       // GET请求
-
1
2
3
4
5
6

方法async返回一个异步HttpTask,�链�使用。

至此,你已轻�学会了 OkHttps 95% 的常规用法�但别急,��还有更精彩的。

- - - diff --git a/okhttps-doc/docs/.vuepress/dist/guide/updown.html b/okhttps-doc/docs/.vuepress/dist/guide/updown.html deleted file mode 100644 index 32ad8f39..00000000 --- a/okhttps-doc/docs/.vuepress/dist/guide/updown.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - 上传下载 | OkHttps - - - - - - - - - - - - - - - - - - -

# 上传下载

# 文件下载

OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例:

http.sync("/download/test.zip")
-        .get()                           // 使用 GET 方法(其它方法也�以,看�务器支�)
-        .getBody()                       // 得到报文体
-        .toFile("D:/download/test.zip")  // 下载到指定的路径
-        .start();                        // �动下载
-
-http.sync("/download/test.zip").get().getBody()                  
-        .toFolder("D:/download")         // 下载到指定的目录,文件�将根�下载信�自动生�
-        .start();
-
1
2
3
4
5
6
7
8
9

或使用异步连接方�:

http.async("/download/test.zip")
-        .setOnResponse((HttpResult result) -> {
-            result.getBody().toFolder("D:/download").start();
-        })
-        .get();
-
1
2
3
4
5

这里�说明一下:sync与async的区别在于连接�务器并得到�应这个过程的�步与异步(这个过程的耗时在大文件下载中�比��),而start方法�动的下载过程则都是异步的。

# 下载进度监�

就直接上代�啦,诸�一看便懂:

http.sync("/download/test.zip")
-        .get()
-        .getBody()
-        .setStepBytes(1024)   // 设置�接收 1024 个字节执行一次进度回调(�设置默认为 8192)  
- //     .setStepRate(0.01)    // 设置�接收 1% 执行一次进度回调(�设置以 StepBytes 为准)  
-        .setOnProcess((Process process) -> {           // 下载进度回调
-            long doneBytes = process.getDoneBytes();   // 已下载字节数
-            long totalBytes = process.getTotalBytes(); // 总共的字节数
-            double rate = process.getRate();           // 已下载的比例
-            boolean isDone = process.isDone();         // 是�下载完�
-        })
-        .toFolder("D:/download/")        // 指定下载的目录,文件�将根�下载信�自动生�
- //     .toFile("D:/download/test.zip")  // 指定下载的路径,若文件已存在则覆盖
-        .setOnSuccess((File file) -> {   // 下载�功回调
-            
-        })
-        .start();
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

值得一�的是:由于 OkHttps 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有Content-Length头),例如:

List<User> users = http.sync("/users")
-        .get()
-        .getBody()
-        .setStepBytes(2)
-        .setOnProcess((Process process) -> {
-            System.out.println(process.getRate());
-        })
-        .toList(User.class);
-
1
2
3
4
5
6
7
8

# 下载过程控制

过于简�:还是直接上代�:

Ctrl ctrl = http.sync("/download/test.zip")
-        .get()
-        .getBody()
-        .setOnProcess((Process process) -> {
-            System.out.println(process.getRate());
-        })
-        .toFolder("D:/download/")
-        .start();   // 该方法返回一个下载过程控制器
- 
-ctrl.status();      // 下载状�
-ctrl.pause();       // 暂�下载
-ctrl.resume();      // ��下载
-ctrl.cancel();      // �消下载(�时会删除文件,����)
-
1
2
3
4
5
6
7
8
9
10
11
12
13

无论是�步还是异步�起的下载请求,都�以�以上的控制:

http.async("/download/test.zip")
-        .setOnResponse((HttpResult result) -> {
-            // 拿到下载控制器
-            Ctrl ctrl = result.getBody().toFolder("D:/download/").start();
-        })
-        .get();
-
1
2
3
4
5
6

# 实现断点续传

OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到 断点,便将��的问题�得简�:

http.sync("/download/test.zip")
-        .get()
-        .getBody()
-        .toFolder("D:/download/")
-        .setOnFailure((Failure failure) -> {         // 下载失败回调,以便接收诸如网络错误等失败信�
-            IOException e = failure.getException();  // 具体的异常信�
-            long doneBytes = failure.getDoneBytes(); // 已下载的字节数(断点),需��存,用于断点续传
-            File file = failure.getFile();           // 下载生�的文件,需��存 ,用于断点续传(��存路径也�以)
-        })
-        .start();
-
1
2
3
4
5
6
7
8
9
10

下�代�实现续传:

long doneBytes = ...    // 拿到�存的断点
-File file =  ...        // 待续传的文件
-
-http.sync("/download/test.zip")
-        .setRange(doneBytes)                         // 设置断点(已下载的字节数)
-        .get()
-        .getBody()
-        .toFile(file)                                // 下载到�一个文件里
-        .setAppended()                               // 开�文件追加模�
-        .setOnSuccess((File file) -> {
-
-        })
-        .setOnFailure((Failure failure) -> {
-        
-        })
-        .start();
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 实现分�下载

当文件很大时,有时候我们会考虑分�下载,与断点续传的�路是一样的,示例代�:

static String url = "http://api.demo.com/download/test.zip"
-
-public static void main(String[] args) {
-    long totalSize = HttpUtils.sync(url).get().getBody()
-            .close()             // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭
-            .getContentLength(); // 获得待下载文件的大�(由于未消费报文体,所以该请求�会消耗下载报文体的时间和网络��)
-    download(totalSize, 0);      // 从第 0 �开始下载
-    sleep(50000);                // 等待下载完�(�然本例的主线程就结�啦)
-}
-
-static void download(long totalSize, int index) {
-    long size = 3 * 1024 * 1024;                 // ��下载 3M  
-    long start = index * size;
-    long end = Math.min(start + size, totalSize);
-    HttpUtils.sync(url)
-            .setRange(start, end)                // 设置本次下载的范围
-            .get().getBody()
-            .toFile("D:/download/test.zip")      // 下载到�一个文件里
-            .setAppended()                       // 开�文件追加模�
-            .setOnSuccess((File file) -> {
-                if (end < totalSize) {           // 若未下载完,则继续下载下一�
-                    download(totalSize, index + 1); 
-                } else {
-                    System.out.println("下载完�");
-                }
-            })
-            .start();
-}
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 文件上传

一个简�文件上传的示例:

http.sync("/upload")
-        .addFileParam("test", "D:/download/test.zip")
-        .post();     // 上传�法一般使用 POST 或 PUT,看�务器支�
-
1
2
3

异步上传也是完全一样:

http.async("/upload")
-        .addFileParam("test", "D:/download/test.zip")
-        .post();
-
1
2
3

# 上传进度监�

OkHttps 的上传进度监�,监�的是所有请求报文体的��进度,示例代�:

http.sync("/upload")
-        .addBodyParam("name", "Jack")
-        .addBodyParam("age", 20)
-        .addFileParam("avatar", "D:/image/avatar.jpg")
-        .setStepBytes(1024)   // 设置��� 1024 个字节执行一次进度回调(�设置默认为 8192)  
- //     .setStepRate(0.01)    // 设置��� 1% 执行一次进度回调(�设置以 StepBytes 为准)  
-        .setOnProcess((Process process) -> {           // 上传进度回调
-            long doneBytes = process.getDoneBytes();   // 已��字节数
-            long totalBytes = process.getTotalBytes(); // 总共的字节数
-            double rate = process.getRate();           // 已��的比例
-            boolean isDone = process.isDone();         // 是���完�
-        })
-        .post();
-
1
2
3
4
5
6
7
8
9
10
11
12
13

咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在get/post方法之�使用这些API,下载是在getBody方法之�使用。很好�解:get/post之�是准备��请求时段,有上传的�义,而getBody之�,已是报文�应的时段,当然是下载。

# 上传过程控制

上传文件的过程控制就很简�,和常规请求一样,�有异步�起的上传�以�消:

HttpCall call = http.async("/upload")
-        .addFileParam("test", "D:/download/test.zip")
-        .setOnProcess((Process process) -> {
-            System.out.println(process.getRate());
-        })
-        .post();
-
-call.cancel();  // �消上传
-
1
2
3
4
5
6
7
8

上传就没有暂�和继续这个功能啦,应该没人有这个需求�?

- - - diff --git a/okhttps-doc/docs/.vuepress/dist/index.html b/okhttps-doc/docs/.vuepress/dist/index.html deleted file mode 100644 index 3d0605ad..00000000 --- a/okhttps-doc/docs/.vuepress/dist/index.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - OkHttps - - - - - - - - - - - - - - - - -
hero

- OkHttps -

- 基于 OkHttp 增强版 HTTP 客户端 -

- �速上手 → -

轻�纯粹优雅

OkHttps �常轻�,体积仅是 Retrofit 的一��到,并且��赖于特定平�,API 语义简�舒适。

开箱�用的功能

异步预处�器�回调执行器�全局监�器�回调阻断机制�文件上传下载�过程控制�进度监�。

更多实用特性

URL ��符�Lambda 回调�JSON自动�装解��OkHttp 的特性:拦截器�连接池�CookieJar 等。

// 构建 HTTP
-HTTP http = HTTP.builder()
-        .baseUrl("https://api.demo.com")
-        .build();
-
-// �步请求
-List<User> users = http.sync("/users")  // http://api.demo.com/users
-        .get()                          // GET请求
-        .getBody()                      // 获��应报文体
-        .toList(User.class);            // 得到目标数�
-
-// 异步请求
-http.async("/users/jack")               //  http://api.demo.com/users/jack
-        .setOnResponse((HttpResult result) -> {
-            // 得到目标数�
-            User jack = result.getBody().toBean(User.class);
-        })
-        .get();                         // GET请求
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

竟然�到 15 秒,你已学会 90% 的精髓�
了解更多

- - - diff --git a/okhttps-doc/docs/.vuepress/dist/logo.png b/okhttps-doc/docs/.vuepress/dist/logo.png deleted file mode 100644 index 3b3b2845420b470e4b091e3862ff98653c4b1cb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5800 zcmX9?c|2768$RclVT^4s*_RpXRMuoG%P?dtA*m#L(n8lZmMhEHm&71ZWGfe4Wi5Ng zo~ww;5;4j}cES*5ese#+KhEcUKi~Izp69He_j%rATWd2Oq!=R5sxYDrp^2IMU_Bh0y>E*~O>!|ph0Kd1zw>qt@EFdT#`V|KkDr5H~Vx$ zx)qN}Ap!Ni=LJ%~4KJ^GhuGQh?bUZ0gP6bYt%j3+HhGK!?l=fvsUG{UYoE##$O+3L zcXJaDBgO*^4X}+3<@1HV`X40nk{wF!_t4kKDi{!MFP%L1P(CCI|9baxI_?ea=Cg%nKp+fbIeFs4TS`T<+@j9@WN^=z+q2S+UuVX zJ08S5nc@z=+e|L71(Fns;bfH}MHahx5{!0&1nRSZk5wOCfttxuth$gLL|cTK2_TWX zJy=EO-aO=tH^Tv(ESk4IyZSS_H|=cFbqDUos}!-J$@LBeU)J`r0{1d~(0R95-6|8PJ$uBxn)R!h`R!oGVeOt8Zk_3mb8P&Qx~Rsl$qY?5ZAR znd`p}FIl_Y?L7>yjD{#egzxhQ3HK8`fNlA7fprdau?sC9x7N+c=0Kh5hbjX-cSBk5zHwMB>BZEb<@Y z#2oE^)g|o!thYh_Z;NtWb_uo_kjDYZHRbcd(KoHQObKGM#7!0I1t3$N^xf+9EksGM zz?0D8jd%BiBi@wHzh0B1_YHj>Y?_S8X^cUb zTq`U5d{K4O=DM?QvY|!LDG|$HEbx7t?<{v@;!>kx#Y(ZOkz;*$>fvdxVN|z5unN_^ z7MEEG1A3I{iHB8-FNL@29d9r3-{^=)az0HG`5CAjSoYZouLY5F>IW*@lf8N^Wi(RH z{B|h5FO9jW?j%szc+R+*C`>Ws1-!>?Aclo6flubmOR+fP_uX!ZROPR~3 z>&xdOdw%#Y&a|+q|54hu?xvMe08=F)FO{0>0~y8X^3X&JSpr7wv^LPdf?nq5FZhgS z1Q7X6G53V=AR@7pg4rFJP!LN*w>lgzL3pl00TWzm;*DIkDT(**ymB-uZ)}JZlrbfM zTG2t+NqtCn6`pieaHjVxF|K05tP@;AnNIgZuXCSTVIvKyUVtiYTlKhpnuhs>ESA`%fNPm-I6&ic%!=cur zrJu^WpyGwoakaA%#V_8iIN{gscF?P>Zrz=~S6x0o?5faZP378&T(l-2G^Tm>&jzwE za-bhZt7erF%l||?uO^@^2^t($@Vz$^*f zO!9d7+0I9N0Tuo6&uD!s==x;pjaeu~kj&nNHQMlW5Ql_x(H`;kMAYCpJ*JWqz6PTC z3`No@)D-046&)>w6zin}1SY({gvc>mi1Yomph7dPCZi7H%pSkLSr8~mfJW({t+$c|! zwfYLT1unZ0tEFO%{e;EICSCD-`_S54$mr^ioaZY6tsYi<7McJh%w@_`fy6ez4qs+iXK0=H;rm!}>Ft77(PG9d`cPmaL6)z%?%Es&N zYmVB55_lBv-*LGe@#bL>kV^F<7JW?)<@Q64VYvVJIh3dWcER)d*0?Qj&ZBWP_xG%v zol>$%*HYBj@kR`nEdX^`cgvZE>V;xbLu9=4tVWGN1mgQzo?d?3bBF+7MFc45A^_o0 z-<9U5=;6Va0K{PAs)J>00<~O67pAlR_z0SipC%<=!U6oVvvS>H+@MSh&slEHB+*3x z?MB2`;z8TE#4OZZ5eQd{7Kqbp3s!PTohEQ8W$Kaub~iYm8fV-1I?v8=nM4n-dPTlPzo<##cHv9x+IN=y@JUN$W1QHR!G781TfE+uY zA{NVv2m&O4MB+WD;AxKA_6dW_zHXB>aYcX#2ix2I8m%9`GC#Y_Em)Y`;|CVAw&yu( z_4DO~alkq1DD5A&of!ua0g(i#2$6Oy&z)AL_o<|i(xJ^Xz*yK=^j ze&#qwJMKeqX{7`@4*DqAO0hXr^{t`1B`fS7Yl5*FY!P%Z={-2JG3No|0LfXJHc01( zC1CL!I(r{zfhuJV5m>MYsHb-L@}}VNB9IUESw~dzmS>_@iSCMprw&U;QP~B=4;RW! zTB%#lmzyKgB=7ScanLuiEKFrh-Q>_@O{=Afs$%#o=bndotMZ?3|bMG$hPhg%6nwsV*iVcjh-QaCd;cW>uUxQTywg9 zpL?QlGH7#rCzLF0*%a5J_oUJg4UmNo-V@_zj%kTXUQP4md2^iBf8$Au5{vxhC;{n3D+ zf7IoLWm)&Viwje(tWuk)rlDPHJAwD-#aGZ0FWmt?*xSfPF@0;A z7Q-w^fCg`*KIL)xDlC*iV^0YHa*qsCL(O>^JUAWD;J)U=dB9^37C!r?dJg7cBwU@~ z0R!ryD%qveb@wKt5mOIHP0p1j6nTpPpvH>~r~ehgVZ5(4^6w&a8D|X03^K0VdSVpD zYAK23X%D?ZD&UTrjWH7V${(enem#CKh$q=dpyfjuKwW8{@Jf@9<4c%2`vNSjI@F01 zB6p{6+kKM1`DnA~55wMhtdtJY!VggQVwPyp5rY5zSrKVW@Kgq>!$$PigzFizc-#hl z@6_4FE4F$~XUQUbkL%1s(`4je_l1EgWPr#w*f(`YOe*f;NXuS|FpyIRP#KmX`!~MZ z@ZJ`-4Hu!E3IRso()ma5Vy>jF1`USK2;W%vGfw-qedmznw2|H90gWGj3!6FAW;ymM zzdfNgxk}9n``tvlANaO>UOPUL?#5m)JC?5->T`ixCV#|OIkNShotY8!{l&6DkaI|1N`ax|&rZ7l z?z&&4G?ri$mD#tosdTvUP}h)WiuU>bJ3$BElSJgJCR-JSCM0=|ps9Xvoopb`+AT?t z!Tc%R!roPI%To~u&COJ9|1uECzuvd#>t+m-i359@$r6&}xh}mimjknKsb3GDo<&LA zm5Xl}*8|{1(l6=^r_NW2?oZDAel)p1O?TPbj2g>2U_bMd7)kHh<#<?7jM!H4`$P+ zY#7^p;vDS@E$v6m2U%_UAE(dUFpKe)_+0OhbPL;r)OS(bI{=pp8nc`y< z9)=!JU3<7XJ}i%Y3vrEV8!#MOdoC+a6*KG3!aYZCBbQ3b-~VW6!1}Jx(Z( zK3@Be+DY);;lt_CXu1t^YiNigz?HF}-R^JL-WbZb$;I_A%x#!QPrit4F)i3Ee{_`^ z3A8giIEG$^UupH;n>b*OYi5*xldc}0e`+^}1MIHe`LZXdvHs&t)PgC^HENTK&KNTE zD-8erv-j#ZMc$+KO+!hq$ixZPYe2V&P9VK8L*iP@e%yo!jcySvw)PM9&5t*uKMo$Z z^>gmEK?8a5?DNR_yl5Q-uq*2s8){Oml`qE|?p>50I|KCdzV%8Q3`Vt@YPNG~tIZ$kt;NT+`hR=gEYMzO6ZD|2Hyu^ewRy6Dkv$++c^3 zFseFe(-b91|8kMr5^X(VT5SmM34NLBoGm*sw*)+QU5Q1X>Z^WpGufAxVQnJx?T+4n z1W;M&>2DVQIQgBd*dN)B&=lpD7p9-1<+?f_MclzZL#e~y_^-U9gnT&u>#n1t?9j2F z9~n{S zIU&?_t)>S{gj3M=QTl~!vkvwNF5sa-Z`iszA$nNCOegYCpxB+&KANFEKad-KPOYM> z4v}owcXM0D6an0Uo@Yh#76Vt{VKJ4=BScPf%4tzKg82f}{dIFkC3rT27vqz1qd%R; z_s`44A|N$#Uqpo(_)o0TWCzXg0gA5ex9eJ5pB3%V1Tc-qtdMU4B;5O}X4P{TE`Q;` zq!s87DyJ=Ml*P)pI+aFhI(gaWRati(c>NDrF`^QTWwJbxl=`l#jXy*_7M&YG!$Fof zZiZzqBk%YQi8ekND$b7!4x)0=o);9DN*xx6-ei729|wr+`bpsv=V0&iPolUGGq=0r zTw~(}ADqAVg3YfwzD6L1Co+h3+q}nkT(($!uWI~t#Z#rpm=Ji~=Ec&1gCkCkrmq+0 z^bTv6&ssG24ZSP=>#yUEz|@%PQpR`7FgX9aJAuf!9f!u^1+CT{Rh7?T#;+EjZTEzW zB#&$Mi4_jb?ym=N|tg2236iIFNRu<^P(9?`q#FJX_mht! z3WEcbZDH>_I;2rZJO>U^Xf)22=7_@QvMqv_IhITWy^eR48ekWJFme$6=$&$p#e#&X zfy5#75#;W6nDBe$`Awq(LX-L3WZ(1WaGJUi(h)3|)Y*#n3&&nG9gyZgvJ|huSS4z`Y`R zf2Y_2aYl(#k2@4(9Y3y#$3Q4fWXG>)!|TVZlyN}Daa+XT@EC<{27?CVt3CW~HGUa& zuvXhJ3py@SYYRLynrTCNP=0T@2ckos{>Cbn;z2doW!@9{K3ORuP9*|cxuQqgEN27v z_(+=jrY)qP^yrLW;73JP@8YLujJqy<6(7JlX*nmV(?mbrguyZH800-v++ST);? { + System.out.println("连接已打开:" + result); + webSocket.send("Hello"); + }) + .setOnMessage((WebSocket webSocket, Message message) -> { + System.out.println("接收到消�:" + message.toString()); + }) + .setOnException((WebSocket webSocket, Throwable throwable) -> { + System.out.println("连接异常:" + throwable); + }) + .setOnClosing((WebSocket webSocket, WebSocket.Close close) -> { + System.out.println("正在关闭:" + close); + }) + .setOnClosed((WebSocket webSocket, WebSocket.Close close) -> { + System.out.println("已关闭:" + close); + }) + .listen(); + + Thread.sleep(2000); + + socket.send("你好呀"); + + Thread.sleep(5000); + + socket.close(1000, "close"); + + Thread.sleep(3000); + System.out.println("。。。"); + } + + +} From 26606094c60a0f3da14416f378b4f9252c0afc7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 15:37:52 +0800 Subject: [PATCH 239/924] =?UTF-8?q?=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ejlchina/okhttps/HTTP.java | 287 +++++++++++++++++- .../ejlchina/okhttps/internal/HttpClient.java | 275 +++-------------- .../okhttps/internal/TaskExecutor.java | 28 ++ 3 files changed, 344 insertions(+), 246 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index 93aec89c..577f90b4 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -1,15 +1,13 @@ package com.ejlchina.okhttps; -import com.ejlchina.okhttps.internal.AsyncHttpTask; -import com.ejlchina.okhttps.internal.SyncHttpTask; -import com.ejlchina.okhttps.internal.TaskExecutor; -import com.ejlchina.okhttps.internal.WebSocketTask; -import com.ejlchina.okhttps.internal.HttpClient.Builder; - -import okhttp3.Call; -import okhttp3.Request; +import com.ejlchina.okhttps.internal.*; + +import okhttp3.*; import okhttp3.WebSocket; -import okhttp3.WebSocketListener; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.Executor; /** * HTTP 客户端接� @@ -89,4 +87,275 @@ static Builder builder() { return new Builder(); } + + class Builder { + + private OkHttpClient okClient; + + private String baseUrl; + + private Map mediaTypes; + + private Configurator configurator; + + private Executor mainExecutor; + + private List preprocessors; + + private DownListener downloadListener; + + private TaskListener responseListener; + + private TaskListener exceptionListener; + + private TaskListener completeListener; + + private JsonService jsonService; + + private int preprocTimeoutTimes = 10; + + public Builder() { + mediaTypes = new HashMap<>(); + mediaTypes.put("*", "application/octet-stream"); + mediaTypes.put("png", "image/png"); + mediaTypes.put("jpg", "image/jpeg"); + mediaTypes.put("jpeg", "image/jpeg"); + mediaTypes.put("wav", "audio/wav"); + mediaTypes.put("mp3", "audio/mp3"); + mediaTypes.put("mp4", "video/mpeg4"); + mediaTypes.put("txt", "text/plain"); + mediaTypes.put("xls", "application/x-xls"); + mediaTypes.put("xml", "text/xml"); + mediaTypes.put("apk", "application/vnd.android.package-archive"); + mediaTypes.put("doc", "application/msword"); + mediaTypes.put("pdf", "application/pdf"); + mediaTypes.put("html", "text/html"); + preprocessors = new ArrayList<>(); + } + + public Builder(HttpClient hc) { + this.okClient = hc.getOkClient(); + this.baseUrl = hc.getBaseUrl(); + this.mediaTypes = hc.getMediaTypes(); + this.preprocessors = new ArrayList<>(); + Collections.addAll(this.preprocessors, hc.getPreprocessors()); + TaskExecutor executor = hc.getExecutor(); + this.downloadListener = executor.getDownloadListener(); + this.responseListener = executor.getResponseListener(); + this.exceptionListener = executor.getExceptionListener(); + this.completeListener = executor.getCompleteListener(); + this.jsonService = executor.getJsonService(); + this.preprocTimeoutTimes = hc.getPreprocTimeoutTimes(); + } + + /** + * �置 OkHttpClient + * + * @param configurator �置器 + * @return Builder + */ + public Builder config(Configurator configurator) { + this.configurator = configurator; + return this; + } + + /** + * 设置 baseUrl + * + * @param baseUrl 全局URL�缀 + * @return Builder + */ + public Builder baseUrl(String baseUrl) { + this.baseUrl = baseUrl; + return this; + } + + /** + * �置媒体类型 + * + * @param mediaTypes 媒体类型 + * @return Builder + */ + public Builder mediaTypes(Map mediaTypes) { + this.mediaTypes.putAll(mediaTypes); + return this; + } + + /** + * �置媒体类型 + * + * @param key 媒体类型KEY + * @param value 媒体类型VALUE + * @return Builder + */ + public Builder mediaTypes(String key, String value) { + this.mediaTypes.put(key, value); + return this; + } + + /** + * 设置回调执行器,例如实现切�线程功能,�对异步请求有效 + * + * @param executor 回调执行器 + * @return Builder + */ + public Builder callbackExecutor(Executor executor) { + this.mainExecutor = executor; + return this; + } + + /** + * 添加�并行处�请求任务的预处�器 + * + * @param preprocessor 预处�器 + * @return Builder + */ + public Builder addPreprocessor(Preprocessor preprocessor) { + preprocessors.add(preprocessor); + return this; + } + + /** + * 添加预处�器 + * + * @param preprocessor 预处�器 + * @return Builder + */ + public Builder addSerialPreprocessor(Preprocessor preprocessor) { + preprocessors.add(new HttpClient.SerialPreprocessor(preprocessor)); + return this; + } + + /** + * 最大预处�时间(�数,相当普通请求的超时时间) + * + * @param times 普通超时时间的�数,默认为 10 + * @return Builder + */ + public Builder preprocTimeoutTimes(int times) { + if (times > 0) { + this.preprocTimeoutTimes = times; + } + return this; + } + + /** + * 设置全局�应监� + * + * @param listener 监�器 + * @return Builder + */ + public Builder responseListener(TaskListener listener) { + this.responseListener = listener; + return this; + } + + /** + * 设置全局异常监� + * + * @param listener 监�器 + * @return Builder + */ + public Builder exceptionListener(TaskListener listener) { + this.exceptionListener = listener; + return this; + } + + /** + * 设置全局完�监� + * + * @param listener 监�器 + * @return Builder + */ + public Builder completeListener(TaskListener listener) { + this.completeListener = listener; + return this; + } + + /** + * 设置下载监�器 + * + * @param listener 监�器 + * @return Builder + */ + public Builder downloadListener(DownListener listener) { + this.downloadListener = listener; + return this; + } + + /** + * 设置 JSON �务 + * @param jsonService JSON �务 + * @return Builder + */ + public Builder jsonService(JsonService jsonService) { + this.jsonService = jsonService; + return this; + } + + /** + * 构建 HTTP 实例 + * @return HTTP + */ + public HTTP build() { + if (configurator != null || okClient == null) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + if (configurator != null) { + configurator.config(builder); + } + okClient = builder.build(); + } + return new HttpClient(this); + } + + public OkHttpClient getOkClient() { + return okClient; + } + + public String getBaseUrl() { + return baseUrl; + } + + public Map getMediaTypes() { + return mediaTypes; + } + + public Configurator getConfigurator() { + return configurator; + } + + public Executor getMainExecutor() { + return mainExecutor; + } + + public List getPreprocessors() { + return preprocessors; + } + + public DownListener getDownloadListener() { + return downloadListener; + } + + public TaskListener getResponseListener() { + return responseListener; + } + + public TaskListener getExceptionListener() { + return exceptionListener; + } + + public TaskListener getCompleteListener() { + return completeListener; + } + + public JsonService getJsonService() { + return jsonService; + } + + public int getPreprocTimeoutTimes() { + return preprocTimeoutTimes; + } + + } + } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 75e9de3d..f27c1812 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -1,19 +1,18 @@ package com.ejlchina.okhttps.internal; -import com.ejlchina.okhttps.*; -import com.ejlchina.okhttps.HttpResult.State; +import com.ejlchina.okhttps.Cancelable; +import com.ejlchina.okhttps.HTTP; +import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.Preprocessor; import okhttp3.*; -import okhttp3.WebSocket; -import java.io.IOException; import java.util.*; -import java.util.concurrent.Executor; public class HttpClient implements HTTP { // OkHttpClient - final OkHttpClient client; + final OkHttpClient okClient; // 根URL final String baseUrl; // 媒体类型 @@ -27,16 +26,16 @@ public class HttpClient implements HTTP { // 最大预处�时间�数(相对于普通请求的超时时间) final int preprocTimeoutTimes; - private HttpClient(Builder builder) { - this.client = builder.client; - this.baseUrl = builder.baseUrl; - this.mediaTypes = builder.mediaTypes; - this.executor = new TaskExecutor(client.dispatcher().executorService(), - builder.mainExecutor, builder.downloadListener, - builder.responseListener, builder.exceptionListener, - builder.completeListener, builder.jsonService); - this.preprocessors = builder.preprocessors.toArray(new Preprocessor[0]); - this.preprocTimeoutTimes = builder.preprocTimeoutTimes; + public HttpClient(Builder builder) { + this.okClient = builder.getOkClient(); + this.baseUrl = builder.getBaseUrl(); + this.mediaTypes = builder.getMediaTypes(); + this.executor = new TaskExecutor(okClient.dispatcher().executorService(), + builder.getMainExecutor(), builder.getDownloadListener(), + builder.getResponseListener(), builder.getExceptionListener(), + builder.getCompleteListener(), builder.getJsonService()); + this.preprocessors = builder.getPreprocessors().toArray(new Preprocessor[0]); + this.preprocTimeoutTimes = builder.getPreprocTimeoutTimes(); this.tagTasks = new LinkedList<>(); } @@ -81,7 +80,7 @@ public int cancel(String tag) { @Override public void cancelAll() { - client.dispatcher().cancelAll(); + okClient.dispatcher().cancelAll(); synchronized (tagTasks) { tagTasks.clear(); } @@ -89,22 +88,22 @@ public void cancelAll() { @Override public Call request(Request request) { - return client.newCall(request); + return okClient.newCall(request); } @Override public WebSocket webSocket(Request request, WebSocketListener listener) { - return client.newWebSocket(request, listener); + return okClient.newWebSocket(request, listener); } public OkHttpClient getOkClient() { - return client; + return okClient; } public int preprocTimeoutMillis() { - return preprocTimeoutTimes * (client.connectTimeoutMillis() - + client.writeTimeoutMillis() - + client.readTimeoutMillis()); + return preprocTimeoutTimes * (okClient.connectTimeoutMillis() + + okClient.writeTimeoutMillis() + + okClient.readTimeoutMillis()); } public int getTagTaskCount() { @@ -200,7 +199,7 @@ public void preprocess(HttpTask> httpTask, Runnable reques * 串行预处�器 * @author Troy.Zhou */ - static class SerialPreprocessor implements Preprocessor { + public static class SerialPreprocessor implements Preprocessor { // 预处�器 private Preprocessor preprocessor; @@ -209,7 +208,7 @@ static class SerialPreprocessor implements Preprocessor { // 是�有任务正在执行 private boolean running = false; - SerialPreprocessor(Preprocessor preprocessor) { + public SerialPreprocessor(Preprocessor preprocessor) { this.preprocessor = preprocessor; this.pendings = new LinkedList<>(); } @@ -335,222 +334,24 @@ private String urlPath(String urlPath, boolean websocket) { return fullUrl; } - public static class Builder { - - private OkHttpClient client; - - private String baseUrl; - - private Map mediaTypes; - - private Configurator configurator; - - private Executor mainExecutor; - - private List preprocessors; - - private DownListener downloadListener; - - private TaskListener responseListener; - - private TaskListener exceptionListener; - - private TaskListener completeListener; - - private JsonService jsonService; - - private int preprocTimeoutTimes = 10; - - public Builder() { - mediaTypes = new HashMap<>(); - mediaTypes.put("*", "application/octet-stream"); - mediaTypes.put("png", "image/png"); - mediaTypes.put("jpg", "image/jpeg"); - mediaTypes.put("jpeg", "image/jpeg"); - mediaTypes.put("wav", "audio/wav"); - mediaTypes.put("mp3", "audio/mp3"); - mediaTypes.put("mp4", "video/mpeg4"); - mediaTypes.put("txt", "text/plain"); - mediaTypes.put("xls", "application/x-xls"); - mediaTypes.put("xml", "text/xml"); - mediaTypes.put("apk", "application/vnd.android.package-archive"); - mediaTypes.put("doc", "application/msword"); - mediaTypes.put("pdf", "application/pdf"); - mediaTypes.put("html", "text/html"); - preprocessors = new ArrayList<>(); - } - - private Builder(HttpClient hc) { - this.client = hc.client; - this.baseUrl = hc.baseUrl; - this.mediaTypes = hc.mediaTypes; - this.preprocessors = new ArrayList<>(); - Collections.addAll(this.preprocessors, hc.preprocessors); - this.downloadListener = hc.executor.downloadListener; - this.responseListener = hc.executor.responseListener; - this.exceptionListener = hc.executor.exceptionListener; - this.completeListener = hc.executor.completeListener; - this.jsonService = hc.executor.jsonService; - this.preprocTimeoutTimes = hc.preprocTimeoutTimes; - } - - /** - * �置 OkHttpClient - * - * @param configurator �置器 - * @return Builder - */ - public Builder config(Configurator configurator) { - this.configurator = configurator; - return this; - } - - /** - * 设置 baseUrl - * - * @param baseUrl 全局URL�缀 - * @return Builder - */ - public Builder baseUrl(String baseUrl) { - this.baseUrl = baseUrl; - return this; - } - - /** - * �置媒体类型 - * - * @param mediaTypes 媒体类型 - * @return Builder - */ - public Builder mediaTypes(Map mediaTypes) { - this.mediaTypes.putAll(mediaTypes); - return this; - } - - /** - * �置媒体类型 - * - * @param key 媒体类型KEY - * @param value 媒体类型VALUE - * @return Builder - */ - public Builder mediaTypes(String key, String value) { - this.mediaTypes.put(key, value); - return this; - } - - /** - * 设置回调执行器,例如实现切�线程功能,�对异步请求有效 - * - * @param executor 回调执行器 - * @return Builder - */ - public Builder callbackExecutor(Executor executor) { - this.mainExecutor = executor; - return this; - } - - /** - * 添加�并行处�请求任务的预处�器 - * - * @param preprocessor 预处�器 - * @return Builder - */ - public Builder addPreprocessor(Preprocessor preprocessor) { - preprocessors.add(preprocessor); - return this; - } - - /** - * 添加预处�器 - * - * @param preprocessor 预处�器 - * @return Builder - */ - public Builder addSerialPreprocessor(Preprocessor preprocessor) { - preprocessors.add(new SerialPreprocessor(preprocessor)); - return this; - } - - /** - * 最大预处�时间(�数,相当普通请求的超时时间) - * - * @param times 普通超时时间的�数,默认为 10 - * @return Builder - */ - public Builder preprocTimeoutTimes(int times) { - if (times > 0) { - this.preprocTimeoutTimes = times; - } - return this; - } - - /** - * 设置全局�应监� - * - * @param listener 监�器 - * @return Builder - */ - public Builder responseListener(TaskListener listener) { - this.responseListener = listener; - return this; - } - - /** - * 设置全局异常监� - * - * @param listener 监�器 - * @return Builder - */ - public Builder exceptionListener(TaskListener listener) { - this.exceptionListener = listener; - return this; - } + public String getBaseUrl() { + return baseUrl; + } - /** - * 设置全局完�监� - * - * @param listener 监�器 - * @return Builder - */ - public Builder completeListener(TaskListener listener) { - this.completeListener = listener; - return this; - } + public Map getMediaTypes() { + return mediaTypes; + } - /** - * 设置下载监�器 - * - * @param listener 监�器 - * @return Builder - */ - public Builder downloadListener(DownListener listener) { - this.downloadListener = listener; - return this; - } + public Preprocessor[] getPreprocessors() { + return preprocessors; + } - /** - * 设置 JSON �务 - * @param jsonService JSON �务 - * @return Builder - */ - public Builder jsonService(JsonService jsonService) { - this.jsonService = jsonService; - return this; - } - - - public HTTP build() { - if (configurator != null || client == null) { - OkHttpClient.Builder builder = new OkHttpClient.Builder(); - if (configurator != null) { - configurator.config(builder); - } - client = builder.build(); - } - return new HttpClient(this); - } + public List getTagTasks() { + return tagTasks; + } + public int getPreprocTimeoutTimes() { + return preprocTimeoutTimes; } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 1381006d..036da400 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -119,4 +119,32 @@ public void shutdown() { } } + public Executor getIoExecutor() { + return ioExecutor; + } + + public Executor getMainExecutor() { + return mainExecutor; + } + + public DownListener getDownloadListener() { + return downloadListener; + } + + public TaskListener getResponseListener() { + return responseListener; + } + + public TaskListener getExceptionListener() { + return exceptionListener; + } + + public TaskListener getCompleteListener() { + return completeListener; + } + + public JsonService getJsonService() { + return jsonService; + } + } From 31e38ee99c7953023dee30a860b32e2b0f5c031a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 15:38:39 +0800 Subject: [PATCH 240/924] Deprecated HttpUtils#of(HTTP http) --- okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java index 9aac93b5..a446bebd 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -33,6 +33,7 @@ public class HttpUtils { * �置HttpUtils�有的HTTP实例(�调用此方法�默认使用一个没有没有�过任何�置的HTTP懒实例) * @param http HTTP实例 */ + @Deprecated public static void of(HTTP http) { if (http != null) { HttpUtils.http = http; From f073b34053d78fb4ce6d27482ad477517354c89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 15:46:33 +0800 Subject: [PATCH 241/924] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20HttpUtils#webSocke?= =?UTF-8?q?t(String=20url)=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ejlchina/okhttps/HttpUtils.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java index a446bebd..c71902db 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -4,6 +4,7 @@ import com.ejlchina.okhttps.internal.SyncHttpTask; import com.ejlchina.okhttps.internal.TaskExecutor; +import com.ejlchina.okhttps.internal.WebSocketTask; import okhttp3.Call; import okhttp3.Request; import okhttp3.WebSocket; @@ -55,7 +56,7 @@ static synchronized HTTP getHttp() { return http; } - static JsonService findJsonService(String[] classes, int index) { + static private JsonService findJsonService(String[] classes, int index) { if (index >= classes.length) { return null; } @@ -91,6 +92,15 @@ public static SyncHttpTask sync(String url) { return getHttp().sync(url); } + /** + * Websocket 连接 + * @param url 连接地� + * @return WebSocket 任务 + */ + public static WebSocketTask webSocket(String url) { + return getHttp().webSocket(url); + } + /** * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 * @param tag 标签 @@ -116,7 +126,7 @@ public void cancelAll() { public static Call request(Request request) { return getHttp().request(request); } - + /** * Websocket(该请求��过 预处�器) * @param request 请求 From 3948d0d2f568584dd357dde4a8ab300a4ba85f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 15:52:25 +0800 Subject: [PATCH 242/924] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20OkHttps=20?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpUtils.java | 14 +-- .../java/com/ejlchina/okhttps/OkHttps.java | 109 ++++++++++++++++++ 2 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java index c71902db..1cd1bbe9 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -11,17 +11,9 @@ import okhttp3.WebSocketListener; /** - * Http 工具类,�装 OkHttp - - * 特性: - * �步请求 - * 异步请求 - * Restfull路径 - * 文件上传 - * JSON自动解� - * TCP连接池 - * Http2 - * + * Http 工具类(�供第三方库,�主应用使用) + * 若需��置,请使用 {@link OkHttps } 类 + * * @author Troy.Zhou */ public class HttpUtils { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java new file mode 100644 index 00000000..6a4daa40 --- /dev/null +++ b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java @@ -0,0 +1,109 @@ +package com.ejlchina.okhttps; + +import com.ejlchina.okhttps.internal.*; +import okhttp3.Call; +import okhttp3.Request; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; + +import java.util.ServiceLoader; + +/** + * OkHttps 工具类 + * 支� SPI 方��置 + */ +public class OkHttps { + + public interface Config { + + void withConfig(HTTP.Builder builder); + + } + + private static HTTP http; + + static synchronized HTTP getHttp() { + if (http != null) { + return http; + } + HTTP.Builder builder = HTTP.builder(); + for (Config config : ServiceLoader.load(Config.class)) { + config.withConfig(builder); + } + http = builder.build(); + return http; + } + + + /** + * 异步请求 + * @param url 请求地� + * @return 异步 HttpTask + */ + public static AsyncHttpTask async(String url) { + return getHttp().async(url); + } + + /** + * �步请求 + * @param url 请求地� + * @return �步 HttpTask + */ + public static SyncHttpTask sync(String url) { + return getHttp().sync(url); + } + + /** + * Websocket 连接 + * @param url 连接地� + * @return WebSocket 任务 + */ + public static WebSocketTask webSocket(String url) { + return getHttp().webSocket(url); + } + + /** + * 根�标签�消HTTP任务,��任务的标签包�指定的Tag就会被�消 + * @param tag 标签 + * @return 被�消的任务数� + */ + public static int cancel(String tag) { + return getHttp().cancel(tag); + } + + /** + * @since 1.0.3 + * �消所有HTTP任务,包括�步和异步 + */ + public void cancelAll() { + getHttp().cancelAll(); + } + + /** + * OkHttp 原生请求 (该请求��过 预处�器) + * @param request 请求 + * @return Call + */ + public static Call request(Request request) { + return getHttp().request(request); + } + + /** + * Websocket(该请求��过 预处�器) + * @param request 请求 + * @param listener 监�器 + * @return WebSocket + */ + public static WebSocket webSocket(Request request, WebSocketListener listener) { + return getHttp().webSocket(request, listener); + } + + /** + * 获�任务执行器 + * @return TaskExecutor + */ + public static TaskExecutor getExecutor() { + return getHttp().getExecutor(); + } + +} From 1cb63c36696e370e323f00886cbfeed93c7cb159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 15:54:11 +0800 Subject: [PATCH 243/924] .. --- okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java index 6a4daa40..b581bb21 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java @@ -12,7 +12,9 @@ * OkHttps 工具类 * 支� SPI 方��置 */ -public class OkHttps { +public final class OkHttps { + + private OkHttps() {} public interface Config { From c8cf532a66599d92312a5b381e00d0a0987708cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 16:03:24 +0800 Subject: [PATCH 244/924] =?UTF-8?q?OkHttps=20JSON=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/FastJsonConfig.java | 12 ++++++++++++ .../services/com.ejlchina.okhttps.OkHttps.Config | 1 + .../main/java/com/ejlchina/okhttps/GsonConfig.java | 12 ++++++++++++ .../services/com.ejlchina.okhttps.OkHttps.Config | 1 + .../java/com/ejlchina/okhttps/JacksonConfig.java | 12 ++++++++++++ .../services/com.ejlchina.okhttps.OkHttps.Config | 1 + 6 files changed, 39 insertions(+) create mode 100644 okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonConfig.java create mode 100644 okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config create mode 100644 okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonConfig.java create mode 100644 okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config create mode 100644 okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonConfig.java create mode 100644 okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonConfig.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonConfig.java new file mode 100644 index 00000000..68062977 --- /dev/null +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonConfig.java @@ -0,0 +1,12 @@ +package com.ejlchina.okhttps; + +public class FastJsonConfig implements OkHttps.Config { + + @Override + public void withConfig(HTTP.Builder builder) { + if (builder.getJsonService() == null) { + builder.jsonService(new FastJsonService()); + } + } + +} diff --git a/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config new file mode 100644 index 00000000..365b9421 --- /dev/null +++ b/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config @@ -0,0 +1 @@ +com.ejlchina.okhttps.GsonConfig \ No newline at end of file diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonConfig.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonConfig.java new file mode 100644 index 00000000..c2190221 --- /dev/null +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonConfig.java @@ -0,0 +1,12 @@ +package com.ejlchina.okhttps; + +public class GsonConfig implements OkHttps.Config { + + @Override + public void withConfig(HTTP.Builder builder) { + if (builder.getJsonService() == null) { + builder.jsonService(new GsonService()); + } + } + +} diff --git a/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config new file mode 100644 index 00000000..365b9421 --- /dev/null +++ b/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config @@ -0,0 +1 @@ +com.ejlchina.okhttps.GsonConfig \ No newline at end of file diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonConfig.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonConfig.java new file mode 100644 index 00000000..70946da7 --- /dev/null +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonConfig.java @@ -0,0 +1,12 @@ +package com.ejlchina.okhttps; + +public class JacksonConfig implements OkHttps.Config { + + @Override + public void withConfig(HTTP.Builder builder) { + if (builder.getJsonService() == null) { + builder.jsonService(new JacksonService()); + } + } + +} diff --git a/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config new file mode 100644 index 00000000..f00ef42b --- /dev/null +++ b/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config @@ -0,0 +1 @@ +com.ejlchina.okhttps.JacksonConfig \ No newline at end of file From 104ee49025902162ca53a08195dc6421976cba43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 16:04:28 +0800 Subject: [PATCH 245/924] =?UTF-8?q?OkHttps=20JSON=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../META-INF/services/com.ejlchina.okhttps.OkHttps.Config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config index 365b9421..98b6b6e7 100644 --- a/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config +++ b/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config @@ -1 +1 @@ -com.ejlchina.okhttps.GsonConfig \ No newline at end of file +com.ejlchina.okhttps.FastJsonConfig \ No newline at end of file From ce2adf2953457ebbee566002f3079a5ccbae18b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Sun, 10 May 2020 16:16:32 +0800 Subject: [PATCH 246/924] JsonService AutoConfig --- .../okhttps/{FastJsonConfig.java => FastJsonAutoConfig.java} | 2 +- .../META-INF/services/com.ejlchina.okhttps.OkHttps.Config | 2 +- .../ejlchina/okhttps/{GsonConfig.java => GsonAutoConfig.java} | 2 +- .../META-INF/services/com.ejlchina.okhttps.OkHttps.Config | 2 +- .../okhttps/{JacksonConfig.java => JacksonAutoConfig.java} | 2 +- .../META-INF/services/com.ejlchina.okhttps.OkHttps.Config | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename okhttps-fastjson/src/main/java/com/ejlchina/okhttps/{FastJsonConfig.java => FastJsonAutoConfig.java} (78%) rename okhttps-gson/src/main/java/com/ejlchina/okhttps/{GsonConfig.java => GsonAutoConfig.java} (79%) rename okhttps-jackson/src/main/java/com/ejlchina/okhttps/{JacksonConfig.java => JacksonAutoConfig.java} (78%) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonConfig.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java similarity index 78% rename from okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonConfig.java rename to okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java index 68062977..52ab16fa 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonConfig.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java @@ -1,6 +1,6 @@ package com.ejlchina.okhttps; -public class FastJsonConfig implements OkHttps.Config { +public class FastJsonAutoConfig implements OkHttps.Config { @Override public void withConfig(HTTP.Builder builder) { diff --git a/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config index 98b6b6e7..a590a34f 100644 --- a/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config +++ b/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config @@ -1 +1 @@ -com.ejlchina.okhttps.FastJsonConfig \ No newline at end of file +com.ejlchina.okhttps.FastJsonAutoConfig \ No newline at end of file diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonConfig.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java similarity index 79% rename from okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonConfig.java rename to okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java index c2190221..1695741b 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonConfig.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java @@ -1,6 +1,6 @@ package com.ejlchina.okhttps; -public class GsonConfig implements OkHttps.Config { +public class GsonAutoConfig implements OkHttps.Config { @Override public void withConfig(HTTP.Builder builder) { diff --git a/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config index 365b9421..637f6eb7 100644 --- a/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config +++ b/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config @@ -1 +1 @@ -com.ejlchina.okhttps.GsonConfig \ No newline at end of file +com.ejlchina.okhttps.GsonAutoConfig \ No newline at end of file diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonConfig.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java similarity index 78% rename from okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonConfig.java rename to okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java index 70946da7..7e7a3a0c 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonConfig.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java @@ -1,6 +1,6 @@ package com.ejlchina.okhttps; -public class JacksonConfig implements OkHttps.Config { +public class JacksonAutoConfig implements OkHttps.Config { @Override public void withConfig(HTTP.Builder builder) { diff --git a/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config index f00ef42b..1aca027c 100644 --- a/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config +++ b/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config @@ -1 +1 @@ -com.ejlchina.okhttps.JacksonConfig \ No newline at end of file +com.ejlchina.okhttps.JacksonAutoConfig \ No newline at end of file From bee4ba93c11e811ca29d203d1f9111599bb2e5b2 Mon Sep 17 00:00:00 2001 From: ejlchina Date: Mon, 11 May 2020 09:14:16 +0800 Subject: [PATCH 247/924] update README.md. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ed3a8f1c..aea850a2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- logo + logo

@@ -1072,7 +1072,7 @@ HTTP http = HTTP.builder() ## è�”系方å¼� -* 微信: +* 微信: * 邮箱:zhou.xu@ejlchina.com ## å�‚与贡献 From 3537513446fe1a8db69ddc115ead6663d91ca83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 09:38:05 +0800 Subject: [PATCH 248/924] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ejlchina/okhttps/FastJsonService.java | 16 +++++----- .../{FastJsonArr.java => FastjsonArray.java} | 12 ++++---- .../{FastJsonObj.java => FastjsonMapper.java} | 12 ++++---- .../java/com/ejlchina/okhttps/TestCases.java | 30 +++++++++---------- .../java/com/ejlchina/okhttps/GsonArr.java | 6 ++-- .../java/com/ejlchina/okhttps/GsonObj.java | 6 ++-- .../com/ejlchina/okhttps/GsonService.java | 12 ++++---- .../java/com/ejlchina/okhttps/TestCases.java | 30 +++++++++---------- .../java/com/ejlchina/okhttps/JacksonArr.java | 6 ++-- .../java/com/ejlchina/okhttps/JacksonObj.java | 6 ++-- .../com/ejlchina/okhttps/JacksonService.java | 12 ++++---- .../java/com/ejlchina/okhttps/TestCases.java | 30 +++++++++---------- .../okhttps/{JsonArr.java => Array.java} | 6 ++-- .../java/com/ejlchina/okhttps/HttpResult.java | 4 +-- .../java/com/ejlchina/okhttps/HttpTask.java | 6 ++-- .../com/ejlchina/okhttps/JsonService.java | 24 +++++++-------- .../okhttps/{JsonObj.java => Mapper.java} | 10 +++---- .../java/com/ejlchina/okhttps/WebSocket.java | 4 +-- .../okhttps/internal/AbstractBody.java | 16 +++++----- .../okhttps/internal/WebSocketTask.java | 6 ++-- .../java/com/ejlchina/test/SimpleTests.java | 3 -- 21 files changed, 127 insertions(+), 130 deletions(-) rename okhttps-fastjson/src/main/java/com/ejlchina/okhttps/{FastJsonArr.java => FastjsonArray.java} (85%) rename okhttps-fastjson/src/main/java/com/ejlchina/okhttps/{FastJsonObj.java => FastjsonMapper.java} (86%) rename okhttps/src/main/java/com/ejlchina/okhttps/{JsonArr.java => Array.java} (92%) rename okhttps/src/main/java/com/ejlchina/okhttps/{JsonObj.java => Mapper.java} (89%) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java index 8f0c57fe..4093be9d 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java @@ -24,32 +24,32 @@ public FastJsonService(Charset charset) { } @Override - public JsonObj toJsonObj(InputStream in) { - return new FastJsonObj(JSON.parseObject(toString(in))); + public Mapper toMapper(InputStream in) { + return new FastjsonMapper(JSON.parseObject(toString(in))); } @Override - public JsonArr toJsonArr(InputStream in) { - return new FastJsonArr(JSON.parseArray(toString(in))); + public Array toArray(InputStream in) { + return new FastjsonArray(JSON.parseArray(toString(in))); } @Override - public String toJsonStr(Object bean) { + public String serialize(Object bean) { return JSON.toJSONString(bean); } @Override - public String toJsonStr(Object bean, String dateFormat) { + public String serialize(Object bean, String dateFormat) { return JSON.toJSONStringWithDateFormat(bean, dateFormat); } @Override - public T jsonToBean(Class type, InputStream in) { + public T toBean(Class type, InputStream in) { return JSON.parseObject(toString(in), type); } @Override - public List jsonToList(Class type, InputStream in) { + public List toList(Class type, InputStream in) { return JSON.parseArray(toString(in), type); } diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonArray.java similarity index 85% rename from okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java rename to okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonArray.java index 829fcb50..3bcdff89 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonArr.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonArray.java @@ -6,11 +6,11 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -public class FastJsonArr implements JsonArr { +public class FastjsonArray implements Array { private JSONArray json; - public FastJsonArr(JSONArray json) { + public FastjsonArray(JSONArray json) { this.json = json; } @@ -25,19 +25,19 @@ public boolean isEmpty() { } @Override - public JsonObj getJsonOjb(int index) { + public Mapper getMapper(int index) { JSONObject subJson = json.getJSONObject(index); if (subJson != null) { - return new FastJsonObj(subJson); + return new FastjsonMapper(subJson); } return null; } @Override - public JsonArr getJsonArr(int index) { + public Array getArray(int index) { JSONArray subJson = json.getJSONArray(index); if (subJson != null) { - return new FastJsonArr(subJson); + return new FastjsonArray(subJson); } return null; } diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMapper.java similarity index 86% rename from okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java rename to okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMapper.java index dfddd9c6..c7c16ee6 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonObj.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMapper.java @@ -7,11 +7,11 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -public class FastJsonObj implements JsonObj { +public class FastjsonMapper implements Mapper { private JSONObject json; - public FastJsonObj(JSONObject json) { + public FastjsonMapper(JSONObject json) { this.json = json; } @@ -26,19 +26,19 @@ public boolean isEmpty() { } @Override - public JsonObj getJsonOjb(String key) { + public Mapper getMapper(String key) { JSONObject subJson = json.getJSONObject(key); if (subJson != null) { - return new FastJsonObj(subJson); + return new FastjsonMapper(subJson); } return null; } @Override - public JsonArr getJsonArr(String key) { + public Array getArray(String key) { JSONArray subJson = json.getJSONArray(key); if (subJson != null) { - return new FastJsonArr(subJson); + return new FastjsonArray(subJson); } return null; } diff --git a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java index c5657995..1acb99a8 100644 --- a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java +++ b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java @@ -19,28 +19,28 @@ public class TestCases { public void testToJsonObj() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - JsonObj jsonObj = jsonService.toJsonObj(in); - Set keys = jsonObj.keySet(); + Mapper mapper = jsonService.toMapper(in); + Set keys = mapper.keySet(); Assert.assertTrue(keys.size() == 2); Assert.assertTrue(keys.contains("id")); Assert.assertTrue(keys.contains("name")); - Assert.assertTrue(!jsonObj.isEmpty()); - Assert.assertTrue(2 == jsonObj.size()); - Assert.assertTrue(1 == jsonObj.getInt("id")); - Assert.assertTrue(!jsonObj.has("age")); - Assert.assertTrue(0 == jsonObj.getInt("age")); - Assert.assertEquals("Jack", jsonObj.getString("name")); + Assert.assertTrue(!mapper.isEmpty()); + Assert.assertTrue(2 == mapper.size()); + Assert.assertTrue(1 == mapper.getInt("id")); + Assert.assertTrue(!mapper.has("age")); + Assert.assertTrue(0 == mapper.getInt("age")); + Assert.assertEquals("Jack", mapper.getString("name")); } @Test public void testToJsonArr() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - JsonArr jsonObj = jsonService.toJsonArr(in); + Array jsonObj = jsonService.toArray(in); Assert.assertTrue(!jsonObj.isEmpty()); Assert.assertTrue(jsonObj.size() == 2); - JsonObj json1 = jsonObj.getJsonOjb(0); - JsonObj json2 = jsonObj.getJsonOjb(1); + Mapper json1 = jsonObj.getMapper(0); + Mapper json2 = jsonObj.getMapper(1); Assert.assertEquals(1, json1.getInt("id")); Assert.assertEquals("Jack", json1.getString("name")); Assert.assertEquals(2, json2.getInt("id")); @@ -49,7 +49,7 @@ public void testToJsonArr() { @Test public void testToJsonStr() { - String json = jsonService.toJsonStr(new User(1, "Jack")); + String json = jsonService.serialize(new User(1, "Jack")); Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); } @@ -58,7 +58,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { String dataFormat = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); String date = "2020-05-09 12:30:15"; - String json = jsonService.toJsonStr(new DateBean(1, sdf.parse(date)), dataFormat); + String json = jsonService.serialize(new DateBean(1, sdf.parse(date)), dataFormat); Assert.assertTrue(json.contains(date)); } @@ -66,7 +66,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { public void testJsonToBean() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - User user = jsonService.jsonToBean(User.class, in); + User user = jsonService.toBean(User.class, in); Assert.assertEquals(1, user.getId()); Assert.assertEquals("Jack", user.getName()); } @@ -75,7 +75,7 @@ public void testJsonToBean() { public void testJsonToList() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - List users = jsonService.jsonToList(User.class, in); + List users = jsonService.toList(User.class, in); Assert.assertTrue(2 == users.size()); User u1 = users.get(0); User u2 = users.get(1); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java index 85ae0620..52c6dc98 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java @@ -6,7 +6,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; -public class GsonArr implements JsonArr { +public class GsonArr implements Array { private JsonArray json; @@ -25,7 +25,7 @@ public boolean isEmpty() { } @Override - public JsonObj getJsonOjb(int index) { + public Mapper getMapper(int index) { JsonElement subJson = json.get(index); if (subJson != null) { return new GsonObj(subJson.getAsJsonObject()); @@ -34,7 +34,7 @@ public JsonObj getJsonOjb(int index) { } @Override - public JsonArr getJsonArr(int index) { + public Array getArray(int index) { JsonElement subJson = json.get(index); if (subJson != null) { return new GsonArr(subJson.getAsJsonArray()); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java index 88d3afbf..fb2fa2f4 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java @@ -7,7 +7,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; -public class GsonObj implements JsonObj { +public class GsonObj implements Mapper { private JsonObject json; @@ -26,7 +26,7 @@ public boolean isEmpty() { } @Override - public JsonObj getJsonOjb(String key) { + public Mapper getMapper(String key) { JsonElement subJson = json.get(key); if (subJson != null) { return new GsonObj(subJson.getAsJsonObject()); @@ -35,7 +35,7 @@ public JsonObj getJsonOjb(String key) { } @Override - public JsonArr getJsonArr(String key) { + public Array getArray(String key) { JsonElement subJson = json.get(key); if (subJson != null) { return new GsonArr(subJson.getAsJsonArray()); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java index 1b25c59e..ead466a4 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java @@ -24,32 +24,32 @@ public GsonService(Gson gson) { } @Override - public JsonObj toJsonObj(InputStream in) { + public Mapper toMapper(InputStream in) { return new GsonObj(gson.fromJson(new InputStreamReader(in), JsonObject.class)); } @Override - public JsonArr toJsonArr(InputStream in) { + public Array toArray(InputStream in) { return new GsonArr(gson.fromJson(new InputStreamReader(in), JsonArray.class)); } @Override - public String toJsonStr(Object bean) { + public String serialize(Object bean) { return gson.toJson(bean); } @Override - public String toJsonStr(Object bean, String dateFormat) { + public String serialize(Object bean, String dateFormat) { return gson.newBuilder().setDateFormat(dateFormat).create().toJson(bean); } @Override - public T jsonToBean(Class type, InputStream in) { + public T toBean(Class type, InputStream in) { return gson.fromJson(new InputStreamReader(in), type); } @Override - public List jsonToList(Class type, InputStream in) { + public List toList(Class type, InputStream in) { T[] beans = gson.fromJson(new InputStreamReader(in), TypeToken.getArray(type).getType()); List list = new ArrayList<>(); Collections.addAll(list, beans); diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java index ebf03180..ce9603f7 100644 --- a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java +++ b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java @@ -19,28 +19,28 @@ public class TestCases { public void testToJsonObj() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - JsonObj jsonObj = jsonService.toJsonObj(in); - Set keys = jsonObj.keySet(); + Mapper mapper = jsonService.toMapper(in); + Set keys = mapper.keySet(); Assert.assertTrue(keys.size() == 2); Assert.assertTrue(keys.contains("id")); Assert.assertTrue(keys.contains("name")); - Assert.assertTrue(!jsonObj.isEmpty()); - Assert.assertTrue(2 == jsonObj.size()); - Assert.assertTrue(1 == jsonObj.getInt("id")); - Assert.assertTrue(!jsonObj.has("age")); - Assert.assertTrue(0 == jsonObj.getInt("age")); - Assert.assertEquals("Jack", jsonObj.getString("name")); + Assert.assertTrue(!mapper.isEmpty()); + Assert.assertTrue(2 == mapper.size()); + Assert.assertTrue(1 == mapper.getInt("id")); + Assert.assertTrue(!mapper.has("age")); + Assert.assertTrue(0 == mapper.getInt("age")); + Assert.assertEquals("Jack", mapper.getString("name")); } @Test public void testToJsonArr() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - JsonArr jsonObj = jsonService.toJsonArr(in); + Array jsonObj = jsonService.toArray(in); Assert.assertTrue(!jsonObj.isEmpty()); Assert.assertTrue(jsonObj.size() == 2); - JsonObj json1 = jsonObj.getJsonOjb(0); - JsonObj json2 = jsonObj.getJsonOjb(1); + Mapper json1 = jsonObj.getMapper(0); + Mapper json2 = jsonObj.getMapper(1); Assert.assertEquals(1, json1.getInt("id")); Assert.assertEquals("Jack", json1.getString("name")); Assert.assertEquals(2, json2.getInt("id")); @@ -49,7 +49,7 @@ public void testToJsonArr() { @Test public void testToJsonStr() { - String json = jsonService.toJsonStr(new User(1, "Jack")); + String json = jsonService.serialize(new User(1, "Jack")); Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); } @@ -58,7 +58,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { String dataFormat = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); String date = "2020-05-09 12:30:15"; - String json = jsonService.toJsonStr(new DateBean(1, sdf.parse(date)), dataFormat); + String json = jsonService.serialize(new DateBean(1, sdf.parse(date)), dataFormat); Assert.assertTrue(json.contains(date)); } @@ -66,7 +66,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { public void testJsonToBean() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - User user = jsonService.jsonToBean(User.class, in); + User user = jsonService.toBean(User.class, in); Assert.assertEquals(1, user.getId()); Assert.assertEquals("Jack", user.getName()); } @@ -75,7 +75,7 @@ public void testJsonToBean() { public void testJsonToList() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - List users = jsonService.jsonToList(User.class, in); + List users = jsonService.toList(User.class, in); Assert.assertTrue(2 == users.size()); User u1 = users.get(0); User u2 = users.get(1); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java index 3d65cf0b..b5ba9bd2 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -public class JacksonArr implements JsonArr { +public class JacksonArr implements Array { private ArrayNode json; @@ -26,7 +26,7 @@ public boolean isEmpty() { } @Override - public JsonObj getJsonOjb(int index) { + public Mapper getMapper(int index) { JsonNode subJson = json.get(index); if (subJson != null && subJson.isObject()) { return new JacksonObj((ObjectNode) subJson); @@ -35,7 +35,7 @@ public JsonObj getJsonOjb(int index) { } @Override - public JsonArr getJsonArr(int index) { + public Array getArray(int index) { JsonNode subJson = json.get(index); if (subJson != null && subJson.isArray()) { return new JacksonArr((ArrayNode) subJson); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java index f67a1d2a..1bc58905 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java @@ -10,7 +10,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -public class JacksonObj implements JsonObj { +public class JacksonObj implements Mapper { private ObjectNode json; @@ -29,7 +29,7 @@ public boolean isEmpty() { } @Override - public JsonObj getJsonOjb(String key) { + public Mapper getMapper(String key) { JsonNode subJson = json.get(key); if (subJson != null && subJson.isObject()) { return new JacksonObj((ObjectNode) subJson); @@ -38,7 +38,7 @@ public JsonObj getJsonOjb(String key) { } @Override - public JsonArr getJsonArr(String key) { + public Array getArray(String key) { JsonNode subJson = json.get(key); if (subJson != null && subJson.isArray()) { return new JacksonArr((ArrayNode) subJson); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java index 301d5a73..7b831649 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java @@ -28,7 +28,7 @@ public JacksonService(ObjectMapper objectMapper) { } @Override - public JsonObj toJsonObj(InputStream in) { + public Mapper toMapper(InputStream in) { try { JsonNode json = objectMapper.readTree(in); if (json.isObject()) { @@ -44,7 +44,7 @@ public JsonObj toJsonObj(InputStream in) { } @Override - public JsonArr toJsonArr(InputStream in) { + public Array toArray(InputStream in) { try { JsonNode json = objectMapper.readTree(in); if (json.isArray()) { @@ -60,7 +60,7 @@ public JsonArr toJsonArr(InputStream in) { } @Override - public String toJsonStr(Object bean) { + public String serialize(Object bean) { try { return objectMapper.writeValueAsString(bean); } catch (JsonProcessingException e) { @@ -69,7 +69,7 @@ public String toJsonStr(Object bean) { } @Override - public String toJsonStr(Object bean, String dateFormat) { + public String serialize(Object bean, String dateFormat) { ObjectMapper mapper = objectMapper.copy(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.setDateFormat(new SimpleDateFormat(dateFormat)); @@ -81,7 +81,7 @@ public String toJsonStr(Object bean, String dateFormat) { } @Override - public T jsonToBean(Class type, InputStream in) { + public T toBean(Class type, InputStream in) { try { return objectMapper.readValue(in, type); } catch (IOException e) { @@ -90,7 +90,7 @@ public T jsonToBean(Class type, InputStream in) { } @Override - public List jsonToList(Class type, InputStream in) { + public List toList(Class type, InputStream in) { CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type); try { return objectMapper.readValue(in, javaType); diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java index 63953de4..8d01d3ad 100644 --- a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java +++ b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java @@ -19,28 +19,28 @@ public class TestCases { public void testToJsonObj() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - JsonObj jsonObj = jsonService.toJsonObj(in); - Set keys = jsonObj.keySet(); + Mapper mapper = jsonService.toMapper(in); + Set keys = mapper.keySet(); Assert.assertTrue(keys.size() == 2); Assert.assertTrue(keys.contains("id")); Assert.assertTrue(keys.contains("name")); - Assert.assertTrue(!jsonObj.isEmpty()); - Assert.assertTrue(2 == jsonObj.size()); - Assert.assertTrue(1 == jsonObj.getInt("id")); - Assert.assertTrue(!jsonObj.has("age")); - Assert.assertTrue(0 == jsonObj.getInt("age")); - Assert.assertEquals("Jack", jsonObj.getString("name")); + Assert.assertTrue(!mapper.isEmpty()); + Assert.assertTrue(2 == mapper.size()); + Assert.assertTrue(1 == mapper.getInt("id")); + Assert.assertTrue(!mapper.has("age")); + Assert.assertTrue(0 == mapper.getInt("age")); + Assert.assertEquals("Jack", mapper.getString("name")); } @Test public void testToJsonArr() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - JsonArr jsonObj = jsonService.toJsonArr(in); + Array jsonObj = jsonService.toArray(in); Assert.assertTrue(!jsonObj.isEmpty()); Assert.assertTrue(jsonObj.size() == 2); - JsonObj json1 = jsonObj.getJsonOjb(0); - JsonObj json2 = jsonObj.getJsonOjb(1); + Mapper json1 = jsonObj.getMapper(0); + Mapper json2 = jsonObj.getMapper(1); Assert.assertEquals(1, json1.getInt("id")); Assert.assertEquals("Jack", json1.getString("name")); Assert.assertEquals(2, json2.getInt("id")); @@ -49,7 +49,7 @@ public void testToJsonArr() { @Test public void testToJsonStr() { - String json = jsonService.toJsonStr(new User(1, "Jack")); + String json = jsonService.serialize(new User(1, "Jack")); Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); } @@ -58,7 +58,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { String dataFormat = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); String date = "2020-05-09 12:30:15"; - String json = jsonService.toJsonStr(new DateBean(1, sdf.parse(date)), dataFormat); + String json = jsonService.serialize(new DateBean(1, sdf.parse(date)), dataFormat); Assert.assertTrue(json.contains(date)); } @@ -66,7 +66,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { public void testJsonToBean() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - User user = jsonService.jsonToBean(User.class, in); + User user = jsonService.toBean(User.class, in); Assert.assertEquals(1, user.getId()); Assert.assertEquals("Jack", user.getName()); } @@ -75,7 +75,7 @@ public void testJsonToBean() { public void testJsonToList() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - List users = jsonService.jsonToList(User.class, in); + List users = jsonService.toList(User.class, in); Assert.assertTrue(2 == users.size()); User u1 = users.get(0); User u2 = users.get(1); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java b/okhttps/src/main/java/com/ejlchina/okhttps/Array.java similarity index 92% rename from okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java rename to okhttps/src/main/java/com/ejlchina/okhttps/Array.java index e9782b66..ce34e899 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonArr.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/Array.java @@ -3,7 +3,7 @@ import java.math.BigDecimal; import java.math.BigInteger; -public interface JsonArr { +public interface Array { /** * @return JSON 的键值对数é‡� @@ -19,13 +19,13 @@ public interface JsonArr { * @param index 元素下标 * @return å­� JsonObj */ - JsonObj getJsonOjb(int index); + Mapper getMapper(int index); /** * @param index 元素下标 * @return å­� JsonArr */ - JsonArr getJsonArr(int index); + Array getArray(int index); /** * @param index 元素下标 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java index 6a1ae528..6c1dd203 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -151,13 +151,13 @@ public interface Body { * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ * @return 报文体转Json对象 */ - JsonObj toJsonObj(); + Mapper toJsonObj(); /** * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ * @return 报文体转Json数组 */ - JsonArr toJsonArr(); + Array toJsonArr(); /** * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 10a6060e..d1354408 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -421,11 +421,11 @@ public C setRequestJson(Object json, String dateFormat) { } else if (dateFormat != null) { requestJson = httpClient.getExecutor() .jsonServiceNotNull() - .toJsonStr(json, dateFormat); + .serialize(json, dateFormat); } else { requestJson = httpClient.getExecutor() .jsonServiceNotNull() - .toJsonStr(json); + .serialize(json); } } return (C) this; @@ -657,7 +657,7 @@ protected State toState(IOException e, boolean sync) { private RequestBody buildRequestBody() { if (jsonParams != null) { requestJson = httpClient.getExecutor().jsonServiceNotNull() - .toJsonStr(jsonParams); + .serialize(jsonParams); } if (files != null) { MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java b/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java index 094d60d4..43edcdb7 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java @@ -7,33 +7,33 @@ public interface JsonService { /** - * è§£æž� JsonObj + * è§£æž� Mapper * @param in JSON 输入æµ� * @return JsonObj */ - JsonObj toJsonObj(InputStream in); + Mapper toMapper(InputStream in); /** - * è§£æž� JsonArr + * è§£æž� Array * @param in JSON 输入æµ� * @return JsonArr */ - JsonArr toJsonArr(InputStream in); + Array toArray(InputStream in); /** - * å°† Java 对象åº�列化为 Json 字符串 + * å°† Java 对象åº�列化为字符串 * @param bean Java Bean - * @return Json 字符串 + * @return 字符串 */ - String toJsonStr(Object bean); + String serialize(Object bean); /** - * å°† Java 对象åº�列化为 Json 字符串 + * å°† Java 对象åº�列化为字符串 * @param bean Java Bean * @param dateFormat 日期类的处ç�†æ ¼å¼� - * @return Json 字符串 + * @return 字符串 */ - String toJsonStr(Object bean, String dateFormat); + String serialize(Object bean, String dateFormat); /** * è§£æž� Java Bean @@ -42,7 +42,7 @@ public interface JsonService { * @param in JSON 输入æµ� * @return Java Bean */ - T jsonToBean(Class type, InputStream in); + T toBean(Class type, InputStream in); /** * è§£æž�为 Java List @@ -51,7 +51,7 @@ public interface JsonService { * @param in JSON 输入æµ� * @return Java List */ - List jsonToList(Class type, InputStream in); + List toList(Class type, InputStream in); } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java b/okhttps/src/main/java/com/ejlchina/okhttps/Mapper.java similarity index 89% rename from okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java rename to okhttps/src/main/java/com/ejlchina/okhttps/Mapper.java index 5a8cd48a..e5f9ec80 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonObj.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/Mapper.java @@ -9,12 +9,12 @@ * @author 15735 * */ -public interface JsonObj { +public interface Mapper { /** * @return JSON 的键值对数é‡� */ - public int size(); + int size(); /** * @return 是å�¦ä¸ºç©º @@ -25,13 +25,13 @@ public interface JsonObj { * @param key é”®å�� * @return å­� JsonObj */ - JsonObj getJsonOjb(String key); + Mapper getMapper(String key); /** * @param key é”®å�� * @return å­� JsonArr */ - JsonArr getJsonArr(String key); + Array getArray(String key); /** * @param key é”®å�� @@ -90,6 +90,6 @@ public interface JsonObj { /** * @return JSON 的键集å�ˆ */ - public Set keySet(); + Set keySet(); } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java index fad33e60..7b05ddaf 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java @@ -45,12 +45,12 @@ public interface Message { /** * @return 消æ�¯ä½“转Json对象 */ - JsonObj toJsonObj(); + Mapper toJsonObj(); /** * @return 消æ�¯ä½“转Json数组 */ - JsonArr toJsonArr(); + Array toJsonArr(); /** * @param 目标泛型 diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java index d3a0a78e..8c8ab239 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java @@ -3,8 +3,8 @@ import java.io.InputStream; import java.util.List; -import com.ejlchina.okhttps.JsonArr; -import com.ejlchina.okhttps.JsonObj; +import com.ejlchina.okhttps.Array; +import com.ejlchina.okhttps.Mapper; public abstract class AbstractBody { @@ -19,19 +19,19 @@ public AbstractBody(TaskExecutor taskExecutor) { public abstract InputStream toByteStream(); - public JsonObj toJsonObj() { + public Mapper toJsonObj() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); } - return taskExecutor.jsonServiceNotNull().toJsonObj(toByteStream()); + return taskExecutor.jsonServiceNotNull().toMapper(toByteStream()); } - public JsonArr toJsonArr() { + public Array toJsonArr() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); } - return taskExecutor.jsonServiceNotNull().toJsonArr(toByteStream()); + return taskExecutor.jsonServiceNotNull().toArray(toByteStream()); } @@ -39,7 +39,7 @@ public T toBean(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); } - return taskExecutor.jsonServiceNotNull().jsonToBean(type, toByteStream()); + return taskExecutor.jsonServiceNotNull().toBean(type, toByteStream()); } @@ -47,7 +47,7 @@ public List toList(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); } - return taskExecutor.jsonServiceNotNull().jsonToList(type, toByteStream()); + return taskExecutor.jsonServiceNotNull().toList(type, toByteStream()); } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index c4a31090..1eab9f2f 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -170,12 +170,12 @@ public boolean send(ByteString bytes) { @Override public boolean send(Object bean) { - return send(taskExecutor.jsonServiceNotNull().toJsonStr(bean)); + return send(taskExecutor.jsonServiceNotNull().serialize(bean)); } @Override public boolean send(Object bean, String dateFormat) { - return send(taskExecutor.jsonServiceNotNull().toJsonStr(bean, dateFormat)); + return send(taskExecutor.jsonServiceNotNull().serialize(bean, dateFormat)); } @Override @@ -226,7 +226,7 @@ boolean send(okhttp3.WebSocket webSocket, Object msg) { if (msg instanceof byte[]) { return webSocket.send(ByteString.of((byte[]) msg)); } - return webSocket.send(taskExecutor.jsonServiceNotNull().toJsonStr(msg)); + return webSocket.send(taskExecutor.jsonServiceNotNull().serialize(msg)); } } diff --git a/okhttps/src/test/java/com/ejlchina/test/SimpleTests.java b/okhttps/src/test/java/com/ejlchina/test/SimpleTests.java index b9e9144e..019aaf2f 100644 --- a/okhttps/src/test/java/com/ejlchina/test/SimpleTests.java +++ b/okhttps/src/test/java/com/ejlchina/test/SimpleTests.java @@ -2,10 +2,7 @@ import com.ejlchina.okhttps.HTTP; -import com.ejlchina.okhttps.JsonObj; -import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; -import org.junit.Test; public class SimpleTests extends BaseTest { From 713074068eb1eabef9c4ac537bea50cd568bb698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 09:42:35 +0800 Subject: [PATCH 249/924] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpResult.java | 8 ++++---- .../java/com/ejlchina/okhttps/WebSocket.java | 16 ++++++++-------- .../ejlchina/okhttps/internal/AbstractBody.java | 4 ++-- .../test/java/com/ejlchina/test/CacheTests.java | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java index 6c1dd203..74edfb21 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -44,7 +44,7 @@ static HttpResult of(Response response, TaskExecutor taskExecutor) { } - public enum State { + enum State { /** * 执行异常 @@ -76,7 +76,7 @@ public enum State { /** * HTTPå“�应报文体 */ - public interface Body { + interface Body { /** * @return 媒体类型 @@ -151,13 +151,13 @@ public interface Body { * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ * @return 报文体转Json对象 */ - Mapper toJsonObj(); + Mapper toMapper(); /** * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ * @return 报文体转Json数组 */ - Array toJsonArr(); + Array toArray(); /** * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java index 7b05ddaf..bdd16b3c 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java @@ -9,7 +9,7 @@ public interface WebSocket extends Cancelable { - public interface Message { + interface Message { /** * 判断是文本消æ�¯è¿˜æ˜¯äºŒè¿›åˆ¶æ¶ˆæ�¯ @@ -45,12 +45,12 @@ public interface Message { /** * @return 消æ�¯ä½“转Json对象 */ - Mapper toJsonObj(); + Mapper toMapper(); /** * @return 消æ�¯ä½“转Json数组 */ - Array toJsonArr(); + Array toArray(); /** * @param 目标泛型 @@ -69,7 +69,7 @@ public interface Message { } - public static class Close { + class Close { private int code; private String reason; @@ -102,7 +102,7 @@ public String toString() { } - public interface Listener { + interface Listener { void on(WebSocket ws, T data); @@ -135,7 +135,7 @@ public interface Listener { * @param bean å¾…å�‘é€�的对象 * @return 如果连接已断开 返回 false */ - public boolean send(Object bean); + boolean send(Object bean); /** * 以JSON文本格å¼�å�‘é€�对象消æ�¯ @@ -143,14 +143,14 @@ public interface Listener { * @param dateFormat 日期类型字段的处ç�†æ ¼å¼� * @return 如果连接已断开 返回 false */ - public boolean send(Object bean, String dateFormat); + boolean send(Object bean, String dateFormat); /** * å�‘é€�字节æµ� * @param data å¾…å�‘é€�的数æ�® * @return 如果连接已断开 返回 false */ - public boolean send(byte[] data); + boolean send(byte[] data); /** * å�Œ {@link okhttp3.WebSocket#close(int, String)} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java index 8c8ab239..82378892 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java @@ -19,7 +19,7 @@ public AbstractBody(TaskExecutor taskExecutor) { public abstract InputStream toByteStream(); - public Mapper toJsonObj() { + public Mapper toMapper() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); } @@ -27,7 +27,7 @@ public Mapper toJsonObj() { } - public Array toJsonArr() { + public Array toArray() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); } diff --git a/okhttps/src/test/java/com/ejlchina/test/CacheTests.java b/okhttps/src/test/java/com/ejlchina/test/CacheTests.java index 962eebb8..add97d87 100644 --- a/okhttps/src/test/java/com/ejlchina/test/CacheTests.java +++ b/okhttps/src/test/java/com/ejlchina/test/CacheTests.java @@ -16,12 +16,12 @@ public void testCache() { .cache(); println("result = " + body.toString()); - println("result = " + body.toJsonArr()); + println("result = " + body.toArray()); body.close(); println("result = " + body.toString()); - println("result = " + body.toJsonArr()); + println("result = " + body.toArray()); } } From fd81805a41a8bc03a8e98fd32863aa616259591f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 09:47:44 +0800 Subject: [PATCH 250/924] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ejlchina/okhttps/{GsonArr.java => GsonArray.java} | 8 ++++---- .../ejlchina/okhttps/{GsonObj.java => GsonMapper.java} | 8 ++++---- .../src/main/java/com/ejlchina/okhttps/GsonService.java | 4 ++-- .../okhttps/{JacksonArr.java => JacksonArray.java} | 8 ++++---- .../okhttps/{JacksonObj.java => JacksonMapper.java} | 8 ++++---- .../main/java/com/ejlchina/okhttps/JacksonService.java | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) rename okhttps-gson/src/main/java/com/ejlchina/okhttps/{GsonArr.java => GsonArray.java} (91%) rename okhttps-gson/src/main/java/com/ejlchina/okhttps/{GsonObj.java => GsonMapper.java} (91%) rename okhttps-jackson/src/main/java/com/ejlchina/okhttps/{JacksonArr.java => JacksonArray.java} (92%) rename okhttps-jackson/src/main/java/com/ejlchina/okhttps/{JacksonObj.java => JacksonMapper.java} (93%) diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArray.java similarity index 91% rename from okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java rename to okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArray.java index 52c6dc98..3208b56a 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArr.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArray.java @@ -6,11 +6,11 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; -public class GsonArr implements Array { +public class GsonArray implements Array { private JsonArray json; - public GsonArr(JsonArray json) { + public GsonArray(JsonArray json) { this.json = json; } @@ -28,7 +28,7 @@ public boolean isEmpty() { public Mapper getMapper(int index) { JsonElement subJson = json.get(index); if (subJson != null) { - return new GsonObj(subJson.getAsJsonObject()); + return new GsonMapper(subJson.getAsJsonObject()); } return null; } @@ -37,7 +37,7 @@ public Mapper getMapper(int index) { public Array getArray(int index) { JsonElement subJson = json.get(index); if (subJson != null) { - return new GsonArr(subJson.getAsJsonArray()); + return new GsonArray(subJson.getAsJsonArray()); } return null; } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMapper.java similarity index 91% rename from okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java rename to okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMapper.java index fb2fa2f4..2b52c9f4 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonObj.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMapper.java @@ -7,11 +7,11 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; -public class GsonObj implements Mapper { +public class GsonMapper implements Mapper { private JsonObject json; - public GsonObj(JsonObject json) { + public GsonMapper(JsonObject json) { this.json = json; } @@ -29,7 +29,7 @@ public boolean isEmpty() { public Mapper getMapper(String key) { JsonElement subJson = json.get(key); if (subJson != null) { - return new GsonObj(subJson.getAsJsonObject()); + return new GsonMapper(subJson.getAsJsonObject()); } return null; } @@ -38,7 +38,7 @@ public Mapper getMapper(String key) { public Array getArray(String key) { JsonElement subJson = json.get(key); if (subJson != null) { - return new GsonArr(subJson.getAsJsonArray()); + return new GsonArray(subJson.getAsJsonArray()); } return null; } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java index ead466a4..b8501bb6 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java @@ -25,12 +25,12 @@ public GsonService(Gson gson) { @Override public Mapper toMapper(InputStream in) { - return new GsonObj(gson.fromJson(new InputStreamReader(in), JsonObject.class)); + return new GsonMapper(gson.fromJson(new InputStreamReader(in), JsonObject.class)); } @Override public Array toArray(InputStream in) { - return new GsonArr(gson.fromJson(new InputStreamReader(in), JsonArray.class)); + return new GsonArray(gson.fromJson(new InputStreamReader(in), JsonArray.class)); } @Override diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArray.java similarity index 92% rename from okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java rename to okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArray.java index b5ba9bd2..a0c5e69e 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArr.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArray.java @@ -7,11 +7,11 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -public class JacksonArr implements Array { +public class JacksonArray implements Array { private ArrayNode json; - public JacksonArr(ArrayNode json) { + public JacksonArray(ArrayNode json) { this.json = json; } @@ -29,7 +29,7 @@ public boolean isEmpty() { public Mapper getMapper(int index) { JsonNode subJson = json.get(index); if (subJson != null && subJson.isObject()) { - return new JacksonObj((ObjectNode) subJson); + return new JacksonMapper((ObjectNode) subJson); } return null; } @@ -38,7 +38,7 @@ public Mapper getMapper(int index) { public Array getArray(int index) { JsonNode subJson = json.get(index); if (subJson != null && subJson.isArray()) { - return new JacksonArr((ArrayNode) subJson); + return new JacksonArray((ArrayNode) subJson); } return null; } diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMapper.java similarity index 93% rename from okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java rename to okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMapper.java index 1bc58905..9e81fa4d 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonObj.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMapper.java @@ -10,11 +10,11 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -public class JacksonObj implements Mapper { +public class JacksonMapper implements Mapper { private ObjectNode json; - public JacksonObj(ObjectNode json) { + public JacksonMapper(ObjectNode json) { this.json = json; } @@ -32,7 +32,7 @@ public boolean isEmpty() { public Mapper getMapper(String key) { JsonNode subJson = json.get(key); if (subJson != null && subJson.isObject()) { - return new JacksonObj((ObjectNode) subJson); + return new JacksonMapper((ObjectNode) subJson); } return null; } @@ -41,7 +41,7 @@ public Mapper getMapper(String key) { public Array getArray(String key) { JsonNode subJson = json.get(key); if (subJson != null && subJson.isArray()) { - return new JacksonArr((ArrayNode) subJson); + return new JacksonArray((ArrayNode) subJson); } return null; } diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java index 7b831649..d3c71519 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java @@ -32,7 +32,7 @@ public Mapper toMapper(InputStream in) { try { JsonNode json = objectMapper.readTree(in); if (json.isObject()) { - return new JacksonObj((ObjectNode) json); + return new JacksonMapper((ObjectNode) json); } if (json.isNull() || json.isMissingNode()) { return null; @@ -48,7 +48,7 @@ public Array toArray(InputStream in) { try { JsonNode json = objectMapper.readTree(in); if (json.isArray()) { - return new JacksonArr((ArrayNode) json); + return new JacksonArray((ArrayNode) json); } if (json.isNull() || json.isMissingNode()) { return null; From 13d6cf716c65991c2bfa7c5cfb21c7141b85ab64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 10:00:54 +0800 Subject: [PATCH 251/924] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ejlchina/okhttps/FastJsonAutoConfig.java | 4 ++-- ...nService.java => FastjsonMsgConvertor.java} | 6 +++--- .../java/com/ejlchina/okhttps/TestCases.java | 14 +++++++------- .../com/ejlchina/okhttps/GsonAutoConfig.java | 4 ++-- ...{GsonService.java => GsonMsgConvertor.java} | 6 +++--- .../java/com/ejlchina/okhttps/TestCases.java | 14 +++++++------- .../ejlchina/okhttps/JacksonAutoConfig.java | 4 ++-- ...onService.java => JacksonMsgConvertor.java} | 6 +++--- .../java/com/ejlchina/okhttps/TestCases.java | 14 +++++++------- .../main/java/com/ejlchina/okhttps/HTTP.java | 16 ++++++++-------- .../java/com/ejlchina/okhttps/HttpUtils.java | 8 ++++---- .../{JsonService.java => MsgConvertor.java} | 9 +++++---- .../ejlchina/okhttps/internal/HttpClient.java | 2 +- .../okhttps/internal/TaskExecutor.java | 18 +++++++++--------- 14 files changed, 63 insertions(+), 62 deletions(-) rename okhttps-fastjson/src/main/java/com/ejlchina/okhttps/{FastJsonService.java => FastjsonMsgConvertor.java} (90%) rename okhttps-gson/src/main/java/com/ejlchina/okhttps/{GsonService.java => GsonMsgConvertor.java} (91%) rename okhttps-jackson/src/main/java/com/ejlchina/okhttps/{JacksonService.java => JacksonMsgConvertor.java} (95%) rename okhttps/src/main/java/com/ejlchina/okhttps/{JsonService.java => MsgConvertor.java} (94%) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java index 52ab16fa..e29139bc 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java @@ -4,8 +4,8 @@ public class FastJsonAutoConfig implements OkHttps.Config { @Override public void withConfig(HTTP.Builder builder) { - if (builder.getJsonService() == null) { - builder.jsonService(new FastJsonService()); + if (builder.getMsgConvertor() == null) { + builder.msgConvertor(new FastjsonMsgConvertor()); } } diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java similarity index 90% rename from okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java rename to okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java index 4093be9d..a43b7288 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonService.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java @@ -11,15 +11,15 @@ import okio.Okio; -public class FastJsonService implements JsonService { +public class FastjsonMsgConvertor implements MsgConvertor { private Charset charset; - public FastJsonService() { + public FastjsonMsgConvertor() { this(StandardCharsets.UTF_8); } - public FastJsonService(Charset charset) { + public FastjsonMsgConvertor(Charset charset) { this.charset = charset; } diff --git a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java index 1acb99a8..0006da0a 100644 --- a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java +++ b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java @@ -13,13 +13,13 @@ public class TestCases { - JsonService jsonService = new FastJsonService(); + MsgConvertor msgConvertor = new FastjsonMsgConvertor(); @Test public void testToJsonObj() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - Mapper mapper = jsonService.toMapper(in); + Mapper mapper = msgConvertor.toMapper(in); Set keys = mapper.keySet(); Assert.assertTrue(keys.size() == 2); Assert.assertTrue(keys.contains("id")); @@ -36,7 +36,7 @@ public void testToJsonObj() { public void testToJsonArr() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - Array jsonObj = jsonService.toArray(in); + Array jsonObj = msgConvertor.toArray(in); Assert.assertTrue(!jsonObj.isEmpty()); Assert.assertTrue(jsonObj.size() == 2); Mapper json1 = jsonObj.getMapper(0); @@ -49,7 +49,7 @@ public void testToJsonArr() { @Test public void testToJsonStr() { - String json = jsonService.serialize(new User(1, "Jack")); + String json = msgConvertor.serialize(new User(1, "Jack")); Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); } @@ -58,7 +58,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { String dataFormat = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); String date = "2020-05-09 12:30:15"; - String json = jsonService.serialize(new DateBean(1, sdf.parse(date)), dataFormat); + String json = msgConvertor.serialize(new DateBean(1, sdf.parse(date)), dataFormat); Assert.assertTrue(json.contains(date)); } @@ -66,7 +66,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { public void testJsonToBean() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - User user = jsonService.toBean(User.class, in); + User user = msgConvertor.toBean(User.class, in); Assert.assertEquals(1, user.getId()); Assert.assertEquals("Jack", user.getName()); } @@ -75,7 +75,7 @@ public void testJsonToBean() { public void testJsonToList() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - List users = jsonService.toList(User.class, in); + List users = msgConvertor.toList(User.class, in); Assert.assertTrue(2 == users.size()); User u1 = users.get(0); User u2 = users.get(1); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java index 1695741b..670103f2 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java @@ -4,8 +4,8 @@ public class GsonAutoConfig implements OkHttps.Config { @Override public void withConfig(HTTP.Builder builder) { - if (builder.getJsonService() == null) { - builder.jsonService(new GsonService()); + if (builder.getMsgConvertor() == null) { + builder.msgConvertor(new GsonMsgConvertor()); } } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java similarity index 91% rename from okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java rename to okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java index b8501bb6..770c886d 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonService.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java @@ -11,15 +11,15 @@ import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; -public class GsonService implements JsonService { +public class GsonMsgConvertor implements MsgConvertor { private Gson gson; - public GsonService() { + public GsonMsgConvertor() { this(new Gson()); } - public GsonService(Gson gson) { + public GsonMsgConvertor(Gson gson) { this.gson = gson; } diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java index ce9603f7..f87aeb66 100644 --- a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java +++ b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java @@ -13,13 +13,13 @@ public class TestCases { - JsonService jsonService = new GsonService(); + MsgConvertor msgConvertor = new GsonMsgConvertor(); @Test public void testToJsonObj() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - Mapper mapper = jsonService.toMapper(in); + Mapper mapper = msgConvertor.toMapper(in); Set keys = mapper.keySet(); Assert.assertTrue(keys.size() == 2); Assert.assertTrue(keys.contains("id")); @@ -36,7 +36,7 @@ public void testToJsonObj() { public void testToJsonArr() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - Array jsonObj = jsonService.toArray(in); + Array jsonObj = msgConvertor.toArray(in); Assert.assertTrue(!jsonObj.isEmpty()); Assert.assertTrue(jsonObj.size() == 2); Mapper json1 = jsonObj.getMapper(0); @@ -49,7 +49,7 @@ public void testToJsonArr() { @Test public void testToJsonStr() { - String json = jsonService.serialize(new User(1, "Jack")); + String json = msgConvertor.serialize(new User(1, "Jack")); Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); } @@ -58,7 +58,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { String dataFormat = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); String date = "2020-05-09 12:30:15"; - String json = jsonService.serialize(new DateBean(1, sdf.parse(date)), dataFormat); + String json = msgConvertor.serialize(new DateBean(1, sdf.parse(date)), dataFormat); Assert.assertTrue(json.contains(date)); } @@ -66,7 +66,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { public void testJsonToBean() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - User user = jsonService.toBean(User.class, in); + User user = msgConvertor.toBean(User.class, in); Assert.assertEquals(1, user.getId()); Assert.assertEquals("Jack", user.getName()); } @@ -75,7 +75,7 @@ public void testJsonToBean() { public void testJsonToList() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - List users = jsonService.toList(User.class, in); + List users = msgConvertor.toList(User.class, in); Assert.assertTrue(2 == users.size()); User u1 = users.get(0); User u2 = users.get(1); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java index 7e7a3a0c..d8413273 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java @@ -4,8 +4,8 @@ public class JacksonAutoConfig implements OkHttps.Config { @Override public void withConfig(HTTP.Builder builder) { - if (builder.getJsonService() == null) { - builder.jsonService(new JacksonService()); + if (builder.getMsgConvertor() == null) { + builder.msgConvertor(new JacksonMsgConvertor()); } } diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java similarity index 95% rename from okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java rename to okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java index d3c71519..25d896c0 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonService.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java @@ -15,15 +15,15 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.type.CollectionType; -public class JacksonService implements JsonService { +public class JacksonMsgConvertor implements MsgConvertor { private ObjectMapper objectMapper; - public JacksonService() { + public JacksonMsgConvertor() { this(new ObjectMapper()); } - public JacksonService(ObjectMapper objectMapper) { + public JacksonMsgConvertor(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java index 8d01d3ad..c7b8ec3b 100644 --- a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java +++ b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java @@ -13,13 +13,13 @@ public class TestCases { - JsonService jsonService = new JacksonService(); + MsgConvertor msgConvertor = new JacksonMsgConvertor(); @Test public void testToJsonObj() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - Mapper mapper = jsonService.toMapper(in); + Mapper mapper = msgConvertor.toMapper(in); Set keys = mapper.keySet(); Assert.assertTrue(keys.size() == 2); Assert.assertTrue(keys.contains("id")); @@ -36,7 +36,7 @@ public void testToJsonObj() { public void testToJsonArr() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - Array jsonObj = jsonService.toArray(in); + Array jsonObj = msgConvertor.toArray(in); Assert.assertTrue(!jsonObj.isEmpty()); Assert.assertTrue(jsonObj.size() == 2); Mapper json1 = jsonObj.getMapper(0); @@ -49,7 +49,7 @@ public void testToJsonArr() { @Test public void testToJsonStr() { - String json = jsonService.serialize(new User(1, "Jack")); + String json = msgConvertor.serialize(new User(1, "Jack")); Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); } @@ -58,7 +58,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { String dataFormat = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); String date = "2020-05-09 12:30:15"; - String json = jsonService.serialize(new DateBean(1, sdf.parse(date)), dataFormat); + String json = msgConvertor.serialize(new DateBean(1, sdf.parse(date)), dataFormat); Assert.assertTrue(json.contains(date)); } @@ -66,7 +66,7 @@ public void testToJsonStrWithDateFormat() throws ParseException { public void testJsonToBean() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - User user = jsonService.toBean(User.class, in); + User user = msgConvertor.toBean(User.class, in); Assert.assertEquals(1, user.getId()); Assert.assertEquals("Jack", user.getName()); } @@ -75,7 +75,7 @@ public void testJsonToBean() { public void testJsonToList() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - List users = jsonService.toList(User.class, in); + List users = msgConvertor.toList(User.class, in); Assert.assertTrue(2 == users.size()); User u1 = users.get(0); User u2 = users.get(1); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index 577f90b4..d70d99d4 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -110,7 +110,7 @@ class Builder { private TaskListener completeListener; - private JsonService jsonService; + private MsgConvertor msgConvertor; private int preprocTimeoutTimes = 10; @@ -144,7 +144,7 @@ public Builder(HttpClient hc) { this.responseListener = executor.getResponseListener(); this.exceptionListener = executor.getExceptionListener(); this.completeListener = executor.getCompleteListener(); - this.jsonService = executor.getJsonService(); + this.msgConvertor = executor.getMsgConvertor(); this.preprocTimeoutTimes = hc.getPreprocTimeoutTimes(); } @@ -284,12 +284,12 @@ public Builder downloadListener(DownListener listener) { } /** - * 设置 JSON æœ�务 - * @param jsonService JSON æœ�务 + * 设置消æ�¯è½¬æ�¢å™¨ + * @param msgConvertor JSON æœ�务 * @return Builder */ - public Builder jsonService(JsonService jsonService) { - this.jsonService = jsonService; + public Builder msgConvertor(MsgConvertor msgConvertor) { + this.msgConvertor = msgConvertor; return this; } @@ -348,8 +348,8 @@ public TaskListener getCompleteListener() { return completeListener; } - public JsonService getJsonService() { - return jsonService; + public MsgConvertor getMsgConvertor() { + return msgConvertor; } public int getPreprocTimeoutTimes() { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java index 1cd1bbe9..6862d111 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -40,7 +40,7 @@ static synchronized HTTP getHttp() { if (http != null) { return http; } - http = HTTP.builder().jsonService(findJsonService(new String[] { + http = HTTP.builder().msgConvertor(findJsonService(new String[] { "com.ejlchina.okhttps.GsonService", "com.ejlchina.okhttps.FastJsonService", "com.ejlchina.okhttps.JacksonService" @@ -48,7 +48,7 @@ static synchronized HTTP getHttp() { return http; } - static private JsonService findJsonService(String[] classes, int index) { + static private MsgConvertor findJsonService(String[] classes, int index) { if (index >= classes.length) { return null; } @@ -56,11 +56,11 @@ static private JsonService findJsonService(String[] classes, int index) { try { clazz = Class.forName(classes[0]); } catch (Exception ignore) {} - if (clazz == null || !JsonService.class.isAssignableFrom(clazz)) { + if (clazz == null || !MsgConvertor.class.isAssignableFrom(clazz)) { return findJsonService(classes, index + 1); } try { - return (JsonService) clazz.getDeclaredConstructor().newInstance(); + return (MsgConvertor) clazz.getDeclaredConstructor().newInstance(); } catch (Exception ignore) { return null; } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java similarity index 94% rename from okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java rename to okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java index 43edcdb7..2bea803b 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/JsonService.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java @@ -3,8 +3,10 @@ import java.io.InputStream; import java.util.List; - -public interface JsonService { +/** + * 消æ�¯è½¬æ�¢å™¨æŽ¥å�£ + */ +public interface MsgConvertor { /** * è§£æž� Mapper @@ -52,6 +54,5 @@ public interface JsonService { * @return Java List */ List toList(Class type, InputStream in); - - + } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index f27c1812..05ed17e7 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -33,7 +33,7 @@ public HttpClient(Builder builder) { this.executor = new TaskExecutor(okClient.dispatcher().executorService(), builder.getMainExecutor(), builder.getDownloadListener(), builder.getResponseListener(), builder.getExceptionListener(), - builder.getCompleteListener(), builder.getJsonService()); + builder.getCompleteListener(), builder.getMsgConvertor()); this.preprocessors = builder.getPreprocessors().toArray(new Preprocessor[0]); this.preprocTimeoutTimes = builder.getPreprocTimeoutTimes(); this.tagTasks = new LinkedList<>(); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 036da400..3c1404ff 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -10,7 +10,7 @@ import com.ejlchina.okhttps.Download; import com.ejlchina.okhttps.HttpResult; import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.JsonService; +import com.ejlchina.okhttps.MsgConvertor; import com.ejlchina.okhttps.OnCallback; import com.ejlchina.okhttps.TaskListener; import com.ejlchina.okhttps.HttpResult.State; @@ -23,18 +23,18 @@ public class TaskExecutor { TaskListener responseListener; TaskListener exceptionListener; TaskListener completeListener; - JsonService jsonService; + MsgConvertor msgConvertor; public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, TaskListener responseListener, TaskListener exceptionListener, - TaskListener completeListener, JsonService jsonService) { + TaskListener completeListener, MsgConvertor msgConvertor) { this.ioExecutor = ioExecutor; this.mainExecutor = mainExecutor; this.downloadListener = downloadListener; this.responseListener = responseListener; this.exceptionListener = exceptionListener; this.completeListener = completeListener; - this.jsonService = jsonService; + this.msgConvertor = msgConvertor; } public Executor getExecutor(boolean onIoThread) { @@ -99,9 +99,9 @@ public void executeOnComplete(HttpTask task, OnCallback onComplete, St } } - public JsonService jsonServiceNotNull() { - if (jsonService != null) { - return jsonService; + public MsgConvertor jsonServiceNotNull() { + if (msgConvertor != null) { + return msgConvertor; } throw new IllegalStateException("没有设置 JsonService,ä¸�å�¯å�š Json æ“�作ï¼�"); } @@ -143,8 +143,8 @@ public TaskListener getCompleteListener() { return completeListener; } - public JsonService getJsonService() { - return jsonService; + public MsgConvertor getMsgConvertor() { + return msgConvertor; } } From f758c336a86c90e8922f3550fe99402db68166ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 10:46:28 +0800 Subject: [PATCH 252/924] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ejlchina/okhttps/FastJsonAutoConfig.java | 12 ------- .../okhttps/FastjsonMsgConvertor.java | 7 +++- .../com.ejlchina.okhttps.ConvertProvider | 1 + .../com.ejlchina.okhttps.OkHttps.Config | 1 - .../com/ejlchina/okhttps/GsonAutoConfig.java | 12 ------- .../ejlchina/okhttps/GsonMsgConvertor.java | 9 +++-- .../com.ejlchina.okhttps.ConvertProvider | 1 + .../com.ejlchina.okhttps.OkHttps.Config | 1 - .../ejlchina/okhttps/JacksonAutoConfig.java | 12 ------- .../ejlchina/okhttps/JacksonMsgConvertor.java | 7 +++- .../com.ejlchina.okhttps.ConvertProvider | 1 + .../com.ejlchina.okhttps.OkHttps.Config | 1 - .../java/com/ejlchina/okhttps/Config.java | 18 ++++++++++ .../com/ejlchina/okhttps/Configurator.java | 17 ---------- .../com/ejlchina/okhttps/ConvertProvider.java | 21 ++++++++++++ .../main/java/com/ejlchina/okhttps/HTTP.java | 33 ++++++++++++------- .../java/com/ejlchina/okhttps/HttpUtils.java | 29 +++------------- .../java/com/ejlchina/okhttps/OkHttps.java | 10 ++---- 18 files changed, 90 insertions(+), 103 deletions(-) delete mode 100644 okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java create mode 100644 okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider delete mode 100644 okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config delete mode 100644 okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java create mode 100644 okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider delete mode 100644 okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config delete mode 100644 okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java create mode 100644 okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider delete mode 100644 okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config create mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/Config.java delete mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/Configurator.java create mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/ConvertProvider.java diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java deleted file mode 100644 index e29139bc..00000000 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastJsonAutoConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ejlchina.okhttps; - -public class FastJsonAutoConfig implements OkHttps.Config { - - @Override - public void withConfig(HTTP.Builder builder) { - if (builder.getMsgConvertor() == null) { - builder.msgConvertor(new FastjsonMsgConvertor()); - } - } - -} diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java index a43b7288..d5290e4d 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java @@ -11,7 +11,7 @@ import okio.Okio; -public class FastjsonMsgConvertor implements MsgConvertor { +public class FastjsonMsgConvertor implements MsgConvertor, ConvertProvider { private Charset charset; @@ -53,6 +53,11 @@ public List toList(Class type, InputStream in) { return JSON.parseArray(toString(in), type); } + @Override + public MsgConvertor getConvertor() { + return new FastjsonMsgConvertor(); + } + private String toString(InputStream in) { try { return Okio.buffer(Okio.source(in)).readString(charset); diff --git a/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider b/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider new file mode 100644 index 00000000..88f3b11d --- /dev/null +++ b/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider @@ -0,0 +1 @@ +com.ejlchina.okhttps.FastjsonMsgConvertor \ No newline at end of file diff --git a/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config deleted file mode 100644 index a590a34f..00000000 --- a/okhttps-fastjson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config +++ /dev/null @@ -1 +0,0 @@ -com.ejlchina.okhttps.FastJsonAutoConfig \ No newline at end of file diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java deleted file mode 100644 index 670103f2..00000000 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonAutoConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ejlchina.okhttps; - -public class GsonAutoConfig implements OkHttps.Config { - - @Override - public void withConfig(HTTP.Builder builder) { - if (builder.getMsgConvertor() == null) { - builder.msgConvertor(new GsonMsgConvertor()); - } - } - -} diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java index 770c886d..b4597263 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java @@ -11,7 +11,7 @@ import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; -public class GsonMsgConvertor implements MsgConvertor { +public class GsonMsgConvertor implements MsgConvertor, ConvertProvider { private Gson gson; @@ -56,6 +56,11 @@ public List toList(Class type, InputStream in) { return list; } + @Override + public MsgConvertor getConvertor() { + return new GsonMsgConvertor(); + } + public Gson getGson() { return gson; } @@ -63,7 +68,7 @@ public Gson getGson() { public void setGson(Gson gson) { this.gson = gson; } - + } diff --git a/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider b/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider new file mode 100644 index 00000000..5eb90888 --- /dev/null +++ b/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider @@ -0,0 +1 @@ +com.ejlchina.okhttps.GsonMsgConvertor \ No newline at end of file diff --git a/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config deleted file mode 100644 index 637f6eb7..00000000 --- a/okhttps-gson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config +++ /dev/null @@ -1 +0,0 @@ -com.ejlchina.okhttps.GsonAutoConfig \ No newline at end of file diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java deleted file mode 100644 index d8413273..00000000 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonAutoConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ejlchina.okhttps; - -public class JacksonAutoConfig implements OkHttps.Config { - - @Override - public void withConfig(HTTP.Builder builder) { - if (builder.getMsgConvertor() == null) { - builder.msgConvertor(new JacksonMsgConvertor()); - } - } - -} diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java index 25d896c0..abc78517 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java @@ -15,7 +15,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.type.CollectionType; -public class JacksonMsgConvertor implements MsgConvertor { +public class JacksonMsgConvertor implements MsgConvertor, ConvertProvider { private ObjectMapper objectMapper; @@ -99,6 +99,11 @@ public List toList(Class type, InputStream in) { } } + @Override + public MsgConvertor getConvertor() { + return new JacksonMsgConvertor(); + } + public ObjectMapper getObjectMapper() { return objectMapper; } diff --git a/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider b/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider new file mode 100644 index 00000000..ddfa7bde --- /dev/null +++ b/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.ConvertProvider @@ -0,0 +1 @@ +com.ejlchina.okhttps.JacksonMsgConvertor \ No newline at end of file diff --git a/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config b/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config deleted file mode 100644 index 1aca027c..00000000 --- a/okhttps-jackson/src/main/resources/META-INF/services/com.ejlchina.okhttps.OkHttps.Config +++ /dev/null @@ -1 +0,0 @@ -com.ejlchina.okhttps.JacksonAutoConfig \ No newline at end of file diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/Config.java b/okhttps/src/main/java/com/ejlchina/okhttps/Config.java new file mode 100644 index 00000000..71a803c7 --- /dev/null +++ b/okhttps/src/main/java/com/ejlchina/okhttps/Config.java @@ -0,0 +1,18 @@ +package com.ejlchina.okhttps; + +import java.util.ServiceLoader; + +/** + * OkHttps é…�置器 + */ +public interface Config { + + void with(HTTP.Builder builder); + + static void config(HTTP.Builder builder) { + for (Config config : ServiceLoader.load(Config.class)) { + config.with(builder); + } + } + +} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/Configurator.java b/okhttps/src/main/java/com/ejlchina/okhttps/Configurator.java deleted file mode 100644 index 54f954ad..00000000 --- a/okhttps/src/main/java/com/ejlchina/okhttps/Configurator.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.ejlchina.okhttps; - -import okhttp3.OkHttpClient.Builder; - -/** - * Http é…�置器 - * - */ -public interface Configurator { - - /** - * 使用 builder é…�ç½® HttpClient - * @param builder OkHttpClient 构建器 - */ - void config(Builder builder); - -} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/ConvertProvider.java b/okhttps/src/main/java/com/ejlchina/okhttps/ConvertProvider.java new file mode 100644 index 00000000..28dc47ba --- /dev/null +++ b/okhttps/src/main/java/com/ejlchina/okhttps/ConvertProvider.java @@ -0,0 +1,21 @@ +package com.ejlchina.okhttps; + +import java.util.ServiceLoader; + +/** + * MsgConvertor æ��供者 + */ +public interface ConvertProvider { + + MsgConvertor getConvertor(); + + static void inject(HTTP.Builder builder) { + for (ConvertProvider provider : ServiceLoader.load(ConvertProvider.class)) { + MsgConvertor convertor = provider.getConvertor(); + if (convertor != null) { + builder.msgConvertor(convertor); + } + } + } + +} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index d70d99d4..5d1ccdc6 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -88,6 +88,21 @@ static Builder builder() { } + /** + * Http é…�置器 + * + */ + interface OkConfig { + + /** + * 使用 builder é…�ç½® HttpClient + * @param builder OkHttpClient 构建器 + */ + void config(OkHttpClient.Builder builder); + + } + + class Builder { private OkHttpClient okClient; @@ -96,7 +111,7 @@ class Builder { private Map mediaTypes; - private Configurator configurator; + private OkConfig config; private Executor mainExecutor; @@ -151,11 +166,11 @@ public Builder(HttpClient hc) { /** * é…�ç½® OkHttpClient * - * @param configurator é…�置器 + * @param config é…�置器 * @return Builder */ - public Builder config(Configurator configurator) { - this.configurator = configurator; + public Builder config(OkConfig config) { + this.config = config; return this; } @@ -298,10 +313,10 @@ public Builder msgConvertor(MsgConvertor msgConvertor) { * @return HTTP */ public HTTP build() { - if (configurator != null || okClient == null) { + if (config != null || okClient == null) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); - if (configurator != null) { - configurator.config(builder); + if (config != null) { + config.config(builder); } okClient = builder.build(); } @@ -320,10 +335,6 @@ public Map getMediaTypes() { return mediaTypes; } - public Configurator getConfigurator() { - return configurator; - } - public Executor getMainExecutor() { return mainExecutor; } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java index 6862d111..74bd8a5b 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -10,6 +10,8 @@ import okhttp3.WebSocket; import okhttp3.WebSocketListener; +import java.util.ServiceLoader; + /** * Http 工具类(å�¯ä¾›ç¬¬ä¸‰æ–¹åº“,é�žä¸»åº”用使用) * 若需è¦�é…�置,请使用 {@link OkHttps } ç±» @@ -21,7 +23,6 @@ public class HttpUtils { private static HTTP http; - /** * é…�ç½®HttpUtilsæŒ�有的HTTP实例(ä¸�调用此方法å‰�默认使用一个没有没有ç»�过任何é…�置的HTTP懒实例) * @param http HTTP实例 @@ -40,32 +41,12 @@ static synchronized HTTP getHttp() { if (http != null) { return http; } - http = HTTP.builder().msgConvertor(findJsonService(new String[] { - "com.ejlchina.okhttps.GsonService", - "com.ejlchina.okhttps.FastJsonService", - "com.ejlchina.okhttps.JacksonService" - }, 0)).build(); + HTTP.Builder builder = HTTP.builder(); + ConvertProvider.inject(builder); + http = builder.build(); return http; } - static private MsgConvertor findJsonService(String[] classes, int index) { - if (index >= classes.length) { - return null; - } - Class clazz = null; - try { - clazz = Class.forName(classes[0]); - } catch (Exception ignore) {} - if (clazz == null || !MsgConvertor.class.isAssignableFrom(clazz)) { - return findJsonService(classes, index + 1); - } - try { - return (MsgConvertor) clazz.getDeclaredConstructor().newInstance(); - } catch (Exception ignore) { - return null; - } - } - /** * 异步请求 * @param url 请求地å�€ diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java index b581bb21..3d24a4f2 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java @@ -16,11 +16,6 @@ public final class OkHttps { private OkHttps() {} - public interface Config { - - void withConfig(HTTP.Builder builder); - - } private static HTTP http; @@ -29,9 +24,8 @@ static synchronized HTTP getHttp() { return http; } HTTP.Builder builder = HTTP.builder(); - for (Config config : ServiceLoader.load(Config.class)) { - config.withConfig(builder); - } + ConvertProvider.inject(builder); + Config.config(builder); http = builder.build(); return http; } From 32f002dc980e9362943c8a13488295cf1cff42cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 11:00:58 +0800 Subject: [PATCH 253/924] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ejlchina/okhttps/HttpTask.java | 6 +++--- .../ejlchina/okhttps/internal/AbstractBody.java | 16 ++++++++-------- .../ejlchina/okhttps/internal/TaskExecutor.java | 4 ++-- .../ejlchina/okhttps/internal/WebSocketTask.java | 16 +++++++--------- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index d1354408..6c656ce7 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -420,11 +420,11 @@ public C setRequestJson(Object json, String dateFormat) { requestJson = json.toString(); } else if (dateFormat != null) { requestJson = httpClient.getExecutor() - .jsonServiceNotNull() + .convertor() .serialize(json, dateFormat); } else { requestJson = httpClient.getExecutor() - .jsonServiceNotNull() + .convertor() .serialize(json); } } @@ -656,7 +656,7 @@ protected State toState(IOException e, boolean sync) { private RequestBody buildRequestBody() { if (jsonParams != null) { - requestJson = httpClient.getExecutor().jsonServiceNotNull() + requestJson = httpClient.getExecutor().convertor() .serialize(jsonParams); } if (files != null) { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java index 82378892..f7007012 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java @@ -21,33 +21,33 @@ public AbstractBody(TaskExecutor taskExecutor) { public Mapper toMapper() { if (taskExecutor == null) { - throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); + throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Mapper 转æ�¢ï¼�"); } - return taskExecutor.jsonServiceNotNull().toMapper(toByteStream()); + return taskExecutor.convertor().toMapper(toByteStream()); } public Array toArray() { if (taskExecutor == null) { - throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); + throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Array 转æ�¢ï¼�"); } - return taskExecutor.jsonServiceNotNull().toArray(toByteStream()); + return taskExecutor.convertor().toArray(toByteStream()); } public T toBean(Class type) { if (taskExecutor == null) { - throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); + throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Bean 转æ�¢ï¼�"); } - return taskExecutor.jsonServiceNotNull().toBean(type, toByteStream()); + return taskExecutor.convertor().toBean(type, toByteStream()); } public List toList(Class type) { if (taskExecutor == null) { - throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Json 转æ�¢ï¼�"); + throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š List 转æ�¢ï¼�"); } - return taskExecutor.jsonServiceNotNull().toList(type, toByteStream()); + return taskExecutor.convertor().toList(type, toByteStream()); } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 3c1404ff..8e5b0f0b 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -99,11 +99,11 @@ public void executeOnComplete(HttpTask task, OnCallback onComplete, St } } - public MsgConvertor jsonServiceNotNull() { + public MsgConvertor convertor() { if (msgConvertor != null) { return msgConvertor; } - throw new IllegalStateException("没有设置 JsonService,ä¸�å�¯å�š Json æ“�作ï¼�"); + throw new IllegalStateException("没有设置 MsgConvertor,ä¸�å�¯å�šè½¬æ�¢æ“�作ï¼�"); } /** diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 1eab9f2f..895def2e 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -116,7 +116,7 @@ static class WebSocketImpl implements WebSocket { okhttp3.WebSocket webSocket; - List queues = new ArrayList<>(); + final List queues = new ArrayList<>(); TaskExecutor taskExecutor; @@ -170,12 +170,12 @@ public boolean send(ByteString bytes) { @Override public boolean send(Object bean) { - return send(taskExecutor.jsonServiceNotNull().serialize(bean)); + return send(taskExecutor.convertor().serialize(bean)); } @Override public boolean send(Object bean, String dateFormat) { - return send(taskExecutor.jsonServiceNotNull().serialize(bean, dateFormat)); + return send(taskExecutor.convertor().serialize(bean, dateFormat)); } @Override @@ -193,12 +193,10 @@ void queueMsgToSend(Object msg) { return; } synchronized (queues) { - if (queues != null) { - queues.add(msg); - } else if (webSocket != null) { + if (webSocket != null) { send(webSocket, msg); } else { - throw new IllegalStateException(); + queues.add(msg); } } } @@ -209,7 +207,7 @@ void setWebSocket(okhttp3.WebSocket webSocket) { send(webSocket, msg); } this.webSocket = webSocket; - queues = null; + queues.clear(); } } @@ -226,7 +224,7 @@ boolean send(okhttp3.WebSocket webSocket, Object msg) { if (msg instanceof byte[]) { return webSocket.send(ByteString.of((byte[]) msg)); } - return webSocket.send(taskExecutor.jsonServiceNotNull().serialize(msg)); + return webSocket.send(taskExecutor.convertor().serialize(msg)); } } From 8cbae3757b8039152b56bc91b89fdbce4602321b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 11:13:24 +0800 Subject: [PATCH 254/924] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20patch=20=E4=BE=BF?= =?UTF-8?q?=E6=8D=B7=E8=AF=B7=E6=B1=82=E6=96=B9=E6=B3=95=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=20restfull=20=E9=87=8A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/internal/AsyncHttpTask.java | 16 ++++++++++++---- .../okhttps/internal/SyncHttpTask.java | 18 +++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index 8fd8c0ec..f7f228d7 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -70,7 +70,7 @@ public AsyncHttpTask setOnResponse(OnCallback onResponse) { } /** - * å�‘èµ· GET 请求 + * å�‘èµ· GET 请求(Rest:读å�–资æº�,幂等) * @return HttpCall */ public HttpCall get() { @@ -78,7 +78,7 @@ public HttpCall get() { } /** - * å�‘èµ· POST 请求 + * å�‘èµ· POST 请求(Rest:创建资æº�,é�žå¹‚等) * @return HttpCall */ public HttpCall post() { @@ -86,15 +86,23 @@ public HttpCall post() { } /** - * å�‘èµ· PUT 请求 + * å�‘èµ· PUT 请求(Rest:更新资æº�,幂等) * @return HttpCall */ public HttpCall put() { return request("PUT"); } + /** + * å�‘èµ· PATCH 请求(Rest:更新资æº�,部分更新,幂等) + * @return HttpCall + */ + public HttpCall patch() { + return request("PATCH"); + } + /** - * å�‘èµ· DELETE 请求 + * å�‘èµ· DELETE 请求(Rest:删除资æº�,幂等) * @return HttpCall */ public HttpCall delete() { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index f574880f..a1cfe03e 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -24,7 +24,7 @@ public SyncHttpTask(HttpClient client, String url) { } /** - * å�‘èµ· GET 请求 + * å�‘èµ· GET 请求(Rest:获å�–资æº�,幂等) * @return 请求结果 */ public HttpResult get() { @@ -32,7 +32,7 @@ public HttpResult get() { } /** - * å�‘èµ· POST 请求 + * å�‘èµ· POST 请求(Rest:创建资æº�,é�žå¹‚等) * @return 请求结果 */ public HttpResult post() { @@ -40,15 +40,23 @@ public HttpResult post() { } /** - * å�‘èµ· PUT 请求 + * å�‘èµ· PUT 请求(Rest:更新资æº�,幂等) * @return 请求结果 */ public HttpResult put() { return request("PUT"); } - + + /** + * å�‘èµ· PATCH 请求(Rest:更新资æº�,部分更新,幂等) + * @return HttpCall + */ + public HttpResult patch() { + return request("PATCH"); + } + /** - * å�‘èµ· DELETE 请求 + * å�‘èµ· DELETE 请求(Rest:删除资æº�,幂等) * @return 请求结果 */ public HttpResult delete() { From a911b426d3031172085fe18fc848f2e1f2a01794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 12:08:32 +0800 Subject: [PATCH 255/924] =?UTF-8?q?MsgConvertor=20=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20mediaType=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/FastjsonMsgConvertor.java | 5 +++ .../ejlchina/okhttps/GsonMsgConvertor.java | 15 +++++++-- .../ejlchina/okhttps/JacksonMsgConvertor.java | 23 +++++++++++-- .../java/com/ejlchina/okhttps/HttpTask.java | 5 ++- .../com/ejlchina/okhttps/MsgConvertor.java | 6 ++++ .../okhttps/internal/TaskExecutor.java | 32 ++++++++++++++----- 6 files changed, 69 insertions(+), 17 deletions(-) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java index d5290e4d..13d8cdca 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java @@ -23,6 +23,11 @@ public FastjsonMsgConvertor(Charset charset) { this.charset = charset; } + @Override + public String mediaType() { + return "application/json; charset=" + charset.displayName(); + } + @Override public Mapper toMapper(InputStream in) { return new FastjsonMapper(JSON.parseObject(toString(in))); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java index b4597263..a39dd25c 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java @@ -2,6 +2,8 @@ import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -14,13 +16,20 @@ public class GsonMsgConvertor implements MsgConvertor, ConvertProvider { private Gson gson; - + private Charset charset; + public GsonMsgConvertor() { - this(new Gson()); + this(new Gson(), StandardCharsets.UTF_8); } - public GsonMsgConvertor(Gson gson) { + public GsonMsgConvertor(Gson gson, Charset charset) { this.gson = gson; + this.charset = charset; + } + + @Override + public String mediaType() { + return "application/json; charset=" + charset.displayName(); } @Override diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java index abc78517..6916c8f7 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java @@ -2,6 +2,8 @@ import java.io.IOException; import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; @@ -18,13 +20,21 @@ public class JacksonMsgConvertor implements MsgConvertor, ConvertProvider { private ObjectMapper objectMapper; - + + private Charset charset; + public JacksonMsgConvertor() { - this(new ObjectMapper()); + this(new ObjectMapper(), StandardCharsets.UTF_8); } - public JacksonMsgConvertor(ObjectMapper objectMapper) { + public JacksonMsgConvertor(ObjectMapper objectMapper, Charset charset) { this.objectMapper = objectMapper; + this.charset = charset; + } + + @Override + public String mediaType() { + return "application/json; charset=" + charset.displayName(); } @Override @@ -112,4 +122,11 @@ public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } + public Charset getCharset() { + return charset; + } + + public void setCharset(Charset charset) { + this.charset = charset; + } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 6c656ce7..5a5c6a97 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -36,8 +36,7 @@ @SuppressWarnings("unchecked") public abstract class HttpTask> implements Cancelable { - private static final MediaType TYPE_JSON = MediaType.parse("application/json; charset=utf-8"); - private static String PATH_PARAM_REGEX = "[A-Za-z0-9_\\-/]*\\{[A-Za-z0-9_\\-]+\\}[A-Za-z0-9_\\-/]*"; + private static final String PATH_PARAM_REGEX = "[A-Za-z0-9_\\-/]*\\{[A-Za-z0-9_\\-]+\\}[A-Za-z0-9_\\-/]*"; protected HttpClient httpClient; protected boolean nothrow; @@ -680,7 +679,7 @@ private RequestBody buildRequestBody() { } return builder.build(); } else if (requestJson != null) { - return RequestBody.create(TYPE_JSON, requestJson); + return RequestBody.create(httpClient.getExecutor().getMapperMediaType(), requestJson); } else { FormBody.Builder builder = new FormBody.Builder(); if (bodyParams != null) { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java index 2bea803b..b937e71f 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java @@ -8,6 +8,12 @@ */ public interface MsgConvertor { + /** + * 消æ�¯çš„媒体类型 + * @return 媒体类型 + */ + String mediaType(); + /** * è§£æž� Mapper * @param in JSON 输入æµ� diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 8e5b0f0b..e0db7f70 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -14,16 +14,17 @@ import com.ejlchina.okhttps.OnCallback; import com.ejlchina.okhttps.TaskListener; import com.ejlchina.okhttps.HttpResult.State; +import okhttp3.MediaType; public class TaskExecutor { - Executor ioExecutor; - Executor mainExecutor; - DownListener downloadListener; - TaskListener responseListener; - TaskListener exceptionListener; - TaskListener completeListener; - MsgConvertor msgConvertor; + private Executor ioExecutor; + private Executor mainExecutor; + private DownListener downloadListener; + private TaskListener responseListener; + private TaskListener exceptionListener; + private TaskListener completeListener; + private MsgConvertor msgConvertor; public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, TaskListener responseListener, TaskListener exceptionListener, @@ -105,7 +106,22 @@ public MsgConvertor convertor() { } throw new IllegalStateException("没有设置 MsgConvertor,ä¸�å�¯å�šè½¬æ�¢æ“�作ï¼�"); } - + + private MediaType mapperMediaType; + + public MediaType getMapperMediaType() { + if (mapperMediaType == null && msgConvertor != null) { + String mediaType = msgConvertor.mediaType(); + if (mediaType != null) { + mapperMediaType = MediaType.parse(mediaType); + } + } + if (mapperMediaType == null) { + MediaType.parse("application/json; charset=utf-8"); + } + return mapperMediaType; + } + /** * 关闭线程池 * @since OkHttps V1.0.2 From 5bbd058d1c6fd940c97568dca9c56f62ea66104c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 14:16:58 +0800 Subject: [PATCH 256/924] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20HTTP.Builder#chars?= =?UTF-8?q?et(Charset=20charset)=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/FastjsonMsgConvertor.java | 8 +-- .../ejlchina/okhttps/GsonMsgConvertor.java | 8 +-- .../ejlchina/okhttps/JacksonMsgConvertor.java | 9 +-- .../main/java/com/ejlchina/okhttps/HTTP.java | 53 ++++++++++++------ .../java/com/ejlchina/okhttps/HttpResult.java | 2 +- .../java/com/ejlchina/okhttps/HttpTask.java | 27 +++++---- .../java/com/ejlchina/okhttps/HttpUtils.java | 4 +- .../com/ejlchina/okhttps/MsgConvertor.java | 13 +++-- .../java/com/ejlchina/okhttps/OkHttps.java | 4 +- .../okhttps/internal/AsyncHttpTask.java | 4 +- .../ejlchina/okhttps/internal/HttpClient.java | 56 ++++++++++++------- .../okhttps/internal/SyncHttpTask.java | 2 +- .../okhttps/internal/TaskExecutor.java | 15 ----- 13 files changed, 114 insertions(+), 91 deletions(-) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java index 13d8cdca..dc36a7a1 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java @@ -39,13 +39,13 @@ public Array toArray(InputStream in) { } @Override - public String serialize(Object bean) { - return JSON.toJSONString(bean); + public byte[] serialize(Object bean) { + return JSON.toJSONString(bean).getBytes(charset); } @Override - public String serialize(Object bean, String dateFormat) { - return JSON.toJSONStringWithDateFormat(bean, dateFormat); + public byte[] serialize(Object bean, String dateFormat) { + return JSON.toJSONStringWithDateFormat(bean, dateFormat).getBytes(charset); } @Override diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java index a39dd25c..621ce9dd 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java @@ -43,13 +43,13 @@ public Array toArray(InputStream in) { } @Override - public String serialize(Object bean) { - return gson.toJson(bean); + public byte[] serialize(Object bean) { + return gson.toJson(bean).getBytes(charset); } @Override - public String serialize(Object bean, String dateFormat) { - return gson.newBuilder().setDateFormat(dateFormat).create().toJson(bean); + public byte[] serialize(Object bean, String dateFormat) { + return gson.newBuilder().setDateFormat(dateFormat).create().toJson(bean).getBytes(charset); } @Override diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java index 6916c8f7..1ae8579c 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java @@ -70,21 +70,22 @@ public Array toArray(InputStream in) { } @Override - public String serialize(Object bean) { + public byte[] serialize(Object bean) { try { - return objectMapper.writeValueAsString(bean); + objectMapper.writeValueAsBytes(bean); + return objectMapper.writeValueAsString(bean).getBytes(charset); } catch (JsonProcessingException e) { throw new HttpException("Java Bean [" + bean + "] Jackson åº�列化异常", e); } } @Override - public String serialize(Object bean, String dateFormat) { + public byte[] serialize(Object bean, String dateFormat) { ObjectMapper mapper = objectMapper.copy(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.setDateFormat(new SimpleDateFormat(dateFormat)); try { - return mapper.writeValueAsString(bean); + return mapper.writeValueAsString(bean).getBytes(charset); } catch (JsonProcessingException e) { throw new HttpException("Java Bean [" + bean + "] Jackson åº�列化异常", e); } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index 5d1ccdc6..5dd03323 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -6,6 +6,8 @@ import okhttp3.WebSocket; import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.Executor; @@ -71,7 +73,7 @@ public interface HTTP { * 获å�–任务执行器 * @return TaskExecutor */ - TaskExecutor getExecutor(); + TaskExecutor executor(); /** * 新的构建器 @@ -129,6 +131,8 @@ class Builder { private int preprocTimeoutTimes = 10; + private Charset charset = StandardCharsets.UTF_8; + public Builder() { mediaTypes = new HashMap<>(); mediaTypes.put("*", "application/octet-stream"); @@ -149,18 +153,19 @@ public Builder() { } public Builder(HttpClient hc) { - this.okClient = hc.getOkClient(); - this.baseUrl = hc.getBaseUrl(); - this.mediaTypes = hc.getMediaTypes(); + this.okClient = hc.okClient(); + this.baseUrl = hc.baseUrl(); + this.mediaTypes = hc.mediaTypes(); this.preprocessors = new ArrayList<>(); - Collections.addAll(this.preprocessors, hc.getPreprocessors()); - TaskExecutor executor = hc.getExecutor(); + Collections.addAll(this.preprocessors, hc.preprocessors()); + TaskExecutor executor = hc.executor(); this.downloadListener = executor.getDownloadListener(); this.responseListener = executor.getResponseListener(); this.exceptionListener = executor.getExceptionListener(); this.completeListener = executor.getCompleteListener(); this.msgConvertor = executor.getMsgConvertor(); - this.preprocTimeoutTimes = hc.getPreprocTimeoutTimes(); + this.preprocTimeoutTimes = hc.preprocTimeoutTimes(); + this.charset = hc.charset(); } /** @@ -308,6 +313,16 @@ public Builder msgConvertor(MsgConvertor msgConvertor) { return this; } + /** + * 设置编ç �æ ¼å¼� + * @param charset ç¼–ç � + * @return Builder + */ + public Builder charset(Charset charset) { + this.charset = charset; + return this; + } + /** * 构建 HTTP 实例 * @return HTTP @@ -323,11 +338,11 @@ public HTTP build() { return new HttpClient(this); } - public OkHttpClient getOkClient() { + public OkHttpClient okClient() { return okClient; } - public String getBaseUrl() { + public String baseUrl() { return baseUrl; } @@ -335,38 +350,42 @@ public Map getMediaTypes() { return mediaTypes; } - public Executor getMainExecutor() { + public Executor mainExecutor() { return mainExecutor; } - public List getPreprocessors() { + public List preprocessors() { return preprocessors; } - public DownListener getDownloadListener() { + public DownListener downloadListener() { return downloadListener; } - public TaskListener getResponseListener() { + public TaskListener responseListener() { return responseListener; } - public TaskListener getExceptionListener() { + public TaskListener exceptionListener() { return exceptionListener; } - public TaskListener getCompleteListener() { + public TaskListener completeListener() { return completeListener; } - public MsgConvertor getMsgConvertor() { + public MsgConvertor msgConvertor() { return msgConvertor; } - public int getPreprocTimeoutTimes() { + public int preprocTimeoutTimes() { return preprocTimeoutTimes; } + public Charset charset() { + return charset; + } + } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java index 74edfb21..0e331db2 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -33,7 +33,7 @@ static HttpResult of(Response response) { /** * 构造一个 HttpResult * @param response Response - * @param taskExecutor 任务执行器, å�¯é€šè¿‡æ–¹æ³• {@link HTTP#getExecutor()} 获得 + * @param taskExecutor 任务执行器, å�¯é€šè¿‡æ–¹æ³• {@link HTTP#executor()} 获得 * @return HttpResult */ static HttpResult of(Response response, TaskExecutor taskExecutor) { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 5a5c6a97..4e1907a4 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -50,7 +50,7 @@ public abstract class HttpTask> implements Cancelable { private Map bodyParams; private Map jsonParams; private Map files; - private String requestJson; + private byte[] requestJson; private OnCallback onProcess; private boolean pOnIO; private long stepBytes = 0; @@ -415,14 +415,16 @@ public C setRequestJson(Object json) { **/ public C setRequestJson(Object json, String dateFormat) { if (json != null) { - if (json instanceof String) { - requestJson = json.toString(); + if (json instanceof byte[]) { + requestJson = (byte[]) json; + } else if (json instanceof String) { + requestJson = json.toString().getBytes(httpClient.charset()); } else if (dateFormat != null) { - requestJson = httpClient.getExecutor() + requestJson = httpClient.executor() .convertor() .serialize(json, dateFormat); } else { - requestJson = httpClient.getExecutor() + requestJson = httpClient.executor() .convertor() .serialize(json); } @@ -596,7 +598,7 @@ protected Request prepareRequest(String method) { stepBytes = Process.DEFAULT_STEP_BYTES; } reqBody = new ProcessRequestBody(reqBody, onProcess, - httpClient.getExecutor().getExecutor(pOnIO), + httpClient.executor().getExecutor(pOnIO), contentLength, stepBytes); } } @@ -655,20 +657,21 @@ protected State toState(IOException e, boolean sync) { private RequestBody buildRequestBody() { if (jsonParams != null) { - requestJson = httpClient.getExecutor().convertor() + requestJson = httpClient.executor().convertor() .serialize(jsonParams); } if (files != null) { MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); if (bodyParams != null) { for (String name : bodyParams.keySet()) { - String value = bodyParams.get(name); - builder.addFormDataPart(name, value); + byte[] value = bodyParams.get(name).getBytes(httpClient.charset()); + RequestBody body = RequestBody.create(null, value); + builder.addPart(MultipartBody.Part.createFormData(name, null, body)); } } for (String name : files.keySet()) { FilePara file = files.get(name); - MediaType type = httpClient.getMediaType(file.type); + MediaType type = httpClient.mediaType(file.type); RequestBody bodyPart; if (file.file != null) { bodyPart = RequestBody.create(type, file.file); @@ -679,9 +682,9 @@ private RequestBody buildRequestBody() { } return builder.build(); } else if (requestJson != null) { - return RequestBody.create(httpClient.getExecutor().getMapperMediaType(), requestJson); + return RequestBody.create(httpClient.mapperType(), requestJson); } else { - FormBody.Builder builder = new FormBody.Builder(); + FormBody.Builder builder = new FormBody.Builder(httpClient.charset()); if (bodyParams != null) { for (String name : bodyParams.keySet()) { String value = bodyParams.get(name); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java index 74bd8a5b..d8db6a5a 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpUtils.java @@ -10,8 +10,6 @@ import okhttp3.WebSocket; import okhttp3.WebSocketListener; -import java.util.ServiceLoader; - /** * Http 工具类(å�¯ä¾›ç¬¬ä¸‰æ–¹åº“,é�žä¸»åº”用使用) * 若需è¦�é…�置,请使用 {@link OkHttps } ç±» @@ -115,7 +113,7 @@ public static WebSocket webSocket(Request request, WebSocketListener listener) { * @return TaskExecutor */ public static TaskExecutor getExecutor() { - return getHttp().getExecutor(); + return getHttp().executor(); } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java index b937e71f..508664e6 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java @@ -1,6 +1,7 @@ package com.ejlchina.okhttps; import java.io.InputStream; +import java.nio.charset.Charset; import java.util.List; /** @@ -29,19 +30,19 @@ public interface MsgConvertor { Array toArray(InputStream in); /** - * å°† Java 对象åº�列化为字符串 + * å°† Java 对象åº�列化为字节数组 * @param bean Java Bean - * @return 字符串 + * @return 字节数组 */ - String serialize(Object bean); + byte[] serialize(Object bean); /** - * å°† Java 对象åº�列化为字符串 + * å°† Java 对象åº�列化为字节数组 * @param bean Java Bean * @param dateFormat 日期类的处ç�†æ ¼å¼� - * @return 字符串 + * @return 字节数组 */ - String serialize(Object bean, String dateFormat); + byte[] serialize(Object bean, String dateFormat); /** * è§£æž� Java Bean diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java index 3d24a4f2..c52d77e8 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java @@ -6,8 +6,6 @@ import okhttp3.WebSocket; import okhttp3.WebSocketListener; -import java.util.ServiceLoader; - /** * OkHttps 工具类 * 支æŒ� SPI æ–¹å¼�é…�ç½® @@ -99,7 +97,7 @@ public static WebSocket webSocket(Request request, WebSocketListener listener) { * @return TaskExecutor */ public static TaskExecutor getExecutor() { - return getHttp().getExecutor(); + return getHttp().executor(); } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java index f7f228d7..78cabb14 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java @@ -234,7 +234,7 @@ public void onFailure(Call call, IOException error) { State state = toState(error, false); HttpResult result = new RealHttpResult(AsyncHttpTask.this, state, error); onCallback(httpCall, result, () -> { - TaskExecutor executor = httpClient.getExecutor(); + TaskExecutor executor = httpClient.executor(); executor.executeOnComplete(AsyncHttpTask.this, onComplete, state, cOnIO); if (!executor.executeOnException(AsyncHttpTask.this, onException, error, eOnIO) && !nothrow) { @@ -245,7 +245,7 @@ public void onFailure(Call call, IOException error) { @Override public void onResponse(Call call, Response response) throws IOException { - TaskExecutor executor = httpClient.getExecutor(); + TaskExecutor executor = httpClient.executor(); HttpResult result = new RealHttpResult(AsyncHttpTask.this, response, executor); onCallback(httpCall, result, () -> { executor.executeOnComplete(AsyncHttpTask.this, onComplete, State.RESPONSED, cOnIO); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 05ed17e7..480b3e13 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -1,11 +1,10 @@ package com.ejlchina.okhttps.internal; -import com.ejlchina.okhttps.Cancelable; -import com.ejlchina.okhttps.HTTP; -import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.Preprocessor; +import com.ejlchina.okhttps.*; import okhttp3.*; +import okhttp3.WebSocket; +import java.nio.charset.Charset; import java.util.*; @@ -25,18 +24,29 @@ public class HttpClient implements HTTP { final List tagTasks; // 最大预处ç�†æ—¶é—´å€�数(相对于普通请求的超时时间) final int preprocTimeoutTimes; + // ç¼–ç �æ ¼å¼� + final Charset charset; + // Mapper的媒体类型 + final MediaType mapperType; public HttpClient(Builder builder) { - this.okClient = builder.getOkClient(); - this.baseUrl = builder.getBaseUrl(); + this.okClient = builder.okClient(); + this.baseUrl = builder.baseUrl(); this.mediaTypes = builder.getMediaTypes(); + MsgConvertor convertor = builder.msgConvertor(); this.executor = new TaskExecutor(okClient.dispatcher().executorService(), - builder.getMainExecutor(), builder.getDownloadListener(), - builder.getResponseListener(), builder.getExceptionListener(), - builder.getCompleteListener(), builder.getMsgConvertor()); - this.preprocessors = builder.getPreprocessors().toArray(new Preprocessor[0]); - this.preprocTimeoutTimes = builder.getPreprocTimeoutTimes(); + builder.mainExecutor(), builder.downloadListener(), + builder.responseListener(), builder.exceptionListener(), + builder.completeListener(), convertor); + this.preprocessors = builder.preprocessors().toArray(new Preprocessor[0]); + this.preprocTimeoutTimes = builder.preprocTimeoutTimes(); + this.charset = builder.charset(); this.tagTasks = new LinkedList<>(); + String mediaType = convertor != null ? convertor.mediaType() : null; + if (mediaType == null) { + mediaType = "application/json"; + } + this.mapperType = MediaType.parse(mediaType + "; charset=" + charset.name()); } @Override @@ -96,7 +106,7 @@ public WebSocket webSocket(Request request, WebSocketListener listener) { return okClient.newWebSocket(request, listener); } - public OkHttpClient getOkClient() { + public OkHttpClient okClient() { return okClient; } @@ -159,7 +169,7 @@ public void setTag(String tag) { } - public MediaType getMediaType(String type) { + public MediaType mediaType(String type) { String mediaType = mediaTypes.get(type); if (mediaType != null) { return MediaType.parse(mediaType); @@ -168,7 +178,7 @@ public MediaType getMediaType(String type) { } @Override - public TaskExecutor getExecutor() { + public TaskExecutor executor() { return executor; } @@ -334,24 +344,32 @@ private String urlPath(String urlPath, boolean websocket) { return fullUrl; } - public String getBaseUrl() { + public String baseUrl() { return baseUrl; } - public Map getMediaTypes() { + public Map mediaTypes() { return mediaTypes; } - public Preprocessor[] getPreprocessors() { + public Preprocessor[] preprocessors() { return preprocessors; } - public List getTagTasks() { + public List tagTasks() { return tagTasks; } - public int getPreprocTimeoutTimes() { + public int preprocTimeoutTimes() { return preprocTimeoutTimes; } + public Charset charset() { + return charset; + } + + public MediaType mapperType() { + return mapperType; + } + } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java index a1cfe03e..f778d1fa 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/SyncHttpTask.java @@ -72,7 +72,7 @@ public HttpResult request(String method) { if (method == null || method.isEmpty()) { throw new IllegalArgumentException("HTTP 请求方法 method ä¸�å�¯ä¸ºç©ºï¼�"); } - RealHttpResult result = new RealHttpResult(this, httpClient.getExecutor()); + RealHttpResult result = new RealHttpResult(this, httpClient.executor()); SyncHttpCall httpCall = new SyncHttpCall(); // 注册标签任务 registeTagTask(httpCall); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index e0db7f70..859a40a9 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -107,21 +107,6 @@ public MsgConvertor convertor() { throw new IllegalStateException("没有设置 MsgConvertor,ä¸�å�¯å�šè½¬æ�¢æ“�作ï¼�"); } - private MediaType mapperMediaType; - - public MediaType getMapperMediaType() { - if (mapperMediaType == null && msgConvertor != null) { - String mediaType = msgConvertor.mediaType(); - if (mediaType != null) { - mapperMediaType = MediaType.parse(mediaType); - } - } - if (mapperMediaType == null) { - MediaType.parse("application/json; charset=utf-8"); - } - return mapperMediaType; - } - /** * 关闭线程池 * @since OkHttps V1.0.2 From 31de0dd7b0c3a87efe504071ade39847659fb071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 15:10:21 +0800 Subject: [PATCH 257/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 28 ++++----- .../com/ejlchina/okhttps/MsgConvertor.java | 18 ++++-- .../okhttps/internal/AbstractBody.java | 14 +++-- .../okhttps/internal/RealHttpResult.java | 10 ++- .../ejlchina/okhttps/internal/ResultBody.java | 63 ++++++++++++------- .../okhttps/internal/WebSocketTask.java | 18 ++++-- 6 files changed, 90 insertions(+), 61 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 4e1907a4..4b4f626c 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -7,6 +7,7 @@ import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; +import java.nio.charset.Charset; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -20,16 +21,10 @@ import com.ejlchina.okhttps.internal.ProcessRequestBody; import com.ejlchina.okhttps.internal.RealHttpResult; -import okhttp3.Call; -import okhttp3.FormBody; -import okhttp3.MediaType; -import okhttp3.MultipartBody; -import okhttp3.Request; -import okhttp3.RequestBody; +import okhttp3.*; import okhttp3.internal.Util; import okio.Buffer; - /** * Created by 周旭(Troy.Zhou) on 2020/3/11. */ @@ -420,13 +415,11 @@ public C setRequestJson(Object json, String dateFormat) { } else if (json instanceof String) { requestJson = json.toString().getBytes(httpClient.charset()); } else if (dateFormat != null) { - requestJson = httpClient.executor() - .convertor() - .serialize(json, dateFormat); + requestJson = httpClient.executor().convertor() + .serialize(json, dateFormat, httpClient.charset()); } else { - requestJson = httpClient.executor() - .convertor() - .serialize(json); + requestJson = httpClient.executor().convertor() + .serialize(json, httpClient.charset()); } } return (C) this; @@ -658,7 +651,7 @@ protected State toState(IOException e, boolean sync) { private RequestBody buildRequestBody() { if (jsonParams != null) { requestJson = httpClient.executor().convertor() - .serialize(jsonParams); + .serialize(jsonParams, httpClient.charset()); } if (files != null) { MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); @@ -796,4 +789,11 @@ protected HttpResult timeoutResult() { throw new HttpException(State.TIMEOUT, "执行超时"); } + public Charset charset(Response response) { + ResponseBody b = response.body(); + MediaType type = b != null ? b.contentType() : null; + Charset defaultCharset = httpClient.charset(); + return type != null ? type.charset(defaultCharset) : defaultCharset; + } + } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java index 508664e6..8d102f66 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java @@ -18,48 +18,54 @@ public interface MsgConvertor { /** * è§£æž� Mapper * @param in JSON 输入æµ� + * @param charset ç¼–ç �æ ¼å¼� * @return JsonObj */ - Mapper toMapper(InputStream in); + Mapper toMapper(InputStream in, Charset charset); /** * è§£æž� Array * @param in JSON 输入æµ� + * @param charset ç¼–ç �æ ¼å¼� * @return JsonArr */ - Array toArray(InputStream in); + Array toArray(InputStream in, Charset charset); /** * å°† Java 对象åº�列化为字节数组 * @param bean Java Bean + * @param charset ç¼–ç �æ ¼å¼� * @return 字节数组 */ - byte[] serialize(Object bean); + byte[] serialize(Object bean, Charset charset); /** * å°† Java 对象åº�列化为字节数组 * @param bean Java Bean * @param dateFormat 日期类的处ç�†æ ¼å¼� + * @param charset ç¼–ç �æ ¼å¼� * @return 字节数组 */ - byte[] serialize(Object bean, String dateFormat); + byte[] serialize(Object bean, String dateFormat, Charset charset); /** * è§£æž� Java Bean * @param 目标泛型 * @param type 目标类型 * @param in JSON 输入æµ� + * @param charset ç¼–ç �æ ¼å¼� * @return Java Bean */ - T toBean(Class type, InputStream in); + T toBean(Class type, InputStream in, Charset charset); /** * è§£æž�为 Java List * @param 目标泛型 * @param type 目标类型 * @param in JSON 输入æµ� + * @param charset ç¼–ç �æ ¼å¼� * @return Java List */ - List toList(Class type, InputStream in); + List toList(Class type, InputStream in, Charset charset); } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java index f7007012..271cf7a7 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java @@ -1,6 +1,7 @@ package com.ejlchina.okhttps.internal; import java.io.InputStream; +import java.nio.charset.Charset; import java.util.List; import com.ejlchina.okhttps.Array; @@ -10,10 +11,11 @@ public abstract class AbstractBody { protected TaskExecutor taskExecutor; + protected Charset charset; - - public AbstractBody(TaskExecutor taskExecutor) { + public AbstractBody(TaskExecutor taskExecutor, Charset charset) { this.taskExecutor = taskExecutor; + this.charset = charset; } public abstract InputStream toByteStream(); @@ -23,7 +25,7 @@ public Mapper toMapper() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Mapper 转æ�¢ï¼�"); } - return taskExecutor.convertor().toMapper(toByteStream()); + return taskExecutor.convertor().toMapper(toByteStream(), charset); } @@ -31,7 +33,7 @@ public Array toArray() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Array 转æ�¢ï¼�"); } - return taskExecutor.convertor().toArray(toByteStream()); + return taskExecutor.convertor().toArray(toByteStream(), charset); } @@ -39,7 +41,7 @@ public T toBean(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Bean 转æ�¢ï¼�"); } - return taskExecutor.convertor().toBean(type, toByteStream()); + return taskExecutor.convertor().toBean(type, toByteStream(), charset); } @@ -47,7 +49,7 @@ public List toList(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š List 转æ�¢ï¼�"); } - return taskExecutor.convertor().toList(type, toByteStream()); + return taskExecutor.convertor().toList(type, toByteStream(), charset); } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java index aa4974fc..89614bf9 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/RealHttpResult.java @@ -1,15 +1,14 @@ package com.ejlchina.okhttps.internal; -import java.io.IOException; -import java.util.Collections; -import java.util.List; - import com.ejlchina.okhttps.HttpResult; import com.ejlchina.okhttps.HttpTask; - import okhttp3.Headers; import okhttp3.Response; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + public class RealHttpResult implements HttpResult { @@ -111,7 +110,6 @@ public IOException getError() { public Response getResponse() { return response; } - @Override public String toString() { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java index 9bafee28..aa3d0eb6 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java @@ -1,17 +1,8 @@ package com.ejlchina.okhttps.internal; -import static java.nio.charset.StandardCharsets.UTF_8; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.net.HttpURLConnection; import java.net.URLDecoder; -import java.nio.charset.Charset; import com.ejlchina.okhttps.Download; import com.ejlchina.okhttps.HttpResult.Body; @@ -21,6 +12,7 @@ import okhttp3.MediaType; import okhttp3.Response; +import okhttp3.ResponseBody; import okio.Buffer; public class ResultBody extends AbstractBody implements Body { @@ -36,19 +28,29 @@ public class ResultBody extends AbstractBody implements Body { private byte[] data; ResultBody(HttpTask httpTask, Response response, TaskExecutor taskExecutor) { - super(taskExecutor); + super(taskExecutor, httpTask.charset(response)); this.httpTask = httpTask; this.response = response; } + + @Override public MediaType getContentType() { - return response.body().contentType(); + ResponseBody body = response.body(); + if (body != null) { + return body.contentType(); + } + return null; } @Override public long getContentLength() { - return response.body().contentLength(); + ResponseBody body = response.body(); + if (body != null) { + return body.contentLength(); + } + return 0; } @Override @@ -93,7 +95,12 @@ public InputStream toByteStream() { if (cached) { input = new ByteArrayInputStream(cacheBytes()); } else { - input = response.body().byteStream(); + ResponseBody body = response.body(); + if (body != null) { + input = body.byteStream(); + } else { + input = new ByteArrayInputStream(new byte[]{}); + } } if (onProcess != null) { long rangeStart = getRangeStart(); @@ -126,21 +133,27 @@ public Reader toCharStream() { if (cached || onProcess != null) { return new InputStreamReader(toByteStream()); } - return response.body().charStream(); + ResponseBody body = response.body(); + if (body != null) { + return body.charStream(); + } + return new CharArrayReader(new char[]{}); } - + @Override public String toString() { if (cached || onProcess != null) { - MediaType contentType = getContentType(); - Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8; return new String(toBytes(), charset); } try { - return response.body().string(); + ResponseBody body = response.body(); + if (body != null) { + return new String(body.bytes(), charset); + } } catch (IOException e) { throw new HttpException("报文体转化字符串出错", e); } + return null; } @Override @@ -231,11 +244,15 @@ private byte[] bodyToBytes() { buffer.close(); } } - try { - return response.body().bytes(); - } catch (IOException e) { - throw new HttpException("报文体转化字节数组出错", e); + ResponseBody body = response.body(); + if (body != null) { + try { + return body.bytes(); + } catch (IOException e) { + throw new HttpException("报文体转化字节数组出错", e); + } } + return new byte[]{}; } private long getRangeStart() { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 895def2e..d8b9809c 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -1,5 +1,7 @@ package com.ejlchina.okhttps.internal; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -35,7 +37,7 @@ public WebSocketTask(HttpClient httpClient, String url) { * @return WebSocket */ public WebSocket listen() { - WebSocketImpl socket = new WebSocketImpl(httpClient.executor); + WebSocketImpl socket = new WebSocketImpl(httpClient.executor, httpClient.charset); registeTagTask(socket); httpClient.preprocess(this, () -> { synchronized (socket) { @@ -119,9 +121,12 @@ static class WebSocketImpl implements WebSocket { final List queues = new ArrayList<>(); TaskExecutor taskExecutor; - - public WebSocketImpl(TaskExecutor taskExecutor) { + + Charset charset; + + public WebSocketImpl(TaskExecutor taskExecutor, Charset charset) { this.taskExecutor = taskExecutor; + this.charset = charset; } @Override @@ -170,12 +175,12 @@ public boolean send(ByteString bytes) { @Override public boolean send(Object bean) { - return send(taskExecutor.convertor().serialize(bean)); + return send(taskExecutor.convertor().serialize(bean, charset)); } @Override public boolean send(Object bean, String dateFormat) { - return send(taskExecutor.convertor().serialize(bean, dateFormat)); + return send(taskExecutor.convertor().serialize(bean, dateFormat, charset)); } @Override @@ -224,7 +229,8 @@ boolean send(okhttp3.WebSocket webSocket, Object msg) { if (msg instanceof byte[]) { return webSocket.send(ByteString.of((byte[]) msg)); } - return webSocket.send(taskExecutor.convertor().serialize(msg)); + byte[] bytes = taskExecutor.convertor().serialize(msg, charset); + return webSocket.send(new String(bytes, StandardCharsets.UTF_8)); } } From 24053c7c7b90c1eebc22f40abcbc5c088d2375fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 15:12:58 +0800 Subject: [PATCH 258/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ejlchina/okhttps/internal/ResultBody.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java index aa3d0eb6..dddb0f59 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java @@ -234,14 +234,12 @@ private byte[] cacheBytes() { private byte[] bodyToBytes() { if (onProcess != null) { - Buffer buffer = new Buffer(); - try { + try (Buffer buffer = new Buffer()) { return buffer.readFrom(toByteStream()).readByteArray(); } catch (IOException e) { throw new HttpException("报文体转化字节数组出错", e); } finally { response.close(); - buffer.close(); } } ResponseBody body = response.body(); From 0001d6ab8e5a7b0f7b5095f9669864f057206c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 15:22:37 +0800 Subject: [PATCH 259/924] =?UTF-8?q?=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/FastjsonMsgConvertor.java | 52 ++++++------------- .../ejlchina/okhttps/GsonMsgConvertor.java | 20 ++++--- .../ejlchina/okhttps/JacksonMsgConvertor.java | 28 ++++------ 3 files changed, 34 insertions(+), 66 deletions(-) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java index dc36a7a1..df74d6f4 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java @@ -1,61 +1,49 @@ package com.ejlchina.okhttps; +import com.alibaba.fastjson.JSON; +import com.ejlchina.okhttps.internal.HttpException; +import okio.Okio; + import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.util.List; -import com.alibaba.fastjson.JSON; -import com.ejlchina.okhttps.internal.HttpException; - -import okio.Okio; - public class FastjsonMsgConvertor implements MsgConvertor, ConvertProvider { - private Charset charset; - - public FastjsonMsgConvertor() { - this(StandardCharsets.UTF_8); - } - - public FastjsonMsgConvertor(Charset charset) { - this.charset = charset; - } - @Override public String mediaType() { - return "application/json; charset=" + charset.displayName(); + return "application/json"; } @Override - public Mapper toMapper(InputStream in) { - return new FastjsonMapper(JSON.parseObject(toString(in))); + public Mapper toMapper(InputStream in, Charset charset) { + return new FastjsonMapper(JSON.parseObject(toString(in, charset))); } @Override - public Array toArray(InputStream in) { - return new FastjsonArray(JSON.parseArray(toString(in))); + public Array toArray(InputStream in, Charset charset) { + return new FastjsonArray(JSON.parseArray(toString(in, charset))); } @Override - public byte[] serialize(Object bean) { + public byte[] serialize(Object bean, Charset charset) { return JSON.toJSONString(bean).getBytes(charset); } @Override - public byte[] serialize(Object bean, String dateFormat) { + public byte[] serialize(Object bean, String dateFormat, Charset charset) { return JSON.toJSONStringWithDateFormat(bean, dateFormat).getBytes(charset); } @Override - public T toBean(Class type, InputStream in) { - return JSON.parseObject(toString(in), type); + public T toBean(Class type, InputStream in, Charset charset) { + return JSON.parseObject(toString(in, charset), type); } @Override - public List toList(Class type, InputStream in) { - return JSON.parseArray(toString(in), type); + public List toList(Class type, InputStream in, Charset charset) { + return JSON.parseArray(toString(in, charset), type); } @Override @@ -63,7 +51,7 @@ public MsgConvertor getConvertor() { return new FastjsonMsgConvertor(); } - private String toString(InputStream in) { + private String toString(InputStream in, Charset charset) { try { return Okio.buffer(Okio.source(in)).readString(charset); } catch (IOException e) { @@ -71,12 +59,4 @@ private String toString(InputStream in) { } } - public Charset getCharset() { - return charset; - } - - public void setCharset(Charset charset) { - this.charset = charset; - } - } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java index 621ce9dd..39943604 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java @@ -16,49 +16,47 @@ public class GsonMsgConvertor implements MsgConvertor, ConvertProvider { private Gson gson; - private Charset charset; public GsonMsgConvertor() { - this(new Gson(), StandardCharsets.UTF_8); + this(new Gson()); } - public GsonMsgConvertor(Gson gson, Charset charset) { + public GsonMsgConvertor(Gson gson) { this.gson = gson; - this.charset = charset; } @Override public String mediaType() { - return "application/json; charset=" + charset.displayName(); + return "application/json"; } @Override - public Mapper toMapper(InputStream in) { + public Mapper toMapper(InputStream in, Charset charset) { return new GsonMapper(gson.fromJson(new InputStreamReader(in), JsonObject.class)); } @Override - public Array toArray(InputStream in) { + public Array toArray(InputStream in, Charset charset) { return new GsonArray(gson.fromJson(new InputStreamReader(in), JsonArray.class)); } @Override - public byte[] serialize(Object bean) { + public byte[] serialize(Object bean, Charset charset) { return gson.toJson(bean).getBytes(charset); } @Override - public byte[] serialize(Object bean, String dateFormat) { + public byte[] serialize(Object bean, String dateFormat, Charset charset) { return gson.newBuilder().setDateFormat(dateFormat).create().toJson(bean).getBytes(charset); } @Override - public T toBean(Class type, InputStream in) { + public T toBean(Class type, InputStream in, Charset charset) { return gson.fromJson(new InputStreamReader(in), type); } @Override - public List toList(Class type, InputStream in) { + public List toList(Class type, InputStream in, Charset charset) { T[] beans = gson.fromJson(new InputStreamReader(in), TypeToken.getArray(type).getType()); List list = new ArrayList<>(); Collections.addAll(list, beans); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java index 1ae8579c..85053eb3 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java @@ -21,24 +21,21 @@ public class JacksonMsgConvertor implements MsgConvertor, ConvertProvider { private ObjectMapper objectMapper; - private Charset charset; - public JacksonMsgConvertor() { - this(new ObjectMapper(), StandardCharsets.UTF_8); + this(new ObjectMapper()); } - public JacksonMsgConvertor(ObjectMapper objectMapper, Charset charset) { + public JacksonMsgConvertor(ObjectMapper objectMapper) { this.objectMapper = objectMapper; - this.charset = charset; } @Override public String mediaType() { - return "application/json; charset=" + charset.displayName(); + return "application/json"; } @Override - public Mapper toMapper(InputStream in) { + public Mapper toMapper(InputStream in, Charset charset) { try { JsonNode json = objectMapper.readTree(in); if (json.isObject()) { @@ -54,7 +51,7 @@ public Mapper toMapper(InputStream in) { } @Override - public Array toArray(InputStream in) { + public Array toArray(InputStream in, Charset charset) { try { JsonNode json = objectMapper.readTree(in); if (json.isArray()) { @@ -70,7 +67,7 @@ public Array toArray(InputStream in) { } @Override - public byte[] serialize(Object bean) { + public byte[] serialize(Object bean, Charset charset) { try { objectMapper.writeValueAsBytes(bean); return objectMapper.writeValueAsString(bean).getBytes(charset); @@ -80,7 +77,7 @@ public byte[] serialize(Object bean) { } @Override - public byte[] serialize(Object bean, String dateFormat) { + public byte[] serialize(Object bean, String dateFormat, Charset charset) { ObjectMapper mapper = objectMapper.copy(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.setDateFormat(new SimpleDateFormat(dateFormat)); @@ -92,7 +89,7 @@ public byte[] serialize(Object bean, String dateFormat) { } @Override - public T toBean(Class type, InputStream in) { + public T toBean(Class type, InputStream in, Charset charset) { try { return objectMapper.readValue(in, type); } catch (IOException e) { @@ -101,7 +98,7 @@ public T toBean(Class type, InputStream in) { } @Override - public List toList(Class type, InputStream in) { + public List toList(Class type, InputStream in, Charset charset) { CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type); try { return objectMapper.readValue(in, javaType); @@ -123,11 +120,4 @@ public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } - public Charset getCharset() { - return charset; - } - - public void setCharset(Charset charset) { - this.charset = charset; - } } From 276f0d255215dd7913c8c368bf4e64f0804752ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 15:24:15 +0800 Subject: [PATCH 260/924] . --- .../src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java index 85053eb3..648321b7 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java @@ -69,7 +69,6 @@ public Array toArray(InputStream in, Charset charset) { @Override public byte[] serialize(Object bean, Charset charset) { try { - objectMapper.writeValueAsBytes(bean); return objectMapper.writeValueAsString(bean).getBytes(charset); } catch (JsonProcessingException e) { throw new HttpException("Java Bean [" + bean + "] Jackson åº�列化异常", e); From 25f92fee224eccef18226610a32baa610329b7d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 15:31:53 +0800 Subject: [PATCH 261/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java | 1 - .../main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java | 1 - okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java index 39943604..9ef63e93 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java @@ -3,7 +3,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java index 648321b7..af677f6e 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index 5dd03323..db6345a4 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -314,11 +314,11 @@ public Builder msgConvertor(MsgConvertor msgConvertor) { } /** - * 设置编ç �æ ¼å¼� + * 设置默认编ç �æ ¼å¼� * @param charset ç¼–ç � * @return Builder */ - public Builder charset(Charset charset) { + public Builder defaultCharset(Charset charset) { this.charset = charset; return this; } From e4addb1ca8cb025bcbfd024a5d710164ef5355a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 21:07:38 +0800 Subject: [PATCH 262/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../okhttps/FastjsonMsgConvertor.java | 17 ++++++++--- .../ejlchina/okhttps/GsonMsgConvertor.java | 18 +++++++++--- .../ejlchina/okhttps/JacksonMsgConvertor.java | 28 +++++++++++-------- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java index df74d6f4..e226c5f4 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java @@ -27,13 +27,22 @@ public Array toArray(InputStream in, Charset charset) { } @Override - public byte[] serialize(Object bean, Charset charset) { - return JSON.toJSONString(bean).getBytes(charset); + public byte[] serialize(Object object, Charset charset) { + return serialize(object, null, charset); } @Override - public byte[] serialize(Object bean, String dateFormat, Charset charset) { - return JSON.toJSONStringWithDateFormat(bean, dateFormat).getBytes(charset); + public byte[] serialize(Object object, String dateFormat, Charset charset) { + if (object instanceof byte[]) { + return (byte[]) object; + } + if (object instanceof String) { + return object.toString().getBytes(charset); + } + if (dateFormat != null) { + return JSON.toJSONStringWithDateFormat(object, dateFormat).getBytes(charset); + } + return JSON.toJSONString(object).getBytes(charset); } @Override diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java index 9ef63e93..045c0096 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java @@ -40,13 +40,23 @@ public Array toArray(InputStream in, Charset charset) { } @Override - public byte[] serialize(Object bean, Charset charset) { - return gson.toJson(bean).getBytes(charset); + public byte[] serialize(Object object, Charset charset) { + return serialize(object, null, charset); } @Override - public byte[] serialize(Object bean, String dateFormat, Charset charset) { - return gson.newBuilder().setDateFormat(dateFormat).create().toJson(bean).getBytes(charset); + public byte[] serialize(Object object, String dateFormat, Charset charset) { + if (object instanceof byte[]) { + return (byte[]) object; + } + if (object instanceof String) { + return object.toString().getBytes(charset); + } + Gson gson = this.gson; + if (dateFormat != null) { + gson = gson.newBuilder().setDateFormat(dateFormat).create(); + } + return gson.toJson(object).getBytes(charset); } @Override diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java index af677f6e..f9827d81 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java @@ -66,23 +66,27 @@ public Array toArray(InputStream in, Charset charset) { } @Override - public byte[] serialize(Object bean, Charset charset) { - try { - return objectMapper.writeValueAsString(bean).getBytes(charset); - } catch (JsonProcessingException e) { - throw new HttpException("Java Bean [" + bean + "] Jackson åº�列化异常", e); - } + public byte[] serialize(Object object, Charset charset) { + return serialize(object, null, charset); } @Override - public byte[] serialize(Object bean, String dateFormat, Charset charset) { - ObjectMapper mapper = objectMapper.copy(); - mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - mapper.setDateFormat(new SimpleDateFormat(dateFormat)); + public byte[] serialize(Object object, String dateFormat, Charset charset) { + if (object instanceof byte[]) { + return (byte[]) object; + } + if (object instanceof String) { + return object.toString().getBytes(charset); + } + ObjectMapper mapper = objectMapper; + if (dateFormat != null) { + mapper = mapper.copy().configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) + .setDateFormat(new SimpleDateFormat(dateFormat)); + } try { - return mapper.writeValueAsString(bean).getBytes(charset); + return mapper.writeValueAsString(object).getBytes(charset); } catch (JsonProcessingException e) { - throw new HttpException("Java Bean [" + bean + "] Jackson åº�列化异常", e); + throw new HttpException("Java Bean [" + object + "] Jackson åº�列化异常", e); } } From 0ac98f1db2608bd1c84ed002dfddca76be3707c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 21:21:27 +0800 Subject: [PATCH 263/924] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ejlchina/okhttps/ConvertProvider.java | 3 +- .../main/java/com/ejlchina/okhttps/HTTP.java | 64 +++- .../java/com/ejlchina/okhttps/HttpTask.java | 307 ++++++++++++------ .../com/ejlchina/okhttps/MsgConvertor.java | 74 ++++- .../ejlchina/okhttps/internal/HttpClient.java | 20 +- .../okhttps/internal/TaskExecutor.java | 62 +++- 6 files changed, 386 insertions(+), 144 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/ConvertProvider.java b/okhttps/src/main/java/com/ejlchina/okhttps/ConvertProvider.java index 28dc47ba..1bead6a4 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/ConvertProvider.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/ConvertProvider.java @@ -13,7 +13,8 @@ static void inject(HTTP.Builder builder) { for (ConvertProvider provider : ServiceLoader.load(ConvertProvider.class)) { MsgConvertor convertor = provider.getConvertor(); if (convertor != null) { - builder.msgConvertor(convertor); + builder.addMsgConvertor(new MsgConvertor.FormMsgConvertor(convertor)); + builder.addMsgConvertor(convertor); } } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index db6345a4..73194ba9 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -127,12 +127,14 @@ class Builder { private TaskListener completeListener; - private MsgConvertor msgConvertor; + private List msgConvertors; private int preprocTimeoutTimes = 10; private Charset charset = StandardCharsets.UTF_8; + private String bodyType = "json"; + public Builder() { mediaTypes = new HashMap<>(); mediaTypes.put("*", "application/octet-stream"); @@ -150,6 +152,7 @@ public Builder() { mediaTypes.put("pdf", "application/pdf"); mediaTypes.put("html", "text/html"); preprocessors = new ArrayList<>(); + msgConvertors = new ArrayList<>(); } public Builder(HttpClient hc) { @@ -163,9 +166,11 @@ public Builder(HttpClient hc) { this.responseListener = executor.getResponseListener(); this.exceptionListener = executor.getExceptionListener(); this.completeListener = executor.getCompleteListener(); - this.msgConvertor = executor.getMsgConvertor(); + this.msgConvertors = new ArrayList<>(); + Collections.addAll(this.msgConvertors, executor.getMsgConvertors()); this.preprocTimeoutTimes = hc.preprocTimeoutTimes(); this.charset = hc.charset(); + this.bodyType = hc.bodyType(); } /** @@ -197,7 +202,9 @@ public Builder baseUrl(String baseUrl) { * @return Builder */ public Builder mediaTypes(Map mediaTypes) { - this.mediaTypes.putAll(mediaTypes); + if (mediaTypes != null) { + this.mediaTypes.putAll(mediaTypes); + } return this; } @@ -209,7 +216,9 @@ public Builder mediaTypes(Map mediaTypes) { * @return Builder */ public Builder mediaTypes(String key, String value) { - this.mediaTypes.put(key, value); + if (key != null && value != null) { + this.mediaTypes.put(key, value); + } return this; } @@ -231,7 +240,9 @@ public Builder callbackExecutor(Executor executor) { * @return Builder */ public Builder addPreprocessor(Preprocessor preprocessor) { - preprocessors.add(preprocessor); + if (preprocessor != null) { + preprocessors.add(preprocessor); + } return this; } @@ -242,7 +253,9 @@ public Builder addPreprocessor(Preprocessor preprocessor) { * @return Builder */ public Builder addSerialPreprocessor(Preprocessor preprocessor) { - preprocessors.add(new HttpClient.SerialPreprocessor(preprocessor)); + if (preprocessor != null) { + preprocessors.add(new HttpClient.SerialPreprocessor(preprocessor)); + } return this; } @@ -304,22 +317,41 @@ public Builder downloadListener(DownListener listener) { } /** - * 设置消æ�¯è½¬æ�¢å™¨ + * @since 2.0.0 + * 添加消æ�¯è½¬æ�¢å™¨ * @param msgConvertor JSON æœ�务 * @return Builder */ - public Builder msgConvertor(MsgConvertor msgConvertor) { - this.msgConvertor = msgConvertor; + public Builder addMsgConvertor(MsgConvertor msgConvertor) { + if (msgConvertor != null) { + this.msgConvertors.add(msgConvertor); + } return this; } /** + * @since 2.0.0 * 设置默认编ç �æ ¼å¼� * @param charset ç¼–ç � * @return Builder */ public Builder defaultCharset(Charset charset) { - this.charset = charset; + if (charset != null) { + this.charset = charset; + } + return this; + } + + /** + * @since 2.0.0 + * 设置默认请求体类型 + * @param bodyType 请求体类型 + * @return Builder + */ + public Builder defaultBodyType(String bodyType) { + if (bodyType != null) { + this.bodyType = bodyType; + } return this; } @@ -354,8 +386,8 @@ public Executor mainExecutor() { return mainExecutor; } - public List preprocessors() { - return preprocessors; + public Preprocessor[] preprocessors() { + return preprocessors.toArray(new Preprocessor[0]); } public DownListener downloadListener() { @@ -374,8 +406,8 @@ public TaskListener completeListener() { return completeListener; } - public MsgConvertor msgConvertor() { - return msgConvertor; + public MsgConvertor[] msgConvertors() { + return msgConvertors.toArray(new MsgConvertor[0]); } public int preprocTimeoutTimes() { @@ -386,6 +418,10 @@ public Charset charset() { return charset; } + public String bodyType() { + return bodyType; + } + } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 4b4f626c..6fdf4b9a 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -9,17 +9,13 @@ import java.net.UnknownHostException; import java.nio.charset.Charset; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import com.ejlchina.okhttps.HttpResult.State; -import com.ejlchina.okhttps.internal.HttpClient; +import com.ejlchina.okhttps.internal.*; import com.ejlchina.okhttps.internal.HttpClient.TagTask; -import com.ejlchina.okhttps.internal.HttpException; -import com.ejlchina.okhttps.internal.ProcessRequestBody; -import com.ejlchina.okhttps.internal.RealHttpResult; import okhttp3.*; import okhttp3.internal.Util; @@ -43,9 +39,10 @@ public abstract class HttpTask> implements Cancelable { private Map pathParams; private Map urlParams; private Map bodyParams; - private Map jsonParams; private Map files; - private byte[] requestJson; + private Object requestBody; + private String dateFormat; + private String bodyType; private OnCallback onProcess; private boolean pOnIO; private long stepBytes = 0; @@ -55,14 +52,17 @@ public abstract class HttpTask> implements Cancelable { private TagTask tagTask; private Cancelable canceler; + private Charset charset; protected boolean skipPreproc = false; protected boolean skipSerialPreproc = false; - - + + public HttpTask(HttpClient httpClient, String url) { - this.httpClient = httpClient; this.urlPath = url; + this.httpClient = httpClient; + this.charset = httpClient.charset(); + this.bodyType = httpClient.bodyType(); } /** @@ -137,14 +137,19 @@ public C skipSerialPreproc() { this.skipSerialPreproc = true; return (C) this; } - + + @Deprecated + public C setTag(String tag) { + return tag(tag); + } + /** + * @since 2.2.0 * 为请求任务添加标签 - * v1.0.4 之å�Žï¼Œè‹¥ set 多次,标签将连接在一起 * @param tag 标签 * @return HttpTask 实例 */ - public C setTag(String tag) { + public C tag(String tag) { if (tag != null) { if (this.tag != null) { this.tag = this.tag + "." + tag; @@ -155,7 +160,33 @@ public C setTag(String tag) { } return (C) this; } - + + /** + * @since 2.0.0 + * 设置该请求的编ç �æ ¼å¼� + * @param charset ç¼–ç �æ ¼å¼� + * @return HttpTask 实例 + */ + public C charset(Charset charset) { + if (charset != null) { + this.charset = charset; + } + return (C) this; + } + + /** + * @since 2.0.0 + * 设置请求体的类型,如:formã€�jsonã€�xmlã€�protobuf 等,默认为 form + * @param type 请求类型 + * @return HttpTask 实例 + */ + public C bodyType(String type) { + if (type != null) { + this.bodyType = type; + } + return (C) this; + } + /** * 下一个回调在IO线程执行 * @return HttpTask 实例 @@ -261,13 +292,18 @@ public C setStepRate(double stepRate) { return (C) this; } + @Deprecated + public C addPathParam(String name, Object value) { + return addPathPara(name, value); + } + /** * 路径å�‚数:替æ�¢URL里的{name} * @param name å�‚æ•°å�� * @param value å�‚数值 * @return HttpTask 实例 **/ - public C addPathParam(String name, Object value) { + public C addPathPara(String name, Object value) { if (name != null && value != null) { if (pathParams == null) { pathParams = new HashMap<>(); @@ -277,12 +313,17 @@ public C addPathParam(String name, Object value) { return (C) this; } + @Deprecated + public C addPathParam(Map params) { + return addPathPara(params); + } + /** * 路径å�‚数:替æ�¢URL里的{name} * @param params å�‚数集å�ˆ * @return HttpTask 实例 **/ - public C addPathParam(Map params) { + public C addPathPara(Map params) { if (pathParams == null) { pathParams = new HashMap<>(); } @@ -290,13 +331,18 @@ public C addPathParam(Map params) { return (C) this; } + @Deprecated + public C addUrlParam(String name, Object value) { + return addUrlPara(name, value); + } + /** * URLå�‚数:拼接在URLå�Žçš„å�‚æ•° * @param name å�‚æ•°å�� * @param value å�‚数值 * @return HttpTask 实例 **/ - public C addUrlParam(String name, Object value) { + public C addUrlPara(String name, Object value) { if (name != null && value != null) { if (urlParams == null) { urlParams = new HashMap<>(); @@ -306,12 +352,17 @@ public C addUrlParam(String name, Object value) { return (C) this; } + @Deprecated + public C addUrlParam(Map params) { + return addUrlPara(params); + } + /** * URLå�‚数:拼接在URLå�Žçš„å�‚æ•° * @param params å�‚数集å�ˆ * @return HttpTask 实例 **/ - public C addUrlParam(Map params) { + public C addUrlPara(Map params) { if (urlParams == null) { urlParams = new HashMap<>(); } @@ -319,13 +370,18 @@ public C addUrlParam(Map params) { return (C) this; } + @Deprecated + public C addBodyParam(String name, Object value) { + return addBodyPara(name, value); + } + /** * Bodyå�‚数:放在Body里的å�‚æ•° * @param name å�‚æ•°å�� * @param value å�‚数值 * @return HttpTask 实例 **/ - public C addBodyParam(String name, Object value) { + public C addBodyPara(String name, Object value) { if (name != null && value != null) { if (bodyParams == null) { bodyParams = new HashMap<>(); @@ -335,12 +391,17 @@ public C addBodyParam(String name, Object value) { return (C) this; } + @Deprecated + public C addBodyParam(Map params) { + return addBodyPara(params); + } + /** * Bodyå�‚数:放在Body里的å�‚æ•° * @param params å�‚数集å�ˆ * @return HttpTask 实例 **/ - public C addBodyParam(Map params) { + public C addBodyPara(Map params) { if (bodyParams == null) { bodyParams = new HashMap<>(); } @@ -350,9 +411,7 @@ public C addBodyParam(Map params) { private void doAddParams(Map taskParams, Map params) { if (params != null) { - Iterator it = params.keySet().iterator(); - while (it.hasNext()) { - String name = it.next(); + for (String name : params.keySet()) { Object value = params.get(name); if (name != null && value != null) { taskParams.put(name, value.toString()); @@ -362,77 +421,85 @@ private void doAddParams(Map taskParams, Map params) } /** + * 推è��方案:setBodyParam 与 bodyType 方法 * Jsonå�‚数:请求体为Json,支æŒ�多层结构 * @param name JSONé”®å�� * @param value JSON键值 * @return HttpTask 实例 */ + @Deprecated public C addJsonParam(String name, Object value) { - if (name != null && value != null) { - if (jsonParams == null) { - jsonParams = new HashMap<>(); - } - jsonParams.put(name, value); - } - return (C) this; + this.bodyType = "json"; + return addBodyPara(name, value); } /** + * 推è��方案:setBodyParam 与 bodyType 方法 * Jsonå�‚数:请求体为Json,å�ªæ”¯æŒ�å�•层Json * 若请求json为多层结构,请使用setRequestJson方法 * @param params JSON键值集å�ˆ * @return HttpTask 实例 */ + @Deprecated public C addJsonParam(Map params) { - if (params != null) { - if (jsonParams == null) { - jsonParams = new HashMap<>(); - } - jsonParams.putAll(params); - } - return (C) this; + this.bodyType = "json"; + return addBodyPara(params); } /** + * 推è��方案:setBodyPara 与 bodyType 方法 * 设置 json 请求体 - * @param json JSON字符串 或 Java对象(将ä¾�æ�® 对象的get方法åº�列化为 json 字符串) + * @param body JSON字符串 或 Java对象(将ä¾�æ�® 对象的get方法åº�列化为 json 字符串) * @return HttpTask 实例 **/ - public C setRequestJson(Object json) { - return setRequestJson(json, null); + @Deprecated + public C setRequestJson(Object body) { + this.bodyType = "json"; + return setBodyPara(body); } /** - * 请求体为json - * @param json JSON字符串 或 Java对象,将跟æ�¢ beançš„get方法åº�列化程 json 字符串 - * @param dateFormat åº�列化json时对日期类型字段的处ç�†æ ¼å¼� + * 此方法性能较低 + * 推è��方案:setBodyPara 与 bodyType 方法,日期格å¼�在 Java Bean 上使用注解的方å¼�指定 + * @param body Json 请求体 + * @param dateFormat 日期格å¼� + * @return HttpTask 实例 + */ + @Deprecated + public C setRequestJson(Object body, String dateFormat) { + this.bodyType = "json"; + this.dateFormat = dateFormat; + return setBodyPara(body); + } + + /** + * 设置 json 请求体 + * @param body 请求体,字节数组ã€�字符串 或 Java对象(由 MsgConvertor æ�¥åº�列化) * @return HttpTask 实例 **/ - public C setRequestJson(Object json, String dateFormat) { - if (json != null) { - if (json instanceof byte[]) { - requestJson = (byte[]) json; - } else if (json instanceof String) { - requestJson = json.toString().getBytes(httpClient.charset()); - } else if (dateFormat != null) { - requestJson = httpClient.executor().convertor() - .serialize(json, dateFormat, httpClient.charset()); - } else { - requestJson = httpClient.executor().convertor() - .serialize(json, httpClient.charset()); - } - } + public C setBodyPara(Object body) { + this.requestBody = body; return (C) this; } + @Deprecated + public C addFileParam(String name, String filePath) { + return addFilePara(name, filePath); + } + /** * 添加文件å�‚æ•° * @param name å�‚æ•°å�� * @param filePath 文件路径 * @return HttpTask 实例 */ - public C addFileParam(String name, String filePath) { - return addFileParam(name, new File(filePath)); + public C addFilePara(String name, String filePath) { + return addFilePara(name, new File(filePath)); + } + + @Deprecated + public C addFileParam(String name, File file) { + return addFilePara(name, file); } /** @@ -441,7 +508,7 @@ public C addFileParam(String name, String filePath) { * @param file 文件 * @return HttpTask 实例 */ - public C addFileParam(String name, File file) { + public C addFilePara(String name, File file) { if (name != null && file != null && file.exists()) { String fileName = file.getName(); String type = fileName.substring(fileName.lastIndexOf(".") + 1); @@ -454,17 +521,20 @@ public C addFileParam(String name, File file) { } /** + * 建议直接使用文件上传,使用输入æµ�性能较差 * 添加文件å�‚æ•° * @param name å�‚æ•°å�� * @param type 文件类型: 如 pngã€�jpgã€�jpeg ç­‰ * @param inputStream 文件输入æµ� * @return HttpTask 实例 */ + @Deprecated public C addFileParam(String name, String type, InputStream inputStream) { return addFileParam(name, type, null, inputStream); } /** + * 建议直接使用文件上传,使用输入æµ�性能较差 * 添加文件å�‚æ•° * @param name å�‚æ•°å�� * @param type 文件类型: 如 pngã€�jpgã€�jpeg ç­‰ @@ -472,6 +542,7 @@ public C addFileParam(String name, String type, InputStream inputStream) { * @param input 文件输入æµ� * @return HttpTask 实例 */ + @Deprecated public C addFileParam(String name, String type, String fileName, InputStream input) { if (name != null && input != null) { byte[] content = null; @@ -484,11 +555,16 @@ public C addFileParam(String name, String type, String fileName, InputStream inp } finally { Util.closeQuietly(input); } - addFileParam(name, type, fileName, content); + addFilePara(name, type, fileName, content); } return (C) this; } + @Deprecated + public C addFileParam(String name, String type, byte[] content) { + return addFilePara(name, type, content); + } + /** * 添加文件å�‚æ•° * @param name å�‚æ•°å�� @@ -496,8 +572,13 @@ public C addFileParam(String name, String type, String fileName, InputStream inp * @param content 文件内容 * @return HttpTask 实例 */ - public C addFileParam(String name, String type, byte[] content) { - return addFileParam(name, type, null, content); + public C addFilePara(String name, String type, byte[] content) { + return addFilePara(name, type, null, content); + } + + @Deprecated + public C addFileParam(String name, String type, String fileName, byte[] content) { + return addFilePara(name, type, fileName, content); } /** @@ -508,7 +589,7 @@ public C addFileParam(String name, String type, byte[] content) { * @param content 文件内容 * @return HttpTask 实例 */ - public C addFileParam(String name, String type, String fileName, byte[] content) { + public C addFilePara(String name, String type, String fileName, byte[] content) { if (name != null && content != null) { if (files == null) { files = new HashMap<>(); @@ -648,16 +729,38 @@ protected State toState(IOException e, boolean sync) { return State.EXCEPTION; } - private RequestBody buildRequestBody() { - if (jsonParams != null) { - requestJson = httpClient.executor().convertor() - .serialize(jsonParams, httpClient.charset()); + + /** + * 请求体为json + * @param body JSON字符串 或 Java对象,将跟æ�¢ beançš„get方法åº�列化程 json 字符串 + * @return HttpTask 实例 + **/ + public C setBodyParaxxx(Object body) { + if (bodyType == null) { + throw new IllegalArgumentException("type can not be null"); + } + if (body != null) { + if (body instanceof byte[]) { + requestBody = body; + } else if (body instanceof String) { + requestBody = body.toString().getBytes(charset); + } else if (dateFormat != null) { + requestBody = httpClient.executor().doMsgConvert(bodyType, (MsgConvertor c) -> + c.serialize(body, dateFormat, charset)); + } else { + requestBody = httpClient.executor().doMsgConvert(bodyType, (MsgConvertor c) -> + c.serialize(body, charset)); + } } + return (C) this; + } + + private RequestBody buildRequestBody() { if (files != null) { MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); if (bodyParams != null) { for (String name : bodyParams.keySet()) { - byte[] value = bodyParams.get(name).getBytes(httpClient.charset()); + byte[] value = bodyParams.get(name).getBytes(charset); RequestBody body = RequestBody.create(null, value); builder.addPart(MultipartBody.Part.createFormData(name, null, body)); } @@ -674,18 +777,34 @@ private RequestBody buildRequestBody() { builder.addFormDataPart(name, file.fileName, bodyPart); } return builder.build(); - } else if (requestJson != null) { - return RequestBody.create(httpClient.mapperType(), requestJson); - } else { - FormBody.Builder builder = new FormBody.Builder(httpClient.charset()); - if (bodyParams != null) { - for (String name : bodyParams.keySet()) { - String value = bodyParams.get(name); - builder.add(name, value); - } + } + if (requestBody != null) { + return toRequestBody(requestBody); + } + if (bodyParams == null) { + return new FormBody.Builder(charset).build(); + } + if (bodyType.toLowerCase().contains("form")) { + FormBody.Builder builder = new FormBody.Builder(charset); + for (String name : bodyParams.keySet()) { + String value = bodyParams.get(name); + builder.add(name, value); } return builder.build(); } + return toRequestBody(bodyParams); + } + + private RequestBody toRequestBody(Object object) { + TaskExecutor.Data data = httpClient.executor() + .doMsgConvert(bodyType, (MsgConvertor c) + -> c.serialize(object, dateFormat, charset)); + byte[] body = data.data; + String mediaType = data.mediaType; + if (mediaType == null) { + mediaType = "application/json"; + } + return RequestBody.create(MediaType.parse(mediaType + "; charset=" + charset.name()), body); } private String buildUrlPath() { @@ -735,37 +854,26 @@ private String buildUrl(String url) { protected void assertNotConflict(boolean isGetRequest) { if (isGetRequest) { - if (requestJson != null) { - throw new HttpException("GET 请求 ä¸�能调用 setRequestJson 方法ï¼�"); - } - if (jsonParams != null) { - throw new HttpException("GET 请求 ä¸�能调用 addJsonParam 方法ï¼�"); + if (requestBody != null) { + throw new HttpException("GET 请求 ä¸�能调用 setBodyPara 方法ï¼�"); } if (bodyParams != null) { - throw new HttpException("GET 请求 ä¸�能调用 addBodyParam 方法ï¼�"); + throw new HttpException("GET 请求 ä¸�能调用 addBodyPara 方法ï¼�"); } if (files != null) { - throw new HttpException("GET 请求 ä¸�能调用 addFileParam 方法ï¼�"); + throw new HttpException("GET 请求 ä¸�能调用 addFilePara 方法ï¼�"); } } - if (requestJson != null) { - if (jsonParams != null) { - throw new HttpException("方法 addJsonParam 与 setRequestJson ä¸�能å�Œæ—¶è°ƒç”¨ï¼�"); - } + if (requestBody != null) { if (bodyParams != null) { - throw new HttpException("方法 addBodyParam 与 setRequestJson ä¸�能å�Œæ—¶è°ƒç”¨ï¼�"); + throw new HttpException("方法 addBodyPara 与 setBodyPara ä¸�能å�Œæ—¶è°ƒç”¨ï¼�"); } if (files != null) { - throw new HttpException("方法 addFileParam 与 setRequestJson ä¸�能å�Œæ—¶è°ƒç”¨ï¼�"); + throw new HttpException("方法 addFilePara 与 setBodyPara ä¸�能å�Œæ—¶è°ƒç”¨ï¼�"); } } - if (jsonParams != null) { - if (bodyParams != null) { - throw new HttpException("方法 addBodyParam 与 addJsonParam ä¸�能å�Œæ—¶è°ƒç”¨ï¼�"); - } - if (files != null) { - throw new HttpException("方法 addFileParam 与 addJsonParam ä¸�能å�Œæ—¶è°ƒç”¨ï¼�"); - } + if (files != null && "form".equals(bodyType)) { + throw new HttpException("方法 addFilePara å�ªèƒ½ä½¿ç”¨ form æ–¹å¼�请求ï¼�"); } } @@ -792,8 +900,7 @@ protected HttpResult timeoutResult() { public Charset charset(Response response) { ResponseBody b = response.body(); MediaType type = b != null ? b.contentType() : null; - Charset defaultCharset = httpClient.charset(); - return type != null ? type.charset(defaultCharset) : defaultCharset; + return type != null ? type.charset(charset) : charset; } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java index 8d102f66..9b1251c7 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java @@ -1,5 +1,6 @@ package com.ejlchina.okhttps; +import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.Charset; import java.util.List; @@ -19,7 +20,7 @@ public interface MsgConvertor { * è§£æž� Mapper * @param in JSON 输入æµ� * @param charset ç¼–ç �æ ¼å¼� - * @return JsonObj + * @return Mapper */ Mapper toMapper(InputStream in, Charset charset); @@ -27,26 +28,26 @@ public interface MsgConvertor { * è§£æž� Array * @param in JSON 输入æµ� * @param charset ç¼–ç �æ ¼å¼� - * @return JsonArr + * @return Array */ Array toArray(InputStream in, Charset charset); /** * å°† Java 对象åº�列化为字节数组 - * @param bean Java Bean + * @param object Java 对象 * @param charset ç¼–ç �æ ¼å¼� * @return 字节数组 */ - byte[] serialize(Object bean, Charset charset); + byte[] serialize(Object object, Charset charset); /** * å°† Java 对象åº�列化为字节数组 - * @param bean Java Bean + * @param object Java 对象 * @param dateFormat 日期类的处ç�†æ ¼å¼� * @param charset ç¼–ç �æ ¼å¼� * @return 字节数组 */ - byte[] serialize(Object bean, String dateFormat, Charset charset); + byte[] serialize(Object object, String dateFormat, Charset charset); /** * è§£æž� Java Bean @@ -68,4 +69,65 @@ public interface MsgConvertor { */ List toList(Class type, InputStream in, Charset charset); + + class FormMsgConvertor implements MsgConvertor { + + MsgConvertor convertor; + + public FormMsgConvertor(MsgConvertor convertor) { + this.convertor = convertor; + } + + @Override + public String mediaType() { + return "application/x-www-form-urlencoded"; + } + + @Override + public Mapper toMapper(InputStream in, Charset charset) { + return convertor.toMapper(in, charset); + } + + @Override + public Array toArray(InputStream in, Charset charset) { + return convertor.toArray(in, charset); + } + + @Override + public byte[] serialize(Object object, Charset charset) { + return serialize(object, null, charset); + } + + @Override + public byte[] serialize(Object object, String dateFormat, Charset charset) { + if (object instanceof byte[]) { + return (byte[]) object; + } + if (object instanceof String) { + return object.toString().getBytes(charset); + } + byte[] data = convertor.serialize(object, dateFormat, charset); + Mapper mapper = convertor.toMapper(new ByteArrayInputStream(data), charset); + StringBuilder sb = new StringBuilder(); + for (String key: mapper.keySet()) { + sb.append(key).append('=').append(mapper.getString(key)).append('&'); + } + if (sb.length() > 1) { + sb.deleteCharAt(sb.length() - 1); + } + return sb.toString().getBytes(charset); + } + + @Override + public T toBean(Class type, InputStream in, Charset charset) { + return convertor.toBean(type, in, charset); + } + + @Override + public List toList(Class type, InputStream in, Charset charset) { + return convertor.toList(type, in, charset); + } + + } + } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java index 480b3e13..ca2f33ed 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/HttpClient.java @@ -26,27 +26,22 @@ public class HttpClient implements HTTP { final int preprocTimeoutTimes; // ç¼–ç �æ ¼å¼� final Charset charset; - // Mapper的媒体类型 - final MediaType mapperType; + // 默认的请求体类型 + final String bodyType; public HttpClient(Builder builder) { this.okClient = builder.okClient(); this.baseUrl = builder.baseUrl(); this.mediaTypes = builder.getMediaTypes(); - MsgConvertor convertor = builder.msgConvertor(); this.executor = new TaskExecutor(okClient.dispatcher().executorService(), builder.mainExecutor(), builder.downloadListener(), builder.responseListener(), builder.exceptionListener(), - builder.completeListener(), convertor); - this.preprocessors = builder.preprocessors().toArray(new Preprocessor[0]); + builder.completeListener(), builder.msgConvertors()); + this.preprocessors = builder.preprocessors(); this.preprocTimeoutTimes = builder.preprocTimeoutTimes(); this.charset = builder.charset(); + this.bodyType = builder.bodyType(); this.tagTasks = new LinkedList<>(); - String mediaType = convertor != null ? convertor.mediaType() : null; - if (mediaType == null) { - mediaType = "application/json"; - } - this.mapperType = MediaType.parse(mediaType + "; charset=" + charset.name()); } @Override @@ -368,8 +363,9 @@ public Charset charset() { return charset; } - public MediaType mapperType() { - return mapperType; + public String bodyType() { + return bodyType; } + } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index 859a40a9..efc4e41a 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -14,7 +14,6 @@ import com.ejlchina.okhttps.OnCallback; import com.ejlchina.okhttps.TaskListener; import com.ejlchina.okhttps.HttpResult.State; -import okhttp3.MediaType; public class TaskExecutor { @@ -24,18 +23,18 @@ public class TaskExecutor { private TaskListener responseListener; private TaskListener exceptionListener; private TaskListener completeListener; - private MsgConvertor msgConvertor; + private MsgConvertor[] msgConvertors; public TaskExecutor(Executor ioExecutor, Executor mainExecutor, DownListener downloadListener, TaskListener responseListener, TaskListener exceptionListener, - TaskListener completeListener, MsgConvertor msgConvertor) { + TaskListener completeListener, MsgConvertor[] msgConvertors) { this.ioExecutor = ioExecutor; this.mainExecutor = mainExecutor; this.downloadListener = downloadListener; this.responseListener = responseListener; this.exceptionListener = exceptionListener; this.completeListener = completeListener; - this.msgConvertor = msgConvertor; + this.msgConvertors = msgConvertors; } public Executor getExecutor(boolean onIoThread) { @@ -100,11 +99,52 @@ public void executeOnComplete(HttpTask task, OnCallback onComplete, St } } - public MsgConvertor convertor() { - if (msgConvertor != null) { - return msgConvertor; - } - throw new IllegalStateException("没有设置 MsgConvertor,ä¸�å�¯å�šè½¬æ�¢æ“�作ï¼�"); + public interface ConvertFunc { + + T apply(MsgConvertor convertor); + + } + + public static class Data { + + public T data; + public String mediaType; + + public Data(T data, String mediaType) { + this.data = data; + this.mediaType = mediaType; + } + } + + public Data doMsgConvert(String type, ConvertFunc callable) { + Throwable cause = null; + for (int i = msgConvertors.length - 1; i >= 0; i--) { + MsgConvertor convertor = msgConvertors[i]; + String mediaType = convertor.mediaType(); + if (mediaType == null || !mediaType.contains(type)) { + continue; + } + try { + return new Data<>(callable.apply(convertor), mediaType); + } catch (Exception e) { + if (cause != null) { + initRootCause(e, cause); + } + cause = e; + } + } + if (cause != null) { + throw new HttpException("转æ�¢å¤±è´¥", cause); + } + throw new HttpException("没有匹é…�[" + type + "]类型的转æ�¢å™¨ï¼�"); + } + + private void initRootCause(Throwable throwable, Throwable cause) { + Throwable lastCause = throwable.getCause(); + if (lastCause != null) { + initRootCause(lastCause, cause); + } + throwable.initCause(cause); } /** @@ -144,8 +184,8 @@ public TaskListener getCompleteListener() { return completeListener; } - public MsgConvertor getMsgConvertor() { - return msgConvertor; + public MsgConvertor[] getMsgConvertors() { + return msgConvertors; } } From 5ba46343bd01c7372b53e5d5bef5d6eda37cec49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Mon, 11 May 2020 21:24:44 +0800 Subject: [PATCH 264/924] . --- okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 6fdf4b9a..32794ded 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -176,7 +176,7 @@ public C charset(Charset charset) { /** * @since 2.0.0 - * 设置请求体的类型,如:formã€�jsonã€�xmlã€�protobuf 等,默认为 form + * 设置请求体的类型,如:formã€�jsonã€�xmlã€�protobuf ç­‰ * @param type 请求类型 * @return HttpTask 实例 */ @@ -421,7 +421,7 @@ private void doAddParams(Map taskParams, Map params) } /** - * 推è��方案:setBodyParam 与 bodyType 方法 + * 推è��方案:setBodyPara 与 bodyType 方法 * Jsonå�‚数:请求体为Json,支æŒ�多层结构 * @param name JSONé”®å�� * @param value JSON键值 @@ -434,7 +434,7 @@ public C addJsonParam(String name, Object value) { } /** - * 推è��方案:setBodyParam 与 bodyType 方法 + * 推è��方案:setBodyPara 与 bodyType 方法 * Jsonå�‚数:请求体为Json,å�ªæ”¯æŒ�å�•层Json * 若请求json为多层结构,请使用setRequestJson方法 * @param params JSON键值集å�ˆ From c308475dc2af42b29ee32731ea7943638a909bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Tue, 12 May 2020 00:03:25 +0800 Subject: [PATCH 265/924] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpTask.java | 45 +++-------- .../java/com/ejlchina/okhttps/WebSocket.java | 34 +------- .../okhttps/internal/AbstractBody.java | 12 +-- .../okhttps/internal/MessageBody.java | 9 ++- .../okhttps/internal/TaskExecutor.java | 15 +++- .../okhttps/internal/WebSocketTask.java | 79 +++++++------------ 6 files changed, 66 insertions(+), 128 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 32794ded..627044f3 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -81,6 +81,10 @@ public String getTag() { return tag; } + public String getBodyType() { + return bodyType; + } + /** * 标签匹é…� * 判断任务标签与指定的标签是å�¦åŒ¹é…�(包å�«æŒ‡å®šçš„æ ‡ç­¾ï¼‰ @@ -729,32 +733,6 @@ protected State toState(IOException e, boolean sync) { return State.EXCEPTION; } - - /** - * 请求体为json - * @param body JSON字符串 或 Java对象,将跟æ�¢ beançš„get方法åº�列化程 json 字符串 - * @return HttpTask 实例 - **/ - public C setBodyParaxxx(Object body) { - if (bodyType == null) { - throw new IllegalArgumentException("type can not be null"); - } - if (body != null) { - if (body instanceof byte[]) { - requestBody = body; - } else if (body instanceof String) { - requestBody = body.toString().getBytes(charset); - } else if (dateFormat != null) { - requestBody = httpClient.executor().doMsgConvert(bodyType, (MsgConvertor c) -> - c.serialize(body, dateFormat, charset)); - } else { - requestBody = httpClient.executor().doMsgConvert(bodyType, (MsgConvertor c) -> - c.serialize(body, charset)); - } - } - return (C) this; - } - private RequestBody buildRequestBody() { if (files != null) { MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); @@ -796,15 +774,14 @@ private RequestBody buildRequestBody() { } private RequestBody toRequestBody(Object object) { + if (object instanceof byte[] || object instanceof String) { + String mediaType = httpClient.executor().doMsgConvert(bodyType, null).mediaType; + byte[] body = object instanceof byte[] ? (byte[]) object : ((String) object).getBytes(charset); + return RequestBody.create(MediaType.parse(mediaType + "; charset=" + charset.name()), body); + } TaskExecutor.Data data = httpClient.executor() - .doMsgConvert(bodyType, (MsgConvertor c) - -> c.serialize(object, dateFormat, charset)); - byte[] body = data.data; - String mediaType = data.mediaType; - if (mediaType == null) { - mediaType = "application/json"; - } - return RequestBody.create(MediaType.parse(mediaType + "; charset=" + charset.name()), body); + .doMsgConvert(bodyType, (MsgConvertor c) -> c.serialize(object, dateFormat, charset)); + return RequestBody.create(MediaType.parse(data.mediaType + "; charset=" + charset.name()), data.data); } private String buildUrlPath() { diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java index bdd16b3c..3fb62071 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java @@ -117,40 +117,10 @@ interface Listener { long queueSize(); /** - * å�Œ {@link okhttp3.WebSocket#send(String)} - * @param text 文本数æ�® - * @return 是å�¦å�¯ä»¥å�‘é€� - */ - boolean send(String text); - - /** - * å�Œ {@link okhttp3.WebSocket#send(ByteString)} - * @param bytes 二进制数æ�® - * @return 是å�¦å�¯ä»¥å�‘é€� - */ - boolean send(ByteString bytes); - - /** - * 以JSON文本格å¼�å�‘é€�对象消æ�¯ - * @param bean å¾…å�‘é€�的对象 - * @return 如果连接已断开 返回 false - */ - boolean send(Object bean); - - /** - * 以JSON文本格å¼�å�‘é€�对象消æ�¯ - * @param bean å¾…å�‘é€�的对象 - * @param dateFormat 日期类型字段的处ç�†æ ¼å¼� - * @return 如果连接已断开 返回 false - */ - boolean send(Object bean, String dateFormat); - - /** - * å�‘é€�字节æµ� - * @param data å¾…å�‘é€�的数æ�® + * @param object å¾…å�‘é€�的对象,å�¯ä»¥æ˜¯ String | ByteString | byte[] | Java Bean * @return 如果连接已断开 返回 false */ - boolean send(byte[] data); + boolean send(Object object); /** * å�Œ {@link okhttp3.WebSocket#close(int, String)} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java index 271cf7a7..8b73ff7c 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java @@ -6,13 +6,13 @@ import com.ejlchina.okhttps.Array; import com.ejlchina.okhttps.Mapper; +import com.ejlchina.okhttps.MsgConvertor; public abstract class AbstractBody { - protected TaskExecutor taskExecutor; protected Charset charset; - + public AbstractBody(TaskExecutor taskExecutor, Charset charset) { this.taskExecutor = taskExecutor; this.charset = charset; @@ -25,7 +25,7 @@ public Mapper toMapper() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Mapper 转æ�¢ï¼�"); } - return taskExecutor.convertor().toMapper(toByteStream(), charset); + return taskExecutor.doMsgConvert((MsgConvertor c) -> c.toMapper(toByteStream(), charset)); } @@ -33,7 +33,7 @@ public Array toArray() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Array 转æ�¢ï¼�"); } - return taskExecutor.convertor().toArray(toByteStream(), charset); + return taskExecutor.doMsgConvert((MsgConvertor c) -> c.toArray(toByteStream(), charset)); } @@ -41,7 +41,7 @@ public T toBean(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Bean 转æ�¢ï¼�"); } - return taskExecutor.convertor().toBean(type, toByteStream(), charset); + return taskExecutor.doMsgConvert((MsgConvertor c) -> c.toBean(type, toByteStream(), charset)); } @@ -49,7 +49,7 @@ public List toList(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š List 转æ�¢ï¼�"); } - return taskExecutor.convertor().toList(type, toByteStream(), charset); + return taskExecutor.doMsgConvert((MsgConvertor c) -> c.toList(type, toByteStream(), charset)); } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java index 4da07e39..f8ae709d 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java @@ -6,6 +6,7 @@ import java.io.InputStreamReader; import java.io.Reader; import java.nio.ByteBuffer; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import com.ejlchina.okhttps.WebSocket.Message; @@ -18,13 +19,13 @@ public class MessageBody extends AbstractBody implements Message { private ByteString bytes; - public MessageBody(String text, TaskExecutor taskExecutor) { - super(taskExecutor); + public MessageBody(String text, TaskExecutor taskExecutor, Charset charset) { + super(taskExecutor, charset); this.text = text; } - public MessageBody(ByteString bytes, TaskExecutor taskExecutor) { - super(taskExecutor); + public MessageBody(ByteString bytes, TaskExecutor taskExecutor, Charset charset) { + super(taskExecutor, charset); this.bytes = bytes; } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java index efc4e41a..9bc3b764 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/TaskExecutor.java @@ -116,15 +116,24 @@ public Data(T data, String mediaType) { } } + public V doMsgConvert(ConvertFunc callable) { + Data vData = doMsgConvert(null, callable); + return vData != null ? vData.data : null; + } + public Data doMsgConvert(String type, ConvertFunc callable) { Throwable cause = null; for (int i = msgConvertors.length - 1; i >= 0; i--) { MsgConvertor convertor = msgConvertors[i]; String mediaType = convertor.mediaType(); - if (mediaType == null || !mediaType.contains(type)) { + if (type != null && (mediaType == null || !mediaType.contains(type))) { continue; } + if (callable == null && mediaType != null) { + return new Data<>(null, mediaType); + } try { + assert callable != null; return new Data<>(callable.apply(convertor), mediaType); } catch (Exception e) { if (cause != null) { @@ -133,9 +142,13 @@ public Data doMsgConvert(String type, ConvertFunc callable) { cause = e; } } + if (callable == null) { + return new Data<>(null, "application/x-www-form-urlencoded"); + } if (cause != null) { throw new HttpException("转æ�¢å¤±è´¥", cause); } + throw new HttpException("没有匹é…�[" + type + "]类型的转æ�¢å™¨ï¼�"); } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index d8b9809c..76930bf5 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -1,12 +1,12 @@ package com.ejlchina.okhttps.internal; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import com.ejlchina.okhttps.HttpResult; import com.ejlchina.okhttps.HttpTask; +import com.ejlchina.okhttps.MsgConvertor; import com.ejlchina.okhttps.WebSocket; import com.ejlchina.okhttps.WebSocket.Close; import com.ejlchina.okhttps.WebSocket.Listener; @@ -30,6 +30,9 @@ public class WebSocketTask extends HttpTask { public WebSocketTask(HttpClient httpClient, String url) { super(httpClient, url); + if (getBodyType().toLowerCase().contains("form")) { + bodyType("json"); + } } /** @@ -37,7 +40,7 @@ public WebSocketTask(HttpClient httpClient, String url) { * @return WebSocket */ public WebSocket listen() { - WebSocketImpl socket = new WebSocketImpl(httpClient.executor, httpClient.charset); + WebSocketImpl socket = new WebSocketImpl(httpClient.executor, getBodyType()); registeTagTask(socket); httpClient.preprocess(this, () -> { synchronized (socket) { @@ -45,8 +48,7 @@ public WebSocket listen() { removeTagTask(); } else { Request request = prepareRequest("GET"); - MessageListener listener = new MessageListener(socket); - socket.setWebSocket(httpClient.webSocket(request, listener)); + httpClient.webSocket(request, new MessageListener(socket)); } } }, skipPreproc, skipSerialPreproc); @@ -56,14 +58,19 @@ public WebSocket listen() { class MessageListener extends WebSocketListener { - WebSocket webSocket; + WebSocketImpl webSocket; + + Charset charset; - public MessageListener(WebSocket webSocket) { + public MessageListener(WebSocketImpl webSocket) { this.webSocket = webSocket; } @Override public void onOpen(okhttp3.WebSocket webSocket, Response response) { + this.charset = charset(response); + this.webSocket.setCharset(charset); + this.webSocket.setWebSocket(webSocket); if (onOpen != null) { HttpResult result = new RealHttpResult(WebSocketTask.this, response, httpClient.executor); onOpen.on(this.webSocket, result); @@ -74,7 +81,7 @@ public void onOpen(okhttp3.WebSocket webSocket, Response response) { @Override public void onMessage(okhttp3.WebSocket webSocket, String text) { if (onMessage != null) { - onMessage.on(this.webSocket, new MessageBody(text, httpClient.executor)); + onMessage.on(this.webSocket, new MessageBody(text, httpClient.executor, charset)); } } @@ -82,7 +89,7 @@ public void onMessage(okhttp3.WebSocket webSocket, String text) { @Override public void onMessage(okhttp3.WebSocket webSocket, ByteString bytes) { if (onMessage != null) { - onMessage.on(this.webSocket, new MessageBody(bytes, httpClient.executor)); + onMessage.on(this.webSocket, new MessageBody(bytes, httpClient.executor, charset)); } } @@ -124,8 +131,14 @@ static class WebSocketImpl implements WebSocket { Charset charset; - public WebSocketImpl(TaskExecutor taskExecutor, Charset charset) { + String bodyType; + + public WebSocketImpl(TaskExecutor taskExecutor, String bodyType) { this.taskExecutor = taskExecutor; + this.bodyType = bodyType; + } + + public void setCharset(Charset charset) { this.charset = charset; } @@ -156,54 +169,18 @@ public long queueSize() { } @Override - public boolean send(String text) { - if (webSocket != null) { - return webSocket.send(text); - } - queueMsgToSend(text); - return true; - } - - @Override - public boolean send(ByteString bytes) { - if (webSocket != null) { - return webSocket.send(bytes); - } - queueMsgToSend(bytes); - return true; - } - - @Override - public boolean send(Object bean) { - return send(taskExecutor.convertor().serialize(bean, charset)); - } - - @Override - public boolean send(Object bean, String dateFormat) { - return send(taskExecutor.convertor().serialize(bean, dateFormat, charset)); - } - - @Override - public boolean send(byte[] data) { - if (webSocket != null) { - return send(webSocket, data); - } - queueMsgToSend(data); - return true; - } - - - void queueMsgToSend(Object msg) { + public boolean send(Object msg) { if (msg == null) { - return; + return false; } synchronized (queues) { if (webSocket != null) { - send(webSocket, msg); + return send(webSocket, msg); } else { queues.add(msg); } } + return true; } void setWebSocket(okhttp3.WebSocket webSocket) { @@ -229,8 +206,8 @@ boolean send(okhttp3.WebSocket webSocket, Object msg) { if (msg instanceof byte[]) { return webSocket.send(ByteString.of((byte[]) msg)); } - byte[] bytes = taskExecutor.convertor().serialize(msg, charset); - return webSocket.send(new String(bytes, StandardCharsets.UTF_8)); + byte[] bytes = taskExecutor.doMsgConvert(bodyType, (MsgConvertor c) -> c.serialize(msg, charset)).data; + return webSocket.send(new String(bytes, charset)); } } From cc4749731abab05bb570b745dccab361face4e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 09:25:10 +0800 Subject: [PATCH 266/924] LOGO --- okhttps-doc/OkHttps. logo.ai | 1327 ++++++++++++++++++++++++++++++++++ 1 file changed, 1327 insertions(+) create mode 100644 okhttps-doc/OkHttps. logo.ai diff --git a/okhttps-doc/OkHttps. logo.ai b/okhttps-doc/OkHttps. logo.ai new file mode 100644 index 00000000..e9a96afc --- /dev/null +++ b/okhttps-doc/OkHttps. logo.ai @@ -0,0 +1,1327 @@ +%PDF-1.5 %âãÏÓ +1 0 obj <>/OCGs[28 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + OKhttps. logo + + + Adobe Illustrator 24.0 (Macintosh) + 2020-04-28T11:13:07+08:00 + 2020-04-28T11:13:09+08:00 + 2020-04-28T11:13:09+08:00 + + + + 256 + 160 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAoAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FXYq7FXYqlHmzzb5f8p6Hca3r14lnp9sPikf7TtQlY416u7U2Ub4q+GPzb/Obzd+bHmCHTbGGaHR TMsek6DDV3llY8VeUJ/eSsTsOi9B3JVfZn5OaF5m0H8s9B0nzPK02t2sDC6LyeqyBpXeKIvU1MUT KmxptttirMsVdirsVdirsVdirsVdirsVdirsVdiqldXVvaWs11cyLFbW6NLNKxoqIgLMxPgAK4q8 /wDI35//AJY+ddZk0bRtSZNQBP1aG7ja3+sAdTBz+1/qmje3XFXouKuxV2KuxV2KuxV2KuxV2Kux V2KuxV2KuxV2KvkH/nNqLzH/AIp0KVxOfLQseNud/q4vvWlM3t6hi9Pr2G3fFUX/AM4by/lgt3cx zrTz+3L6u93xKG27iy8Hp/eD7VOnw8sVfWeKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KobU9OtNT02 7029T1LO+hktrmOtOUUqFHWo8VbFXwv+cv8Azjv5p/Lm5bWdJeXUvLKuHi1GIET2hBqouAn2aHpI vw/6poMVehfkj/zllJEbfy9+Ykpkj2itfMVKsvZVvAPtD/i0b/zA7tir6rt7i3uYI7i2lSa3mUPD NGwdHRhVWVhUEEdCMVVMVdirsVdirsVdirsVdirsVdirsVdirsVSvzN5Y0LzPotzouu2aXum3S0l hkHcfZZWG6sp3VhuMVfDX5xfkb5q/K7W49T0ySe70AyiTTdZhBWW3kB5JHMU+xItPhcUDdRQ1UKv sL8ltc8167+Weiap5rhaLWriNzMXT0mkRZWWKVo6DiZIwrdN+vfFWb4q7FXYq7FXYq7FXYq7FXYq 7FXYq7FXYqtliilieKVFkikUrJGwDKysKEEHYgjFXy3+en/OKdsY7nzN5BSO2KBpr7QWYJER1ZrR moqf8Yyafy02UqvKvyd/5yA82flteLpt0JNS8teoRc6RMSHgJPxtbM392wO5Q/C3eh+IKvtvyR58 8r+dtEj1jy7erd2rUEqfZlhelTHNH1Rh+PUVGKsgxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kux V2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvPPzn/OTRPy08vrdXCi81q95LpWmA0MjLTlJIR9mNKi p79B7KvivWvNn5r/AJueYBaySXms3UrF7fSbRW+rQrXqsK/AirXd3/2TYqyEf84p/ncbP6x+hYhJ /wAspvLX1aUr/vzh/wANirEtP1H8yfyo81iWNbvy/rUQHqW8yFUmir0dG+CaJqbHcdwajFX23+Sf 50aR+ZmgvMsa2Wu2PFdU03lULy+zLETu0b0+anY9iVXoN9f2Fhbtc31zFaWyfbnndY0HzZiAMVVI J4J4lmgkWWFxVJEIZWHiCNjiq/FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXYq7FXYq7FX55/nB5m1T8xfzhvvqpM4lvV0jQ4Qfh9JJfRhC/8AGRyXPuxxV9t/lZ+WOgfl55Xg 0fTI1e6ZVfU9Q40kuZ6fE7HrxHRF/ZHvUlVmOKsS/M78ttA/MDyvcaLqsSibizaffcQZbaenwyI3 WlQOa/tDbFXw7+V3mLV/y0/OCz+tkwPZ3zaVrcAJ4mFpfRnBp9rgRzX3UYqzL/nMXVPME35pJp18 8i6TaWUEmkwEkRFZQfWlVa0LNKrIW8FA7Yq88/LD81/NX5e67Df6Tcu1gZAdQ0pnP1e4j6MGToHp 9lwKj5VBVforo+qWer6TZarZNzstQt4rq2c7FopkEiH6VYYqi8VdirsVdirsVdirsVdirsVdirsV dirsVdirsVdirsVdirsVdirsVdirsVdir85/ygkj0385/LX6VPEw6vFFOz9pjJ6YLFqdJCCScVfo xirsVdir86fzxlt7/wDOXzV9QHNX1KSFQm/KVKRvT5yKcVfe/m7yD5N84W0Vt5l0m31OOAkwNKpE kdacuEqFZFDcRyAbfvir4/8A+cl/yX0Pyd5p0FPKEEgi8yerHDo6s8zJcQtEgERcs/GX1xRSTuD2 2Cr7D8i6DN5f8laDoU7B59M0+2tJmBJBkhiVHIJ7cgaYqnmKuxV2KuxV2KuxV2KuxV2KuxV2KuxV 2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV8Gf85Mfl3feTPzMutUtUaPSdelfUdOuI6qEnZg1xECKcWS VuQp+yy4q+jPyK/5yG8v+dtItdK1y7isPN8CLFNDMwjW8KgD1oCaKWfq0Y3BrQccVez4q8d/PD/n IXy35G0m603SLuLUPN8qtFb2sREi2rnb1bkioXh1EZ+IntTfFXzR/wA44/l7qHnj8zrW/ukabS9G mXUtWuZKsHkVucMbE/aaWUbg/shjir75xVjcHkDQB5oHmm+Emp69FH6FneXhVvq0RrVLeNFjijry NWC8z3bFWSYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqkHnj yN5d87eXp9B1+39ezm+JHU8ZIpQCElib9l1rt27GoqMVfHX5gf8AOJn5j+X7qWXy/EPMek1Jikty qXSr2EkDEEt/xjLfR0xVhg8vfnqsf6IGm+Z1iI4/UBDqASlK09KlKU9sVZh+X/8Azid+ZPmK5jl1 yEeW9JqDJLdUa5Ze4jt1PIN/xkK/Tir7F8h+QvLXkby9DoWgW/o2sfxyyvRpp5T9qWZwByY0+QGw oBTFWRYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqgtI1rR9Zs/ruk3sN/Zl3jFxbSLLHzj Yq68lJFVYUxVG4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXYq7FXYqkPk7z35U85aa+oeXL9L23ikMU60aOWKQEjjLFIFkQ7bcl3xVLPzi1i90b8rfNGo2TFL uHTpxBIpoyNIvphwfFOXIYq+bP8AnDj8yf0Z5iu/I9/LSy1mtzpnI7LeRL8aD/jLEv3oB3xV9iYq 7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FVO5nEFvLOVZxEj OVUVY8RWgHc4q+WvKP8AzmrLP5kaHzVo8Nn5enfjBc2XqPPbgnZpgzMJh/NwVT4A9MVfT2kavpes abb6npV1Fe6fdKHt7mBg6Op8CPuPhir4R85S+c/yV/ObVJdDnazV52u7JWBNvdWM7l0jkStHQboe 4ZTShxV9P/l1+bfkv85fKd/oNzSx1a7tJbbVdHdgX9OVDG8tu5A9RPi69VPUdCVXxr5v8p+bPyv8 9CzuuVtqWmTpdaZfoCElWN+UNxET1BK9OxqDuMVfoB+XHnax87eS9K8y2lFF9CDcQg19K4T4JovH 4ZAQK9RQ98VZJirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVa5LyC1HIgkL3IFKn8cV bxV2KuxV2KuxV2KuxV89/nf/AM4saX5lNz5g8lpHp3mBuUtzpxolrdv1JXtDK3j9hj1pUtir57/L 780vzC/J/wAx3GnvDKlvHLTVvL16GRGYUqygiscnHo69dq8hir6guYfyn/5yL8nL6crQarYglCOK 39hJJSoZDVXicrv+y3Yhhsq8I1r/AJxd/Ojyhq8ep+WCmqmzkEtpf6dMsFwhXoxilZGDeyFsVeze WtN1X83PLEnlb83PKF7putadGXtPMHoGBHNVQvDIRxSU7Fo90cCtOwVTr8jfyq84/llqmtaHPfQ6 p5PvaXmnXQJjniugRG6PAagepHSrBiPgHjir1/FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FUp8zXWqWemm90+W3RrZhJPHdEJHJGNinqEgIx7E4C0aiUox4o1t3sL8pXmo67rFtqFtqMcv6P MiPBMzfWPq0zDnFKACr8KVSVTuR8XtCO7rtLOWWYkJfT86PQ/oPzelZY7h2KuxV2KuxV2KuxV2Kv Df8AnJKD8jL7TTb+c9SisPMsUf8AuOuLNPW1BKiqq8UdS0Rr9mUgdeJB3xV8Z6H5j1nyxryar5d1 GW0vLVz9WvIvgLJX9pDUFXH2kaoPQ4q+zPyT/wCcndA85rBonmUxaP5oPGOIk8bW8Y7D0mb7EhO3 psdz9knoFXuWKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KsZ8+2lzNp9lPHbteW1 lexXN9ZRjk0sKV5AL+1QkHj3yMnD1sSYg1YEgSPJJtGKap5r0y+sBJMlktz+kNQa2NqpjkTjDb0I XmY2+7IjcuNh9eWMo71dmq9w+DP8sdq7FXYq7FXYq7FXYq8Q/wCcl/zyn8haVDoOguo80arGXE5o fqlsSU9ah6yOwIjrtsT2AKr5j/LT8mvP35qajcX1s/Cx9U/pDXr5nZTK3xMAd3ml3qQP9kRXFXu0 H/OEHlcWfCfzNfPe/wC/kghSKv8AxiJdv+SmKvHvza/5xr85+QLeXVYpF1vy7Gf3moQKUkhBIAM8 BLFBU/aVmXxIxV6v/wA4tfn5qGqXUXkPzVcm4uih/QepSmsj+mKtbSuftNxFY2O+3H+XFX0/irsV dirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdir87vzS1DUPPP52 6vHG/Ka+1b9F2FTVRHHKLSClNgCFBNO5xV99+UvLGl+VvLeneX9LjEdjp0Kwx0ABYjd5Gp+3IxLM e5OKvP8AzF/zkz+V3l/zo/lO/nujdQSi3vNQjiVrO3lJoyyuXEnwH7RVGA+g4q9Ruba2u7WW2uY1 ntrhGjmicBkeNxxZWB2IYGhxV+df5h6Fcflr+buoWWlyFG0O/iu9LkJJKxnhdW9T3Kq6g4q/Q/St Qi1HS7PUIhSK8gjuIxWvwyoHG49jiqKxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku xV2KuxV2KuxV2KuxV2Kvzo8xNL5L/PC8uJkP+4PzCbxV6lo4bv14yK/zIAcVfojY3tpf2VvfWcqz 2l1Gk9vMm6vHIoZGX2ZTXFXhHm7/AJxE8t+YvP8Ac+Z21qa107ULk3mo6QkIZpJJG5zenceovpiR jX+7alT9Cr3xESNFjQBUQBVUdABsAMVfnn+fnmCHzV+cuv3emH6zA1xHY2nDfmbaNLc8KfaDyIxU ++Kvv3y7pp0vy/pmmGlbG0gtjQ1H7mNU2J/1cVTDFXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq+W/+cu/ycvbyUfmHoduZzHEsXmCCMVcJEKR3dBuQqAJJ4AKe nIhVhv5E/wDOT0/kuwi8teaYZdQ8vQ1FjdQ0a5tQTX0+LFRJFU7CtV7VFAFX0ZB/zkj+Sc1n9bHm iBIwKtG8Vwso9vSMfM/QMVeM/nH/AM5c219ptzoP5fpNGLlWiuNfmUxOEbZhaxn41LDbm9CvYVoQ qxb/AJxX/Jy98yeaLfzhqluU8u6LKJbVnG11eRmsapXqkTfEzeIC+NFX2zirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirTKrKVYBlYUZTuCD2OKvCPzH/wCc RvJHmW6m1Hy/cN5b1CYl5IYoxNZOx3qIaoY6/wCQ1P8AJxV5VL/zhN+YgueMWt6Q9tv+8Z7lX70+ AQMPD9rFWe+Rf+cMPLenXMd55u1V9aZCGGnWyG2tyQekj8mlkX5cMVfRNhYWOn2cNjYW8drZ26CO 3toVCRoi7BVVaAAYqr4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX/2Q== + + + + proof:pdf + uuid:65E6390686CF11DBA6E2D887CEACB407 + xmp.did:e162cb60-21aa-4ff8-8217-8d09729c2dd3 + uuid:6f336833-9404-b643-9a8f-9e47e02abffc + + xmp.iid:77657c28-e3ae-4323-aeac-9c0f28920502 + xmp.did:77657c28-e3ae-4323-aeac-9c0f28920502 + uuid:65E6390686CF11DBA6E2D887CEACB407 + proof:pdf + + + + + saved + xmp.iid:2afc754f-ab50-44e3-9c34-d29c32560605 + 2020-04-28T10:58:27+08:00 + Adobe Illustrator 24.0 (Macintosh) + / + + + saved + xmp.iid:e162cb60-21aa-4ff8-8217-8d09729c2dd3 + 2020-04-28T11:13:05+08:00 + Adobe Illustrator 24.0 (Macintosh) + / + + + + Web + Document + AIRobin + Adobe PDF library 15.00 + 21.0.0 + 1 + False + False + + 256.000000 + 256.000000 + Pixels + + + + Cyan + Magenta + Yellow + + + + + + 默认色æ�¿ç»„ + 0 + + + + 白色 + RGB + PROCESS + 255 + 255 + 255 + + + 黑色 + RGB + PROCESS + 0 + 0 + 0 + + + RGB 红 + RGB + PROCESS + 255 + 0 + 0 + + + RGB 黄 + RGB + PROCESS + 255 + 255 + 0 + + + RGB 绿 + RGB + PROCESS + 0 + 255 + 0 + + + RGB é�’ + RGB + PROCESS + 0 + 255 + 255 + + + RGB è“� + RGB + PROCESS + 0 + 0 + 255 + + + RGB 洋红 + RGB + PROCESS + 255 + 0 + 255 + + + R=193 G=39 B=45 + RGB + PROCESS + 193 + 39 + 45 + + + R=237 G=28 B=36 + RGB + PROCESS + 237 + 28 + 36 + + + R=241 G=90 B=36 + RGB + PROCESS + 241 + 90 + 36 + + + R=247 G=147 B=30 + RGB + PROCESS + 247 + 147 + 30 + + + R=251 G=176 B=59 + RGB + PROCESS + 251 + 176 + 59 + + + R=252 G=238 B=33 + RGB + PROCESS + 252 + 238 + 33 + + + R=217 G=224 B=33 + RGB + PROCESS + 217 + 224 + 33 + + + R=140 G=198 B=63 + RGB + PROCESS + 140 + 198 + 63 + + + R=57 G=181 B=74 + RGB + PROCESS + 57 + 181 + 74 + + + R=0 G=146 B=69 + RGB + PROCESS + 0 + 146 + 69 + + + R=0 G=104 B=55 + RGB + PROCESS + 0 + 104 + 55 + + + R=34 G=181 B=115 + RGB + PROCESS + 34 + 181 + 115 + + + R=0 G=169 B=157 + RGB + PROCESS + 0 + 169 + 157 + + + R=41 G=171 B=226 + RGB + PROCESS + 41 + 171 + 226 + + + R=0 G=113 B=188 + RGB + PROCESS + 0 + 113 + 188 + + + R=46 G=49 B=146 + RGB + PROCESS + 46 + 49 + 146 + + + R=27 G=20 B=100 + RGB + PROCESS + 27 + 20 + 100 + + + R=102 G=45 B=145 + RGB + PROCESS + 102 + 45 + 145 + + + R=147 G=39 B=143 + RGB + PROCESS + 147 + 39 + 143 + + + R=158 G=0 B=93 + RGB + PROCESS + 158 + 0 + 93 + + + R=212 G=20 B=90 + RGB + PROCESS + 212 + 20 + 90 + + + R=237 G=30 B=121 + RGB + PROCESS + 237 + 30 + 121 + + + R=199 G=178 B=153 + RGB + PROCESS + 199 + 178 + 153 + + + R=153 G=134 B=117 + RGB + PROCESS + 153 + 134 + 117 + + + R=115 G=99 B=87 + RGB + PROCESS + 115 + 99 + 87 + + + R=83 G=71 B=65 + RGB + PROCESS + 83 + 71 + 65 + + + R=198 G=156 B=109 + RGB + PROCESS + 198 + 156 + 109 + + + R=166 G=124 B=82 + RGB + PROCESS + 166 + 124 + 82 + + + R=140 G=98 B=57 + RGB + PROCESS + 140 + 98 + 57 + + + R=117 G=76 B=36 + RGB + PROCESS + 117 + 76 + 36 + + + R=96 G=56 B=19 + RGB + PROCESS + 96 + 56 + 19 + + + R=66 G=33 B=11 + RGB + PROCESS + 66 + 33 + 11 + + + + + + ç�°è‰² + 1 + + + + R=0 G=0 B=0 + RGB + PROCESS + 0 + 0 + 0 + + + R=26 G=26 B=26 + RGB + PROCESS + 26 + 26 + 26 + + + R=51 G=51 B=51 + RGB + PROCESS + 51 + 51 + 51 + + + R=77 G=77 B=77 + RGB + PROCESS + 77 + 77 + 77 + + + R=102 G=102 B=102 + RGB + PROCESS + 102 + 102 + 102 + + + R=128 G=128 B=128 + RGB + PROCESS + 128 + 128 + 128 + + + R=153 G=153 B=153 + RGB + PROCESS + 153 + 153 + 153 + + + R=179 G=179 B=179 + RGB + PROCESS + 179 + 179 + 179 + + + R=204 G=204 B=204 + RGB + PROCESS + 204 + 204 + 204 + + + R=230 G=230 B=230 + RGB + PROCESS + 230 + 230 + 230 + + + R=242 G=242 B=242 + RGB + PROCESS + 242 + 242 + 242 + + + + + + Web 颜色组 + 1 + + + + R=63 G=169 B=245 + RGB + PROCESS + 63 + 169 + 245 + + + R=122 G=201 B=67 + RGB + PROCESS + 122 + 201 + 67 + + + R=255 G=147 B=30 + RGB + PROCESS + 255 + 147 + 30 + + + R=255 G=29 B=37 + RGB + PROCESS + 255 + 29 + 37 + + + R=255 G=123 B=172 + RGB + PROCESS + 255 + 123 + 172 + + + R=189 G=204 B=212 + RGB + PROCESS + 189 + 204 + 212 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 5 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 33 0 R/TrimBox[0.0 0.0 256.0 256.0]/Type/Page>> endobj 30 0 obj <>stream +H‰l–Ín%E …÷ýõ·RvýzK@¬F0bÁ]„“ÀûóÙÕ¹¹š‰¢t_×�Ë>>>Õ?=¦‡O�%}÷ýc:¾%iññÇËÓñkúûxxü¥¤ëk*Y[å9ÖàÙx¦×+Ó??½\Ÿþù÷¿ßžÓËŸÇÃ�¬þãõø’$þ$I“\´µ4[îUjºþuøŒ?/–­hº,VÌt‘™­Ê7ïëqÑ™Wmï3µç5ô¶ÿ4‹/=ûLMocŸÞöŸ&«÷ɧ]Î]%<ý~|¾OCk.�4¤‘ÇöžÇEjžE>:pÐ (Û"¡º²TL‘,‘«H ôJxÕraÚàÝ +ëO + k. Z»÷ÂFÑ×{^Ñ5â<W&_8CNÀɃâ Õâú­Yß í®+,p^‚°x?Sü6ÖS°Dö@÷^BF¯a«jØbAI¬Æ¨â+[Œ mêHoÊ:�õÍøŠÝÏ_+ÕBžG¥zÓAï÷JEgz¯Á>©çÃ1ê¨%Ðñ&ÄAÙƒ�²MÔÀMÍFÙ¦„ÁWs½Êq)¨K2mLÇñ +%T1 +â�ÞøP^µ@ˆNÈ®œÀð2Å(ÆíñGÈ­¤‰lºsËd¹9œ)Íi¯¾Ôv¸0A‰Œ0£J¨eßmà¹"b–}€šD¼Ã‰�FÀ÷Q¼ikÔ‡"B.ôá°uqö¡�½}[�K� ÞsÐó>U—‡‡®™Å‹>+Y�<én’Í“Âå0‡_§.ôÏÇÙäíéyÔe…F­¾¹'¥EýŒ O.7’µúía€®˜:YÈv#�åÈŒÐI:¸àä9ôïˆq¿Á߈hrm“ÄåY±mà á; 6ì&ÎŽ±„`¬`“ñ5q‡-6 ô?úl îîõ&M—CÐ’ýÒ7˳D˜‡Ü¦Qœæ·Î¹÷4ã“áüí3΋½ïÎ�žF虹ÍrîxOê‡O|H}>þ`Ÿ*ÉÅ endstream endobj 33 0 obj <>stream +8;V_XJJ#jD#Xd4d5+1SX4k?U7kXQc'G=>.H6q"@BLur1a^ul6G:$$B0#_4l*GRFZb +ec9[[Yo*>D!^mYY!'TMP[%[P_FB]Hl=l#A^/CJ)-5eZb/6L[pm(T]sucI\gipAofZ +ni2^*Z"gR?)ci72n@(8#s#g=>fBS![-X30TkI(+/ +m;(X,!3nPEQi~> endstream endobj 34 0 obj [/Indexed/DeviceRGB 255 35 0 R] endobj 35 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 28 0 obj <> endobj 36 0 obj [/View/Design] endobj 37 0 obj <>>> endobj 32 0 obj <> endobj 31 0 obj [/ICCBased 38 0 R] endobj 38 0 obj <>stream +H‰œ–yTSwÇoÉž�•°Ãc [€°�5la‘QIBHØADED„ª•2ÖmtFOE�.®c­Ö}êÒõ0êè8´׎�8G�Ng¦Óïï÷9÷wïïÝß½÷�ó '¥ªµÕ0 �Ö ÏJŒÅb¤  + 2y­.-;!à’ÆK°ZÜ ü‹ž^�i½"LÊÀ0ðÿ‰-×é @8(”µrœ;q®ª7èLöœy¥•&†Qëñq¶4±jž½ç|æ9ÚÄ +�V�³)g�B£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚óÈtÕ;\ú” Ó¥$ÕºF½ZUnÀÜå˜(4TŒ%)ë«”ƒ0C&¯”阤Z£“i˜¿óœ8¦Úbx‘ƒE¡ÁÁBÑ;…ú¯›¿P¦ÞÎӓ̹žAü om?çW= +€x¯Íú·¶Ò-Œ¯Àòæ[›Ëû0ñ¾¾øÎ}ø¦y)7ta¾¾õõõ>j¥ÜÇTÐ7úŸ¿@ï¼ÏÇtÜ›ò`qÊ2™±Ê€™ê&¯®ª6ê±Z�L®Ä„?â_øóyxg)Ë”z¥�ÈçL­UáíÖ*ÔuµSkÿSeØO4?׸¸c¯¯Ø°.òò· åÒR´ ß�Þô-•’2ð5ßáÞüÜÏ ú÷Sá>Ó£V­š‹“då`r£¾n~ÏôY &à+`œ�;ÂA4ˆÉ 䀰ÈA9Ð=¨- t�°lÃ`;»Á~pŒƒ�Á ðGp| ®�[`Lƒ‡`<¯ "A ˆ YA�+äùCb(ЇR¡,¨*�T�2B-Ð +¨ꇆ¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°Ž�Sàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r 9‹\A&‘GÈ ”ˆrQ ¢áhš‹ÊÑ´íE‡Ñ]èaô4z�BgÐ×Á–àE#H ‹*B=¡‹0HØIøˆp†p�0MxJ$ùD1„˜D, V›‰½Ä­ÄÄãÄKÄ»ÄY‰dEò"E�ÒI2’�ÔEÚBÚGúŒt™4MzN¦‘Èþär!YKî ’÷�?%_&ß#¿¢°(®”0J:EAi¤ôQÆ(Ç()Ó”WT6U@� æP+¨íÔ!ê~êêmê�æD ¥eÒÔ´å´!ÚïhŸÓ¦h/èº']B/¢éëèÒ�Ó¿¢?a0nŒhF!ÃÀXÇØÍ8ÅøšñÜŒkæc&5S˜µ™�˜6»lö˜Iaº2c˜K™MÌAæ!æEæ#…寒°d¬VÖë(ëk–Íe‹Øél »—½‡}Ž}ŸCâ¸qâ9 +N'çÎ)Î].ÂuæJ¸rî +î÷ wšGä xR^¯‡÷[ÞoÆœchžgÞ`>bþ‰ù$á»ñ¥ü*~ÿ ÿ:ÿ¥…�EŒ…Òb�Å~‹ËÏ,m,£-•–Ý–,¯Y¾´Â¬â­*­6X�[ݱF­=­3­ë­·YŸ±~dó ·‘ÛtÛ´¹i ÛzÚfÙ6Û~`{ÁvÖÎÞ.ÑNg·Åî”Ý#{¾}´}…ý€ý§ö¸‘j‡‡ÏþŠ™c1X6„�Æfm“�Ž;'_9 œr�:œ8Ýq¦:‹�ËœœO:ϸ8¸¤¹´¸ìu¹éJq»–»nv=ëúÌMà–ï¶ÊmÜí¾ÀR 4 ö +n»3Ü£ÜkÜGݯz=Ä•[=¾ô„=ƒ<Ë=GTB(É/ÙSòƒ,]6*›-•–¾W:#—È7Ë*¢ŠÊe¿ò^YDYÙ}U„j£êAyTù`ù#µD=¬þ¶"©b{ųÊôÊ+¬Ê¯: !kJ4Gµm¥ötµ}uCõ%�—®K7YV³©fFŸ¢ßY Õ.©=bàá?SŒîƕƩºÈº‘ºçõyõ‡Ø Ú† �ž�kï5%4ý¦m–7Ÿlqlio™Z³lG+ÔZÚz²Í¹­³mzyâò]íÔöÊö?uøuôw|¿"űN»Îå�wW&®ÜÛe֥ﺱ*|ÕöÕèjõê‰5k¶¬yÝ­èþ¢Ç¯g°ç‡^yïkEk‡Öþ¸®lÝD_pß¶õÄõÚõ×7DmØÕÏîoê¿»1mãál {àûMśΠnßLÝlÜ<9”úO¤[þ˜¸™$™�™üšhšÕ›B›¯œœ‰œ÷�d�Òž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª�««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½�¾ +¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäü儿 æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿ ÷„óû endstream endobj 7 0 obj <> endobj 22 0 obj <> endobj 23 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 24.0 %%AI8_CreatorVersion: 24.0.0 %%For: (Geoffrey) () %%Title: (未标题-1) %%CreationDate: 2020/4/28 上å�ˆ11:13 %%Canvassize: 16383 %%BoundingBox: 346 -1086 4373 1381 %%HiResBoundingBox: 346.440002441406 -1085.90124511719 4372.73776087041 1380.27267906984 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 14.0 %AI12_BuildNumber: 332 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([套版色]) %AI3_Cropmarks: 372 -628 628 -372 %AI3_TemplateBox: 500.5 -500.5 500.5 -500.5 %AI3_TileBox: 220.5 -880 779.5 -97 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 6 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: 34.7825975116702 -216.213424585018 2.27083790911365 2548 1324 18 1 0 6 43 0 0 0 1 1 0 1 1 0 0 %AI5_OpenViewLayers: 7 %%PageOrigin:100 -800 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 24 0 obj <>stream +%AI24_ZStandard_Data(µ/ýXÜ©.!Fð 9BkUUUU-Ö�0×Oãñª�ãüMß$µ<þ§hŠÅkŒd眭N)¥”´‰ì”˜ PpX¨ Ý öÒ)�ägÓÑÁËÒ§åçãU’óQHRX ú ¬ö¾åM&}äm’F¬xŸ_‘Ûg¡:lWD‰*—>.åu ÍTúx.¡ôñ±Ûáj�¾}$–Æp‘áHzÅì Ë*úØ$ÉôQ½ Ú�wÒûøüäv”O‡–¿8$iž¹êÏÑHK)là0t!ÞÍmNmmì×6ËÙÛìw�6`½b¸€@Á0\@ Ã*€A6” C + + �À¡B‡ +Åpq€ƒ+¤À¡Ã†2l`´°BÂ. 8`¸€€ p`¸€0Á�á¢Á1èÀ�cz¨àèA‚c°`Ç,$ŽÂp� *Ø@â ¯²­n锫ü%ý‘*tW’xÜwù�$ì  6ÂpÀ—£¥P'JAư�4Æÿ¦ì|Tû_t-§sfô~’F(MfˆèŽ°È¨éÚšt…µrºCâ¬Ì�U»vãá«p0 +Ï2ˆc ‰G„`@&à L¸ ž€ˆi‘ˆCdAˆT ÂFÑH0ŠÄ˜@0‘Ô/ áÄ{@ Ž(Ä”À…™!ˆ#�@B,ˆW!(‚ œp$<á @dà„$ì  c&¿ÌaÌtõ²HYìeöv“ãÉÎñòIn¡œÑÉ”]úG†ÄÎý‹ðîh™£Ìe5yþ˜a^M.�TòçÇHfêsÞm²¤c%ÞN渲�‹Lõ^ÑL‚ј"¨ìù„Áh úPÓTˆÅ˜_0j‡˜šÊ3¡X0 +DAWFÆaDX>¡¨:„a¹] ŠEb s�ÔÄÓ¨�i$ﱉ¸žÝ‘@C(ž ‡D4��ŒD2Ô0Fñ H,j".Æ1œsÆ$ˆ�‘ŒF# C'èÄH”AH˜Ff$Š#¡ A°‘ÌaT¾ßå_u)sœ½ ;‡Y–F ‚Le‡¸N(EØe¢�¨ÆX Qs^±hŒë +o "þл +a‡O �‡O�(;LÄ‚Ñ(„)ì† +ƒÑ0V±P$O+rŒ…"ñÄ3D­@�¢Š>|�#o$®ÈD`ˆÅÕƒ1,�D0Ÿ# +DâFóÐ`,Žh‚nqC”•û�È:D=0OdO¿gã“p¢M¸.�Eâ‰Db.S\×W|ñИX0†Qk´|‰†íþTZ¢}¹Ž9�I=Ê's UÙÇn«O©Lí™^žÕ§É�ÊV2wCÕÛTžoî®ù9Ó4æD¤B×_Æ8†‡‡x.“¥¤¬DXZ^.ã»n¿ßñøL, @ÌôaQC“ø€Œcšq·@à¡QÖX$Òΰ<Œd$1Ìpc�H-U Ï¶#Ó(ä±�6úUþ6+’9Ézö™ò1eŽòåÐç2•8÷ÎËF渤V“Lh+Ù æ‘ =c…”ö¢”9�® 1g:š››œOb³Æ4‹Ä"¸¸…-ÜP(Œ㌜Æã�Ñ`0 †‚qF2�qŒc4 E#Ñx#ذF5¨áFÓX¡±PLç‹YÌ¢”g$ÉS£ÈFÄ›d|œm¤XÖ“¢£m¥wÜa'Ï�ÔêqÇ\e¶u9Ó¦UÅ,×¼NæpOshÛÕ%ÊXé¼Ó•G™£J‰wdˆo¥ ¢�‡„±@0EÔT†À|B±`4<%„Éd¢¤¼‚Œ5è�hjªÕr!\TTUV†…¯D%�z¨‡«Õldde†·ba k؃=Ø\ÏGvwxy¿Äâ׸‡, � Tàø€“M„“²Ò3ó™HE.²‘9ïéu;>ÿ'¾8ãŸD”¨„%0‘‰DB1Šž�Š+ŠEO±`8g( Æ£ jXo(ŒÆC£ô`øðÅ�(„ˆD= Šcy²±H "Œð!/Ë÷`·ÛÙ¶±1ƱªªÜ %Îä2��ÛbŸ´±)�@$¢ÁP ÐÌH, +Kõá�E"�Èc©HÅ1 ÆÁ‡{¸Å).�t>£YˆhÔƒîË@,ˆÄ‰ˆ"÷ÁXàY)H�PÌãÊ“@<¼ÁPüÿÝ|¿Ÿ3R‘‰<5�� L ⣰«cØ"ÍÕx%¢Œ¤ë 'œsçØÐ�Ç@œ‚\Ä0Œ…b�Hà˜ÀDÄCCÂâÃ5Žq‰ûåÝÕùº0E¢¬öP 4ƒFDC 3œpúL®²Wjû0ŒI N�í˜C33 àÐ`(,(,(0\@X@�áÂ1Óc츣‡ñî.¯ès×[æ°mfgf’9謎3{•$ƒèb† G%ŠÄ"ÁH4ˆ‡Ä(ª°‚¥0Å)P‘Š+ +…b¡`(ŠÅ,ºð‚µ°Å-p‘‹/ Åb±`,‹‡Å0Ê0ƒÅ82É8#ÁP0 £Áx`L£ 7¨Q k\Ùx#ÑP4 F£ÑxhÌCü@õ`÷€ùð‡ÄƒâañÀxh<<< €„‰ÂBÐT!Úh,JQˆL¹a†V8a6—et‘°Å(&‘ƒcUÂ×›{°†!¶0…%, í¬¬Œ¬6öP�b”¢õºº²ªrµ¦¨A Z�‚NIHGFE¥¡#fXá„ï4úl&Ûõø¡�.ª¨¢o{­RÝvú0�aŒbóÁ¹©¡1"ˆ @ 8|Ì�@ Ð`‚8pÀ@Ž´ÀAä°Â8(Žk + f�:£€%æŒÂhha +,p¬ 6„`-¤@ )Ø�– +„f4¨ÀÂ6@`ZHAX¡C @Ð8Ì5BÁͰa'HalPA…vdBÁna…Ä Q˜óZH�&À�*tèp›B£@U*tèp�c, `ű‚†ZH!ƒ 4´À , A… ZX! +à€ ¡`4 +„&`aƒ +>`X ZÈ á,¬ a-hà�‚ + 3 +mK(ÔÎ(¸t¬�‡T @  +‡F¡Ê(�–Q +w„B™P@ +UBÁE(à¬Ð!8phX!p‚ )H´ŒB ¡0F(Ð +=BK(+¡€C-dÐ@‚Là�†lX¡C 4d ˆ!àЀ  Ã + à°A(P�RpØÐ‡ +P€C `8 +ZÐ`tP¡Ã +à°A. Xh�ƒ˜ Ã. ,™‰ÀƒËAC -¤ Âƒ«i=üýñÛIÉ +,à˜é8lÁ†& A)Pàª@Æ pÐp‚ ”ê¸ìQ¦YæÃŽÚÏ‘rÐâ#;–V.ªåê¼ÖðæD)Ê@‡ pÐp‚ `8 +h`A +0 +$�- @…,h¨@ D°B +h +*<ô8€ +@Ð!o@â⎰ÐÂXAƒ +(¨ÀL•ZX!¡�C P�† )Ѐ/ÀarÄc2m6\ ‡ÉŒih!N` @*À‘¾#}8Œt€…¬�‚ NÐax 2pB dЄa ÀP, . æ8 "à°¡…4X@ƒR0A0`Ç4ˆ 0€��¸€0Ñq€4|À(�TØ€·‰-¤`‚: ¡…:l@  <=`‚xÀ„РB .páB8À +„ 4, ÇVèðp6°°‚† `È$.\@Œ”T +th!…Z`*¨Ð€ã8À +ZHAà +‹ Ç@Ã:€ Q P®J«ò%å^O÷鼎§”Ž«*É¥‹e(´IaÏX#‡‰=K×;M¦ôªÌ7X»ŸáP�¦ìW»4K5Í¡ÑÍ�à 摚û”UfZa•ÍCuIT÷_eÞ|X•u¥CÛÑòr/²šXCÁúêF´\[;­~ä*»QË&)ëj›²»2¥Fc»«´6×Ê{ºx¥'R™ÈÌî?ëd¹,‹°¥7oSWMjÖÝÕôÝgdEÿ‰Ò“®ÏÎÖ8›u{íÖ¤ü%Ö]ð°pZciûYvW¬õöÖèT›ò¬½DÙØÌȪ&?X�È–HfX»6…%ex®Oõröaøîv’”åԳع[™�Äf{•HêjGǼ¥G²£±;zýPÆ|¾|ö±¬]s’^4sgÐküaáäGÐWT?Oâ•n½u„XuSO²•´è©9«™,ëU[Ö½†èz—õ³-4•s¿þ7ïØóWA·÷*L3_Ó‡ãûe›veÛ¯4òüø¦ûä�Xy\¯ŸÝéŽbÔ)Ó�ïþ˜LUeû‘tíNUs¶¬O}Yij»]kÍ©»#»K³TmFxŸ²åõªg}»šlöj4M£šè¿¡:¡‘˜í¿»ã›mÚí´Ò}•­—|ø�¦¬wý/æ2KÁšº>¾Êí²¿»•]†^Ly†Ãª»Õ'Sµz\w³AiåÕ%Ý«5äVÏF'¼Ä;Þ+øûLfi3YeÀœü{cDÆw~·K™YyK›¼ç[×›B)"3ëT²Í›–•‰_œÌ�}(8½ž,¯Ü'á=Ÿ•»wžî^w„¨Y>Û!uèŽe•«"]ÕkOUÝ2ÜÉI$¶oÔV}ΖÚùÕ])»Ð“3…d§�HO2Þí¬ÌHX¾ÕžjSÝ<É&ëE5âñ¤±rü_YYmæ;Õ%Y‡ï•¡üA¼£�‚î•Þm(%mÔ*Þqpdè¨÷žJIåëé½±W„vwÌ’˜Šá‚q\�‘Ñ`oòŒìv&­öœº¼rzÖãvß|8v/›I¢Brùèt�³ß4ï•e9÷ ÖÑíy–ƒÍ«ûÊk±ò¾§mrecœö¨2Ë»›ÇRêa+y°-Ý=ç¢y6xWj¹)W'Ïd2-TWféÊuçìêÕ2im÷ñ‹žÚ3-…2Ôýô·¿|=]%Ù¬š{ŸD7ö²–Ø[‡Ô×iœˆWSW�ý»îzÞRÌÆ�åIÙFO£"ûvB¬›1åÆ×4ie´ú¤)ë÷ŸÜ˜p³žx#4Fjëcd'«‘ʺlÈì&_‹SìÙí^BXê&ÚíÆ™ëïîæÌêCä;º•WOsº÷2ÅU¤©©Õ«««Ë©ZÖ{æœ�••3çìv¥6‘æÊ~3(Çfbšì÷¹T¶dŸÎ‰e)é¶ÝrÙ9#ÙmX¡¬�Æì‡Mêo°5?¥½ˆ'u¤¦�ª(v­}ü”»šýˆÛ²Wù¤Ùœ_Ùžc•Ìv®°öRGúÞhZ{ÏLè½ú‘Iî5Ãûë%É—Š¥±ÓïäÞÎX~æ$ÖÒG0Ã]|Κ*чî¤Ît«Ã7møÿïòNuK�X¯UÖ•íÉ,ú)‰IV–g¼<áÝ=œó<:aS^x72®9åÏ<üiáÕ!%½Ž.T”wttëSjžn\©cõ$ŸU#¼[)5=jò*-s^až ÖÇ»’â$ÕÙóTb¬�„°—3sv¬}¼MK®ÅÛüäY²×^÷¼�-Å®Ù^y§–¬jöA3AìïÊ&ÖÉœ%$sÙér¤Ùc‰a_Yˆ†WÄzçŽy&h}§ˆÎª˜þܽµ¥¨Ë9R÷ʪx«�Yòž<鱃‚é_ɼŽHü¡{³Hî—r¯Ÿ,t§/ô™¾l6ʧdçÅ® NÓb·°éß'oR÷¢Á#V ¶wÍ»kéȇ¿£ýäí�Õ™„\¬¹òŽ™—ro‹¹W¼Bs­ðƒ7”/›ÝûUÝJ¢;R]ªŠwj›­¦º§ÉÒªÑ�l–ªæ É«X³:�íws¹³}Ä·3¡ ff˜WšÊ¢/ËÎŒgw‡¤ØÃðN²Žã��°GÚ+X“$VÇÙžVXµŸËâ·v³´Ð᬴ñ4E9MVÞIÞ˜ÆÛI‚Í—ðµ�ÜôHLóØiærïÙ¶±ZŠÝzEøÚæW9v¿veñä+iñCtqÏuÄ×óiÇ̺O9í¥!±ë1ø+›ю׃ÎäÈ�â ¥ÚB;ešäu~Ôž•ÊX&é�7‘jï¯Ä§NŠX?˜(ùöB©è +NZáozU}õN/nщ\N²¼z&’L} �Žäøp&Yž_÷8eÆ7~ël�üÑÆžé{#¿Õ¹¼Úî)’gã{¼¼fËnE’f�Ïâ­ÊÒöÀÛ˜Ùé®öè{S¼k&Õw®‘ä×Ó“y?²¼×ÙÙ“LD–f§2”ÂÖ&Ïd�cºÐõÈ;'UËßæn»¢ÑNŒ�l¼[Êm"B"´±ÞÉzXÙ™ð–=p<‡)tõKý¸cQÚé˜RWxÔéí®ÇùNòÎFt|Lu֛ʯU½J™ìñÏ ùHë-6cbvÜù½úÜ/®áåw´c™u;,ñø(cñ°;ö©²à{TæÈ¡eó7ÙÑhRYwBÐÛÈ�ãS0CçZ¼ù*ek� ÞgØÌJ¶šFÌŽî•¿ÏÉ{‚ÄÑ«^4™ ”“V7¬IÙjV?Ä+Y­î¶‚õAÓ²·.¦“æáÄWÕÇå=úJ9;ŽÆ;žÝÑÂ2×Ñ\‚.²)×�yAû¨™Îìú$š¤}´òfÜ:¢¡˜ü æqK¢Ösj1ù £ÿ(|M4™Ü�<º^H%g#‹ý°æ¯êã^²>,ÇR?þ_ÝX×ÇÝÑö‡õªÁñ;Ò<¨j&ë-§Øø(¼åwXÕ*ëW6RãÃtö‰Õ63RvÔMÕ§^BvyÒ•WxGbY¥mf~û�ìÏàiæ ,J3Pšñè>·º×]eŠJÒjíNÝ ­ÄÕƒ¦#•t)ÎÃé^Lª>O,Ÿé”|Îáo½JN�bå�Ù͵¾¼ž%Û�{síáÂ2¼]I:ÉxK“|zÃ£Š„ÑO›e9µWHwX=Ü<¡;\›{7% Y�K“ÌÕK·-ßÉŽ’…‰sy¾åš*m©Uî �C®˜6p ÇCÐ NÐa��Æ"€�…¬�À -¤ á*€�…`Àá"¯’-[œÁVWã*¹?�ïê‰=ãûgr¥s.…ÇíßSÙKåc…ð(Îí=þ–,9é„ì¸{‰e(“9;]$záI|iD%:�{e™™NÍŸ ÐŽZŽé8•’Œ`¸€Èp˜lí¸aöuyRÓÑÃÃ’±?¤4a¸€È`<ì� {¦#)�*±G«ÅLÇáK0êœßSÎÉK6ÉåQ”Dmé8]*ûÍŸtè ©IÞQ3ôóËòÄ&ÊÝatÞ}#Iô‘ö“º£²3DÏÖiYrxœ+hH$yÇï‡IÏ#‰ËÇÙ ÔYwMÝ>)F>^²œeŸRJ‰òÄêháT‘�žIÒQ¤³+9òAE£ã.§'Iú@�!–Lù°:©�ÎÛÓ™ÂèÚSG¢“#C™棙zïH�|ÐÉ&uÜzyº¡�$ù¸¬UZ€ª¹Òèˆw!ó�UiÒ#ëTD¯c=ûÊ�£™>ÔËÝ•ÅzÐïgzfKî|xnÅ4½Ð(vÆŸèƒhÒ££’HZG­¶¢û^¹ù(,“«ó碓_™K²`V½æ:.]°Ž¾¨LŸ³<Ô”ªÃcÓ›­üjèätU¶*ùï.bM±:W¥âón¡ö°Cª%ÖÑ­‡ƒ¯ ÅŒÌ7~~)Ö,¡™ÁÁ“ówùbñ‡–dY4<õU9øNËøœ,Õ1æQg0ÝÎíΔCxw‡­Ê<)¶Ò ïJÅÖXâ]i°5Ö<’Ò`ëçCÊ«±%C5‡­OÓ¨¥ÄæØ¸.Ë�Œ\Y7åsK´œ�¨^hKÙ7:“^³Œm\bÌš¹~–$˜’=k}n’Rš%#§©÷”œ¤C××,,U§ŽçËÑŒ�¤©?^ºS/Oˈ…'é©'¹PÒ5SÇ)$×ðÒý” æYÙà)éSˆw2«Ç>µw“gxu«šáݾ×ÏI›$š¤§ÝX4“%VX„’ä!£ÞÑð$©Žtª]éÎ$í£á–ê¡“¤>¡sÒ6¤“Ýdå8¹ÊU©HD,:×o˜‚s{‚‡‰äf¹óÕ¤®gW8s&ïQªAc�¤TÕt®{Ò•´°GÝa-SÛ2ªk•`Q�‘ v|r™‚¶Ë–Ñ¿¡ÒY ÙìûËw·›4�%Dtvßy +¥>\Jº{Ù©>ˆ~ Q[u/[Ê”ùtE=»¹r ³T÷Av£ÙÝGËQÏY]‰)¥£>‡‰R_Që$HG9‹n}›¢ÏýÙk½ò9ìÉø12b?u_i� i8¦4U†Ó™ënï²ØÞw•î�®$i$É:fINÙÙ­²$XGÕdΫ¯Š3é^\Gæ-¥�:~Ë,“Öq÷"¹òQõ—]}GC2wy)T;®jyR.ú“wN[RIÒI3nÑÔ>f%ilI:1ÏðÒwÃóœmÍ:LöÿN„(™Eeƒ/š“ë¯Lê4Ýüì’±ÃhIELÌ?ª#Ou¼ä`Í�æð¿ÕáŒQ²%©:�fÐê(V_GQ–|:Ç2æqh½)ÉiæÜ¥œ†cv9)ÅÛMÚÝRˆ~ªšr]n‡«ªèî žZ×:*$ì[4]Þdk—dÓ*i6Ç!Ëq¤H­ëؘÄî8:Ë—Gï„s2æ’Ö�“Uóôà ˜4Ù{ÿJ[Ÿ¤‰Wõ½†HÊSþFæ§é&¾içyâcæ%¦øòJ¢´‹�iÆ<;]å/Ù‘«ãvôÛqnE9oi6%):°FSG¬Õi.„Óñ¥;)D½²ºÉK"Lóßf½LÒL\¥e¹)i« ÑѲÍKê|kš:½«”ùÖ÷š¾Ý(‹Ï‘�è6u¥|xèè’z)ç£4ã9ÏAhÄÃ^ŠŽìëÞ�jB#æÃžªž­8G·Ó§R’WÚq†¤ˆ${ �›vO¢ØQïî\­ƒG‰§—MöÆR¦ÛGš®ÒžvI–ÔRR¥Õ‘åý´å‡õâ‘|F�ës°äSª Xò9I<°ÌæêònŠÎ¬ ÖHIâQ4„Vï9¥žWù2Ì«ÛËêI†bY,«Û+ÅzT¾iÙ¹œdõ¡±Ü©Gè¤Ë£õ¤3SÞ¸•–ÌÄ[íöÛ–©Ç~G{[wY4ëvÕkC¹5X“eú4³L^îÚÔ?5®×1k™qUðU¦R~žþð\•íuY²òæ&ÓòøÎ Ì\¢a;˜'³²}l,™ÆI3~N&9“NÁ¬Í†Ìl§l +ÚpÍ6cΜ 'kF,2ã�Œ’s•gþ Ïv<‘`RÕ†ìg•UEM*²iÙ‘ð¤yF§Ç�Ýö±–ð¦ÌNg“ÃvJ¦ðΞ“bUiÄÐè–�ÅGU�´íOŠŸ©«ì™ôŠfŸìO‡(S¬ã´¾Õp�Ìï&ÇxËšLûë!Ö8µ¥ÝøVÚŒ>yÒiO%”›9Ú Ÿf(4‚·2™©´ŸkRw&ÿ‘/´Þ§˜bË·…÷U‰§WfâÁëq +)Mz”Sx»š©:ÏaIjÍ^]µH<ػٙ¤v£¹Ùå,_â«í¼Ì¡¹·,”5Ë—dk÷DÊ<š¿¢ Õ™H(�ÊÌÚc¶ÃOY­'˜uC3£ UŽÇeRM©>Å¢o]x'—F{Ú,o±h·bZ �_f%Ë8æ´«±Šáqg–vï\­Ž²™6bT7fÚµ,ã{ŽíŽ3“wUDiO7ï¹ô¹þ± 0™5g»ÞŸè!£Í!ð‚07`84-pÐ�a À`‚ Œ±   A…¤ÐÂ4ê. ‚`A… -ph€ãÐa… 6`h! 0‚@°A6lÐÀ TØp�4TÀ‡ñjìN>’¤²@Ã0° aà :,0˜`C.Éä¯'=† ˆ øJM«Ÿ2ÞY˧ÒD—8+Kt±4L“²[Ì*g#h5EA³ I;RT9¢{ÊõÅDŸdIÆ7>!¬Šñ#x*<ÖO:Å,¬‰¯gD)i‰çAq^¾Ð’h¥:ê"�TÕ‘ML>Êg†¤\Dbt9Âp‘á®’u;©³VŒ(…—Ê¿oöú/m1\@d°$ÖÝrœLDiš Qœ. ‡¹Fæ…ug|ÝXrJxô»!ü4û*œé‘Oާ,),É«é#·!“¬¹T!¢X%Ž Vö%vä$´ÊàQÓær(M¡ÌâÈeJ3ïÆi>²Œ3Ð`õ…>‘Ub Kv¤#±:ö.ooø’Ì].kž©³ÓÓÄhYvæ vu÷¹�Ê7hwÞk¬?÷g¯™ÉP ]žùÝh,ÑŽuÊ5í‰ubÐòæ÷l!æ�,fgo·š4³Ìô½–öû+u‚î$"’±ÈnÄjªšR[•�$oˆÊ/–üèòæ4dþ}ÂJÛó°0ídÈt•Õ:š®39%�‹ §¤È•uVÊl|gíüU¡¬*q´)ï·zÑŒÌ++ß:(chÒ”xsÄãÏò%ÙdΡ bÙñ˜Ê#ÓcO+WÊb9cÃ{¹L2Ñ=Þ;‚nV~íHUâû(õÜdt™w"³P&åÝd=K¥1CqŒ2”x=ºOùRjÝç•Y?¼‰ÉS÷ñIlITÓV(KìÉêßq.3ØìªÔÏн钫¦›†¿“‹rŸýED2èœú½ø‘úÊYõäQæ­Ók·gÀϵã3ËNõòˆ.­îüC·—lNm·£É³l,¶æY½:#V”ÁÈRr=D­ºNë¾,!›Ænœz¥ÑS“ºÌ†YY5(FÎÒœYÞÐ*–ÁˆJ°æI6’î½®Ó5ÉCgħÝYõìÅ›�Ùqޤ0C†s«lZSÖ d»G0;å4ËþœF(”-ÒÑF,Áß{$«rR•“nÕ*gæÑ¯œòª5ÞjæŒnó¥ÌGÏO…ÌiµºÒΓÛ4t•’[ǶBäæ%É9—„T6›ÎÌYd6:óçuHRæ–Oõ;y9§G7òYJÏä" ¡ 3Ý4âÐ1=RhÓó¦’‡3½‘ùu)©Ê¯)‘ñçë ŽÛÁ}WìMÓxéÕƒuÕŠL¬+©ºi;ñÄjCyòf�¡ª©ÏŠÑ�.“Ž8cYG,5�–,Ϋٽ:&G®ÖáÝýüùý°HÈܱÂzÎrlIdq]ço´ÛZ=-X'•d»Û—ô©zkHjwΪª¶¼±ØKõú,5>IkÖteFrv­®u#ÛSŠÜÌOkÐÄdÚw´ª»IòÚpÊìÇh/óɳ86U;úHü¢Ø3¸TGû¿³33¹n9DuxE7Ë7uFs?™:±ŒÇªÓÙÖ:9KJeóÛñˆâ*¼�ïu$—ü®©t:Ïií-/HI™b›«]VÊ©\—39±(gºŸœPˆ7W«Ž{U54¶ï�=SÆ�9˜ýÝLk°ÙZqн¢õ~œÕàYN¡UÓŒölZí6çZÞ çÐ:EJšÎYyŠž*æ1;X³)þz‚fFŸçΊk™Ê~6“I£«¬|n Ñó3”¤ôáž ÍðÒÎ2I¼<ú’N,ŸõZöú»©»ÄJ+¬â%9›ƒføÎëâÍ©æÿ”™x>ÌÌú¤éšx>?Ë“Ç;׳œ„dˆžú©E<´�,x­¬$;^ÑõñR®UYO,3=Ë–Te#˜YWS3¯N]Ѽ:¦³yuŠi6¯ŽïhŽƒž”{_6wõ4‰ðS$±¿øÊ›×^¶f×°&ËÅ[¦{<ì~…^|M�.t:ªÂq©fìyÌÐy9�ìS÷œ#û%õÈ-±G—72ÊÉ32JÃÌñkGÃʼt>²ÝFOÉdÇD_¶¬*{C˜ˆ—g¿šyos|÷ØÜëÇíõ9Ió°úÛ¬½éÿ…·¹¿f‡Tfº‡jgtuWúYÚùV»òÉîG¿ßkÝa5D·9›Î펓‘>WCÊãî¨æä¬Þ«¬9cN³g¼1G^fÌùÐQ‘ÚìqŸil.Î¥dI«ÿ²¦ñ/õ/m#¦ÍF¼$ü˜ñSw6~*�\CÓÁ[Ó•gÓ‘RúÕ§²Á³ByNbin®wCer}f¶�&K’޼~ä|9:æè$B:Ž6–4&T$«kšMÅ'Þ¥ƒî\|Û¤Ãj4¿×E:£ Ý݉ШÏÝ‹úß®ìN-Užíª®†|Jªº)ļSžŒ¡ï®¦ ——Ö*�çêì(Ýwe‡ÕõjS3:|¯Ì»=¬,ê´.ÉFÒ£Éñ-gHNÇ­ÇžŽ´boW™tÜz-4);¿¾×ÂGÞáÍ㞈¨ùtþóg4YrI:o9rÄ´×Ý�—¢ˆ}¦ËdÒÄé²ÉªISÙ¤1‹2YHe“REgÆ»nÑçõ¦y¾v”h$´¼'¡åõ@“¤¹V¡¯G�¸3gGZ"Ι•ŒU™¢Q%«ì~ë Ëu7Ú¤®Ë›�\WeãºVŸóË9)GHD&vàÑœï%Éê�ÂÉ{ÉÍ}WRU<ÕMu¨v™=‘Ða$FõQÚõ,Í•Y3BÒõvÏWèð‘5óèÔá]É„há±Êª¼‡e‰�ŽÚdÕþæãë.ç–™VÚ[Ëã‘h�”³³;Ž5ÊÞrqTyØÁ¢TbÓ*­ø©A<_þÞ~êzFè±õW˜'»Ú^…Tö]ѧ{GÓô×zâkT5I#¥›bÕ×jµ×zaUJtÕk•ªÅ*��3C”BS$«–Óu­bRRÙŸTC–Á;}.Qrêç´#ÓºÛ•‰‰v?§¼y§L´½®’•|îêV¢©ëÔ´y;é“dReBBK|ëŠÊF²²©½y»,�gŸëI)>×Ýs½¦¤[I� +?FÃÚŸ¢—=e®÷�MD–GgYG…ôÞ Ý¹H2�¢9Ï �žG$U?¶.‡zËå¹Ò&Ivb&½ãbR¡Ï,‘*«ò¸ËS~*ég“Bev?%e +•)?D9µÑHåa¤»� ñŽB{¢¼sX�øÃuf¬×%ÍÄ¿jåYï«Êd¡´™hluE²góþ]}i?�ÆœC#ÙNïZÒx4�àÜ®Z󱊽¥¥É!¥ÜÞÔ®iwÕÞý¾¨øIJ4›Þ…Õ£¶FÌÕ8-¬©q0Ó5âàÔV:lh!…:TÀ(È�!¡Pà‡ +´` *@ éœãÄiqɉι´œg®ê5Ö)±-‡hTõ*C£"×=i!;mGu|��}Ê#ç�ʶ¥UÕ·ãìl².Xw«Ã&Ͷûò)6k±Ž-’Ïažo²l*§Ä©nÖ«ÊÖ,WfÙJ¥!Z)±ðþÛö9Š–Ýx™ûÙ�òîê•G;ÃNÚ]±&íÎ'­1ó®sÇëðz¿ˆ¶£Ô41;ì¤I{ÙT®ÐjhÒ0­t™~�ÓëÍ4ßá¥ÏƒÆ´g¡½WL{æQ�-UUiϽŒJÐJs5g5wÄ19+ÝœOBwVY6wFhsr.ÖÒæŽäªw3¿¨‡K•h•rtôsT'“Fˆ¿¬3ã™±¾±ìCfgˆEÇÙ)o®‘UÞ”­¶gçC–uäæ‘ÉNT%•¥$²»dR™—2"«¼”‰Œîre+MV‰r¾ìa;+²¬=1¾³[Úlì>B±W(m(3ß Vúdü!”¹ññ$ì% Ëbéä™L}äÜþ‘ë �rÖ”CÁ±sèeõ:ÈÐ~¥ºk„¯qÖ\56¢“Ž2íe,÷Q/¶jl¼V’YN‡!åØê ¿ŠˆUxÄ©§íVNUqêxxD&98UvF¶:)×�LŠl»Á¼km9x;lÐZu¢ªuJnŒÈæì0N� kæ’9æƒ?‘¯G9Æ£~ŽŽó¹[KF¶:ꧪ_�f†l +ËϺ©’Ú(™c’Úm-5"V«ŽsºVݲ#µÅΊÄ4›Jé¸Ì[{Jk%}P ölð¬x,ZÝx”ª1Ѥê£ÐG�‹l2ƒ.¡³Z©&_ï_$©ž_¦e�ÝѳHòF§»5òQDB?<‡­Ý„:ìx%D¡ã.³sO8ö92“ëaEy2±ã‡He29sTó¬L:gŸiY×â Ýˆ.?ÃAìÔ/582Ø;Ð.u/ñ\<¨Ó2;æ˜Öf¦”³’GtTë&GÎç¶æê‘TZ]e?{ ºeÖVç´´o4¹;®Z8•sV·É:¨¶Y�Æè©liCD—Ut]|ÓPhšDÕ)+º-¢ÏÑ„Ž¬xêOÜ2ʼZÑ©sÚ(Ô^ŠKmëèJXó ‡.}e„·›J¥oÄ9•¥…Gcž�qMâ�qZ"K+«ñtÔfñ̌ǜ‘ñ�èuWÉt–oÑEK£²`ù’~éçÍœŒ0ov…Dev•^ΔÝó «’ŒŠiFF7zŠÙ”�ìbæÉ(ÅÌdT:ª�ß*Ò[F<5±rå¹´â‘�ÑRæš•¡™ìŠ|d&<Ã&M«?º"£f{Wt£:I›úQô¯(Íô½.�ìÀÊñÀžæ'LëOGW +’ó&© �ôÌ»»I!<ŽäaŠe½vkB?n¿zRr¾M8¦zÙiú”þ—¡§š»ÎW1Ÿòêª2_V7›ð(³ªÛ=1ÛuTÝL%ã;yMû‘XÕÓX!ûY•hUãM«d•‡Fy.4ñÄæÔaâ�µÿá¡LÍ9…7I8c%Ø^á�YwHu›9±M3„7ª£o¯íG-)¯^5W×|¾"4¿1´Pê—ù†Y¾Š«€‹[ø�"&–Yè%­ðQó†Ä^ê¿Àšår1�ëÎyõõÝ>XÏ"FBœÎ‹•å_¼q›¶ëÈMŽ z„… LM¨i:ªh!ߢË1b.çÕÛ¯n�‹å•œÕ½¬~çÌtLAXHZ¦¾6Í2C’FÅ,õ¢V +ÁoVúâÓD!Ô%Rgc5Ö—(½h’5çS9„]‘¥µ¦¬KC>Ý"ƒ…ï<|1M�ÐZô3¥²½¿Ÿ,èAÙZ@¾á—ÒKÒr«‹"GÛ@fTÉ(ÓÎ#Æãiö_ýÌyT¿ÜJ¾»ieWÐHM‰t<Êyç8²ÔÂþEVøÌƒŠ~ Ü¢‰z_1Ьœ’s•fKo×ðVe%£ z{€Û†ËýfRÀöcòlBB_¤ÞÝ™v=QQù×LE Ù Ä€Í ºÉ­88æò‚dUÛbkeWþtF7óÚ‰ï"p®€Ôˆ•²øýédøW y6[îtH&\À åmóZ|‰çòضڂ2Nù¨}¥Æ€ç¼›•�Õ¦ëxŠeÞE‹=œè Û¢° u#:­¼\ˆL =zÇÔ½®Wƒ6¡�r¬&åËæW¾�ƒ ?Rb>{waú¦ä·¨7Þ§Õ½Žuo…d èõ;Ž i“7…_J©OÜ©°Fòl&)mjlçÂqòcdZÄ t ëhó®5¹ðæð}C¶ µÉ•ïAš¤S´@ª¯ÜþΧ Åš%Ä"P?=”iÅÎÐá�ÁÒ&;xd8p†¸»ù>�‹F¹ž‹¦ÿ£¢O€�eÜ%!È«òõe<þEÝÜÞ‰欰�cw$�:‚R¯�ù6D‚@ë$PìßgME¤/Î@Tï°Á£\6Þkq©&‹1÷Sͼšý¨þ îjàó<›taD9eis‚6¤½2šÚÐ%Çc5ëBà‚þŸ(QH0*R‚ ~6v#XøbF�P ›Áktðd +¾%êË1Ðã›ÕEB]×ĉ®|Eƒ-›ðsízrÍÍC‘ô†Rì§õ�ÜâŸæWø¤k–¤?Ñl· 5¥Ú÷¡>LŒ&EÁôö+aŽ5z�ZR‰�—$©ô«ëà 2ÌaBù<^ØÔ,Ñxà›kšø·^›[kЉãê×úÊÍ:œ¤5»üQ?ð&Ï')0$¡�z Ü¿ºfé afÀâ6@�ó¸¶f\ .I0„™€O›°¹P¦Ý<ö úÃi‰ñþ&…rïÂ_Ylõ×õr�^¾c<�>ç@D×’»q° R�‚A=€Äjæ@Ò=²_LêÅÝÏ*=º”EP¦÷ˆ¢ÄƒïÅ'y¤Öž¶ŸŠ …Ë=Z4N’âDz)''dRA|�*Þ;åâN§Êõb³1?¬9¤— +^@|PiAÐî­É'·_g +{�Ú#@'RG´^æÛ\×¾¬—”Sáq =iûP‚Tßa b59Ú¸?«+Oý¼¤9ª‡Ò8TH®1:ìY—êpW_ “s?@˵’ ¨†SŸsȪ^H{³ÞQ~^ÍÊ|u˜EYtÞŸÿ!qW& Xô‡ Û�*˵2BRA!“sÃpÂ+’È×¢ÓªÕöšcÜäFDº›ž÷_Äû·Š9gÿÀâ›zÐñžÛ)NÊÇ)å§¢–ÕèB°yÜXêèÝ4ð æˆ€d´®â#NŒc•,&Ä68kp‚˜ñ—šöpד5™q‹Ù÷j@iU­aE?]Íú¥J¬˜ÿ}±¹úT�%�ßâÖšï?½ü‘%Di°? øúM‘\_à!K3@^Ög!VAÈ$3<*‡žÞVT°îÎýµbŒ%,¥Ë(ߟ"5§=[6"ZŸ#vü'}q4¡ žO!  +Œ"ñ6�ç˾ÛX¥2þ1PŸÏ Q\²ã¾’žŒör|Ó”+ÊÞ0/Jr 71~28¯¢åZÏLùszÒ¦µÞ9aOÏŒyø›ôËç9Gžø —h8œ£•—a“à�a‘û” 7 Œs¶œŠÖœQÌiVe +¿’¡3jÌ aã cR@ïáÖÅDf £ÿ;ªS�½”LøÊ¿ì ´b ÆÜÁ/ª¤êŒéóþ÷¯€1¥æ„i»‰“²µt÷ÁÕùc¶éd8²VÂXÅÛÚ–ƒ†À¦“ʪ‚MF~#CãõZl1ÚYI¿{7‚„¼Š“vûUõ÷¾/èI²{ditÞE.�_hDoŠƒ”ˆãƒIŽ,¢€ÓQßæ�TB€�š\ù�…[LøœñØŽ¦ð�Æü+¤¯?A¹„,Q\êÛâð¹°Ýr"7ÚE4ÙøÑ'¬`¦$ ¢¿*¤M’û0ùÍ¡©ñØ[¢ÀæÑ+9hŸ·×³Ý:Ÿ�3�QÞ¡ŸÁ7¼/]ާ]LàÔQ%nò8iÂÑg{(ÐîÆ +k–¿¬rà¶Mзӹ‹LY y ÛÊOòhÝæðnâç:o<¤m„¯É‰€˜1Àíã1 GHý~9sØùwŠ”LÜ|(D·^ù˜=Pø# ¢^¬ñ_5P†Áxuµ˜�Vôk€bõ9¼†Ô¸V�Ö¶z+M# ¾†qúÚ^‰§"X2rÄ÷—Åúodñk x&b¶ðOà¨Ä¬B¸2÷i\o–üÛ#Œžt’Ò‡WŽm’c¯^cÖ¬ º,Ýñ ‚k˜@Hç•­`lc[í8¢@»†]ðLÀB ­S ïl?­7ÿRßní’ø—¥_Hå+�² V¿]°À0ëª]oHÂS†Wñ¼JÅvwà•$ê¹n_~�Ò¹¿O}9ð×kÆdԇñØk¶–—`�:ˆË{[K¤ß’ìH°‘íh Œ)œ@›ï—-Šž�äÙ&«¿è0–Ïüp0DL2™"ÙÎ{RãÅûvLnÜTP­p\‰6�a*4Ád¶=qW %®X¯lñ¬Æé19-Ö‡èt +Ôú ÖÇY=„y¢m&5B;¤þ%'ä½,€�Ê3ÔÖ=L£íYh†#‰³HH'‘JY!í£ñ­L®@16œçš�­¶B×1W¾¬ˆ“ D(ù(Ê ç€¯ª¼>Ü*pI+ Ï]½²@Kÿ¥ëÃJÈûNxæ‰ED{'RhØ.©ç"sZ¸¦ø#PÕ¸Ä'0-Cq,–Ÿéôµƒ“F4–÷ªLyÎ~=4ðà¯·Þ 2ÈY?ƒkÊ8çvë«lKéÍœÍE¢ص¾²j â[b"ÞJVIíoÎ2e®Ño/k¸M\+‚½�EÅWÃ߸�âБòV{/sÊPº (È¿ c +R’ç!l§f[IJ•–æ8q͈dL‹:@]íÊŠü\`½¯eIîi(ƒ(toö)|g§üÖ¼¸À²¿÷éW„`A»Ã*Ö°Â^'m¥SÙ=³¡³QuÙÆí$½­KR�<9JýfiAÞg×È“ø¥å£$ÐEŽrÀojQQÇr€[pÓafè�šØÅ>ИgÛ1/^áJ‘hÞ‡ÿ›7¨é ’$ éáž°üôrá³Èª+“>†4± Ü´?�ÁA†hÁö'b_�|ÓÉDè_c]Lˆþè9˜²*¨‘ü’pð¾3œÈqGÁFHˆg�ärä~¼ØHš�»®�*}iä—]^3gsRg-C>†ß`c9g†°ñE’ÿê_]ù,�ÅIƒà—+öðnQ©¾‰±;FíÔË™ÊÞXdSØr#Ki¸š<ž�„Èøñ{oâ€F°‘)ÀŒÃ`©P=¬ñÿ/@ÚͺÏCÐIºäK¾aN•So*áÄ ²ºLKÞ”Ò8’bêP;VÝý…tEa:�V0�‘0“Ä•tv[š´£ÍI‘¸&w�Yº¬~Pb÷;ZPÁð3þ…P[^A +XÌeÞÚ©éöxLÉ=‘’ º’v¥×�(p„]é3w•™ÈÊt9>¦’±‚”¡CÚ¬j…Ô„íCÒÐjžÜ7š–/+ ï·Vt¤~Qè:]³¸×&ñ¬N›ïøâÞç¸ÝžRv¤<–*~ åÎ9@%`£�ÞQ^ÍÌ�ÁÔõ�o4óG‰!)¤&³¤¸­Ø^Üd È'`"âá¯x“¾4†Ü7BÔ=[¤½~ë�CvÇ´èõÓgŽDÚEt™è î9“�~'ÃÊá™m$tïá8#«¬õ–b']�Qlª#£ý>Ë’2ÛÌ�ʼn¤¯{½4ÏOc&ü8ž:, ’µƒ˜ÏÚâ>Tô(Á‰‹³*܉OoUÿ‘?l M*L2ƒê PuÔŠ1©¡†1Ù^yA½—�ö+üÚLÔFªC™¶ŠÌ]©…R5‘—דJΗ:‰[Ìß ;ÐÐE×CÒYâƒs—c€ÂÄígf†;Sm° +_‰€[ªüÍ%#•3m´M`˜¡t‰mçDâøCúoM`æ…@LŽ Š_¸Î¸‰ 8rr/ß®SÂL{\n¤—Ÿ2À;J÷KŒ)~ªÐƒ‚:©bîMï–ÔgqµEjÇPcÜS¿‘' 3hyÿ#Ä£ó¨C,�Pæ“’Kð-Û`•„ÖØËÚùéÌØ¬®"—¼ÓV_ÁÅxå?š6ÔÛ�Sy ñ™x‡úÍÖÊzzÆZ] Ò)*òòyÊíƒÛ%¤ªˆçö÷ÉÿŠ2̬V\ +®›•ÌMñ5Ã0ËŠ°­¨r�N)w›s1©1ß™‘‘‘˜²1ƒhÐÒk U¡‘Ü=?ü¡ú¯÷ ö³I®ée¡OPÜý4ƒæw`Z9Á¨8ÄÑìêá";3 ž‘‚„1}–s[Ój+›Ã�æ,N'Ã$™ö¾¦ÚlÜÖvÊþe§^(á^°é<)Dý ËIä‘fã ÝÙš0-kxØ“é¦Iæ8Îz!�Àïs ÊÑŒCó¹1žÆªÀPÊãòp0?p»È¿:¢Ï@èßÒ`A™nvÞg3ÚX†Ñš_R4¶èÓáõ"áÆÝ\ µ 3̘5˜-¿_½¦ YþLPöäMáŸÞ÷wdÜê¨Ïz¥>ÐÔÙ_CgJ­QТ�©êq +G¨¢‰`xŒGØk¿6XˎβòËø€Ô†Sدö¢“þ*ñKƒ]©5°‰CºÂvkò„B¸aÐ$Ë, ¡á±ð–¶á�¹Í”Ž_ëÏDõ�üfKüÿVÐÉÆÚVÕ¦PyÁ2àÑÎ…ùsT +ì>ﺋFhWa®[„j‡Í |ºì˜¿ªfTœãÊ™Ìg¯�¦7¤'(»+J„Ú&“ú¸ÑOdÄD;šU˜ÁT=UÄ¢¤äjG“R[§˜R¶ÒSRþÏ*pŠäåÌÁÑúOâÜûÅ6¢‚R¶×_Ó#Ã\aÌS4G`ök¹&©Ô|h}>!{¶“�‘!fÚð–ÑŒ‰ÙþG�±Z »q³©Ç*“l¨—Ïð ­‘Jý 3™såY�A“Í7¶ÂƒÈ~ÑKöD¯ý‚BÞ.4`’"(¿Ñƒ­Ísv‰p“¼ §è«øH†6×Rƒ,lýVôíÛ7@2�“à Ñý3Æ/°Ý¢…uS|"Èån‰ó„.=;8�Ka ‚ÒÏ‚Q%°® +=tÎ%5\Tÿ˜=ÂÓÉÄ¥(åÆE~®‹¤²iº�ˆbB&&|;·„&Eš>îÕ�‹Õ�Cc`±ZrzÌ�רRdz٩€ ’ž–_ „ŽÌ|?ÚHö-3cÉX�Ó«ÒÀÊ1^QtÏ/j �8ó«'¿™b®K�¡uè»ÁCÛåü;ì+.* g¾f²Ž?A‘MZµFxFPKÁ«9\š µÙaÏ#;8P|@Z¥c×èœá¹¥%ñÞ1� C€Õkma瓚ŒOá ¿Š\ï>]OuÎçÜjÊ´t’�Db™_´Oœmö_Éùò—‚Ѓ)$çiÉr1IÒÂ�/ +|ŸÁñ `ûË$ ˜i߀,SK [ÎÊ+á¢k•8ÐIcˆÐ;È7ò®•,Õ­ ZÆŠªq5dHZçüæçœ’xá¸~nóí?A¯£´›g«XûY `ÔœLqèänŽÜçѶšf˜aNYÕSiÈk÷‘¬ý°R�7¤ûë˯Ù‘î&äÚÂÙÂò¸VÞ>‚�G{;^y¨„ 9dïÑ1"��Å· ç?TØs£’B‘8±`I_Š·‚�Éi»þÐ7¸ÏãŠÖ¶,dSö!X5BUµ X%˜}¢kˆ¡¬’¸€”õ·¢þL6*Kœ¢3ºþ¥…�/Œb¡ÈkdnÖ_’á=­¹¦Ó¬Ì±Y™©ð¢3@ûÿóøI'a b8Îó�^�(°†:0Î:ð‚ðC<\å™Ï—I=ÿæ»MV1Ç5CàºÉ¤’1ßÚt¶k!,LFz²”~�: )µ@æ<šty¹dÅ´“Q‡F~á�ž±çœ�kFvt)”VaÁ ·„^ ,ŠoË'ô_X§Ú¸½ËJkó8¼`’€ü> ©°T“:Õî½Ëν[8ÏL‰d ì³~\»’Ö<.z6ÝO?>‰”Ÿ¥¦ã8j¥±¨XŸãù‚Ë<%«Ã=ìÕÊ…]<Ç^�eb›©Ò=ßp虃®¸«¢ æ¼zÊ—ý.°ÍTHŠ&I^+QA�eß-fQÍ"äc‚*8:ƒ|â�€_úK +™¢††/´°½�ˆ�ö¥C +lŒèwØzXÂõsI y¯øïÎAœ€<‹ØŒ¥‹�ÐÕ=qH†1u�UŠzáÂô‘3`‚5l’‡ +� ¢R‰ Ò1µÉƒŸK¦(€KBièn!ð€+·€’8Gùžé­N†Ø7ÌÌo:A©UK$sU,£B$Õµ3ˆ›`”}¬Ïíi,%BùsSüe@c-h[4Œ×"D.Â刦Óä]�A&¥l£°’¡7OÚÑìØƒ¶(Ê$,;CZïŽõæ�ÿÙUŒü*çb¾‚�IvNή8T”¼×áœñƒGv¶‹ ú2Ò�£.E¸‡‰áv?8yt1ч(�Í1!Îj¿»X‰µ:äϵ‰æåŒú³³+¯¤Åsé1†¨¡õ+ûTSè] £Ñp¹`A“õ[Õ]‚Àõr1$ŠüFȪl™…Yï,ƒ‚u‘þeÅ‘1MN"0·?Moü²F¼/ 2�´�lÇwVÂX;È€’Ègªè.;}ÝB°ÃÔÛìP7p?átQ³!}¹ì—ÞßqZ‰—à�î,óãOåÑ^�;X!úNA~ð6în»}òi,ÓyS1‡%S�JÉ$<»^¢zcØÈßÒ¡zŸ|në}èèÖQY€20¿ïå¯étôËE†ò@¶;ÝÖn—³Œ +¦q0QÛ(x²ô7ƒöÐ)@Åû¨±>ïU…'g�®ZƒW PhÇÆ�`Ppï§Ã&`€Î†W®®QA†¤. +À6ÀéO1µÁ +šï¸¡ö$ËD§¦‹Z±Õ©ô%Cl®è`ƒÐ)M .¢nèû V›L¾Õ ­1 �4ÙÀøû¬×uÚtdmã)Æ�’ôÈ„8A¤ À‡�ñEÚLZF)a»ïV…‰è –QÅl¾U ³P_oh.ñrù~¸¸´üR¶$5d¶5éÀPp⹊äœÑ.3u¾�ã +Ï;f«øO�™ž`8e„§ÙµÌË@Z¯(Ó6¨Ž§v¨)Ÿ>Ð�¼¡çrŒ1!€¡Èósi2->2â$Ã̲àFV{�!|¼*Zån…g¶EåD@‘0vODê³Ø,=�€\ƒ™Vf€€m¾æºlo�×à›Õ2®µ»xÀw%”�F Ï'ˆ,zÖz Êж^ÜüïlQ¬¬­nR0`ë½²�-Ää¸q{Í]R;qÎ.øŠ}tY�u +�þˆ|Þözï ñ´}VQ°X♄Á„a‰—bsS`"÷Þi�Šƒ²rš›e?ü ŠØai¯Óª»ŒmâÙ+AÝaåÆ^~wOž5Ž‹V°b*ÈÛ°ûn(í¦dŠÝ nT—ø.壚GÉk1(ëØYäP$�Œ�öRö9³ÕbI)0@‹çdÚ¸p&jë:z$”�4¬¨é5µÑš�?ëßúY®ê¬'0‰‘È\ò^ÜVd‚À~}Œ¤9�FÙ9¿ü +tã�¶ßä¶T¿ºV·©z~�y´´ø-GôÁC"©B¤ÑÏš'Ÿ›e�‘:,%ª¤âÓ±«êo®“‚"k,Ù´�òo+œèÒ¯˜vÅ!°)”)9¶ÛÊgë°±d¨´FI†Äò´�6U §§®}¨<•Ì»RÙøDf·s¥`°9uO!I#·6ÕðõZ¨Ü +’g5 ÊwúXÝ*¯�4þ@M×Xü½ã +›k¶éÌ–§¤¼ó„¢ù<7ˆÓœ4Ã_ꢳ”åèºÿÆ• u §¸++Ø çê=#•$ð�P¨ +?Žeè6‚Táisµ9/Ý é›<é›é3j½¨xÙ)PÒâW«sÙr™ÅózX–æ}xÞ ´Ï/Ëev*À¡[�rŠú~±t¨"*ambH(¸¡þÙt½b±M–ûŽ|þ®î?¿É¶aTKSç K\@v.µ]Øš:0àÏXâï|-ÜÀv˜i$(×’W¡47µx¿¦Ð^5 úï8“NÛ/&³Á¼.£§;‹×Êùr[º"ç�™ä&¢·Cw~bË4aBÓý‹^=i "�þ× Çhà ÜâÑ}¸%õ‰HøHxYäщg÷òò2Æ·2þi¤† g‚Ó’¯n%«�¯êPØë<‰†F €WB­½5/-3—Å�m~Ž<@y±7ÚNÙfCm©êƒjœ¯A ¦Ø—îr¹ý‘ªÎ 4* aðI i´»£uf,!N¥™:B«Š¡OñE_)!^ f¿GŠËL”ƒÎ<ŒRmgleŒl"rù�þ¾f;W¼î$ùYL~”®„�ÀŠæ-\Ä "Z‡€¾5$¢vÁ7Ü 9v؃h"?â!äY2/8ùĵ—ÿfl ?†e‰§¼-8×IÁpe�ÊN¯«=Çä_ å̸%uÊJFz€×N�¢‚'ª€Ó”+Ú _xý< ã³TUŽÏËhHX„ð'%4ëC +ÅåàGuB%LOw*é`ÙÔc%®æ 6Sz}~õVIÄXѪT™T|z²<ÓåY¡îÔRÐΓkóX1?þ Zù6![Ù§©sWøEôWו½Rš×C­ÉçWš{I~¢`Ùär –ù²Ôea�â,ÉüZÌ»ãY–½€*³Ü£<½–LÕ–2çítËåØÙ¾Åˆf\¶m.fœ®PžrÉÏÜ ‹YÎ1Ìþº÷.&fèo„žøù2¡�¨„_hYÛË_ LˆØÿ/ 1 �É ¬Âˆ`Î8Z¿nÀQ³ü[ZÜ?0שÔÓlÀ£Cšeƒ¯¨5QC°ùU/ß2S…ÖÝ®Â.™ø‡å9Iëü â#EVwu·˜ã2öQ^ô„=­Q°ÏçGõ Äý^Ì»šÇdÆ$ÀÀÛiÆÈl_õúÄBoe 6ÿÙŒaˆ6º@ÚØ³6ñº� æY£DþVa’ Õ&Smú LÊÔöÙÊ~Áó,[fqÿ24Bfp»s4s‹h3�ÇË“Æ3vÆ[(Lz江¡µB@zÐ~2ÀѨÉhŠ_• M5Ð?/žÒœ¦@ÓftŒM'ö$É^wÈú €Übšì‡3”>¼& IàëŒþÝH§LE1I’\œ–— y‘ݘe“m'ù»ˆ§Un,‘*Îòy!ž7Ú^Æ<‡Þ�æ!Ðç0ˆ%"肌ûÃݵ´Ìõ²e昆=Mc¿©~^0MXµºCc·‚ļ¢4• +Ô2ƒ +†ÿðefKšãÕ 3F{Ùΰ˜Œ Šã§bùëÛþ“ ¼†uÝ3�8tcD»~ô¼ DCñfžÄ\›þOÊ–vÓðË~–á„_vD�³JϘîIYd¥œÍË@V-)³ÚE¹g’ÎÞ\°í[OËþŸ¿¥L+ŒÅñxløþ g Às _c»¿Ló«Q§¹ xЖW‚ ‰– Á×^Àz©Í"ŸãNñéh%8¶üöœì¬Ñ|AtPÂîÌcýqyÞ9?�Eõsp*%ÕÎ)NØFKRþ\ELÁK?5‡Ï•iØvVìñ`'nåO%X’¯l™'QN#ÖÑa _8ÑÁÓ!`SX”Â5´8h¥Ó–£®„EP«ÅÔPÓï¾U¥Xت�èÕ°4´G©eØÃNúÉ$c6ÿ´L‡¬�¯µÜÌ¡¤:Ù²tÔêè)²Rì_z1?:½†’ +žÚ`^–Àã�VŒãåœOuÒ5žÑιLÖÞ6à¾I³;½”ê˜pà=ž·Š1ëw¸ Z?¡í£DC!µªXõ–Vcr]Zfî@‹4ˆMüi…aµÖ^96÷C +nûíLA7j˜^õQæé¸÷$&sf™ÙæNa—&§à! [‚0À܆¦@m{Z’gb.©Q`‡Õjü‡­o_ã¿ÖRÏš„‘Šñõ^éýËŒù0QŠ›¾@& ß0;†!H{p3èýÝ…I*€ÇƒÖñÜÏ¡@5áÅÌæ<Cc=Ãå *MŒ¶©0tÕ³‰Hô¶žÎ€œJyŒCj%m1éM¶o|‚ç´—¨$=¾E†²¯¤»ÿ,ã˜W£ÙG­ÝØ‚³°•ñ%A§5x”®3Œò‡œ %RµßrM¨Å>ŒY+“<ɱ¬›ñU]ßú‰¡&Z9~$§ÎBÆ¢d½çwœåXN}-Ø0æ¯[QpsP[\(Y•‹¥v”ûrÐ�îøº|1Ró„YÕ¹´ñ7ö+¡ÂÇ}„lG�Ùoh±‘–EÇ‘&4: ¢�ÞŠ�9b“ ¡DB›™×®£¾†™¿¦°®·e»ªXi§cœ’—,Š ? ¥¨Ššª+xô®óB3£Šž!kAC"µhÌlJi#UQ©ÊÛHƒ�"VøÏI§'¯þÃ8ldš–Ah´(ª€µQ0–ð½®V�m©—\ÿ“Á #颾NûKÈ5ÈZƒÒcéõc4Ä (..Î Û{h¦À’S¸'ï= +pKĵÕâ^Í3ûÎQÔ^ò;µÐáÿ+ë€.¢ g DúÍôŒùr*+j�h9HÂ’Àä$\ÈÉ:ð!J¤�y ˆË+½å +œ5 ÏBê-8™ìD•2ÐØ�Ë ¡)‘€§pÞ¡n."¶‘� Ò¦ádóˆÞÍ€i ½6Ý–‡(›ÈxXÝÿå¼!¹Â üÕ�óPÑ÷±@»†ð „ÿu¡Á\,4ÐÁ-*´ì'Ä A ZB0ÞÔMX„L”Á:=ˆ°ð8¨\„P* ¢Aèƒø#„Ö+ˆMC¨t‚p:Š >¡½±×•2.i„Žˆ¿Gh@lŒ„ ß'¡´bÇŠ@aBñâð?P¦’©¨êT' �Žc?–<Á…b ¬úä¬î>VaÂ;ñ‰_M8Dýyðú'¿|âš@9>w>t¾G§oçïk[µ§6÷°ç›†v?ŸOONN£‡§ªéyÚÅ„î4[–еòàÃTmàÁýyÜ}3ÖûÒ€gÐA<�@ªj‰Tê½TÙt€Ù’.<¹%“u§šOv •áÒ퀌êÒæäŽ@¨$ô_½ti7‹stiÄëÌü=Ü5˜U] ’Õ®‡�¨u ØƒûÆÑÚ/ �–ÊAëè–hƒúÆ[èŸß u–5½Á ›¸r'XÊË{>î„K•tØ„~SBáCŒ(¢ñbÅ�£ÊwÐÃ&½…ÖÑi’i¢É<Ãi‰v2툰»s™¤FÕI Àšu°ý“éöã|3" )vêÈëÀšO‰D¥QUdSöÑ—`'ëlß»¯Ÿê#µ]:ºƒƒ:Ç¡ævépÔ:/Ýt¼Zƒ:L£Ã�‰/f´t´Z›Û-�?c‘@Œ/�â€ÄK§í ×%½tôêèi©�ré,ŽNƵ8囘ã‘eØÝ4òœzÐ3 >Ê÷É}Á;rxGP}ÁMÎÉ`£fãä_|c¬°8í�!yå‹AìÁ¼HÕ'˜LD,óÄ ¨ÀÌ奣ßÅ-è]`q›Ô@WðfµìöÒlrˆÝóFKùÅWc€E¯êyjkjRn91JLAðõKD9#ivbÍ™! b.SvPg³Œ0îÑQÕ¦‹¿º¿86MfÂЩ,œà‚Ž£À$VÍÌ7 +¦âÖüUçà¾'/¼%[2wýOx–A�wú’¦B8é€^ ŽºŒ ó%�#=LÉú„ ]d•À¿¼È\ /𶬿Ö7Üí¢ìr]lV{o—%Ú‹ä©9ïíOcïß5Ëäâ“Ég¦jq—˜¾(Ñ“.pá®YYÚHqq{Þê\;Fâ–×g‚èúÖ -2֕įÅÄOFêâƒÕb�¥òE0-÷Ì*ÂZÞ]»ëŽé,° Q>Zò  潪èx²)¹\E‡p(™°k2™d<3 +Çg0³´IÃhšC˜Vp•Á(Єsi\Hp†ÆŒ¨†Ä6EØøA¸ƒï½Þ‰¼16ã0a‹ 3ß÷·¿kõ»ù>äglñ©‰>p i âÕM?L»üv�'3‹yôž<µ(¸ªÀ?j60z7ZŠÀѽ~)Â[Z@»"”}žq•QÇ·ôIöU‰)d 3s"mSñ*M|÷Y‚©Š††úÙ�ž!­:O3ëC@?vÜ1€ý›¸$·j6í*+ ªJ’ÓÜe5Àî)~Vñ5£gÉ 7^ðg?Xyê­}Òuw²¯Î§SÌÚl5¹„ÐaBa—šÛÁh +¡çXÕ¤ .x@߸ Ë­„䇕~æ]�í»²ºIÌÙnhÙÀ,`È÷`A*LYqÒÆù¡’{�ËM:-pK¹t•_bª·KæÔÅrÆ*Á2À†deQ9IQ h�7„·–aâ±ÏWAhÚÊå@ðt |F­ z/;*_ÓU}&Î`ù)Ԁ؄BuŽhbQJ°Á;'-º„^àaÌÍhÈ›»@чY™6&ª-Î*g–þe…3 6Udhí]3®Zƒe&úÄñI’ìö3¼—/êÄ?�VëxžnýÌ.ZM¿X] Åuíó† o©;î!mž-‡ÚH×ÞøÕ†[S´€ð%ü\zŒ:R‚Jççn°ÚbÐãà.U©¼Ót%È–,†ê�9©Ñáb·[0E›y;¯Lþ¨\Ò=·tO’²÷i x9™óvƒ–�‚èïÀ¡�z¡'»Òƒ¬U[ýž*âÉAÈÙU~ Â"Ö´!²©…`�]Áx\¸ŸJǨBò¦rŠ˜Ë«dk¢Tƒ`ÀDáœ�¨¤Ï�vþüøÅ[Ÿ<¡(oöI#5òFë ±ÊèøBic¸~‘ó4ˆ¶— ŒŠæd)ÌpsYP5é¾_6‹r jÿîP¹»£•ƒ_Œmvƒ™2s™Àׯ¢ÎVBŸß_ÂB�S pg;zqW&›'WCQ¯5OorJC̯E˜4'Å“:œa$XÄYã¼x€&mN÷rÿ·Ä~…œPŸˆ/ĸ +ryÔ›€T¾>ûVÈEøfÃnå $¨éšÐõ®X8j+X+ÓÒÞÆl`4ÊØ4üòíµGŠï¿Jö; £%ñû{O·�¤#EHä ,KŸ%5É­Ðg qÕ¢«ZÊÿRæq!ÎkJ ¦,¦¬ÅŽ@Ô: zœj¹|ÌK•Váò^²­²8Ê"·5Üd „”<¤ aÛ ¶æÏuüUE°%^7Φà,1~©TÈ9:oëX1¨-.”p£:Iˆ…,T«÷ÌÓ¥T…ÑÊœŒ >ÉfTS™PH,ʼnÐ_Z‹�t²S‰5ÎØz† !ÁÕ_ïœìV…ÖŠ-Y^o^®PõЕDª“ü¦íjÄúÍòˆöôú”6€’ë]ÊðæÌ'~´S#¥çv_Ü%€+«Í‡ç&µÒè&G‰�Ãå¢Mј³šò®Ù8§Q Eùé{¿ +÷"œ?JãÝà!† ƒìæD.yƒ” þ$Ó¢ÁßB4Â�ÇB�°^Ö°wéàl§ Ó3X¹=Q`][qä îÐęҲ˜á_ Ûa¾ÂÌømg<ꋃû|5|9ÿV•S‰Ô$œ +_½¢ _¬=.%¤ÂñŸØ­ÑìM�OÄ…èÉï¼ëz ØfvN‚ÑJÄ«²ýŽ& ×ñÓŽšs’`<´± +·FbKæã¹§ÄŒñˆãõg¬…5/*�ÕQX„(jBqðì��qéïn{™ÛÁóꮤ »‹Ê·RnwCzyö_ÛU?øQÈ?Yzh&•Xl`üSR2OG¶ªM+y…h•Úˆ„B d™ÐN�¤i÷‹øð¥{µÑ�k”ŒØW†”žu¸:oép»„gO–çÀ! ®®žîÌWÍ+ÒŸ ¹ùÝÅ@jk±C¸"NUeJÚDʃ*O .�Š3XâXœPii�ª7Z1O¨ø~V2g¶KJÈpÄF©ð$ÁSÕ–lU­zŒ$¬#͉‚js§’+§ÆÓÄ£›x僄¨ul’-4ÖwQ²fÈAÓÇs›ö—ÉáŽIô6ë +“>ÂV­ø’/7¹dçié€Ã¤¹O–ÖZ%µú$rßmh©)ù+!JW;I �oÐ=>“¸9Ä~fÒ[A W%ÑâOIzùÆ…$b<,$#y¾«EA’�ºjÎÑÏtÀûkE 4uã imëðÁ—6²Œ32ó,ÚXåa¾Öy/J˜E ЧqŠªÈÞ•EY3Ï‹ÆDQ‘bÑW QÆ+}ˆÙÒ¡;Ú¦«±5Ô�"W:.­b˜¤I”ô›Z9#ù‡¡­]• €Ô˜Bz^Nﱜœžâˆ–êØÞ�Þ&€®rš¦,¨*?þ³p•�nX¢£ WM~9Iºª¸½W¾àã +? +U0R¸1�û…‹7�‹‹4|ëÒ+ZÒ‹ïO¶èW8”0“­‚š ªúè�/:¦JÁÉÈHå=Xõ PÁ¡…¦�ÁÒRã^ N?Ýé�Æ{¡'÷Æè¾Ã÷Áê÷àC£‰ÈBh‡i'ÚúmÑÙÓiO:FCؼ"Â(T€+; m)†XVU«öm½ ¢TÂÉ]â"O7Øn6 �p­üÚņ…aZ/óh „jÃø5ÁP Á[±P#ƒà +m|Üš –ëŽ]‰ZÀ®“bJZ1o³æb×Ö¬lPC=öu\; +Æ!ÕK”-ѨG;<»¯g!Û·€ðÙ$—̥㭟=m#me †Ë€9¤Ý*V?úi†Þ:¤ÝïLÎñg+3Ò–ÛQˬhm´Æ²íçÚöt»2Hè´oë7Üb�aÏ�[sk¢ —†„�[™)×fÛšgý¸Ú Òý¸XŸ¯ ]¼Çd΂¹¤”¦Ý„¹L Ò8C·Fˆ.Ë\È«Á¥¢;ÁÕE¶tDÒÕµË>éœ(R}IJ ÑícU ýb¨¤™»rçRæ‚XYרe@ÅÿÈÜù’ísr‰·27ruAsÝçôùEÝ!!`‘0ëÇ$¨™·¼ªÜb։Ш­‚uqm`uaCÁcƒkÙÜ}£ø¹QÆ<Âùû…D—‘5[ܵ©ñø­vÓðP‡w-Ù+ÏåLÆ[c$Oÿ¼ÈlUIÈ[U;´UÍÃÌJ-æÌa°ˆ*ýé¬ÔÕƒg¡óSçØ©–�€m†Ó1R(&h­KHaêæ`��‚>l2]q|l¢@¤Hj¤|î¶H§+Å ´¼f•ªÿ´°îŸ÷!Ÿ ¨‰pˆ&+5{uYßÝOãnZÒˆ—žÃØY£¯}„l*¬âÞàp¦”êqÈDkz1÷\¡+±;€½°½ô††YîN˜]Z"0YIÇSmeO1ÎØ“$ÝV$Ê(8BÌ #Ý~rYD 7êL•�öÌbAßJ¢œþ¥ý;Z¢r>�'fkÿmŽíŒÕ%«6ÎÚ>BÓÛ4 ÿ¸ýú›°g ²6§aewXGl8™­\4ÌæF§B±,ÆÇ©tÏM5úÍg"Ý¢»5Ð6Dy^1çÐ+3JPÂb)i ÷îj€ÈœïÄV Ô×EšÃ9¾°6?VŒv¼ÃC‚ˆþ0ãš3.rŠÿ[3OØŸbõ₾d¢ækTŸ¢¥ +n0­Øä”è”ü‹¨Z�°hã¡c¼:2½“¤m¯7ÖS�¾Ç2qw‰¶Ic�`¯¡™ÜO+v9ê=°¶+Àhà#ú–rŸbÄzÑ[ràkb«9à)Кô+ ¸}樴‡`>�%V…®lˆptc-k!¥<óU `íá*ze³ñ „zLº?êl1 +7¯x!S€Nò¢- « +]âï*Ù�@u¬‹Ñg™y¼”ÚÂDóþ/ø­Õ1�9‰»ŠilHAP8CÛKq”÷Ús쌢Uí�cŠ~„©ú6>«®:“ÕÆmp£Œ¬;ƒçíž\'YM‹•“kQ¿UÀS͵]¬AU¦y6‚�y(ý̌ա Ì“]A€ÄB… a�̵z�Úp¨[,õ½òõøÚ8àé!lÄŸ‚¦ƒ ù ÒeÍ[#UÄPìÕ&鹸`fØqk‚RÒûÞjã¢íß®�œxCíPß¡Ðþ5…†Æ^ù<›¦–òÝrüë¤êóÂHöÖà�å'‡N 5ûwìêÃ’Ñ}ƒ˜Ôøÿli‹ ®ÒëR>ô±…ýãð»¡J±¯gFª)®ÐþªÖÿo+{øJnèþª)j¸ý ¹~ö^*êýAC3ƒ§ ý¼„÷=�5ëÛ¬€pZ·’‡;_¬õP òäÑ ëÏìdKŽ‘Ê"âsæËa $‡rª$¾.‚ì´¹ÅYgu—Í“D#KTê6‘Ò.Ñ8V Œ¢°¬%Ý~«¨Ç ^Š˜ÞýMÔì‡rjú¨›Ÿ•ÁõÀ´ü~Jö¡ÝÙpÔZçôcÔ ´il³¡¶•í#€^ T,/×›á#V)zµ„ûÃ*îYã²]ØotB]¶£>t JAª‹Œ^¯�§HeÃG߃ê�%Ûã;À¦ô�Wl‰®NÌ’ý»’òˆI£)=\eYQŠîÒ¿¢Pü´ô0=F“A�O,€—Òivà +?Xõmö8´é2û§¶À‰—ÎfÈj:°Ž>œJJzÂDAH¢¼‰¢RZC¤H4L“Fn�HªJ!ªOØþÏ>JˆåQyt9˜•zŒó‡lÓ&ìb2¡+~#?Dfs}k¶T�3[*áóFæ.­”éÆÅÄÈcU×Í*¢IÖ7¿6fl«†¾3‹w£õ3¾& “‘•2ô×¢dšgÇy*€Þ‹:Àìo¬&\¬@eÖVöô"æùVŸFðR¦að²L ‚*µ��H0=ï-ÚîÄ%á�„,éØ F1CS10ˆ1Î=w'ŸN²â7?�?Nw"´ÄH!e¨ë˜À,<—’ɸdH´´Ô!⇩b†§.Ñã/£6s474á¥IŒoo rµÈ,YЬ+„:¶Wíg„"/2ï/,¯Û�‘6 ªGëŒm>aQ_Fµehê´§>¬êzÔ)ýŠ)Èê¼zõwG¬�”u½Š†9ͳ>w9eØ:@¡É­G—ÓKP4D(bA߮ט½ËæHöX‡�ê¿ë˜u} +aÒ^ßµ,‘¡oÊ·ž1€ò®ÛøÓï¥D˜€8”Ãë›» �Ÿ Œã'Œ™W°d³ýc­¤BàcAÛò÷ü’34•1ÝÙ‰:4@G/ïýO´>ûT:'!†É¶¾H¦“`ÊtÒZŸcì’È»fºr²½—›A =ý7@ +íbÖõ˜)>èŠÑïa ¾�í×6º¶Ï×­:.P]Î7mB}º!>ÛrA‚b|ä¨âRƒf—û€�…ùfr¸ô�Þ^_ïXäþnóËÝŽß“ciÂåí£vS¡>T]ÉDÞã-o–]'°ßñZÍ¿á8ÅÀï+·hZ�±ö½ ¯*‘îÒ-Ãi;=ñ­ì–-K‘¿ÔUO�Ó.ZíŠy:Ä„)–f»Øò¶�à„@J·6ì?ä˜yqü‚ÿ36Ä6 ü©�ó°žw±˜OZTLÞŠÏ%ä¹ÈÀ#èö¹ysKáXˆ·“·à–�&åQ4¹¨Ú�/�+Lz¨~C-2è-™©|‡6? )šoŸÈñ?4³‰8t[è~ÊJ„'á¨J˜jm©Wh÷\£ä��(!Ù5ó^3[x¹ßÈ›ž4æf�§!ÒïÆ0=±²^«½W«©“]BãŽ×ˆë#âñ¶ë’íÐß0ˆ.~ø„@Hï9i¯zÈ´ßÎ2 ªV$w¸ï â=ûŠ+ßiC»åh*Öý8ß{øŠ¹|‰Ãôÿ -/–h'ÿX{Ùkʳ+ãOW?#œy]óqðhκæi›€#\Z!ˆ3�W±›>J&]Ûô +óùL¢‘vçÉ»ÑÕnÈe¾ž =9â†r +^¶}Ðq?›,Ã` z¿P64jyw“k)‘`) �bæ¢cës"Øa:4U�åa´ª¢-JúwKóbÈ£Ãx‰˜ŸÂ´±Ý$£Bá^Îuyš_y„zÈÿŠ�º‘þ1Fr*�c{›ÏöÇÕ�·Tƒlt;2× ™©#Få>E¡¿�vptŒžæ Ë9Âûs}tÜ2�ôŒBŒ^‡Æü °Ñt$‚OïL�R½k ¿ã:jËlÚüɯ½•:©ù^ÞûÖl›ßc­gö^Wªfcûê½\l;‘}Ü»‡eëÐRéÚY£Õ¥i§oS�‘P·¢JðÔ¸øÓ8U oê`síÉðÁæÔ\¸2¶l„½Pßœ6Ž¢RbéÂC3ŽYa3•’Oô’ÝÞÐàµ(Íi&£3^3¡Zñ“ŠXÞþùpFÈZ3±à3VVv—wpÅ39À¨ÝåÚUUѾA]ÕèÏuÛ`êÄGñiéGÃè»í…9¶á î�HâˆýIJ_¤ë�Žun7ý]C>)@:˜“´&$ñdÐÏ ‡[:´m‚nùr˼3  ¯‹K¬¿|îI/ ïÓpR_,ïaþle•Q¨‘nûa6 ²Ç•’„ËÓ aC‚¤»f¯pFå .äÉáZ†Š}¿ ùEèªþ­K—gIÓ$ìLιÆMqxT£2e?û˜b¶ø [w–ÆñŸ"ö5Â�aŠý­)Ë1%«¥Ä¼šLIù/¤lÙˆæÔ2+Êu-º‹Í×Íä˜åOIÕ?`/+…µA~Ï(h5-µOŠY1Ûƒ3_áÅ4ǘ°Ç��…Eb§±'v@rT˺§–¿Ñý·ñ�HXþD!{§�×¥Dúô +%‹B®Sma `åáè£FéµGþ~: U�È âBóÇV$ÚÛsᯔ‡–Žïˆ§|7>þ¢œB”S >Y¼¥SóéšGwÎ;RtDç_ŒðÄ¥Úw#y éòQUq:md^èµÿõ›…†%wâ$d®»—iù¯ÞôÖIÔ݈^DµpYùkÀ ËŠºç �«HÝnláG§¡lRêOèR›‡RDsÞ;¹á37¸O½IÀ#×(t²=”«ø*÷Y9^ì`­‡T.ý²øWéYx—ÐÄúåî„üÕΉ×,=ÿt• I¸¬¶RäTm$T[5%fVÔ•DÈ/°ûØZrÊ-FÃÇcÕ‹êÌpß}*‹À°�Tߤ)JÂhjÒnVÔAB]=_2JéÀÎÏŒ=+�ðãXµèJ(F—s5ËTfè ¯[ÈܤÎG�щ±à³wóËØ�­ qÏ8\,óMÙY2lƒ\¿\}Z©a8•ªœ½§³vâeÆ¡‚#HÉÕŠ¬PH¨ÝZ¾QHŸú,ÿ8¿fÌ_YcÌžRÝ÷üП<ÁeF8T;Üw*ôØbÁsÃ<›%,rhû':�| +„ õ’|†à3ãõ¸Ä‰ü[1ÛÔnñ%£éÔ9[”βpLWæ�‘¯ºRæÌ)öù›1eåvn†+�{~Ò»}ÏVη&šh¬3XH·BŠ4Fë4ˆe7óÿÌQ·?¸P›ÇêÝw?R{\Ž‘‚€Rš¿8¹ÎTâJyt‘UDÒgBn¥¨½SþD/Z¼<|ª7P1· @)䦸ä ÖÁ-NÁDv2µ³›;÷�eTœäÔ¹¶Ôßß‚‚ƒÑAZèž@ô鹟·R3)*cbo+*b Y¦ÉH˜ìJY`¾\R]9ó'Нtt;–Œ«¸G&aiºÔ �ézùã§±`{ �“ÍÀÇØXÅ=Å2.º@ÜO—ܰþìÅ%ü\z×å2î’˜^-¤V>×*âàˆâ0)âÃJŸ¬èF¯)¬„ŒŸŽ´¢¾?´A/œð`#<„0ùâÏi³Ãk!ÜXvQ'Dü xHðO +ËÍé ¨’@‰Ї՟¹ð]åŸD}Ü�뼩g~º¿1ƒ¿±kâÌDcãVƒR])ÿ{nŒîðàš*êLiW0²Í€ƒÇGvF∠DBr_‡«MÌØÉUJ+‘Plwd¾)ø†ö'C=ú=nÚ*ÙŒA(¬©Ó³ØiÝÿ™ì©6f=ÌÅ¥²/UùææÚuOÍ}2A Ÿ 謮å6ÂH<,(Âa¢/ÉéjD´ÿ¨Y4ÿò¾†ÁþôªÂlJ××Å– Ltñvÿ‹%æ?_ôR„?Téh:ªÀ1¼¤ŠRt*å0û´í�.ú” ¿|ŠBÔ?Ik'¶V ÚWom�³w9«n’/,__W”vY| ê]Vm•sˆ’­×~}jƒ^�¬·ß~³ Ì÷-Ln}£û·�Q¯ð�¢Uº&ñL6C„áŽàÁd­¦‹ÂŠ‹K}ÞrÉoT«�€fþ$¡ß0b{[¯�õ„HÓq½- hSPŒŠ£Uqýãñ,]v.ª�kÁ´Å ·PÞ‚((£ßµ¨õÏ'1Ðkvâ'eaPªSæ©ÞIƒ^]„òÿ§›¡‰oTPúvû•˜¤nQ• �òSØ0 æ¤õ_ÂOP^ +²¨2AÇ­Êpwæ«-Ÿ)V6 ‘¤ùN“Ôn©öPË- ø¼¢n./iâwª„µrX0ðñŽåÃe‰¿æËTj@KS ‘n!ØwQC/éŒñΞ(õãhð½ê³ˆÔÊž>ˆ§W§UÃò”Z«õ|Î~t ª +ô£V¡‰ýù�‡÷wÂ0Yáݧ{�ýÜ£q¹rÝœ,g6oæ½<ÀÌŒÞí‹¢c¼� t°-¿Ùò]SšNkç‘ÑR×, F¢Ö¯ýXã…å/çþSLàµ`Þ”ÊûEï¤s�üÇÉÄ7Y3 æËùË$hz˾¤™ü[cOw‚N âÅ•€âG°¸.^Á˜18åT œ-ИÒÀБ¡Ì¶ZÝ=‚?ï¬f}ÕÌof°wß(Ѻ‰h£I‰Dô½é—È´Í$¦Éòž¬á`ÅÕöŽtä Ó»&¾‘$¾ÇB)¤ÿ¶ ý6®·V(õÓÓ7 ^lsIÑbíó¨éX¶åâ.ypwµ0" �”km—¤ŽÖtËq–AÀŽ�ÁÒˆWVq† G8| ;-ç¹é (¹±Üí<8J�~H�’%« ;Óñ�;ùÛм#!¥—r÷ bî®Cî®ÿ�9‰E«QnÎW·ðQ\/írË;y­áŒ¼4Fæ™t +¯ q/Ï%{žÊÉ€×]Ø)Bä BˆùÎM‘âî!iœûñÎíñƒTU ¸¥˜ñJmæ™pÂü3k¨#%,÷·�9£u6ñ ÜþîqQO]ßí{T¬R†QÆ?»Vj]¿Bˆ"L{}”zÝè—‘þ‡¾P΢nzûo$g$3æ×�XjrnðãmnV™d0º4+Ui»£4]~|ú¬ †Y†êî¡KþßTðæÂ�ŒF6ðµ×žw(�Íü…Á¦ú�ðÆÏU!Ìsn½ù>Vù¥cTHhTÿFä%¾#d=6¤Nù³RíuÖ¯ÃçYþTßÑ>Æþ‘p³1}û¹ÒfÆ:0T~ê\—#Ûu…Ý_¸)fßîE‡*HŠÃ�2Ë`_Ǥ«÷ñ`QíW)7zºip†ÐÌ ;蘙àz `ñ�\!¬•«Ãá4OÚ­Jõf�‚‚7By�(=æÌ@!5]%J5Žà‰]Ó × +�Z¯Qc€µ),ûÍr7.¿µzWól…w®„Â|,±£dv +¤Ã±Q�é>réŽ[àh�“¨ a GàþFyD)¸gÜ0.ý@x6¬Â- Ó?:šåyÚ‡áÚˆYŒ¢V0Â<½¢ÜŽg¡3E8\�jÁiAѰÅ�Ø&ð&"7ÜÑ"øÃß“†wÄ�%Ö}Ä-jô".ý�{ó±@ÿIÿúO ;jûãPÜ>Ñ]Û\æeœø3°lì¯Ç6ÓÉ5ýÅÍ•ñµ êŸïË69V0½X#*šÄŒ@IÈ$)ÖɈ’Dä†h4É€œ÷°ÍËÏ�jˆã@Ù𫥃†ã?ãÊeXçûbÎÅÑAµéˆ ñÔ"—Å ÑTq—SV¼4as{�’0O�\B]¤Úëœo…×ï(}©Ó?»±‘àÞ!èÛéyµ­Ï±?R��"DR ÃÇHL““ ¹0nt€Ll´>e%*áJIuÝóe ØÊ„át+vônÁâ{ÛÊOm8ÑÙŽ4kmŽ=•ñÅõJ·9¸@éI%õ¡Ýö\«í»h}µ³Cö4ØÈ•féNv['¿'³óý—Ç&+´.]eÏI¨¤KAzP®óÂ4ÉØ�§QB]@+Ÿ†3Ïbœ¾Úl»R4-��̘({»´à´? Þ¨¦¸oY®¢í%q´šz�Ë^…dëbŒm¦Ípœ�ÔZ?:Áü¿w°fd{`Íøà]òÚü�-‚b>—U\‚•‘ ë y©Íö ·OéNeÓ{aåhÇâ!åàObR®‰ú^zML`aa¹<¤cRªãb:‡9">,€Ü +Ö:cWëgYqwó/YDæ8g?Ì~3Ð&!dŸè,*,É´¸�a„Ï™Œ„rNP8µ˜€€6Ö%sE§ñû2¸õÐH­†ËìÙæ�ïú.�߯“&[²ç‹-�f*º©'}ZÌDŸÐF0JRBºCñ�þÄ-¢\JF5’“&r*|o‡r� N[6  —&–?�\…€3v"·F"&,u¹+u”Ìô.�JIPHðßÙB÷¢•”z¼FànáéO,,©�G�…z�KL{ · +̆Q` X>ƒ†¾åŒ<#<‡�2¥$e’Z’ü%¼Ä ó¯áVŽIgBžB¸E?%R3T5Ó*šaÍD†ÅÏkQ¡ê” J<Α‡!‚J¢ô8W�"©Žƒ”ƒTɘ‚ÔDXŒlçÅK""F¢ $AhaªF^ŒM̨ZõB+´B«5¡55¥¬¥}ÛC7Y™\¬¢õàå�6™MgJ¡6©ÖLË8å¢O„ÚZ#—³ƒ*ë©JúùÜE HäDipjËä㜂ƒe—q“úb¡b½¾Æ2\²¢©@²¸ÄçávÓP•Õˆ¤CŸNØÔH„À¡P(Ä@bF&^ ”%E()]((%ž0ÂGiT L…“„$TŒñrRpHS!B„B‘Äì%(8‚!!‚ž2Er¬j1øã+½…`p"CydB»!è¿8D¬!^’ á á1‡1X‚ÙP¡‹EŠÄQ(¶(9!$„&3p6‘@•‡ÍD‘« +�šš2LcÚ0åç0�†Ã4mݶ�°„ÖB†VZ†(͇†­+°ìP`Ë–l`k>ó…N`;¶mÛ +­kÒ‚K©(3P.3ö6ìbܳqˆñx +1›� ^ïRa>SÔbE Ô¶s•ʆª˜&Œ{‹ÔËaŠÊÃë{…Õ˜¨ÊRpÕ«LR“À +¯‘äU�¢b",&4T�˜‹T˜*™†"ÆCU…ÌîÆ&<Æ1Ö¤þ®7…óaÕƒP0­Jêae) +«UI*¬V3X•¸B)Ôç3a ›B½hBýêžõõ‰†?ÈÅ í8aZ2HËRâлYpW¹ÉL� 2‹ CfEŽÌMh…þ@súB ë—PìÖa(†â°ÃÑx�EƒJs ©W”ÐŒ^W¨ 9•8—�»Ï;M3/Ï´BSñ÷‘  z\§ixêA4 v$– +uh©¹“øèŸ…ÑZÝ4¬©q‹[†xq�ßEJ£¡[´MÕ>ùi‚UDÒ» Q‡ÈAšjpå7¤cº£)§Ì8¬ñ¦KÖ2�=Êí��Þ>S'i”©¨³ãÑ�‰[¦†ŒÊ”Ozˆƒ$”œ„ É·‘ÃXIé$,"ÙðE#QR j”‡%FØÐrWC“+¡¸F³›µ)ò§�£˜ÈHS¡PI}ÈZ½H,ų́¤¢ÃïR\£ œ"Y¢‘èÓK ! £B!rL^8DžC +å2$GæÄò�ñoJWp²ŠåU½V²îòè>¿pšdnè'?ò?zoŠId&•)m™P„=scA’ƒ¸Îh2~\2ÖItMgá³?”Ìœ˜qIX®„çâi•5\ëhrê«eªÝŠ,&ªŸ˜ªœâª¶æ)^#*.ÆØÄÑêêžÙÑ\¡·VxÚêf¦A›ùTeF¦­UWÔMJš×ÍÃïb¤¼OÖ’é•ɧ¡¡�­øBÌÝáŽG,2³…‚Ì$.–™Xf%ô¬ž‰pу²7ÂÈÆ�-2š-² +"Ñ$™?2$® œÌ$ÝBd×c&»(¾0›ìš·0ÙÇÓü¢àlßÛ¢Z‘£¸ ¢Ò”uM.Ÿ’«�+jA¶hÜ*µZåDó0:Ó’OLÐ…T’³b:Z…PÌ'­EâºìØ«GÁ]ù‚´Ó.$&št{ê[§%ò˜Hm}‘DEÇr¾F´Ø™D‹*ÑEKßô[�7}¼ +ÍY!õqЭÑ«a* +M9K*üOуƒôxìüÄd +“‚•ÒtE&N Q,44þ�…!šNIÁã�›ñ¦LÎÙ—Sê�AŽ.2äg¦F¡™@£Ç +OÍcˆ(ú˜ +r<‹®©ß¥’L±ñpÜø!MÍX2tiª>kè+k¤¬%±†°E£˜p­†%šÈÈTdfÎN‡Ã¡xŸ÷CCÃ55Ó1ð¶ã!^D qy_6ÍGBì…dJJªQ$Ñz…Ww¹¤¤‚”‡ˆj 5J%¡z/íɾÊBaÄõ“ãu"ªšÚjµ ++FÊÆY�Ú¶S¶2�™±lyi,D0„<8|„F™ $N)"Á‚ÐÄÁ<E TmDíÃg%¡o(™¡ì ƒi¢Ye‘2a¤J,D±PRU"$$U231BlèÈ©TŠ*Q»T<™a´Â\šçiô¡(LË<ÏÏ­Nàß�Ýw­z&„Ãá0'#¡¦h<3%1A„""""B1D¢b‘)‡’˜‰Å«7œ¦åLs¦išg–Vщ¢�hg ²ý’ �qQ}Î׫6“#÷f©ŠP›ãEU÷E•äEE­Â· Qì®�ýñÑ,N!sÈŠjÁÒÌ÷¦OeªAqÇn�Eñ¢K˜ÈT¤0]lÓ9LUÁNMÜY}Qc{¸/ëåpËF9\âpË„v®õ .È‘b»À®è"w×d'Žˆ¡düŒ¸ûuýï„ÊF~_‰É§QjSóGßÔˆdLäíX‰¸³RM¤²b…¤kFœÙ�ŒöíÑ®¶°^}\²áX¾PBúÆã<”#q†\Ñ\ç*6)ܼ‹.‹ž"Ti>ájè '¡h†xœ¡x,0P@®y8šNMYª­UІj.ƒ;Ô£ù%ÐYU…ŽÈ›@fˆ! 1ž<‘Ã� +þÊÛó÷¢‚̳'®f®à)£,Q«ðÃ'ROhÒ:�„`æ2X`@�‡ øX+jr„û%fxÑT�„/ \ˆQ­Tµ¨Í´ŒÕ©šQˆÈ®À/ƒ à�  �‚ L 1 ‚À�D  (Ͷr„Ÿ>ž±IØÚs‰ƒ8¦ü8½hV3u)·©ŠÅ™=4úªj.3ènQ£ñòx‡D£§cHkg#"$Êl™Ë43c ƒí«&£S¡bˆ•TÉòÂ) 8ªXC{á—c!ƒ1,Ï`Œ…Raaeш�Å‚%ô~H^¼²¨GÌ,>ÅàÇQÉŒ4÷rG?ReŸEk«é¤›µVÖD*œÅk©‰àX¯˜¢™Œ¾ŒÄ׊Ú|ý=ZÔ„SÚMà µÄ¡Ö©§¶.£šµoˆ†.ܘÄ{^C'ÍïSº…Ë]D&“É ²_5TŒ¡e³’¯EyrÆ�é¦.s”(*7DŸ8?ç$såPÅïþíß·÷ ?kWSõ|�ŽùõÃo�¬ÊãýOGBãÈ(Œá$fÂ3ôÄ©š’ö/qyæˆñ+1#âoõ\�Yö:ì͆åvøus|âh*ë/É$•Ÿ�I®sÆB®��\V¬HÅø¶‡D.b˜ r>ãñkœö�[Œ)¶•0Ê|ç³Ó¦JÇËrͳ�ÒÍãZ;‘‡l”ä!‰Jò:q,1“©ág¡‹¦t‘áF"‹È�¤!gâðÔ‰~üUFg:Ãuj‚ 5ÎÔhUGÆëªÚ¦Á¨.Ì83²Óéø¸ M°Šjˆî}$EaÙ¬${]õª‡ÄžQê1%fE[Ѩ˜š§¢j"Q>ZT• OŸ!‰sF+ÍRÔˆ‹Mmj%‹š\«Ô<1�R5Ó­ +Ê&¬3ʨkäsÎÜ•Ùþ{»—73 Y_Ñ“?ŸS¶}"ª5j$ô­µ/'IKhõGeÇåcܙ٥Q}ÿ…êK˜.Ÿ¸ôǬšØ_g­4Þ+Äd�Ù�fEçã¶7b’JðHÊ+Clé™_Ž#<3¬q¬÷A2™‘—<¡í-o„hÝÖUB t©ê°‹G�d!$S‹?ŠN-L-¤4âІ$®ìª™—Ðk‰ÆâR q�ñìžlÛ®˜ø&¨â¹!¦kˆ:!®H©«t¤cÑ3‘ŸddÖYÑÈ*žñSqÑ+%uÆéŒ‹3açk›bYK4�O]¢:²…�×~vé"dñ²¸�¡1U'E¶6ãò+¾Í8‹sNEc’�˜5A¬aÔ˜Nã’‘:¬ÊEJ ¢ˆqïbë?�pQ‹TöDÑQŠöS}f¯3w\žY‚ã�"^ÑR¤´5®xUV›&Iêþ·ž„Ä.Ö/šâ’»ˆ´ØÐ$îgß.«Îƒt7Dgð±¥²Uêõ‰-VcÉCÎeî¸yÝVÛ¼ÅPDdÅP켉ÉPVŸÍ+ ©�Õ&ä[Þ½èWËa†êÚ¨W+‘T­ŽF/Z¸ºN4<O‹‘zôO„:žKþ–ÛÚ°U¯fâv´ë„Héjí4Ó¤bÞ6s +3mÑ/Ó¿Ê´þb³ —.AB +U8$C‘Gž ÒÄzžQb.ì”iqÌŒ,©–Plœ-qYdˆ‘›<…�8@(XÅSAí0¨j�� ÿÄ "ùé€` +ø(^ôi ¡í-n#¢y8p‘pÛé3š¢ J+¢·F‰êè$R2iI>5 —Óžå¡£Î3’•ŒFŸ;ÄhÁ ª@ª +vÐ#øÁ®9èE�F5è�M…È6ƒÄ‚‰„èT#AdP`É Òɳ ¢K!BH´5ˆŠ ¨ª²ªT®ª¢â/ƒRÉ뻄º\Ÿ¾ÁU—A•„ÖKSSSõ*)–YŽjQG%3�ˆB©ôpZpPè¦*PÚFÍØá¨u$T ¥Ód­�\îðɧ¿ÁŸC}²fE�û…¾ÁÓ~¤<ïÐ×ë!þ8 1.sÄ+”IZÃPÁågzK1d\îûn{‚Z·ó‚;2¶+&�ƒ*ŽO0ý®±Çƒ]Z»uwr(z…j«üP V(µk û +mtêJƒçPZʵnÅ -Uë¿m;.‡°‚´ÔÖîÍ %ŒÖÂöl¥CëÏF`ß–e×OæF+ZÜ*ÔT¨‡¶Æ•šÆGË9…Òt¥‰Ò“ÔSkÁOé¡G”½J]®03C�(†ÊX"¸Df†A†CžÞЃCL1b³6ê¡æP²à’a( �¼;�˜„Ä$ž@b¢Ðh $þ4˜„þ²$&7‚,ËÜp(…9 iWŠA$ü@_L¡ø_)Ê#Ÿ`ñæ…ì !Uƒe:U@ç´™¥ø òX|�çiˆ DD¤@,±È +4êLQB¾UR +‘Q(„üatÍ<: ”S ÉŠ< Ró}<ˆ|<#J!úa +æR”1T¤*¯à1 …‰V¤Â¿2ÕÊeàF m¦£ÉMCÁò +–sŠ–¹L—ÁÈe0†‹ð¡DbbëŒ33.gÄ<'3S‡™ágún&LQ˜ðvVvÞñpc‡{~÷ ‹Ù¿-ñ@ÀÿCásËLs’)jZxg$Ôˆ ;5œ¸ ‚BTÂÂg:¬ž —{0°�½;�Ò¿&X‰ +Ž™KÉÔ 7H/µ0�Žÿ í{TÚ¹îé÷dê„ê[ /|ÓÉóePaŸ©Š¨ñe Q†1ÕHŸAÆ¡êË€"¸däû2bòep›ûE�ˤõ?P„þ3ã·Á¿½ „Ë9Ђ¨A2ùжS] ™@:�ø"údúD F ? ]-/ÐéUJ0‘ I*\êy0�NE +.iT„?L—Áe°y‘Ñ#B‘«è­¯èžÉ*<Š(]Q¯ºÃ„3~sQxY üL©~¤ ÕqŠ,aª&LÉepSXWp}EÁ£Õ$|Uÿê¯;üÅ +'ª²$4*H4‚hA 4"΀°Àй¯à˜ ôcê‹À©—ЦnføãE^B2�èðpy,Pœ&4M th¹hb…ZBCtk­_};„H¦�"�ú†Vê¹@�†~b„üQAë€W+T2¡wCÏ +íÏÿ4¡ÿØCga`ï*/� ½L«€P”(Q 4"µ~Q…o@£…Ž:ü¥I9ÔL +ÕÂaäßÂHYˆ.ƒ(*'S(É–U¨ÔÜèìµ³Š¨Ô4ØÛ:£p@ …C‚Á¨tû€›x8žF‹CBA(Ó*²"€èT¯'¸)$õˆ£Žžà!Ç]Õ\L\Ì›ds)J`EÁ–‰†ëQâ^±õáb¢ç¡»Þ!Ñã!épüÆ­€×?ØC̨4“¥‹&xJšT#Âû8õÞ‡mÒÕî Â–ØÞ*poPŽr6†€wÇ 1ÿôn·!ã;ÄúÙ~|ìÚiîéL¶Läù)ûŠ‘–[.ÒÀôbS/9³ó ä½ƒ,!kaeÄ@°rÐ KŸÑ61L•JáŠx±PÞp„[çÞb±äw“…kÈÛMèyu�5�#��Ñßt' so$fÙm(¥A„Ïáô–æ sÇF‘ŽÄ„¨ž'§Û\˜M?h&¶.hnzOÁÙüØP�!Æaæ¨?^ “Þdñ­6{ƒEgn’ƒ·I}þòçšÓ�d!õ=w�cŠOõ–­pz2Ii›{ƒæ#�-¯*h¡v‚ë”�߬âd�¼Rç×ÁJbļƒÃÇèîNס‡ÐI6C§w�ÉCåæ8ƒ\G>¹A8Â~e˜…"ŽpÌç§­b+ݯÆÇA¶G’P9'Z-°'ò_LLš+P›d‰÷%AeĉJòð™ —ò»n/˜‘l†D§€Å«ÎÚ§�f©§X8YÉ56Ð;pB²Áx~£s¸›¼#tíÛ\)ÉËÐ_HÅFi6"0¦”\D)Q‘xê•ð›^Úãwy1,@§œÞ¼í²H8êñqcYlI˜ìÊ~åŒ#è‡ °%|Ë)*’'†šŸI쭗󨿑ÑGj:^TÁÑŽ—Á†Ëo/B…KÉ€-�ø7‚¥§šÉkÇeE ¹˜b3¢åŠ›G*¸ˆxµ´·u�> €Û0ùŒÊ ¢×Ýùφg_¯c)òN =!ÄÕ‡rå^¤ =’ª•ØUv®™/Ôìp˜£Šƒä&æN³ÌP˜m ÚZ>—|+ˆ(“§Ÿ KL­Ïf8QFK$íóuueŠåâ¸?")ô;ÅKl+aoŒ‰Ljûª^€û|¿lt’ 4ÍK}lº8ͦ »ð§õ º1ËüË2ͦ˜4„±äk¦`¸Ÿº÷³Ñü.Þ ¤5À#qÓs“£ª{4s±Î¼íÐèœn\>aòh—˜™»õÊ�Ì!1$²ñ\¯wwQpþóUŽ™,Fu§rƒÒZ¸Çȶ¹0!µ©›¾1+«›e4ýÍM¥Ø‚…¥ŽíHx+ìÝ2ÙY}”H¤Fu|ÉON¤›/úÒ©`µ“ê£îšGÆúá…{r�ç cm·<8ƒXt@p²!Œ«’²ªÇdJw±ñ/TÌ–�C«z‚£STÆ[ôø|a�LÞšÈ Š²ŒWðE?ävŒáÉÉ̓(ø@ç¤IHüÆûРÅÍöuI!ä‰# T‰8;‚¤.ç'Q¹¯¼14òó6L žÐ’%@?µès˜,žÜ¾±)NÊHƒ�Š}Zö)úÏ0Ó Zi'²ÓĤ™¬óG`X›¨ÆOª>LªÄ³4éO @?D‰6òsƒ‹B %:ô£ÿ”cÇ¢ñ&§¡Š5„ ó%†·½†K¿1°3x¦å×rÓÛpNÈb§HÍé�ÌVÉ(jLViOÑUèϼ.‹Tštcùø*Aõ:iDãŠm5Ã!8�³�$T©hn�*?MJQÄšÎiê±t…åÖ|¤�Ëd±�à ½4-˜#¤›>ÂÞh^ˆjà’õ§+#ÝõVua_Ý�à}ñÞlx×eõA²rÄU]HT­Kvìhò›�:}ƒV3ÉRýœmc GŠfÖy·MûãCl[ÓS m€»{Ù•„ØQÆ�Ó€5º +nx!…F¡V•ã�Īã"Ü­¥"ʺðá´þšrÞÁSE+—R‰_çñ�Þ±N¶´‰Ì} ½Á¥8…43,ùi2—Þ"9�êm÷¤©bI™wœª@}^šº68C ‡¨c*޲�ð4ë Ò>Üä=±ãºÁëÓÆùNüýp‹å©…›ª+º4ÃÃv=ÈÁëDaÉjX 5 +`ì¢f—1œ3Y7»p†]— 2ÍaþâE뽊æÅ‡Nä ôD€Ò¼!efˆVÒ®œ¾‰±‘‡ö''—vJ1I[ƒÄÔé:®¡1¨ÈïzôÇkû•®7d´5OöÍ:€¢ ª2MZw?Aq¡Ÿûš4ñmfÎn$&|gÏÿÖpf’²O­µ×�á‘…öCÒ°0pÙ4ÌZ&NzjŽùäBÂ|Ô$àL†ðcÜò ¼À Øðý5f€«Ä+Â2À}×è†ÙG`p6àÍø +Ç"œˆdb¦»|¥g27¾Ê\{F”ÜÊ„‘’ƒî~]�›H¹ð2F›úI±ƒ9JG‚¶ú�Ch D×t4üš¹Ä_êÀUf¹ôTn±ÓøIÁ zøúË]E›TÇ乡½ LÊ’ùÍK%,‰…,e—¨„"•AGŒ‰Ôí‚ÎÙ=Ìûp¦B*ßgL"šµŽ4±'Ó0ÚMàÉ/ÍLÛ2¡1,÷ï̧ÿ‚þ.Ó�ïCÜŠt™qkýŽ!ê~ѹƒš,ETsÿüHd]ܳ#ÀÑŒÑÄÍ:‡½”I@ãa¤ ]¥U‡HõÓà}¼¦/dVfP¢luÒ9Ò/ÞêOÛ0ZZäÆ[@“`�JÆ^eEÆzÐ_DuŒxØ=Þ¿f†¥8Zº�³†t]*�¼êNZ°ýèb  µTµ0¨n¯Y1¹bÄ…w9P2–Âw×Nç¸òŠí=Mˆ·"«ùœ¢R#ìƒ]ÝîÇ9×ç|bƒ�Qq\otô�dãØԻϢÙpZáB8ƈ—M®D� +ó‰È Ï]&�¾f&FA³¶ßy*olWb.� 7Ò'Ïœ­!Å- j(êŒÄ{¹eCD8"ãòôÎ2+}¥dìì‚K +7uÊ[£N‰‹$îð¤Íîð„Ø|*î^uÐ=&”ë‡ÑEò¦YÅšjn÷�ð²5ïGÚóŠ4Á 54DZžpdáôåc×'ùÃò\ˆ® 0 À²gŒ&’(/K,£‘3IùwŒ‡Ø© “³©”+A%ÖÉ_jÆJÁz 󾜬ÞoP/�r÷Ÿ ¸•7]+Þ{ð�+“f]«Ÿ+vÕO^" ?åqÈÚ'‡KŸ€fÄÞö�"^ÛÒó¥iHþÆP&Œlˆ½h~1>ðIÞ5·C¤Ûå&ÍÜç0ƒÑœð¦¦j*z•rÀè[êt53ŽTÍ$)ÚÛôøó~Ün‡X$³ 5ÓyÓóÞîÊrþÆxtª<ÄkÝì‘EjHÙ\Àgˆ=+����p•â$©ÅTÏ•X™Ò|7H›¢§¨t¯ /??0°„êÝ4éÕPÜSGZy§A„¢ÔRT�`«ö ‚$…·ät|úq¼`­‰Kïqÿ9†ƒè6¿ [%Z¨Û®ÏÈH]”¾1_IœӀ˜ œÝ—kà¿…íI;^ç·Ù¼ÍW¢ËB†ÏiáF3*;ª–­fbÁ!:hÓM7”ȼt\6ÈÇ‘,Lo< +v:`€zO€ŸÃ˜�ì“@�Žç¡ï�ЛTDЃ½¶�°þ½&ðV©›7;tܧ!nCª4Häyެ¼«às<á^áÐShplUÛWÌ0ÈÔ34-Ô�sY­Ð ›¸ÈHB·Ÿ—‡Eõ Èúò§.ú 'QeûÃöp�ðª:¶xHxî¶¼Å:´ÆBÃ7¹æµNa+Õ¾øÇ%™c"JðâFH`…o³m†¸Y+[ºêÚ˜$>.HS‘ÂÂl'7ñ\ïî3% +@üÉ{eµð0ÈÚç³ +¸…eÀéƒu'DtYŒ‹IFÅSk#öAþ–è¦��^�4# Û©TÝlY˜…èÆË@9e#¦í‡F?°^¶êk“¾¹0W×k…ðhd¼W7™¶•¤Å‘Èô¸M“ím+‚„jå'¶dÔ«‹SùŒélŽcdÀÔPÑ�’s1> b†Ìߤø΀ º㈧õ—yÝð›�vn†:¬;c�'8\hDD£œ,åþ¯aÜ7óƒ¾0DÈäpü“÷%|Ó;¶<­ âì²ÔÄvéÓ*ÏO�8}:Nàj‡È#o%Ô£À‡!´Á’fcB¼<þjz÷×bážšìI×£„|—•š.Æ­Ò°ÙŠ´€V„Õe@º¨¦|ÈU÷ Æ8zq+?´Ü~GëÊH97¡aÑÕN˜ÐD`É 6â|ƒÃž/@U^Vvy}Í!è4H>Ù³Nó=UÑ‚h&)wM`œj‘ìZ½¦â0ÌÀ ?írîôõÚ5"ÉËåõŒÞf"Û2µ5ãJ¦ß]6Ù"ij¶˜M«yã“ÐýcL!DtíÅqS„æfﯘ¾?±f•¼«WXªúWteŒÂ®{’# dÖ{ÝK¤WÌ1µø4f…MŒuÜPyE¨"†NçâwKУ=ÃùÇ –è�:{âU©IžÌ8™l/ +°H…m(�Øþ]éz³–åj“‘2ÓŠÿQ4Ÿ&ßÓçkü†‚_a¼aV· =©cè¸lU‘ãöѶÛPµ¸†‚q,(èÑÔF²7Ø âgê;�+3-PyGÁß”ï:5§óOêâ‚&¦!·š‚r#–eØ¡Àˆ²ðH¸y¹ õM)À�ð{ÁªKÉ2o “÷Ñ㪓욣•ÀÆç=4—mF\×}ÀQ)•V�ýÌ¡&lYÌýºßW}Ãz�_.0aaAù¡`ꮨª0~fnã�”�X„±”»–?­ð1‘ɼÙÞ/`ÝÞÑF}ÙÙ:ì!ü +Õâ%·-Ó>:{Ëh0µ$‚‚Þa�¡1;£68eÅãÌ�¹¾y�fŠØàVJ¥÷8N§AÉbi<$â$xÈw£½l¾>�d ¥ãˆ’‘Û&èq|IÏï"m6Ô^äç‚>¥iJ±—ýíø%@ç¿24œŸV8îÀl|E”ª£<á"îCüåRAQby5²LTWú¼å�ƒ÷GŒut¹Ä2æ|Ø›ÞÈvÇQ(½&!gï3Ì�¹«”5Jβ»Ùý­¼’w+© s ‡.¥¿Û¬1ºž.�Þ±!Âv‡¢ú!ÂûøÎ�š;Tø|F �›©xùmi¼Q€É×fܽ±QYÉŽ=&‚™<ÏØ +Ieù„}öO‰,@Ç ±3 I+ >¿†�Ñe—|; +¸®ðº¶Üì„×Õød*&ÂʺǸ(Æ“LPÑ®”£ê/¨6ՉDZ9ݸB¶ÇFá.dp3~N”ñA¥)’ç°’o¦e{ªH÷ÒŠË BKœ”•h0¨+ #ãG�¤•™}dоj�­_�pL»ä×°G¥p¿çi»ŒÌ´Ð�h)¬­>W©9mnV—Íö õû…^®¢ÜI¡‚æ0=þ8{9;šb‚nZ_È êNÌyƒyüIëÔ®}¾€#Š&Ö •ûãÁøÑé"_ç‰Z%Þšß“rn(}×Ôb€GÍ¡Bü¾«1´‡šÐ$ ˜£=rÓÕêÿŸÞ6zr¨Ý=ÍVžäbo’EþèAk(˜©œ +Ò4WÖæ""ùq{„Šš~œ£Ë÷B$åLXð, þàáºâ<—Ú…ó2¢BÔë3¦n1˜úŠAûý$ù•/sƒî ©w¹d—»zXC)Nïžð7¢Dö}P�Hû‚0Äã¹›«Á +ñÍåÚ¤P>¸Ç™¼ï¥@#ŦÉ\˜°%Xë±ÌÙ1,½­(%‚kt-,y0‘—\ó’ȈZ´Î—*VÂ/ž¼ÝÔRí�Z%Åë}×~Þû]±![çl'DD&Örü oæµ�©¯ØÈGæ,ÞÌZT”2ãð O�tS4Ê™9’‰Ý×ýÁfÃFk¦Y+ê¸ ÄP™¸¹:Z¡mÉ5¡NM½ìð… -ÓÄz "R˜÷�Þ¥¯n)= –ð쮈ƒ„?„Í{æ©f„K%–CK/áÏÊöÂHÐÙÚ 0G`A{ÜïÏTy®ýT§D˜Ú~"0Ùu÷zî|bï1¦–³;òº­Ž³ Œ#»›zûâE °”É A'äú�Ú¡h–ÌéJÒ©$Ř[ИYAøy¾IS +ùý ,±t8äøËJxTs’êÞ¾yI\ÇA1ö_÷òeÍ]-µ•Ðéùk]Ƭ´sL¯Þ_÷fÛÀÎDaVë6ÇÜe“.!KBÚ%²9«?a›o5A4ÌòÀ*û¦ãiíè*øßó¡÷©Ãùä#bu6(Å»øÝJààea0�ã¥eI \pî\”¦�ò´’÷´Çø$˜ã‰9Š –Ÿs§fÇjf7�•G:$$•ÑêKË}£z<ÕÆAH§~‡¾æµ,¡‹ÏHˆO)ø½èÎ<ž˜·àPê˜�jÈú�š�9Ü*€}JD¥ZéGìpY › æŠo¤ƒJëЛ`Áà¢ÕS^+•¹Åÿ«‘Ø8;Ù»kEç<¿R”Iµ7ÃçxÙË“vD3¼T«»@¹£þ‘ ú°ÿiB’i‹'vÔ·ÔK^:K A SŒ�(] ûϬêáŠ2pdj9ÉFÇqA&l®å‹lH=Ì¢ê‰aY~²Î·åü( ÈÎA�Î9Ì&�Ü6ê3ˆ.UX€/„Ç”“ã�8mAÈó.öhz٦Ƽ$0P¤Z ÓñÞú1ëÑ>³.^˜Ð­åA…à^1Qå|2äT‡6¨¿@α+¿èp¢ó • ñFÊóÞT„C�&%¬Iœmîê?µ[~Ã"{E¸ô<ªCþ�"†9³BPù'ùa‹ãɼš–™n"¤èè» +=ýwÈ!ŽWr)¼. šøW»ªÚù¶AO‹ÇãhMFù¿e^VOAÃÃŽ\ÁÒAF½ªÍ•ص|ÉÕƒ*ýFÉ.’'t—³©Õ4 U+éCÃß×# h~ %t¨·k¯ÏÒ$½³몒œ‹w�<*t…�™0vnÊ0 ++ß8´ƒ×?MWqBæiQI*ïü-]£ ×Y9¶ùÿƒœîÚ¸rœà ++šƒRûi¥ôa}�Ƀ4é.BÅ®ÅÂã$}Ö/]{læVUlÔâ¡ÎüL�jd-9 +4¾Lç0ÓP"šiï“°Ž^í è¶¶tI'­¨ñ ‡†a38ÓI¶Zâ ¤:ŸË\mÅæ:j]²{æ¡Jau“�W�–„’°æ«S&L‚t”ùµ�Ò¥+–¡†öP:Å8›íf¡d°„'(›ƒ`»æ§cíN…Z?p†ÐâÂN-�ü>´8’$t¥©ß£-‘Ê*.Jl4ÿ×½Y.ðNÖÖ›æÒr¡Z"¢‘]6í.çÿWcŽqíûæî�£ŽÐSBKÈ�j*?ÜXoÜ¥›O)�€ÄwÎMa×Ì ŒE•ƒŸú÷ÈtXã÷O×[ƒBaÊÒx«kšœ½ÊöºYîè-Æ�”Üã•ß¡—K8=Õ\`Íü_;Ãúô+¿„º–Ž›’7qškÿxá‹sÙIožÛ´<×/ØIεùŒÿ€N=%2Ù6&슩×<â´ƒa7V⎠3ò­o9-a@…Áèɪ°¬–ñ@Ý<¶Àj‡ã�Æxä£K§ iG®Éœ†î§Bef>;€BÓê¥É§²5¥îOCž Š“à‚ëà%!IXc\vÆ7Áy*(´3ÁzŒ shˆv‹·S†A=~qÌ#/B(äEOÚ9ø¤¦±l�¾ýv÷8Å7=´ñd¨"?ÿjÄD#YN¤²]Ÿr"`ã¹’Oà›TÁ¹6 +áfµ:?ÊXcí!Tp… 2�0d9èrtmóSÌÕ Ûë^ë J-³Oxî€î8÷2æ´ü ]s�ÛÙU{…ã�›"ºh–àI)¼U{³ó·Ü²(˜S@ˆ¶a$ŠÚɬ;“Ýôu7Ïv‡¥¡ë\‚iY‘ô)ãUÛ±„«(³»ƒvFÑRaQP‚œKžÛåÁ¯X*1Y`¥È¦]¿m¡Ðéã\?¡™g×U l-ΚÕKd g÷D_ ŠÇýšŒZÀÄ0²¿ÕOˆºŽÓ‡ü3ØkÖ|Æ ê�¤íT-1"ð nçË7@Ù⪵%änÅÞÝÇíé÷ò]+}ò#-�»%aµ­Ü“¸>_æ¹MñIRÜO d æö÷I--SÀoËÝQ81ëò ßLõ6¿‡*fpÉÜØ¨‚f“E{¶F–cŠŽulµ§jê|�@íãØž¹®ÂÕ}ä”ò„�7�ZìXdœ“ìúVa¢)Ù¶®ÄWаªR[9}‰K±cUT%²3Æ¡ÝyK8;T¾%�D9Ìr¯‹öHþò�ŒÆÿAqä]ê^‰/™vÂ�2ÔÞNå´°ß9`“ !Ï3D¢3Â}?�¹·;œ+U¤ÎâsÞ¶-â�ñ—ah¯…ÓÕkiìžÜ]=X‡ZáuabVÛL[F”¸$µŠ²¶0Uºª(6)ººV3ž’?�šO,_l5F£ZKX¥ëK•&‚"èÕ-á\D䨤»¹§ç‰¶_š&VßE µØÂU‚1Î¦Š´z'Å–d)HaY*BhÎ5òµÝIFÚ.=FH©Í×(ÞîÀ }tb (%TìM?>äm‘¹„?73L)üUÒ"3x“½`ø—ª²¬‘§z{$ÂY}­/¤š Z‡ùz�‡åüÞVi|ê $Í�,Ï`¡x"¥EB¯¨D`L Åçmˆ}5;cKR=¸FÙ~DwÈÝÒ#ú�í-÷÷"-j2 LúYCeÝ 1ýŸPŸ?4¡\ ¶aáÈÅfq@ƒß¥"9³,uÆ€içÕ�<˜K{€d¡0ê^Ù‚ŽH±pïP«—¦lë_óœ¥ës +%Ž`X´øç÷¶:ËckÆ ¥nT+�a&¼S°$:ê+$»µ¶C§9ëæÜzÅçûžïzØx'ŒÊaÿ$®)ÌÀùA +³Î’Zož!ìH?µÎ éüB×ãÀò„+–â«I85° jÞK`"å$âz’-Mª&.¢Yù?t·Cç±f—•3íó#<õßKgF‚7qíÀmCÏG¡M*…ý-UÜŒ>_ÓDQT0‚ÔÕG›"¡¸íë]ìPµêònp^`¯0ª GZÔ°íY ”ý C%ѰøMº£D^“<¹p^¨¶Ô=Hûµ‹�sõ7…ù=zª©�ÓK�ìwç©u±RNOÁ¿Hy&*˜„ VÏ©±KÍÜX»|ñâ¡�=ƒ] éÞ†û¯ˆÃ3ö—Eé´æ~œ«2wÈý»Iv£ˆ®þTÇ eõGv“—À5¦�¡e•¨k•ýšn]óØrn$ÕŒj^Çbã½óçé�áSºD.�¢ä%¡˜SY™“µŠåEï%€ÓQàÔämÀ䆳†m€!ˆï z¨GJ:©ËÂ|~8H’å¼ÛFŽç)%ͨa⪌÷òý¿RïdÙ‘]ùi²Õ£}*É7nÃÅð·'ÉÅ&áê¯�Àm¼‰÷$'«^ÐM�`ÉɈHu3¿F9ÐzNJá@;ÁÞ•iD˯ +=àÛ0燺ľB¬•$Í(üz�ýPët�Ô^T$¦R2 �_.*V5gßaÞ\¿T +�RÚÝ#®-,Hù ˆ^>”C/\ÿàöRúúÿÚ4¯ÊŸ¡ÝŠø×É^ÀžÊþü? U´tjU‘'Ú{Þ+¡ÎTÏÕ•òƒÑ­Z {;4_sv±'b»¡‹95®i\KˆX»ËŸ•.Ì(ìR¹:Ld*Ëè‹ï +6¸w¡´£±à!WØ +˜�•“p1_Ìõ­Njàîõ·‘´•2…,·2H lÉ„¡‘‘Šœºyïa¥^¿B—0DJd+Nq rk§Cò6“æ +…¼K6‘ *%7¯¥õØ×Ù“抴íëØ=ê¨mpJ²HG ^Êlàß[´­ôi›6kç½å¶ïöËË c ÑáGü¥Úø‡\Ò  µ²š0ttù{Ô=Þú"Yô—ŠAaì‹¥,!ÆŠY÷Þ³V¤¸~ÉÔCY´ü?m z{öãÊbšgN:òÙ”ö�4f·1XÿTň>¥=èüŸ¸]ÜW. ԶĈùéŸ0¤]¸�S ›0bÃ^P‚MáúŠ0Ržá0q@E`k/2 Îvrí{‘;„Áò3 J0´]1HŸ:½4(Ûc@QŽ x†Pè.²Í2Xø•A‘Ì€¼Z»µœ!dÁÆ8”ÁDåFao Ï�í¶ˆUÑ•q' i[Dç4$ÁJ @rÓÕpÊèV(5‚´-‚Ÿ6À—�’ã5#ê°H°Üð¥ºD÷†w+Âp8¨VEÈ„C%2VâO×�ÒÆá½Š¾ìÊaˆµæÕø(­ÞÑ�­Š€„: Q̬ÁÁ/v€¼Í�Êr];ð º5éí;Ì>ô†‡E'‚ýx k"HÌ–'ôi«HLùì45_ðècñá|aœG‘aëÃOû÷áÏ#¢ý`gD4ã¶gþÁ:"¢@X5D\G& D#Dî£!Š ÒŸ�ÿC@iÛ‚ÛC�m@üƒ`¶C°‘¤t8 +A“C€h!à_ã1~Ü�#É;•!€@Ø�°³< iÿ ŒgýWd"dÍQ ±Î@ð`¾ÄPéˆè–é´ˆDZˆ\ IÖ‹ÈW!f®SHõuVîúª¿Hã )Ž8V>¢)¤„ª#<��à<âãs‚<Ia#€½ÑCZ„ø@GCÓ�žN™’È™˜ 哸ìƒ4‰O¤ß”ø ƒD¬×o�æ+ñZƒôÐ_3Hd\âJ Òè%N{ÍL¸² H^` #câ¦%XüO™˜ +ÒÍ™øt â*i¶#ˆk4ác!ˆ—j“ÄÕ² Ûs .Ý„Oˆt8aó5é%i,s"C�üª8p¿è#�=qû€Å'Žz~âÀÎë³M�DÝ‚"~D±Ô4@º(!q‚ÕC1I¡w¢xJ˜uzn£`¾eŽbâþƒ½ÓKP‚�B˜Çl-)håçžJ£Â¤—¢\ù#DSœÁAâ'îG­§ø_? + *.¨FÅÒmCÙ¨PY~à¶T¼?P*hš 1CUà ± +`ïcùRîÃÒUøi…”ÌûZV„¯>(µ"ïôAìV„¢ æŠ0Ï¥»"ü>QÝ+¢”+‹䣃°øB>*0Œ�Ÿˆ…Åó±¸|@’ů߃¡eq7½=žz�ågá®{„FZœâvÔÂÏö0d-Lh!±…éØCÕ÷z¨-,TpߪG7·8‰zP¾Å#ÓƒáâCzp'CJ¹xöy°ÎÅm« ë§§‹›G »8Æ<”Ë]8[ná…)å!,/™:€lÆÛPBqƃ§ƒe�qœé ¤g\«tp¥Ÿñ™ë%4BŒ ä¡–ŒÌ FHƒéçˆJƒ«ž€™cç€Î"4Îá&j×(95à3tÌѸj_@_ ø—DÝrAkø°ã •—×€?9Ð(ö‹ ´%ÇlÙ°4rÈφñ ‡ÜS6=Áv‡‚eŽ¢qÛm¼ƒqè*X&qÃF¿ŸKsC�âèA�8xëÆÇ‡#ò»qÕp4Ðo,E¾qgÛoÈF8$ÙyƒC—PGuƒ#CàŽˆ&Ž<È�cŠ"w¿Ñ¤CE«^EŠò ²Ë8Þ¹7ºÙqœlèZRÔ!rÐ)oorülX9Zq7Â/ÇñºÍqšnTqŽçF«žãˆr£2è¸üK§ÕL2A +ã«$ôã†SJÇ—€a�Ͳ˜:• « ñ3øðMÅ´ÞNÞÁuœ·!h–aÐN®ãž 뉼:Pô¹ðp¬¢P ·1TvW)Ô�mÔðÄ u‘뀻6`�jÿ§­¤Ð·Æ¹c§ÿ­´á&p— ic~uÄ�6¤×Ýl¦Žàÿ²8Ó]—�°Ôá‘dƒmê¸nl´˜¼Äôè×äÆF¼xL¢ÄÏNGH´ °9y{�1¥4€ÓÕ®ÑO¨£.é +ãp:<¶„äœý›=kä6�5xtæ2 f^�³¤# ¬†|Ò±S åÒBÕ $ÑŸ'9K …¶Q£ŸèÈ50$!~ñ½Ëi8#:N6AC ш_ÍÎЀÈiŽ3„† šÃî�†¨¡ý3|Œ«Ï``Ù3þi/ã\)óŒÒܧxbèŒå²ãŒÀsŽPn¤`j30èY3"âÑ ü²f:ÊÈ ØçÈ…˜q_ì—�¥Q—ÁªsÄl7'®Æ2ú¯¢2ÿV «¢2°j¤ 쌟 öš#n“qé´dRs„ŸpR÷•µ…œ"2¼‘2àœã÷£#ÞãçðhÇà“clèmc(ÊÒùâdŒ9Šƒ1¢ƒ¸ð4Gø+Ƶ0ÈãÆr �ë"k| J ¸‰¶ˆ�FÒŠBA µ:£b9Œp„ÃËqŸaÀa@/ Àû*ŒŠ� Ã?\" r Œi© ÆUÌa5Ã%•5$ã1FÁƒdäGæ¾7 Kto9®FC§Þï™Cèµ9à +Œ^ÙßyÌñ—rš;© h9&xÌÍæÀ¸:Xíç@X:0ÆÒa¦™….`\òs)߀„^Ág€+«c!ÿBU†¿j?¿À ½/ðË«/Ð)™/à¨#wøâqQN�º{ê£^›†^€Èt„0/®Í�H�áŽ~ßFGwÁ‡täb~tÀj!¦ãvAj°.æ†:üÓ…WÕaj7SÄž ’ƒ5Ó¬Ãg¹€ó:î‘ âbÇ;ã‚;;žð׎�pÁËJúÀ¸Ãü[4ÓŸŸòŽkoÚw|í2ÁÃAn!×ðð·-¼�@)maY<d –�üׂCy„m- e«K˜G&µøæ<@›Wè�”´xYzà‰ªhqw=�wÏì�àfA #çe,ïä²p|äSÞ�G¨daS>A.8É ·ô†±`Á‰…áÜGÞÃB?†æG´ÁÂÓúX8¿i¿ÂþÈÊWˆHÓ+ð�^ÁÏd×��ˆs³I‹+øS@B,°<³ÞÑ´M œµè&­hþ"oV à@ b¿3á VLÊ1¢ Ŭ ?»Š†ÒV!ô b&«¨Dƒ<¼YÝõ¡ASqã /U…Mb—*|!†¡ +#Ä Sa®„˜˜ +‘'Äc{ +QN*®°üGÅQ³¨ “ I5TÜoTpaH0?Å3;O±VCpuб7ƒsÁ†StÛ×#æ£Ïre˜)7¦hÐ 1ûR@½!×R@ÃÕÀJÑ)2)õ†«†(lRÈÖ�D’Âý†Ä)TˆI-fã<¤°£ˆíCnEã¨d»>ÄV. +’ÕÍÓS˜Z•(ÐÌ +d‡‚m>$ï…âÊmB�©ÉY4n½Ÿ¨ä‡ì +˜>h &ü÷‹�û„þó‰ø>ÄØ=Á,SOä2OŒž�r'0\Ø þ‘ÐéÄ•B4þ²rBæ@dß{-Ñà%C$¤hˆá%Îx ‹0Š›¬Ð&ȆHèkâ.®Õ’‘“·jM"CÄœh¢negBZˆø² +‘Gf�HÊD•3dÂBBä cG"qŽ˜ˆ"L œ ‘ô½Ä/AÜ%Žõr ‹6—@/Û[1ÊnD®j uŽˆ³„/‰HàY㔩%W"†•x9"ù©„Ã’Hô”кD¢•z7‘dÓŠ aRDù%áKEyÊ[‘NBHÉÎ$TŠ—D­m‘¤•ll’²‹Ä¶‹Ý=¤¿È”íAña$TGÀ`ŒD˜±D‘hºÑH€X#�„0rO­»6ì# }#Çöˆêqä›Å +:nG`dG Oñ*±p=b˜Ñë@TŒ>bG ÝáÛœ $6ã O#^H¸g A$ÄË<Š8F@#á… –„$@½ˆÉK! ’xÏ"l—Äáak&ñ©"¼os)“8B.%CBC'BW”ø1É&%%BÈ)ñ|D¨M‹Û¤ßÑi•œ¶­ÄÉò+îC\d Râ-�é?µ%(pˆÏ¸œÒ‰]ž!ÆÖK°ÆË_‚ë…8l´8&Ù*Ä +1Á‹B64!ø“è�7ì!42ÉÛ`Ë%–k&Ú(u ÉâÙŠAÔ&J4y¡;‹PDÂrj‰MâÅðfM’“Ø$³€ðqmr€PÌ}¸oÓþƒê3 â�“èüÁÇœ„»d¡“õƒ;u’”TÁ@ÒAÓ¸'¾Iòú ”2}¨O"œ¬äIš|€Ô(>à/ | Ò“d¼‡9z‚{{¸‘oö€¡ñ;»d¡'ŽT=eÛ€|UÐCªÄrÁ(U{h%G7u}ï•Åy^J¯ +„í¥S[pLq„f¢'N!(íª}uFöäË_«�=¹²×õ ë ´N´·®ù=Ý[·»÷ä#â{"ç<œ¬žÀ…y˜Ö  ¿°sÇòä¡gõD¿KítO¸­Þ“uáÔ=9 +<®ËwhTOÀ;ñ9­žˆ�; þ{;xĨøá˜ÆIÖ¼aàDסÌõĈu€�¡:T¾ŸY:°�ŒãÞA‡Gç‰_ÏAÑÕâÌO4ä»ËÁé<™¦rÀö¦à-oñÒR°î¾Åy‘Q‚_�\ìH +ø†Ë•¤€sq�€ëÇ…f£Ÿ\0- +�ü°$ +´ð‡ö` ¾Å#¡ —.FäTAáéºÿ G³ XŸ0äÛ;Ãô;ïÒÉôl˜ƒD?ìr€ÉxÁÏ|JÊ‹™œPB'l;/ÆÛ²ôrº&€]/_iÛíåÉ™_žÉ0ùrUL€—¾\� Lܾ̘!ùÅpK˜Ñ~ñÊûË—+¡þ¿XÙgyPfÎ||Tg\|9¹ÿmÞ™îÞI‰î çŸ%B “ˆ¼ù™ëàütP  qà4¼ç_…†™9&Út»ÿDS¨L\ø!¼2ÆAÅÑ8Xi¾ÁAWIsê7P7ý |Ð)�›köŸì—æ3n@U¦¹´ nšmÀ»Ó|� šk¯ƒœ°´ÿH ¦j©©‰‚0£šôÒ€gÕd k5Q¡ÃW“òðǚ̜�´&×jp«àd&׸0ƒ®Øö6øÇ2ˆ ÐÍ2è«z� ~+úkzGŠòHúÝ�A~"6«r‹A¬×äI Àøk¢†Øa€.B0@Öÿ/ d°Éˆ‡itù7’x©1àÔü¨)õ4G&•ûç:£`WûUQBP4�FXB°gö±EYü ‚íø�v‡ãy¥ª1d4TN�� ¦<¨rGbÉ-ä0“�Qȉ0ÙuŠÅJ‰¼xÁ]ýÂOŘù<!È Z JûD¤vÝàÀX¢Ü%BàmH~T¢?ƒ åF_óHePé@Œ;Cœ½øn@í]Œbþ=ùê08ŠQ5Œôä4ĹéøªëÍ£ˆd fL§C}ÖÎaåE-:•·/ Žm·æÈ …À…8ÚX™Cô»FBÜ�z`ÚG· øÈƒ¨`Wã_'§ ”$™ŠÔŸàa”¹w€ìJ +•Þ�Xó#.àJŸ8—îJÏÖªòŠ`Të©Ó­ž«�£ª1q‡Y΄qŒgCÚÇÞmþ*d¾3Jq ñìÅ9`ñ?:ÔœÐ$â€=Ü ÕÝNÓ(þdÉ¢¿�X@3»vé¥wV8ê*¥¶�œàÄfv'�|g2óA1öm ¬ÅH·“4(¤¢®A]’PâC%~iÅ�À®™ØŽ¥oà‡Î{:RÔŸ%&d|}#nùk2PÀ—x�š)«ÇÀÂjÅ€aõÁçÜ«ä0 l2fNSŒ16Ô”3Є&”Ï:<×\Xlè«òÏ+@/Ðpìvï_© óe˜#ßÉ^M ’\ ø±p¥ 6; ý‚ Jê½áÚV,Pü2Ã+Ð,î>ÉH\»úgôLzÑhQ¥ªÀâR&ã°Â£ŠŒ 0943£ñÕP°W�T+CÒQÀKaÑóû¨»0Èw+5¡@[nMr¤[BÇ™å{°-ËT÷Á ž-,—Ë o½˜“Øè>@~W®ia±K?òÁC¡%/€ó0b$O á,€0¡ò|ÄöyŒÆ©˜GE.4¤�è*’´ÍåÜ›¾y à4‚ÉîIAZ€ G("¦>ø|Õ¾3«ð†îºý’N¬á}ˆ<ü†ÿmj`:€ù•ÚpO“5te›l¦f‰,[Æb `Іß4È. aY;û€ ˜íô.û‚Xãë0æâ¯ü,=8HꜾ.@AÀøÌ’9é+•Ö?°X�ÍÄÌÈd`Šp¡URR ´¬[°6K®M”[uC¶Ô€`"8î8jKï€çƒÀ]�’øÿ-t‚±pÿðH�þß�*@(žÖÿk­ G×ÿ)`)þ¹1‹“]Œ +hÿGQê¢eïsLôßsXªÐÇržü—^lféZÁíZ vÀ$ï%±$¼ãöO’·Ëý¿e†0\ÿTù^Û½�Œf¦sõÒ–…ZàSé%{½òtSú/©ÞKÙGMsË ëcó¯Ëø4ª½dTò¿ Ó˜¹'O¶oâ_WC‹^&’GÂ…ÂçD#ïßš#٠ؾÑ´^“†1: œP€YÚA®¿Fˆ”ÇÓóäAõGñ +2µ”ÖÒ?°7þu×)¹ ýÕ×%þ½u$<›œ?Å�:ã#H–EwwÁfò“réɾ“5"¥Ä„]|'•ÇXâü}Üë®ÿÐÜy +±gí ª^ÆLeEÉÃ0ðßÌBO”k¶«ïG&dÓp€—ï"Þ_“KšöèìÀ\Žîçü³Ä£û»¨RÁ´@÷‹”mÕÜ¹í›ø£Ë™÷íg2i þì¬ýá;ÐEýeÞA³Ÿ +,¤?AB ¹gÃ~™,ö +¡ëçó¶I½™ghY�õû+ÔTÒÏ H'2xUÿæV”M¨¿º�RyŸÂ¼Žcú‰ÂÊL±Rø +½zô§ï³FM*¤úÏ^FOÉζöù�+03sH éüE¼5wƒÅ?Öü%Ž„(Ü1#÷¶ÐçÚ´üÅæïÙ(®8í“-òóy";¤ûĹÖãw̳‡Iì +³i�kFX$ÎB±„ÅßV`CŒ�w°Åïu~J‰=°�â„…0Íë_Ú{øÅ(î�~O;ÂÂO¥w!'‹ü2Ñ]ƒ¿˜*Q@—õÉ +h{ˆÀ?¿‰»"ß÷û+CR)0RÛ†â߯,‡ï +¨ÔªË£÷ Qm ÎA¾û8û%ÍeR­ûG�‰ÚÇϨœûw£Ó¸0£/Ç};A`;ú²þÜ}ûû\x¸BwíÖäÂlª¯ú+вöçJ~ºßòÍÓgíIyn€­R¡Ù×ôcjMÇ‘}^N<Œ¾žÙõ?œ1ŸWÚ‰}Ûÿõ +K›Ò—¿>Ã!/ +Ÿœ3j×_'yµ»~¼yÛ¼ÕtëË•¥Þ-rJб²&Þ®~(oiNõ§¯wxl �”·+õà�X° Rfõë$îsˆS#§?œ+B%ËjúÒ‰0”f^fÙ0ë&ýò=J0>UwGŸ£þÆ*­`êê¤è—ãÃß ·k¡_�^ÈTš‹@ÿóY:÷|1o5‚ùZi•Ï�‹gEn ôù©eLªÏ„~-j&g�­Ï�B%<ÁæS™Øâùs,úF!Cç�™‹ª%ý«o¾…I„¡z õǼ¾ùICåö¼ÖôQS¬ ö柈z_Zž�7ß—íoï7V=]Л_,5¤Âró"yóU þﬡÞ±)¥Âª^bæÍ'5&xƒÐÊÀzóËv¦‰ð~oþ6‹¡C6“Ïj>•ôò}4:VóI…-S™;ð©æ/?¸—Õü6+Cªv#5aåËü|˜-KðóŠ{™Ÿ Àö +ó·æõ9 .=¶ÅåcBU«Ÿ²ãò‡»^)Qb€.Ÿ¢±˜Tø¾àòç�ކž@Šð¦]å“�âòŸï¼VJ¸T0·ü*:Ãö-?‚ú«‰«î¯³�aÂäSÉ-;¿¥ü­dÈ�í`'N~‘„ÀB!N>‘YÔŠ"µkY˜“¿2šþ�KŒ“O®ô\M�ÿ�ÞŽ$Ÿª5˜ÑÖóa‰|�‹Uùì½ÐÒQó€EÈA“ì›ÜᎯ¼.Ƭn|õbž¯¤ôdü3°ˆR³N²[ü9’ÐË´çÝ+Î(êì^¾›ÛAuÏŠº40eu–È€ï£.¿ÃÒí©/Â9k¾ÇýÀ0ÅP£¼ÚYÉíÃ=äeã…š0ÇÜíÞ~û´|~`Ï\@Ý>ÐzÙj//c¶ý<l{èÁÇ�ü6¶_µvÌüˆwSk¿Íè7j{:xßê©åÕ×ì�s‹K7gÙ;Mù玉°-8²wh=£u•§Æ>ç>C ž©…GÄ~ˆz +� ÁEØk[S6µ{ÕT±ÿúÖ ÃbD3Ds±×ò~ÝûF�]ÿŽò¾#{wKIÇõí€E�u¾€¶¾ãGëÕïTæ-ÙÁà²7º–ð«opîêù2³ÕÏ!Cÿî£yÚØª4ü!û¦†5R}¬mú™0…#™ŽœnêýÆV$G^¶MRŸúxŽ»jUõ*(m<èQaEéÖòr{ú Ì,^=&Xª�ž oäUßɳM�‹b謑“ßS¸2ý!>-2a4wI¸5²“Ù¦”>É…:¸”Jú[’>lÀëq—ªHOIð1º”ÊëF¯°CÏ÷3rý=3x�“P}3¶5�]hô}©y¢f6ßHÂQœç“³Yæ#•½‰¯�Œ*¯¶&]@/Ùå³wX/¾ªßÅçç9¨'vÓ×Kaø<¨Áã“¶&øü ’iãy~˜héÑEÀ{ç% Úc^ÞM½Õ>/?fÿdêu¶NËË[äÅNÙ¡0³IÆükcí¼7ISr$^ƒBÄî•owÿ9Òˆ0Vå Ælådâ=gÊ3û7|œ‰À¡üdrl>nöPwÕÉ“Bö@L>×Âséb;þÊN¿ÐNý~äɦ¿nåU¨ª†yÝ%ÿð‰@6ú�‡ÌlA¶œwéxû™µN2Î1tg2úñë[¼4]Òž"¾K¤Ç'£i8nýÐÀú×ñh Ccq<ÿ0WO½oWØøB–BzÀ›ºüv‚NØžwÏø»©‹"}lDZòfŒ¯€Áð¤ÿ°°öâ;RÄõÃ3¶‚ž0ØéW°ƒ¬É~¦ƒUü”ªÌ?°!ßÈã@‚…:ý"@¯OãlÑ#Ÿñl?Ô‡x™- Špè<š×Ÿ‡í:;ûtðr–ÞvøP6»U/4X>%ÉÙ�y˜Éðÿå°lÔÞ‡=¸ Ç_Z°t Ÿ¯†¹“òXK,…¥óZã°§IøWrËžw‘`½Ë Øà;$*é¸ße·>-ø÷y�Ïüa„%�߉–x˜ÐG‘eNÆÈ¢`¨N?PŸ¥ƒ˜T  ø(]ð¹äÌc$ž7ÞÕ)ñÛ»¿/‚�9hŸÌN#î÷Mx™,9¶Ÿç@ùýî]ÆüÄÚ×&÷],ZèÓ÷Á3pÁÙ4)ßu¾äžÎ�?} +¾ó›‚Ù¶ø8#îýÜÒ‚]$–ïâõŽe^8"¬¥‹Ö€Ó;|tJ¨<¡§ yÞ)ƒƒJ‡'§«ª¼²¼öÒÖa½)êÀxG.ÆqŸ—ûrƒw +À{÷* ß\³Pî>iŒÒ€j�SÚ½AfÐü|)Ø]Ž+¨sÌ- ÉÁ,æêƒ0¹qqº{\§õã[—¤¢;`Úº¡30P¶'ÄsÁ€•{ÃyxæN÷©þ‘©¬KŸÊÕÁ`¤B¶ëq"wêÓ+’7 �;Äj=Ř~%w²p¾ »ÅÓœp3`îóy&Æl,Íäìí`X ªdÜaªÝÎhl¤ÀG+rû›ŸwF¬ äsЙ¤ñ0+b)i{Nk”í¬º9TÇAv!Øþ>›^æ‡Û]Rp45\æÚ3f¬gdvÚ8ÖžN,Èçۧ°OTû‡á-9äDì§½ÅÀ35¡Fð´ÒŽbWb'„•võ, v!7—¥F;£ u±ÉÅ/|~·T.-MÜ¢{öêO£ˆ\�Ô™³¿•b•-m�3a5{–Ц¥Jß"̾WåŲS5Z ZH°MOöýFfl‘€¼wÅ›°Ù5Þœ ‡ËRp[=ö&ªpó“Ç4võzgõ¨ŸÅ.õïÔ|UÈj# F„òÚ^i“-Gö§¸ÛÞO�°3™xFQ+ß’`_›ŠêJ°«d Xüí¸ÑEvî¸�/YP!.¾¯WûSK–wvn„Üë®Í=[¡"äuZ¡FÄø²õ�7’0cîeéº-¾A̤Aå:/Á t.yÑ ®Ð+Ǥ߀ pë �k-¨×úÆêú¦u~ž-ÖwÌŒÔHiÞY‡@‹a˜šÃSÖ¹ãWJ<$á=jˆ²Ä0%«¯ ;ãUöl¦³¯ü>^e¡’ãBðKfd»x®tEY]mMˆÒtRC6W½�õÜë¼9´Fªºî‚eÞ©([ªëµʱ/ +ÕÑH[\`]Á–ý}#�:”¼A~n¤0õNœnœ¸àIÝç~2†‡°=ê´šÞr`ØûUÔOSõ˶ª'… +Žl +Éh ãû�zµH¢ŽK­=õéLOü^ƒ»7žl¿ÓZa£Ñé^‘ɵØßtAÍòÕÖtã^ŸŸ ¸U�ôfz^ +¶I‡ƒó€‚šÚÁó©BBzAÜ¥{g{ïUq+K/R©¾IvÜ2À_x*�òt‘¢&T:(]É>ËG5Pú(Ýé`ýÈÀrIWz,ýH×BÝ»²úwA/éÇ Ákr*�¶üч�f°‡ íèôB“w4€@µŠäÐ>®_€HÛ%@›ÕÛ³ å2éo�ÌEGŒ‘£ý€)ú Ñ\YD/*zGÝ©“(aC�ÅD‡ÄZ ·~èRíº†è—Ç­_& ëй&B˜»xR?ÍË×>6²Q0ælprBÇkµÖ`DìÃ9žtˆŽèÕÒôí)�TÐÛý…9]'30DØ;@ç¿’4�k,z�³ÈIŽ'îêÜ�Çõõ}7Æ,á?Ÿ�CÌ×;ÂÎÍAá=áÈ(SïÓ«ç�VÕ|Žü�PÍ;Ì!×6ˆçÙÇöò€³íÎ�æ0K +¬Fìœ=ç¹:`™cç- ò�:'%UÛç\ïåÉr�zØBîmãüÁÀ– èˆàœ‹­~ßtá ³K>�l~—1šÏÖü’¥3aØM8|Ró>—$] ˜4§Ò¨_&Üêšk�¿¢-wá/p›sÄ ùey–³áôµ[Œsâq™k¶‰WL©ÇKQ¼KæTáìàQÉ Ìc.Û]S{á¶b þVÌíÍê–çäGT?î¯Âe˜#U1·^Ìo±“co`:Ìdøåç_­äD¿fìv^^$uHô7*ƒ.·vcµÒ]Ž~w°w)Ç«·\ëEHùðƒªå‚?�½Ðšþ,e–{#Ê••)JZ¿ó„åûØ#ˆ*�²¼¢n®üNx�HàÆVÎŽ•_·¬üÄbT9¹ E¡v_œ+ú”ô\™–V¼ÕäPb);#,¬7Êñ›0·$NE�pÈ&+z»ˆÕtÄÚ“ƒß)V…”è󉌜œN‰ÍýJ“#¢ÉB’&·Ì‚{ÇuI˜ü’§  熯Юäø½–Ç–)NrÂ÷?èÓH~Á�§·�ždï‘Ë«’(H wù”cA§_‘£†kX(–œ0>+T¾-\ +·ÿ€øŽåJá©®Z°½¿ïgÙ Gÿ¬G„E'uÐÓ ï¸‘Wh�”¦ðSNm ±wíŒ`S¸YÔY=h +7’ó/EQÁX3…—Ч ïSM[ÇÉEÜ`Ò[dOá¡“yMQýß)jàÎqOÅŒTéöS8’ºëÌNáCú¨6iê)œ^ûeù®-�Â=ÙÛÔt˹·²žÂY!<9yÊ™”œÂ…}–ÑЊOá;r ºbö™ø^aº…>…øÇý c&žp6LØ C*ái¶´/VÂ×£H`ÿË¡.ÚzÏD{C3s»^Øs¿21yYg„—hçmðíá |´%Ý4C ßòàƒDÁ;[Lpƒƒ«O$á�ÅDÑJ8ƒ? +е5 +/8Y endstream endobj 25 0 obj <>stream +Ù©w<+Þc4ÖÆPÔ Ü××x[²¼G~«Wi›Ò�; Oñ/yñ=®8°úlÄ +\\n‚Á¥›»ön­OzæäIXÀ1/+«£a•&Îø!½Ño_Ü_óð†ê( EÿMåÙÓ˜’ãßt)QÇårVñжï7º„*iï÷ýI¯‚.à €ÂÂú=žÜs¥bù ž³éØžyá÷,<üQEªµÀ¬¸fê Œì›÷â,øíô=Ic¸8®Ÿ“çÛN—ü%Qúލ|£PîÀu4  Œo‚àð¶MÒÊuKøÛ/®: +_{÷Þz›@uE,iµ2�uÑÈÇËœöÆ`UŸ;%öÖÿEöY¹«’«7å"Â@~V׿oz“5�T4ôN?¶JæX:o6†EñˆòÔ æ­tMoŒÍBH]”7€±ƒŽ>´?Þ +ȃæ‡2‹·Y#øtähx‹ š¿YÛ¿nCð†¤,û7LÒ3´í»çêDC=Q%bòî•Ç©:É‹´f‘t7Òs©ŠÔT�»›U8Jtï8ànemµG&€$rtPñ)»ÐÀZýçð?¬ÃGz‹³;^vÛò{1g7¹áš6ÂyÙM 3 GºdaTŠ»_úîÈÐ¥4sn×m_f[ FŠàA¿®¨VT·b¾ŽŠZ)=+;‘§;üÔ’º­n¼<`ä˜#SþtGl¾üD™óO÷|ÞqYÌkËøt‹äPÆNePõ§› ˜y¿\ðÓ�fm\üdX%~º—\‚o¬ž®O÷ÈýmŒ]§f\‹}ºArÍpÈjÞòæÓMš³Ùz짽ϺÚyúQÝ.uq°KmRzTw‰ =Æ^’é‡ênr_wù¬êŽþ0 Ÿ&:ªÛ.cPðkÔ‰ê.nóâ†mÁë +gޱØ=R†êæŒpÖ.8�0u{j”%‚ëæ“Ò³^Ý ÛÞ•�j¿“ö�ºm +]Hk°nCd`�ùYä`Ý�5ÍÍ´‹m®Eƒ3†7È^º_ç4�ëê~£‡u{·çmMlX·RZ•LÂy|t›>¬ÛýÏ +ë¾ÀV—C÷]Ö­õL\‘¹nêßh®[ÞÁ¦ @ÙÃ\wöñ[h&ÞçÀ\wY×Ò]Ù5×íjO«4ò™ŠúœëÖ†^´dXw¦+“aМ +¬;hÁ­õ�µaݹ Ú4ø��¯îð´°�Éë«©[ÑÇÌ7Ò}=Sw±7´þW÷$±Š*zuÇ콦îP# e¼›ºÕ“B^݃ÃO„5qÀîÕ ›²ŸŠx…�W÷â•Cº*š“W7 h3ÀÖ¯n´âDu÷«;Ùé!Ô5õMÝÕØ'–M¼©ûÜ›«¥ ©©;²ZÚ[‹©[-ê¨à Œ‰¤löMÝ—ó#VRÖ-`Óðú஘hÀº¡¥Ð\7óí[—åÂsÝŠ¨$Ö‚Ý„Xn|Ïz"XÀuo ±=\·ÃZÃŽ Öý�>ZCtu¬ûŒ×@1wÚS· Vâÿî•B·žÙ¦”¾‰'m¥±—î”nL°ªk©Áúàåz‹”`ÞåußBIõ0XJš»!pÎ�’}gnf�éJ´<t½Ü—l?ÖfT_ϽÊÍäk½$‹3°1¹ÕçÎð²N©ªš3æ#ÚÁ ò:nsÄÁ¬�>ÆÝHçÀ(í-«ÅMNxÒ(” ?Ü÷R{<(6K 7àò˜Ê‚ƒú niøWÙP ð¸ïCcºŸ2òï·Ñuze;žãæ$ü›dÍPpþ“ÞÞe©õ¥ß©’J9x{°ð€ç6€6Ÿä™pE˜ ¢ýæö Ňñõç"k}Äm¡Z|Üqû;!ÔX:áŒî¶m„5y¶Z0…l›7d¿æä¤�ÚÇ–D=È^~|¶IÕÖŸ˶š“Œ$E­±ýy€jùЉ“€a{½b®Hñ L赋RòåÒ`-sɵÑcÞ¦ú/ˆÍÒÚÉlj ?ÔÖ´´È·éñªmºÖ¡+Y{›E§v?â–Ù[ÔNÜ/Óàh<í +¸"5¨#ìZëL^‚~Ñ0ÂÒv„-~#m®ç¦< k´ÁV¨�öH…×ʼZ0]&¢}¡Ýˆˆ0ˆ´þg¿½ãnÑ=8â³Y¡Ù¯Š r,ßÙ� @ FaÎÎÖ`@v՜ư ò²0ã걤S³Ïä(¦¢¸ÓÈÌže¸5³ÁB×+U˜!f#äà�ô¡Åuµ»ì°"øÐî²=Z!–Æ.×�˜ÈE£Þ½qSÙ ËòÊ+nèeóP²¹kYÝ l“nÈ9Œ=Ê‘-¬£�9 …l£)F” +½ge|ì¾A<çósl=ŒÅçÉcȯ{Ç·æX�®øåcYœµ2Œ}«Æ_Rº)g,vñ¬wM‡ppM÷‰­s ªö]i܈ Š`mÏ÷°WC˜ˆkQvÒ<âÚ>fTp… gôyÇQ´‘{Ëhð0áÎ`'�’×�ïlÉC°o8Ñ€qVìlè€M™Ê®|þ½<²ˆ«æ6´0º~-¹õÕ¼K~Y‰}-1•h¤�&ÄòÆ×ç¿ÖÞjÖQh¯k(] è5/AÁñ~)E^ÃÀþ•ÝYaN÷»fñ!l}f�¶kç''þvÍ/{GµŸÑŸÅÒÌ(Ù�¿„t!]W='=ð†ÂæÚ["K®µ8–ŸÄµºs ‹03¢ˆ†®Á''žO78K±[«s3us�“ýmkÚñ‰ß±5Sì˜ÚŠ]ɤ-\âÐZK„ÈÞ&”¢Öɲ öj m(%­‡ºjÖ¹ð +´ÎàŒ@<© »YëÅ~ +Pò`eØéa¥’–X%ë¸;α6’˜qv%'Ö� v;q-ˆ:)¬©’?`=#\ó¡5EùCÁÃWOì~<‹ ¸5˜w5ñ¯Å î/Í\ÍÄh§ +�Ç@s«÷½~¼bz•Æi5Iwí€K ²ÒŸ²7Õ‚Õp<ËXN®­-Œ0‡¸j-ü^s’S¯jŠcØ)ÕXqªvÞ‡ó"ÉE2O5gAzÊ+ÕBp—sUS0›�Q-|†8c”5 +¬AõX`1=5YY$•Ü,NMeÃoVnœúþ¿êª‘ijѸ`îJÍ^`jréA›Š-û•šÅ±ø 'umœ€¡x‘:s7]>B¶”Ç+ä[¼sæ°Œ:äϪëùÆ)jÉRwô%�cN¢& ÔI¸PÓ)%pVBqP�X±K’¾j,Pã³|ãý´8ï•�•ñin£ýÆ12 Äðôt¤Ê9bËÀÓ.užï&gßë4ä9ŠjPêÓšÓתd—8}KiE»iÔ¦dÓÞ$-¡’—�ÔtfI0€š6ðžn ààË4G¼¢¸aµðzÈ1+Å{HÓEaÏòäL†|é!Ô`T~‡t¢�ÁŠ©§î´4N†NCÛH…ü5{Ú‰ÝGtéƒJP%0�±7n�Ò›…&ã:‹H%JOlD €:w~'MáõÀÖûP& ֯Р+�ä)iíù;2%=•oXô…þHhÔPõ~héÓ…“zQ;[€Ò!ű®�ý`Ô…)‚4lX4öÑ œd.0Å–…ĽIAû`dÒÑ@ðlÊ +D¾ûް8º�’¶{ê‰ÁÊšÙèc�¶Ú 4šHºk‚|rÙö»1šeŒ\£ÁÝ«íÔ}îk*Ó¢Ù9Ú*c/îUtR7¿Ç¯sUY>…¢éü½ê>F¨T ¿b¢ís§ÉT�8�ÙG4¾j´?RÁÅùƒç�ÓôÙ‡1 ¼r‡åB‡Vi Pg>5½Þzb¥¡‡£9ìŽ!uSE)4C7`rYã•·ZšÇ_ÿ@™4¥mÚtÙê2¥D•¾EB÷—" c›¤E©ÚfÏldpþw š%ш23üO¶t¢õ8-ß1®ò@"hðu’À@ËÍ< ³�怶tÆþÁ’æ0† ÐÝ�vHxùÏÁÚù|=€;çÏø^¶á”Iý\¥ç)�Ô…Ÿ«µÈ¿µ\ˆû\±(¼,Ïç¾×)­ñY‹Ì×ñK'iù«ºIž>¬ÈN>TÜ9f—M¼ö,Øž�†˜è¹Â¿1¶ž‡U&³%•Mz–1£\£u¼Í³$›´*¾ÿÔJžÃ¹†ÎCŒÖY#že2)–dn\zqNȺEF#çóìÎ5à�Ê©åPÌjk;S«@ÝQ(t²x%;k (N댌º¹6–í¨3uøY•é ’ÓhIß tÎn&™�7ÂioÎÕO!Ò§õX”º]ÎÏh.HÚ—œ‘5£³Ò5@•ž¸ÙoÉ…¾§¹„#iô_Öžf¥×QñªÈ` +ÐÓ,�;›H)ÙžæymÐfŠp?5kk={j¬™¥�:'�X³ìòó±fA#¤ÃŽèÿXsÏRÍŒ^Æ`¬yªF€X×l�O¡Š¯Õ¡TÃW×lLM+/˜]sñƒ’˜‡IkÆšIç­1B™š¡Å®u·Òã”…Jhƒbh§¥f…ÔR3,­îÜÿ—A©YA5LËRâKͧ]SË I(•Í�¹ßí>ï1ý¥f™XXM!†Ö’.²ºì» +J}Ò\[Ó.�nж’ÍŒ?Ž|W7Øù™³@óô«Æ:³a§ç–x¥lf Oö/3$iw3»b¨J?À¡aæÓ2ûÜ»!Á\D™‹‰ˆÅêÃ� ™šéŽi#B?æ>Y3çB†Û˜)båU—s|°?ÄS `‹yG¼(jÍËB#æ”åØ@�P„†Ùà,:„¹¶‰˜D˜í£Ä‘£LúÀRf~¿Ô.?‚™vzÂM_¡m®Ü•m�?)è% QìË–&—´úäçôq¦ù´�Çýäƒt¦ÑGÝÍžJoH­Sêרpm+¶Œ�ž[§ØÎ¹®/û_ã_|¬×�Ej_Üïü‘N¼EM~'b¨²âáY�óX O‡œX$óä' +OáF91¢§ŸXWO×¢’î_¨öü8F9à{ÎJÓP©½Ÿ�kîŸÒ‹#~6£Îç— +$óõ©M•�ŸݾϮ¸’÷ÙàO‘À¾÷îÓ­ò·Îc1uŸËà³3?Û›ô™÷SDðÏj¾k„¨S4MP@eaƒƒî(×ÕÔÄô'~“Öh‚‚.S·=k­` ´˜ÍÓv„)Ah‰âÚáTÅ¢O(�p¡Yã§ í^õ‰·Ëù¶Åwh°$çÅÑ£lÝ#U +¼cB¢ÂÊ™˜‰†™Î8¥QÔíÀŠŠy‹þ¨ªk0 %î‹æÝ¼{Œ†²EÌÝ9@‰DÀ1=„h8qt×Ѭ ×Q£G,7k?Ú UÑ õ Û‡´¼ ÊX�‘ZðÌ\Hš'» [%uË ÏfÒ÷4ÚxÒ8‹ƈÒÞi:8ÖôsTÇ\µ)]rªcc•®†Ó§m˜ý,�8²šÂ¥.u´±[*ÒÆé»Ôº>g`êSŒs-1¥1%.™^á&j3]þ; ijÜ€­©ü™‹Ú6�hÁ`ûMmb5"§LîÂètpœs«„ùNÌËU¥Øå€yN%2Br} +ejãüS4·â@<B� ž<Ù‰ ‚ÏP¡˜7„-¢æ`Ô cóMkE¥‡FÀ@£"JZ¥G•¿ÀC¯µ!TˆÍöIý [ða©Áã§KtƒŒºÝê©q6iƒVªq^S丕¤£Íí“ñ9!½1¨šXV¤MUWÎÆ}æA¨¤=aÞŒ8%¸‰U�€:kVßYÔZMOr|«ø¤Œ3º¾Ò"P¼zª¦§ôUÍ-›º�u£t�…rOÜu2`%V„:ó.¨Ä‚j¯G4ŒuÄr£| «À¿†~ƒ Y–ŠYM¦$£³F–FÍSPDn^™¡õ°´ÐÖ´ön fµ +ÆæÈ×ê‰^Pæ³uß\%ÜÊc’‘@uå­ N‚nè+¡YYYrZ˜rNK%±Ù/Þßkõm8ëTbjÕYv»OOɳj$´ÏŠy§"Ðú5Y +YhÉfÃuU´^z´Ãû}Ì“6X×`ZÙR9­³4³¥Pû={–Zjãá¿'Uûî¥Ñ»Z‘Wä¥P&xlom0ÈÓt˜^kcLPØZ-ß4[Ä{öÉ6-¼äZÎöá¥-bz¦k›?n;ˆSo[ÙQ´Np'ämoÛœ~åÖ§H°ãtë°@(p'ᤕ¼­ÙLýn°½Mi¢ê[[+"å¿eÙFŽb‰w„.p±; wŒrP¶—)¶xdq{±òÕ¸ØÏ“ñIž4hƒ#WíÕÊÕº³Üí‘\Ò^ÜssÍmÈæ•ÎŹhÄûÜÐXù¡›[9ÄEm“½ÂLYVÅt]Ñ·1u¨˜Û6Yð.Éë ”,Yì¾ y·ØEn†6®Ù ©³GÈÈÚ�Ðε|»¹tî›ï*Í ÝÌw͉÷HðŠ�Ýžmñ‹÷z–fƒ¢óA^åŽ[.!éS^I"<è2/@%Ó²ó¦ˆÞ¥k¢R†‹ôMèÑôN:¬ÕkÎ òÀ^yðG ÓÞChȽÇÖÊ-yи{/ÝcÒi—º±P}yGÿç. `ãËÚ?„”-Ž’Çú /’ú­Àä?^¬Cî"Ûæ§ý\‰ßoñù½ù]wÚ Z¿A˜�û¿ÒGw×€ ÿŽ +ñ09Dã㯈w=ßç> À¥p[€]ò¹RÀ“þ©ì;z³²þK€wS}ŸkœÓ¤ |¦eNh¦e[ÈT«)3m¼ÙÞ@�Tc;ÞxN௠]d8v‰ìŒ�ì¿)‹Î:`–l�À’1}“oÅ”°”p’Y¶Šï·É9ìË$BûΗ²SyÓ”°d+� …ÉrJ/gø—éRbJ¿£XéëAÜ";ÏçÀŠì%¤ThMÊ\kw&ì®eó*åë0Á©¤Þ<ªFº•JŸÿ×£$-Ë–Yz[ì@w¯!1¥ÆˆÞvÀÎHP €Õ[ ­{~… +;`üÇÀâÙÑ8fìY0_ß3;`÷[qÙ§¢QòpPš9}±(`“žs(r§€ïðÔ‡™1‡:š"}·±—Y3'hËÏz’+t}'à'††3ͤeú˜R©*¡¢€ `®µŸµr÷ÜÑ©Ú/À¢l:§àìŒû¦^”©» ñÇ<ùsd�^0ØW¬RÂò¼1^äßö亼³&±íøÖÄ ðš˜ Á®h pPs9p¯3F:ô²� £üUöùÝ„¿§ æ`W-W_)�û”ÊfÙqá1°§$_ÁI‡&a°tÿ&8hçÉ÷ï{¥ü¯xÞËþ}&Ö`U ‘ý›"°®þå[éßzó­ò˜k¦ú^²" ¡Ð,—-9t#áš»÷ý9‚ËοH\S¯°…¿q'^‡¥þaØo]G8‚ÒU ¡ëwùk†!Þõë@cMž¬ßá�<„’ö ðÇ�а§ªgtƒ–Ão“ùõ;! ~,,²ubåëW8kŽPyý¶¾ÓÃh^¿›.šá¯2)Èïéß/ì€ð_ÜP†M1üEnVˆ‘ ­„¿�oý-–€âòú�pý ¦¹ÉsX—DKŒù½�*ôóúKOLrÂß (¡´…<¾²eýêPåñ×ÿ„Ê|:’"Çßù7WIጿœ2þ£ïÂ*xÏì€}áoön.¯¡L‡eø+Aö§’‚ý„¿Õè |®´ð—R#âÐjkM¿Î|²ü~˨^ô +5™ï¼ë×sV¤Â®_ ´ˆ¬(ÚU‘e\¿®40©×o!ùùâj±$r\¿ùÓtäë4곕ßõkh™$‹y~+Y€ ØÇ`ü%ªXŒZ¿ÚÇ™y%Gшª'Ü-ÑÖ@6~P +÷¿Ãͨ}iüzâIØ] +K>ò14áþƯ�YäÒó ztÊ9m#lÏïq…rL;…~1DS[»_y³7e~V‡þ§p°Þƒ òâ»P»Š''�xcA¿|%B $Sú•‚6I*Ù?ìA¿tÓ D¿½'‡Äœô»œ¤’jî¤_±ñ£æJJéw8cÚH£ �NÈ¡ØN~9À¾d|f:A]8 ;)sÉï0;T^Òou(&ÒÚÔ-/ýês,Fg­ô»Dºí7:M`Dl¥ö[I)À£ßÇ£ T3 ôõ ?%�ð'’ú eŸƒÑ”&¾á'ˆ5£_ e<Ö~ßž·ñwG—³Àþ²B•ê¨Ú:ú¿ÁÍ„¢XÆ8F8¦Ä%ÿ"áõ¦#Å ¡[ ƒ Nz˜ÑÞÌv ‡‚ˆ­0`m^"à£0åáå!v…wÀ%Þ2FOÿÞý@Kó/!¶ �ïîúÌ"VtûªŒS`™æ…‰ÀÑž^‚e"y{ I–ôŒ#x>ü(£Óþ¯D } íÿ¦_ìÜÿ.æõ€? T¶ižIýßé°½rØÿñÖH à¡*ÒZV?À&ì´®�AYd�Ϫ'^¡Þ¨iF¤xS/,¼·úzÌ–SÖ°‰yÙ Vú&Â^Át›$Ð˃÷i0se›•ƒé\ö`çøØç#’äY¸Âõ!vÖ« ebZÂk­ß�˜v´Fí4¨»ßmÇaýçÃÂÇ«B• sí� †µ€¾ªšÈPð&Ô±qÎáë5R¼ <|*åÛn�X·BlW1¦â‰øéª"!¦“¸´$¶LüÚÜ'æ�ø¹"åZ Y?§õÜÍÕˆë~§†‚¦Ì+Æ×yŽClG#¬vÇGà\üq7wæÅÓW�:P0¾dáW,Æ—›2^ôbQ«uvƨDѦ± ØØÔ 4tcIK°&v±DÂÖ±�ÁÍ1ÄZ2`[Çs“£KE‹ñ;†(‰Kôx8¨��á‡5?ýØP+òÞ|P�i¤?%·rëègòÎxq �I!ÄžónÔ‰œ‚�ñŠŒ|ë+ÕJG>[ÁIô�,`’�ÎÅà§Jö¤Åï=Â)•h‘,Ég6…’KS‹2“\À8�jmõ“Ô��]&9æ^v±“Œ9Í69°>ˆ¹’ç·n:s` áÙ<eé¤MK\YÉ9x�K˜|¾Hqi²2ö³4YL<ÄÑdqYŽ=j¾™£ÅA¶ž×x&{º»·rÎdYEš™&;0:ê3Y®d%&|U2Å´ÕÙFÇŸæ€wùl¤ÉŠkaÒÑþΩÉ㥱æ|rOš¬îU}ô²OiòWq.;»h0Ó[ OÈÓd„>ŽH¸ |ˆŽ¡„œLÁ4S.½Ék£fš¿1¹¨œ\WÓu?!�œ¼bÞIí[N6 ƒ´-Ž¡8ùd3 _ˆ“!ÙV½ÆÉ1[AËa‹4€íy$¬›éÉâ•&‘Ñ“s¨™¡(&'ù©ÒÊòSЂÙE’Á2¥'ߪ¥H‹ÐFO¶®³A~&§pÙý×]á~™ØA¬žìcø²AåɈazj?ž'ÇÝ*à¨*ॣ'¸çó�\�Ün6ƒ;ù~¯r–ÿ©ÜÉk6™!±¹“aD�®èñ=Ç:ô{%$ëØxW²;¹SÙ d@¹ˆÇÈefð†€b1Q6ÿ(�[¹e¤ßéëÕ£L”‹ü+° Ìè›~¶Ç>nI ¥ìjiɤŒ6cô>/EùÌÕæE›ŠV~h�©<'Ü<åŸ�{NÊsNY-SQ+•µ77\嬱Ô[9E×ݶéd¢X’妊KËî ôHh[néåMþ’ GÉåè¼\o—H-y½,.üg cƤ®Ë¼mÙ·u�\�™Ý_ç5ÿ›eÖ ;ý53 ŸvXÅ£&å*¨ùÿ¬™ ¤è›w�¾_›Ùâè.Ý,Ü®¨9-ËØa�ΟŽ_tœ�Ǽ°M6¼ Éä|ÎfÔªÚ2`ç/A›Üù˜qˆ…çH¢¬ýG=+dF�ÔèžË·ùœZïsñRPõ Ëß_\‰¤6ýí–*Ð`�Ã8ů€½ è7hr‰³™“ÐF¶ÐSä§+6´ñTã‡niò*$ZXÙîdí^‰Ï´ès‚C‡2Fãltpòj”::æ]%±Ž¶�RÎ��ZáCÚìÖÀÒ‚8P1N¤0B$=ÍX¢I+ÍÄ¥�>]±õÏ!e¹ÂC¤Ã–ƒG#Gî¼å"$DàKŸ|Lçø]qiËØ àÐ4fLE6›ÆêXFœ¦/ }ë4 +Ÿd±ÒòK»úé©Ò Ï ö¡.Ƥ{¨ý}QLMJÝJG´Lrz~ò…™KM1®ä ‹€K­ÆMý§èÖ¨íJïETò+6q@u~€ŸOÜOÜÈŽç» ••Ÿ­¤’]ó©cƒ‹9¢OmÈñÿ×>õ´?uaꌕ œ´�™ÚO­¾ù· ðþÔuW#ñ•ÖÜNf“j�WÛ ‹ŸX'[ý÷°ö§��ºâÔUÈ‚?u~±ò-S‰ø©Ëÿšõ^Mø~jÒh¨ÚvPMVÿÙfùwî§¶¼íC…y”ŸšˆÜ¥g¸€ ^Y#s¡%Ðû©ù�WüxTg7¯ �j—íúBW¿E�j…šàƒÂêþ‚�êWîãHX¦¨vŽÓè�B¿&QM½ Í4 ¦úFl+^©›jò˜m»©VÈ>S›rÙTÏÆ +|$�W´ÃT¿@(“›»GRuM5:zŠâäd‰?8TÃY—V‰t!ªi{QŒÇÍǬ¡º¥9Ù�@üÃ} C5{?x0†jÐ b(óÙª»~ãRݽNU[Ѿ¢M”pí¼¹•3KõÑ7e¨6#V€[€CõA¥à�Ô˜Úè ,(ÜÕ= ¿Åu‚Th’¨n¦`±®�vÂ)Q­c ¸ˆj�®$mu€¨F÷®Õú‚UãvéEõíT�~ žúšãàÇ�9Oíw@4�ÉÁyjQÄv’pÞÐp+¸ˆøÑ>Òõ‘� è·Ý<µ%x>œ™zçPUeŸ©SÈ9gªÒ´35Öd þoç©3Ê÷bq2Ä€)/²oO½ç/Qb +å4õ·]:õ’',M=à‘Ž&Sƒ$û™mê$S{_ŽâÁ)µð‘˜ƒ‹P ©EÁ—å=vä�:âÞZòŽ@Ñ�ÚE‹ ÿÄÑŸ•X1Öm¯�Ôçâ…cˆó^òÎ¥cîo�y�ÆŒ<êÕþQû�®~à +^×\O¤ŸSOùçµèŃPÀG}ÖÀ ؉â\åAS{‰NÜì°¨¨BßônQ›81ô£6º5Í¥†ƒ©å�NÌÍœÚ^Vñ2ªã”jx ¥Ø%z©¾Ë*iC£×\*¡Ôúš#»PÞSE¨ÎéGRÒäBuhÁ3v[ª)·øîÖœªÎ76TáªKÖnguP1Ø'ÂÕÃék©y§özõ +,£ó`m,˜±~w/g«•5„™wy²QeM¦âú7]ÖV±VòÌF‹É¾$«Ú³&8¸G8­K§ü_z­'kTèpë�Àx1¸^Ñ 7Ôê‚]®ßkNd“]R ˵FêŒ#ÏËÐÀÀÂu4’ k?¬\#ç+®×8˵ÑS¹nžpÎVÙÈH®oñtzÍ-”&7¹>;ìe·GjáB¹[×ë ßÊ53ÔÔêeˆë\{+å:õ�¢ª\ šºx$zGQ(×Ý Ñ÷Àõˆö)×�Q§ÿŠÊ6+×&#»âΆÓʵöõKf7e +åÚ|5§ëç*äC´Áéæ6%rB*¹˜`W*ÿL×oÁ jK�.O×�¶p�\}kºþÀ£«ÞßàU`­#-�ŽEºŽÆO—�+¸†]ºî›ò¾ˆ�K×zbND�ÖXº^C°XüÛ®4›k$êíÌÞVF½Ð­ç—íÚ2Ö[ƒ*»æh‚©L˜/£Ùµ0-܉<ÿÁ¹jשy»ÉùøíÚµm(²C¡­œ½h×õìɆ3ÿ‚v}-•Â5i¼*EÇëX“ÖÄ)ýO‰×xíe»˜ÑGÝy5Ýx:Éóûam 9™š;ò¡Œ×ðë;GEmÆë1f’©�}7ãµdZgž‹85^ƒAÊë`ú#h×pÍ5õŠ®]oƈ÷¢%ßÞkEÔ®·® +á§sç‚ñz¬’Šíõpós]óþ­“._Åãä"×k¡�í]úz0‡Q¤¿.”=”þºaD¯!]&O¢„½A"~â#ceØ;í} bï…Þ„Z + “bŸ›ÆÖ{¶zìÐþݵ‘ݳdq<ÙÐo�è•éì—c¨@ îšÚoF‹ë9š¬ä H$ÏÆlJš?‚6©E;ͅܤ´½ë7í¼Gj,‰Ëõ'ˆ°µa¿¶—p.:�m<²4wh;x‰T²m�Wl7×ñÇ*Ý.ƒ�Y$µoçÿùö.Oµ~ ‰Ðîè+]wšã&ÊhúºLKn½Ëýõmnî7¤T ù?·Ï§{çF7×VUÑÍ~ {Ãtk9b¤ºaZÜö\w†‘ìN�évi»cn&Î3Qªæ÷wO…ì"Þñœ§È;Æñšw4€¬. Òª¬7^Dˆ3ð.Œ)ðÞ;ðé(¾ã�[¸ùTßòÉ®ÍÐõæŽ'œØÖkÇ¥ÁߌØ|šÌ¿#|·ï/qÿˀߢÄf~ï�µÅÿ}‚_íŒ&‚Œá 18¯%3¯ƒÓYDøÎ Çz…ËÚì]e0ܶK×ÃÐ~{¸±Üþâe²”�xpd•8ÍÀNã£áŸŽ:ÿÝL÷Œß�uíB”öba|ÂûÖË8Ý64ÏÙØÔhAÝ8øò÷âÿ>•âñ* +ä¢>¾ñª…u¹Ó*â…<–M/øDŽç«upäåb%9¶@ÙÐ䜃›¼§UÝÊ-û|s’òy©\¼lh]¶rG–»wk…÷K[ŽŒ`y»ÜY ú�yIš\Ñ®æ ÃÀ’3Ï(Ü¥¹õžá5l1àæZ¤"'8—26ý};‹ó�¼¾ìtŽ»·syn´v®”nÒ1ö9,õN²8ẚ,¡Ã<·�hè&…õ\î3#,-úQ£ˆ¦}=:‰ÿDxÑ·¥‹x J÷³tSºkÓ9c— ›¯Ór½M¤ÕÇþ �Õ¤ö¡ŽúP u>–sž©OÜ’{ôbßÞJ>Z’V÷&Tvs�G±aR…íñ&([8 Þ¥%½Ç‹JœZ _þN#ÿar%KÞÍøü'ožàþ.Tþ¥Ãò¸¹üÕú…•…yW™· +ƒ·L󦞛7Ëy´e·�;o›„i½ç•ô¦ÊÊ´a%ôÿ%úfq’ ƒ-�¤—?•üÿEBqò9ÉËP+=A/©Zšž@mLWCÛ—òQ_ƒ !¨¨¾&¹5[½F 9k’õº¾]¹­×Uéìú�›=uÆvå!müõ¶¡=Èn‰Øg›ÂÏ‹ì/f÷(¿Õì!R7"í»û"!×þ2†2[mnû5ÈŠ,p/�0Ur¯J§ò[ºG ÈÊç·{™7]ÏíÞð�Ù«Biäxê*„Çû1mªµì}éó×û%¡%s }Ï~ª¤£fàgh[pð—SDÌœZøîðªa>~£øl}ŒŸeŽßÛt³!_GpSÀg•OõPQáå' •ä<óm*"œo^·.ôHQ">€íàðÿëÿÿ<1×°¾?¯ïû÷ÿûûGYIiîÿÿï�¼ï½{ï.Ì +ðö}eg¿“ûÿÿ{j=6!#é"˜ É<µYPÎïpån¾·“çVÓÌ¥ÑÄ™Ñ2mdsMÞY}³·æsüÜ~Ðaž]¹§½\ë|Þââ´×M`š§2Qø›8½÷LœÙÌ;��«é±šæ_$¾ø‡ #dàìyqMÂKŠì‡)£òƒ‘µ�QÂÞÔéýN›‚6ƒŒþꇸS¡ú¥Ìî� +%üR£†5xgµuÍcqþÚº�¢^‘£Ÿ-ã&FÇ”ÕØ9²Yˆq¯P‘X]öu:6¬Lœ�åuסÁߺ‚Ó"FXÙ~˜Î÷­îQ¤›oþØh™9mö&°MÎl«cÊj,ãòâ_`_ÖµY®Ù3ó:Þ7OuŠè;0 �+|½Ï ^]Ó—6ÏЕÍ7ynõ ßšÿ!´³�$í¿¸Ÿã'WóxñºŒDÒÙ‡¯Mv;"i,,Ÿt-Ÿ2�>hï÷ ÊI¡/a~½�QÂ~ Äá§:%¼�<½5uhõ�ŸÚ7’äÓÖÝ3qcóLÝX½³•³{Às7Rcà”æwL)²k!òÝ>^¼;ið&büû>…t2wÚlÌYÖË +gƒ]þÑ$˜„þK>k$È@{°îûÚÙ;ß¹^“wVÏÌ�ÉA‹{´Ô°Ÿ¤’®0s¦*AøƒñúNw*4lOÈQY+pÑX#Mn{åîœ>8¿Ó•ûAˆ{þi3l'`‘x“÷Fô¸gK�ÞT£…7œbܳ�4Ãö�ÓÃêâ7@öCŽ|~Ç;×y¸w_'Pîãô±}›¼µš'<ǘg÷|í|^šO¸îþ)´³?W¿¿¼jöÐè¦Ð®Úß4rf=flÆÆØ=Ë¿´À8 ^<»t¨÷3éœ5¨†b-Ñ”±VGe F4é¦N®‰2ÐnPCñgH’YW¡8üKšÜ¦NAÿShg×à™Ñ3vb4Oî'MjŸ4µCˆ|7 žmeÓbeâ´s�=CG†}³¯6l3Ï`ÝluóYNgiŤa¿höв>‰uu‘Ø�çP®.ûu!H½Žã÷ÖiàÖ:ÏWÎFªü»£HÁ7†¶q�ut&eÔWø‘9ëlá< ½¤Éý +`$ú+û�^Štð&ÄûCŒ{öä6ê4l3u†k2i H2ç«%—r‰½é“kAâý$LÀï Fd�ÁÈ&]¡È%� Äâ¯2qø ˜‚ÐbžÐb_‚ÄûN„o«S'÷¾Ló5|hôУ�v ³kKyj‘ íîÝÇÙ{û5wl5Î\­Ãuû:[8nƒ�ñ;Œ«hs� ÊiÍ4Ièƒ÷hâÖúŽ÷MûcHgßø±ušº³Y‡ çGc�PC\3i%ìL™Þ�DÉí?ƒvZn\P¢ž‚Š_ F¿¤ÉÍñ‹û;\9®û?a½_Äø§„ÉýO�á/»Ô ¾„Ùõkë:ݸþSˆ×…óýlžoœ�èVç¾õœ¿¸ž³uûZ¯0ëZÇî„áúå�×üc²ü1îi«J$z1S&ø?uö +@<³!VAûŽý‡Ðî-âA¨Ù‰û~ÎßÛßáÒù Ä<;è0Ïj¼³ƒñ Ì`,‚üó6|h]FN;Óô‘É:ß·ú°�®Ù[“…ù:ThØ~ +ýÚ:à8ÚÊ&c­k=lgPn~:õv8kª‡ý€ŠÃ~¢?€ÑjG%�¥ +Úà˜Ú œxz¨OðýÔ9øÄhìfLö¦Í¯&÷c’Ys@ÒY_©¬ÀxüF�}7ŸÛïÏÝOœ‚ZªaŸ°�M f6 Ô,/¦r†%œ2U‰Ã?¹ç_0ú E2gK>k M:ç-½“'ø)âý½´ºfÏŒÖ|«¥H ÿÕN�ÕDó;}roš¼²zænl&’ÜûM¡]U:ø™2½_Çoîópï¾Ñãß tˆ÷yßfèÈh.}YÛä°&Ònÿ`*ö*ˆ¦¼téýG’€ÿf¯­[Ñ´²N÷ÍVÊ ´u¶p¿FmŠÜë f8ÒV=ç,UÐ~ çœB±^Êüú"È¿¯tÉý�|L›\[ªÔÐ7¨ñH[騤È€¬ Œ +î|çjôÔ÷l*TCßø—*¿6‚‰ŸÁ FÞéÎ}¡E½/Ô¸çw¾p¿§PîÿÞùžðÜçùÊÙ?ˆu_hqï!ÞÙ?„v6N`›—©³g™¹/Óà¥É4{gY�0[§B¡H[™%‘¥´–UUx0'§?+ɧŸ:5ôAˆzQ¤…¾ +5Ñ÷ÞÙ7|lR¦„_jtÐZܳoøØ¼ÌYÝž³—,»¶Q¯˜’%àýƒXÆ»u¸nÿ†ð­#iþy(Ò°gâüz-�]îgcȲa>Žr}ÂȾá 'Ý €ÆÞDêíBŽzÞh°+ˆÁXGà!I/ ÁXKÐ1IG™‚sþâ:ÐáÝWªüú(QÂïäùµŸ:Áÿ� H¯F¢jÔ³süà>ŸÛÇñsó<Ý8m�¢�v¨Qïö¬Ë`eôêÁÒ,+¡ò„•s”)a7ÂôK°bÑSèAYSàqIKÀ!Y7i~s¾m^Fn,;S76û„ï<…ÿÃÎïAI¦íúõ4yg³ ��Õ ¿ÕH“ÛŸ€…#]áG&-UZh'Yv½)áíÚO%ºªÄ×ó„ãþL]Y¶æMîaœ£´@¬-¤jÊ€XÎ:ÅlòÔ:M�Ú ¶§H¿MßZMSW6ÿ€ïl§OpW0c±v°ã±¾‚9W‚9/€±è¡@ŠN +-âý D½¾”¹ýT& +m+ûÔ©¡gÊôþ¡Å½ÿƒX÷yŒ"ÿþ“§  õ ¾ƒ +û~Ï�WÂä~§Í¯½„É R´»‘"·6Ô§àýä)x'MÞA‡yöøÎ&Z컑$o#G?[ÉðjÜóAŽv¾ÇPîÏØ™ekøÈènZ·ñ¦eqßè¥MoÁÅtÖFyñ¹¬œ ØÏG“Ü”¨çw¸tÞGðî÷pï¾ žZ×ÙÂý£HÀeJØ©N í£É¾{‡gëŠÞM™]-ŽŸÚ§¡;«­ivvæm¬Æá®y�/œ—‰ÓfgäʲD‘|¾È2ÏbÄëF‘€_ ÓO»”éýG–~>§ëÖmöÒê¢J=Ÿ¢opã‘>°¢Ð ‰ójp�Óuë9€oý1Óïû$ÒÕ5zj´Í^ d˜ç…÷þQäQ$ŸÎî˸‰Ñ2nb3ŽŸ[M_Y=s'FÓÈ•Ñ9[·ãÇÖ1¨~f­ŒTfØhì n0.ezûУÞoýz,}ƒ�uƒ�þè‘ûyçºÎ7®'QÚW?Ä]C“Î9C“M+IæŸDL?…vC<ú¦Û65æÕP¢„�‚�Ì,(Ÿòƒ“5’柊ÜëM£‚u%”u‡+ž´‚Š=ˆ¯ÏЕÉ8]6:éÓÏ?™ +Ö d8ö*‡NŸàŽ Eboòôþn]ÿÔ«‡ùn C=/´Èׇýê*Š=ÑιÁ‹Go”ðW¡8ü ^<ö(Rðí¾û:\9„xg;}~íP …¡§25Rìû<à¹ßCHç�*ý† ñn£F@›çkçmìØ‚ñ>œ¯¹c«süâþøîN¢ ´ Œ +ÚLÞLÞQŸƒKbï}ùgû Ö} E;¨aßÀFc/’üë6i³µÍÆZÝl0¹1,$ ÝÁKiÖ+ŒŠYË€ò•M¹‰3ìwçlÁ»¯”¹ýL–_ûœçsá…wõ‚Žô&Ÿò’¦·[Õþ•k±_2sÚìX®>’Üv«#’3WRÈØ/+ê.*&h 8*ižnÝBÔûR£†BŽÉ>AÇdoêlÒüÚMœÞû‡Íã¶ù Å;›'<#§�müÒj›<¶šFïlÆn,;C'&×ô¥Í4ug³ÌÛ—eê¾l]»¯V¶FsG&×ü¡É8ܵz',Wß®Õ3u·cæÃ¸ŒÛÙ0™9[¾ \£mÑh¾6º¨’Ï;… +z¥L®÷1´³®ý¬ÌšV®ÑCë=ˆs=§ëÖ­i=k-«±V¸K“g•óY™ºKÃ7–µ®u,ß +A‚葯ÉÓk/ir‰ ù|ÐbžÏñÆÑ>ƒw5Ò¶ÿÞyŸCº'NBo@4l?�vm&Î@[¨qÏÿ(Öõ H¼´hgã·6÷ÒÕI–Ý›¿7Zn,{ãç6Qúy§NÁO$©÷qßz�[P£^Í#hGßô±Õ7j݇pî']n=‚ˆþÃÒ9ŒJ‰>"Ëhm¥#rg;÷}Âw>ªtÐ;ˆñØ¥LûPãžï ÏÙ;Þ¸!Æ<Û(�Hrï)ö} Â<{¨QÏ.z䳇ûì¡F½{‡+çiæÒèš»µ~ã×Ö¿s=‡ Wû€ó<ÐàÞ2ô³ƒ õîœ=9{pî&rÔÓ2Q~µK–Ü[I̵‘"·7XîïléüÏ Þ× ”ó4uj3MÝ™Ĉ×#ôxìV<Ä´Ob]c÷°™:´,Ñd_’åöC™Ö¬pb³P"«åŴΰÄS>rÜÚ;ݹ Q8e N6é©„PŸà{©Òû}íþ ßš·áKó7€l]§ÛfóÆy›½µ.3'–�¹#“ɲaÖ3úK&î‡Yß>Ø ÞØ¬Ž£oºjô Þ-ËÐ}¬õí_­p6ÍZ¶†�MöA´«q¸mõ ÝYvf.Mžq#£gèÆdn[ÍCç}ëúPä^OÒ ô b4ö-?Îö­¦¹3£�ï>ÒåßW²ìò€éjëš-[ÛìlŒZ¿ZßnìŒ�Mƒg&Óì�Í1dòWÌØ£– JÄû>ƒv]Ç;Gÿ,Úu"H>¿–«mòÜæ>4'Ð�ÞñÎuœ@¶ŽóçÖyÂuu�!ß'‚ôóBŒ{}Ç+çéÄä�0\�”yÃ×F×ð­Í8�mu�Û,ó&†�±;Ëò ÖÑGâ@¿¤Éý=…rž¹#ë9”«¡HÃ~rÏïtç>Î_›·ÑS«kðÒê/]}@ãŒÁIgÖ‚MÙÀ(aNœò¨ÏAŸDh=úyÓ�ëA‹yþHè‹"û>Ðažï×ý~ÓçVãüµù?·�Ã÷æsúàüÍ^[ã�?’´‹"k¤Ë?O丷ã�³mîÖ<ŽŸ#à7’ô³—0··ÐâÞÏŒë8€oÝÇÐëtã¼Ï ]?ªìMŸ]›ÒÏë|ãz�Ú ´hçŸ>Ã> +•°/ir?S§÷/¨ñ8cXÝ”/0Ù”§LqúذV;ë H6å¡F?¯Ã�û?ƒxCˆ|6P¢ÝßùÎuï›z¼ûAŒvöNX®¶ñK«­lZ¬umnóW«œöZ÷&óÒÕB�z='Ü6[ß:6f­£Ñ;Ëò ÊÍH��sÒ&·NÚäÖC’|5Q¤_mDX]ÖP§à®`c=u¢Ð 9-êõ¡H=ïsˆGûÚõ*†þBMz‚É:A ÞB¹OSWVËĉeeâì¬LÜ}µÂõ0k[}µ¶Ùט4ûËÚV_cÒê°(QB;ïûÒy$1à'‚äó4ziY¹1,N—�Öñ¾užïœßùÆõ E¼n$é÷—4»þKçmöÚè=5ºq®G�†í*ˆž(ò¯î9”ë=…u='ðÍã®ù›­Zï1¬«—6·AŒÆîÔ)øqÝ: ]š\³·&ã¾ÑC‘z>Ê´°@ ûÒyž/�ï ×u Ƽz©ó[O©0¬¬HìH”ܤ¸×ÿº�â_RÔûGbÀÿÈg‰ý“§à=ezؼp¤Ì�¤¸`¬�<½wâžßñÊùœÀ7Oc‡Fר¥õ!Æ=û@‰Ã/EJø‹ýl¡D>Ïdùµ«N$z2‡÷ì�îÜ^×ñ¾ùžB9„ˆ÷{ÂsŸ,÷ë>‘ãž}$üA‡zŸÇ;gët㼎 \ï!¤óC�zßg°îë|ß<Ï—Î=úù"È?Dé÷—4¹ß‰Ó{C…‚‰^Š”ð îÙ8{oö¡�-%Jø%ä×NÚ@ˆxß&/Íˬ�Õ=á9»‰³kK‘ +j“,ÿl Ã»/¤ˆwâÝ:]¸�¸ægêÆf=µú³ïC�†½hØ7€ÑøÀ€ô X4þ¢È¾/ãæ³\{ýêa„ëVC »†'™u‚‡ý(Ó¯÷Êý!G¾Ÿ Æb=H%íàÆcm¡È%Ý€†¢7‚ì»y¼uÝg°îïtçºÎîE~)ÓBïÀ£—:-ô>ƒugÏÍçôÁý®ÛçéÆi�ën!Æ<Ûg°îû Ö};7Z¦�l–q£yÀr¿ÈÑÏBÄûH“Û¿„ùõ?‰w5�Ú\³gFß¶É<‚w5�ažBÔûA‹y¾g°®!êÕ@†yžç;çyÂuõ�á�7¢ôóR§…> +•°Mvp]�Ãm«{é¼Ð"Þ'rܳ�&ÿ>•‰B;ŽI:ÁŠÅîôùµ…÷<Ïà\Z´óL Þ>…jø«P z'а?ªìJ˜ÜT Ø‘2{U‹ÄÚ È:� Å^¥±W¡@ôP¡à�dè‡÷þÒ¥÷S¡(ôH½÷‘ðQúý#q OºÜþ&ͯ :ø¡Bö’e×-îÙA‰zÞç�ÎïÊyŸÁº_ùçŸ:m(OÁ;¨�ïóÒùC;�Dh3Y~í$Ê@[HQï%ÖÝJ”][jtÐ6 ¶‘$o!Ä<û'Œw òÙE�|¶Qc }$ùwïtç: [÷)¤³‡÷>’eßMä¸gïxçúŽ7Î.ëÙE’}?‰2ÐNºÜþ"ɾ_4¹g+Uní¥Ë®�ô¸½‡÷þ¡]‘¤¢ž­Ã…³÷Þl"ƽ{*ÔÐVº¼mðÒüŒ-ƒvÏ4tcµÎ·íëxß¼­ÆZÓìëУÞ/²ÄûC‘z~ “k?uzÅ BÁ?I3Ðã¶uš;3šHRïWµ üXv'Qïß)Œ£iöÐd<3ùÆ�­!êÕGâ@�tù÷wçh«šçÏ­Æùs«mîÖ:ŽŸ›Çùkë:ܹn“çV[ÙlÙÊvÏ7|lþ¦/Í×ô•õ™;1zFŽlÎÙ¶ù?¶:†Œ¾Æhk¬ ßMÉçmðÒ<� �'j샓eÖlyfŽLÞùÎõ E¼txçqßê?¹ç/Žæ¤óFb¾žA»îSh×…÷¼Pã^ïœó5zjôMŸ[m$Ù÷¡@¿Z¦NÀ{ê”ðv0ñK�~¡„_Ê´Ð#MrÿNw®ïxéj&ίg£±žB%üL›\û ü›0½÷Qäö?�‚ÿ“´’=ÁŠE¿ …â7 ¶�Ä€Ÿ¨±ï%æù"É>¤Ê?»‡p®û„ï|ãÞOºÜþ'NÁ{ +•ðS™ÚHbÀ/”È÷{ÂsöÏá�/šÜ³‰ ù8d¨w7qvíª†vƒŒ E{JÔÐfºìÚL˜Þ[J”ÐvêDªü³•2mªƒ6Ué Vérû‡õ웽¶~ó§Öƒñ>Ó¥×Vºä~%Ë®b̳s¶nž¨±ïS�ÚTÚQž…¶ÐâÞÇl«qþÚüТÞí®û7xl>§ÏÍ"̳•*·6“å×Îù{ûV´Ÿ•�³åº19Ç«f÷Ê}ë›-s Hp;ûÄx÷}é|Í�ãmóB‹y',Wï€éjʾ#(ç‹,÷þP¤ž:¼ó;`¸N³76ËÈݲ̜6«³…û>ˆw5—�®ñC£­guÏ~mÉÀ�egàÐf™6²l ÞY}˜æmöÔúLœmU»³Ö´;KSg6×ì¥Õ2r>˵\]|Ñem«³3rd4¿riñ¯ZÖ´å ×ÕIš�žN­¶ÉSó;\¸{èqïëláþÌÛX-#§�w¼q?QïïpçúNw®ãø¹}Ÿ/Þ7‚ ôF‘ŸIÓû—0¹¶ÎW®ÎÙ¾Õ;`:šgp®Aúy¤Éí‡ +©ÒÂo ”ðO•~©Rð½”Ùõ;\ºŸã÷•2í¨Ò¯v)ð^ÒäÚN ae +þQ¦àÿÄ ¾«L~©ÑA[I̵§PÃ÷éá—*5ôM›_›ˆñï )ê}!Æ<›G�Îïxã>O·îÞÙBŠy7‘ãž 4¸÷�ñþQ$àWÊ ´ Œ +ÚJ$ÚS¦ƒöÑdß Ö»u¶pž†î¬¾és« +ñ:� �Ï |ó;^9ßCHç}íìž/�]c—ækèÔê�îÜ?‚¼©F ï¨ÏA�‰Ã;‚ Ç»ÊáÝt)h'QÚD�}_H‘ï)òÝM—‚7„Œ¶ŒþH ø‹&ùl¢É¼o“×FÛܱÕAˆwö�âÞí3X÷í¾ÎŸœ�³…óK–[-éá?€Ñ9öÀ·^Ów6×è™õ"Æ>-ãÞ�ÃçfëÂÙAŠu7Ñãž­ómû3rb´UÍÆÊÌÙY�pÛ¿ás«eäìlLYö+¦ &#wË8Û¶:‡ëöoÓ¼Ž×í×Ü¥ÑV¶fmóW™º‹óUëB’y'°Í[×:6͇ŨÑa1g2ØÌ�6›v£wáh>3Ùf{VÏÔ•e­l7Öšö¯\+ƒÅ˜ÍØ=´Ç®–‰ÓfcȲa¼ÞòâÞ«ËÚæ¯3wZyæN›µºù¬Ìœ¿ÎäÝXk}å!@„àZBXÑ<˜Ž \Wòì4oiæmŒÞáÂÝB‰|_HQïßèµõŸB¼îÄ齃Â}‡®ÎŒë?á<ÏtÙ½ „þ&Oï:¼ó7�kµu­c­l7vG�ŽZÄûGâm?pB±Î�Šé+ø ìQ¥ƒßé³k!âýð›ÿ!´ûE“|6Õ)¡=5jø›8»vÓæ×þ1´ó9�rµÎÎQêÝ Z0~(o#Ⱦˆ0ÏÜû=a¹›†­ž‰S›ïü�á�¿ñkë5vktNà›bܳ›:¹·e×î!œû8�i¿GðÎ#IÞK•�Z£Ç?{g[WçpÝ>Nœ§‰3£eØÄf™5­L3w&ÓØ‘Ñ3rfrÏ×Î!òÝEŠ÷PâÞ­³WwóÒi‘"ûÄž2¿Z§Ì¯j3¬�ú¼¡8µ>…töMÞ[ÇÙ‹ë5tjGï­#1no«�ß‚±½d¹½qüܾ’˜k'eúÙ5zl3ŽÞ[÷¬»‡ùn¥KÀ»h±ïZÔ»•*·öÓ§÷VÚ ´‡÷¾µM›µªÝÙ�o\/‚üûN™_mäVì‡ïïpán�n›]³—FÏÌÝôLžÖÊæe¸�­ùK›cÆd0þõ�÷]$dî´aÖ·f•«³;a¸Èñ®û0Æù>²:¦ìÚÅ¿Dxà¾KK†Î, ¨Ñ®¶¶ÙXŽõÒ²ºi¯2mÚ,'ûúŠIË~Yßü•f¯,›SÈ&ç ²Ñ7]69¦ ƹ@dñÆe]ëØš>³™Ï,+÷±ÖµƳ#¶¸­ÕÅ?WWŒ™ f}벌Ý��±³gnƒmÅ�]ÁbÒ¾¸æƒVYÕn0kÚ³ŽõYÆMlÞñÆÙ;ݹï3Hg×à�Õ?‰wu’e×An�õ¾P"ŸOsm$Ë@_$öë;ܹ.#Gv•‰»Ãnºjô$_‚Äû@�wu!�”¹íP¥‚Ÿ‰s{!â} Ãº{Ç÷w¾o6àš?šô»§J w¾pŸÏŒŽa³ÃnøÚj'Ðî� ¢mÔhçôÉy›<·º&﬎)óØ˜±,Öš&–í ÏÙ8€n�Æm¦¹K£iêÔæ<¶ùÇÐÎ9Öu™72™wùj=ÓÊ5uhÝ�Í×ЩÕ4tg´ ÚŸq+«­f_ŽÑÎÙ˜³[Ó‡F÷Òy�À9úçðÎ%âÙ>‚uwO8N[c—æoöÖl"Ç=é‘û�$m'Oïm øu¶s§¯íçÂy¿·žç{¾töS§÷~ТÑFzäÚ7|k>çïí#]þyA»?CW6ï|ßì£È?Û |?e~µI”�v¦÷f²üÚ@Švö7Îö´³u¼oÞ&�­¶Ñc«‘(¹½)³«5bôÓ-öÝ;Þ8»†/mŽaëac\\2vwÖP�¶ªõ0~ 1‚“à�ű!Fð;LK,lkfoìjFËÎÜ™a­mÿ‹—}uq±ëMÚWÎ`[6ç 'ËÌ‘…ÑØ¡]­k7ï_$8Xˆ< ¯µBXݲ^V:­WŒÛìÅ{|Dü +ËJgƒÑä�]kÓ²5�iY›mÚ\ÃEÃÆ¬e¯üoiñ+ˆÜo�ˆIûêŠ1 óŠ!“¿¬e¾ËªFƒYÕh°˜3l§»Hð®Yœ&1"‡DÍsE�«§ dwd ž¬ Ãgø §á6ü†÷ðþä4%ãÇ–5T +Ö*B$a¥#ËâU ð'ªüÃ1}¶!áÆ@@¸�à%ù‰åmÑÎK:ûª$9§e̘·ºšI˜„²Rð¨ä¶ÈÉîâ.�Ä\"7(‰�Já!æ¡Q9ø£”2,DT bBöJID3“qIáeŠ+l‹V¶Ø„[T?8Œ¯¨¥ËÄñE¬o€kÜ80cÕLa4±v +Øë 9¶�‡]9àOBRœHæ‰q#ÎÃ}8Ïá8|‡ëpN4sÄ¥ŠžxÔ‘îàIг];P=¹Ôº0–¡50H­ Û PbÄ×8Š– —Èš`)�ŽzS <î©6¹Œ”øíâ…Þ Yl£K™¥aÉËÂ!™bA!(Äß *. ƒtn>*ä\TbˆI˜ji)ˆ¤sr;ÄFä_ªÉ-‘ ’Û ?.ÃANÅC°ŒÍ!ÄŸ�ƒÌxÈ’õã%]Æ8F%9ôÀçÀ&pp«%¼�ЧºYâO3G<ÉúËdx8âH\‰/Qq:ÃA­+ M‚øT’žt“€ñ'.Ä“¸_âE܉ÍàOK +øßúð#æûšp@‰®Ã(è’|VV@òQYÉ'ådß•Þ$¢‘= sC€l£ê6æ KJ¯‘•‚ED1 ƒ€n"¦BjrBÁÃdQeM2‰1D.]<¦©¹KF$…–‹> Åá¡•ˆ=0+HR†y ¨4Ô!:™ÊíZI`1~ÁL³€jfÅleü‹ÂÞ�®ÁêÇ¢�{°@�o¸`ŵÄÜ!60“$Šep1“âEŒ²E4ËðQq7ˆ ñW +ñ7ÈŠÊ/“�Etˆ½@Zp62 k²°ÂÆÅ"¥«…ùQ£°£ö㥇Á|©'O`I›U…›\L% +A!  ½TLbب$?n�,W¬1K%·Ž0!¹,„q±å5âe6vrýSË ˆ€–9qõ¿©ø„SÊ%&æj^æi¸Ë[Ò$‘„#”²Åo±`¡ µ  ¾4­òÆ)ÙÄ šøD´s54Ë[Ì$‘|Ñb %�3 +ßd7ÈŒJð›˜Jü8'—t;G£Ô9Fér•<ùVžt¯(~QÉ–SЦà‘RNC$”Ÿ”L¶œ-¦´!.a2æ·JÄ>+@�YÄøØUJ.{<¥‹›@òà’úà:Þ¸auc„™�ÃtÕã/Z~ìeëÙ²Ç\¸ÄÆYºîƧВV)È$,5‹Û6K—ùIUO¯¡ÎíWPgŸ—S E¯ +˜zm�w|öx"†: å‹é‹Ú“+´Z˜Õ0·±•0ñ /f•*°¨5.Qà néR÷ €‹|hÅoyƒË%Ž.e—,®¨mž®Ê�šªÖQ¦ªš¡ ¿…óYføD*«7£”+÷£.·øÆ3G \´âÓÕ6ËO(u”žPè,)•R†…”R‚�h^*YÄœ\²u¬ñe¬{À²Þx�+\¼„±�¹€}·`¾d±EÍr4’/Š�IÀ&-&½HD'·LPLþ)ÑÉå$_”¥�NÀwG�x?$Qº%Œ,i£)¨Ì•hdÂX‚qÉ#è +)pŒ©X´t ¬f»Æ<¾ºÆAººaÀÌš,°´u&�ììTÅã¤|X"jI(SñHãeŠ*kmc)Wì˜G˜—KšSÉâe˜H'&ä/&$°e"’ÄJÅ"‹•…DÄŒ©X´€L�Ø|QŠ|>'Fl¸*>|á&ZBU+~qŠŸ²„•6Êp*¦˜k„E%—È Ì.‘bÀ#:&·©4&•°� \‚B2p +±×I&¦"”ð&£*X“¶ï,ý±È—ÛÓtÊ'ØÉ%¦×É&g¥ª_%Œ-g�P`Oñ2fÙ£ËÙ¤�.c�)¨¼}zJÁ”¢ê—uˆP³WP8±Z8!»QéáÅB¨��Š™tA“,:ir›% £¾»òÃΓäF«2ÃΪžÚ¼ŒÊÀœfé¤ù“D¬�1 +‰2&bd¬nˆm¦ÅÅ]ö%†ýÁ¸ðXcT,#‘`~œúåèãíå¢ÂJA$ž•ß#¢•_% ”]#0&—Ü€ìsÒ²ïIH¾(@ ù¤ì€ä‹ò#²Ï‰qà’•a&�—“Sú,ShQËd¡eí²€-hˆBºÜ•d9#5]½=„²èéØDPäËØã’/·aUí[_¾rCÆ l`–)µXI—±H#_´‰Vð‚\ÀÐ�H°!�|¹ÃW²tÂ)Y|£j—;Kª§pQÓYPí,|Ö` ú2,3þï"£Æ*°¢Æ&àÅ|×ÀÒà‰,®¡ÅL± ˜ÿ¸ã‹Øeh”9LÄÔFÊojéä65†$ #‘}J�Dú-I}äc¢ä‘¯‰‘È¿$?"ý–qÔ“’ +Éç¤Çd “b/’ÒIB%�“ŽP)™bŠ¥ü‰†ªâq¾¨ÒFYÃÊYæŠ*l‰<¢ŒÕ!âµM^|®+%j0ÕQ›mõ†MgÅH—…H ÈeJ]™cËY%.eyT†ü �‚MÐúbœ£ lä« Jd¶4ÉÞ0ruC€�ÈËí™b®uuΓtµN³Ä*œaô¾ql¢~Øê‰N¯¶èlQnØzL€ÜsQtÜoQnÜd` +¨å¾¡Ã\¸ôI\Ê,/¡ìU&Y¤L,²X™ˆÄ�œds’›…ä¶É©¸»¤ÔR0Фå!ÃOÈ(_ñ�/dwUžÐ†D¦Ü ŒN1¿K<9�„;� rrJÉ›L #FØäÊgLÅ¢Õ,@‹Úæ�+kàT'·Ɔ절øÊˆ£ì€ÈdÖƒL³d\jxn’Ô[05‰¶Pg +C,ç I6»VÏ;û¤TLžbâËTNø{Š‹_–%ÆßÚrZ_¥^Ê„æeÍ×$õ&™b#2ó/uxAË|‘e�Ó8NWÚ&…h!;T¢ªõ2qò“$±Ó¨èè=KŒú +F†Üµ ÙÌ +�ÏF¥†÷$‡-ÅÇO›¢£w-7dí•Ý®2£&[ÂBÌlÉ ­X7ZÚ¹#9´yHtˆ¥E)àu9Qo`b¦à„rv°ã‘~$Rþêr¢ÖnÑA×]IB7ª`_ÊÐ’¹ä€1JhÀš-�$Ù´‘Ç `Kv#Ø¿+TèE)[ìÃU/þPŠ–ÿ¸Ä‹öñˆ-!”*_Í‹�9llãš•€×M0¯S/±´Œ†‰M™Ñé”ü°éŒø¸á’ä¸Û ä°Ë²ð Ó°èèuRzØsN‚ü9':n¼Õ"¿ÐÇ’±í#wŸ!·"n•‡\Mµ‰Lã“RĶµØ¨ç0/h5.;|ÛZî‘csRrÜÀ„Ê0Í¢…ÑÑÓÂð¨ç´©õ°8¡U­ÜŒS¸Øâ"[Æ0_\QsTõb{f®L�eí²ðˆd&#ÂÊÐU9ñ)•6ÇT0vØ ˜ÚÐ zb”<¢–ôÄ+xF#alÆ"Ø]ºÐf +‘Á#{Õ$3ËD +hS@"¦I|íY^Bi[Dg]Hi¯)¥>ÌÊéÿª*î·&8ì?#=ÆÀ@Š”}…¤Šõ ¢m[Ò‚Lžbª%Æó_P€K¡ËeK§XL ¹F@GvK²ˆR`Ìp¬C8ѼõrÐHÓCä¾±Àð`âÊ€I䕨±Ï–"%üV?(ç«!˜³�4e}dùç܈¤IPbFë£öÃ¥ÎC Êœ6nr�¯f£„±%‹|#TÍâñ¦@©ÏT}Ð~Õ…Ïz™!g¯¸˜³�eF]k‰QÛ`pÌuX”ÔwW’ÔrZŠÔvXŽô¹-C:zÐZ/9æYË kÆ,WIÑ» `!kÅLVå†'“ò¦«¬ð]XLÐaZTÐõ”Þíˆ ­‘cjIfh¿¨˜úXJå-*§u�⢓©Æ°m+2:�ÅEÝ«Àè •5Tñ”I„9¥³\XÐdW +¨�(ùˆE¬Ü‡©Uî9-Gj²~Ì>Y1xÌhø1³!¤žëR¤¦Ûb¤Vû„F; GÝVÅG7³R€ï^fÐÚ.7ê6-=<] ^ûÅ�M`†ÌEY¸(9î6'9þ˜* û:e-Ëh­Ee´gY ¥C`!¥µLPˆ¡)QA–eBªS=ý^SL½ÖÒžAŠ&m� æ,wIÑךÄÐb³˜ð¨pf³0•µL\ØtDf�ñõÐQw$ÙX“Ú{ +‹_E‡Ö +»mK_´mŽyPÉ“{3G•5ñ‘,cŽP°h¯lù�OÀØ—(ª´‰]p9s$æþ*à…à¥æK`u–K ‰|˜å‹gtòÅÞ3—¬ÛXõ*��€q(ÀéUƒ¢W _4³X œb?l¥I\ ýZVDÿ"� ÃA£ŸÐC²gH²IS "¦´8ìE•~µ‰]kKi÷ÚbúµVC= õž©œÞßJ +[Û†ÛÒâÏ!)@ËćX¨ÙžÅ9yÏ,L®ìú¡Jg#b¢lƒÍâ h¿·Àð·9æ2=…”µ„‘µUÉÞAt&ÁÅ´îZE­µJXÜqClŒå Ù1¨$ÕÆ£’ê=pÈc’U3 G§¨!{F¶ /°$¼¤È^³´ í)2zÙª [ %†Ÿ«°è~ŠŠ_–%Æ_ã²£ßà˜û–tY—]û…FýeÀŠ¹Ë€3˜r—4 /¨4ˆ0%°¸”Ê®„ÊŽhÊT;ç[Bûˆ-¥tUÐ9D“ÑÚ'A¡�› j½¢”ú/+§žD–ÒZ‹Ê¨‘…”î`t¦P¤’~Àã±ÖÅSî ETÆÒ"*gpò™ aE´S"ãÛÉ1vÖ$Æm¯ºøÊŒŽÕÒ‚¦­°èa`XÌa ¨½ÀBþÓB®³¼¨ë*-úÕʉÞ!ËhÎ9Óy¶bâ§UÉáÕžØøeVnt?FïU`ô°/(ê/+'jSFé E2ç M:ç +@.é 9(k +<$ýT)X,ˆÐn É1ð6°)8f@4üØPü!ªtþù éXØ*©Ý�Jg½ÀÆãìÀF$�!If Bõ³ñ¤óÎZ¢y_›Œj͘´ƒsbCû‡m¹A05è´.8ü¶I[0‰ÖîŠ�ÿæåG§ã’„Þ0¥6¼²Å&@…6#Á– H6M4ـȷ:ælnd³Æ.À <É3cPvB¤™L½ôQ'_M墰žPd’&±%ôƒ= ÕZ0rI3¨�ø+©dCñSÙ™D·¿¦­«F/ qÈáÉfÍAŠ'Ý €Ä_cð?òH‡À(�Æ„…Ø™bV=é H<šç�n~Dœõ0ų¦2-´� ûî J0ëì–ÝSyáA$Ù´-©¬�>¿¶ÒæöS­0¬±¨˜fIp)¥å&%îYŠ +oÆ$ÆíÖäÆÝ³Ä 9 pz­åR~0r†`r®³¼ècR`|™J‹Ú«®øYÕ]¬ ‹ÛGyák*)|MåE­¶zÆÃ¤Û]òŶܨC,p*_ ¢™ÝÐ%+_iQû(/üu5E­Å•öpetî`t¾‚9W(rI_P²)g`Â9_`²)g`Ò9k€â){X¥¹¢”ú/ÕÓ?Bµ”ö :{¸2*S(RI;°IO� ìX~6= R Ú|dÎ^OL?ˆ& ½ÃjgMbË)�e¥tæ *; áØ- Éœ¯R/å ª Ù,,£4‡ÕÐ H6i M:g M:gU<ë,/¡õ—ÓšëŠiÏÊzõc²g`Ò9W ’9KÀáø78Ѭ30áœ!à€¬7·Ú!G¼[ “û9Áü×TP2IhÙGrJ6?AÕ~�òÙÜhôVú+é&Oï7Šü?áº[çN;ÕY(†aÈe±e´¶±Ì¨ã¤ð°éžì¸ÕTmØX-*z˜ÒĦòÖ¨tÿƒ.3 Ç,¦ÀŽÙ«0²Y0�õò‚‚q€ YBªXv*ñ¥�:g H<¹³OB�JŒÅÚ +p:!øà£_£±C• +6˜Áè‹(ù|ã�wåÚNxÿøÍç€×ê G;ÿD*è«PEòùžÁ:”ˆ‡a çÜ¥:ú=T¥£Lö#οzˆr�–$²®j‘XC• +þ©„‚‘ȺÃÐÙC–ÐÙé M\Û2ç1$û“õÕ�KšÂÌY‚ŽJújæ,!Gd�!Ifí …ãwÒìj‹ ùîB¹ 8.é G>g&�>û‡h@N‰.ú©ÓÂ5&i E8g,'Ÿô•�Êz�‹Å_¥ÂО*Ah&-!d—*-´›:½N�‚_ “«àÅ¢‡ +Iöý#I@ +?&;ƒ‰v*â—"=�ÂÐ+ˆqø7»öRæ6Ê,¦t x÷€ëþÑäŸ�$s¾B"¦ØXD² ôJ›[�D !Çc_£±#an{‘# §àÍã�û2pcXkœ��Á“�,ÿê«#–t„�5Ó§·ï|åê¼4¹¦OMÎÙÆÉ5zh³Œœ–f-;#gÖ&–­ÑK«ízŽ—­×ô�̓m]춤‰Ñ60JØ—2½(r/2pê´Ð#PahMúÙAŠw_‰ðW­0ôk^FN;³™Í@ŒwÞBÎ,‰-§´ÕJš©Óû½tvP¢^WÊ ´©Pú2=R&`j¼«‡&õ:ŽÝÂ�̓OYŽJº +Å"�¾Jb CÐÁè-Ù”- ÉœÈXôO¢àîD®¯‚hʦ˜Ê ¦ŒÒxXÒN aEZè¨Pì ^4ö ?*g+’BÇ^¥B±+]v­xˆkJ>eQ<ç ?*ç2 ½Ti¡]4Ég#‰‡ ó~�ž„”Q¯!É&t˜gëlåê Æá;Oä¸g ,Ęg+eî|á<‘ä_=U‚ðG•zªƒ6ŠBŒF;�‰DûHðæI™v*TÃßÄùõP£a¯ã�†AŠx_)3Ð d˜ç‰ûl�¿8™·›GPn)4ÐP‘X[qôO¦ÞoÓ×&[ÕÄ®V¶&7vå)¤ã ßÍ4tlX¿µyÉs{³÷Fëxß¼ŸZMcw6÷ Îu¥M®WðbQ‚ŽH#Ë¿ÚÈò¯.û 5îIÐ1IOð1Ù¯~ˆ­rLö§ÏÁ¡Fd=ujÈ–û<`¹àÅ ïòRêAl�§TÖD‘|ŸéÒ{+Unœ@¼1øÐ¬¼PôBŽy'ð�î9”ëR§…rTÊt\ÎX$ú(}• D(QAÛ2Ð7i~m«“½�Kz +EašÔë<ˆr3e=…â�¾2¢)oX*7hYC‰~A?ƒ�uƒ�µŒþ@‰Ã¿tÙµ�Ä€ Z0ú+©N ÚNÚS¥…LžÜÿ4ö b4ö I4u¾o>ÇÛæwÀq¬Œfg)*¼ÖÑÿ †¤Õ ʺ‚ÊžÀD¢Í$þÞDŒ{wQäÞ­”ˆTùa¤OÀ"Ñ/enÿNw®ÛÜÁÑB�{¾ +¢G�©òïÉlG‰ÚO�ƒÿéÓ{Iê}¿´šF¯lÖñ¾y$1 ‹�ŒÅ/U +¾�óìœ>¸Ï#HWùç�$·~*Å Ÿ0ä’� Ç~4ù‡÷}ílîܺ žZ§™3£gâÈæ8²>#GFß®õð›·ªy9†,f`”ÐoIý¤|ÊDâ=/7–¥ÁCÃQúÑpLÒ f0z"ÉÀyˆ’ofýÖN„ë%N®?`B±‹X­+¹¤ƒõþŽ7î+yú7�Ä€]È1Ï/mnÔ‰Áž c ÁFdŸ2´•6í(=Œ~Á Fß æ 2͇ÕRT|¬'ž5”é`-$ΫŸP¿>R:Lµ„ï`åSŽàC’–2%üNDiJ:%œ6‡"›5U)bç×O�ÞU'ý–4�>Ê �†ãoðâÑ7Y†m¦MpO°b±/hÁè§V ÖK£ÝZ§ðMÎÃÍO¨_e$3[áGæìF£wâ [í¨œ9Hñ¤¯€`ÎU'yÂr5Q$Ÿ7’ôûBŒ{=IÌýQ¦ƒ‹ÃOÁÇdçÅ“Îb"ZgU ¥%訤¸`¬£FÃv’e÷æO­ó¬VMÝ™œ�Ò¢îâc ͈ -USYjÔÐW™8übHvªÒÃ_¤øgûxéÆŒ÷Ä @¿Z$IÀûÇ�ÎVÚÜz,%žõ(›Z +<.éľd˜ç—2½_ŒE$Ê@ûgïIÚT¨†_B�Ç/eBКÄû8Û5�Øæ}ÀtvQãž6*”ð#(‘hO•~$1 Ï �÷!ÄëEb¿N4ÙסF½·‚‰_Á‹E ÄáŽ7nÈ‘Ï/I‚ÿbÝ�Ó×ömðÜêš;¶Ú<§Õ Œ³gäÈ蘲åwö‹s�Ðâ_ZZCŠ}ÿÃPºB�M™‰³ûÃhw@Åa_Êüz°]mÔÉW7ÈáH/¸ÑHcq)q=[2ã–ÛQƒln’âƒpâé©LMÞðµùÚu§Ñ¯‡ð’!ôw@‚ùÀh4 þNœ5xg5§¯^V´ŸÍÊZ[ ±”™F»õÒç¶'¨�X[h’9/ˆ!9S­0¬Ykp²Ic©~f5íXJ<{•5„�^jtÐvòÿ§Ï¯tˆw5öÙR£†¾‚�ʚŒÊ_e‘êÑ;i‚m*SC»ªtQˆ±¯' Qè€X‰÷èG»™IÔ)4\W�p¤/ùÌbU!•ç('ì« }Â�KÙÁ IºÒÏï|çz!�ÏáÂÕ:ݸŽ$<²üóN£_OAˆ˜¡ZZwˆ:WèÑ)k1!õ^MFoF@{TéàçöŒs‰ØB𱻥ÖО-ÁỚ˜¨”hì@„}�h±ïRÔÓ¤óDŽzÚ)QÂ;Á +CIìwû„ï4¹üYK2o¬$™ßJG¤2äó¼û@ˆxN›_;©2È0ÏAâ1yV�0´ÀX¼§B o¨Ë°¶éRÐnÊìj-û쪆6“õ—r“uU +Å®¤Ùõ8mžçK'¡Ç£ÿp„ógH²I+]n?P¢Ýé ¶Á Ä[IóÏÎáºý˜±:ŒÏZ_Ö6õ)´ëT'ýâÚ€ Á/©WÓà¥ÉV6;,f¬›™3Ãò ÖÑ=Šur$m´ÙG+°ÁHûU7“÷V•ÓzDÏ_G¥bìRìrÔó6|k4ÍÞY¶¨Ò�ŽÀC’î d³gH½ìR¥à[HQ�Ç;gÙwS™H¬!à€¬¸P\p£‘¦‚QX?ø9c€²)S¥üK�Ûu +î|HÒ–xʘxÒŽ|ÒR?û‡$œ>ƒ�Mzª´ÐÞéÊýš»4§�íëlá¨H´­nDú(ý“¦à¤àÝ E£=zxÿÚÙK™[;ƒM:ÃO™ +†!�n“køÖ²6Ûµ™çKç¥L {)¤²ˆ/§óÓ¯¥eÔopÒ9GÀ1YK¥(¬ŸJÃu‚‹µ‚Š]‚ŽIA‰D{ˆ‘Ïæ¤ó<‚vô�Š]ëÉiÝ�IèL!Ge‘ÄÓ_‘œÞR3gàÈê¡G½¿¥Jê¿VOÔj\f¸pì: í%̯OsÿMŸ[]ƒ§V?}zµW=$½…–Ÿ +Õð»Õ;ß¹.5¾«L~¨P°Mô¨gϼ•Õü–¯2kZÙfO­-î}§Ìï­tx÷„çþŒœØleûXkZÏÞÙhDú)m&ÍÀûæ®í¶™S³søàlš¹3o-ó²Îî/€ñX‹ÈbJ“°"Ú5,ñ”ŸB»’e׉‡û˜4½ö’µˆÔOC*& ´h×kðÖh!E½?UZhG�ÑhC}‚ï:µšÛ3Öºö³D⽞áçÌ�‰' Eömý‹‡‰ ÁE|Àâ_Y"¬löUçûVÿ<ÞÍA‘z´!œ¼DºíŠLÒH½w®çðÉyC¹ûf/;ùSëK–]ûAŒÈÞÄö:_¹Ú†¯�ÖùÆÑD‘}¿h’Ïþ ×Ý}m§¯ígð®CÐ9SZi3ÐG™ü˜lÊX`@g­-¤„•Ïú€ŠAÛˆÒ¯ +Åá¯:‘(‡d· IJcHŤ¥H ÿУžµíÏ2lct ^š¯ÁS«}ÀsbM˜Þ‰1Pû¾³�ï¦Ê¯V +”ð6ð9hCiÞU¨‡7‚ˆÞA�5Óh·¶Ê}/.æµ5“wc“2¹}ƒÍÚ‚LÚ +eM¡G¦Lu±9òy'S0]A‰¦Ë(ýe…ÔÆF)½G$ ýRŸ†vQ#Ÿ6‡ëö +ñú)Ÿ²”Ò!†dŸ"=üR¢„ö“&øÈ10�Jú� HïäéýC‹�ÊD¡MAGeÁ†d?Šô¬Ë°#’ô‡*¢´U‘IúÉT°¦RaØ5¬~f³À˜Ê¶”Ê"¾¤À~0 –Á ÈY©“Ûuãd™:í•‹a½bÎä°ðÜÜàÆ¢G#±ë|ßj™9m¶æo »ô¹íP€{�ãmó—6ÛªÉ@�yU3uÀr3ΟÜL4Ù‡tÉ­�HÁt�ãMé‡tÙ­…÷j£Ê¿z(òo>ªìR*û¤­„éí²”b³ @ÍZ Ï j<ÖlLÎL—a¯ó7×Âz^Cj¨,Š)Í€…dt¨çëÎf½7ºtðæy+šC֝ܯbcÈè+·Ã¼8—†ܪÁ÷ºÜËxQˆEâäÎS-³VC(g^D³¾€ÊA“z2�¤6BË+—Xdí-4H„I‘MÐR>šìÖQ¦†u‡(§Ø/-'ê5U?NÊ�O{¡1{@Å«Ë)öªº‚Æ69ñ±¤„ÎjDÖU&;ˆ)£´Ö”ÓºC“OzC”PÙÀ)âlt¹�¡FÃÞÁ ICjfm ô«ÅáS»­gýãô©‰Ýð©ÙE’zÚ(»‹~A Å>4É7Óè�YÝ´×™:µkÎßܼó�ë4uhY«™�å3Ö‹_¹Hð@p 2ð­ føÆÂ’B¹ó•“Ï«„TLë™ýųa[4ujY©…µ‡N±À˜f!g=|AÅvPÀ»$*˜ý‘¼Ãun±X(q5³Âƒ&«rÃg!€šE0Ã1«¤é­%¹Ì†qa1¯=ááå’äÐÞQ`ø3%1n±%*´_VN½#žY3 -DÙÌF¥×<ƒuó à›œÓ…›{éfŸÅ:ºIô[s°*ce!ÍRpb)WÁ@¬•<·õÍwmŽA«¿xݵEÓ7†-ºìë:à9Ùúæ¯V8;LÑMžé»Z×è/™:í•QnŽja(H`TÛ‚öâÂBÞ€…+¥q†*AH7°!9?ÀA)#€¡ȤœF#�„¹ ZÔ«wÀrµQ¦m”éW3¸9‡0 „¼ÅŒAµ3ËÄ ¦�Ä[ºéÜ©L mªÑDOUzø«P,v$É.§¿Â¸6{¥¡;«•(»6„Œö†#—?Ä�λʄ¡¤xg[Ï´2Çnuq."¸‡ 8U“~ÁB `ÛµçqNžÙ+‹9ËjYé<Mà˜Ó Bì/ aW]@Á¤2f«t0^E ö¬Š ÖEm5dEª8#A~ýÔ +ÄÙ“Ì9+SYD§r–¦ò—´=†¿ŸÄøY''¼†%žrf·G™"Ö`QPýO’âöR5QK�*Ò:Þ9ùIì±VCgª �K+š,ÇŒ]e«Ù\ÓÈ™uœ½·ß®û:_¹Ú'±®’äËÊÈ™�q0­ü+ÄN{iñ¦Å»´Hp#@p/.< Ü�Ô70Ä€?8 �“y‰ÂÔÃrXàØ…-¡×CÄÙ)ˆ2ÕŠE™̬‡0¤2Óì�Š4N \Ög�o¾°ú‰Å€Ð+ƒ “W aF±Ú/ÐtVŒÔo«Bú¬e†ÜáK‰+“Ù ªŸÙ¯.'jì´—3VÒlÖ–Óùë +Šz Ë ÚÃê'�áH§¬F£¸�.ª”§V ÎJ ^z'\'ãpßä,ë-0¨t–—Pº��FºÉL7™zi I»ÙW‡Å°Ñ_6Ü´ùçñnN œëæ/›l]ë_ü«CN‡au›¿pÀoX¦S°|aõKk¡1£QñQ“aÙAc¿Ä�³T\ÐaTRÔR-e¨QCºjE#�•Å4;¢Ëh�áI§ŒáɦÜÀFälDXû$ÖÑ9á¶YÃRìÌeE'� ¬•’LìR¨—fp£‘Æ�ä3»!È'-AeW’ü?ƒw:\·?㦭¹Ï^gäÆ<‚„b”`v2o§Ï¯í Åã‡òôŠYÉ´Y~5A_úYÀ…x¤øPNg@e…Cøv-Âì£cή]|Ä,þ�BŽÁªÏf}¼ÃFåXK*ý^ƒ(ÿ©¼vHõŠ F£Œ`E#ý@GäüZX#xÁH_5ÓTv'TAZÄRú.ǘ¤‹%l_BÌÒ†Ô¸?<¥�=Ðâ­ c-B )}á‰(6ˆ‘o^Ê$”ò° í(+l°(¨‚�ÈŽ£çgäÌ:NÛ×ù“³ƒ +óì=9_£w6[ÓÈ®:Ý9ºGñNæÙ[ü… ƒ… <ËC‡<-¶fMž¡3 «ñkÃÖø±]yÍ‚/-àN< +¸”Ñ®†!„ñËk<"0Àî.9èmjí7±¶'6nœÎL¦^Z†n ,†¬wé ÂÉpâú¿Ø˜C@Åû%†¬f¥Gë¢c¾µ@kµì�Á¾¼Èvøb"¬“Nl0§X?(³Cb¿¨qozÜ«—:½ô”‰Åy‚ŽËùꩌ%…TÆ�D“¾ ³ñåDvVeÑAXù¬“2¹=érë;¬jÖ dÎK¡^ZFïgùý¥ÅÇ®[5~kX#Ë¿ÚÀ +BÙhÓoîQÄ“©b ÎE›~3 –°-nkmYÛf0B¹,‘& – Eøj@…"vC%Â@,Ð", ,²ã+ì‹ ùƒ¨X©†µÐcßÌ*H;è!)ce1Íf@:ßSXØeUb|DIJõͳ¾ý0*ç_L¯‚ˆå¢Î¿l‘²vÊ +Û,IŒ›‹‰ioÒüÚ;�t¾ç[wû„ëîÂ8í ›�ë3ÍÚÿ1¤³u¾rµŒÛ-ÇŒe¿¬jÿÊ¿¶ºx† 8 xS�þɸ��îÅ«ÒîT™—�9ã²æÍ_2öVLœº§%!TÊ÷u`Hä—Ó +D0¢ÎÀëfW‚ œ°`œ»¶°�E €"›� +(Öc¡Ac�!•à8¤°X{y)ý‚=ˆ”u–J¡ÓD�ˆˆ™”Ò5zØ�>ÁýÀ +EÚI4\Yré§ÓÂùÖØ{‰ +íå„=bÊh½aIh¶C*è<"I¨—p£ÑZÌÓÎÌ•ÕÖ²3V‡Åˆu/¤J/�•Å4û“˜7s 8p ,p¬ XÖ¶lfo,KógvµÒÙ^T6±"Æ0Â~:÷¼¬t´góò`ƒÛµÀK¥WÖø†××8Ø÷I–¾)# [á’Õ[Ë}…óº4ê•{ñèžÄ»¬‡L`ߨôðtT„tš‹ ÚC¨X˜b?(`âzE@†,×ÈÃâCþðÅÄ5ª„¢ì$j(#iné#M@ZésÛ‰$ûº’¦—f CR&á唯JIáéUÝ;yោ–³’r• +D/„¨w÷„çl£IÀ~Ãe›ù�åâhàUSWÜ…1h R/K´é—º“@3lþc¶ À(˜Pe÷ ‰tð ^pÕv IØ×XˆW‡1 / @õ¢fôëAjf˜ûP`VO>Á¢X f—>¿sÒ¦ làÄ¡Ì$ú­�6ýè.,ê»Õw�fwå°B–z2"âlD³M¤á¹Èr›ý€*Ö¾Òâ¯)aAÆUµ3U‚í¥HÁ{ª³P j˜L +Tp¬ç¯ŽLÆLûùü…å^Y$¸‡ XÜKD«œç 4ˆàV :pDð{Äÿp¥�ÿ­¬ʼ«ÌÞíÅo0ü‹A3.)(Ž]Æ*Ht�¡h‘�±x•�­xÉc%]²~„q)«`†d6A�GùB•Ðkˆ¨¸Þ9òƒXË +Zg°Ò™ÕPE“ÖúRÚËžÀ¸o)1¾Ú‘÷—”}C“ÎÙ+ +èíáʨœF#äØ'÷ÞÍS&e+›Xª£Ù0ë'Pðß åS¶‰ #ñ„´n£ñóÊi¹Ÿ¯œ¾zq-,§K—í *:ƒE)Ὢ˜¨qþ沃œƒ…<ëÊïê�ÅŶF™z½ÌÆJ®‹Tø{c®Æ/HìœÞ…ð�¡'"çt. ¨F`ˆ c$ &»M Œ|ÿ«*`1$‰G8AH[XýÄb¿¬ ÿ† Ñ*þpB&ˆDÉ}6¥†-õbpzüÃXQ˜µ³à˜ q){C’ãž`3‹T饑2»ô)!­aЧŒÁÉg–È’¯Þ”«�·7U(¢} Äá‡Eœ•>e%ÐÀÚGñnž¹+»ÊÈÙÙ91ÚÆ�mÞéÖÕ5zg3÷úÒâWW¸S \ -¹²0™93¯š®\ד G®­qޝ>&¶5Öáµ5ÂÅ5†¢Õ5#Â@ËküEÄ…±�Vc\p‚ËBJx�· 1ŽFaKè‘× I:¯!À”�¹Àœ 1DÅMþÑ8€q²Q§ß !‰å• 'æ+2³ª\^C(p"KWYá¿°¤ £J(ÊL¡…Ù ZN¯"(!_­Ä�Ç Ððcª0l @:ç£Æ?íO—®Lˆ{—ÄÍ;“1³Ç8–/.!Á®`ª¿±ZU5媈œì +ÆIpdy—í +Ô õ°ñ~[¤Ô ¢hvŬÙ"xÙW‡Ÿ{$*Œa��ÇXHÄ�Ë àÚ7.61Ê]Ì"U±:Œ YBª&VéS0‹…aŠGTµ‹L¸Ø´•÷J³ l@ΚhÒ°„ÎR,ÒD‘|žÈ°_Hµì÷S3­UÑ …a}€E"]£Qž�Š)/i‚iž ãWFpì—?’ä‹:t«=Ïâàů&„àYºdànìÎ`=S'†eú Ï lDfyó²4ykaC™\0¬ñ‰°zÌãÚÀ—YЀæzÌE ÄX5ëçG‹=¨âP:E¼éFˆ?ñqÃB³ H9C™‚µt ó¾†&å)‡tVX<&=î.#b‹<�˜}“¤Šµ1±q‹ƒ:3y~k(ÍCo¥€¹WyQèR*Oà±™•0ãr¶ò±‰�à áÇ%V)S�¶’i³V²Ûæ`ךwi]ù† YœÄ‡<ŠqôÒ‰?šÉÄ–>êìëB—yó蟌 G#öÔ/+'¡_R*&Á˜@àPÊH¿^9”w"„R€CPqÍ’0~!bø‡ˆ c"ŒY„0jâˆYfÅɰ p +’ølEŵX»¶‡¢^­^8½(„ ýš¢±x}P¤òZƒÁ!ë=é!F‡¤ÆØ—–Sš:¶,Mž¶fk–=õ›©t(b³ °"ÌŒ ޾Ö$†öKÊŠ™ªRR ÌR½XÌf V+-°×ÌÀ&Ib³U Bg%Ð"Ìêe�TxF´õKË¡‹+ã"Fd¹’Ržôä€wÈ�(S/lCPòÆ/¾*$ +ö@Ë%‡ñ‹.@t‘7#™t9›€Á„¡àt„P�o–�Œ½6%ܰhN×2Ìœ®U�U³dä�Ö8Iˆ³q–¯¼.Ph´0?f-´À2Ø)ƒ@©\§*äãiYRwUö- t„‘u-Ÿ> ‹§¯baèkøÌhœ­——>Šw3–ØŽÅÝödÇ·ê�)ó+!x‚ \I*W’ºÀ“ ®ø•Ë‹�ŒÅ®Áˆ¥§úüšíü¹•YÇäÎÇ®aûaã"A³Eãºp]cã&`~¬…«�Áh¥�èZàE�¹�P0vÂ&Å\>·µ€HÐÄüqŽÃ33Ä5X=Ø¡¼Û2€B;Á¦ "‹©|¥RÂÛV`ø8'8´ƒBRÇúŒÑÒOLÅ2¤bvªÐD»És°er³˜\f±^ZÐ!¾œÊz\fŸB{OâÞÕÁM0 ¨f•ªy-‚ä»y�­¹… $øÖVQ§Ÿlƒ‰Ñ»«©7XŠ;.Œ�ÚÀM� ³ž'txÊ—~cKÚd0d‰PÐÁU 0^)@V;€Ö†1” Æ8°’¶TvˆYÔVàÙ«\ÂÑW’ùá43\Æ + Š×ueØ¡¬ã +Êä Ó1”Ëbó‰ÕkòC«'…‡ÖK5†(š4Ó§·ÿ„ódÞ´2φmÉÔ‰a….õdX‘ óâB®­Ü˜G`• I°X@½¼Æ;¾:Œgt1ñ@Üj`@©–'ùú‚1`®ŒÑåÌS•Ôt +]wˆ”?¢Ë‹0š»9/Á.¢C T?}<… F�YP�f·q0{¬Ê%6þÂU7F L;6`«ÃX Ÿ[¬˜Än�g,àG3A|Ã(�S;Æ8¶Êè1—]©á³ �?`1•³0‘Ýæ4L/µˆý¶*¤›UÉÑáTwØ?K _á‰dMóW–íiœË’(€ yÃL€Íð•yñ%ÑÄ¢,pŠ”>(E‹× ኊQÉÕ3ØýªÁ³ûšY“û2¢Lüúÿðòëâ% –¦vôF«yâŠÛÕ:Äx—Ñ /W(Ü#ƒ#4ŒuŒø?ÑÂ0Vò¡ )2ì 1¼šIñvÅûºð­P|BQ‡ê âL7?|IƇñœ„zœúÅxd˽¨C•¬V�Q;ÂX_%‘¬A„éìdYjøEPÈ…¹í!1~X“4…œò�2#—Øf=Ôy‚“Íë D0 +(Áå6®rå€õrñB£ Öj è‹0ƒ*b°c^}|äëmœ%ìo &k6†Ö5.Â%��xÉc'\Ùq”-´ñ^sã€Á�+CDÕø¡*�¬�bVÜO�âU>C܇ïpN#Å£ÄÁ",°aLÛ22ýÃB¥Ó"0�ÅÀÄð[8¥£bt=Pdœ½4ú÷!ì�¤;H •+¹¤möÔ:Ï +¡Å+HÀ²º‰yuËè2¼’@od¢€ h0Yº±–+ÙXõ+ÄøÈ«± Wc!üx‹Ö6 ² Ž0²‘‰W,˜s²{¤„xÒIßÚ˜]Yã-YÆG°.ŒU=Øã´ÐÆà: €k#0¢ÂX‰£ñç…+‰hvÀ]qëŽe@ůŒšøï¡á6)N¼³»Ø¨g(%l8"k·³šw�yq®°âæ*åsµÌUܼ_°ÐacØ#]° +(áu6>‚ÕÿàªiL�3 ·µäƒqÄØXKWXËõÙ\÷x�­ë_ãB´� àŧj€kdí�€°¿$�½6øvaÆ`×qB$á4DÒ ç8[àaùŠÃ‰ˆÀÃ$Lq +JJ\JGˆCÝ ñ$!Äu¸•“¨0�,“„ýR“p>.‡©démP’½ÇE®|`œÐ‹V ø•:´˜YÞèröer¥:‘ÒåÀDÉ’�“\鱑/°qj—ÕøÄÖ-žZ `:¢�§lý�,Ÿ +` ‡ ð#QXIã.�€L6îÒ6~¢õa¼$„„zÈâgÁ†Æ]…˜E™÷ðUU[)àlp¼ øà•ï AÅß®¢ø˜(~}j₊8ÔMÐ O’’Y´;„�…xm˜R×Mña³1¡¡½»ÀðdØèd Èøa (ѱ šõ2€ŠyM�þÝ#Ì-æ*!�`Uª”\LFGøñ–-°�z^˜\ÇÆØ1¾’aLÄ.±„¦ nèIõj 1g!†RkÅ¿S6 +@O1«Ø`a¬Äı¬ªqLcÔ =M¯dL¸Ià�ß/”pB¹§óp€ƒUñ,§"ÞáȈW0"âtŒ¬œFÃ�¨=Ï!IEø+›ŒÙ«ž¸�&¹�{è"ÁÁè¯ËH%]Jp�Sq7�J š“—LôöÆa°~¬ÊõÇU¸²c(["ÆND—øP´ÚØ!jŒ‚C†± Æ4<ð$ _°éÁGáfÈvÂÄ ;«ŠrŽN É±u0ScÏÁM�°œ"‰j‚ 2˜‰¸€G¦à}s§Á€o)0À-q%#Ä…fpŽf„„Št?ª& gr‹4éì&CXDUÐHêävH•Þ4ÄÝ 4&¹@lLr�̰DLukJ©sœá…ŒPH^n|XÝø€0¬±Æ1°€�$j¸¡±gaçˆ×�–Ç +B]Ä�à™áÀ˜cXUãœÆ&4y�Ô0ƒƒN×ãÅ· �8ƒž!þDÄ�h‚¸ÑŒ_š!âL4CA¼GGLjÿðÔÐqA˜Ç^FP†‰hBö%ñòèwäè¤/%.d›¨ªq˜‡<:1 w€bžJ�›|‘åÌÒô \dŠUµA/\ºÛ¸ËWÚ8Œ—‡ñ•Æ_°’Æ3*ì`�Œ scÍŠcÒ 8£W^‡EÅÿ(N/€â_ x…¤%.AH‰7Râ ‚”xƒ &®ÁÉ¿"˜âfWSœ/DžaŠƒXRâ |Šx“ OÒ©©‘á4xŒ„„vØ06nŒ%L�Š•^¶À�yÄøE˜Ö¸€¯²R±•‚»J¶t>AÀ3ðI—ÎÀ&Y6·KV-»BŠX~}ì¸ôþ QYèCSRQâ!ª”´7ìjœ+Â8 ¤1êž(�dX¸EàŒa8Ü'>öÀˆ‡€2âXIF\KJ‰{%Pâõƒ&~Ghâ^RI|K +‰`2ràcÄ›d†�¬B|ˆqÞÃq¸�•ï3ÈÛR€°I°‘NÎ@&G<ÿV¿hþ99²oÉ•É@#6$»=ŒTz{@©üîH"ãPAɸÒ1”‰Ü +7ÜØ X‡q”Æ*6è8!¼²ªHcÀµ ø¤—ïj�âo xZƒ'NÆà‰kE%q CE<ÁχÚâP:BT-XGÅðÉkÿËjâ~YL¼�ƒ÷~˜âßRœow“ÅeN|C‘·BâtŒx‚�"^…cÄ—¬CÜg‡óð>Ä{x’UˆCÕq#™¡šnMòAÂ0’5©Éäβ ¤f`’*˜[$Z.·©U*·DR+»AhTr‹È ìYBÙRd’H¢¤$�ð£ç½="]hãTDxÌ`µa�wθfGÀ½¦øÖŸ£ÀÄÇ"$q/)$޵„Ä) ñDF|Á�²âGV~díáNÖ î$3Ä™d„¸’Uˆ'Éq$kÐŒ•„‚) c'"•brSƒxB©òÉ]R%tëÄÊ'·IMnjÊÀT&”] P.¿>˜`†s@©X&"ê5µ±^ÆD°hx¬]à^ øˆ¢#¾ˆGÉôp©>E#Ä�¬?\‰q!ÎËb|8“ ?Šâ:\‡×ð.Ãgd"P°5NÕzT¡åL Vb),"JÙ˜D�rÉ–rÉV<øã“Òû#æ÷G�]"©Ÿ‚>Žl~}Áä‘Ãr0‡ŠJD�†)¢ ¥�èb—jˆá´%p½xö· +:âI܇ûÜð^ƒÃe8�¿9@¸Ça¶* …lV~Ô¨ì±aé ²Ãr{¤Éf·ˆª§ ÕM¯(™]!O,½?Šl +öhB Eî0ˆØRTI¤‹)h|ã-Yc!hT´]ànð?E82œf‡ëp¾Ã¸Ïá9|‡çÔX¹L ·ZeŽ�˜l ÷°ìñ—-1 /f˜_'œ�|‘|M Dú-A2é-R X\¢ +›%e?KE#ˆ”„B0-�$bB"W‚F™«<¥âFY:å­2‘HãäWH Æ[ȶY�CŒ¡„°†’Qànª8#%.EÄ�8â:ü†ßÌð.cÃmx�•ËÐp.Ãi8ç8‡ïpë§ÐÀ�Õ/ kHa…ñŽxc\+é�“ÝTâ-’”Þ$¥•†H-S/!“|ňC)¿=vX +êbùõ‘ò;äEfWH�KÁ5*½>lX†y¬¨LÔ±éØiïïÈ󈱖,Ÿ%ß |/DîeÀŸ²)¢áœÇX¹•Ëìp žæu!ĸ‰¾ñØ·±°>ÆÂ•6ã¥HÄ{2ðK.‘(”^4ÄÝ 6(»B^ˆ»?tT†wÀ  û ­4‚I9øC´rðG©¥àŽ—•Nø01›ìU–˜Â6YÀ³F%V´„\°ôµ1¯cYDT;ð· +8Õ ¿á9|†Óðcå211<<ˆûð!ŽÃydx ç<†ßpN´óĹ4HXâQ n<€¯É#Þ•%™ŽR¸‰RЧÀSšVq£$‚)îa1É2Cü ¢"ÓñÈ d .d˜�I‘[!9$‹è rJ R*Ùõñƒ2ÜãÓÄ·ÅU/6ÚØÉ•;#ë�Á\‹–‚àgð@Gœˆóðk ïá6(Ɔóp~Ãgx�•sÎ9·rÎ9çœsÎy Ÿá5‡ëp¾Ãi¸ ·rnÃuøÿáA<‰W!Uñ61 ^c-#,»ª–�zTz@ò­î¸´œ¢÷= 2"<"tÍE%WOa2®ª§ O HÈ\]µ´723ìÓÙÓ]Ö“U„¼xêÐîìÈ®#j²;2gqYSSc1¼�£ŠBÊz +Ea�ÞÙ\£§F@Ñ8oM1í]WP»×Ù VP¯C‹�fNíH øAI(½”éšÜ«ÈXœÔpœ£J xö£Èí�"-ô X,6qvï"G?[)“Û”)ø‡ù~Ï¡\ßÇÕ@�y³Ô‰D/i%Ë.ŠC)í¡Ä¿¤ˆ‡ D¢MUâðK™~Æ=ƒ“ÏlדÑ/G%ÍÔÙ*Ükº´‡ùþ�#Ÿ�~A‹FO¡€LºÌú�IB“´“ô‹ÅnU€äOXïïlç€ñ$Ø ¬!Ì€”ñاP ÿQäö+Yv!ÌBôó?„v<Þ9¥Ì-ªá7¢ôóE“}ýÉüÀHôS¤‡ÈqÏÖä%âý›¼·¾ã•óO à"˽?ÄÈWôè•2¹=JtОE<šü³ hôhL~*íÀ8Ï38×›:¿”ia ÞY�Ó×y¾vC‹{¿ +¢ê Û<`¹?ÃVFsƯ[_4si´Rf ­ Å"Ò%à×ù¾ù%ήw +ôB‹z¿§Ð®Öé›ûM�Þÿäé½Âx÷Nî )ê})?Õèbwò/mn¿Q%Ÿ­ó…ó9Û6oàôk•c²O�~>8À·ºÉs°[õ°”)üÀ”/ 锫P<ÎO¢ƒ]ÉÒû•8»ý¨2ð�Iú*H¦ü4ö5{krL[ÿª 4£} +íúÕqß@¤³†C¬$þÚS§ˆýésÐAn½‘ØÏ=þÕP¢‚¶“gØ-Úù¾4YÆîÎÒð™ÉR¦…þ�IºBNùŒÉº)ŒD È�SÊ ´”8üLš^¡Ç½:Äs…"œY K@�Ä€*üäIèô)„˜g!fíõÄôc—œÚXR@g,?T(X ÅŸáçŒaÉæ¼AµsžÐC²+XáØ›2Ð"Þ‚ŒËÉ'}�ç‘$à‡ü8(ë¨ÑA{¨q¯‰s{3Xé¼`TºÜ5æõ#Ë?�$4šì ^0ú Hz©Rð­(ç}ÂvIš�þÇðΑïçláj›¾´šH’¯#hQh#X�è§P ŠÃOÇä?€J¸³�û=„t=‚uß&�­ö!¤óJ›Û�à„âo0CÈq�V²ìzž¯�ç¾rZ]3mi´UŽÉ�†ã¿ú1Ù�*ÿÄ®X»±zç+Wó„çºd^M#‡FAþy!E½OcgÖeÐÈ.ü¨ôXB8?‚ˆ^Çûöèƒól%Ê®=…j(Á†¸~´âYÓPPØY''¼‡(žu”hb úõvˆë H6i :,ç +=6å«¥µ+¦4‹ÝP�Ž9›Ã¬hýê¾Ó@D³®BÁX”*-„ÑøœPìOœ„U'kúÐh+ÜÇÖð¡ÑLœ_¿ …cw@ƒRž s¦B5|âßI”�@a¾�h3XÑè PÔ ¿UþÕ‚`ÊTIg 6(k¢a[ÉÒû‹ ý|ŠÅŽ@ÅbÔhØ.rô;pjho(¢Ù5á¬ÀÐñ¶aH‚YA!ýŠŠÛ«Ê ¢H½OSWVãü±yo]oð‚Ñk5 õŽxÒM™‚©òï>Šü»0IJfàBñ¦2Õ!îNÚOžÞ›IÓû§L„í2 +ÒåÖÿÚ%Yn¿UHŸ!³/pÁè“,»ÞI3l/há8…jø¨ üG˜}Ÿ†�Œž¡»eœ-[}Dùç“*»^� ÆÚÁŒÆE +¦yS«iîÒh?¸zGP®æÛÕO¦Þ?¡HåܠƢ�ÒÁ%JhG…~1cnksÇV;} +þ @,é 9&û(øÛô¥Ñ\{År¬–Ëf­luVÇûæïê E½ÿ$úµƒñþÌÛmmÓb‹$ûþ˜ÞAŒÅO•‚ðßpÕ:„ŒöT¨¡í †ãoà±3qnm¦Lî �†ãÇ‚âY{@"J‡%)Õ¦Qa6W#FZ›dX&)¼O—¯� E»‘Ì™KúBj§¼u%Å…tT'í ?"} Co`TÐ^²$jôó>(;‘µ”(¢Wªüz¡ƒŸ� Ç~aˆe}€ázÄû7€h¾fï¬æùÆ%ü +T,~*ÓBž/�ßéÒùœ­\ý“x…*h[‰¬#䈬 ”z$Ìmgêìú©ÒB›ÊDá_ÂÜÞ9€o]§w4É%ïu¸±,¿é0^gÃx ³¢ýy¦î–‹ ýÀ�€Š}0âÙ‡õî>7û§ÐÎîùÒÙF�vÍYŸÉÓΜìú…µ„³_øQé7 Éô ^$êxß(øÐ”;¨ŠÊ]MHÿ—”}frÂCRz+@ÑèiàÒh¤Ë¾»�ŒD +ô«…" û'»�t›³†ÔÏ9KɧÇJíìU¨ˆM™\-á�VQÏž"=üvXö 5&í)ÓAÛéÓC}ú0 ½• KÚLº‚�ÊA +D&LîÝ#8w Äá¯À³ž0ƒÒW™@¤:EôMšà/ZhO}**î!ÀA÷,ÎÉK Ünàt°?…v(ë F>³¨Œfé(%î« �‘ËB’´QäßÏ ”£qþÜj�ï[íShç�<ÃÖ´šæ_]_9|p¶‡ÔÏ’m5 µIDí#´„v E8çG4=àoòô:�Y3Pñè�"·ÿœç‘"»žÁŠFoá¥C\ÿ âý:µºæ.�ÞñÊù"H¾ûÉü¥J =•i¡­€£¯:‘è‹ý6Áw‘ÞªF¤7ˆ±é“k/xÁè˜(ü^,Ú™„bM—‚7S&÷RÔûG”}wU +Cû�Iº‚Mù*ˆ%Ý€Æ#eZ؇&õ:cmdùW@ ÷§ÎÁžð\çöÞùÎõ›>¶zOL¶®u°˜2,˜ŒÜ-óÒùžÂºnÓgæo×ê£JÀ.'¡¶‚ŽIð¦B5ôG�7 ÝYÝSw×ø™Õ1e×0^‡Øbìûž`ë™XÖŠVcqþÜê'PÂz“OY†¢Âƒ JC¨Ù£@ýçWû}‚¼³�Ä}7¤×S�"VøqIwpÒY_ÙÀìK–Û»æ.�ža+£oðØþÎV.ÁŠÃû F{ +ôð3UvµG�Ûÿ¤IhU@”õS§÷Æùkë3qfô ›ßÙÎý#Èí_Àñ¶*@ò+8ñØŸ2¿Ú#È@[éñk3HÁhO}fÚ¢hÎ7‚l2ÍžÚÕf›6ïxçºÔi¡ï…Tu[Eý[XFý†&ô!’ÝÃ*(��Èe_²ÜjsþÚ´3ofµÐ žØ„bïÕ„Ô–0c²/x�ho�ò)c(Â9G¸!Ù…ùü“'‚�È L>e +;0ç C8é¬$ž>Ã�ÌÚ +ä—*þD�~þhÒ�©lC…†ÅÜ B2�(ÿïĤ>Ãb L4Úä±Õ3pbsŒÚ|�!Ëb +ïl+�¿ +-Þ‡ï­'hÁȵJê±TGå+i|þÈÒÏW©0ü \,ú¦L0RäÖ®:M´‘"m=¶:†lãY[<bKæíËK™ÛŸÀcG² ô3ug²µÍÆÖð¥ÉH—€ÿg�¦©;›yÂuõ£Ÿ·–i±\ó’yÓÊ6�htŒÚ|埗ŒÙ|ƒw¸æeÞ´³Ì›V–Q“}é<)žÙ--%j >(g¤KÀÃ×VÛà±étá¤J %ÀXô +`,Òä•ÕÖµŸ�9›e™¶1Ú&OÍ×à¥-]vm¥É®6¨Pï>r ´£FÃvÕ‰D�`E¢gÚìÖì¡u8[¶®Õ² ›m“'w-ÞM•‚Z)PÂ;êsð†Ò¼«NY3‘v»UÎöâZ¯-Ìí#˜µ�L™Ê„“)˜¾R’™ÍÂ2:ƒM)ý¿‰ m‰é]ešh+EŠ!Mò�étÝî%ñVë!õ³ÎBÚ©JPâ^_Úôv*…A +Ä?aG%�•ä“6Àyx売ž`£²‹8"ÚÁ–˜ÚYG>=Žÿ ´«-šÜûOž‚·"š}CÍ~ Ä¡� �MÔØ÷¥D}U E¿”Ùý:Û¸O#wV×Ì�y>·ÏfÓá{û̳…ñn¾4Ïi\œ&Q‚ð3]vï™83šw:#VÓV±^ó.-/þ!Ãëš-KÐ!ÙIp9!c©ŠÊlDv/ûŠBM®¯JQø£J…ý<e‘âß-£¦¥ùÕ‹‹Ó\]œ ,Œ§PÎ[‰¬!ô€¬�,;Í™Ìm¬—ÞÙ5&­ƒñ�í²¢ù/î实ýš‰#›ußê™:*ÒÃou“Ž`C\O¡ò€ç¾Î7®WÁü_\L}/¤4• +C¥Ê­�$ x1þ& +Å>ðè¼-ð-âð´Ÿ@Á_æí¦kòÎ|‘£žXOXΦÏÌ!òÝG�}7Òc Iì§E¢ ´›.ï&ͯ]¹w1ÚÙ6xj}N[×ä�y¢Æ9:¨1¯S±(쪈Ê_RJôKHi§ÌÁ)?Žÿª†ØNP‚ÑN‚ìÚL•]mP"ž�ÏAûJ‡e�`CR‡;×qúäêB½Ît鵓&¹6{k�ÆÎ¬ßô¥y<´�ÃÇvãü©Ý7}h7ŽŸ›·¦y™_³¼¸Öëk©së¡èlŒÝ±#²¸xvë è0Ïg8Â9kp"н‚9˜2*ƒ�J'hqø‹ý õn¦ËîÏ Þ÷ ÛÍÀ™uþ¯×˜1[ãw6ï|áþ�¡�OúüóU*{…#‘>ÊøÓÐ�ecÆæ¯˜2ÙËúf_uÀrsP#^·ñkËZÛÆÂjöÔ²N¢Þ¿´hÛìµ}*-þšZP®ª&æ%¡^K6É´R;ŨDo Â=¯ã•«“Ä\;‚ ÉÎèõIœûT%µr@ÚNŸÜ[ÌöyãúR&àÝ´Ùµ™ÄÞ;(1Ï%þ%eþÙ7~l=çÛö“8gS•ÔZá€üMž�Ú@´£œ=8;ç/®sã¾�žZÍí/0®Õë#¸œÒ[ONk&I@9›n­ïtÝ´}8~p5’ð3�±Ø-Á¤¬hôH—Eb¿ I2Ù¼N8Ž>²¤5L!Åú(/ü“R;B q}5±Wè1é«Pí$H@1 0ÞýS('6ô¨g=êÙDŽ{rT*Yv=Žß[Ÿic“}ï’&ƒëno›=§­gàÈj8³.S&Fˬݵõ¬Ï< ¢+¦,{Õ|«½’æß-5jè—,¿6�wî5*6iö +@<³]«¥¿Â�Ìy¨qïïxá~ÍÝ™ÏéƒãùÊÙ5tkg6ÖšfÓ2nbôMÛØ5LÊô°= ½;Hñ¤‡$ó¼UMì:ƒ‡v5Êô«'쨤À` ŠÌ›�JõTŠB)ë¯'¥vWÇ3³Uwˆ,¢J‘òcÍA +'ía”A%´“�2ê³–t~+“]A Æn]§:Eô d,ÆœÕXë[}µùS›§J íT>=ˆ&™·RïmˆÖq¸j= ð;} +~'Oð'jôóIb®U:øw引Íg­põÕæ/m±êéA@Ñ´iðÈh"I½ß$ÚmÒüÚ9|rž‡{÷‹ýìA™ËËÚ6ƒ5‘zûJdí³;›„ øiôÎj0ÖYW@; +©˜”^Äêhÿ@ô@ŠÄ:j4l/aví£KBKFn,KSyÑ·;ˆŒ© ¡¡AU¦*EüR¡‡‘ïîáÆ�-æ‰I•‚ï£ÈK>ë.'žÚ G:ç&ήýC¨×ïþ‘d —2=ÜñÆÙ3pd½F¯ è°îÖñ²Ý=a¹ÛêVgeÞz–æ-;“g†Í¯aHýÌj]1­g)*üµ ê±ôO¡J•ú,½�÷Φ±3ë8€lJ’‚ÿi3l-ÒÉ¥Ñ=‚sc?Œ÷«'‘%‚ke‘BÜó ¨„Ö„hÊJ›Û¯ó�£}ëh¦Îo]¥Ñ/ez;§_íà‡#Ýäü!̉ëZª�;³´Ôw‡(¤2‚‰u‹Äz�ŽFšê! !Hä¬� +ç<•bÐ+uZ¡œ;H•=,ù¬³˜ˆÖZKD¿W’O1M:ï 6*}Àw6 Ymeó2ŸÃº¬e5–çKçÔ@´·¤lŠ…hÂi?‘ +þš¿´yOLr¼ó0"i.ûQ$ C6‡Å õ,� �_Ñ&!…S›ÅdÓn +ýú¼²¬5®csÛê£InOÐÂQŠ”ð+Yvÿ…P&¼ª„àç Ã}¹±,�žv'n¦jqHcXÂ9W’9K…†ï<µšfîl† +×ì¡Ñ2mer�×Înâüz8ëBÄ3ÕO™DS B@å®&¤? Ié"5tæòâZX$äˆäв%ÙñÁœ¤èPk¾;(QgÎ1Þ‰Q�Ú `$ÞI”ÚB:¿„ɵ;¤b~­%šb!šlÚWA$=aŸw®ïpå€ñ~QäÞÍd¹Õ*Uno£È½»©s{Yúy£L>Ïžë2pÚìŒ�=Ûü¥ÍLžß³'2l°**h :,å¾Ã­ë=_»·2£Ç?Û*Hd=bɧ͡ g�„ øç>�"^§"Ô>€±x+]Þ7~m;‚˪V_{ éjª‡Q'Â^HŒ×kðÒ䘵þÅíì— \Y˜XnÞ1œ“ ëè#M@ºA�ÇYLŠ  í•ýP: +µ°NÊäö©„}CP9ë€Qì +ªßÊ"ú¸(üG–~>êD¸7�áØ´ˆì„HÖŠdÎYJ:?ÍÄT l‰©�•”†ãÑÆÙ{û2kZ™ÆÎ¬1úi7$ÙìVAkW@iP<ï «œt”‰Âúg¯¨Ò¯fã±ÖàD4Ëáˆ'½téý7�kõ àšOš¼7 Ѭ=¬‚Öª€Ò!œpÞ�dÎP¦ƒµObmÃM›} ñè(SÃú‚Ïì‡'¢J�žh²¯?�‚»…&•5й��EÿƒxW[×îk�_Z6)Ô¯†*¦!à€¬¸`ôJš]ÿ4 +î `4ÒM¡_¯Ã•«{ÀwõOïîßÕ>ƒz58oVñsr¢ƒx"J_‚Yk)ýµÔ±©œhqÏ–qÓÖC�z¬‰©-KYÑ'ìàÄ6ˆYG}"v&MA›¼6šfÎŒvòôÞˆ`v <,ÿª¡çË}:´9‡ WK�†ï)m¨Ñ°RÄû1c=Ë»¸¶bÄf,Í]Ùt¨ç™*»Ú§Î®v‰r+F—Ö­k‹Ãm«ïú†µƒëŸE<š¾ZÛþ—LÜØuèñ�þ€€‰ëÜåýåeEÓ&¸çôÉý/^gÚ÷&ͯݾë8m=©²ë+©¬¹’ˆÚ�xÒvhsÐ"ÞUŽHû©3lÓÀ¡Í¼¾‚Å Õ¢€Î¤xÒO¤‚>'ìFǨÉ^œœ† „¬²ú«¦oMæYœ“ƒ$ófølS .�áɦšg°Ž–�“eâ´2aœw +ýú +C2çú‰Šß¶¤†öGYñ58Ù¤•,»§Îû Þ}3$éJBë D8g(ÐÁ_´ØwÿÖÙ;Ü$1÷+@Áè-Á¬�<Á¿FŽ­¾ñs›‹&ùl*m0ýNw®ÓÌ•ÕAŠw?*”ð3`áøÀ˜¬Ôx¤•2¹Ýǰ®þ çùn�Ÿq+£¹Ç~YÛIJB‹{:ݸ>ó†6Ûà¥ù®ÜL X+az;O¸®¶¦}0~%!¢æOíŠauS±EtöA¼«ùŒ‹ænM>Âü«‘2§^Î!Æ+ÂzlÌbThø-,&f'Ͱý3ˆ÷¸`ôôª‰Û;AqO B9/iv}U +Å~ …"=ÔÈçiìÊf«ÚŒ¥¹3›‡÷ì'MA­¢ž-§�cȲ`l?Œkô8؈üþ"!3wciöή¼‹C¯pÀçÊÐ!Æ,Ëuãe“‹.ÿæžÃ»Ù‡±Ž^òìÖB’z´L›XV†lŒbìë +X¬—µÜ!¾lµÿ¥åDmÅ3»¤éívLÒ"TKkmb|7p áñ( ,ÛÄ„-!‡¸v0ñ3páA†dï€ä“ád´ÎRíRAg)RÄn$¹í;^¹>#g–µºu¬ÍŸ ĈG×ü�ecÎì/«›³ñc›qáfkÚ¿ZÝ´Wï�ÙõE��¾Ç�®¦¡+›¹óâu×–Í_ÚÌ*hm ‹Y«Áàΰpb`>ˆy3æ¶>ªì6}iu }µ®ÕaV¸ÿ5d©WWH²™… {œ>8ÿ6&˰�ew¾uó”ý‹K +Z‚ŽIšgp®óÒù +?2é PB³'é!Æ< Â<ûH2Ð6@ŠÕ䓯RâY8�è·oµ�¡]ZÜûBˆ~ÞGP¯Eþý¥Lo•‰ÅnaȦü¡K©lÁ‰¦Luâ°f�æ=ûų]]4zjÙ#̾¿Ô¹õA‰z]G®Ö”›q¸qØŸFà�„ꨳTaX£ +ee8€Ã@ÒQo�c @0 ÄÓéPÒ®<€A¤&¡œBÌÄ Ð­˜UÓ–C ûWMëØÜœ|±àR¨¦§5XM¡øfY²å™„Öec„'ê(ôL™Ì³Î1}ä­:BÕ¬“ðù6˜¨MKÞjØe´i6í¼Çªß¿î*›vÂólÎkM6aõ¶£›& «�IÞ€j›ÐŽÿ$´¬¨MRïÖ¦ÐÝÕ¦…þUxù»Sxáo15oÃÛÿNî§Žóä’yøÅt,ÌŠ@n7.Kx=Ùº}DØÙªÚœ$Û/« ÞÔñ˜˜`.üW.ø Ð1ËJæ›"ùÒÿ¯\�)VØé<ß§ä›þÁ×UØt’Õz�vóšºuòºà"f‘ò«”îH„KŠÁ£‚ÑRÌŸé#ý!„yçHöúwüHXúû†äÏæÍáe9‹ÐÇ;¶Àd~q�õ½Ü1ŽOêU2èOä|_YÞJSæ‹ûñ”=:íêë!{yÉí¾­³[› cÃ\¬#~šwÓ±œO_á÷Ù^O.sØkç{X*. àbÄ5¼çóU þB?Y…àÒÚ;vÕœ+¼•×<«=Ýz{šðÃ…›•vg©ÀüRêïaì;Ò�ï4Ê%z|yžíúNÂq–ÄÜ +¶5ˆE}·`ƒî¬×ªŸ•œû8ãa·Èþ¬Ë)¨¶æ|…çÔTØë^<|Âes<Ì1ü¨�Ð�*À[_çý~`Æp³ Ñaöù/GäžÌµ7âËxzƒc�œdpaæMHæJøD%ü¸Ïü¬OâÎܲ Ä£e–Oÿð,Ý’‚kU[TÎ~ÖG×n+~r2¹ù=œêÞ}ßq^绯ñ÷ éŽ)ñŽŽ‘ÆÒv¾æÏÏ�Éü¨gsx†OöÂ= 2“3yîãú¯> bÐJštæÏªgaë–ÆÜ +©1ùÍÁŠý}v5ÚuÈý³rz~ügü¬2üÔ³f øYóLÃ=÷GatÿsèÏz“›‚oºã/Ãxa§ü{å~¯ÂÃî»é (š„9êáo¥”Ä?ëÅïÀ5ÍÀà\÷³¶éÉúÿÛç>VÀoÛ€Q¯æ¼XŽ£zìš#íùgm?³-äÛÅq-Ö#~àóóõjBçž×à�‚8 m`<ŠÝ/~°�Yª Ãàèt èë�ìŸ|>®ù †¯kÝšåQÑÇóƒáq3ìk�‹`Ë‘·ÆƒùûÏzœ5ÓçÖÓ{ì,þ¬ïp‹¶ß!MŽöàОYˆ~™áÒB+🵮{?ã¿DuÇßäü¬¸Nì[e5Ïãæ×±¿qÕ«Lƒ+K&É>÷³ +ÜÜÊÇ`ÛYƒýpðK²ê¼�}øY²7Âc:œ’Ý'ÊÜ«OKðιŒû_lH hžâÖãã ûåᕇ»QÂÏ*èU#bVå¼æÌ‡LˆyL9[’´ŸÁ87¿Îþ¯ÀÖ:œÄÙ§!ž{ОNo?3õà˜Ï9Ípy?žë-°åÅãpùŸYHrÚÚ™Z`;޵²hsbÈk§¾­ì t]ûy¿ØvŠ—@�ÔOi|0AÊg<–™àa‰û™ð¹ÃÔ"l”´ëÒUž{•-{C="Ö–€�P.Iõ[„†¿Šàд„˜[XLŽA(¨_HóÛ§:[Ë^û×¶>�C°¢;�· +÷ ÉïÑ ¾Ó–Wcw¤ß>,ô/§é�Kþ/†‡ùþ$-3ÿ& /<.Ÿw ü»?Føº@ÎZ"–Iwä�àæªýr€zvÞB’u 3’íë§ÕÃ�‰¥Äq˜�èæJÒÕ„v¼ÅE³U�K ™Ú�õÓkÑÐ>û:G4¡t§"Þ¯ ¼ Áò›†…îpíûð~w?zSHšRî-¦°®'ßµøú¾u È’X#&ýÄ�&ÿߎ>a)î¦$c ´’Ó“œWL…sëIóÞ }Ùh±›“^DZ9OÊ r­ÞŒÚtOåÒë\åÎ9ÑœmݪÛZÿ%[51ó›£þ<ïÍTªg_³ÿɹV·Ì»O»šw(®{Œ½ |” †In ¢ìr¼U,O€|ÿé6]­£õ� ZíÌj +¥k¯ž‰³ÈÃäžÿÿÿç·#Íd7]Óaå—ÄT®ÁÓº˜–MëókîùM¬)ŸmÁÔ‘xsŠKힿÆt¬ßÔ³n.%ŽÇŸ*f™ r&h,fÆä³Úkî´âßÊmûïßUùõ½òȵva›ÉæësŒ;A¢ûj¨Wels¿›‹쑸§ •oö´!>BàÝj[ŽÌ#¤Ý*ï«�œÑþjdöÉ3kê&Ï–0¬éµéX�ØÛlh¨=lÔÚtëLî°Yz,«Ž~”Y·ÖÇL}Á3žÆåP,ñBÝ5˜·œf”¢¯pÇRÛ~£ˆúLb=sy:üóä9�³ûúw}“kHú¶ã½µ: <¯Óxïž×62~~<Na9¥daåã[ä· 0MºX•ø;ïs¢é¶Ëü™>ü½;ïÜõ ¿šp¬\ÿí‘¿“æFè/èöu¹Ûô�Öãaç‹ýÑ"·=1û?�–™,üsh²'àåÆu,Þ%9Çtþ3úÙ¤žÚ¨ÈtŽ$iäAƒPø).þ C‡‹ŽóŠêC¾»Û¸“ ?ñUf†Ý¾eýŸúô3~ÏOÝ(…£?:9UT_UÓƒ(°bŒ!¿iµïÓ'ü™w8lÔø¿¦Ã9h‰w¥ÃŒÏÚCŽW0Ì×ú=ê7ÅЮ°ÍìÑÎ)±¹&Ä樎­ 6û¼?šü´ÇãjÊjûúœ8Í}£f5{|É ¸�œ½a [ÜBÀ­Œó8®(4T=ïøè¨µ‡Ôö9px}Í·õÉÍÉáu8Û×^.Ÿ�,÷¦a[úLp‚ ?³Góýn»:î+â”nýc“=ž­Ò�’ŽCßbÁÂ+�ó÷*ý?êÄ×UŸY—…{ÒEŸß! \{ÎaïÅR|Êg*é¢ã¿ 9dkÚ/'�É.KzÉ™7,žÍü@æž³aAYÛ;Ž;¦z‡Ñâz¸8Aâz(£8꺽]ÄD¾ÿ˜¢ûe^º¸Ý¸d$�n¶GDMçm˜txO¢Sbäœ:ƒ·ùugÌ)ãí0:ž¨­ÌEí‚£F=Æ4JÑj$Sç6°Ò éZb`üWÿß›æÿ~Ú è¨»–˜È(šÁ=•Ž>Ðð¶1à¸;“´"ai¦VþSbw¢Ì¾…(N¸ ˜öá +ö¹ç÷ϰç‰%7�Èû)&6.©Û$é%t;r‰¹*8ì°ÑæÀi£"›ˆ|8]»ÇÃÞ‹�ÍXe‹¢Iòn5#´¬,�*±O¬›*ÓâˆtJˆ¡((„þó¾mAm[ð¨ÃüÔ|ä�jmÇ.�=ˆœ#PѬ}Ñ@ò€BôxŠ‘þ‰aôÀ¹¸h¾‡ÛÑ‘)Ý‚Ið¼™S·•\ÏËî~ntÝÈsE°h¹ø¦+¯º"Îj…4À�ƒFÕ”¢‰pP/îý¸¨Þa¡×f¿Y§ø­øôÁܹÀéˆAV™W¥¢ —¿üß”±¨wºáo¿54ã@=’yž?VFqœ!+ÍÖÅïWö×JôÝDã̳CsØ‹Ïl*±še®ZŽjÆ.6(ÈK:²`1Û µí–û”Ä`qÉÙm�ŠÔ|úâ¬ï�/?úè{&�F—7-þ¤áI2]vX™Ê£ÈlÏ…;Üç’ È3©¿•�q¦�ËN&6ƒ…ð¬9&<£ÜçÚ¦e"Èñ/ Yn‚›Ž +ĉK@ïÅnêX]Å·Ù`tvP›ª‡qÕ ¨Jžl‘=•ÒÕ- O­ëf™í2ö§€.Þ*ä"¸;!¨è +Ú Kà?©ý†T•ªqŒpoÄ8þpœ‘fû�t–F¦êE !3ƒ 8'ŽXÈgáú`g_QMë;2ã¼}¢à˜šè²À5_=¢³'AfÔ‚ˆ�¸‰À4¼T¥©:é­¦èÿlãz¯¼Bš[-ú˜—A�.g+H)ÐO´^šðq|Óô‰[µÅ`óQ½Ÿ}àÏáæ]ĉ1}3¢fUlX—V?þâÚÝ }gT¼™>#HœÈŠ�ÝÁ Bí$!€&‚%/Á H¨Qe{3ò—LI†Ì�×ó$¯”A¸¥íFî0¶‚ó/§´¶-csíO€®�œäýâÊ·anw—/é»ò?ø›4è dÂ@R,2§_÷Ø$Å+(’(k&ÓRø�`…ІÄߟçñçyžú<Ïó<Õ=nÀ½WdaFYWôUUqîXU‹¿8°êR©ƒ‡ä¹ÓݘnU9“ V¾+îáQ±X“Õq¹¬™9×s r2ŸàƒTø hHœ$ÂTÎE«nåžÑLß�xªÌü»$×�8.”5ùç$®l¸PÖ$äœÿoŒ‡seHæPý±Ëä„9‹·¬ÉÃk˜ô8‹#%gªp€,kЬLF®ÀŠt­¾tçÝ+�@0ØÀÿÛ½%K„g2ÒÞ¹~î3y`˜Ž,>v1Qde2äñ3™è&¼ … B*„ƒ >Þy»KŽLšJtoL+ë’À/gÊž{ÁÜË-ÞRI�ÔÁMÜéÎŒ’ ²¾f;¿U0ÄÁÎM¹“¶�]ŠÕ�P¨ËŠHhH&ºÐe=wf�¸` îySŒƒÂöù¨œÕ:|×(:)ÛØ“:†ïÔv¿k vžM'œŽÝ:noŒÖ4Uvkªãù¨uÓÊöW]­Ó�Ť5mb›6iwM?êÚdZÇ“J9_åH§ôWã›®¡ØÆnù&»´Ö>Û,Ü‚»½e0H ¬`Àƒ\aÇ)P€`Ѐ + ø€@(ZäÂ0’厀¤+ÃRIÒ´a)Z•–Úç‘¡µ$°Ëºd( )˸SÅ©€Þ&îø=>}–­tì­©ÏB #�Ž%mÇݾ)iœðÍúl‹Z3©ó=[jß;®Õé|?'íÝk¶Ž#ŒÖãkž2Œ®=þ ¿·õÅøÜñ£\%�› «WøšÎg9J¯ýà¼ÓsIOÔžÎé“íqØ_ŸuÓã|յǣcû,ÏHã|•ò¯B×(¯S> å‹Ð­÷;îînZÛt�Ó—ïø)þ¦”å«qRÇRVÇÿŽN˜r»k×ÎpJQ›°ü)ŸeÙnnwü–å³Ð5 ·cwך6aZ›¾:aw–o6LÛ„é?�ÓW¡s¿5»;–Ý#Tâ@,0 bT¸3„\#ϦMxºÖ8ëα¥ì;×v~Jñt¶ß:pOøßµ†g›´¦MøŸç;þ~~_kÜµŽºj­ãù($P‘‚(bx’Ú('|ÔzkØcÿ‹V÷íhó-jMW[ŸÇÿ~îÞµ¦>gÙ®5lß?Jè˜RÛݳëó‡Þ®°‰îBèï¿QðIÇé‹Ð[@ +(BZˆ%°çF×1ÝŒ$B6än l”G×FpئPþœ ¥œ³ÝòW·ÝÒ-}Ý0†OkO÷®_ý«}ÔRk3­ll3©‡N¨ÃZ®c ÉC@pH%CI;ÞÀ@†Q@ †A0 €€H @Q€1 G”ºGô>(îó:�ƒôtm('ÀÄ¢W6s<1Têz;îœrÒeù¾Ê-ÞrÈôl ©vE»lAÎ��\àîÊ‹Ç_±°|›@?Dó²ÍŠÊNL⢠#ÍL)�øÜtM¦•àV4ù.…ƒ¿8wdhÙ�m�`h€‘Zå’_kÀ›Í¤ +jÂL3S„E®�Ü?T«d¸lî/–&bÀ¦UTHx¦ßbö‰¡+£ºèëyT>ôýˆ¾1c$ü! 4…,WºÌ 5ÏDæd¯�aÈi¼¦Þ2FALº„€|–ß�Pí Ý»´2æ.lŸ8á`NœËªÑš#~ö^„ù¡ºöö¬òa [/ˆ{Œ3eýmt�%,gDn+ŸÿF�\mà´*Q?}Š™‹ÔOa’{©JJ ¨£›ÔA˘-Á�…|¾Žåbˆu?7Œ¼oNoò›190<ÉéïÛoSVH“\V(ØzyWHÇ•nbòM|N�ºà"_ã«M:bº‹¢s "B}¿½sùý‹®²œD#�åÞ"ÄLÏMõº tQèyQE;jnà]‘ào^IKo¦ÌÈŽ­®#Ô#³HiŒ¦A¬ÛΉé þGϤ†ï893Ê¡09‘k>üß ®Ñ7ÖòMŠ´Ù¢Ãs:ç߸ëˆÞ²;Yù~‡•)1Î †˜Û¿õüC®±|(ˆ�%æ×™ˆ?Øÿ•ÂÇ ,�  +´Aãd³"y<¯I6q¥ñ»ÓcúREÒ»ÐÊFx§û¬&”J°Þò“,µ�åQD;òÖØ Љ!0 ü•Ìüî$îˆÁ÷¡dJžfs~’²hú4cóáì–§e„bíú�T½¹+ìÓ6Àâ‘:•Û$!#î1ˆõ«Í³,/뇬Ìü2…­§¶yàW6n“rtG¤;=€�úM;[ª°Š˜žßb¿L]\’šŸ¿ƒæÙ%›(¯œ’Ñf‡aMá +£½ù´ámK5ÙìAF—÷é¨kf<äñ-7�0&òÕyùGìêpqéC?Àá04å"†`Ñ€×'·~»ü,ýªŽ T_åÁ[Höâ/ÛÜé·k² ާûRú(†yTá-ÝÛ dåDn�2²¡P|yBJÀ€n•ŠÀa¥”ÓÖéq¾7w5p7±ÃÑ„DYôTË÷´-U½3�¾]J‘@-Þ›kƱGšÌ?gà¾UWzw„Çå:óò2Ëœ¢©¡ò®Õ”/Â>,ÿpŠD�d¼v  Z³òÒÖùÉh~GôÄÐL²¥=¼» ïzÑ6gèÌû"K¦àOÉLšÎ„F» z…þëx¡ážØ�wÑIÄçìHÚ¯…ã\ÎÈ'Ÿ@ui�ž¨6¯EG‡HE´©eG‡÷îPLl÷2´Üol¾¦®3”}�vÈ$J-Š6Þ©ÈÏ}¦¦M!%±èÆdQ@øŠÏEH ÖÁÀ¿Á<³üº»ÎI@õ\˜fm­ÃÝ�µ ¿0ɧ4†ÞC1õ1¬ÜÏ$€Úð6 qûßÕŸÆYJ–ÏB4¸Æ·¹áò{ xÌLKôßgñ˜ö;ÜÇùÖêQUá¾={Žì)‘ ëHGOoÇÇs¬‘ôP¨¬Ð¬¢^!ѱ{T "7–Ñõ¡&Q\±Þ»& äÉÏ?ì>U”#\ªEJ²$þ]¡–çëyhd+8å©n°ul¥x~pHZ" KØ TWôU¨Lt½èå6¥0xÑ¡Ìo#_v$t­ïÑÖw:`´dÿN�¥·rG ’„PZX†Å9EH(ŸŽçoCÊšt;ۆýiŸÅø)Ñ_�ô%�oX‰ã̹ý` ÀŒn\Å•®Ày11�N¤ù =%ëN fk WœŒ²OÙ)ŒZs»Ì)�Û´-lOïåjòÙÅ=S´I/m6Œœš´6Øì]Ä3‘]÷|ø”¯óRm’—¸C} °O!£WKah³õøÊG)„z�(_Þ‰Z'aÛ7{<ÓÁ’ï_ÙdмL–g�¤ŒìÒæß#|þ®…× O�`:SHb +éuÄsGÇéîNÚà9 °+Žëaœ¹MaºSÐâ$Ë…·ÁH2ôP”P (<= §¸Ö^‡2}Rm/¡;­7~†.(Ôéª}ÖÅÙɶvÒé”Ï'—ø/ÊØ�™UÜÆ€×x}-æ¸u.~Û¬Ñês£Q€h—+"fŽÅ¸¶gÈi¶Ø+¤‹¥*W¥�ŽY`ŠŠDû`-|üÓ*2°Óx‚0¨¤Ð,VÙ)#kÉ;í}â¿ìÓ�ƒÆþž²�´Lô4˜›N‰¿Ì涉‹BöŒŸO,� K%þ�ØÆ“®Ò²¬p<€†ë%6ƒü§Ñªº¿ÝÔ²¬;‘ñ0¿ã3�öSJ!,™8)†oë.äJåÅC$w-$Â$,žx…LÔ3àg£)�¶?;1Lv¥Šx¶3›n‰KÆÁ–†þëÎ¥¨ wÀ˚Á»0qZZ*XPZ––b«†aP‡.8_,jÍE-ljnáØSs^„H.ýècÞ€XøTO'Ÿ Õvsù×A¿>Ð/}5Ø ñ+L„eu“g·àãig1Ħ誌wu–ñAÍR¹ŒcÇôùkúXöF\s_bþÕõº}aº3–`;¢±öÿ2”Øy›VòpË4]¯)Ã*_¯hhÒñÁ’å…0Å´«¦JÞˆpl%7›!_¢ˆÊíjïÞYG!ƒm¹<1©ï%}ȤRQùZŠÒ¢Î0?9â˰àÊ¢%c¼»¸Hî'U9ÛêË@?Yúħç\½ «Q“XzÕE‡ÎhSÆ2‘¤Ã„D¶Wµ™…V‚—Ó*XÃ5QeŽgX=ä¡KüÃÂyU—1fB ÒÕô3¤r¨N§ÃR (fùF÷£@g£I†ó¸Z¹2vàpàÁŸP�G:b¡¹xeäËà\#°BËÁ²»¡}Ïñ1ðw.ðÂy8ŒÞÉÅ 5¶67ÒF/àûWÜÀú§b¡ æB÷IC ´Ç1“Àƒ¾äÀ“LáG ø=ê�ÿíZ šÌT{‘,žØ¨~6Zô!s–I”L ªúª®+Úï|4Þ\õS¨Tßô�#=à £xvsI9z%¡�‰+À„6:·õŽ0V?ëp6Ý{§­ä™Á‡£û6 ¹ª7‘ØuUþ ×ò FÀoÅMàè®LûvvŠi/,ðº^,òª”¹wÞ Äµà¬-C™? pgŠ…jçí–_‚Q¤+°âÄКÚý¤F\œ¹VaQÇ0&L¾ƒ œÆÉ@ 6Sð.€¸3èL�Ü  ãÂàY%£ƒ4&ô‹Q³D�3 +kò–ZˆŒ;J¯SEÊGúã¼­O:-ïÃ×¼½IÃÕ›ª1³]ù\o"/S0(Sœ¾R&ú8ïÌb^&Èv;�ÛÃíLÊø¦ÙÌèŦy'·jèO\Ýüédl.Óå‹8ìŽõ—@ª*µ6{žÖUÑ +ÿ��‹Ê±yD^vÞåB±Cq¶Žàš¬ÞŠª/±º\Ë'ÇZ:„±álPýHÀÒõ·%—ø7ê¢_*2Šèô‹!ypã 4Ù ìRÌþ%;s m£[Î'—,èÕ=Õ­y«˜×aQ’ÕȦ£7]Öõ-ü¥TªG‡Q¯šZçÿiNpZ™v÷K5C…êœy0Fò«Û' �W4Œ©‰ =£Y¾ž%æ(–¾¿8‡-™ê<¾œb&£€™²â0°t\Ï�ð ¶•Fÿ^*€ÿVXYvšiaçAj˜Û2ƒàËõ‰Ñ•GR¦ß ‹F1˜õ(v°‰¬—a@¿C3Û‰“_¨äÃôˆïxÁ3UQq»¸áw¶�&“¸í4y±ù.7BÀ%°ê!ñ%rk¨;¨“Y_?Ö+æ¸0çEðôõ¤Hâñ†P!sŸôÃÇ[棷BúÉ LQ…¦hƒú±uŽ ÛÑÜJD çâv!úÅá=IºW"Mð0/–ϘídÏé=>1¬¥ñ_µìCÊ”\Œ-ÊÓ +£ù‚W¥9¥ñeBùIo 3ÝPwp(Ó�˜±Ñˆ2;i²mQc 5� EüŠ£�ÒÏÇ­ØføQ‹�¢(÷¯„zKž9o\º¸ûMèÖƒËN¦X^EíV¸yQZ�L3_lŠ·WÁÍS¨•¬�ôè”Ó?4_ CÁ“èˆ^GHº£UªoÈÆ… C=KSIYì»pÎëPäpÞ•Ä}é"Sžã¢»%¢8t�|•«Åtð‹P —Ù>nNŽÃ †XÉî Óî ˆØºzp/{®ãZkm4 }e–¹!Æx–…�3ˆªk�LÇba_Ÿ(öXág$;WzÁ—wŽ´®º–ý) +éJæ\ð:�á¸b°yÈTÒ99”ñHL'Ù·­¹n–´z¯N×ìÊ-.ÆÄAŽ^5ãšPq‘Ib 'N­ ÝL‰š‹»‹°E¡d\fy; ›’A!vP1‘&gZ.Óÿ°gÉëu;V`0ör—î8ÝŠ„á#r­öv¯$`$à]É2,rtÜF�ñÊ™ð…¨ÁÞÒ<EФ:;` -µõ\}KcçñK%‹ì’O8¹YÜ�ÅéÞÜù t ý›Q‘ehÂbÚ9°��EÀÌ€-ÖòúF6¡°hÏà__:Z³|<ÀRÈ�üþÅ"׌Z‰Ï°À¨©µ9ðƒï ¨¤°‰s ÇpÏ å,åA™Ò­Nã¶wTC� hdô5— ‚ aÞ/÷9I|Þ«U/É2Ožôì.áV,º0MEâß}ÒáŒ4cƒß€Ïi ó3¥øBR’H³–Û!²SÀše:rpYÜ ×J8礘ÆVN%Ø‘,t{rÉóÿ³ƒ©/qF*Ù\d*)›'‘YÔ7ˆµ Ð jvj2ìxS¶N…®µ€;Ù(#C“ÑÛ“Œ¡é†8�î·ÕÔÙ*jézH©aš£¿.à.‚7†V­^¢•ëï'?:sߘZ@$Ò­öÕ|¶Ll`èˆÊÆîdp°«Ú ˜µí×Ü© ¢›&³¶Ò.º-¾S/EÖ«(ù1“¦ ¯�‡È‘€ßAM�™%¬´€esÛCóâ«.rÝ0cL+¸Д镄ÊΊZ2±Íqwríj–(ôwT“™9`Ò* º¼Ý]ÒEÞìÂhÄ£ÛŒ +¯§ÃèÆy ±‚Õ$¤ªÕ`« ½Ö'2wd‚Q ÉcÈ¿n}Ï +Ûµ¾·@¡Þ¬œkŸY8°0.ä:ï­µÚi1]F<°€€XÀ0Ìj1]†Fg¦Su‚3g¬…1¶¿ªWl_ùþ +oü+mmþU¾¿²ù®tþÕß_uðÿ +ç_mŒ?ÿ¯®Æø®êþ•ý_i|Wÿjã�‘¹˜+wÛ¸úWÖÖ_Yû+�«ÅtàÌtÿ*o]…ï¯2¾+»õõWßÕ¼³C»Ý6ff_ãÅŒЦfŒÌ�¡Ù]Ød%9šŠg‹g¦×ÎŒ»­�¼ßÌ7×�ŸbÌé_®¹Ý{ZÞ¹þ…êDàÔϵýZ÷¶ýŠ8ÈAÁ©§ž|vŒ«¥ÛÒ=9ïF³v¨N4õì³÷Ú§îD³ÏvpöÝÁy78uW›]³'Èà|à� "ðÀ _ó¦ÙÞ™ñkº]ûòß¶~Ws}ÕZSû¼sa½A¢žož©¥Õ‚ÏmW»ô‚“FQl»Õìjub®3µ�ëêï½wªÿAl±Å¿®T÷§ù‚ú‚VƒÝ‚û­Feúéþùý¿YÊ+x©�¸ckëå™Ú‰­­¶Zð C +LÀÀ‚dà(‘¨†¡P¢Šb}(Ö‡B±>ÖסXŠõ±>Ö'â¼²>ÍÜ͵®wöŸ"SkT'Bu¢NÔ‰P"”…²Ûn�Ú{ÓÞißÕ‰î}Zm‡ªÖZkuïP�(c�9Õû+Ýjw"mÿ)ç¼Cu"‹Q•âN”³î—f~cZëÛ¯=Jƒù-~écÌû¥–[jyÞ¶R‹wíP�ç�sÕߌû¥˜bÐÒb®Qœƒ�hkºk¼Ñ·ï}µ¶ôQUÔ+ï¶þoöŽu~ËûÍ·rÜ9®´“¬Ä +ÖKaÉÖ…lÞÊhž@ÖWb}¬�õ±>Ö× +±¾’™ÓØù¬ŽÃÉh"Z+$e£:³ÉP/±El§ºù`}32LÍ*TÈ•fg}¬�õ A !|µ,^g½óïCX_ áhb}¬¯ó|°¾ÎaÎÈ0Õ)u®�î¹~¯¶ÿÝŸmÖšÖ­ñÞÿØÖ½çãþ�í~LùÆ{W¾óóz­Íš¿µzÓ]·®»^»÷Üs�÷ãª1ÕÛöþ¶ë|)Çckõo»ñ÷\ÿ¥Ù^m{Í»Þz÷æÚ~Çõv{7ÏYó͵Î_1ÏÏ-Þú³¥Xïý¯oÅßרâÞ)¯qÔµàÓkmW2«¦MÀPƒdxü4sÝŸõ±>žóß«·½µCÙ]9µ¶CuŠÁš¥zæïÂ�É{å×ͳ͹æª;­SÛXëc}¬�õ±>ÖÇúXëc}¬�õ±>ÖÇúXëc}¬�õ±>Ö'êóvû=×ü3gl{ÅSÿι>ýN„íįé_¼à¶ ßàÄ`'zœ/ÝŸé�X×JwçÊvf}±¶�«^�nÛÓû÷ëíP¶s­;îûR›7Åà¼WãÞiƒ™b};Î9Sü÷ùÛçö;Wµ8_Ê;TþM­¹9ÍÿàìÝ•ñßÏ®û ½vüÜjÚi~ðñíÛliµÚ‚]í; ,@jP� X€Øàç¶zsÎóƒµ^iÅ÷V|ëÅ÷V|EµÚµfšÿÕ·ƒóƒOq‡¢Õ~sÅúñóœ5½ö;ÑÌÞgþ· ¸Ð`H.×!l7çv[p^›wµ×ÚZø1«¥÷ßv{õw|5î{o~¿sZñÎ÷æŒsÆ£æÍ]­âZÿëæõ¿bŽÁ¹yýïjwßz¯µ·ÖŠk­÷Z{kÝà¬÷Z{uµúæ{s¾ûfjÁ×OüSƒšëPÝXƒ“ƒwm/8-8qÖUߌqƺë�­œ»ë=1·œœYç5385ÎÜ¥&ÖzÏ=õÞjjpj n®k¦Wó¾7ÞçÌk‹ñ¿½kÌwÆ;c´àX`á¸P Ø>¹µšk®¹æ”ïn„‰µ¦•D�(šñÌtïÊóµ½Ó +úÐTó~¿Þׯ+­sWœóÕÕ¾í<×Þ¿×.cVƒ €a‚ó°�ƒXXA.$à¹ã~éÆóyß4§&îoAL'²Ú>Ý—^ûÜRÞ‰æÎõZ{¹¥üíÍœVû¶½/8ííD¼vÚLßÞÎ+í�è¾¥xÞ[ñ¥ØRüó+ˆ+ïÔ‚�ëŽïƒ3cpò>ÅZkL/8s¯ÝÒmW»¥NduþM9h¿>}pâ‰óÞ˜f°ÍmÿŸîI­¦Ó×ú9½�ÈÒ<ûžVS<ëϺÒmk½—v;qÎ�;ÑÔ|Ú©¶·Óý5gª»ZßÜÒ¼»œfŸ¶› „™¶ã`YÖ×ÁPØÒ‹âtOü ýi7ÈY�õ±>ÖÇúXÈúj¬�õu¹ÜëcÖY;ŽÖÑnÖZÓ}-8÷Ók-º-} ^�i·ô‚sãz÷cº§½¹kú`G›¼OýØZzA»­Å™êïTƒß»5ý‰µåšî‰+Æ6[Ë©µVßÜéÛlç­9ÌC"p'·³ê‰CøïƒÓòìšÕ‚ Þš&B�ØîÌ58ÿЬµìD�?Ïöv£YE|Ú÷ÌÓÖ‹âÎÞ;­vþÿ‚v(þüëå6w´i1þLíÜ;ß‚(¼ïÛ�©µ(°«¡¶ÕµÉwF=ªg\¯¾\w£YE@‰~r ’9}‚ª�|ëNí±ŸjpîKñ[þNt78¹­·V©ýšõ°@.p;_ßk¿«ÁÞVX‡¢Í··CÍ®6ÿ¯ý›©½Vk¬58«õ4ñu«½p¸Q´‰²ñF_£ë7­$Gœq8œŒ£¯Ñ…Ë‘GÂÛ\.’¾F—ÍR .[Ž´‰¥¬lÝL0ãΕ»F1VÞn0›L, q”_# v{‰"­Egµܬ„šËÒš G‘N3dÊ 1bi“Ñš«F{ÑÒkåHZÚ`¸[IG®g‘F»¹H`¡-È€‚XÐÁ 0t$ ‚p‚ �–è1_8Ü‹ÒJÒº( iT, k2:âp�Ž¾Ø¨¡ŽŽ†Š4í´ÉæÍ6û ”!š8MtÍ·'�H-'{‰© Êh )+m yuæƒXb c¢GÕråhk9‹’ÑB¤µBÌ|°ö�,ÇÝmÎÿ·n~-Ö¶ZtJ—lTŠ$ šÈÁÐ æ&+à ²´ÝJ¥H¶r–¶¦à¸o²qœ$ˆ4\íæš8ÍUÚd#nE¸áFYéæ5H_¶Sî{Ú­q·�¾i4Q+‘i{y Q¥†h iª›,FÊlaG Å\²˜)ޏÚM$Òd°Û¨z‰­IV†¸ÚMT©È1T�@3²–$ˆåm2Z™»Uš(‚ˆš%”2Z˜Ã˜%6Y?�J -W:�f´Rl1¶[Ùx›xMÝÜMD£‰¢&¢,ï<—0e_ÿx»ÑJ›g QbI)‡%Æ|Ún¹«Ä&A”up˜ˆ]a _„L[ï¿¥K6i­pC¬…´ÐuC‘£Ó(–¶“ë6*à š¨�™%LD•2ë%M– e´pÊJ[›Úž@©ñF»‰ÊNƒõöùkpò׬Ïv“•2ò¦Ê¸mÐÄŒ}3@ªé\ÐA0`X_ji¹Œyuå%-ÂĈ<…âÂÝFLDÑr81ƒ¶n4SÆÝ6:ÊX‰,ã%Š´bI˜+±…¨Zæpeîbö¨Þ#ÅÔì'Ð,Gqâr¥¨1Eð (èA(À n„ ëë8•–á+,ÅÚ0òeËÝB¶„‰¨Ú­,o­º¹ÅTkü$�ð%¸d4ÒŽ#m)j”¢FX†#‘†«…¤ƒ¶v+ÉœK‡V(³¥¨1†"XYËu£aXÉúÈ1�EÚ,˜Rãò«KMÖ +KÙ‹4KÄ�)Žªií âôe}7W�Êp¯Íún8’”Ñ‘œ/ÙX2KpÙÄ1Ä‘¶p,g?�^6‘ÖšbÒn¤LFÎQÄ…¸Ù[ÓÞœõü9_cxk•c8û‰?þ\2ËÜmæºÙf¯i;¬¯ã?�>Ìg4L¬’”¡Bª·�Û|wÇÏqƶnÝ{Î;g�íî¶ëúûíœ×šýwµToŽmÝÙr[íÍy×·ö7þïU÷ü9뻹½™ëǯŸß|ëû÷f½µt€!&dè€N˜-Ñ3-~Oh>Æï ÍZï÷Në|k¿v^ã«׫­ ™&®Ïiæ·ö¬ïoËÿVË·µwg›-¶ù~ß}Û½-{ßžŸÿ~«ïÍý­~‹ïÍún}óýû›ï}i­öÚçÝjüö­'ó_íÆÕj®y®ù{}Ì¿Z�mݽv®÷Þ½â­÷ö„æÞÓÜ[߯œß›-¾6ç~µÍÕÚ}oçuk¼÷_}õ¾;{BÓfOÆšúßVýUg}÷ÛÚ7í¼f\sϵòmkåÕ~ÕsOhÖÕ´32¼`0Óv.U‡›".U—€\˜€.H 'Ìïb¡àên+­ó¬·æ˜oüo7®úù[í1MÝÿZŽ¿c~iÿ�wÝ:óÏ¿5ÏÖ>­ûöº¿òšíÆüþ?Ö¶öÌ-§UóËsö˜f½:k½yµµîÎ{Ý;ß�sýÞxc¬/ï¼ßjŸ[�ijm±î{[~ù×Ê5þM+×¼n~{Õ™ïŒí¿Õ¼ë¯|÷¬/¯šó¾/Öü9ÎõòמдÛcš—Çúï_l¿îloו_\»¾�{B³w�if{û߬_cÛyÕ8cžñµúµ¶ÖšøZ�iÞl9Î{sü¹o«1Çzÿæš_Þû~M묷ﮱ¾x÷½ëÆûyÏ6ÛKëÌÖZÍí}½mÝoÿÖÉùç½õÝ÷³¾ü;­öï®ý-Ïœb�7·xïÛ7®\÷ËëÍ»Úýö»'4«Ç4yίi�›c\oµ¸ÖŒëí{g�3Þ½r[ñÆöêÎ1¶Ûölo®”÷ü�_Û{õÅÙzB3c�i~µ”㛯ÝÛ>߸ö­mżîÍ¿ïçÿ®ÕzB³~¯YWŒ­Õ•¿¶X÷ý¯sÎüyÞõÚÚyïc�ijœñ¶ôùåyó­±åºê~»æßúý÷ï~y½˜së Íkõ¿'4í¶ž ÌÎÖš]ëÝóçÞ5Öx_Ë-¿öj»¯¶ßmsþç»jloµ6ãl{¾;gOhâŠ+æu¿þz«æoq­µïº9ïúõîûfÛ5Ç7klkç]cûß®ŸÛ¿ç\oÍ·^«q½Ù>ÇÛš–[�iî|?æ¹îÿ×ûwç9÷Ý/çÛfm·îÖcš[¼éÅÙV‹oþýÿ~ï½?ßü滳þŒ[þŸuµü¹½™gËqÝ{ãÇœ÷ŽñßûÓü·´Î‹;­³VÛmݸ[œëÖ|?®ýö¬yÏžÐÔÛf^uíôZl/¯õùí[g®+®ü~Å´jží­×š[Üÿßâ}qÖ�oþÿ—ï›éÝs›ûß[»Ç4-æ<×ßv[kuÖ�÷ýúx?ß´Î×X_Ohò÷˜æ¾ïé¿;¯ørËëßÿºuý×øj]3ö„f¿Ó¼ÝzpÿªqÅü­½µZ›¹½Úrþ�ó^µ~½¿âºëeÀ .ì­/Í7ó¬õg»¯(�!W[5î־Ɵï¶wg|ñ÷ x ökñk¼·¥<×ßßÊ-ÇÙ:xœñÛËmÎüZmœ�¯}ZñkÝ»þûÕŠ fÈ”�ÁtáGèRu]…�–jÖY;±,EZ¨zÙH¬~}ØfKÿwžzS2ë�Á„dðANÈÿ¯ùëK+WÚLj2Z­$a·Ï—VPë_éý«]u¬ U³âç{ïlkå÷¹­¶Þÿl÷ÖÙæLkíwßÌñÊF$)Ú.È—Mĉ£¾!Š +Cš˜!ÒJl Ì|˜ÓaÂÄ “Ö…©Ó-þJ« °�œ2@'¬€'üεÚϼ׌¹Îúî½ïþ¯uWýVW›_뺿îœw®yïªëî¸ë[ëý]/­¼Þ�sî½îÇüuæÿo/Ï•w˜kºó~üyg^yÖù/ßvß¿6ã»÷­ÏwÇ™?½ßï¦uê�i�–Þ‹ÿÞ�5ïóß½Óï8ïœïÞxs}+ïUãŽ;·œ_Z7¾¶k[ó®<㊳æ}Ú·ÖnËs¦µË0™vRL‹ÿóÆ5篸sýù«Î7w‹«}]µÍ¹v.@ Ô×…žåA�Œƒ*e ±ŠŠ#<dȦâ#vÄ(Db›Šø¡°ø\†b4u““ÈÂq2Éd@§OÅçTBÓÔ&>¤ØÇÄlT�&D½NŒ™Í‰)åúDL_·±ÈœL#Ì&OÆÁ3‘åE«Ä1-J=Öy(‘&—HM##�¼)£á!’ìcé�4R$¸(æ!2¢ô‚bDZ\ìÑ+÷Ñ0ê0µ`"вÔ}P]�}ÝÆ5âBSh$4V\E¨–Ãè!“Ä% /& ˜G‰¨äEÉB š‰Œx ܬö’ð>Œ†Äån�DÇtÑ‘è!nŒqJa„ +…»ˆ->3FXp2ÜçëvŠësÒTX|DZ#Ïg¬0q>7Sà< ,�+Zx2/ÍÇ#‰=$`'™!N®˜ +Bf"’€ÈL…ð¨aùp¡ðx= DFäe4z(™DøáF«hxøº‘gC怋‰ ¦ +…ƒG)98`€È4Žë" "I‡ˆ‘0:®Ãêª +ñûK\Tº‰D…Œ[<|(pUpÜÄ÷¸H�Ôz‘[s_{öŸŽýQ1bÚ_WzeúÖx¥Ù�~¢iZK³426´F'TÒ$–ëˆ�F£·†s’k èÊ™‹GþD"S¦l�žKÍl“ɆKb²DÄeƒæS6 ز!Mæ´“Ì×El|d™ +ïF’ñQ|d^3ªÊ�£S†’#™ +µ3ª�¨“q‰¡K†R*1º†hŽâ…q…«Æ¢aÛÀ|F›æã¡D”ÜăqÐ]c>:Œb<Ïç‚ùº‰Yya�PµËDÃ.©Xnä‚ÃÈ<.Ÿ•êòÒ¸8]ð­"tY=`<\¨H¾|tDðz�–‹GÌY¨ÇÈf Éb‰Ëjhi™0(X<ˆÅ6ûHY*:´Éòu�LÂbU–ÊÆ\ÍB-¯Ùł×g©¹`¸OEÂ2ù´Ìäõ�Ìh#ßGIù$èÖø2žŠÔÈ™> X }‹Ä·•ú³…ö[]r›eñaù¾Î“{ð>j*q 9’dÖ«HÁB*aƒª£³j09P�ÉÉhÈ›Tº ;5x¸ŠOà kÕj^n0©x¨ 1ÓȦ¡DĹ4À".( % Y‰‰2l•¯3©x“JM£D¬Œ¡*¬Pp]¤rÉT@* Çd£‚1VªŠgæ�ª”ªÆDå‚ÂbT¡`’!Q�=�@TȰÆ+›kÉrmeBk€�–,S‰E`K¥aÔ T4Ç¥¤|݉«p\¥F9á�Qþô£L|­Eay, +…ZQ +BÙè(9(6 Z§^”‹‰ŠB;‰œ(¸b¤DÑȈ‰(' £"¼|(+›Ãs±à +“LùºZÊ^ÊC˜ª’�)5B´¡p|Ä0K%d¡¤B¸ +%ž<ÊÄsJïÄÃuâ™èÅÍ;q¨yÕ2óÊðóPŸÌkÀ}¼<�ŒŽ–ÇÉ$ÞŠ†1âmŽ�•÷u1‹‚GâÜ><ŠI®Ããø¨N�4<¨…á�´Eåe6ë Q(VxÜÅÉ[á¾ OâDUòF ÉcUBDÞHãò6Ö&á•x:"¼ ŠÏÇÛ�÷u¥Ëõà�xÞ.uï¦$¸7²ìöF*íQ@X²§9r×k(+×7i= U­zYIÇË€-ê™�V ×1ÒÁñBŒ�G*4ÞMƒ”ñBhÏT.Þ×å �ÅóbûóZ›oð,FœŠç b¡xÏó¼ô<¯/É�è¡+T~Ô*žçy"¯Åó4ÝAã�|Xd<Šˆ&Cñ<Ï+)"Th¼¯c�ôP³ÏÆÓ0‰q¼Ý��ñ>´![*‚U²ò•¡Ïh8�|l8)LˆC¶F–id™>'+Ó)¤X�bAŠ)ödåáñáñaêŸ JhïÉÊ´2}6¢“ ¬þÉv�Õ¯Ã�àD+’Õ|V$ËñaÑi쌫�‘bçÖaú@ +/¬P¬#+׫ÀY*2›#âb8TÜÎ×QÜ“~s6‚¢†Á ÷RÔ2‡†KQÓä(lDéùºrt:™�0'“S†„‰(KH‘G˜ˆ ë#ô%vb¢äÉODùE”%–sê³N3ñ%œÔ¦SïÛJ;<—ÿºé…ɸ0QDÏåU¦ÜˆçÂgçó¦É3}6&ŽÊsùOQB[¢°(á·nßú�FH#¤ÑÅq@H#«É’FH_w±"YÒÈèo•…h.ª…|Ýè–âü(äG!š\)äëHªÏFiD¢¡—H¹WeÄ +;h¦ØÅ‡Uú:��…z*‚U*‚U*‚Å>B‚|„Þvx.ÿÑá¹¼H�,Ógda`µ ñ\ã endstream endobj 26 0 obj <>stream +ÀÁ8€›¢„VTS”°“¢„4E S”�bOV¦“ÕêE 7&Jh/œ“ ìëÒñ‘éøèø8­Hö䫚“ ¬nf¤X;ÏæëPð¤±wFŠõÖaºuÜ:8>n �Íd�Æ^:oym|l|l|d2$ädH&ªHƒÉXV(ÖT¦šÊôÑø¨aH&ªˆ¼….’‰z¹†CÄ×Uà*ð×y_W�Ëx8"*p–#âVà4_ç}·T9Dl(òIo¸7Ga#º[ÅIo¸é“Ú舸_w± ×RÔ,‡†{)j´a"¾“•éó1²dÒØr„‰Ø`ˆ2_wÙ”_w29UJRäO&ÏFŠ�ÂË«žLh¦üù:òSž8X^UÔ}W) UñÐp'J2$LÄf‚2ûýÄm}6?QbêŸÙHS!G>Bò)?00Š…}œ\`Õô2½:D±r°B±VfŠN!ô_gza0-�¬ãõÙÄ¥!´¦WÉ„éâÃsùPÆÈg'˜‡qBE°ºá¤<˜çä[¤Ï­åD¾b8)Ïå/9Ö©Ï>›y �| gÉV×á(Å*1²¾®3Z‘¬¥Âtq�)VÒˆ¥¦2},T%Ö +‚ª°RÇŠTr@,òÙ�:äF¿®>€4„baUƒ1}ÝÃæá†Ûš+…á‘á©rçžjÄå¿®2c�o$Æ:!Hco)ÎGú|6—!ÙQˆ©>ÂÏB2QU¦þ)]TŸÍˆ¼…nóhyd�ïË5”JhX^U¤E››EõÙ`dhàNµmHp‘—C8–ƒc%D!—W¥åJõª GÔ +?8x  Ìz¸¶† n +± }`XpÝëk% +‚W9}R©hjIrã×5h` ‚fz@Å>ð¯X,¯šH”ìâ«hŒÐFçU¢|€à›ñib™ìPPå¹’ME'$¹hHTªeG‚B�(Œ6@JF ;b£$º”‰ÏFŒ£IÃDÿ„ÄɆ2"/gp°y m6^˜ (2¡À­ü�Äõ@äO`>—· È\<ùJˆ‡ ÛH¶T˜€ØÌKö3 {sQP0*¬F«4b ÙJ+õ$ÝbÂ\¡¡vdu–fU‰Õ}à©�3©{…ÇQCáC¤šˆì +…ª +‘´Gµõ�Š +Á`IG¥Áx<ŽŽ:B·—«AO<ŽšC0)‰�JC¼J‡Få„àq,g"�ÊÊ8¹.*‰ǯã^ªŠtÅ UA0Gd j…¿¨ê¡€I¤ª‘¥ZŸÍ˜Ábþ|6¸ ÆÕ^׳äZ6‡÷jå‹T$õ3ÇσǯC¡8"îŒä¹™P ‡ˆØEè=�Âòª ʧ-¾®bÁ=1S!rh¸›×%–9$L5!‘J‘åUU×ÖZXpòë@Sˆ©f€œ,Hèa”Ø7Á5}ƹ9l¾nôX^Uâƒ4r‚ñ\pªèæFÂTRÂKÒôÍÏÜV´ǯ;a”ËQ¡H$5µ*ÁDˆ·¯c}ŒŒp,>‡™ŒÃbCŠT½ +¡6(&_7²Á¡ ¹„džŠ=j*Ž%b:HÏHǃ†õÚ¨€¨>R;ê×�H6tJã$;mx¥jäVP¾.w‚Ò¨›î„VLˆ´ îAñ¯ËQN£†ª! +˜¥yW4±8¡*n[^µâ4'¹ÆšÐ�‰ ™¡@”f+RŒz e‚]Ç0qÄD”ÅÓ`ÚØ¸•* $"óüU4Ù¡³Q£¢TS9}RÉa‰’Q{€Øˆdð×™ÄÐ%Ëäs!G¶ŠÜ8�cƃøº‹¬³-6À‘NÉ‹#³¾.£Õ!2Š�Z �¥™ö¾\TŸ‡¶¼ê¥Ìßõ |]†â]«‘ƒ|HaÅ¥¢Q·Š©f¤dŸ®D!1B¥ºé°ÞPѵT¿ŽÄƒø4’ܘºp=l>2¸Ã¶1>_Ò#EÃqT2! �Mgdly“×&>*á bxeM Ü©ª‘‘ù0Ž$jbyÕ¯£™òg«‰-ž‰—�«ñ"#ò²ÍZ^µ¤c~ÃVâ¤Hdá4ògs’ÉýºÙ(6$¡Œp¢~H."p�"68ˆ îsËØ‡ó|6^G] +òbq<9�ñ4JÏñB^,Ž÷}]Ã%1FFäeœ¤±6Èg“ã¨K5$2ÏTzŽG²âç]\èY‡ÜÆÛ0‰q¼um¼¯›0‰q¼“ ÜÅ‹é Ïæ? 6 +=•‰™©ÃF¡r#â>`\ ü©M§Þ2±S›Ní´:"6›$6]I‚¸aÃ2=d`beˆk%"9Þb.[È*±ÉD¸¥FÇ‘H“Åè°/Cš¶†5vˆP‰Q¤×)áÉã$HøÉ×Qx›Ž„¥¡ÂU.êã >­ØÍãNPÜJº97Oí¸l+{!Ù.s±Q”~¤VÓ€�¨}j”šhs 4ŽA‚ …8r¶A£ŽÙ‹fé3Ï©gRÛ¬4LN.•6ùº ÊÂ& qàÀ�=dVX6Ž3Z¬£ÖQÅl7æÝÈY Ë¢qQrºK®lË}x\À\'–ñ ¢‰! +•˜+3!µ×X]/“Ž~…§Š›+Ä’®¯ë(-¸+£¥[ªŽWGK¥Êxha¨N¹PC%A!ôè�ˆW­SCè*CFHfÖ&"É�p†dûp±¶ÅœX$ÊâÐlÙŒ‚w1RÑ!Ù´�›JƒC¤å`ñ òu*â‰|p­ÕŠ‚ì­<—'³ú´F^!#%·"DCÂl*CªQ¸9p6(D b`²Ð£À?D¤Å!2Ù $WjVòñ€Ù\|˜ˆLèÒ6zP>NÁƒVòø:¬Êx˜�,°ŽÔ'–ê°ž‘Ü1{Ø90$4(p8T„„8*. G V–l\`T|c³¢x¸ÌňF+£cÒà°ˆ +‹ZFD‡wdl“‘QULFFo`_÷aúåVâ9˜ˆ‡QŽ”,UnqRUÂØ«.3ÒÉ'G ¹ø:2ºx(¥èÅhQ³°¨d‹’YÄJöÆÂ{™¤^Ʊ‘…dŸT‡g3)“�ŽJ +š”¨ds(t‘ž´" ó0h$‘‰„¢©(uhÔcT0rRD,ƒ¡PRHqQd�a£²¡ +apæìزðQÆÔ3OÔY¬³’}œÝ’µþN°Z¥ÇiŠã[ôuv:ÿ[3Ú«—,Ðt�n¾QörÈÆ+QÕ<ò{kî/ ³ì…Ô™ýžåÀõ¦û¿Aå.šÖa{–ÍOþ¥ßý[ZéJ‹ÀäâÅQ+ûÙ+”·;ÙÝž¡'¼µÏlÀ‚ÆÕ}XÁs j5°/àJ‰õÜ0ë:5¤}i·ïB¼ñÓlˆÖ!lNhuU¸O¸ŠË  "Eä6enÒµ×kGgg\Œóhcž5�­Ü†­y9аõ|Œ¥wñЦƒÁ¾¢yÂ3¬1Ò‰ĭǯÆ­Qs1ê+à}Z¥¡Âl0ú[§Ñdæ5‡ò{Y¨.—£u ŒXè2xËd´à7çoéý•XR´=.˹ùŽŽJF™ +†AÜG¯™ä>hÇT. +ÀgšìpïKõÀ¤\û‡¸Ÿ‡b™‹xàg1o”½h M#µ²#µU’’€Ðs/dïYÒÇ€ –,–3å~ä»RK€«ã.kÀ·ú6e +›Þ£ +þ§íõH=à T—ÀÉ~1øðƒÖZ›6ÿãr~Õ1C™A­ÍQÔ²¦�1銣ÉÒ&hKN ìÞ‘ZU©EÛæjÉ sÁ¦êhy(Þà¬}­ý‰qB�M j.cÇeLöd ¸á~Oq2a9…6ˆ-ù†£V²BŒ¨¬Ñ°ŒÑõlÚgÏ)s2/j?À轟ÎÛeJÏ@̽‰6¾ƒJx‹Bé r'·D›Ò¸`û) €Ø5iŸC +¡”Ö¢€b¶&aÉ ¡/ñ?¨x¨S‰=h˜ÿº_25´îMлóš±ßç^Î’Ý!/“Ç6ÊW)$컩‚²>ó6E:qK4@�Ä!=HlW]‹ûëÄ­,fz.ëw'QÆöÄí÷tv¹Ï9õ½x]@–›Š«\ÙöÄÍF¥Ê«oð£IÞ(õ»ÄHDë3jâr:žŒþÔøI1í5«‰ûç÷@שâöz¬c=qÚÝçîò°B�c©× 5À.ÀÍP3ª¢v5’D09NŸÂe£8j,˜Ì ÚßhQ7*h±�šÅó>õ´Y¼Â÷žÆð£ÒäÔ�Ô†x½"·gmVîhì¨pØQ®T%vÅÄ!rÏ6Tz­xѧç¿—ÌÒ�‰î¿Þ‘nÞuVÛŽ˜½©¼þlÚM!DœlžÝ½?S)Z@zzŸ²ÞZue( û1ûc’Vjv£ÊÈ x§NXñ V¤%Ê}9!ýÌ9ªðóÄP®?W:Ä ¯>EçÓJ©2mdó„„Љƒ(#Ǫ=-@B]ÑÓååÌSc ›mHæë*R;ÀïPIi–‡…q…o]&ª2ÎÊè&Ya¢$A¦X·ÊHÙèù!rÚÂ+Á[;®|¬mš3H¯Èu�É™ ,’DidëØ“)¬íÜ{ÜÅÜ™Œ(˜!0ÇHðõ˜äÊü\%8þ¸JëB¶ß÷­¡ZvÑ�5‰¶,© ï—ÇÙ�¬nqäð®Ó^ÿËeÂúÞx‡R5×"‚�âLíK!÷Лþ73|ñ¯x5¯ Ýþ;R·X®/Õ<Ýñmh_H=¢vè°Ÿ’ÀNÃKõŒ_U ¢†²_„C£bgtDûúóÜ_ ¶?ÙÏ�!ñgn‚XA¬Ò7ù�ò”#ì9ÌñhÀë'ÓøuŠpì$u%×é¬ìa9?5µò†,é õ!©Í±�èMÊìÁœì*&·áoYœ‰ô“ÉÅØFYJ÷àõ§qÖÙ4?Å8xï…¨Ì7§nóo. bŒ{LO¢/×^;ÔÈ�ƒg ÏêÄñ'&:À™e$Ì¡hûÃ#j“? 1EAÝ#+øìEÚß»æw[%œ¹94ïà™çæ*ïs´¯{™ôf· §Mxw5³mn4ý£%“xWòBòw¾Ì/„‚Ÿ›\,¡|nXPMä?<_EGC9SäÈB '&jµƒØºf„áöl-.þ!ö8`še}è â°ëPå�¯„.ŸÎ”š6~:×þ¤.èßp‘,ßcÂrâØÉ”Sßt�ÂDPé +Jk;¹Éš·Úopÿ98WrbLúΆd‘¨lsÒÝ�i¥: ·´ †-™3ÔD牠GÈ�óä¨Ñ‘<=žA¨þ ¹CÖ¬28‚òn`ô„4b?¬]‚«O„+]fÌÇó9ÕöÉ-½½®T³ž€w!¶û£ 3TWY� ˆÚ«žû¿µ—.K˜·¨*ç�‰ ëïvŽëÛ Ò•m:ðAJ†Á£«bMZÑå�Ô»…µ£k§\\”7z›á)~mÝG÷�^xaEDÑ�÷£Û]÷# §StK’xÆptµ�ÉÇ¢[!]À¿ùÊà+ºR¡m‰0ûèJ‰ÁmVto#Gïí;fGÑåÚþt G׃AXtݺèè‚Ç{¥ÌÉ]q[¶3çut‡ÇK uòC:GmÁ¢+sYmwÀí¸YQÁ#1,§IÞò?Ì¡,¿/”¤Îõ1ñ¥µ"�†mJø‚K®ÙÊâ6?ƒ.´’D%bNI"›SpŽèsòæ�,H½\£4EþÑåÅ@W‚k2š€Ÿ·^ãvl@O"䓉u¤M{’‘4E-œÎ^P¥Ù¯Ö µ˜Å°ªPÝùš¹¾zÔ^ý4)Ò*?³”п˜Qe(k¤_‹e�›ï�oœ:|p«GLùý�å»ÃnC$ý* ­‹E¤£,µ}§!#z¨^•K3ú}j¯[8-Žø–ÈhÂül.;1â#–!ÁÂG´1½xÔÂq�¤îôúayo4Æ\ýBG„ëÉò¦.FÉæžxÄ#c/C7|!É84¾›ø�æ‚|ÄCKDðá0iibÄpÚëüa*2(¸JÂ×¹â ÛÓ“¢sÙžõ}¾�=Hêm +“—nõÄíå¹WïI¬åS €%­É­ÓÄ¢Þ߯UÐc� ²ûÀ`°•3Ñ*Ðô‘GR¸½2ÁЊ؛ï[†ÏçÏ�;f•—ñßIhÒötëéãt"¹UÝ " �OÑ_íÃ$EŸÖèÙ;†x¬ ¶L›Q{ÞÛ•“02Œž ‚©EܘÄÇ™–R�ÚüßN�ݱ�¤n«-¡ç\�ÈÑ8µ +nhË|L°®†ŠŠWƃÝD5n݄ϕ“½.TSðúŽ^ö¥Š`j¶v8™è{<ìo£à'kSÎQ¤“XFms%wÆ�¬m/Aû\ùB±Ld£yçÌû,£²â½¼~„ù-ýnÓ$Ø«?fayù¶ Bq3¸›§†AWP{Vw³Iõ kHvë¶šõC �÷Ö×ñ—•Å:]^5‹Ý³ƒ<é¾B´N%Yc£À¤£\G�™lçÍBHÓ4Œ“ Ñÿ:[…}®òæÎ GO¿€çG”GšÓbã,\’�˜’å:ëó¸Nã9áþ˜Ÿ вÎ^}…ƒp�'ÿuÌî÷cüÓÅ�Âê Ô„Ô¹`ñ]«[›ê@*ûÆì1ëÉaªO<úx٘Ϸ4!æV~lI#ª3ºP.ï,16A~´[ òVßÿ[o(™!§ÕX;•ÔÒ9ÎG>˜ÌÃY²ðä«Áó¨À<Þ)½«OOȈy\Jêšj„÷8lŸs¤¥¬È#­z)ÿùšþrV!éf¹úá RÞ–./~.·+ï#e@–clE·Ö|¶%Jô2m±û¼h1Lt=è +„üB€§^Ì1, zÔÉ´&¨ÍW²‹ƒc&ïà*\»ñˆgDeŽ�5ú{#µÏªÅùR­b8E}âÀBicŠŒlGb—�a0¹OçÍ \!Ζ¤}ØÝ £A–üÔøöBêú,Ï#tÝ3§IíÎÖI²…ˆÛs'›.ÓÎ/s~‰ãâ^<®Ÿ‘5û¸óPÔˆ™Ô=Ó¦xM€�D·È<¯«a"ÌÜeû¨†¬�ch¾,zׂÊÞîá°‰ýœN  Á1ÌMg û”á°Z§Žb0÷S¶�u¢À›áÇüç Éa¹e'„cf!x#±rsxO'o§3þM­‚ ÊXÔ‘º0d\ãVw,Øf›UAAp +Ðó�zÙCJä6óYü@�£ÄÜC¯ ^{)Ž CÂtpÑ ceÅÄc,x wæÚàÍØ�pi›f¿Z΄Žei˜ëì.©çó1/jî÷n^@H’)ÈÓþÏ%ã8C�žUMN-�&³†JÊ®Ð`­ßcüààu–rY@'¾Yòb¯ÌABÞÂ;˜¤�=uf˜l½³Ña„»(d²ÝÖ[>ž?Šr‚ËØã¥ÞÄù)[yâ2ÚµŽÌ¦ç�ÿ9t²ìÓyᘹ@>�qkO‰ìpkDÏ$~L>�PÜCõImFý½™>³?=¿•‡ú™càP½uÑÕ!/+¼@1 ÂD0ùW)RL/Ø)0@Ç[);eýJ <68<\‹êzË5#ó’ñš—0ôú’YžI€$hd]XŸ2k@'[n1 À܇H)C{[䔨R²5�ePHÅd4Qɪ¾æ¤› +c ßŒ„ªYoBï@�Ú‘5ø%^Ø›,9tÀIæÿ0ÁßÄ¿%5xˆHdШŸõ4ÅqìGÒPí›ýNÊΦE ÛaZ¾E¡âÈ3÷g°%=¨¬¯u†Aæd¹a2̓ +�q\AÜè¤;‡k®VÐ ´îqYž™üj’µG‡¨æ¿d,,5œ çêÈÚ½&s�»ÿÞÆµ@/å”Ê[$B�à‡:ÅÉ­³g²,˜Èý‡ÚOÛ›Òz,U“ši>ÜPB�Éœ¿ñ­vh�/)leЭÁ?ze¿¶ð1NŒÝ[q(c‚’`g!s¯³¼|M@i„¦Œ#Á;Ej²ÁF´N‘·-£jbU+`Pêµ¾35 +ùþ%2Ð"™J¡B3�}Œ5ÒTI8*IÜšñ» àpí½ÌàÿtÂMi³bhû¦Ðv˜¸rÍÔ,\}¤»uU� „”x4EÓ«+¸ó[d«CE¥\˜>Mš«ÙˆFCaGÓÕ±*DL€¯€ЩÈåO“yp �Q!ÜX…”‚¾µ†ÉöôÛ°ƒ T㽓Á²ô¬t En` :ç’©¥›–+ŽÉvåÁÍ,Jrêï§x‰@W•ûapÕùÓa¥†åþ©”$~㥀 ê +oa |,½3"'ÝZ7Ð'Œ«_ÜŒI!mqOpô®®ë­»ù·¶ý ZóòwQ›€(Ÿ'�R³çÌ%Ÿ¤gv“í�HšqïÙØè•³{�)cSÑÓ†’�êÖÇ7“ûµRÖJ¦Îè±9-ÝHÀKíõcx_!ôå?eÜDwúl£¬çž?MmÎá0ÆØ¿íðlÐãïUäõç7ƒíõeÛÏjîÿ?Ê¡½0ñ G ÷a ·,™‰f“¯Ec°±�šÈ�› ŠxiE÷÷„ؤß )«rÃÚ†8ðoÐh­´ºL ƒ"Äè;–e”Üjšo1¬,HZÙˆŽ��Ó‡‘µi±ŒSá�žBomÑøÀº¨%Ôƒ_òóˆsC¶†Smöà�µf—W %� ¢ Ø�¶åKd‡`˜{=ufe`·é½d¤ìJì“8n]¼72óûB7ØòËä{ÿçh"mZ!÷°Ì—xCžÓÛo±‚É#þH»gb‡gÀì” EYƒ`"<@ ?8ig¯�Õé•ÕW)3µ«|�00Qçy:I`¢~£�°X”8²4Ä_Ø[pKM’²vñd{Eç´I 5u!¥ò„0Ь.¶ ®#w2ãݤϯžå¼Ö|ó9DJÁ¶ =ê>NCPú\Kå5•ºâ雉‰6qåCâ¢ô(ÖV츲Õ9Ù¼ + ¸í‰ÁËIÅ]Ìó[i‘È®ö(½ +Í*·ô8�Zcáì±�YH¾§^ü`¼�ÌÖï÷Ö ì�¦ø^Ü#LJ; +ŽZa¯ØÆ…gò»Åsmþ1¹{'ÜÄJEv\‰b>i™ ÒÜk®O’ËÕ&ãÕ\�>ñ�»ˆåã,]F›ÃTÉZç�\C°ë*ÃÉê#¡_Ø÷j0ùL?~H'qΞõ4ñ5ùž˜,ˆðrÄ⻺„®m×¥Âë„3^íCY5*(Õý!mì= ’F2ÀëYȱ¯ä•eÔï¹Ðv‚ä„o.0»Zv ›#JÅrüc•�êdL|alVöD~zàu³©…U=Wü¦ãS¹¬€o0j‚í‚ߦD/ÎÌäQÈD�b¬›9«Ð�Ž@åCïeµO±•˜Q¿—íœC[³™5�Bü&óÁ'öx§§êU+{¨"ÙÆ8šKMVè ¦ãë×·[1Ó«à>(— N"ðMÃäâ#îxáJ«ÎožÀZ;‡ òNÕ²_¡[™—튯àUM:¿.®ïø¶/ +5g«4°¼ŸÅ9à ì ežé4óE«ë'-Ç9r 0Bïža: …çªÌ°öB=™‹¡æ:å +›“ÔO �s¬nòˆ¯<'öˆëˆMNÆ�8ãs÷N€_µîÖûöôÇ“™ï8Hö�ÉŸjlEy\BMçQ‡ÒµÅ¥4æ8`DSC0à oMË3jólÅx�™†[Îe÷ƒ•±ÐýOzªû +Jz5=Jž®º.9Yá̊7a/õ.ËSa’ч‰uKzÉQ‡äÛ£Ÿ™1†#xb­ÄÀ¡-©òd÷ÄÈ8¯¹Ò¨¡�¸©Ù7|— sEºîÊÄCë´jZéA×.ÓŒyWëóL�ªÒµ0óðïÀfãiJ€“}Á?=ÛþEd�—sruë?@Ј#†õŠÄ´¿}",è«Ë.·jõ§òÄ“Ç L¹y–ødÎfu8‘ô;|üŒlƒÁ" Ç`CõdCPbC'¤Ãg;•¨ˆ¤âX+Û kŒ‘ó•.d`ñŠCD(Csi=<´aºK¸õ©yWÊ/­$ž¡ ‹É9hl@ŽU£(ä>óƒéóÝ¥àëÅ¥bØl…¡¯—¬Npi-¹º±<T2¦þ—â8 ¡°%�Ë“–#÷YRÅŸ¸:ÐÑžÿ|ò¬¬œÒé»-Š“^*¹nó¸¦(þUåäµH^-à}%Ä;öJ±sy|ð&pzÃIPuIJßüÚl„¢XòŽ.S³ÏÊúO19šFä(Ÿ¸ã.ÅzóÛ…˜ ŠJ.U±Ô'YØ­$4o¾š/ÀÍ3š½Ê¥¾³6¯ôdéǨxè:û¢‘7 o¹o7ò" ‡òu7[{üœp�U™S ;´’ïà€x€ÑàŒÔ—žÃ£a”íX�š.6õ41©ú£YÕªiÔ·í\4Ã3ª‚&[pqdÙFšv74"e¨®bQ¹õ€xþbÛ6µõ&×ÛUaiñ=-áÊôcVD¨ÏªÖ]Å<ŒÅy#Ú H8Åõäásì�B W(Ô£ûWlŸ$¸‘åóDùZz„)º<�…[3xÑË”‰ÿµÒj„ëÃÏï¦<Íøs:ߟÜSª¸dV�7 &¯�mõ?æ¦PÍ\IÉXš�‡[qBkµ.#µ3»Õ�rW fA. Á|`�z1��Û8ºX¨5À9=›5(xÞ�›OÊÄ!æè–²1b`ÌžïBû\Ûûd.@¥íq m׆[æZýi +äfÜÑi¶XªúT ÐÃÕPîÏ’`³õf? —Ë%]ë‰üD³åN‡’‹3«XàyÉÛ¬ææ/$··¤œý¬oL˜Éù÷Sú|üj…èÒÝÇ�”¥@õ81OE4Â6MÈuØÉÇ;ǵºVðn,p7±]%yWù£j¶›94—oÒ�X+U‹? +gñȩ˙!|WöP‡�åJöÏáñ:ZûˆûÀ�ÕšêÑà«‹ÎDÒ¸‚¶±Sÿ¤3 w.Ï*Å—¶¸ ú¶æû¡œÐÛ2ã~ž(´žî˜(¸ƒ‘‰ '†«Š‡ˆ[²%µÖL�áKx�•�å0ÿ“ÜnH"‚¹Öªì:‹ËÉé´Ç‹{™®ƒQ¬´¥a©\Â=褢ʡž¥š½Ò LÖËK+™'J:�üßP5Ö91åñ³¦ÔuÆeKŒ>*I5Ž:¢{ ÏË@O‹Y5÷#ŽMì'u±˜ +ÆAØ/½²H,É!��rV-ë”±³‰Â¨òšª33á*çf½[Ypº2aüKù@HØÅ\Ax&V~+\r8PÀY�l9H…æèUe9½{.qÍÈ,a²…2]c8W~O5-$ ïœk³÷F.t�9]i©JdBž!:}Ùpßj�1�ôT›×(rhý‡ØBgg¢H쨩 ‰/4Úë¼— ½UiG5îEk;"�'WÉ£1ÊV›g\UÇŠ‰/žˆœ�ƒf( HOl尿zc;km6ª¸^ŒñýMV¨Ôþ­=î¿ÍQæÃ Þ„Rò_J:UÆOÕÈTôª«Š$_†QâÇZƒa+¾u--]�¾eÀlb‘Poôçu¦:Y)˜@²£Aq%FÖR€}ÃT4 Ý}:ˆMÛ¢Sƒã Ã×�š.¹Lû*¾›0ª—_é´HË‹³Í—«!=Ê*ý¿[>µÙÕ«�™ˆ êçúÑÞÕþª<âì²ñ¬t૞ÚÛ3œ(héþkžÒ[-Ë$ì·bcÊß nT™Ûì<Ú´¬·{;?bæ¾9A$æ£Hu(�1Ì.Ð9jü�£H;á€8%µ«éfµhç— Ö\Dóä;(¸�üøG~ÁÏU©ÿîã÷lŠie!T,$†P‡ýLàÓBWÊê*®œÏ’Æ7ê#ýÎ^ G +ëÐÉ�ṗ‰s­*w \áÖ•ƒõy58†nB2LˆõEKˆ7cÃ!�¿·†Uú~¨ÄŽP[È!!âEà Ña8”6Sœq5š?¥iA“à¼!bSéã¬Ê�â4Žl{uÌœ©4Ã[·ŒF]nèšÎ¨X‹7¥©Úîn ®²pžV{ûÃ[$ø(ãPì=i)–ˆä4qB>5q£N(6+¯Ù\nÔD„K«;¤Ð™vý +& X!ø#¾–šs¡ÑØG%Y郠a¸ p9\ÐÃMn0¡ Ò+r¸R²)à¼}Cx«•–S+ûRµŸL,ü;Õë“™£íD²XúÀÇÿ¾c;1Å”‹?o›8px—�·“r[�–Ùw@…É_·žz56«·�PwëÑÔ—s? >o»Wªa˜¡J˜YèÑbŇvã(pÃ+ãÞ&žozÛ$èR⾓fÁÙÏ»z�‹œlÞæ¡~�•"rÖizx£ÅG“qè™ÛVTÒÒ•$DbðÞÐFç¦Mô(ÄODÅFS*Ð3òÕZ Ç„bßïÓ}�Ç 1R)f>p¡…~OHøãf#’ĈþˆÖ~¤ÒL" |±D …Î盛ËP�#*ÔR~ZÀÍÃ;g~ì”Ôòk æÃIÖ#Zé3ªÎ™›Ï¤ýb2ãLr+oÜ"ÚâŸH^$Íà&ŒQsÔ}’¸ñÖ^AÚ~Ì\\³©˜3IÑé&7qµE»XîzYcð}®äß2äoÅþÙz)¿�9�Þ�kÛxŸæ’JëFö1Úã÷µ.¤¡Dˬ¶Û¸ÐÎ>³í-³cfü~Uj”?–çñápþ®ëHZ%KÔa×#§'ý2!õ:ñ�ó¯$éEù>²ux££híûÅ™á(ÅØioKEÜ^i. oȈî›ÖÜôbw�Ö²ûáÛÝð&÷«“b±Ê9^ü~5Vì¾û—“Á1¶ÄÞçÐ092LžM=Ü­ø‡û”ÀRßüäÒ+ñ'•W9ÚDm,�ØHIp„ÐBßýñ®p'DÝ(Ft¤Ù|Ž9îÔ%g*¾uœ–Ì$¥ +á­ šòÌ<‡�”Ñm5=‚³� ÷_ÿÉà€¿�+Y€•“¥‘ë�Vo~vý’Ô6˜xŸªƒûàâË»dÿøCÕ�7éÒ25ÖÅ1sªN#'Ç +a5¯÷Ø`y)].¥X^p½zHéîºÃnÔƒ‰ü Êú)Rp€Y«ÛÏëîè´9žh’l~o3�¦eÛQ—jȭĸ+‡yv£Ž2¶ürí¬¤àª€L®.úÀãŠô`&uÀÇ„Ë5!ÛDÓH3ïÈ�‚L7qðC=^+RÙxBdR­wtkƒPÔˆ…H;‘î‚’dN½T +£3±„*ª»àU—ÎÙÐÈJÝfŽ¡v P6Ý‚ã¶$¾g‰“í3aìôû,¿ŒŸ¦è»�m+7…;¯Á?¤Ù#º2#<ÍËÖê›æ)¬eUJ­WD�·×h}± +è°q:.lÑ Ä:T�J{p@†K¼·‚|ýUª^äÕ .Ò€ÓdP|]¸t—özK±ˆpÞ?CBè¾W��^Õ;É�4 i_%û‘O� €å.ØÑB·©¶™r²%…Ê*ñ(×_ÿ¯WIb£á¤Ý#1ª@%�R)0<æn°ÌÜc7¬ê_ó\ۮƛôekMxP• 1­ÅRì}‚NFñ•ûènî–øÏ5QËeà¡Ë�×|鞢Þ +”P +%ö Xb�o_={§Å»÷xw|—�^¤êÄv�Öó¹jà@iÅ*ˆ3VО½jœ©ýê…]y,âÏ–‡å÷Wy3  H´ê/ñö†çàT“_]¼·¬îϵʟFl1Ç»ìA˜®÷»tÍäŸz¾Âlªþ{é0ÎGÿ±º8ÎwEaðîú*â4JûÔÌ(Úœ±EhƒKÀBš +¬‹Óˆ5y$Ø=IŠdí{DM""$öB(â?D„ ÀÞðlb|ä[ Н$šØ%€û u5“O@­W?1"Phÿ;ÉßG·ö ^=íùä0Ï[˜<3“ç ä“\ÕG§ýÆýöÈ\Èc•;;Ÿ&tú$¹@Wî_‡[^Gœ¶|”o^4¡HòæÆ3p!!îD²F�9GxU×iæ0*ŠæÂÖÃñE…¬ùrÿ�±A'%Ö`æ<e™ÛV +¤LGÖ¸š9ÝËQÈø€ßé‘Oo—[ô´qÌ/Öh”+ŽAôÞ‹dãy´:ï¢:à ¿TÇëûA®dä0Ûцà)29¹ä$ïŠ&Ešoõ¸å§2P¶ɉµÌ–›£%°h“Vfyc¾Õú $8yíf2…ì ßÑCQ²»6é6llÿ p�LÂàÈ:ÒÑbµÃé­^”Eá¾ +“�ncó7Á2©—ͪÍ!+ªp5¾<±Í;æÆf´òl‰g=2°,Ço¢`ƒšžmd˜Æ~n™\Ÿ•öЦ–_)àr“q!~e¶.œŽõÏ‘¾w˜‰˜ÐÊaû�{FÝ�~•Án ö™¨E +V±×Ù®CÕc¥ªªÎtÖÍ-Äúeš‚ˆ%r!¨·“ˆ>‚ÿÌš%=¼,ß<Î5qŠõ5œ±•»À?®¦KX÷‹•EîcR/|_>ûÚà©•mb «",ü…<»brcb N˜rsÛ�%OcL6ÑMx#Ÿ†š%‡eñ6HU…*m,ýc `@î"P" +D·hîZ+î3Цî#¹Z­´!‚*¿’‰ëÖ�NvTS[.(â!ˆ…SOy�^SÅ7E«”ˆ£Þu+;<ÖT¢$Ì¥\iðÏbmmã��ÌuR‡„N|ŽÈN’Û•,£:*üV>ÀœyþÃÆÂÌ™¤ÙžMÓ;xlgžéÏ(·Ax¸Œ1*£¨wéP–Å0:û;¥Æuƒòƒ-ñÉ“6�cc˜4m;Tk5¤“æ,Â¥ùTú3ÝHè‘=’*Ïòn8w°7¤%üÕx‘Чí‰Â¡Q±¥©­ÎæîûÏ(Çþø‡<›Q‡^4ߣ›Š fNOvQâ)1¤z.\¡ I˜TÉdËî[]ŠòKýÐF•Å:%1ãcÒKXˆ>Ú´€G'< 5? +·Çu“ñE•a`&ÔÞlY—ÝŒ’%ç¤W¡á.ÆgQüÁq$à‚T?YÍJV@„d }MJŠàÙV%1 ¶%pß;t$m“NzIH�§¹�:Ì ù/À¢uto$l|)½JDßtb¦îÞÛÎö±wþMpÕoµ—ª±Ò ¨Êi*º='ºª5pBÀu{8ˆ3媸¾û}}nÏ©SN×¾©eï†Þ²%EüÃ*Óõ¿ù öÍpdädËÚ/ЕÿÒ ‘Å0ô.`Áuó ”ÎbcÍ[jÊ §süc€Ù𨩉~y“�7�|ÛLËoÞ÷ùKçÞS÷¶ÈÓ‰ø¤R­ãjwÊ×v¢:šø­´tq>ó}ÙL:ê p©a [mJ® =ÆU§!Š!j;à;ŽÂûPCÞ²ƒƒWŒÒˆ4ûòÁØ‹%ˆçFyKÿ—¹u`Å®L âÓ­”&+¦"S×Çñ–å¦jŒÑÓÖ“�ýü{æÅQWC…θè ën†RbÝRˆ¹5dR€ÙÄÑr á΋¹�Ì®¤¬N· +uÅåCÇ<à æ0£]WHn÷Š«¡Í'oä,žaÔåþ&¾�cžW¸LëTX[É“¸j‰¨“çª�²ÕâôÔ$ó¯õø|éÊ�—.}¢‹„Á¥«¥`]™ÕzRÇc ÿÙN8Æ++=?ÿ¸õ� uyb£R?áqúééH5ÏBg0Ã#¨d–³Î”©(7‡GkÜðxN÷[9½àð «ÍðXD§ò{“× ¶«ÅÉx¹‚(«i3£%aûõ¸³eúOÉ,ÓDÅŸ/ÓÂi®B·eS^àD¢3Øqñk ‡{}HêÆåÇ—R{Zºýo·[\-ÊfM®ó>GÑ-&•ÊÐâ,L…4S»oWÀŸ"…¸+m•�.Š8¥/@OÉmijäRo.ƒšÝgX¨–N­Ÿ*癹k…-³ÀÕïЃIÓŸ’Ç8�KFM|e_Kk“6j9¥c>Ë•"=N±ÝñEqô˜503Í»ðz¢ñŠœ#Üí—5ÜÅMj³ôcƒpÃÔ¦b¬7$X­×RªQ¹Ð FHd·šH˜ó/oÂY´÷opéCmà�ß°d,ÙTö¹i˜žÛDšßX…Èdd«€æèʼxuáÂÍéhŠq™döWM‡Ñ˜‡Êæö [”#o-÷&äh(äèË=V•™Š_…$I>rÕ½G¢kTv¸ýåý ä‚f"ª/–îwœvp>ê lD‡²‘9å9¯�8ªÆÀ¡‹S¦æMùEn~ÏÒFÆfó,/­á52„3ñ»NÀå ìåF£9m'Ü2BV} †ÇCÁ�_’øIdI¸p÷€Ïœ–¦sºõ,�rSCgÆMÀÍïw+N¡%Q°EŠWPÒ,î$|¢Êr2&� I­Üƒ�¤<$£oS“°—Tµ¯? £ø§Œ²›ëYH]ÑÑäøl¡³ÉkonÙÅŠÿ3dʨ‡p Ì"šy¤ÝÏ#–-9«–N”Eø(§r—7†4‘€Í‚Wá,f( °áZâ,÷Ø”Ô71·Rኑd÷þI«GP�(Aíþ%ƒÈ£Â²7µ-ò³MèØ+˜Ã7@ù]‘”*‰QzR§8ÄTzž$´’L°©æÐÀH=ãà>õäøñ”¾�ÓÖ¤�Àíú¡òðtýOÉ0Ï^8n&¸C6ô\ìƒÞï^‘f€ÐvfÈqËð� +˜ ‚ĺa[óí™êTˆZ¡ù �íz(ÿÁw.U1Z{Jy·¤" ø2� ¼Zσ¿?’½Xtm]ÚD‡?À¤ +µK¬¾?Çï«ï(ÛVV‡XVޱւȹå É“Ø"@ ?(ó¤êátÞ0ú«#DäþåU.Á†ú@°VOÖRkyzähÁŠŒŽô—™¥ñ×ÇPU8¡~ElÊœð}Év‘’R7ôÔ43yWϸmÕ‹ëLÂðç3jâRG)?�¦?� à;îXwDðÓÉ(žÿ̅΋êñ…|L6P4�>¹&O#5tµÐ +s‚ãî…}z…-Ïl•#èžàÞ…_|~#ʹaÁ°f´%»ÝØ8‡ÇÍß«±$²ÜAJ¬qû²MäðæÒ8+O\ S�à‚3]ÐäŒ4t"ˆKX‰¼?Œ'a{:öÁËn÷Dsõ{¹@¡ ,þá'ºöõu� &k@g)[•ÿZÓÛ?#CIyµ©.÷¸ñ‚cèT•öÔOÔZ~ëg“A!Ù�S�!Ä8¦XM™´q�d®Åù!ébË\åé<Ä´c”iç6+"¿”È\\ø@AîE Mñ$³¹ó´§‘èª-éãEÃ;Ĭ�œô!åv¨-¥å˜0+¨õè. ÉÑ$äŸ lòˆ÷ÿ^ÅZ“ç*‡¿îµ(ÿYLšOÏ©ÍÒÁd¡ùÕ§ŒPà-7ôwš”>SâÚùÁ“Âí:xK'K‡®z.zYêøèôš´ë5hoÛ¤©µ&¬¦´£UeluÑVðÚRßµ|§¼”·³<øü^¹ì³ºxUËÕ²#9>ÓbéÒæ‘$`™žm9»l µàü�¡2ã²å8p÷�³Þ§ªQ—~ÝÆ8âÉÛ‡Ý&S jmª–OœusŽî�E#7§@¾�P¢±Ìˆ¼'õÖ’zÒ,T|Ìõ˜Où…|0áѪÆ"Ó‰¦êÎHÞöÛ‘ÊA–¦4—Öë™õzýÜ3฀PˬûÀ߯ºn�\îÙì]î]W6¥À*&®æÉ�q‡6œrR@ÏxŽÒª¾%ê¶5ô$k¥ý ’Æ« LAJõb2<MÊßSÃæÅ›×YÁš “¢«,Dìpl1ô�Õ/¿ ؉^×z�ÔÃÍЃ`ªiw…8ˆ>…2½ž8«Jç+ax®(~3JÔ&Ð’g~“Ð9›ˆøp×‡Êø#¯jî/ÎóÛ!á{�Ú#•ZòîÞ…`5 ;üÔE¤Ñª±?¸6��þÿ+!‚jàÃ7{à2f¥gu¢ mCt‚I1@±Ê¢%ïf¾5”ª¯†Ê{<™6"±`K8¨eKVÿOþ³"kòÙš–ŽY:T‰–—^Îp£'ór½TgÒåhö•2„y‚¬­â_I 5ø€L^¶ÇþµoûÏŸ©W%]À~°^N$?ˆPa¾ì��\èsœÎîõPÒ”Ÿ³.ÕUÆ\”û×T+*FÐ&âÞrá!Í 9‹VÚ(PŸfd”¥ü :ìî«^“£eËê…}t}[ŠÉÞØK/À§H™Y÷q¢Í®„ŒŽà��rÜ¿D&­¬é�¡yµ¥á˜lAfXý.¸û`療Ü·â=Æ”6¶oV)5ŵ~ÏòˆÄÒ‘ËMîï“Ç‹€W!>'\Zªá¡#!Â}Ú¥¬„ð󉬸‰3n“ ³'h­ŸX¼â�ø3‚ì�Hã|‘ÊÞ1\P"H5 @ÿ˜]ÿZ+rîûžÐùßêóBþ‚¤8ñgbíµñn=ÇËóÁέÇ@2òEÅþAx%ø‹Ó‡XÒ¤æ–Ю|HÔà (èƒpýW¬fÄÊÍ6 +%Îãÿ…æ\Ÿ¯L°äÈïïŽ 3®CÛ ØÕ5[¹ZÁ‚‰àáUèÛøoq2UÆ”À\”3†ç³qyƒ—©ƒîÝ&2H¸AˆìUj²ÐmDn:7¢�Ù˜6¢%ò„§qÉY艈Þ?Õ¦ƒšøRŽà¥ñ½&„‚‚n£ÑŸMS` zä„!6Á$ÔøòÇË¡½jŠØ lÿ ž�Ð v•ï)况²rT~£å›ÙkS^žv½£\W®PD¨Žîq$wó…“)¨�¡ß¤ÆT2§ÜŸç>Tý&-ØG.þ¶vŠ­up H÷9ÍæHýÞ8no÷£»·Ês÷ÝEx+M”èO\{Jƒc§z©NA®•BW)¨1¬uänŽiî+�3«íßûn[àf÷žGX6{¹åX¥GµÚÇ3/`õÑùf{ªoDoâÊ ¬„dLDX. >(*ڀˤ$l@"�’`æÄ>\Np5XÏfa48YëÙlÛ±*ı؎mTØa86ZφÓ#2Jzyñl"BëÙ¬“‘¥p0¸HÛŒ‰«$Ä<À HÇ` lDJÈ:,ÝBR�€ÈÇ…By &<$�g³Ö³i0’JrQ�± †‚°áziÀ› Ì2pÜj˜ÈȘ¸Õ€²Ž™Š|@@zå¨è�€‰@ñP‘ÒÙ¨°gã(¡‘‹TÙáB¤�ª`J‹ÅÇ!%"ƒŽ«$LD<]#Hɦ%d�’ŽI, „Yp‘$!‹a‰y€§ó)É„tl}„tl¦òéLgLg3&nó y™”�M4 „ E@�ÍfLœ�€:ÖùuŒ’ªŽ + +Ž3Ù`PDD°˜DJÈ$(@F.òÃÓ1‹œ£¤År"êÃ9�PDÇ ÅÙØL@�1Îp qÒA⡲ Ȉù¨ð’aÛ1Jú -+2"ô£ª"(6¡õl6,<‰Ðz6" +')"ë¬3™—wÈÅÐÒ1Jº0²ž�'Bιäèi>`œœttì:)>î3q" � ú…”Ž�.Lh:Q@cf]\xÎ�ÉÇçAG#Jz‰@IÀÑEÀ�tì¤G8Œ’”èh¤9éà¸àQa“†˜— #°¡Ã4 +htDVlH$tS�$L*PìÂŒR ™…‹–hTš +8š˜ +!ëÙ°ˆŒ¢¤ :24(ÔgF3Q±ABAäáÕƒZqiˆ8ÐyªEÂ�‚JÃe€;„�Pš Œ`@ø!�Ë„ +BG#™Ú±ÑCCÄPR„ŸÌŒF`nf4 1£Çh4BaÅ HÅd2Á‰A 111•&!Âi`#›±011bDld‚Çû4 À$ˆ\@,„—;9àñaÕ#%}L¨Ða +tEE�Ã:88¬BË„›’*6Á3`“AÁbi$„L 4¡yØ@iF)! 6¡Ý`ð@ ~*d:xF£�è$ô�aHÙ @ �` +FI"�ç‰~.)itr�‚’>”t�‘( ‰Š³‰(ð !e /2"�gãáAI2" ›ã„pä-è-8r!÷|f¼Åƒ  ÞrUR¥#…ƒƒâH“6LL  $Üp°Ñ‘1q£™ÏKJ„„ÃäBü̘¼°4øHˆÜ@gAõCCI�HÌâci*(IBGˆ x…2�é`x`‚/ ò€=Z”H8xq¸à y‘„†XVN܃‚ŽBCƒE+6 efôÀP1=2舺˜ÑƒÃäú$Øàh¬•�ƒ‚Nɨ4”ä ƒ£QÌŒ�õœ�h”�¬OŒ +ȣ ŒQ‰QYltB5H°€@�Š’ŒN@"ø��>`ÀÀAÄ�r†ƒ`Épì./BŽ…P ¨Âæ¦%¦Âˆ‰„Èg4òl`Lˆ(ˆDD&¢ ²‘½„€^B@$2(!£>%d›“‘) ‰�hJä" X D.’’R#Q((²€…(.–€%%xy Ðiy‡d 1$$xP��óe6".b(0ñ*Jâ0‘(‰ý€`¶á`ÃDÈCÈŒŒ‰óK7+K´_^¾}iëØ¾7MÑ×W×™¡_§ÿj÷çW^3#Ÿî¯wS^Ó>Éeº}3ÿýíô¥_M�Žæè÷¾º×ÔkVÓ3»vï*’•É×6í·/§ÆÎ7O4Û6äÍÎ˼Uij=Çi™µsOÍüMùMsµj5ywº>þM«Û®yÎZMy¿hj¨¸t[‘ñÌò/- ›³WõòØôsí÷µ¹µ'gf´>oã~ýDw[¾ÞÝL~žÔúU×xí8ÙúºO÷ný¦ÃÛdôó}wí>[ɆϨk¹Ý¹˜¸ì츹ɞ¾Žu[wS›µÚö›° YßÛõ_Û½ýÖ³:ú:÷K^xÏ̆íÎÕ¯×CGÝ[眬‹ípÿÙõOú|æê¦äí}ïµm·» ÛÓÎñî­c¯¦gÝÓÅ«êù\M¹Ç¾þ5WW“ï±k¢·/Ýåå=ésÏn[Myé»ù&Ëmçu·¯ë‘ïv÷¶šra²m¥ÉÛ¸6ùº×xq«ë-/u>dÏtï^æ…Ú'½LˆÚ›§«¹¬ŸNÖ›rÛûy97ã÷IŸ­¦Eæ^í¼¸¿î·B^÷­¦Ã}6T䥿hŠÇ‡k\¹›÷bä…jÜÈ7]«¯ùræjzÄã{ç…ÏÕôi¼~ÝÕ”lˆ½ô÷&]ÚÝ�¿è¸Ì÷Ú¦WSærß“>Óåþ-¯s¯úø,q]~5õb[oÕ•Ï'}üí&6]ÿŠÛÒôsŸÛŸáZï“>æ¦~g¿Ú¿²fô›œqõl©ÅlŸÛûíÛÏù«Iß<{iïWz¾º+õýWæß´¸îßäÞx_MÈÒÓqïyá{5ý:ÿkl¯¦ó¶ÕµŸÞ˜ËÖ«É37u­JÛ]Œ~gØw«]MlŒ†ˆÝÕ.JÃÆ\É\=ú_k¯<ÞÃC^¿þÈû®ËÛìÞŸôyµ¥¼Öë7)?.®ßtßîŽ+y«IÓÏÝ—®Ÿôáí·í…ë7-ú¯??éå1‘ÛVïV/cëïïù„‡Ì(åN82&“`>&‰›P€€ˆ�Tv²é$Š’X`8Nî(‰’(‰’(‰’ B�& Bó!0‚b;VƒŽƒÐíDƒÈEJˆyP]Hé‡%t‚U Œ$‚ÈCÆv¬á <ø|€Rf6HN6º¢©<´ÕmÇ2D`€„.<.V>¼R@Bc´,ª•vX9ÎYðŒ6›*”‰ÊUˆ, ]Ç3”t:ë¨B! +  £$�:MÅY& еl0|€®c�s«M6œ“€± †aÁŽbéÊÆ¥ø‚èBŽLPRk„@ 1çáPù¹8È)Ô‡s2ÏA‹j}6 Á6`(‰–‘ÉXTÔL ÅEG£� %QÒ:ÍË$ØÀ€LèŒJ.Œx(8:"ž �ˆ �‘tœ�ŽÆhô°²á AiØ@UQá%#¤ 4¡!12M_©¬ ‡ƒ�€:¡;°žÍÒ ;°ž Hê" óþÀ5€r¡,V M8×Ãà¢Ñ¢ó#ª�G„%¢À�‘‹$À1À!7œ �’ Î BT(‘QA„"´º�bAÁN”XüZÙh@Si<.$4 .$8šÅLDƒ8“ކ„‚ކ’f:LP|`ƒ‘ðƒõlv"`sò�”ô”” ÕHðHLtŒÈ¬R�Ya¹™ŽE`èÌDfe‘È<¬¿´P  PÒIjLP%Y<¨bÒbZHZ:v�â�Ū-ÊBI™¢Ò± +èñ4Q9*“ðøP9#Q鈨T *)šÒpâ"�”„ ޤ¤c, D N@â)©j€òQÒPÑàÙlÒAÈ„HHÇ.�ht@B:6aH9ÿp‹ �‰Ž�ŽUÐ;™¡ó% ÑÀ ΋-� çš°u̅ʈ0À!)‰’B$8–̨4¾á 9°V6š 6�Jƒ�!ÁÑt|ÃACI-ž�f¢Siô@…„¦‚Ét0Œt4Ø(Ð #Ô©ˆÓÁH Ò`ÀAI (ÏàÃÀ†cFc$Úh˜‰FX`DHœ©#yCI{ÒÁd*0*$ÈXapÙè ¤ > /#ù`BÊÆC®ƒ©"ø��"�*5¨OmG2ÉÀˆ>ú2£¢ ! +hY©àò¡ ÅX˜àâÂAA1!夕³ëÉÿ4›Õ=Ïo1Û—×Îue÷I+¨Ï–ßkù¦�¾ ½šrÝúø}a:f/~îjêõsüÉ õpB}ô´s´Ÿ²‘í�QUït¯›¿Ý²³‘•ÛÏí7í¦?ÃÅj:­â-ûúz³{KVÓeü™¦hèö‡æŠ¹‰úÌÜߘÌìùk¨ÆßŒÚ¦¦ÿ—ž¹þ™îÌˉv¶§Èœ¨Ìÿ;ýª/fÞ^ã{r.Û¿&'£#ºn²ß¹+gcg²ÙïgšßúKÍ^D3<¼©[óòZ�ÑNíqµ­*¯w[ã®ËSÄïµ=uo³ËSésx¾ÔìÔíuž*s®ãŸÒRñtsÙ7›ªô™”yJäÔ^·h‹15Ù—ÿ©ôÉö·åš¦ëwŸi«ÍTúàòÏIÕ�—שz:óÂãI¯SúLîçܧÈë–në·Ü‡·þ~!zææ2þÉW{¡{N¨x¹�ýðx­+ÿô¶Ë=·m1êºÇÿé|™~NûÜyÌ—èËÿSz™|õì&Ï�ÅÏêò3E˵ö›ö§ôq_©Ÿê>¹¯~vZÞa/sŸØôì×goçúöüü_Ê>ùçÝ®VO÷œÔ'Ål^Î6å½ñ®^Oéóz޽ºîËÖsúÝk¾U]œžÊ“«j.ü�¶Óze{N‹ÝϽPwÒÏ_=Û]¯ŸÒçuÚN\k¦É­ªË]Ñn%æ%çúàžîúµßs[ì¦ÉÙºþë�í´_Y¿—ãõêäÞ¹½©»®oU÷^�Ù×ñNŠî¹Îw·å‰:=Ÿ:ÞŸ®3v=^·¨wؼ™Q¿uñVZO—»† õ¸ß–6ªôÁµol^v®ïŠ‹ËØ§óô^{¨ÓßíÚ÷iÑÖsŸWÞiæ²{~_w§Ó³Þ½ÞkÛº{]z?åÂ7MVïÄ_|?!Þú5• +°™ ós\k�þ´KÛ /5õ–ÿ4$—‰u«)õOz™žO"0NL"¤—ÉÔ'|v$N¨éåÓ�O¨Êr=»ßïÕWÚúå®7^·úúñúUéswf™w—·Ây§ÉÝÛÓ¦½µsf'«5ö‹$Z·ê„:¡N¨ê„ú8¡N¨ê儊8Mík×õ[È;íºu®¾r.Åm<î»ÿůìêl¯î½®ujFTÿkÕ^ª;eš�ùæê„ÍÏËn¥Ï”«Sfzêä›~hÛkÇŽêˆlæ¹ÞÖÖ¬Y¥Ï»³#/G]vLß3[s4×Õ¹šš«ª!ã½ÚJ+“b¿©ón#oó¶òýBVíOÆ<[Ý�üc}Æß\DO[Ç:᯳vZ2¶½�NmßÉû9›ÝõZêó»Ý²lMV~[†=ñ¿ÛãvÚ1žJ+S^¿½ïío³òâÕiÙVýÖî­ªcûõö©ôÁl½mÙ Y¥Og³zÿÂ>V5ÿGÏþ¶æTécïꋘ›®Žø:Ý­mNn®é»ÔvúóõsTÃI›ù:u¥•©Mû˜û¯ßS=ÚÙ†­»Òy:FÇÕ¾Ã\ýۻ̌½V_&åNcn´d)&cÚ“f¸úDì3^œYMÊìlz~8íjVÓù2çB?ìÌ^CÅ|;Æ©_÷v•õyý_5Ý?þ.t¿µ5\ì…ö'­L|ç§íëÞÎûÙ8q}2_~c/}o}CÉeò]5=_‰Ž ÏpoO×µ×cV¦¨Ê·Ô9Fˆ|N2BB2 +œ(ð8 -Èñ=ÕeÞæ¶n³šòú,?Ñд»›q!ço.dCieBk|ôÍ»…œÕÔæ|Æk8�¦1·REQ”$Š�b¡€ +b&Ѩ‚LŒhaEH± ’I™DH‰‰ �D.RF ªj$ +@ÊÇ&Ûš©íI+Øùÿ‰ÈÜ+õnÑn¹f&ï}¾«´òy+YÿV—Ùv¶±fçõ~§�øéŸköñ™êRÄV¾Ûÿ[Ãeií¯Œ~Øï»²ê{š¿Þ6Ï»[ÕÞÑzý­ÍÓ–¿vîòDõlsÃô[Îo[ÜÕC­²}ujúï½VÓ{öó/L½Ó³<[Џ©ß¿uÓïW.²ï!êd·µšXýqsuz{ßu×óµ©ÕÔÙ~ºwž†¹ëSϳ—õlûÿ�W“wîdÊ|Ç+­­ó?qYón·Õ5Ïúì]&Tþf\i[�Ú±ÿˤ®†~š¯¼,¿÷ð.Õl¡ïtìvÝ|íœÈv}¶¶úÏwÒ3ãÌ¥¨Õäˆgö¹y˜ÞÞ÷‹=«é/5WZѼµ{[ìÙ™Æmí缯ow×—¾>wñ•3w)wªõ:Ýk}[ÎÌÅØ�fÉûÒiKW+ÄÜscõ5­&6ËÍ³Ý ÿ-oýõ”ÙWZÙÖûïÜ�üp{ñ67Õu:u^kK­NÕÿ3‘ÝMýîß?óý'›ygëÔ|̸þ›Ñ~™«ä2yŸ§â¿i•}�ŠöjˆªîüŽ ‚9qËŠêxk‰êŠûilK]«Él±-²±åûîíºÛI5•UOUoyͲÍXu»—÷uá-Û»ïeöZ×jºÌßËÝõ_x;�¯2殯}ÅÛéø’±Ñl«Iy·WúLh¬y¶ëƧ~ÝÓî:êa·õR{Ô]ôÛ^»Ûk÷§Ê¸Œú‰ˆxv–†¼¸¹šïTúL½¹jkì3<|Wång7?L�RÓVѲ·rõVt][|³»Å¨“²&÷êzêú[ÇïÛ×ìûFD¶SåãcNuÎ_ºöŸk_«Éµs}ïÓ½[÷»×üº¯ïc³jê.}­&ecÆ6{{eKSƼ劋èjÿnªÒK7®ôSÝéãÃü1?Ýz¼zf‰ývǬ¼ü˹üÝ,�¹±½Ñ—s×þY�[]m7×”Uû>—³NëxɎݬÒGuOÕM]W'·®æ®æît¶[î]‡[]?ëë.ßfÝÆÅ¸•›ùöêºÜÕÉ}�yçVÓ²™±²§ázÝlãnÝjÂûV�^³õÛ;ÝÖîVSÞâ™.U�üxÛͱUqñ›ýZ²n5q¿³Þ-kjâ¡·?ºíúÕIñÏ/M}ù¯¶JûkV<4õFSîɷÖ}—†z{»¾ØÕõ^¥Oë­}í®úÓLO½×�«i3—ÿ¥�™æ¥Û:ãjêÎÍ�,×ÿVSÿr[ãßNýÞÿýÖÎÇj—‰ÈØšè¬Žê¹ 7QÕín=î¤êÝ­‹}«É}ß}«Ã=Ë�ò¯Ñ¼ý\W?#3»:úòÜi™ÍýŒ u¡%ãÚ¿­c÷ö»sw>[äS÷Æ}Í¥‰ÆÞku'tït´Ó­&ÇEý•ºšxÿìîëq«‰Û.õÝtßðxyöíù{îÞYþ.»eûƵe¸ÒÇ-¿UÙt¯ •mÍ}›ý±7¯ÙuOm¯=½ûwÍo•yõ9ýÛVÓwÞ£{âÞkû1ö+kþÛÚVÓ¾²³¶ž*º5;ûÚ$9gäeÃìܵ9é¡´âlÈ·ºío­«´âišëÉù¶öuú~ÔîÆÿ\×[M‰‹¹ªÌÿ·–÷è¬+w«ÉúXÑVÞJ)$fØ–¿÷§kÜŸÛiöyk$ra�I QPˆ,¤HP À„�)#–”.)d&Àx°Àp”„~ïØÏµyŽÖ¨TQ&Å©X�²$TJª™& ã0@$ eÂñHÈYà€�\,HD4"†ƒ¡` ¤(!ˆ¢0È Ä2 +!« È¡×öª)í§vN}Óa©/&+ @×(�Э“Ô;ˆD‡XœnoIjßp“T�¦|aLÒúßÌ?boŒ]€2öd3ì&:v8#<%í•þ‚¬êi–MºDÆZˆ­b}ƒ&ë'ßÌÑCU£qê&úrùÐc<+Ù¸;N0åH(¯C#‘ZîH” cƒ+–ò‡¯ÑClÈZ±ñyÝ?9æJ+¿Þþ�Å­A +Ï^ní|;Ñ8|ÉÃT!ž+-2t6-Zt¾öÆÿD/)� ¼IN‰- ŽÀKEôUMå¡Ì•Á­ê©?!mf ?ù�¸º•¢ˆ!ûЀ 2…{}¦ËöèÆØ_³–„2X}…#ÃKÚú2g�PÀцǞ½€àj¤„éQñ–«Öm±R£?%«˜§v^ƒ�— ug�êØ¤'É{Æòò�P,Àl+"¹†»W» îWœˆ˜½:’7ë£dèqñ4^ýü^ƒ­?@3ŽÈ=¨ ¦èûæ}Dá±µ̱bÇ;xs2r2q�ÿb Ù�Y¹6‹—”{•ch&C¶òŽ£®_>Ãê'0RÆLÏåáèp¬æU|T¥„£(¾ÍÛ¢‘ Z2`mæð?áÌ®…D=ª©3’óSN•Ø`-³óŒÄÇ­ïB˜M¶N B.øÐ0þ$‘h ûˆ•ý$Íïfjm6œ/ÜËË¢Œ‚¬p…åÝ™ÖÌÎE}wÛ%ÎæZ}Æûr¤["ÝJ‰‚~"©F…t�b˜k°©L$`2meÆk„$§ÜGÐú´uK¢ã¿ÎC䱂’œf­4T?'WÔ ½�ÝSD +‰î:ã<û8Qœ¸BßÔJ�˜>P“uCô$ÃÕ5ÈÊÌTÔÓK³È3Èñ¬ÖT–„á-ÐÞìƒó$FÙ%Õ/™$Ëý*X—z¤^Zðõœy!‚¼@7�y9ÀcÌŽŸA6QwAˆ‚ª¶s�óMôÍpÞ×ðùÍ|D­¿p4÷­‘aF¼E~˜À¶±ú«†KÉSbx¯ñG«q¯2¤—æÍmžf a÷³^ïw©Ow”g¸W¡Ê˜T£¹ü¬F +Ý;�suá¼,BpÏn%‹=+2B#K†íE1§|¢a©¡¨Ïwí5iâ‹¥ÃQåJÇ¥pí…mFd:Õ©!ôŽYב(©!tjVøuŨ„+£Ô\Q¼L¨Qv�Ž\&f}¬D&¡ÇùçÎq ‰íºä0’½r=h’Ûl“¹xH“kÓk×鑯û¥¹\–dbÄë�©©\fÙyÛ€fËO³¸m®û—ìâ˜ÂÂ\%K«·#(´Ý©#•-Å5Ì(UÄ|³˜Ï2׆=Þ"–·GN¦__i,Îù_µ‰dè³RѦÍyµÚ·$œþQäé¨a`sí®�¾‹µ3bí +ÌÝ2Í¢i¶#b€ÕØBÈ/2Œ %²kÍæ ÞÆè|X°·Û-ËAÒþ’S +…žUáË ³U;™V×5¢\ÈÄšW¡‚—b™pE³4 ŽAÍ,í~`È9Qªt°\±\˪‘7ZÉN»®Y£å¼~èâÇ´7;$‹ýD¶´lZ„"}ÞKoÓã”ÒÎÖ+\ÔæÅœrºª� dÖþ +;x$.­P�¤ EmQŸ'ÁƳDô0bbSuYÚÄ‚ˆ¤ÑO¨ hÜê2 £Ar¢bù÷Ö`Û�å©TŽ<"[*Û®-3dE‡šÌ7b)s-)Jjòaë•Ì#bâ4¤’rb+EO{·ns\cø5b?²‚¤!bñ€?v.éLGrý¹§–D¿lB$æOÍÊÇ©âþI¢Eë¨Ç÷4Heb[vጥU?Þ=n/I$:©€ü»Zª2vˆ…˜uexb¾©™’=Ö‚ýt@ÆlûÚœdUÌ<{D¬¨ž ˆ/¾èe5©œB?ѾÌfP<1c ¬¿ÓøX4-Þ²Áz¬ß‘§�*ý|çÃÙJ1{“]¯–;©ï¤q(MˆåÇ/�â#ê„$šÎä’|„Öez§æ=qPMô–dÇÖ‡PÕÇžA¯b²Q}¡Î)HÃÑ¿î�¬¿^b”O3²§©ìW“øÏ +ÎmBÚó‹‹»órcý˜Õ9· ¬$9é4º£Ðð1xÇ@`gTÚèvI[Ÿ\þ¹eÛ• p$;J)PXƒ‘_oË! HUV5î\þÒ‡oÅHê#¹›;Û‚:>¢æ'ßÿÊO¤7òC®öÿ"zpÏœÙiC‹9�Ià¡êÔ´8ÝÂâ£_b'PÕ!‡oE®²ÿ!°F»ëÿ2‰£dæ9O9†HáƒþBp"ŽL Þ�fí^wó¼‹Ýgm™¶âe¶=¸`ú<¬“û�„I;Qÿ¶|4µ[‰ˆk…,ñõi™0Ó øo¨$J†¨³LdÕ�8C}/J O\ÌÉâò¨D#£ßÞYÅáá*f×�¾§èý_P$ÊùO6.ÝÃÀ{Í·Ó‘…,öcž¤+×õéé«…¤„ ÅÄnGÀÈç×Ã9ØC\u€�næ×Vˆš»ßœ´„ 3õ4Á­ª�÷P€�R·ÀÛpùEÊ;ÝY¨/ÙQœâ +-¢‰R2° ÅYváQsBµª_(ú¤Âû�5H\É ì©›�Æ É&þÕšgÆ…¢N(}f I+èRO…hðfìÓÆuéôF'5sU1ê%ÚQ”êÂüª0$ÝÃñó›Ã¨Lÿ4i7Tþ0.ÕÞ�ažäú²¾3’h»í\¨™Â"—Ö‘ l×Àß»1”xFÉæüËäŸÃŠpˆág­GNÕ3LIÚJB sר3™q…N”ͪ4æ (^ˆuç¨] êU£ÉÓé¥äœÁZMN˜=û‘{`Kg@¯tºó=èÓ®vF̆­E:[°·z'g£®-#܉ÜÏO�™¿Kðš°.óö¯iÑa™C-ëa<ž KÇÍ&À�ÁnÁÞXÔÛ)S9 +O½ƒu\ vµªº°wÃ{’‹çÚêàÔʪG«’BMZ‹ƒ7……i*UB-f¯’<h;}+n½”9€_Ú9°ïNMÉ xƲ3ü¦¡ÐòN6ÒF¶CÙ¹—ßÈ‚D“KPH&K]aù@‡Í Œý!ȟʾº]¢Òו£æ’ìåÙ!?ñ¶ i S×£6ßDX«${v´²7(©hìÔi<µ%B¸ ä—*uÇj�Tr´Õš¬t ù`ðú!åIìÏÚ3NéSܺ;˜ó­.•#ý4•t¼BäùaHëK 8Q­Ò¡µü¬{|Á¯–‚ã𥤲&K†o°t7Þ-ˆ ”·s’ž¦ƒh¡Ôa'µã‰v�ÍANÑöµd†KÔ.a3ªôè .ÄÈÎ Sðb]_¬€‡ø/ÜþÓ8î(Féq{F]¬TÊ!¥ÍK–ï‡ÔÇ 1éÄÉ€±=áˆ�©u( +f ø“˜‰ììñcb�ø.¥Äì;^:^VP¿c×Í.µË¦OÂò®Œ>‹>uõ÷�à­½âe‹*k•>bf‡#ðê�·¼"X”·¨÷�´�ÚP>ƒbî@›0<½ Õ'Ë<¬OÞ E1&³}¬> (‚æLQ¤ákªÈ2u'hIdŸX(ÍÖFl=y,¿õ ºò5õZûÂþT½™*EU8rž–þ…M,ý¼ò×@üüÒDVȆ€VŒæ>vV%²‰§‹€¥ÂVy'„S»D 5óÜ[™lg*&>'Ú0Šà�z{Z×¶‘S¸Å$æ1ƒ+e loKؤ‹ÿG‘‘Fñ ÙpFºcw·Ó(P;_÷ ç;´ú–Ã%¬÷‚øJ{®«¾‚,·UÁ Û)Y…ÞpÕÒ‰ýVEûªg*Å,ª“Ï>7¢)¡£ýÜâ»Çã"©×SrTôHQÝiôƒ­ ê—UàÄ!롚e4“ñ5�úÅy$åÉÏN×Ðí;ò8Xñ…oŠ-69*ÖåmI7()IL#^â¥,6jÞC %Þ†ZÛjB“CÿÑ·BepËÛ7“:Q¼5W9ÄÁ�@ÕÉ ˆ?Æ;!iZ».' …ë +ÓS^¸™÷Â^Dñ3ÕÇ.ÆR•áÝeFJî²êH9„ôÄPÈŸ¡›¨ñôŸ˜¾lpÃCFë0ý-y >ZVPp~ ‡œJœX˜þ„ÕÞ•�”ðé7YÂÁ¨M‡“© ”šžØL _I«Ùí¹Q=sbP!.V½ã¢øý‘Ìr£UîbŠÊ~ß�5îœ1G~à +Ô(Q4q øúb±&¨!“ß‘®WdwÔþº¾‘Uß’j£,u[Á°I�ÍUÖü¤TÂVk˽™œÐNš§òol‘2<¿–­‰¿—ÊEH6#‚LÊ™¿¡± ÎÁ7«º2Qƽ9¾3Àñ÷1AJ'*Å`ƒÆ¸×²eþ#½¡Ã :ÉåQ·Ð·mÇW¿üÏò,šÚ ¸~œ‰¶v¦xðJû û#+›0œü¿uqdú×âUY�ÏÇ”ð¢\¾0 #·@ÿM,¨oï9'¡½ÜصZ¹¥;øYF‹Hì8I�­#*l¶xþ0t�¼Ø?Ìêq@áøÛœ™|!fm�é7+°çÛ“5 �ð*Øœ3†‡¨B\—aN¸êe£ãÒË“µ�Ù mqƇ@Ãtšù˜çë fÇ_tË”‹fú�Éu㪚(ñVŸŠÉJ.œ¾9á©Ul�[™ª6¤oZѹJ‹ ¸•ª�›‘®Ü +�ÙÐO©.m>×RI . ÓKØ|v<*NwˆËÔ.àøh >^xß/€^ È8/~èà ˜sSXK·©ƒé°9Aµ¦¼ +�ðBræ.]•‚: +' ż˜iå?×4¢º?Rœ<§ Ϧ~®ñD…�ö Sò[gV!cc?¬ËH›ä¯p/|y‹ e§ç*äÂÖ(\ +ÙîÕ«dÔ¼2★ùŒ�¤ÞuÙnDM«tã½Ì ϧ¬3Rf9:'¸ôhC!x†•ðÄ}TŽGxy¤‚5s†²È¸ÓR­#E£9æ •®è—åÈüf�1ÁYÒ€M\Àúèç±ÅjWØÔ®'3*¼:ØÔÌÃ-… ÛsF¢éñË…íúhÐó +ó[·0}£6C÷7݉÷æøÒã¨A¤»ÎËj~`JËL`*Õ0ôHE甘byw{ó³R™ÚGÑé4̉W¹îñ'2A¿¿©Ñ2ìé ~~C@QºáFùk¸ù£Cš+NpAçˆn L§3ÂÓx)KöC§™S²Ò€ñÿTU@y [ŸÁ¤€[ãøyEéÊ™‰WHªÀŸ³c„óÔcX*3=2Gžx´ÿ\"SÎ/Š¥âè¡Å£4¯o6J¤&W4Y”RQ[䀥~Ží +ôè�­&¡¼~Ó�¥Ãâ™Ì±š‚áè™�>§™60fhNþ1˜¹=Ä)QCͨ:û%øÈT6E ÌÚÞÌ�¿cú\:!@·5 *£xÓ…Žåf[„Ìd¤N–T¡.åˆü)@s}ò‘!öÎN Z'¡ °+>‘Hf¡o8ÈkªŽ†§šcˆòGN´8ÈNÑýïEÔ‰xP…O�p>$øˆ ¢R §Ñ¢¢â=%÷#c!†P% Nwü›£ZéaYúÒb.†Vp\·�¦“kKÑ5ªiŠñ-æŽpšÕ ª,ùe%‡ÿL p‘å45IiF+dе”RÍCüÎg¥g°*¢-Õ`HIÊni Ö·=๻v#0�u!úÆ€ÊK2ybú÷ßÖ�³ã¼OYÌ‘øz®Ÿhû^u9‘(�8žÀ#¹5;¤‚n(SÐV®SCIz‹Œ½¶“öãä·bÁÌä—Kà7²@=:¹å]‘LÛÉNÞɃ§ Æ¡é˜/%Ór‚bC5£ÜË“ˆÔ¤Ê¬¿nHf`aµQv†2ÎŽ§ˆ ?†{A‹*?ëSFÌHtÄ¿ïǯÞDŒáLÄ0brC×Dyh£Ï@–ÂíþËä"ï”ðÀ:—–&_?ûT_^)�³Ä¢$êè,’y�4%)ÈÄ8&„ê6Tf)ëWï”›·&cÉ.eE/Áô�"Þò¸<(ftm¸+jvÓ5×14ç!ÎÚì (pªÑ“´uÈ|ÁŒ—d©Ù~w*4ÇÐ+Ý3œÅ{îSÊëpƒéÇjÉ«ËoãëxFVøë§+—|?²|�˜!þ: É¿c`XŸ¢fƒ'‡væ—¯º` ŽÓû©ø0ê„Úó㦚iÚ…³t€Ø¦<ó»�Õ)˜¨\ºvövBuûoø +³T¤Ond{¶U­€É9]¿*Œ<=3(+§˜Ofà¸cù!¢m®ý´úÇaF ZɾÅ1ÁBÁP]3ÕºÞÃN齿X©Ýzb1ÒpkXáŽ;Íø¦ƒL_ßSâe‚Úìðø“ƒ|W¿ßlåçEYÍæfjjš ÂËu…ƒ´vàÄDp]dÉm¼ÀžÙv×(û)KÜhI€~EõG“ïy†çØI‹NëЛ(vwó.©šO8äª>B yÉá|'ÿ¢7Ùc�\Þ(ðš‚.ÅÏMžÇXsL-¹0690öc §ë?bøŒ¯`N˰Q>X# GÚq¹ ¾<ÚÆO*SA°ûåâŒ#49 þîïêÀC¨>ŒÐö>°=„.àâ©5åB8–·4ú�RʼYX1–³�–¹r]SÝ”yd˜�3w‹Ó˜.Ü TžéسBe¡§ç ï�·x)ªš¬Mûüè +}oyš³/}tDÛ«/ó‘SB)un$ËCŸNC±‹â6^ÙÿVjó«NÕ1j@%®wðó5ýmàV¤PЄJ~�¦½b+.òN„2¥Ô?çaJ'øiyþ]ñ˜Gn96VfrǨ“6ý0ΜºÉc¨"l1o¶&”=”�;Ѿ `íúwâWKœEÉ•çf;`Áñ,×ÐEGH Ãè¼â3ð20¢ç$Æö½<×~W'ïïÑÞ÷Å‚ˆÞ!"�ÕŒL,ÂtôáobæÙ1äHU÷À\ Õš¯ªH=„”–6äĹß!€aéâe:¾ i(àº­Ž”‘EF>¹ˆÜcKë*Æî#¼ø3¤L}C1b#PmðÔO˜“í\*I `½Vf¤­?«ÿj#• ¾æþÎxÝVT¡çŒ–ó_¦¿’¾Z7Š «…Ó/Œ ôú%ã·0 š3Rð¤ +Þ¶’Ò¬SÁý–@}%ùñÒ&Û7ÄÇ~�l8Dè«ð/|`vÓ”©µV7óìLLK‹äý�ªé‘ÑÓ\!}~5LDHMÖF…MÔ¯0ì_ôb€ýŸ.:ê%têíÚ—÷7>†GiÎ¥–ùñÔ žà“°CbR ë)¹™›hYpD„C¯þr€Õ—ï{�;2€~&Ø:mM€+^²9Ä/Üå¸Y]ü§szêé´#GE¿„JÞ“ÆTíµþª6 ŠsLWâG/ÚWdäÚ G•9ÌØ¹ioˆ¸WŒÚП2;!%»âotá;R²~Jǰ3‡më9SÉÒsåËa©á„:ø^@¢ÖàRâîÿ.—.ˆÕ¨94̶ܮ¥^h̆-0”WTÓ–,jûöó¬FvT3õ·§‘—ëž�3aìfinˆ· šÐÆ«0%·¿™2¼ƒQÔçPÒgÛ¤a±²ðk~¸Ðéø)RÞ± *¯Ö$î)váiÓÌÆþ�å  ySâüºØâ|¯B¶tÒœC1±¥<(5úØúhÏÝWC ofùг_ª¸ý® œÀæ ¢o.}þÐ`a*Û/qt�z²[f¿Íh;¶»ý´càKÖöör;¯ñúþ]ÞäU`ÇÐe¿@™Œ ºýbR¹¸g¿SµýJ´‡j"–/NVuB>å¶_ZÐku‰Š…š�eb!’K~ïO“ÉMRÙæ¦ä²eQû‹rû% +1UñðZfÉ~?À%èÔa¬‹¹ÖÜäÌ®ä(u²ïéÆãíwM"·Ø&”¶ÚSÔ’ýÆ šäJö 5¦©›êC¦M'ÜIŸ:JcÞ”ýQxûÝdLl6RÑj7{»|¶~²÷o¿¡µ|Z¿9OÄkûý‡ ó(‰g¿† Û¯û +Ú[}Éo¿…e¿Q—~’¸õ»f²?o¿°Úerd¿Úì}!Þ~»PC  ³_wûe)…’ê©Wò€·*ö£·&<ùXèâIÅ´ÎçC�°ývlTôÑ‹Í^fY©Na·_òH0+Òœ¯Îÿxß~‰ŠÄ´u—„X³_ó‚í×(‡Lb¯3ŽvläöûlE4?•Þ.Ê-Å"i²sÝ~sÎØ³’lÈö4TDÄÅÑì×›®Oÿ©cû="Ý'[2熗ö‡Ü~uÁé’ç~7C�ýò+RÖö;7ׯJwÒgÑMŸ ß~·n éêà +)R/Ø»¯›Pz¦“€ƒ ¾:뽂ÂuR9„yŸæe‹„.¦›d³ÖMqm/8⦌ÏK¼ý~ï­j pþÈEc6 ”7™Ç.%ÝÉWô“ò¾ýnù�#Hh8ìç|kö É3VÞöûo\„(œ&W˜Úº Gëx£'3+otÝDŽ'ˆ°íwÞdz”ݪpû½¦’þ„dÖ™îVo¦TBÌR*­/‡Ó�`šý>�em¿à}‚÷ýëI�§íWå;(ÇLsÖªÚ" d¿YÛ¥ü¢F¯ðü0DŰ¯ôÌ‚·_G¯™ÝhÌ¿e¿¹ì°y·ßå-©¼Ó‘“’·7o¿…ÌÙWýøÙ” h×Î8¼Yîg¿Û|Y— +‹îo¿™ÿì× Á;Ö´ýjn³ß�)\4޲Ûol|(ñf¾+ûMÚàCÝïËOfÕžýŽœî~s]ÐórŽá¼he�B,Ú¡[!­&8™¥{‹B[ä‹­õìàÐl‚‹_G'£�ÂwlÈ29&Žê‰jâ®Ë¼™¯}q¿Ý5@Ö9að +ÜkÁ×0ß©ƒò{#³äàé8ØL0ÉNŽô× +0Ë©DŠÄ`Úàö©¾¾z#¨™²Y9ûþû$gò ½‰{®k»Ôäø#;<+ooÛû>¯^-iUUoAIʵ°`ùËSàŸç.Yúìsõjç‡{+ŠÆ÷‡ƒZU ª± pýx€ûØ&†JÀ}/í·'š¿›l„(Œƒ_ÄÕ F)äJÂ�Î0Æ\¡7 ̈ªÑ€‚Úbú�R~_ˆ=ßâ G/C“—è&Ù$ªvM±}!¹ª3)©ŒXFȤGÜ›AUž%©³g_œH˜K®L¡K³S=ec‚3à!‘æ6ùüGdºð£H±þ|5PÛšx +™dX ‘¸X·vL%?A(VÓSí ™lvË•OÁƒ›B’È„¢˜!“\+ÂÑ0?‰=tË&oJ ¢_–�>ÖEÓ‚Ù5ºÛ3=‚¥IûfŶÃaÊ„ÓnûêÁëSP?;›&Áy„¬öKשÒþŽß‚‚ðU{OiN!¯Ò´jº·!: 8[Ò`Š P×´í +—¹‘àÅ-õ4ÈÚ³; ¹í,…�YÌ(7÷ç +»š:þg®lz} ¾ò}…_ŠeZ!Lø�¨°½&‡£‰†–äÐÁ„~™'ú‚ªcWÍ6¸z²×IÜ¥”žyN +u°„\bÉ�“áÛP!þb÷Ÿ«„3ëõ4ÖýUwÝäê_œSÓóµOIjYàdœŒè<÷Ôo†'Çh:¼ìÛ˜¹ný@@ß6ÏðìnÂñ§Ãp×kå$€ë7¿âÍÏ=;§?èØÝpû<]Éĉ5ýêÜŸŠÛÀ\†ŸO /?*ŠÝuÏ?ñ¨êÜ’y´ÒŽçóQC|ß;P Mc¦÷O. #TŸ|,¨AÄOETi>w$*€ªfð5e¬¾‹iEäÔ@RGA4-¯Íœÿ¥ÔE©qÇØHü½%%lâ‘­«‰‡%Çûp†@ìb²óO(Ø<š;à?,&Ý’¬Ò­øë¿C3r¨kò�Oi.pÓh�1 |dÔä�Ú¿W`íí¹:Ra,Ξ½ÔtãÊećè[Fõ.ðŒŒ  ùµ=µsí á+Í%QnÖiU@U½7µ*óˆ²÷4>’¾I�Ÿ-}ãll“¾(„å¸Ip6g)ÕQ¤r÷•çëßÅJäÈLŽ?²ðqÛHÐOˆÍ! *J¸å5½ ™(wé“_ʃsü¾ì+×Û{Åý~LéØÈ}VüÑ2Δ» ¦Ø–ÔK¸\0ÎÝÁ�Ä•+wõ�âœÃtB˜!òÉŒ¡ù•wΰ¥jNÿ«"foVââ>"39�³¸»ëƒÝýÂM”}�@µ&åh)øZöSŠÃÿðÒ÷ÿõÎÚ“iR‰0­ŸÉ‹ôotÃÜ„ñé”P�‹qõKòŸufà[åÛWŒR‘p“aM {³·”Ð-jiô²§-)ÿ4û«­)oÊÒ� ¶ª›þÇtÕŸUsm »#¿šf—³1»ÛËxøÔ]Àe9y§T¸º«=�iÿÛyÙ][· CÁ¿¿��8FØ"—Ã(fX$í–!VJS† +™‚!—à%= ²½#°îµ/eð®?Nm<ÙÛën$÷ÝxO#æs +RXtì}2^20_ŒÌôœ²cB©´CV:›R‚ôè´Øa�µg]ìcˆ£0$ŒŽ˜¼”>~Ú®ŽÆßéîÿר±}“ØŠœVØÁ�’Þ œ9 Ó4VVäP¤*µQQ×–;-® l®íxº]uI¤Ëµ…syºt‡($D]°±òCc*õtﲨ‹ÒOxÓuÅDÝ­?H\B;ìÓ­t¸u ê¶ù�}Ê +bqJL& 3“RvmzšÕ'“XËÏjÔuôcÛw-í¼‚,±kŒDrÔuEßáKaËKb�ºŒfUÂÙÄh�Êf¹¹[à1õ¨«éá"Åk–5‚ïʶÃGækpFÝE¬“�oÁùZsÔ�½ºs1N!%·Ù¨+p e‘vÝÓz¬ÈQw5½+o/ZÉÁ¼ônë1Y;) PËÂuÙ*}ÍkÔ��ÿf29ðt{¿ŒdGÝþ ËMã/—�ºîªò¨æMÝ®ŠG]d Yª*!¬u„|[£.¿~èÜ�u¿!DÝkŒ6™B*�ÍEÝ•¥Øéiõtÿ5펺֘iTíLp9ÿ‹G·•!º¼ùâ£.pgç+6ŽÅÔŽº=Uãåz!Ë 9©Æw�Q— ¼Úå3tíxºŒ¢nxynùÑgN¯Çº=c2fViá肌• ³‡ö~Wœ ´Ù¢Ã’a¤yj®ÞÇsÔ"û:˜çÖão €Rj‚è”/Q¨OäÂÀÈE3T9G»Š öãíE8EÓ÷oeW™¼(K6›\½ˆ^ä¬cw[ô?Qq­µ3hr|KA8-Ç …Þ•_°ÀážÛ°íPwÈÛ< endstream endobj 29 0 obj [28 0 R] endobj 39 0 obj <> endobj xref +0 40 +0000000004 65535 f +0000000016 00000 n +0000000147 00000 n +0000040637 00000 n +0000000000 00000 f +0000040688 00000 n +0000000000 00000 f +0000046158 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000046231 00000 n +0000046427 00000 n +0000047598 00000 n +0000113186 00000 n +0000178774 00000 n +0000000000 00000 f +0000043171 00000 n +0000215111 00000 n +0000041070 00000 n +0000043475 00000 n +0000043362 00000 n +0000042257 00000 n +0000042610 00000 n +0000042658 00000 n +0000043246 00000 n +0000043277 00000 n +0000043510 00000 n +0000215136 00000 n +trailer <]>> startxref 215352 %%EOF \ No newline at end of file From 0cb33072f8c92be57d7dba4a4ff92f8225f9e9bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 09:32:12 +0800 Subject: [PATCH 267/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/FastjsonMsgConvertor.java | 6 ------ .../main/java/com/ejlchina/okhttps/GsonMsgConvertor.java | 6 ------ .../main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java | 6 ------ .../src/main/java/com/ejlchina/okhttps/MsgConvertor.java | 6 ------ 4 files changed, 24 deletions(-) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java index e226c5f4..e138e701 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMsgConvertor.java @@ -33,12 +33,6 @@ public byte[] serialize(Object object, Charset charset) { @Override public byte[] serialize(Object object, String dateFormat, Charset charset) { - if (object instanceof byte[]) { - return (byte[]) object; - } - if (object instanceof String) { - return object.toString().getBytes(charset); - } if (dateFormat != null) { return JSON.toJSONStringWithDateFormat(object, dateFormat).getBytes(charset); } diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java index 045c0096..e0792fbd 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMsgConvertor.java @@ -46,12 +46,6 @@ public byte[] serialize(Object object, Charset charset) { @Override public byte[] serialize(Object object, String dateFormat, Charset charset) { - if (object instanceof byte[]) { - return (byte[]) object; - } - if (object instanceof String) { - return object.toString().getBytes(charset); - } Gson gson = this.gson; if (dateFormat != null) { gson = gson.newBuilder().setDateFormat(dateFormat).create(); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java index f9827d81..35fe7085 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMsgConvertor.java @@ -72,12 +72,6 @@ public byte[] serialize(Object object, Charset charset) { @Override public byte[] serialize(Object object, String dateFormat, Charset charset) { - if (object instanceof byte[]) { - return (byte[]) object; - } - if (object instanceof String) { - return object.toString().getBytes(charset); - } ObjectMapper mapper = objectMapper; if (dateFormat != null) { mapper = mapper.copy().configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java index 9b1251c7..e8aa54ca 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java @@ -100,12 +100,6 @@ public byte[] serialize(Object object, Charset charset) { @Override public byte[] serialize(Object object, String dateFormat, Charset charset) { - if (object instanceof byte[]) { - return (byte[]) object; - } - if (object instanceof String) { - return object.toString().getBytes(charset); - } byte[] data = convertor.serialize(object, dateFormat, charset); Mapper mapper = convertor.toMapper(new ByteArrayInputStream(data), charset); StringBuilder sb = new StringBuilder(); From 61c04603801f204f532e664166214368c37b24d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 09:33:11 +0800 Subject: [PATCH 268/924] logo --- okhttps-doc/{OkHttps. logo.ai => OkHttps.logo.ai} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename okhttps-doc/{OkHttps. logo.ai => OkHttps.logo.ai} (100%) diff --git a/okhttps-doc/OkHttps. logo.ai b/okhttps-doc/OkHttps.logo.ai similarity index 100% rename from okhttps-doc/OkHttps. logo.ai rename to okhttps-doc/OkHttps.logo.ai From 18b20c35d63951ec25d713f91c4a12e9374c75dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 10:04:56 +0800 Subject: [PATCH 269/924] TestCase --- okhttps-fastjson/pom.xml | 6 ++ .../java/com/ejlchina/okhttps/TestCase.java | 17 ++++ .../java/com/ejlchina/okhttps/TestCases.java | 88 ------------------- .../test/java/com/ejlchina/okhttps/User.java | 66 -------------- okhttps-gson/pom.xml | 6 ++ .../java/com/ejlchina/okhttps/DateBean.java | 40 --------- .../java/com/ejlchina/okhttps/TestCase.java | 15 ++++ okhttps-jackson/pom.xml | 6 ++ .../java/com/ejlchina/okhttps/DateBean.java | 40 --------- .../java/com/ejlchina/okhttps/TestCase.java | 15 ++++ .../java/com/ejlchina/okhttps/TestCases.java | 88 ------------------- .../test/java/com/ejlchina/okhttps/User.java | 66 -------------- okhttps-test/.gitignore | 1 + okhttps-test/pom.xml | 30 +++++++ .../com/ejlchina/okhttps/test}/DateBean.java | 2 +- .../okhttps/test/MsgConvertorTest.java | 88 +++++++++++-------- .../java/com/ejlchina/okhttps/test}/User.java | 2 +- pom.xml | 1 + 18 files changed, 150 insertions(+), 427 deletions(-) create mode 100644 okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCase.java delete mode 100644 okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java delete mode 100644 okhttps-fastjson/src/test/java/com/ejlchina/okhttps/User.java delete mode 100644 okhttps-gson/src/test/java/com/ejlchina/okhttps/DateBean.java create mode 100644 okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java delete mode 100644 okhttps-jackson/src/test/java/com/ejlchina/okhttps/DateBean.java create mode 100644 okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java delete mode 100644 okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java delete mode 100644 okhttps-jackson/src/test/java/com/ejlchina/okhttps/User.java create mode 100644 okhttps-test/.gitignore create mode 100644 okhttps-test/pom.xml rename {okhttps-fastjson/src/test/java/com/ejlchina/okhttps => okhttps-test/src/main/java/com/ejlchina/okhttps/test}/DateBean.java (93%) rename okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java => okhttps-test/src/main/java/com/ejlchina/okhttps/test/MsgConvertorTest.java (51%) rename {okhttps-gson/src/test/java/com/ejlchina/okhttps => okhttps-test/src/main/java/com/ejlchina/okhttps/test}/User.java (96%) diff --git a/okhttps-fastjson/pom.xml b/okhttps-fastjson/pom.xml index 2ce76aa4..9c7a04ab 100644 --- a/okhttps-fastjson/pom.xml +++ b/okhttps-fastjson/pom.xml @@ -22,6 +22,12 @@ fastjson ${fastjson.version} + + com.ejlchina + okhttps-test + ${okhttps.version} + test + diff --git a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCase.java b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCase.java new file mode 100644 index 00000000..dc3e6d1c --- /dev/null +++ b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCase.java @@ -0,0 +1,17 @@ +package com.ejlchina.okhttps; + +import com.ejlchina.okhttps.test.MsgConvertorTest; +import org.junit.Test; + + +public class TestCase { + + + @Test + public void doTest() throws Exception { + MsgConvertor msgConvertor = new FastjsonMsgConvertor(); + new MsgConvertorTest(msgConvertor).run(); + } + + +} diff --git a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java deleted file mode 100644 index 0006da0a..00000000 --- a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/TestCases.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.ejlchina.okhttps; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.List; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Test; - - -public class TestCases { - - MsgConvertor msgConvertor = new FastjsonMsgConvertor(); - - @Test - public void testToJsonObj() { - String json = "{\"id\":1,\"name\":\"Jack\"}"; - InputStream in = new ByteArrayInputStream(json.getBytes()); - Mapper mapper = msgConvertor.toMapper(in); - Set keys = mapper.keySet(); - Assert.assertTrue(keys.size() == 2); - Assert.assertTrue(keys.contains("id")); - Assert.assertTrue(keys.contains("name")); - Assert.assertTrue(!mapper.isEmpty()); - Assert.assertTrue(2 == mapper.size()); - Assert.assertTrue(1 == mapper.getInt("id")); - Assert.assertTrue(!mapper.has("age")); - Assert.assertTrue(0 == mapper.getInt("age")); - Assert.assertEquals("Jack", mapper.getString("name")); - } - - @Test - public void testToJsonArr() { - String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; - InputStream in = new ByteArrayInputStream(json.getBytes()); - Array jsonObj = msgConvertor.toArray(in); - Assert.assertTrue(!jsonObj.isEmpty()); - Assert.assertTrue(jsonObj.size() == 2); - Mapper json1 = jsonObj.getMapper(0); - Mapper json2 = jsonObj.getMapper(1); - Assert.assertEquals(1, json1.getInt("id")); - Assert.assertEquals("Jack", json1.getString("name")); - Assert.assertEquals(2, json2.getInt("id")); - Assert.assertEquals("Tom", json2.getString("name")); - } - - @Test - public void testToJsonStr() { - String json = msgConvertor.serialize(new User(1, "Jack")); - Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); - } - - @Test - public void testToJsonStrWithDateFormat() throws ParseException { - String dataFormat = "yyyy-MM-dd HH:mm:ss"; - SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); - String date = "2020-05-09 12:30:15"; - String json = msgConvertor.serialize(new DateBean(1, sdf.parse(date)), dataFormat); - Assert.assertTrue(json.contains(date)); - } - - @Test - public void testJsonToBean() { - String json = "{\"id\":1,\"name\":\"Jack\"}"; - InputStream in = new ByteArrayInputStream(json.getBytes()); - User user = msgConvertor.toBean(User.class, in); - Assert.assertEquals(1, user.getId()); - Assert.assertEquals("Jack", user.getName()); - } - - @Test - public void testJsonToList() { - String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; - InputStream in = new ByteArrayInputStream(json.getBytes()); - List users = msgConvertor.toList(User.class, in); - Assert.assertTrue(2 == users.size()); - User u1 = users.get(0); - User u2 = users.get(1); - Assert.assertEquals(1, u1.getId()); - Assert.assertEquals("Jack", u1.getName()); - Assert.assertEquals(2, u2.getId()); - Assert.assertEquals("Tom", u2.getName()); - } - -} diff --git a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/User.java b/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/User.java deleted file mode 100644 index 1fcb6484..00000000 --- a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/User.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.ejlchina.okhttps; - -public class User { - - private int id; - private String name; - - - public User() { - } - - public User(int id, String name) { - this.id = id; - this.name = name; - } - - public void setId(int id) { - this.id = id; - } - - public void setName(String name) { - this.name = name; - } - - public int getId() { - return id; - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return "User [id=" + id + ", name=" + name + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + id; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - User other = (User) obj; - if (id != other.id) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } - -} diff --git a/okhttps-gson/pom.xml b/okhttps-gson/pom.xml index 3fefaaf1..fdf36c1b 100644 --- a/okhttps-gson/pom.xml +++ b/okhttps-gson/pom.xml @@ -22,6 +22,12 @@ gson ${gson.version} + + com.ejlchina + okhttps-test + ${okhttps.version} + test + diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/DateBean.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/DateBean.java deleted file mode 100644 index 2e016c80..00000000 --- a/okhttps-gson/src/test/java/com/ejlchina/okhttps/DateBean.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.ejlchina.okhttps; - -import java.util.Date; - -public class DateBean { - - private int id; - private Date date; - - - public DateBean() { - } - - public DateBean(int id, Date date) { - this.id = id; - this.date = date; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - @Override - public String toString() { - return "DateBean [id=" + id + ", date=" + date + "]"; - } - -} diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java new file mode 100644 index 00000000..1f82e948 --- /dev/null +++ b/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCase.java @@ -0,0 +1,15 @@ +package com.ejlchina.okhttps; + +import com.ejlchina.okhttps.test.MsgConvertorTest; +import org.junit.Test; + + +public class TestCase { + + @Test + public void doTest() throws Exception { + MsgConvertor msgConvertor = new GsonMsgConvertor(); + new MsgConvertorTest(msgConvertor).run(); + } + +} diff --git a/okhttps-jackson/pom.xml b/okhttps-jackson/pom.xml index 62d867ec..e5a2e005 100644 --- a/okhttps-jackson/pom.xml +++ b/okhttps-jackson/pom.xml @@ -22,6 +22,12 @@ jackson-databind ${jackson.version} + + com.ejlchina + okhttps-test + ${okhttps.version} + test + diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/DateBean.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/DateBean.java deleted file mode 100644 index 2e016c80..00000000 --- a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/DateBean.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.ejlchina.okhttps; - -import java.util.Date; - -public class DateBean { - - private int id; - private Date date; - - - public DateBean() { - } - - public DateBean(int id, Date date) { - this.id = id; - this.date = date; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - @Override - public String toString() { - return "DateBean [id=" + id + ", date=" + date + "]"; - } - -} diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java new file mode 100644 index 00000000..71f5d99e --- /dev/null +++ b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCase.java @@ -0,0 +1,15 @@ +package com.ejlchina.okhttps; + +import com.ejlchina.okhttps.test.MsgConvertorTest; +import org.junit.Test; + + +public class TestCase { + + @Test + public void doTest() throws Exception { + MsgConvertor msgConvertor = new JacksonMsgConvertor(); + new MsgConvertorTest(msgConvertor).run(); + } + +} diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java deleted file mode 100644 index c7b8ec3b..00000000 --- a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/TestCases.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.ejlchina.okhttps; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.List; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Test; - - -public class TestCases { - - MsgConvertor msgConvertor = new JacksonMsgConvertor(); - - @Test - public void testToJsonObj() { - String json = "{\"id\":1,\"name\":\"Jack\"}"; - InputStream in = new ByteArrayInputStream(json.getBytes()); - Mapper mapper = msgConvertor.toMapper(in); - Set keys = mapper.keySet(); - Assert.assertTrue(keys.size() == 2); - Assert.assertTrue(keys.contains("id")); - Assert.assertTrue(keys.contains("name")); - Assert.assertTrue(!mapper.isEmpty()); - Assert.assertTrue(2 == mapper.size()); - Assert.assertTrue(1 == mapper.getInt("id")); - Assert.assertTrue(!mapper.has("age")); - Assert.assertTrue(0 == mapper.getInt("age")); - Assert.assertEquals("Jack", mapper.getString("name")); - } - - @Test - public void testToJsonArr() { - String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; - InputStream in = new ByteArrayInputStream(json.getBytes()); - Array jsonObj = msgConvertor.toArray(in); - Assert.assertTrue(!jsonObj.isEmpty()); - Assert.assertTrue(jsonObj.size() == 2); - Mapper json1 = jsonObj.getMapper(0); - Mapper json2 = jsonObj.getMapper(1); - Assert.assertEquals(1, json1.getInt("id")); - Assert.assertEquals("Jack", json1.getString("name")); - Assert.assertEquals(2, json2.getInt("id")); - Assert.assertEquals("Tom", json2.getString("name")); - } - - @Test - public void testToJsonStr() { - String json = msgConvertor.serialize(new User(1, "Jack")); - Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); - } - - @Test - public void testToJsonStrWithDateFormat() throws ParseException { - String dataFormat = "yyyy-MM-dd HH:mm:ss"; - SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); - String date = "2020-05-09 12:30:15"; - String json = msgConvertor.serialize(new DateBean(1, sdf.parse(date)), dataFormat); - Assert.assertTrue(json.contains(date)); - } - - @Test - public void testJsonToBean() { - String json = "{\"id\":1,\"name\":\"Jack\"}"; - InputStream in = new ByteArrayInputStream(json.getBytes()); - User user = msgConvertor.toBean(User.class, in); - Assert.assertEquals(1, user.getId()); - Assert.assertEquals("Jack", user.getName()); - } - - @Test - public void testJsonToList() { - String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; - InputStream in = new ByteArrayInputStream(json.getBytes()); - List users = msgConvertor.toList(User.class, in); - Assert.assertTrue(2 == users.size()); - User u1 = users.get(0); - User u2 = users.get(1); - Assert.assertEquals(1, u1.getId()); - Assert.assertEquals("Jack", u1.getName()); - Assert.assertEquals(2, u2.getId()); - Assert.assertEquals("Tom", u2.getName()); - } - -} diff --git a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/User.java b/okhttps-jackson/src/test/java/com/ejlchina/okhttps/User.java deleted file mode 100644 index 1fcb6484..00000000 --- a/okhttps-jackson/src/test/java/com/ejlchina/okhttps/User.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.ejlchina.okhttps; - -public class User { - - private int id; - private String name; - - - public User() { - } - - public User(int id, String name) { - this.id = id; - this.name = name; - } - - public void setId(int id) { - this.id = id; - } - - public void setName(String name) { - this.name = name; - } - - public int getId() { - return id; - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return "User [id=" + id + ", name=" + name + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + id; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - User other = (User) obj; - if (id != other.id) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } - -} diff --git a/okhttps-test/.gitignore b/okhttps-test/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/okhttps-test/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/okhttps-test/pom.xml b/okhttps-test/pom.xml new file mode 100644 index 00000000..de096609 --- /dev/null +++ b/okhttps-test/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + + okhttps-test + OkHttps Test + jar + + + com.ejlchina + okhttps-parent + 2.0.0 + + + + + com.ejlchina + okhttps + ${okhttps.version} + + + junit + junit + ${junit.version} + + + + + okhttps-test + + \ No newline at end of file diff --git a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/DateBean.java b/okhttps-test/src/main/java/com/ejlchina/okhttps/test/DateBean.java similarity index 93% rename from okhttps-fastjson/src/test/java/com/ejlchina/okhttps/DateBean.java rename to okhttps-test/src/main/java/com/ejlchina/okhttps/test/DateBean.java index 2e016c80..34cfdb53 100644 --- a/okhttps-fastjson/src/test/java/com/ejlchina/okhttps/DateBean.java +++ b/okhttps-test/src/main/java/com/ejlchina/okhttps/test/DateBean.java @@ -1,4 +1,4 @@ -package com.ejlchina.okhttps; +package com.ejlchina.okhttps.test; import java.util.Date; diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java b/okhttps-test/src/main/java/com/ejlchina/okhttps/test/MsgConvertorTest.java similarity index 51% rename from okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java rename to okhttps-test/src/main/java/com/ejlchina/okhttps/test/MsgConvertorTest.java index f87aeb66..4f2d6bd1 100644 --- a/okhttps-gson/src/test/java/com/ejlchina/okhttps/TestCases.java +++ b/okhttps-test/src/main/java/com/ejlchina/okhttps/test/MsgConvertorTest.java @@ -1,44 +1,59 @@ -package com.ejlchina.okhttps; +package com.ejlchina.okhttps.test; + +import com.ejlchina.okhttps.Array; +import com.ejlchina.okhttps.Mapper; +import com.ejlchina.okhttps.MsgConvertor; +import org.junit.Assert; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.List; import java.util.Set; -import org.junit.Assert; -import org.junit.Test; +public class MsgConvertorTest { -public class TestCases { + MsgConvertor msgConvertor; - MsgConvertor msgConvertor = new GsonMsgConvertor(); - - @Test - public void testToJsonObj() { + public MsgConvertorTest(MsgConvertor msgConvertor) { + this.msgConvertor = msgConvertor; + } + + public void run() throws Exception { + testToMapper(); + testToArray(); + testSerialize(); + testSerializeWithDateFormat(); + testToBean(); + testToList(); + } + + + void testToMapper() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - Mapper mapper = msgConvertor.toMapper(in); + Mapper mapper = msgConvertor.toMapper(in, StandardCharsets.UTF_8); Set keys = mapper.keySet(); - Assert.assertTrue(keys.size() == 2); + Assert.assertEquals(2, keys.size()); Assert.assertTrue(keys.contains("id")); Assert.assertTrue(keys.contains("name")); - Assert.assertTrue(!mapper.isEmpty()); - Assert.assertTrue(2 == mapper.size()); - Assert.assertTrue(1 == mapper.getInt("id")); - Assert.assertTrue(!mapper.has("age")); - Assert.assertTrue(0 == mapper.getInt("age")); + Assert.assertFalse(mapper.isEmpty()); + Assert.assertEquals(2, mapper.size()); + Assert.assertEquals(1, mapper.getInt("id")); + Assert.assertFalse(mapper.has("age")); + Assert.assertEquals(0, mapper.getInt("age")); Assert.assertEquals("Jack", mapper.getString("name")); } - - @Test - public void testToJsonArr() { + + void testToArray() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - Array jsonObj = msgConvertor.toArray(in); - Assert.assertTrue(!jsonObj.isEmpty()); - Assert.assertTrue(jsonObj.size() == 2); + Array jsonObj = msgConvertor.toArray(in, StandardCharsets.UTF_8); + Assert.assertFalse(jsonObj.isEmpty()); + Assert.assertEquals(2, jsonObj.size()); Mapper json1 = jsonObj.getMapper(0); Mapper json2 = jsonObj.getMapper(1); Assert.assertEquals(1, json1.getInt("id")); @@ -46,37 +61,36 @@ public void testToJsonArr() { Assert.assertEquals(2, json2.getInt("id")); Assert.assertEquals("Tom", json2.getString("name")); } - - @Test - public void testToJsonStr() { - String json = msgConvertor.serialize(new User(1, "Jack")); + + void testSerialize() { + byte[] data = msgConvertor.serialize(new User(1, "Jack"), StandardCharsets.UTF_8); + String json = new String(data, StandardCharsets.UTF_8); Assert.assertEquals("{\"id\":1,\"name\":\"Jack\"}", json); } - @Test - public void testToJsonStrWithDateFormat() throws ParseException { + + void testSerializeWithDateFormat() throws ParseException { String dataFormat = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(dataFormat); String date = "2020-05-09 12:30:15"; - String json = msgConvertor.serialize(new DateBean(1, sdf.parse(date)), dataFormat); + byte[] data = msgConvertor.serialize(new DateBean(1, sdf.parse(date)), dataFormat, StandardCharsets.UTF_8); + String json = new String(data, StandardCharsets.UTF_8); Assert.assertTrue(json.contains(date)); } - - @Test - public void testJsonToBean() { + + void testToBean() { String json = "{\"id\":1,\"name\":\"Jack\"}"; InputStream in = new ByteArrayInputStream(json.getBytes()); - User user = msgConvertor.toBean(User.class, in); + User user = msgConvertor.toBean(User.class, in, StandardCharsets.UTF_8); Assert.assertEquals(1, user.getId()); Assert.assertEquals("Jack", user.getName()); } - - @Test - public void testJsonToList() { + + void testToList() { String json = "[{\"id\":1,\"name\":\"Jack\"},{\"id\":2,\"name\":\"Tom\"}]"; InputStream in = new ByteArrayInputStream(json.getBytes()); - List users = msgConvertor.toList(User.class, in); - Assert.assertTrue(2 == users.size()); + List users = msgConvertor.toList(User.class, in, StandardCharsets.UTF_8); + Assert.assertEquals(2, users.size()); User u1 = users.get(0); User u2 = users.get(1); Assert.assertEquals(1, u1.getId()); diff --git a/okhttps-gson/src/test/java/com/ejlchina/okhttps/User.java b/okhttps-test/src/main/java/com/ejlchina/okhttps/test/User.java similarity index 96% rename from okhttps-gson/src/test/java/com/ejlchina/okhttps/User.java rename to okhttps-test/src/main/java/com/ejlchina/okhttps/test/User.java index 1fcb6484..deb7c6dd 100644 --- a/okhttps-gson/src/test/java/com/ejlchina/okhttps/User.java +++ b/okhttps-test/src/main/java/com/ejlchina/okhttps/test/User.java @@ -1,4 +1,4 @@ -package com.ejlchina.okhttps; +package com.ejlchina.okhttps.test; public class User { diff --git a/pom.xml b/pom.xml index 5440f01d..fa6f9743 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ okhttps-fastjson okhttps-gson okhttps-jackson + okhttps-test From 92c59102f74177bd032861c3bcdec8bc39b3452f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 11:51:37 +0800 Subject: [PATCH 270/924] =?UTF-8?q?WebSocket=20=E6=96=B0=E5=A2=9E=20msgTyp?= =?UTF-8?q?e=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/WebSocket.java | 8 +++++++- .../okhttps/internal/WebSocketTask.java | 19 +++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java index 3fb62071..1e30a087 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java @@ -126,5 +126,11 @@ interface Listener { * å�Œ {@link okhttp3.WebSocket#close(int, String)} */ boolean close(int code, String reason); - + + /** + * 设置消æ�¯ç±»åž‹ + * @param type 消æ�¯ç±»åž‹ï¼Œå¦‚ jsonã€�xmlã€�protobuf ç­‰ + */ + void msgType(String type); + } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 76930bf5..b2592cc0 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -40,7 +40,9 @@ public WebSocketTask(HttpClient httpClient, String url) { * @return WebSocket */ public WebSocket listen() { - WebSocketImpl socket = new WebSocketImpl(httpClient.executor, getBodyType()); + String bodyType = getBodyType(); + String msgType = bodyType.toLowerCase().contains("form") ? "json" : bodyType; + WebSocketImpl socket = new WebSocketImpl(httpClient.executor, msgType); registeTagTask(socket); httpClient.preprocess(this, () -> { synchronized (socket) { @@ -131,11 +133,11 @@ static class WebSocketImpl implements WebSocket { Charset charset; - String bodyType; + String msgType; - public WebSocketImpl(TaskExecutor taskExecutor, String bodyType) { + public WebSocketImpl(TaskExecutor taskExecutor, String msgType) { this.taskExecutor = taskExecutor; - this.bodyType = bodyType; + this.msgType = msgType; } public void setCharset(Charset charset) { @@ -159,7 +161,12 @@ public synchronized boolean close(int code, String reason) { cancelOrClosed = true; return true; } - + + @Override + public void msgType(String type) { + this.msgType = type; + } + @Override public long queueSize() { if (webSocket != null) { @@ -206,7 +213,7 @@ boolean send(okhttp3.WebSocket webSocket, Object msg) { if (msg instanceof byte[]) { return webSocket.send(ByteString.of((byte[]) msg)); } - byte[] bytes = taskExecutor.doMsgConvert(bodyType, (MsgConvertor c) -> c.serialize(msg, charset)).data; + byte[] bytes = taskExecutor.doMsgConvert(msgType, (MsgConvertor c) -> c.serialize(msg, charset)).data; return webSocket.send(new String(bytes, charset)); } From 8f23d237a9c03a55fec0bd211116b80fcc007841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 12:01:47 +0800 Subject: [PATCH 271/924] =?UTF-8?q?=E6=8A=BD=E8=B1=A1=20Toable=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/HttpResult.java | 54 +--------------- .../java/com/ejlchina/okhttps/Toable.java | 60 ++++++++++++++++++ .../java/com/ejlchina/okhttps/WebSocket.java | 61 ++----------------- .../okhttps/internal/AbstractBody.java | 14 ++--- .../okhttps/internal/WebSocketTask.java | 4 +- .../{MessageBody.java => WebsocketMsg.java} | 6 +- 6 files changed, 76 insertions(+), 123 deletions(-) create mode 100644 okhttps/src/main/java/com/ejlchina/okhttps/Toable.java rename okhttps/src/main/java/com/ejlchina/okhttps/internal/{MessageBody.java => WebsocketMsg.java} (87%) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java index 0e331db2..d6c31dec 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -76,7 +76,7 @@ enum State { /** * HTTPå“�应报文体 */ - interface Body { + interface Body extends Toable { /** * @return 媒体类型 @@ -122,59 +122,7 @@ interface Body { * @return Body */ Body setRangeIgnored(); - - /** - * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ - * @return 报文体转字节æµ� - */ - InputStream toByteStream(); - - /** - * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ - * @return 报文体转字节数组 - */ - byte[] toBytes(); - - /** - * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ - * @return 报文体转字符æµ� - */ - Reader toCharStream(); - - /** - * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ - * @return 报文体转字符串 - */ - String toString(); - /** - * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ - * @return 报文体转Json对象 - */ - Mapper toMapper(); - - /** - * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ - * @return 报文体转Json数组 - */ - Array toArray(); - - /** - * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ - * @param 目标泛型 - * @param type 目标类型 - * @return 报文体Json文本转JavaBean - */ - T toBean(Class type); - - /** - * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ - * @param 目标泛型 - * @param type 目标类型 - * @return 报文体Json文本转JavaBean列表 - */ - List toList(Class type); - /** * 下载到指定路径 * å�Œä¸€ä¸ª Body 对象的 toXXX 类方法å�ªå�¯ä½¿ç”¨ä¸€ä¸ªå¹¶ä¸”å�ªèƒ½è°ƒç”¨ä¸€æ¬¡ diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/Toable.java b/okhttps/src/main/java/com/ejlchina/okhttps/Toable.java new file mode 100644 index 00000000..ef8cff4d --- /dev/null +++ b/okhttps/src/main/java/com/ejlchina/okhttps/Toable.java @@ -0,0 +1,60 @@ +package com.ejlchina.okhttps; + +import okio.ByteString; + +import java.io.InputStream; +import java.io.Reader; +import java.util.List; + +public interface Toable { + + /** + * @return 消æ�¯ä½“转字节æµ� + */ + InputStream toByteStream(); + + /** + * @return 消æ�¯ä½“转字节数组 + */ + byte[] toBytes(); + + /** + * @return ByteString + */ + ByteString toByteString(); + + /** + * @return 消æ�¯ä½“转字符æµ� + */ + Reader toCharStream(); + + /** + * @return 消æ�¯ä½“转字符串 + */ + String toString(); + + /** + * @return 消æ�¯ä½“转Json对象 + */ + Mapper toMapper(); + + /** + * @return 消æ�¯ä½“转Json数组 + */ + Array toArray(); + + /** + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean + */ + T toBean(Class type); + + /** + * @param 目标泛型 + * @param type 目标类型 + * @return 报文体Json文本转JavaBean列表 + */ + List toList(Class type); + +} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java index 1e30a087..5c943f53 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java @@ -1,71 +1,18 @@ package com.ejlchina.okhttps; -import java.io.InputStream; -import java.io.Reader; -import java.util.List; - -import okio.ByteString; - public interface WebSocket extends Cancelable { - - interface Message { + /** + * WebSocket 消æ�¯ + */ + interface Message extends Toable { /** * 判断是文本消æ�¯è¿˜æ˜¯äºŒè¿›åˆ¶æ¶ˆæ�¯ * @return 是å�¦æ˜¯æ–‡æœ¬æ¶ˆæ�¯ */ boolean isText(); - - /** - * @return 消æ�¯ä½“转字节æµ� - */ - InputStream toByteStream(); - - /** - * @return 消æ�¯ä½“转字节数组 - */ - byte[] toBytes(); - - /** - * @return ByteString - */ - ByteString toByteString(); - - /** - * @return 消æ�¯ä½“转字符æµ� - */ - Reader toCharStream(); - - /** - * @return 消æ�¯ä½“转字符串 - */ - String toString(); - - /** - * @return 消æ�¯ä½“转Json对象 - */ - Mapper toMapper(); - - /** - * @return 消æ�¯ä½“转Json数组 - */ - Array toArray(); - - /** - * @param 目标泛型 - * @param type 目标类型 - * @return 报文体Json文本转JavaBean - */ - T toBean(Class type); - /** - * @param 目标泛型 - * @param type 目标类型 - * @return 报文体Json文本转JavaBean列表 - */ - List toList(Class type); - } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java index 8b73ff7c..507ee093 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AbstractBody.java @@ -1,14 +1,14 @@ package com.ejlchina.okhttps.internal; -import java.io.InputStream; import java.nio.charset.Charset; import java.util.List; import com.ejlchina.okhttps.Array; import com.ejlchina.okhttps.Mapper; import com.ejlchina.okhttps.MsgConvertor; +import com.ejlchina.okhttps.Toable; -public abstract class AbstractBody { +public abstract class AbstractBody implements Toable { protected TaskExecutor taskExecutor; protected Charset charset; @@ -18,9 +18,7 @@ public AbstractBody(TaskExecutor taskExecutor, Charset charset) { this.charset = charset; } - public abstract InputStream toByteStream(); - - + @Override public Mapper toMapper() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Mapper 转æ�¢ï¼�"); @@ -28,7 +26,7 @@ public Mapper toMapper() { return taskExecutor.doMsgConvert((MsgConvertor c) -> c.toMapper(toByteStream(), charset)); } - + @Override public Array toArray() { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Array 转æ�¢ï¼�"); @@ -36,15 +34,15 @@ public Array toArray() { return taskExecutor.doMsgConvert((MsgConvertor c) -> c.toArray(toByteStream(), charset)); } - + @Override public T toBean(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š Bean 转æ�¢ï¼�"); } return taskExecutor.doMsgConvert((MsgConvertor c) -> c.toBean(type, toByteStream(), charset)); } - + @Override public List toList(Class type) { if (taskExecutor == null) { throw new IllegalStateException("没有 taskExecutor,ä¸�å�¯å�š List 转æ�¢ï¼�"); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index b2592cc0..0f4884f1 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -83,7 +83,7 @@ public void onOpen(okhttp3.WebSocket webSocket, Response response) { @Override public void onMessage(okhttp3.WebSocket webSocket, String text) { if (onMessage != null) { - onMessage.on(this.webSocket, new MessageBody(text, httpClient.executor, charset)); + onMessage.on(this.webSocket, new WebsocketMsg(text, httpClient.executor, charset)); } } @@ -91,7 +91,7 @@ public void onMessage(okhttp3.WebSocket webSocket, String text) { @Override public void onMessage(okhttp3.WebSocket webSocket, ByteString bytes) { if (onMessage != null) { - onMessage.on(this.webSocket, new MessageBody(bytes, httpClient.executor, charset)); + onMessage.on(this.webSocket, new WebsocketMsg(bytes, httpClient.executor, charset)); } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebsocketMsg.java similarity index 87% rename from okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java rename to okhttps/src/main/java/com/ejlchina/okhttps/internal/WebsocketMsg.java index f8ae709d..f0569061 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/MessageBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebsocketMsg.java @@ -13,18 +13,18 @@ import okio.ByteString; -public class MessageBody extends AbstractBody implements Message { +public class WebsocketMsg extends AbstractBody implements Message { private String text; private ByteString bytes; - public MessageBody(String text, TaskExecutor taskExecutor, Charset charset) { + public WebsocketMsg(String text, TaskExecutor taskExecutor, Charset charset) { super(taskExecutor, charset); this.text = text; } - public MessageBody(ByteString bytes, TaskExecutor taskExecutor, Charset charset) { + public WebsocketMsg(ByteString bytes, TaskExecutor taskExecutor, Charset charset) { super(taskExecutor, charset); this.bytes = bytes; } From 6bfa5c590eade44992800a4f61980625848d48d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 12:14:54 +0800 Subject: [PATCH 272/924] =?UTF-8?q?=E7=AE=80=E5=8C=96=20Mapper=20=E5=92=8C?= =?UTF-8?q?=20Array=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ejlchina/okhttps/FastjsonArray.java | 13 --------- .../com/ejlchina/okhttps/FastjsonMapper.java | 16 ++--------- .../java/com/ejlchina/okhttps/GsonArray.java | 21 -------------- .../java/com/ejlchina/okhttps/GsonMapper.java | 24 ++-------------- .../com/ejlchina/okhttps/JacksonArray.java | 21 -------------- .../com/ejlchina/okhttps/JacksonMapper.java | 28 +++---------------- .../main/java/com/ejlchina/okhttps/Array.java | 20 ++++--------- .../java/com/ejlchina/okhttps/Mapper.java | 21 +++----------- .../java/com/ejlchina/okhttps/OkHttps.java | 6 ++-- 9 files changed, 19 insertions(+), 151 deletions(-) diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonArray.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonArray.java index 3bcdff89..0755c484 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonArray.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonArray.java @@ -1,8 +1,5 @@ package com.ejlchina.okhttps; -import java.math.BigDecimal; -import java.math.BigInteger; - import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -72,16 +69,6 @@ public String getString(int index) { return json.getString(index); } - @Override - public BigDecimal getBigDecimal(int index) { - return json.getBigDecimal(index); - } - - @Override - public BigInteger getBigInteger(int index) { - return json.getBigInteger(index); - } - @Override public String toString() { return json.toJSONString(); diff --git a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMapper.java b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMapper.java index c7c16ee6..7e5aa6d4 100644 --- a/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMapper.java +++ b/okhttps-fastjson/src/main/java/com/ejlchina/okhttps/FastjsonMapper.java @@ -1,12 +1,10 @@ package com.ejlchina.okhttps; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Set; - import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import java.util.Set; + public class FastjsonMapper implements Mapper { private JSONObject json; @@ -73,16 +71,6 @@ public String getString(String key) { return json.getString(key); } - @Override - public BigDecimal getBigDecimal(String key) { - return json.getBigDecimal(key); - } - - @Override - public BigInteger getBigInteger(String key) { - return json.getBigInteger(key); - } - @Override public boolean has(String key) { return json.containsKey(key); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArray.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArray.java index 3208b56a..99795e4b 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArray.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonArray.java @@ -1,8 +1,5 @@ package com.ejlchina.okhttps; -import java.math.BigDecimal; -import java.math.BigInteger; - import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -96,24 +93,6 @@ public String getString(int index) { return null; } - @Override - public BigDecimal getBigDecimal(int index) { - JsonElement val = json.get(index); - if (val != null) { - return val.getAsBigDecimal(); - } - return null; - } - - @Override - public BigInteger getBigInteger(int index) { - JsonElement val = json.get(index); - if (val != null) { - return val.getAsBigInteger(); - } - return null; - } - @Override public String toString() { return json.toString(); diff --git a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMapper.java b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMapper.java index 2b52c9f4..90ea3f90 100644 --- a/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMapper.java +++ b/okhttps-gson/src/main/java/com/ejlchina/okhttps/GsonMapper.java @@ -1,12 +1,10 @@ package com.ejlchina.okhttps; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Set; - import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import java.util.Set; + public class GsonMapper implements Mapper { private JsonObject json; @@ -97,24 +95,6 @@ public String getString(String key) { return null; } - @Override - public BigDecimal getBigDecimal(String key) { - JsonElement val = json.get(key); - if (val != null) { - return val.getAsBigDecimal(); - } - return null; - } - - @Override - public BigInteger getBigInteger(String key) { - JsonElement val = json.get(key); - if (val != null) { - return val.getAsBigInteger(); - } - return null; - } - @Override public boolean has(String key) { return json.has(key); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArray.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArray.java index a0c5e69e..95559db5 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArray.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonArray.java @@ -1,8 +1,5 @@ package com.ejlchina.okhttps; -import java.math.BigDecimal; -import java.math.BigInteger; - import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -97,24 +94,6 @@ public String getString(int index) { return null; } - @Override - public BigDecimal getBigDecimal(int index) { - JsonNode subJson = json.get(index); - if (subJson != null && subJson.isNumber()) { - return subJson.decimalValue(); - } - return null; - } - - @Override - public BigInteger getBigInteger(int index) { - JsonNode subJson = json.get(index); - if (subJson != null && subJson.isNumber()) { - return subJson.bigIntegerValue(); - } - return null; - } - @Override public String toString() { return json.toString(); diff --git a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMapper.java b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMapper.java index 9e81fa4d..49bad435 100644 --- a/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMapper.java +++ b/okhttps-jackson/src/main/java/com/ejlchina/okhttps/JacksonMapper.java @@ -1,15 +1,13 @@ package com.ejlchina.okhttps; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + public class JacksonMapper implements Mapper { private ObjectNode json; @@ -100,24 +98,6 @@ public String getString(String key) { return null; } - @Override - public BigDecimal getBigDecimal(String key) { - JsonNode subJson = json.get(key); - if (subJson != null && subJson.isNumber()) { - return subJson.decimalValue(); - } - return null; - } - - @Override - public BigInteger getBigInteger(String key) { - JsonNode subJson = json.get(key); - if (subJson != null && subJson.isNumber()) { - return subJson.bigIntegerValue(); - } - return null; - } - @Override public boolean has(String key) { return json.has(key); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/Array.java b/okhttps/src/main/java/com/ejlchina/okhttps/Array.java index ce34e899..99b897c2 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/Array.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/Array.java @@ -1,8 +1,10 @@ package com.ejlchina.okhttps; -import java.math.BigDecimal; -import java.math.BigInteger; - +/** + * @since 2.0.0 + * Array 接å�£ 类似于 JsonArray + * 但为什么ä¸�å�–å��为 json 呢,因它ä¸�止是 json,它还å�¯ä»¥æ˜¯ xmlã€�ymlã€�protobuf 等任何一ç§�æ ¼å¼�的数æ�® + */ public interface Array { /** @@ -62,17 +64,5 @@ public interface Array { * @return String 值 */ String getString(int index); - - /** - * @param index 元素下标 - * @return BigDecimal 值 - */ - BigDecimal getBigDecimal(int index); - - /** - * @param index 元素下标 - * @return BigInteger 值 - */ - BigInteger getBigInteger(int index); } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/Mapper.java b/okhttps/src/main/java/com/ejlchina/okhttps/Mapper.java index e5f9ec80..e99ab8cc 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/Mapper.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/Mapper.java @@ -1,13 +1,12 @@ package com.ejlchina.okhttps; -import java.math.BigDecimal; -import java.math.BigInteger; import java.util.Set; /** - * JSON 对象 + * @since 2.0.0 + * Mapper 接å�£ï¼Œç±»ä¼¼äºŽ json + * 但为什么ä¸�å�–å��为 json 呢,因它ä¸�止是 json,它还å�¯ä»¥æ˜¯ xmlã€�ymlã€�protobuf 等任何一ç§�æ ¼å¼�的数æ�® * @author 15735 - * */ public interface Mapper { @@ -68,19 +67,7 @@ public interface Mapper { * @return String 值 */ String getString(String key); - - /** - * @param key é”®å�� - * @return BigDecimal 值 - */ - BigDecimal getBigDecimal(String key); - - /** - * @param key é”®å�� - * @return BigInteger 值 - */ - BigInteger getBigInteger(String key); - + /** * @param key é”®å�� * @return 是å�¦æœ‰è¯¥é”® diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java index c52d77e8..7a2c0cf1 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java @@ -12,11 +12,10 @@ */ public final class OkHttps { - private OkHttps() {} - - private static HTTP http; + private OkHttps() {} + static synchronized HTTP getHttp() { if (http != null) { return http; @@ -28,7 +27,6 @@ static synchronized HTTP getHttp() { return http; } - /** * 异步请求 * @param url 请求地å�€ From bf2c95eee1aa752dcb0de77ef6fd2df8260f493e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 12:36:38 +0800 Subject: [PATCH 273/924] =?UTF-8?q?ResultBody=20=E5=AE=9E=E7=8E=B0=20toByt?= =?UTF-8?q?eString=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ejlchina/okhttps/internal/ResultBody.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java index dddb0f59..b65382f7 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/ResultBody.java @@ -14,6 +14,7 @@ import okhttp3.Response; import okhttp3.ResponseBody; import okio.Buffer; +import okio.ByteString; public class ResultBody extends AbstractBody implements Body { @@ -99,7 +100,7 @@ public InputStream toByteStream() { if (body != null) { input = body.byteStream(); } else { - input = new ByteArrayInputStream(new byte[]{}); + input = new ByteArrayInputStream(new byte[0]); } } if (onProcess != null) { @@ -156,6 +157,11 @@ public String toString() { return null; } + @Override + public ByteString toByteString() { + return ByteString.of(toBytes()); + } + @Override public Download toFile(String filePath) { return toFile(new File(filePath)); @@ -250,7 +256,7 @@ private byte[] bodyToBytes() { throw new HttpException("报文体转化字节数组出错", e); } } - return new byte[]{}; + return new byte[0]; } private long getRangeStart() { From 18a5ccbe6f6343b94ce8cd481a39c30589bbc430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 13:59:04 +0800 Subject: [PATCH 274/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index 73194ba9..36b30d85 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -335,7 +335,7 @@ public Builder addMsgConvertor(MsgConvertor msgConvertor) { * @param charset ç¼–ç � * @return Builder */ - public Builder defaultCharset(Charset charset) { + public Builder charset(Charset charset) { if (charset != null) { this.charset = charset; } @@ -348,7 +348,7 @@ public Builder defaultCharset(Charset charset) { * @param bodyType 请求体类型 * @return Builder */ - public Builder defaultBodyType(String bodyType) { + public Builder bodyType(String bodyType) { if (bodyType != null) { this.bodyType = bodyType; } From fe2ef94aa36afadb433f5e33d04206369877008c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 14:13:28 +0800 Subject: [PATCH 275/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ejlchina/okhttps/HTTP.java | 2 +- .../java/com/ejlchina/okhttps/HttpTask.java | 12 ++++----- .../java/com/ejlchina/okhttps/OkHttps.java | 5 ++++ .../okhttps/internal/WebSocketTask.java | 26 +++++++------------ 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java index 36b30d85..f21a3d84 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HTTP.java @@ -133,7 +133,7 @@ class Builder { private Charset charset = StandardCharsets.UTF_8; - private String bodyType = "json"; + private String bodyType = OkHttps.FORM; public Builder() { mediaTypes = new HashMap<>(); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index 627044f3..a93376e0 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -433,7 +433,7 @@ private void doAddParams(Map taskParams, Map params) */ @Deprecated public C addJsonParam(String name, Object value) { - this.bodyType = "json"; + this.bodyType = OkHttps.JSON; return addBodyPara(name, value); } @@ -446,7 +446,7 @@ public C addJsonParam(String name, Object value) { */ @Deprecated public C addJsonParam(Map params) { - this.bodyType = "json"; + this.bodyType = OkHttps.JSON; return addBodyPara(params); } @@ -458,7 +458,7 @@ public C addJsonParam(Map params) { **/ @Deprecated public C setRequestJson(Object body) { - this.bodyType = "json"; + this.bodyType = OkHttps.JSON; return setBodyPara(body); } @@ -471,7 +471,7 @@ public C setRequestJson(Object body) { */ @Deprecated public C setRequestJson(Object body, String dateFormat) { - this.bodyType = "json"; + this.bodyType = OkHttps.JSON; this.dateFormat = dateFormat; return setBodyPara(body); } @@ -762,7 +762,7 @@ private RequestBody buildRequestBody() { if (bodyParams == null) { return new FormBody.Builder(charset).build(); } - if (bodyType.toLowerCase().contains("form")) { + if (bodyType.toLowerCase().contains(OkHttps.FORM)) { FormBody.Builder builder = new FormBody.Builder(charset); for (String name : bodyParams.keySet()) { String value = bodyParams.get(name); @@ -849,7 +849,7 @@ protected void assertNotConflict(boolean isGetRequest) { throw new HttpException("方法 addFilePara 与 setBodyPara ä¸�能å�Œæ—¶è°ƒç”¨ï¼�"); } } - if (files != null && "form".equals(bodyType)) { + if (files != null && OkHttps.FORM.equals(bodyType)) { throw new HttpException("方法 addFilePara å�ªèƒ½ä½¿ç”¨ form æ–¹å¼�请求ï¼�"); } } diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java index 7a2c0cf1..2e4d705a 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/OkHttps.java @@ -12,6 +12,11 @@ */ public final class OkHttps { + public static final String FORM = "form"; + public static final String JSON = "json"; + public static final String XML = "xml"; + public static final String PROTOBUF = "protobuf"; + private static HTTP http; private OkHttps() {} diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 0f4884f1..4711b6a9 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -4,10 +4,7 @@ import java.util.ArrayList; import java.util.List; -import com.ejlchina.okhttps.HttpResult; -import com.ejlchina.okhttps.HttpTask; -import com.ejlchina.okhttps.MsgConvertor; -import com.ejlchina.okhttps.WebSocket; +import com.ejlchina.okhttps.*; import com.ejlchina.okhttps.WebSocket.Close; import com.ejlchina.okhttps.WebSocket.Listener; import com.ejlchina.okhttps.WebSocket.Message; @@ -30,9 +27,6 @@ public class WebSocketTask extends HttpTask { public WebSocketTask(HttpClient httpClient, String url) { super(httpClient, url); - if (getBodyType().toLowerCase().contains("form")) { - bodyType("json"); - } } /** @@ -41,7 +35,7 @@ public WebSocketTask(HttpClient httpClient, String url) { */ public WebSocket listen() { String bodyType = getBodyType(); - String msgType = bodyType.toLowerCase().contains("form") ? "json" : bodyType; + String msgType = bodyType.toLowerCase().contains(OkHttps.FORM) ? OkHttps.JSON : bodyType; WebSocketImpl socket = new WebSocketImpl(httpClient.executor, msgType); registeTagTask(socket); httpClient.preprocess(this, () -> { @@ -123,17 +117,17 @@ public void onFailure(okhttp3.WebSocket webSocket, Throwable t, Response respons static class WebSocketImpl implements WebSocket { - boolean cancelOrClosed; + private boolean cancelOrClosed; - okhttp3.WebSocket webSocket; - - final List queues = new ArrayList<>(); - - TaskExecutor taskExecutor; + private okhttp3.WebSocket webSocket; - Charset charset; + private final List queues = new ArrayList<>(); + + private TaskExecutor taskExecutor; + + private Charset charset; - String msgType; + private String msgType; public WebSocketImpl(TaskExecutor taskExecutor, String msgType) { this.taskExecutor = taskExecutor; From 6f3d691ba3ac031ecabfd1780654c9a06a907da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 14:31:42 +0800 Subject: [PATCH 276/924] =?UTF-8?q?=E5=8F=82=E6=95=B0=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ejlchina/okhttps/internal/WebSocketTask.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 4711b6a9..8fa5e5dc 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -158,6 +158,9 @@ public synchronized boolean close(int code, String reason) { @Override public void msgType(String type) { + if (type == null || type.equalsIgnoreCase(OkHttps.FORM)) { + throw new IllegalArgumentException("msgType ä¸�å�¯ä¸ºç©º 或 form"); + } this.msgType = type; } From 56d70587ff508b14606485154a34f9d185cdf711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 14:34:43 +0800 Subject: [PATCH 277/924] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java | 2 +- .../main/java/com/ejlchina/okhttps/internal/WebSocketTask.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java index a93376e0..0ae3aa00 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpTask.java @@ -762,7 +762,7 @@ private RequestBody buildRequestBody() { if (bodyParams == null) { return new FormBody.Builder(charset).build(); } - if (bodyType.toLowerCase().contains(OkHttps.FORM)) { + if (OkHttps.FORM.equalsIgnoreCase(bodyType)) { FormBody.Builder builder = new FormBody.Builder(charset); for (String name : bodyParams.keySet()) { String value = bodyParams.get(name); diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java index 8fa5e5dc..a7f71407 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java @@ -35,7 +35,7 @@ public WebSocketTask(HttpClient httpClient, String url) { */ public WebSocket listen() { String bodyType = getBodyType(); - String msgType = bodyType.toLowerCase().contains(OkHttps.FORM) ? OkHttps.JSON : bodyType; + String msgType = OkHttps.FORM.equalsIgnoreCase(bodyType) ? OkHttps.JSON : bodyType; WebSocketImpl socket = new WebSocketImpl(httpClient.executor, msgType); registeTagTask(socket); httpClient.preprocess(this, () -> { From 301745208cccf1117504306f6889e32871ac577f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 15:37:36 +0800 Subject: [PATCH 278/924] V2.0.0.RC --- okhttps-fastjson/pom.xml | 2 +- okhttps-gson/pom.xml | 2 +- okhttps-jackson/pom.xml | 2 +- okhttps-test/pom.xml | 12 +++++++++++- okhttps/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/okhttps-fastjson/pom.xml b/okhttps-fastjson/pom.xml index 9c7a04ab..9fd65d29 100644 --- a/okhttps-fastjson/pom.xml +++ b/okhttps-fastjson/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 2.0.0 + 2.0.0.RC diff --git a/okhttps-gson/pom.xml b/okhttps-gson/pom.xml index fdf36c1b..f7a13cd1 100644 --- a/okhttps-gson/pom.xml +++ b/okhttps-gson/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 2.0.0 + 2.0.0.RC diff --git a/okhttps-jackson/pom.xml b/okhttps-jackson/pom.xml index e5a2e005..973c8d9e 100644 --- a/okhttps-jackson/pom.xml +++ b/okhttps-jackson/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 2.0.0 + 2.0.0.RC diff --git a/okhttps-test/pom.xml b/okhttps-test/pom.xml index de096609..252a9e94 100644 --- a/okhttps-test/pom.xml +++ b/okhttps-test/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 2.0.0 + 2.0.0.RC @@ -26,5 +26,15 @@ okhttps-test + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + \ No newline at end of file diff --git a/okhttps/pom.xml b/okhttps/pom.xml index ebffcd88..cdc49691 100644 --- a/okhttps/pom.xml +++ b/okhttps/pom.xml @@ -8,7 +8,7 @@ com.ejlchina okhttps-parent - 2.0.0 + 2.0.0.RC diff --git a/pom.xml b/pom.xml index fa6f9743..942a5544 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.ejlchina okhttps-parent - 2.0.0 + 2.0.0.RC OkHttps pom @@ -17,7 +17,7 @@ - 2.0.0 + 2.0.0.RC 1.8 3.14.7 2.8.6 From 7dc4d867e2ea84d193b4aaf9908674d181b5cf9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 17:16:46 +0800 Subject: [PATCH 279/924] remove unused imports --- okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java index d6c31dec..001b3a73 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/HttpResult.java @@ -2,8 +2,6 @@ import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; import java.util.List; import com.ejlchina.okhttps.internal.RealHttpResult; From df5d92d0ab612e8cacd7fcd9de63f7d62bba55ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Tue, 12 May 2020 18:56:16 +0800 Subject: [PATCH 280/924] =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps/src/main/java/com/ejlchina/okhttps/Toable.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/Toable.java b/okhttps/src/main/java/com/ejlchina/okhttps/Toable.java index ef8cff4d..0f89c1af 100644 --- a/okhttps/src/main/java/com/ejlchina/okhttps/Toable.java +++ b/okhttps/src/main/java/com/ejlchina/okhttps/Toable.java @@ -34,12 +34,12 @@ public interface Toable { String toString(); /** - * @return 消æ�¯ä½“转Json对象 + * @return 消æ�¯ä½“转 Mapper 对象(ä¸�想定义 Java Bean 时使用) */ Mapper toMapper(); /** - * @return 消æ�¯ä½“转Json数组 + * @return 消æ�¯ä½“转 Array 数组(ä¸�想定义 Java Bean 时使用) */ Array toArray(); From cf2cbcb007ab887f0d7c472a7d02b37d86093e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= <15735559897@qq.com> Date: Wed, 13 May 2020 00:30:39 +0800 Subject: [PATCH 281/924] =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps-doc/docs/.vuepress/config.js | 35 ++- okhttps-doc/docs/README.md | 4 +- okhttps-doc/docs/{guide => v1}/README.md | 2 +- okhttps-doc/docs/{guide => v1}/android.md | 0 .../docs/{guide => v1}/configuration.md | 0 okhttps-doc/docs/{guide => v1}/features.md | 0 okhttps-doc/docs/{guide => v1}/foundation.md | 10 +- okhttps-doc/docs/{guide => v1}/updown.md | 0 okhttps-doc/docs/v2/README.md | 103 ++++++++ okhttps-doc/docs/v2/android.md | 181 ++++++++++++++ okhttps-doc/docs/v2/configuration.md | 158 +++++++++++++ okhttps-doc/docs/v2/features.md | 170 +++++++++++++ okhttps-doc/docs/v2/foundation.md | 209 ++++++++++++++++ okhttps-doc/docs/v2/updown.md | 223 ++++++++++++++++++ 14 files changed, 1078 insertions(+), 17 deletions(-) rename okhttps-doc/docs/{guide => v1}/README.md (97%) rename okhttps-doc/docs/{guide => v1}/android.md (100%) rename okhttps-doc/docs/{guide => v1}/configuration.md (100%) rename okhttps-doc/docs/{guide => v1}/features.md (100%) rename okhttps-doc/docs/{guide => v1}/foundation.md (94%) rename okhttps-doc/docs/{guide => v1}/updown.md (100%) create mode 100644 okhttps-doc/docs/v2/README.md create mode 100644 okhttps-doc/docs/v2/android.md create mode 100644 okhttps-doc/docs/v2/configuration.md create mode 100644 okhttps-doc/docs/v2/features.md create mode 100644 okhttps-doc/docs/v2/foundation.md create mode 100644 okhttps-doc/docs/v2/updown.md diff --git a/okhttps-doc/docs/.vuepress/config.js b/okhttps-doc/docs/.vuepress/config.js index 3e22cadd..ca27057a 100644 --- a/okhttps-doc/docs/.vuepress/config.js +++ b/okhttps-doc/docs/.vuepress/config.js @@ -7,19 +7,36 @@ module.exports = { themeConfig: { logo: '/logo.png', nav: [ - { text: '教程', link: '/guide/' }, + { + text: '教程', + ariaLabel: '版本', + items: [ + { text: 'v1.x', link: '/v1/' }, + { text: 'v2.x', link: '/v2/' } + ] + }, { text: '历å�²ç‰ˆæœ¬', link: 'https://gitee.com/ejlchina-zhxu/okhttps/releases' }, { text: 'Grails 中文', link: 'http://grails.ejlchina.com' }, { text: 'ç �云', link: 'https://gitee.com/ejlchina-zhxu/okhttps' } ], - sidebar: [ - ['/guide/', 'èµ·æ­¥'], - ['/guide/foundation', '基础'], - ['/guide/configuration', 'é…�ç½®'], - ['/guide/features', '特色'], - ['/guide/updown', '上传下载'], - ['/guide/android', '安å�“'], - ], + sidebar: { + '/v1/': [ + '', + 'foundation', + 'configuration', + 'features', + 'updown', + 'android' + ], + '/v2/': [ + '', + 'foundation', + 'configuration', + 'features', + 'updown', + 'android' + ] + }, sidebarDepth: 2, smoothScroll: true, lastUpdated: '上次更新', diff --git a/okhttps-doc/docs/README.md b/okhttps-doc/docs/README.md index e7ab259a..c57380ab 100644 --- a/okhttps-doc/docs/README.md +++ b/okhttps-doc/docs/README.md @@ -4,7 +4,7 @@ heroImage: /logo.png heroText: OkHttps tagline: 基于 OkHttp 增强版 HTTP 客户端 actionText: æž�速上手 → -actionLink: /guide/ +actionLink: /v2/ features: - title: è½»é‡�纯粹优雅 details: OkHttps é�žå¸¸è½»é‡�,体积仅是 Retrofit 的一å�Šä¸�到,并且ä¸�ä¾�赖于特定平å�°ï¼ŒAPI 语义简æ´�舒适。 @@ -68,4 +68,4 @@ http.async("/users/jack") // http://api.demo.com/users/jack --> **
竟然�到 15 秒,你已学会 90% 的精髓�
** -
[**了解更多**](/guide/)
\ No newline at end of file +
[**了解更多**](/v2/)
\ No newline at end of file diff --git a/okhttps-doc/docs/guide/README.md b/okhttps-doc/docs/v1/README.md similarity index 97% rename from okhttps-doc/docs/guide/README.md rename to okhttps-doc/docs/v1/README.md index ea0465f7..84a45c42 100644 --- a/okhttps-doc/docs/guide/README.md +++ b/okhttps-doc/docs/v1/README.md @@ -64,7 +64,7 @@ HTTP http = HTTP.builder().build(); * `request(Request request)` OkHttp 原生请求 * `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 -  为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(详� [设置 BaseUrl](/guide/configuration.html#设置-baseurl)): +  为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(详� [设置 BaseUrl](/v1/configuration.html#设置-baseurl)): ```java HTTP http = HTTP.builder() diff --git a/okhttps-doc/docs/guide/android.md b/okhttps-doc/docs/v1/android.md similarity index 100% rename from okhttps-doc/docs/guide/android.md rename to okhttps-doc/docs/v1/android.md diff --git a/okhttps-doc/docs/guide/configuration.md b/okhttps-doc/docs/v1/configuration.md similarity index 100% rename from okhttps-doc/docs/guide/configuration.md rename to okhttps-doc/docs/v1/configuration.md diff --git a/okhttps-doc/docs/guide/features.md b/okhttps-doc/docs/v1/features.md similarity index 100% rename from okhttps-doc/docs/guide/features.md rename to okhttps-doc/docs/v1/features.md diff --git a/okhttps-doc/docs/guide/foundation.md b/okhttps-doc/docs/v1/foundation.md similarity index 94% rename from okhttps-doc/docs/guide/foundation.md rename to okhttps-doc/docs/v1/foundation.md index 4cccf799..e48cd8af 100644 --- a/okhttps-doc/docs/guide/foundation.md +++ b/okhttps-doc/docs/v1/foundation.md @@ -39,7 +39,7 @@ http.async("/users/{id}") // http://api.demo.com/users/1 .get(); ``` -  OkHttps �时还支� **全局回调** 和 **回调阻断** 机制,详� [全局回调监�](/guide/configuration.html#全局回调监�)。 +  OkHttps �时还支� **全局回调** 和 **回调阻断** 机制,详� [全局回调监�](/v1/configuration.html#全局回调监�)。 ::: tip * �有异步请求��以设置这三�(�应|异常|完�)回调 @@ -169,10 +169,10 @@ System.out.println(call.isCanceled()); // true * `addFileParam(String name, String type, String fileName, byte[] content)` 上传文件 * `setTag(String tag)` 为HTTP任务添加标签 -* `setRange(long rangeStart)` 设置Range头信�,用于[断点续传](/guide/updown.html#实现断点续传) -* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,�用于[分�下载](/guide/updown.html#实现分�下载) +* `setRange(long rangeStart)` 设置Range头信�,用于[断点续传](/v1/updown.html#实现断点续传) +* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,�用于[分�下载](/v1/updown.html#实现分�下载) -* `bind(Object object)` 绑定一个对象,�用于实现Android里的[生命周期绑定](/guide/android.html#生命周期绑定) +* `bind(Object object)` 绑定一个对象,�用于实现Android里的[生命周期绑定](/v1/android.html#生命周期绑定) ## 使用标签 @@ -206,4 +206,4 @@ http.async("/users") //(5) int count = http.cancel("B"); //(2)(3)(4)被�消(�消标签包�"B"的任务) System.out.println(count); // 输出 3 ``` -  标签除了�以用��消任务,在预处�器中它也�以�挥作用,请�� [并行预处�器](/guide/configuration.html#并行预处�器) 与 [串行预处�器(token问题最佳解决方案)](/guide/configuration.html#串行预处�器(token问题最佳解决方案))。 +  标签除了�以用��消任务,在预处�器中它也�以�挥作用,请�� [并行预处�器](/v1/configuration.html#并行预处�器) 与 [串行预处�器(token问题最佳解决方案)](/v1/configuration.html#串行预处�器(token问题最佳解决方案))。 diff --git a/okhttps-doc/docs/guide/updown.md b/okhttps-doc/docs/v1/updown.md similarity index 100% rename from okhttps-doc/docs/guide/updown.md rename to okhttps-doc/docs/v1/updown.md diff --git a/okhttps-doc/docs/v2/README.md b/okhttps-doc/docs/v2/README.md new file mode 100644 index 00000000..84a45c42 --- /dev/null +++ b/okhttps-doc/docs/v2/README.md @@ -0,0 +1,103 @@ +--- +description: OkHttps 安装 构建实例 HTTP build �步请求 异步请求 sync async BaseUrl request webSocket gradle maven ejlchina +--- + +# 起步 + +  OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 + + * 链�调用,一点到底 + * BaseURL�URL��符�JSON自动�装与解� + * �步拦截器�异步预处�器�回调执行器�全局监��回调阻断 + * 文件上传下载(过程控制�进度监�) + * �方法回调,充分利用 Lambda 表达� + * TCP连接池�Http2 + +::: tip +* OkHttps �常轻�(59Kb),仅是 Retrofit(124Kb)的一�,并且更加的开箱�用,API 也更加自然和语义化。 +* OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit �� +* OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。 +::: + +## 安装 + +### Maven + +```xml + + com.ejlchina + okhttps + 1.0.5 + +``` +### Gradle + +```groovy +implementation 'com.ejlchina:okhttps:1.0.5' +``` + +安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��: + +```groovy +android { + // �略其它�置.. + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } +} +``` + +## 使用 + +### 构建实例 + +```java +HTTP http = HTTP.builder().build(); +``` +  以上代�构建了一个最简�的`HTTP`实例,它拥有以下方法: + +* `sync(String url)` 开始一个�步请求 +* `async(String url)` 开始一个异步请求 +* `cancel(String tag)` 按标签�消请求 +* `cancelAll()` �消所有HTTP任务,包括�步和异步 +* `request(Request request)` OkHttp 原生请求 +* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 + +  为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(详� [设置 BaseUrl](/v1/configuration.html#设置-baseurl)): + +```java +HTTP http = HTTP.builder() + .baseUrl("http://api.demo.com") + .build(); +``` +  为了简化文档,下文中出现的`http`�是在构建时设置了`BaseUrl`的`HTTP`实例。 + +### �步请求 + +  使用方法`sync(String url)`开始一个�步请求: + +```java +List users = http.sync("/users") // http://api.demo.com/users + .get() // GET请求 + .getBody() // 获��应报文体 + .toList(User.class); // 得到目标数� +``` +  方法`sync`返回一个�步`HttpTask`,�链�使用。 + +### 异步请求 + +  使用方法`async(String url)`开始一个异步请求: + +```java +http.async("/users/1") // http://api.demo.com/users/1 + .setOnResponse((HttpResult result) -> { + // 得到目标数� + User user = result.getBody().toBean(User.class); + }) + .get(); // GET请求 +``` +  方法`async`返回一个异步`HttpTask`,�链�使用。 + + +**至此,你已轻�学会了 OkHttps 95% 的常规用法�但别急,��还有更精彩的。** \ No newline at end of file diff --git a/okhttps-doc/docs/v2/android.md b/okhttps-doc/docs/v2/android.md new file mode 100644 index 00000000..73c7fde5 --- /dev/null +++ b/okhttps-doc/docs/v2/android.md @@ -0,0 +1,181 @@ +--- +description: OkHttps 安� 生命周期 UI线程 主线程 IO线程 自由 �活 切� 生命周期绑定 �置预处�器 定义生命周期监视器 �置全局回调监� +--- + +# 安� + +## 回调线程切� + +  在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 + +  在 **默认** 情况下,**所有回调** 函数都会 **在 IO 线程** 执行。为什么会设计如此呢?这是因为 OkHttps �是纯粹的 Java 领域 Http工具包,本身对 Android �会有任何�赖,因此也�知 Android 的 UI 线程为何物。这么设计也让它在 Android 之外有更多的�能性。 + +### �置 + +  但是在 Android 里使用 OkHttps 的�,UI线程的问题能�优雅的解决呢?当然�以�简�粗暴的方法就是�置一个 回调执行器: + + ```java +HTTP http = HTTP.builder() + .callbackExecutor((Runnable run) -> { + // 实际编�中�以� Handler �出�,�需��次执行回调都�新创建 + new Handler(Looper.getMainLooper()).post(run); // 在主线程执行 + }) + .build(); +``` + +### 用例 + +  上述代�便实现了让 **所有** 的 **回调函数** 都在 **主线程(UI线程)** 执行的目的,如: + +```java +http.async("/users") + .addBodyParam("name", "Jack") + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .setOnResponse((HttpResult result) -> { + // 在主线程执行 + }) + .setOnException((Exception e) -> { + // 在主线程执行 + }) + .setOnComplete((State state) -> { + // 在主线程执行 + }) + .post(); +``` +  但是,如果�时还想让�些回调放在IO线程,实现 **自由切�**,怎么办呢?OkHttps 给出了�常�活的方法,如下: + +```java +http.async("/users") + .addBodyParam("name", "Jack") + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnResponse((HttpResult result) -> { + // 在 IO 线程执行 + }) + .setOnException((Exception e) -> { + // 在主线程执行(没有指明 nextOnIO 则在回调执行器里执行) + }) + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnComplete((State state) -> { + // 在 IO 线程执行 + }) + .post(); +``` +  无论是哪一个回调,都�以使用`nextOnIO()`方法自由切�。�样,对于文件下载也是一样: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .setOnProcess((Process process) -> { + // 在主线程执行 + }) + .toFolder("D:/download/") + .nextOnIO() // 指定下一个回调在 IO 线程执行 + .setOnSuccess((File file) -> { + // 在 IO 线程执行 + }) + .setOnFailure((Failure failure) -> { + // 在主线程执行 + }) + .start(); +``` + +## 生命周期绑定 + +  由于 OkHttps 并��赖于 Android,所以它并没有�供关于生命周期绑定的直接实现,但它的一些扩展机制让我们很容易就�以实现这个需求。在开始之�,我们首先��解何为生命周期绑定: + +::: tip HTTP 请求的生命周期绑定 +所谓的生命周期绑定:�是让 HTTP 任务感知其所属的 Activity 或 Fragment 的生命周期,当 Activity 或 Fragment 将被销�时,框架应自动的把由它们�起的但尚未完�的 HTTP 任务全部�消,以�导致程�出错� +::: + +  现在我们需�对`HTTP`实例进行�置,�置�的`HTTP`实例具有生命周期绑定的功能,在`Activity`或`Fragment`里,它的使用效果如下: + +```java +// 在 Activity 或 Fragment 内�起请求 +http.async("http://www.baidu.com") + .bind(getLifecycle()) // 绑定生命周期 + .setOnResponse((HttpResult result) -> { + Log.i("FirstFragment", "收到请求:" + result.toString()); + }) + .get(); +``` +  上述代�中的`getLifecycle()`是`Activity`或`Fragment`自带的方法,而`bind()`是`HttpTask`的现有方法。在�置好`HTTP`实例�,上述代��起的请求便�以感知`Activity`或`Fragment`的生命周期。 + +  那`HTTP`实例到底该如何�置呢? + +### 第一步:�置预处�器 + +```java +HTTP http = HTTP.builder() + ... // �略其它�置项 + .addPreprocessor((Preprocessor.PreChain chain) -> { + HttpTask task = chain.getTask(); + Object bound = task.getBound(); + // 判断 task 是�绑定了 Lifecycle 对象 + if (bound instanceof Lifecycle) { + // �新绑定一个 生命周期监视器(LCObserver)对象,它的定义�下一步 + task.bind(new LCObserver(task, (Lifecycle) bound)); + } + chain.proceed(); + }) + ... // �略其它�置项 + .build(); +``` + +### 第二步:定义生命周期监视器 + +```java +public class LCObserver implements LifecycleObserver { + + HttpTask task; + Lifecycle lifecycle; + + LCObserver(HttpTask task, Lifecycle lifecycle) { + this.task = task; + this.lifecycle = lifecycle; + lifecycle.addObserver(this); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + public void onStop() { + task.cancel(); // 在 ON_STOP 事件中,�消对应的 HTTP 任务 + } + + public void unbind() { + // 在请求完�之�移除监视器 + lifecycle.removeObserver(this); + } + +} +``` + +### 第三步:�置全局回调监� + +  以上两步其实已�实现了生命周期绑定的功能,但是在请求完�之�,我们需�在`lifecycle`中移除`LCObserver`对象: + +```java +HTTP http = HTTP.builder() + ... // �略其它�置项 + .completeListener((HttpTask task, HttpResult.State state) -> { + Object bound = task.getBound(); + // 判断 task 是�绑定了生命周期监视器(LCObserver)对象 + if (bound instanceof LCObserver) { + // 解绑监视器 + ((LCObserver) bound).unbind(); + } + return true; + }) + ... // �略其它�置项 + .build(); +``` + +**以上三步便在Android中实现了生命周期与HTTP请求绑定的功能** + +  �常简�,懒得敲代�的�学还�以 [点这里 OkHttps.java](https://gitee.com/ejlchina-zhxu/okhttps-android-demo/blob/master/app/src/main/java/com/flower/myapplication/http/OkHttps.java) 直接下载�装好的��,其中�仅编写了生命周期绑定的�置,还有在UI线程执行回调的�置。 + +  有需�的�学,�以直接下载下�使用,还�以基于它�次扩展,比如实现自动添加 TOKEN 的功能,具体�以�考[6.5 串行预处�器(TOKEN问题最佳解决方案)](#65-串行预处�器token问题最佳解决方案),�比如扩展实现生命周期与下载事件绑定的功能,都�常简�。 diff --git a/okhttps-doc/docs/v2/configuration.md b/okhttps-doc/docs/v2/configuration.md new file mode 100644 index 00000000..30bf60e9 --- /dev/null +++ b/okhttps-doc/docs/v2/configuration.md @@ -0,0 +1,158 @@ +--- +description: OkHttps �置 BaseUrl 回调执行器 主线程 UI线程 OkHttpClient 预处�器 TOKEN问题最佳解决方案 刷新TOKEN 全局 回调监� 下载监� 回调阻断 拦截器 CookieJar�SSL�缓存�代��事件监� +--- + +# �置 + +## 设置 BaseUrl + +```java +HTTP http = HTTP.builder() + .baseUrl("http://api.demo.com") // 设置 BaseUrl + .build(); +``` +  该�置全局生效,在�置了`BaseUrl`之�,具体的请求便�以�略`BaseUrl`部分,使得代�更加简�,例如: + +```java +http.sync("/users").get() // http://api.demo.com/users + +http.sync("/auth/signin") // http://api.demo.com/auth/signin + .addBodyParam("username", "Jackson") + .addBodyParam("password", "xxxxxx") + .post(); // POST请求 +``` +  在�置了`BaseUrl`之�,如有特殊请求任务,�然�以使用全路径的方�,一点都�妨�: + +```java +http.sync("https://www.baidu.com").get(); +``` + +## 回调执行器 + +  OkHttps 默认所有回调都在 **IO线程** 执行,如何想改�执行回调的线程时,�以�置回调执行器。例如在Android里,让所有的回调函数都在UI线程执行,则�以在构建`HTTP`时�置如下: + +```java +HTTP http = HTTP.builder() + .callbackExecutor((Runnable run) -> { + runOnUiThread(run); // 在UI线程执行 + }) + .build(); +``` +  该�置默认 **影�所有回调**。 + +## �置 OkHttpClient + +  与其他�装 OkHttp3 的框架��,OkHttps 并�会�蔽 OkHttp3 本身就很好用的功能,如下: + +```java +HTTP http = HTTP.builder() + .config((Builder builder) -> { + // �置连接池 最�10个连接(��置默认为 5) + builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES)); + // �置连接超时时间(默认10秒) + builder.connectTimeout(20, TimeUnit.SECONDS); + // �置拦截器 + builder.addInterceptor((Chain chain) -> { + Request request = chain.request(); + // 必须�步返回,拦截器内无法执行异步�作 + return chain.proceed(request); + }); + // 其它�置: CookieJar�SSL�缓存�代��事件监�... + }) + .build(); +``` + +## 并行预处�器 + +  预处�器(`Preprocessor`)�以让我们在请求�出之�对请求本身�一些改�,但与`OkHttp`的拦截器(`Interceptor`)��:预处�器�以让我们 **异步** 处�这些问题。 + +  例如,当我们想为请求任务自动添加`Token`头信�,而`Token`�能通过异步方法`requestToken`获�时,这时使用`Interceptor`就很难处�了,但�以使用预处�器轻�解决: + +```java +HTTP http = HTTP.builder() + .addPreprocessor((PreChain chain) -> { + HttpTask task = chain.getTask();// 获得当�的HTTP任务 + if (!task.isTagged("Auth")) { // 根�标签判断该任务是�需�Token + chain.proceed(); + return; + } + requestToken((String token) -> { // 异步获� Token + task.addHeader("Token", token);// 为任务添加头信� + chain.proceed(); // 继续当�的任务 + }); + }) + .build(); +``` +  和`Interceptor`一样,`Preprocessor`也�以添加多个。他们之间的区别如下: + +::: tip 拦截器与预处�器的区别 +* 拦截器�能处��步�作,预处�器支�处�异步�作 +* 拦截器都是并行处�请求,预处�器支�串行处�(详�6.5章节) +* 拦截器处�时机在请求�和�应�,预处�器�在请求�,并且先于拦截器执行。关于�应�,OkHttps还�供了全局回调监�(详�6.6章节) +::: + +## 串行预处�器(TOKEN问题最佳解决方案) + +  普通预处�器都是�并行处�的,然而有时我们希望�个预处�器�时�处�一个任务。比如 当`Token`过期时我们需�去刷新获�新`Token`,而刷新`Token`这个�作�能有一个任务去执行,因为如果`n`个任务�时执行的�,那么必有`n-1`个任务刚刷新得到的`Token`�能就立马失效了,而这是我们所�希望的。 + +  为了解决这个问题,OkHttps �供了串行预处�器,它�以让 HTTP 任务排好队,一个一个地进入预处�器: + +```java +HTTP http = HTTP.builder() + .addSerialPreprocessor((PreChain chain) -> { + HttpTask task = chain.getTask(); + if (!task.isTagged("Auth")) { + chain.proceed(); + return; + } + // 检查过期,若需�则刷新Token + requestTokenAndRefreshIfExpired((String token) -> { + task.addHeader("Token", token); + chain.proceed(); // 调用此方法�,�会有其它任务进入该处�器 + }); + }) + .build(); +``` +  串行预处�器实现了让HTTP任务排队串行处�的功能,但值得一�的是:它并没有因此而阻塞任何线程� + +## 全局回调监� + +  全局回调是实际开�中�常需�的功能,比如对�务器�应的状��进行统一处�等,�时 OkHttps 的全局回调还具有 **回调阻断** 的功能: + +```java +HTTP http = HTTP.builder() + .responseListener((HttpTask task, HttpResult result) -> { + // 所有请求�应�都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnResponse 回调,false 表示��执行 + }) + .completeListener((HttpTask task, State state) -> { + // 所有请求执行完都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnComplete 回调,false 表示��执行 + }) + .exceptionListener((HttpTask task, IOException error) -> { + // 所有请求�生异常都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 + }) + .build(); +``` + +::: tip 全局回调监�与拦截器的异�: +* 拦截器�以添加多个,全局回调监�分三�,��最多添加一个 +* 拦截器处的�时机在请求�和�应�,全局回调监��在�应�,并且晚于拦截器 +* 全局回调监��以 **阻断**(return false)�个请求的具体回调,而拦截器�能 +::: + +## 全局下载监� + +```java +HTTP http = HTTP.builder() + .downloadListener((HttpTask task, Download download) -> { + // 所有下载在开始之�都会先走这里 + Ctrl ctrl = download.getCtrl(); // 下载控制器 + + }) + .build(); +``` \ No newline at end of file diff --git a/okhttps-doc/docs/v2/features.md b/okhttps-doc/docs/v2/features.md new file mode 100644 index 00000000..56771574 --- /dev/null +++ b/okhttps-doc/docs/v2/features.md @@ -0,0 +1,170 @@ +--- +description: OkHttps 使用 HttpUtils 类 WebSocket 异常处� nothrow 异常回调 多�方� �消请求 标签 批��消 cancelAll +--- + +# 特色 + +## 使用 HttpUtils 类 + +  类`HttpUtils`本是 [�身 HttpUtils](https://gitee.com/ejlchina-zhxu/httputils) 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。 + +  类`HttpUtils`共定义了四个��方法: + +* `of(HTTP http)` �置`HttpUtils`�有的`HTTP`实例(�调用此方法�默认使用一个没有没有�过任何�置的`HTTP`懒实例) +* `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) +* `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) +* `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) +* `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) +* `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) +* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 +  也就是说,能使用`http`实例的地方,都�以使用`HttpUtils`类,例如: + +```java +// 在�置HTTP实例之�,�能使用全路径方� +List roles = HttpUtils.sync("http://api.demo.com/roles") + .get().getBody().toList(Role.class); + +// �置HTTP实例,全局生效 +HttpUtils.of(HTTP.builder() + .baseUrl("http://api.demo.com") + .build()); + +// 内部使用新的HTTP实例 +List users = HttpUtils.sync("/users") + .get().getBody().toList(User.class); +``` + +## 异常处� + +  使用 OkHttps 时,**异常处��是必须的**,但相比其它的 HTTP 开�包,它还�供一个特别的处�方法:`nothrow()`,以满足��的异常处�需求。 + +### �步请求的异常 + +  默认情况下,当�步请求执行异常时,会直接�外抛出,我们�以用 `try catch` ��获,例如: + +```java +try { + HttpResult result = http.sync("/users/1").get(); +} catch (HttpException e) { + Throwable cause = e.getCause(); // 得到异常原因 + if (cause instanceof ConnectException) { + // 当没网络时,会抛出连接异常 + } + if (cause instanceof SocketTimeoutException) { + // 当接�长时间未�应,会抛出超时异常 + } + if (cause instanceof UnknownHostException) { + // 当把域�或IP写错,会抛出 UnknownHost 异常 + } + // ... +} +``` +  这�传统的异常处�方�,当然�以解决问题,但 OkHttps 有更佳的方案: + +```java +// 方法 nothrow() 让异常�直接抛出 +HttpResult result = http.sync("/users/1").nothrow().get(); +// 判断执行状� +switch (result.getState()) { + case RESPONSED: // 请求已正常�应 + break; + case CANCELED: // 请求已被�消 + break; + case NETWORK_ERROR: // 网络错误,说明用户没网了 + break; + case TIMEOUT: // 请求超时 + break; + case EXCEPTION: // 其它异常 + break; +} +// 还�以获得具体的异常信� +IOException error = result.getError(); +``` + +### 异步请求的异常 + +  异步请求最常用的异常处�方�就是设置一个异常回调: + +```java +http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .setOnException((IOException e) -> { + // 这里处�请求异常 + }) + .get(); +``` +  当然,还有一个全局异常监�(`ExceptionListener`): + +```java +HTTP http = HTTP.builder() + .exceptionListener((HttpTask task, IOException error) -> { + // 所有请求�生异常都会走这里 + + return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示��执行 + }) + .build(); +``` +  如果�设置`OnException`回调,也没有`ExceptionListener`,�生异常时会在 **IO 线程** 中�上抛出,外层无法�获: + +```java +try { + http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .get(); +} catch (HttpException e) { + // 这�方�是�获�到异常的������ +} +``` +  �使没有`OnException`回调,�生异常时,�然会走`OnComplete`回调,如果设置了的�: + +```java +http.async("/users/1") + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .setOnComplete((State state) -> { + // �生异常,会先执行这里,�以根� state 判断�生了什么 + // 但执行完��然会在IO线程中�上抛出 + }) + .get(); +``` +  如果就是想 **�处�异常,也��上抛出**,�生错误完全无视,�以�到�?�以�还是使用`nothrow()`方法: + +```java +http.async("/users/1") + .nothrow() // 告诉 OkHttps �生异常时��外抛出 + .setOnResponse((HttpResult result) -> { + // 当�生异常时就�会走这里 + }) + .get(); +``` + +## �消请求 + +  在 OkHttps 里�消请求共有 **4 �** 方��选: + +* 使用`HttpCall#cancel()`�消�个请求(适用于异步请求,[详� 3.3 章节](#33-httpcall)) +* 使用`HttpTask#cancel()`�消�个请求(适用于所有请求)(since v1.0.4) + +```java +HttpTask task = http.async("/users") + .setOnResponse((HttpResult result) -> { + // �应回调 + }); + +task.get(); // �起 GET 请求 + +// �消请求,并返回是��消�功 +boolean canceled = task.cancel(); +``` + +* 使用`HTTP#cancel(String tag)`按标签批��消请求(适用于所有请求,[详�第 5 章节](#5-使用标签)) +* 使用`HTTP#cancelAll()`�消所有请求(适用于所有请求)(since v1.0.2) + +```java +http.cancelAll(); // �消所有请求 +``` \ No newline at end of file diff --git a/okhttps-doc/docs/v2/foundation.md b/okhttps-doc/docs/v2/foundation.md new file mode 100644 index 00000000..e48cd8af --- /dev/null +++ b/okhttps-doc/docs/v2/foundation.md @@ -0,0 +1,209 @@ +--- +description: OkHttps 请求方法 回调函数 HttpResult cache 多次 消费报文体 HttpCall 构建HTTP任务 请求�数 JSON 使用标签 �起请求 �消请求 +--- + +# 基础 + +## 请求方法 + +  �步与异步的`HttpTask`都拥有`get`�`post`�`put`与`delete`方法。��的是:�步`HttpTask`的这些方法返回一个`HttpResult`,而异步`HttpTask`的这些方法返回一个`HttpCall`。 + +```java +HttpResult res1 = http.sync("/users").get(); // �步 GET +HttpResult res2 = http.sync("/users").post(); // �步 POST +HttpResult res3 = http.sync("/users/1").put(); // �步 PUT +HttpResult res4 = http.sync("/users/1").delete();// �步 DELETE +HttpCall call1 = http.async("/users").get(); // 异步 GET +HttpCall call2 = http.async("/users").post(); // 异步 POST +HttpCall call3 = http.async("/users/1").put(); // 异步 PUT +HttpCall call4 = http.async("/users/1").delete();// 异步 DELETE +``` + +## 回调函数 + +  OkHttps 的回调函数全部使用�方法模�,这样�以充分利用 Java8 或 Kotlin 中的 Lambda 表达�,使你的代�更加简�优雅: + +```java +http.async("/users/{id}") // http://api.demo.com/users/1 + .addPathParam("id", 1) + .setOnResponse((HttpResult result) -> { + // �应回调 + }) + .setOnException((IOException e) -> { + // 异常回调 + }) + .setOnComplete((State state) -> { + // 完�回调,无论�功失败都会执行 + // 并且在 �应|异常回调 之�执行 + }) + .get(); +``` + +  OkHttps �时还支� **全局回调** 和 **回调阻断** 机制,详� [全局回调监�](/v1/configuration.html#全局回调监�)。 + +::: tip +* �有异步请求��以设置这三�(�应|异常|完�)回调 +* �步请求直接返回结果,无需使用回调 +::: + +## HttpResult + +  `HttpResult`是HTTP请求执行完�的结果,它是�步请求方法( `get`�`post`�`put`�`delete`)的返回值,也是异步请求�应回调(`OnResponse`)的�数,它定义了如下方法: + +* `getState()` 得到请求执行状�枚举,它有以下�值: + * `State.CANCELED` 请求被�消 + * `State.RESPONSED` 已收到�应 + * `State.TIMEOUT` 请求超时 + * `State.NETWORK_ERROR` 网络错误 + * `State.EXCEPTION` 其它请求异常 +* `getStatus()` 得到HTTP状�� +* `isSuccessful()` 是��应�功,状��在 [200..300) 之间 +* `getHeaders()` 得到HTTP�应头 +* `getHeaders(String name)` 得到HTTP�应头 +* `getHeader(String name)` 得到HTTP�应头 +* `getBody()` 得到�应报文体`Body`实例,它定义了如下方法(对�一个`Body`实例,以下的`toXXX()`类方法�能使用一个且仅能调用一次,除�先使用 cache 方法): + * `toBytes()` 返回字节数组 + * `toByteStream()` 返回字节输入� + * `toCharStream()` 返回字符输入� + * `toString()` 返回字符串 + * `toJsonObject()` 返回Json对象 + * `toJsonArray()` 返回Json数组 + * `toBean(Class type)` 返回根�type自动json解��的JavaBean + * `toList(Class type)` 返回根�type自动json解��的JavaBean列表 + * `toFile(String filePath)` 下载到指定路径 + * `toFile(File file)` 下载到指定文件 + * `toFolder(String dirPath)` 下载到指定目录 + * `toFolder(File dir)` 下载到指定目录 + * `getContentType()` 返回报文体的媒体类型 + * `getContentLength()` 返回报文体的字节长度 + * `cache()` 缓存报文体,开�缓存����使用`toXXX()`类方法 + * `close()` 关闭报文体,未对报文体�任何消费时使用,比如�读�报文头 +* `getError()` 执行中�生的异常,自动�获执行请求时�生的 网络超时�网络错误 和 其它IO异常 +* `close()` 关闭报文,未对报文体�任何消费时使用,比如�读�长度 + +  示例,请求结果自动转Bean和List: + +```java +// 自动转Bean +Order order = http.sync("/orders/1") + .get().getBody().toBean(Order.class); + +// 自动转List +List orders = http.sync("/orders") + .get().getBody().toList(Order.class); +``` + +  示例,使用 cache 方法: + +```java +Body body = http.sync("/orders").get().getBody().cache(); + +// 使用 cache �,�以多次使用 toXXX() 方法 +System.out.println(body.toString()); +System.out.println(body.toJsonArray()); +System.out.println(body.toList(Order.class)); +``` + +  示例,获�下载文件的大�: + +```java +long size = http.sync("/download/test.zip") + .get().getBody() + .close() // �是想获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); // 获得待下载文件的大� + +// 由于未消费报文体,所以本次请求�会消耗下载报文体的时间和网络�� + +System.out.println("size = " + size); +``` + +## HttpCall + +  `HttpCall`对象是异步请求方法(`get`�`post`�`put`�`delete`)的返回值,与`java`的`Future`接�很�,它有如下方法: + +* `cancel()` �消本次请求,返回�消结果 +* `isCanceled()` 返回请求是�被�消 +* `isDone()` 返回是�执行完�,包��消和失败 +* `getResult()` 返回执行结果`HttpResult`对象,若请求未执行完,则挂起当�线程直到执行完��返回 + +  �消一个异步请求示例: + +```java +HttpCall call = http.async("/users/1").get(); + +System.out.println(call.isCanceled()); // false + +boolean success = call.cancel(); // �消请求 + +System.out.println(success); // true +System.out.println(call.isCanceled()); // true +``` + +## 构建HTTP任务 + +  `HTTP`对象的`sync`与`async`方法返回一个`HttpTask`对象,该对象�供了�链�调用的`addXXX`与`setXXX`等系列方法用于构建任务本身。 + +* `addHeader(String name, String value)` 添加请求头 +* `addHeader(Map headers)` 添加请求头 + +* `addPathParam(String name, Object value)` 添加路径�数:替�URL里的{name}��符 +* `addPathParam(Map params)` 添加路径�数:替�URL里的{name}��符 + +* `addUrlParam(String name, Object value)` 添加URL�数:拼接在URL的?之�(查询�数) +* `addUrlParam(Map params)` 添加URL�数:拼接在URL的?之�(查询�数) + +* `addBodyParam(String name, Object value)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) +* `addBodyParam(Map params)` 添加Body�数:以表�key=value&的形�放在报文体内(表��数) + +* `addJsonParam(String name, Object value)` 添加Json�数:请求体为Json(支�多层结构) +* `addJsonParam(Map params)` 添加Json�数:请求体为Json(支�多层结构) + +* `setRequestJson(Object json)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean +* `setRequestJson(Object bean, String dateFormat)` 设置请求体的Json字符串 或待转�为 Json的 JavaBean + +* `addFileParam(String name, String filePath)` 上传文件 +* `addFileParam(String name, File file)` 上传文件 +* `addFileParam(String name, String type, InputStream inputStream)` 上传文件 +* `addFileParam(String name, String type, String fileName, InputStream input)` 上传文件 +* `addFileParam(String name, String type, byte[] content)` 上传文件 +* `addFileParam(String name, String type, String fileName, byte[] content)` 上传文件 + +* `setTag(String tag)` 为HTTP任务添加标签 +* `setRange(long rangeStart)` 设置Range头信�,用于[断点续传](/v1/updown.html#实现断点续传) +* `setRange(long rangeStart, long rangeEnd)` 设置Range头信�,�用于[分�下载](/v1/updown.html#实现分�下载) + +* `bind(Object object)` 绑定一个对象,�用于实现Android里的[生命周期绑定](/v1/android.html#生命周期绑定) + +## 使用标签 + +  有时候我们想对HTTP任务加以分类,这时候�以使用标签功能: + +```java +http.async("/users") //(1) + .setTag("A") + .get(); + +http.async("/users") //(2) + .setTag("A.B") + .get(); + +http.async("/users") //(3) + .setTag("B") + .get(); + +http.async("/users") //(4) + .setTag("B") + .setTag("C") // 从 v1.0.4 标签将以追加模�添加,等效于 setTag("B.C") + .get(); + +http.async("/users") //(5) + .setTag("C") + .get(); +``` +  当使用标签�,就�以按标签批�的对HTTP任务进行�消: + +```java +int count = http.cancel("B"); //(2)(3)(4)被�消(�消标签包�"B"的任务) +System.out.println(count); // 输出 3 +``` +  标签除了�以用��消任务,在预处�器中它也�以�挥作用,请�� [并行预处�器](/v1/configuration.html#并行预处�器) 与 [串行预处�器(token问题最佳解决方案)](/v1/configuration.html#串行预处�器(token问题最佳解决方案))。 diff --git a/okhttps-doc/docs/v2/updown.md b/okhttps-doc/docs/v2/updown.md new file mode 100644 index 00000000..73486bac --- /dev/null +++ b/okhttps-doc/docs/v2/updown.md @@ -0,0 +1,223 @@ +--- +description: OkHttps 文件 上传 下载 进度监� 过程控制 断点续传 分�下载 +--- + +# 上传下载 + +## 文件下载 + +  OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例: + +```java +http.sync("/download/test.zip") + .get() // 使用 GET 方法(其它方法也�以,看�务器支�) + .getBody() // 得到报文体 + .toFile("D:/download/test.zip") // 下载到指定的路径 + .start(); // �动下载 + +http.sync("/download/test.zip").get().getBody() + .toFolder("D:/download") // 下载到指定的目录,文件�将根�下载信�自动生� + .start(); +``` +  或使用异步连接方�: + +```java +http.async("/download/test.zip") + .setOnResponse((HttpResult result) -> { + result.getBody().toFolder("D:/download").start(); + }) + .get(); +``` +  这里�说明一下:`sync`与`async`的区别在于连接�务器并得到�应这个过程的�步与异步(这个过程的耗时在大文件下载中�比��),而`start`方法�动的下载过程则都是异步的。 + +### 下载进度监� + +  就直接上代�啦,诸�一看便懂: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .setStepBytes(1024) // 设置�接收 1024 个字节执行一次进度回调(�设置默认为 8192) + // .setStepRate(0.01) // 设置�接收 1% 执行一次进度回调(�设置以 StepBytes 为准) + .setOnProcess((Process process) -> { // 下载进度回调 + long doneBytes = process.getDoneBytes(); // 已下载字节数 + long totalBytes = process.getTotalBytes(); // 总共的字节数 + double rate = process.getRate(); // 已下载的比例 + boolean isDone = process.isDone(); // 是�下载完� + }) + .toFolder("D:/download/") // 指定下载的目录,文件�将根�下载信�自动生� + // .toFile("D:/download/test.zip") // 指定下载的路径,若文件已存在则覆盖 + .setOnSuccess((File file) -> { // 下载�功回调 + + }) + .start(); +``` +  值得一�的是:由于 OkHttps 并没有把下载�的很特别,这里设置的进度回调��对下载文件起用作,�使对�应JSON的常规请求,��设置了进度回调,它也会告诉你报文接收的进度(��是�务器�应的报文有`Content-Length`头),例如: + +```java +List users = http.sync("/users") + .get() + .getBody() + .setStepBytes(2) + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .toList(User.class); +``` + +### 下载过程控制 + +  过于简�:还是直接上代�: + +```java +Ctrl ctrl = http.sync("/download/test.zip") + .get() + .getBody() + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .toFolder("D:/download/") + .start(); // 该方法返回一个下载过程控制器 + +ctrl.status(); // 下载状� +ctrl.pause(); // 暂�下载 +ctrl.resume(); // ��下载 +ctrl.cancel(); // �消下载(�时会删除文件,����) +``` +  无论是�步还是异步�起的下载请求,都�以�以上的控制: + +```java +http.async("/download/test.zip") + .setOnResponse((HttpResult result) -> { + // 拿到下载控制器 + Ctrl ctrl = result.getBody().toFolder("D:/download/").start(); + }) + .get(); +``` + +### 实现断点续传 + +  OkHttps 对断点续传并没有��更高层次的�装,因为这是app该去�的事情,它在设计上使��网络问题的处��简�的�时力求纯粹。下�的例��以看到,OkHttps 通过一个失败回调拿到 **断点**,便将��的问题�得简�: + +```java +http.sync("/download/test.zip") + .get() + .getBody() + .toFolder("D:/download/") + .setOnFailure((Failure failure) -> { // 下载失败回调,以便接收诸如网络错误等失败信� + IOException e = failure.getException(); // 具体的异常信� + long doneBytes = failure.getDoneBytes(); // 已下载的字节数(断点),需��存,用于断点续传 + File file = failure.getFile(); // 下载生�的文件,需��存 ,用于断点续传(��存路径也�以) + }) + .start(); +``` +  下�代�实现续传: + +```java +long doneBytes = ... // 拿到�存的断点 +File file = ... // 待续传的文件 + +http.sync("/download/test.zip") + .setRange(doneBytes) // 设置断点(已下载的字节数) + .get() + .getBody() + .toFile(file) // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + + }) + .setOnFailure((Failure failure) -> { + + }) + .start(); +``` + +### 实现分�下载 + +  当文件很大时,有时候我们会考虑分�下载,与断点续传的�路是一样的,示例代�: + +```java +static String url = "http://api.demo.com/download/test.zip" + +public static void main(String[] args) { + long totalSize = HttpUtils.sync(url).get().getBody() + .close() // 因为这次请求�是为了获得文件大�,�消费报文体,所以直接关闭 + .getContentLength(); // 获得待下载文件的大�(由于未消费报文体,所以该请求�会消耗下载报文体的时间和网络��) + download(totalSize, 0); // 从第 0 �开始下载 + sleep(50000); // 等待下载完�(�然本例的主线程就结�啦) +} + +static void download(long totalSize, int index) { + long size = 3 * 1024 * 1024; // ��下载 3M + long start = index * size; + long end = Math.min(start + size, totalSize); + HttpUtils.sync(url) + .setRange(start, end) // 设置本次下载的范围 + .get().getBody() + .toFile("D:/download/test.zip") // 下载到�一个文件里 + .setAppended() // 开�文件追加模� + .setOnSuccess((File file) -> { + if (end < totalSize) { // 若未下载完,则继续下载下一� + download(totalSize, index + 1); + } else { + System.out.println("下载完�"); + } + }) + .start(); +} +``` + +## 文件上传 + +  一个简�文件上传的示例: + +```java +http.sync("/upload") + .addFileParam("test", "D:/download/test.zip") + .post(); // 上传�法一般使用 POST 或 PUT,看�务器支� +``` +  异步上传也是完全一样: + +```java +http.async("/upload") + .addFileParam("test", "D:/download/test.zip") + .post(); +``` + +### 上传进度监� + +  OkHttps 的上传进度监�,监�的是所有请求报文体的��进度,示例代�: + +```java +http.sync("/upload") + .addBodyParam("name", "Jack") + .addBodyParam("age", 20) + .addFileParam("avatar", "D:/image/avatar.jpg") + .setStepBytes(1024) // 设置��� 1024 个字节执行一次进度回调(�设置默认为 8192) + // .setStepRate(0.01) // 设置��� 1% 执行一次进度回调(�设置以 StepBytes 为准) + .setOnProcess((Process process) -> { // 上传进度回调 + long doneBytes = process.getDoneBytes(); // 已��字节数 + long totalBytes = process.getTotalBytes(); // 总共的字节数 + double rate = process.getRate(); // 已��的比例 + boolean isDone = process.isDone(); // 是���完� + }) + .post(); +``` +  咦�怎么感觉和下载的进度回调的一样?没错�OkHttps 还是使用�一套API处�上传和下载的进度回调,区别�在于上传是在`get/post`方法之�使用这些API,下载是在`getBody`方法之�使用。很好�解:`get/post`之�是准备��请求时段,有上传的�义,而`getBody`之�,已是报文�应的时段,当然是下载。 + +### 上传过程控制 + +  上传文件的过程控制就很简�,和常规请求一样,�有异步�起的上传�以�消: + +```java +HttpCall call = http.async("/upload") + .addFileParam("test", "D:/download/test.zip") + .setOnProcess((Process process) -> { + System.out.println(process.getRate()); + }) + .post(); + +call.cancel(); // �消上传 +``` +  上传就没有暂�和继续这个功能啦,应该没人有这个需求�? \ No newline at end of file From f519009621607fcd72bf5ccb33af471299803eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 13 May 2020 09:03:24 +0800 Subject: [PATCH 282/924] =?UTF-8?q?=E4=BC=98=E5=8C=96=20pom=20=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps/pom.xml | 7 +++++-- pom.xml | 14 -------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/okhttps/pom.xml b/okhttps/pom.xml index cdc49691..25996b07 100644 --- a/okhttps/pom.xml +++ b/okhttps/pom.xml @@ -12,14 +12,17 @@ - + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + com.squareup.okhttp3 mockwebserver ${okhttp.version} test - diff --git a/pom.xml b/pom.xml index 942a5544..fd8b563e 100644 --- a/pom.xml +++ b/pom.xml @@ -52,20 +52,12 @@ - - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - - junit junit ${junit.version} test - @@ -98,7 +90,6 @@ okhttps - org.apache.maven.plugins maven-release-plugin @@ -109,7 +100,6 @@ -Psonatype-oss-release - org.apache.maven.plugins maven-compiler-plugin @@ -121,7 +111,6 @@ true - org.apache.maven.plugins maven-source-plugin @@ -135,7 +124,6 @@ - org.apache.maven.plugins maven-javadoc-plugin @@ -149,7 +137,6 @@ - org.apache.maven.plugins maven-gpg-plugin @@ -164,7 +151,6 @@ - From 1ab1a199043bb2897d07dd61b584bb6816470a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 13 May 2020 10:17:37 +0800 Subject: [PATCH 283/924] =?UTF-8?q?v2=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okhttps-doc/docs/.vuepress/config.js | 1 + okhttps-doc/docs/v2/README.md | 95 ++++++---------------------- okhttps-doc/docs/v2/getstart.md | 88 ++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 74 deletions(-) create mode 100644 okhttps-doc/docs/v2/getstart.md diff --git a/okhttps-doc/docs/.vuepress/config.js b/okhttps-doc/docs/.vuepress/config.js index ca27057a..ab1603b0 100644 --- a/okhttps-doc/docs/.vuepress/config.js +++ b/okhttps-doc/docs/.vuepress/config.js @@ -30,6 +30,7 @@ module.exports = { ], '/v2/': [ '', + 'getstart', 'foundation', 'configuration', 'features', diff --git a/okhttps-doc/docs/v2/README.md b/okhttps-doc/docs/v2/README.md index 84a45c42..caecab82 100644 --- a/okhttps-doc/docs/v2/README.md +++ b/okhttps-doc/docs/v2/README.md @@ -2,102 +2,49 @@ description: OkHttps 安装 构建实例 HTTP build �步请求 异步请求 sync async BaseUrl request webSocket gradle maven ejlchina --- -# 起步 +# 介� + +## OkHttps 简介   OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 * 链�调用,一点到底 - * BaseURL�URL��符�JSON自动�装与解� + * BaseURL�URL��符�HTTP�WebSocket + * JSON�Xml 等自动�装与解�,且支�与任�格�的数�解�框架集� * �步拦截器�异步预处�器�回调执行器�全局监��回调阻断 * 文件上传下载(过程控制�进度监�) * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 ::: tip -* OkHttps �常轻�(59Kb),仅是 Retrofit(124Kb)的一�,并且更加的开箱�用,API 也更加自然和语义化。 +* OkHttps �常轻�(83Kb,Retrofit:124Kb),除 Okhttp 无第三方�赖,并且更加的开箱�用,API 也更加自然和语义化。 * OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit �� * OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。 ::: -## 安装 - -### Maven - -```xml - - com.ejlchina - okhttps - 1.0.5 - -``` -### Gradle - -```groovy -implementation 'com.ejlchina:okhttps:1.0.5' -``` - -安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��: - -```groovy -android { - // �略其它�置.. - compileOptions { - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - } -} -``` - -## 使用 - -### 构建实例 - -```java -HTTP http = HTTP.builder().build(); -``` -  以上代�构建了一个最简�的`HTTP`实例,它拥有以下方法: +### �选�赖 -* `sync(String url)` 开始一个�步请求 -* `async(String url)` 开始一个异步请求 -* `cancel(String tag)` 按标签�消请求 -* `cancelAll()` �消所有HTTP任务,包括�步和异步 -* `request(Request request)` OkHttp 原生请求 -* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 +项目 | 最新版本 | �述 +-|-|- +okhttps-fastjson | 2.0.0.RC | 与 fastjson 集� +okhttps-gson | 2.0.0.RC | 与 gson 集� +okhttps-jackson | 2.0.0.RC | 与 jackson 集� -  为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(详� [设置 BaseUrl](/v1/configuration.html#设置-baseurl)): +以上是官方维护的与三大JSON框架集�的案例,�续将�供 xml 和 protobuf 的集�。 -```java -HTTP http = HTTP.builder() - .baseUrl("http://api.demo.com") - .build(); -``` -  为了简化文档,下文中出现的`http`�是在构建时设置了`BaseUrl`的`HTTP`实例。 -### �步请求 +## v2.x 的新特性 -  使用方法`sync(String url)`开始一个�步请求: +* HTTP 任务新增`patch()`方法,��起 PATCH 请求,目�直接支�的 HTTP 方法有:GET�POST�PUT�PATCH�DELETE,并且暴露了`request(String method)`方法,�自定义�起任何请求,如:HEAD�OPTIONS�TRACE�CONNECT 等; -```java -List users = http.sync("/users") // http://api.demo.com/users - .get() // GET请求 - .getBody() // 获��应报文体 - .toList(User.class); // 得到目标数� -``` -  方法`sync`返回一个�步`HttpTask`,�链�使用。 +* HTTP 任务新增`skipPreproc()`和`skipSerialPreproc()`,具体请求�跳过 所有 或�跳过 串行 预处�器; -### 异步请求 +* 新增`MsgConvertor`接�,实现 OkHttps 与 fastjson 解耦,且���赖�个具体 json 框架�甚至��赖 json,它�以与 **任何格�** 的数�解�框架 集�,如:json �xml �protobuf 等; -  使用方法`async(String url)`开始一个异步请求: +* 构建`HTTP`实例时支�注入多个`MsgConvertor`,�实现�一个`HTTP`实例下,既有 json 解�,�有 xml 解�等强大特性,�时还�以让表�(form)请求�数 � json�xml 一样,支��列化功能。 -```java -http.async("/users/1") // http://api.demo.com/users/1 - .setOnResponse((HttpResult result) -> { - // 得到目标数� - User user = result.getBody().toBean(User.class); - }) - .get(); // GET请求 -``` -  方法`async`返回一个异步`HttpTask`,�链�使用。 +* `HTTP`接�新增`webSocket(String url)`方法,与`sync(String url)`和`async(String url)`一样,支� Lamda 编程�预处�器机制�消�数�自动�列化和��列化机制; +* 新增`OkHttps`工具类,支� SPI 方�注入�置,`OkHttps`和`HttpUtils`默认自动以 SPI 方�寻找�赖中的`MsgConvertor`; -**至此,你已轻�学会了 OkHttps 95% 的常规用法�但别急,��还有更精彩的。** \ No newline at end of file +* 新增�自定义默认编�(�自定义�然默认为 utf-8)�具体请求�指定特殊编�功能。 \ No newline at end of file diff --git a/okhttps-doc/docs/v2/getstart.md b/okhttps-doc/docs/v2/getstart.md new file mode 100644 index 00000000..7b75628c --- /dev/null +++ b/okhttps-doc/docs/v2/getstart.md @@ -0,0 +1,88 @@ +--- +description: OkHttps 安装 构建实例 HTTP build �步请求 异步请求 sync async BaseUrl request webSocket gradle maven ejlchina +--- + +# 起步 + +## 安装 + +### Maven + +```xml + + com.ejlchina + okhttps + 1.0.5 + +``` +### Gradle + +```groovy +implementation 'com.ejlchina:okhttps:1.0.5' +``` + +安�中使用需�把 JDK 版本调� 1.8,在 app 模�的 build.gradle 中加入以下�置��: + +```groovy +android { + // �略其它�置.. + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } +} +``` + +## 使用 + +### 构建实例 + +```java +HTTP http = HTTP.builder().build(); +``` +  以上代�构建了一个最简�的`HTTP`实例,它拥有以下方法: + +* `sync(String url)` 开始一个�步请求 +* `async(String url)` 开始一个异步请求 +* `cancel(String tag)` 按标签�消请求 +* `cancelAll()` �消所有HTTP任务,包括�步和异步 +* `request(Request request)` OkHttp 原生请求 +* `webSocket(Request request, WebSocketListener listener)` WebSocket通讯 + +  为了使用方便,在构建的时候,我们更愿�指定一个`BaseUrl`(详� [设置 BaseUrl](/v1/configuration.html#设置-baseurl)): + +```java +HTTP http = HTTP.builder() + .baseUrl("http://api.demo.com") + .build(); +``` +  为了简化文档,下文中出现的`http`�是在构建时设置了`BaseUrl`的`HTTP`实例。 + +### �步请求 + +  使用方法`sync(String url)`开始一个�步请求: + +```java +List users = http.sync("/users") // http://api.demo.com/users + .get() // GET请求 + .getBody() // 获��应报文体 + .toList(User.class); // 得到目标数� +``` +  方法`sync`返回一个�步`HttpTask`,�链�使用。 + +### 异步请求 + +  使用方法`async(String url)`开始一个异步请求: + +```java +http.async("/users/1") // http://api.demo.com/users/1 + .setOnResponse((HttpResult result) -> { + // 得到目标数� + User user = result.getBody().toBean(User.class); + }) + .get(); // GET请求 +``` +  方法`async`返回一个异步`HttpTask`,�链�使用。 + + +**至此,你已轻�学会了 OkHttps 95% 的常规用法�但别急,��还有更精彩的。** \ No newline at end of file From 64b1227e83e8fe6395cd802889aee925251b694d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 13 May 2020 10:29:52 +0800 Subject: [PATCH 284/924] =?UTF-8?q?v2=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 52 ++++++++++++++++++++++++++++++++++- okhttps-doc/docs/v2/README.md | 8 +++--- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index aea850a2..e8068c0e 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,60 @@ Troy.Zhou

-## Documentation +# 文档 官网 http://okhttps.ejlchina.com/ +# OkHttps 简介 + +  OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 + + * 链�调用,一点到底 + * BaseURL�URL��符�HTTP�WebSocket + * JSON�Xml 等自动�装与解�,且支�与任�格�的数�解�框架集� + * �步拦截器�异步预处�器�回调执行器�全局监��回调阻断 + * 文件上传下载(过程控制�进度监�) + * �方法回调,充分利用 Lambda 表达� + * TCP连接池�Http2 + +::: tip +* OkHttps �常轻�(83Kb,Retrofit:124Kb),除 Okhttp 无第三方�赖,并且更加的开箱�用,API 也更加自然和语义化。 +* OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit �� +* OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。 +::: + +# 相关项目 + +项目 | 最新版本 | �述 +-|-|- +okhttps-fastjson | 2.0.0.RC | 与 fastjson 集� +okhttps-gson | 2.0.0.RC | 与 gson 集� +okhttps-jackson | 2.0.0.RC | 与 jackson 集� + +以上是官方维护的与三大 JSON 框架集�的案例,�续将�供 xml 和 protobuf 的集�。 + + +# v2.x 的新特性 + +* HTTP 任务新增`patch()`方法,��起 PATCH 请求,目�直接支�的 HTTP 方法有:GET�POST�PUT�PATCH�DELETE,并且暴露了`request(String method)`方法,�自定义�起任何请求,如:HEAD�OPTIONS�TRACE�CONNECT 等; + +* HTTP 任务新增`skipPreproc()`和`skipSerialPreproc()`方法,具体请求�跳过 所有 或�跳过 串行 预处�器; + +* 新增`MsgConvertor`接�,实现 OkHttps 与 fastjson 解耦,且���赖�个具体 json 框架�甚至��赖 json,它�以与 **任何格�** 的数�解�框架集�,如:json �xml �protobuf 等; + +* 构建`HTTP`实例时支�注入多个`MsgConvertor`,�实现�一个`HTTP`实例下,既有 json 解�,�有 xml 解�等强大特性,�时还�以让表�(form)请求�数 � json�xml 一样,支��列化功能。 + +* `HTTP`接�新增`webSocket(String url)`方法,与`sync(String url)`和`async(String url)`一样,支� Lamda 编程�预处�器机制�消�数�自动�列化和��列化机制; + +* 新增`OkHttps`工具类,支� SPI 方�注入�置,`OkHttps`和`HttpUtils`默认自动以 SPI 方�寻找�赖中的`MsgConvertor`; + +* 新增�自定义默认编�(�自定义�然默认为 utf-8)�具体请求�指定特殊编�功能。 + + +## v2.x 的文档续完善中请关注官网:http://okhttps.ejlchina.com/ + +## 以下是 v1.x 的文档 + ## 介�   OkHttps 是近期开�的对 OkHttp3 轻��装的框架,它独创的异步预处�器,特色的标签,�活的上传下载进度监�与过程控制功能,在轻�解决很多原本�人头疼问题的�时,设计上也力求纯粹与优雅。 diff --git a/okhttps-doc/docs/v2/README.md b/okhttps-doc/docs/v2/README.md index caecab82..279f47c1 100644 --- a/okhttps-doc/docs/v2/README.md +++ b/okhttps-doc/docs/v2/README.md @@ -22,7 +22,7 @@ description: OkHttps 安装 构建实例 HTTP build �步请求 异步请求 sy * OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。 ::: -### �选�赖 +### 相关项目 项目 | 最新版本 | �述 -|-|- @@ -30,16 +30,16 @@ okhttps-fastjson | 2.0.0.RC | 与 fastjson 集� okhttps-gson | 2.0.0.RC | 与 gson 集� okhttps-jackson | 2.0.0.RC | 与 jackson 集� -以上是官方维护的与三大JSON框架集�的案例,�续将�供 xml 和 protobuf 的集�。 +以上是官方维护的与三大 JSON 框架集�的案例,�续将�供 xml 和 protobuf 的集�。 ## v2.x 的新特性 * HTTP 任务新增`patch()`方法,��起 PATCH 请求,目�直接支�的 HTTP 方法有:GET�POST�PUT�PATCH�DELETE,并且暴露了`request(String method)`方法,�自定义�起任何请求,如:HEAD�OPTIONS�TRACE�CONNECT 等; -* HTTP 任务新增`skipPreproc()`和`skipSerialPreproc()`,具体请求�跳过 所有 或�跳过 串行 预处�器; +* HTTP 任务新增`skipPreproc()`和`skipSerialPreproc()`方法,具体请求�跳过 所有 或�跳过 串行 预处�器; -* 新增`MsgConvertor`接�,实现 OkHttps 与 fastjson 解耦,且���赖�个具体 json 框架�甚至��赖 json,它�以与 **任何格�** 的数�解�框架 集�,如:json �xml �protobuf 等; +* 新增`MsgConvertor`接�,实现 OkHttps 与 fastjson 解耦,且���赖�个具体 json 框架�甚至��赖 json,它�以与 **任何格�** 的数�解�框架集�,如:json �xml �protobuf 等; * 构建`HTTP`实例时支�注入多个`MsgConvertor`,�实现�一个`HTTP`实例下,既有 json 解�,�有 xml 解�等强大特性,�时还�以让表�(form)请求�数 � json�xml 一样,支��列化功能。 From 2db058d3f06f3d4ef4da339c0a1f96f50a0eb516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 13 May 2020 10:32:35 +0800 Subject: [PATCH 285/924] =?UTF-8?q?v2=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index e8068c0e..1756934c 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,6 @@ * �方法回调,充分利用 Lambda 表达� * TCP连接池�Http2 -::: tip -* OkHttps �常轻�(83Kb,Retrofit:124Kb),除 Okhttp 无第三方�赖,并且更加的开箱�用,API 也更加自然和语义化。 -* OkHttps 是一个纯粹的 Java 网络开�包,并��赖 Android,这一点和 Retrofit �� -* OkHttps 用起�很优美,�以� RxJava 那样链�用,�比 RxJava 更简�。 -::: - # 相关项目 项目 | 最新版本 | �述 From 19b55ed47f01b34106b8f929bea437a47928320e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 13 May 2020 10:35:11 +0800 Subject: [PATCH 286/924] =?UTF-8?q?v2=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 1756934c..faba8872 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ okhttps-jackson | 2.0.0.RC | 与 jackson 集� * 新增�自定义默认编�(�自定义�然默认为 utf-8)�具体请求�指定特殊编�功能。 -## v2.x 的文档续完善中请关注官网:http://okhttps.ejlchina.com/ +## v2.x 的文档续完善中,请关注官网:http://okhttps.ejlchina.com/ ## 以下是 v1.x 的文档 @@ -160,9 +160,7 @@ HTTP http = HTTP.builder().build();   以上代�构建了一个最简�的`HTTP`实例,它拥有以下方法: * `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) -* `async()` 开始一个异步HTTP任务,使用该方法必须在构建时设置 BaseUrl * `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) -* `sync()` 开始一个�步HTTP任务,使用该方法必须在构建时设置 BaseUrl * `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) * `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) * `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) @@ -563,9 +561,7 @@ HTTP http = HTTP.builder() * `of(HTTP http)` �置`HttpUtils`�有的`HTTP`实例(�调用此方法�默认使用一个没有没有�过任何�置的`HTTP`懒实例) * `async(String url)` 开始一个异步请求 (内部通过一个`HTTP`�例实现) -* `async()` 开始一个异步HTTP任务,使用该方法必须在构建时设置 BaseUrl * `sync(String url)` 开始一个�步请求 (内部通过一个`HTTP`�例实现) -* `sync()` 开始一个�步HTTP任务,使用该方法必须在构建时设置 BaseUrl * `cancel(String tag)` 按标签�消请求(内部通过一个`HTTP`�例实现) * `cancelAll()` �消所有HTTP任务,包括�步和异步(内部通过一个`HTTP`�例实现) * `request(Request request)` OkHttp 原生请求 (该请求��过 预处�器) From b86a2728618e9b3372e47b87d6075320443930d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 13 May 2020 10:38:25 +0800 Subject: [PATCH 287/924] update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index faba8872..81a52566 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ okhttps-jackson | 2.0.0.RC | 与 jackson 集� * 新增�自定义默认编�(�自定义�然默认为 utf-8)�具体请求�指定特殊编�功能。 -## v2.x 的文档续完善中,请关注官网:http://okhttps.ejlchina.com/ +## v2.x 的文档将在官网中�续完善,请关注:http://okhttps.ejlchina.com/ ## 以下是 v1.x 的文档 From 347432ed2d190ea3f7bac9827d8b2f347bb10de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 13 May 2020 11:05:34 +0800 Subject: [PATCH 288/924] v2 doc --- okhttps-doc/docs/v2/README.md | 1 - okhttps-doc/docs/v2/android.md | 2 ++ okhttps-doc/docs/v2/configuration.md | 2 ++ okhttps-doc/docs/v2/features.md | 2 ++ okhttps-doc/docs/v2/foundation.md | 2 ++ okhttps-doc/docs/v2/getstart.md | 2 ++ okhttps-doc/docs/v2/updown.md | 2 ++ 7 files changed, 12 insertions(+), 1 deletion(-) diff --git a/okhttps-doc/docs/v2/README.md b/okhttps-doc/docs/v2/README.md index 279f47c1..a589f702 100644 --- a/okhttps-doc/docs/v2/README.md +++ b/okhttps-doc/docs/v2/README.md @@ -32,7 +32,6 @@ okhttps-jackson | 2.0.0.RC | 与 jackson 集� 以上是官方维护的与三大 JSON 框架集�的案例,�续将�供 xml 和 protobuf 的集�。 - ## v2.x 的新特性 * HTTP 任务新增`patch()`方法,��起 PATCH 请求,目�直接支�的 HTTP 方法有:GET�POST�PUT�PATCH�DELETE,并且暴露了`request(String method)`方法,�自定义�起任何请求,如:HEAD�OPTIONS�TRACE�CONNECT 等; diff --git a/okhttps-doc/docs/v2/android.md b/okhttps-doc/docs/v2/android.md index 73c7fde5..36c8399d 100644 --- a/okhttps-doc/docs/v2/android.md +++ b/okhttps-doc/docs/v2/android.md @@ -4,6 +4,8 @@ description: OkHttps 安� 生命周期 UI线程 主线程 IO线程 自由 � # 安� +#### 哎呀,作者还在加�中,2.x 的文档很快就出�,先看一下 1.x 的文档� :joy: + ## 回调线程切�   在 Android 开�中,�常会把�些代�放到特点的线程去执行,比如网络请求�应�的页�更新在主线程(UI线程)执行,而�存文件则在IO线程�作。OkHttps 为这类问题�供了良好的方案。 diff --git a/okhttps-doc/docs/v2/configuration.md b/okhttps-doc/docs/v2/configuration.md index 30bf60e9..a2026b82 100644 --- a/okhttps-doc/docs/v2/configuration.md +++ b/okhttps-doc/docs/v2/configuration.md @@ -4,6 +4,8 @@ description: OkHttps �置 BaseUrl 回调执行器 主线程 UI线程 OkHttpCli # �置 +#### 哎呀,作者还在加�中,2.x 的文档很快就出�,先看一下 1.x 的文档� :joy: + ## 设置 BaseUrl ```java diff --git a/okhttps-doc/docs/v2/features.md b/okhttps-doc/docs/v2/features.md index 56771574..72e4d754 100644 --- a/okhttps-doc/docs/v2/features.md +++ b/okhttps-doc/docs/v2/features.md @@ -4,6 +4,8 @@ description: OkHttps 使用 HttpUtils 类 WebSocket 异常处� nothrow 异常 # 特色 +#### 哎呀,作者还在加�中,2.x 的文档很快就出�,先看一下 1.x 的文档� :joy: + ## 使用 HttpUtils 类   类`HttpUtils`本是 [�身 HttpUtils](https://gitee.com/ejlchina-zhxu/httputils) 的 1.x 版本里的最��的核心类,由于在��的版本里抽象出了`HTTP`接�,使得它的��性已�如往昔。但��的使用它,�然�以带��少便利,特别是在没有IOC容器的环境里,比如在Android开�和一些工具项目的开�中。 diff --git a/okhttps-doc/docs/v2/foundation.md b/okhttps-doc/docs/v2/foundation.md index e48cd8af..6679df54 100644 --- a/okhttps-doc/docs/v2/foundation.md +++ b/okhttps-doc/docs/v2/foundation.md @@ -4,6 +4,8 @@ description: OkHttps 请求方法 回调函数 HttpResult cache 多次 消费报 # 基础 +#### 哎呀,作者还在加�中,2.x 的文档很快就出�,先看一下 1.x 的文档� :joy: + ## 请求方法   �步与异步的`HttpTask`都拥有`get`�`post`�`put`与`delete`方法。��的是:�步`HttpTask`的这些方法返回一个`HttpResult`,而异步`HttpTask`的这些方法返回一个`HttpCall`。 diff --git a/okhttps-doc/docs/v2/getstart.md b/okhttps-doc/docs/v2/getstart.md index 7b75628c..04c3cd11 100644 --- a/okhttps-doc/docs/v2/getstart.md +++ b/okhttps-doc/docs/v2/getstart.md @@ -4,6 +4,8 @@ description: OkHttps 安装 构建实例 HTTP build �步请求 异步请求 sy # 起步 +#### 哎呀,作者还在加�中,2.x 的文档很快就出�,先看一下 1.x 的文档� :joy: + ## 安装 ### Maven diff --git a/okhttps-doc/docs/v2/updown.md b/okhttps-doc/docs/v2/updown.md index 73486bac..679efd46 100644 --- a/okhttps-doc/docs/v2/updown.md +++ b/okhttps-doc/docs/v2/updown.md @@ -4,6 +4,8 @@ description: OkHttps 文件 上传 下载 进度监� 过程控制 断点续传 # 上传下载 +#### 哎呀,作者还在加�中,2.x 的文档很快就出�,先看一下 1.x 的文档� :joy: + ## 文件下载   OkHttps 并没有把文件的下载排除在常规的请求之外,�一套API,它优雅的设计使得下载与常规请求��的毫无�和感,一个最简�的示例: From f62709aef38ce1591c658271257a40f56d8aaf8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 13 May 2020 11:18:13 +0800 Subject: [PATCH 289/924] v2 doc --- okhttps-doc/docs/.vuepress/config.js | 2 +- okhttps-doc/package.json | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/okhttps-doc/docs/.vuepress/config.js b/okhttps-doc/docs/.vuepress/config.js index ab1603b0..6ad753aa 100644 --- a/okhttps-doc/docs/.vuepress/config.js +++ b/okhttps-doc/docs/.vuepress/config.js @@ -51,7 +51,7 @@ module.exports = { }, // 若全局使用 vuepress,back-to-top 就会失效 plugins: [ - '@vuepress/back-to-top', 'code-switcher', 'baidu-autopush', 'seo', + '@vuepress/back-to-top', 'baidu-autopush', 'seo', ['baidu-tongji', {hm: '6eb41c0ab450d5a4ae8769682ecb0ab2'}], ], markdown: { diff --git a/okhttps-doc/package.json b/okhttps-doc/package.json index f9d1f6a9..338b4466 100644 --- a/okhttps-doc/package.json +++ b/okhttps-doc/package.json @@ -7,11 +7,9 @@ "@vuepress/plugin-back-to-top": "^1.4.1", "vuepress": "^1.4.1", "vuepress-plugin-baidu-autopush": "^1.0.1", - "vuepress-plugin-baidu-tongji": "^1.0.1", "vuepress-plugin-seo": "^0.1.2" }, "dependencies": { - "vuepress-plugin-code-switcher": "^1.0.3", - "vuepress-plugin-smartlook": "0.0.6" + "vuepress-plugin-baidu-tongji": "^1.0.1" } } From 23a4c268005bd59cd2d32eefe2f649b5e7ee3da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=97=AD?= Date: Wed, 13 May 2020 17:22:58 +0800 Subject: [PATCH 290/924] =?UTF-8?q?v2=20doc-=E8=B5=B7=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.vuepress/public/spi_config_android.png | Bin 0 -> 11143 bytes okhttps-doc/docs/README.md | 52 ++--- okhttps-doc/docs/v2/getstart.md | 204 ++++++++++++++++-- .../com/ejlchina/test/WebSocketTests.java | 16 +- 4 files changed, 212 insertions(+), 60 deletions(-) create mode 100644 okhttps-doc/docs/.vuepress/public/spi_config_android.png diff --git a/okhttps-doc/docs/.vuepress/public/spi_config_android.png b/okhttps-doc/docs/.vuepress/public/spi_config_android.png new file mode 100644 index 0000000000000000000000000000000000000000..82db91236b3e6aab516b7a0fd37163abf4c314a8 GIT binary patch literal 11143 zcmb_?XH-+`)@}f$iZqd}NR@zerGwHzIw(jFguSImk3i_51}Q2{AX0=)??FQ`bPc-c zAOd2jMu|w5-r=r9-DjV1&mDJ+?>j#T$(yV>=bGi2&wSS#f6G{hk^Uk*2n1r()73Hs zfhZv$5XBilqz(eTNMbnr{WS2I4yJ4E3j&?( zApKEvdY3tZK%$rQwAAke+Alxzd?e6`$eXKGv8H9+Wn&jOPZfBI>Nce&v%{&nl&-7y zz-ltrm?>_myrWeUxaB9O@kaMXfxT`#t<&Y;NP$}vv=1-}35}xFMUy>gZwlXBH?8yA zoEmSuJ`_^09Vm4nRnQVscYX(w84foOFb{y6>=+Ij8ZB>tR9F1qaQN1efpXQt;)P4x z+#(vZd`Mi3iQv`lwou2ObuFt@_A|LR==gFFS8WYGYp`rA(aW2;kdc2Mr)lpez z**e~7hw9iHWG*pqv1y)XL04MVROoOAY3bOv9yG#&{EFgUKAY1^&$ralQ|(Wuz_ z@UpE~<$EMk*-qO|>q6VXirJSnE3%9yO8Ix2zlO{l5 z!oq^MDr#56_#q*d#~R^Bg~QOAA_yvZgpFjJg%HGKs@SV>{ycolEE0kAP}3@!-pJi4 zGeInvxrK*AQPy-RW2S-!MFW^3cYA!Q9}5~~AFPMiX`UIaX+JqytuzVW9}eP~txxM# zDZdP#x;vI06l37nn_zC;;IVgec7L^8er9cB0Ws!uP`mIfphXiQaYr&~N^;@fm&8U?t3(*GdGJL6eW%){?YFO)c9K%91 z&!Iz@ryS4GHywBn(bO`LuD-sWYu%TxZ|7G#?wZ^n>Y-XBP@`Z{Lez1fUAdc<1>wDRCW>&23&@96 zl0IfFV#P7rG5m1i(|2v~;%Zno&x7GolgjI>Ez+n8q1-_J8Oa*Y#*vgJpGOmaDZTGB z+Mpe4Vy%UB@1c0_3-&Tg#EaTVwjNqmI~jb|r<|AcrAMXb#g2GlCIfrz7KH6OJ?0vX zlpQCAr5y+S%h8fPM8rvlx4bG8F$*?T$Ckyw4e>h+O{*5w(qkf7!;yO&A9dXh79+ud4iLQU1Cji?g$%I%r9 zaDLnAYtskzUSoCFY9+O+{19KdOY8h%7Leqk{R%PdL-w+XT-M7~Q1-LE-N`0VzSxs< zJ%s&UscEU5gk95}kdt_z&NOwe(4yKU!G!%S=n3j|9UIz1t*YntpOD@(F2jB`HyRUB z8+F3{yVR?p4V^6M2?Bd_6^nPjALr}a%5KdbGAU4gvMbD1<7sIcfPeGZx#*HJlRZT5 z9fI%~T(omBDhex{?Q3c%IYv2SDOW>?HcGT8-Ha{^6keQ+HS@6H&}Y1vaS(Io+?-%E z%$3D=VxRyl`Z2Mn8K##Tw(p8ieS8!xUQ;Y~2bJ9Pyy)q4Y5{wNH62%Wsn^xB8O>6> z(XQ4aSq(;;Y7&$L9j1@zug6=^><`uzi^83o-&+_d4}S=))ml0D-CmV<%u=Oo{?Lol zv!U1NeZwZcom;YgHBWDDwSGyo!97NFWTmQ2;l++eykE@9yjudPeEe)oH+SmUC5CTW zV;3?`hn$z_ZuFhoR2@ZiE#BhN$if+I%umU9$B4)@gRK)`_{fGEw1eYvt`}ire2^yl zsWXqCWUj`xLnS?w!fU1wy(|)s%IzVLMlP4@(1Gld$@Y?B0e%lY=phoZscQQMNjPw~W4V=J9jokPA&7r-*GU`=<`vpq;8eD6LnY|%fV>G&X}-mEL8S`?l&uqx(qk!9_rQFCy)l;5;r;5tHf z$9g_ai|DBUhi9Ry8&9@yPA@&Phwmy)%cy#5VARf=M8mdnFfbNOBuh#vUesD@wh-~T zC)gRwuOIYW5NJAH9cEd#Ar_?H4)!1o292*tYqQ3QvG*KVlaQ)f4`>uy^^dTRfQBR- z76>N;0O#G!z5#mbFa14&45-c48)gT< z*!6jt*Ak>5)2W}`91X}dn;{87CSM`7?{RYb1e$hEGVqct_n#ZNMrs`G7$Q6{iy7lU z(#3?+rq$#BSN9#rQ>~%pa~uYG{(F<$&~-fw^2|Aq8f6@;JdfMMZ#H^MlQ@PJ*3d=L z9kqQpO`wbrPy@PtrSZ3&dI?$%kN^cB&>F7MUISOhf_UiwBG6UAwvVW0z?}x^MF4hM zJbSn5ZpSPE(xpU-PKAE{5P9(oW^z9s_Usr_YCHuA$c=A;Up37uOY=6(La!DHgfJ}) zj`WvqCm^7lmD$%1b7I1vi%~ENHC7phu@m#~^>;#}LaKXuTb-5~2VZD$qiN>xIDXuy z-%^5hXPl<_9nSr=_>_y2H!PsNy*+Tta0J?eiCPoB;7$mBX4+^h)O!wHT`g{os&yH3 z4)1pU{(Ys;-Z)RO6wM8h51{~Mn6$#;J(SCiXJZVTn9)Z470BZG8`=Dj_a<`?8~&;) zna#^0gr0HENhP`^TQTT$*`?|!(mhg7OiZZbQ`b8>I+i5yXL@i>zOEg@D#y)$~ z$xy=jiTBKfU3X_`M~B9}5i6!PspMR#&X*U@EjsHu-r64Tq7G;l`?B-G6DpOW2&T$c z9I*X5RDR)|yNi!=(YC_LjbPZo4ktlsHS*2&@P~~jdd9P1N*{{H9|)!po9sw`HNtn|zb@2#p!GqvJ(i83A=iq+^9q z)Y9Y8cY8OJ1WO>xJ@CoybcV}}p2-57rK_h0VLt^p?;^qN__%+cJ0?kzwdt(u@Lpqf@D~QVX>=B z?(x{w?mijc62r2DW#MPrRBAoE5N$jTXMQ2Da%g!Hq7qP^H{dWf$st_Hljh!Qvnicc zAgOI_jrBT0ZkA8RnyOmzLV~KgGWNOjr?#9{;T>Dm>e%(P8WZp4PIlM7tysyct2rn& zJA4!i)I&kc;_j~1^2&-EKD7oj6_adOug4YgWj;Fv`c(4H@uPHGId@f1k>NNlossgj zx(3q~r*2`S;Pso-`IymoW7sRXo?4HM7`&|aLGfHits2* zUt?_Sdv4I&5OL*2aoEC9m@2~y;hwCW`bPgJul9ml+YS%h8mLzH7SNK{1IF_9QMO=9zp7e+PVE7v*tht4`H-dB+G zg#>c~xPl*HuoSde*Nx+c-U?@_YMz#v>PTl&8*We84!?P%-j~5ab(@p$9$wNJMD<9E z>CV93QbggPIrmaRq}-D#F}%^bwQ4pH>Vd||ZPBr3;8kxsRU@~Wny<>0XRsyqLxW#m zPp&3Sculo=joG&)+Si!a4>F@i?V%kn>c`{{Lhc-jop;J_)Ab0S%v%(*&d#41YYH4B zGzDJcRTrnF%iv6@<~iJC-^$B9fG$9nW(wPniS9L7gsJ~(qP2K~6-hR;&S#6H`|;%-wI*{>Z%SOGpMng5oIgW;2o-z~Nqfq`?Z_O}=CF6oANEq*h@rM3P~T ztYq{V{LmMIy$B%ppWMiY%$NlvkXjfi0wu^w5awg#cT^tu6mlaOBg5p2Ci!4Jf3Nf|x z_6~KN7`6Hn4PH0(E0!A1Y@COm4Cf=H*Q1##LyRAf%=2_@&y5_FPFLri9er}+$P2!Z z%T&pO+-A`TrUULv_}xR8^6{?aD1i_Veb7`S29c|=+nss6zXi;wdSF@(t=9~L*&Lva zp@%R}PtWq@Wl#9=q5SC3(5S;Rpmkbg-dJ+!7_;)PA0TUCJ=Ox;e0p}zaQxl@<`D<;w5AlXr0ciM} zCD6CO-XnXz;$muF-_-!B2e7RNxtJzuAjQd^R`K4y8s>x{4rD1KRB_r}m}uB*o4w@; z27Kz|`a?YHWi=hvJVJ$VwhmUKH&#rT6|>0;c`kRn6eVdZ$8&%%qxe%<=o_~LpxNjQ z?zHpopi8&qM54wuL z;<-lo#k|A9=MFJA#?5!EKQqZnIN%ud+-fw2^IJX;V?Kce;8vw_8$YYg)_DQ~Y)Jg0 z;4JR6sOFn){j^a30#WmPEFAd8`R{KClk!scQ#lF5t*TB9-C61LOu7BJHwPIvuSS={ zC_ry|kB^V{b0&0u^57J`9oi@<%3YMJN zm8do6>-M=^>i`lbRfHRG9cL{!)7rCAL+uDWF9gI)a^mBrLDRYvC#{H#zgK3I+0Tn} zdZosm)dEA9R#g^=o0+}~3$Nj|FB#ZmFFqTy>~5A@zt#_Uir99^NMsUpmyfOK2q zW?b9mVAV6yI$`JGV3l$KTLcTO4xZ_g>K2tK}i882) z6VRYPRmjJ^n^!`qcAXjhKaTe zF;kSJgOwe?9g-6gcJ9#vQ^}~M;pqr}z`G!j6A+f`(}jG7ASDvF90APm?@4;_=`O@R;9AK#;`E!wSYck~C<(EvTFOdad69GLXr=~wxg-~YJ=C{6zULggyW&s1>lM93h; zM8m!t*HZnd{P$vr%o`cZ8`^g)NCr>=Q1@40JdD?Z-kqcTC7qXkT}QJeH)$)fQSC?W z#8DpHqumSSX)I;<^YU#v%e~7X|Kh5j1fpQ-=RWFa#=*F5xYJXN4?l!GQx35JAa3;L z_RD+#22tC41ZstHUI_E)y+S^FZvdhI4CLbGu2^1P{?kLRamia#w_*Gg=>2KHp65vq zb`Qck&w>03UxKywG+9{D65(nZQlo;PWPt8#MIvP0sO~nGfd1rcr5hXCjJ^MFOig3y zaje_b-=01i5fC;1LQs1w$R?Y*P6)K&f9m;!pdflWVk;V^E_3)rUSx~uBo`0*cC$vl zAKK{imQ4b`qM=(dUWA*rV)X6y=|)yEU*&ruF2KNR%q$T{4LBh}@tZj|F)3+uWd)rf zz9%waM@z!S7t$7*#E`US1gUJC<7}TFg_;L&vy9tA%pl))l`y(7wB0Zc3~eSOap%B2 z>opB5NRAQ7P@wLW6TT?Ya>TX`G>C25);G>$)P zU}6>~nXYyRx3&8vsj{O(vsPBsiG&g-Rpl?JEv`VOX#$$dL*3-n4go8ZDR0w_efW?u zK0R$QH<)J$(D9PG>wI{(C&ieh3uO)mKcL7iO<9)v?724TMG#OJ=i-d99{&FRBg9_R z=wnX#zUgg}Co|}Ar>}C5wbub{w7I$R2-TC^P$@t_(5Kgud z@o>af{RIhH95q<~GZ zB{B`(z+852%HlpZv@OABr_pW?<3_v$>Lrcu=i>CS`}{x%C_!sv;{}9)n4cxZ=)akn z|B?mBCnhZ^BEIG{1;eJ6?5Or@8Kws9PDM2QN;Z70%jky>7M_mboWEw~yKjLneaTe< zpml6)tXoLP^((ff5(g8^snv265xYO4Z)=*Ss=!BBSdYE(k6Y3bg8W}YWQE~~ZU&_g zMnK_KwChbaVea{{)cj`SGSu1H^%gICm8=HAr*fULo}dUC5}#xy8f{pjA!|s3hGu3G zhvWB=NiQH+xq>kTPDVX!40Ok_9HqS!!jOk_;b1G2!6?7p9U4rEFyVW77Gn*JM0ZlBtrp+mhwlC4$8 zo5gugTe;rl6?e^nDf_5Mu1zi?QS~ni-@m`}=r^&(dJMFFziUrtX;aGh^qJL(&JW@CY_pjQrS36>45j zGM20m+<1YsG<}^eR4emTk}Knln^ezsJY)~PkVK(-fgBBMLc#)6xG8E@oU=zFv)*S` zZ{e(tn~Wd#+2Ws3w#o8nuo{as-S7t@_9`@&YyyVjkcBGO(P$*o)3 zqz+1H5b?8gcp;){k`zh?QJ{C+BxN9ijo|(oBj!xk()m}wtOH;@kUAvl3KEX^L4y8Q zOO{ms##%W*78JiM+aiqqYB?03UTTs9bxpAi4GkmP+YL(L$1O@qN>asBweLq+Lo)lOz-C(NaPAmmS;pHwQ z)|&oKBCdPi-4(jYB86^ZJtQDl2e*DfQe41n63`s2h6fceF;S;=pQ;DC=Of6b{fKR& zYtm)2jP5RgWTy7}05sOJ3uFw;#Q;+7z+{RX4O1Z&$O}0_-8oTTSeYk?LNc=A;{0&uyjNJ ziqA54Vmht(Qc>XhJ>3Fb={&L**q0la(a9}A%dTJNIbZqwz>M>xhvW4CJ#jK<>+$E% zkRp~SCqB2TyMnha;Lkk#hzDB+mvmj*>q{$Ee?W;dpVusI6$Vs0=>3Q#0}8f0E-MaM zuNNhaevq(FmQic-yw|z$_Zufi=u!BYQW$)h^Hu6Ei28-*semF1Jn;B{lq0kEMD)M3 zOe)JgKlQCA<$RS!1SX{VBC_&*Z2UzRXL+3&PzE`|Fn$sVO(ou>?f23Pb$g@5VEV#w zj=}i0%J;K%2ElRzk3O8+d9Y2mlX}qwd#Z-X*w%OJrajM{mYO;bgnpf}`SK>ZDm3 z*y(bo{x<@GW!>6S4KqZztYQ*d{CCpLij&!(UL{uX^J3C)9Jn*fNv@_p7>5H(YBN6z z>*Is$Ej>$|fYv^8GgWT4b8fYpQkn9fk)A5q)ZD2t%7zn-j-s`H^lS8a$j|X9O7!-i z^2v!|x#{2$kzu;cr$WJp|9vXcQt^6f-#PxPMsGdbkiG6Y3w>>!zM1)1>cPf`t&>FHcqC7P>aywNKAbMJMp2dO4FB53Ou zb)Sgpt+>~CpM5-6G0(F}`2*MLXUFT^ZLqWMmXP>VYw=zUX-HH`^b1iX-)=)|EF|A& z_{PIwF^E~+N5kG0&iRSWq14g-w>!y3D?4#xUBIkVTjp!$TR1y+XlC;amo(t zG;dWRvJ9OhCOqy1D41Rj3C|Mmt$8{5RqHYQ?Sp^1#6pdPR{HR(W0YTP)wG=ttt-}- z49u}wIU0l06{0WeSkNsdc1ZUGm6xs5FEMD#B~kx=h45m=Ipy!;RiZl+=w%);UdjJe#qyZk-B74INQ4L*MT<|{r;<=DMm&dfSDoV?t)?GnZw-f^ zWb3!Cxr`F_ylECU0jk1l$Bbqiyqu(rZdbt`g^LJ}fgRau&k|CLI|{FdTRzNans*sV zT5XrKs#yi@V?GMz3DW`&gQPq4X6WR3Pot;(ItR-G5M~Xl=HBgqY9@`XbzLso_H#AW z=8m?liz|`A2Pln$i~E^c829iguHnTzu^j}o9(J^A#$y(K@HM;so?fE&k<(V8j`18F z*RUl(kNwoKax%Zpyy);C-Mdr59RDcVSPP+oH_b8R?KKuugWFdtS-^`Wf2ouAeqRIBJMr*!CrxYJuwd_biIn`Ys^|YwJ}e;5^}cOOa;34+i>jQxw%bL!(_u@u>FkRRKarawY7s!?L6Sy7|(^{ zk*(U1=_zls_9f35bX)Sv#WDCn8ESJK;gx4N8&WVKk{;sP)Zliqd?17&a(!uCCHfn2 zN*|c!O~)+m&5fF@wAvmme=m9du_(hf>_u|jOt1@|Yw9pmOkg=v)Y%FY;S>S$bf~&@ zG+r}xvCo6hL;a@W(&?UhL;UNJGe!R2>k8P#j5xb@3b82u@56B@6T9%LexME z1aRP_AnaO(e9T+q?tPcxu!C)l_bS^5#~v4Zb3xT=Sh=efWzJx~D&r}KOJV^|YShD+ zJ2IZx-y$KWa7o_pEHeRWUz{7FY2N~-sq<0p4IT8^<0=-zJ0Mzd!fUIL{z z@!sVmxMid*T<}@@7^dbUnjL+sxprUbGGY)`{Ux`0di}v!Ivx` zH;>pW-YsPmg%dDTomjYn$-b|+zu zxWa?7q>TgHkgy%B&-DTSwj6n*#-vqxuEnh>?l0TFXStr#E@r|#jgDp}!EbN%3{E8o zuD>%6Xebl*KksVMb{yA!$%-R`jv|>kYdQqT4{Eaymm>|9smVkrYcJ*XeydSGO>*PA4|WBbxY0Xwhh6!wUzm&H za9muw=lG~Wdj5tp?#XIpLX%wMj~Pht%A?Q?}i#qIq2L}Gfs#wH=`!i$p9C4v${ z%j{=>ZcJ8!oE1rX_hLu@y6}g8Wfo%|VLjs<#}n~xCE$rp&B^!3!)vTQPY`9sc|R^7 zfi#>Rl^ArZqA##}(cxJxz&(J0PMbDf$(=)jtue`9WsQD$@m~B}q<->?1d*RJ{QIsB*WQK;dZ7lG(rkcn;pbEVSNnC4Q6Jd2 zbx^PfajumPxhs3=%qSKesXdVwtDm<$5(w;@yapz$k}D#DZZf|aoiLE6xPG1T6Q+=e X%2QHOL1Vz-S&*K#u@+jxA?p7CHC??a literal 0 HcmV?d00001 diff --git a/okhttps-doc/docs/README.md b/okhttps-doc/docs/README.md index c57380ab..7f4e3b61 100644 --- a/okhttps-doc/docs/README.md +++ b/okhttps-doc/docs/README.md @@ -1,7 +1,7 @@ --- home: true heroImage: /logo.png -heroText: OkHttps +heroText: OkHttps V2 tagline: 基于 OkHttp 增强版 HTTP 客户端 actionText: �速上手 → actionLink: /v2/ @@ -20,52 +20,30 @@ footer: Apache Licensed | Copyright © 2020-present ejlchina