Spring Boot学习笔记:系统配置

271 阅读7分钟

本文内容来自Spring Boot相关书籍学习总结

1、系统配置文件

1.1 application.properties

Spring Boot支持两种不同格式的配置文件:一种是Properties,另一种是YML。Spring Boot默认使用application.properties作为系统配置文件。

该文件包含Spring Boot项目的全局配置。我们可以在application.properties文件中配置Spring Boot支持的所有配置项,比如端口号、数据库连接、日志等。

1、基本语法

# 服务器端口配置
server.port=8081

2、配置文件加载顺序

Spring Boot系统启动时会按顺序依次读取4个不同路径下的配置文件:

1)项目根目录下的config目录。

2)项目根目录。

3)classpath下的config目录。

4)classpath目录。

注:一般在项目中习惯将配置文件放置在resources目录下。

3、修改默认配置文件名

通过修改项目启动类,调用SpringApplicationBuilder类的properties()方法可以实现自定义配置文件名称:

public static void main(String[] args) {
//        SpringApplication.run(MyApplication.class, args);
    new SpringApplicationBuilder(MyApplication.class)
            .properties("spring.config.location=classpath:/mytest.properties")
            .run(args);
}

Spring Boot项目启动加载时会默认读取更改名称的配置文件。

4、特殊数据类型注入

除了单个数值注入,properties文件还支持数组(列表)、Map类型的注入:

# list配置
user-list=aa,bb,cc,dd,ee

# Map配置
user-info={'name':'wang', 'age':'1', 'gender':'male'}

# list配置—引用类型
user-info-list[0].name=xx
user-info-list[0].age=12
user-info-list[1].name=ff
user-info-list[1].age=13

注入到类的对应属性:

@Value("#{'${app.user-name-list}'.split(',')}")
private List<String> userNameList;
@Value("#{${app.user-map}}")
private Map<String, String> userMap;

注入到类的List引用属性:

@Data
@Configuration
@ConfigurationProperties(prefix = "app")
public class UserConfig {
    private List<User> userInfoList;
}

1.2 application.yml

application.yml是以yml为后缀,使用YAML(YAML Ain't a Markup Language)的配置文件。

1、基本语法

YML基本语法为key:(空格)value的键值对形式,冒号后面必须加上空格。通过空格的缩进来控制属性的层级关系,只要是左对齐的一列数据,都是同一个层级的。具体格式如下:

# 日志配置
logging:
  level:
    root: warn
  file:
    max-history: 30
    max-size: 10MB
    path: /var/log

YML文件虽然格式简洁直观,但是对格式要求较高,使用YML配置文件时需要注意以下几点:

1)属性值和冒号中间必须有空格,如name: Weiz正确,使用name:Weiz就会报错。

2)需要注意各属性之间的缩进和对齐。

3)缩进不允许使用tab,只允许空格。

4)属性和值区分字母大小写。

2、特殊数据类型注入

(1)普通的值(数字、字符串、布尔值)

可以使用双引号("")来转义字符串中的特殊字符

name: "zhangsan \n lisi"

(2)对象、Map(属性和值)

对象同样是以k:v的键值对方式展现的

person:
    lastName: zhangsan
    age: 20

如果使用行内写法,可以将对象的属性和值写成JSON格式,具体写法如下:

person: {lastName: zhangsan,age: 20}

(3)数组(List、Set)

数组是以- value的形式表示数组中的元素的,具体写法如下:

persons:
 - zhangsan
 - lisi
 - wangwu

可以采用行内写法,数组使用中括号的形式,具体写法如下:

persons: [zhangsan, lisi, wangwu]

1.3 Properties与YML配置文件的区别

1)YML文件以数据为中心,对于数据的支持和展现非常友好。

2)Properties文件对格式的要求没那么严格,而YML文件以空格的缩进来控制层级关系,对格式的要求比较高,缩进格式不对时容易出错。

3)Properties文件支持@PropertySource注解,而YML文件不支持。

4)YML文件支持多文档块的使用方式,使用起来非常灵活。

5)Properties配置的优先级高于YML文件。因为YML文件的加载顺序先于Properties文件,如果两个文件存在相同的配置,后面加载的Properties中的配置会覆盖前面YML中的配置。

2、自定义配置项

Spring Boot提供了@Value注解、@ConfigurationProperties注解和Environment接口等3种方式自定义配置项。

2.1 @Value

Spring Boot提供@Value注解来设置简单的配置项,默认读取application.properties文件中的配置属性。

注意:

1)使用@Value注解时,所在类必须被Spring容器管理

2)@Value需要传入完整的配置项的Key值

3)@Value注解默认读取application.properties配置文件,如果需要使用其他的配置文件,可以通过@PropertySource注解指定对应的配置文件。

2.2 Environment

Environment是Spring为运行环境提供的高度抽象的接口,它会自动获取系统加载的全部配置项,包括命令行参数,系统属性,系统环境,随机数,配置文件等。使用时无须其他的额外配置,只要在使用的类中注入Environment即可。

演示:

添加配置项:

app.username=mimang

读取配置项

@Autowired
private Environment env;

@Test
public void getProp() {
    System.out.println(env.getProperty("app.username"));
}

注意:

