Log4j寫入數據庫詳解

log4j是一個優秀的開源日誌記錄項目,咱們不只能夠對輸出的日誌的格式自定義,還能夠本身定義日誌輸出的目的地,好比:屏幕,文本文件,數據庫,甚至能經過socket輸出。本節主要講述如何將日誌信息輸入到數據庫(能夠插入任何數據庫,在此主要以MSSQL爲例進行詳解)。
用log4j將日誌寫入數據庫主要用到是log4j包下的JDBCAppender類,它提供了將日誌信息異步寫入數據的功能,咱們能夠直接使用這個類將咱們的日誌信息寫入數據庫;也能夠擴展JDBCAppender類,就是將JDBCAppender類做爲基類。下面將經過一個實例來說解log4j是如何將日誌信息寫入數據庫的。
咱們的需求:咱們在軟件開發的過程當中須要將調試信息、操做信息等記錄下來,以便後面的審計,這些日誌信息包括用戶ID、用戶姓名、操做類、路徑、方法、操做時間、日誌信息。
設計思想:咱們採用JDBCAppender類直接將日誌信息插入數據庫,全部只須要在配置文件配置此類就能夠;要得到用戶信息須要用過濾器來實現;(假如不須要用戶的信息,就不須要設計過濾器,其實大部分狀況下都是須要這些用戶信息,尤爲是在web應用開發中)在日誌信息中得到用戶信息,就的經過過濾器的request或session對象,從session中拿到用戶信息怎樣傳到log4j呢,log4j爲咱們提供了MDC(MDC是log4j種很是有用類,它們用於存儲應用程序的上下文信息(context infomation),從而便於在log中使用這些上下文信息。MDC內部使用了相似map的機制來存儲信息,上下文信息也是每一個線程獨立地儲存,所不一樣的是信息都是以它們的key值存儲在」map」中。相對應的方法,java

MDC.put(key, value); MDC.remove(key); MDC.get(key);web

在配置PatternLayout的時候使用:%x{key}來輸出對應的value)。有了MDC,咱們能夠在過濾器中先得到用戶信息,再用MDC.Put(「key」)方法,log在執行sql語句時經過%x{key}來輸出對應的value。spring


實現步驟:
一、在你的項目中要確保有log4j和commons-logging這兩個jar文件;
二、設置要你要插入日誌信息的表結構sql

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[WDZLOG]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[WDZLOG]
GO

CREATE TABLE [dbo].[WDZLOG] (
    [WDZLOGID] [int] IDENTITY (1, 1) NOT NULL ,
    [LogName] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//用戶ID
    [UserName] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//用戶姓名
    [Class] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//類名
    [Mothod] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL //,方法名
    [CreateTime] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//產生時間
    [LogLevel] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,//日誌級別
    [MSG] [varchar] (555) COLLATE Chinese_PRC_CI_AS NULL //日誌信息
) ON [PRIMARY]
GO

三、配置文件(摘自咱們的項目)後面將對此配置文件進行詳細講解,它也log4j的核心部分。數據庫

log4j.properties
log4j.rootLogger=INFO,stdout
            
log4j.logger.org.springframework.web.servlet=INFO,db

log4j.logger.org.springframework.beans.factory.xml=INFO
log4j.logger.com.neam.stum.user=INFO,db

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p [%c] - - <%m>%n

log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.File=${webapp.root}/WEB-INF/logs/exppower.log
log4j.appender.logfile.DatePattern=.yyyy-MM-dd
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] wang- <%m>%n

########################

# JDBC Appender

#######################


#log4j.logger.business=INFO,db
#log4j.appender.db=com.neam.commons.MyJDBCAppender
log4j.appender.db=JDBCExtAppender

log4j.appender.db.BufferSize=10

log4j.appender.db.sqlname=log

log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver
                      
log4j.appender.db.URL=jdbc:jtds:SqlServer://localhost:1433;DatabaseName=pubs

log4j.appender.db.user=sa

log4j.appender.db.password=sa

log4j.appender.db.sql=insert into WDZLOG (LogName,UserName,Class,Mothod,createTime,LogLevel,MSG) values ('%X{userId}','%X{userName}','%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%m')

log4j.appender.db.layout=org.apache.log4j.PatternLayout

四、編寫過濾器(ResFilter.java)apache

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 javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.log4j.MDC;

import com.neam.domain.User;

