okHttp 重试

本贴最后更新于 2091 天前,其中的信息可能已经物是人非
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 回帖 • 85 关注

相关帖子

回帖

欢迎来到这里!

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

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

推荐标签 标签

  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    239 引用 • 224 回帖 • 1 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    6 引用 • 26 回帖 • 545 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 632 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 437 关注
  • Elasticsearch

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

    117 引用 • 99 回帖 • 204 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    86 引用 • 165 回帖 • 1 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    7 引用 • 69 回帖
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    181 引用 • 821 回帖
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 2 关注
  • OnlyOffice
    4 引用 • 22 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    245 引用 • 1338 回帖
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    210 引用 • 2040 回帖
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    498 引用 • 1395 回帖 • 248 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 178 关注
  • 酷鸟浏览器

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

    3 引用 • 59 回帖 • 47 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    188 引用 • 318 回帖 • 253 关注
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 57 关注
  • wolai

    我来 wolai:不仅仅是未来的云端笔记!

    2 引用 • 14 回帖
  • 一些有用的避坑指南。

    69 引用 • 93 回帖 • 1 关注
  • Typecho

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

    12 引用 • 67 回帖 • 447 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 30 关注
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    8 引用 • 26 回帖 • 3 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 1 关注
  • 导航

    各种网址链接、内容导航。

    44 引用 • 177 回帖
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖 • 1 关注