跳至主要内容

Modernization Tutorial

在 ChatGPT 中打开

本教程讲解了如何通过集成 WebswingConnector 将现有的 Java Swing 应用现代化。您将学习如何使传统的桌面应用程序可通过网络访问,并逐步添加现代网页特性,例如使用 webforJ 组件的基于网络的对话框和交互式表单。

前提条件

在开始本教程之前,请完成 设置和配置 步骤以配置您的 Webswing 服务器和 CORS 设置。

源代码

本教程的完整源代码可在 GitHub 上找到:webforj/webforj-webswing-integration-tutorial

场景

假设您有一个用 Swing 构建的客户管理应用程序,已经投入生产多年。它运行良好,但用户现在期望能够网络访问和现代化界面。与其从头开始重写,不如使用 Webswing 使其立即可通过网络访问,然后逐步添加现代网络功能,如使用 webforJ 组件的基于网络的对话框和表单。

起始点:Swing 应用程序

示例 Swing 应用程序是一个包含典型 CRUD 操作的客户表。像许多企业级 Swing 应用程序一样,它遵循标准模式:

public class Application {
private List<Customer> customers;
private DefaultTableModel model;
private JTable table;

private void createTable() {
String[] columnNames = { "Name", "Company", "Email" };
model = new DefaultTableModel(columnNames, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};

table = new JTable(model);
table.setRowHeight(30);
table.setRowSelectionAllowed(true);

table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
// 处理双击以编辑
}
}
});
}

private void showEditDialog(Customer customer) {
JTextField nameField = new JTextField(customer.getName());
JTextField companyField = new JTextField(customer.getCompany());
JTextField emailField = new JTextField(customer.getEmail());

Object[] fields = {
"Name:", nameField,
"Company:", companyField,
"Email:", emailField
};

int result = JOptionPane.showConfirmDialog(null, fields, "Edit Customer",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
}
}

这个应用程序作为桌面应用程序运行良好,但缺乏网络可访问性。用户必须安装 Java 并在本地运行 JAR 文件。

第一步:使其具备 Webswing 感知

第一步是使 Swing 应用程序能够检测它是否在 Webswing 下运行。这使其能够适应其行为而不破坏桌面兼容性。

检测 Webswing 环境

将 Webswing API 依赖项添加到您的 Swing 项目中:

<dependency>
<groupId>org.webswing</groupId>
<artifactId>webswing-api</artifactId>
<version>25.1</version>
</dependency>

然后修改您的应用程序以检测 Webswing 运行时:

private void initWebswing() {
api = WebswingUtil.getWebswingApi();
isWebswing = api != null;

if (isWebswing) {
setupWebswingListeners();
}
}

此处的关键点是 WebswingUtil.getWebswingApi() 在作为常规桌面应用程序运行时返回 null,允许您保持双模式兼容性。

为网络部署适应行为

有了检测,您现在可以适应应用程序的行为。最重要的变化是用户交互的处理方式:

private void handleDoubleClick(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
if (row >= 0 && row < customers.size()) {
Customer customer = customers.get(row);

if (isWebswing) {
api.sendActionEvent("select-customer", gson.toJson(customer), null);
} else {
showEditDialog(customer);
}
}
}

通过根据 isWebswing 的值分支行为,代码库可以处理两种环境。

第二步:创建 webforJ 包装器

现在 Swing 应用程序可以通过事件进行通信,创建一个 webforJ 应用程序,将 Swing 应用程序嵌入并添加现代网页功能,如基于网页的对话框和表单。

设置连接器

WebswingConnector 组件将您的 Webswing 托管应用程序嵌入到 webforJ 视图中:

@Route("/")
public class CustomerTableView extends Composite<FlexLayout> {
private final FlexLayout self = getBoundComponent();

public CustomerTableView(@Value("${webswing.connector.url}") String webswingUrl) {
WebswingConnector connector = new WebswingConnector(webswingUrl);
connector.setSize("100vw", "100vh");

self.add(connector);
}
}

连接器连接到您的 Webswing 服务器,建立双向通信通道。

处理来自 Swing 的事件

当 Swing 应用程序发送事件(如用户双击行时),连接器接收这些事件:

connector.onAction(event -> {
switch (event.getActionName()) {
case "select-customer":
event.getActionData().ifPresent(data -> {
JsonObject customer = JsonParser.parseString(data).getAsJsonObject();
CustomerForm dialog = new CustomerForm(customer);
self.add(dialog);
dialog.onSave(() -> {
Gson gson = new Gson();
connector.performAction("update-customer", gson.toJson(customer));
});
});
break;
}
});

现在,用户看到的是使用 webforJ 组件构建的现代网页表单,而不是 Swing 对话框。

第三步:双向通信

当通信双向流动时,集成变得强大。webforJ 应用程序可以将更新发送回 Swing 应用程序,使两个用户界面保持同步。

发送更新到 Swing

在使用 webforJ 对话框编辑客户后:

dialog.onSave(() -> {
// 将更新的客户发送回 Swing
connector.performAction("update-customer", gson.toJson(customer));
});

在 Swing 中处理更新

Swing 应用程序监听这些更新并刷新其显示:

private void setupWebswingListeners() {
api.addBrowserActionListener(event -> {
if ("update-customer".equals(event.getActionName())) {
Customer updated = gson.fromJson(event.getData(), Customer.class);
updateCustomer(updated);
}
});
}

架构优势

这种方法相比于完全重写提供了几个优势:

立即网络部署

您的 Swing 应用程序立即变得可通过网络访问,无需代码更改。用户可以通过浏览器访问它,同时您进行增强工作。

渐进增强

首先只替换编辑对话框,然后逐步替换更多组件:

  1. 第一阶段:嵌入整个 Swing 应用程序,只替换编辑对话框
  2. 第二阶段:在嵌入的应用程序周围添加 webforJ 导航和菜单
  3. 第三阶段:用 webforJ 表替换表格,保留 Swing 以处理不可替换的特性
  4. 第四阶段:最终替换所有 Swing 组件

风险缓解

由于原始 Swing 应用程序保持功能,您可以:

  • 如有需要,可以回退到桌面部署
  • 在现有功能旁边测试新功能
  • 逐步迁移用户
  • 保持相同的业务逻辑