Skip to content

Commit 554b1fd

Browse files
committed
newui: 修复无法加载 HTML 插件的问题
1 parent cfad017 commit 554b1fd

5 files changed

Lines changed: 92 additions & 35 deletions

File tree

src/main/java/com/xwintop/xJavaFxTool/model/PluginJarInfo.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package com.xwintop.xJavaFxTool.model;
22

33
import com.alibaba.fastjson.annotation.JSONField;
4-
import java.io.File;
54
import lombok.Data;
65
import lombok.NoArgsConstructor;
76

7+
import java.io.File;
8+
89
/**
910
* 插件信息
1011
*
@@ -45,6 +46,8 @@ public class PluginJarInfo {
4546

4647
private String fxmlPath; // FXML 资源路径
4748

49+
private String pagePath; // 网页资源路径
50+
4851
private String iconPath; // 图标资源路径(可选)
4952

5053
private String bundleName; // 配置资源路径

src/main/java/com/xwintop/xJavaFxTool/newui/NewLauncherService.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package com.xwintop.xJavaFxTool.newui;
22

3+
import com.xwintop.xJavaFxTool.AppException;
34
import com.xwintop.xJavaFxTool.model.PluginJarInfo;
45
import com.xwintop.xJavaFxTool.plugin.PluginLoader;
5-
import java.util.HashMap;
6-
import java.util.Map;
7-
import java.util.Map.Entry;
86
import javafx.scene.control.Tab;
97
import javafx.scene.control.TabPane;
108
import lombok.extern.slf4j.Slf4j;
119

10+
import java.util.HashMap;
11+
import java.util.Map;
12+
import java.util.Map.Entry;
13+
1214
/**
1315
* 新界面中负责与插件操作相关的逻辑
1416
*/
@@ -55,7 +57,17 @@ public void loadPlugin(PluginJarInfo pluginJarInfo) {
5557
}
5658
}
5759

