Skip to content

日志的使用

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);

Logback的配置

  • 方法一:在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其他的作用

上面引入的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注解。

Clone this wiki locally