Как создать собственную логику повторных попыток для источника данных Spring?
Я подключаюсь к базе данных SQL Azure, и моя следующая задача - создать собственную логику повторных попыток при сбое подключения. Мне бы хотелось, чтобы логика повторения запускалась как при запуске (если необходимо), так и в любое время, когда происходит сбой соединения во время работы приложения. Я провел тест, в котором я удалил ограничения IP из своего приложения, и это вызвало исключение в моем приложении (как исключение). Я хотел бы обработать, когда это исключение выдается, чтобы я мог вызвать задание, которое проверяет, что приложение и сервер настроены правильно. Я ищу решение, где я могу обработать эти исключения и повторить транзакцию БД?
Конфигурация источника данных
@Bean
@Primary
public DataSource dataSource() {
return DataSourceBuilder
.create()
.username("username")
.password("password")
.url("jdbc:sqlserver://contoso.database.windows.net:1433;database=*********;user=******@*******;password=*****;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;")
.driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
.build();
}
application.properties
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
spring.jpa.show-sql=true
logging.level.org.springframework.web: ERROR
logging.level.org.hibernate: ERROR
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=1
spring.datasource.tomcat.test-on-borrow=true
spring.jpa.hibernate.ddl-auto=update
2 ответа
Следующий код может помочь вам создать логику повторения для источника данных в Spring Boot:
package com.example.demo;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.datasource.AbstractDataSource;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Retryable;
@SpringBootApplication
@EnableRetry
public class DemoApplication {
@Order(Ordered.HIGHEST_PRECEDENCE)
private class RetryableDataSourceBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof DataSource) {
bean = new RetryableDataSource((DataSource)bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public BeanPostProcessor dataSouceWrapper() {
return new RetryableDataSourceBeanPostProcessor();
}
}
class RetryableDataSource extends AbstractDataSource {
private DataSource delegate;
public RetryableDataSource(DataSource delegate) {
this.delegate = delegate;
}
@Override
@Retryable(maxAttempts=10, backoff=@Backoff(multiplier=2.3, maxDelay=30000))
public Connection getConnection() throws SQLException {
return delegate.getConnection();
}
@Override
@Retryable(maxAttempts=10, backoff=@Backoff(multiplier=2.3, maxDelay=30000))
public Connection getConnection(String username, String password)
throws SQLException {
return delegate.getConnection(username, password);
}
}
Не уверен, что вы считаете нестандартным, но есть встроенная опция с Spring boot и Aspectj, использующая pom.xml в проекте mavern, так как spring-retry зависит от Aspectj:
Добавьте следующие зависимости в ваш проект pom.xml:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${version}</version>
</dependency>
А затем добавьте аннотацию @EnableRetry в свой код:
package com.example.springretry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
@EnableRetry
@SpringBootApplication
public class SpringRetryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRetryApplication.class, args);
}
}
Пример модуля повтора Spring можно найти здесь: https://howtodoinjava.com/spring-boot2/spring-retry-module/