Spring 使用 javaFx 启动
Spring boot with javaFx
我正在使用 spring 引导和 javaFx 开发 java 桌面应用程序。
这是一个 crud 应用程序,所以我正在使用 mysql 数据库
我希望控制器既是 spring 引导控制器又是 javaFx 控制器,为此我使用了 setControllerFactory()
.
这是我的申请
申请:
package com.gi.quizui;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
javafx.application.Application.launch(QuizApplication.class, args);
}
}
测验申请:
package com.gi.quizui;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ConfigurableApplicationContext;
public class QuizApplication extends Application {
private ConfigurableApplicationContext applicationContext;
@Override
public void init() {
applicationContext = new SpringApplicationBuilder(com.gi.quizui.Application.class).run();
}
@Override
public void start(Stage stage) {
applicationContext.publishEvent(new StageReadyEvent(stage));
}
@Override
public void stop() {
applicationContext.close();
Platform.exit();
}
class StageReadyEvent extends ApplicationEvent {
public StageReadyEvent(Stage stage) {
super(stage);
}
public ConfigurableApplicationContext getAppContext() {
return applicationContext;
}
public Stage getStage() {
return ((Stage) getSource());
}
}
}
和阶段初始化程序:
package com.gi.quizui;
import com.gi.quizui.QuizApplication.StageReadyEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class StageInitializer implements ApplicationListener<StageReadyEvent> {
@Value("classpath:fxml/quiz.fxml")
private Resource quizResource;
public StageInitializer(@Value("${spring.application.ui.title}") String applicationTitle) {
this.applicationTitle = applicationTitle;
}
private String applicationTitle;
@Override
public void onApplicationEvent(StageReadyEvent event) {
Stage stage = event.getStage();
ConfigurableApplicationContext springContext = event.getAppContext();
try {
FXMLLoader fxmlLoader = new FXMLLoader(quizResource.getURL());
fxmlLoader.setControllerFactory(springContext::getBean);
Parent parent = fxmlLoader.load();
stage.setScene(new Scene(parent, 800, 600));
stage.setTitle(applicationTitle);
stage.show();
} catch (IOException e) {
throw new RuntimeException();
}
}
}
我不断收到此错误:(编辑)
Exception in Application start method
2021-01-16 15:37:15.286 INFO 8652 --- [lication Thread] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2021-01-16 15:37:15.320 INFO 8652 --- [lication Thread] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2021-01-16 15:37:15.343 INFO 8652 --- [lication Thread] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.RuntimeException: javafx.fxml.LoadException:
/C:/Users/FacilOrdi/IdeaProjects/quizManagement/target/classes/fxml/quiz.fxml:7
at com.gi.quizui.StageInitializer.onApplicationEvent(StageInitializer.java:40)
at com.gi.quizui.StageInitializer.onApplicationEvent(StageInitializer.java:16)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:426)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383)
at com.gi.quizui.QuizApplication.start(QuizApplication.java:20)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1(LauncherImpl.java:846)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait(PlatformImpl.java:455)
at com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:427)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$runLoop(WinApplication.java:174)
... 1 more
Caused by: javafx.fxml.LoadException:
/C:/Users/FacilOrdi/IdeaProjects/quizManagement/target/classes/fxml/quiz.fxml:7
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
at com.gi.quizui.StageInitializer.onApplicationEvent(StageInitializer.java:35)
... 16 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.gi.controllers.QuizController' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1177)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:938)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:980)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:227)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:752)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2722)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
... 19 more
控制器:
package com.gi.controllers;
import org.springframework.stereotype.Component;
@Component
public class QuizController {
}
我不明白为什么它不起作用,我找到了相关问题,但我不明白它是如何工作的。如果有其他替代方法可以做到这一点,那将非常有帮助。
为了知道 classes 有诸如 @Component
等注释,Spring 引导需要扫描部分 classpath在启动时。默认情况下,它将扫描包含您传递给 SpringApplicationBuilder
(在您的情况下为 Application
)和所有子包的 class 的包。
因此,根据您的设置方式,它将扫描 com.gi.quizui
和所有子包。
您的 QuizController
class 不在 com.gi.quizui
的子包中;它在 com.gi.controllers
。因此它不会被发现。
Spring Boot 文档中的建议实际上是在包含[=36=]es 或资源的最高级包中包含Application
class,即在你的情况下可能 com.gi
。如果您将 class 移动到那个包,它应该可以解决问题。
或者,您可以使用 @ComponentScan
注释覆盖默认行为:
package com.gi.quizui;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan ;
@SpringBootApplication
@ComponentScan(basePackages={"com.gi.quizui","com.gi.controllers"})
public class Application {
public static void main(String[] args) {
javafx.application.Application.launch(QuizApplication.class, args);
}
}
类型安全的替代方法是使用 basePackageClasses
参数而不是 basePackages
:
package com.gi.quizui;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan ;
import com.gi.controllers.QuizController ;
@SpringBootApplication
@ComponentScan(basePackageClasses={Application.class, QuizController.class})
public class Application {
public static void main(String[] args) {
javafx.application.Application.launch(QuizApplication.class, args);
}
}
我正在使用 spring 引导和 javaFx 开发 java 桌面应用程序。
这是一个 crud 应用程序,所以我正在使用 mysql 数据库
我希望控制器既是 spring 引导控制器又是 javaFx 控制器,为此我使用了 setControllerFactory()
.
这是我的申请
申请:
package com.gi.quizui;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
javafx.application.Application.launch(QuizApplication.class, args);
}
}
测验申请:
package com.gi.quizui;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ConfigurableApplicationContext;
public class QuizApplication extends Application {
private ConfigurableApplicationContext applicationContext;
@Override
public void init() {
applicationContext = new SpringApplicationBuilder(com.gi.quizui.Application.class).run();
}
@Override
public void start(Stage stage) {
applicationContext.publishEvent(new StageReadyEvent(stage));
}
@Override
public void stop() {
applicationContext.close();
Platform.exit();
}
class StageReadyEvent extends ApplicationEvent {
public StageReadyEvent(Stage stage) {
super(stage);
}
public ConfigurableApplicationContext getAppContext() {
return applicationContext;
}
public Stage getStage() {
return ((Stage) getSource());
}
}
}
和阶段初始化程序:
package com.gi.quizui;
import com.gi.quizui.QuizApplication.StageReadyEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class StageInitializer implements ApplicationListener<StageReadyEvent> {
@Value("classpath:fxml/quiz.fxml")
private Resource quizResource;
public StageInitializer(@Value("${spring.application.ui.title}") String applicationTitle) {
this.applicationTitle = applicationTitle;
}
private String applicationTitle;
@Override
public void onApplicationEvent(StageReadyEvent event) {
Stage stage = event.getStage();
ConfigurableApplicationContext springContext = event.getAppContext();
try {
FXMLLoader fxmlLoader = new FXMLLoader(quizResource.getURL());
fxmlLoader.setControllerFactory(springContext::getBean);
Parent parent = fxmlLoader.load();
stage.setScene(new Scene(parent, 800, 600));
stage.setTitle(applicationTitle);
stage.show();
} catch (IOException e) {
throw new RuntimeException();
}
}
}
我不断收到此错误:(编辑)
Exception in Application start method
2021-01-16 15:37:15.286 INFO 8652 --- [lication Thread] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2021-01-16 15:37:15.320 INFO 8652 --- [lication Thread] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2021-01-16 15:37:15.343 INFO 8652 --- [lication Thread] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.RuntimeException: javafx.fxml.LoadException:
/C:/Users/FacilOrdi/IdeaProjects/quizManagement/target/classes/fxml/quiz.fxml:7
at com.gi.quizui.StageInitializer.onApplicationEvent(StageInitializer.java:40)
at com.gi.quizui.StageInitializer.onApplicationEvent(StageInitializer.java:16)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:426)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383)
at com.gi.quizui.QuizApplication.start(QuizApplication.java:20)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1(LauncherImpl.java:846)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait(PlatformImpl.java:455)
at com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:427)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$runLoop(WinApplication.java:174)
... 1 more
Caused by: javafx.fxml.LoadException:
/C:/Users/FacilOrdi/IdeaProjects/quizManagement/target/classes/fxml/quiz.fxml:7
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
at com.gi.quizui.StageInitializer.onApplicationEvent(StageInitializer.java:35)
... 16 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.gi.controllers.QuizController' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1177)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:938)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:980)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:227)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:752)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2722)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
... 19 more
控制器:
package com.gi.controllers;
import org.springframework.stereotype.Component;
@Component
public class QuizController {
}
我不明白为什么它不起作用,我找到了相关问题,但我不明白它是如何工作的。如果有其他替代方法可以做到这一点,那将非常有帮助。
为了知道 classes 有诸如 @Component
等注释,Spring 引导需要扫描部分 classpath在启动时。默认情况下,它将扫描包含您传递给 SpringApplicationBuilder
(在您的情况下为 Application
)和所有子包的 class 的包。
因此,根据您的设置方式,它将扫描 com.gi.quizui
和所有子包。
您的 QuizController
class 不在 com.gi.quizui
的子包中;它在 com.gi.controllers
。因此它不会被发现。
Spring Boot 文档中的建议实际上是在包含[=36=]es 或资源的最高级包中包含Application
class,即在你的情况下可能 com.gi
。如果您将 class 移动到那个包,它应该可以解决问题。
或者,您可以使用 @ComponentScan
注释覆盖默认行为:
package com.gi.quizui;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan ;
@SpringBootApplication
@ComponentScan(basePackages={"com.gi.quizui","com.gi.controllers"})
public class Application {
public static void main(String[] args) {
javafx.application.Application.launch(QuizApplication.class, args);
}
}
类型安全的替代方法是使用 basePackageClasses
参数而不是 basePackages
:
package com.gi.quizui;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan ;
import com.gi.controllers.QuizController ;
@SpringBootApplication
@ComponentScan(basePackageClasses={Application.class, QuizController.class})
public class Application {
public static void main(String[] args) {
javafx.application.Application.launch(QuizApplication.class, args);
}
}