前言
在开发中,我们有很多参数需要在不同环境,不同场景下使用,所以我们需要统一的定义到指定的配置文件中,同时我们真正使用的时候必须要映射到代码变量上。这时候我们有可以有多种方式能直接获取到属性值。
配置文件类型和不同的后缀
有yml格式和properties格式,对应不同环境可以通过在名称后面指定-xx的指定环境
- application.properties / application-xx.properties
- application.yml / application-xx.yml
- bootstrap.yml / bootstrap-xx.yml
配置文件的区别
对于properties和yml格式的区别
application.properties:是一种传统的键值对(key=value)格式的配置文件application.yml:是 YAML(YAML Ain't Markup Language)格式的配置文件,它使用缩进和层次结构来表示数据。
对于bootstrap和application的区别
bootstrap.yml: 这个文件在应用程序上下文(ApplicationContext)创建之前加载 ,主要配置应用程序基本信息,如springcloud相关配置源信息。application.yml: 在应用程序上下文创建过程中加载 , 用于配置应用程序的具体业务属性。如数据库连接等信息
不同位置的配置文件的优先级
file: ./config/ - 优先级最高(项目根路径下的config)file: ./ - 优先级第二 -(项目根路径下)classpath: /config/ - 优先级第三(项目resources/config下)classpath: / - 优先级第四(项目resources根目录)
编写的方式
对于数组项的编写形式,配置的value具有多项时的场景。
spring.profiles.include:
- 子项1
- 子项2
- 子项3
spring.profiles.include: 子项1,子项2,子项3
如果遇到配置值的需要换一行编写,内容还是连贯的
name: sdfsd\
sdfdsf
配置生效应用不同场景
Spring Boot 允许通过创建多个以application-{profile}.yml或application-{profile}.properties命名的配置文件来指定不同环境的配置。其中{profile}是环境名称
激活配置环境的方式
- 通过命令行参数激活: 在启动应用程序时,可以使用
--spring.profiles.active=dev - 在
application.yml或application.properties中设置默认环境
spring:
profiles:
active: dev
- 也可以通过@Profile生效环境, 用于在 Bean 的定义或者配置类层面,根据不同的配置文件(profiles)来决定是否创建 Bean 或者使配置类生效。
@Configuration
public class DataSourceConfig {
@Profile("dev")
@Bean
public Student devDataSource() {
// 配置test环境
Student stu = new Student();
stu.setName("gjc");
stu.setAge(18);
return devDataSource;
}
@Profile("prod")
@Bean
public Student prodDataSource() {
// 配置prod环境
Student stu = new Student();
stu.setName("gjc");
stu.setAge(18);
return devDataSource;
}
}
- 通过
Conditional注解家族的使用@ConditionalOnProperty: 用于根据配置属性的值来决定是否创建一个Bean或者使一个@Configuration类生效@ConditionalOnClass: 用于检查特定的类是否在类路径(classpath)上,以此来决定是否创建Bean或者使@Configuration类生效@ConditionalOnMissingBean: 用于检查容器中是否不存在某个特定类型的Bean,如果不存在,则创建一个新的Bean@ConditionalOnExpression: 基于 SpEL(Spring Expression Language)表达式来决定是否创建Bean或者使@Configuration类生效。
@Configuration
public class MyConfiguration {
// 只有当配置文件中${stu.name}为18的时候,myService这个Bean才会被创建
@Bean
@ConditionalOnProperty(name = "stu.age", havingValue = "18")
public MyService myService() {
return new MyService();
}
// 只有当类路径上存在这个类,这个bean才会创建
@Bean
@ConditionalOnClass(Student.class)
public TestseService testService() {
return new TestseService();
}
// 只有Spring容器还没创建AnotherService这个bean才会创建这个AnotherServiceBean
@Bean
@ConditionalOnMissingBean(AnotherService.class)
public AnotherService anotherService() {
return new AnotherService();
}
// 只有newService这个Bean只有在服务器端口大于8080并且当前激活的环境是prod时才会被创建
@Bean
@ConditionalOnExpression("${server.port} > 8080 && '${spring.profiles.active}' == 'prod'")
public NewService newService() {
return new NewService();
}
}
- 自定义实现了
@Conditional: 自定义规则,配合自定义注解生效场景。
// 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Conditional(OnClassNameConditional.class)// 指定规则的内容
public @interface ConditionalOnClassName {
// 暴露参数value传递
String value();
}
// 定义规则
public class OnClassNameConditional implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
// 自定义规则判断返回true,或者false 是否生效
}
}
// 使用注解
@Configuration
@ConditionalOnClassName("com.mysql.jdbc.Driver")
public class MysqlConfiguration extends AbstractJdbcConfiguration{
@Bean
public DataSource dataSource() {
....
}
}
获取配置文件属性
通过@Vlaue注解
针对配置文件application.yml/application.properties 中的属性参数
// application.yml
stu:
name: gjc
// application.properties
stu.name=gjc
配置文件字段直接通过注解@Value映射获取到值。
@Value("${stu.name}")
private String name;
// 设置默认值的方式
@Value("${stu.name:111}")
private String nameDefalut;
注意:
- 不能作用于静态变量(static);
- 不能作用于常量(final);
- 不能在非注册的类中使用(类需要被注册在spring上下文中,如用@Service,@RestController,@Component等);
- 使用这个类时,只能通过依赖注入的方式,用new的方式是不会自动注入这些配置的。
如果需要使用配置文件字段映射到静态变量上,可以通过如下方式实现,增加静态变量对应的set方法,且再通过注解标识。
private static String userName;
@Value("${stu.name}")
public void setUserName(String userName) {
UserService.userName = userName;
}
通过@ConfigurationProperties注解
当我们的配置文件对应一个属性下有多个字段,可以将这些字段收整到统一的对象中。
stu:
name: gjc
age: 18
score: 100
@ConfigurationProperties(prefix = "stu")
@Data
public class Student{
private String name;
private Integer age;
private Integer score;
// 设置别名
@Value("${stu.score}")
private Integer currentScore;
}
最后为了使它生效成为一个bean,通过注解@EnableConfigurationProperties(Student.class)标记 或者 @ConfigurationPropertiesScan扫描生效。后面就能通过bean的注入该实体类,就能获取到对应配置属性值。
通过@PropertySource注解使用
@PropertySource是 Spring 框架中的一个注解,用于指定外部属性文件的位置,使得 Spring 能够加载这些文件中的属性,并将其注入到 Spring 管理的 Bean 中。主要也是配合 @Value和 @ConfigurationProperties联合使用将配置文件值注入字段。
一: 创建自定义外部属性文件custom.properties
stu.name=gjc
stu.age=18
二: 使用@PropertySource注解加载属性文件
通过@PropertySource注解告诉spring在类路径下查找,然后配合@Value加载属性值到字段上。
@Component
@PropertySource("classpath:custom.properties")
public class Test {
@Value("${stu.name}")
private String name;
@Value("${stu.age}")
private int age;
}
注意:
- 文件位置可以是相对于类路径(classpath:zz.properties),也可以是绝对路径(file:/xx/yy/zz.properties)
- 文件格式一般都是.properties
通过class.getClassLoader加载流
通过获取类加载器加载属性文件的方式,也能从配置文件中获取对应的属性。通过配合读取到Properties上来使用。
try {
// 获取当前类的类加载器
ClassLoader classLoader = ResourceLoader.class.getClassLoader();
// 使用类加载器加载属性文件
InputStream inputStream = classLoader.getResourceAsStream("custom.properties");
Properties properties = new Properties();
properties.load(inputStream);
String propertyValue = properties.getProperty("stu.name");
} catch (IOException e) {
e.printStackTrace();
}
当然,通过class.getClassLoader 可以加载其他资源文件,例如图片文本等内容。
使用environment对象获取配置属性
Environment是 Spring 框架中的一个接口,用于访问应用程序的运行环境,包括配置属性、系统环境变量、应用程序参数等。可以通过@Autowired将Environment对象注入到 Spring 组件中,然后使用getProperty方法获取配置属性
@Component
public class Test{
@Autowired
private Environment environment;
public String getName(){
return environment.getProperty("stu.name")
}
}
命令行启动加载配置属性
Spring Boot 允许通过命令行参数来设置配置属性,可以覆盖application.properties或application.yml中设置。
java -jar demo.jar --stu.name=gjc
同理可由上面介绍的几种方法,获取命令行上的参数字段属性。
总结
主要介绍了配置文件的格式,使用和生效环境。以及我们在配置文件中属性值,如何被我们代码所应用上。