ssm框架配置日志

作为一名长期bug程序员(也是很无奈呀),最重要的就是日志的输出了,才能在出现bug的情况下及时找到问题原因,这篇文章对日志做一个总结。
大家应该最熟悉的就是System.out.println();学java的小伙伴人生中第一次写的代码大概就是System.out.println("hello world!");但是对于一个简单的main方法来说还可以,但是真正在项目中,用System.out.println();却比较麻烦,比如代码修改好了怎么办?当然是删除System.out.println();。那又改错了怎么办,再添加System.out.println();,反复来这么几次,就觉得太麻烦了,有小伙伴说,那不删除不就行了么?System.out.println();作为调试手段,用来向控制台输出,但是多了也是会影响程序效率的,程序发布后,这些打印的信息也很可能泄露程序的一些重要信息,所以要去掉,而且打印不可控制、打印时间无法确定、不能添加过滤器、日志没有级别区分。所以就用到了我们今天说的SLF4J
想要摸透SLF4J。首先要把它的兄弟们也要了解清楚。
一、jdk logging

从jdk1.4起,JDK开始自带一套日志系统。JDK Logger最大的优点就是不需要任何类库的支持,只要有Java的运行环境就可以使用。看代码👇

 public static void main(String[] args) {
        Logger logger = Logger.getGlobal();
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }

按照日志级别打印,控制台输出的,只有info之前的,之后的没有打印出来,原因是jdklogging默认日志为infoinfo级别以下的,不会被打印出来,使用日志级别的好处在于,调整级别,就可以屏蔽掉很多调试相关的日志输出。

十二月 08, 2020 5:07:56 下午 com.centrin.report.controller.aa main
严重: severe
十二月 08, 2020 5:07:57 下午 com.centrin.report.controller.aa main
警告: warning
十二月 08, 2020 5:07:57 下午 com.centrin.report.controller.aa main
信息: info

二、Commons Logging

commons-logging是apache提供的一个通用的日志接口。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。当然,common-logging内部有一个Simple logger的简单实现,但是功能很弱。所以使用common-logging,通常都是配合着log4j来使用。使用它的好处就是,代码依赖是common-logging而非log4j, 避免了和具体的日志方案直接耦合,在有必要时,可以更改日志实现的第三方库。

默认情况下,Commons Loggin自动搜索并使用Log4j(Log4j是另一个流行的日志系统),如果没有找到Log4j,再使用JDK Logging
先在pom.xml中导入commons-Logging的依赖

<dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.2</version>
</dependency>

后端进行日志打印

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Testlogging {

    public static Log log = LogFactory.getLog(Testlogging.class); //commons.logging

    //commons.logging
    public static void main(String[] args) {
        log.debug("debug()...");
        log.info("info()...");
        log.error("error()...");
        try {

        } catch (Exception e) {
            e.printStackTrace();
            log.error("error()...", e);
        }
    }
}

如果只是依赖JCL,不依赖其它日志组件的话,会打印出info,errordebug是不打印的

[INFO ][2020-12-10 09:39:20][Testlogging-main] info()...
[ERROR][2020-12-10 09:39:20][Testlogging-main] error()...

Process finished with exit code 0

到这里,Commons Loggin就已经完成了!!!

三、log4j

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
所以简单的来说,Log4j可以理解为一个通过配置文件进行配置的日志操作工具

第一步:首先在pom.xml中引入log4j的依赖

 <dependency>
         <groupId>log4j</groupId>
         <artifactId>log4j</artifactId>
         <version>1.2.16</version>
</dependency>

第二步log4j.properties这个文件就是采用Log4j操作包完成日志部分的操作配置。
那么如何让ssm框架知道这个配置并让他其作用呢?👇
web.xml插入以下代码块,这里就告诉了框架我们采用了Log4j配置,配置文件位置是classpath路径下的log4j.properties文件。

<!--log4j配置文件开始-->
  <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>classpath:config/log4j.properties</param-value>
  </context-param>
  <!--log4j配置文件结束-->

第三步:在resources下添加log4j.properties文件

### 配置根 ###
log4j.rootLogger = info,console ,fileAppender,dailyRollingFile,ROLLING_FILE

### 设置输出sql的级别,其中logger后面的内容全部为jar包中所包含的包名 ###
log4j.logger.org.apache=${log.level}
log4j.logger.java.sql.Connection=${log.level}
log4j.logger.java.sql.Statement=${log.level}
log4j.logger.java.sql.PreparedStatement=${log.level}
log4j.logger.java.sql.ResultSet=${log.level}

### 配置输出到控制台 ###
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = [%-5p][%d{yyyy-MM-dd HH:mm:ss}][%c-%M] %m%n

