Konfigurieren Sie DataSource programmgesteuert in Spring Boot

73

Mit Spring Boot kann ich a JdbcTemplatemit folgendem instanziieren :

Code:

@Autowired
private JdbcTemplate jdbcTemplate;

Eigenschaften:

spring.datasource.url=jdbc:postgresql://my_url:my_port/my_other_stuff
spring.datasource.username=my_user_name
spring.datasource.password=my_password
spring.datasource.driver-class-name=org.postgresql.Driver

Dadurch wird eine DataSource der Klasse erstellt: org.apache.tomcat.jdbc.pool.DataSource

Wie setze ich den DataSource-Benutzernamen / das Passwort programmgesteuert?

Wir haben die Richtlinie, Anmeldeinformationen nicht im Klartext zu speichern, und ich muss einen bestimmten Anbieter für Anmeldeinformationen verwenden, bei dem ich arbeite.

Marsellus Wallace
quelle

Antworten:

89

Sie können verwenden, DataSourceBuilderwenn Sie jdbcStarter verwenden. Um die Standard-Bean für die automatische Konfiguration zu überschreiben, müssen Sie Ihre Bean als markieren@Primary

In meinem Fall habe ich Eigenschaften, die mit dem datasource.postgresPräfix beginnen.

Z.B

@ConfigurationProperties(prefix = "datasource.postgres")
@Bean
@Primary
public DataSource dataSource() {
    return DataSourceBuilder
        .create()
        .build();
}

Wenn es für Sie nicht machbar ist, können Sie verwenden

@Bean
@Primary
public DataSource dataSource() {
    return DataSourceBuilder
        .create()
        .username("")
        .password("")
        .url("")
        .driverClassName("")
        .build();
}
Eddú Meléndez
quelle
7
@Primary ist nicht erforderlich, da die AutoConfiguration nur dann eine DataSource-Bean erstellt, wenn keine andere Bean definiert ist.
Dunni
create () sollte wahrscheinlich der erste sein
Marsellus Wallace
Primär nicht erforderlich. Mit @Bean kann Spring Boot die Konfiguration registrieren. Name der Treiberklasse, URL, Benutzer, PwD erforderlich
Kishore Guruswamy
Gemäß JavaDoc @Primary "Gibt an, dass einer Bean der Vorzug gegeben werden soll, wenn mehrere Kandidaten für die automatische Verdrahtung einer einwertigen Abhängigkeit qualifiziert sind." docs.spring.io/spring/docs/current/javadoc-api/org/…
Andres Felipe
6
Aber wie wäre es mit Set spring.datasource.validation-queryund spring.datasource.test-while-idleundspring.datasource.time-between-eviction-runs-millis
zhuguowei
26

Mein Projekt von Spring-Boot ist gemäß Ihrer Unterstützung normal gelaufen. Die Konfiguration der Yaml-Datenquelle lautet:

spring:
  # (DataSourceAutoConfiguration & DataSourceProperties)
  datasource:
    name: ds-h2
    url: jdbc:h2:D:/work/workspace/fdata;DATABASE_TO_UPPER=false
    username: h2
    password: h2
    driver-class: org.h2.Driver

Benutzerdefinierte DataSource

@Configuration
@Component
public class DataSourceBean {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    @Primary
    public DataSource getDataSource() {
        return DataSourceBuilder
                .create()
//                .url("jdbc:h2:D:/work/workspace/fork/gs-serving-web-content/initial/data/fdata;DATABASE_TO_UPPER=false")
//                .username("h2")
//                .password("h2")
//                .driverClassName("org.h2.Driver")
                .build();
    }
}
Alfer Wei
quelle
3
Diese Antwort ist hilfreich, da sie zeigt, wie die Standardeigenschaften spring.datasource zum Definieren der DataSource verwendet werden. Beachten Sie, dass Sie, wenn Sie beispielsweise nur das Kennwort überschreiben möchten, die Kennwortdefinition aus application.properties (oder application.yml) entfernen und diese eine Eigenschaft im Code festlegen müssen.
@ Willie Wheeler Bist du sicher, dass das funktionieren würde? Denn was ich verstehe, wird der obige Code eine völlig neue Datenquellen-Bean zurückgeben. Dies bedeutet, dass die Eigenschaften von spring.datasource nicht wirksam werden und durch die neue Bean ersetzt werden.
Fadhlie Ikram
1
Ja, ich habe diesen Ansatz verwendet, um Passwörter in Vault zu externalisieren.
1
@ WillieWheeler Du hast recht. Ich habe es gerade versucht und es funktioniert.
Fadhlie Ikram
Schön, @FadhlieIkram zu hören. Danke für das Kontrollieren.
13

Sie müssen lediglich eine Methode mit Anmerkungen versehen, die eine DataSource mit @Bean zurückgibt. Es folgt ein vollständiges Arbeitsbeispiel.

@Bean
public DataSource dataSource() {
    DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.url(dbUrl);
        dataSourceBuilder.username(username);
        dataSourceBuilder.password(password);
        return dataSourceBuilder.build();   
}
Rodrigo Villalba Zayas
quelle
10

