복붙노트

[SPRING] Spring Boot - application.yml에서 맵 삽입

SPRING

Spring Boot - application.yml에서 맵 삽입

기본적으로 여기에서 가져온 다음 application.yml이있는 Spring Boot 응용 프로그램이 있습니다.

info:
   build:
      artifact: ${project.artifactId}
      name: ${project.name}
      description: ${project.description}
      version: ${project.version}

특정 값을 주입 할 수 있습니다.

@Value("${info.build.artifact}") String value

그러나 다음과 같이 전체지도를 삽입하고 싶습니다.

@Value("${info}") Map<String, Object> info

그것 (또는 비슷한 것)이 가능합니까? 분명히 yaml을 직접로드 할 수 있지만 Spring에서 이미 지원되는 것이 있는지 궁금해하고 있습니다.

해결법

  1. ==============================

    1.@ConfigurationProperties를 사용하여지도를 삽입 할 수 있습니다.

    @ConfigurationProperties를 사용하여지도를 삽입 할 수 있습니다.

    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @EnableAutoConfiguration
    @EnableConfigurationProperties
    public class MapBindingSample {
    
        public static void main(String[] args) throws Exception {
            System.out.println(SpringApplication.run(MapBindingSample.class, args)
                    .getBean(Test.class).getInfo());
        }
    
        @Bean
        @ConfigurationProperties
        public Test test() {
            return new Test();
        }
    
        public static class Test {
    
            private Map<String, Object> info = new HashMap<String, Object>();
    
            public Map<String, Object> getInfo() {
                return this.info;
            }
        }
    }
    

    질문에 yaml과 함께 이것을 실행하면 다음과 같은 결과가 나온다.

    {build={artifact=${project.artifactId}, version=${project.version}, name=${project.name}, description=${project.description}}}
    

    접두사를 설정하고 누락 된 속성을 처리하는 방법을 제어하는 ​​등 다양한 옵션이 있습니다. 자세한 내용은 javadoc을 참조하십시오.

  2. ==============================

    2.아래 해결책은 @Andy Wilkinson의 솔루션의 단축형입니다. 단, 별도의 클래스를 사용하거나 @Bean 주석이 달린 메서드를 사용할 필요가 없습니다.

    아래 해결책은 @Andy Wilkinson의 솔루션의 단축형입니다. 단, 별도의 클래스를 사용하거나 @Bean 주석이 달린 메서드를 사용할 필요가 없습니다.

    application.yml :

    input:
      name: raja
      age: 12
      somedata:
        abcd: 1 
        bcbd: 2
        cdbd: 3
    

    SomeComponent.java:

    @Component
    @EnableConfigurationProperties
    @ConfigurationProperties(prefix = "input")
    class SomeComponent {
    
        @Value("${input.name}")
        private String name;
    
        @Value("${input.age}")
        private Integer age;
    
        private HashMap<String, Integer> somedata;
    
        public HashMap<String, Integer> getSomedata() {
            return somedata;
        }
    
        public void setSomedata(HashMap<String, Integer> somedata) {
            this.somedata = somedata;
        }
    
    }
    

    우리는 @Value 주석과 @ConfigurationProperties 모두 문제없이 사용할 수 있습니다. 하지만 getter와 setter는 중요하며 @EnableConfigurationProperties는 @ConfigurationProperties를 작동시켜야합니다.

    @Szymon Stepniak이 제공하는 그루비 솔루션에서이 아이디어를 시도했지만 누군가에게 유용 할 것이라고 생각했습니다.

  3. ==============================

    3.오늘 같은 문제가 발생하지만 안타깝게도 Andy의 해결책이 효과가 없습니다. Spring Boot 1.2.1.RELEASE에서는 훨씬 쉽지만 몇 가지 사항을 알고 있어야합니다.

    오늘 같은 문제가 발생하지만 안타깝게도 Andy의 해결책이 효과가 없습니다. Spring Boot 1.2.1.RELEASE에서는 훨씬 쉽지만 몇 가지 사항을 알고 있어야합니다.

    내 application.yml에서 흥미로운 부분은 다음과 같습니다.

    oauth:
      providers:
        google:
         api: org.scribe.builder.api.Google2Api
         key: api_key
         secret: api_secret
         callback: http://callback.your.host/oauth/google
    

    제공자지도에는 하나의지도 항목 만 포함되어 있습니다. 제 목표는 다른 OAuth 제공자에게 동적 구성을 제공하는 것입니다. 이 yaml 파일에 제공된 구성을 기반으로 서비스를 초기화 할 서비스에이 맵을 삽입하려고합니다. 나의 초기 구현은 다음과 같다.

    @Service
    @ConfigurationProperties(prefix = 'oauth')
    class OAuth2ProvidersService implements InitializingBean {
    
        private Map<String, Map<String, String>> providers = [:]
    
        @Override
        void afterPropertiesSet() throws Exception {
           initialize()
        }
    
        private void initialize() {
           //....
        }
    }
    

    응용 프로그램을 시작한 후 OAuth2ProvidersService의 공급자 맵이 초기화되지 않았습니다. Andy가 제안한 해결책을 시도했지만 제대로 작동하지 않았습니다. 그 응용 프로그램에서 Groovy를 사용하므로 private을 제거하고 Groovy가 getter와 setter를 생성하도록 결정했습니다. 그래서 내 코드는 다음과 같습니다.

    @Service
    @ConfigurationProperties(prefix = 'oauth')
    class OAuth2ProvidersService implements InitializingBean {
    
        Map<String, Map<String, String>> providers = [:]
    
        @Override
        void afterPropertiesSet() throws Exception {
           initialize()
        }
    
        private void initialize() {
           //....
        }
    }
    

    그 작은 변화 후에 모든 것이 효과가있었습니다.

    언급 할만한 가치가있는 것은 하나 있지만. 내가이 필드를 비공개로 만들고 setter 메서드에서 직접 인수 형식을 제공하기로 결정했습니다. 불행히도 그것은 작동하지 않을 것이다. 메시지와 함께 org.springframework.beans.NotWritablePropertyException이 발생합니다 :

    Invalid property 'providers[google]' of bean class [com.zinvoice.user.service.OAuth2ProvidersService]: Cannot access indexed value in property referenced in indexed property path 'providers[google]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'providers[google]' of bean class [com.zinvoice.user.service.OAuth2ProvidersService]: Bean property 'providers[google]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    

    스프링 부트 애플리케이션에서 Groovy를 사용하고 있다면 명심하십시오.

  4. ==============================

    4.

    foo.bars.one.counter=1
    foo.bars.one.active=false
    foo.bars[two].id=IdOfBarWithKeyTwo
    
    public class Foo {
    
      private Map<String, Bar> bars = new HashMap<>();
    
      public Map<String, Bar> getBars() { .... }
    }
    

    https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding

  5. ==============================

    5.구성에서 맵을 검색하려면 구성 클래스가 필요합니다. @Value 주석은 유감스럽게도 트릭을 수행하지 않습니다.

    구성에서 맵을 검색하려면 구성 클래스가 필요합니다. @Value 주석은 유감스럽게도 트릭을 수행하지 않습니다.

    Application.yml

    entries:
      map:
         key1: value1
         key2: value2
    

    구성 클래스 :

    @Component
        @ConfigurationProperties("entries")
        @Getter
        @Setter
        public static class MyConfig {
            private Map<String, String> map;
        }
    
  6. from https://stackoverflow.com/questions/24917194/spring-boot-inject-map-from-application-yml by cc-by-sa and MIT license