有没有办法用 SpringBoot 启动 FXGL?

Is there a way to launch FXGL with SpringBoot?

我需要通过 springboot 启动带有 fxgl 动画的应用程序以利用它的功能。

我真的不知道该怎么做。

我尝试将初始化放入 GameApplication 继承者的不同 init() 方法中。

我这样试过:

    @Override
    protected void onPreInit() {
        context = SpringApplication.run(getClass(), savedArgs);
        context.getAutowireCapableBeanFactory().autowireBean(this);
        super.onPreInit();
    }

或尝试模仿网页版:

public class App extends Application {
    private ConfigurableApplicationContext applicationContext;

    @Override
    public void init() {
        String[] args = getParameters().getRaw().toArray(new String[0]);
        this.applicationContext = new SpringApplicationBuilder()
                .sources(DiplomaBaseApplication.class)
                .run(args);
    }

    @Override
    public void stop() {
        this.applicationContext.close();
        Platform.exit();
    }

    @Override
    public void start(Stage stage) {
        GameApplication gameApplication = new SimulationApplication();
        GameApplication.embeddedLaunch(gameApplication);
    }
}
@SpringBootApplication
public class DiplomaBaseApplication {

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

}

使用 javafx-weaver-spring-boot-starter.

应用程序已启动,但 spring 初始化已提前结束 spring 功能和 bean 不起作用:

22:08:38.879 [JavaFX Application Thread] INFO  Engine               - FXGL-11.17 (16.07.2021 15.46) on WINDOWS (J:11.0.10 FX:16)
22:08:38.879 [JavaFX Application Thread] INFO  Engine               - Source code and latest versions at: https://github.com/AlmasB/FXGL
22:08:38.880 [JavaFX Application Thread] INFO  Engine               -              Join the FXGL chat at: https://gitter.im/AlmasB/FXGL
22:08:39.418 [FXGL Background Thread 1 ] INFO  FXGLApplication      - FXGL initialization took: 0,325 sec

  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.7)

2022-05-13 22:08:39.900  INFO 31948 --- [lication Thread] o.s.boot.SpringApplication               : Starting application using Java 11.0.10 on DESKTOP-2DKK20I with PID 31948 (started by pro56 in C:\Users\pro56\Desktop\Course)
2022-05-13 22:08:39.903  INFO 31948 --- [lication Thread] o.s.boot.SpringApplication               : No active profile set, falling back to 1 default profile: "default"
2022-05-13 22:08:39.985  INFO 31948 --- [lication Thread] o.s.boot.SpringApplication               : Started application in 0.425 seconds (JVM running for 1.813)
22:08:40.056 [FXGL Background Thread 1 ] INFO  FXGLApplication      - Game initialization took: 0,024 sec
22:08:40.852 [FXGL Background Thread 2 ] INFO  UpdaterService       - Your current version:  11.17
22:08:40.852 [FXGL Background Thread 2 ] INFO  UpdaterService       - Latest stable version: 17.1

我不确定为什么这对您不起作用。我试过了,对我来说效果很好。

生成此警告:

Unsupported JavaFX configuration: classes were loaded from 'unnamed module @307f6b8c'

我想这就是 fxgl 的工作原理,默认情况下,它 运行s JavaFX 在不受支持的配置中脱离了 class 路径。我从 FXGL 文档中看到它可以用作模块,所以我猜想在该配置中它将 运行 一个使用 JavaFX 模块而不是离开 class 路径的受支持配置。但是,SpringBoot 当前未编码为使用模块路径(我相信 SpringBoot 3 会发生这种情况)。因此,就目前而言,最好 运行 不受支持的配置中的所有内容,如本示例所示。

虽然示例中我在DemoSpringApplication中放置了一个main方法进行测试,但实际的mainclass到运行并不是那个,而是Basic Spring扩展 FXGL GameApplication 的 GameApp。

BasicSpringGameApp 将调用 SpringApplication 静态方法到 运行 Spring 应用程序(这将创建 Spring 的实例申请)。

Spring 应用程序独立于 FXGL GameApplication(它在内部独立于 JavaFX 应用程序),因此所有这些东西都有不同的实例(每个只有一个),应用关注点分离。

src/main/java/com/example/glboot/BasicSpringGameApp.java

扩展 FXGL GameApplication。 FXGL GameApplication 将(在内部)启动 JavaFX 应用程序。此示例还将 运行 一个 spring 应用程序,以便 spring 服务可用。 spring 上下文自动连接到 GameApplication class 中,因此 spring 服务可在 GameApplication class 中使用。 Spring 注入服务的使用通过调用 UserService 来演示,这是一个 Spring 服务。

package com.example.glboot;

