Vodič za proljetni pokušaj

1. Pregled

Spring Retry pruža mogućnost automatskog ponovnog poziva na neuspjelu operaciju. Ovo je korisno ako pogreške mogu biti prolazne (poput trenutnog kvara na mreži).

U ovom uputstvu vidjet ćemo razne načine korištenja Spring Retry: napomene, RetryTemplatei povratne pozive.

2. Ovisnosti Mavena

Krenimo od dodavanjem proljetni-ponovni pokušaj ovisnost o našoj pom.xml datoteka:

 org.springframework.ponovni pokušaj opruge-ponovni pokušaj 1.2.5.OBUSTAVLJANJE 

U naš projekt također trebamo dodati Spring AOP:

 org.springframework spring-aspekti 5.2.8.OBUSTAŽENJE 

U Maven Centralu potražite najnovije verzije ovisnosti o opružnom ponovnom pokušaju i proljetnim aspektima.

3. Omogućavanje proljetnog ponovnog pokušaja

Da biste omogućili proljetni pokušaj u aplikaciji, moramo dodati @EnableRetry bilješka našem @Konfiguracija razred:

@Configuration @EnableRetry javna klasa AppConfig {...}

4. Korištenje proljetnog ponovnog pokušaja

4.1. @Retryable Bez oporavka

Da bismo metodama dodali funkcionalnost ponovnog pokušaja, možemo koristiti @Retryable napomena:

@Service javno sučelje MyService {@Retryable (value = RuntimeException.class) void retryService (String sql); }

U ovom se primjeru pokušava ponoviti pokušaj kada a RuntimeException baca se.

Po @RetryableZadano ponašanje, ponovni pokušaj može se dogoditi do tri puta, s odgodom od jedne sekunde između ponovljenih pokušaja.

4.2. @Retryable i @Oporavak

Dodajmo sada metodu oporavka pomoću @Oporavak napomena:

@Service javno sučelje MyService {@Retryable (value = SQLException.class) void retryServiceWithRecovery (String sql) baca SQLException; @Recover void recovery (SQLException e, String sql); }

U ovom se primjeru pokušava ponoviti pokušaj kada se SQLException baca se.The @Oporavak napomena definira zasebnu metodu oporavka kada a @Retryable metoda ne uspije s navedenom iznimkom.

Slijedom toga, ako je retryServiceWithRecovery metoda nastavlja bacati a SqlException nakon 3 pokušaja, oporavak() pozvat će se metoda.

Rukovatelj oporavkom trebao bi imati prvi parametar tipa Bacljivo (nije obavezno) i isti tip povrata.Sljedeći se argumenti popunjavaju s popisa argumenata neuspjele metode istim redoslijedom.

4.3. Prilagođavanje @ Retryable's Ponašanje

Da biste prilagodili ponašanje ponovnog pokušaja, možemo koristiti parametre maxAttempts i odstupi:

@Service javno sučelje MyService {@Retryable (value = SQLException.class, maxAttempts = 2, backoff = @Backoff (delay = 100)) void retryServiceWithCustomization (String sql) baca SQLException; }

U gornjem primjeru bit će do 2 pokušaja i kašnjenje od 100 milisekundi.

4.4. Korištenje svojstava opruge

Također možemo koristiti svojstva u @Retryable bilješka.

Da bi to demonstrirali, vidjet ćemo kako eksternalizirati vrijednosti odgoditi i maxAttempts u datoteku svojstava.

Prvo, definirajmo svojstva u datoteci koja se zove ponovitiConfig.Svojstva:

retry.maxAttempts = 2 retry.maxDelay = 100

Zatim upućujemo svoje @Konfiguracija razred za učitavanje ove datoteke:

// ... @PropertySource ("classpath: retryConfig.properties") javna klasa AppConfig {...}

Konačno, možemo ubrizgati vrijednosti pokušaj ponovnog pokušaja. max i ponoviti.maxDelay u našem @Retryable definicija:

Javno sučelje @Service MyService {@Retryable (value = SQLException.class, maxAttemptsExpression = "$ {retry.maxAttempts}", backoff = @Backoff (delayExpression = "$ {retry.maxDelay}")) ​​void retryServiceWithExternalized StonWf SQLException; }

Imajte na umu da sada koristimo maxAttemptsExpression i delayExpression umjesto maxAttempts i odgoditi.

5. RetryTemplate

5.1 RetryOperations

Spring Retry nudi RetryOperations sučelje koje pruža skup izvršiti() metode:

javno sučelje RetryOperations {T izvršavanje (RetryCallback retryCallback) baca iznimku; ...}

The RetryCallback što je parametar izvršiti() je sučelje koje omogućuje umetanje poslovne logike koju treba pokušati ponovno nakon neuspjeha:

