logback、log4j、log4j2 全是以同一个人为首的团伙搞出来的(日志专业户!),这几个各有所长,log4j性能相对最差,log4j2性能不错,但是目前跟mybatis有些犯冲(log4j2的当前版本,已经将AbstractLoggerWrapper更名成ExtendedLoggerWrapper,但是mybatis 2.3.7依赖的仍然是旧版本的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%n
13 </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.zip
23 </fileNamePattern>
24 <minIndex>1</minIndex>
25 <maxIndex>10</maxIndex>
26 </rollingPolicy>
27
28 <triggeringPolicy
29 class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
30 <maxFileSize>5MB</maxFileSize>
31 </triggeringPolicy>
32 <encoder>
33 <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n
34 </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 是自己开发的类,代码如下:(从网上掏来的)
注:该处理方式同样适用于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 = servletContext
100 .getInitParameter(EXPOSE_WEB_APP_ROOT_PARAM);
101 return (exposeWebAppRootParam == null || Boolean
102 .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) LoggerFactory
24 .getILoggerFactory();
25 private static JoranConfigurator configurator = new JoranConfigurator();
26
27 /**
28 * Initialize logback from the given file location, with no config file
29 * refreshing. Assumes an XML file in case of a ".xml" file extension, and a
30 * properties file otherwise.
31 *
32 * @param location
33 * the location of the config file: either a "classpath:"
34 * location (e.g. "classpath:mylogback.properties"), an absolute
35 * 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 FileNotFoundException
39 * if the location specifies an invalid file path
40 */
41 public static void initLogging(String location)
42 throws FileNotFoundException {
43 String resolvedLocation = SystemPropertyUtils
44 .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 logback
66 * in a scenario where the host VM stays alive (for example, when shutting
67 * 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 that
77 * leverage logbackWebConfigurer's "webAppRootKey" support in a web
78 * environment.
79 *
80 * @param key
81 * system property key to use, as expected in logback
82 * configuration (for example: "demo.root", used as
83 * "${demo.root}/WEB-INF/demo.log")
84 * @see org.springframework.web.util.logbackWebConfigurer
85 */
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目录下)