Spring Boot - 从application.yml注入地图

 想零的时候 发布于 2023-01-01 14:58

我有一个带有以下内容的Spring Boot应用程序application.yml- 基本上从这里开始:

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

我可以注入特定的值,例如

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

但是,我想注入整个地图,例如:

@Value("${info}") Map info

是(或类似的)可能吗?显然,我可以直接加载yaml,但是想知道Spring是否已经支持了某些东西.

4 个回答
  • 下面的解决方案是@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,没有任何问题.但是吸气剂和孵化器很重要,@EnableConfigurationProperties必须要有@ConfigurationProperties工作.

    我从@Szymon Stepniak提供的groovy解决方案中尝试了这个想法,认为它对某人有用.

    2023-01-01 15:00 回答
  • 您可以使用@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.

    2023-01-01 15:00 回答
  • 要从配置中检索地图,您将需要配置类。不幸的是,@ Value注释无法解决问题。

    Application.yml

    entries:
      map:
         key1: value1
         key2: value2
    

    配置类:

    @Component
        @ConfigurationProperties("entries")
        @Getter
        @Setter
        public static class MyConfig {
            private Map<String, String> map;
        }
    

    2023-01-01 15:00 回答
  • 我今天遇到了同样的问题,但不幸的是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
    

    providersmap只包含一个map条目,我的目标是为其他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() {
           //....
        }
    }
    

    启动应用程序后,providers映射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() {
           //....
        }
    }
    

    在那之后,一切都变得很有效.

    虽然有一件事值得一提.在我开始工作之后,我决定创建这个字段,private并在setter方法中为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?
    

    如果您在Spring Boot应用程序中使用Groovy,请记住这一点.

    2023-01-01 15:00 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有