[JAVA] So erhalten Sie den Einstellungswert (Eigenschaftswert) aus der Datenbank in Spring Framework

Bei der Verarbeitung von Einstellungswerten in Spring Framework können Einstellungswerte in Eigenschaftendateien, Systemeigenschaften (durch -D angegebene Werte), Betriebssystemumgebungsvariablen, JNDI (nur Webanwendungsumgebung) usw. und auf der Anwendungsseite angegeben werden Es kann über "@ Value" oder "Environment" bezogen werden.

Zum Beispiel sieht es wie folgt aus.

Beispiel für die Einstellung der Wertespezifikation(Eigenschaftendatei)


services.user.url=http://user.service.com/{id}
services.company.url=http://company.service.com/{id}

Referenzbeispiel für Einstellwert


@Service
public class MyService {

  private final RestTemplate restTemplate = new RestTemplate();
  private final Environment environment;

  @Value("${services.user.url}") //Injizieren Sie den Einstellwert beim Generieren der Bean
  private String userServiceUrl;

  public MyService(Environment environment) {
    this.environment = environment;
  }

  public User getUser(String id) {
    User user = restTemplate.getForObject(userServiceUrl, User.class, id);
    return user;
  }

  public Company getCompany(String id) {
    String companyServiceUrl = environment.getProperty("services.company.url"); //Holen Sie sich den eingestellten Wert zur Laufzeit
    Company company = restTemplate.getForObject(companyServiceUrl, User.class);
    return company;
  }

}

In Spring Boot anstelle von "@ Value" "[Typensichere Konfigurationseigenschaften](https://docs.spring.io/spring-boot/docs/2.1.7.RELEASE/reference/htmlsingle/#" Ich denke, es ist üblich, "boot-features-external-config-typesafe-configuration-properties" zu verwenden, aber hier wird ** absichtlich ** " @ Value"als Eigenschaftsplatzhalter verwendet (" Gibt an, dass $ {...})) verwendet werden soll. (Obwohl ich es nicht erklären werde, gilt die hier vorgestellte Methode auch für "typsichere Konfigurationseigenschaften".)

Spring Framwork (leider?) Bietet keine Klasse zum Abrufen der Einstellungen aus der Datenbank, aber das Speicherziel der Einstellungen wird von einer Klasse namens "PropertySource" abstrahiert, sodass die Einstellungen aus der Datenbank stammen. Wenn Sie eine "PropertySource" erstellen, um die zu erhalten und auf die "Umgebung" anzuwenden, können Sie in der Anwendung darauf verweisen.

Erstellen einer "PropertySource", um die Einstellungen aus der Datenbank abzurufen

Versuchen Sie, eine Klasse zu erstellen, die beim Start den Einstellungswert aus der Datenbank abruft, zwischenspeichert und den Cache jederzeit aktualisiert (obwohl ich der Meinung bin, dass die Thread-Sicherheit verdächtig ist ...).

package com.example.demo;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class JdbcPropertySource extends EnumerablePropertySource<DataSource> implements InitializingBean {

  private final JdbcTemplate jdbcTemplate;
  private final String[] tableNames;
  private Map<String, Object> properties = Collections.emptyMap();

  public JdbcPropertySource(String name, DataSource dataSource, String... tableNames) {
    super(name, dataSource);
    this.jdbcTemplate = new JdbcTemplate(dataSource);
    this.tableNames = tableNames.length == 0 ? new String[]{"t_properties"} : tableNames;
  }

  @Override
  public String[] getPropertyNames() {
    return properties.keySet().toArray(new String[0]);
  }

  @Override
  public Object getProperty(String name) {
    Map<String, Object> currentProperties = properties;
    return currentProperties.get(name);
  }

  @Override
  public void afterPropertiesSet() {
    load();
  }

  public void load() {
    Map<String, Object> loadedProperties = Stream.of(tableNames)
        .flatMap(tableName -> jdbcTemplate.queryForList("SELECT name, value FROM " + tableName).stream())
        .collect(Collectors.toMap(e -> (String) e.get("name"), e -> e.get("value")));
    this.properties = loadedProperties;
  }

}

Anwendung auf "Umwelt"

package com.example.actuatordemo;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;

import javax.sql.DataSource;

@Configuration
public class MyConfiguration {

  //DataSource-Einstellungen
  @Bean
  DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
        .setType(EmbeddedDatabaseType.H2)
        .setName("demo")
        .addScript("classpath:init-db.sql")
        .build();
  }

  //Diesmal wurde die Einstellung von JdbcPropertySource erstellt
  @Bean
  JdbcPropertySource jdbcPropertySource(DataSource dataSource) {
    return new JdbcPropertySource("jdbcProperties", dataSource);
  }

  //Bean-Definition zum Anwenden der diesmal erstellten JdbcPropertySource auf Environment
  @Bean
  static BeanFactoryPostProcessor environmentPropertySourcesCustomizer() {
    return bf -> {
      ConfigurableEnvironment environment = bf.getBean(ConfigurableEnvironment.class);
      JdbcPropertySource propertySource = bf.getBean(JdbcPropertySource.class);
      //Anwendung gemäß der folgenden Priorität von Betriebssystemumgebungsvariablen (Priorität wird gemäß den Anforderungen bestimmt)
      environment.getPropertySources()
          .addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, propertySource);
    };
  }

  //Bean-Definition zum Aktivieren von Eigenschaftsplatzhaltern
  @Bean
  static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
  }

}

Dieses Mal habe ich es mit dem Mechanismus von "BeanFactoryPostProcessor" auf "Umgebung" angewendet. Ist dies die beste Methode? Ist nicht sehr zuversichtlich. Ich würde mich freuen, wenn Sie kommentieren könnten, ob es einen besseren Weg gibt.

