linugb118--java space

Java

log4j java版如何将日志写入数据库

 

其实如果是直接通过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到不同字段,这个有很多方式,可以思考一下哪种更方便,更简洁。

 

 

 

 

posted on 2010-07-09 15:25 linugb118 阅读(2862) 评论(1)  编辑  收藏

Feedback

# re: log4j java版如何将日志写入数据库[未登录] 2010-07-09 15:44 ada

弱弱问句,Log4J还分Java和.net版本吗?  回复  更多评论   



只有注册用户登录后才能发表评论。


网站导航:
 

My Links

Blog Stats

常用链接

留言簿(1)

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