本文主要应用了OkHttp的Interceptor来实现自定义重试次数

虽然OkHttp自带retryOnConnectionFailure(true)方法可以实现重试,但是不支持自定义重试次数,所以有时并不能满足我们的需求。

#1.自定义重试拦截器:

/**
* 重试拦截器
*/
public class RetryIntercepter implements Interceptor { public int maxRetry;//最大重试次数
private int retryNum = ;//假如设置为3次重试的话,则最大可能请求4次(默认1次+3次重试) public RetryIntercepter(int maxRetry) {
this.maxRetry = maxRetry;
} @Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
System.out.println("retryNum=" + retryNum);
Response response = chain.proceed(request);
while (!response.isSuccessful() && retryNum < maxRetry) {
retryNum++;
System.out.println("retryNum=" + retryNum);
response = chain.proceed(request);
}
return response;
}
}

#2.测试场景类:

 public class RetryTest {
String mUrl = "https://www.baidu.com/";
OkHttpClient mClient; @Before
public void setUp() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY); mClient = new OkHttpClient.Builder()
.addInterceptor(new RetryIntercepter())//重试
.addInterceptor(logging)//网络日志
.addInterceptor(new TestInterceptor())//模拟网络请求
.build();
} @Test
public void testRequest() throws IOException {
Request request = new Request.Builder()
.url(mUrl)
.build();
Response response = mClient.newCall(request).execute();
System.out.println("onResponse:" + response.body().string());
} class TestInterceptor implements Interceptor { @Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String url = request.url().toString();
System.out.println("url=" + url);
Response response = null;
if (url.equals(mUrl)) {
String responseString = "{\"message\":\"我是模拟的数据\"}";//模拟的错误的返回值
response = new Response.Builder()
.code()
.request(request)
.protocol(Protocol.HTTP_1_0)
.body(ResponseBody.create(MediaType.parse("application/json"), responseString.getBytes()))
.addHeader("content-type", "application/json")
.build();
} else {
response = chain.proceed(request);
}
return response;
}
} }

#3.输出结果:

 retryNum=
--> GET https://www.baidu.com/ HTTP/1.1
--> END GET
url=https://www.baidu.com/
<-- null https://www.baidu.com/ (13ms)
content-type: application/json {"message":"我是模拟的数据"}
<-- END HTTP (-byte body)
retryNum=
--> GET https://www.baidu.com/ HTTP/1.1
--> END GET
url=https://www.baidu.com/
<-- null https://www.baidu.com/ (0ms)
content-type: application/json {"message":"我是模拟的数据"}
<-- END HTTP (-byte body)
retryNum=
--> GET https://www.baidu.com/ HTTP/1.1
--> END GET
url=https://www.baidu.com/
<-- null https://www.baidu.com/ (0ms)
content-type: application/json {"message":"我是模拟的数据"}
<-- END HTTP (-byte body)
retryNum=
--> GET https://www.baidu.com/ HTTP/1.1
--> END GET
url=https://www.baidu.com/
<-- null https://www.baidu.com/ (0ms)
content-type: application/json {"message":"我是模拟的数据"}
<-- END HTTP (-byte body)
onResponse:{"message":"我是模拟的数据"}

#4.结果分析:
>1. 这里我用一个TestInterceptor拦截器拦截掉真实的网络请求,实现response.code的自定义
2. 在RetryIntercepter中,通过response.isSuccessful()来对响应码进行判断,循环调用了多次chain.proceed(request)来实现重试拦截
3. 从输出中可以看到,一共请求了4次(默认1次+重试3次)。

#5.其它实现方式
如果你是使用OkHttp+Retrofit+RxJava,你也可以使用retryWhen操作符:retryWhen(new RetryWithDelay())来实现重试机制

 public class RetryWithDelay implements Func1<Observable<? extends Throwable>, Observable<?>> {

         private final int maxRetries;
private final int retryDelayMillis;
private int retryCount; public RetryWithDelay(int maxRetries, int retryDelayMillis) {
this.maxRetries = maxRetries;
this.retryDelayMillis = retryDelayMillis;
} @Override
public Observable<?> call(Observable<? extends Throwable> attempts) {
return attempts
.flatMap(new Func1<Throwable, Observable<?>>() {
@Override
public Observable<?> call(Throwable throwable) {
if (++retryCount <= maxRetries) {
// When this Observable calls onNext, the original Observable will be retried (i.e. re-subscribed).
LogUtil.print("get error, it will try after " + retryDelayMillis + " millisecond, retry count " + retryCount);
return Observable.timer(retryDelayMillis,
TimeUnit.MILLISECONDS);
}
// Max retries hit. Just pass the error along.
return Observable.error(throwable);
}
});
}
}

