SpringBoot 配置文件
SpringBoot 配置文件的使用及多环境下的配置

# SpringBoot 配置文件

# properties 和 yaml

  1. 语法

    appliction.properties

    server.port=8080
    

    appliction.yaml

    server:
      port: 8080
    

    在 properties 文件中是以点进行分割的, 在 yaml 中是用冒号进行分割

    yaml 是 json 的超集,同样是键值对格式,通过冒号进行赋值,且冒号后赋值时需要一个空格

  2. 官方推荐使用 yaml

    yaml 支持中文:

    ​ 需要注意文件编码,使用 UTF-8 确保不会乱码或报错

    yaml 支持列表:

    my:
      servers:
        - dev.example.com
        - another.example.com
    
    # 使用 properties
    # my.servers[0]=dev.example.com
    # my.servers[1]=another.example.com
    

    yaml 支持单文件多配置:

    # 用 --- 分割多个配置
    server:
        address: 192.168.1.100
    ---
    spring:
        profiles: development
    server:
        address: 127.0.0.1
    ---
    spring:
        profiles: production
    server:
        address: 192.168.1.120
    
  3. 配置文件优先级

    配置文件可存放位置

    • 外置,在相对于应用程序运行目录的 /config 子目录里。
    • 外置,在应用程序运行的目录里
    • 内置,在 config 包内
    • 内置,在 classpath 根目录

    优先级从上到下递减,同位置 properties 文件比 yaml 优先级高

# 使用 @Value

application.yaml

app:
  name: Spring Boot Demo
  version: 1.0

App.java

@Component
@Data
@ToString
public class App {

    @Value("${app.name}")
    private String name;

    @Value("${app.version}")
    private String version;
}

测试

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    App app;

    @Test
    void contextLoads() {
        System.out.println(app);
    }
}
// App(name=Spring Boot Demo, version=1.0)

注意,静态变量的注入

@Component
@Data
@ToString
public class App {
    
    private static String flag;

    // 在 set 方法上 @Value
    // 注意该方法不是静态的
    @Value("${app.flag}")
    public void setFlag(String s) {
        flag = s;
    }
}

# 使用 @ConfigurationProperties

application.yaml

app:
  name: Spring Boot Demo
  version: 1.0

App.java

@ConfigurationProperties(prefix = "app")
@Data
@ToString
public class App {

    private String name;

    private String version;
}

测试

@SpringBootTest
@EnableConfigurationProperties(App.class)
class DemoApplicationTests {

    @Autowired
    App app;

    @Test
    void contextLoads() {
        System.out.println(app);
    }

}

@EnableConfigurationProperties 将 @ConfigurationProperties 标注的类加入 IOC 容器,相当于 @ConfigurationProperties 与 @Component 连用

SpringBoot 2.2 之后还可以使用 @ConstructorBinding,通过构造方法注入

@ConstructorBinding
@ConfigurationProperties(prefix = "app")
@ToString
public class App {

    private String name;

    private String version;

    public App(String name, String version) {
        this.name = name;
        this.version = version;
    }
}

# @PropertyResource

@PropertyResource 常与 @ConfigurationProperties 连用,用来选择指定要读取的配置文件

App.java

@Component
@ConfigurationProperties(prefix = "app")
// 指定配置文件
@PropertySource(value = {"classpath:app.properties"})
@Data
@ToString
public class App {

    private String name;

    private String version;
}

resource 下的 app.properties

app.name=Spring Boot Demo
app.version=1.1

如果使用 yaml 格式配置文件,指定 yaml 位置,需要自定义 PropertySourceFactory

public class YamlAndPropertySourceFactory extends DefaultPropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        if (resource == null) {
            return super.createPropertySource(name, resource);
        }
        Resource resourceResource = resource.getResource();
        if (!resourceResource.exists()) {
            return new PropertiesPropertySource(null, new Properties());
        } else if (resourceResource.getFilename().endsWith(".yml") ||
                resourceResource.getFilename().endsWith(".yaml")) {
            List<PropertySource<?>> sources = new YamlPropertySourceLoader()
                    .load(resourceResource.getFilename(), resourceResource);
            return sources.get(0);
        }
        return super.createPropertySource(name, resource);
    }
}
@Component
@ConfigurationProperties(prefix = "app")
// 指定 PropertySourceFactory
@PropertySource(value = {"classpath:app.yaml"}, factory = YamlAndPropertySourceFactory.class)
@Data
@ToString
public class App {
    // ...
}

