ホームページ  >  記事  >  Java  >  SpringBoot で yml ファイルを動的に更新する方法

SpringBoot で yml ファイルを動的に更新する方法

WBOY
WBOY転載
2023-05-12 16:22:061136ブラウズ

プロジェクトの依存関係

プロジェクトはバージョン 2.0.0.RELEASE に基づいているため、snakeyaml を別途導入する必要があり、より高いバージョンが含まれています

        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.23</version>
        </dependency>

インターネット上のほとんどのメソッドは、 spring-cloud の導入 -context 構成コンポーネントは、同じ効果を達成するために ContextRefresher の更新メソッドを呼び出します。使用されていない次の 2 つの点を考慮してください。

  • 開発フレームワークはログバック ログを使用します。 spring-cloud-context を導入すると、ログ設定の読み取りが発生します。エラーが発生します。

  • spring-cloud-context を導入すると、spring-boot-starter-actuator コンポーネントも導入され、これが開きます。一部のヘルス チェック ルートとポート。フレームワーク セキュリティに対する追加の制御が必要です

YML ファイル コンテンツの取得

リソース ファイルの下のファイルを読み取るには、ClassPathResource を使用して InputStream を取得する必要があります

    public String getTotalYamlFileContent() throws Exception {
        String fileName = "application.yml";
        return getYamlFileContent(fileName);
    }
    public String getYamlFileContent(String fileName) throws Exception {
        ClassPathResource classPathResource = new ClassPathResource(fileName);
        return onvertStreamToString(classPathResource.getInputStream());
    }
    public static String convertStreamToString(InputStream inputStream) throws Exception{
       return IOUtils.toString(inputStream, "utf-8");
    }

YML ファイルのコンテンツの更新

yml ファイルのコンテンツを取得した後、表示変更のためにそれをフロント デスクに視覚的に表示し、yaml.load を通じて変更されたコンテンツを Map 構造に変換します。メソッドを作成し、yaml.dumpAsMap を使用してストリームに変換し、ファイルに書き込みます。

    public void updateTotalYamlFileContent(String content) throws Exception {
        String fileName = "application.yml";
        updateYamlFileContent(fileName, content);
    }
	public void updateYamlFileContent(String fileName, String content) throws Exception {
        Yaml template = new Yaml();
        Map<String, Object> yamlMap = template.load(content);
        ClassPathResource classPathResource = new ClassPathResource(fileName);
        Yaml yaml = new Yaml();
        //字符输出
        FileWriter fileWriter = new FileWriter(classPathResource.getFile());
        //用yaml方法把map结构格式化为yaml文件结构
        fileWriter.write(yaml.dumpAsMap(yamlMap));
        //刷新
        fileWriter.flush();
        //关闭流
        fileWriter.close();
    }

YML プロパティのリフレッシュ

プログラムで yml プロパティを読み取って使用するには、通常 3 つの方法があります。

値のアノテーションを使用する

    @Value("${system.systemName}")
    private String systemName;

環境インジェクションを読み込む

    @Autowired
    private Environment environment;
    environment.getProperty("system.systemName")

ConfigurationProperties アノテーションを使用するRead

@Component
@ConfigurationProperties(prefix = "system")
public class SystemConfig {
    private String systemName;
}

プロパティの更新

構成コレクション環境を介して読み取ります。getProperty メソッドは、実際には PropertySources に格納されます。すべてのキーと値のペアを取り出して、propertyMap に格納するだけです。更新された yml ファイルの内容を同じ形式の ymlMap に変換し、

しかし、yaml.load 後の ymlMap と PropertySources データ分解によって取り出された propertyMap は両方とも異なり、手動変換が必要です

propertyMap コレクションは単純なキーと値のペアであり、キーは system.systemName=>xxxxx などのプロパティ形式の名前です。 Group Management System

ymlMap コレクションはキー、ネストされた階層構造です。 LinkedHashMap の例、system=>(systemName=>xxxxx Group Management System)

変換方法は次のとおりです

  public HashMap<String, Object> convertYmlMapToPropertyMap(Map<String, Object> yamlMap) {
        HashMap<String, Object> propertyMap = new HashMap<String, Object>();
        for (String key : yamlMap.keySet()) {
            String keyName = key;
            Object value = yamlMap.get(key);
            if (value != null && value.getClass() == LinkedHashMap.class) {
                convertYmlMapToPropertyMapSub(keyName, ((LinkedHashMap<String, Object>) value), propertyMap);
            } else {
                propertyMap.put(keyName, value);
            }
        }
        return propertyMap;
    }
    private void convertYmlMapToPropertyMapSub(String keyName, LinkedHashMap<String, Object> submMap, Map<String, Object> propertyMap) {
        for (String key : submMap.keySet()) {
            String newKey = keyName + "." + key;
            Object value = submMap.get(key);
            if (value != null && value.getClass() == LinkedHashMap.class) {
                convertYmlMapToPropertyMapSub(newKey, ((LinkedHashMap<String, Object>) value), propertyMap);
            } else {
                propertyMap.put(newKey, value);
            }
        }
    }

更新方法は次のとおりです

        String name = "applicationConfig: [classpath:/" + fileName + "]";
        MapPropertySource propertySource = (MapPropertySource) environment.getPropertySources().get(name);
        Map<String, Object> source = propertySource.getSource();
        Map<String, Object> map = new HashMap<>(source.size());
        map.putAll(source);
        Map<String, Object> propertyMap = convertYmlMapToPropertyMap(yamlMap);
        for (String key : propertyMap.keySet()) {
            Object value = propertyMap.get(key);
            map.put(key, value);
        }
        environment.getPropertySources().replace(name, new MapPropertySource(name, map));

Annotation Refresh

Value アノテーションであっても、ConfigurationProperties アノテーションであっても、実際には Bean オブジェクトのプロパティ メソッドを注入することで使用されます。最初にアノテーション RefreshValue をカスタマイズして、プロパティが設定されている Bean のクラスを変更します。が見つかります

InstantiationAwareBeanPostProcessorAdapter インターフェイスを実装すると、システムの起動時に対応する Bean がフィルタリングされて保存されます。yml ファイルを更新するときに、対応する

Bean のプロパティを Spring のイベントを通じて更新できます。 notification.

イベントを登録する EventListener アノテーションを使用します

    @EventListener
    public void updateConfig(ConfigUpdateEvent configUpdateEvent) {
        if(mapper.containsKey(configUpdateEvent.key)){
            List<FieldPair> fieldPairList = mapper.get(configUpdateEvent.key);
            if(fieldPairList.size()>0){
                for (FieldPair fieldPair:fieldPairList) {
                    fieldPair.updateValue(environment);
                }
            }
        }
    }

トリガー イベントを通知し、ApplicationContext のpublishEvent メソッドを使用します

    @Autowired
    private ApplicationContext applicationContext;
  	for (String key : propertyMap.keySet()) {
       applicationContext.publishEvent(new YamlConfigRefreshPostProcessor.ConfigUpdateEvent(this, key));
    }

YamlConfigRefreshPostProcessor の完全なコードは次のとおりです

リーリー

以上がSpringBoot で yml ファイルを動的に更新する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。