从 SWT Browser 迁移到 JxBrowser

article/2025/9/7 12:30:47

多年来,SWT 一直内置一个 Browser 组件。这是一个依赖于操作系统自带的 Web engine 的简单组件。该组件可以很好地显示网页并处理简单的任务,但对于需要跨平台行为一致、更好地控制 Engine、隔离用户数据等更高级需求来说,它显然不够用。

因此,许多开发人员开始寻求像 JxBrowser 这样的替代方案。JxBrowser 拥有更丰富的 API 和跨平台统一的 Browser engine,是内置 Browser 最受欢迎的替代方案。

在本指南中,我们提供了替换 SWT Browser API 中每个方法的代码示例,以及相关 JxBrowser 文档的链接。

本指南主要介绍如何迁移到 JxBrowser。要了解为什么需要迁移,请查看选择 JxBrowser 还是 SWT Browser 博客文章,其中我们解释了这两种解决方案在技术和架构上的差异。

JxBrowser

JxBrowser 是一个商业库,可以将 Chromium 嵌入到 Java 应用程序中。它相比内置的 Browser 组件提供了更多功能,并提供原生支持 SWT 和 Eclipse RCP 应用程序的 Web 视图组件。

在所有操作系统上,JxBrowser 均使用其自身内置的同一版本 Chromium 内核。这确保了在不同平台上的行为和渲染效果始终稳定一致。

作为一款商业软件,JxBrowser 提供不限时的技术支持、Bug 修复服务,以及功能定制请求支持。

内置浏览器与 JxBrowser 的 API 接口范围

内置浏览器与 JxBrowser 的 API 接口范围

SWT 项目的依赖项

将 JxBrowser 添加到项目非常简单,只需将几个 JAR 文件添加到类路径(classpath)即可。例如,在 Windows 上运行的 SWT 应用程序需要以下文件:

  • jxbrowser-{version}.jar。此文件包含大部分 JxBrowser API。
  • jxbrowser-swt-{version}.jar。此文件包含 JxBrowser 的 SWT 组件。
  • jxbrowser-win64-{version}.jar。此文件包含适用于 64 位 Windows 的 Chromium 二进制文件。

您可以从 JxBrowser 8.7.0 版本发布说明下载所需的文件。

如果您使用的是普通的 Maven 或 Gradle,您可以按照常规方式添加 JxBrowser,即从我们的 Maven 仓库添加依赖项。

Eclipse RCP 的依赖项

如果您正在使用 Apache Tycho,那大概已经深有体会——一切都没那么简单。不过别担心,我们已经为您准备了详细的教程。在将 JxBrowser 集成到 Eclipse RCP 应用程序的教程中,您将了解:

  • 如何使用 Maven 在构建时下载 JxBrowser 依赖项。
  • 如何使用 Fragments(片段) 为多个平台分发 Chromium 二进制文件。

迁移

线程安全

与 SWT 中其他 UI 组件一样,Browser 组件只能在 UI 线程中使用。

JxBrowser 是线程安全的:您可以在不同的线程中安全地使用 JxBrowser 对象。但请注意,在 UI 线程中调用 JxBrowser API 时,它的许多方法是同步的。为了避免用户体验问题,我们通常不建议在 UI 线程中调用 JxBrowser。

创建 Browser

在 SWT 中,创建 Browser 非常简单。以下代码片段将 Web 视图组件添加到 parent 并加载网页:

var browser = new Browser(shell, SWT.NONE);
browser.setUrl("https://www.example.com");
...
// 当不再需要 Browser 时,将其释放。
browser.dispose();

在 JxBrowser 中,类似的逻辑如下:

var engine = Engine.newInstance(HARDWARE_ACCELERATED);
var browser = engine.newBrowser();var view = BrowserView.newInstance(shell, browser);
browser.navigation().loadUrl("https://example.com");
...
// 当不再需要 Browser 时,将其关闭。
browser.close();
// 或者关闭 Engine。稍后会详细介绍两者的区别。
engine.close();

如您所见,JxBrowser 的代码更多,但控制力也更强。

现代 Browser 拥有复杂的进程模型、安全特性以及多种渲染 Web 内容的方式。然而,SWT 的 Browser API 并未体现出这种复杂性,因为它最初的设计理念就是简单且不依赖特定 Engine。