OkHttp自定义重试次数的更多相关文章

  1. Dubbo重试次数

    服务超时后重试次数[retries],不包含第一次调用,0代表不重试 *我们应该在幂等方法上设置重试次数[查询.删除.修改],在非幂等方法上禁止设置重试次数. ★幂等:指多次运行方法所产生的最终效果是 ...

  2. 一个带重试次数的curl 函数

    <?php/** * [curl 带重试次数] * @param [type] $url [访问的url] * @param [type] $post [$POST参数] * @param in ...

  3. SpringCloud Feign 之 超时重试次数探究

    SpringCloud Feign 之 超时重试次数探究 上篇文章,我们对Feign的fallback有一个初步的体验,在这里我们回顾一下,Fallback主要是用来解决依赖的服务不可用或者调用服务失 ...

  4. Redis解决“重试次数”场景的实现思路

    很多地方都要用到重试次数限制,不然就会被暴力破解.比如登录密码. 下面不是完整代码,只是伪代码,提供一个思路. 第一种(先声明,这样写有个bug) import java.text.MessageFo ...

  5. python重试次数装饰器

    目录 重试次数装饰器 重试次数装饰器 前言, 最近在使用tornado框架写Restful API时遇到很多的问题. 有框架的问题, 有异步的问题. 虽然tornado 被公认为当前python语言最 ...

  6. Shiro密码重试次数限制

    如在 1 个小时内密码最多重试 5 次,如果尝试次数超过 5 次就锁定 1 小时,1 小时后可再次重试,如果还是重试失败,可以锁定如 1 天,以此类推,防止密码被暴力破解.我们通过继承 HashedC ...

  7. 使用Python请求http/https时设置失败重试次数

    设置请求时的重试规则 import requests from requests.adapters import HTTPAdapter s = requests.Session() a = HTTP ...

  8. python requests 配置超时及重试次数

    import requests from requests.adapters import HTTPAdapter s = requests.Session() s.mount('http://', ...

  9. springcloud超时时间与重试次数配置

    #hystrix配置hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=120000ribbon.Conn ...

随机推荐

  1. java中重载一定在一个类里面吗?

    虽然这些概念在翻译成中文的过程中,有很多不同的翻译方式但本质上只有两种说法,就是Override和Overload其中,Overload一般都被翻译成重载而Override的翻译就乱七八糟了,所谓覆盖 ...

  2. TLB和MMU的区别

    MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器.物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制 ...

  3. 前端构建工具gulp之基本介绍

    1.基本介绍 gulp.js是一个自动化构建工具,是自动化项目的构建利器.可以对网站的资源进行优化,将开发过程中一些重复的任务通过执行命令自动完成.这样能很大的提高我们的工作效率. gulp.js是基 ...

  4. java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题

    一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...

  5. Codeforces Round #336 (Div. 2)【A.思维,暴力,B.字符串,暴搜,前缀和,C.暴力,D,区间dp,E,字符串,数学】

    A. Saitama Destroys Hotel time limit per test:1 second memory limit per test:256 megabytes input:sta ...

  6. dfs学习总结

    今天做到了dfs的训练,感觉和bfs有相似之处,接下来用一道题来总结一下方法,可类比bfs. 上题: Description There is a rectangular room, covered ...

  7. Dora.Interception, 一个为.NET Core度身打造的AOP框架:不一样的Interceptor定义方式

    相较于社区其他主流的AOP框架,Dora.Interception在Interceptor提供了完全不同的编程方式.我们并没有为Interceptor定义一个接口,正是因为不需要实现一个预定义的接口, ...

  8. c++(快速排序)

    快速排序是编程中经常使用到的一种排序方法.可是很多朋友对快速排序有畏难情绪,认为快速排序使用到了递归,是一种非常复杂的程序,其实未必如此.只要我们使用好了方法,就可以自己实现快速排序. 首先,我们复习 ...

  9. 解决get乱码

    也可以在tomcat中修改,但是每次配置tomcat中都得修改.容易忘记,还是图片这个方法最好,推荐

  10. Docker+Jenkins持续集成环境(3)集成PMD、FindBugs、Checkstyle静态代码检查工具并邮件发送检查结果

    为了规范代码,我们一般会集成静态代码检测工具,比如PMD.FindBugs.Checkstyle,那么Jenkins如何集成这些检查工具,并把检查结果放到构建邮件里呢? 今天做了调研和实现,过程如下 ...