Spring Boot项目的重要数据都是在配置文件中设置的。配置文件可以包含各种属性和值,用于定义应用程序的各种配置选项,如数据库连接信息、日志级别、缓存策略等。
配置文件把配置信息与代码分离。就拿数据库连接来说,程序员调试运行时连接的数据库肯定和正式发布连接的数据库是不同的,假如直接写死在代码中,后续如果出现问题也没有办法修改。但是配置文件是可修改的,有哪些不合适的直接在配置文件中修改即可,无需重新编译和部署代码。
此外,配置文件具有很高的灵活性。应用程序在不同的环境下(如开发、测试、生产)可能有不同的部署需求,例如在开发环境下,使用8080作为端口号没问题,但在生产环境下就可能出现冲突。
除此之外,配置文件还可以保证安全性(某些敏感信息如数据库密码放在配置文件中可以更好地保护)等。
配置文件主要有.properties和.yml两种
.properties属于默认配置文件,当我们新建一个Spring Boot项目时,在resources目录下会自动生成一个application.properties配置文件:
当同一个项目中同时有.properties和.yml两种配置文件时,并不会发生冲突,但如果两个配置文件配置了相同的属性,则以.properties配置为准。
properties是以键值对的形式配置的:
# 设置端口号
server.port=8181
# 连接数据库(要添加mysql依赖)
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
除了设置这些属性,还可以设置自定义属性,例如设置"myTest=zhangsan"
yml是YAML(Yet Another Markup Language) 的缩写,即另一种标记语言。
yml通过"key: value"的形式来设置属性(注意冒号与value之间要有一个空格):
# 设置端口号
server:
port: 9090
# 连接数据库
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8
username: root
password: root
从写法上来看,可以发现:
在代码中读取配置文件中的内容,无论properties还是yml,都需要使用@Value注解:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody
public class TestController {
// 前面properties中设置了myTest=zhangsan
@Value("${myTest}")// 这里的${}是必要的
public String myTest;
@RequestMapping("/hi")// 设置路由
public String hi() {
return "你好," + myTest;
}
}
启动服务器后通过浏览器访问hi路由可以得到:
在日志中也可以发现:
这里的端口号也被改为了8181(properties配置文件)而不是9090(yml配置文件)
当然一般情况下,一个项目不会出现既有properties又有yml的情况。
前面提到不同环境的配置可能不同,那就需要多个配置文件。例如application-dev.yml配置文件和application-prod.yml配置文件(注意任何配置文件都要以application为开头,无论是properties还是yml):
application-dev.yml文件内容:
# 开发环境端口号
server:
port: 8181
application-prod.yml文件内容:
# 生产环境端口号
server:
port: 8282
至于使用哪个配置文件的端口号,则需要在application.yml文件中添加spring.profiles.active属性:
例如选用生产环境:
spring:
profiles:
#选用生产环境
active: prod
再次运行可以发现端口号已经设置为了生产环境的端口号(8282):
日志是用来输出信息的,每次项目启动,控制台就会自动打印一些日志信息:
那么日志有什么用呢?
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {
//获取日志对象
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@RequestMapping("/test")
public void test() {
// Logger共提供了五种日志
logger.trace("trace日志");
logger.debug("debug日志");
logger.info("info日志");
logger.warn("warn日志");
logger.error("error日志");
}
}
Spring Boot 内置的日志框架是slf4j,但slf4j并不会真正地实现日志,实际上slf4j只是一个中介,日志的实现另有其人。由于日志的实现并不算很难,有多个公司实现了日志,但他们的写法不会完全一样,假如使用A公司的日志写法,万一A公司突然出现了问题,就需要紧急替换日志的写法为B公司。像这样的人工替换是很麻烦的。于是就使用slf4j统一写法,再内部替换成和它对接的实际框架(Spring Boot默认使用logback框架)。
写好代码以后,在浏览器上访问test:
在控制台上可以发现打印了info日志、warn日志和error日志:
左数第二个属性就是日志级别名,最右边就是日志信息。
通过前面的方法来打印日志信息看起来是比较麻烦的,为了简化操作,可以添加lombok依赖,然后使用注解的方式来获取日志对象:
import lombok.extern.slf4j.Slf4j;// 导入对应包
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody
@RequestMapping("/user")
@Slf4j// 使用@Slf4j来代替那一长串来获取Logger对象
public class UserController {
@RequestMapping("/test")
public void test() {
// 使用注解就不用在像上面这样获取了,可以直接使用log对象
// 注解生成的对象名就是log
log.trace("trace日志");
log.debug("debug日志");
log.info("info日志");
log.warn("warn日志");
log.error("error日志");
}
}
lombok除了可以简化获取日志的操作外,还可以通过注解的方式帮助生成Getter和Setter方法、重写toString、hashCode、equals等方法,非常之方便。
lombok的实现原理
lombok的实现原理其实就是在编译阶段把注解替换成相应的代码填进去。
可以在服务器运行后查看target中的编译过的文件:
由此可得,lombok的实现并不高深。
虽然日志成功打印了,但只打印了三个,明明之前写了五个,那前两个日志呢?这就涉及到日志的级别问题了。
日志的级别由低到高分为六种:trace、debug、info、warn、error、fatal
而Spring Boot的默认日志级别是info,因此只能打印info日志或比info级别更高的日志。
前面写了五种日志的级别,没有fatal,这是因为一旦发生fatal级别的错误,程序就会立即退出执行。
在配置文件中设置logging.level属性即可修改日志级别,例如:
# 设置根路径的日志级别为debug
logging:
level:
root: debug
再次重启服务器并打开浏览器访问就会发现多了很多的日志,同时自定义的日志也可以多打印debug日志的内容了:
假如只关注自定义日志的信息又该如何操作呢:
# 设置根路径的日志级别为warn设置UserController类的日志级别为trace
logging:
level:
root: warn
# 前面是包名,最后是类名
com.example.demo.UserController: trace
重启服务器可以发现那些默认的日志信息不见了,同时也可以打印自定义的trace日志了:
(上面那个logo不是以日志的形式打印的,而是通过println函数直接输出到控制台上的)
仅仅把日志打印到控制台上显然是不够合理的,因为每次重启服务器控制台上的内容都会消失。为了日志可以长久地保存下来,需要在配置文件中指定存储的路径或文件名:
指定path属性默认日志名为spring.log:
logging:
file:
#任意指定路径即可
path: D:\\
重启服务器后就可以在对应路径找到log文件:
访问路由后再打开日志就会发现日志中已经有内容了:
后续每次访问一次都会添加相应的日志进来,重启服务器也不会消失:
设置name属性可以修改日志的默认名:
logging:
file:
# 设置日志名为spring-log,前面可以加路径名(不加默认放到项目目录下)
name: spring-log
level:
root: warn
com.example.demo.UserController: trace