而 JxBrowser 则完全基于 Chromium engine,并赋予您更加精细的控制能力。让我们拆解一下前面的代码片段,看看这种控制具体体现在哪些方面。

首先,我们创建一个 Engine 实例,它会启动 Chromium 主进程。您可以将其理解为在计算机上打开 Google Chrome:

var engine = Engine.newInstance(HARDWARE_ACCELERATED);

接下来,我们创建一个新的 Browser。您可以将其视为 Google Chrome 中的一个标签页。与标签页一样,您可以根据需要创建任意数量的 Browser 实例:

var browser = engine.newBrowser();

创建的 Browser 对象已完全可用。您目前无法看到它,但您可以加载网页并从中获取信息:

browser.navigation().loadUrl("https://example.com");

最后,您可以通过添加 SWT 组件 BrowserView 在 UI 中显示 Browser:

var view = BrowserView.newInstance(shell, browser);

我们在文档中详细描述了这一点以及其他架构细节。

关闭 Browser

在 SWT 中,当您不再需要 Browser 时,应该将其释放:

browser.dispose();

在 JxBrowser 中,您也需要关闭 Browser,但您可以选择:关闭单个“标签页”,或者一次性关闭整个 Engine 及所有已创建的 Browser:

// 您可以关闭单个 "标签页"。
browser.close()// 或者,您可以关闭整个 Engine,这将自动关闭其中创建的所有 Browser。
engine.close();

在 SWT 中,您可以接收浏览器关闭的通知,但该通知仅在 JavaScript 通过调用 window.close() 关闭页面时才会触发:

browser.addCloseWindowListener(event -> {// Browser 已被 JavaScript 关闭。
});

而在 JxBrowser 中,无论 Browser 以何种方式关闭,都会触发对应的等效事件:

browser.on(BrowserClosed.class, event -> {// Browser 已被 JavaScript 关闭,// 或通过调用 browser.close() 或 engine.close() 关闭。            
});

导航方法

SWT Browser 中的大多数导航方法在 JxBrowser 中都有一一对应的实现:

SWT
browser.setUrl("https://example.com");
var url = browser.getUrl();browser.reload();
browser.stop();
browser.back();
browser.forward();
var canGoBack = browser.isBackEnabled();
var canGoForward = browser.isForwardEnabled();
JxBrowser
var navigation = browser.navigation();
navigation.loadUrl("https://example.com");
var url = browser.url();navigation.reload();
navigation.stop();
navigation.goBack();
navigation.goForward();
var canGoBack = navigation.canGoBack();
var canGoForward = navigation.canGoForward();

您可以在两种 Browser 中加载包含 POST 负载和附加标头的 URL。在 SWT 中,您可以将数据和标头指定为原始字符串。而在 JxBrowser 中,我们提供了更高级别的 API:

SWT
var url = "https://example.com/login";
var postData = "username=user&password=secret";
var headers = new String[] {"Content-Type: application/x-www-form-urlencoded","Authorization: Bearer xyz1234"
};
browser.setUrl(url, postData, headers);
JxBrowser
var url = "https://example.com/login";
var formData = FormData.newBuilder().addPair(Pair.of("username", "user")).addPair(Pair.of("password", "secret")).build();
var header = HttpHeader.of("Authorization", "Bearer xyz1234");
var params = LoadUrlParams.newBuilder(url).addExtraHeader(header).uploadData(formData).build();
navigation.loadUrl(params);

位置监听器

在 SWT 中,您可以注册一个 LocationListener 来监听 Browser 中加载的位置何时发生变化。在 JxBrowser 中,您可以通过订阅 NavigationFinished 事件来实现这一点:

SWT
browser.addLocationListener(new LocationAdapter() {@Overridepublic void changed(LocationEvent event) {var url = event.location;var isMainFrame = event.top;}
});
JxBrowser
navigation.on(NavigationFinished.class, event -> {var url = event.url();var frame = event.frame();var hasCommitted = event.hasCommitted();var isSameDocument = event.isSameDocument();var isErrorPage = event.isErrorPage();if (isErrorPage) {var error = event.error();}
});