import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.dsl.FXGL;
import javafx.scene.control.Label;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

public class BasicSpringGameApp extends GameApplication {

    private ConfigurableApplicationContext springContext;

    @Autowired
    UserService userService;

    @Override
    protected void initSettings(GameSettings settings) {
        settings.setWidth(200);
        settings.setHeight(150);
        settings.setTitle("Game App");

        springContext =
                new SpringApplicationBuilder(DemoSpringApplication.class)
                        .web(WebApplicationType.NONE)
                        .run();

        springContext
                .getAutowireCapableBeanFactory()
                .autowireBeanProperties(
                        this,
                        AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE,
                        true
                );
    }

    @Override
    protected void initGame() {
        String welcomeText =
                "hello, " + userService.getUsername() + "\n" + userService.getWelcomeMessage();

        FXGL.entityBuilder()
                .at(50, 50)
                .view(new Label(welcomeText))
                .buildAndAttach();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

src/main/resources/DemoSpringApplication.java

Spring引导应用程序,通过Spring引导框架配置和启动spring服务。

package com.example.glboot;

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

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

src/main/java/com/example/glboot/UserService.java

一个示例用户信息 spring 服务,其中包含一些来自 spring 上下文和应用程序配置属性的注入值。

package com.example.glboot;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Value("${user.name}")
    private String username;

    @Value("${welcome.message}")
    private String welcomeMessage;

    public String getUsername() {
        return username;
    }

    public String getWelcomeMessage() {
        return welcomeMessage;
    }
}

src/main/resoruces/application.properties

Spring 配置属性。

welcome.message=Welcome to FXGL Boot

pom.xml

Maven 项目文件。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>glboot</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>glboot</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>18.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>18.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-media</artifactId>
            <version>18.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.github.almasb</groupId>
            <artifactId>fxgl</artifactId>
            <version>17</version>
            <exclusions>
                <exclusion>
                    <groupId>org.openjfx</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.9.0</version>
                <configuration>
                    <source>18</source>
                    <target>18</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

控制台输出

/Users/js732745/Library/Java/JavaVirtualMachines/openjdk-18.0.1.1/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=59335:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/js732745/dev/glboot/target/classes:/Users/js732745/.m2/repository/org/openjfx/javafx-controls/18.0.1/javafx-controls-18.0.1.jar:/Users/js732745/.m2/repository/org/openjfx/javafx-controls/18.0.1/javafx-controls-18.0.1-mac.jar:/Users/js732745/.m2/repository/org/openjfx/javafx-graphics/18.0.1/javafx-graphics-18.0.1.jar:/Users/js732745/.m2/repository/org/openjfx/javafx-graphics/18.0.1/javafx-graphics-18.0.1-mac.jar:/Users/js732745/.m2/repository/org/openjfx/javafx-base/18.0.1/javafx-base-18.0.1.jar:/Users/js732745/.m2/repository/org/openjfx/javafx-base/18.0.1/javafx-base-18.0.1-mac.jar:/Users/js732745/.m2/repository/org/openjfx/javafx-fxml/18.0.1/javafx-fxml-18.0.1.jar:/Users/js732745/.m2/repository/org/openjfx/javafx-fxml/18.0.1/javafx-fxml-18.0.1-mac.jar:/Users/js732745/.m2/repository/org/openjfx/javafx-media/18.0.1/javafx-media-18.0.1.jar:/Users/js732745/.m2/repository/org/openjfx/javafx-media/18.0.1/javafx-media-18.0.1-mac.jar:/Users/js732745/.m2/repository/com/github/almasb/fxgl/17/fxgl-17.jar:/Users/js732745/.m2/repository/com/github/almasb/fxgl-core/17/fxgl-core-17.jar:/Users/js732745/.m2/repository/com/gluonhq/attach/audio/4.0.9/audio-4.0.9.jar:/Users/js732745/.m2/repository/com/github/almasb/fxgl-io/17/fxgl-io-17.jar:/Users/js732745/.m2/repository/com/gluonhq/attach/storage/4.0.9/storage-4.0.9.jar:/Users/js732745/.m2/repository/com/gluonhq/attach/util/4.0.9/util-4.0.9.jar:/Users/js732745/.m2/repository/com/github/almasb/fxgl-entity/17/fxgl-entity-17.jar:/Users/js732745/.m2/repository/com/github/almasb/fxgl-scene/17/fxgl-scene-17.jar:/Users/js732745/.m2/repository/com/github/almasb/fxgl-gameplay/17/fxgl-gameplay-17.jar:/Users/js732745/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.13.2/jackson-annotations-2.13.2.jar:/Users/js732745/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.13.2.1/jackson-databind-2.13.2.1.jar:/Users/js732745/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.13.2/jackson-core-2.13.2.jar:/Users/js732745/.m2/repository/com/gluonhq/attach/lifecycle/4.0.9/lifecycle-4.0.9.jar:/Users/js732745/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib/1.5.32/kotlin-stdlib-1.5.32-modular.jar:/Users/js732745/.m2/repository/org/jetbrains/annotations/13.0/annotations-13.0.jar:/Users/js732745/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.21/kotlin-stdlib-common-1.6.21.jar:/Users/js732745/.m2/repository/org/springframework/boot/spring-boot-starter/2.6.7/spring-boot-starter-2.6.7.jar:/Users/js732745/.m2/repository/org/springframework/boot/spring-boot/2.6.7/spring-boot-2.6.7.jar:/Users/js732745/.m2/repository/org/springframework/spring-context/5.3.19/spring-context-5.3.19.jar:/Users/js732745/.m2/repository/org/springframework/spring-aop/5.3.19/spring-aop-5.3.19.jar:/Users/js732745/.m2/repository/org/springframework/spring-beans/5.3.19/spring-beans-5.3.19.jar:/Users/js732745/.m2/repository/org/springframework/spring-expression/5.3.19/spring-expression-5.3.19.jar:/Users/js732745/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.6.7/spring-boot-autoconfigure-2.6.7.jar:/Users/js732745/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.6.7/spring-boot-starter-logging-2.6.7.jar:/Users/js732745/.m2/repository/ch/qos/logback/logback-classic/1.2.11/logback-classic-1.2.11.jar:/Users/js732745/.m2/repository/ch/qos/logback/logback-core/1.2.11/logback-core-1.2.11.jar:/Users/js732745/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.17.2/log4j-to-slf4j-2.17.2.jar:/Users/js732745/.m2/repository/org/apache/logging/log4j/log4j-api/2.17.2/log4j-api-2.17.2.jar:/Users/js732745/.m2/repository/org/slf4j/jul-to-slf4j/1.7.36/jul-to-slf4j-1.7.36.jar:/Users/js732745/.m2/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/Users/js732745/.m2/repository/org/springframework/spring-core/5.3.19/spring-core-5.3.19.jar:/Users/js732745/.m2/repository/org/springframework/spring-jcl/5.3.19/spring-jcl-5.3.19.jar:/Users/js732745/.m2/repository/org/yaml/snakeyaml/1.29/snakeyaml-1.29.jar:/Users/js732745/.m2/repository/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar com.example.glboot.BasicSpringGameApp

  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.7)

