、、 全是以同一个人为首的团伙搞出来的(日志专业户!),这几个各有所长,log4j性能相对最差,log4j2性能不错,但是目前跟mybatis有些犯冲(log4j2的当前版本,已经将AbstractLoggerWrapper更名成ExtendedLoggerWrapper,但是mybatis 2.3.7依赖的仍然是旧版本的log4j2,所以mybatis使用log4j2会报错),说到日志,还要注意另一外项目( java的世界里,记日志的组件真是多!),SLF4J只一个接口标准,并不提供实现(就好象JSF/JPA 与 RichFaces/Hibernate的关系类似),而LogBack是SLF4J的一个实现,下面介绍logback的基本用法
一、基本用法
1.1 maven依赖项
1 23 7 8org.slf4j 4slf4j-api 51.7.7 69 13 14ch.qos.logback 10logback-core 111.1.2 1215 ch.qos.logback 16logback-classic 171.1.2 18
1.2 配置文件logback.xml
1 24 5 6 7 8 9 10 11 16 1712 15%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n13 1419 38 39${USER_HOME}/${FILE_NAME}.log 20 2122 27 28${USER_HOME}/${byDay}/${FILE_NAME}-${byDay}-%i.log.zip23 241 2510 2630 5MB 31 3233 36 37%-4relative [%thread] %-5level %logger{35} - %msg%n34 3540 43 4441 42 45 4746
1.3 示例程序
跟前面log4j2的示例程序几乎完全一样:1 package com.cnblogs.yjmyzz; 2 3 import org.slf4j.*; 4 5 public class App2 { 6 7 static Logger logger = LoggerFactory.getLogger(App2.class); 8 9 10 public static void main(String[] args) {11 for (int i = 0; i < 100000; i++) {12 logger.trace("trace message " + i);13 logger.debug("debug message " + i);14 logger.info("info message " + i);15 logger.warn("warn message " + i);16 logger.error("error message " + i); 17 }18 System.out.println("Hello World! 2");19 }20 }
运行后,会在当前目录下创建logs目录,生成名为mylog-logback.log的日志文件,该文件体积>5M后,会自动创建 yyyy-mm-dd的目录,将历史日志打包生成类似:mylog-logback-2014-09-24-1.log.zip 的压缩包,每天最多保留10个
二、与spring -mvc的集成
2.1 maven依赖项
注:${springframework.version},我用的是3.2.8.RELEASE 版本
1 23 7org.springframework 4spring-core 5${springframework.version} 68 12org.springframework 9spring-beans 10${springframework.version} 1113 17org.springframework 14spring-context 15${springframework.version} 1618 22org.springframework 19spring-web 20${springframework.version} 2123 27org.springframework 24spring-webmvc 25${springframework.version} 2628 32 33 34org.springframework 29spring-expression 30${springframework.version} 3135 39 40org.slf4j 36slf4j-api 371.7.7 3841 45 46ch.qos.logback 42logback-core 431.1.2 4447 51 52 53ch.qos.logback 48logback-classic 491.1.2 5054 javax.servlet 55servlet-api 562.5 57provided 58
2.2 web.xml里增加下面的内容
1 23 6logbackConfigLocation 4classpath:logback.xml 57 9com.cnblogs.yjmyzz.util.LogbackConfigListener 8
其中com.cnblogs.yjmyzz.util.LogbackConfigListener 是自己开发的类,代码如下:(从网上掏来的)
注:该处理方式同样适用于struts 2.x
1 package com.cnblogs.yjmyzz.util; 2 3 import javax.servlet.ServletContextEvent; 4 import javax.servlet.ServletContextListener; 5 6 public class LogbackConfigListener implements ServletContextListener { 7 8 public void contextInitialized(ServletContextEvent event) { 9 LogbackWebConfigurer.initLogging(event.getServletContext());10 }11 12 public void contextDestroyed(ServletContextEvent event) {13 LogbackWebConfigurer.shutdownLogging(event.getServletContext());14 }15 }
1 package com.cnblogs.yjmyzz.util; 2 3 import java.io.FileNotFoundException; 4 5 import javax.servlet.ServletContext; 6 7 import org.springframework.util.ResourceUtils; 8 import org.springframework.util.SystemPropertyUtils; 9 import org.springframework.web.util.WebUtils; 10 11 public abstract class LogbackWebConfigurer { 12 13 /** Parameter specifying the location of the logback config file */ 14 public static final String CONFIG_LOCATION_PARAM = "logbackConfigLocation"; 15 16 /** 17 * Parameter specifying the refresh interval for checking the logback config 18 * file 19 */ 20 public static final String REFRESH_INTERVAL_PARAM = "logbackRefreshInterval"; 21 22 /** Parameter specifying whether to expose the web app root system property */ 23 public static final String EXPOSE_WEB_APP_ROOT_PARAM = "logbackExposeWebAppRoot"; 24 25 /** 26 * Initialize logback, including setting the web app root system property. 27 * 28 * @param servletContext 29 * the current ServletContext 30 * @see WebUtils#setWebAppRootSystemProperty 31 */ 32 public static void initLogging(ServletContext servletContext) { 33 // Expose the web app root system property. 34 if (exposeWebAppRoot(servletContext)) { 35 WebUtils.setWebAppRootSystemProperty(servletContext); 36 } 37 38 // Only perform custom logback initialization in case of a config file. 39 String location = servletContext 40 .getInitParameter(CONFIG_LOCATION_PARAM); 41 if (location != null) { 42 // Perform actual logback initialization; else rely on logback's 43 // default initialization. 44 try { 45 // Return a URL (e.g. "classpath:" or "file:") as-is; 46 // consider a plain file path as relative to the web application 47 // root directory. 48 if (!ResourceUtils.isUrl(location)) { 49 // Resolve system property placeholders before resolving 50 // real path. 51 location = SystemPropertyUtils 52 .resolvePlaceholders(location); 53 location = WebUtils.getRealPath(servletContext, location); 54 } 55 56 // Write log message to server log. 57 servletContext.log("Initializing logback from [" + location 58 + "]"); 59 60 // Initialize without refresh check, i.e. without logback's 61 // watchdog thread. 62 LogbackConfigurer.initLogging(location); 63 64 } catch (FileNotFoundException ex) { 65 throw new IllegalArgumentException( 66 "Invalid 'logbackConfigLocation' parameter: " 67 + ex.getMessage()); 68 } 69 } 70 } 71 72 /** 73 * Shut down logback, properly releasing all file locks and resetting the 74 * web app root system property. 75 * 76 * @param servletContext 77 * the current ServletContext 78 * @see WebUtils#removeWebAppRootSystemProperty 79 */ 80 public static void shutdownLogging(ServletContext servletContext) { 81 servletContext.log("Shutting down logback"); 82 try { 83 LogbackConfigurer.shutdownLogging(); 84 } finally { 85 // Remove the web app root system property. 86 if (exposeWebAppRoot(servletContext)) { 87 WebUtils.removeWebAppRootSystemProperty(servletContext); 88 } 89 } 90 } 91 92 /** 93 * Return whether to expose the web app root system property, checking the 94 * corresponding ServletContext init parameter. 95 * 96 * @see #EXPOSE_WEB_APP_ROOT_PARAM 97 */ 98 private static boolean exposeWebAppRoot(ServletContext servletContext) { 99 String exposeWebAppRootParam = servletContext100 .getInitParameter(EXPOSE_WEB_APP_ROOT_PARAM);101 return (exposeWebAppRootParam == null || Boolean102 .valueOf(exposeWebAppRootParam));103 }104 105 }
1 package com.cnblogs.yjmyzz.util; 2 3 import java.io.File; 4 import java.io.FileNotFoundException; 5 import java.net.URL; 6 7 import org.slf4j.LoggerFactory; 8 import org.springframework.util.ResourceUtils; 9 import org.springframework.util.SystemPropertyUtils;10 11 import ch.qos.logback.classic.LoggerContext;12 import ch.qos.logback.classic.joran.JoranConfigurator;13 import ch.qos.logback.core.joran.spi.JoranException;14 15 public abstract class LogbackConfigurer {16 17 /** Pseudo URL prefix for loading from the class path: "classpath:" */18 public static final String CLASSPATH_URL_PREFIX = "classpath:";19 20 /** Extension that indicates a logback XML config file: ".xml" */21 public static final String XML_FILE_EXTENSION = ".xml";22 23 private static LoggerContext lc = (LoggerContext) LoggerFactory24 .getILoggerFactory();25 private static JoranConfigurator configurator = new JoranConfigurator();26 27 /**28 * Initialize logback from the given file location, with no config file29 * refreshing. Assumes an XML file in case of a ".xml" file extension, and a30 * properties file otherwise.31 * 32 * @param location33 * the location of the config file: either a "classpath:"34 * location (e.g. "classpath:mylogback.properties"), an absolute35 * file URL (e.g.36 * "file:C:/logback.properties), or a plain absolute path in the file system (e.g. "37 * C:/logback.properties")38 * @throws FileNotFoundException39 * if the location specifies an invalid file path40 */41 public static void initLogging(String location)42 throws FileNotFoundException {43 String resolvedLocation = SystemPropertyUtils44 .resolvePlaceholders(location);45 URL url = ResourceUtils.getURL(resolvedLocation);46 if (resolvedLocation.toLowerCase().endsWith(XML_FILE_EXTENSION)) {47 // DOMConfigurator.configure(url);48 configurator.setContext(lc);49 lc.reset();50 try {51 configurator.doConfigure(url);52 } catch (JoranException ex) {53 throw new FileNotFoundException(url.getPath());54 }55 lc.start();56 }57 // else {58 // PropertyConfigurator.configure(url);59 // }60 }61 62 /**63 * Shut down logback, properly releasing all file locks.64 *65 * This isn't strictly necessary, but recommended for shutting down logback66 * in a scenario where the host VM stays alive (for example, when shutting67 * down an application in a J2EE environment).68 */69 public static void shutdownLogging() {70 lc.stop();71 }72 73 /**74 * Set the specified system property to the current working directory.75 *
76 * This can be used e.g. for test environments, for applications that77 * leverage logbackWebConfigurer's "webAppRootKey" support in a web78 * environment.79 * 80 * @param key81 * system property key to use, as expected in logback82 * configuration (for example: "demo.root", used as83 * "${demo.root}/WEB-INF/demo.log")84 * @see org.springframework.web.util.logbackWebConfigurer85 */86 public static void setWorkingDirSystemProperty(String key) {87 System.setProperty(key, new File("").getAbsolutePath());88 }89 90 }
2.3 JBOSS EAP 6+ 的特殊处理
jboss 默认已经集成了sf4j模块,会与上面新加的3个类有冲突,app启动时会报错:
java.lang.ClassCastException: org.slf4j.impl.Slf4jLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
所以,需要手动排除掉jboss默认的slf4j模块,在web-inf下创建名为jboss-deployment-structure.xml的文件,内容如下:
1 23 4 115 106 7 8 9
2.4 最后将logback.xml放到resouces目录下即可(打包后,会自动复制到classpath目录下)