Java 应用程序和网页中的 Javascript 之间的通信
当使用 WebView 显示你自己的自定义网页并且此网页包含 Javascript 时,可能需要在 Java 程序和网页中的 Javascript 之间建立双向通信。
此示例显示如何设置此类通信。
网页应显示输入字段和按钮。单击该按钮时,输入字段中的值将发送到 Java 应用程序,Java 应用程序将对其进行处理。在处理之后,结果被发送到 Javascript,Javascript 又在网页上显示结果。
基本原则是,对于从 Javascript 到 Java 的通信,在 Java 中创建一个对象,该对象被设置到网页中。而对于另一个方向,在 Javascript 中创建一个对象并从网页中提取。
以下代码显示了 Java 部分,我将它保存在一个文件中:
package com.sothawo.test;
import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
import java.io.File;
import java.net.URL;
/**
 * @author P.J. Meisch (pj.meisch@sothawo.com).
 */
public class WebViewApplication extends Application {
    /** for communication to the Javascript engine. */
    private JSObject javascriptConnector;
    /** for communication from the Javascript engine. */
    private JavaConnector javaConnector = new JavaConnector();;
    @Override
    public void start(Stage primaryStage) throws Exception {
        URL url = new File("./js-sample.html").toURI().toURL();
        WebView webView = new WebView();
        final WebEngine webEngine = webView.getEngine();
        // set up the listener
        webEngine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
            if (Worker.State.SUCCEEDED == newValue) {
                // set an interface object named 'javaConnector' in the web engine's page
                JSObject window = (JSObject) webEngine.executeScript("window");
                window.setMember("javaConnector", javaConnector);
                // get the Javascript connector object. 
                javascriptConnector = (JSObject) webEngine.executeScript("getJsConnector()");
            }
        });
        Scene scene = new Scene(webView, 300, 150);
        primaryStage.setScene(scene);
        primaryStage.show();
        // now load the page
        webEngine.load(url.toString());
    }
    public class JavaConnector {
        /**
         * called when the JS side wants a String to be converted.
         *
         * @param value
         *         the String to convert
         */
        public void toLowerCase(String value) {
            if (null != value) {
                javascriptConnector.call("showResult", value.toLowerCase());
            }
        }
    }
}
加载页面后,通过以下调用将 JavaConnector 对象(由内部类定义并创建为字段)设置到网页中:
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("javaConnector", javaConnector);
用网页检索 javascriptConnector 对象
javascriptConnector = (JSObject) webEngine.executeScript("getJsConnector()");
当调用 JavaConnector 的 toLowerCase(String) 方法时,转换传入的值,然后通过 javascriptConnector 对象发回。
这是 html 和 javascript 代码:
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Sample</title>
    </head>
    <body>
        <main>
    
            <div><input id="input" type="text"></div>
            <button onclick="sendToJava();">to lower case</button>
            <div id="result"></div>
    
        </main>
    
        <script type="text/javascript">
            function sendToJava () {
                var s = document.getElementById('input').value;
                javaConnector.toLowerCase(s);
            };
    
            var jsConnector = {
                showResult: function (result) {
                    document.getElementById('result').innerHTML = result;
                }
            };
    
            function getJsConnector() {
                return jsConnector;
            };
        </script>
    </body>
</html>
sendToJava 函数调用由 Java 代码设置的 JavaConnector 的方法:
function sendToJava () {
    var s = document.getElementById('input').value;
    javaConnector.toLowerCase(s);
};
并且 Java 代码调用以检索 javascriptConnector 的函数只返回 jsConnector 对象:
var jsConnector = {
    showResult: function (result) {
        document.getElementById('result').innerHTML = result;
    }
};
    
function getJsConnector() {
    return jsConnector;
};
Java 和 Javascript 之间的调用的参数类型不仅限于字符串。有关可能的类型和转换的更多信息,请参阅 JSObject API 文档 。