我正在尝试运行一个集成 JavaFX 和 Spring Boot 的示例应用程序,并与 Intellij 和 Gradle 配合使用。为了实现集成,我正在使用 Wiki 中的 Spring Boot Sample 来测试 Gluon Ignite。
我将应用程序作为 Spring Boot 应用程序运行(Gradle 中的
bootRun
任务),但收到错误
JavaFX runtime components are missing, and are required to run this application
这清楚地表明 JavaFX 组件不在模块路径中。如果我将应用程序作为 JVM 应用程序运行(任务
Run
),则不会发生此错误,但显然 Spring Boot 部分不起作用(使用 Spring Boot WebSocket 组件在更复杂的版本上进行了测试)。
让 Spring Boot 应用程序在将 JavaFX 运行时组件正确添加到模块路径的情况下运行的正确方法是什么?
在正常运行中,
org.javamodularity.moduleplugin
会处理所有事情,但在引导运行中,它显然不起作用。
相关要素如下。
build.gradle
plugins {
id 'application'
id 'org.springframework.boot' version '3.0.2'
id 'io.spring.dependency-management' version '1.1.0'
id 'org.javamodularity.moduleplugin' version '1.8.12'
id 'org.openjfx.javafxplugin' version '0.0.10'
}
javafx {
modules = ['javafx.controls','javafx.fxml']
}
repositories {
mavenCentral()
}
dependencies {
implementation 'com.gluonhq:ignite-spring:1.1.0'
implementation 'javax.inject:javax.inject:1'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'org.webjars:webjars-locator-core'
implementation 'org.webjars:stomp-websocket:2.3.3'
implementation 'org.webjars:bootstrap:3.3.7'
implementation 'org.webjars:jquery:3.1.1-1'
}
application {
mainModule = "com.my.ignite"
mainClass = "com.my.ignite.SpringBootApp"
}
module-info
module com.my.ignite {
requires javafx.controls;
requires javafx.fxml;
requires javafx.graphics;
requires javafx.base;
requires spring.messaging;
requires spring.web;
requires spring.context;
requires spring.boot.autoconfigure;
requires spring.boot;
requires spring.websocket;
requires spring.beans;
requires javax.inject;
requires ignite.spring;
exports com.my.ignite;
opens com.my.ignite;
}
申请代码:
package com.my.ignite;
import com.gluonhq.ignite.spring.SpringContext;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import java.io.IOException;
import java.util.Arrays;
@SpringBootApplication
@ComponentScan("com.gluonhq.ignite.spring")
public class SpringBootApp extends Application implements ExampleApp {
public static void main(String[] args) {
Application.launch(SpringBootApp.class, args);
}
@Autowired
private FXMLLoader fxmlLoader;
// Originally in the sample code:
// private final SpringContext context = new SpringContext(this);
// Modified (see "Basic Spring Sample" code):
private final SpringContext context = new SpringContext(this,
() -> Arrays.asList(SpringBootApp.class.getPackage().getName()));
@Override
public void start(Stage primaryStage) throws IOException {
// Originally in the sample code:
// context.init(() -> SpringApplication.run(SpringBootApp.class));
// Modified:
context.init();
fxmlLoader.setLocation(getViewLocation());
Parent view = fxmlLoader.load();
primaryStage.setTitle("Spring Boot Example");
primaryStage.setScene(new Scene(view));
primaryStage.show();
}
}
作者自己解决了这个问题,这样做的是:
使用独立的 Spring boot Websocket 解决了最初的问题 客户端作为消息代理工作。 JavaFX 应用程序启动代理 并通过 TCP 套接字与其进行通信。经纪人发送 消息发送到 websocket 服务器并将响应发送到 JavaFX 应用程序。也许不是优雅和性能的最佳解决方案, 但易于实现,依赖性最小,使用 Spring boot 和 保持 JavaFX 应用程序的模块化和独立性。 – CT95 评论二月 2023 年 25 月 21 日 21:08