### 配置输出到文件 ###
log4j.appender.fileAppender = org.apache.log4j.FileAppender
log4j.appender.fileAppender.File = logs/log.log
log4j.appender.fileAppender.Append = true
log4j.appender.fileAppender.Threshold = DEBUG
log4j.appender.fileAppender.layout = org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern = [%-5p][%d{yyyy-MM-dd HH:mm:ss}][%c-%M] %m%n

### 配置输出到文件,并且每天都创建一个文件 ###
log4j.appender.dailyRollingFile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyRollingFile.File = ${log.dir}/log.log
log4j.appender.dailyRollingFile.Append = true
log4j.appender.dailyRollingFile.Threshold = DEBUG
log4j.appender.dailyRollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.dailyRollingFile.layout.ConversionPattern = [%-5p][%d{yyyy-MM-dd HH:mm:ss}][%c-%M] %m%n

### 配置输出到文件,且大小到达指定尺寸的时候产生一个新的文件 ###
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender 
log4j.appender.ROLLING_FILE.Threshold=ERROR 
log4j.appender.ROLLING_FILE.File=rolling.log
log4j.appender.ROLLING_FILE.Append=true 
log4j.appender.ROLLING_FILE.MaxFileSize=10KB 
log4j.appender.ROLLING_FILE.MaxBackupIndex=1 
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout 
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}][%c-%M] %m%n

第四步,后端就可以打印日志了

import org.apache.log4j.Logger;

public class Testlogging {

    public static Logger logger = Logger.getLogger(Testlogging.class); //log4j
    //log4j
    public static void main(String[] args) {
        //使用默认的配置信息,不需要写log4j.properties
        // BasicConfigurator.configure();
        //设置日志输出级别为info,这将覆盖配置文件中设置的级别
        // logger.setLevel(Level.INFO);

        logger.info("info()...");
        logger.error("error()...");
        try {
            int a=0;
            int b= 1/0;//0不能为除数,所以会走catch

        } catch (Exception e) {
            e.printStackTrace();
            logger.error("0不能为除数",e);
        }
    }
}

控制台打印效果

[INFO ][2020-12-10 10:20:42][Testlogging-main] info()...
[ERROR][2020-12-10 10:20:42][Testlogging-main] error()...
java.lang.ArithmeticException: / by zero
	at Testlogging.main(Testlogging.java:18)
[ERROR][2020-12-10 10:20:42][Testlogging-main] 0不能为除数
java.lang.ArithmeticException: / by zero
	at Testlogging.main(Testlogging.java:18)

到这里,log4j的配置就已经完成,就可以随意使用日志啦!!!

五,SLF4J+logback

SLF4J类似于Commons Logging,也是一个日志接口,而Logback类似于Log4j,是一个日志的实现,它提供了Java中所有日志框架的简单抽象。因此,它使用户能够使用单个依赖项处理任何日志框架,例如:Log4j,Logback和JUL(java.util.logging)。可以在运行时/部署时迁移到所需的日志记录框架。
CekiGülcü创建了SLF4J作为Jakarta commons-logging框架的替代品。

  1. 使用SLF4J框架,可以在部署时迁移到所需的日志记录框架。
  2. Slf4J提供了对所有流行的日志框架的绑定,例如log4j,JUL,Simple logging和NOP。因此可以在部署时切换到任何这些流行的框架。无论使用哪种绑定,SLF4J都支持参数化日志记录消息。
  3. 无论使用哪种绑定,SLF4J都支持参数化日志记录消息。由于SLF4J将应用程序和日志记录框架分离,因此可以轻松编写独立于日志记录框架的应用程序。而无需担心用于编写应用程序的日志记录框架。
  4. SLF4J提供了一个简单的Java工具,称为迁移器。使用此工具,可以迁移现有项目,这些项目使用日志框架(如Jakarta Commons Logging(JCL)或log4j或Java.util.logging(JUL))到SLF4J。

第一步,在pom.xml中加入SLF4Jlogback的依赖

 <!--SLF4J  start-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.20</version>
    </dependency>

   // 这个jar包用log4j的时候写,如果用logback的话,要删掉, 否则出现jar包冲突警告👇
   // Class path contains multiple SLF4J bindings.警告
  
   <!-- <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>${slf4j.version}</version>
    </dependency> 
   --> 
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
      <version>1.7.20</version>
    </dependency>
    <!--SLF4J  end-->


<!-- LOGGING end -->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.1.7</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-access</artifactId>
      <version>1.1.7</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.1.7</version>
    </dependency>
    <!-- LOGGING end -->

第二步,在resources下面添加logback.xml,直接复制即可

<?xml version="1.0" encoding="UTF-8"?>
 