Wenn Sie den neuesten Spring Boot (mit JDBC-Starter und Hikari) verwenden, werden Sie auf Folgendes stoßen: java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName. Um dies zu lösen:

  1. In Ihren application.properties:

datasource.oracle.url=youroracleurl

  1. In Ihrer Anwendung als Bean definieren ( @Primaryist obligatorisch! ):
@Bean
@Primary
@ConfigurationProperties("datasource.oracle")
public DataSourceProperties getDatasourceProperties() {
    return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("datasource.oracle")
public DataSource getDatasource() {
    return getDatasourceProperties().initializeDataSourceBuilder()
           .username("username")
           .password("password")
           .build();
}
ACV
quelle
Ich musste auch die DataSource-Bean als @Primary deklarieren.
Nis
3
Es gibt einen einfacheren Weg: In den Anwendungseigenschaften (dh applyaiotion.yml) umbenennen: spring.datasource.urlin spring.datasource.jdbc-url. Das sollte den Trick machen !!! (In meinem Fall - SpringBoot v2.3.2)
davide79
4

Wenn Sie mehr Datumsquellenkonfigurationen wünschen, z

spring.datasource.test-while-idle=true 
spring.datasource.time-between-eviction-runs-millis=30000
spring.datasource.validation-query=select 1

Sie können den folgenden Code verwenden

@Bean
public DataSource dataSource() {
    DataSource dataSource = new DataSource(); // org.apache.tomcat.jdbc.pool.DataSource;
    dataSource.setDriverClassName(driverClassName);
    dataSource.setUrl(url);
    dataSource.setUsername(username);
    dataSource.setPassword(password);
    dataSource.setTestWhileIdle(testWhileIdle);     
    dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMills);
    dataSource.setValidationQuery(validationQuery);
    return dataSource;
}

Siehe : Spring Boot JDBC-Verbindung

zhuguowei
quelle
2

Alternativ können Sie DriverManagerDataSource verwenden, z.

public DataSource getDataSource(DBInfo db) {

    DriverManagerDataSource dataSource = new DriverManagerDataSource();

    dataSource.setUsername(db.getUsername());
    dataSource.setPassword(db.getPassword());
    dataSource.setUrl(db.getUrl());
    dataSource.setDriverClassName(db.getDriverClassName());

    return dataSource;
}

Seien Sie jedoch vorsichtig bei der Verwendung, da:

HINWEIS: Diese Klasse ist kein tatsächlicher Verbindungspool. Verbindungen werden nicht zusammengefasst. Es dient lediglich als einfacher Ersatz für einen vollständigen Verbindungspool, der dieselbe Standardschnittstelle implementiert, aber bei jedem Anruf neue Verbindungen erstellt. Referenz

MMKarami
quelle
1
NOTE: Within special class loading environments such as OSGi, this class is effectively superseded by SimpleDriverDataSource due to general class loading issues with the JDBC DriverManager that be resolved through direct Driver usage (which is exactly what SimpleDriverDataSource does).
Spezialisiert
1

Für Springboot 2.1.7 scheint das Arbeiten mit URL nicht zu funktionieren. Ändern Sie stattdessen mit jdbcUrl.

In Eigenschaften:

security:
      datasource:
        jdbcUrl: jdbc:mysql://ip:3306/security
        username: user
        password: pass

In Java:

@ConfigurationProperties(prefix = "security.datasource")
@Bean("dataSource")
@Primary
public DataSource dataSource(){

    return DataSourceBuilder
            .create()
            .build();
}
Christian Altamirano Ayala
quelle
0

Ich habe Tomcat DataSource in Spring-Boot 2 angepasst .

Abhängigkeitsversionen:

  • Spring-Boot: 2.1.9.FREIGABE
  • tomcat-jdbc: 9.0.20

Vielleicht ist es für jemanden nützlich.

application.yml

spring:
    datasource:
        driver-class-name: org.postgresql.Driver
        type: org.apache.tomcat.jdbc.pool.DataSource
        url: jdbc:postgresql://${spring.datasource.database.host}:${spring.datasource.database.port}/${spring.datasource.database.name}
        database:
            host: localhost
            port: 5432
            name: rostelecom
        username: postgres
        password: postgres
        tomcat:
            validation-query: SELECT 1
            validation-interval: 30000           
            test-on-borrow: true
            remove-abandoned: true
            remove-abandoned-timeout: 480
            test-while-idle: true
            time-between-eviction-runs-millis: 60000
            log-validation-errors: true
            log-abandoned: true

Java

@Bean
@Primary
@ConfigurationProperties("spring.datasource.tomcat")
public PoolConfiguration postgresDataSourceProperties() {
    return new PoolProperties();
}

@Bean(name = "primaryDataSource")
@Primary
@Qualifier("primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource primaryDataSource() {
    PoolConfiguration properties = postgresDataSourceProperties();
    return new DataSource(properties);
}

Der Hauptgrund, warum dies getan wurde, sind mehrere DataSources in der Anwendung, von denen eine als @Primary markiert werden muss .

Vladimir
quelle