日志是程序的重要组成部分,最常见的,当程序报错时,打开控制台就能看到报错信息,这些就是日志.通过日志,可以看到错误信息,找到错误原因
除了发现和定位问题,日志还能实现这些实用的功能:
记录用户登录日志,分析用户是正常登录还是恶意破解用户(用来分析用户的行为)
记录系统的操作日志,方便数据恢复和定位操作人
记录程序时间,为优化程序提供数据支持
当我们启动SpringBoot项目时,控制台就会出现系统打印的日志
这是SpringBoot内置了日志框架,才能输出日志
默认情况下,输出的日志并非是开发者自定义的,那么开发者如何自定义日志呢?
当项目重启,控制台就会输出新的日志,那么旧的日志是不能被保存的,如何让日志持久保存呢?
常见的日志框架
SpringBoot内置的日志框架:Slf4j 日志实现是:logback
我们并没有在依赖中引入,是因为SpringBoot已经内置了
所以我们可以在程序中直接调用Slf4j直接输出日志
自定义日志实现(尽可能设施8080之后的端口,端口太小可能启动失败!)
结果:
控制台:
可以看到:SpringBoot输出的日志非常详细,可以用来定位问题位置
我们打印的没有时间,位置等等.无法精确定位到一个问题,并且不支持持久化,不能保存
使用SpringBoot日志打印分为两步
1.得到日志对象
参数是类类型
这里传参,就决定了日志打印时,打印的类的信息
2.使用对象的方法打印日志
上述只出现了三个自定义打印的日志信息:info,error,warn,和日志级别有关
info是默认的日志级别,日志打印只能打印比默认级别更高的日志信息,所以trace和debug没打印
这里有日志时间,级别,日志线程的id,日志的线程名,简化包名加完整类名,自定义信息
@Controller
@ResponseBody
public class UserController {
//1.得到日志对象
/*
每个日志对象只归属于一个类,是类私有的
日志打印时需要输出:是在哪个类中的日志
修饰符为private,静态方法可直接调用
不期望被修改,加上final
*/
private static final Logger log = LoggerFactory.getLogger(UserController.class);
//2.打印日志
@RequestMapping("/hi")
public String hi(){
//System.out.println("打印日志");
log.trace("i'm trace");
log.debug("i'm debug");
log.info("i'm info");
log.error("i'm error");
log.warn("i'm warn");
return "hi world -> ";
}
}
使用另一个注解也能完成:@RestContrller ,更加简单
打印的日志是没有包名的,如果一个项目其它包中有相同名称的类,就分不清楚了
自定义日志推荐使用参数为类类型的,信息更全
日志级别可以筛选出重要的信息,设置为error,就能看到程序的报错日志,普通的调试日志和业务日至就忽略了
日志级别可以控制不同环境下,一个程序是否需要打印日志,开发时需要详尽的日志帮助开发;生产环境下需要尽可能少的日志信息,保证程序的性能和安全性
日志级别从低到高分为:
trace:级别最低
debug:需要调试的时候的关键信息打印
info:(默认日志级别)普通信息打印
warn:警告,不影响使用,但需要注意问题
error:错误信息,级别较高
fatal:致命的,代码异常导致程序退出
如何设置日志默认级别?
在配置文件中,设置 logging.level 即可
这是yml的写法:
重启项目,访问 UserController 的 hi 方法
上述日志都是输出在控制台的,生产环境下需要保存日志,以便出问题时追溯问题,把日志保存下来的过程叫做日志持久化
进行日志持久化,需要在配置文件中指定日志的存储目录或者指定日志保存文件名之后,Spring Boot就会将控制台的日志写到相应目录或文件下
记得在主配置文件中设置下运行环境
日志文件一旦产生,文件及其内容就会永久保存,不会出现文件或内容丢失,无论任何操作都会保持以上特性
没有设置过路径,会默认保存在项目路径下
路径+名称可以实现在某个路径下保存日志
日志是中文需要设置字符集为utf8
当日志文件超过10m,就会重新创建一个新的日志文件,所以不用担心文件时间太长积累数据过大
也可以通过配置修改文件存储上限(loggin.logback.rollingpolicy.max-file-size)
生产级别日志分类:
1.程序运行日志,存放在文件中
2.业务日志,存放到数据库
步骤:
1.添加lombok支持
快速添加springboot的依赖方式:
1.安装插件,重启IDEA
2.pom.xml中右键Generate
reload一下,添加lombok
2.使用@Slf4j注解输出日志
这种方法就省略了我们自己获取日志对象的过程,非常简便!
之前已经介绍和使用了lombok
Lombok能通过注解的方式,在编译时自动为属性生成构造函数、getter/setter、equals、hashcode、toString等方法。奇妙之处在于源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。省去了手动重建这些代码的麻烦,使代码看起来更简洁明了
原理就是在编译时,根据语义生成相应的字节码文件,是一个编译期框架
这么多注解,可以使用一个聚合注解代替:@Data
@Data
注解在类上,会为类的所有属性自动生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。@Value
注解和@Data
类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法
@NoArgsConstructor
、@RequiredArgsConstructor
和@AllArgsConstructor
三个注解都是用在类上的,第一个和第三个都很好理解,为该类产生无参的构造方法和包含所有参数的构造方法,第二个注解则使用类中所有带有@NonNull注解的或者带有final修饰的成员变量生成对应的构造方法,当然,成员变量都是非静态的,另外,如果类中含有final修饰的成员变量,是无法使用@NoArgsConstructor注解的