将 SLF4J 日志重定向到 JavaFX 中的 TextArea

2024-04-09

我想显示 SLF4J 记录的错误TextArea在JavaFX中。到目前为止我所拥有的是appender in logback-test.xml:

<appender name="err" class="logtest.AppTA">
    <filter class="logtest.ErrFilter" />
    <encoder>
        <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
</appender>

TextArea准备接收流:

public class Output extends OutputStream{
    private final TextArea ta;
    public Output(TextArea ta) {
        this.ta = ta;
    }
    @Override
    public void write(int b) throws IOException {
        if (ta!=null) {
            ta.appendText(String.valueOf((char) b));
        }
    }
}

和一个处理附加的类:

public class AppTA extends AppenderBase<ILoggingEvent> {

    PatternLayoutEncoder encoder;
    OutputStream os;

    @Override
    protected void append(ILoggingEvent event) {
        try {
            if (isEncoderInitialized) {
                this.encoder.doEncode(event);
            }
        } catch (IOException e) {
        }
    }

    @Override
    public void start() {
        if (this.encoder == null) {
            addError("No encoder set for the appender named [" + name + "].");
            return;
        }
        try {
            encoder.init(os);
        } catch (IOException ex) {
            Logger.getLogger(AppTA.class.getName()).log(Level.SEVERE, null, ex);
        }
        super.start();
    }

    public PatternLayoutEncoder getEncoder() {
        return encoder;
    }

    public void setEncoder(PatternLayoutEncoder encoder) {
        this.encoder = encoder;
    }
}

现在我遇到的问题是我的TextArea在控制器类中,我不知道如何将它们链接在一起。特别是当 SLF4J 创建时AppTA实例本身 - 我真的没有办法通过我的TextArea to AppTA由记录器使用。

我该如何解决这个问题?


这个答案取决于你的底层日志框架是 logback。 由于 SLF4J 一次只支持一种日志记录实现,我认为不可能以一种与实现无关的方式来解决。

解决此问题的最简单方法是创建自己的附加程序并利用静态,以便您可以跨应用程序访问流。
下面我演示了一个附加程序的基本示例,它可以随时静态设置其输出流。
这有一些限制,主要是它一次只能处理一个输出流,但扩展以支持多个输出流应该不会太困难。

在下面的应用程序中,当您单击日志按钮时,它将记录信息和错误消息,所有输出都将转到标准输出,但只有错误消息将显示在文本区域中。

基本 JavaFx 应用程序类

public class Main extends Application {

    private static final Logger LOG = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        Button btn = new Button();
        btn.setText("Log stuff");
        btn.setOnAction(a-> {
            LOG.info("This is some info");
            LOG.error("This is some error");
        });

        TextArea textArea = new TextArea();
        OutputStream os = new TextAreaOutputStream(textArea);

        MyStaticOutputStreamAppender.setStaticOutputStream(os);

        GridPane grid = new GridPane();
        grid.add(textArea, 0 ,0);
        grid.add(btn, 0, 1);
        primaryStage.setScene(new Scene(grid, 500, 250));
        primaryStage.show();
    }

    private static class TextAreaOutputStream extends OutputStream {

        private TextArea textArea;

        public TextAreaOutputStream(TextArea textArea) {
            this.textArea = textArea;
        }

        @Override
        public void write(int b) throws IOException {
            textArea.appendText(String.valueOf((char) b));
        }
    }
}

简单的自定义appender类

public class MyStaticOutputStreamAppender<E> extends OutputStreamAppender<E> {


    private static final DelegatingOutputStream DELEGATING_OUTPUT_STREAM = new DelegatingOutputStream(null);

    @Override
    public void start() {
        setOutputStream(DELEGATING_OUTPUT_STREAM);
        super.start();
    }

    public static void setStaticOutputStream(OutputStream outputStream) {
        DELEGATING_OUTPUT_STREAM.setOutputStream(outputStream);
    }

    private static class DelegatingOutputStream extends FilterOutputStream {

        /**
         * Creates a delegating outputstream with a NO-OP delegate
         */
        public DelegatingOutputStream(OutputStream out){
            super(new OutputStream() {
                @Override
                public void write(int b) throws IOException {}
            });
        }

        void setOutputStream(OutputStream outputStream) {
            this.out = outputStream;
        }
    }

}

登录配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="MyCustomAppender" class="example.MyStaticOutputStreamAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
        </encoder>
    </appender>

    <root>
        <appender-ref ref="STDOUT" />
        <appender-ref ref="MyCustomAppender" />
    </root>

