java - 如何将 Angular 2+ 应用程序仅作为 GUI 嵌入到 JavaFX WebView 中?

标签 java angular javafx webview angular-cli

我正在开发一个简单的 Java 客户端应用程序,我想为其 GUI 使用 HTML 和 Web 应用程序框架,而不是使用 Swing 或 JavaFX。

因此,我正在使用 Angular 6(使用 angular-cli 生成)设计、构建和测试整个应用程序,并且我想使用 JavaFX WebView 和 WebEngine 组件来指向我的 Angular UI。

是否有任何简单/开箱即用/最佳实践的方法来连接所有内容?

我希望用户只是启动应用程序,甚至没有意识到他正在浏览 webby 的内容。如果可能的话,我什至不会启动任何网络服务器。我只想要一个独立的应用程序,并仅将 Angular 框架用于 GUI 目的。

如果我必须启动一个网络服务器,我想在幕后进行,并且不希望用户意识到。

问题

  • 我试图让 WebEngine 指向构建的 Angular 应用程序,但是 this does not work Angular-cli 开箱即用;
  • 我尝试使用com.sun.net.httpserver,但网上的所有解释都只说如何实现你自己的虚拟HttpHandler,所以我无法理解如何绑定(bind)服务器到我实际构建的 Web 应用程序(位于我的项目路径中的文件夹中)或如何将我的 Web 应用程序部署到 HttpServer,以正确者为准。

最佳答案

你可以使用webkit嵌入任何HTML应用程序——webkit版本的jvm相对最新,我上次检查时,可能缺少一些功能,也许是WebGL。

要使其正常工作,请不要使用 file:// 协议(protocol),创建自己的网络服务器就太过分了。您只需定义自己的协议(protocol)并在 java 层中声明它即可。

示例如下:Registering and using a custom java.net.URL protocol

这是我的自定义协议(protocol)实现:

/**
 * Register a protocol handler for URLs like this: <code>myapp:///pics/sland.gif</code><br>
 */
public class MyURLConnection extends URLConnection
{

    protected MyURLConnection(URL url) {
        super(url);
    }

    private byte[] data;

    @Override
    public void connect() throws IOException
    {
        if (connected)
        {
            return;
        }
        loadImage();
        connected = true;
    }

    public String getHeaderField(String name)
    {
        if ("Content-Type".equalsIgnoreCase(name))
        {
            return getContentType();
        }
        else if ("Content-Length".equalsIgnoreCase(name))
        {
            return "" + getContentLength();
        }
        return null;
    }

    public String getContentType()
    {
        String fileName = getURL().getFile();
        String ext = fileName.substring(fileName.lastIndexOf('.')+1);
        switch(ext){
        case "html":return "text/html";
        case "jpg":
        case "png":return "image/"+ext;
        case "js": return "application/javascript";
        }
        return "text/"+ext;
         // TODO: switch based on file-type "image/" + ext
    }

    public int getContentLength()
    {
        return data.length;
    }

    public long getContentLengthLong()
    {
        return data.length;
    }

    public boolean getDoInput()
    {
        return true;
    }

    public InputStream getInputStream() throws IOException
    {
        connect();
        return new ByteArrayInputStream(data);
    }

    /**
     * Reads all bytes from an input stream and writes them to an output stream.
     */
    private static long copy(InputStream source, OutputStream sink)
        throws IOException
    {
        long nread = 0L;
        byte[] buf = new byte[8192];
        int n;
        while ((n = source.read(buf)) > 0) {
            sink.write(buf, 0, n);
            nread += n;
        }
        return nread;
    }

    private void loadImage() throws IOException
    {
        if (data != null)
        {
            return;
        }

            String fileName = getURL().getFile();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            copy(this.getClass().getResourceAsStream(fileName),byteArrayOutputStream);
           data = byteArrayOutputStream.toByteArray();

    }

    public OutputStream getOutputStream() throws IOException
    {
        // this might be unnecessary - the whole method can probably be omitted for our purposes
        return new ByteArrayOutputStream();
    }

    public java.security.Permission getPermission() throws IOException
    {
        return null; // we need no permissions to access this URL
    }

}

public class MyURLHandler extends URLStreamHandler
{

    @Override
    protected URLConnection openConnection(URL url) throws IOException
    {
        return new MyURLConnection(url);
    }

}

public class MyURLStreamHandlerFactory implements URLStreamHandlerFactory
{

    public URLStreamHandler createURLStreamHandler(String protocol)
    {
        if (protocol.equals("myapp"))
        {
            return new MyURLHandler();
        }
        return null;
    }

}

然后只需在 javafx 启动中注册协议(protocol)即可:

public void start(Stage stage) {
    URL.setURLStreamHandlerFactory(new MyURLStreamHandlerFactory());
    // etc. 

并在你的webkit中使用url myapp://anyhost/yourfile.html(不使用anyhost,使用你想要的任何内容或修改协议(protocol))

编辑: 我在 github 上的项目(正在进行中)中做到了这一点:您只需启动 WebDesktop 主类。它使用 src/main/resources 的资源 https://github.com/pdemanget/blue-browser

关于java - 如何将 Angular 2+ 应用程序仅作为 GUI 嵌入到 JavaFX WebView 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50965756/

相关文章:

java - 简单的 DAWG 创建算法?

java - 发送 0xFF 并计算带符号字节的 CRC - WriteSingleCoil & ModBUS & Java & Android -

typescript - 管道中的 Angular 2 依赖注入(inject)

java - 如何在 JavaFX 游戏中创建跟随玩家的 View ?

java - Android:防止Alert中的EditText为空

java apache HC BasicHttpEntityEnclosingRequest 与 BasicHttpRequest

javascript - Angular2 在按键或按键按下时获取整个输入值

typescript - 订阅可观察值

java - 如何使用队列元素填充组合框?

java - java for循环中的分支预测