log4j java版如何將日誌寫入資料庫 __資料庫

來源:互聯網
上載者:User

其實如果是直接通過jdbc去串連資料庫,那麼下面的連結的

http://www.dankomannhaupt.de/projects/index.html
的jdbcappender.zip 已經能很方便的實現這個功能,

但是在現實情況,特別是大型應用,基本都是通過datasource來擷取
connection,而這個zip中已經明確說了不支援 DataSource,那麼我們怎麼辦呢。

我是這樣解決的,對於j2ee的應用本身不管你用spring+hibernate還是c3p0 來擷取
Datasource,最終他還是得到jdbc中的connection來進行資料庫操作,而jdbcappender
也是通過connection來操作資料庫,那麼思路就是如果通過在你架構中擷取jdbc的connection,
然後將他set到jdbcapplender中就可以了。

確定這種思路後,我就需要瞭解jdbcappender.zip中的代碼,看如果將connection 放入jdbcappender中

首先 我們看一下如果正常通過jdbc配置,這個jdbcAppender是怎麼整合到log4j中的
下面是jdbcAppender的用法

public class Log4JTest {
 // Create a category instance for this class
 static Logger logger = Logger.getLogger(Log4JTest.class);

 public static void main(String[] args) {
 
  
  JDBCAppender ja = new JDBCAppender();

  // Set options with method setOption()
  ja.setConnector("org.apache.log4j.jdbcplus.examples.OracleConnectionHandler");
  ja.setUrl("jdbc:oracle:thin:@..");
  ja.setUsername("mex_pr_dev65");
  ja.setPassword("mex_pr_dev65");

  ja.setSqlhandler("org.apache.log4j.jdbcplus.examples.SqlHandler");

  // Add the appender to a category
  
  logger.addAppender(ja);
  logger.debug("debug");
 
  
        }
 }
}

上面的類基本分為這麼幾個部分
1.和一般log4j用法一樣, 擷取logger instance
2.new 一個JDBCAppender
3.為jdbc設定兩部分參數,一個是jdbc 建立串連的參數,如url等 另一部分是具體insert sql的handler(你可以用handler來體現insert 語句也可以將sql寫入log4j的設定檔,我這裡就用handler處理insert語句)
4.將logger instance中添加剛才設定的JDBCAppender
5.完成

從上面的例子來看好像不能set connection,那麼後來查看JDBCAppender的源碼發現
JDBCAppender有setConnectionHandler(interface JDBCConnectionHandler())方法;
可以通過這個方法能將connection放入jdbcappender中,但必須實現介面DBCConnectionHandler

介面JDBCConnectionHandler 如下
public interface JDBCConnectionHandler {

    /**
     * Get a connection
     *
     * @return The Connection value
     * @exception Exception
     *                Description of Exception
     */
    Connection getConnection() throws Exception;

    /**
     * Get a defined connection
     *
     * @param _url
     *            Description of Parameter
     * @param _username
     *            Description of Parameter
     * @param _password
     *            Description of Parameter
     * @return The Connection value
     * @exception Exception
     *                Description of Exception
     */
    Connection getConnection(String _url, String _username, String _password) throws Exception;
}

這個時候你發現 我們找了半天Connection的地方原來在這裡

那麼我只要實現這個介面的getConnection() 方法就能將connection放入JDBCAppender中,

現在我們構建一個Handler,我這裡用的架構只是Hibernate3

我需要從hibernate3中擷取connecion就可以了

public class Cas2HibernateConnectionHandler implements JDBCConnectionHandler {

   //hibernate 的session Factory
   SessionFactory sf = HibernateConnection.getInstance();
 
 public Connection getConnection(){
  Connection con =null;
  try {
   con = sf.openSession().connection();
  
  } catch (Exception e) {
   e.printStackTrace();
  }
  
  return con;
 }

 public Connection getConnection(String arg0, String arg1, String arg2)
   throws Exception {
  // TODO Auto-generated method stub
  return null;
 }

}

這就是我的handler,為了讓代碼更清楚,我把我的HibernateConnection也貼出來,這是常見的Sington模式擷取hibernate的SessionFactory
public class HibernateConnection {

