You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Swing升级至Java17+Maven后窗口无法正常加载求助

Java Swing项目升级Java17+Maven后界面异常排查

问题现象

原本基于Java8+Ant运行正常的Swing项目,升级为Java17+Maven(Netbeans IDE)后,启动仅显示极小窗口,预期组件全部缺失;手动放大窗口后界面仍异常。

当前Maven依赖(pom.xml)

<dependencies>
     <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.30</version>
    </dependency>

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-dbcp2</artifactId>
        <version>2.9.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>2.11.1</version>
    </dependency>
    <dependency>
        <groupId>commons-net</groupId>
        <artifactId>commons-net</artifactId>
        <version>3.8.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
        <optional>true</optional>
    </dependency>

</dependencies>

原Ant项目依赖说明

原项目使用的库包含mysql驱动、commons-dbcp、commons-pool、commons-net、commons-lang3等类库。

核心启动代码

PrincipalLayout构造方法

public PrincipalLayout() {
    this.service = new ProductService();
    //La base de datos esta vacia
    this.model = new TableModel(service.selectAllProducts());
}

ProductService构造方法

private final InMemoryProductRepository mysqlController;
private List<Product> inMemoryList;
public ProductService(){
    this.mysqlController = new InMemoryProductRepository();
    var optionalProducts = mysqlController.selectAll();
    
    if(optionalProducts.isPresent())
        optionalProducts.get().forEach(p-> this.inMemoryList.add( p));
    if(optionalProducts.isEmpty())
        this.inMemoryList.addAll(Collections.emptyList())
}

Repository的selectAll方法

@Override
public Optional<List<Product>> selectAll() {
    List<Product> products = Collections.emptyList();

    try {
        PreparedStatement preparedStatement = ConnectionJDBC
                .getConnection().prepareStatement(SQL_SELECT.getCommand());
        ResultSet resultSet = preparedStatement.executeQuery();
 
        while (resultSet.next()) {
            var product = new Product(
                    resultSet.getInt("product_id"),
                    resultSet.getString("name"),
                    resultSet.getDouble("price")
            );
            products.add(product);
        }

        ConnectionJDBC.close(resultSet);
        ConnectionJDBC.close(preparedStatement);
        ConnectionJDBC.close(ConnectionJDBC.getConnection());
    } catch (SQLException ex) {
        JOptionPane.showMessageDialog(null, "Ocurrio un error al ejecutar SellectAll", "ERROR", 0);
    }
 
    return Optional.of(products);
}

排查方向

  1. Swing线程违规:Java17对Swing UI线程规范要求更严格,检查是否所有UI初始化代码都在EventQueue.invokeLater()或SwingUtilities.invokeLater()中执行。原Ant项目可能直接在主线程初始化UI,Java17下会导致渲染异常。
  2. 数据库操作阻塞UI线程:PrincipalLayout构造方法直接调用数据库查询,会阻塞UI线程导致窗口无法正常渲染,必须将数据库操作移到后台线程。
  3. 空指针异常隐藏:ProductService中inMemoryList未初始化就调用add/addAll,会抛出空指针但可能被线程异常吞掉,导致UI初始化中断。
  4. 依赖版本兼容:检查Maven依赖是否与原Ant项目版本一致,尤其是commons-dbcp2、mysql驱动是否存在Java17兼容性问题;原项目可能使用commons-dbcp而非dbcp2,两者API存在差异。
  5. 连接池资源泄漏:selectAll中多次调用ConnectionJDBC.getConnection(),可能获取多个连接,且关闭逻辑存在风险(若getConnection()每次返回新实例,最后关闭的不是当前使用的连接)。

代码优化建议

  1. 修复空指针问题:
    在ProductService中初始化集合:

    private List<Product> inMemoryList = new ArrayList<>();
    // 或在构造方法内初始化
    public ProductService(){
        this.mysqlController = new InMemoryProductRepository();
        this.inMemoryList = new ArrayList<>();
        var optionalProducts = mysqlController.selectAll();
        
        optionalProducts.ifPresent(products -> this.inMemoryList.addAll(products));
    }
    
  2. 将数据库操作移到后台线程:
    使用SwingWorker异步加载数据,避免阻塞UI:

    public PrincipalLayout() {
        initComponents(); // 先初始化UI框架
        new SwingWorker<List<Product>, Void>() {
            @Override
            protected List<Product> doInBackground() throws Exception {
                ProductService service = new ProductService();
                return service.selectAllProducts();
            }
    
            @Override
            protected void done() {
                try {
                    List<Product> products = get();
                    model = new TableModel(products);
                    table.setModel(model); // 更新UI组件
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(null, "加载数据失败", "ERROR", JOptionPane.ERROR_MESSAGE);
                }
            }
        }.execute();
    }
    
  3. 修复数据库连接管理:
    使用try-with-resources自动关闭资源,确保连接一致性:

    @Override
    public Optional<List<Product>> selectAll() {
        List<Product> products = new ArrayList<>();
        try (Connection conn = ConnectionJDBC.getConnection();
             PreparedStatement preparedStatement = conn.prepareStatement(SQL_SELECT.getCommand());
             ResultSet resultSet = preparedStatement.executeQuery()) {
    
            while (resultSet.next()) {
                var product = new Product(
                        resultSet.getInt("product_id"),
                        resultSet.getString("name"),
                        resultSet.getDouble("price")
                );
                products.add(product);
            }
        } catch (SQLException ex) {
            JOptionPane.showMessageDialog(null, "执行查询时出错", "ERROR", JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace();
        }
        return Optional.of(products);
    }
    
  4. 确保UI线程安全:
    主方法中强制在EDT线程启动UI:

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new PrincipalLayout().setVisible(true);
        });
    }
    
  5. 对齐依赖版本:
    若原项目使用commons-dbcp而非dbcp2,替换Maven依赖:

    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>
    

内容的提问来源于stack exchange,提问作者Marcos Lopez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 10:25:32