Включить новые добавленные источники данных в объект источника данных маршрута без перезапуска сервера приложений. - PullRequest
0 голосов
/ 08 марта 2020

Реализация SpringR AbstractRoutingDatasource путем динамического определения фактического источника данных на основе текущего контекста. Ссылался на эту статью: https://www.baeldung.com/spring-abstract-routing-data-source.

Здесь при запуске приложения весенней загрузки. Создана карта контекстов для объектов источника данных для настройки нашего AbstractRoutingDataSource. Все эти детали контекста клиента извлекаются из таблицы базы данных.

@Bean
    @DependsOn("dataSource")
    @Primary
    public DataSource routeDataSource() {

        RoutingDataSource routeDataSource = new RoutingDataSource();

        DataSource defaultDataSource = (DataSource) applicationContext.getBean("dataSource");

        List<EstCredentials> credentials = LocalDataSourcesDetailsLoader.getAllCredentails(defaultDataSource); // fetching from database table

        localDataSourceRegistrationBean.registerDataSourceBeans(estCredentials);

        routeDataSource.setDefaultTargetDataSource(defaultDataSource);
        Map<Object, Object> targetDataSources = new HashMap<>();

        for (Credentials credential : credentials) {
            targetDataSources.put(credential.getEstCode().toString(),
                    (DataSource) applicationContext.getBean(credential.getEstCode().toString()));
        }
        routeDataSource.setTargetDataSources(targetDataSources);

        return routeDataSource;
    }

Проблема заключается в том, что если я добавлю новые данные клиента, я не смогу получить их в routeDataSource. Очевидная причина в том, что эти значения устанавливаются при запуске.

Как мне добиться добавления нового контекста клиента, и мне пришлось заново инициализировать объект routeDataSource.

Планирование написать сервис для получения всего нового контекста клиента и сброса объекта routeDataSource, не нужно перезапускать сервер каждый раз, когда вносятся какие-либо изменения в детали клиента.

Ответы [ 3 ]

1 голос
/ 21 марта 2020

Простым решением этой ситуации является добавление @RefreshScope к определению компонента:

@Bean
@Primary
@RefreshScope
public DataSource routeDataSource() {

    RoutingDataSource routeDataSource = new RoutingDataSource();

    DataSource defaultDataSource = (DataSource) applicationContext.getBean("dataSource");

    List<EstCredentials> credentials = LocalDataSourcesDetailsLoader.getAllCredentails(defaultDataSource); // fetching from database table

    localDataSourceRegistrationBean.registerDataSourceBeans(estCredentials);

    routeDataSource.setDefaultTargetDataSource(defaultDataSource);
    Map<Object, Object> targetDataSources = new HashMap<>();

    for (Credentials credential : credentials) {
        targetDataSources.put(credential.getEstCode().toString(),
                (DataSource) applicationContext.getBean(credential.getEstCode().toString()));
    }
    routeDataSource.setTargetDataSources(targetDataSources);

    return routeDataSource;
}

Добавление Spring Boot Actuator в качестве зависимости:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Затем вызовите refre sh конечная точка POST to /actuator/refresh для обновления источника данных (фактически каждый refre sh bean-объект с областью видимости).

0 голосов
/ 21 марта 2020

Учитывая, что вы используете Oracle, вы также можете использовать его функции уведомления об изменении базы данных.

Думайте об этом как о слушателе в драйвере JDB C, который получает уведомления при любых изменениях в таблице базы данных. Таким образом, после получения изменения вы можете повторно инициализировать / добавить источники данных.

Учебное пособие о том, как это сделать, можно найти здесь: https://docs.oracle.com/cd/E11882_01/java.112/e16548/dbchgnf.htm#JJDBC28820

Хотя, в зависимости от Уведомления базы данных вашей организации нуждаются в дополнительных настройках брандмауэра, чтобы коммуникация работала.

Преимущество: вам не нужно вручную вызывать конечную точку REST, если что-то меняется (хотя ответ Marcos Barber ios совершенно действителен!)

0 голосов
/ 21 марта 2020

Таким образом, это будет зависеть от того, сколько вы знаете об источниках данных, которые нужно добавить, но вы можете настроить это как мультитенантный проект . Еще один пример создания новых источников данных:

@Autowired private Map <String, Datasource> mars2DataSources;

public void addDataSourceAtRuntime() {

    DataSourceBuilder dataSourcebuilder = DataSourcebuilder.create(
        MultiTenantJPAConfiguration.class.getclassloader())
            .driverclassName("org.postgresql.Driver")
            .username("postgres")
            .password("postgres")
            .url("Jdbc: postgresql://localhost:5412/somedb");

        mars2DataSources("tenantX", datasourcebuilder.build())
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...