1log4j 概述

log4j 环境包括三个主要组件:
logger(日志记录器):控制要启用或禁用哪些日志记录语句。可以对日志记录器指定如下级别: ALL 、 DEBUG 、 INFO 、 WARN 、 ERROR , FATAL 。
layout(布局):根据用户的愿望格式化日志记录请求。
appender:向目的地发送格式化的输出。
2.理解 appender
log4j 框架允许向任何日志记录器附加多个 appender。可以在任何时候对某个日子记录器添加(或删除)appender。附随 log4j 分发的 appender 有多个,包括:
ConsoleAppender;FileAppender;SMTPAppender ;JDBCAppender;JMSAppender;NTEventLogAppender;SyslogAppender。
也可以创建自己的自定义 appender。
3.本工程设计的目标
通过自建appender类,来实现:
[1]在控制台输出日志;
[2]在log文件输出日志;
[3]在应用程序中建立日志模块(在UI层表现为建立一个日志面板),输出日志;
[4]对于不同包路径下的日志独立输出(在UI层表现为分不同的面板输出)。
4.预备知识
你可以在下面2篇文章中找到Log4j的相关基础介绍。
5.项目文件分布与效果
文件分布如图一所示。我们对于com.log.one包下的所有java文件中的日志信息输出到log one模块(图二);对于com.log.two包下的所有java文件中的日志信息输出到log two模块(图四)。本文只象征性的建立了两个测试文件,分别放在两个包下。
com.log.one.LogTestOne.java
public class LogTestOne {
    private final static Logger log = Logger.getLogger(LogTestOne.class);
    public void doLog(){
       log.debug("TestOne debug");
       log.info("TestOne info");
       log.warn("TestOne warn");
       log.error("TestOne error");
       log.fatal("TestOne fatal");
    }
}
 
com.log.two.LogTestTwo.java
public class LogTestTwo {
    private final static Logger log = Logger.getLogger(LogTestTwo.class);
    public void doLog() {
       log.debug("TestTwo debug");
       log.info("TestTwo info");
       log.warn("TestTwo warn");
       log.error("TestTwo error");
       log.fatal("TestTwo fatal");
    }
}
 
 
 
图一
 
对于应用程序中的日志模块,提供一些UI层的基本操作,包括清空(图二,图四);变灰(图三);复制到粘贴板。
The Main Text象征性的表示主应用程序的所有操作。
 
 
图二
 
 
 
图三
 
 
 
图四
 
同时在控制台输出所有日志信息。(图五)
 
 
图五
 
    同时在文本文件中输出所有日志信息。(图六)
 
 
图六
6log4j.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();
    }
}
8log类的实体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;
    }
}
 

如何自建appender扩展Log4j框架的更多相关文章

  1. 002 使用Appender扩展logger框架

    这个地方,在看公司的源代码的时候,写的知识点: 现在再看,竟然不是太懂,重新写一份新的文档,外加示例说明. 一:说明 1.log4j 环境的三个主要组件: logger(日志记录器):控制要启用或禁用 ...

  2. log4j框架logger的继承关系以及使用场景

    log4j框架logger的继承关系以及使用场景 log4j日志框架logger是存在继承关系的,我们一般都会在log4j.properties文件中定义log4j.rootLogger.其他所有lo ...

  3. Log4j框架

    一.Log4j基本使用方法 Log4j由三个重要的组件构成:日志信息的优先级 Loggers,日志信息的输出目的地 Appenders,日志信息的输出格式 Layouts .日志信息的优先级从高到低 ...

  4. Log4J Appender - 将Log4J的日志内容发送到agent的source

    项目中使用log4j打印的内容同时传输到flume 1.flume端 flume的agent配置内容如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 a1.sour ...

  5. 扩展Log4j支持JNDI数据源

    log4j.properties配置文件: log4j.rootLogger=INFO,db #使用log4j扩展支持JNDI数据源 log4j.appender.db=com.qdgswx.log4 ...

  6. Kotlin的扩展函数:扩展Android框架(KAD 08)

    作者:Antonio Leiva 时间:Jan 11, 2017 原文链接:https://antonioleiva.com/extension-functions-kotlin/ 扩展函数是Kotl ...

  7. 架构探险笔记3-搭建轻量级Java web框架

    MVC(Model-View-Controller,模型-视图-控制器)是一种常见的设计模式,可以使用这个模式将应用程序进行解耦. 上一章我们使用Servlet来充当MVC模式中的Controller ...

  8. Robot Framework(十四) 扩展RobotFramework框架——创建测试库

    4.1创建测试库 Robot Framework的实际测试功能由测试库提供.有许多现有的库,其中一些甚至与核心框架捆绑在一起,但仍然经常需要创建新的库.这个任务并不复杂,因为正如本章所示,Robot ...

  9. Robot Framework(十五) 扩展RobotFramework框架——远程库接口

    4.2远程库接口 远程库接口提供了在运行Robot Framework本身的机器上运行测试库的方法,以及使用除本机支持的Python和Java之外的其他语言实现库的方法.对于测试库,用户远程库看起来与 ...

随机推荐

  1. NOI全国赛(2001)--食物链

    今天写了道并查集的题,看来并查集的题刷少了,,,,,用法好神奇啊!!!开三倍并查集 用i表示自己,i+n存天敌,i+2*n存可以克制de,再逻辑判断一下即可. 所以,要意识到并查集的分类处理可以开不同 ...

  2. php从气象局获取天气预报并保存到服务器

    思路:1.打开网页时读取中国气象网的接口得到每个城市的该日json:2.解析并保存到mysql:3.客户端访问mysql得到数据集. 所包含的技巧: 进度条.flush()问题.mysql.xml.p ...

  3. Windows Phone 8.1开发:触控和指针事件2

    原文出自:http://www.bcmeng.com/windows-phone-touch1/ 请在此输入内容(想死啊,写了一个小时,直接没保存不小心删掉了.那就简单说说吧)Pointer事件有以下 ...

  4. 前端学PHP之Session

    前面的话 Session技术和Cookie相似,都是用来储存使用者的相关资料.但最大的不同之处在于Cookie是将数据存放在客户端的计算机之中,而Session则是将数据存放于服务器系统之下.Sess ...

  5. Python注释用法

    在Python中的注释与其他语言相比有很大的不同,但使用起来也很简单.在Python中有两种注释,一种是单行注释,一种是多行注释.单行注释适用于简短快速的注释(或者用于调试),而块注释常用于描述一段内 ...

  6. javaWEB与Session

    HttpSession(*****)1. HttpSession概述  * HttpSession是由JavaWeb提供的,用来会话跟踪的类.session是服务器端对象,保存在服务器端!!!  * ...

  7. 【iOS】7.4 定位服务->3.2 地图框架MapKit 功能2:路线规划(导航)

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  8. 【webpack学习笔记(一)】流行的前端模块化工具webpack初探

    从开发文件到生产文件   有一天我突然意识到一个问题,在使用react框架搭建应用时,我使用到了sass/less,JSX模版以及ES6的语法在编辑器下进行开发,使用这些写法是可以提高开发的效率.可是 ...

  9. VSCode里的一些有用的插件

    1.EaseServer 作用:开启本地 http server,然后在browser里打开html: 在调试页面的时候,打开页面比较方便,不需要先开启server,再打开html 2.Debugge ...

  10. 解析新浪微博表情包的一套js代码

    本文出自本人原创,转载请注明出处 /** * Created by Lemon on 2017/4/6. *//** * return 解析后的值 * analysis 参数 * obj.value: ...