简体   繁体   English

无法在 logback.xml 中使用 Spring 属性占位符

[英]Unable to use Spring Property Placeholders in logback.xml

I have a Spring Boot console app using Logback.我有一个使用 Logback 的 Spring Boot 控制台应用程序。 All of the properties (for the app as well as for Logback) are externalized into a standard application.properties file in the classpath.所有属性(对于应用程序以及 Logback)都被外部化到类路径中的标准 application.properties 文件中。 These properties are picked up just fine in the app itself, but are not picked up in the logback.xml file.这些属性可以在应用程序本身中很好地获取,但不会在 logback.xml 文件中获取。 It appears as though the logback.xml is processed before Spring Boot fires up, therefore the EL placeholders are not processed.看起来好像在 Spring Boot 启动之前处理了 logback.xml,因此不处理 EL 占位符。

Using the FileNamePattern as an example, in the application.properties, I have something like this:以 FileNamePattern 为例,在 application.properties 中,我有这样的内容:

log.filePattern=/%d{yyyy/MM-MMMM/dd-EEEE}

and in logback.xml, I'll have this:在 logback.xml 中,我会有这个:

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <FileNamePattern>${log.logDirectory}${log.filePattern}.log
    </FileNamePattern>
</rollingPolicy>

When running the app, I'll see errors such as:运行应用程序时,我会看到如下错误:

ERROR in ch.qos.logback.core.joran.spi.Interpreter@24:25 - 
RuntimeException in Action for tag [rollingPolicy]
java.lang.IllegalStateException: FileNamePattern
[log.logDirectory_IS_UNDEFINEDlog.filePattern_IS_UNDEFINED.log]
does not contain a valid DateToken

Similar code works just fine in other Spring (not Spring Boot) apps, so I'm curious if Spring Boot just behaves a bit differently.类似的代码在其他 Spring(不是 Spring Boot)应用程序中工作得很好,所以我很好奇 Spring Boot 的行为是否有点不同。

Solution:解决方案:

Thanks for the reply @Gary!感谢@Gary 的回复! Good to know about the difference between Spring EL and Logback's variables...I had assumed it was Spring that was in charge of parsing those variables for me.很高兴知道 Spring EL 和 Logback 的变量之间的区别......我以为是 Spring 负责为我解析这些变量。 I did have the element, but that got me to thinking.确实有这个元素,但这让我开始思考。

My application.properties file was outside of the jar, so Logback had no idea where to find it.我的 application.properties 文件在 jar 之外,所以 Logback 不知道在哪里可以找到它。 By keeping my Spring-related properties in my external application.properties file, moving the logging-related properties into an application-internal.properties file (located inside the jar), and pointing Logback to that file ( <property resource="application-internal.properties" /> ) got everything working as expected!通过保持我的春节,相关性在我的外部application.properties文件,移动测井相关性为application-internal.properties文件(位于罐内),并指向的logback文件( <property resource="application-internal.properties" /> ) 一切正常!

Since Spring Boot 1.3 you have a better way of getting spring properties into your logback-spring.xml configuration:从 Spring Boot 1.3 开始,您可以更好地将 spring 属性放入 logback-spring.xml 配置中:

Now you can just add a "springProperty" element.现在您可以添加一个“springProperty”元素。

<springProperty name="destination" source="my.loggger.extradest"/>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${destination}</file>
        ...
    </file>
</appender>

https://github.com/spring-projects/spring-boot/commit/055ace37f006120b0006956b03c7f358d5f3729f https://github.com/spring-projects/spring-boot/commit/055ace37f006120b0006956b03c7f358d5f3729f

edit: thanks to Anders编辑:感谢安德斯

......... …………

${...} is not "Spring EL" in Spring; ${...}在 Spring 中不是“Spring EL”; they are property placeholders.它们是属性占位符。

I think you are confusing logback "variables" with Spring "Property Placeholders".我认为您将 logback“变量”与 Spring“属性占位符”混淆了。

They just happen to use the same syntax ${...} .他们只是碰巧使用相同的语法${...}

logback knows nothing about the Spring property placeholder mechanism and vice-versa. logback 对 Spring 属性占位符机制一无所知,反之亦然。 You need to configure your logback variables according to the logback documentation and not in application.properties / application.yml which is strictly a Spring (boot) concept.您需要根据 logback 文档配置您的 logback 变量,而不是在application.properties / application.yml ,这是严格的 Spring (boot) 概念。

EDIT:编辑:

After a quick look at the logback docs, adding快速查看 logback 文档后,添加

<property resource="application.properties" />

to the logback.xml should work.logback.xml应该可以工作。

如上所述,您可以使用<springProperty>元素访问 spring boot 属性……但要记住的是,logback 配置文件必须命名为logback-spring.xml ,如果您将其命名为文件logback.xml (我使用的是spring-boot 1.3.5.RELEASE

The solutions above work mostly for bootrap.properties .上述解决方案主要适用于bootrap.properties However, the only way to use properties from remote Spring Config Server in logback config I've currently found, is to apply them programatically:但是,在我目前找到的 logback 配置中使用来自远程 Spring Config Server 的属性的唯一方法是以编程方式应用它们:

@Component
public class LoggerConfiguration implements ApplicationListener<EnvironmentChangeEvent> {

    @Autowired protected Environment environment;

    @Override
    public void onApplicationEvent(EnvironmentChangeEvent event) {
        // enviroment here has already loaded all properties and you may alter logback config programatically
        ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
    }


}

Here is a good example how to customize logback with new appender this way.是一个很好的示例,如何以这种方式使用新的 appender 自定义 logback。

There is a way to map Spring properties to Logback properties and use them in the Conditions:有一种方法可以将 Spring 属性映射到 Logback 属性并在条件中使用它们:

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="ACTIVE_PROFILE" source="spring.profiles.active"/>
<!--   defined in the application-prod.properties/>-->
<springProperty scope="context" name="SPRING_WRITER_DISABLED" source="writer.disabled"/>
<property name="LOGBACK_WRITER_DISABLED" value="${SPRING_WRITER_DISABLED}"/>

<if condition='property("LOGBACK_WRITER_DISABLED").equals("false")'>
    <then>
        <appender name="testappender" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${ACTIVE_PROFILE}/${HOSTNAME}/testappender.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                <fileNamePattern>
                    {ACTIVE_PROFILE}/${HOSTNAME}/testappender-%d{yyyy-MM-dd}.%i.log
                </fileNamePattern>
                <maxFileSize>300MB</maxFileSize>
                <maxHistory>3</maxHistory>
                <totalSizeCap>1GB</totalSizeCap>
            </rollingPolicy>
            <encoder>
                <pattern>%msg%n</pattern>
            </encoder>
        </appender>
        <logger name="testappender" level="INFO" additivity="false">
            <appender-ref ref="testappender"/>
        </logger>
    </then>
</if>
</configuration>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM