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

基于Jersey+Postgres的RESTful服务及Swing管理GUI功能拓展问询

实现Swing GUI客户端对接REST服务的核心方案指南

看起来你已经把后端的REST服务搭得很稳了,现在就差把Swing界面和服务打通,让运营人员能直观操作数据库。下面是我整理的分步实现要点,都是实际项目里常用的方案:

1. 先搞定HTTP客户端依赖

Swing本身没带REST调用工具,咱们得加个轻量级的HTTP库,我推荐用Apache HttpClient搭配Jackson处理JSON(和你Jersey后端用的序列化工具一致,避免格式问题)。如果是Maven项目,直接在pom.xml加这些依赖:

<!-- Apache HttpClient 处理HTTP请求 -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.14</version>
</dependency>
<!-- Jackson 处理JSON序列化/反序列化 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

如果是手动导包,去官网下载对应的Jar包放进项目lib目录就行。

2. 封装REST调用工具类

为了避免在界面代码里写一堆重复的HTTP请求代码,咱们写个工具类把常用的GET/POST/PUT/DELETE都封装好:

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import com.fasterxml.jackson.databind.ObjectMapper;

public class RestServiceClient {
    // 替换成你实际的REST服务根地址
    private static final String BASE_API_URL = "http://localhost:8080/your-jersey-service/api";
    private static final ObjectMapper jsonMapper = new ObjectMapper();
    private static final HttpClient httpClient = HttpClients.createDefault();

    // GET请求:获取数据列表或单个实体
    public static <T> T get(String endpoint, Class<T> responseType) throws Exception {
        HttpGet request = new HttpGet(BASE_API_URL + endpoint);
        request.setHeader("Accept", "application/json");
        HttpResponse response = httpClient.execute(request);
        return jsonMapper.readValue(response.getEntity().getContent(), responseType);
    }

    // POST请求:新增数据
    public static <T> T post(String endpoint, Object data, Class<T> responseType) throws Exception {
        HttpPost request = new HttpPost(BASE_API_URL + endpoint);
        request.setHeader("Content-Type", "application/json");
        request.setHeader("Accept", "application/json");
        StringEntity jsonEntity = new StringEntity(jsonMapper.writeValueAsString(data));
        request.setEntity(jsonEntity);
        HttpResponse response = httpClient.execute(request);
        return jsonMapper.readValue(response.getEntity().getContent(), responseType);
    }

    // PUT请求:更新数据
    public static <T> T put(String endpoint, Object data, Class<T> responseType) throws Exception {
        HttpPut request = new HttpPut(BASE_API_URL + endpoint);
        request.setHeader("Content-Type", "application/json");
        request.setHeader("Accept", "application/json");
        StringEntity jsonEntity = new StringEntity(jsonMapper.writeValueAsString(data));
        request.setEntity(jsonEntity);
        HttpResponse response = httpClient.execute(request);
        return jsonMapper.readValue(response.getEntity().getContent(), responseType);
    }

    // DELETE请求:删除数据
    public static void delete(String endpoint) throws Exception {
        HttpDelete request = new HttpDelete(BASE_API_URL + endpoint);
        httpClient.execute(request);
    }
}

3. Swing界面与服务的异步交互

重点提醒:绝对不能在Swing的事件调度线程(EDT)里直接调用REST服务,不然界面会直接卡死。必须用SwingWorker做异步处理:

示例:异步加载数据到表格

import javax.swing.*;
import java.util.List;

// 假设你有个实体类叫User,还有对应的表格模型UserTableModel
public class LoadUsersWorker extends SwingWorker<List<User>, Void> {
    private final JTable userTable;
    private final UserTableModel tableModel;

    public LoadUsersWorker(JTable userTable, UserTableModel tableModel) {
        this.userTable = userTable;
        this.tableModel = tableModel;
    }

    @Override
    protected List<User> doInBackground() throws Exception {
        // 后台线程调用REST服务获取数据
        return RestServiceClient.get("/users", List.class);
    }

    @Override
    protected void done() {
        try {
            List<User> users = get();
            tableModel.setUsers(users);
            userTable.setModel(tableModel);
            JOptionPane.showMessageDialog(null, "数据加载完成", "提示", JOptionPane.INFORMATION_MESSAGE);
        } catch (Exception e) {
            // 给用户友好的错误提示
            JOptionPane.showMessageDialog(null, "加载数据失败:" + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }
}

然后在界面的“刷新”按钮点击事件里启动这个Worker:

refreshBtn.addActionListener(e -> new LoadUsersWorker(userTable, tableModel).execute());

示例:新增数据的交互

比如弹出一个新增用户的对话框,用户输入信息后点击保存:

saveUserBtn.addActionListener(e -> {
    // 从输入框获取用户信息,构建实体对象
    User newUser = new User();
    newUser.setUsername(usernameTxt.getText());
    newUser.setEmail(emailTxt.getText());

    // 异步提交数据
    new SwingWorker<User, Void>() {
        @Override
        protected User doInBackground() throws Exception {
            return RestServiceClient.post("/users", newUser, User.class);
        }

        @Override
        protected void done() {
            try {
                User savedUser = get();
                JOptionPane.showMessageDialog(null, "用户新增成功,ID:" + savedUser.getId(), "成功", JOptionPane.INFORMATION_MESSAGE);
                // 刷新表格数据
                new LoadUsersWorker(userTable, tableModel).execute();
                // 关闭对话框
                addUserDialog.dispose();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(null, "新增失败:" + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                ex.printStackTrace();
            }
        }
    }.execute();
});

4. 优化用户体验的小细节

  • 操作过程中可以加个加载提示(比如JProgressBar或者动态标签),让用户知道程序在工作。
  • 对输入做基本校验(比如非空、格式正确),避免无效请求发到后端。
  • 把常用的错误类型(比如网络超时、服务返回错误码)转换成用户能看懂的提示,别直接抛技术术语。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:18:00