Panduan untuk Percubaan Musim Semi

1. Gambaran keseluruhan

Spring Retry menyediakan kemampuan untuk melakukan operasi semula yang gagal secara automatik. Ini berguna di mana kesalahan mungkin sementara (seperti gangguan rangkaian sesaat).

Dalam tutorial ini, kita akan melihat pelbagai cara untuk menggunakan Spring Retry: anotasi, RetryTemplate , dan callback.

2. Pergantungan Maven

Mari mulakan dengan menambahkan kebergantungan percubaan musim bunga ke dalam fail pom.xml kami :

 org.springframework.retry spring-retry 1.2.5.RELEASE 

Kami juga perlu menambahkan Spring AOP ke dalam projek kami:

 org.springframework spring-aspects 5.2.8.RELEASE 

Lihatlah Maven Central untuk versi terkini pergantungan dari spring-retry dan spring-aspek.

3. Membolehkan Spring Retry

Untuk mengaktifkan Spring Retry dalam aplikasi, kita perlu menambahkan anotasi @EnableRetry ke kelas @Konfigurasi kami :

@Configuration @EnableRetry public class AppConfig { ... }

4. Menggunakan Spring Retry

4.1. @Dapatkan semula tanpa Pemulihan

Untuk menambahkan lagi fungsi ke kaedah, kita boleh menggunakan anotasi @Retryable :

@Service public interface MyService { @Retryable(value = RuntimeException.class) void retryService(String sql); }

Dalam contoh ini, percubaan semula dicuba apabila RuntimeException dilemparkan .

Mengikut tingkah laku lalai @Retryable , percubaan semula boleh berlaku hingga tiga kali, dengan kelewatan satu saat di antara percubaan semula .

4.2. @Retryable dan @Recover

Mari sekarang tambahkan kaedah pemulihan menggunakan anotasi @Recover :

@Service public interface MyService { @Retryable(value = SQLException.class) void retryServiceWithRecovery(String sql) throws SQLException; @Recover void recover(SQLException e, String sql); }

Dalam contoh ini, percubaan semula dicuba apabila SQLException dilemparkan . The @Recover anotasi menentukan kaedah pemulihan yang berasingan apabila @Retryable Cara gagal dengan pengecualian tertentu.

Akibatnya, jika kaedah retryServiceWithRecovery terus melemparkan SqlException setelah 3 percubaan, kaedah recovery () akan dipanggil.

Pengendali pemulihan harus mempunyai parameter pertama jenis Throwable (pilihan) dan jenis pengembalian yang sama.Argumen berikut diisi dari senarai argumen kaedah yang gagal dalam urutan yang sama.

4.3. Menyesuaikan Tingkah Laku @ Retryable

Untuk menyesuaikan tingkah laku yang cuba semula ini, kita boleh menggunakan parameter maxAttempts dan backoff :

@Service public interface MyService { @Retryable( value = SQLException.class, maxAttempts = 2, backoff = @Backoff(delay = 100)) void retryServiceWithCustomization(String sql) throws SQLException; }

Dalam contoh di atas, akan ada hingga 2 percubaan dan penundaan 100 milisaat.

4.4. Menggunakan Hartanah Musim Semi

Kami juga boleh menggunakan sifat dalam anotasi @Retryable .

Untuk menunjukkan ini, kita akan melihat bagaimana untuk keadaan luar nilai-nilai kelewatan dan maxAttempts ke dalam fail hartanah .

Pertama, mari kita tentukan sifat dalam fail yang dipanggil retryConfig. sifat :

retry.maxAttempts=2 retry.maxDelay=100

Kami kemudian mengarahkan kelas @Configuration kami memuat fail ini:

// ... @PropertySource("classpath:retryConfig.properties") public class AppConfig { ... }

Akhirnya, kami dapat memasukkan nilai retry.maxAttempts dan retry.maxDelay dalam definisi @Retryable kami :

@Service public interface MyService { @Retryable( value = SQLException.class, maxAttemptsExpression = "${retry.maxAttempts}", backoff = @Backoff(delayExpression = "${retry.maxDelay}")) void retryServiceWithExternalizedConfiguration(String sql) throws SQLException; }