# 其他方式读取配置文件

  1. JDK 原生方法

    Properties 类读取 properties

    Properties properties = new Properties();
    InputStream stream = 
        this.getClass().getClassLoader().getResourceAsStream("app.properties");
    // 或 InputStream stream = this.getClass().getResourceAsStream("/app.properties");
    properties.load(stream);
    String name = properties.getProperty("app.name");
    

    ResourceBundle 类读取 properties

    // app.properties
    ResourceBundle bundle = ResourceBundle.getBundle("app");
    String name = bundle.getString("app.name");
    
  2. SpringBoot 提供

    Environment 类可读取 application.yaml 或 application.properties

    @SpringBootTest
    class DemoApplicationTests {
    
        @Autowired
        private Environment env;
        
        @Test
        void contextLoads() throws Exception {
            String name = env.getProperty("app.name");
            System.out.println(name);
        }
    }
    

    YamlPropertiesFactoryBean 解析 yaml,并转换为 Properties

    YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
    Resource resource = new ClassPathResource("app.yaml");
    yaml.setResources(resource);
    Properties properties = yaml.getObject();
    String name  = properties.getProperty("app.name");
    System.out.println(name);
    

    YamlMapFactoryBean 解析 yaml,并转换为 Map

    YamlMapFactoryBean yaml = new YamlMapFactoryBean();
    yaml.setResources(new ClassPathResource("app.yaml"));
    Map<String, Object> map = yaml.getObject();
    Map<String, Object> app = (Map<String, Object>) map.get("app");
    String name = (String) app.get("name");
    System.out.println(name);
    

# 多环境配置

SpringBoot 的配置文件默认为application.ymlapplication.properties

不同 profile 下的配置文件由 application-{profile}.yml 管理

  1. 通过 spring.profiles.active 指定 profile

    通过指定 spring.profiles.active 属性决定使用具体哪个环境的 profile

    application-{profile}.yml 配置文件会覆盖默认配置文件 application.yml下的同一属性

    一般 profile 有以下几种:dev、test、prod

    spring:
      profiles:
        active: dev
    
  2. 通过 maven 指定 profile

    在项目或模块的 pom.xml 里添加 profiles 节点

    <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <profileActive>dev</profileActive>
            </properties>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <profileActive>prod</profileActive>
            </properties>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <profileActive>test</profileActive>
            </properties>
        </profile>
    </profiles>
    

    配置资源过滤

    <build>
        <finalName>ROOT</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <!-- 过滤资源 -->
                <excludes>
                    <exclude>application*.yml</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <!-- 是否替换 @xx@ 表示的 maven properties 属性值 -->
                <filtering>true</filtering>
                <!-- 引入资源 -->
                <includes>
                    <include>application.yml</include>
                    <include>application-${profileActive}.yml</include>
                </includes>
            </resource>
        </resources>
    </build>
    

    application.yaml

    spring:
      profiles:
        active: @profileActive@
    

    maven 命令,通过 -P 指定 @profileActive@

    mvn clean package -D maven.test.skip=true -P dev
    
  3. 在程序中获取 profile 配置

    通过 Environment 类

    @SpringBootTest
    class DemoApplicationTests {
    
        @Autowired
        Environment env;
    
        @Test
        void contextLoads() throws Exception {
            // 获取生效的 profile 数组
            String[] activeProfiles = env.getActiveProfiles();
            // 判断 profile 是否生效
            Profiles profiles = Profiles.of("dev", "test");
            boolean b = env.acceptsProfiles(profiles);
            
            System.out.println(activeProfiles[0]);
            System.out.println(b);
        }
    }
    // dev
    // true
    

    通过注解 @Profile

    @Profile("dev","test")
    // 可以加在类或方法上
    // 环境满足时才生效
    
Comment here, be cool~

Copyright © 2020 CadeCode

Theme 2zh powered by VuePress

本页访问次数 0

Loading