Spring重试–与项目集成的方式

如果您需要在代码中实现健壮的重试逻辑,一种行之有效的方法是使用spring重试库。 我的目的不是要展示如何使用spring retry项目本身,而是要展示可以将其集成到代码库中的不同方式。

考虑一种服务来调用外部系统:

package retry.service;public interface RemoteCallService {String call() throws Exception;
}

假定此调用可能失败,并且您希望每次调用失败都可以重试三次该调用,每次延迟2秒,所以为了模拟此行为,我已经使用Mockito定义了模拟服务,请注意,此返回为嘲笑的Spring bean:

@Bean
public RemoteCallService remoteCallService() throws Exception {RemoteCallService remoteService = mock(RemoteCallService.class);when(remoteService.call()).thenThrow(new RuntimeException("Remote Exception 1")).thenThrow(new RuntimeException("Remote Exception 2")).thenReturn("Completed");return remoteService;
}

因此,该模拟服务本质上将失败2次,并在第三个调用成功。

这是对重试逻辑的测试:

public class SpringRetryTests {@Autowiredprivate RemoteCallService remoteCallService;@Testpublic void testRetry() throws Exception {String message = this.remoteCallService.call();verify(remoteCallService, times(3)).call();assertThat(message, is("Completed"));}
}

我们确保该服务被调用3次,以解决前两个失败的呼叫以及成功的第三个呼叫。

如果我们在调用此服务时直接合并spring-retry,则代码将如下所示:

@Test
public void testRetry() throws Exception {String message = this.retryTemplate.execute(context -> this.remoteCallService.call());verify(remoteCallService, times(3)).call();assertThat(message, is("Completed"));
}

但是,这不是理想的选择,更好的包含方式是调用者不必明确知道存在重试逻辑的事实。

鉴于此,以下是合并Spring重试逻辑的方法。

方法1:自定义方面合并Spring重试

这种方法应该非常直观,因为可以将重试逻辑视为跨领域关注点,并且使用Aspects是实现跨领域关注点的好方法。 包含Spring重试的一个方面将遵循以下原则:

package retry.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.support.RetryTemplate;@Aspect
public class RetryAspect {private static Logger logger = LoggerFactory.getLogger(RetryAspect.class);@Autowiredprivate RetryTemplate retryTemplate;@Pointcut("execution(* retry.service..*(..))")public void serviceMethods() {//}@Around("serviceMethods()")public Object aroundServiceMethods(ProceedingJoinPoint joinPoint) {try {return retryTemplate.execute(retryContext -> joinPoint.proceed());} catch (Throwable e) {throw new RuntimeException(e);}}
}

这方面拦截了远程服务调用,并将该调用委托给retryTemplate。 完整的工作测试在这里 。

方法2:使用Spring-retry提供的建议

Spring-retry项目提供了开箱即用的建议,可确保确保可以重试目标服务。 围绕服务编织建议的AOP配置需要处理原始xml,这与以前的方法不同,前一种方法可以使用Spring Java配置来编织方面。 xml配置如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><aop:config><aop:pointcut id="transactional"expression="execution(* retry.service..*(..))" /><aop:advisor pointcut-ref="transactional"advice-ref="retryAdvice" order="-1"/></aop:config></beans>

完整的工作测试在这里 。

方法3:声明式重试逻辑

这是推荐的方法,您将看到代码比前两种方法更加简洁。 使用这种方法,唯一需要做的就是声明性地指出需要重试的方法:

package retry.service;import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;public interface RemoteCallService {@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 2000))String call() throws Exception;
}

以及使用此声明性重试逻辑的完整测试,也可以在此处获取 :

package retry;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import retry.service.RemoteCallService;import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.*;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class SpringRetryDeclarativeTests {@Autowiredprivate RemoteCallService remoteCallService;@Testpublic void testRetry() throws Exception {String message = this.remoteCallService.call();verify(remoteCallService, times(3)).call();assertThat(message, is("Completed"));}@Configuration@EnableRetrypublic static class SpringConfig {@Beanpublic RemoteCallService remoteCallService() throws Exception {RemoteCallService remoteService = mock(RemoteCallService.class);when(remoteService.call()).thenThrow(new RuntimeException("Remote Exception 1")).thenThrow(new RuntimeException("Remote Exception 2")).thenReturn("Completed");return remoteService;}}
}