<!-- 级别从高到低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志输出规则 根据当前ROOT 级别,日志输出时,级别高于root默认的级别时 会输出 -->
<!-- 以下 每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志 -->
<!-- scan 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true-->
<!-- scanPeriod 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false-->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
 
    <!-- 动态日志级别 -->
    <jmxConfigurator />
     
    <!-- 定义日志文件 输出位置 -->
    <property name="log_dir" value="${log.dir}" />
     
    <!-- 日志最大的历史 30-->
    <property name="maxHistory" value="30" /> 
        
    <!-- ConsoleAppender 控制台输出日志 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                <!-- 设置日志输出格式 -->
                %-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger - %msg%n
            </pattern>
        </encoder>
    </appender>
 
    <!-- ERROR级别日志 -->
    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender -->
    <appender name="ERROR"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 过滤器,只记录WARN级别的日志 -->
        <!-- 果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">         
            <!-- 设置过滤级别 -->
            <level>ERROR</level>
            <!-- 用于配置符合过滤条件的操作 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 用于配置不符合过滤条件的操作 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志输出位置 可相对、和绝对路径 -->
            <fileNamePattern>
            ${log_dir}/error/%d{yyyy-MM-dd}.log
            </fileNamePattern>
            <!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>6, 则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除 -->
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>
                <!-- 设置日志输出格式 -->
               %-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger - %msg%n
            </pattern>
        </encoder>
    </appender>
 
     
    <!-- WARN级别日志 appender -->
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 过滤器,只记录WARN级别的日志 -->
        <!-- 果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 设置过滤级别 -->
            <level>WARN</level>
            <!-- 用于配置符合过滤条件的操作 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 用于配置不符合过滤条件的操作 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志输出位置 可相对、和绝对路径 -->
            <fileNamePattern>${log_dir}/warn/%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory> 
        </rollingPolicy>
        <encoder>
            <pattern>%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger - %msg%n</pattern>
        </encoder>
    </appender>
     
     
     <!-- INFO级别日志 appender -->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/info/%d{yyyy-MM-dd}.log</fileNamePattern> 
            <maxHistory>${maxHistory}</maxHistory> 
        </rollingPolicy>
        <encoder>
            <pattern>%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger - %msg%n</pattern>
        </encoder>
    </appender>
     
     
    <!-- DEBUG级别日志 appender -->
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/debug/%d{yyyy-MM-dd}.log</fileNamePattern> 
            <maxHistory>${maxHistory}</maxHistory> 
        </rollingPolicy>
        <encoder>
            <pattern>%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger - %msg%n</pattern>
        </encoder>
    </appender>
     
     
    <!-- TRACE级别日志 appender -->
    <appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>TRACE</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/trace/%d{yyyy-MM-dd}.log</fileNamePattern> 
            <maxHistory>${maxHistory}</maxHistory> 
        </rollingPolicy>
        <encoder>
            <pattern>%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger - %msg%n</pattern>
        </encoder>
    </appender>
    
        <!-- ALL级别日志 appender -->
    <appender name="ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}.log</fileNamePattern> 
            <maxHistory>${maxHistory}</maxHistory> 
        </rollingPolicy>
        <encoder>
            <pattern>%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger - %msg%n</pattern>
        </encoder>
    </appender>
    
     
    <!-- root级别   DEBUG -->
    <root>
        <!-- 打印debug级别日志及以上级别日志 -->
        <level value="${log.level}" />
        <!-- 控制台输出 -->
        <appender-ref ref="console" />
        <!-- 文件输出 -->
        <appender-ref ref="ERROR" />
        <appender-ref ref="WARN" />
        <appender-ref ref="INFO" />
        <appender-ref ref="ALL" />
<!--         <appender-ref ref="ERROR" />
        <appender-ref ref="INFO" />
        <appender-ref ref="WARN" />
        <appender-ref ref="DEBUG" />
        <appender-ref ref="TRACE" /> -->
    </root>
</configuration>

第三步,测试

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class aa {

    public static Logger logger = LoggerFactory.getLogger(aa.class);
    public static void main(String[] args) {
        logger.info("info()...");
        logger.error("error()...");
        try {
            int a=0;
            int b= 1/0;//0不能为除数,所以会走catch

        } catch (Exception e) {
            e.printStackTrace();
            logger.error("0不能为除数",e);
        }
    }

}

控制台输出

INFO  2020-12-10 13:30:14.767 [main] aa - info()...
ERROR 2020-12-10 13:30:14.770 [main] aa - error()...
java.lang.ArithmeticException: / by zero
	at aa.main(aa.java:17)
ERROR 2020-12-10 13:30:14.773 [main] aa - 0不能为除数
java.lang.ArithmeticException: / by zero
	at aa.main(aa.java:17)

到这里就全部完成啦
觉得不错的点个赞,希望更多的人可以看得到!笔芯

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值