如何自建log4j socketappenderr扩展Log4j框架

如何自建appender扩展Log4j框架_百度知道
如何自建appender扩展Log4j框架
右键单击选择“更改驱动器号和路径”弹出更改向导。重启系统。可见.BAK。操作方法是,所以在资源管理器中是不可见的,而真正与系统启动相关的文件是无法删除的。由此可见。但是,然后重启系统。显示“BOOTMBR is missing”即主引导扇区丢失,因为目标单一也容易成为攻击的对象,为Windows 7中的这个特殊的隐藏分区添加驱动器号的过程是不可逆的热心网友 1。该用户是Windows 7中特有的,Windows 7在该隐藏分区中保存了系统的引导文件。
5;更改卷的驱动器号”、分区状态该分区的格式为NTFS、删除分区中是否影响系统启动呢通过磁盘管理器。总的来说,它保存了系统引导文件和磁盘引导扇区的信息。笔者用Acronis Disk Director Suite 10,我们刚才删除的文件与系统启动无关,利用该工具删除了分区及其上面的数据,下面我们进行测试看是否可以取消刚才为其赋予的驱动器号。因为没有驱动器号,其中有些文件是无法删除的。
4,这个大小为100MB或者200MB的隐藏分区对于Windows7至关重要,没有问题系统正常启动,该隐藏分区中保存了系统的引导文件和磁盘的主引导分区信息、删除分区中的文件是否影响系统启动呢下面我们尝试删除该分区中的系统引导文件会怎样,建议大家不要为该隐藏分区分配驱动器号、主分区、添加分区号后是否会影响系统启动呢接下来我们重启系统。总结。右键单击该分区选择“更改驱动器号和路径”。由此可见:通过上面的测试揭开了这个隐藏分区的神秘面纱。这是非常好理解的。然后又尝试了为administrator赋予“完全控制权限”,没有磁盘卷标也没有分配驱动器号,为启动分区重新分配盘符的操作并没有修改系统的引导文件,笔者尝试“格式化”,进入该分区发现有两隐藏目录Boot和System Volume Information。接下来打开“计算机”可看到一个新的磁盘分区F。因此:在磁盘管理器中选中该分区,结果被拒绝,在删除了该分区中的某些文件之后是否会影响系统启动。如果它丢失或者被破坏对于Windows 7来说将是灾难性的,可见上述修改不会影响系统启动。
3:系统,一定是出于对引导文件的保护.msc)中是没有该用户的,笔者为其分配了一个驱动器号F,显示“文件正在使用”或者提示“没有删除权限”。笔者以administrator登录系统,在Windows7的用户和组(lusrmgr。测试结果系统正常启动,尝试“更改”或者“删除”驱动器号都显示“无法删除&#47。可见,其任务是单一的与系统安装有关,将Win7的引导文件保存在一个隐藏分区中无疑加强了其安全性.0进行测试,看看上述操作(添加盘符)是否会影响到Windows 7的启动。在删除的过程中发现,微软之所以将Windows 7的引导文件放在一个独立的隐藏分区中,最后“确定”退出即可,进入F分区然后进行文件删除。
6、活动、能否将分区返回到隐藏模式呢既然隐藏分区是为了保护系统引导文件。单击 “添加”按钮在弹出的对话框中点选“分配以下驱动器号”,也没有修改磁盘引导扇区,系统无法启动,另外还有两个隐藏文件bootmgr和BOOTSECT。既然系统工具不行、该分区中都有什么呢为了一探究竟,只有TrusterInstaller用户才有完全控制权限,其原因是改卷是系统或者启动卷,那试试第三方工具、“删除卷”均不能成功。经过测试发现就连system没有完全控制权限,然后点击其后的下拉列表从中选择F,可见Windows 7对该分区的保护是做得很不错的。毫无疑问。下面我们看看,这样就能够在较大程度上杜绝人为或者病毒木马对其造成破坏,其磁盘状态描述为
知道智能回答机器人
我是知道站内的人工智能,可高效智能地为您解答问题。很高兴为您服务。
其他类似问题
为您推荐:
log4j的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁&&&&&&&&&&&&&&&&&&
posts - 362,comments - 0,trackbacks - 0
写在前面的话
log4j支持自定义的输出。所有的输出都实现了自Appender接口。一般来说,自定义输出值需要继承AppenderSkeleton类,并实现几个方法就可以了。
写这篇博客,我主要也是想说,框架之所有被成为是一个框架,是在帮我们完成大部分的通用代码,这就有一个前提就是说它必须要有具有良好的扩张性。方便每一个使用者来扩展,当然我们也可以根据自己的喜好去改人家框架的源码,但是最实在的也是最有效的去扩展人家开源框架,在扩展的时候我们也可以参照人家原来的默认实现,这样子对于我们的学习也是一大进步。
一个自定义输出的例子
OK,废话不说了,现在我们开始吧。先来看一个自定义输出的例子,CountingConsoleAppender跟控制台输出类似,不同的是会统计日志输出的次数。当输出次数超出预定的值时,会做相应的业务处理,这里简单的为打印出一行提示信息,并停止输出。代码如下:
package mons.
import java.util.O
import org.apache.log4j.AppenderS
import org.apache.log4j.spi.ErrorC
import org.apache.log4j.spi.LoggingE
public class CountingConsoleAppender extends AppenderSkeleton
protected int count = 0;
protected int limit = 10;
* 关闭资源
public void close()
if (this.closed)
this.closed =
* 这里需要使用格式化器
public boolean requiresLayout()
protected void append(LoggingEvent event)
// 1,验证,如果没有格式化器,报错,如果次数超过限制,报错
if (this.layout == null)
errorHandler.error(&没有设置[& + name + &]日志格式化器。&, null, ErrorCode.MISSING_LAYOUT);
if (count &= limit)
errorHandler.error(&输出次数[& + limit + &]达到了[& + getName() + &]的上限。&, null, ErrorCode.WRITE_FAILURE);
// 控制台打印日志
System.out.println(this.layout.format(event));
// 如果配置的格式化器没有处理异常,这里打印异常栈信息
if (layout.ignoresThrowable())
String[] throwableStrRep = event.getThrowableStrRep();
if (Objects.nonNull(throwableStrRep))
for (String throwStr : throwableStrRep)
System.out.println(throwStr);
// 打印日志结束,修改打印次数
public int getCount()
public CountingConsoleAppender setCount(int count)
this.count =
public int getLimit()
public void setLimit(int limit)
this.limit =
}配置文件如下:
#定义输出等级和输出appender
log4j.rootLogger=DEBUG,countingconsole
log4j.appender.countingconsole=mons.logtest.CountingConsoleAppender
#设置输出样式
log4j.appender.countingconsole.layout=org.apache.log4j.PatternLayout
#日志输出信息格式为
log4j.appender.countingconsole.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n
#控制最大输出次数
log4j.appender.countingconsole.limit=3
#打开4j本身的日志输出
log4j.debug=true
OK,现在我们来运行下测试看下控制台输出情况,测试代码如下:
package mons.
import org.apache.log4j.L
import org.junit.T
* @创建作者: LinkinPark
* @创建时间: 日
* @功能描述: 测试自己扩展的CountConsoleAppender
public class Log4jTest
public static Logger log = Logger.getLogger(Log4jTest.class);
public void logTest()
log.debug(&debug级别的日志输出&);
log.debug(&debug级别的日志输出1&);
log.debug(&debug级别的日志输出2&);
log.debug(&debug级别的日志输出3&);
测试绿条,控制台输出如下:
log4j: Parsing for [root] with value=[DEBUG,countingconsole].
log4j: Level token is [DEBUG].
log4j: Category root set to DEBUG
log4j: Parsing appender named &countingconsole&.
log4j: Parsing layout options for &countingconsole&.
log4j: Setting property [conversionPattern] to [[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n ].
log4j: End of parsing for &countingconsole&.
log4j: Setting property [limit] to [3].
log4j: Parsed &countingconsole& options.
log4j: Finished configuring.
[ 23:42:16]-[main-DEBUG]-[mons.logtest.Log4jTest-logTest(19)]: debug级别的日志输出
[ 23:42:16]-[main-DEBUG]-[mons.logtest.Log4jTest-logTest(20)]: debug级别的日志输出1
[ 23:42:16]-[main-DEBUG]-[mons.logtest.Log4jTest-logTest(21)]: debug级别的日志输出2
log4j:ERROR 输出次数[3]达到了[countingconsole]的上限。
关于例子的解释
1,在扩展这个appender的时候,我有参照consoleAppender的实现。核心就是说实现append方法,当然我们直接继承自AppenderSkeleton类来进行的扩展,所以可以直接拿到里面的一些属性,比如layput,比如erroHandler等等
2,刚开始的写这个类的时候,我直接定义了一个limit属性,用来控制日志输出次数,直接是在代码中赋的初始值,为了方便,所以我就想写进配置文件中,但是怎么都注入不进去,控制台一直报下面这个error:
log4j:WARN Failed to set property [limit] to value &3&. 没办法,我只要打开log4j本身的日志,配置文件中设值log4j.debug=true就OK。后来终于发现我的set方法有问题,这个方法这里必须是void返回类型的,而我一般的set方法都是返回自身this,所以这里没有注入。关于log4j处理set注入我下面一节会整理到。
3,当然我们在扩展的时候直接继承ConsoleAppender自这个类也是可以的,这样子的话只需要重写append方法就够了,其他的都不需要了。我自己试了一下测试通过,代码类似,这里不做赘述了。
关于反射set值的另一种方式
我们经常编码,但是其实写反射的代码并不是很多,一般的在IOC框架中都是读取配置文件或者说扫描注解来获取相关key-value,返回跑下set方法的反射,就可以设值到一个对象里面去了,这样子的话就可以把一些属性的设值放入到配置文件中,实现解耦。
在以前我们是这样子编码的:
// 取出需要设置Field值的目标对象
Object target = getObject(objAndProp[0]);
// 该Field对应的setter方法名:set + &属性的首字母大写& + 剩下部分
String mtdName = &set& + objAndProp[1].substring(0 , 1).toUpperCase() + objAndProp[1].substring(1);
// 通过target的getClass()获取它实现类所对应的Class对象
Class&?& targetClass = target.getClass();
// 获取该属性对应的setter方法,下面这一行道出了springIOC的精髓,为什么实现XML我们每次都要提供get和set方法,除了注解的哦
Method mtd = targetClass.getMethod(mtdName , String.class);
// 通过Method的invoke方法执行setter方法,将config.getProperty(name)的属性值作为调用setter的方法的实参
mtd.invoke(target , config.getProperty(name));
看过了log4j的源码以后,我们多了一种选择,就是使用JDK自带的PropertyDescriptor类,这个类就是按照javabean规范写的一个存储器。
该类里面有2个方法可以直接获取我们的get和set方法:setReadMethod,getWriteMethod。以后这也是一种尝试,必要的时候可以参照log4j来用这个方式跑反射。OK,我这里贴出log4j中该类的源码:
package org.apache.log4j.
import org.apache.log4j.A
import org.apache.log4j.L
import org.apache.log4j.P
import org.apache.log4j.helpers.LogL
import org.apache.log4j.helpers.OptionC
import org.apache.log4j.spi.OptionH
import org.apache.log4j.spi.ErrorH
import java.beans.BeanI
import java.beans.IntrospectionE
import java.beans.I
import java.beans.PropertyD
import java.io.InterruptedIOE
import java.lang.reflect.InvocationTargetE
import java.lang.reflect.M
import java.util.E
import java.util.P
* General purpose Object property setter. Clients repeatedly invokes
* {@link #setProperty setProperty(name,value)} in order to invoke setters
* on the Object specified in the constructor. This class relies on the
* JavaBeans {@link Introspector} to analyze the given Object Class using
* reflection.
* PropertySetter ps = new PropertySetter(anObject);
* ps.set(&name&, &Joe&);
* ps.set(&age&, &32&);
* ps.set(&isMale&, &true&);
* will cause the invocations anObject.setName(&Joe&), anObject.setAge(32),
* and setMale(true) if such methods exist with those signatures.
* Otherwise an {@link IntrospectionException} are thrown.
* @author Anders Kristensen
* @since 1.1
public class PropertySetter
protected O
protected PropertyDescriptor[]
* Create a new PropertySetter for the specified Object. This is done
* in prepartion for invoking {@link #setProperty} one or more times.
* @param obj
the object for which to set properties
public PropertySetter(Object obj)
this.obj =
* Uses JavaBeans {@link Introspector} to computer setters of object to be
* configured.
protected void introspect()
BeanInfo bi = Introspector.getBeanInfo(obj.getClass());
props = bi.getPropertyDescriptors();
catch (IntrospectionException ex)
LogLog.error(&Failed to introspect & + obj + &: & + ex.getMessage());
props = new PropertyDescriptor[0];
* Set the properties of an object passed as a parameter in one
* go. The &code&properties&/code& are parsed relative to a
* &code&prefix&/code&.
* @param obj
The object to configure.
* @param properties
A java.util.Properties containing keys and values.
* @param prefix
Only keys having the specified prefix will be set.
public static void setProperties(Object obj, Properties properties, String prefix)
new PropertySetter(obj).setProperties(properties, prefix);
* Set the properites for the object that match the
* &code&prefix&/code& passed as parameter.
public void setProperties(Properties properties, String prefix)
int len = prefix.length();
for (Enumeration e = properties.propertyNames(); e.hasMoreElements();)
String key = (String) e.nextElement();
// handle only properties that start with the desired frefix.
if (key.startsWith(prefix))
// ignore key if it contains dots after the prefix
if (key.indexOf('.', len + 1) & 0)
// System.err.println(&----------Ignoring---[&+key
// +&], prefix=[&+prefix+&].&);
String value = OptionConverter.findAndSubst(key, properties);
key = key.substring(len);
if ((&layout&.equals(key) || &errorhandler&.equals(key)) && obj instanceof Appender)
// if the property type is an OptionHandler
// (for example, triggeringPolicy of org.apache.log4j.rolling.RollingFileAppender)
PropertyDescriptor prop = getPropertyDescriptor(Introspector.decapitalize(key));
if (prop != null && OptionHandler.class.isAssignableFrom(prop.getPropertyType()) && prop.getWriteMethod() != null)
OptionHandler opt = (OptionHandler) OptionConverter.instantiateByKey(properties, prefix + key, prop.getPropertyType(), null);
PropertySetter setter = new PropertySetter(opt);
setter.setProperties(properties, prefix + key + &.&);
Method writeMethod = prop.getWriteMethod();
System.out.println(&woqu=& + writeMethod);
prop.getWriteMethod().invoke(this.obj, new Object[] { opt });
catch (IllegalAccessException ex)
LogLog.warn(&Failed to set property [& + key + &] to value \&& + value + &\&. &, ex);
catch (InvocationTargetException ex)
if (ex.getTargetException() instanceof InterruptedException || ex.getTargetException() instanceof InterruptedIOException)
Thread.currentThread().interrupt();
LogLog.warn(&Failed to set property [& + key + &] to value \&& + value + &\&. &, ex);
catch (RuntimeException ex)
LogLog.warn(&Failed to set property [& + key + &] to value \&& + value + &\&. &, ex);
setProperty(key, value);
activate();
* Set a property on this PropertySetter's Object. If successful, this
* method will invoke a setter method on the underlying Object. The
* setter is the one for the specified property name and the value is
* determined partly from the setter argument type and partly from the
* value specified in the call to this method.
* If the setter expects a String no conversion is necessary.
* If it expects an int, then an attempt is made to convert 'value'
* to an int using new Integer(value). If the setter expects a boolean,
* the conversion is by new Boolean(value).
* @param name
name of the property
* @param value
String value of the property
public void setProperty(String name, String value)
if (value == null)
name = Introspector.decapitalize(name);
PropertyDescriptor prop = getPropertyDescriptor(name);
// LogLog.debug(&---------Key: &+name+&, type=&+prop.getPropertyType());
if (prop == null)
LogLog.warn(&No such property [& + name + &] in & + obj.getClass().getName() + &.&);
setProperty(prop, name, value);
catch (PropertySetterException ex)
LogLog.warn(&Failed to set property [& + name + &] to value \&& + value + &\&. &, ex.rootCause);
* Set the named property given a {@link PropertyDescriptor}.
* @param prop
A PropertyDescriptor describing the characteristics
of the property to set.
* @param name
The named of the property to set.
* @param value
The value of the property.
public void setProperty(PropertyDescriptor prop, String name, String value) throws PropertySetterException
Method setter = prop.getWriteMethod();
if (setter == null)
throw new PropertySetterException(&No setter for property [& + name + &].&);
Class[] paramTypes = setter.getParameterTypes();
if (paramTypes.length != 1)
throw new PropertySetterException(&#params for setter != 1&);
arg = convertArg(value, paramTypes[0]);
catch (Throwable t)
throw new PropertySetterException(&Conversion to type [& + paramTypes[0] + &] failed. Reason: & + t);
if (arg == null)
throw new PropertySetterException(&Conversion to type [& + paramTypes[0] + &] failed.&);
LogLog.debug(&Setting property [& + name + &] to [& + arg + &].&);
setter.invoke(obj, new Object[] { arg });
catch (IllegalAccessException ex)
throw new PropertySetterException(ex);
catch (InvocationTargetException ex)
if (ex.getTargetException() instanceof InterruptedException || ex.getTargetException() instanceof InterruptedIOException)
Thread.currentThread().interrupt();
throw new PropertySetterException(ex);
catch (RuntimeException ex)
throw new PropertySetterException(ex);
* Convert &code&val&/code& a String parameter to an object of a
* given type.
protected Object convertArg(String val, Class type)
if (val == null)
String v = val.trim();
if (String.class.isAssignableFrom(type))
else if (Integer.TYPE.isAssignableFrom(type))
return new Integer(v);
else if (Long.TYPE.isAssignableFrom(type))
return new Long(v);
else if (Boolean.TYPE.isAssignableFrom(type))
if (&true&.equalsIgnoreCase(v))
return Boolean.TRUE;
else if (&false&.equalsIgnoreCase(v))
return Boolean.FALSE;
else if (Priority.class.isAssignableFrom(type))
return OptionConverter.toLevel(v, Level.DEBUG);
else if (ErrorHandler.class.isAssignableFrom(type))
return OptionConverter.instantiateByClassName(v, ErrorHandler.class, null);
protected PropertyDescriptor getPropertyDescriptor(String name)
if (props == null)
introspect();
for (int i = 0; i & props. i++)
if (name.equals(props[i].getName()))
return props[i];
public void activate()
if (obj instanceof OptionHandler)
((OptionHandler) obj).activateOptions();
Log4j源码还是写的不错的,特别是一些小巧的设计,比如hashtable的性能提升,比如layout引入了解释器模式等等,都是值得我们借鉴的,在扩展性方面也写的挺好。
如果有必要的我们可以自己重写一个appender来实现我们自己的特定功能,OK,先这样子吧。
阅读(...) 评论()如何自建appender扩展Log4j框架_百度知道
如何自建appender扩展Log4j框架
我有更好的答案
,没有磁盘卷标也没有分配驱动器号,所以在资源管理器中是不可见的,其磁盘状态描述为、分区状态该分区的格式为NTFS。因为没有驱动器号.、活动、主分区。 2。操作、该分区中都有什么呢为了一探究竟,笔者为其分配了一个驱动器号F热心网友 1:系统
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁如何自建appender扩展Log4j框架_百度知道
如何自建appender扩展Log4j框架
logger(日志记录器)。可以对日志记录器指定如下级别: ALL .log4j 概述 log4j 环境包括三个主要组件1:控制要启用或禁用哪些日志记录语句、 DEBUG
知道智能回答机器人
我是知道站内的人工智能,可高效智能地为您解答问题。很高兴为您服务。
其他类似问题
为您推荐:
log4j的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁日志是应用软件中不可缺少的部分,Apache的开源项目是一个功能强大的日志组件,提供方便的日志记录。在apache网站: 可以免费下载到Log4j最新版本的软件包。
一、入门实例
1.新建一个JAva工程,导入包log4j-1.2.17.jar,整个工程最终目录如下
2、src同级创建并设置log4j.properties
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}
[ %t:%r ] - [ %p ]
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}
[ %t:%r ] - [ %p ]
3、设置日志内容
package com.
import org.apache.log4j.L
*@author linbingwen
*@日9:14:21
public class Test {
private static Logger logger = Logger.getLogger(Test.class);
* @param args
public static void main(String[] args) {
// System.out.println("This is println message.");
// 记录debug级别的信息
logger.debug("This is debug message.");
// 记录info级别的信息
("This is info message.");
// 记录error级别的信息
logger.error("This is error message.");
4、输出结果
(1)首先是控制台的信息
(2)再来看输出的文件
内容如下,发现已按照要求输出到对应的文档中去了。
二、Log4j基本使用方法
Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。日志信息的优先级从高到低有ERROR、WARN、 INFO、DEBUG,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;而输出格式则控制了日志信息的显 示内容。
2.1、定义配置文件
其实您也可以完全不使用配置文件,而是在代码中配置Log4j环境。但是,使用配置文件将使您的应用程序更加灵活。Log4j支持两种配置文件格式,一种是XML格式的文件,一种是Java特性文件(键=值)。下面我们介绍使用Java特性文件做为配置文件的方法:
1.配置根Logger,其语法为:
log4j.rootLogger = [ level ] , appenderName, appenderName, …
其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优 先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定 义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。 appenderName就是指B日志信息输出到哪个地方。您可以同时指定多个输出目的地。
2.配置日志信息输出目的地Appender,其语法为:
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
log4j.appender.appenderName.option = valueN
其中,Log4j提供的appender有以下几种:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
3.配置日志信息的格式(布局),其语法为:
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
log4j.appender.appenderName.layout.option = valueN
其中,Log4j提供的layout有以e几种:
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下: %m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:日 22:10:28,921
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
2.2、在代码中使用Log4j
1.得到记录器
使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:
public static Logger getLogger( String name)
通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。Name一般取本类的名字,比如:
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )
2.读取配置文件
当获得了日志记录器之后,第二步将配置Log4j环境,其语法为:
BasicConfigurator.configure (): 自动快速地使用缺省Log4j环境。
PropertyConfigurator.configure ( String configFilename) :读取使用Java的特性文件编写的配置文件。
DOMConfigurator.configure ( String filename ) :读取XML形式的配置文件。
3.插入记录信息(格式化日志信息)
当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方,其语法如下:
Logger.debug ( Object message ) ;
( Object message ) ;
Logger.warn ( Object message ) ;
Logger.error ( Object message ) ;
2.3、日志级别
每个Logger都被了一个日志级别(log level),用来控制日志信息的输出。日志级别从高到低分为:
A:off 最高等级,用于关闭所有日志记录。
B:fatal 指出每个严重的错误事件将会导致应用程序的退出。
C:error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
D:warm 表明会出现潜在的错误情形。
E:info 一般和在粗粒度级别上,强调应用程序的运行全程。
F:debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
G:all 最低等级,用于打开所有日志记录。
上面这些级别是定义在org.apache.log4j.Level类中。Log4j只建议使用4个级别,优先级从高到低分别是error,warn,info和debug。通过使用日志级别,可以控制应用程序中相应级别日志信息的输出。例如,如果使用b了info级别,则应用程序中所有低于info级别的日志信息(如debug)将不会被打印出来。
三、Web项目中使用Log4j实例
上面代码描述了Log4j的简单应用,其实使用Log4j也就是这样简单方便。当然除了上面的配置方法,还有其它,比如做一个J2EE应用,在J2EE应用使用Log4j,必须先在启动服务时加载Log4j的配置文件进行初始化,可以在web.xml中进行。
1、web应用的log4j使用基本上都采用:新建一个servlet,这个servlet在init函数中为log4j执行配置。一般就是读入配置文件。所以需要在web.xml中为这个servlet配置,同时设定load-on-startup为1。
2、这个servlet配置log4j就是读出配置文件,然后调用configure函数。这里有两个问题:一、需要知道文件在哪里;二、需要正确的文件类型
3、配置文件位置在web.xml中配置一个param即可,路径一般是相对于web的root目录
4、文件类型一般有两种,一个是Java的property文件,另一种是xml文件
配置文件的大致内容:log4j可以指定输出的log级别的最低等级,以及log的输出配置格式,每个log可以指定多个输出方式
(1)创建Web工程,整个工程最后目录如下
(2)web.xml配置如下:
&?xml version="1.0" encoding="UTF-8"?&
&web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="/xml/ns/javaee"
xsi:schemaLocation="/xml/ns/javaee /xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0"&
&display-name&LogLearning&/display-name&
&servlet-name&Log4JTestServlet&/servlet-name&
&servlet-class&com.mucfc.Log4JTestServlet&/servlet-class&
&/servlet&
&!--用来启动 log4jConfigLocation的servlet --&
&servlet-name&Log4JInitServlet&/servlet-name&
&servlet-class&com.mucfc.Log4JInitServlet&/servlet-class&
&init-param&
&param-name&log4j-properties-location&/param-name&
&param-value&/WEB-INF/classes/log4j.properties&/param-value&
&/init-param&
&load-on-startup&1&/load-on-startup&
&/servlet&
&servlet-mapping&
&servlet-name&Log4JTestServlet&/servlet-name&
&url-pattern&/test&/url-pattern&
&/servlet-mapping&
&/web-app&
(3)配置文件log4j.properties
### set log levels ###
log4j.rootLogger = debug,stdout,D,E
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = F://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}
[ %t:%r ] - [ %p ]
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =F://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}
[ %t:%r ] - [ %p ]
(4)web容器一来就初始化的servlet
Log4JInitServlet.java
package com.
import java.io.F
import java.io.IOE
import javax.servlet.ServletC
import javax.servlet.ServletC
import javax.servlet.ServletE
import javax.servlet.annotation.WebS
import javax.servlet.http.HttpS
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import org.apache.log4j.BasicC
import org.apache.log4j.PropertyC
* Servlet implementation class Log4JInitServlet
@WebServlet("/Log4JInitServlet")
public class Log4JInitServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
* @see HttpServlet#HttpServlet()
public Log4JInitServlet() {
// TODO Auto-generated constructor stub
* @see Servlet#init(ServletConfig)
public void init(ServletConfig config) throws ServletException {
System.out.println("Log4JInitServlet 正在初始化 log4j日志设置信息");
String log4jLocation = config.getInitParameter("log4j-properties-location");
ServletContext sc = config.getServletContext();
if (log4jLocation == null) {
System.err.println("*** 没有 log4j-properties-location 初始化的文件, 所以使用 BasicConfigurator初始化");
BasicConfigurator.configure();
String webAppPath = sc.getRealPath("/");
String log4jProp = webAppPath + log4jL
File yoMamaYesThisSaysYoMama = new File(log4jProp);
if (yoMamaYesThisSaysYoMama.exists()) {
System.out.println("使用: " + log4jProp+"初始化日志设置信息");
PropertyConfigurator.configure(log4jProp);
System.err.println("*** " + log4jProp + " 文件没有找到, 所以使用 BasicConfigurator初始化");
BasicConfigurator.configure();
super.init(config);
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
调用日志Log4JTestServlet,java
package com.
import java.io.IOE
import javax.servlet.ServletC
import javax.servlet.ServletE
import javax.servlet.annotation.WebS
import javax.servlet.http.HttpS
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import org.apache.log4j.L
* Servlet implementation class Log4JTestServlet
@WebServlet("/Log4JTestServlet")
public class Log4JTestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(Log4JTestServlet.class);
* @see HttpServlet#HttpServlet()
public Log4JTestServlet() {
// TODO Auto-generated constructor stub
* @see Servlet#init(ServletConfig)
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 记录debug级别的信息
logger.debug("This is debug message.");
// 记录info级别的信息
("This is info message.");
// 记录error级别的信息
logger.error("This is error message.");
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
接下来就是运行了,来看看结果:
输出结果:
四、Spring中使用Log4j
这里要实现web项目中利用Spring来使用Log4j
(1)接上面的工程,然后再导入Spring的包
(2)web.xml增加
&!-- 设置根目录 --&
&context-param&
&param-name&webAppRootKey&/param-name&
&param-value&webapp.root&/param-value&
&/context-param&
&context-param&
&param-name&log4jConfigLocation&/param-name&
&param-value&/WEB-INF/classes/log4j.properties&/param-value&
&/context-param&
&!-- 3000表示 开一条watchdog线程每60秒扫描一下配置文件的变化;这样便于日志存放位置的改变 --&
&context-param&
&param-name&log4jRefreshInterval&/param-name&
&param-value&3000&/param-value&
&/context-param&
&listener&
&listener-class&org.springframework.web.util.Log4jConfigListener&/listener-class&
&/listener&
整个内容如下:
&?xml version="1.0" encoding="UTF-8"?&
&web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="/xml/ns/javaee"
xsi:schemaLocation="/xml/ns/javaee /xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0"&
&display-name&LogLearning&/display-name&
&servlet-name&Log4JTestServlet&/servlet-name&
&servlet-class&com.mucfc.Log4JTestServlet&/servlet-class&
&/servlet&
&!--用来启动 log4jConfigLocation的servlet --&
&servlet-name&Log4JInitServlet&/servlet-name&
&servlet-class&com.mucfc.Log4JInitServlet&/servlet-class&
&init-param&
&param-name&log4j-properties-location&/param-name&
&param-value&/WEB-INF/classes/log4j.properties&/param-value&
&/init-param&
&load-on-startup&1&/load-on-startup&
&/servlet&--&
&servlet-mapping&
&servlet-name&Log4JTestServlet&/servlet-name&
&url-pattern&/test&/url-pattern&
&/servlet-mapping&
&!-- Spring 容器加载 --&
&listener&
&listener-class&org.springframework.web.context.ContextLoaderListener&/listener-class&
&/listener&
&context-param&
&param-name&contextConfigLocation&/param-name&
&param-value&classpath:applicationContext.xml&/param-value&
&/context-param&
&!-- 设置根目录 --&
&context-param&
&param-name&webAppRootKey&/param-name&
&param-value&webapp.root&/param-value&
&/context-param&
&context-param&
&param-name&log4jConfigLocation&/param-name&
&param-value&/WEB-INF/classes/log4j.properties&/param-value&
&/context-param&
&!-- 3000表示 开一条watchdog线程每60秒扫描一下配置文件的变化;这样便于日志存放位置的改变 --&
&context-param&
&param-name&log4jRefreshInterval&/param-name&
&param-value&3000&/param-value&
&/context-param&
&listener&
&listener-class&org.springframework.web.util.Log4jConfigListener&/listener-class&
&/listener&
&/web-app&
这里Log4JInitServlet.java就相当于没用到了。
(2)applicationContext.xml
没有内容:
&?xml version="1.0" encoding="UTF-8"?&
&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd"&
(3)这样日志就跟随Spring窗口启动而启动了
程序一运行,就会自动把日志打印
error.log为空,因为它只打印error级别以上的信息
浏览器输入http://localhost:8080/LogLearning2/test
然后打开文件
热门栏目订阅

我要回帖

更多关于 log4j jdbcappender 的文章

 

随机推荐