SpringBoot 的配置文件与日志
目录
前言
一、配置文件
1. 配置文件的格式
2. application.properties
3. application.yml
1. 配置属性
2. 配置对象
3. 配置集合
4. 配置 Map
二、日志
1. Slf4j
2. 日志格式
3. 日志配置
4. 日志输出
前言
本文介绍了SpringBoot中的配置文件管理和日志系统。配置文件部分对比了.properties和.yml格式,详细说明了键值对、对象、集合和Map的配置方法,推荐使用可读性更高的yml格式。日志部分阐述了Slf4j日志框架的使用,包括日志级别、格式配置、持久化和分割策略,并提供了通过LoggerFactory和@Slf4j注解输出日志的示例代码。文章还简要介绍了外观模式在日志系统中的应用及其优势。
一、配置文件
1. 配置文件的格式
SpringBoot 的配置文件的格式分三种:
- application.properties;
- application.yml;
- application.yaml;
其中 .yml 是 .yaml 的简写,两者配置及使用方式相同;
application.properties 和 application.yml 是可以并存的,项目启动两个配置文件中的配置都会被加载,当配置出现冲突的时候,以 application.properties 为准;
虽然两种配置文件可以共存,但实际上在开发中,会选择统一的配置;
2. application.properties
application.properties 是 Spring 默认的配置文件;
.properties 是以键和值的形式配置,键和值以 ‘=’ 分割,如:
# 配置项⽬端⼝号 server.port=8080 # 配置数据库连接信息 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=root
读取配置文件需要用 @Value 注解来实现;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/config")
public class ConfigController {@Value("${server.port}")private String port;@RequestMapping("/getPort")public String getPort(){return port;}
}
.properties 的缺点是配置文件中冗余信息较多,可以 .yml 格式优化;
3. application.yml
.yml 是树形结构的配置文件,基础语法是 key: value,注意冒号后边必须要加空格;
1. 配置属性
spring:application:name: captcha-demo
.yml 读取方式和 .properties 读取方式相同,也是用 @Value 注解;
@RestController
@RequestMapping("/config")
public class ConfigController {@Value("${spring.application.name: }")private String name;@RequestMapping("/getName")public String getName(){return name;}
}
字符串默认不加单双引号,单引号会转义字符和不加一样,双引号不会转义字符;
2. 配置对象
student:id: 1name: zhangsanage: 12
配置对象不能用 @Value 注解读取,需要用到 @ConfigrationProperties 注解读取;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "student")
public class Student {private int id;private String name;private int age;
}
import com.example.demo.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/config")
public class ConfigController {@Autowiredprivate Student student;@RequestMapping("/getStudent")public String getStudent(){return student.toString();}
}
3. 配置集合
dbtypes:name:- mysql- sqlserver- db2
读取集合也是用 @ConfigrationProperties 注解;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;import java.util.List;@Data
@Configuration
@ConfigurationProperties(prefix = "dbtypes")
public class DbTypes {private List<String> name;
}
import com.example.demo.model.DbTypes;
import com.example.demo.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/config")
public class ConfigController {@Autowiredprivate DbTypes dbTypes;@RequestMapping("/dbNames")public String dbNames(){return dbTypes.getName().toString();}
}
4. 配置 Map
maptypes:map:key1: value1key2: value2key3: value3
Map 的读取和对象的读取一样,也是使用 @ConfigrationProperties 注解实现;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;import java.util.Map;@Data
@Configuration
@ConfigurationProperties(prefix = "maptypes")
public class MapConfig {private Map<String, String> map;
}
import com.example.demo.model.MapConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;@RestController
@RequestMapping("/config")
public class ConfigController {@Autowiredprivate MapConfig mapConfig;@RequestMapping("/getMap")public String getMap(){return mapConfig.getMap().toString();}
}
.yml 配置文件优点:
- 可读性高,写法简单,易于理解 ;
- 支持更多的数据类型,可以简单表达对象,数组,List,Map 等;
- 支持更多的变成语言,可以在 Golang,Python,Ruby,JavaScript 中使用;
.yml 配置文件的缺点:
- 不适合写复杂的配置文件;
二、日志
日志主要用于发现问题,分析问题,定位问题,除此之外,还用于系统监控,数据统计,推荐排序,日志审计等;
1. Slf4j
SpringBoot 内置了 Slf4j 日志框架,可以在程序中调用输入日志;
在程序中获取日志对象,需要使用日志工厂;Logger 对象是 Slf4j 框架使用工厂模式创建的;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/log")
public class LogController {private Logger logger = LoggerFactory.getLogger(LogController.class);@RequestMapping("/print")public String print(){logger.error("==========ERROR==========");logger.warn("==========WARN==========");logger.info("==========Info==========");logger.debug("==========DEBUG==========");logger.trace("==========TRACE==========");return "SUCCESS";}
}
Slf4j 并不是日志的真正实现,而是一个抽象层,对日志框架制定的规范标准接口,因此不能单独使用,必须配合具体的日志框架使用;
Slf4j 是典型的外观模式的应用;
外观模式:提供统一的接口,用来访问子系统的一群接口;通过定义一个高层接口,让子系统更容易使用;
门面模式分为外观角色和子系统角色;
外观角色(Facade):是系统对外的统一接口;
子系统角色(Subsystem):可以有一个或者多个子系统,子系统并不知道外观角色的存在,对于子系统,外观角色只是一个客户端;
门面模式的优点:
- 减少了系统的相互依赖,实现了客户端和子系统的耦合关系,使得子系统变化不会影响到客户端;
- 提高了灵活性,简化了客户端调用子系统的难度;客户端无需关心子系统的实现方式,只需要和门面对象交互即可;
- 提高了安全性,可以灵活设定访问权限;不在门面对象中开通方法,就无法访问;
2. 日志格式
分别为:时间日期,日志级别,进程 ID,应用名,线程名,Logger 名,日志内容;
日志级别:
fatal:致命错误;
error:错误信息,级别较高,但不影响系统运行;
warn:警告信息,不影响使用,但需要注意;
info:普通信息,记录正常运行时的一些信息;
debug:调试信息,需要调试时的关键信息打印;
trace:追踪信息,比 Debug 粒度更细的信息;
3. 日志配置
日志级别配置:logging.level
日志持久化:logging.file.name,logging.file.path
日志文件分割:
文件命名格式:logging.logback.rollingpolicy.file-name-pattern
文件大小分割:logging.logback.rollingpolicy.max-file-size
# 日志 logging: # 日志级别level:root: info # 日志持久化file:name: logger/captcha.log # 日志分割logback:rollingpolicy:file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gzmax-file-size: 10MB
控制台日志格式:
logging.pattern.console:
%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM dd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN: %5p})
%clr(${PID:- }){magenta}
%clr(---){faint}
%clr([%15.15t]) {faint}
%clr(%-40.40logger{39}){cyan}
%clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
日志文件的日志格式:
%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM dd'T'HH:mm:ss.SSSXXX}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- }--- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
%clr:日志颜色;
%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}:日期和时间,精确到毫秒;
%5p:显示日志级别;
%t:线程名;
%c:类的全限定名;
%M:方法名;
%L:行号;
%thread:线程名;
%m/%msg:显示输出消息;
%n:换行符;
%5 若字符长度小于5,则右边用空格填充;
%-5 若字符长度小于5,则左边用空格填充;
%.15 字符⻓度超过15,截去多余字符;
%15.15 若字符⻓度⼩于15,则右边用空格填充.若字符长度超 过15,截去多余字符;
4. 日志输出
可以使用 @Slf4j 注解,使用 log 对象输出日志;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@Slf4j
@RestController
@RequestMapping("/log2")
public class LogController2 {@RequestMapping("/print")public String print(){log.error("==========ERROR==========");log.warn("==========WARN==========");log.info("==========Info==========");log.debug("==========DEBUG==========");log.trace("==========TRACE==========");return "SUCCESS";}
}