Web應用中Log4j與JNDI結合2 -- JNDI指定日誌路徑

Web應用中Log4j與JNDI結合1 – JNDI指定配置文件一文中,我展示瞭如何通過定製ServletListener來從JNDI指定地址讀取log4j配置文件。這一篇我來講解如何通過JNDI指定日誌路徑。普通的log4j appender沒有辦法處理JNDI相關的日誌文件。同ServletListener定製一樣,我們要定製Appender。這裏以DailyRollingFileAppender爲例。普通按照天來自動截斷,例如:

<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
    <param name="file" value="default.log" />
    <param name="append" value="false" />
    <param name="datePattern" value="'.'yyyy-MM-dd" />
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{ABSOLUTE} [%-5p] [%t] [%c{1}] %m%n" />
    </layout>
  </appender>

通過Log4j源碼分析(org.apache.log4j.LogManager.java, org.apache.log4j.xml.DOMConfigurator.java and DailyRollingFileAppender.java),我們可以知道,在Web應用XML的配置方式下,LogManager.java的static初始化塊會根據log4j.configuration的配置,通過org.apache.log4j.helpers.OptionConverter.selectAndConfigure方法找到對應的log4j xml配置文件,然後通過Call org.apache.log4j.xml.DOMConfigurator.java的doConfigure方法,去到parse方法,根據Logger和Root node的APPENDER_REF_TAG調用findAppenderByReference,最後在parseAppender 中把param配置賦值給appender的屬性,然後通過調用appender的activeOptions來打開日誌記錄文件。

DailyRollingFileAppender.java
public void setFile(String file) {
    // Trim spaces from both ends. The users probably does not want
    // trailing spaces in file names.
    String val = file.trim();
    fileName = val;
  }

public void activateOptions() {
    //based on fileName to open log file
    super.activateOptions();
    if(datePattern != null && fileName != null) {
      now.setTime(System.currentTimeMillis());
      sdf = new SimpleDateFormat(datePattern);
      int type = computeCheckPeriod();
      printPeriodicity(type);
      rc.setType(type);
      File file = new File(fileName);
      scheduledFilename = fileName+sdf.format(new Date(file.lastModified()));

    } else {
      LogLog.error("Either File or DatePattern options are not set for appender ["
           +name+"].");
    }
  }

那麼想通過jndi來指定日誌文件,就是要給修改對filename賦值。簡單實現可以通過繼承DailyRollingFileAppender,在新的子類(JndiDailyRollingFileAppender )中加入新的屬性jndiDirURL來接受JNDI指定日誌路徑文件夾(在xml配置中必須放在file參數之前),然後重寫filename賦值的setFile方法,獲取基於JNDI的完整文件路徑。列出參考代碼如下:

public class JndiDailyRollingFileAppender extends DailyRollingFileAppender  {
   private String jndiDirURL;
   public void setJndiDirURL(String jndiDirURL){
       this.jndiDirURL= jndiDirURL;
   }
   public String getJndiDirURL(){
       return this.jndiDirURL;
   }
   public JndiDailyRollingFileAppender (String jndiDirURL, Layout layout, String filename, String datePattern) throws IOException {
       super(layout, getAbsoluteName(jndiDirURL,filename), datePattern);
   }
   private String getAbsoluteName(String filename){
       try{
        Context ic = new InitialContext();
        String parent= ((URL)ic.lookup(jndiDirURL)).toExternalForm();
        String absolutePath = parent + File.separator + filename;
        return absolutePath;
        }catch(Exception e){
           LOG.error("unable to find jndidirurl: {}, JndiDirURL);
           return filename;
        }
  }

   @Override
   public void setFile(String file) {
      return super.setFile(getAbsoluteName(file));
   }
}

對應的log4j.xml中的配置文件如下:

<appender name="default" class="com.demo.JndiDailyRollingFileAppender">
    <param name="jndiDirURL" value="java:comp/env/demo_log" />
    <param name="file" value="default.log" />
    <param name="append" value="false" />
    <param name="datePattern" value="'.'yyyy-MM-dd" />
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{ABSOLUTE} [%-5p] [%t] [%c{1}] %m%n" />
    </layout>
  </appender>
發佈了110 篇原創文章 · 獲贊 14 · 訪問量 35萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章