(转)如何自建appender扩展Log4j框架
?
图一?对于应用程序中的日志模块,提供一些UI层的基本操作,包括清空(图二,图四);变灰(图三);复制到粘贴板。The Main Text象征性的表示主应用程序的所有操作。
图二?
图三?
图四?同时在控制台输出所有日志信息。(图五)
图五?????同时在文本文件中输出所有日志信息。(图六)
图六6.log4j.xml本项目使用如下日志配置文件,将其放在项目的classpath下。<!DOCTYPE?log4j:configuration?SYSTEM?"log4j.dtd"><log4j:configuration?xmlns:log4j="http://jakarta.apache.org/log4j/"debug="false">????<!-- =================== -->???<!-- Appenders???????????-->???<!-- =================== -->???<appender?name="CONSOLE"?class="org.apache.log4j.ConsoleAppender">??????<errorHandler?class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>??????<param?name="Target"?value="System.out"/>??????<param?name="Threshold"?value="DEBUG"/>??????<layout?class="org.apache.log4j.PatternLayout">?????????<!-- The default pattern: Date Priority [Category] Message\n -->?????????<param?name="ConversionPattern"?value="%-5p %l%m%n"/>??????</layout>???</appender>????<appender?name="FILE"?class="org.apache.log4j.RollingFileAppender">?????<errorHandler?class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>?????<param?name="File"?value="logui.log"/>?????<param?name="Threshold"?value="INFO"/>?????<param?name="Append"?value="false"/>?????<param?name="MaxFileSize"?value="5000KB"/>?????<param?name="MaxBackupIndex"?value="50"/>?????<layout?class="org.apache.log4j.PatternLayout">???????<param?name="ConversionPattern"?value="%d %-5p [%c{1}] %m%n"/>?????</layout>???????</appender>????????<appender?name="ONE"?class="com.log.utils.LogOneAppender">??????<errorHandler?class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>???</appender>??????<appender?name="TWO"?class="com.log.utils.LogTwoAppender">??????<errorHandler?class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>???</appender>?????<!-- =============== -->???<!-- Loggers?????????-->???<!-- =============== -->???<logger?name="com.log.one">?????<level?value="DEBUG"?/>?????<appender-ref?ref="ONE"/>?????<appender-ref?ref="CONSOLE"/>???</logger>??????<logger?name="com.log.two">?????<level?value="DEBUG"?/>?????<appender-ref?ref="TWO"/>?????<appender-ref?ref="CONSOLE"/>???</logger>?????<root>??????<priority?value="INFO"?/>??????<appender-ref?ref="FILE"/>???</root></log4j:configuration>这里除常规的CONSOLE和FILE appender,增加两个appender,ONE和TWO,分别通过自建类LogOneAppender和LogTwoAppender定义。public?class?LogOneAppender?extends?AppenderSkeleton{????public?LogOneAppender() {}????protected?void?append(LoggingEvent event) {???????LogUI.log(event);????}????public?void?close() {}????public?boolean?requiresLayout() {???????return?false;????}}?public?class?LogTwoAppender?extends?AppenderSkeleton{????public?LogTwoAppender() {}????protected?void?append(LoggingEvent event) {???????LogUI.log(event);????}????public?void?close() {}????public?boolean?requiresLayout() {???????return?false;????}}在logger中通过logger name,com.log.one和com.log.two指定到上述的appender。7.主界面设计LogUI.java主面板为frame,其中嵌入LogPanel。log类的实体是一个Log4Jmonitor类的实例,通过它的addLogArea方法可以添加日志模块,其中的第二个参数对应log4j配置文件中的logger name。这里还提供一个Cache功能,即如果在主类(LogUI)或日志类(Log4Jmonitor)还没有实例化之前,已经有日志信息,则进行缓存。public?class?LogUI {????private?static?LogUI?instance;????private?static?JFrame?frame;????private?Log4JMonitor?logMonitor;????private?static?List<Object>?logCache?=?new?ArrayList<Object>();????public?LogUI() {???????instance?=?this;????}????///////////////////////UI????private?void?buildUI() {???????frame.addWindowListener(new?WindowAdapter() {???????????public?void?windowClosing(WindowEvent e) {??????????????System.exit(0);???????????}???????});???????frame.getContentPane().add(buildContentPanel(), BorderLayout.CENTER);???????frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);???????frame.setSize(100, 75);????}?????private?Component buildContentPanel() {???????JSplitPane contentSplit =?new?JSplitPane();???????contentSplit.setTopComponent(new?JTextArea("The Main Text"));???????contentSplit.setBottomComponent(buildLogPanel());???????contentSplit.setDividerLocation(550);???????contentSplit.setResizeWeight(1);???????return?contentSplit;????}?????private?Component buildLogPanel() {???????logMonitor?=?new?Log4JMonitor();???????logMonitor.addLogArea("log one",?"com.log.one",?true).setLevel(??????????????Level.DEBUG);???????logMonitor.addLogArea("log two",?"com.log.two",?true).setLevel(??????????????Level.DEBUG);???????for?(Object message :?logCache) {???????????logMonitor.logEvent(message);???????}???????return?logMonitor;????}?????public?void?show() {???????buildUI();???????frame.setVisible(true);????}????////////////////////Log????public?static?synchronized?void?log(final?Object msg) {???????if?(instance?==?null?||?instance.logMonitor?==?null) {???????????logCache.add(msg);???????????return;???????}???????if?(SwingUtilities.isEventDispatchThread()) {???????????instance.logMonitor.logEvent(msg);???????}?else?{???????????SwingUtilities.invokeLater(new?Runnable() {??????????????public?void?run() {??????????????????instance.logMonitor.logEvent(msg);??????????????}???????????});???????}????}????//////////////////Test Cases????public?void?doTests(){???????LogTestOne one=new?LogTestOne();???????one.doLog();???????LogTestTwo two=new?LogTestTwo();???????two.doLog();????}???????public?static?void?main(String[] args)?throws?Exception {???????frame?=?new?JFrame("LogUI ");???????LogUI logUi =?new?LogUI();???????logUi.show();???????logUi.doTests();????}}8.log类的实体Log4Jmonitor通过此类来建立日志模块。其中用到的JlogList.java(见附件)提供对日志模块的所有基本功能。addLogArea方法增加日志模块。logEvent方法对输出的日志事件类型做出判断,对该日志所属的日志模块(本实例为com.log.one和com.log.two)做出判断。public?class?Log4JMonitor?extends?JTabbedPane {????private?JLogList?defaultLogArea;????public?Log4JMonitor() {???????super(JTabbedPane.BOTTOM, JTabbedPane.SCROLL_TAB_LAYOUT);????}????public?JLogList addLogArea(String title, String loggerName,???????????boolean?isDefault) {???????JLogList logArea =?new?JLogList(title);???????logArea.addLogger(loggerName, !isDefault);???????addTab(title, logArea);???????if?(isDefault)???????????defaultLogArea?= logArea;???????return?logArea;????}????public?void?logEvent(Object msg) {???????if?(msg?instanceof?LoggingEvent) {???????????LoggingEvent event = (LoggingEvent) msg;???????????String loggerName = event.getLoggerName();???????????for?(int?c = 0; c < getTabCount(); c++) {??????????????Component tabComponent = getComponentAt(c);??????????????if?(tabComponent?instanceof?JLogList) {??????????????????JLogList logArea = (JLogList) tabComponent;??????????????????if?(logArea.monitors(loggerName)) {?????????????????????logArea.addLine(msg);??????????????????}??????????????}???????????}???????}?else?if?(defaultLogArea?!=?null) {???????????defaultLogArea.addLine(msg);???????}????}????public?boolean?hasLogArea(String loggerName) {???????for?(int?c = 0; c < getTabCount(); c++) {???????????Component tabComponent = getComponentAt(c);???????????if?(tabComponent?instanceof?JLogList) {??????????????JLogList logArea = (JLogList) tabComponent;??????????????if?(logArea.monitors(loggerName)) {??????????????????return?true;??????????????}???????????}???????}???????return?false;????}}?本文出自 “子 孑” 博客,请务必保留此出处http://zhangjunhd.blog.51cto.com/113473/48895