原文链接:http://www.cnblogs.com/shenliang123/archive/2012/05/02/2479286.html

由于最近正在扩展卫生局考务系统,由于上一次使用过一次该系统后,发现很多考生最后出现说已打印报名表但却在数据库中找不到她的报名记录;

因此为了以后有依据,将所有用户的操作日志文件写入数据供管理员查询成为了这次扩张项目的一个内容;

这里我决定使用的log4j日志文件,在多次的使用中感觉这个很不错;

首先我们要使用log4j日志文件时,我们需将两个必须的包放入lib目录下:log4j.XX.jar和commons-logging.XX.jar;

然后在classpath目录下(IDE中即为项目下的src目录下)新建一个日志文件,统一命名为:log4j.properties;

1.需求一:只需要满足存储数据库:

a.以下我们一ms sql 2000为例:首先在数据库中建一个用来存储日志的数据库命名为 operate_log;字段如下:

b.数据库成功建立后,就可以去配置日志文件log4j.properties,代码如下:

log4j.properties  

log4j.rootLogger=INFO,db

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

# JDBC Appender  

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

#log4j.logger.business=INFO,db
#log4j.appender.db=com.neam.commons.MyJDBCAppender log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender log4j.appender.db.BufferSize=1 log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver log4j.appender.db.URL=jdbc:jtds:sqlserver://localhost:1433;DatabaseName=infor_manage
#enter
log4j.appender.db.user=sa log4j.appender.db.password=123
log4j.appender.db.sql=insert into operate_log(class,method,createtime,loglevel,logmsg,user_id,user_type) values ('%C','%M','%d{yyyy-MM-dd HH\:mm\:ss}','%p','%m','1',1) log4j.appender.db.layout=org.apache.log4j.PatternLayout

上面的配置就是最精简的将日志内容直接存储进入数据库
下面来稍微解释:

log4j.rootLogger=INFO,db语法为:

##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个输出地方,这个名字可以任意(如上面的db),但必须与我们在后面进行的设置名字对应;

然后下面就是进行数据库连接的配置,log4j是使用jdbc进行连接的,该封转的类就是log4j包下的 org.apache.log4j.jdbc.JDBCAppender,大家对jdbc了解的话上面的内容应该是很简单的;

这里要注意的就是:1.记得把数据库连接的相关包放到lib目录下,2.在写连接数据库的信息时如user等注意后面不要有空格,否则就不能连上数据库

c.日志文件配置完成后,我们就可以进行测试了,我们可以随便在后台写一个类:

package xidian.sl.action.admin;

import org.apache.log4j.Logger;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorld extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(HelloWorld.class);//日志文件 public static void main(String[] args) {
log.error("访问了HelloWorld");
log.warn("访问了HelloWorld");
log.info("访问了HelloWorld");
log.debug("访问了HelloWorld");
}
}

然后右键运行,如果没有报错的话应该是成功了,可以去数据库看看:

可以看到日志信息已经进行了存储,但发现只有三条,少了debug,对了,由于我们进行了日志优先级的配置:log4j.rootLogger=INFO,db,只有debug级别就不能进行打印了;

到这里我们可以说基本成功了,但还远远不能满足我的需求:

我们发现数据库中出现了很多的日志信息,这个日志信息应该是启动等,从系统文件(spring等)中打印的,但这个其实不是我们需要的,或者说我们需要将其分开:

我们重新进行日志文件的配置

log4j.properties  

log4j.rootLogger=INFO,stdout
log4j.logger.xidian=INFO,db
log4j.logger.org=WARN, A1
log4j.logger.com =WARN, A2 #stdout\u5e94\u7528\u4e8e\u63a7\u5236\u53f0
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%d %5p (%c\:%L) - %m%n #A1\u5e94\u7528\u4e8e\u6587\u4ef6\u56de\u6eda
log4j.appender.A1=org.apache.log4j.RollingFileAppender
log4j.appender.A1.File=${webapp.root}/WEB-INF/logs/org.log
log4j.appender.A1.MaxFileSize=500KB
log4j.appender.A1.MaxBackupIndex=50
log4j.appender.A1.Append=true
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} - [%p] [%C{1}] - %m%n #A2\u5e94\u7528\u4e8e\u6587\u4ef6\u56de\u6eda
log4j.appender.A2=org.apache.log4j.RollingFileAppender
log4j.appender.A2.File=${webapp.root}/WEB-INF/logs/com.log
log4j.appender.A2.MaxFileSize=500KB
log4j.appender.A2.MaxBackupIndex=50
log4j.appender.A2.Append=true
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} - [%p] [%C{1}] - %m%n ######################## # JDBC Appender ####################### #log4j.logger.business=INFO,db
#log4j.appender.db=com.neam.commons.MyJDBCAppender log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender log4j.appender.db.BufferSize=1 log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver log4j.appender.db.URL=jdbc:jtds:sqlserver://localhost:9433;DatabaseName=infor_manage
#enter
log4j.appender.db.user=sa log4j.appender.db.password=123@sports log4j.appender.db.sql=insert into operate_log(class,method,createtime,loglevel,logmsg,user_id,user_type) values ('%C','%M','%d{yyyy-MM-dd HH\:mm\:ss}','%p','%m','1',1) log4j.appender.db.layout=org.apache.log4j.PatternLayout

