diff --git a/okhttps-doc/docs/.vuepress/config.js b/okhttps-doc/docs/.vuepress/config.js
index 6c60b7b8b5994b43f71984bbe287a68f99bf8359..16f328c7e77dfa1c744ec3881de246f784dce9c0 100644
--- a/okhttps-doc/docs/.vuepress/config.js
+++ b/okhttps-doc/docs/.vuepress/config.js
@@ -45,6 +45,8 @@ module.exports = {
'foundation',
'configuration',
'updownload',
+ 'websocket',
+ 'stomp',
'android'
]
},
diff --git a/okhttps-doc/docs/v2/README.md b/okhttps-doc/docs/v2/README.md
index 6e35dfd1442271edc37638ddba12aba147849007..ddbc1d7133426053add7aaafa88c92a25ff66cc0 100644
--- a/okhttps-doc/docs/v2/README.md
+++ b/okhttps-doc/docs/v2/README.md
@@ -33,6 +33,15 @@ okhttps | 2.3.0 | OkHttps 核心模块
[okhttps-stomp](https://gitee.com/ejlchina-zhxu/okhttps-stomp) | 1.0.1 | 超级轻量的 Stomp 客户端
+## v2.3 的新特性
+
+重新实现 WebSocket 心跳机制
+使用者可以选择使用 OkHttp 自带的新桃模式,也可以选择使用 OkHttps 提供的增强型新增机制,它具有如下特性
+
+1. 客户端发送的任何消息都具有一次客户端心跳作用
+2. 服务器发送的任何消息都具有一次服务器心跳作用
+3. 若服务器超过 3 * pongSeconds 秒没有回复心跳,才判断心跳超时
+
## v2.2 的新特性
1. 增强泛型反序列化,支持复合泛型
diff --git a/okhttps-doc/docs/v2/foundation.md b/okhttps-doc/docs/v2/foundation.md
index 0f0b58ddcd5ba277f2686966f503a1fad5d5b702..5e7ce347b91e43b964d798c847ca8abea0c03998 100644
--- a/okhttps-doc/docs/v2/foundation.md
+++ b/okhttps-doc/docs/v2/foundation.md
@@ -6,7 +6,7 @@ description: OkHttps 请求方法 回调函数 HttpResult cache 多次 消费报
## 请求方法
-OkHttps 使用`sync()`和`async()`方式发起的请求,支持的 HTTP 方法有:
+OkHttps 使用`sync(String url)`和`async(String url)`方法发起 同步和异步的 HTTP 请求,它们支持的方法有:
HTTP 请求方法 | 实现方法 | Restful 释义 | 起始版本
-|-|-|-
diff --git a/okhttps-doc/docs/v2/getstart.md b/okhttps-doc/docs/v2/getstart.md
index 6c70e042e9926490f5ab3248ddc8fb682089da11..58fc6efdae71df2a5bd94922ccbe65ae8c31d74b 100644
--- a/okhttps-doc/docs/v2/getstart.md
+++ b/okhttps-doc/docs/v2/getstart.md
@@ -14,7 +14,7 @@ description: OkHttps 安装 构建实例 HTTP build 同步请求 异步请求 sy
com.ejlchina
okhttps
- 2.2.0
+ 2.3.0
```
@@ -26,7 +26,7 @@ description: OkHttps 安装 构建实例 HTTP build 同步请求 异步请求 sy
com.ejlchina
okhttps-fastjson
- 2.2.0
+ 2.3.0
```
@@ -36,7 +36,7 @@ description: OkHttps 安装 构建实例 HTTP build 同步请求 异步请求 sy
com.ejlchina
okhttps-gson
- 2.2.0
+ 2.3.0
```
@@ -46,7 +46,7 @@ description: OkHttps 安装 构建实例 HTTP build 同步请求 异步请求 sy
com.ejlchina
okhttps-jackson
- 2.2.0
+ 2.3.0
```
@@ -54,12 +54,22 @@ description: OkHttps 安装 构建实例 HTTP build 同步请求 异步请求 sy
以上依赖四选一即可
:::
+#### 使用 Stomp 客户端
+
+```xml
+
+ com.ejlchina
+ okhttps-stomp
+ 1.0.1
+
+```
+
### Gradle
#### 单独使用 OkHttps
```groovy
-implementation 'com.ejlchina:okhttps:2.2.0'
+implementation 'com.ejlchina:okhttps:2.3.0'
```
单独使用 OkHttps 需要自定义[`MsgConvertor`](https://gitee.com/ejlchina-zhxu/okhttps/blob/master/okhttps/src/main/java/com/ejlchina/okhttps/MsgConvertor.java),否则无法使用 **自动正反序列化** 相关功能,后文会详细讲解哪些功能会受到此影响。
@@ -67,25 +77,30 @@ implementation 'com.ejlchina:okhttps:2.2.0'
#### 与 fastjson 一起使用
```groovy
-implementation 'com.ejlchina:okhttps-fastjson:2.2.0'
+implementation 'com.ejlchina:okhttps-fastjson:2.3.0'
```
#### 与 gson 一起使用
```groovy
-implementation 'com.ejlchina:okhttps-gson:2.2.0'
+implementation 'com.ejlchina:okhttps-gson:2.3.0'
```
#### 与 jackson 一起使用
```groovy
-implementation 'com.ejlchina:okhttps-jackson:2.2.0'
+implementation 'com.ejlchina:okhttps-jackson:2.3.0'
```
::: tip
以上依赖四选一即可
:::
+#### 使用 Stomp 客户端
+
+```groovy
+implementation 'com.ejlchina:okhttps-stomp:1.0.1'
+```
#### JDK 版本
diff --git a/okhttps-doc/docs/v2/stomp.md b/okhttps-doc/docs/v2/stomp.md
new file mode 100644
index 0000000000000000000000000000000000000000..932a7e1e744a3f9e26574d5cccc1fa7a95ed4edc
--- /dev/null
+++ b/okhttps-doc/docs/v2/stomp.md
@@ -0,0 +1,144 @@
+---
+description: OkHttps WebSocket Stomp OkHttp
+---
+
+# Stomp
+
+项目 [OkHttps Stomp](https://gitee.com/ejlchina-zhxu/okhttps-stomp) 基于 OkHttps 的 [WebSocket](/v2/websocket.html) 功能实现了一个非常轻量的 Stomp 客户端协议,它可以让你轻松实现 **广播发布与订阅** 和 **队列发布与订阅** 的客户端功能。
+
+## 添加依赖
+
+要开启 Stomp 功能,需要添加以下依赖:
+
+### Maven
+
+```xml
+
+ com.ejlchina
+ okhttps-stomp
+ 1.0.1
+
+```
+
+### Gradle
+
+```groovy
+implementation 'com.ejlchina:okhttps-stomp:1.0.1'
+```
+
+## 构建 Stomp 实例
+
+类`Stomp`提供静态方法`over`来构建`Stomp`实例:
+
+* `over(WebSocketTask task)` 基于 OkHttps 的 WebSocket 构建一个 Stomp 实例,并自动确认消息
+* `over(WebSocketTask task, boolean autoAck)` 构建一个 Stomp 实例,并可指定是否自动确认消息
+
+例如:
+
+```java
+// 使用一个 Websocket 连接构建一个 Stomp 实例,同时设置心跳间隔为 20 秒
+Stomp stomp = Stomp.over(OkHttps.webSocket("wss://...").heatbeat(20, 20));
+```
+
+以上代码构建了一个简单的 Stomp 客户端,并默认在收到消息时会**自动确认**,如果需要收到确认,可以使用下面的方式:
+
+```java
+Stomp stomp = Stomp.over(
+ OkHttps.webSocket("wss://...").heatbeat(20, 20),
+ false // 参数设置 autoAck 为 false,将需要手动确认消息
+ );
+```
+
+## 连接 Stomp 服务
+
+得到一个`Stomp`实例后,可使用以下两个方法连接 Stomp 服务器:
+
+* `connect()` 直接连接 Stomp 服务器
+* `connect(List headers)` 携带一些 Stomp 头信息连接 Stomp 服务器
+
+例如:
+
+```java
+stomp.connect();
+```
+
+如果服务器在连接时需要指令一些额外信息,比如连接 RabbitMQ 时需要指定`login`、`passcode` 和 `vhost`:
+
+```java
+List headers = new ArrayList<>();
+headers.add(new Header("login", "username"));
+headers.add(new Header("passcode", "xxxxxxx"));
+headers.add(new Header("host", "your_vhost"));
+
+stomp.connect(headers);
+```
+
+## 连接状态监听
+
+```java
+Stomp.over(OkHttps.webSocket("wss://...").heatbeat(20, 20))
+ .setOnConnected(stomp -> {
+ // 服务器连接成功回调
+ })
+ .setOnDisconnected(close -> {
+ // 连接已断开回调
+ })
+ .connect();
+```
+
+## 消息订阅与退订
+
+### 订阅广播
+
+```java
+stomp.topic("/your-topic", (Message msg) -> {
+ // 得到消息负载
+ String payload = msg.getPayload();
+
+ // 如果需要手动确认消息,调用此方法确认
+ stomp.ack(msg)
+});
+```
+
+### 退订广播
+
+```java
+stomp.untopic("/your-topic");
+```
+
+### 订阅队列
+
+```java
+stomp.queue("/your-queue", (Message msg) -> {
+ // 得到消息负载
+ String payload = msg.getPayload();
+
+ // 如果需要手动确认消息,调用此方法确认
+ stomp.ack(msg)
+});
+```
+
+### 退订队列
+
+```java
+stomp.unqueue("/your-queue");
+```
+
+## 发送消息
+
+```java
+// 发送到广播
+stomp.sendTo("/topic/your-topic", "Hello World");
+// 发送到队列
+stomp.sendTo("/queue/your-queue", "Hello World");
+```
+
+## 断开服务
+
+```java
+stomp.disconnect();
+```
+
+
+
+
\ No newline at end of file
diff --git a/okhttps-doc/docs/v2/websocket.md b/okhttps-doc/docs/v2/websocket.md
new file mode 100644
index 0000000000000000000000000000000000000000..a749536c76881171701bdb759817df2e6a3352d0
--- /dev/null
+++ b/okhttps-doc/docs/v2/websocket.md
@@ -0,0 +1,162 @@
+---
+description: OkHttps WebSocket Heatbeat 心跳 OkHttp
+---
+
+# WebSocket
+
+OkHttps 使用`webSocket(String url)`方法发起 WebSocket 连接,并使用`listen()`方法启动监听。
+
+## 连接参数
+
+如果在连接时需要向服务器传递参数,处理方式和 HTTP 请求一样,例如需要用户名和密码才能连接 WebSocket 服务:
+
+```java
+http.webSocket("/chat")
+ .addUrlPara("username", "Jack")
+ .addUrlPara("password", "xxxxxxxx")
+ .setOnMessage((WebSocket ws,Message msg) -> {
+
+ })
+ .listen(); // 启动监听
+```
+
+::: warning 注意
+WebSocket 连接只能添加 **请求头**、 **Url 参数**(查询参数)和 **Path 参数**, 报文体参数(Body)和 文件参数是不允许添加的。
+:::
+
+## 心跳机制
+
+OkHttps 自带两种心跳机制
+
+### 全局心跳配置
+
+在构建`HTTP`实例时,可以配置一个全局心跳时间间隔:
+
+```java
+HTTP http = HTTP.builder()
+ .config((OkHttpClient.Builder builder) -> {
+
+ // 配置 WebSocket 心跳间隔(默认没有心跳)
+ builder.pingInterval(10, TimeUnit.SECONDS);
+ })
+ .build();
+```
+
+如上配置,当使用这个`HTTP`实例发起 WebSocket 连接时,客户端会每隔 10秒 向服务器发送一次 PING 消息,同时服务器必须在客户端发送心跳后的 10秒 内回复 PONG 消息,否则就会触发`SocketTimeoutException`异常
+
+### 单次心跳配置(since V2.3.0)
+
+自 V2.3.0 起 OkHttps 提供了另外一种心跳机制,它在发起具体的 WebSocket 连接时通过方法`heatbeat(int pingSeconds, int pongSeconds)`分别指定客户端与服务器的心跳时间间隔:
+
+```java
+http.webSocket("/chat")
+ .heatbeat(10, 10)
+ .setOnMessage((WebSocket ws,Message msg) -> {
+
+ })
+ .listen(); // 启动监听
+```
+
+如上配置,客户端仍会每隔 10秒 向服务器发送一次 PING 消息,并期望服务器回复 PONG 消息的间隔也是 10 秒一次,但如果服务器或网络由于某些未知原因导致客户端未能正确收到 PONG 消息,客户端还会容忍两次失败,当第三个 10 秒后还未收到服务器的任何消息时,则会触发`SocketTimeoutException`异常
+
+::: tip OkHttps 的心跳机制相对于 OkHttp 主要有以下特点
+* 客户端发送的任何消息都具有一次心跳作用
+* 服务器发送的任何消息都具有一次心跳作用
+* 若服务器超过 3 * pongSeconds 秒没有回复心跳,才触发心跳超时
+:::
+
+## 消息收发
+
+### 接收消息
+
+发起 WebSocket 连接是,设置一个`OnMessage`回调,便可接收到服务器的消息:
+
+```java
+http.webSocket("/chat")
+ .setOnMessage((WebSocket ws,Message msg) -> {
+ // 接收到消息 msg
+ })
+ .listen(); // 启动监听
+```
+
+在该回调内接收到一个`Message`类型的消息对象,它和`HttpReault.Body`都继承自`Toable`接口,他共有如下一些方法:
+
+* `isText()` 判断是文本消息还是二进制消息
+* `toByteStream()` 消息体转字节流
+* `toBytes()` 消息体转字数组
+* `toByteString()` 消息体转字数组
+* `toCharStream()` 消息体转字符流
+* `toString()` 消息体转字符串
+* `toMapper()` 消息体转 Mapper 对象(不想定义 Java Bean 时使用)
+* `toArray()` 消息体转 Array 数组(不想定义 Java Bean 时使用)
+* `toBean(Class type)` 报文体Json文本转JavaBean
+* `toBean(Type type)` 报文体Json文本转JavaBean
+* `toBean(TypeRef type)` 报文体Json文本转JavaBean
+* `toList(Class type)` 报文体Json文本转JavaBean列表
+
+### 发送消息
+
+向服务器发送消息,首先要获得一个`WebSocket`实例,该实例可以通过`listen()`方法的返回值或回调方法的参数获取,如:
+
+```java
+WebSocket ws = http.webSocket("/chat").listen(); // 启动监听,并返回一个 WebSocket 实例
+```
+
+接口`WebSocket`继承自`Cancelable`,它共定义了如下方法:
+
+* `cancel()` 取消连接(连接成功前可以取消)
+* `queueSize()` 排队待发送消息的数量
+* `send(Object object)` 发送消息,参数是待发送的对象,可以是 String | ByteString | byte[] | Java Bean
+* `close(int code, String reason)` 关闭连接(连接成功后可以关闭)
+* `msgType(String type)` 设置消息传输类型,类似于`bodyType`
+
+一个发送消息的例子
+
+```java
+WebSocket ws = http.webSocket("/chat").listen();
+ws.send("Hello World!") // 该消息会先进入排队等待状态,当连接成功时发送给服务器
+```
+
+或者
+
+```java
+http.webSocket("/chat")
+ .setOnOpen((WebSocket ws, HttpResult res) -> {
+ // 当连接成功时发送给服务器
+ ws.send("Hello World!")
+ })
+ .listen();
+```
+
+## 回调方法
+
+WebSocket 连接共可设置 **5** 种回调方法:
+
+```java
+http.webSocket("/websocket-endpoint")
+ .setOnOpen((WebSocket ws, HttpResult res) -> {
+ // WebSocket 连接成功时回调
+ })
+ .setOnMessage((WebSocket ws, Message msg) -> {
+ // 收到服务器下发的消息时回调
+ })
+ .setOnException((WebSocket ws, Throwable thr) -> {
+ // 连接发生异常时回调
+ })
+ .setOnClosing((WebSocket ws, WebSocket.Close close) -> {
+ // 连接正在关闭时回调
+ })
+ .setOnClosed((WebSocket ws, WebSocket.Close close) -> {
+ // 连接已关闭(v2.0.0 之后包含连接被取消 和 连接发生异常)时回调
+ })
+ .listen();
+```
+
+::: tip 需要注意的是
+如果设置了 [全局回调监听](/v2/configuration.html#全局回调监听), 它们对 WebSocket 连接 同样起作用
+:::
+
+
+
+
+
\ No newline at end of file
diff --git a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java
index bb4b9d790cc283cd0a1bac272b31376b00dfbc42..aecc48e7e755fa43e83cbcf4a719f3152ad49811 100644
--- a/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java
+++ b/okhttps/src/main/java/com/ejlchina/okhttps/WebSocket.java
@@ -87,7 +87,7 @@ public interface WebSocket extends Cancelable {
}
/**
- * 若连接已打开,则:
+ * @return 若连接已打开,则:
* 同 {@link okhttp3.WebSocket#queueSize()},返回排序消息的字节数
* 否则:
* 返回排队消息的数量
@@ -102,8 +102,10 @@ public interface WebSocket extends Cancelable {
/**
* 同 {@link okhttp3.WebSocket#close(int, String)}
+ * @param code Status code as defined by Section 7.4 of RFC 6455
+ * @param reason Reason for shutting down or {@code null}.
*/
- boolean close(int code, String reason);
+ void close(int code, String reason);
/**
* 设置消息类型
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 81e4d32b8ce076e69334acd97581c6594c4361be..d357c7e38f4233a292f942cbe48e799f40f9f52b 100644
--- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java
+++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/AsyncHttpTask.java
@@ -109,6 +109,8 @@ public class AsyncHttpTask extends HttpTask {
/**
* 设置请求得到响应后的回调函数
+ * @param 泛型
+ * @param type 期望的转换类型
* @param onResBean 响应 Bean 回调
* @return HttpTask 实例
*/
@@ -122,6 +124,8 @@ public class AsyncHttpTask extends HttpTask {
/**
* 设置请求得到响应后的回调函数
+ * @param 泛型
+ * @param type 期望的转换类型
* @param onResBean 响应 Bean 回调
* @return HttpTask 实例
*/
@@ -135,6 +139,8 @@ public class AsyncHttpTask extends HttpTask {
/**
* 设置请求得到响应后的回调函数
+ * @param 泛型
+ * @param type 期望的转换类型
* @param onResList 请求响应回调
* @return HttpTask 实例
*/
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 dd32f5028a51092f55a17b40a1b68312ff74414c..03b1962ce69e9196284be60b28aeb1a294cc0178 100644
--- a/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java
+++ b/okhttps/src/main/java/com/ejlchina/okhttps/internal/WebSocketTask.java
@@ -65,6 +65,7 @@ public class WebSocketTask extends HttpTask {
* 2、服务器发送的任何消息都具有一次心跳作用
* 3、若服务器超过 3 * pongSeconds 秒没有回复心跳,才判断心跳超时
*
+ * @since v2.3.0
* @param pingSeconds 客户端心跳间隔秒数(0 表示不需要心跳)
* @param pongSeconds 服务器心跳间隔秒数(0 表示不需要心跳)
* @return WebSocketTask
@@ -310,12 +311,11 @@ public class WebSocketTask extends HttpTask {
}
@Override
- public synchronized boolean close(int code, String reason) {
+ public synchronized void close(int code, String reason) {
if (webSocket != null) {
webSocket.close(code, reason);
}
cancelOrClosed = true;
- return true;
}
@Override