最近刚把进公司的第一个项目忙完,有点空闲时间,于是就打算把公司项目会使用的一些框架看一看,之前的项目是在别人搭好的框架之上写代码,但是要让我一个人从无到有搭建一个项目框架我是做不到的。在之前的项目中我大概使用了这样几种框架:spring, slf4j, mybatis, pigeon等。
首先我打算从slf4j开始。slf4j的全称为Simple Logging Facade for Java,即简单日志门面。它并不是具体的日志框架,而是作为一个代理服务于各种具体的日志框架,比如说log4j,logback等。阿里巴巴的java开发手册中强制要求使用slf4j中的api来记录日志,而不可以直接使用具体的日志系统,有利于维护和统一各个类和项目的日志处理方式。
为了在spring中使用slf4j,需要在pom.xml文件中添加slf4j的依赖,具体如下:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.13</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.13</version>
<scope>runtime</scope>
</dependency>
其中slf4j-api为slf4j自身api的jar包,由于我在项目中使用了log4j2作为slf4j代理的具体的日志系统,因此需要在slf4j中排除它和log4j1.x的桥接依赖,以免产生冲突。而jcl-over-slf4j为slf4j提供的桥接器,用来建立slf4j和具体日志系统的联系。
在添加了slf4j的依赖关系之后,便能够在代码里使用slf4j来进行记录log,只需要引入
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
两个包就可。LoggerFactory用来根据类的类型生产出特定的Logger,这样在记录日志的过程中,便可以输出类的相关信息,用来快速定位log,确定问题。
private static final Logger LOGGER = LoggerFactory.getLogger(TestClass.class);
为了能够正常使用slf4j,必须还需要设置一个具体的日志系统,这边我选择了log4j4作为具体的日志系统,Log4j的1.x版本已经被广泛使用于很多应用程序中。然而,它这些年的发展已经放缓。它变得越来越难以维护,因为它需要严格遵循很老的Java版本,并在2015年8月寿终正寝,log4j2作为它的代替品,在很多方面都有了很大的进步,但是这边我们不讲这些,这篇文档主要讲解log4j2的相关配置。
首先,最基本的还是引入相关的依赖关系:
<!--核心log4j2jar包-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.4.1</version>
</dependency>
<!--slf4j与log4j桥接-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.4.1</version>
</dependency>
此外由于spring默认使用common-logging作为log工具,因此还需要在spring中排除这个依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.17.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
最终的log4j2配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- log4j2使用说明:
使用方式如下:
private static final Logger logger = LogManager.getLogger(实际类名.class.getName());
2、日志说明:
(1)请根据实际情况配置各项参数
(2)需要注意日志文件备份数和日志文件大小,注意预留目录空间
(3)实际部署的时候backupFilePatch变量需要修改成linux目录
-->
<configuration status="debug">
<Properties>
<Property name="fileName">TestController.log</Property>
<Property name="backupFilePatch">/workspace/TestController/log/</Property>
</Properties>
<!--先定义所有的appender-->
<appenders>
<!--这个输出控制台的配置-->
<Console name="Console" target="SYSTEM_OUT">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
<!-- 输出日志的格式-->
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" />
</Console>
<!--这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFile" fileName="${backupFilePatch}${fileName}"
filePattern="${backupFilePatch}$${date:yyyy-MM}/app-%d{yyyyMMddHHmmssSSS}.log.gz">
<PatternLayout
pattern="%d{yyyy.MM.dd 'at' HH:mm:ss.SSS z} %-5level %class{36} %L %M - %msg%xEx%n" />
<!-- 日志文件大小 -->
<SizeBasedTriggeringPolicy size="20MB" />
<!-- 最多保留文件数 -->
<DefaultRolloverStrategy max="20"/>
</RollingFile>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<Logger name="com.hewenkai.controller" level="debug"
additivity="true">
<AppenderRef ref="RollingFile" />
</Logger>
<Root level="error">
<AppenderRef ref="Console" />
</Root>
</loggers>
</configuration>
下面一个一个分析log4j2配置文件的元素。
- configure元素,其为根节点,有status和monitorInterval等多个属性,其中status属性表示log4j2本身的日志信息打印级别,设置不同的级别,可以看到log4j2加载插件,组装logger时的一些信息,这里设置了debug级别。
- appender元素,为输出源,定义日志输出的地方,主要可以输出到这样几个地方:
- Console:将日志打印到控制台上,开发的时候一般都会配置,以便调试。
- File:文件输出源,用于将日志写入到指定的文件,需要配置输入到哪个位置。
- RollingRandomAccessFile:该输出源也是写入到文件,不同的是比File更加强大,可以指定当文件达到一定条件(大小、时间)时,另起一个文件继续写入日志。其有一下一些属性:
- fileName:指定当前日志文件的位置和文件名称。
- filePattern 指定当发生Rolling时,文件的转移和重命名规则。
- SizeBasedTriggeringPolicy:指定当文件体积大于size指定的值时,触发Rolling。
- DefaultRolloverStrategy:指定最多保存的文件个数。
- TimeBasedTriggeringPolicy:按时间转移log文件,需要和filePattern结合使用。
- MongoDB:输出到MongDb数据库中。
- PatternLayout:控制台或文件输出源(Console、File、RollingRandomAccessFile)都必须包含一个PatternLayout节点,用于指定输出文件的格式。
- Flume:输出到Apache Flume,Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统。
- Property元素:用来定义一些路径常量之类的,如filepath,filename,以供后面文件使用。
- Loggers(日志器):日志的输入源,和一个appender相对应,其中的元素AppenderRef能够指定appender。Loggers有两种,分别为root日志器和自定义日志器。root日志器用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出。自定义日志器用来单独指定日志的形式,比如某个类或者某个包下面的所有类的日志输出形式。
- level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF
- name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点
- AppenderRef:用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。