@EnableRetry批注激活@Retryable批注方法的处理,并在内部使用方法2的逻辑,而最终用户无需明确说明。

我希望这会使您对如何将Spring-retry合并到项目中有所了解。 我在这里演示的所有代码也可以在我的github项目中找到 :https://github.com/bijukunjummen/test-spring-retry

翻译自: https://www.javacodegeeks.com/2014/12/spring-retry-ways-to-integrate-with-your-project.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360988.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(1)《Head First HTML与CSS》学习笔记---HTML基本概念

前言&#xff1a; 1. 这本书并没有面面俱到&#xff0c;涵盖所有内容&#xff0c;只提供作为初学者真正需要的东西&#xff1a;基本知识和信心。所以这不是唯一的参考书。&#xff08;我买了一本《HTML5权威指南》作为参考书和这本一起看&#xff0c;但还是以本书为第一个…

mac中如何从vim文本编辑器退回到命令

有的时候&#xff0c;我们经常从命令行中进入vim文本编辑器&#xff0c;如何退回来呢&#xff1a; 只需要经过两步&#xff1a;1.按下esc键 2.输入":wq"(保存退出) 输入":q!"(不保存退出) 在文件名前面加./ ,表示在当前目录中查找该文件 例如执行可执行文…

拥有您的堆:使用JVMTI迭代类实例

今天&#xff0c;我想谈一谈我们大多数人每天都不会看到和使用的另一种Java&#xff0c;更确切地说&#xff0c;是有关较低级别的绑定&#xff0c;一些本机代码以及如何执行一些小的魔术。 尽管我们不会在JVM上找到真正的魔力源&#xff0c;但是在单个帖子的范围内可以实现一些…

Dojo高级Web2.0 UI组件库---Tree组件

Tree组件可以把有层次关系的数据用树状结构展现出来&#xff0c;就如同 Windows 系统的资源浏览器。Tree有两个模板&#xff0c;一个是Tree模板&#xff0c;一个是TreeNode模板&#xff0c;应该说Tree模板就是一个容器&#xff0c;里面有很多TreeNode.而初始化树&#xff0c;打…

使用Java 8防止日志过宽

一些日志将被机器消耗并永久保存。 其他日志仅用于调试和供人类使用。 在后一种情况下&#xff0c;您通常要确保您不会产生过多的日志&#xff0c;尤其是不会产生太宽的日志&#xff0c;因为一旦行长超过一定大小&#xff08; 例如&#xff0c;此Eclipse bug &#xff09;&…

[one day one question] webpack打包压缩 ES6 js、.vue报错

问题描述&#xff1a; 报错&#xff1a; ERROR in js/test.js from UglifyJs Unexpected token punc ?(?, expected punc ?:? [js/test.js:1374,5]&#xff0c;这怎么破&#xff1f; 解决方案&#xff1a; 配置babel&#xff0c;把配置放到文件【.babelrc】中{"prese…

UVA10236 斐波那契素数

题意&#xff1a;任取斐波那契数列中一项f[i],若对于所有j 解法&#xff1a;这题的理论分析在黑书上有&#xff0c;结论是从第五项开始下标为素数的斐波那契数都是斐波那契素数 #include <stdio.h> #include <string.h> const int MAXN 250010;; int prime[25010]…

[one day one question] safari缓存太厉害

问题描述&#xff1a; safari缓存太厉害&#xff0c;这怎么破&#xff1f; 解决方案&#xff1a; window.onpageshow function(event) {if (event.persisted) {window.location.reload() }}; 君生我未生&#xff0c;我生君已老 君恨我生迟&#xff0c;我恨君生早 君生我未生&…

Android 网络编程之Http通信

Android中提供的HttpURLConnection和HttpClient接口可以用来开发HTTP程序。以下是本人在学习中的总结与归纳。1. HttpURLConnection接口 首先需要明确的是&#xff0c;Http通信中的POST和GET请求方式的不同。GET可以获得静态页面&#xff0c;也可以把参数放在URL字符串后面&…

EE Servlet 3:在Servlet中生成HTML输出

