1. Spring Boot 配置文件
我们知道, 当我们创建一个Spring Boot项目之后, 就已经有了配置文件存在于目录结构中.
1. 配置文件作用
整个项目中所有重要的数据都是在配置文件中配置的,比如:
- 数据库的连接信息 (包含用户名和密码的设置) ;
- 项目的启动端口;
- 第三方系统的调用秘钥等信息;
- 用于发现和定位问题的普通日志和异常日志等
想象一下如果没有配置信息,那么 Spring Boot 项目就不能连接和操作数据库,甚至是不能保存可以用于排查问题的关键日志,所以配置文件的作用是非常重要的。
2. 配置文件的格式
Spring Boot 配置文件主要分为以下两种格式:
- .properties
- .yml
特殊说明:
- 两个配置文件从功能上来讲是可以同时存在的,但是企业中通常会规定使用某一种格式的配置文件。
- 如果同一个配置出现在两种格式的配置文件中的话,那么以 properties 为主。
如果配置文件中出现了同样的配置,比如 properties 和 yml 中都配置了"server.port", 那么这个时候会以 properties 中的配置为主,也就是 properties 配置文件的优先级最高,但加载完.properties 文件之后,也会加载 .yml 文件的配置信息
3. properties配置文件说明
properties 配置文件是最早期的配置文件格式,也是创建 Spring Boot 项目默认的配置文件.
3.1 properties基本语法
properties 是以键值的形式配置的,key 和 value 之间是以“=”连接的,如:
# 配置项目端口号
server.port=8084
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
注: 配置文件中使用“#”来添加注释信息
配置项分类:
- 系统配置项,比如 server.port/spring.datasource.url... -> 系统
- 用户自定义配置 (非系统配置项) -> key 用户自定义
IDEA默认这个配置文件不支持中文, 也就是说如果写了中文的注释, 下次启动就变成乱码了. 针对这种情况, 可以在IDEA中Settings搜索file encoding进行设置.(注意"新建项目"也同时要设置)
3.2 读取配置文件
如果在项目中,想要主动的读取配置文件中的内容,可以使用 @Value 注解来实现.
@Value 注解使用“${}”的格式读取,如下代码所示:
package com.example.demo.component;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class ReadYml {
@Value("${server.port}")
private String port;
@PostConstruct
public void postConstruct() {
System.out.println("Read YML, port: " + port);
}
}
最终执行效果:
@Component 在Spring Boot 启动时候会注入到框架中,注入到框架中时会执行 @PostConstruct初始化方法,这个时候就能读取到配置信息了。
3.3 properties优缺点分析
优点:
- 系统默认的配置文件;
- properties 配置项的优先级比 yml 高
- 格式简单、不容易出错。
缺点:
写法比较冗余。
4. yml配置文件说明
yml是 YAML 是缩写,它的全称 Yet Another Markup Language 翻译成中文就是“另一种标记语”
yml优点分析
- yml 是一个可读性高,写法简单、易于理解,它的语法和 JSON 语言类似。
- yml 支持更多的数据类型,它可以简单表达清单 (数组)、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件等
- yml 支持更多的编程语言,它不止是 Java 中可以使用在 Golang、PHP、Python、Ruby、JavaScript、Perl 中。
4.1 yml基本语法
yml 是树形结构的配置文件,它的基础语法是“key: value”,注意 key 和 value 之间使用英文冒汗加空格的方式组成的,其中的空格不可省略。
yml示例如下:
server:
port: 9999
使用yml连接数据库
yml使用示例:
spring:
datasource:
url: jdbc:mysql://127.0.0.0:3306/dbname?characterEncoding=utf8
username: root
password: root
4.2 yml使用进阶
4.2.1 yml配置不同数据类型及null
# 字符串
string.value: Hello
# 布尔值,true或false
boolean.value: true
boolean.value1: false
# 整数
int.value: 10
int.value1: 0b1010_0111_0100_1010_1110 # ⼆进制
# 浮点数
float.value: 3.14159
float.value1: 314159e-5 # 科学计数法
# Null,~代表null
null.value: ~
4.2.1.1 yml配置读取
yml 读取配置的方式和 properties 相同, 使用@Value注解即可, 实现代码如下:
package com.example.demo.component;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class ReadYml {
@Value("${string:hello}")
private String hello;
@PostConstruct
public void postConstruct() {
System.out.println("Read YML, hello: " + hello);
}
}
4.2.1.2 注意事项: value值加单双引号
字符串默认不用加上单引号或者双引号,如果加英文的单双引号可以表示特殊的含义。
尝试在 application.yml 中配置如下信息:
string:
str1: Hello \n Spring Boot.
str2: 'Hello \n Spring Boot.'
str3: "Hello \n Spring Boot."
package com.example.demo.component;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class ReadYml3 {
@Value("${string.str1}")
private String str1;
@Value("${string.str2}")
private String str2;
@Value("${string.str3}")
private String str3;
@PostConstruct
public void postConstruct() {
System.out.println("string.str1: " + str1);
System.out.println("string.str1: " + str2);
System.out.println("string.str1: " + str3);
}
}
从上述结果可以看出:
- 字符串默认不用加上单引号或者双引号
- 单引号会转义特殊字符,特殊字符最终只是一个普通的字符串数据。
- 双引号不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思.
4.2.2 配置对象
student:
id: 1
name: 张三
age: 18
package com.example.demo.entity;
@ConfigurationProperties("student")
@Component
@Setter
@Getter
@ToString
public class StudentComponent {
private int id;
private String name;
private int age;
}
注意:以上代码中的 getter 和 setter 方法不能省略.(本文使用lombok, 所以省略)
package com.example.demo.component;
import com.example.demo.entity.StudentComponent;
@Component
public class ReadYml4 {
@Autowired
private StudentComponent studentComponent;
@PostConstruct
public void postConstruct() {
System.out.println(studentComponent);
}
}
查看更多的系统配置项
想要查看 Spring Boot 更多系统配置项,访问官网: Common Application Properties
5. properties VS yml
- properties 是以 key=value 的形式配置的键值类型的配置文件,而 yml 使用的是类似json 格式的树形配置方式进行配置的,yml层级之间使用换行缩进的方式配置,key 和 value 之间使用“:”英文冒号加空格的方式设置,并且空格不可省略
- properties 为早期并且默认的配置文件格式,但其配置存在一定的几余数据,使用 yml可以很好的解决数据几余的问题。
- yml 通用性更好,支持更多语言,如 Java、Go、Python 等,如果是云服务器开发,可以使用一份配置文件作为 Java 和Go的共同配置文件
- yml支持更多的数据类型
2. Spring Boot日志文件
1. 日志的作用
- 记录错误日志和警告日志(发现和定位问题)
- 记录用户登录日志,方便分析用户是正常登录还是恶意破解用户
- 记录系统的操作日志,方便数据恢复和定位操作人。
- 记录程序的执行时间,方便为以后优化程序提供数据支持。
2. 日志的使用
Spring Boot 内置了日志框架, 在启动的时候默认就有日志输出,如下图所示:
2.1 Spring Boot内置日志框架
下图是常用的一个日志框架, 其中SLF4J和logback是Spring Boot所内置的日志框架.
SLF4J是门面模式, 它类似于代理模式, 是设计模式的一种, 就是来了用户之后, 它不是直接具体去操作某一个日志框架, 而是由某一个代理(门面)先行处理.
也就是用户在写日志时, 首先请求会先来到门面模式SLF4J, 然后SLF4J再根据我们系统的配置决定我们要调用的具体的框架是什么.
类似于生活中买房子先通过中介(SLF4J), 中介能够根据我们的诉求来匹配最合适的房源.
2.2 自定义日志打印
Spring Boot自定义日志打印的步骤:
- 得到日志对象
- 使用日志对象提供的方法打印日志.
2.2.1 得到日志对象
在程序中获取日志对象需要使用日志工厂 LoggerFactory,如下代码所示:
// 1. 得到日志对象
private static final Logger logger = LoggerFactory.getLogger(TestController.class);
注意: Logger 对象是属于 org.slf4j 包下的,不要导入错包.
2.2.2 使用日志对象打印日志
日志对象的打印方法有很多种,我们可以先使用 info()方法来输出日志,如下代码所示:
logger.info("--------------打印日志------------");
2.2.3 日志格式说明
3. 日志级别
3.1 日志级别的作用
- 日志级别可以帮你筛选出重要的信息,比如设置日志级别为 error,那么就可以只看程序的报错日志了,对于普通的调试日志和业务日志就可以忽略了,从而节省开发者信息筛选的时间。
- 日志级别可以控制不同环境下,一个程序是否需要打印日志,如开发环境我们需要很详细的信息而生产环境为了保证性能和安全性就会输入尽量少的日志,而通过日志的级别就可以实现此需求.
3.2 日志级别的分类与使用
日志的级别分为:
- trace: 微量,少许的意思,级别最低;
- debug: 需要调试时候的关键信息打印
- info: 普通的打印信息(默认日志级别)
- warn: 警告,不影响使用,但需要注意的问题;
- error: 错误信息,级别较高的错误日志信息;
- fatal:致命的,因为代码异常导致程序退出执行的事件
日志级别的顺序:
越往上接收到的消息就越少,如设置了 warn 就只能收到 warn、error、fatal 级别的日志了
日志级别的设置
在配置文件中设置:
logging:
level:
root: error
com:
example:
demo:
controller: trace
默认日志输出级别
清除掉配置文件中的日志设置,观察控制台输入的日志级别得到以下结论,日志的输出级别,默认是 info.
4. 日志持久化
以上的日志都是输出在控制台上的,然而在生产环境上咱们需要将日志保存下来,以便出现问题之后追溯问题,把日志保存下来的过程就叫做持久化。
想要将日志进行持久化,只需要在配置文件中指定日志的存储目录或者是指定日志保存文件名之后Spring Boot 就会将控制台的日志写到相应的目录或文件下了。
注: 日志文件一旦产生,那么日志文件及其内容就会永久的保存,不会出现文件或内容的丢失,无论任何操作都会保持其以上特性。
配置日志文件的保存路径:
logging:
file:
path: D:\LearningSoftware
配置日志文件的文件名:
logging:
file:
name: D:\\springboot.log
根据业务场景来订, 生产级别日志分类:
1.程序运行日志(存放在文件中)
2.业务日志(存放到数据库)
6. 更简单的日志输出 - lombok
每次都使用 LoggerFactory.getLogger(xxx.class)很繁琐,且每个类都添加一遍,也很麻烦,这里讲一种更好用的日志输出方式,使用 lombok 来更简单的输出
1.添加 lombok 框架支持
2.使用 @slf4j注解输出日志。
6.1 添加 lombok 依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Spring Boot是默认添加的
6.2 输出日志
package com.example.demo.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class LogController {
@RequestMapping("/log/sayhi")
public String sayhi(){
log.info("log的info");
return "log say hi";
}
}
注意:使用 @SIf4j 注解,在程序中使用 log 对象即可输入志,并且只能使用 log 对象才能输出, 这是lombok 提供的对象名。
6.3 lombok更多注解说明
基本注解
注解 | 作用 |
---|---|
@Getter | 自动添加getter 方法 |
@Setter | 自动添加setter方法 |
@ToString | 自动添加 toString 方法 |
@EqualsAndHashCode | 自动添加 equals 和hashCode 方法 |
@NoArgsConstructor | 自动添加无参构造方法 |
@AllArgsConstructor | 自动添加全属性构造方法,顺序按照属性的定义顺序 |
@NonNull | 属性不能为null |
@RequiredArgsConstructor | 自动添加必需属性的构造方法,final + @NonNull 的属性为必需 |
组合注解
注解 | 作用 |
---|---|
@Data | @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor + @NoArgsConstructor |
日志注解
注解 | 作用 |
---|---|
@SIf4j | 添加一个名为 log的日志,使用 slf4j |
6.4 lombok原理
lombok能够打印日志的原理就在于它所应用的是在编译的时候自动添加得到日志对象的代码, 可以在target中看到:
Java程序运行原理:
lombok的作用如下: