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”中。相对应的方法,
MDC.put(key, value); MDC.remove(key); MDC.get(key);
在配置PatternLayout的时候使用:%x{key}来输出对应的value)。有了MDC,我们可以在过滤器中先获得用户信息,再用MDC.Put(“key”)方法,log在执行sql语句时通过%x{key}来输出对应的value。
实现步骤:
1、在你的项目中要确保有log4j和commons-logging这两个jar文件;
2、设置要你要插入日志信息的表结构
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[WDZLOG]') and OBJECTPROPERTY(id, N'IsUserTable') = )
drop table [dbo].[WDZLOG]
GO CREATE TABLE [dbo].[WDZLOG] (
[WDZLOGID] [int] IDENTITY (, ) NOT NULL ,
[LogName] [varchar] () COLLATE Chinese_PRC_CI_AS NULL ,//用户ID
[UserName] [varchar] () COLLATE Chinese_PRC_CI_AS NULL ,//用户姓名
[Class] [varchar] () COLLATE Chinese_PRC_CI_AS NULL ,//类名
[Mothod] [varchar] () COLLATE Chinese_PRC_CI_AS NULL //,方法名
[CreateTime] [varchar] () COLLATE Chinese_PRC_CI_AS NULL ,//产生时间
[LogLevel] [varchar] () COLLATE Chinese_PRC_CI_AS NULL ,//日志级别
[MSG] [varchar] () COLLATE Chinese_PRC_CI_AS NULL //日志信息
) ON [PRIMARY]
GO
3、配置文件(摘自我们的项目)后面将对此配置文件进行详细讲解,它也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
4、编写过滤器(ResFilter.java)
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"); }
}
5、在需要写入日志的地方引入
private Log logger = LogFactory.getLog(this.getClass()); 在具体方法中就可以写入日志
logger.info("");
logger.debug("");
logger.warn("");
logger.error("");
配置文件详解:
log4j.properties
log4j.properties
log4j.rootLogger=INFO,stdout
//配置根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.PatternLayout
转自:http://blog.csdn.net/ziruobing/article/details/3919501
Log4j写入数据库详解的更多相关文章
- commons-logging和Log4j 日志管理/log4j.properties配置详解
commons-logging和Log4j 日志管理 (zz) 什么要用日志(Log)? 这个……就不必说了吧. 为什么不用System.out.println()? 功能太弱:不易于控制.如果暂时不 ...
- Spark log4j日志配置详解(转载)
一.spark job日志介绍 spark中提供了log4j的方式记录日志.可以在$SPARK_HOME/conf/下,将 log4j.properties.template 文件copy为 l ...
- slf4j log4j logback关系详解和相关用法
slf4j log4j logback关系详解和相关用法 写java也有一段时间了,一直都有用slf4j log4j输出日志的习惯.但是始终都是抱着"拿来主义"的态度,复制粘贴下配 ...
- Hibernate4搭建Log4J日志管理(附Log4j.properties配置详解)
1.首先加入slf4j的jar包,即slf4j-api-1.6.1.jar 在hibernate官网下载hibernate-release-4.2.2.Final.zip并解压,在hibernate- ...
- log4j.properties配置详解与实例
log4j.properties配置详解与实例 第一步:加入log4j-1.x.x.jar到lib下. 第二步:在工程的src下下建立log4j.properties.内容如下: #OFF,syste ...
- Log4j介绍,log4j.properties配置详解
http://www.cnblogs.com/simle/archive/2011/09/29/2195341.html本文主要解释log4j的配置文件各个配置项的含义,内容是从网上转载的 1.Log ...
- (转)phonegap 数据库详解
原文:http://firepix.iteye.com/blog/1618343 phonegap 数据库详解 博客分类: web App phonegap 今天就把之前使用pho ...
- SQLServer 远程链接MySql数据库详解
SQLServer 远程链接MySql数据库详解 by:授客 QQ:1033553122 测试环境: Microsoft Windows XP Professional 版本2000 Service ...
- JAVA通过JDBC连接Oracle数据库详解【转载】
JAVA通过JDBC连接Oracle数据库详解 (2011-03-15 00:10:03) 转载▼http://blog.sina.com.cn/s/blog_61da86dd0100q27w.htm ...
随机推荐
- Eolinker——前置用例返回的reponse值进行传递
如下补充均是Eolinker的文档中未说明的部分 示例:将login接口reponse中的mobile的值作为参数,传递给”重置密码”的请求体“code" 1.打开”前置用例“,先点击左上角 ...
- [loj6038]「雅礼集训 2017 Day5」远行 lct+并查集
给你 n 个点,支持 m 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. n≤3×10^5 n≤3×10^5 ,m≤5×10^5 m≤5 ...
- iis应用池内存溢出卡死优化
1.修改回收阀值memoryLimit 在ASP.NET Web服务器上,ASP.NET所能够用到的内存,通常不会等同于所有的内存数量.在machine.config(C:/WINDOWS/Micro ...
- 14:Spark Streaming源码解读之State管理之updateStateByKey和mapWithState解密
首先简单解释一下)) //要使用updateStateByKey方法,必须设置Checkpoint. ssc.checkpoint("/checkpoint/") val sock ...
- 454. 四数相加 II
给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为了使问题简单化,所有的 A ...
- BZOJ4327 [JSOI2012] 玄武密码 [AC自动机]
题目传送门 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神 ...
- python中if和elif的区别
多个if语句是每次单独判断 比如: 例子一: a = 5 if a < 6: #条件1 print(1) if a < 7: #条件2 print(2) else: print(3) 条件 ...
- 分布式锁的理解,java自带的锁为什么会失效
前段时间在发送短信的代码块上通过网上找的工具类基于Redis实现了分布式锁的功能 对应的链接https://www.cnblogs.com/c-h-y/p/9391602.html 周末想细细看一下. ...
- 创建模态提醒窗口(UIAlertView)
UIAlertView类创建一个简单的模态提醒窗口,可能包含消息.按钮以及文本框.模态UI元素要求用户必须与之交互(通常是按下按钮)后才能做其它事情.它们通常位于其他窗口前面,在可见时禁止用户与其他任 ...
- 给出一列数a1,a2,a3....an,求它们的逆序对数,即有多少个有序对(i,j) 使得iaj,n高达10的6次方
//归并排序 //#include<stdio.h> //#include<string.h> //#include<algorithm> //#include&l ...