okHttp 重试

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

相关帖子

回帖

欢迎来到这里!

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

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

推荐标签 标签

  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 114 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    12 引用 • 5 回帖 • 635 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 2 关注
  • Excel
    31 引用 • 28 回帖
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    142 引用 • 442 回帖
  • CentOS

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

    240 引用 • 224 回帖
  • RemNote
    2 引用 • 16 回帖 • 25 关注
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    10 引用 • 77 回帖
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    948 引用 • 1460 回帖 • 1 关注
  • Solo

    Solo 是一款小而美的开源博客系统,专为程序员设计。Solo 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    1444 引用 • 10083 回帖 • 501 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    4 引用 • 16 回帖 • 200 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    498 引用 • 934 回帖 • 1 关注
  • FreeMarker

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

    23 引用 • 20 回帖 • 476 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 90 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    957 引用 • 944 回帖 • 1 关注
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 616 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 2 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 653 关注
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    59 引用 • 22 回帖 • 3 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    188 引用 • 1057 回帖 • 1 关注
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    36 引用 • 35 回帖
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    77 引用 • 37 回帖
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 509 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 347 关注
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 142 关注
  • 996
    13 引用 • 200 回帖
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 73 关注