[Java]日志系统

来源:互联网 发布:知乎每日精选接口 编辑:程序博客网 时间:2024/06/06 01:04

首先来看log4j是怎么使用的,首先在web.xml中配置listener在初始化的时候对日志系统进行初始化:

<context-param><param-name>log4jConfigLocation</param-name><param-value>/WEB-INF/classes/log4j.properties</param-value></context-param><listener><listener-class>org.springframework.web.util.Log4jConfigListener</listener-class></listener>

其中Log4jConsigListener是一个ServletContextListener,用来监听web应用的生命周期,那么就可以在web应用初始化的时候完成日志的初始化。在log4j.xml的配置文件中有下面几种角色:

  • appender
  • logger
  • root

在appender中定制了写文件的方式:buffer(缓存)、file(文件)、encoding(编码)、layout(格式),举个例子:

<appender name="PROJECT" class="com.alibaba.common.logging.spi.log4j.DailyRollingFileAppender"><param name="file" value="project.log"/><param name="append" value="true"/><param name="encoding" value="GBK"/>        <layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern" value="%d [%X{requestURIWithQueryString}] %t %-5p %c{2} - %m%n"/></layout></appender>

可以配置多个logger,用来在不同的地方使用:

<logger name="com.my.project" additivity="false"><level value="info"/> <appender-ref ref="PROJECT"/></logger>

然后就可以在日志中使用它来打印日志:

static Logger logger = LoggerFactory.getLogger(getClass());logger.info("message");

而在root中接受所有日志,比如可以通过拦截所有ERROR的日志来将所有的错误日志。


---------- ---------- ---------- ---------- 分割线 ---------- ---------- ---------- ----------


日志的初始化的过程就是解析log4j.xml然后构造内存中的数据,解析的过程在org.apache.log4j.xml.DOMConfigurator#doConfigure中,得到的数据有:


LoggerRepository是Logger的容器,是一个以RootLogger为根的树,Logger之间的关系和层次由name决定,Hierarchy是log4j中默认实现。在使用是根据name查找Logger,然后依次调用Logger中的Appender.doAppend方法来执行真正的日志输出。


---------- ---------- ---------- ---------- 分割线 ---------- ---------- ---------- ----------


log4j是早期成功的日志系统,该开发团队因为对其不满意又开发了logback。在系统中强依赖某个日志不是一件好事情,这样便有了日志框架(比如slf4j),它提供了统一的记录日志的接口,允许最终用户在部署应用的时候使用自己喜欢的日志系统。slf4j的结构如下:


如果一个日志系统要使得用户可以通过slf4j框架使用,要提供一个StaticLoggerBinder来进行绑定,绑定的方法是直接让ClassLoader找到类,如下:

private static void singleImplementationSanityCheck() {try {ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader();Enumeration paths;// 是用ClassLoader找到所有的相同的"类文件"if (loggerFactoryClassLoader == null) {paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);} else {paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH);}List implementationList = new ArrayList();while (paths.hasMoreElements()) {URL path = (URL) paths.nextElement();implementationList.add(path);}// 如果有多个"类文件",那么说明是要矛盾的,打印错误信息if (implementationList.size() > 1) {Util.report("Class path contains multiple SLF4J bindings.");for (int i = 0; i < implementationList.size(); i++) {Util.report("Found binding in [" + implementationList.get(i) + "]");}Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");}} catch (IOException ioe) {Util.report("Error getting resources from path", ioe);}}

这种绑定的方式叫静态绑定,当有多个相同的类Binder的时候,用的是哪个日志系统就要看先加载的是哪个类了。如果代码中已经使用了common logging的方式进行日志处理,这时候如果想改用slf4j来做,可以使用

jcl-over-slf4j

来实现。

---------- ---------- ---------- ---------- END ---------- ---------- ---------- ----------

0 0
原创粉丝点击