这次的配置要复杂点

log4j.logger.xidian=INFO,db  
log4j.logger.org=WARN, A1
log4j.logger.com =WARN, A2

这个配置就是将不同的包下的信息输出到不同的文件中,根据下面的配置可知以xidian开头的包下的java文件的日志信息时进行数据库存储的,而org与com包开头的日志信息是输出到文件中,文件的输出地址是${webapp.root}/WEB-INF/logs/org.log即项目的WEB-INF目录下的logs文件夹中,为了得到${webapp.root}我们还需要到web.xml文件中进行配置:

 <!--由Sprng载入的Log4j配置文件位置-->
<context-param>
<param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value>
</context-param>
<!--Spring log4j Config listener-->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

这样我们再次运行HelloWorld程序
查看数据库(很干净了,哈哈):

然后在到WEB-INF目录下的logs文件夹中查看输出的日志文件:

由于我们在根Logger下也进行了配置:这个根Logger的配置是对所有日志操作都是有作用的

log4j.rootLogger=INFO,stdout

#stdout\u5e94\u7528\u4e8e\u63a7\u5236\u53f0
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%d %5p (%c\:%L) - %m%n

这个配置是进行控制太的输出,因此我们在控制台中也会发现有输出:

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

到此为止我们日志的基本操作都应该掌握了,但我还有一个需求没有满足,就是我一开始数据库字段的设计中还包含了两个字段:

这两个字段是存储用户的id和用户类型的,以便我们在后面日志的核查中能正确的找出用户信息;但这里就有一个问题了我们就靠上面的操作还是不能将用户信息得到的,

还有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中,然后再在log4j.properties配置文件中的sql语句中进行读取:

过滤器代码:

package xidian.sl.filter;

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.MDC; public class LogResFilter implements Filter { private final static double DEFAULT_USERID= 0.0; @Override
public void destroy() { } @Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//System.out.println("进入过滤器");
HttpServletRequest req=(HttpServletRequest)request;
HttpSession session= req.getSession();
if (session==null){
MDC.put("userId",DEFAULT_USERID);
MDC.put("userType",DEFAULT_USERID);
}
else{
//StuInfor stuInfor =(StuInfor)session.getAttribute("admin");
//用户的id
Integer userId = (Integer)session.getAttribute("userId");
//用户的类型
String adminType = (String)session.getAttribute("adminType");
if (userId == null&& adminType == null){
MDC.put("userId",DEFAULT_USERID);
MDC.put("userType",DEFAULT_USERID);
}
else
{
System.out.println("用户id"+userId+ "类型"+ adminType);
MDC.put("userId", userId);
MDC.put("userType", adminType);
}
}
chain.doFilter(request, response);
} @Override
public void init(FilterConfig arg0) throws ServletException { } }

然后在web.xml中进行过滤器的配置:

    <filter>
<filter-name>LogResFilter</filter-name>
<filter-class>xidian.sl.filter.LogResFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LogResFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>

这样用户登录后存储在session中的信息通过该过滤器就存储MDC中,然后我们在日志文件中写sql语句:

log4j.appender.db.sql=insert into operate_log(class,method,createtime,loglevel,logmsg,user_id,user_type) values ('%C','%M','%d{yyyy-MM-dd HH\:mm\:ss}','%p','%m','%X{userId}','%X{adminType}')  

到这里我的需求基本上满足了,不知道有没有满足你的需求。

