Log4j高级配置

来源:互联网 发布:dijkstra算法图解 编辑:程序博客网 时间:2024/06/06 07:07

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

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

1.需求一:存储数据库

a. 首先在数据库中建一个用来存储日志的数据库命名为operate_log字段如下:


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

log4j.rootLogger=INFO,db          ########################   # JDBC Appender   ####################### log4j.appender.db=org.apache.log4j.jdbc.JDBCAppenderlog4j.appender.db.BufferSize=1log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver                       log4j.appender.db.URL=jdbc:jtds:sqlserver://localhost:1433;DatabaseName=xxxlog4j.appender.db.user=sa   log4j.appender.db.password=123log4j.appender.db.sql=insertinto 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 :
是日志记录的优先级,分为OFFFATALERRORWARNINFODEBUGALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR##WARNINFODEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志##信息将不被打印出来。
appenderName:
就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。
例如:log4j.rootLoggerinfo,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 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.logger.xidian=INFO,db log4j.logger.org=WARN, A1log4j.logger.com =WARN, A2 #A1log4j.appender.A1=org.apache.log4j.RollingFileAppenderlog4j.appender.A1.File=${webapp.root}/WEB-INF/logs/org.loglog4j.appender.A1.MaxFileSize=500KBlog4j.appender.A1.MaxBackupIndex=50log4j.appender.A1.Append=truelog4j.appender.A1.layout=org.apache.log4j.PatternLayoutlog4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-ddHH:mm:ss} - [%p] [%C{1}] - %m%n #A2log4j.appender.A2=org.apache.log4j.RollingFileAppenderlog4j.appender.A2.File=${webapp.root}/WEB-INF/logs/com.loglog4j.appender.A2.MaxFileSize=500KBlog4j.appender.A2.MaxBackupIndex=50log4j.appender.A2.Append=truelog4j.appender.A2.layout=org.apache.log4j.PatternLayoutlog4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-ddHH:mm:ss} - [%p] [%C{1}] - %m%n


这次的配置要复杂点

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

这个配置就是将不同的包下的信息输出到不同的文件中,根据下面的配置可知以xidian开头的包下的java文件的日志信息时进行数据库存储的,而orgcom包开头的日志信息是输出到文件中,文件的输出地址是${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 #stdoutlog4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d%5p (%c\:%L) - %m%n

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

 

2.需求二:提取用户信息

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


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

还有log4j的设计者已经为我们想到了,log4j为我们提供了MDCMDClog4j种非常有用类,它们用于存储应用程序的上下文信息(contextinfomation),从而便于在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 {     @Override    public void doFilter(ServletRequest request, ServletResponse response,            FilterChain chain) throws IOException,ServletException {                       //用户的id            Integer userId =(Integer)session.getAttribute("userId");            //用户的类型            String adminType =(String)session.getAttribute("adminType");                       MDC.put("userId", userId);             MDC.put("userType",adminType);         chain.doFilter(request, response);     }}


然后在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=insertinto 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}')  

0 0
原创粉丝点击