Rumah  >  Artikel  >  Java  >  Bagaimana untuk mengemas kini fail yml secara dinamik dalam SpringBoot

Bagaimana untuk mengemas kini fail yml secara dinamik dalam SpringBoot

WBOY
WBOYke hadapan
2023-05-12 16:22:061207semak imbas

Kebergantungan projek

Projek ini berdasarkan versi 2.0.0.RELEASE, jadi snakeyaml perlu diperkenalkan secara berasingan dan versi yang lebih tinggi disertakan

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

Kebanyakan kaedah di Internet adalah untuk memperkenalkan spring-cloud Komponen konfigurasi -context memanggil kaedah refresh ContextRefresher untuk mencapai kesan yang sama Pertimbangkan dua perkara berikut:

  • Rangka kerja pembangunan menggunakan log balik spring-cloud-context akan menyebabkan bacaan konfigurasi log Dapatkan ralat

  • Memperkenalkan spring-cloud-context juga akan memperkenalkan komponen spring-boot-starter-actuator, yang akan membuka beberapa pemeriksaan kesihatan laluan dan pelabuhan, yang memerlukan kawalan tambahan ke atas keselamatan rangka kerja

pemerolehan kandungan fail YML

Membaca fail di bawah fail sumber memerlukan penggunaan ClassPathResource untuk mendapatkan InputStream

rreee

Kemas kini kandungan fail YML

Selepas kami memperoleh kandungan fail yml, kami memaparkannya secara visual ke meja depan untuk pengubahsuaian paparan, menukar kandungan yang diubah suai menjadi struktur Peta melalui kaedah yaml.load, dan kemudian gunakan yaml.dumpAsMap untuk menukarnya menjadi strim dan menulisnya pada fail

    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");
    }

penyegaran semula Atribut YML

Secara amnya terdapat tiga cara untuk membaca dan menggunakan atribut yml dalam program

Gunakan anotasi Nilai

    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();
    }

Baca melalui suntikan persekitaran

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

Gunakan anotasi ConfigurationProperties Baca

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

Refresh Hartanah

Koleksi konfigurasi yang kami baca melalui kaedah environment.getProperty sebenarnya disimpan dalam PropertySources Kami hanya perlu mengeluarkan semua pasangan nilai kunci dan menyimpannya dalam propertyMap Tukar kandungan fail yml yang dikemas kini kepada ymlMap dengan format yang sama, gabungkan dua Peta , dan panggil kaedah ganti PropertySources untuk penggantian keseluruhan

Tetapi kedua-dua ymlMap selepas yaml.load dan propertyMap yang diambil oleh penyahbinaan Data PropertySources adalah berbeza dan memerlukan penukaran manual

Koleksi propertyMap ialah kunci ringkas, pasangan nilai kunci nilai dan kunci ialah nama dalam bentuk sifat, seperti system.systemName=>xxxxx Sistem Pengurusan Kumpulan

koleksi ymlMap ialah kunci, hierarki bersarang bagi LinkedHashMap, contohnya system=>(systemName=>xxxxx Group Management System)

Kaedah penukaran adalah seperti berikut

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

Kaedah muat semula adalah seperti berikut

  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);
            }
        }
    }

Penyegaran semula anotasi

Sama ada anotasi Nilai atau anotasi ConfigurationProperties, ia sebenarnya digunakan dengan menyuntik kaedah atribut objek Bean Kami mula-mula menyesuaikan anotasi RefreshValue untuk mengubah suai kelas Bean di mana atribut itu berada terletak

Dengan melaksanakan antara muka InstantiationAwareBeanPostProcessorAdapter, kacang yang sepadan ditapis dan disimpan apabila sistem bermula apabila mengemas kini fail yml, kemas kini sifat

kacang yang sepadan melalui pemberitahuan acara musim bunga 🎜>

Daftar acara Gunakan anotasi EventListener

        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));

untuk memberitahu peristiwa pencetus Gunakan kaedah publishEvent ApplicationContext

    @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);
                }
            }
        }
    }

Kod lengkap YamlConfigRefreshPostProcessor adalah seperti berikut

Atas ialah kandungan terperinci Bagaimana untuk mengemas kini fail yml secara dinamik dalam SpringBoot. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam