ソースを参照

docs: 更新文档

drake 1 年間 前
コミット
5c4f22f718

+ 33 - 29
docs/converter-customize.md

@@ -3,7 +3,7 @@ Net自定义转换器可支持任何数据类型, 甚至`Bitmap`
 !!! failure "泛型和转换器关系"
     1. 如果`Post<Model>`, 那么`NetConverter.onConvert`返回值必须为Model
     2. 如果`Post<Model?>`, 允许`NetConverter.onConvert`返回值为null
-    3. 其他情况请抛出异常
+    3. 任何错误请在转换器中直接抛出异常
 
 ```kotlin
 scopeNetLife {
@@ -34,7 +34,7 @@ Net由于低耦合原则不自带任何序列化框架
 
 ## 常见转换器
 
-实现[JSONConverter](https://github.com/liangjingkanji/Net/blob/master/net/src/main/java/com/drake/net/convert/JSONConvert.kt)的`parseBody`方法使用自定义序列化框架解析
+实现[JSONConverter](https://github.com/liangjingkanji/Net/blob/master/net/src/main/java/com/drake/net/convert/JSONConvert.kt)接口快速实现JSON解析, 或直接复制以下转换器示例
 
 | 序列化框架                                                   | 示例代码                                                       | 描述                 |
 | ------------------------------------------------------------ | ------------------------------------------------------------ | -------------------- |
@@ -46,36 +46,40 @@ Net由于低耦合原则不自带任何序列化框架
 
 ## 自定义转换器
 
-实现`NetConverter`返回自定义请求结果
-
-??? example "转换器实现非常简单"
-    ```kotlin title="NetConverter.kt" linenums="1"
-    interface NetConverter {
-
-        @Throws(Throwable::class)
-        fun <R> onConvert(succeed: Type, response: Response): R?
-
-        companion object DEFAULT : NetConverter {
-            /**
-             * 返回结果应当等于泛型对象, 可空
-             * @param succeed 请求要求返回的泛型类型
-             * @param response 请求响应对象
-             */
-            override fun <R> onConvert(succeed: Type, response: Response): R? {
-                return when {
-                    succeed === String::class.java && response.isSuccessful -> response.body?.string() as R
-                    succeed === ByteString::class.java && response.isSuccessful -> response.body?.byteString() as R
-                    succeed is GenericArrayType && succeed.genericComponentType === Byte::class.java && response.isSuccessful -> response.body?.bytes() as R
-                    succeed === File::class.java && response.isSuccessful -> response.file() as R
-                    succeed === Response::class.java -> response as R
-                    else -> throw ConvertException(response, "An exception occurred while converting the NetConverter.DEFAULT")
-                }
+转换器原理非常简单, 实现`NetConverter`接口返回一个对象(等于请求泛型)
+
+
+???+ example "建议保留默认支持的类型"
+    ```kotlin hl_lines="5"
+    class CustomizeConverter: NetConverter {
+
+        override fun <R> onConvert(succeed: Type, response: Response): R? {
+            try {
+                return NetConverter.onConvert<R>(succeed, response)
+            } catch (e: ConvertException) {
+                // ... 仅自定义不支持的类型
+                return 任何对象 as R
             }
         }
     }
     ```
 
-转换器中可以根据需加上解密数据, token失效跳转登录, 限制多端登录等逻辑
+转换器中可以根据错误码抛出自定义异常
+
+??? example "转换器异常链"
+    ```kotlin
+    // 非CancellationException/NetException及其子类的上抛ConvertException
+    try {
+        return request.converter().onConvert<R>(type, this) as R
+    } catch (e: CancellationException) {
+        throw e
+    } catch (e: NetException) {
+        throw e
+    } catch (e: Throwable) {
+        throw ConvertException(this, cause = e)
+    }
+    ```
+
 
-1. 日志信息输出, 请阅读[日志记录器](log-recorder.md)
-2. 转换器中抛出异常被全局错误处理捕获, 请阅读[全局错误处理](error-handle.md)
+1. [日志记录](log-recorder.md)建议使用拦截器
+2. 转换器中抛出异常被[全局错误处理](error-handle.md)捕获

+ 10 - 9
docs/interceptor.md

@@ -19,21 +19,22 @@ NetConfig.initialize(Api.HOST, this) {
 }
 ```
 
-演示客户端自动刷新token的拦截器
+客户端token自动续期示例
 
 ```kotlin
-/**
- * 演示如何自动刷新token令牌
- */
 class RefreshTokenInterceptor : Interceptor {
     override fun intercept(chain: Interceptor.Chain): Response {
         val request = chain.request()
-        val response = chain.proceed(request) // 如果token失效
-
+        val response = chain.proceed(request)
         return synchronized(RefreshTokenInterceptor::class.java) {
-            if (response.code == 401 && UserConfig.isLogin && !request.url.pathSegments.contains("token")) {
-                val json = Net.get("token").execute<String>() // 同步刷新token
-                UserConfig.token = JSONObject(json).optString("token")
+            if (response.code == 401 && UserConfig.isLogin && !request.url.encodedPath.contains(Api.Token)) {
+                val tokenInfo = Net.get(Api.Token).execute<TokenModel>() // 同步请求token
+                if (tokenInfo.isExpired) {
+                    // token过期抛出异常, 由全局错误处理器处理, 在其中可以跳转到登陆界面提示用户重新登陆
+                    throw ResponseException(response, "登录状态失效")
+                } else {
+                    UserConfig.token = tokenInfo.token
+                }
                 chain.proceed(request)
             } else {
                 response

+ 1 - 0
sample/src/main/java/com/drake/net/sample/constants/Api.kt

@@ -16,4 +16,5 @@ object Api {
     const val CONFIG = "/config"
     const val USER_INFO = "/userInfo"
     const val TIME = "/time"
+    const val Token = "/token"
 }

+ 9 - 10
sample/src/main/java/com/drake/net/sample/interceptor/RefreshTokenInterceptor.kt

@@ -2,29 +2,28 @@ package com.drake.net.sample.interceptor
 
 import com.drake.net.Net
 import com.drake.net.exception.ResponseException
+import com.drake.net.sample.constants.Api
 import com.drake.net.sample.constants.UserConfig
+import com.drake.net.sample.model.TokenModel
 import okhttp3.Interceptor
 import okhttp3.Response
-import org.json.JSONObject
 
 
 /**
- * 演示如何自动刷新token令牌
+ * 客户端token自动续期示例
  */
 class RefreshTokenInterceptor : Interceptor {
     override fun intercept(chain: Interceptor.Chain): Response {
         val request = chain.request()
-        val response = chain.proceed(request) // 如果token失效
-
+        val response = chain.proceed(request)
         return synchronized(RefreshTokenInterceptor::class.java) {
-            if (response.code == 401 && UserConfig.isLogin && !request.url.pathSegments.contains("token")) {
-                val json = Net.get("token").execute<String>() // 同步刷新token
-                val jsonObject = JSONObject(json)
-                if (jsonObject.getBoolean("isExpired")) {
-                    // token刷新失败跳转到登录界面重新登录, 建议在错误处理器[NetErrorHandler]处理所有错误请求, 此处抛出异常即可
+            if (response.code == 401 && UserConfig.isLogin && !request.url.encodedPath.contains(Api.Token)) {
+                val tokenInfo = Net.get(Api.Token).execute<TokenModel>() // 同步请求token
+                if (tokenInfo.isExpired) {
+                    // token过期抛出异常, 由全局错误处理器处理, 在其中可以跳转到登陆界面提示用户重新登陆
                     throw ResponseException(response, "登录状态失效")
                 } else {
-                    UserConfig.token = jsonObject.optString("token")
+                    UserConfig.token = tokenInfo.token
                 }
                 chain.proceed(request)
             } else {

+ 9 - 0
sample/src/main/java/com/drake/net/sample/model/TokenModel.kt

@@ -0,0 +1,9 @@
+package com.drake.net.sample.model
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class TokenModel(
+    var token: String = "",
+    var isExpired: Boolean = false
+)