Datenbank vorbereiten

Da dieser Eintrag die eingebettete Datenbank verwendet, bereiten Sie die SQL für die Eingabe der Tabelle und der Daten vor.

src/main/resources/init-db.sql


drop table t_properties if exists;
create table t_properties (
  name varchar(512) not null primary key,
  value text
);

insert into t_properties (name, value) values ('services.user.url','http://dev01/services/user/{id}');
insert into t_properties (name, value) values ('services.company.url','http://dev01/services/company/{id}');

Zusammenfassung

In dem Fall, an dem ich gerade arbeite (Nicht-Spring-Boot-Fall ...), müssen möglicherweise (möglicherweise) einige Einstellungswerte in der Datenbank vorhanden sein (aus Sicht des Systembetriebs). Was kann ich also technisch tun? Ich habe darüber nachgedacht und einen Prototyp gemacht. Es scheint Verbesserungspotenzial zu geben, beispielsweise die Gewährleistung der Thread-Sicherheit, aber ich bin erleichtert zu wissen, dass dies mithilfe der Erweiterungspunkte von Spring Framework realisiert werden kann.

Recommended Posts

So erhalten Sie den Einstellungswert (Eigenschaftswert) aus der Datenbank in Spring Framework
So erhalten Sie das Datum mit Java
So erhalten Sie eine Klasse von Element in Java
So binden Sie mit einer Eigenschaftendatei in Spring Boot
[Spring Boot] So verweisen Sie auf die Eigenschaftendatei
Ich möchte den Wert in Ruby erhalten
So erstellen Sie Ihre eigene Anmerkung in Java und erhalten den Wert
[Spring Boot] So rufen Sie Eigenschaften dynamisch aus einer in einer URL enthaltenen Zeichenfolge ab
[Java] So erhalten Sie den Maximalwert von HashMap
[Android] So erhalten Sie die Einstellungssprache des Terminals
[Java] So erhalten Sie den Schlüssel und den Wert, die in Map gespeichert sind, durch iterative Verarbeitung
So erhalten Sie den Namen einer Klasse / Methode, die in Java ausgeführt wird
So rufen Sie den Hashwert in einem Array in Ruby ab
So erhalten Sie die längsten Informationen von Twitter ab dem 12.12.2016
So ändern Sie den Einstellwert von Springboot Hikari CP
[Schienen] Anzeigen von Informationen, die in der Datenbank gespeichert sind
Wie man Lombok im Frühling benutzt
So erhalten Sie Parameter in Spark
So legen Sie ein Profil mit annotationsbasierter Konfiguration im Spring-Framework fest und verwenden es
Was ich bei der Migration von der Spring Boot 1.4-Serie zur 2.0-Serie getan habe
So erhalten Sie die ID des automatisch inkrementierten PRIMAY-Schlüssels in MyBatis
So erhalten Sie den Wert von Boolean mit jQuery in einfacher Rails-Form
Was ich bei der Migration von der Spring Boot 1.5-Serie zur 2.0-Serie getan habe
Abrufen und Hinzufügen von Daten aus dem Firebase Firestore in Ruby
[Java] So konvertieren Sie vom Typ String in den Pfadtyp und erhalten den Pfad
[Android] Ich möchte den Listener über die Schaltfläche in ListView abrufen
So ermitteln Sie die Länge einer Audiodatei mit Java
So erhöhen Sie den Wert von Map in einer Zeile in Java
[Spring Boot] Ich möchte meine eigene Eigenschaftendatei hinzufügen und den Wert mit env.getProperty () abrufen.
Wie kann ich Spring Tool in Eclipse 4.6.3 einbinden?
[Java] So erhalten Sie das aktuelle Verzeichnis
So übergeben Sie den Wert an einen anderen Bildschirm
So erhalten Sie das aktuelle Datum als Zeichenfolge im Format JJJJMMTT
Versuchen Sie, mit MyBatis im Micronaut + Kotlin-Projekt Daten aus der Datenbank abzurufen
[Rails] So erhalten Sie die aktuell mit devise angemeldeten Benutzerinformationen
So ändern Sie den Wert einer Variablen an einem Haltepunkt in IntelliJ
So ermitteln Sie den absoluten Pfad eines in Java ausgeführten Verzeichnisses
Android-Entwicklung, wie man den Wert des JSON-Objekts auf null überprüft
Wie Bean-Eigenschaften Anforderungsparameter im Listenstil in Spring binden
[Swift] So ermitteln Sie die Anzahl der Elemente in einem Array (Super Basic)
So erhalten Sie Keycloak-Anmeldeinformationen in der Interceptor-Klasse
graphql-ruby: So erhalten Sie den Namen der Abfrage oder Mutation im Controller Hinweis
So überprüfen Sie das Protokoll im Docker-Container
So erhalten Sie einen Heapdump aus einem Docker-Container
So erhalten Sie die ID eines Benutzers, der sich in Swift bei Firebase authentifiziert hat
So sichern Sie von der Datenbank (DB) in die Seeds-Datei
So überprüfen Sie die neueste Version von io.spring.platform für das Schreiben in pom.xml von Spring (STS)
Wie komme ich zum heutigen Tag?
So löschen Sie die Datenbank beim Neuerstellen der App
Ordnen Sie GET-Anforderungen im Frühjahr komplexen Objekten zu.
So erhalten Sie eine SIMD-Optimierung für HotSpot JavaVM
So legen Sie Umgebungsvariablen in der Eigenschaftendatei der Spring-Boot-Anwendung fest
So ermitteln Sie das Datum aus dem Datumstyp von JavaScript, von dem C # -Entwickler abhängig sind
[Java] So erhalten Sie die endgültige umgeleitete URL