logback日志输出到xxl-job中

一、介绍

是这样的,最近我在调研xxl-job的使用,想把它整合到自己的项目工程中。

整合得很顺利,没什么问题,但在使用上出现了一个小小的繁琐,就是日志的输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Slf4j
@Component
public class SampleTask {

@XxlJob("demoJobHandler")
public void demoJobHandler() throws Exception {
XxlJobHelper.log("XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) {
XxlJobHelper.log("beat at:{}", i);
log.info("beat at:{}", i);
TimeUnit.SECONDS.sleep(2);
}
}
}

看到是什么问题了吗,没错就是日志的输出,我写了两次。

至于为什么写两次,纯属无奈之举,一个是logback日志的打印,一个xxl-job自己的日志

有没有什么办法,能只写一次就行的呢?

二、代码

logback中,我们可以自己编写filter来对日志等信息进行过滤。

所以,我们只需要在filter中写上,一些逻辑判断,就可以实现日志往xxl-job中打印了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.banmoon.filter;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
import com.xxl.job.core.context.XxlJobContext;
import com.xxl.job.core.context.XxlJobHelper;

import java.util.Objects;

public class XxlJobLogFilter extends Filter<ILoggingEvent> {

@Override
public FilterReply decide(ILoggingEvent event) {
// 判断是否处于xxl-job上下文中
if (Objects.nonNull(XxlJobContext.getXxlJobContext())) {
XxlJobHelper.log(event.getFormattedMessage());
}
return FilterReply.NEUTRAL;
}
}

然后,再将这个过滤器指定放在我们的CONSOLE输出中(片段代码)

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<included>
<!-- 输出到控制台 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!-- 日志输出编码格式化 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>${LOG_FORMAT_ONE}</Pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="com.banmoon.filter.XxlJobLogFilter"/>
</appender>
</included>

这样的话就可以实现,只需要一个log.info()就能在xxl-job的日志打印了

三、其他

其实到上面一步,已经能实现了。

但由于我项目工程的设计,我的logback配置文件,根本就不是同一个工程,我不能直接将filter写入CONSOLE

这是我项目的结构,banmoon-common-core包完全不知道项目有没有引用banmoon-xxl-job-client,也就不知道里面有没有filter了。

image-20240416212849383

对于上面这种情况,我想了想,能不能从其他方面进行入手呢?

比如说AOP,但我看到logback中的Loggerfinal类,顿时就无语了。

没办法,只能想想其他办法了

后面我看到了一个新的解决思路,就是获取到CONSOLEConsoleAppender,直接往里面塞一个XxlJobLogFilter不就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.banmoon.config;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import com.banmoon.filter.XxlJobLogFilter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

import static org.slf4j.Logger.ROOT_LOGGER_NAME;

@Slf4j
@Configuration
public class XxlJobConfig {

@PostConstruct
public void init() {
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = context.getLogger(ROOT_LOGGER_NAME);
Appender<ILoggingEvent> console = logger.getAppender("CONSOLE");
XxlJobLogFilter filter = new XxlJobLogFilter();
console.addFilter(filter);
}

}

当项目启动的时候,就会去找ConsoleAppender,这样后面打印的日志就会经过这个过滤器。

四、最后

我是半月,你我一同共勉!!!