🍓 成功/失败条件
Forest 对每个请求都会判断其发送和响应结果是否成功。
成功,就会去执行OnSuccess回调函数和拦截器中的onSuccess方法,并返回响应结果。
失败,则会进行重试,如果该请求不允许重试,或者达到了最大重试次数限制,则会调用OnError回调函数,和拦截器中的onError方法。
# 默认成功/失败条件
Forest 提供了默认的请求成功/失败条件,其逻辑如下:
- 判断是否在发送和等待响应的过程中出现异常,如: 网络连接错误、超时等
 - 在取得响应结果后,判断其响应状态码是否在正常范围内 (
100~399) 
以上两条判断条件如有一条不满足,则就判定为请求失败,否则为成功。
默认的判断条件可以满足绝大部分场景的需要,也比较符合HTTP协议标准的规范,但也存在一些特殊场景,并不以HTTP标准为判断逻辑,这时候就需要用户进行自定义的请求成功/失败条件的判断了。
# 自定义成功/失败条件
这里举一个栗子,除了正常的异常判断外,当响应码为203的时候判断为请求失败。这样的条件如何定义请看如下代码:
# 使用 @Success 注解
# 第一步,先要定义 SuccessWhen 接口的实现类
// 自定义成功/失败条件实现类
// 需要实现 SuccessWhen 接口
public class MySuccessCondition implements SuccessWhen {
    /**
     * 请求成功条件
     * @param req Forest请求对象
     * @param res Forest响应对象
     * @return 是否成功,true: 请求成功,false: 请求失败
     */
    @Override
    public boolean successWhen(ForestRequest req, ForestResponse res) {
        // req 为Forest请求对象,即 ForestRequest 类实例
        // res 为Forest响应对象,即 ForestResponse 类实例
        // 返回值为 ture 则表示请求成功,false 表示请求失败
        return res.noException() &&   // 请求过程没有异常
                res.statusOk() &&     // 并且状态码在 100 ~ 399 范围内
                res.statusIsNot(203); // 但不能是 203
        // 当然在这里也可以写其它条件,比如 通过 res.getResult() 或 res.getContent() 获取业务数据
        // 再更具业务数据判断是否成功
    }
}
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
特别注意
在successWhen方法的逻辑代码中,千万不能调用 res.isSuccess() 或 !res.isError() 进行判断
不然会引起死循环
# 第二步,挂上 @Success 注解
 public interface MyClient {
    /**
     * 挂上了 @Success 注解
     * <p>该方法的请求是否成功
     * <p>以自定义成功条件类 MySuccessCondition 的判断方法为准
     * 
     * @return 请求响应结果
     */
    @Get("/")
    @Success(condition = MySuccessCondition.class)
    String sendData();
}
 2
3
4
5
6
7
8
9
10
11
12
若调用sendData()方法后,返回的状态码为 203, 就会被认为是请求失败,如果设置了重试次数大于0,就会去执行重试任务。
若没有重试次数可用,则进入 onError 请求失败流程
# 接口上的成功/失败条件
@Success注解也可以挂在interface接口类上,代表其下的所有请求方法都设置为此自定义条件
/**
 * interface 上挂了 @Success 注解
 * <p>该接口类下的所有方法都依据
 * <p>自定义的 MySuccessCondition 请求成功条件类
 * <p>为请求是否成功的判定条件
 */
@Success(condition = MySuccessCondition.class)
public interface MyClient {
    
    @Get("/test1")
    String sendData1();
    @Get("/test2")
    String sendData2();
}
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
此时,不管是调用sendData1()还是sendData2()方法,都会依据 MySuccessCondition 的判定条件为准
如果其中有一个方法想以另一种逻辑作为请求成功/失败的判断条件,可以在那个方法上加上@Success注解
/**
 * interface 上挂了 @Success 注解
 * <p>该接口类下的所有方法都依据
 * <p>自定义的 MySuccessCondition1 请求成功条件类
 * <p>为请求是否成功的判定条件
 * <p>除非该方法定义了自己的请求成功条件
 */
@Success(condition = MySuccessCondition1.class)
public interface MyClient {
    
    // 以 MySuccessCondition1 作为成功判断条件
    @Get("/test1")
    String sendData1();
    // 以 MySuccessCondition1 作为成功判断条件
    @Get("/test2")
    String sendData2();
    // 以 MySuccessCondition2 作为成功判断条件
    @Get("/test3")
    @Success(condition = MySuccessCondition2.class)
    String sendData3();
}
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 全局请求成功/失败条件
在 spring boot 环境下,可以在 application.yml 等全局配置文件中设置全局的请求成功/失败条件
forest:
    # MySuccessCondition 为您自定义的 SuccessWhen 实现类
    # 通过 forest.success-when 属性配置全局请求成功/失败条件类
    success-when: com.your.site.MySuccessCondition
 2
3
4
在其它环境可以通过ForestConfiguration对象的setSuccessWhenClass(Class<? extends SuccessWhen> successWhenClass)进行设置
// 获取默认全局配置对象
ForestConfiguration configuration = Forest.config();
// MySuccessCondition 为您自定义的 SuccessWhen 实现类
// 调用 setSuccessWhenClass 设置全局请求成功/失败条件类
configuration.setSuccessWhenClass(com.your.site.MySuccessCondition.class);
 2
3
4
5
# 手动设置请求成功/失败条件
文档导航
ForestRequest 对象如何手动设置请求成功/失败条件,请参见《请求设置对象成功/失败条件》