public class ResFilter implements Filter{

     
    private final static double DEFAULT_USERID= Math.random()*100000.0;  

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
           FilterChain chain) throws IOException, ServletException {
       HttpServletRequest req=(HttpServletRequest)request;
        HttpSession session= req.getSession();
        if (session==null){
            MDC.put("userId",DEFAULT_USERID);  
        }
        else{
            User customer=(User)session.getAttribute("user");
            if (customer==null){
                MDC.put("userId",DEFAULT_USERID);
                MDC.put("userName",DEFAULT_USERID);
            }
            else
            {
                MDC.put("userId",customer.getName());
                MDC.put("userName",customer.getName());
            }
        }
        //logger.info("test for MDC.");

       chain.doFilter(request, response);
    }
    public void init(FilterConfig Config) throws ServletException {
//     this.filterConfig = Config;
//     String ccc = Config.getServletContext().getInitParameter("cherset");
//     this.targetEncoding = Config.getInitParameter("cherset");

    }
}

五、在須要寫入日誌的地方引入緩存

private Log logger = LogFactory.getLog(this.getClass());

在具體方法中就能夠寫入日誌
logger.info("");
logger.debug("");
logger.warn("");
logger.error("");

配置文件詳解:
log4j.properties
log4j.properties
log4j.rootLogger=INFO,stdoutsession

 //配置根Logger,其語法爲:
log4j.rootLogger = [ level ] , appenderName1, appenderName2, …
level : 是日誌記錄的優先級,分爲OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定義的級別。Log4j建議只使用四個級別,優先級從高到低分別是ERROR、WARN、INFO、DEBUG。經過在這裏定義的級別,您能夠控制到應用程序中相應級別的日誌信息的開關。好比在這裏定義了INFO級別,則應用程序中全部DEBUG級別的日誌信息將不被打印出來。
appenderName:就是指定日誌信息輸出到哪一個地方。您能夠同時指定多個輸出目的地。
例如:log4j.rootLogger=info,A1,B2,C3 配置了3個輸出地方咱們能夠設置讓A1在控制檯輸出;B2生產日誌文件;C3讓日誌信息插入數據庫中。
本例中是將全部的日誌信息在控制檯打印出來。 
log4j.logger.org.springframework.web.servlet=INFO,db
//設置將spring下包的某些類的日誌信息寫入數據庫中,而且在控制檯上打印出來。(是經過log4j.rootLogger=INFO,stdout來體現的)db是將日誌信息寫入數據庫中
log4j.logger.org.springframework.beans.factory.xml=INFO
//本實例中爲了讓某些包下的日誌信息能寫入數據庫
log4j.logger.com.neam.stum.user=INFO,db
//設置本身某個模塊下的日誌信息既在控制檯上打印並且往數據庫中保存

//下面是配置在控制檯上打印日誌信息,在這裏就再也不仔細描述了
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p [%c] - - <%m>%n

//下面是配置將日誌信息寫入文件中,在這裏也就再也不仔細描述了
log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.File=${webapp.root}/WEB-INF/logs/exppower.log
log4j.appender.logfile.DatePattern=.yyyy-MM-dd
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] wang- <%m>%n

########################

# JDBC Appender

#######################


#log4j.appender.db=com.neam.commons.MyJDBCAppender
//下面是配置將日誌信息插入數據庫,
log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender
//配置輸出目標爲數據庫(假如要將日誌在控制檯輸出,配置爲log4j.appender. stdout =org.apache.log4j.ConsoleAppender;將日誌寫入文件,配置爲log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
這樣的配置在許多地方都要有,須要可查有關資料),固然你也能夠本身擴展org.apache.log4j.jdbc.JDBCAppender這個類,只須要在這裏配置就能夠了例如咱們配置我本身擴展的MyJDBCAppender,配置爲#log4j.appender.db=com.neam.commons.MyJDBCAppender

log4j.appender.db.BufferSize=10
//設置緩存大小,就是當有10條日誌信息是才忘數據庫插一次

log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver
//設置要將日誌插入到數據庫的驅動                     
log4j.appender.db.URL=jdbc:jtds:SqlServer://localhost:1433;DatabaseName=pubs

log4j.appender.db.user=sa

log4j.appender.db.password=sa

log4j.appender.db.sql=insert into WDZLOG (LogName,UserName,Class,Mothod,createTime,LogLevel,MSG) values ('%X{userId}','%X{userName}','%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%m')
//設置要插入日誌信息的格式和內容,%X{userId}是置取MDC中的key值,由於咱們在過濾器中是將用戶id和用戶姓名放入MDC中,全部在這裏能夠用%X{userId}和%X{userName}取出用戶的ID和用戶姓名;'%C'表示日誌信息是來自於那個類;%M表示日誌信息來自於那個方法中;%d{yyyy-MM-dd HH:mm:ss}表示日誌信息產生的時間,{yyyy-MM-dd HH:mm:ss}表示一種時間格式,你也能夠直接寫成%d;%p表示日誌信息的級別(debug info warn error);
%m表示你寫入的日誌信息
log4j.appender.db.layout=org.apache.log4j.PatternLayoutapp

 

轉自:http://blog.csdn.net/ziruobing/article/details/3919501dom

相關文章
相關標籤/搜索