>Java >java지도 시간 >SpringBoot에서 yml 파일을 동적으로 업데이트하는 방법

SpringBoot에서 yml 파일을 동적으로 업데이트하는 방법

WBOY
WBOY앞으로
2023-05-12 16:22:061242검색

프로젝트 종속성

프로젝트는 2.0.0.RELEASE 버전을 기반으로 하기 때문에 snakeyaml을 별도로 도입해야 하며 상위 버전도 포함되어 있습니다

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

인터넷에 있는 대부분의 방법은 spring-cloud-context 구성 컴포넌트를 도입하고 이를 달성하려면 ContextRefresher의 새로 고침 메소드를 호출하십시오. 동일한 효과를 위해 사용되지 않는 다음 두 가지 사항을 고려하십시오.

  • 개발 프레임워크는 로그백 로그를 사용합니다. spring-cloud-context를 도입하면 로그 구성 읽기 오류가 발생합니다

  • spring-cloud-context를 도입하면 spring-boot -starter-actuator 구성 요소도 도입되어 일부 상태 확인 경로와 포트가 열리게 되며, 이를 위해서는 프레임워크 보안에 대한 추가 제어가 필요합니다

YML 파일 콘텐츠 획득

리소스 파일 아래의 파일을 읽으려면 다음을 사용해야 합니다. 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 파일을 얻기 위한 ClassPathResource 콘텐츠 업데이트

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 속성을 읽고 사용하는 방법에는 일반적으로 세 가지가 있습니다.

값 주석 사용

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

Read 환경 주입을 통해

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

ConfigurationProperties 주석을 사용하여 읽기

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

Property 새로 고침

environment.getProperty 메소드를 통해 읽습니다. 검색된 구성 컬렉션은 실제로 PropertySources에 저장되며 모든 키-값 쌍을 검색하여 propertyMap에 저장하기만 하면 됩니다. , 업데이트된 yml 파일 콘텐츠를 동일한 형식의 ymlMap으로 변환하고, 두 맵을 병합하고, PropertySources 교체를 호출합니다. 메서드는 전체적으로 교체될 수 있습니다

하지만 yaml.load 후 ymlMap의 데이터 분해와 propertyMap이 사용됩니다. PropertySources별로 다르며 수동 변환이 필요합니다

propertyMap 컬렉션은 간단한 키, 값 키-값 쌍이며 키는 속성 형식입니다. 이름은 예를 들어 system.systemName=>xxxxx 그룹 관리입니다. 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를 구현하면 시스템이 시작될 때 인터페이스가 해당 빈을 필터링하고 저장합니다. yml 파일을 업데이트할 때 스프링의 이벤트 알림을 통해 해당

빈의 속성을 업데이트합니다.

이벤트를 등록하려면 EventListener 주석을 사용하세요.

알림 트리거 이벤트는 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);
                }
            }
        }
    }

YamlConfigRefreshPostProcessor의 전체 코드는 다음과 같습니다

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

위 내용은 SpringBoot에서 yml 파일을 동적으로 업데이트하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제