58-
Tab tab = PluginLoader.loadIsolatedPluginAsTab(pluginJarInfo, tabPane);
60+
Tab tab;
61+
String controllerType = pluginJarInfo.getControllerType();
62+
63+
if (controllerType.equals("Node")) {
64+
tab = PluginLoader.loadIsolatedPluginAsTab(pluginJarInfo, tabPane);
65+
} else if (controllerType.equals("WebView")) {
66+
tab = PluginLoader.loadWebViewAsTab(pluginJarInfo, tabPane);
67+
} else {
68+
throw new AppException("找不到 controllerType=" + controllerType + " 的加载方式");
69+
}
70+
5971
if (tab != null) {
6072
tab.setOnClosed(event -> this.jarInfoMap.remove(tab));
6173
jarInfoMap.put(tab, pluginJarInfo);

src/main/java/com/xwintop/xJavaFxTool/plugin/PluginContainer.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,59 @@
44
import com.xwintop.xJavaFxTool.model.PluginJarInfo;
55
import com.xwintop.xJavaFxTool.utils.Config;
66
import com.xwintop.xcore.javafx.dialog.FxAlerts;
7+
import javafx.fxml.FXMLLoader;
8+
import org.apache.commons.lang3.StringUtils;
9+
710
import java.io.IOException;
811
import java.net.URL;
912
import java.util.ResourceBundle;
10-
import javafx.fxml.FXMLLoader;
11-
import org.apache.commons.lang3.StringUtils;
1213

1314
/**
1415
* 插件运行容器,在单独的 ClassLoader 中运行插件,防止不同插件依赖库冲突
1516
*/
1617
public class PluginContainer {
1718

18-
private final ClassLoader parentClassLoader;
19-
20-
private PluginClassLoader pluginClassLoader;
19+
private final PluginClassLoader pluginClassLoader;
2120

2221
private final PluginJarInfo pluginJarInfo;
2322

23+
public PluginContainer(PluginJarInfo pluginJarInfo) {
24+
this(ClassLoader.getSystemClassLoader(), pluginJarInfo);
25+
}
26+
2427
public PluginContainer(ClassLoader parentClassLoader, PluginJarInfo pluginJarInfo) {
25-
this.parentClassLoader = parentClassLoader;
2628
this.pluginJarInfo = pluginJarInfo;
29+
this.pluginClassLoader = new PluginClassLoader(parentClassLoader, pluginJarInfo.getFile());
30+
}
31+
32+
public <T> T createInstance(Class<T> type) {
33+
try {
34+
return type.newInstance();
35+
} catch (InstantiationException | IllegalAccessException e) {
36+
throw new AppException(e);
37+
}
2738
}
2839

2940
public PluginJarInfo getPluginJarInfo() {
3041
return pluginJarInfo;
3142
}
3243

44+
public URL getResource(String path) {
45+
// 必须去掉前缀的 "/" 才能正确读取
46+
return this.pluginClassLoader.getResource(StringUtils.removeStart(path, "/"));
47+
}
48+
3349
/**
3450
* 从 ClassLoader 中创建 FXMLLoader 对象
3551
*/
3652
public FXMLLoader createFXMLLoader() {
3753
try {
38-
pluginClassLoader = new PluginClassLoader(parentClassLoader, pluginJarInfo.getFile());
3954
FXMLLoader pluginFxmlLoader = (FXMLLoader)
4055
pluginClassLoader.loadClass("javafx.fxml.FXMLLoader").newInstance();
4156

4257
pluginFxmlLoader.setClassLoader(pluginClassLoader);
4358

44-
// 必须去掉前缀的 "/" 才能正确读取
45-
String fxmlPathFixed = StringUtils.removeStart(pluginJarInfo.getFxmlPath(), "/");
46-
47-
URL resource = pluginClassLoader.getResource(fxmlPathFixed);
59+
URL resource = getResource(pluginJarInfo.getFxmlPath());
4860
if (resource == null) {
4961
FxAlerts.error("加载失败", "无法在插件 " + pluginJarInfo.getFile().getName() +
5062
" 内找到所需资源 " + pluginJarInfo.getFxmlPath());

src/main/java/com/xwintop/xJavaFxTool/plugin/PluginLoader.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@
44
import com.xwintop.xJavaFxTool.utils.Config;
55
import com.xwintop.xcore.javafx.dialog.FxAlerts;
66
import com.xwintop.xcore.util.javafx.JavaFxViewUtil;
7-
import java.lang.ref.WeakReference;
8-
import java.net.URL;
9-
import java.util.ResourceBundle;
107
import javafx.fxml.FXMLLoader;
118
import javafx.scene.Node;
129
import javafx.scene.control.Tab;
1310
import javafx.scene.control.TabPane;
1411
import javafx.scene.image.Image;
1512
import javafx.scene.image.ImageView;
13+
import javafx.scene.web.WebEngine;
14+
import javafx.scene.web.WebView;
1615
import lombok.extern.slf4j.Slf4j;
1716
import org.apache.commons.lang3.StringUtils;
1817

18+
import java.lang.ref.WeakReference;
19+
import java.net.URL;
20+
import java.util.ResourceBundle;
21+
1922
@Slf4j
2023
public class PluginLoader {
2124

@@ -133,4 +136,23 @@ public static Tab loadIsolatedPluginAsTab(PluginJarInfo plugin, TabPane tabPane)
133136
return null;
134137
}
135138

139+
public static Tab loadWebViewAsTab(PluginJarInfo plugin, TabPane tabPane) {
140+
PluginContainer pluginContainer = new PluginContainer(plugin);
141+
WebView browser = pluginContainer.createInstance(WebView.class);
142+
WebEngine webEngine = browser.getEngine();
143+
String url = plugin.getPagePath();
144+
String title = plugin.getTitle();
145+
146+
if (url.startsWith("http")) {
147+
webEngine.load(url);
148+
} else {
149+
webEngine.load(pluginContainer.getResource(url).toExternalForm());
150+
}
151+
152+
Tab tab = new Tab(title);
153+
tab.setContent(browser);
154+
tabPane.getTabs().add(tab);
155+
tabPane.getSelectionModel().select(tab);
156+
return tab;
157+
}
136158
}

src/main/java/com/xwintop/xJavaFxTool/plugin/PluginParser.java

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package com.xwintop.xJavaFxTool.plugin;
22

3-
import static org.apache.commons.lang.StringUtils.defaultString;
4-
53
import com.xwintop.xJavaFxTool.AppException;
64
import com.xwintop.xJavaFxTool.model.PluginJarInfo;
75
import com.xwintop.xJavaFxTool.utils.Config;
6+
import lombok.extern.slf4j.Slf4j;
7+
import org.apache.commons.lang3.StringUtils;
8+
import org.dom4j.Document;
9+
import org.dom4j.DocumentException;
10+
import org.dom4j.Element;
11+
import org.dom4j.io.SAXReader;
12+
813
import java.io.File;
914
import java.io.IOException;
1015
import java.io.InputStream;
@@ -15,12 +20,8 @@
1520
import java.util.jar.JarEntry;
1621
import java.util.jar.JarFile;
1722
import java.util.stream.Collectors;
18-
import lombok.extern.slf4j.Slf4j;
19-
import org.apache.commons.lang3.StringUtils;
20-
import org.dom4j.Document;
21-
import org.dom4j.DocumentException;
22-
import org.dom4j.Element;
23-
import org.dom4j.io.SAXReader;
23+
24+
import static org.apache.commons.lang.StringUtils.defaultString;
2425

2526
/**
2627
* 用来解析插件文件中的 toolFxmlLoaderConfiguration.xml
@@ -64,31 +65,38 @@ public static void parse(File pluginFile, PluginJarInfo pluginJarInfo, ClassLoad
6465
}
6566

6667
String resourceBundleName = getChildNodeText(pluginElement, "resourceBundleName");
67-
ClassLoader tmpClassLoader = classLoader == null ? new PluginClassLoader(pluginFile) : classLoader;
68-
ResourceBundle pluginResourceBundle =
69-
ResourceBundle.getBundle(resourceBundleName, Config.defaultLocale, tmpClassLoader);
70-
68+
String title = getTitleFromResourceBundle(pluginFile, classLoader, pluginElement, resourceBundleName);
7169
String menuId = getChildNodeText(pluginElement, "menuParentId");
7270
String url = getChildNodeText(pluginElement, "url");
7371
String controllerType = getChildNodeText(pluginElement, "controllerType");
74-
String title = pluginResourceBundle.getString(
75-
defaultString(getChildNodeText(pluginElement, "title"), "Title")
76-
);
7772
String menuTitle = menuTitles.get(menuId);
7873

7974
pluginJarInfo.setMenuParentTitle(menuTitle);
8075
pluginJarInfo.setBundleName(resourceBundleName);
81-
pluginJarInfo.setFxmlPath(url);
8276
pluginJarInfo.setControllerType(controllerType);
8377
pluginJarInfo.setTitle(title);
8478

79+
if (controllerType.equals("Node")) {
80+
pluginJarInfo.setFxmlPath(url);
81+
} else if (controllerType.equals("WebView")) {
82+
pluginJarInfo.setPagePath(url);
83+
}
84+
8585
pluginJarInfo.setName(StringUtils.defaultString(pluginJarInfo.getName(), title));
8686

8787
} catch (IOException | DocumentException e) {
8888
throw new AppException(e);
8989
}
9090
}
9191

92+
private static String getTitleFromResourceBundle(
93+
File pluginFile, ClassLoader classLoader, Element pluginElement, String bundleName
94+
) {
95+
String titleResourceBundleKey = getChildNodeText(pluginElement, "title");
96+
ClassLoader tmpClassLoader = classLoader == null ? new PluginClassLoader(pluginFile) : classLoader;
97+
ResourceBundle resourceBundle = ResourceBundle.getBundle(bundleName, Config.defaultLocale, tmpClassLoader);
98+
return resourceBundle.getString(defaultString(titleResourceBundleKey, "Title")); }
99+
92100
private static String getChildNodeText(Element element, String childNode) {
93101
return element.selectSingleNode("child::" + childNode).getText();
94102
}

0 commit comments

Comments
 (0)