log4j2 JDBC管理器无法连接到数据库。

6

我尝试配置log4j v2与mysql,但返回以下错误:

2014-08-01 15:35:24,819 ERROR Unable to write to database [jdbcManager{ description=databaseAppender, bufferSize=0, connectionSource=factory{ public static java.sql.Connection it.prisma.presentationlayer.webui.ConnectionFactory.getDatabaseConnection() }, tableName=logs, columns=[ { name=message, layout=%message, literal=null, timestamp=false } ] }] for appender [databaseAppender]. org.apache.logging.log4j.core.appender.AppenderLoggingException: Cannot write logging event or flush buffer; JDBC manager cannot connect to the database.

Caused by: java.sql.SQLException: Failed to obtain connection from factory method.

Caused by: java.sql.SQLException: No suitable driver found for jdbc:mysql://10.41.1.68:3306/test

我的配置类似于 文档,唯一的区别在于:

new PoolableConnectionFactory(connectionFactory, pool, null, "SELECT 1", false, false, Connection.TRANSACTION_READ_COMMITTED);

我认为我的tomcat7配置良好,因为我可以使用log4j v1进行日志记录。


你的 MySql JDBC 驱动程序是否在 classpath 中可用? - HamoriZ
2个回答

8
好的,解决方案如下:
1- 创建一个连接工厂类。
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnection;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;


public class ConnectionFactory {

    private static interface Singleton {
        final ConnectionFactory INSTANCE = new ConnectionFactory();
    }

    private final DataSource dataSource;

    private ConnectionFactory() {

        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            System.exit(0);
        }

        Properties properties = new Properties();
        properties.setProperty("user", "root");
        properties.setProperty("password", "root");

        GenericObjectPool<PoolableConnection> pool = new GenericObjectPool<PoolableConnection>();
        DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
                "jdbc:mysql://example.org:3306/exampleDb", properties
        );
        new PoolableConnectionFactory(connectionFactory, pool, null, "SELECT 1", 3, false, false, Connection.TRANSACTION_READ_COMMITTED);
        this.dataSource = new PoolingDataSource(pool);
    }

    public static Connection getDatabaseConnection() throws SQLException {
        return Singleton.INSTANCE.dataSource.getConnection();
    }
}

2- 在src/main/resources中创建一个名为log4j2.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="TRACE" monitorInterval="30">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
        <JDBC name="databaseAppender" tableName="logs">
            <ConnectionFactory class="my.pack.ConnectionFactory"
                method="getDatabaseConnection" />
            <!-- <Column name="id" literal="LOGGING.APPLICATION_LOG_SEQUENCE.NEXTVAL" /> -->
            <Column name="date" isEventTimestamp="true" />
            <Column name="level" pattern="%level" />
            <Column name="message" pattern="%message" />
            <Column name="class" pattern="%class" /> 
        </JDBC>
    </Appenders>
    <Loggers>
        <Root level="trace">
            <AppenderRef ref="Console" />
            <AppenderRef ref="databaseAppender" />
        </Root>
    </Loggers>
</Configuration>

3- 创建如下表格: enter image description here

4- 将MySQL连接器添加到{tomcat}/bin目录下

Maven提示:

    <commons-dbcp.version>1.4</commons-dbcp.version>

    <commons-pool.version>1.6</commons-pool.version>

    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>${commons-dbcp.version}</version>
    </dependency>

    <dependency>
        <groupId>commons-pool</groupId>
        <artifactId>commons-pool</artifactId>
        <version>${commons-pool.version}</version>
    </dependency>

GenericObjectPool不需要任何参数???为什么它在我的项目中不起作用? - Kjenos
现在看起来好像可以了,但我也无法让这个工作。从你的另一个问题中找到了这个链接,帮助解决了问题。https://git-wip-us.apache.org/repos/asf?p=commons-dbcp.git;a=blob_plain;f=doc/PoolingDataSourceExample.java;hb=HEAD - Arka Mallick
1
@Kjenos 你需要添加一个依赖项来获取该功能。请参见答案中的“Maven提示”。 - granadaCoder
工作得非常好。唯一的问题是如何为日志表的主键生成NEXTVAL。这不是很清楚。我正在使用Oracle数据库。非常感谢您的答案,它非常有帮助 :=) - Beezer
当我尝试在我的OSGi应用程序中应用这些配置时,我遇到了java.lang.ClassNotFoundException: br.com.prodist.database.ConnectionFactory cannot be found by org.apache.logging.log4j.api_2.11.0的错误,有什么解决方法吗? - skrenato

0

给未来的读者。我在使用Hikari时遇到了这个错误。 我的代码(很糟糕,不起作用)...如下所示。

所以我改成了Mateo在这个问题中发布的答案,并且我又回到了正常状态。

我留下这个答案,以防其他人遇到同样的问题。

PS 我的日志依赖项是“干净的”。请参见https://www.logicbig.com/tutorials/spring-framework/spring-boot/log4j2.html

[INFO] +- org.springframework.boot:spring-boot-starter-log4j2:jar:2.1.3.RELEASE:compile
[INFO] |  +- org.apache.logging.log4j:log4j-slf4j-impl:jar:2.11.2:compile
[INFO] |  |  \- org.apache.logging.log4j:log4j-api:jar:2.11.2:compile
[INFO] |  +- org.apache.logging.log4j:log4j-core:jar:2.11.2:compile
[INFO] |  +- org.apache.logging.log4j:log4j-jul:jar:2.11.2:compile
[INFO] |  \- org.slf4j:jul-to-slf4j:jar:1.7.25:compile

..

    <HikariCP.version>3.1.0</HikariCP.version>

..

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.sql.DataSource;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

public class LogDataSource {

    private static LogDataSource logDataSource = new LogDataSource();

    public static final String ENVIRONMENT = "environment";
    private Properties prop;
    public String environment;
    private HikariDataSource hikariDataSource;

    private LogDataSource() {
        try {
            environment = System.getProperty(ENVIRONMENT);
            String url = getProperty("LogDatabaseConnectionString");
            HikariConfig hikariConfig = new HikariConfig();
            hikariConfig.setPoolName("eisltier2LogPool");
            hikariConfig.setConnectionTestQuery("SELECT 1");
            hikariConfig.setDataSourceClassName(getProperty("dataSourceClassName"));

            String dsClassName = hikariConfig.getDataSourceClassName();
            try {
                Class.forName(dsClassName);
            } catch (ClassNotFoundException e) {
                throw new NullPointerException(String.format("DataSourceClassName did not load. (DataSourceClassName='%s')", dsClassName));
            }

            hikariConfig.setMaximumPoolSize(Integer.valueOf(getProperty("hikari.maximumPoolSize")));
            hikariConfig.setIdleTimeout(Integer.valueOf(getProperty("hikari.idleTimeout")));
            Properties dsProperties = new Properties();
            dsProperties.put("url", url);
            hikariConfig.setDataSourceProperties(dsProperties);
            HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
            this.hikariDataSource = hikariDataSource;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static DataSource getConnection() {
        DataSource returnItem = logDataSource.hikariDataSource;
        return returnItem;
    }

    public String getProperty(String key) throws IOException {

        if (prop == null) {
            prop = new Properties();
            try(InputStream inputConnectionStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("connection.properties");){
            prop.load(inputConnectionStream);
            }catch (Exception e) {
                throw new IOException(e);
            }
        }
        String value = ((environment == null || environment == "") ? prop.getProperty(key)
                : prop.getProperty(environment + "." + key));
        return value;
    }
}

我认为你的getConnection()方法有误,它应该从logDataSource.hikariDataSource.getConnection()返回一个Connection。 - Joram

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接