javno sučelje RetryCallback {T doWithRetry (kontekst RetryContext) baca Throwable; }

5.2. RetryTemplate Konfiguracija

The RetryTemplate je provedba RetryOperations. Konfigurirajmo a RetryTemplate grah u našem @Konfiguracija razred:

@Configuration javna klasa AppConfig {// ... @Bean public RetryTemplate retryTemplate () {RetryTemplate retryTemplate = new RetryTemplate (); FixedBackOffPolicy fixedBackOffPolicy = novo FixedBackOffPolicy (); fixedBackOffPolicy.setBackOffPeriod (2000l); retryTemplate.setBackOffPolicy (fixedBackOffPolicy); SimpleRetryPolicy retryPolicy = novo SimpleRetryPolicy (); retryPolicy.setMaxAttempts (2); retryTemplate.setRetryPolicy (retryPolicy); vratiti retryTemplate; }} 

The RetryPolicy određuje kada operaciju treba ponoviti.

A SimpleRetryPolicy koristi se za ponovni pokušaj određenog broja puta. S druge strane, BackOffPolicy koristi se za kontrolu nadoknade između pokušaja ponovnog pokušaja.

Konačno, a FixedBackOffPolicy zastaje na određeno vrijeme prije nastavka.

5.3. Koristiti RetryTemplate

Za pokretanje koda s ponovnim rukovanjem možemo nazvati r etryTemplate.execute () metoda:

retryTemplate.execute (new RetryCallback () {@Override public Void doWithRetry (RetryContext arg0) {myService.templateRetryService (); ...}});

Umjesto anonimne klase, možemo koristiti lambda izraz kako slijedi:

retryTemplate.execute (arg0 -> {myService.templateRetryService (); vrati nulu;}); 

6. Slušatelji

Slušatelji pružaju dodatne povratne pozive nakon ponovnih pokušaja. Možemo ih koristiti za razne presječne probleme u različitim pokušajima.

6.1. Dodavanje povratnih poziva

Povratni pozivi navedeni su u a RetryListener sučelje:

javna klasa DefaultListenerSupport proširuje RetryListenerSupport {@Override public void close (RetryContext context, RetryCallback callback, Throwable throwwable) {logger.info ("onClose); ... super.close (context, callback, bacanje);} @Override public void onError (RetryContext context, RetryCallback callback, Throwable throwable) {logger.info ("onError"); ... super.onError (context, callback, bacanje);} @Override public boolean open (RetryContext context, RetryCallback callback) {logger. info ("onOpen); ... povratak super.open (kontekst, povratni poziv); }}

The otvorena i Zatvoriti povratni pozivi dolaze prije i nakon cijelog ponovnog pokušaja, dok onError odnosi se na pojedinca RetryCallback poziva.

6.2. Registriranje slušatelja

Dalje, registriramo našeg slušatelja (Podržana podrška za slušatelje) našem RetryTemplate grah:

@Configuration javna klasa AppConfig {... @Bean public RetryTemplate retryTemplate () {RetryTemplate retryTemplate = new RetryTemplate (); ... retryTemplate.registerListener (novi DefaultListenerSupport ()); vratiti retryTemplate; }}

7. Testiranje rezultata

Za kraj našeg primjera, provjerimo rezultate:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = AppConfig.class, loader = AnnotationConfigContextLoader.class) javna klasa SpringRetryIntegrationTest {@Autowired private MyService myService; @Autowired private RetryTemplate retryTemplate; @Test (očekuje se = RuntimeException.class) javna praznina givenTemplateRetryService_whenCallWithException_thenRetry () {retryTemplate.execute (arg0 -> {myService.templateRetryService (); return null;}); }}

Kao što možemo vidjeti iz dnevnika ispitivanja, RetryTemplate i RetryListener su pravilno konfigurirani:

2020-01-09 20:04:10 [glavna] INFO obsDefaultListenerSupport - onOpen 2020-01-09 20:04:10 [glavna] INFO o.baeldung.springretry.MyServiceImpl - baci RuntimeException u metodu templateRetryService () 2020-01 -09 20:04:10 [glavna] INFO obsDefaultListenerSupport - onError 2020-01-09 20:04:12 [glavna] INFO o.baeldung.springretry.MyServiceImpl - baci RuntimeException u metodu templateRetryService () 2020-01-09 20 : 04: 12 [glavna] INFO obsDefaultListenerSupport - onError 2020-01-09 20:04:12 [glavna] INFO obsDefaultListenerSupport - onClose

8. Zaključak

U ovom smo članku vidjeli kako se koristi Spring Retry koristeći napomene, RetryTemplate, i slušatelji povratnih poziva.

Izvorni kod za primjere dostupan je na GitHubu.