log4j java版如何將日志寫入數(shù)據(jù)庫(kù)
其實(shí)如果是直接通過(guò)jdbc去連接數(shù)據(jù)庫(kù),那么下面的鏈接的
http://www.dankomannhaupt.de/projects/index.html
的jdbcappender.zip 已經(jīng)能很方便的實(shí)現(xiàn)這個(gè)功能,
但是在現(xiàn)實(shí)情況,特別是大型應(yīng)用,基本都是通過(guò)datasource來(lái)獲取
connection,而這個(gè)zip中已經(jīng)明確說(shuō)了不支持 DataSource,那么我們?cè)趺崔k呢?
我是這樣解決的,對(duì)于j2ee的應(yīng)用本身不管你用spring+hibernate還是c3p0 來(lái)獲取
Datasource,最終他還是得到j(luò)dbc中的connection來(lái)進(jìn)行數(shù)據(jù)庫(kù)操作,而jdbcappender
也是通過(guò)connection來(lái)操作數(shù)據(jù)庫(kù),那么思路就是如果通過(guò)在你框架中獲取jdbc的connection,
然后將他set到j(luò)dbcapplender中就可以了。
確定這種思路后,我就需要了解jdbcappender.zip中的代碼,看如果將connection 放入jdbcappender中
首先 我們看一下如果正常通過(guò)jdbc配置,這個(gè)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");
}
}
}
上面的類基本分為這么幾個(gè)部分
1.和一般log4j用法一樣, 獲取logger instance
2.new 一個(gè)JDBCAppender
3.為jdbc設(shè)置兩部分參數(shù),一個(gè)是jdbc 建立連接的參數(shù),如url等 另一部分是具體insert sql的handler(你可以用handler來(lái)體現(xiàn)insert 語(yǔ)句也可以將sql寫入log4j的配置文件,我這里就用handler處理insert語(yǔ)句)
4.將logger instance中添加剛才設(shè)置的JDBCAppender
5.完成
從上面的例子來(lái)看好像不能set connection,那么后來(lái)查看JDBCAppender的源碼發(fā)現(xiàn)
JDBCAppender有setConnectionHandler(interface JDBCConnectionHandler())方法;
可以通過(guò)這個(gè)方法能將connection放入jdbcappender中,但必須實(shí)現(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;
}
這個(gè)時(shí)候你發(fā)現(xiàn) 我們找了半天Connection的地方原來(lái)在這里
那么我只要實(shí)現(xiàn)這個(gè)接口的getConnection() 方法就能將connection放入JDBCAppender中,
現(xiàn)在我們構(gòu)建一個(gè)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也貼出來(lái),這是常見(jiàn)的Sington模式獲取hibernate的SessionFactory
public class HibernateConnection {
private static SessionFactory sessionFactoryInstance = null;
private HibernateConnection() {
}
//單元測(cè)試用的
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;
}
}
說(shuō)到這里我順便說(shuō)一下,我這邊框架用的是hibernate3,還有很多數(shù)據(jù)庫(kù)相關(guān)的框架比如hibernate+spring或者c3p0等等,這些都無(wú)所謂
只要找到相應(yīng)如果獲得jdbc connection的方法,同時(shí)構(gòu)建自己的ConnectionHandler并實(shí)現(xiàn)里面的getConnection()就可以了。
到這個(gè)時(shí)候數(shù)據(jù)庫(kù)連接已經(jīng)能獲取了,接下來(lái)就需要寫具體的insert語(yǔ)句,這里有兩種方法,一種就是直接在log4j的配置文件中寫
這個(gè)配置文件可以xml,也可以properties,這個(gè)網(wǎng)站也都有具體描述怎么做,這么不說(shuō)了;
另外一種就是ja.setSqlhandler("org.apache.log4j.jdbcplus.examples.SqlHandler");
自己實(shí)現(xiàn)一個(gè)sqlHandler 后set到JDBCAppender中就可以了
新構(gòu)建的sqlHander需要實(shí)現(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;
}
他里面只有一個(gè)方法getStatement,里面寫入具體insert 語(yǔ)句就可以了
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();
}
}
這是我構(gòu)建的CasLoginHandler。
然后將該Handler 設(shè)置到JDBCAppender中就行了
ja.setSqlhandler("com.bgao.log.CasLogHandler");
這樣整個(gè)將log日志寫入數(shù)據(jù)庫(kù)就完成了。當(dāng)然下面還有問(wèn)題可以供思考,一般log.debug("msg");這種寫法所有的日志信息都是以一條msg輸出
,比如"張三在127.0.0.1機(jī)器查詢表×××" ;如何簡(jiǎn)單得將一句話insert到不同字段,這個(gè)有很多方式,可以思考一下哪種更方便,更簡(jiǎn)潔。
posted on 2010-07-09 15:25 linugb118 閱讀(2870) 評(píng)論(1) 編輯 收藏