SpringMVC與LogBack整合
阿新 • • 發佈:2019-01-12
最近在做專案中需要用到日誌,本來選取的是Log4j,最後經過對比之後還是發現LogBack在效能上比Log4j有優勢。至於有什麼好處,請參考下面這篇文章。
從Log4j遷移到LogBack的理由
下面廢話不多說了,就看一下,如何來把LogBack整合到我們的web專案中吧。本人前臺用的是SpringMVC。
jar包配置 如果要使用LogBack做為日誌的外掛的話,需要的jar包有如下,直接看一下Maven依賴
<span style="font-family:Comic Sans MS;font-size:18px;"><dependency> <groupId>org.slf4j</groupId> <artifactId> slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version >1.1.3</version> <scope>compile</scope> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.3</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> </exclusions> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-access</artifactId> <version>1.1.3</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> </exclusions> <scope>compile</scope> </dependency></span>
Web.xml
在web專案中需要通過web.xml來載入我們所需要的LogBack.xml具體如下
<span style="font-family:Comic Sans MS;font-size:18px;"><?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- logback-begin --> <context-param> <param-name>logbackConfigLocation</param-name> <param-value> classpath:logback.xml</param-value> </context-param> <listener> <listener-class>com.util.LogbackConfigListener</listener-class> </listener> <!-- logback-end --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:springMVC-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 這裡一定要是/根據Servlet規範來的 --> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping></web-app></span>
上面的XML中用到了自定義的監聽器,分別是三個類,如下所示
LogbackConfigListener類
<span style="font-family:Comic Sans MS;font-size:18px;">package com.util;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;public class LogbackConfigListener implements ServletContextListener { public void contextInitialized(ServletContextEvent event) { LogbackWebConfigurer.initLogging(event.getServletContext()); } public void contextDestroyed(ServletContextEvent event) { LogbackWebConfigurer.shutdownLogging(event.getServletContext()); }}</span>
LogbackConfigurer類
<span style="font-family:Comic Sans MS;font-size:18px;">package com.util;import java.io.File;import java.io.FileNotFoundException;import java.net.URL;import org.slf4j.LoggerFactory;import org.springframework.util.ResourceUtils;import org.springframework.util.SystemPropertyUtils;import ch.qos.logback.classic.LoggerContext;import ch.qos.logback.classic.joran.JoranConfigurator;import ch.qos.logback.core.joran.spi.JoranException;public abstract class LogbackConfigurer { /** Pseudo URL prefix for loading from the class path: "classpath:" */ public static final String CLASSPATH_URL_PREFIX = "classpath:"; /** Extension that indicates a logback XML config file: ".xml" */ public static final String XML_FILE_EXTENSION = ".xml"; private static LoggerContext lc = (LoggerContext) LoggerFactory .getILoggerFactory(); private static JoranConfigurator configurator = new JoranConfigurator(); /** * Initialize logback from the given file location, with no config file * refreshing. Assumes an XML file in case of a ".xml" file extension, and a * properties file otherwise. * * @param location * the location of the config file: either a "classpath:" * location (e.g. "classpath:mylogback.properties"), an absolute * file URL (e.g. * "file:C:/logback.properties), or a plain absolute path in the file system (e.g. " * C:/logback.properties") * @throws FileNotFoundException * if the location specifies an invalid file path */ public static void initLogging(String location) throws FileNotFoundException { String resolvedLocation = SystemPropertyUtils .resolvePlaceholders(location); URL url = ResourceUtils.getURL(resolvedLocation); if (resolvedLocation.toLowerCase().endsWith(XML_FILE_EXTENSION)) { // DOMConfigurator.configure(url); configurator.setContext(lc); lc.reset(); try { configurator.doConfigure(url); } catch (JoranException ex) { throw new FileNotFoundException(url.getPath()); } lc.start(); } // else { // PropertyConfigurator.configure(url); // } } /** * Shut down logback, properly releasing all file locks. * <p> * This isn't strictly necessary, but recommended for shutting down logback * in a scenario where the host VM stays alive (for example, when shutting * down an application in a J2EE environment). */ public static void shutdownLogging() { lc.stop(); } /** * Set the specified system property to the current working directory. * <p> * This can be used e.g. for test environments, for applications that * leverage logbackWebConfigurer's "webAppRootKey" support in a web * environment. * * @param key * system property key to use, as expected in logback * configuration (for example: "demo.root", used as * "${demo.root}/WEB-INF/demo.log") * @see org.springframework.web.util.logbackWebConfigurer */ public static void setWorkingDirSystemProperty(String key) { System.setProperty(key, new File("").getAbsolutePath()); }}</span>
LogbackWebConfigurer類
<span style="font-family:Comic Sans MS;font-size:18px;">package com.util;import java.io.FileNotFoundException;import javax.servlet.ServletContext;import org.springframework.util.ResourceUtils;import org.springframework.util.SystemPropertyUtils;import org.springframework.web.util.WebUtils;public abstract class LogbackWebConfigurer { /** Parameter specifying the location of the logback config file */ public static final String CONFIG_LOCATION_PARAM = "logbackConfigLocation"; /** * Parameter specifying the refresh interval for checking the logback config * file */ public static final String REFRESH_INTERVAL_PARAM = "logbackRefreshInterval"; /** Parameter specifying whether to expose the web app root system property */ public static final String EXPOSE_WEB_APP_ROOT_PARAM = "logbackExposeWebAppRoot"; /** * Initialize logback, including setting the web app root system property. * * @param servletContext * the current ServletContext * @see WebUtils#setWebAppRootSystemProperty */ public static void initLogging(ServletContext servletContext) { // Expose the web app root system property. if (exposeWebAppRoot(servletContext)) { WebUtils.setWebAppRootSystemProperty(servletContext); } // Only perform custom logback initialization in case of a config file. String location = servletContext .getInitParameter(CONFIG_LOCATION_PARAM); if (location != null) { // Perform actual logback initialization; else rely on logback's // default initialization. try { // Return a URL (e.g. "classpath:" or "file:") as-is; // consider a plain file path as relative to the web application // root directory. if (!ResourceUtils.isUrl(location)) { // Resolve system property placeholders before resolving // real path. location = SystemPropertyUtils .resolvePlaceholders(location); location = WebUtils.getRealPath(servletContext, location); } // Write log message to server log. servletContext.log("Initializing logback from [" + location + "]"); // Initialize without refresh check, i.e. without logback's // watchdog thread. LogbackConfigurer.initLogging(location); } catch (FileNotFoundException ex) { throw new IllegalArgumentException( "Invalid 'logbackConfigLocation' parameter: " + ex.getMessage()); } } } /** * Shut down logback, properly releasing all file locks and resetting the * web app root system property. * * @param servletContext * the current ServletContext * @see WebUtils#removeWebAppRootSystemProperty */ public static void shutdownLogging(ServletContext servletContext) { servletContext.log("Shutting down logback"); try { LogbackConfigurer.shutdownLogging(); } finally { // Remove the web app root system property. if (exposeWebAppRoot(servletContext)) { WebUtils.removeWebAppRootSystemProperty(servletContext); } } } /** * Return whether to expose the web app root system property, checking the * corresponding ServletContext init parameter. * * @see #EXPOSE_WEB_APP_ROOT_PARAM */ private static boolean exposeWebAppRoot(ServletContext servletContext) { String exposeWebAppRootParam = servletContext .getInitParameter(EXPOSE_WEB_APP_ROOT_PARAM); return (exposeWebAppRootParam == null || Boolean .valueOf(exposeWebAppRootParam)); }}</span>
logback.XML配置 下面來看一下這個xml是如何配置的
<span style="font-family:Comic Sans MS;font-size:18px;"><?xml version="1.0" encoding="UTF-8"?><!-- ROOT 節點 --><!-- 屬性描述 scan:性設定為true時,配置檔案如果發生改變,將會被重新載入,預設值為true scanPeriod:設定監測配置檔案是否有修改的時間間隔,如果沒有給出時間單位,預設單位是毫秒。當scan為true時,此屬性生效。預設的時間間隔為1分鐘。 debug:當此屬性設定為true時,將打印出logback內部日誌資訊,實時檢視logback執行狀態。預設值為false。 --><configuration scan="true" scanPeriod="60 seconds" debug="false"> <!-- 定義日誌檔案 輸入位置,注意此處的/ --> <property name="log_dir" value="E:/logs" /> <!-- 日誌最大的歷史 60天 --> <property name="maxHistory" value="60"></property> <!-- 控制檯輸出日誌 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </encoder> </appender> <!-- 出錯日誌 appender --> <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 在多數的Log工具中,級別是可以傳遞,例如如果指定了日誌輸出級別為DEBUG, 那麼INFO、ERROR級別的log也會出現在日誌檔案。這種預設給程式的除錯帶來了很多的麻煩 通過配置Filter 來嚴格控制日誌輸入級別 <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR/level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滾 daily --> <fileNamePattern>${log_dir}/error-log-%d{yyyy-MM-dd}.log </fileNamePattern> <!-- 日誌最大的歷史 60天 --> <maxHistory>${maxHistory}</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </encoder> </appender> <!-- INFO 日誌 appender --> <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滾 daily --> <fileNamePattern>${log_dir}/info-log-%d{yyyy-MM-dd}.log </fileNamePattern> <!-- 日誌最大的歷史 60天 --> <maxHistory>${maxHistory}</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </encoder> </appender> <!-- 訪問日誌 appender --> <appender name="ACCESS" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滾 daily --> <fileNamePattern>${log_dir}/access-log-%d{yyyy-MM-dd}.log </fileNamePattern> <!-- 日誌最大的歷史 60天 --> <maxHistory>${maxHistory}</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </encoder> </appender> <!-- 系統使用者操作日誌 appender --> <appender name="SYS-USER" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滾 daily --> <fileNamePattern>${log_dir}/sys_user-log-%d{yyyy-MM-dd}.log </fileNamePattern> <!-- 日誌最大的歷史 60天 --> <maxHistory>${maxHistory}</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </encoder> </appender> <!-- 列印SQL輸出 --> <logger name="java.sql.Connection" level="DEBUG" /> <logger name="java.sql.Statement" level="DEBUG" /> <logger name="java.sql.PreparedStatement" level="DEBUG" /> <!--error錯誤日誌 additivity="false"表示不向上傳遞 --> <!-- <logger name="com.test" level="error" > --> <!-- <appender-ref ref="ERROR" /> --> <!-- </logger> --> <!--info日誌 --> <logger name="com.test" level="info" additivity="false"> <appender-ref ref="INFO" /> </logger> <!--訪問日誌 --> <!-- <logger name="com.test" level="info" additivity="false"> --> <!-- <appender-ref ref="ACCESS" /> --> <!-- </logger> --> <!--系統使用者操作日誌 --> <!-- <logger name="com.test" level="info" additivity="false"> --> <!-- <appender-ref ref="SYS-USER" /> --> <!-- </logger> --> <root> <level value="INFO" /> <appender-ref ref="stdout" /> </root></configuration></span>
關於這個XML檔案的詳細講解請參考 http://blog.csdn.net/haidage/article/details/6794509
再分享一下我老師大神的人工智慧教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智慧的隊伍中來!https://blog.csdn.net/jiangjunshow