Springboot整合JAVAFX
Springboot整合JAVAFX
实体与VO设计
pom.xml文件如下:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.elitedatai</groupId><artifactId>javafxTest</artifactId><version>1.0</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.2</version><relativePath/> <!-- lookup parent from repository --></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><javafx.version>21</javafx.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><scope>runtime</scope></dependency><!-- javaFX --><dependency><groupId>org.openjfx</groupId><artifactId>javafx-controls</artifactId><version>${javafx.version}</version></dependency><dependency><groupId>org.openjfx</groupId><artifactId>javafx-fxml</artifactId><version>${javafx.version}</version></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin><!-- JavaFX Maven Plugin --><plugin><groupId>org.openjfx</groupId><artifactId>javafx-maven-plugin</artifactId><version>0.0.8</version><configuration><mainClass>com.elitedatai.MainApp</mainClass></configuration></plugin></plugins></build></project>
实体类设计:
package com.elitedatai.model;import jakarta.persistence.*;
import lombok.Data;import java.time.LocalDateTime;/*** @author llg* @slogan 致敬大师,致敬未来的你* @create 2025-04-10 15:57*/
@Data
@Table(name = "Work_Order")
@Entity
public class WorkOrder {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(nullable = false, length = 50)private String orderNo; // 工单编号@Column(nullable = false, length = 100)private String productName; // 产品名称@Column(nullable = false, length = 50)private String productCode; // 产品编码@Column(nullable = false)private Integer plannedQuantity; // 计划数量@Column(nullable = false)private Integer completedQuantity = 0; // 已完成数量@Column(nullable = false)private LocalDateTime startTime; // 计划开始时间@Column(nullable = false)private LocalDateTime endTime; // 计划结束时间@Enumerated(EnumType.STRING)@Column(nullable = false, length = 20)private OrderStatus status; // 工单状态@Column(length = 500)private String remark; // 备注// 工单状态枚举public enum OrderStatus {PENDING, // 待开始IN_PROGRESS, // 进行中PAUSED, // 已暂停COMPLETED, // 已完成CANCELLED // 已取消}
}
VO类设计:
/*** 工单值对象 - 用于前后端数据传输* 这个类可以被Spring MVC和JavaFX共同使用*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class WorkOrderVO {private Long id;private String orderNo;private String productName;private String productCode;private Integer plannedQuantity;private Integer completedQuantity;private LocalDateTime startTime;private LocalDateTime endTime;private WorkOrder.OrderStatus status;private String remark;// 计算进度百分比public Double getProgress() {if (plannedQuantity == null || plannedQuantity == 0) {return 0.0;}return (completedQuantity.doubleValue() / plannedQuantity.doubleValue()) * 100;}// 从实体类转换public static WorkOrderVO fromEntity(WorkOrder entity) {if (entity == null) return null;WorkOrderVO vo = new WorkOrderVO();vo.setId(entity.getId()); vo.setOrderNo(entity.getOrderNo()); vo.setProductName(entity.getProductName()); vo.setProductCode(entity.getProductCode()); vo.setPlannedQuantity(entity.getPlannedQuantity()); vo.setCompletedQuantity(entity.getCompletedQuantity()); vo.setStartTime(entity.getStartTime()); vo.setEndTime(entity.getEndTime()); vo.setStatus(entity.getStatus()); vo.setRemark(entity.getRemark()); return vo;}// 转换为实体类public WorkOrder toEntity() {WorkOrder entity = new WorkOrder();entity.setId(this.getId()); entity.setOrderNo(this.getOrderNo()); entity.setProductName(this.getProductName()); entity.setProductCode(this.getProductCode()); entity.setPlannedQuantity(this.getPlannedQuantity()); entity.setCompletedQuantity(this.getCompletedQuantity()); entity.setStartTime(this.getStartTime()); entity.setEndTime(this.getEndTime()); entity.setStatus(this.getStatus()); entity.setRemark(this.getRemark()); return entity;}
}
SpringBoot与JavaFX集成配置
JavaFX配置类 (JavaFXConfiguration.java)
package com.elitedatai.config;/*** @author llg* @slogan 致敬大师,致敬未来的你* @create 2025-04-10 15:47*/import javafx.application.Application;
import javafx.application.HostServices;
import javafx.application.Platform;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.GenericApplicationContext;import java.util.function.Consumer;/*** JavaFX配置类,负责启动JavaFX应用并集成Spring上下文* 核心功能:* 1. 初始化Spring应用上下文* 2. 加载JavaFX主舞台(Stage)* 3. 管理两者生命周期*/
public class JavaFXConfiguration extends Application {// Spring应用上下文,用于依赖注入private ConfigurableApplicationContext context;// JavaFX根节点,所有UI组件的容器private Parent root;// Stage自定义配置回调函数private Consumer<Stage> stageConsumer;@Overridepublic void init() throws Exception {// // 创建Spring上下文初始化器,注册JavaFX核心对象ApplicationContextInitializer<GenericApplicationContext> initializer = ac -> {// 将JavaFX Application实例注册为Spring Beanac.registerBean(Application.class, () -> JavaFXConfiguration.this);// 注册启动参数(命令行参数)ac.registerBean(Parameters.class, this::getParameters);// 注册HostServices(用于打开网页等操作)ac.registerBean(HostServices.class, this::getHostServices);};// 构建Spring应用(关键步骤)this.context = new SpringApplicationBuilder().sources(com.elitedatai.Application.class) // 指定SpringBoot主类.initializers(initializer) // 添加上文初始化器.run(getParameters().getRaw().toArray(new String[0])); // 传递启动参数}/*** JavaFX主入口(UI线程开始执行)* @param primaryStage 主舞台(相当于主窗口)*/@Overridepublic void start(Stage primaryStage) throws Exception {// 从Spring容器获取FXML加载配置FxmlViewConfiguration viewConfig = context.getBean(FxmlViewConfiguration.class);// 加载主视图(触发FXML文件的解析和控制器初始化)this.root = viewConfig.mainView();// 创建场景图(Scene是UI组件的根容器)Scene scene = new Scene(root, 1200, 800);// 配置主舞台primaryStage.setScene(scene); // 绑定场景到舞台primaryStage.setTitle(" 工厂MES上位机系统"); // 设置窗口标题primaryStage.centerOnScreen(); // 窗口居中显示// 执行自定义舞台配置(如果有)if (stageConsumer != null) {stageConsumer.accept(primaryStage);}// 显示窗口(至此UI可见)primaryStage.show();}/*** JavaFX停止方法(窗口关闭时调用)*/@Overridepublic void stop() throws Exception {// 关闭Spring应用上下文(触发@PreDestroy等生命周期回调)this.context.close();// 确保JavaFX平台完全退出Platform.exit();}/*** 设置舞台自定义配置器* @param stageConsumer 接收Stage对象的函数式接口*/public void setStageConsumer(Consumer<Stage> stageConsumer) {this.stageConsumer = stageConsumer;}
}
FXML视图配置 (FxmlViewConfiguration.java)
package com.elitedatai.config;/*** @author llg* @slogan 致敬大师,致敬未来的你* @create 2025-04-10 15:48*/import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.net.URL;/*** FXML视图配置类,负责加载FXML文件并注入Spring管理的控制器*/
@Component
public class FxmlViewConfiguration {private final ApplicationContext context;@Autowiredpublic FxmlViewConfiguration(ApplicationContext context) {this.context = context;}/*** 加载主视图*/public Parent mainView() throws IOException {return loadView("/fxml/main.fxml");}/*** 加载工单管理视图*/public Parent workOrderView() throws IOException {return loadView("/fxml/work_order.fxml");}/*** 通用视图加载方法*/private Parent loadView(String fxmlPath) throws IOException {FXMLLoader loader = new FXMLLoader();URL resource = getClass().getResource(fxmlPath);loader.setLocation(resource);loader.setControllerFactory(context::getBean); // 使用Spring管理的控制器return loader.load();}
}
服务层接口
我使用的是JPA框架,根据实体,写好实体相关仓库接口和业务层接口,直接贴代码:
/*** 工单服务类 - 业务逻辑处理*/
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class WorkOrderService {private final WorkOrderRepository workOrderRepository;private final ModelMapper modelMapper;/*** 创建工单*/@Transactionalpublic WorkOrderVO create(WorkOrderVO vo) {WorkOrder entity = vo.toEntity(); WorkOrder saved = workOrderRepository.save(entity); return WorkOrderVO.fromEntity(saved); }/*** 更新工单*/@Transactionalpublic WorkOrderVO update(WorkOrderVO vo) {WorkOrder existing = workOrderRepository.findById(vo.getId()) .orElseThrow(() -> new RuntimeException("工单不存在"));// 更新字段existing.setOrderNo(vo.getOrderNo()); existing.setProductName(vo.getProductName()); existing.setProductCode(vo.getProductCode()); existing.setPlannedQuantity(vo.getPlannedQuantity()); existing.setCompletedQuantity(vo.getCompletedQuantity()); existing.setStartTime(vo.getStartTime()); existing.setEndTime(vo.getEndTime()); existing.setStatus(vo.getStatus()); existing.setRemark(vo.getRemark()); WorkOrder updated = workOrderRepository.save(existing); return WorkOrderVO.fromEntity(updated); }/*** 获取所有工单*/public List<WorkOrderVO> findAll() {return workOrderRepository.findAll().stream() .map(WorkOrderVO::fromEntity).collect(Collectors.toList()); }/*** 分页查询工单*/public Page<WorkOrderVO> findAll(Pageable pageable) {return workOrderRepository.findAll(pageable) .map(WorkOrderVO::fromEntity);}/*** 根据ID获取工单*/public WorkOrderVO findById(Long id) {return workOrderRepository.findById(id) .map(WorkOrderVO::fromEntity).orElseThrow(() -> new RuntimeException("工单不存在"));}/*** 删除工单*/@Transactionalpublic void delete(Long id) {workOrderRepository.deleteById(id); }/*** 更新工单进度*/@Transactionalpublic WorkOrderVO updateProgress(Long id, Integer completed) {WorkOrder order = workOrderRepository.findById(id) .orElseThrow(() -> new RuntimeException("工单不存在"));order.setCompletedQuantity(completed); if (completed >= order.getPlannedQuantity()) {order.setStatus(WorkOrder.OrderStatus.COMPLETED); }WorkOrder updated = workOrderRepository.save(order); return WorkOrderVO.fromEntity(updated); }
}
控制层
javafx相关控制层
Main控制层:
package com.elitedatai.controller.fx;import com.elitedatai.config.FxmlViewConfiguration;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import org.springframework.stereotype.Controller;/*** 主界面控制器 - 负责管理主界面的导航和状态显示*/
@Controller
public class MainController {@FXML private StackPane contentPane;@FXML private Label statusLabel;private final FxmlViewConfiguration viewConfig;public MainController(FxmlViewConfiguration viewConfig) {this.viewConfig = viewConfig;}/*** 初始化方法,FXML加载后自动调用*/@FXMLpublic void initialize() {// 默认加载工单管理视图showWorkOrderView();}/*** 显示工单管理视图*/@FXMLpublic void showWorkOrderView() {try {contentPane.getChildren().clear();contentPane.getChildren().add(viewConfig.workOrderView());updateStatus("工单管理视图已加载");} catch (Exception e) {updateStatus("加载工单视图失败: " + e.getMessage());e.printStackTrace();}}/*** 退出应用程序*/@FXMLpublic void handleExit() {javafx.application.Platform.exit();}/*** 更新状态栏信息*/private void updateStatus(String message) {statusLabel.setText(message);}
}
main.fxml:
<?xml version="1.0" encoding="UTF-8"?><?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?><BorderPane xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"fx:controller="com.elitedatai.controller.fx.MainController"><top><MenuBar BorderPane.alignment="CENTER"><menus><Menu text="文件"><items><MenuItem text="退出" onAction="#handleExit" /></items></Menu><Menu text="工单管理"><items><MenuItem text="工单列表" onAction="#showWorkOrderView" /></items></Menu><Menu text="帮助"><items><MenuItem text="关于" /></items></Menu></menus></MenuBar></top><center><StackPane fx:id="contentPane" /></center><bottom><HBox alignment="CENTER" spacing="10" style="-fx-background-color: #f0f0f0; -fx-padding: 5;"><Label text="工厂MES上位机系统" /><Label text="版本: 1.0.0" /><Label fx:id="statusLabel" text="就绪" /></HBox></bottom>
</BorderPane>
WorkOrderController:
package com.elitedatai.controller.fx;import com.elitedatai.model.Test;
import com.elitedatai.service.WorkOrderService;
import com.elitedatai.vo.TestVO;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;import java.time.LocalDateTime;
import java.util.List;/*** JavaFX工单控制器*/
@Controller
@RequiredArgsConstructor
public class WorkOrderController {private final WorkOrderService workOrderService;// FXML注入的UI组件@FXML private TableView<TestVO> workOrderTable;@FXML private TableColumn<TestVO, String> orderNoColumn;@FXML private TableColumn<TestVO, String> productNameColumn;@FXML private TableColumn<TestVO, Integer> plannedQuantityColumn;@FXML private TableColumn<TestVO, Integer> completedQuantityColumn;@FXML private TableColumn<TestVO, String> progressColumn;@FXML private TableColumn<TestVO, String> statusColumn;@FXML private TextField orderNoField;@FXML private TextField productNameField;@FXML private TextField productCodeField;@FXML private TextField plannedQuantityField;@FXML private DatePicker startDatePicker;@FXML private DatePicker endDatePicker;@FXML private ComboBox<String> statusComboBox;@FXML private TextArea remarkArea;private final ObservableList<TestVO> workOrderData = FXCollections.observableArrayList();/*** 初始化方法,由FXML加载器调用*/@FXMLpublic void initialize() {// 配置表格列orderNoColumn.setCellValueFactory(new PropertyValueFactory<>("orderNo"));productNameColumn.setCellValueFactory(new PropertyValueFactory<>("productName"));plannedQuantityColumn.setCellValueFactory(new PropertyValueFactory<>("plannedQuantity"));completedQuantityColumn.setCellValueFactory(new PropertyValueFactory<>("completedQuantity"));progressColumn.setCellValueFactory(cellData -> {double progress = cellData.getValue().getProgress();return new javafx.beans.property.SimpleStringProperty(String.format("%.2f%%", progress));});statusColumn.setCellValueFactory(new PropertyValueFactory<>("status"));// 绑定数据workOrderTable.setItems(workOrderData);// 加载数据refreshData();// 配置状态下拉框statusComboBox.getItems().addAll("PENDING", "IN_PROGRESS", "PAUSED", "COMPLETED", "CANCELLED");}/*** 刷新表格数据*/private void refreshData() {List<TestVO> orders = workOrderService.findAll();workOrderData.clear();workOrderData.addAll(orders);}/*** 创建新工单*/@FXMLprivate void handleCreate() {try {TestVO vo = new TestVO();vo.setOrderNo(orderNoField.getText());vo.setProductName(productNameField.getText());vo.setProductCode(productCodeField.getText());vo.setPlannedQuantity(Integer.parseInt(plannedQuantityField.getText()));vo.setCompletedQuantity(0);vo.setStartTime(LocalDateTime.from(startDatePicker.getValue().atStartOfDay()));vo.setEndTime(LocalDateTime.from(endDatePicker.getValue().atStartOfDay()));vo.setStatus(Test.OrderStatus.valueOf(statusComboBox.getValue()));vo.setRemark(remarkArea.getText());workOrderService.create(vo);refreshData();clearFields();showAlert("成功", "工单创建成功", Alert.AlertType.INFORMATION);} catch (Exception e) {showAlert("错误", "创建工单失败: " + e.getMessage(), Alert.AlertType.ERROR);}}/*** 更新工单进度*/@FXMLprivate void handleUpdateProgress() {TestVO selected = workOrderTable.getSelectionModel().getSelectedItem();if (selected == null) {showAlert("警告", "请先选择一条工单", Alert.AlertType.WARNING);return;}TextInputDialog dialog = new TextInputDialog(selected.getCompletedQuantity().toString());dialog.setTitle(" 更新进度");dialog.setHeaderText(" 请输入已完成数量");dialog.setContentText(" 数量:");dialog.showAndWait().ifPresent(completed -> {try {int completedQty = Integer.parseInt(completed);workOrderService.updateProgress(selected.getId(), completedQty);refreshData();showAlert("成功", "工单进度更新成功", Alert.AlertType.INFORMATION);} catch (NumberFormatException e) {showAlert("错误", "请输入有效的数字", Alert.AlertType.ERROR);} catch (Exception e) {showAlert("错误", "更新进度失败: " + e.getMessage(), Alert.AlertType.ERROR);}});}/*** 显示警告对话框*/private void showAlert(String title, String message, Alert.AlertType type) {Alert alert = new Alert(type);alert.setTitle(title);alert.setHeaderText(null);alert.setContentText(message);alert.showAndWait();}/*** 清空输入字段*/private void clearFields() {orderNoField.clear();productNameField.clear();productCodeField.clear();plannedQuantityField.clear();startDatePicker.setValue(null);endDatePicker.setValue(null);statusComboBox.setValue(null);remarkArea.clear();}
}
workorder.fxml:
<?xml version="1.0" encoding="UTF-8"?><?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?><VBox xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"fx:controller="com.elitedatai.controller.fx.WorkOrderController" spacing="10"><Label text="工单管理" style="-fx-font-size: 16pt; -fx-font-weight: bold;" /><HBox spacing="10" alignment="CENTER_LEFT"><Label text="工单编号:" /><TextField fx:id="orderNoField" promptText="请输入工单编号" /><Label text="产品名称:" /><TextField fx:id="productNameField" promptText="请输入产品名称" /><Label text="产品编码:" /><TextField fx:id="productCodeField" promptText="请输入产品编码" /></HBox><HBox spacing="10" alignment="CENTER_LEFT"><Label text="计划数量:" /><TextField fx:id="plannedQuantityField" promptText="请输入计划数量" /><Label text="开始日期:" /><DatePicker fx:id="startDatePicker" /><Label text="结束日期:" /><DatePicker fx:id="endDatePicker" /><Label text="状态:" /><ComboBox fx:id="statusComboBox" promptText="选择状态" /></HBox><HBox spacing="10" alignment="CENTER_LEFT"><Label text="备注:" /><TextArea fx:id="remarkArea" promptText="请输入备注信息" wrapText="true" prefRowCount="2" /></HBox><HBox spacing="10"><Button text="创建工单" onAction="#handleCreate" style="-fx-base: #4CAF50;" /><Button text="更新进度" onAction="#handleUpdateProgress" style="-fx-base: #2196F3;" /></HBox><TableView fx:id="workOrderTable" prefHeight="400"><columns><TableColumn text="工单编号" fx:id="orderNoColumn" prefWidth="120" /><TableColumn text="产品名称" fx:id="productNameColumn" prefWidth="150" /><TableColumn text="计划数量" fx:id="plannedQuantityColumn" prefWidth="80" /><TableColumn text="完成数量" fx:id="completedQuantityColumn" prefWidth="80" /><TableColumn text="进度" fx:id="progressColumn" prefWidth="80" /><TableColumn text="状态" fx:id="statusColumn" prefWidth="100" /></columns></TableView>
</VBox>
web控制层
package com.elitedatai.controller.web;/*** @author llg* @slogan 致敬大师,致敬未来的你* @create 2025-04-10 16:19*/import com.elitedatai.service.WorkOrderService;
import com.elitedatai.vo.TestVO;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;/*** 工单REST API控制器*/
@RestController
@RequestMapping("/api/work-orders")
@RequiredArgsConstructor
public class WorkOrderApiController {private final WorkOrderService workOrderService;/*** 获取所有工单*/@GetMappingpublic ResponseEntity<List<TestVO>> findAll() {return ResponseEntity.ok(workOrderService.findAll());}/*** 分页查询工单*/@GetMapping("/page")public ResponseEntity<Page<TestVO>> findAll(Pageable pageable) {return ResponseEntity.ok(workOrderService.findAll(pageable));}/*** 根据ID获取工单*/@GetMapping("/{id}")public ResponseEntity<TestVO> findById(@PathVariable Long id) {return ResponseEntity.ok(workOrderService.findById(id));}/*** 创建工单*/@PostMappingpublic ResponseEntity<TestVO> create(@RequestBody TestVO vo) {return ResponseEntity.ok(workOrderService.create(vo));}/*** 更新工单*/@PutMapping("/{id}")public ResponseEntity<TestVO> update(@PathVariable Long id, @RequestBody TestVO vo) {vo.setId(id);return ResponseEntity.ok(workOrderService.update(vo));}/*** 删除工单*/@DeleteMapping("/{id}")public ResponseEntity<Void> delete(@PathVariable Long id) {workOrderService.delete(id);return ResponseEntity.noContent().build();}/*** 更新工单进度*/@PatchMapping("/{id}/progress")public ResponseEntity<TestVO> updateProgress(@PathVariable Long id,@RequestParam Integer completed) {return ResponseEntity.ok(workOrderService.updateProgress(id, completed));}
}
启动类与主应用
SpringBoot主类 (Application.java)
package com.elitedatai;/*** @author llg* @slogan 致敬大师,致敬未来的你* @create 2025-04-10 16:12*/import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** SpringBoot主启动类*/
@SpringBootApplication
public class Application {public static void main(String[] args) {// 检查是否以JavaFX模式启动if (args.length > 0 && args[0].equals("--javafx")) {com.elitedatai.MainApp.main(args);} else {SpringApplication.run(Application.class, args);}}
}
JavaFX主类 (MainApp.java)
package com.elitedatai;import com.elitedatai.config.JavaFXConfiguration;
import javafx.application.Application;/*** JavaFX主启动类*/
public class MainApp {public static void main(String[] args) {// 启动JavaFX应用Application.launch(JavaFXConfiguration.class, "--javafx");}
}
运行与部署
1. 运行应用
直接想启动web就运行web主类,想启动javafx就运行javafx主类
2.打包应用
创建可执行JAR:
mvn clean package
然后运行:
java -jar target/mes-upper-machine-1.0.0.jar --javafx
或者作为Web应用运行:
java -jar target/mes-upper-machine-1.0.0.jar
JavaFx在Springboot中的依赖关系如图:
相关文章:
Springboot整合JAVAFX
Springboot整合JAVAFX 实体与VO设计 pom.xml文件如下: <?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"xs…...
【算法】——一键解决动态规划
前言 动态规划是一种高效解决重叠子问题和最优子结构问题的算法思想。它通过分治记忆化,将复杂问题分解为子问题,并存储中间结果,避免重复计算,从而大幅提升效率。 为什么重要? 优化…...
Git使用与管理
一.基本操作 1.创建本地仓库 在对应文件目录下进行: git init 输入完上面的代码,所在文件目录下就会多一个名为 .git 的隐藏文件,该文件是Git用来跟踪和管理仓库的。 我们可以使用 tree 命令(注意要先下载tree插件)…...
npm、nvm、nrm
NVM (Node Version Manager) 常见指令 NVM 是一个用于管理 Node.js 版本的流行工具,允许你在同一台机器上安装和切换不同版本的 Node.js。以下是 NVM 的常见指令: 安装与卸载 nvm install <version> - 安装指定版本的 Node.js 例如:…...
Java 文件内容转换为MD5哈希值
若要把读取到的 files 列表里的内容转换为 MD5 哈希值,你可以逐个遍历 files 列表中的元素,将每个元素的内容计算成 MD5 哈希值。 以下是一个完整的 Java 示例代码,展示了如何实现这一功能: import java.io.BufferedInputStream…...
未来郴州:科技与自然的交响诗篇
故事背景 故事发生在中国湖南郴州,描绘了未来城市中科技与自然共生共荣的奇妙图景。通过六个充满诗意的场景,展现雾能转化系统、立体生态书库、智能稻田等创新设计,编织出一曲人类智慧与自然韵律共鸣的未来交响。 故事内容 在东江湖的晨雾中&…...
UE5 运行时动态将玩家手部模型设置为相机的子物体
在编辑器里,我们虽然可以手动添加相机,但是无法将网格体设置为相机的子物体,只能将相机设置为网格体的子物体 但是为了使用方便,我们希望将网格体设置为相机的子物体,这样我们直接旋转相机就可以旋转网格体࿰…...
Ubuntu系统下的包管理器APT
Ubuntu系统下的包管理器APT 在Linux操作系统生态中,软件包管理工具是连接用户与系统功能的桥梁。Ubuntu作为基于Debian的流行发行版,其强大的包管理系统APT(Advanced Packaging Tool)为开发者与系统管理员提供了便捷的软件生命周…...
超级码科技发布镂空AI保险胶带,重塑包装防伪新标准
在酒类、物流、奢侈品、电子产品等领域,包装安全与防伪需求日益迫切。传统封箱胶带易被转移或重复利用,导致商品被仿冒的风险居高不下。 为此,超级码科技推出镂空型防揭AI数字身份保险封箱胶带——一款集结构防伪、信息追踪与增值服务于一体的…...
微软Exchange管理中心全球范围宕机
微软已确认Exchange管理中心(Exchange Admin Center,EAC)发生全球性服务中断,导致管理员无法访问关键管理工具。该故障被标记为关键服务事件(编号EX1051697),对依赖Exchange Online的企业造成广…...
前端通信库fetch-event-source实现丰富的SSE
环境:SpringBoot3.4.0 + Vue3 1. 简介 SSE(Server-Sent Events)是一种基于HTTP的服务器向客户端单向推送实时数据的轻量级协议,配合浏览器原生EventSource API,可实现高效实时通信。前端通过创建EventSource对象订阅服务端流,自动处理连接、重试与数据解析;服务端设置C…...
JVM 中Minor GC、Major GC、Full GC 的区别?
Minor GC、Major GC 和 Full GC 是 Java 虚拟机 (JVM) 垃圾回收 (Garbage Collection) 中的不同类型的 GC 事件,它们在范围、触发条件、停顿时间等方面有所不同。 1. Minor GC (Young GC): 范围: 只针对新生代 (Young Generation) 进行垃圾回收。触发条…...
2747. 统计没有收到请求的服务器数目
文章目录 题意思路代码 题意 题目链接 思路 代码 class Solution { public:vector<int> countServers(int n, vector<vector<int>>& logs, int x, vector<int>& queries) {sort(logs.begin(), logs.end(), [](vector<int> &a, v…...
设计模式:抽象工厂 - 掌控多产品族的创建之道
一、什么是抽象工厂模式? 抽象工厂模式是一种创建型设计模式,提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。 核心思想 1.定义多个产品的抽象接口,统一管理具体产品和工厂的创建逻辑。…...
图神经网络+多模态:视频动作分割的轻量高效新解法
一、引言 在智能监控、自动驾驶、人机交互等领域,准确理解视频中的动作序列至关重要。然而,传统方法依赖复杂的视觉模型,计算成本高且难以捕捉长时依赖。近期,一项名为 Semantic2Graph 的研究通过图神经网络(GNN&am…...
技术与情感交织的一生 (五)
目录 初入“江湖” 分工 陌生 CraneOffice 内功 宝典 枪手 回到大二 通关 小聚 唱一首歌 初入“江湖” 分工 软件工作室是坐落在和平区宜昌道的一间民房,和我想象中的公司形象多少有些偏差。天津的道路有点凌乱,初次的时候不太好找…...
简单-快速-高效——模块化解析Pulid(实现不同风格下的人脸一致)
资源 论文:https://arxiv.org/abs/2404.16022 github:https://github.com/ToTheBeginning/PuLID?tabreadme-ov-file comfyui插件:https://github.com/sipie800/ComfyUI-PuLID-Flux-Enhanced 讲解参考 https://zhuanlan.zhihu.com/p/69684…...
XYZ to xyY 求解
免责声明:本文所提供的信息和内容仅供参考。作者对本文内容的准确性、完整性、及时性或适用性不作任何明示或暗示的保证。在任何情况下,作者不对因使用本文内容而导致的任何直接或间接损失承担责任,包括但不限于数据丢失、业务中断或其他经济…...
科技自然的协奏曲-深圳
故事背景 故事发生在中国广东深圳的现代城市环境,这里呈现出未来科技与自然生态共生的独特图景。没有具体的角色,却通过多样的场景描绘,展现出未来生活的活力与创新,反映出社会创新与人类情感的紧密结合。 故事内容 在未来的深…...
idea 创建 maven-scala项目
文章目录 idea 创建 maven-scala项目1、创建普通maven项目并且配置pom.xml文件2、修改项目结构1)创建scala目录并标记成【源目录】2)导入scala环境3)测试环境 idea 创建 maven-scala项目 1、创建普通maven项目并且配置pom.xml文件 maven依赖…...
C++项目:高并发内存池_下
目录 8. thread cache回收内存 9. central cache回收内存 10. page cache回收内存 11. 大于256KB的内存申请和释放 11.1 申请 11.2 释放 12. 使用定长内存池脱离使用new 13. 释放对象时优化成不传对象大小 14. 多线程环境下对比malloc测试 15. 调试和复杂问题的调试技…...
【UE5】RTS游戏的框选功能+行军线效果实现
目录 效果 步骤 一、项目准备 二、框选NPC并移动到指定地点 三、框选效果 四、行军线效果 效果 步骤 一、项目准备 1. 新建一个俯视角游戏工程 2. 新建一个pawn、玩家控制器和游戏模式,这里分别命名为“MyPawn”、“MyController”和“MyGameMode” 3. 打开“MyGam…...
多图超详细:Docker安装知识库AI客服RAGFlow的详细步骤、使用教程及注意事项:
RAGFlow 介绍 RAGFlow 是一款基于深度文档理解的开源检索增强生成(RAG)引擎,通过结合信息检索与生成式 AI 技术,解决复杂场景下的数据处理和可信问答问题。其核心设计目标是提供透明化、可控化的文档处理流程,并通过多…...
docker compose安装智能体平台N8N
使用 docker volume create n8n_data 创建了一个名为 n8n_data 的数据卷。你通过 docker run 启动容器,映射了端口 5678,并挂载了 n8n_data 数据卷。 以下是对应的 docker-compose.yml 配置文件: version: "3.7"services:n8n:ima…...
FRP调用本地摄像头完成远程拍照
from flask import Flask, Response import cv2app Flask(__name__)# 基础文字回复 app.route(/) def hello_world():return <h1>你好啊世界</h1><img src"/camera" width"640" /># 摄像头拍照并返回图像 app.route(/camera) def captu…...
【Linux】39.一个基础的HTTP Web服务器
文章目录 1. 实现一个基础的HTTP Web服务器1.1 功能实现:1.2 Log.hpp-日志记录器1.3 HttpServer.hpp-网页服务器1.4 Socket.hpp-网络通信器1.5 HttpServer.cc-服务器启动器 1. 实现一个基础的HTTP Web服务器 1.1 功能实现: 总体功能: 提供We…...
蓝桥杯-小明的背包(动态规划-Java)
0/1背包问题介绍 0/1背包问题是经典的动态规划问题,具体描述如下: 解题思路: 输入数据 首先,程序通过 Scanner 从输入中读取数据: n 表示物品的数量。 v 表示背包的最大容量。 接着读取每个物品的重量和价值ÿ…...
(四十一)Dart 中的空安全与 `late` 关键字教程
Dart 中的空安全与 late 关键字教程 空安全简介 空安全(Null Safety)是 Dart 语言的一项重要特性,旨在帮助开发者避免空指针异常(NullPointerException)。空安全通过在编译时检查变量是否可能为 null,从而…...
GaussDB使用指南
目录 1. GaussDB 概述 1.1 GaussDB 简介 1.2 核心技术架构 1.3 适用场景与行业案例 2. GaussDB 安装与部署 2.1 环境准备与依赖检查 2.2 单机版安装(Linux) 2.3 分布式集群部署 3. GaussDB 基础操作与语法 3.1 数据库连接与用户管理 3.2 DDL …...
算法训练之动态规划(一)
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...
dubbo配置中心
配置中心 简介 配置中心(config-center)在dubbo中可承担两类职责: 外部化配置:启动配置的集中式存储。流量治理规则存储。 Dubbo动态配置中心定义了两个不同层次的隔离选项,分别是namespace和group。 namespace&a…...
移动端六大语言速记:第11部分 - 内存管理
移动端六大语言速记:第11部分 - 内存管理 本文将对比Java、Kotlin、Flutter(Dart)、Python、ArkTS和Swift这六种移动端开发语言在内存管理方面的特性,帮助开发者理解和掌握各语言的内存管理机制。 11. 内存管理 11.1 垃圾回收机制对比 各语言垃圾回收…...
对象的创建方式有哪些?在虚拟机中具体的创建过程是怎样的?
在Java中,对象的创建方式及其在虚拟机中的具体过程如下: 一、对象的创建方式 使用 new 关键字 最常见的对象创建方式,直接调用类的构造方法。 MyClass obj new MyClass();反射(Reflection) 通过 Class 或 Constructor…...
openwrt软路由配置3
1.启用sftp文件连接 使用ssh连接openwrt时,我发现无法打开sftp windows进行上传和下载文件,提示 sftp channel closed by server: stderr:ash /usr/libexec/sftp-server:not found 原因是系统刚刚装好后,没有安装openssh-sftp-server包 opk…...
C语言for循环嵌套if相关题目
一、题目引入 以下代码程序运行结果是多少? 二、思路解析 进入一个for循环 a<100 进入第一个if b1不大于20为假 进入第二个if b4 a这时a自增为2 当b4时,满足第二个if条件 1.b4,a2 当b7时,满足第二个if条件 2.bb37,a3 当b10时,满足第二个if条件 …...
Redis与Mysql双写一致性如何保证?
我们在面试的时候redis与mysql双写一致性是一个常考的问题,今天我们就一起探讨一下吧 所谓的一致性就是数据的一致性,在分布式系统中,可以理解为多个节点中数据的值是一致的。 强一致性: 这种一致性级别是最符合用户直觉的&…...
STM32 CRC校验与芯片ID应用全解析:从原理到实践 | 零基础入门STM32第九十七步
主题内容教学目的/扩展视频CRC与芯片ID原理实现CRC校验和读取芯片ID为单片机应用提供数据验证和身份识别的功能。 师从洋桃电子,杜洋老师 📑文章目录 一、CRC校验功能解析1.1 CRC基本原理1.2 核心功能对比 二、CRC校验应用实战2.1 典型应用场景2.2 程序实…...
《微服务与事件驱动架构》读书分享
《微服务与事件驱动架构》读书分享 Building Event-Driver Microservices 英文原版由 OReilly Media, Inc. 出版,2020 作者:[加] 亚当 • 贝勒马尔 译者:温正东 作者简介: 这本书由亚当贝勒马尔(Adam Bellemare…...
⼤模型(LLMs)基础
⼤模型(LLMs)基础 ⽬前 主流的开源模型体系 有哪些?prefix Decoder 和 causal Decoder 和 Encoder-Decoder 区别是什么?⼤模型LLM的 训练⽬标 是什么?涌现能⼒是啥原因?为何现在的⼤模型⼤部分是Decoder o…...
IDEA :物联网ThingsBoard-gateway配置,运行Python版本,连接thingsboard,接入 MQTT 设备
准备阶段(教程只针对本地操作,未涉及虚拟机环境) Thingsboard源码编译并运行 没有操作过的小伙伴,可以看我上一篇文章 物联网ThingsBoard源码本地编译篇,超详细教程,小白看过来!_thingsboard…...
面向大模型的开发框架LangChain
这篇文章会带给你 如何使用 LangChain:一套在大模型能力上封装的工具框架如何用几行代码实现一个复杂的 AI 应用面向大模型的流程开发的过程抽象 文章目录 这篇文章会带给你写在前面LangChain 的核心组件文档(以 Python 版为例)模型 I/O 封装…...
每日算法:洛谷U535992 J-C 小梦的宝石收集(双指针、二分)
题目描述 小梦有 n 颗能量宝石,其中第 i 颗的能量为 ai,但这些能量宝石十分不稳定,随时有可能发生崩坏,导致他们全部消失! 小梦想要留住宝石们,不希望他们发生崩坏,同时他发现:如…...
写给新人的深度学习扫盲贴:ReLu和梯度
一、ReLU(Rectified Linear Unit,修正线性单元) 梯度是深度学习中最常用的激活函数之一,因其简单、高效且能有效缓解梯度消失问题而被广泛使用。 1. 数学定义 函数表达式: $$ \text{ReLU}(x) \max(0, x) \begin{…...
Spring 框架的核心基础:IoC 和 AOP
一、IoC(Inversion of Control,控制反转) 定义: IoC(Inversion of Control,控制反转),就是把对象创建和依赖关系的管理交给 Spring 容器,而不是由程序员手动去创建对象…...
JavaScript逆向工程实战:如何精准定位加密参数生成位置
前言:一个令人困惑的调试案例 最近在进行某网站的JavaScript逆向分析时,我遇到了一个有趣的现象:当我尝试定位一个名为m的加密参数(值为MTIwMTE3NDQxODk1NTY1NjkA这样的Base64字符串)时,调试器却带我来到了…...
SSM智能停车场管理系统
🍅点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅 项目视频 SS…...
[定位器]晶艺LA1823,4.5V~100V, 3.5A,替换MP9487,MP9486A,启烨科技
Features 4.5V to 100V Wide Input Range 3.5A Typical Peak Current Limit Integrated 500mΩ low resistance high side power MOS. Constant On Time Control with Constant Switching Frequency. 180μA Low Quiescent Current 150kHz/240kHz/420kHz Swi…...
天元证券|A股大反攻!北证50涨超10%!芯片股大爆发
今日,A股全线走强。 科技成长股领涨,北证50指数飙升逾10%,科创50也大涨超4%,深证成指、上证指数午后也稳步拉升涨逾1%。值得注意的是,上证50指数临近收盘集合竞价的时候直线拉升。近4600只个股上涨,成交稳步…...
利用python从零实现Byte Pair Encoding(BPE):NLP 中的“变形金刚”
BPE:NLP 界的“变形金刚”,从零开始的奇幻之旅 在自然语言处理(NLP)的世界里,有一个古老而神秘的传说,讲述着一种强大的魔法——Byte Pair Encoding(BPE)。它能够将普通的文本“变形…...
最新Web系统全面测试指南
你有没有遇到过这样的情况: 系统上线当天,用户频频报错,运维一脸懵逼,开发说“我本地没问题”? 你明明写了几十个测试用例,结果却还是有 Bug 漏网? Web 系统测试,不只是点点点&#…...