[Java]日志系统

首先来看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 ---------- ---------- ---------- ----------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值