面试题答案
一键面试自定义日志级别实现思路
- Log4j2:
- 定义自定义日志级别:通过实现
org.apache.logging.log4j.Level
接口,创建自定义的日志级别类。例如:
public class CustomLevel extends Level { public CustomLevel(int level, String name, int syslogEquivalent) { super(level, name, syslogEquivalent); } }
- 使用自定义日志级别:在配置文件(如
log4j2.xml
)中,可以通过additivity
等属性配置该级别日志的输出规则。例如:
<Logger name="com.example" level="CustomLevel" additivity="false"> <AppenderRef ref="ConsoleAppender"/> </Logger>
- 定义自定义日志级别:通过实现
- SLF4J 结合 Logback:
- 定义自定义日志级别:在
logback.xml
中,可以通过<root>
标签或<logger>
标签自定义日志级别。例如:
<logger name="com.example" level="TRACE"> <appender - ref ref="STDOUT"/> </logger>
- 由于 SLF4J 是日志门面,本身不实现日志功能,而 Logback 是常用实现。要在代码中使用自定义级别,在获取日志记录器时,如
Logger logger = LoggerFactory.getLogger(YourClass.class);
,然后使用logger.trace("Your message with custom level")
等方法记录日志。
- 定义自定义日志级别:在
复杂过滤规则代码实现架构
- 定义过滤条件接口:
- 创建一个接口,例如
LogFilter
,定义一个方法boolean filter(LogRecord record)
,其中LogRecord
类包含日志级别、业务标识、请求来源等多维度信息。
public interface LogFilter { boolean filter(LogRecord record); }
- 创建一个接口,例如
- 实现具体过滤规则:
- 对于基于日志级别的过滤:
public class LevelLogFilter implements LogFilter { private final Level level; public LevelLogFilter(Level level) { this.level = level; } @Override public boolean filter(LogRecord record) { return record.getLevel().isGreaterOrEqual(level); } }
- 对于基于业务标识的过滤:
public class BusinessIdLogFilter implements LogFilter { private final String businessId; public BusinessIdLogFilter(String businessId) { this.businessId = businessId; } @Override public boolean filter(LogRecord record) { return record.getBusinessId().equals(businessId); } }
- 对于基于请求来源的过滤:
public class RequestSourceLogFilter implements LogFilter { private final String requestSource; public RequestSourceLogFilter(String requestSource) { this.requestSource = requestSource; } @Override public boolean filter(LogRecord record) { return record.getRequestSource().equals(requestSource); } }
- 组合过滤规则:
- 创建一个
CompositeLogFilter
类实现LogFilter
接口,用于组合多个过滤规则。
import java.util.ArrayList; import java.util.List; public class CompositeLogFilter implements LogFilter { private final List<LogFilter> filters = new ArrayList<>(); public void addFilter(LogFilter filter) { filters.add(filter); } @Override public boolean filter(LogRecord record) { for (LogFilter filter : filters) { if (!filter.filter(record)) { return false; } } return true; } }
- 创建一个
- 在日志框架中应用过滤规则:
- Log4j2:可以通过自定义
Filter
类,在filter
方法中调用上述CompositeLogFilter
进行过滤。然后在log4j2.xml
中配置该自定义Filter
。 - Logback:类似地,通过自定义
Appender
或Filter
类,在doAppend
或decide
方法中调用CompositeLogFilter
进行过滤,并在logback.xml
中配置。例如,自定义一个Filter
:
然后在import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.filter.Filter; import ch.qos.logback.core.spi.FilterReply; public class CustomLogbackFilter extends Filter<ILoggingEvent> { private CompositeLogFilter compositeLogFilter; @Override public FilterReply decide(ILoggingEvent event) { LogRecord record = convertToLogRecord(event); if (compositeLogFilter.filter(record)) { return FilterReply.ACCEPT; } return FilterReply.DENY; } private LogRecord convertToLogRecord(ILoggingEvent event) { // 实现将ILoggingEvent转换为LogRecord的逻辑 } }
logback.xml
中配置该CustomLogbackFilter
。 - Log4j2:可以通过自定义