-
Notifications
You must be signed in to change notification settings - Fork 627
日志的使用
sqmax edited this page Aug 7, 2018
·
7 revisions
- 一套能够实现日志输出的工具包。
- 能够描述系统运行状态的所有时间都可以算作日志,包括用户下线,接口超时,数据库崩溃。
- 定制输出目标。
- 定制输出格式。
- 日志携带的上下文信息,如时间戳、类路径、线程、调用对象等等。
- 运行时的选择性输出,比如现在的系统正常,我就只关心正常的日志,假如现在系统运行特别慢,那我可能就比较关心数据库访问层的问题,也就是DAO层的细节,这时候如果能够把这部分相关的日志打印出来,就很重要了。
- 灵活的配置。
- 优异的性能。
日志门面 日志实现
JCL Log4j
SLF4J Log4j2
jboss Logback
JUL
进过比较,我们选用SLF4j和Logback。Spring Boot里面用的就是SLF4j和Logback,在使用Spring Boot构建web项目是,我们引入了,下面的起步依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
这个起步依赖已经引入了SLF4j和Logback,所以我们不必再显示引入。
- 使用方法: 如果在A类中使用日志,先以该类为参数构造一个对象,如下:
private final Logger logger=LoggerFactory.getLogger(A.class);
然后就可以使用:
log.debug("debug......");
log.info("name: {} , password: {}",name,password);
log.error("error......");
log.warn("warning.....");
上面每次使用都要构造一个Logger对象,有没有很麻烦。 其实在IEDA里,我们可以有一点小技巧。可以不用构造Logger对象。
首先,添加以下依赖。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency>
然后,在IDEA中安装lombok插件(IDEA中安装插件方式可在仓库首页有提到),然后在需要打印日志的类上用@Slfj
注解。
这样在该类中就可以直接使用log
对象了。如下:
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class LoggerTest {
// private final Logger logger= LoggerFactory.getLogger(LoggerTest.class);
@Test
public void test1(){
String name="imooc";
String password="123456";
//要安裝Lombok插件,才能直接用log
log.debug("debug......");
log.info("name: {} , password: {}",name,password);
log.error("error......");
log.warn("warning.....");
}
}
- 在日志里输出变量,用占位符。
String name="Mary";
log.info("name: {}",name);
- 方法一:在application.yml中配置,这里能配置的东西比较简单,只能配置日志文件的路径,日志输出格式等一些简单的配置。
logging:
pattern:
console: "%d - %msg%n" #配置日志的打印格式
file: F:/日志/sell.log
level:
com.imooc.LoggerTest: debug #将日志级别指定到一个类
- 方法二:在logback-spring.xml配置,可以进行一些复杂的配置。比如有下面的需求:
- 区分info和error日志
- 每天产生一个日志文件
在resource
目录下建立logback-spring.xml文件。
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!--1. 控制台日志输出的配置-->
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
%d - %msg%n
</pattern>
</layout>
</appender>
<!--2. 日志输出文件,infor级别-->
<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
<encoder>
<pattern>
%msg%n
</pattern>
</encoder>
<!-- 滚动策略,按时间滚动,每天一个日志-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>F:/日志/info.%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<!--3. 日志输出文件,error级别-->
<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>
%msg%n
</pattern>
</encoder>
<!-- 滚动策略,按时间滚动,每天一个日志-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>F:/日志/error.%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<!--下面声明把以上的配置用在哪里,root即对整个项目都适用-->
<root level="info">
<appender-ref ref="consoleLog"/>
<appender-ref ref="fileInfoLog"/>
<appender-ref ref="fileErrorLog"/>
</root>
</configuration>
对于每个配置项的含义,已用注解作简要说明。不过我们还是有必要了解一下日志级别,在package org.slf4j.event;
有一个Level的枚举类,它定义了日志级别,如下:
public enum Level {
ERROR(ERROR_INT, "ERROR"), WARN(WARN_INT, "WARN"), INFO(INFO_INT, "INFO"), DEBUG(DEBUG_INT, "DEBUG"), TRACE(TRACE_INT, "TRACE");
private int levelInt;
private String levelStr;
Level(int i, String s) {
levelInt = i;
levelStr = s;
}
public int toInt() {
return levelInt;
}
/**
* Returns the string representation of this Level.
*/
public String toString() {
return levelStr;
}
}
里面定义的TRACE、DEBUG、INFO、WARN、ERROR,表明严重性逐渐增加。
上面引入的lombok依赖还有其他的作用,我们在项目中与许多Entity和DTO,它们有许多字段,而且需要get、set方法。我们可以在该实体类上使用@Data注解,那么实体类就不需要显示写get、set方法了。
import lombok.Data;
/**
* Created by SqMax on 2018/3/31.
*/
@Data
public class CategoryForm {
private Integer categoryId;
/**类目名字**/
private String categoryName;
/** 类目编号**/
private Integer categoryType;
}
如果该实体类只需get或set方法,那么就可以使用@Getter或@Setter注解。
目录