当前位置: 首页 > news >正文

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;

    @Override
    public void init() throws Exception {
        // // 创建Spring上下文初始化器,注册JavaFX核心对象
        ApplicationContextInitializer<GenericApplicationContext> initializer = ac -> {
            // 将JavaFX Application实例注册为Spring Bean
            ac.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 主舞台(相当于主窗口)
     */
    @Override
    public 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停止方法(窗口关闭时调用)
     */
    @Override
    public 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;

    @Autowired
    public 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;
    
    /**
     * 创建工单
     */
    @Transactional
    public WorkOrderVO create(WorkOrderVO vo) {
        WorkOrder entity = vo.toEntity(); 
        WorkOrder saved = workOrderRepository.save(entity); 
        return WorkOrderVO.fromEntity(saved); 
    }
    
    /**
     * 更新工单
     */
    @Transactional
    public 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("工单不存在"));
    }
    
    /**
     * 删除工单
     */
    @Transactional
    public void delete(Long id) {
        workOrderRepository.deleteById(id); 
    }
    
    /**
     * 更新工单进度
     */
    @Transactional
    public 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加载后自动调用
     */
    @FXML
    public void initialize() {
        // 默认加载工单管理视图
        showWorkOrderView();
    }

    /**
     * 显示工单管理视图
     */
    @FXML
    public void showWorkOrderView() {
        try {
            contentPane.getChildren().clear();
            contentPane.getChildren().add(viewConfig.workOrderView());
            updateStatus("工单管理视图已加载");
        } catch (Exception e) {
            updateStatus("加载工单视图失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 退出应用程序
     */
    @FXML
    public 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加载器调用
     */
    @FXML
    public 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);
    }

    /**
     * 创建新工单
     */
    @FXML
    private 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);
        }
    }

    /**
     * 更新工单进度
     */
    @FXML
    private 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;

    /**
     * 获取所有工单
     */
    @GetMapping
    public 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));
    }

    /**
     * 创建工单
     */
    @PostMapping
    public 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中的依赖关系如图:

相关文章:

  • 【JavaScript】面向对象与设计模式
  • 用Java写一个MVCC例子
  • 理解CSS3 的 max/min-content及fit-content等width值
  • 这是一个文章标题
  • 《网络管理》实践环节04:SNMP监控数据采集流程及SNMP协议详细分析
  • 边缘分布的定义与公式详解
  • 探索 OSPF 协议:构建高效网络的基石
  • [蓝桥杯 2024 省 B] 拔河
  • 心有猛虎,细嗅蔷薇
  • Netty之内存池的原理和实战
  • WebStorm中使用live-server插件
  • Ubuntu 安装 MySQL
  • 国产三维皇冠CAD在「工业自动控制系统装置制造」建模教程:千分表指示器
  • vue项目打包里面pubilc里的 tinymce里的js文件问题
  • Linux 驱动中的资源获取与自动管理机制:深入理解与实战
  • iphone各个机型尺寸
  • Java权限修饰符深度解析
  • 【机器学习算法】基于python商品销量数据分析大屏可视化预测系统(完整系统源码+数据库+开发笔记+详细启动教程)✅
  • springboot starter机制,自动装配
  • LangChain-检索系统 (Retrieval)
  • 青海建设信息网站/网站建设公司哪家好?该如何选择
  • 金昌市建设工程质量监督站网站/十大嵌入式培训机构
  • 临泉网站建设/百度的营销推广
  • 企业所得税应纳税所得额怎么算/沈阳百度seo关键词排名优化软件
  • php除了做网站还能做什么/网络推广外包费用
  • ps做的网站保存不了jpg/web个人网站设计代码