目录
1.1.控制台打印日志,用于发现,排除,定位问题(程序属性)。
1.2.记录用户登录日志,方便分析追踪用户是正常登录还是恶意破解程序(业务属性)。
1.3.记录系统的操作日志,方便数据恢复和定位操作人(业务属性)。
1.4.记录程序的执行时间日志,方便为以后优化程序提供数据支持(业务属性)。
4.1.2.日志级别可以控制不同环境下一个程序是否需要打印日志。
4.2.1.trace:跟踪日志,微量,少许的意思,级别最低。
4.2.6.fatal:致命的,因为代码异常导致程序退出执行的事件。自己不能定义,不能打印,系统会自动打印。
4.3.3.全局日志级别设置和局部日志级别设置并存时局部日志级别设置优先
1.日志的作用
日志是程序的重要组成部分,它提供了非常实用的功能:
1.1.控制台打印日志,用于发现,排除,定位问题(程序属性)。
调试阶段日志默认打印到控制台,不持久化;但做项目上线时要持久化,不能只打印到控制台。
1.2.记录用户登录日志,方便分析追踪用户是正常登录还是恶意破解程序(业务属性)。
可以记录用户的IP,【从Request对象里拿到,http协议是基于TCP/IP协议(有目的端口号,源端口号,源IP,目标IP)】,登录次数等,如果这个用户IP一段时间内有大量的登录试错,就可知道其为恶意用户,就可以封掉这个IP地址,再去登录时直接显示非法登录。
1.3.记录系统的操作日志,方便数据恢复和定位操作人(业务属性)。
如教务系统里所有老师都有调班的权限,一班的学生张三错误地被调到了二班。恢复数据时直接查看最新日志(有操作之前的信息和操作之后的信息)将张三调整回原班级即可,也能知道是哪个老师做的进行惩罚培训。
1.4.记录程序的执行时间日志,方便为以后优化程序提供数据支持(业务属性)。
可以知道程序中所有方法执行所用时间,把执行时间长的方法做定期优化,优化用户体验。
⽇志真实使⽤案例: 【关键节点上的关键数据⽇志记录】
学生在注册时不仅要在教务系统添加⼀条⽤户记录,同时也会给论坛添加⼀条⼀模⼀样的⽤户记录,这样做的⽬的是为了实现⼀次注册,多处使⽤,不需要⽤户在两边系统注册,等于在程序中以极低的成本实现的⽤户数据的同步。
但这样设计有⼀个致命的问题,因为⽤户在注册的时候需要同步注册到论坛系统,⽤户在教务系统注册信息的时候,如果论坛挂了,那么⽤户的注册⾏为就会失败?
最简单的解决⽅案,教务系统在注册的时候,不管论坛是否注册成功,都给⽤户返回成功,那这个时候如果论坛注册失败了怎么办?⾮常简单,记录⼀下⽇志,等论坛恢复正常之后,把⽇志给论坛的管理⼈员,让他⼿动将注册失败的⽤户同步到论坛系统,这样就最低成本的解决了问题。这就是⽇志的重要作⽤。
2.日志怎么用?
Spring Boot项目在启动时默认就有控制台日志信息输出:
- Spring Boot 内置了日志框架(不然也输出不了日志)。
- 默认情况下,输出的日志是系统日志,并非是开发者定义和打印的,那开发者怎么在程序中⾃定义打印日志呢? (当然不能使用sout输出语句,因为很多日志的关键信息sout语句拿不到;需要屏蔽掉一些日志时sout语句做不到)
- 日志默认是打印在控制台上的,而控制台的日志(在内存中)是不能被保存的,那么怎么把日志永久的保存下来(存到硬盘中)呢?
3.自定义日志打印(内容加格式)
3.1.在程序中得到日志对象
需要使用日志工厂LoggerFactory,日志工厂需要将每个类的类型传递进去,这样才能知道日志的归属类,才能更方便直观地定位到问题类。
// 1.得到⽇志对象
private static Logger logger = LoggerFactory.getLogger(类名.class);
//static表示在所有的方法中可以直接去用这个对象
注:Logger对象是属于org.slf4j包下的,不要导入错包。(Spring Boot 中内置了日志框架 Slf4j,所以可以直接在程序中调⽤ slf4j 来输出⽇志)
PS:常见的日志框架说明
类似JDBC。
3.2.使用日志对象的相关语法输出要打印的日志内容
日志对象的打印方法有很多种,先使用info()方法来输出日志。
// 2.使⽤⽇志对象打印⽇志
logger.info("要输出⽇志的内容");
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
public class UserController {
//1.得到日志对象
private static Logger logger = LoggerFactory.getLogger(UserController.class);
@RequestMapping("/index")
@ResponseBody //返回一个非静态页面的数据
public void loggerTest() {
//2.打印日志
logger.info("要输出日志的内容");
}
}
啥都不打印
PS:日志格式说明
4.日志级别
4.1.日志级别的作用
4.1.1.日志级别可以帮助筛选出符合目标的日志信息。
比如设置日志级别为error,那么就可以只看程序的报错日志了,对于普通的调试日志和业务日志可忽略,从而节省开发者筛选信息的时间。
4.1.2.日志级别可以控制不同环境下一个程序是否需要打印日志。
比如开发环境需要很详细的信息,而生产环境为了保证性能和安全性,就会输入尽量少的日志。而通过日志级别就能实现此需求。
试想每个员⼯的⽇常⼯作和琐碎的信息都要反馈给老板吗?⼀定不会,因为老板根本没有那么多时间。
于是就有了组织架构,⽽组织架构就会分级,有很多的级别设置,如下图所示:
![]()
有了组织架构之后,就可以逐级别汇报消息了,例如:组员汇报给组⻓;组⻓汇报给研发⼀组;研发⼀组汇报给 Java 研发,等等依次进⾏汇报。
4.2.日志级别的分类
4.2.1.trace:跟踪日志,微量,少许的意思,级别最低。
4.2.2.debug:需要调试时候的关键信息打印。
4.2.3.info:普通的打印信息,默认级别。
4.2.4.warn:警告,不影响使用,但需要注意的问题。
4.2.5.error:错误信息,级别较高的错误日志信息。
4.2.6.fatal:致命的,因为代码异常导致程序退出执行的事件。自己不能定义,不能打印,系统会自动打印。
PS:日志级别的顺序:
日志级别越高接收的消息越少。
如果设置了某个日志级别(在配置文件中),则只能打印看到当前设置的日志级别的信息和比它级别高的日志级别的信息,比它级别低的日志级别做了屏蔽,看不到。
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 public class UserController { //1.得到日志对象 private static Logger logger = LoggerFactory.getLogger(UserController.class); @RequestMapping("/sayhi") @ResponseBody //返回一个非静态页面的数据 public String sayHi(String name){ //2.打印日志 logger.trace("我是trace."); logger.debug("我是debug."); logger.info("我是info."); logger.warn("我是warn."); logger.error("我是error."); return "你好:" + name; } }
name没有传值。
name传值。
默认级别info,只会打印它及比它级别更高的日志。
4.3.日志级别的设置
日志级别配置只需要在配置文件中设置"logging.level"配置项即可:
4.3.1.设置项目中所有目录的日志级别(默认的)
root表示根目录/所有目录。只有当某个目录没有设置明确的日志输出级别时,才会使用默认的日志级别。(root)
①yml格式
logging:
level:
root: error
②properties格式
logging.level.root=error
二者同时存在会以properties中的设置为主。
4.3.2.精确化设置某个目录下的日志输出级别
"logging.level"下面是java源代码文件夹 下的目录。
# 设置controller目录的日志级别
logging.level.com.example.demo.controller=warn
4.3.3.全局日志级别设置和局部日志级别设置并存时局部日志级别设置优先
5.日志持久化:将日志永久保存到磁盘上
以上的日志都是输出在控制台上(存在内存中)稍纵即逝的,而在生产环境上需要将日志永久保存下来(存在磁盘中)以便出现问题之后进行追溯。
想要将日志进行持久化,只需要在配置文件中指定日志的存储目录或者是在配置文件中指定日志的保存文件名,那么Spring Boot就会将控制台的日志写到相应的目录或文件夹下(是追加,不是覆盖)。
5.1.在配置文件中配置日志文件的保存路径
在写路径时注意在properties格式的配置文件中(盘符名称等大小写都可):
//写法Windows不行,Linux行
E:\Users\Data
//Windows行
e:\\Users\\Data
//Windows行
E:\\Users\\Data\\
//Windows行,Linux行
e:/Users/Data
//注意:
//表示在Data文件夹下
E:/Users/Data/
//表示在Users文件夹下,名称为Data
E:/Users/Data
在yml格式的配置文件中上述所有写法都可以。
①yml格式
# 设置⽇志⽂件的⽬录
logging:
file:
path: E:\Users\Data
②properties格式
# 设置日志的保存目录
logging.file.path=E:\\Users\\Data
打印前:
打印后:
打开内容一样:
5.2.在配置文件中配置日志文件的保存文件名
默认保存的日志起名为spring.log,也可以自定义日志名称。
可以写全路径的名称(大多数情况),也可以直接只写一个名字(默认是在当前项目的目录下创建日志)。
①yml格式
# 设置⽇志⽂件的⽂件名
logging:
file:
name: e:/Users/Data/springboot.log
②properties格式
# 设置日志的保存名称
logging.file.name=e:/users/data/springboot.log
打印前:
打印后:
打开内容一样:
6.更简单的日志输出——lombok
每次都使用LoggerFactory.getLogger(xxx.class)很繁琐,且每个类都添加一遍也很麻烦。那么来看lombok实现更简单的日志输出。
6.1.添加lombok框架依赖支持
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
两种方式:
①创建项目时就将其添加进来。
②项目已经建好时需要添加->手动添加。
第一次会没有Edit Starters插件,需要先去安装。
记得点击重新导入。
6.2.使用@Slf4j注解(严格注意大小写)输出日志
使用@Slf4j注解,在程序中使用log对象即可输入日志,并且只能用log对象才能输出,这是lombok提供的对象名。
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@Slf4j //1.相当于通过loggerfactory获取日志对象
public class StudentController {
@RequestMapping("/sayhi2")
public String sayHi2() {
//2.使用日志对象打印日志
log.info("stuent里面的info"); //规定只能用log
log.warn("stuent里面的warn");
log.error("stuent里面的error");
return "你好,student.";
}
}

6.3.lombok原理解释
缺点:无法调试;优点:更简单。
lombok框架只在编译阶段有用,在其他阶段都没用。
lombok能够打印⽇志的密码就在 target ⽬录⾥⾯,target 为项⽬最终执⾏的代码,查看 target ⽬录如下:
打开target下的StudentController类(字节码)为啥看起来像源代码,而不是二进制文件呢?因为IDEA编译器将二进制字节码处理转换成了我们能看懂的源代码,是包装出来虚的东西,真正的内容是一大串二进制数据。

Java程序的运行原理:(JVM不认识.java源代码,认识.class字节码(二进制文件,target中生产文件))
lombok的作用:
lombok在项目进行编译之前,就可以将一些注解生产想要的对象(代码)。