给log4j配置数据库连接

利用log4j的JDBCAppender把日志写入数据库中 log4j提供了多种Appender,通过这些Appender可以把log4j产生的日志写到数据库中,把所用的日志集中起来管理,能够进行日志的分析和集中监控,提升系统的可维护性和系统的可用性,下面是我利用derby嵌入式数据库,写入数据库的配置:在log4j文件中,增加关于JDB 阅读详情
 我们都知道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 implement closeConnection 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;

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。:)


log4j 配置mysql 数据库 demo 立即下载

相关推荐

Xilinx DMA IP核心配置与实战解析

本文介绍了Xilinx DMA IP核在直接寄存器模式下的配置与工作流程。DMA通过AXI4-Lite接口接收指令,实现内存与数据流之间的高速传输,无需CPU介入。文章详细说明了开发环境配置、IP参数设置(包括地址位宽、数据宽度等关键参数)以及寄存器操作流程。通过仿真分析,展示了读操作中AXI4接口的突发传输机制,包括地址、长度和突发大小的配置。文中还提供了寄存器地址映射表、信号定义等关键信息,为DMA IP核的应用开发提供了实用参考。

weixin_37688766的博客 884

IDEA中运行出现ERROR Could not find value for key log4j.appender.fileAppender

开发遇到:Could not find value for key log4j.appender.fileAppender

Timeless__1的博客 2476

DeepSeek的训练与优化流程

DeepSeek的训练体系不仅追求极致的计算效率,更注重将物理规律、人类知识、安全伦理深度融入训练过程,其"效率-安全-可解释性"三角平衡的设计理念,为行业提供了重要参考范式。

m0_56896669的博客 1437

给Log4j配上数据库连接池

   我们都知道log4j是一个优秀的开源日志记录项目,我们不仅可以对输出的日志的格式自定义,还可以自己定义日志输出的目的地,比如:屏幕,文本文件,数据库,甚至能通过socket输出。        现在让我们对日志输出到数据库来进行配置         配置如下:#---JDBC ---输出到数据库# JDBCAppender log4j.properties file#log4j.rootCa

我的地盘,csdn说了算! 1295

基于树莓派与ROS的桌面机器人开发:从硬件组装到AI集成实战

嵌入式系统与机器人操作系统(ROS)是构建智能硬件的核心技术基础。嵌入式系统为设备提供了专用计算与控制能力,而ROS作为机器人开发的中间件框架,通过节点、话题和服务等机制,实现了感知、决策、执行等模块间的松耦合通信与高效集成。这种架构极大地提升了机器人系统的可扩展性与可维护性,其技术价值在于能够将复杂的AI算法,如计算机视觉和语音识别,与实体硬件执行机构无缝结合,从而快速构建出具备环境交互能力的智能体。在桌面机器人、教育套件及服务机器人原型开发等应用场景中,该技术栈尤为适用。本文以开源的Wall-E桌面机器

weixin_26775679的博客 651

保姆级教程:用ROS2 Humble和激光雷达,5分钟搞定机器人避障(附Python代码)

本文提供了一份详细的ROS2 Humble激光雷达避障实战指南,帮助开发者快速实现机器人避障功能。通过环境配置、硬件连接和Python代码实现,5分钟内即可让机器人自主避开障碍物。文章还涵盖了参数调优、常见问题排查及进阶优化技巧,适合机器人开发初学者和进阶用户。

weixin_42528902的博客 342

应用启动报错:Could not find value for key log4j.appender.WARN

问题表现:tomcat启动应用日志报错:log4j:ERROR Could not find value for key log4j.appender.WARN log4j:ERROR Could not instantiate appender named "WARN". 此报错在部分环境下会导致应用无法访问,报404,部分环境下,应用可正常访问 经测 tomcat8.5.9上 即使报错 但是项目访问正常 但是apache-tomcat-8.5.59访问要报404 经过验证发现,此log4j:E...

yeyuningzi的博客 8101

cadence capture CIS 之添加数据库

2021-08-20 cadence capture CIS 之添加数据库准备一、添加数据源 准备 1、数据库文件(*.mdb) 2、电脑上安装好 cadence 软件 一、添加数据源 打开“ ODBC数据源管理器” ( 路径:C:\Windows\SysWOW64\odbcad32.exe ) ...

weixin_42256550的博客 6055

log4j遇到的问题

log4j:ERROR Could not find value for key log4j.appender.logfilel log4j:ERROR Could not instantiate appender named “logfilel”. 1.上一个Appender没写满 不是 一些必须的Appender属性是必须要有的,比如不管哪种Appender,layout要有;又比如...

Jimmy的博客 2238

Unity 游戏实例开发集合 之 Car Racing 2D (2D赛车) 休闲小游戏快速实现

Unity 游戏实例开发集合 之 Car Racing 2D (2D赛车) 休闲小游戏快速实现 目录 Unity 游戏实例开发集合 之 Car Racing 2D (2D赛车) 休闲小游戏快速实现 一、简单介绍 二、Car Racing 2D (2D赛车) 游戏内容与操作 三、相关说明 四、游戏代码框架 五、知识点 六、游戏效果预览 七、实现步骤 八、工程源码地址 九、延伸扩展 一、简单介绍 Unity 游戏实例开发集合,使用简单易懂的方式,讲解常见游戏的开发实现过程,方便

仙魁XAN 7702

Unreal5 从入门到精通之 如何实现 离线语音识别

本文介绍了如何使用离线语音识别插件 Offline Speech Recognition 进行本地语音转文本处理。该插件支持离线运行,用户可以通过下载并运行语言服务器(如 Vosk)来处理语音数据。文章详细说明了如何设置语言服务器、下载语言模型,并在虚幻引擎(UE)项目中配置麦克风和语音捕获。此外,还介绍了如何将 SoundWave 作为输入,以及如何通过节点将语音数据发送到语言服务器进行处理。最后,提供了相关文档链接以供进一步参考。