 private static SessionFactory sessionFactoryInstance = null;

 private HibernateConnection() {
 }
 
 //單元測試用的
 synchronized public static SessionFactory getInstance() {
  
   if (sessionFactoryInstance == null) {
    Configuration config;
    try {    
     config = new Configuration().configure(new File("E://cas2//config//hibernate//hibernate.cfg.xml"));
     sessionFactoryInstance = config.buildSessionFactory();
    } catch (HibernateException e) {
     e.printStackTrace();
    }
   }

  return sessionFactoryInstance;
 }
}

說到這裡我順便說一下,我這邊架構用的是hibernate3,還有很多資料庫相關的架構比如hibernate+spring或者c3p0等等,這些都無所謂
只要找到相應如果獲得jdbc connection的方法,同時構建自己的ConnectionHandler並實現裡面的getConnection()就可以了。

到這個時候資料庫連接已經能擷取了,接下來就需要寫具體的insert語句,這裡有兩種方法,一種就是直接在log4j的設定檔中寫
這個設定檔可以xml,也可以properties,這個網站也都有具體描述怎麼做,這麼不說了;
另外一種就是ja.setSqlhandler("org.apache.log4j.jdbcplus.examples.SqlHandler");
自己實現一個sqlHandler 後set到JDBCAppender中就可以了

新構建的sqlHander需要實現介面
public interface JDBCSqlHandler {

 /**
  * Get a sql-statement.
  * Return null or empty string if nothing should be logged.
  *
  * @return The SQL statement. Null if there is nothing to log.
  * @exception Exception
  *                Any Exception
  */
 String getStatement(LoggingEvent event) throws Exception;
}

他裡面只有一個方法getStatement,裡面寫入具體insert 語句就可以了

public class CasLoginHandler implements JDBCSqlHandler {

 private final int MAX_LENGTH_MESSAGE = 3000;

    public String getStatement(LoggingEvent event) throws Exception {
        // try { throw new Throwable(); } catch (Throwable th) {
        // th.printStackTrace(); }
        LocationInfo locinfo = event.getLocationInformation();
        ThrowableInformation throwableinfo = event.getThrowableInformation();
        StringBuffer throwableStringBuffer = new StringBuffer();
        String locinfoString = "'', '', '', ''";

        if (locinfo != null) {
            locinfoString = "'" + locinfo.getClassName() + "', '" + locinfo.getMethodName()
                    + "', '" + locinfo.getFileName() + "', '" + locinfo.getLineNumber() + "'";
        }
        if (throwableinfo != null) {
            String[] lines = throwableinfo.getThrowableStrRep();
            for (int index = 0; index < lines.length; index++) {
                throwableStringBuffer = (StringBuffer) throwableStringBuffer.append(lines[index]
                        + "/r/n");
            }
        }

        StringBuffer sb = new StringBuffer();
        sb.append("Insert into UM_SYS_LOG (ID, LOG_DATE, LOG_LEVEL, LOGGER, OPERATOR, APPLICATION_NAME, MESSAGE_KEY, LOG_MESSAGE)Values(");
        sb.append("SEQ_UM_SYS_LOG.nextval,");
        sb.append("TO_DATE('");
        sb.append(DateFormatUtil.formDateToyyyyMMdd24(new Date(event.timeStamp)));
        sb.append("','YYYY-DD-MM HH24:mi:SS')");
        sb.append(",'");
        sb.append(event.getLevel().toString());
        sb.append("','");
        sb.append(event.getLoggerName());
        sb.append("','bgao','CAS2','login sucess','user bgao loginSuccess')");

        return sb.toString();
    }

}

這是我構建的CasLoginHandler。
然後將該Handler 設定到JDBCAppender中就行了
ja.setSqlhandler("com.bgao.log.CasLogHandler");


這樣整個將log日誌寫入資料庫就完成了。當然下面還有問題可以供思考,一般log.debug("msg");這種寫法所有的日誌資訊都是以一條msg輸出
,比如"張三在127.0.0.1機器查詢表×××" ;如何簡單得將一句話insert到不同欄位,這個有很多方式,可以思考一下哪種更方便,更簡潔。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.