|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
主要缺点就是:速度比较慢,没有C和C++快数据|数据库|数据库毗连 我们都晓得log4j是一个优异的开源日记纪录项目,我们不但能够对输入的日记的格局自界说,还能够本人界说日记输入的目标地,好比:屏幕,文本文件,数据库,乃至能经由过程socket输入。
如今让我们对日记输入到数据库来举行设置
设置以下:
#---JDBC---输入到数据库
#JDBCAppenderlog4j.propertiesfile
#log4j.rootCategory=WARN,JDBC
#APPENDERJDBC
log4j.appender.JDBC=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.JDBC.driver=com.mysql.jdbc.Driver
log4j.appender.JDBC.URL=jdbc:mysql://localhost:3306/test
log4j.appender.JDBC.user=use
log4j.appender.JDBC.password=password
log4j.appender.JDBC.layout=org.apache.log4j.PatternLayout
log4j.appender.JDBC.sql=INSERTINTOLOGGING(log_date,log_level,location,message)VALUES(%d{ISO8601},%-5p,%C,%L,%m)
表布局以下:
log_date varchar2(50)
log_level varchar2(5)
location varchar2(100)
message varchar2(1000)
笔者照做,但没有运转乐成,并且此种办法是使用传统的数据库毗连办法,关于数据库的办理和效力严峻不敷,在如今这个毗连池横行的时期,为何我们不克不及给给Log4j配上毗连池,让Log4j使用数据毗连池的毗连和数据库举行通信。现检察Log4j的Api,发明JDBCAppender这个类有以下几段话:WARNING:ThisversionofJDBCAppenderisverylikelytobecompletelyreplacedinthefuture.Moreoever,itdoesnotlogexceptions.TheJDBCAppenderprovidesforsendinglogeventstoadatabase.
Foruseasabaseclass:
OverridegetConnection()topassanyconnectionyouwant.Typicallythisisusedtoenableapplicationwideconnectionpooling.
OverridecloseConnection(Connectioncon)--ifyouoverridegetConnectionmakesuretoimplementcloseConnectiontohandletheconnectionyougenerated.Typicallythiswouldreturntheconnectiontothepoolitcamefrom.
OverridegetLogStatement(LoggingEventevent)toproducespecializedordynamicstatements.Thedefaultusesthesqloptionvalue.
本来log4j倡议我们把其供应的JDBCAppender作为基类来利用,然后Override三个父类的办法:getConnection(),closeConnection(Connectioncon)和getLogStatement(LoggingEventevent)。
本来云云,那就写一个子类JDBCPoolAppender来替换这个JDBCAppender
JDBCPoolAppender代码和其相干代码以下:
JDBCPoolAppender.java:
packagecommon.log;
importjava.sql.Connection;
importorg.apache.log4j.spi.LoggingEvent;
importjava.sql.SQLException;
importjava.sql.Statement;
importjava.util.Iterator;
importorg.apache.log4j.spi.ErrorCode;
importorg.apache.log4j.PatternLayout;
importcommon.sql.MyDB;
importcommon.sql.GeneralDb;
publicclassJDBCPoolAppenderextendsorg.apache.log4j.jdbc.JDBCAppender{
privateMyDBmydb=null;
protectedStringsqlname="";//增添一个数据库jndiName的属性
protectedConnectionconnection=null;
protectedStringsqlStatement="";
/**
*sizeofLoggingEventbufferbeforewrittingtothedatabase.
*Defaultis1.
*/
protectedintbufferSize=1;
publicJDBCPoolAppender(){
super();
}
/**
*ArrayListholdingthebufferofLoggingEvents.
*/
publicvoidappend(LoggingEventevent){
buffer.add(event);
if(buffer.size()>=bufferSize)
flushBuffer();
}
/**
*BydefaultgetLogStatementsendstheeventtotherequiredLayoutobject.
*ThelayoutwillformatthegivenpatternintoaworkableSQLstring.
*
*OverridingthisprovidesdirectaccesstotheLoggingEvent
*whenconstructingtheloggingstatement.
*
*/
protectedStringgetLogStatement(LoggingEventevent){
returngetLayout().format(event);
}
/**
*
*Overridethistoprovideanalertnatemethodofgetting
*connections(suchascaching). Onemethodtofixthisistoopen
*connectionsatthestartofflushBuffer()andclosethematthe
*end. IuseaconnectionpooloutsideofJDBCAppenderwhichis
*accessedinanoverrideofthismethod.
**/
protectedvoidexecute(Stringsql)throwsSQLException{
Connectioncon=null;
Statementstmt=null;
try{
con=getConnection();
stmt=con.createStatement();
stmt.executeUpdate(sql);
}catch(SQLExceptione){
if(stmt!=null)
stmt.close();
throwe;
}
stmt.close();
closeConnection(con);
//System.out.println("Execute:"+sql);
}
/**
*Overridethistoreturntheconnectiontoapool,ortocleanupthe
*resource.
*
*Thedefaultbehaviorholdsasingleconnectionopenuntiltheappender
*isclosed(typicallywhengarbagecollected).
*/
protectedvoidcloseConnection(Connectioncon){
mydb=null;
try{
if(connection!=null&&!connection.isClosed())
connection.close();
}catch(SQLExceptione){
errorHandler.error("Errorclosingconnection",e,
ErrorCode.GENERIC_FAILURE);
}
}
/**
*Override此函数来使用毗连池前往一个Connetion对象
*
*/
protectedConnectiongetConnection()throwsSQLException{
try{
mydb=GeneralDb.getInstance(sqlname);
connection=mydb.getConnection();
}catch(Exceptione){
errorHandler.error("Erroropeningconnection",e,ErrorCode.GENERIC_FAILURE);
}
returnconnection;
}
/**
*Closestheappender,flushingthebufferfirstthenclosingthedefault
*connectionifitisopen.
*/
publicvoidclose(){
flushBuffer();
try{
if(connection!=null&&!connection.isClosed())
connection.close();
}catch(SQLExceptione){
errorHandler.error("Errorclosingconnection",e,
ErrorCode.GENERIC_FAILURE);
}
this.closed=true;
}
/**
*loopsthroughthebufferofLoggingEvents,getsa
*sqlstringfromgetLogStatement()andsendsittoexecute().
*ErrorsaresenttotheerrorHandler.
*
*IfastatementfailstheLoggingEventstaysinthebuffer!
*/
publicvoidflushBuffer(){
//Dotheactuallogging
removes.ensureCapacity(buffer.size());
for(Iteratori=buffer.iterator();i.hasNext();){
try{
LoggingEventlogEvent=(LoggingEvent)i.next();
Stringsql=getLogStatement(logEvent);
execute(sql);
removes.add(logEvent);
}catch(SQLExceptione){
errorHandler.error("Failedtoexcutesql",e,
ErrorCode.FLUSH_FAILURE);
}
}
//removefromthebufferanyeventsthatwerereported
buffer.removeAll(removes);
//clearthebufferofreportedevents
removes.clear();
}
/**closestheappenderbeforedisposal*/
publicvoidfinalize(){
close();
}
/**
*JDBCAppenderrequiresalayout.
**/
publicbooleanrequiresLayout(){
returntrue;
}
/**
*
*/
publicvoidsetSql(Strings){
sqlStatement=s;
if(getLayout()==null){
this.setLayout(newPatternLayout(s));
}else{
((PatternLayout)getLayout()).setConversionPattern(s);
}
}
/**
*Returnspre-formatedstatementeg:insertintoLogTable(msg)values("%m")
*/
publicStringgetSql(){
returnsqlStatement;
}
publicvoidsetSqlname(Stringsqlname){
sqlname=sqlname;
}
publicStringgetSqlname(){
returnsqlname;
}
publicvoidsetBufferSize(intnewBufferSize){
bufferSize=newBufferSize;
buffer.ensureCapacity(bufferSize);
removes.ensureCapacity(bufferSize);
}
publicintgetBufferSize(){
returnbufferSize;
}
}
MyDB.java:
packagecommon.sql;
importjava.sql.*;
importcom.codestudio.sql.*; //引进开源项目Poolman数据库毗连池的包
publicclassMyDB{
publicstaticfinalStringmodule=MyDB.class.getName();
privateStringdbName="";
privatePoolManplmn=null;
publicMyDB(StringdbName){
try{
if(plmn==null){
plmn=(PoolMan)Class.forName("com.codestudio.sql.PoolMan").
newInstance();
}
}catch(Exceptionec){
System.out.println(ec.toString()+module);
}
this.dbName=dbName;
}
privateConnectiongetNewConnection(){
Connectionconn=null;
try{
conn=plmn.connect("jdbc:poolman://"+dbName);
conn.setAutoCommit(true);
}catch(Exceptionec){
System.out.println(ec.toString()+"First:Connectsqlseverfailed"+module);
try{
Thread.sleep(1000);
conn=plmn.connect("jdbc:poolman://"+dbName);
conn.setAutoCommit(true);
}catch(Exceptionecs){
System.out.println(ecs.toString()+"Again:Connectsqlseverfaile"+module);
}
}
returnconn;
}
publicConnectiongetConnection(){
returngetNewConnection();
}
}
GeneralDb.java:
packagecommon.sql;
packagecommon.sql;
importjava.util.*;
publicclassGeneralDb{
privatestaticHashtabledbPool;
publicstaticMyDBgetInstance(Stringdbname){
if(dbPool==null){
dbPool=newHashtable();
}
MyDBdb=(MyDB)dbPool.get(dbname);
if(db==null){
db=newMyDB(dbname);
dbPool.put(dbname,db);
}
returndb;
}
}
Log4j数据库毗连池的设置以下:
log4j.appender.JDBC=common.log.JDBCPoolAppender
log4j.appender.JDBC.sqlname=log
log4j.appender.JDBC.layout=org.apache.log4j.PatternLayout
log4j.appender.JDBC.sql=INSERTINTOLOGGING(log_date,log_level,location,message)VALUES(%d{ISO8601},%-5p,%C,%L,%m)
poolman.xml设置以下:
〈?xmlversion="1.0"encoding="UTF-8"?>
〈poolman>
〈management-mode>local〈/management-mode>
〈datasource>
〈dbname>log〈/dbname>
〈jndiName>log〈/jndiName>
〈driver>com.mysql.jdbc.Driver〈/driver>
〈url>jdbc:mysql://localhost:3306/test〈/url>
〈username>use〈/username>
〈password>password〈/password>
〈minimumSize>0〈/minimumSize>
〈maximumSize>10〈/maximumSize>
〈logFile>logs/mysql.log〈/logFile>
〈/datasource>
〈/poolman>
运转乐成!关于JDBCPoolAppender的属性(好比sqlname属性)我们能够使用Log4j的反射机制任意增加,只需在设置文件给其附上值便可使用,而本来的父类内里的一些属性(username甚么的)和其get,set办法因为在毗连池中不必要,以是删除。而在JDBCPoolAppender类中,我也只是将getConnection办法Override,在这个办法中我们能够依据必要天生我们的Connection对象,别的两个办法人人能够依据需求来决意如何Override。:)
还得说上一点,就java本质而言,是面相对象的,但是你有没有发现,java也不全是,比如说基本类型,int,那他就是整型而不是对象,转换类型是还得借助包装类。 |
|