在对应的Configuration类中配置多个yml文件(Spring Boot)
Posted
技术标签:
【中文标题】在对应的Configuration类中配置多个yml文件(Spring Boot)【英文标题】:Multiple yml files configuring in corresponding Configuration class (Spring Boot) 【发布时间】:2020-05-31 19:22:59 【问题描述】:我在 Spring Boot 中的资源类路径位置中有多个 yml 文件,例如 Spring Boot 的以下结构。最初我只为 application-abc.yml 编写,当时这个文件的所有值都加载到它们相应的类中,但是当我添加到另一个文件 application-xyz.yml 时,它也会加载到它们相应的配置类中,但是此时只在两个配置类中加载 application-xyz.yml 的值。因此,需要帮助在单个构建中配置相应配置文件中的两个文件的值:
-src
-main
-java
-packages
-config
-ApplicationAbcConfig.java
-ApplicationConfig.java
-ApplicationFactory.java
-ApplicationXyzConfig.java
-Authentication.java
-Operations.java
-Payload.java
-RequestPayload.java
-ResponsePayload.java
-services
-YmlConfigurationSelection.java
-resources
-application.yml
-application-abc.yml
-application-xyz.yml
-MultipleYmlDemoProject.java
application-abc.yml 的内容
authentication:
name: name
type: type
payload:
request:
- sequence: 1
attributes:
- attributes1
- attributes2
response:
- sequence: 1
attributes:
- attributes3
- attributes4
operations:
name: name
type: type
payload:
request:
- sequence: 1
attributes:
- attributes5
- attributes6
response:
- sequence: 1
attributes:
- attributes7
- attributes8
application-xyz.yml 的内容
authentication:
name: name
type: type
payload:
request:
- sequence: 1
attributes:
- attributes9
- attributes10
response:
- sequence: 1
attributes:
- attributes11
- attributes12
operations:
name: name
type: type
payload:
request:
- sequence: 1
attributes:
- attributes13
- attributes14
response:
- sequence: 1
attributes:
- attributes15
- attributes16
ApplicationConfig.java 的内容
public interface ApplicationConfig
public Authentication getAuthentication();
public void setAuthentication(Authentication authentication);
public Operations getOperations();
public void setOperations(Operations operations);
Authentication.java 的内容
public class Authentication
private String name;
private String type;
private Payload payload;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getType()
return type;
public void setType(String type)
this.type = type;
public Payload getPayload()
return payload;
public void setPayload(Payload payload)
this.payload = payload;
Operations.java 的内容
public class Operations
private String name;
private String type;
private Payload payload;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getType()
return type;
public void setType(String type)
this.type = type;
public Payload getPayload()
return payload;
public void setPayload(Payload payload)
this.payload = payload;
Payload.java 的内容
public class Payload
private List<RequestPayload> request;
private List<ResponsePayload> response;
public List<RequestPayload> getRequest()
return request;
public void setRequest(List<RequestPayload> request)
this.request = request;
public List<ResponsePayload> getResponse()
return response;
public void setResponse(List<ResponsePayload> response)
this.response = response;
RequestPayload.java 的内容
public class RequestPayload
private String sequece;
private List<String> attributes;
public String getSequece()
return sequece;
public void setSequece(String sequece)
this.sequece = sequece;
public List<String> getAttributes()
return attributes;
public void setAttributes(List<String> attributes)
this.attributes = attributes;
ResponsePayload.java 的内容
public class ResponsePayload
private String sequece;
private List<String> attributes;
public String getSequece()
return sequece;
public void setSequece(String sequece)
this.sequece = sequece;
public List<String> getAttributes()
return attributes;
public void setAttributes(List<String> attributes)
this.attributes = attributes;
ApplicationAbcConfig.java 的内容
@Configuration
@SpringBootConfiguration
@EnableConfigurationProperties
@org.springframework.context.annotation.PropertySource("classpath:application-abc.yml")
public class ApplicationAbcConfig implements ApplicationConfig, PropertySourceFactory
private Authentication authentication;
private Operations operations;
@Override
public Authentication getAuthentication()
return authentication;
@Override
public void setAuthentication(Authentication authentication)
this.authentication = authentication;
@Override
public Operations getOperations()
return operations;
@Override
public void setOperations(Operations operations)
this.operations = operations;
@Override
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException
Properties propertiesFromYaml = loadYamlIntoProperties(resource);
String sourceName = name != null ? name : resource.getResource().getFilename();
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException
try
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
catch (IllegalStateException e)
// for ignoreResourceNotFound
Throwable cause = e.getCause();
if (cause instanceof FileNotFoundException)
throw (FileNotFoundException) e.getCause();
throw e;
ApplicationXyzConfig.java 的内容
@Configuration
@SpringBootConfiguration
@EnableConfigurationProperties
@org.springframework.context.annotation.PropertySource("classpath:application-xyz.yml")
public class ApplicationXyzConfig implements ApplicationConfig, PropertySourceFactory
private Authentication authentication;
private Operations operations;
@Override
public Authentication getAuthentication()
return authentication;
@Override
public void setAuthentication(Authentication authentication)
this.authentication = authentication;
@Override
public Operations getOperations()
return operations;
@Override
public void setOperations(Operations operations)
this.operations = operations;
@Override
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException
Properties propertiesFromYaml = loadYamlIntoProperties(resource);
String sourceName = name != null ? name : resource.getResource().getFilename();
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException
try
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
catch (IllegalStateException e)
// for ignoreResourceNotFound
Throwable cause = e.getCause();
if (cause instanceof FileNotFoundException)
throw (FileNotFoundException) e.getCause();
throw e;
ApplicationFactory.java 的内容
@Component
public class ApplicationFactory
@Autowired
private ApplicationAbcConfig applicationAbcConfig;
@Autowired
private ApplicationXyzConfig applicationXyzConfig;
public ApplicationConfig getApplicationPropertiesConfig(String application)
if (application.equalsIgnoreCase("abc"))
return applicationAbcConfig;
else if (application.equalsIgnoreCase("xyz"))
return applicationXyzConfig;
else
return null;
YmlConfigurationSelection.java 的内容
public class YmlConfigurationSelection
@Autowired
private ApplicationFactory applicationFactory;
private ApplicationConfig applicationConfig;
public Object accessingProperties(String application)
applicationConfig = applicationFactory.getApplicationPropertiesConfig(application);
return null;
MultipleYmlDemoProject.java 的内容
@SpringBootApplication
@SpringBootConfiguration
@PropertySource(factory = ApplicationAbcConfig.class, value = "classpath:application-abc.yml")
@PropertySource(factory = ApplicationXyzConfig.class, value = "classpath:application-xyz.yml")
public class MultipleYmlDemoProject
public class MultipleYmlDemo
public static void main(String[] args)
ConfigurableApplicationContext ctx =
SpringApplication.run(YamlPropertysourceApplication.class, args);
ConfigurableEnvironment env = ctx.getEnvironment();
【问题讨论】:
【参考方案1】:您似乎有一个旧的 Spring 应用程序试图迁移到 Spring Boot。
Spring boot 原生使用 yaml 文件,因此如果您以 Spring Boot 方式进行集成,则可以删除许多您必须维护的样板代码。配置的命名也有问题:名称application-<something>.yml
保留用于spring boot 配置文件,也许如果你将重命名为myprops-abc/xyz.yaml
它会以不同的方式运行,我不能肯定地说。
总而言之,我建议您采用以下方式,这比 IMO 更好:
-
必须将两个配置集加载到一个配置中,因此请创建一个表示该配置的配置属性文件:
@ConfigurationProperties(prexix="security")
public class SecurityConfigProperties
private SecurityRealm abc;
private SecurityRealm xyz;
// getters, setters
public class SecurityRealm
private Authentication autentication;
private Operations operations;
// getters setters
public class Authentication ...
private class Operations ...
-
现在将 abc 和 xyz yaml 中的所有内容放入一个文件
application.yaml
并给出“安全”前缀:
security:
abc: // note, this 'abc' matches the field name of the configuration
authentication:
...
operations:
....
xyz:
authentication:
...
operations:
....
-
好的,一切都映射好了,像这样创建配置:
@Configuration
@EnableConfigurationProperties(SecurityConfigProperties.class)
public class SecurityConfiguration
@Bean
public SecurityBeanForABC(SecurityConfigProperties config)
return new SecurityBeanForABC(config.getAbc().getAuthentication(), config.getAbc().getOperations());
... the same for XYZ
请注意,使用这种方法,您只需在 java 对象中维护配置映射,并且没有用于加载/解析属性的代码) - 一切都由 spring boot 自动完成。如果您配置一个特殊的注释处理器并拥有一个下降 IDE,您甚至可以获得这些 yaml 属性的自动完成功能,但它超出了这个问题的范围。关键是用spring boot直接支持的方式做事有很多优点:)
【讨论】:
实际上,我不能将所有内容都写在像 application.yml 这样的单个 yml 文件中,因为我有这样的情况,不同的应用程序需要许多不同的配置,这会导致单个 yml 文件过载。所以,如果你能帮助处理不同的文件,那对我会有帮助。为此,我将非常感谢您。 当然可以。像以前一样创建不同的文件:application-abc.yml、application-xyz.yml。一个将包含:security:abc:...,另一个将包含 security:xyz:...(关键是它们仍然会有不同的前缀)。现在使用 --spring.profiles.active=xyz,abc 运行应用程序,它将加载这两个文件。配置将“合并”到 SecurityConfigProperties 嗨,我想知道一些关于这个问题的延伸。作为@Mark Bramnik 在我的情况下工作正常的答案,但我想要一些改变,比如我想从应用程序含义之外读取属性'application-abc.yml'和'application-xyz.yml'文件,即使在部署jar文件之后也是如此。所以,如果有人可以帮助我,那我很高兴。 为什么需要这个?一般来说,在 Spring Boot 中,您可以指定一个包含配置的文件夹(它不必在 jar 中),但它仍会在应用程序启动期间读取所有配置。但是,您可以将使用此配置的 Bean 定义为 @Lazy,以便仅在有人调用它们时才实际初始化它们,而不是在启动期间直接初始化。 我需要它,因为其他人会编写属性,而我只需要读取所有这些属性。那么,你能用一些小例子来解释一下吗?以上是关于在对应的Configuration类中配置多个yml文件(Spring Boot)的主要内容,如果未能解决你的问题,请参考以下文章
Spring注解中@Configuration和@Configurable的区别
001 IOC基础注解 @Configuration @Bean