JavaFX8WebEngine:如何在java中从javascript获取console.log()到System.o



我正在使用JavaFX和JavaFXWebEngine中的javascript引擎来开发应用程序。出于调试目的,我想从javascript获得反馈。WebEngine中的控制台输出会发生什么?有没有什么方法可以访问它,或者重定向到java中的System.out?

以下代码将console.log()重定向到JavaBridge.log():

import netscape.javascript.JSObject;
[...]
public class JavaBridge
{
    public void log(String text)
    {
        System.out.println(text);
    }
}
// Maintain a strong reference to prevent garbage collection:
// https://bugs.openjdk.java.net/browse/JDK-8154127
private final JavaBridge bridge = new JavaBridge();
[...]
webEngine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) ->
{
    JSObject window = (JSObject) webEngine.executeScript("window");
    window.setMember("java", bridge);
    webEngine.executeScript("console.log = function(message)n" +
        "{n" +
        "    java.log(message);n" +
        "};");
});

您只需添加消息侦听器即可查看输出中发生了什么。您不必为每个加载的页面注入重新定义console.log等函数的js桥

WebConsoleListener.setDefaultListener((webView, message, lineNumber, sourceId) -> {
    System.out.println(message + "[at " + lineNumber + "]");
});

我喜欢走另一个方向。我们使用log4j,所以我创建了一个javascript包装器,如下所示:

module.exports = {
    levels:[ "ALL", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF"],
    level:"INFO",
    error:function(msg){
      if(this.isErrorEnabled()){
        console.error(msg)
      }
    },
    warn:function(msg){
      if(this.isWarnEnabled()){
        console.warn(msg)
      }
    },
    info:function(msg){
      if(this.isInfoEnabled()){
        console.log("INFO: "+msg)
      }
    },
    debug:function(msg){
      if(this.isDebugEnabled()){
        console.log("DEBUG: "+msg)
      }
    },
    trace:function(msg){
      if(this.isTraceEnabled()){
        console.log("TRACE: "+msg)
      }
    },
    isErrorEnabled:function(){
      return this.isEnabled("ERROR");
    },
    isWarnEnabled:function(){
      return this.isEnabled("WARN");
    },
    isInfoEnabled:function(){
      return this.isEnabled("INFO");
    },
    isDebugEnabled:function(){
      return this.isEnabled("DEBUG");
    },
    isTraceEnabled:function(){
      return this.isEnabled("TRACE");
    },
    isEnabled:function(statementLevel){
      return this.levels.indexOf(this.level)<=this.levels.indexOf(statementLevel);
    }
  }

然后在javascript的开头,我检查日志是否存在,并将其设置为:

if(window.log == undefined){
  window.log = require("./utils/log4j-wrapper")
  window.log.level = "INFO"
}

这样,如果你在加载url之前直接在引擎上设置Log4j记录器,比如:

WebEngine webEngine = webView.getEngine()
JSObject win = (JSObject) webEngine.executeScript("window")
win.setMember("log", log)  //log being the java log4j logger

这样,如果我直接在浏览器中打开,或者在JavaFX程序中从WebView运行,我就可以登录。还有一个额外的好处,那就是登录javascript的级别与WebView控制器的包相匹配。只是较大javascript视图的替代方案。

最新更新