首页 > 代码库 > logback + slf4j + jboss + spring mvc

logback + slf4j + jboss + spring mvc

logback、log4j、log4j2 全是以同一个人为首的团伙搞出来的(日志专业户!),这几个各有所长,log4j性能相对最差,log4j2性能不错,但是目前跟mybatis有些犯冲(log4j2的当前版本,已经将AbstractLoggerWrapper更名成ExtendedLoggerWrapper,但是mybatis依赖的仍然是旧版本的log4j2,所以mybatis使用log4j2会报错),说到日志,还要注意另一外项目SLF4J( java的世界里,记日志的组件真是多!),SLF4J只一个接口标准,并不提供实现(就好象JSF/JPA 与 RichFaces/Hibernate的关系类似),而LogBack是SLF4J的一个实现,下面介绍logback的基本用法

一、基本用法

1.1 maven依赖项

 1         <!-- log --> 2         <dependency> 3             <groupId>org.slf4j</groupId> 4             <artifactId>slf4j-api</artifactId> 5             <version>1.7.7</version> 6         </dependency> 7  8         <dependency> 9             <groupId>ch.qos.logback</groupId>10             <artifactId>logback-core</artifactId>11             <version>1.1.2</version>12         </dependency>13 14         <dependency>15             <groupId>ch.qos.logback</groupId>16             <artifactId>logback-classic</artifactId>17             <version>1.1.2</version>18         </dependency>
View Code

1.2 配置文件logback.xml

 1 <?xml version="1.0" encoding="UTF-8" ?> 2 <configuration scan="true" scanPeriod="1800 seconds" 3     debug="false"> 4  5     <property name="USER_HOME" value="logs" /> 6     <property scope="context" name="FILE_NAME" value="mylog-logback" /> 7  8     <timestamp key="byDay" datePattern="yyyy-MM-dd" /> 9 10     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">11         <encoder>12             <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n13             </pattern>14         </encoder>15     </appender>16 17     <appender name="file"18         class="ch.qos.logback.core.rolling.RollingFileAppender">19         <file>${USER_HOME}/${FILE_NAME}.log</file>20 21         <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">22             <fileNamePattern>${USER_HOME}/${byDay}/${FILE_NAME}-${byDay}-%i.log.zip23             </fileNamePattern>24             <minIndex>1</minIndex>25             <maxIndex>10</maxIndex>26         </rollingPolicy>27 28         <triggeringPolicy29             class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">30             <maxFileSize>5MB</maxFileSize>31         </triggeringPolicy>32         <encoder>33             <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n34             </pattern>35         </encoder>36 37     </appender>38 39     <logger name="com.cnblogs.yjmyzz.App2" level="debug" additivity="true">40         <appender-ref ref="file" />41         <!-- <appender-ref ref="STDOUT" /> -->42     </logger>43 44     <root level="info">45         <appender-ref ref="STDOUT" />46     </root>47 </configuration>
View Code

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 }
View Code

运行后,会在当前目录下创建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 <!-- Spring --> 2         <dependency> 3             <groupId>org.springframework</groupId> 4             <artifactId>spring-core</artifactId> 5             <version>${springframework.version}</version> 6         </dependency> 7         <dependency> 8             <groupId>org.springframework</groupId> 9             <artifactId>spring-beans</artifactId>10             <version>${springframework.version}</version>11         </dependency>12         <dependency>13             <groupId>org.springframework</groupId>14             <artifactId>spring-context</artifactId>15             <version>${springframework.version}</version>16         </dependency>17         <dependency>18             <groupId>org.springframework</groupId>19             <artifactId>spring-web</artifactId>20             <version>${springframework.version}</version>21         </dependency>22         <dependency>23             <groupId>org.springframework</groupId>24             <artifactId>spring-webmvc</artifactId>25             <version>${springframework.version}</version>26         </dependency>27         <dependency>28             <groupId>org.springframework</groupId>29             <artifactId>spring-expression</artifactId>30             <version>${springframework.version}</version>31         </dependency>32 33         <!-- logback -->34         <dependency>35             <groupId>org.slf4j</groupId>36             <artifactId>slf4j-api</artifactId>37             <version>1.7.7</version>38         </dependency>        39 40         <dependency>41             <groupId>ch.qos.logback</groupId>42             <artifactId>logback-core</artifactId>43             <version>1.1.2</version>44         </dependency>45 46         <dependency>47             <groupId>ch.qos.logback</groupId>48             <artifactId>logback-classic</artifactId>49             <version>1.1.2</version>50         </dependency>51 52         <!-- Servlet -->53         <dependency>54             <groupId>javax.servlet</groupId>55             <artifactId>servlet-api</artifactId>56             <version>2.5</version>57             <scope>provided</scope>58         </dependency>
View Code

2.2 web.xml里增加下面的内容

1 <!-- logback-begin -->2     <context-param>3         <param-name>logbackConfigLocation</param-name>4         <param-value>classpath:logback.xml</param-value>5     </context-param>6     <listener>7         <listener-class>com.cnblogs.yjmyzz.util.LogbackConfigListener</listener-class>8     </listener>9     <!-- logback-end -->
View Code

其中com.cnblogs.yjmyzz.util.LogbackConfigListener 是自己开发的类,代码如下:(从网上掏来的)

 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 }
LogbackConfigListener
  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 }
LogbackWebConfigurer
 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      * <p>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      * <p>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 }
LogbackConfigurer

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 <?xml version="1.0" encoding="UTF-8"?> 2 <jboss-deployment-structure> 3     <deployment>         4         <exclusions> 5             <module name="org.slf4j" /> 6             <module name="org.slf4j.impl" /> 7             <module name="org.slf4j.jcl-over-slf4j" /> 8             <module name="org.slf4j.ext" />             9         </exclusions>10     </deployment>11 </jboss-deployment-structure>
View Code

2.4 最后将logback.xml放到resouces目录下即可(打包后,会自动复制到classpath目录下)

 

logback + slf4j + jboss + spring mvc