linugb118--java space

          Java

          log4j java版如何將日志寫入數(shù)據(jù)庫

           

          其實如果是直接通過jdbc去連接數(shù)據(jù)庫,那么下面的鏈接的

          http://www.dankomannhaupt.de/projects/index.html
          的jdbcappender.zip 已經(jīng)能很方便的實現(xiàn)這個功能,

          但是在現(xiàn)實情況,特別是大型應用,基本都是通過datasource來獲取
          connection,而這個zip中已經(jīng)明確說了不支持 DataSource,那么我們怎么辦呢?

          我是這樣解決的,對于j2ee的應用本身不管你用spring+hibernate還是c3p0 來獲取
          Datasource,最終他還是得到jdbc中的connection來進行數(shù)據(jù)庫操作,而jdbcappender
          也是通過connection來操作數(shù)據(jù)庫,那么思路就是如果通過在你框架中獲取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設置兩部分參數(shù),一個是jdbc 建立連接的參數(shù),如url等 另一部分是具體insert sql的handler(你可以用handler來體現(xiàn)insert 語句也可以將sql寫入log4j的配置文件,我這里就用handler處理insert語句)
          4.將logger instance中添加剛才設置的JDBCAppender
          5.完成

          從上面的例子來看好像不能set connection,那么后來查看JDBCAppender的源碼發(fā)現(xiàn)
          JDBCAppender有setConnectionHandler(interface JDBCConnectionHandler())方法;
          可以通過這個方法能將connection放入jdbcappender中,但必須實現(xiàn)接口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;
          }

          這個時候你發(fā)現(xiàn) 我們找了半天Connection的地方原來在這里

          那么我只要實現(xiàn)這個接口的getConnection() 方法就能將connection放入JDBCAppender中,

          現(xiàn)在我們構建一個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,還有很多數(shù)據(jù)庫相關的框架比如hibernate+spring或者c3p0等等,這些都無所謂
          只要找到相應如果獲得jdbc connection的方法,同時構建自己的ConnectionHandler并實現(xiàn)里面的getConnection()就可以了。

          到這個時候數(shù)據(jù)庫連接已經(jīng)能獲取了,接下來就需要寫具體的insert語句,這里有兩種方法,一種就是直接在log4j的配置文件中寫
          這個配置文件可以xml,也可以properties,這個網(wǎng)站也都有具體描述怎么做,這么不說了;
          另外一種就是ja.setSqlhandler("org.apache.log4j.jdbcplus.examples.SqlHandler");
          自己實現(xiàn)一個sqlHandler 后set到JDBCAppender中就可以了

          新構建的sqlHander需要實現(xiàn)接口
          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日志寫入數(shù)據(jù)庫就完成了。當然下面還有問題可以供思考,一般log.debug("msg");這種寫法所有的日志信息都是以一條msg輸出
          ,比如"張三在127.0.0.1機器查詢表×××" ;如何簡單得將一句話insert到不同字段,這個有很多方式,可以思考一下哪種更方便,更簡潔。

           

           

           

           

          posted on 2010-07-09 15:25 linugb118 閱讀(2867) 評論(1)  編輯  收藏

          Feedback

          # re: log4j java版如何將日志寫入數(shù)據(jù)庫[未登錄] 2010-07-09 15:44 ada

          弱弱問句,Log4J還分Java和.net版本嗎?  回復  更多評論   



          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           

          My Links

          Blog Stats

          常用鏈接

          留言簿(1)

          隨筆檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 余庆县| 讷河市| 闵行区| 舒兰市| 股票| 南川市| 达州市| 东乡族自治县| 米林县| 永济市| 谢通门县| 翼城县| 敦煌市| 江油市| 海门市| 岳普湖县| 綦江县| 阿拉善盟| 安塞县| 西畴县| 武邑县| 水富县| 喀什市| 万荣县| 广饶县| 靖远县| 栖霞市| 婺源县| 边坝县| 察哈| 长白| 酒泉市| 雷波县| 宁明县| 静安区| 万源市| 周口市| 弋阳县| 江都市| 姜堰市| 黔西县|