SpringBoot + @Slf4j + log4j 日志分级输出

SpringBoot + @Slf4j + log4j 日志分级输出

      • 一、概念介绍
      • 二、环境准备
        • 1、SpringBoot项目搭建
        • 2、依赖引入
      • 三、log4j 日志配置
      • 四、日志测试
      • 五、动态设置项目日志级别

一、概念介绍

  • SLF4J
    SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志实现方案,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。
  • Log4J
    具体介绍这了不在赘述了~

二、环境准备

演示环境:SpringBoot 2.2.1.RELEASE、Slf4j简单日志门面、log4j

1、SpringBoot项目搭建

参考我的另外一篇博客:
链接: IDEA 创建SpringBoot多级Maven父子项目-swotXu.

2、依赖引入

  • 引入spring-boot-starter包,

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
    <version>2.2.1.RELEASEversion>
    
    <exclusions>
        <exclusion>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-loggingartifactId>
        exclusion>
    exclusions>
dependency>

注意:这里需要移除默认log配置,否者抛出以下异常:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/maven/maven-repository-3.5.3/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/D:/maven/maven-repository-3.5.3/org/slf4j/slf4j-log4j12/1.7.29/slf4j-log4j12-1.7.29.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
  • 引入log4j
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-log4jartifactId>
    <version>1.3.8.RELEASEversion>
dependency>
  • 引入lombok,可使用@Slf4j注解,全局log对象
<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    <version>1.18.10version>
    <optional>trueoptional>
dependency>

三、log4j 日志配置

在项目resources目录下创建文件log4j.properties
博主这里,将日志分级别输出到不同文件中

先定义日志附加器:

  • DEBUG 级别
    输出:项目名/debug/debug.log
    策略:日志文件每达到80M,生成一个新文件
log4j.appender.file_debug=org.apache.log4j.RollingFileAppender
log4j.appender.file_debug.layout=org.apache.log4j.PatternLayout
log4j.appender.file_debug.MaxFileSize=80MB
log4j.appender.file_debug.MaxBackupIndex=10
log4j.appender.file_debug.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss} (%C:%L line)] %m%n
log4j.appender.file_debug.Threshold=DEBUG
log4j.appender.file_debug.filter.F1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.file_debug.filter.F1.LevelMin=DEBUG
log4j.appender.file_debug.filter.F1.LevelMax=DEBUG
log4j.appender.file_debug.append=true
log4j.appender.file_debug.Encoding=UTF-8
log4j.appender.file_debug.File=logs/concurrency/debug/debug.log
  • INFO 级别
    输出:项目名/info/info.log
    策略:日志文件每半天,生成一个新文件
log4j.appender.file_info=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file_info.DatePattern='_'yyyy-MM-dd-a
log4j.appender.file_info.layout=org.apache.log4j.PatternLayout
log4j.appender.file_info.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss} (%C:%L line)] %m%n
log4j.appender.file_info.Threshold=INFO
log4j.appender.file_info.filter.F1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.file_info.filter.F1.LevelMin=INFO
log4j.appender.file_info.filter.F1.LevelMax=INFO
log4j.appender.file_info.append=true
log4j.appender.file_info.Encoding=UTF-8
log4j.appender.file_info.File=logs/concurrency/info/info.log
  • ERROR 级别
    输出:项目名/erro/erro.log
    策略:日志文件每天,生成一个新文件
log4j.appender.file_error=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file_error.DatePattern='_'yyyy-MM-dd
log4j.appender.file_error.layout=org.apache.log4j.PatternLayout
log4j.appender.file_error.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss} (%C:%L line)] %m%n
log4j.appender.file_error.Threshold=ERROR
log4j.appender.file_error.filter.F1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.file_error.filter.F1.LevelMin=ERROR
log4j.appender.file_error.filter.F1.LevelMax=ERROR
log4j.appender.file_error.append=true
log4j.appender.file_error.Encoding=UTF-8
log4j.appender.file_error.File=logs/concurrency/erro/error.log
  • 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.Encoding=UTF-8
log4j.appender.stdout.layout.ConversionPattern=[%-5p][%d{HH:mm:ss} %c{1}:%L line] %m%n

最后,设置项目日志级别为 INFO,使用前面定义的四种附加器

log4j.rootCategory=INFO,file_debug,file_info,file_error,stdout

四、日志测试

  • 测试代码
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LogTest {
    public static void main(String[] args) {
        log.debug("test debug!");
        log.info("test info!");
        log.error("test error!");
    }
}
  • 运行结果
    控制台,上面我们设置项目级别为INFO,所以只输出 INFO、ERROR级别日志
    SpringBoot + @Slf4j + log4j 日志分级输出_第1张图片
  • 对应日志文件,博主这里保留了之前产生的日志文件
    SpringBoot + @Slf4j + log4j 日志分级输出_第2张图片

五、动态设置项目日志级别

背景:修改日志配置文件,无法立即生效,需要重新项目。在生成环境下,当然不能随便重启项目,可使用下面这种方式进行设置

import lombok.extern.slf4j.Slf4j;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Writer;
import java.util.Enumeration;

@Slf4j
@Controller
@RequestMapping("/logger")
public class LoggerController {

    /**
     * 设置指定包的日志级别
     * @param packageName 需要修改的包名
     * @param logLevel 日志级别
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/change", method = RequestMethod.GET, produces = "application/json")
    public String change(String packageName, String logLevel) {
        try {
            Level level = Level.toLevel(logLevel);
            Logger logger = LogManager.getLogger(packageName);
            logger.setLevel(level);
        } catch (Exception e) {
            return "失败";
        }
        return "成功";
    }

    /**
     * 修改全局日志级别
     * @param logLevel
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/changeRoot", method = RequestMethod.GET, produces = "application/json")
    public String change(String logLevel) {
        try {
            Level level = Level.toLevel(logLevel);
            LogManager.getRootLogger().setLevel(level);
        } catch (Exception e) {
            return "失败";
        }
        return "成功";
    }

    /**
     * 查看现在包的日志级别
     * @param request
     * @param response
     */
    @RequestMapping(value = "/packageLoggers", method = RequestMethod.GET)
    public void index(HttpServletRequest request, HttpServletResponse response) {
        StringBuilder sb = new StringBuilder();
        try {
            sb.append("");
            Writer writer = response.getWriter();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html; charset=utf-8");
            Enumeration logs = LogManager.getCurrentLoggers();
            while (logs.hasMoreElements()) {
                Logger logger = (Logger) logs.nextElement();
                sb.append("");
                sb.append(logger.getName()).append(",").append(logger.getEffectiveLevel());
                sb.append("");
            }
            sb.append("");
            writer.write(sb.toString());
            writer.flush();
            if(writer != null){
                writer.close();
            }
            log.info("项目日志级别:{}", sb.toString());
        } catch (Exception e) {
        }
    }
}
  • 设置指定包com.swotxu.webdemo.demo日志级别为DEBUG
http://localhost:8080/logger/change?logLevel=DEBUG&packageName=com.swotxu.webdemo.demo2
  • 设置全局日志级别为DEBUG
http://localhost:8080/logger/changeRoot?logLevel=DEBUG
  • 查看项目各包日志级别
http://localhost:8080/logger/packageLoggers

大家如果有什么疑问,欢迎评论留言!别忘了收藏关注~

你可能感兴趣的:(#,springboot)