我可以将控制台输出镜像到网站吗?

Can i mirror the console output to a website?

提问人:CreativeDifference 提问时间:12/31/2021 更新时间:12/31/2021 访问量:935

问:

有什么方法可以在 java 中将控制台输出镜像到 localhost,甚至可以添加一些不错的 CSS。如果同一网络中的其他设备也可以访问控制台,那就太酷了。我已经对这个主题做了很多研究,但没有找到任何关于这个的网站/线程/问题。 帮助将不胜感激!

Java localhost 镜像 控制台输出

评论


答:

1赞 JJS 12/31/2021 #1

为了拦截通常进入控制台的输出(或标准输出),您需要在代码中的某个位置使用以下 API:

System.setOut(myStream); 
System.setErr(myStream); //If you want to grab the error stream also. Could go do a different location

许多日志库已经可以为您执行此操作。但这基本上是您需要捕获输出的方式。“myStream”的实际作用取决于您。将其传输到 http://localhost:8888 上的 Web 服务器的最快方法是将输出定向到文件并启动 JDK 的嵌入式 Web 服务器。下面是一个您应该能够运行的示例:

package test.example;

import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpServer;

import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class SystemOutToWeb
{
    public static void main(String... args ) throws Exception
    {
        final Path myOutputFile = Paths.get("./MyOutputFile.txt");
        final PrintStream myStream = new PrintStream(myOutputFile.toFile());

        System.out.println("Going to redirect to : " + myOutputFile.toAbsolutePath());

        System.setOut(myStream);
        System.setErr(myStream);

        System.out.println("Starting the Output");

        //Have something that logs every 5 seconds
        final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleAtFixedRate(() ->
        {
            System.out.println("Hello - the time is now " + Instant.now());
        }, 1, 5, TimeUnit.SECONDS);

        // Start the simple Java Built in Web Server.
        final HttpServer http = HttpServer.create(new InetSocketAddress(8888), 0);
        final HttpContext context = http.createContext("/");
        context.setHandler(exchange ->
        {
            byte[] data = Files.readAllBytes(myOutputFile);
            exchange.sendResponseHeaders(200, data.length);
            OutputStream os = exchange.getResponseBody();
            os.write(data);
            os.close();
        });
        http.start();

    }
}

如果你给它几秒钟的时间来运行,那么你应该能够在 http://localhost:8888 看到一些东西。

当然,这只是起点。例如,您可以同时使用不同的 Web 服务器,或者进一步使用一些 CSS 来增强此资源(甚至可以使用 Web 套接字在文件更新时流式传输文件)。

评论

0赞 CreativeDifference 12/31/2021
是否可以在不按浏览器刷新的情况下“刷新”网站内容?
0赞 JJS 12/31/2021
一般来说,有两种方法可以做到这一点。最简单(低技术)的解决方案是将资源作为 HTML 提供,并在标头中带有“<head> <meta http-equiv=”refresh“ content=”30“></head>”。这将指示浏览器每 30 秒刷新一次(因此无需用户干预即可刷新)。第二种方法更复杂一些 - 你基本上必须设置一个 Websocket (en.wikipedia.org/wiki/WebSocket),它将“推送”更新到客户端。涉及更多 - 也许超出了这个问题的范围。
0赞 CreativeDifference 12/31/2021
但是我该如何编辑页面的源html呢?
1赞 JJS 1/2/2022
您可以将流定向到内存缓冲区,如果这是您想要的。但是,通常的警告是关于内存不足,现在您有责任在它适用后进行清理。为此,请改为使用以下命令实例化 PrintStream:final ByteArrayOutputStream bous = new ByteArrayOutputStream(); final PrintStream myStream = new PrintStream(bous);
1赞 JJS 1/2/2022
随后,如果你想用 HTML 包装你的字符串,你可以做:context.setHandler(exchange -> { StringBuilder html = new StringBuilder("<html>"); html.append(new String(bous.toByteArray())); html.append("</html>"); exchange.sendResponseHeaders(200, html.length()); OutputStream os = exchange.getResponseBody(); os.write(html.toString().getBytes()); os.close(); });
0赞 Adam Malik 12/31/2021 #2

你想要像集中式日志这样的东西吗?有一些工具可以做到这一点,比如 Grafana Loki,你可以使用一个名为 promtail 的日志收集器从文件中收集日志并将它们发送到你的 Loki 实例,而使用 Grafana 前端,你就有了可搜索的彩色日志。这可以包括来自多个应用程序的日志。

https://grafana.com/docs/loki/latest/clients/promtail/

您可以将其发送到 Grafana Cloud,它为最多三个用户提供免费层,或者使用 docker 托管 Grafana 堆栈,这里有一个现成的堆栈:

https://github.com/stefanprodan/dockprom

评论

0赞 CreativeDifference 12/31/2021
不,不是真的,无论如何谢谢