2022-05-13 15:54:30.381  INFO 32226 --- [           main] com.example.glboot.BasicSpringGameApp    : Starting BasicSpringGameApp using Java 18.0.1.1 on C02ZX2NFMD6T with PID 32226 (/Users/js732745/dev/glboot/target/classes started by js732745 in /Users/js732745/dev/glboot)
2022-05-13 15:54:30.384  INFO 32226 --- [           main] com.example.glboot.BasicSpringGameApp    : No active profile set, falling back to 1 default profile: "default"
2022-05-13 15:54:30.772  INFO 32226 --- [           main] com.example.glboot.BasicSpringGameApp    : Started BasicSpringGameApp in 0.675 seconds (JVM running for 0.988)
2022-05-13 15:54:30.835  WARN 32226 --- [JavaFX-Launcher] javafx                                   : Unsupported JavaFX configuration: classes were loaded from 'unnamed module @307f6b8c'
15:54:31.118 [JavaFX Application Thread] INFO  Engine               - FXGL-17 (31.12.2021 18.16) on MAC (J:18.0.1.1 FX:18.0.1)
15:54:31.119 [JavaFX Application Thread] INFO  Engine               - Source code and latest versions at: https://github.com/AlmasB/FXGL
15:54:31.119 [JavaFX Application Thread] INFO  Engine               -       Ask questions and discuss at: https://github.com/AlmasB/FXGL/discussions
15:54:31.119 [JavaFX Application Thread] INFO  Engine               -              Join the FXGL chat at: https://gitter.im/AlmasB/FXGL
15:54:31.534 [FXGL Background Thread 1 ] WARN  FXGL.DefaultMenu     - FXGLDefaultMenu is not designed for resolutions < 800x600
15:54:31.686 [FXGL Background Thread 1 ] INFO  FXGLApplication      - FXGL initialization took: 0.399 sec
15:54:31.757 [FXGL Background Thread 4 ] INFO  FXGLApplication      - Game initialization took: 0.005 sec
15:54:32.035 [FXGL Background Thread 2 ] INFO  UpdaterService       - Your current version:  17
15:54:32.036 [FXGL Background Thread 2 ] INFO  UpdaterService       - Latest stable version: 17.1