TxNet 906

SpringBoot数据库连接池Druid的配置及log4j:WARN的解决

目录 前言 一、导入相关依赖 二、在配置文件中对Druid数据源进行配置 三、自定义Druid数据源配置 四、进行监控 五、遇到的问题 前言 常见的数据库连接池有c3p0,druid,hikari,DBCP等。Hikari是一款非常强大,高效,并且号称“史上最快连接池”。并且在springboot2.0之后,采用的默认数据库连接池就是Hikari。Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 数据库连接池的优点,同时加入了日志监控。 一、导入..

静水流深,沧笙踏歌 4513

交通仿真软件:SUMO_(1).SUMO基础知识

SUMO 中的交通网络由节点(junctions)和边(edges)组成。节点表示交叉口或路网的连接点,边表示连接节点之间的道路。节点:节点文件(.nod.xml)定义了网络中的所有节点。每个节点有一个唯一的 ID 和坐标。</边:边文件(.edg.xml)定义了连接节点的边。每个边有一个唯一的 ID、起点节点 ID 和终点节点 ID。</车辆文件(.vtype.xml)定义了不同类型的车辆。每个车辆类型可以有不同的参数,例如长度、最大速度、加速度等。</

kkchenjj的博客 1432

配置文件(Mybatis,db.properties,Mapper,log4j)

Mybatis 核心配置文件 <?xml version="1.0" encoding="UTF8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--configuration核心配置文件--> <configuration>

weixin_44836728的博客 283

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

配置数据源、数据库连接池、log4j、Junit单元测试

先贴个hibernate.cfg.xml<?xml version="1.0"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/

zytdoit的博客 885

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

配置log4j配置数据库连接池(以dbcp连接池为例),并将log信息存储在数据库中(以mysql为例)

上一篇中是以单一数据库配置为例,这一篇主要是讲如何将log4j中的数据库配置改成数据库连接池。 1.准备相关jar包 log4j-1.2.16.jar mysql-conector-java-5.1.22.jar commons-dbcp-1.4.jar commons-pool-1.5.4.jar 以上这些都是maven仓库自己对应的依赖,我都下好了,你们直接在下边的实例连接

frank0417的专栏 3158

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

用mybatis实现简单的CRUD的优化(三:连接数据库的配置文件,别名,打印日志信息)

1.新建db.propreties jdbc.url=jdbc:mysql://localhost:3306/lx_batis jdbc.driver=com.mysql.jdbc.Driver jdbc.username=root jdbc.password=123456 2.将数据库配置文件引入到conf.xml中 <properties resource="db.prop...

小蜗牛的博客 357

Hibernate 高级配置(数据库连接池和日志框架 Log4J)

数据库连接池配置 反问数据库,需要不断的创建和释放连接,假如访问量大的话,效率比较低级,服务器消耗大; 使用数据库连接池,我们可以根据实际项目的情况,定义连接池的连接个数,从而可以实现从连接池获取连 接,用户放回到连接池。从而有效的提高的系统的执行效率; Hibernate 自带的连接池不是很好,有 bug; 推荐使用 C3P0,proxool 等 第一步:引入c3p0的jar包 ...

qq_40135955的博客 965

Log4j 配置数据库连接池(将日志信息保存到数据库)

 org.apache.log4j.jdbc.JDBCAppender 是利用传统的 JDBC 连接方法,这种方式连接数据库效率低下,为了解决这个问题,现在自定义一个 Log4j 的 Appender, 将数据库连接改为连接池的形式,此 Appender 继承自 org.apache.log4j.jdbc.JDBCAppender, 并运用了开源项目Poolman(可从http://nchc.dl...

weixin_33705053的博客 100

log4j 配置数据库连接池添加自定义信息

log4j写数据库,通常只能写入log4j提供的信息,如果用来记录用户ID号,操作等的记录,则无法实现.    这里,我在log4j里加了一个字段userID (当然你可以再加几个)用来记录用户ID,操作 1.log4j配置文件 #向控制台和数据库输出 log4j.rootLogger=DEBUG,stdout,JDBC log4j.addivity.org.apache=true

LANGZI7758521的专栏 1615

项目重构之数据源配置与优化:log4j 配置数据库连接池Druid,并实现日志存储到数据库

作者:泥沙砖瓦浆木匠 网站:http://blog.youkuaiyun.com/jeffli1993 个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节。 交流QQ群:【编程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=FhFAoaWwjP29_AonqzL0rpdQAjjqlHQQ 如果我的帮到了你,是否乐意捐助一下或请一杯啤酒也

程序员泥瓦匠 3209

mybatis - mapper配置文件的头部--mybatis-config.xml--log4j 文件--db.properties

目录1)mapper配置文件的头部2) mybatis-config.xml3)log4j.xml4)db.properties 1)mapper配置文件的头部 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...

weixin_41705396的博客 740

项目重构之数据源配置与优化:log4j 配置数据库连接池Druid,并实现日志存储到数据库...

作者:泥沙砖瓦浆木匠网站:http://blog.youkuaiyun.com/jeffli1993个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节。 交流QQ群:【编程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=FhFAoaWwjP29_AonqzL0rpdQAjjqlHQQ 如果我的帮到了你,是否乐意捐助一下或请一杯啤酒也好呢?有你支持,...

weixin_30849591的博客 103
上一篇: Apache-common包之common-cli笔记
下一篇: 线程池与工作队列
socoolfj
博客等级 码龄21年 9粉丝 52原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值