分类目录归档:后端

slf4j与common-logging

相通点:

  • 两者都为通用日志接口

异同:

  • slf4j 静态绑定日志(编译时绑定)
  • jcl 动态绑定(动态绑定跟类加载器有关,会有一定的问题)

slf4j 解决 jcl 以下两点问题

解决加载问题

Commons Logging存在的ClassLoader问题,即当服务器本身引入Commons Logging时,如果在服务器中载入Commons Logging包,则该包中的类由服务器的ClassLoader加载,从而在加载Log4J中的Logger类时会出现ClassNotFoundException,因为服务器中的ClassLoader没法找到Web App下的jar包。对于父ClassLoader优先的类加载机制来说,目前的一个解决方案是使用commons-logging-api-1.1.1.jar包,该包的Log实现类只包含Jdk14Logger、SimpleLog、NoOpLog三个类,因而在加载这几个类时会使用Web App中的Commons Logging包,从而解决ClassNotFoundException的问题,然而这种方式对那些实现Child ClassLoader First的服务器来说,由WebClassLoader父ClassLoader加载的类在使用日志时会存在问题,因为它们的Log接口由加载自身类的ClassLoader加载,而Log4JLogger类却由WebClassLoader加载。

性能优一些

在使用Commons Logging时,我们经常会看到以下方法的写法:
if (logger.isDebugEnabled()) {
logger.info(“Loading XML bean definitions from ” + encodedResource.getResource());
}

存在isDebugEnabled()的判断逻辑是为了在避免多余的字符串拼接,即如果不存在isDebugEnabled()判断,即使当前日志级别为ERROR时,在遇到logger.info()调用时,它还会先拼接日志消息的字符串,然后进入该方法内,才发现这个日志语句不用打印。而这种多余的拼接不仅浪费了多余的CPU操作,而且会增加GC的负担。SLF4J则提供以下的方式来解决这个问题:

logger.info(“Loading XML bean definitions from {}”, encodedResource.getResource());

jstl 中 c:set 的 scope 作用域要注意的问题

在jstl使用c:set 时,去设置一个变量,需要注意 变量的 scope 问题。设置一个值的行为,相当于,变量已经存在,则更新变量的值,不存在则建增值。

在项目中遇到这样的情况,已经设置了一个session级别的变量a(scope=session),当前页需要新建一个变量,恰好名称也为a。

<c:set var=”a” value=”b”/>

c:set 会首先查找变显是否存在,当未指定 scope 的情况下,查找的顺序为:page->request->session->application,一直往上找,直到找到为止。项目中遇到恰好在session级时找到同名变量存在,c:set 就会把session级的变量 更新了,但实际项目是在当前页创建一个变,在这情况下,就会产生意想不到的问题。

所以使用c:set的话,最好明确指定scope 避免不必要的错误。