为什么从 XML 配置 Logback 时,DriverManagerConnectionSource 未启动,导致连接失败?

问题描述 投票:0回答:1

升级到 slf4j 2.0.13、logback 1.5.6 和 logback-db 1.2.11.1 后,之前正常的 logback XML 配置失败了。据我所知,框架正在尝试在初始化 DriverManagerConnectionSource 之前初始化记录器。我怀疑我错过了新的配置要求。

我已将配置文件与位于 https://logback.qos.ch/manual/appenders.html 的 DBAppender 示例进行了比较

当我追踪源代码时,

DBAppenderBase.start()
包含这一行:

DBUtil.getDialectFromCode(connectionSource.getSQLDialectCode());

connectionSource(

DriverManagerConnectionSource
的实例)包含 null 作为
SQLDialectCode
。当我深入研究时,
DriverManagerConnectionSource
应该根据connectionSource.url标签中提供的URL在其
SQLDialectCode
方法中设置
start()
。我在调试器中使用了断点来确定
DriverManagerConnectionSource.start()
永远不会被调用。

我不可能是唯一使用过 DBAppender 的人,所以我想知道自从我们上次将 POM 引用更新为 logback 以来,配置要求发生了哪些变化。

pom.xml:

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.13</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.5.6</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.5.6</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-access</artifactId>
            <version>1.4.14</version>
        </dependency>
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>7.4</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback.db</groupId>
            <artifactId>logback-classic-db</artifactId>
            <version>1.2.11.1</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback.db</groupId>
            <artifactId>logback-core-db</artifactId>
            <version>1.2.11.1</version>
        </dependency>

Java代码:

package com.me.myApp;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@WebListener
public class MyContextListener implements ServletContextListener  {
    
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.setProperty("my.web.container", sce.getServletContext().getServerInfo());
    
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        logger.info("Shutting down.");
    }

}

XML配置:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">

    <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <resetJUL>true</resetJUL>
    </contextListener>
    
    <property file="/my/properties/my-datastore.properties"/>
    <!-- To enable JMX Management -->
    <jmxConfigurator />
  
    <!-- Notification Appender -->
    <appender name="me.notification.appender" class="ch.qos.logback.classic.db.DBAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
            <driverClass>org.postgresql.Driver</driverClass>
            <url>jdbc:postgresql://me.myapp.com:5432/mydb</url>
            <user>postgres</user>
            <password>postgres</password>
        </connectionSource>
        <encoder>
            <pattern>%-5level %logger{0} - %msg%n</pattern>
            <pattern>Id : %X{Id},Name : %X{Name},ModelName : %X{ModelName} %thread %date{ISO8601} %-5level %logger{5} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="me.notification" level="info">
        <appender-ref ref="me.notification.appender" />
        <appender-ref ref="logFile" />
    </logger>
</configuration>

基于此 XML 配置,Logback 代码没有执行我所期望的操作:

public abstract class DBAppenderBase<E> extends UnsynchronizedAppenderBase<E> {

    protected ConnectionSource connectionSource;
    protected boolean cnxSupportsGetGeneratedKeys = false;
    protected boolean cnxSupportsBatchUpdates = false;
    protected SQLDialect sqlDialect;

    protected abstract Method getGeneratedKeysMethod();

    protected abstract String getInsertSQL();

    @Override
    public void start() {

        if (connectionSource == null) {
            throw new IllegalStateException("DBAppender cannot function without a connection source");
        }

        sqlDialect = DBUtil.getDialectFromCode(connectionSource.getSQLDialectCode());
        if (getGeneratedKeysMethod() != null) {
            cnxSupportsGetGeneratedKeys = connectionSource.supportsGetGeneratedKeys();
        } else {
            cnxSupportsGetGeneratedKeys = false;
        }
        cnxSupportsBatchUpdates = connectionSource.supportsBatchUpdates();
        if (!cnxSupportsGetGeneratedKeys && (sqlDialect == null)) {
            throw new IllegalStateException(
                            "DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect");
        }
...
        // all nice and dandy on the eastern front
        super.start();
    }
java logback
1个回答
0
投票

有几个相互影响的问题,每个问题(单独)都会导致相同的症状 (

DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method and without a specific SQL dialect
),我可以在调试器的帮助下跟踪这些问题。

  1. 引用了错误的 logback.xml 文件。类路径中有一个虚假文件。
  2. 当错误的配置文件被删除时,类加载器找不到 jdbc 驱动程序。 Maven clean + maven rebuild + Eclipse build,然后是 Eclipse Reset Perspective
  3. 当使用正确的配置文件并且类加载器正在查找 jdbc 驱动程序时,jdbc 密码不正确,因此无法获得连接。
© www.soinside.com 2019 - 2024. All rights reserved.