【转】玩转log4j的更多相关文章

  1. 玩转log4j

    我的目标是授人以渔,而不是授人以鱼,我相信你仔细看完这篇文章,玩转log4j不成问题 先来一个log4j最简单的例子 public class MyApp { static Logger logger ...

  2. 玩转Spring MVC(五)----在spring中整合log4j

    在前边的基础上,本文主要总结一下如何在spring 中配置log4j,在本文末尾会给出完整项目的链接. 首先是web.xml中要新添加的代码: <!-- 6. 配置log4j --> &l ...

  3. 项目自动化建构工具gradle 入门2——log4j输出helloWorld

    上一章节呢,有一个能跑的程序了.但是对做工程的人来说,用日志输出感觉比用System.out要有档次一点.比如使用log4j.直接上例子: 1进入D:\work\gradle\log目录  ,您电脑没 ...

  4. 玩转Nodejs日志管理log4js(转)

    转自:http://blog.fens.me/nodejs-log4js/ 前言 日志对任何的应用来说都是至关重要的.在Nodejs中使用express框架并没有自带的日志模块,我们可以选择log4j ...

  5. 玩转mongodb(九):通过log4jmongo来实现分布式系统的日志统一管理

    背景 在分布式系统中,我们有多个web app,这些web app可能分别部署在不同的物理服务器上,并且有各自的日志输出.当生产问题来临时,很多时候都需要去各个日志文件中查找可能的异常,相当耗费人力. ...

  6. (转)log4j(一)——为什么要用log4j?

    1 试验环境 OS:win7 JDK:jdk7 Log4j:1.2.17(好尴尬,原本是想试验下log4j2的,结果阴差阳错用了这个版本,不过幸好,试验也不白试验,试验的作用是一样的) 2 先看两个简 ...

  7. log4j(一)——为什么要用log4j?

    一:试验环境 OS:win7 JDK:jdk7 Log4j:1.2.17(好尴尬,原本是想试验下log4j2的,结果阴差阳错用了这个版本,不过幸好,试验也不白试验,试验的作用是一样的) 二:先看两个简 ...

  8. Java logger组件:slf4j, jcl, jul, log4j, logback, log4j2

    先说结论 建议优先使用logback 或 log4j2.log4j2 不建议和 slf4j 配合使用,因为格式转换会浪费性能. 名词:jcl 和 jul 标题中的 jcl 是 apache Jakar ...

  9. log4j.xml——java日志处理组件配置简介

    (从一篇好文开始)log4j(一)——为什么要用log4j? 三:看完栗子后的感想 (1)很明显我们在编写代码的时候有各种需要打印日志的需求,比如:我们调试代码的时候:我们的应用出现了问题,我们分析. ...

随机推荐

  1. 使用Myeclipse完成Hibernate的逆向工程

    前面已经提到过Hibernate的开发流程一般有两种: 1.由Domain object > mapping > db 2.由db开始,用工具生成生成mapping 和Domain obj ...

  2. CSS样式的特点与优先选择权

    CSS样式的特点:(子元素会继承父元素的某些样式,子元素有自己的样式就用自己的样式,没有的就用父元素的)      1.继承:              网页中子元素,将继承父元素的样式(比如要控制p ...

  3. hibernate4 二级缓存demo实例

    转载:http://blog.csdn.net/chaoowang/article/details/21236501 hibernate使用版本是:hibernate-release-4.3.4.Fi ...

  4. 读取Excel文件中的单元格的内容和颜色

    怎样读取Excel文件中的单元格的内容和颜色 先创建一个Excel文件,在A1和A2中随意输入内容,设置A1的字体颜色为红色,A2的背景为黄色.需要 using Excel = Microsoft.O ...

  5. (转载)DataTable使用技巧总结

    在项目中经常用到DataTable,如果DataTable使用得当,不仅能使程序简洁实用,而且能够提高性能,达到事半功倍的效果,现对DataTable的使用技巧进行一下总结.         一.Da ...

  6. Linux setjmp longjmp

    /********************************************************************* * Linux setjmp longjmp * 说明: ...

  7. MySQL Database on Azure - 利用PowerShell快速创建使用数据库服务

    如果您的应用需要通过脚本快速创建一个或多个MySQL数据库,MySQL Database on Azure目前开放了对于PowerShell的支持,可以帮助您快速利用自动化脚本进行数据库服务的创建.管 ...

  8. HiveQL 与 SQL的异同

    1 select 别名 (1)别名一定要加as 例:select ID as stuID from students (2) Hive QL不支持在group by, order by 中使用sele ...

  9. 一起学CUDA(零)

    1.Nvidia为什么引入CUDA最近实验室已经有不少豪在入手本本了,因为学霸居多,所以大家一般都会说对显卡要求不高,不玩大型游戏,只是CPU不能差,Intel I7.3G的主频…… 其 实现在CPU ...

  10. 2016第20周四java基础概念

    简单的说JDK=JRE+Java编译器.调试器.工具类库等:JRE=JVM(类似于jre目录下的bin)+必要运行的类库(类似于jre目录下的lib) JVM:Java Virtual Mechina ...