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…...
01分数规划
好久没发博客了……浅浅复活一下,讲个冷门些的算法。 算法目的:选出k组ai,bi使得 最大。 算法过程: 不妨考虑二分答案,那么答案的形式便是 的形式,则可通过移项转化为,进一步的,我们可以将…...
网络安全防护技术
边界安全防护——防火墙 控制:在网络连接点上建立一个安全控制点,对进出数据进行限制隔离:将需要保护的网络与不可信任网络进行隔离,隐藏信息并进行安全防护记录:对进出数据进行检查,记录相关信息 防火墙…...
[数据结构]Trie字典树
GPT的介绍 🧠 一句话总结: 字典树是一种专门用来存很多字符串的“超级前缀树”,查找某个字符串或前缀的时候,特别快! ✍️ 举个生活例子(类比): 你想做一个词典(Dictio…...
【WPF】IOC控制反转的应用:弹窗但不互相调用ViewModel
全称:Inversion of Control,控制反转 场景:A页面需要调用B/C页面等,防止直接在VM中新建别的页面实例,使用IOC设计架构; 创建Service,在Service中实现页面的实例创建和定义页面输入输出参数。 在…...
课程分享 | 安全设计原则
讲师介绍 前言 在数字化时代,软件安全已从技术问题升级为关乎企业存亡的战略要务。从SolarWinds供应链攻击到Log4j漏洞风暴,一次次安全事件不断警示我们:传统的边界防护思维已无法应对日益复杂的威胁环境。面对不断演进的攻击手段࿰…...
【数据结构 · 初阶】- 单链表
目录 一.相关指针知识点 二.链表 1.为什么学了顺序表还要学链表 2.优点 三.实现 1.链表的打印 —— 理解链表结构 (2) 物理结构图 2.链表的尾插 —— 入门 错误写法:tail ! NULL 总结: 正确代码物理图解: (2) 尾插整体代码 (思考…...
在Linux系统命令行如何使用deepseek官方API调用AI大模型?
在Linux系统命令行如何调用deepseek官方API调用AI大模型? 书接上文: 同样的开头哈哈哈哈: ”在这个AI技术飞速发展的时代,每一个程序员都应该问问自己:如何将人工智能的强大能力融入到我们熟悉的操作系统中ÿ…...
我开源了一个“宝藏”开源项目
我开源了一个“宝藏”开源项目 - AI需求分析项目 | 适合交作业和学习 🚀 前言 大家好!最近在学习软件工程和大模型应用开发的过程中,我发现许多学生都遇到了需求分析AI的题目。把一份需求文档转化为用户故事、实体关系或数据库设计ÿ…...
SmolDocling:一种超紧凑的视觉语言模型,用于端到端多模态文档转换
paper地址:SmolDocling: An ultra-compact vision-language model for end-to-end multi-modal document conversion Huggingface地址:SmolDocling-256M-preview 代码对应的权重文件:SmolDocling-256M-preview权重文件 一、摘要 以下是文章摘要的总结: SmolDocling 是一…...
理解CSS3 的 max/min-content及fit-content等width值
本文首发在我的个人博客: 理解CSS3 的 max/min-content及fit-content等width值https://www.brandhuang.com/article/1744253362074 width/height 的属性值 fit-content 这是一个 CSS3 属性,用来设置元素的宽度和高度,值为 fit-content&#…...
关键路径任务延误,如何快速调整
快速识别延误原因、优化资源配置、实施任务并行、调整任务优先级是关键路径任务延误后快速调整的有效方式。其中,快速识别延误原因尤为重要,需要项目管理者及时发现影响关键路径任务延误的核心问题,通过系统性的分析,确保延误的具…...
Elasticsearch 全面解析
Elasticsearch 全面解析 前言一、简介核心特性应用场景 二、核心原理与架构设计1. 倒排索引(Inverted Index)2. 分片与副本机制(Sharding & Replication)3. 节点角色与集群管理 三、核心特点1. 灵活的查询语言(Que…...
linux入门四:Linux 编译器
一、C 语言编译器 GCC:开启编程之旅 1.1 GCC 安装:一站式工具链 GCC(GNU Compiler Collection)是 Linux 下最常用的 C/C 编译器,支持多种编程语言。安装命令(适用于 Debian/Ubuntu 系统)&…...
springboot集成springcloud vault读值示例
接上三篇 Vault---机密信息管理工具安装及常用示例 Vault机密管理工具集群配置示例 vault签发根证书、中间证书、ca证书流程记录 项目里打算把所有密码都放到vault里管理,vault提供了springcloud vault用来在springboot里连接vault,启动加载vault里的值放…...
什么是虚拟线程?与普通线程的区别
引言:线程的演进与挑战 在传统的并发编程中,线程是一种非常重要的概念。我们使用线程来实现任务的并发执行,从而提高程序的执行效率。普通线程(如 Thread 类)是一种重量级的线程,每个线程都对应着操作系统…...
edis 主从复制
Redis 主从复制是一种数据同步机制,主节点(Master)将数据复制到一个或多个从节点(Slave),从 而实现数据备份、读写分离和高可用性。 1、解决我们的日常一个单机故障,而衍生出来 主从架构 2、…...
机器视觉+深度学习,让电子零部件表面缺陷检测效率大幅提升
在精密加工的3C电子行业中,一抹0.1毫米的油渍,一粒肉眼难辨的灰尘或将引发整机性能隐患。当制造业迈入微米级品质竞争时代,产品表面看似微不足道的脏污缺陷,正成为制约企业高质量发展的隐形枷锁。分布无规律的污渍斑点、形态各异的…...
Java基础关键_035_Lambda 表达式
目 录 一、引例:TreeSet 排序 1.实现 Comparable 接口 2.比较器 3.匿名内部类 4.Lambda 表达式 5.Lambda 表达式和匿名内部类的区别 二、函数式编程 三、Lambda 表达式的使用 1.无返回值函数式接口 (1)无返回值无参数 (…...
OPEX baota 2024.02.26
OPEX baota 2024.02.26 运维集成软件宝塔2024.02.26作废例子: 最重要的两个地方:上传文件 网站,重启应用服务器(tomcat) 其他很少用的...
若依 前后端部署
后端:直接把代码从gitee上拉去到本地目录 (https://gitee.com/y_project/RuoYi-Vue ) 注意下redis连接时password改auth 后端启动成功 前端:运行前首先确保安装了node环境,随后执行: !!一定要用管理员权限…...
LeetCode算法题(Go语言实现)_37
题目 给你一棵以 root 为根的二叉树,二叉树中的交错路径定义如下: 选择二叉树中 任意 节点和一个方向(左或者右)。 如果前进方向为右,那么移动到当前节点的的右子节点,否则移动到它的左子节点。 改变前进方…...
网络3 子网掩码 划分ip地址
1.根据子网掩码判断主机数 IP地址网络位主机位 核心:将主机位划分为子网位和主机位 疑问:子网位有什么作用 子网掩码:网络位全为1,主机位全为0 主机数2^主机位 -2 2.根据主机和子网判断子网掩码 有一个B类网络145.38.0.0需要划…...
使用 react-three-fiber 快速重构 Three.js 场景⚛️
不明白的知识先放在一边,激发兴趣是第一步,所以不必纠结代码的细节,相信我你很快就会爱上这种感觉!!! 今天,我们将更进一步,将上一篇中vite npm传统 Three.js 原生代码完整 重构为 …...
RT-Thread 屏蔽在线软件包的方法
说明 可能大家对 RT-Thread 的 Kconfig 配置项,Scons 构建有些疑惑,其实 BSP 的 Kconfig 可以自由的配置,目录也可以自由的调整 RT-Thread BSP 默认都有在线软件包的配置项,如果你不需要在线软件包,也可以把这个配置项…...
深入理解Java反射
反射(Reflection)是Java语言的一个强大特性,它允许程序在运行时动态地获取类的信息并操作类或对象的属性、方法和构造器。就是在获取运行时的java字节码文件,通过各种方法去创建对象,反射是Java被视为动态语言的关键特性之一。 反射其实就是…...
Apipost自定义函数深度实战:灵活处理参数值秘籍
在开发过程中,为了更好地处理传递给接口的参数值,解决在调试过程中的数据处理问题,我们经常需要用到函数处理数据。 过去,我们通过预执行脚本来处理数据,先添加脚本,然后将处理后的结果再赋值给请求参数。…...
对重大保险风险测试的算法理解
今天与同事聊到重大保险风险测试,借助下面链接的文章, 谈IFRS 17下的重大保险风险测试 - 知乎 谈一下对下图这个公式的理解。 尤其是当看到下面这段文字的解释时,感觉有些算法上的东西,需要再澄清一些。 首先,上面文…...
如何白嫖Grok3 API? 如何使用Grok3 API调用实例?怎么使用Grok3模型?
前段时间,Grok3(想要体验Grok3的童鞋可以参考本文:Grok 上线角色扮演功能,教你课后作业手到擒来,Grok3使用次数限制?如何使用Grok3? Grok3国内支付手段如何订阅升级Premium - AI is all your need!&#x…...
学习Python的优势体现在哪些方面?
文章目录 前言易于学习和使用应用领域广泛丰富的开源库和社区支持跨平台兼容性职业发展前景好 前言 学习 Python 具有多方面的优势,这使得它成为当今最受欢迎的编程语言之一,以下为你详细介绍。 易于学习和使用 语法简洁易懂:Python 的语法…...
