okHttp 重试

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

相关帖子

回帖

欢迎来到这里!

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

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

推荐标签 标签

  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 682 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 409 关注
  • DevOps

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

    59 引用 • 25 回帖 • 2 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 409 关注
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 118 关注
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 8 关注
  • etcd

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

    6 引用 • 26 回帖 • 546 关注
  • jsDelivr

    jsDelivr 是一个开源的 CDN 服务,可为 npm 包、GitHub 仓库提供免费、快速并且可靠的全球 CDN 加速服务。

    5 引用 • 31 回帖 • 107 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    108 引用 • 153 回帖
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    89 引用 • 150 回帖 • 3 关注
  • 游戏

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

    187 引用 • 832 回帖
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 248 回帖
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 441 关注
  • Wide

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

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

    30 引用 • 218 回帖 • 644 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 672 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    554 引用 • 675 回帖
  • Swagger

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

    26 引用 • 35 回帖 • 2 关注
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    115 引用 • 319 回帖
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    6 引用 • 143 回帖
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    183 引用 • 3885 回帖
  • 阿里云

    阿里云是阿里巴巴集团旗下公司,是全球领先的云计算及人工智能科技公司。提供云服务器、云数据库、云安全等云计算服务,以及大数据、人工智能服务、精准定制基于场景的行业解决方案。

    85 引用 • 324 回帖 • 1 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    118 引用 • 54 回帖 • 6 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 369 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    229 引用 • 476 回帖
  • AWS
    11 引用 • 28 回帖 • 7 关注