javascript
Spring重试–与项目集成的方式
如果您需要在代碼中實現健壯的重試邏輯,一種行之有效的方法是使用spring重試庫。 我的目的不是要展示如何使用spring retry項目本身,而是要展示可以將其集成到代碼庫中的不同方式。
考慮一種服務來調用外部系統:
假定此調用可能失敗,并且您希望每次調用失敗都可以重試三次該調用,每次延遲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
總結
以上是生活随笔為你收集整理的Spring重试–与项目集成的方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于第六代宽带框架,诺基亚推出宽带战略
- 下一篇: gradle idea java ssm