使用Apache Tailer包监控文件时如何获取文件名?
解决Apache Commons IO Tailer无法获取对应日志文件名的问题
这个问题我之前也碰到过,默认的TailerListenerAdapter确实没提供直接获取事件对应文件名的方法,不过我们可以通过自定义监听器的方式,把文件名和监听器实例绑定起来,这样就能在事件处理时拿到对应的文件名了。
解决方案步骤:
- 自定义TailerListener子类:继承
TailerListenerAdapter,添加文件名属性,通过构造方法传入文件名,让每个监听器实例对应一个日志文件。 - 重写事件处理方法:在
handle()、handleException()等方法中,直接使用我们保存的文件名即可。 - 为每个日志文件创建对应监听器:启动Tailer时,给每个文件分配一个绑定了自身文件名的自定义监听器实例。
代码示例:
首先是自定义的监听器类:
import org.apache.commons.io.input.TailerListenerAdapter; public class CustomLogTailerListener extends TailerListenerAdapter { // 保存当前监听器对应的日志文件名 private final String logFileName; // 通过构造方法传入文件名 public CustomLogTailerListener(String logFileName) { this.logFileName = logFileName; } @Override public void handle(String line) { // 现在可以直接拿到当前行对应的日志文件名了 System.out.printf("文件[%s]新增内容:%s%n", logFileName, line); } @Override public void handleException(Exception ex) { // 异常处理时也能知道是哪个文件出了问题 System.err.printf("文件[%s]发生异常:%s%n", logFileName, ex.getMessage()); } }
然后是使用这个监听器的主类:
import org.apache.commons.io.input.Tailer; import java.io.File; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ApacheLogFileTailer { public static void main(String[] args) { String filelog1 = "C:\\Users\\eventfile1.log"; String filelog2 = "C:\\Users\\eventfile2.log"; // 为每个日志文件创建绑定了文件名的自定义监听器 CustomLogTailerListener listener1 = new CustomLogTailerListener(filelog1); CustomLogTailerListener listener2 = new CustomLogTailerListener(filelog2); // 创建Tailer实例 Tailer tailer1 = new Tailer(new File(filelog1), listener1, 1000); // 1秒轮询一次 Tailer tailer2 = new Tailer(new File(filelog2), listener2, 1000); // 使用线程池启动Tailer(因为Tailer是阻塞的,需要单独线程运行) ExecutorService executor = Executors.newFixedThreadPool(2); executor.submit(tailer1); executor.submit(tailer2); // 可以添加关闭钩子,优雅停止Tailer Runtime.getRuntime().addShutdownHook(new Thread(() -> { tailer1.stop(); tailer2.stop(); executor.shutdown(); })); } }
说明:
每个CustomLogTailerListener实例都和一个日志文件一一对应,通过构造方法注入文件名,这样在处理日志行或者异常时,就能准确知道是哪个文件的事件。另外,因为Tailer的run()方法是阻塞的,所以需要用线程池或者单独线程来运行每个Tailer实例,避免阻塞主线程。
内容的提问来源于stack exchange,提问作者ankitj
相关产品推荐
相关产品推荐

