Springboot整合JAVAFX

Springboot整合JAVAFX

实体与VO设计

pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
://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">
    >4.0.0>

    >com.elitedatai>
    >javafxTest>
    >1.0>

    >
        >org.springframework.boot>
        >spring-boot-starter-parent>
        >3.3.2>
        > <!-- lookup parent from repository -->
    

    >
        >17>
        >17>
        >21>
        >UTF-8>
    >

    >

        >
            >org.springframework.boot>
            >spring-boot-starter-web>
        >
        <!-- Spring Boot Starter -->
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
            org.postgresql
            postgresql
            runtime
        
        
        
            org.openjfx
            javafx-controls
            ${javafx.version}
        
        
            org.openjfx
            javafx-fxml
            ${javafx.version}
        

        <!-- Lombok -->
        
            org.projectlombok
            lombok
            true
        
    >

    >
        >
            >
                >org.springframework.boot>
                >spring-boot-maven-plugin>
                >
                    >
                        >
                            >org.projectlombok>
                            >lombok>
                        >
                    >
                >
            >


            <!-- JavaFX Maven Plugin -->
            
                org.openjfx
                javafx-maven-plugin
                0.0.8
                
                    com.elitedatai.MainApp
                
            
        >
    >


>

实体类设计:

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:






<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:






<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中的依赖关系如图:

你可能感兴趣的:(Spring,JAVA,中间件,spring,boot,后端,java)