完善的Web应用需要有完善的日志系统的支持,日志系统在项目的跟踪调试过程中发挥着重要作用。Struts,Spring和Hibernate均提供了自己的日志框架,有效地配置日志系统在项目开发过程中占据着一定的比重。本文简要介绍SSH框架的日志系统和相关配置,以方便日常项目的开发。
- Struts 2的日志系统
Struts使用commons logging来封装其日志系统,JCL(Apache Commons Logging)使用两个基本的抽象概念:Log(基本的logger)和LogFactory(用于创建Log实例)。指定一个特定的Log实现是很有用处的,默认的LogFactory实现使用如下发现机制来决定它应该使用哪种类型的Log实现:
- 寻找该工厂的一个名为org.apache.commons.logging.Log的配置属性,该配置属性可由java代码显式设置,但通常是通过在classpath中放置一个名为commons-logging.properties的文件来设置;
- 寻找一个名为org.apache.commons.logging.Log的系统属性;
- 如果在应用的classpath中log4j日志系统可用,则使用相应的包装类(Log4JLogger);
- 如果应用运行在JDK 1.4系统上,则使用相应的包装类(Jdk14Logger);
- 使用默认的简单日志包装器(SimpleLog)。
在Web应用中通常使用Log4j来实现Struts的日志系统,由上述内容可知,Struts提供了Log4j的自动发现功能。
- Spring 2的日志系统
Spring使用Log4j作为其日志系统。在Web环境中,可以使用Log4jWebConfigurer来实现定制的Log4j初始化,它允许指定Web应用中的日志文件的路径,并提供实现自动刷新检查的选择项。
在servlet context层次支持三个初始化参数,在web.xml中通过context-param来配置:
- log4jConfigLocation:指定Log4j配置文件的位置。可以是一个“classpath:”位置(例如:“classpath:log4j.properties”);或者是一个文件的绝对URL(例如:“file:c:/log4j.properties”);或者是相对于应用根目录的相对路径(例如:”/WEB-INF/log4j.properties“)。如果没有指定,将应用默认的Log4j初始化(位于classpath中的”log4j.properties“或者”log4j.xml“)
- log4jRefreshInterval和log4jExposeWebAppRoot:具体内容参见Spring Java Doc。
为定制Log4j初始化,需要在web.xml中注册相应的监听器,如下
- <!--
- - Configures Log4J for this web app.
- - As this context specifies a context-param" log4jConfigLocation", its file path
- - is used to load the Log4J configuration, including periodic refresh checks.
- -
- - Would fall back to default Log4J initialization (non-refreshing) if no special
- - context-params are given.
- -
- - Exports a "web app root key", i.e. a system property that specifies the root
- - directory of this web app, for usage in log file paths.
- -->
- <listener>
- <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
- </listener>
在web.xml文件中,还可以设置webAppRootKey参数,来导出可以在log4j.properties配置文件中使用的代表Web应用根目录的占位符。配置如下:
- <context-param>
- <param-name>webAppRootKey</param-name>
- <param-value>sshintegration.root</param-value>
- </context-param>
如果希望使用webAppRootKey,则需要注册Log4jConfigListener监听器,另外,该监听器需要在ContextLoaderListener之前注册。对于Servlet 2.3或者之前的版本,需要使用Log4jConfigServlet,并且其load-on-startup的值应低于ContextLoaderServlet。
- Hibernate 3的日志系统
Hibernate使用Simple Logging Facade for Java (SLF4J)来记录各种系统事件。SLF4J能够将你的日志输出定向到多种日志框架(NOP,Simple,Log4j version 1.2,JDK 1.4 logging,JCL,或者logback),最终选择何种框架来实现你的日志系统依赖于你选择的绑定。为了建立日志,你需要将slf4j-api放置在你的classpath中,另外还需要一同放置你所选定的绑定,比如slf4j-log4j12.jar,如果你选定log4j作为你最终的日志系统实现。
为使用log4j,你需要放置log4j.properties在你应用的classpath中。
注:对于Hibernate 3.3.2 GA版本发布的包中,提供slf4j-api-1.5.8.jarJAR包,但是却没有提供相应绑定的JAR包,相应绑定的JAR包可以到SLF4J的官方网站(www.slf4j.org)获取,如果使用Log4j作为日志系统的实现,需要将slf4j-log4j12-1.5.8.jar包与上述jar包一同放置在/WEB-INF/lib下。
如果在配置过程中,出现如下类似的异常,则可能的原因就是缺少slf4j与具体的日志实现绑定的JAR包:
- ...
- Caused by: java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder
- at org.slf4j.LoggerFactory.getSingleton(LoggerFactory.java:223)
- at org.slf4j.LoggerFactory.bind(LoggerFactory.java:120)
- at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:111)
- at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:269)
- at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:242)
- at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:255)
- ...
可见,Struts,Spring和Hibernate均支持Log4j作为其日志实现系统,因此如果能够合理地配置Log4j,便可以为SSH架构建立起完善的日志系统。一个典型的Log4j配置具有如下形式:
- # For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml!
- # For all other servers: Comment out the Log4J listener in web.xml to activate Log4J.
- log4j.rootLogger=INFO, stdout, logfile
- log4j.appender.stdout=org.apache.log4j.ConsoleAppender
- log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
- log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
- log4j.appender.logfile=org.apache.log4j.RollingFileAppender
- log4j.appender.logfile.File=${sshintegration.root}/WEB-INF/SSHIntegration.log
- log4j.appender.logfile.MaxFileSize=512KB
- # Keep three backup files.
- log4j.appender.logfile.MaxBackupIndex=3
- # Pattern to output: date priority [category] - message
- log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
- log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
- ...
其中,${sshintegration.root}便是上述在web.xml文件中通过context-param来指定的参数。
至此,SSH架构所需的日志系统基本完成,log4j.properties中的配置项需要根据具体的应用需求而发生变化,具体的配置可以参看Log4j的官方网站(http://logging.apache.org/)和SSH相关开发文档。