zoukankan      html  css  js  c++  java
  • 【Log4J 系列】:log4j 整合SpringMVC+MyBatis 实现日志记录(01)

    一、准备工作

    1、工程目录

      

    2、所需jar包 

         <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>

    二、配置log4j

    1、修改log4j DailyRollingFileAppender.java 这个类太大就不复制了,直接看关键性代码

    由于log4j自带的DailyRollingFileAppender在根据时间来生成日志文件时控制台日志会显示Failed to rename(无法重命名)

    所以没办法根据log4j提供的方法去根据日期生成日志文件,我们先去看看log4j的这个BUG

    由于tomcat在运行期间会一直占用该文件,在调用该方法的时候就会抛出这个异常来,接下来我们需要创建自己的DailyRollingFileAppender类,

    log4j提供的DailyRollingFileAppender类有很多方法在我们的项目中是无法重写的在这里我们去继承DailyRollingFileAppender父类FileAppender.java

    文件来达到我们想要的效果

    public class CmsDailyRollingFileAppender extends FileAppender

     在这里只为大家演示关键性代码,PS:这段代码是在网上Copy下来的,在我们自己定义的DailyRollingFileAppender 添加一个复制方法用来处理log4j的这个bug

    boolean copy(File src, File dst) throws IOException {  
              try {  
               InputStream in = new FileInputStream(src);  
               
               OutputStream out = new FileOutputStream(dst);  
               
               // Transfer bytes from in to out  
               byte[] buf = new byte[8192];  
               int len;  
               while ((len = in.read(buf)) > 0) {  
                out.write(buf, 0, len);  
               }  
               in.close();  
               out.close();  
               return true;  
              } catch (FileNotFoundException e) {  
               LogLog.error("源文件不存在,或者目标文件无法被识别." );  
               return false;  
              } catch (IOException e) {  
               LogLog.error("文件读写错误.");  
               return false; 
              }
          }

    修改rollOver()方法,找到这段代码干掉替换成 copy方法保存文件

    2.配置log4j.properties文件

    # 这里的INFO,Stdout,D,E 看官们可以理解为变量,也可以说是输出平台,在下面我们可以看到
    log4j.rootLogger = info,stdout,D,E # 控制台输出,stdout在这里就对应了上面的变量,consoleAppender 看名字也可以明白这个是控制台输出日志信息 log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    # 这里没人的是System.out,也就是输出 out输出是黑色字体,err输出的字体是红色 log4j.appender.stdout.Target
    = System.out
    # layout是指布局,也就是说输出日志信息的格式样式,在这里我们使用的是log4j提供的 log4j.appender.stdout.layout
    = org.apache.log4j.PatternLayout
    # 这里就是指定我们日志文件以哪一种格式去输出 log4j.appender.stdout.layout.ConversionPattern
    = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} %m%n
    # INFO级别输出日志文件
    # 这里可以看到使用的是我们自定义的DailyRollingFileAppender.java log4j.appender.D
    = com.nc.rms.log4j.CmsDailyRollingFileAppender
    # 指定日志输出位置${catalina.home}这个是tomcat的变量,不了解的看官可以自行脑补下 log4j.appender.D.File
    = ${catalina.home}/logs/rms/info/info
    #这个的意思是指是追加还是覆盖 默认是 true true是追加 false是覆盖 log4j.appender.D.Append
    = true
    # 这个是指日志输出的级别在这里指定的是 INFO级别 log4j.appender.D.Threshold = INFO
    #这个就不做介绍了 log4j.appender.D.layout
    = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
    #这里就根据时间来生成日志文件了,在这里为了演示定义的是每分钟生成日志文件 log4j.appender.D.DatePattern
    = '.'yyyy-MM-dd-HH-mm'.log' # ERROR级别输出日志文件
    # 这个跟上面一样 只不过是日志级别是 ERROR级的,方便我们直接查看系统异常信息 log4j.appender.E
    = com.nc.rms.log4j.CmsDailyRollingFileAppender log4j.appender.E.File =${catalina.home}/logs/rms/error/error log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n log4j.appender.E.DatePattern = '.'yyyy-MM-dd-HH-mm'.log'
    # 记录日志至数据库
    # 这里定义了数据源 log4j.appender.db
    =com.nc.rms.log4j.JndiDSAppender
    # 这玩意就是每次缓存多少条数据然后插入数据库,为了演示这里设置为1 log4j.appender.db.BufferSize
    =1
    # 这里使用的是tomcat的中提供的数据库连接池
    log4j.appender.db.jndiName=java:comp/env/jdbc/DefaultDS
    # 看名字也该明白这里是定义Sql语句的啦 log4j.appender.db.sql
    =insert into my_log (ID,DATE,MESSAGE,USER_NAME) values (REPLACE(UUID(), '-', ''),'%d{yyyy-MM-dd HH:mm:ss}','%m','%X{userName}')
    log4j.appender.db.layout
    =org.apache.log4j.PatternLayout
    # 这里定义的哪些包下的日志信息需要记录到数据库当中 log4j.logger.com.nc.rms.manage.web
    =info,db log4j.logger.com.nc.rms.service=info,db log4j.logger.com.nc.rms.dao=info,db

    3. 在将日志记录进数据库时候 log4j.appender.db=com.nc.rms.log4j.JndiDSAppender 在这里定义了我们的DataSource

    log4j.appender.db.jndiName=java:comp/env/jdbc/DefaultDS这玩意不了解的朋友可以看下tomcat,context.xml文件

    接下来我们去看看如何获取数据源,在这里我们需要去继承org.apache.log4j.jdbc.JDBCAppender.java

    package com.nc.rms.log4j;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    import javax.sql.DataSource;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.log4j.jdbc.JDBCAppender;
    import org.apache.log4j.spi.LoggingEvent;
    
    public class JndiDSAppender extends JDBCAppender {
    
        protected DataSource ds = null;
        protected String jndiName;
    
        public void setJndiName(String jndiName) {
            this.jndiName = jndiName;
        }
        
        protected synchronized void init() {
            if (ds != null) {
                return;
            }
            try {
                InitialContext context = new InitialContext();
                ds = (DataSource) context.lookup(jndiName);
            } catch (NamingException e) {
                this.errorHandler.error(e.getMessage());
            }
        }
        @Override
        public synchronized void doAppend(LoggingEvent event) {
            if (!StringUtils.isEmpty(name) && "db".equals(name) && closed) {
                closed = false;
            }
            super.doAppend(event);
        }
        
         @Override  
        protected Connection getConnection() throws SQLException {  
            while(ds==null){
                init();
            }
            
            Connection conn = ds.getConnection();
            conn.setAutoCommit(true);
            
            return conn;
        }
        
        @Override  
        protected void closeConnection(Connection conn) {  
            try {  
                if(conn!=null&&!conn.isClosed()) {
                    conn.close();  
                } 
            } catch (SQLException e) {  
                this.errorHandler.error(e.getMessage());  
            }  
        }  
    }

    4.配置Log4jMDCUserFilter过滤器主要是用于配置登录用户

    package com.nc.rms.log4j;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.log4j.MDC;
    
    import com.nc.rms.bean.User;
    
    
    /**
     * log4j
     * @author Carl
     *
     */
    public class Log4jMDCUserFilter implements Filter {
    
        private final String LOG4J_USER_ACCOUNT = "account";
    
        private final String LOG4J_USER_NAME = "userName";
        
        private final String LOG4J_REMOTE_UNITID = "remoteUnitId";
    
        
        public Log4jMDCUserFilter() {
        }
    
        public void destroy() {
    
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            try {
                User user = (User) req.getSession().getAttribute("user");
                if (user != null) {
                    MDC.put(LOG4J_REMOTE_UNITID, user.getName());
                    MDC.put(LOG4J_USER_ACCOUNT, user.getName());
                    MDC.put(LOG4J_USER_NAME, user.getName());
                }else {
                    MDC.put(LOG4J_REMOTE_UNITID, LOG4J_REMOTE_UNITID);
                    MDC.put(LOG4J_USER_ACCOUNT, LOG4J_USER_ACCOUNT);
                    MDC.put(LOG4J_USER_NAME, LOG4J_USER_NAME);
                }
            } catch (Exception e) {
            }
            chain.doFilter(request, response);
        }
    
        public void init(FilterConfig fConfig) throws ServletException {
    
        }
    
    }

    5.配置web.xml文件,写了这么多,认真的朋友或许已经发现不管那个框架哪门技术都离不开配置web.xml

    喜欢看web项目源码的朋友可以先从web.xml 去了解该项目究竟使用了哪些技术。废话点到为止看配置

    <!-- 配置log4j  %X{userName} ,主要用于将日志记录数据库中,如:userName 做了什么样的操作-->
        <filter>
            <filter-name>Log4jMDCUserFilter</filter-name>
            <filter-class>com.nc.rms.log4j.Log4jMDCUserFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>Log4jMDCUserFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
        <!--设置log4j的配置文件位置 -->
        <context-param>
            <param-name>log4jConfigLocation</param-name>
            <param-value>classpath:conf/log4j.properties</param-value>
        </context-param>
        
        <!--使用监听加载log4j的配置文件 -->
        <listener>
            <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
        </listener>

    一切准备就绪运行起来看看效果吧!

    数据库记录正常

     

    日志文件按照分钟生成成功。

  • 相关阅读:
    time和/usr/bin/time
    Linux系统-real/user/sys time
    PL/SQL:集合类型 (定义,分类,使用场景,集合方法)
    关于Android开发中使用的XML
    Android Studio 常用快捷键
    Android中Adapter总结
    Android 中的 Context
    Android Studio 项目结构
    Android Studio 连接真机调试
    Android Studio 入门
  • 原文地址:https://www.cnblogs.com/ncjava/p/5850416.html
Copyright © 2011-2022 走看看