Harap maklum bahawa kami sekarang menggunakan maxAttemptsExpression dan delayExpression dan bukannya maxAttempts dan delay .

5. Mencuba semula Templat

5.1 Percubaan semula

Spring Retry menyediakan antara muka RetryOperations yang menyediakan satu set kaedah eksekusi () :

public interface RetryOperations {  T execute(RetryCallback retryCallback) throws Exception; ... }

The RetryCallback yang merupakan parameter daripada melaksanakan () adalah satu antara muka yang membolehkan kemasukan logik perniagaan bahawa keperluan untuk dibicarakan semula atas kegagalan:

public interface RetryCallback { T doWithRetry(RetryContext context) throws Throwable; }

5.2. RetryTemplate Konfigurasi

The RetryTemplate merupakan pelaksanaan RetryOperations . Mari konfigurasikan kacang RetryTemplate di kelas @Konfigurasi kami :

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

The RetryPolicy menentukan apabila operasi perlu dicuba semula.

A SimpleRetryPolicy digunakan untuk mencuba semula nombor tetap masa. Sebaliknya, BackOffPolicy digunakan untuk mengawal undur antara percubaan mencuba semula.

Akhirnya, FixedBackOffPolicy berhenti untuk jangka masa yang tetap sebelum meneruskan.

5.3. Menggunakan RetryTemplate

Untuk menjalankan kod dengan mencuba semula kita boleh memanggil kaedah r etryTemplate.execute () :

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

Daripada kelas tanpa nama, kita boleh menggunakan ungkapan lambda seperti berikut:

retryTemplate.execute(arg0 -> { myService.templateRetryService(); return null; }); 

6. Pendengar

Pendengar memberikan panggilan balik tambahan semasa percubaan semula. Kami boleh menggunakannya untuk pelbagai permasalahan silang di pelbagai percubaan yang berbeza.

6.1. Menambah Panggilan Balik

Panggilan balik disediakan dalam antara muka RetryListener :

public class DefaultListenerSupport extends RetryListenerSupport { @Override public void close(RetryContext context, RetryCallback callback, Throwable throwable) { logger.info("onClose); ... super.close(context, callback, throwable); } @Override public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { logger.info("onError"); ... super.onError(context, callback, throwable); } @Override public boolean open(RetryContext context, RetryCallback callback) { logger.info("onOpen); ... return super.open(context, callback); } }

Yang terbuka dan berhampiran panggilan balas datang sebelum dan selepas keseluruhan cuba semula, manakala onError terpakai kepada individu RetryCallback panggilan.

6.2. Mendaftar Pendengar

Seterusnya, kami mendaftarkan pendengar kami ( DefaultListenerSupport) ke kacang RetryTemplate kami :

@Configuration public class AppConfig { ... @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); ... retryTemplate.registerListener(new DefaultListenerSupport()); return retryTemplate; } }

7. Menguji Keputusan

To conclude our example, let's verify the results:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( classes = AppConfig.class, loader = AnnotationConfigContextLoader.class) public class SpringRetryIntegrationTest { @Autowired private MyService myService; @Autowired private RetryTemplate retryTemplate; @Test(expected = RuntimeException.class) public void givenTemplateRetryService_whenCallWithException_thenRetry() { retryTemplate.execute(arg0 -> { myService.templateRetryService(); return null; }); } }

As we can see from the test logs, the RetryTemplate and the RetryListener have been properly configured:

2020-01-09 20:04:10 [main] INFO o.b.s.DefaultListenerSupport - onOpen 2020-01-09 20:04:10 [main] INFO o.baeldung.springretry.MyServiceImpl - throw RuntimeException in method templateRetryService() 2020-01-09 20:04:10 [main] INFO o.b.s.DefaultListenerSupport - onError 2020-01-09 20:04:12 [main] INFO o.baeldung.springretry.MyServiceImpl - throw RuntimeException in method templateRetryService() 2020-01-09 20:04:12 [main] INFO o.b.s.DefaultListenerSupport - onError 2020-01-09 20:04:12 [main] INFO o.b.s.DefaultListenerSupport - onClose

8. Conclusion

In this article, we have seen how to use Spring Retry using annotations, the RetryTemplate, and callbacks listeners.

The source code for the examples is available over on GitHub.