给log4j配置数据库连接
http://blog.csdn.net/socoolfj/article/details/542169 我们都知道log4j是一个优秀的开源日志记录项目,我们不仅可以对输出的日志的式自定义,还可以自己定义日志输出的目的地,比如:屏幕,文本文件,数据库,甚至能通过socket输出。 现在让我们对日志输出
http://blog.csdn.net/socoolfj/article/details/542169
我们都知道log4j是一个优秀的开源日志记录项目,我们不仅可以对输出的日志的格式自定义,还可以自己定义日志输出的目的地,比如:屏幕,文本文件,数据库,甚至能通过socket输出。
现在让我们对日志输出到数据库来进行配置
配置如下:
#---JDBC ---输出到数据库
# JDBCAppender log4j.properties file
#log4j.rootCategory=WARN,JDBC
# APPENDER JDBC
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=INSERT INTO LOGGING (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:
This version of JDBCAppender is very likely to be completely replaced in the future. Moreoever, it does not log exceptions. The JDBCAppender provides for sending
log events to a database.
For use as a base class:
- Override
getConnection()
to pass any connection you want. Typically this is used to enable application wide connection pooling. - Override
closeConnection(Connection con)
-- if you override getConnection make sure to implementcloseConnection
to handle the connection you generated. Typically this would return the connection to the pool it came from. - Override
getLogStatement(LoggingEvent event)
to produce specialized or dynamic statements. The default uses the sql option value.
原来log4j建议我们把其提供的JDBCAppender作为基类来使用,然后Override三个父类的方法:getConnection(),closeConnection(Connection con)和getLogStatement(LoggingEvent event)。
原来如此,那就写一个子类JDBCPoolAppender来替代这个JDBCAppender
JDBCPoolAppender代码和其相关代码如下:
JDBCPoolAppender.java:
package common.log;
import java.sql.Connection;
import org.apache.log4j.spi.LoggingEvent;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import org.apache.log4j.spi.ErrorCode;
import org.apache.log4j.PatternLayout;
import common.sql.MyDB;
import common.sql.GeneralDb;
public class JDBCPoolAppender extends org.apache.log4j.jdbc.JDBCAppender {
private MyDB mydb = null;
protected String sqlname=""; //增加一个数据库jndiName的属性
protected Connection connection = null;
protected String sqlStatement = "";
/**
* size of LoggingEvent buffer before writting to the database.
* Default is 1.
*/
protected int bufferSize = 1;
public JDBCPoolAppender() {
super();
}
/**
* ArrayList holding the buffer of Logging Events.
*/
public void append(LoggingEvent event) {
buffer.add(event);
if (buffer.size() >= bufferSize)
flushBuffer();
}
/**
* By default getLogStatement sends the event to the required Layout object.
* The layout will format the given pattern into a workable SQL string.
*
* Overriding this provides direct access to the LoggingEvent
* when constructing the logging statement.
*
*/
protected String getLogStatement(LoggingEvent event) {
return getLayout().format(event);
}
/**
*
* Override this to provide an alertnate method of getting
* connections (such as caching). One method to fix this is to open
* connections at the start of flushBuffer() and close them at the
* end. I use a connection pool outside of JDBCAppender which is
* accessed in an override of this method.
* */
protected void execute(String sql) throws SQLException {
Connection con = null;
Statement stmt = null;
try {
con = getConnection();
stmt = con.createStatement();
stmt.executeUpdate(sql);
} catch (SQLException e) {
if (stmt != null)
stmt.close();
throw e;
}
stmt.close();
closeConnection(con);
//System.out.println("Execute: " + sql);
}
/**
* Override this to return the connection to a pool, or to clean up the
* resource.
*
* The default behavior holds a single connection open until the appender
* is closed (typically when garbage collected).
*/
protected void closeConnection(Connection con) {
mydb=null;
try {
if (connection != null && !connection.isClosed())
connection.close();
} catch (SQLException e) {
errorHandler.error("Error closing connection", e,
ErrorCode.GENERIC_FAILURE);
}
}
/**
* Override 此函数来利用连接池返回一个Connetion对象
*
*/
protected Connection getConnection() throws SQLException {
try {
mydb = GeneralDb.getInstance(sqlname);
connection = mydb.getConnection();
} catch (Exception e) {
errorHandler.error("Error opening connection", e, ErrorCode.GENERIC_FAILURE);
}
return connection;
}
/**
* Closes the appender, flushing the buffer first then closing the default
* connection if it is open.
*/
public void close() {
flushBuffer();
try {
if (connection != null && !connection.isClosed())
connection.close();
} catch (SQLException e) {
errorHandler.error("Error closing connection", e,
ErrorCode.GENERIC_FAILURE);
}
this.closed = true;
}
/**
* loops through the buffer of LoggingEvents, gets a
* sql string from getLogStatement() and sends it to execute().
* Errors are sent to the errorHandler.
*
* If a statement fails the LoggingEvent stays in the buffer!
*/
public void flushBuffer() {
//Do the actual logging
removes.ensureCapacity(buffer.size());
for (Iterator i = buffer.iterator(); i.hasNext(); ) {
try {
LoggingEvent logEvent = (LoggingEvent) i.next();
String sql = getLogStatement(logEvent);
execute(sql);
removes.add(logEvent);
} catch (SQLException e) {
errorHandler.error("Failed to excute sql", e,
ErrorCode.FLUSH_FAILURE);
}
}
// remove from the buffer any events that were reported
buffer.removeAll(removes);
// clear the buffer of reported events
removes.clear();
}
/** closes the appender before disposal */
public void finalize() {
close();
}
/**
* JDBCAppender requires a layout.
* */
public boolean requiresLayout() {
return true;
}
/**
*
*/
public void setSql(String s) {
sqlStatement = s;
if (getLayout() == null) {
this.setLayout(new PatternLayout(s));
} else {
((PatternLayout) getLayout()).setConversionPattern(s);
}
}
/**
* Returns pre-formated statement eg: insert into LogTable (msg) values ("%m")
*/
public String getSql() {
return sqlStatement;
}
public void setSqlname(String sqlname){
sqlname=sqlname;
}
public String getSqlname(){
return sqlname;
}
public void setBufferSize(int newBufferSize) {
bufferSize = newBufferSize;
buffer.ensureCapacity(bufferSize);
removes.ensureCapacity(bufferSize);
}
public int getBufferSize() {
return bufferSize;
}
}
MyDB.java:
package common.sql;
import java.sql.*;
import com.codestudio.sql.*; //引入开源项目Poolman数据库连接池的包
public class MyDB {
public static final String module = MyDB.class.getName();
private String dbName = "";
private PoolMan plmn = null;
public MyDB(String dbName) {
try {
if (plmn == null) {
plmn = (PoolMan) Class.forName("com.codestudio.sql.PoolMan").
newInstance();
}
} catch (Exception ec) {
System.out.println(ec.toString()+module);
}
this.dbName = dbName;
}
private Connection getNewConnection() {
Connection conn = null;
try {
conn = plmn.connect("jdbc:poolman://" + dbName);
conn.setAutoCommit(true);
} catch (Exception ec) {
System.out.println(ec.toString()+"First:Connect sqlsever failed"+module);
try {
Thread.sleep(1000);
conn = plmn.connect("jdbc:poolman://" + dbName);
conn.setAutoCommit(true);
} catch (Exception ecs) {
System.out.println(ecs.toString()+"Again:Connect sqlsever faile"+module);
}
}
return conn;
}
public Connection getConnection() {
return getNewConnection();
}
}
GeneralDb.java:
package common.sql;
import java.util.*;
public class GeneralDb {
private static Hashtable dbPool;
public static MyDB getInstance(String dbname) {
if (dbPool == null) {
dbPool = new Hashtable();
}
MyDB db = (MyDB) dbPool.get(dbname);
if (db == null) {
db = new MyDB(dbname);
dbPool.put(dbname, db);
}
return db;
}
}
Log4j数据库连接池的配置如下:
log4j.appender.JDBC=common.log.JDBCPoolAppender
log4j.appender.JDBC.sqlname=log
log4j.appender.JDBC.layout=org.apache.log4j.PatternLayout
log4j.appender.JDBC.sql=INSERT INTO LOGGING (log_date, log_level, location, message) VALUES ('%d{ISO8601}', '%-5p', '%C,%L', '%m')
poolman.xml配置如下:
〈?xml version="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。:)

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Go 언어는 효율적이고 간결하며 배우기 쉬운 프로그래밍 언어입니다. 동시 프로그래밍과 네트워크 프로그래밍의 장점 때문에 개발자들이 선호합니다. 실제 개발에서 데이터베이스 작업은 필수적인 부분입니다. 이 기사에서는 Go 언어를 사용하여 데이터베이스 추가, 삭제, 수정 및 쿼리 작업을 구현하는 방법을 소개합니다. Go 언어에서는 일반적으로 사용되는 SQL 패키지, Gorm 등과 같은 타사 라이브러리를 사용하여 데이터베이스를 운영합니다. 여기서는 sql 패키지를 예로 들어 데이터베이스의 추가, 삭제, 수정 및 쿼리 작업을 구현하는 방법을 소개합니다. MySQL 데이터베이스를 사용하고 있다고 가정합니다.

C++에서 HTTP 스트리밍을 구현하는 방법은 무엇입니까? Boost.Asio 및 asiohttps 클라이언트 라이브러리를 사용하여 SSL 스트림 소켓을 생성합니다. 서버에 연결하고 HTTP 요청을 보냅니다. HTTP 응답 헤더를 수신하고 인쇄합니다. HTTP 응답 본문을 수신하여 인쇄합니다.

MySQLi를 사용하여 PHP에서 데이터베이스 연결을 설정하는 방법: MySQLi 확장 포함(require_once) 연결 함수 생성(functionconnect_to_db) 연결 함수 호출($conn=connect_to_db()) 쿼리 실행($result=$conn->query()) 닫기 연결( $conn->close())

Hibernate 다형성 매핑은 상속된 클래스를 데이터베이스에 매핑할 수 있으며 다음 매핑 유형을 제공합니다. Join-subclass: 상위 클래스의 모든 열을 포함하여 하위 클래스에 대한 별도의 테이블을 생성합니다. 클래스별 테이블: 하위 클래스별 열만 포함하는 하위 클래스에 대한 별도의 테이블을 만듭니다. Union-subclass: Joined-subclass와 유사하지만 상위 클래스 테이블이 모든 하위 클래스 열을 통합합니다.

Apple의 최신 iOS18, iPadOS18 및 macOS Sequoia 시스템 릴리스에는 사진 애플리케이션에 중요한 기능이 추가되었습니다. 이 기능은 사용자가 다양한 이유로 손실되거나 손상된 사진과 비디오를 쉽게 복구할 수 있도록 설계되었습니다. 새로운 기능에는 사진 앱의 도구 섹션에 '복구됨'이라는 앨범이 도입되었습니다. 이 앨범은 사용자가 기기에 사진 라이브러리에 포함되지 않은 사진이나 비디오를 가지고 있을 때 자동으로 나타납니다. "복구된" 앨범의 출현은 데이터베이스 손상으로 인해 손실된 사진과 비디오, 사진 라이브러리에 올바르게 저장되지 않은 카메라 응용 프로그램 또는 사진 라이브러리를 관리하는 타사 응용 프로그램에 대한 솔루션을 제공합니다. 사용자는 몇 가지 간단한 단계만 거치면 됩니다.

HTML은 데이터베이스를 직접 읽을 수 없지만 JavaScript 및 AJAX를 통해 읽을 수 있습니다. 단계에는 데이터베이스 연결 설정, 쿼리 보내기, 응답 처리 및 페이지 업데이트가 포함됩니다. 이 기사에서는 JavaScript, AJAX 및 PHP를 사용하여 MySQL 데이터베이스에서 데이터를 읽는 실제 예제를 제공하고 쿼리 결과를 HTML 페이지에 동적으로 표시하는 방법을 보여줍니다. 이 예제에서는 XMLHttpRequest를 사용하여 데이터베이스 연결을 설정하고 쿼리를 보내고 응답을 처리함으로써 페이지 요소에 데이터를 채우고 데이터베이스를 읽는 HTML 기능을 실현합니다.

GoWebSocket을 데이터베이스와 통합하는 방법: 데이터베이스 연결 설정: 데이터베이스/sql 패키지를 사용하여 데이터베이스에 연결합니다. WebSocket 메시지를 데이터베이스에 저장: INSERT 문을 사용하여 데이터베이스에 메시지를 삽입합니다. 데이터베이스에서 WebSocket 메시지 검색: SELECT 문을 사용하여 데이터베이스에서 메시지를 검색합니다.

PHP에서 데이터베이스 연결 오류를 처리하려면 다음 단계를 사용할 수 있습니다. mysqli_connect_errno()를 사용하여 오류 코드를 얻습니다. 오류 메시지를 얻으려면 mysqli_connect_error()를 사용하십시오. 이러한 오류 메시지를 캡처하고 기록하면 데이터베이스 연결 문제를 쉽게 식별하고 해결할 수 있어 애플리케이션이 원활하게 실행될 수 있습니다.