</configuration>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 SLF4J 日志重定向到 JavaFX 中的 TextArea 的相关文章

  • Java Sqlite Gradle

    我对 gradle 和 java 还很陌生 我有一个使用 sqlite 的项目 它通过 intellij idea 运行良好 但我无法从终端运行它 它会抛出异常 java lang ClassNotFoundException org sq
  • Java - 从配置文件加密/解密用户名和密码

    我们正忙于为客户开发 Java Web 服务 有两种可能的选择 将加密的用户名 密码存储在Web服务客户端上 从配置中读取 文件在客户端 解密并发送 将加密的用户名 密码存储在 Web 服务器上 从配置中读取 Web 服务器上的文件 解密并
  • 如何限制 Chrome 中的最大文本区域宽度和高度或如何禁用文本区域调整大小

    Chrome 允许通过在右下角添加文本区域来调整文本区域的大小 但有时这种移动可能会破坏页面的设计 所以我想知道如何限制该操作的最大和最小宽度 即如何完全禁用该功能和thml javascript css在页面上 您可以使用 resize
  • 在哈希图中存储字符和二进制数

    我正在尝试存储字母到二进制数的映射 这是我的映射 h 001 i 010 k 011 l 100 r 101 s 110 t 111 为此 我创建了一个哈希映射并存储了键值对 我现在想显示给定句子的相应二进制值 这是我的代码 package
  • 在 Android 中绘制一条带有弯曲边缘的线

    I am using canvas drawLine to draw some line in android but the lines are too sharp but i need a curved edges 这里的 1 是我所拥
  • 使用 JAXB 编组 LocalDate

    我正在构建一系列链接类 我希望能够将其实例编组到 XML 以便我可以将它们保存到文件中并稍后再次读取它们 目前我使用以下代码作为测试用例 import javax xml bind annotation import javax xml b
  • 为什么一个线程会中断另一个线程[重复]

    这个问题在这里已经有答案了 在Java多线程应用程序中 我们处理InterruptedThreadException 如果另一个线程中断当前线程 则会抛出此异常 现在 当另一个线程知道它将导致异常时 它可能想要中断当前线程的原因是什么 很多
  • 通过 JNI 从 Applet 调用 DLL

    我有一个 概念验证 的作品 它跨越了一些不熟悉的领域 我的任务是将 EFTPOS 机器连接到在内联网浏览器中作为小程序运行的应用程序 我暂时忽略了 EFTPOS dll 并用我选择的语言 Delphi 创建了一个简单的 JNI 修饰的 DL
  • 用于防止滥用的 Servlet 过滤器? (DoS、垃圾邮件等)

    我正在寻找一个 Servlet 过滤器库 它可以帮助我保护我们的 Web 服务免受未经授权的使用和 DDoS 攻击 我们的网络服务有 授权客户 因此理想情况下 过滤器将帮助检测未经授权或行为不当的客户 或检测使用同一帐户的多个人 此外 我们
  • Scala(或 Java)中泛型函数的特化

    是否可以在 Scala 中专门化泛型函数 或类 例如 我想编写一个将数据写入 ByteBuffer 的通用函数 def writeData T buffer ByteBuffer data T buffer put data 但由于 put
  • MessageDigest MD5 算法未返回我期望的结果

    我脑后的某个东西告诉我 我在这里遗漏了一些明显的东西 我正在将现有的 java 项目与第三方 api 集成 该第三方 api 使用 api 密钥的 md5 哈希进行身份验证 它对我不起作用 在调试过程中我意识到我生成的哈希值与他们提供的示例
  • Kerberos 缓存票证

    我使用的是 Windows 7 64 位 我创建了一个简单的应用程序来对实现 PrivilegedAction 的类的 run 方法中的文件进行计数 以下是我的 jaas conf 文件 CountFiles com sun securit
  • 更改 RowLayout SWT Java 中元素的顺序

    有没有办法更改在行布局中创建的元素的顺序 我想将其显示在元素中 首先显示 例如 如果我创建 element1 则 element2 element3 element4 我想看到的布局为 元素4 元素3 元素2 元素1 这意味着最后创建的元素
  • 在多模块项目中访问绑定适配器

    我有一个多模块项目 其中应用程序模块包含我的绑定适配器 而我的功能模块取决于我的应用程序模块 因为它是动态功能模块 应用程序 包含绑定适配器 gt 动态功能模块 存在布局的地方 我在所有模块中启用了数据绑定和 kapt 我无法成功构建应用程
  • NoSuchMethodError:将 Firebase 与应用程序引擎应用程序集成时

    我试图将 firebase 实时数据库与谷歌应用程序引擎应用程序集成 我在调用时收到此错误 gt DatabaseReference ref FirebaseDatabase gt getInstance gt getReference t
  • 膨胀类片段 InflateException 二进制 XML 文件时出错

    我正在使用 Material Design 和 NavigationDrawer 布局等设计我的第一个应用程序 但我遇到了一个问题 该应用程序非常简单 它只显示文本 并且基于 Android Studio 中提供的模板 尝试启动我的应用程序
  • 如何使用 SAX Java 解析器读取注释文本

    我只想使用 Java 中的 SAX 解析器读取 XML 文件中对象标记的注释 这是我的文件的摘要
  • 如何使用maven创建基于spring的可执行jar?

    我有一个基于 Maven 的 Spring WS 客户端项目 我想将其打包为单个 jar 在eclipse中 一切运行正常 当我尝试将其打包为可执行 jar 时 我收到 ClassNotFound 异常 因为 Spring jar 未包含在
  • java数据结构模拟数据树

    我需要帮助定义使用什么方法 我有一个 SOAP 响应 给我一个 xml 文件 我需要在屏幕上显示 3 个相关列表 当您在第一个列表中选择一个项目时 相应的选择将出现在第二个列表中 依此类推 我只对从 xml 流中提取数据后如何有效地组织数据
  • 编译时在代码中替换Java静态最终值?

    在java中 假设我有以下内容 fileA java class A public static final int SIZE 100 然后在另一个文件中我使用这个值 fileB java import A class b Object t

随机推荐