1)使用Environment无须指定配置文件,其获取的是系统加载的全部配置文件中的配置项。

2)需要注意配置文件的编码格式,默认为ISO8859-1。

2.3 @ConfigurationProperties

使用注解@ConfigurationProperties将配置项和实体Bean关联起来,实现配置项和实体类字段的关联,读取配置文件数据。

添加配置文件mytest.properties

app.username=迷茫
app.password=123456
app.age=12

将配置文件中的配置项注入到自定义配置对象类

@Data
@Configuration
@ConfigurationProperties(prefix = "app")
@PropertySource(value = "classpath:mytest.properties", encoding = "UTF-8")
public class UserConfig {
    private String username;
    private String password;
    private Integer age;
}

3、其他配置

3.1 随机数

Spring Boot支持在系统加载时配置随机数,使用${random}可以生成各种不同类型的随机值。Spring Boot提供的RandomValuePropertySource配置类可以很方便地生成随机数,可以生成integer、long、uuids和string类型的数据。

演示:

添加随机数配置项:

# 随机字符串
cfg.random.value=${random.value}
# uuid
cfg.random.uuid=${random.uuid}
# 随机int
cfg.random.number=${random.int}
# 随机long
cfg.random.bignumber=${random.long}
# 10以内的随机数
cfg.random.test1=${random.int(10)}
# 10-20的随机数
cfg.random.test2=${random.int[10,20]}

读取随机数配置项:

@Data
@Component
public class ConfigRandomValue {
    @Value("${cfg.random.value}")
    private String secret;
    @Value("${cfg.random.number}")
    private int number;
    @Value("${cfg.random.bignumber}")
    private long bigNumber;
    @Value("${cfg.random.uuid}")
    private String uuid;
    @Value("${cfg.random.test1}")
    private int number2;
    @Value("${cfg.random.test2}")
    private int number3;
}

3.2 配置引用

Spring Boot支持使用占位符获取之前的属性配置,也就是在后一个配置的值中直接引用先前定义过的配置项,直接解析其中的值。这样做的好处是:在多个具有相互关联的配置项中,只需要对其中一处配置项预先设置,其他地方都可以引用。

使用格式为:${name},name表示先前在配置文件中已经设置过的配置项名。

my.database.username=root

spring.datasource.username=${my.database.username}

可以通过冒号设置默认值,当配置项为空或未找到时,使用默认值代替

spring.datasource.username=${my.database.username:root}

4、日志配置

4.1 Spring Boot日志

Spring Boot提供spring-boot-starter-logging组件实现系统日志功能,该组件默认使用LogBack日志记录工具。

spring-boot-starter-web组件中,默认引入了spring-boot-starter-logging,如果不想使用默认的LogBack日志框架,可以使用exclusions标签关闭,然后引入其他日志框架依赖,如:

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <!--排除logback-->
        <exclusion>
            <artifactId>spring-boot-starter-logging</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 添加log4j2 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

如果项目不是web项目,则需要单独添加日志组件依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

Spring Boot提供了logging.pattern.console和logging.pattern.file配置项来定制日志输出格式,只需要在application.properties文件中添加logging.pattern.console的配置项即可。但是在企业开发中,常常使用xml文件设置日志属性,命名需要注意。

日志框架配置文件
Logbacklogback-spring.xml , logback.xml
Log4j2log4j2-spring.xml , log4j2.xml

logback.xml模板:

<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true" scanPeriod="10 seconds">

    <contextName>realtime</contextName>

    <!-- 设置日志输出路径  可以使“${}”来使用变量。-->
    <property name="log.path" value="logs"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>


    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/realtime-info.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/logs/realtime-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>1000MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 ERROR 日志 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/realtime-error.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/logs/realtime-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>1000MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <root level="info">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="INFO_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
    </root>

</configuration>

4.2 日志输出级别

系统的日志级别为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,级别逐渐提高。如果日志级别设置为INFO,则意味着TRACE和DEBUG级别的日志都不会输出。

5、系统多环境配置

实际项目开发过程中,需要面对不同的运行环境,比如开发环境、测试环境、生产环境等,每个环境的配置项都会有所区别。Spring Boot为我们提供了简单方便的配置方案来解决多环境的配置问题。

5.1 创建多环境配置文件

创建多环境配置文件时,需要遵循Spring Boot允许的命名约定来命名,格式为application-{profile}.properties,其中{profile}为对应的环境标识。

一般环境包括开发环境(dev)、测试环境(test)、生产环境(prod),在resources文件夹下添加application.propertiesapplication-dev.propertiesapplication-test.propertiesapplication-prod.properties文件,分别作为项目主配置文件、开发环境配置文件、测试环境配置文件、生产环境配置文件。

5.2 多环境切换

项目打包或者运行时,需要切换到指定的profile环境。指定项目的启动环境有以下3种方式:

(1)配置文件指定项目启动环境

Spring Boot支持通过spring.profiles.active配置项目启动环境,在application.properties配置文件中增加如下配置项指定对应的环境目录:

# 指定系统运行环境 
spring.profiles.active=dev

(2)命令行启动指定项目环境

在命令行通过java -jar命令启动项目时,需要如下指定启动环境:

java -jar xxx.jar --spring.profiles.active=dev