首页 > 代码库 > 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>
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>
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 <!-- 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>
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 -->
其中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 }
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 * <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 }
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>
2.4 最后将logback.xml放到resouces目录下即可(打包后,会自动复制到classpath目录下)
logback + slf4j + jboss + spring mvc