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. (8)集合之List,ArrayList,LinkedList

    集合的体系结构 Collection 单列集合的接口 |----List 如果实现了List接口的集合类,具备的特点是有序,可重复 |----Set 如果实现了Set接口的集合类,集合特点无序不可重复 ...

  2. 内网转发ngrok的使用

    1.下载解压ngrok:https://ngrok.com/download 2.执行ngrok会打开控制台 3.输入命令,开始映射本地的8080端口 ngork http 8080 控制台会返回一个 ...

  3. unity3d屏蔽Windows10输入法

    在win10上,如果安装了某些输入法(比如QQ输入法),会造成unity的键盘事件被输入法捕获而不能触发的情况.只有将输入法切换到英文状态下才能响应键盘事件. 解决办法有, 1:用户主动切换输入法,甚 ...

  4. Asp.net SignalR 应用并实现群聊功能 开源代码

    ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务 ...

  5. Linux ubuntu 安装gcc、g++、 pcre、zlib、ssl、nginx和该内存不能为written解决方法

    1.楼主也是第一次接触Linux  如果有错误的地方还请各位朋友指出.... 2.gcc.g++依赖库:sudo apt-get install build-essential,sudoapt-get ...

  6. 自己写的一个 java swing 的闹钟

    上一周新入职,把代码down下来之后,领导和我讲了一些大概的业务以及代码流程(领导是技术出身),领导让我自己先看看代码,然后我看了两天,觉得已经完全可以接任务了,但是领导却迟迟没有分配任务给我,虽然他 ...

  7. 20155231 2016-2017-2 《Java程序设计》第5周学习总结

    # 20155231 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 学习目标 理解异常架构 掌握try...catch...finally处理异常的方法 会 ...

  8. (转)POPTEST创始人李爱然:谢谢,帮助我的朋友!!!!

    2015年11月15日,脉脉上随意浏览信息.每天有很多人加我,我也会主动加一些人.脉脉的广告语“打通职场人脉”,很直白的告诉我们脉脉是用来找人办事的.简单明了,不用故作清高. “利”,有利可图便是“友 ...

  9. Hibernate(二)之Hibernate-api详解

    一.Hibernate体系结构 二.Hibernate-api详解 2.1.Configuration配置对象 Configuration是用来加载配置文件的 我们Hibernate中主要有两个配置文 ...

  10. 进入html+css世界的正确姿势

    今天,我带大家一起走进html+css的世界. HTML其实是HyperText Markup Language的缩写, 超文本标记语言.他是用于告诉浏览器这是一个网页, 也就是说告诉浏览器我是一个H ...