okHttp 重试

本贴最后更新于 2150 天前,其中的信息可能已经物是人非
package club.wujingjian.util; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import okhttp3.ConnectionPool; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient.Builder; import org.springframework.http.*; import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.util.ClassUtils; import org.springframework.web.client.RestTemplate; @Slf4j public class OKHttpUtil { private static final boolean jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", RestTemplate.class.getClassLoader()) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", RestTemplate.class.getClassLoader()); private static final boolean springwebPresent = ClassUtils.isPresent( "org.springframework.http.converter.json.Jackson2ObjectMapperBuilder", RestTemplate.class.getClassLoader()); private int readTimeout = 2000; private int connectTimeout=1000; private boolean isRetry = true; private int retryCount = 3; private long retryDelay = 100; public okhttp3.OkHttpClient okHttpClient() { Builder builder = new Builder(); ConnectionPool pool = new ConnectionPool(1000, 50, TimeUnit.MINUTES); builder.connectionPool(pool); builder.retryOnConnectionFailure(isRetry); // RetryInterceptor retryIntercepter = new RetryInterceptor(retryCount, retryDelay,new ArrayList<>()); RetryInterceptor retryIntercepter = new RetryInterceptor(retryCount, retryDelay); builder.addInterceptor(retryIntercepter); builder.followRedirects(false); return builder.build(); } public RestTemplate restClientOnlyTemplateSimple() { OkHttp3ClientHttpRequestFactory okHttp3ClientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory( okHttpClient()); okHttp3ClientHttpRequestFactory.setReadTimeout(readTimeout); okHttp3ClientHttpRequestFactory.setConnectTimeout(connectTimeout); RestTemplate restTemplate = new RestTemplate(okHttp3ClientHttpRequestFactory); // 使用 utf-8 编码集的 convert 替换默认的 convert(默认的 string conver 的编码集为 // "ISO-8859-1") List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters(); Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator(); while (iterator.hasNext()) { HttpMessageConverter<?> converter = iterator.next(); if (converter instanceof StringHttpMessageConverter) { iterator.remove(); } if (converter instanceof MappingJackson2HttpMessageConverter) { iterator.remove(); } } StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter( Charset.forName("UTF-8")); stringHttpMessageConverter.setWriteAcceptCharset(false); List<MediaType> mediaTypeList = new ArrayList<>(); mediaTypeList.add(MediaType.APPLICATION_JSON_UTF8); mediaTypeList.add(MediaType.APPLICATION_FORM_URLENCODED); mediaTypeList.add(MediaType.APPLICATION_JSON); mediaTypeList.add(MediaType.TEXT_PLAIN); mediaTypeList.add(MediaType.TEXT_HTML); mediaTypeList.add(new MediaType("text", "json")); mediaTypeList.add(new MediaType("text", "javascript")); stringHttpMessageConverter.setSupportedMediaTypes(mediaTypeList); messageConverters.add(0, stringHttpMessageConverter); // 兼容JSON与实体字段不对应 if (jackson2Present && springwebPresent) { ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(objectMapper); messageConverters.add(jsonConverter); } return restTemplate; } public static void main(String[] args) { OKHttpUtil okHttpUtil = new OKHttpUtil(); RestTemplate restTemplate = okHttpUtil.restClientOnlyTemplateSimple(); String url ="http://mobileself-xxx.ffff.beta/api/v2/staffinfo/exist/xxx"; HttpHeaders headers = new HttpHeaders(); MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8"); headers.setContentType(type); headers.set("Accept", MediaType.APPLICATION_JSON_VALUE); headers.set("xiaofanAuthorization","aaa#aaa"); HttpEntity<?> entity = new HttpEntity<>(headers); try { ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class); if (null != response) { System.out.println("响应数据:" + response.getBody()); } } catch (Exception e) { log.error("请求小凡接口异常:"+e.getMessage(),e); } } }
package club.wujingjian.util; import java.io.IOException; import java.io.InterruptedIOException; import java.net.ConnectException; import java.net.UnknownHostException; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.net.ssl.SSLException; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; import org.apache.commons.collections.CollectionUtils; import org.apache.http.conn.HttpHostConnectException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class RetryInterceptor implements Interceptor { private static Logger logger = LoggerFactory.getLogger(RetryInterceptor.class); private final int retryCount; private final long retryDelay; private final Set<Class<? extends IOException>> nonRetriableClasses;//不会重试的类型 private static final Charset UTF8 = Charset.forName("UTF-8"); protected RetryInterceptor(int retryCount, long retryDelay, Collection<Class<? extends IOException>> clazzes) { this.retryCount = retryCount; this.retryDelay = retryDelay; this.nonRetriableClasses = new HashSet(); if (CollectionUtils.isNotEmpty(clazzes)) { Iterator noRetryIterator = clazzes.iterator(); while(noRetryIterator.hasNext()) { Class<? extends IOException> clazz = (Class)noRetryIterator.next(); this.nonRetriableClasses.add(clazz); } } } public RetryInterceptor(int retryCount, long retryDelay) { this(retryCount, retryDelay, Arrays.asList(InterruptedIOException.class, UnknownHostException.class, SSLException.class, HttpHostConnectException.class,ConnectException.class)); } public RetryInterceptor() { this(3, 50L); } public Response intercept(Chain chain) throws IOException { Response response = null; try { Request request = chain.request(); for (int execCount = 0; execCount <= retryCount; execCount++) { if (execCount >= 1) { logger.info("重试第{}次,url:{}", execCount, request.url().url()); } try { Exception exception; Iterator varException; try { response = chain.proceed(request); break; } catch (Exception ex) { exception = ex; if (execCount >= this.retryCount) { throw ex; } if (this.nonRetriableClasses.contains(ex.getClass())) { throw ex; } varException = this.nonRetriableClasses.iterator(); } while (varException.hasNext()) { Class<? extends IOException> rejectException = (Class) varException.next(); if (rejectException.isInstance(exception)) { throw exception; } } try { Thread.sleep(this.retryDelay); } catch (InterruptedException interruptedException) { logger.error("重试错误:" + interruptedException.getMessage(), interruptedException); } } finally { if (execCount >= 1) { logger.info("重试{}次结束,url:{}", execCount, request.url().url()); } } } } catch (Exception e) { logger.error("请求错误了:"+e.getMessage(),e); } return response; } }
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 92 关注

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 197 关注
  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    76 引用 • 1742 回帖 • 1 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 642 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 394 关注
  • 印象笔记
    3 引用 • 16 回帖 • 2 关注
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    440 引用 • 1238 回帖 • 593 关注
  • danl
    176 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 50 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 2 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 566 关注
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 564 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 465 关注
  • Outlook
    1 引用 • 5 回帖 • 1 关注
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    211 引用 • 358 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 3 关注
  • OneNote
    1 引用 • 3 回帖
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖
  • Typecho

    Typecho 是一款博客程序,它在 GPLv2 许可证下发行,基于 PHP 构建,可以运行在各种平台上,支持多种数据库(MySQL、PostgreSQL、SQLite)。

    12 引用 • 67 回帖 • 444 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    19 引用 • 23 回帖 • 737 关注
  • Access
    1 引用 • 3 回帖 • 2 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 26 关注
  • Word
    13 引用 • 41 回帖
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    91 引用 • 59 回帖
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 507 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    59 引用 • 25 回帖 • 3 关注