如果您只需要在EE Web模块中处理少量请求URI&#xff0c;则在Servlet代码中生成自己HTML响应可能比使用完整的模板库更容易。 作为示例的一部分&#xff0c;我尝试了一个非常简单的Java DSL&#xff0c;该Java DSL在编写自己的Serlvet时生成html输出。 代码如下&#xff1a; p…

[one day one question] express 不缓存如何实现

问题描述&#xff1a; express 默认缓存&#xff0c;这怎么破&#xff1f; 解决方案&#xff1a; apiRoutes.use(function (req, res, next) {res.setHeader(Cache-Control, no-cache, no-store, must-revalidate);res.setHeader(Pragma, no-cache);res.setHeader(Expires, 0)…

正则表达式摘录

正则表达式到底是什么东西&#xff1f;在编写处理字符串的程序或网页时&#xff0c;经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说&#xff0c;正则表达式就是记录文本规则的代码。常用元字符 代码说明.匹配除换行符以外的任意…

Java生态系统– 2014年我的5大亮点

1. 2月1日-RedMonk Analyst公司宣布Java比以往任何时候都更加流行和多样化&#xff01; 2014年&#xff0c;随着FOSDEM的Free Java会议室的年会&#xff0c;Java生态系统开始轰轰烈烈地响起。 除了关于OpenJDK和相关主题的许多精深的技术讲座外&#xff0c;Steve OGrady&#x…

WEB前端大神之路之基础篇

CSS篇&#xff1a; 1.CSS权重&#xff1a; 不重复造轮子啦&#xff0c;直接传送门&#xff08;CSS选择器的权重与优先规则&#xff09; JavaScript篇&#xff1a; 1.this关键字&#xff1a; 它是一种引用&#xff08;referent&#xff09;。指向的是当前上下文&#xff08;con…

与Java EE和Camel的轻量级集成

Enterprise Java具有不同的风格和观点。 从简单的平台技术开始&#xff0c;即众所周知的Java EE&#xff0c;再到不同的框架和集成方面&#xff0c;最后是涉及以数据为中心的用户界面或特定可视化效果的用例。 Java EE本身无法解决的最突出的问题是“集成”。 有许多来自知名供…

java=====Striing date 转化

java中string与date(日期)格式之间的转换 经常遇到string和date之间的转换&#xff0c;把相关的内容总结在这里吧&#xff1a; 1.string格式转化为Date对象&#xff1a; //把string转化为dateDateFormat fmt new SimpleDateFormat("yyyy-MM-dd"); Date date fmt.par…

oracel Pipelined pipe row的用法

oracle的管道也可以返回集合类型&#xff0c;跟游标类似 CREATE TYPE my_type AS OBJECT ( field1 NUMBER, field2 VARCHAR2 (50) ); CREATE TYPE my_typelist AS TABLE OF my_type; CREATE OR REPLACE FUNCTION pipelineme RETURN my_typelist PIPELINED IS -…

在Spring中使用Netflix Hystrix批注

除了在主页上引述之外&#xff0c;我想不出更好的方式来描述Netflix Hystrix库的特定功能&#xff1a; 延迟和容错方式&#xff1a; 停止级联故障。 后备和正常降级。 无法快速快速恢复。 使用断路器隔离线程和信号量。 我看到了Josh Long&#xff08; starbuxman &#xff0…

[工具库]JFileDownloader工具类——多线程下载网络文件,并保存在本地

本人大四即将毕业的准程序员&#xff08;JavaSE、JavaEE、android等&#xff09;一枚&#xff0c;小项目也做过一点&#xff0c;于是乎一时兴起就写了一些工具。 我会在本博客中陆续发布一些平时可能会用到的工具。 代码质量可能不是很好&#xff0c;大家多担待&#xff01; 代…

使用JAX-RS和Spring构建HATEOAS API

在我以前的博客文章中&#xff0c;我展示了如何使用Spring Boot配置Jersey多么容易。 我对Spring Boot和Jersey的探索并没有结束&#xff0c;我研究了在Spring Boot应用程序中将Spring HATEOAS和Jersey一起使用的可能性。 Spring HATEOS允许创建遵循HATEOAS原理的REST表示形式&…