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