从 springboot 后端内的 javafx bean 加载本地主机内容

问题描述

我正在尝试使用 web 和 thymleaf一个简单的 springboot 应用程序中托管 javafx 应用程序。

它向本地主机提供静态 html,我可以使用 webengine.load("localhost:port") 从浏览器和通过独立 javafx 的 webview 获取这些内容

当我尝试在 Spring Boot 中实例化 javafx 应用程序/bean 时会出现问题。我成功实例化了客户端,使 fxml 和控制器运行良好,但 webengine.load 方法返回一个空窗口。我尝试加载从单独运行的应用程序提供的内容,并且可以正常工作,因此问题在于尝试使用由同一 springboot 应用程序实例化的 javafx 客户端加载 springboot 应用程序提供的内容

JAVAfx 应用程序像这样被实例化为一个 bean,

@Component
public class Cool extends Application {


    public void start(Stage stage) throws IOException {

        Parent parent = FXMLLoader.load(getClass().getResource("/rendum/webView.fxml"));
        Scene scene = new Scene(parent,300,300);
        stage.setScene(scene);
        stage.show();

    }

    @Bean
    public void go() {
        launch();
    }
}

尝试像这样加载网页内容

public class Controller {
    @FXML
    WebView webView;


    public void initialize() {
        System.out.println("Controller up");
        WebEngine webEngine = webView.getEngine();

        webEngine.load("http://localhost:8080/");
        JSObject window = (JSObject) webEngine.executeScript("window");

        window.setMember("java",new JSApi());

        webEngine.setonAlert((e)-> {
            System.out.println(e.getData());
        });
    }
}

所以只是为了确认,我已经尝试将 url 更改为其他正在运行的应用程序并且它可以工作,并且我可以在不同的 javafx 应用程序中使用相同的控制器设置并显示内容

我正在使用 jdk 8. 有谁知道为什么内容无法加载? 入口点

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class,args);
    }

}

控制器实例化。它在“/”(入口点)处提供带有 som js 的 html

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class ViewController {

    @GetMapping("/")
    public String index() {
        return "index";
    }
}

项目结构。

因此它实例化了向本地主机提供 html 和 js 的控制器。这个对javafxbean中的webengine是不可用的,但是对于这个springboot应用之外的应用是可用的

Treeview

解决方法

事实证明有一种方法可以实现这一目标。您实际上想从 Springboot 入口点启动 JavaFx 应用程序,而不是像普通的 spring-boot 应用程序一样运行它。在您的 Javafx 应用程序中,您将需要一个 ConfigurableApplicationContext,它将用于启动一个事件,该事件将告诉您的应用程序您的初级阶段已准备就绪。可以通过初始化 spring-boot ApplicationListener 的 bean 来监听此事件,您将从其 onApplicationEvent 方法创建您的场景。

您可以像往常一样使用 spring 初始化程序并添加依赖项。 一个普通的 spring-boot 应用程序像这样启动

public class SpringApplication{

    public static void main(String[] args) {
        SpringApplication.run(SpringApplication.class,args);

    }

}

相反,使用 java fx 中的 Application 类来启动应用程序

    public class SpringApplication{

    public static void main(String[] args) {
            Application.launch(JavaFXApplication.class,args);

    }

}    

通过使用 SpringApplicationBuilder 在 init 方法中创建可配置应用程序上下文来配置 JavaFXApplication。在 start 方法中从中启动 ApplicationEvent 的实例并将其传递给舞台。 ApplicationEvent 是抽象的,因此您需要从中扩展自定义类。

JavaFXApplication 看起来像这样

public class JavaFxApplication extends Application {
    ConfigurableApplicationContext applicationContext;

    @Override
    public void start(Stage stage) throws Exception {
        applicationContext.publishEvent(new StageReadyEvent(stage));
    }

    public void init() {
        applicationContext = new SpringApplicationBuilder(SpringApplication.class).run();
    }

    public void stop() {

        applicationContext.close();
    }


    public static class StageReadyEvent extends ApplicationEvent {
        public StageReadyEvent(Stage stage) {
            super(stage);
        }
    }
}

最后,通过实现 ApplicationListener 实例化一个监听该事件的 Bean

@Component
public class StageReadyListener implements ApplicationListener<JavaFxApplication.StageReadyEvent> {

    @Override
    public void onApplicationEvent(JavaFxApplication.StageReadyEvent stageReadyEvent) {
        Stage stage = (Stage)stageReadyEvent.getSource();
        stage.setScene(new Scene(new Label("Hello"),300,300));
        stage.show();
    }
}

通过这种方式,现在也可以在 javafx 应用程序中使用 spring 依赖注入。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...