JxBrowser 中共有 9 种细粒度的导航事件。请查看完整列表。

在 SWT 中,LocationListener 还可用于阻止不必要的导航。在 JxBrowser 中,您可以通过注册 StartNavigationCallback 来实现这一点:

SWT
browser.addLocationListener(new LocationAdapter() {@Overridepublic void changing(LocationEvent event) {var url = event.location;if (...) {event.doit = true;} else {event.doit = false;}}
});
JxBrowser
navigation.set(StartNavigationCallback.class, params -> {var url = params.url();var isRedirect = params.isRedirect();var isMainFrame = params.isMainFrame();if (...) {return StartNavigationCallback.Response.start();} else {return StartNavigationCallback.Response.ignore();}
});

进度监听器

在 SWT 中,您可以接收到页面加载进度的事件,尤其是在页面完全加载完成时的通知。

而在 JxBrowser 中,虽然无法查看加载进度,但可以检测页面是否已完全加载,并据此执行操作:

SWT
browser.addProgressListener(new ProgressAdapter() {@Overridepublic void completed(ProgressEvent event) {// 某个位置已完全加载。}
});
JxBrowser
// 检查 HTML 文档是否已完全加载。
browser.navigation().on(FrameDocumentLoadFinished.class, event -> {var frame = event.frame();var isMainFrame = frame.isMain();frame.document().ifPresent(document -> {var element = document.documentElement();});
});

JxBrowser 不提供与 ProgressLister.changed(ProgressEvent) 方法等效的 API。

从 Java 调用 JavaScript

在 SWT 中,您可以通过调用 execute()evaluate() 方法在当前文档中执行 JavaScript 代码。如果可能,evaluate() 方法会自动将返回值转换为 Java 原始类型和 String。这两种方法都是同步执行的:

boolean isSuccessful = browser.execute("document.documentElement");
String zipCode = browser.evaluate("getZipCode()");

在 JxBrowser 中,您可以在任意 Frame 上下文中执行 JavaScript,并且 JxBrowser 会将返回值自动转换为 11 种可用类型 之一:

Element element = frame.executeJavaScript("document.documentElement");
String zipCode = frame.executeJavaScript("getZipCode()");// 也有异步版本:
frame.executeJavaScript("longOperation()", (result) -> {// 非阻塞 JavaScript 调用的结果。
});

在 SWT 中,您可以启用或禁用 JavaScript。在 JxBrowser 中,我们提供了这些方法的直接替代方案:

SWT
browser.setJavascriptEnabled(false);
var isEnabled = browsser.getJavascriptEnabled();
JxBrowser
var settings = browser.settings();
settings.enableJavaScript();
settings.disableJavaScript();var isEnabled = settings.isJavaScriptEnabled();

从 JavaScript 调用 Java

在 SWT 中,若要从 JavaScript 调用 Java 代码,需要注册 BrowserFunction。该函数在被释放前,可在所有网页中访问。其参数类型和返回值将自动转换为相应的 Java 原始类型和 String

// 该函数将在顶部 Frame 和其他两个 Frame 中以 `sayHello()` 的形式提供。
var function = new BrowserFunction(br, "sayHello") {@Overridepublic Object function(Object[] args) {return "Hello from Java!";}
};
...
function.dispose();

在 JxBrowser 中,您可以将任意 Java 对象注入 JavaScript,但这一操作只能在 Frame 就绪时进行。由于在页面重新加载时,注入的对象会自动关闭,因此您无需手动处理。

// 此回调在文档创建后、页面执行自身脚本之前调用。
browser.set(InjectJsCallback.class, params -> {var frame = params.frame();JsObject window = frame.executeJavaScript("window");window.putProperty("sayHello", (JsFunctionCallback) args -> {return "Hello from Java!";});return InjectJsCallback.Response.proceed();
});

加载 HTML

在这两种 Browser 中,您都可以从内存中加载简单的 HTML:

SWT
browser.setText("<html>Hello</html>");
JxBrowser
frame.loadHtml("<html>Hello</html>");

在 JxBrowser 中,loadHtml() 方法是通过从给定的 HTML 加载数据 URL 来实现的,这使得页面大小被限制在约 2 MB。

若要突破这一限制或处理其他高级情况,请查阅我们的加载 HTML 与本地资源指南。

获取页面内容

在 SWT 中,您可以使用 Browser 的 getText() 方法来读取页面的 HTML 内容。在 JxBrowser 中,您需要获取文档的内部或外部 HTML:

SWT
var html = browser.getText();
JxBrowser
frame.document().flatMap(Document::documentElement).ifPresent(element -> {var innerHtml = element.innerHtml();var outerHtml = element.outerHtml();
});

状态栏与页面标题

在两种 Browser 中,您都可以在状态栏发生变化时收到通知:

SWT
browser.addStatusTextListener(event -> {var newStatus = event.text;
});
JxBrowser
browser.on(StatusChanged.class, event -> {var newStatus = event.statusText();
});

您可以用类似的方法跟踪页面标题的变化:

SWT
browser.addTitleListener(event -> {var newTitle = event.title;
});
JxBrowser
browser.on(TitleChanged.class, event -> {var newTitle = event.title();
});

Cookies

在 SWT 中,您可以使用 getCookie() 方法读取现有的 Cookies。在 JxBrowser 中,您可以使用 CookieStore 读取 Cookies:

SWT
String cookie = Browser.getCookie("auth_token", "https://example.com");
JxBrowser
var cookieStore = browser.profile().cookieStore();
for (Cookie cookie : cookieStore.cookies("https://example.com")) {String domain = cookie.domain();Timestamp expiration = cookie.expirationTime();...
}

要创建新的 Cookie,可在 SWT 中使用 setCookie(),在 JxBrowser 中使用 CookieStore.set()

SWT
Browser.setCookie("auth_token=abc123; Path=/;", "https://example.com");
JxBrowser
var cookieStore = browser.profile().cookieStore();
var cookie = Cookie.newBuilder("example.com").name("auth_token").value("abc123").path("/").build();
cookieStore.set(cookie);

同样,您也可以清除 Cookies:

SWT
Browser.clearSessions();
JxBrowser
// 删除特定的 Cookie。
cookieStore.delete(cookie);// 删除所有 Cookie。
cookieStore.deleteAll();

身份验证

在 SWT 中,您需要注册一个 AuthenticationListener 来自动处理服务器的身份验证请求。在 JxBrowser 中,您需要使用 AuthenticateCallback:

SWT
browser.addAuthenticationListener(event -> {var url = event.location;if (...) {event.user = "username";event.password = "password";event.doit = true;} else {event.doit = false;}
});
JxBrowser
var network = browser.profile().network();
network.set(AuthenticateCallback.class, (params, action) -> {var url = params.url();var proxy = params.isProxy();var scheme = params.scheme();var hostPort = params.hostPort();if (...) {action.authenticate("username", "password");} else {action.cancel();}
});

弹出窗口

当网页需要打开新的弹出窗口时,SWT 会向您发送一个事件。根据事件类型,操作系统会为您创建新的 Browser 窗口,或者让应用程序自行创建:

browser.addOpenWindowListener(event -> {if (event.required) {// 您的应用程序需要为弹出窗口创建一个窗口。event.browser = new Browser(shell, SWT.NONE);} else {// 操作系统将创建弹出窗口。}
});

JxBrowser 会自动为新的弹出窗口创建 Browser 对象。您只需在用户界面中显示它或在后台使用即可。默认情况下,JxBrowser 会在新的 Shell 中打开弹出窗口:

// 首先,允许创建弹窗 Browser。
browser.set(CreatePopupCallback.class, e -> {var url = e.targetUrl();var name = e.targetName();if (...) {return CreatePopupCallback.Response.create(); } else {return CreatePopupCallback.Response.suppress();}
});browser.set(OpenPopupCallback.class, e -> {var popupBrowser = e.popupBrowser();var bounds = e.initialBounds();var scaleFactor = e.scaleFactor();// 您可以在此处将 `popupBrowser` 嵌入到 UI 中。return OpenPopupCallback.Response.proceed();
});

JxBrowser 支持以编程方式处理 JavaScript 对话框、文件选择框、颜色选择器等各类对话框。具体用法请参考对话框指南。

结论

从 SWT Browser 迁移到 JxBrowser,本质上就是将 API 调用进行替换,因为大多数方法在 JxBrowser 中都有直接对应的实现。

在本指南中,我们为 SWT Browser 的每个方法提供了 JxBrowser 的直接替代方案,涵盖了整个 Browser API。

尽管在实际项目中迁移工作可能存在一定挑战,但我们相信,这一过程是可以清晰、有序推进的。希望本指南能够成为您使用 JxBrowser 替代 SWT Browser 的良好起点。


http://www.hkcw.cn/article/ACqumsyaNU.shtml

相关文章

编译原理笔记 2025/4/22

基本概念 汇编语言与高级程序设计语言的关系/汇编干嘛的&#xff1a;高级语言与硬件无关&#xff0c;汇编语言的定义与CPU的指令系统直接相关。只要将高级语言编写的程序等价地转换成特定硬件平台所支持的方式来实现&#xff08;汇编程序或机器指令序列&#xff09;&#xff0…

(ICML-2025) RIFLEx:视频扩散Transformer中长度外推的“免费午餐”

RIFLEx&#xff1a;视频扩散Transformer中长度外推的“免费午餐” paper title&#xff1a;RIFLEx: A Free Lunch for Length Extrapolation in Video Diffusion Transformers paper是THU发表在ICML 2025的工作 Code:链接 Abstract 近期视频生成的进展使模型能够合成高质量的分…

树莓派超全系列教程文档--(52)如何启用VNC功能

如何启用VNC功能 使用 VNC 共享屏幕启用 VNC 服务器以图形方式启用 VNC 服务器在命令行上启用 VNC 服务器 连接到 VNC 服务器 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 VNC 共享屏幕 有时&#xff0c;使用设备进行物理操作并不方便。…

TDengine 运维——巡检工具(安装工具)

背景 TDengine 的安装包自带安装脚本&#xff0c;但无法基于集群进行自动化安装部署&#xff0c;本文档旨在说明如何使用安装工具进行 TDengine 的集群式安装部署。 安装工具支持功能 安装方式详细说明单节点安装部署单节点环境安装部署 TDengine集群安装部署集群环境安装部…

Qt Creator调用Python代码

Qt Creator下调用Python代码 在Qt编写的上位机,现在可能经常用到Python相关的代码。本篇记录Qt Creator中调用Python的一种方法。 Python使用的版本为 3.9.10,(安装参考:Python3.9的安装和配置) Qt 使用的版本为5.14.2,(Qt的安装可以参考网上的安装案例:Qt 5.14安装…

政策+技术双轮驱动:MiC建筑如何成为“好房子”建设的破局之道

在建筑行业不断追求创新与可持续发展的今天&#xff0c;模块化集成建筑&#xff08;Modular Integrated Construction&#xff0c;简称MiC&#xff09;正逐渐崭露头角&#xff0c;成为推动行业转型升级的重要力量。近日&#xff0c;全国政协常委、人口资源环境委员会副主任&…

Python Day37

Task&#xff1a; 1.过拟合的判断&#xff1a;测试集和训练集同步打印指标 2.模型的保存和加载 a.仅保存权重 b.保存权重和模型 c.保存全部信息checkpoint&#xff0c;还包含训练状态 3.早停策略 1. 过拟合的判断&#xff1a;测试集和训练集同步打印指标 过拟合是指模型在训…

2025年全国青少年信息素养大赛 scratch图形化编程挑战赛 小低组初赛 内部集训模拟题解析

2025年信息素养大赛初赛scratch模拟题解析 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】 scratch资料 Scratch3.0系列视频课程资料零基础学习scratch3.0【入门教学 免费】零基础学习scratch3.0【视频教程 114节 免费】 历届蓝桥杯scratch国赛真题解析历届蓝桥杯scr…

Linux环境基础开发工具->gcc/g++

引入&#xff1a;gcc/g是什么&#xff1f; 在上篇博客我们知道&#xff0c;vim是一个编辑器&#xff0c;vim负责的是代码的编辑&#xff1b;而gcc/g是一个编译器&#xff0c;负责的就是代码的编译&#xff01;gcc负责C语言代码的编译&#xff0c;而g负责c代码的编译&#xff0…

云原生与DevOps融合实践:加速企业数字化转型的加速器

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;为什么“云原生DevOps”是当下最强组合&#xff1f; 在传统软件交付模式逐步被淘汰的当下&#xff0c;越来…

孙颖莎王曼昱出战WTT美国站女双 拉斯维加斯再携手

2025年WTT美国大满贯将于7月3日至13日在拉斯维加斯奥尔良体育馆及美高梅大酒店会议中心举行。孙颖莎和王曼昱将搭档出战女双正赛。在不久前结束的多哈世乒赛女单决赛中,孙颖莎以4比3的大比分险胜王曼昱,成功卫冕。责任编辑:zx0176

基于51单片机和8X8点阵屏、独立按键的射击消除类小游戏

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、8X8点阵屏2、独立按键3、定时器04、定时器1 四、主函数总结 系列文章目录 前言 使用的是普中A2开发板。 【单片机】STC89C52RC 【频率】12T11.0592MHz 【外设】8X8点阵屏、独立按键 效果查看/操作演示&#x…

ubuntu22.04安装docker

1. 准备工作 更新系统软件包索引 sudo apt update2. 卸载旧版本 Docker&#xff08;可选&#xff09; 清理旧版 Docker 及相关依赖 sudo apt-get remove docker docker-engine docker.io containerd runc3. 设置 Docker 仓库 安装依赖工具 (apt-transport-https, ca-certi…

burpsuit抓包完整示例

1.确保浏览器&#xff08;这里使用的是火狐浏览器&#xff09;和burpsuit配置完整&#xff08;有需要留言&#xff09;&#xff0c;配置完整包括jdk安装&#xff0c;配置环境变量&#xff0c;下载burp,下载并导入证书&#xff0c;ip端口一致&#xff0c;代理能正常打开。 2.注意…

其他 | 边缘端应用的轻量级优化调研

1.调研目标 由于边缘计算场景的性能受限&#xff0c;无法提供与常规服务器相同或略低的环境&#xff0c;因此对我们的上层业务应用有着较高的资源要求。 目前我们的应用程序基于 Oracle JDK&#xff08;开发者端&#xff09;与 OpenJDK&#xff08;生产环境&#xff09;进行开…

Shell 脚本常用命令笔记

一、系统配置命令 1. 主机名设置 文件方式 修改文件&#xff1a;vim /etc/hostname&#xff0c;写入新主机名&#xff08;如czg.easylee.org&#xff09;。生效方式&#xff1a;需重新打开 Shell 或重启系统。 命令方式 即时生效命令&#xff1a;hostnamectl set-hostname 新…

不规则瀑布流布局拖拽重排序

因为业务&#xff0c;所以需要用flutter去实现一种不规则图形的瀑布流&#xff0c;但是同时需要支持拖拽并重新排序。效果类似如下。 查询过现有的插件&#xff0c;要么是仅支持同样大小的组件进行排序&#xff0c;要么就是动画效果不是很满意&#xff0c;有点死板&#xff0c;…

线程de安全性备忘

文章仅供学习参考 线程安全的本质定义 public class Counter {private int value 0; // 共享资源// 线程安全方法public synchronized void increment() {value; // 原子操作} }原子性&#xff08;Atomicity&#xff09;&#xff1a;操作不可分割&#xff08;如 synchroniz…

进行性核上性麻痹健康护理全指南:从症状管理到生活照护

进行性核上性麻痹&#xff08;PSP&#xff09;是一种罕见的神经退行性疾病&#xff0c;主要影响运动、平衡及眼球运动功能&#xff0c;常表现为步态不稳、吞咽困难、眼球上视受限、情绪改变等。由于目前尚无根治方法&#xff0c;科学的健康护理对延缓病情进展、提升患者生活质量…

[智能算法]蚁群算法原理与TSP问题示例

目录 ​编辑 一、生物行为启发的智能优化算法 1.1 自然界的群体智能现象 1.2 人工蚁群算法核心思想 二、算法在组合优化中的应用演进 2.1 经典TSP问题建模 2.2 算法流程优化 三、TSP问题实战:Python实现与可视化 3.1 算法核心类设计 3.2 参数敏感性实验 3.3 可视化…