飞道的博客

通过debug深度解析xJavaFxTool的源码

331人阅读  评论(0)

背景

       在上一篇的博客JavaFX爱好者看过来,这款工具值得拥有中,简单介绍了一款JavaFx开发框架xJavaFxTool。本次将采用debug的方式对xJavaFxTool进行调试,深度讲解重点模块的代码设计实现。希望通过本文的讲解,能够让您对xJavaFxTool有更深入的了解和认识。

 一、项目主体结构

        在这里再次重复一遍工程项目的主体结构,遵循MVC三层架构,在JavaFx中也是有相应的应用的,视图层采用Fxml来进行展示,控制层有对应的Contoller,每个视图层对象都会对应一个Controller,模型层对象这里采用了多个JavaBean和业务实体来组成,共同完成相应的逻辑功能封装。

xJavaFxTool
├─ images	项目截图
├─ pom.xml	maven配置文件
├─ README.md	说明文件
├─ src
│  ├─ main
│  │  ├─ java
│  │  │  └─ com
│  │  │   └─ xwintop
│  │  │    └─ xJavaFxTool
│  │  │     ├─ common	第三方工具类
│  │  │     ├─ controller	javafx控制层
│  │  │     │  └─ index	首页控制层
│  │  │     ├─ model	基础bean类层
│  │  │     ├─ services	工具服务层
│  │  │     │  └─ index	首页工具服务层
│  │  │     ├─ utils	系统工具类
│  │  │     └─ view	javafx视图层
│  │  │        └─ index	首页工具视图层
│  │  └─ resources
│  │   ├─ com
│  │   │  └─ xwintop
│  │   │   └─ xJavaFxTool
│  │   │    └─ fxmlView     .fxml文件
│  │   ├─ config	配置文件
│  │   │  └─ toolFxmlLoaderConfiguration.xml	系统菜单加载配置文件
│  │   ├─ css	样式资源
│  │   ├─ images	图片资源
│  │   ├─ locale	国际化
│  │   ├─ banner.txt	启动banner图片
│  │   └─ logback.xml	logback日志配置文件
│  └─ test  测试类
│   ├─ java
│   └─ resources
 

二、Main.java 程序入口


  
  1. public static void main (String[] args) {
  2. XJavaFxSystemUtil.initSystemLocal(); //初始化本地语言
  3. XJavaFxSystemUtil.addJarByLibs(); //添加外部jar包
  4. SplashScreen splashScreen = new SplashScreen() {
  5. @Override
  6. public String getImagePath () {
  7. return "/images/javafx.png";
  8. }
  9. };
  10. launch(Main.class, IndexView.class, splashScreen, args);
  11. }

1、本地语言设置 

      下面通过Debug来看看在这短短的几行代码中会包含那些操作。第一步需要进行本地语言设置,通过调用InitSystemLocal方法来实现。

 2、加载外置的插件jar包


  
  1. /**
  2. * @Title: addJarByLibs
  3. * @Description: 添加libs中jar包到系统中
  4. */
  5. public static void addJarByLibs () {
  6. PluginManager.getInstance().loadLocalPlugins();
  7. try {
  8. // 系统类库路径
  9. File libPath = new File( "libs/");
  10. // 获取所有的.jar和.zip文件
  11. File[] jarFiles = libPath.listFiles(
  12. (dir, name) -> name.endsWith( ".jar")
  13. );
  14. if (jarFiles != null) {
  15. for (File file : jarFiles) {
  16. if (!PluginManageService.isPluginEnabled(file.getName())) {
  17. continue;
  18. }
  19. addJarClass(file);
  20. }
  21. }
  22. } catch (Exception e) {
  23. log.error( "添加libs中jar包到系统中异常:", e);
  24. }
  25. }

      这里需要注意的是,为了方便集中统一管理jar包,将外置的可运行的jar都放在libs目录下面,应用程序启动后在固定目录下读取指定jar,通过反射即可完成插件的调用。这也是该框架的一个亮点,在开发时大大减少了工作量,也降低了代码的复杂度。

       通过上述代码可以看到,通过配置的插件json配置,插件读取器会自动将数据解析并绑定到相应的数据集合中。下图是解析出来的插件json文件。


  
  1. private void addOrUpdatePlugin (PluginJarInfo pluginJarInfo, Consumer<PluginJarInfo> ifExists) {
  2. PluginJarInfo exists = getPlugin(pluginJarInfo.getJarName());
  3. if (exists == null) {
  4. this.pluginList.add(pluginJarInfo);
  5. } else {
  6. ifExists.accept(exists);
  7. }
  8. }

       加载已下载插件,并通过反射机制进行调用,核心代码如下:

      至此主程序的驱动入口函数调试完成,最后两行代码是指定程序的启动窗口。关键代码如下:

launch(Main.class, IndexView.class, splashScreen, args);

      IndexView是应用程序的入口窗口。splashScreen定义了启动页面,同时在启动页面中嵌入了一张本地图片。

 三、IndexView解析

       通常来说,一个IndexView包含了三个文件,一个是IndexView.java,在这个文件中绑定了相对应的页面配置fxml,controller是页面视图对象上所有操作逻辑的处理对象。核心的功能也是放在Controller对象中。


  
  1. @Scope("prototype")
  2. @FXMLView(value = "/com/xwintop/xJavaFxTool/fxmlView/Index.fxml", bundle = "locale.Menu")
  3. public class IndexView extends AbstractFxmlView {
  4. public IndexView () throws Exception {
  5. //反射修改默认语言
  6. ResourceBundle bundle = ResourceBundle.getBundle( this.getResourceBundle().get().getBaseBundleName(), Config.defaultLocale);
  7. FieldUtils.writeField( this, "bundle",Optional.ofNullable(bundle), true);
  8. GUIState.getStage().setTitle(bundle.getString( "Title")); //修改标题国际化
  9. }
  10. @Override
  11. public Parent getView () {
  12. JFXDecorator decorator = JavaFxViewUtil.getJFXDecorator(GUIState.getStage(),GUIState.getStage().getTitle() + Config.xJavaFxToolVersions, "/images/icon.jpg", super.getView());
  13. decorator.setOnCloseButtonAction(() -> {
  14. if (AlertUtil.showConfirmAlert( "确定要退出吗?")) {
  15. System.exit( 0);
  16. }
  17. });
  18. return decorator;
  19. }
  20. }

       下面是通过场景编辑器打开Index.Fxml页面对象,可以看到这里的布局选择器采用的是:AnchorPane、BorderPane,中间采用的是TabPane,通过Tab页来切换功能。

 在这里主要完成页面上相关菜单的加载和展示。


  
  1. private void initView () {
  2. menuMap.put( "toolsMenu", toolsMenu);
  3. menuMap.put( "moreToolsMenu", moreToolsMenu);
  4. File libPath = new File( "libs/");
  5. // 获取所有的.jar和.zip文件
  6. File[] jarFiles = libPath.listFiles((dir, name) -> name.endsWith( ".jar"));
  7. if (jarFiles != null) {
  8. for (File jarFile : jarFiles) {
  9. if (!PluginManageService.isPluginEnabled(jarFile.getName())) {
  10. continue;
  11. }
  12. try {
  13. this.addToolMenu(jarFile);
  14. } catch (Exception e) {
  15. log.error( "加载工具出错:", e);
  16. }
  17. }
  18. }
  19. }

      通过以上的方法可以生成相应的菜单列表供调用。在默认的tab页面,前面可以看到有一个默认的记事本的页面。


  
  1. public void addNodepadAction (ActionEvent event) {
  2. TextArea notepad = new TextArea();
  3. notepad.setFocusTraversable( true);
  4. if (indexController.getSingleWindowBootCheckBox().isSelected()) {
  5. JavaFxViewUtil.getNewStage(indexController.getBundle().getString( "addNodepad"), null, notepad);
  6. } else {
  7. Tab tab = new Tab(indexController.getBundle().getString( "addNodepad"));
  8. tab.setContent(notepad);
  9. indexController.getTabPaneMain().getTabs().add(tab);
  10. if (event != null) {
  11. indexController.getTabPaneMain().getSelectionModel().select(tab);
  12. }
  13. }
  14. }

      窗口的默认设置方法和参数可以参考以下的配置。


  
  1. /**
  2. * 获取新窗口
  3. **/
  4. public static Stage getNewStage (String title, String iconUrl, Parent root) {
  5. double[] screenSize = JavaFxSystemUtil.getScreenSizeByScale( 0.74, 0.8);
  6. Stage newStage = getNewStageNull(title, iconUrl, root, screenSize[ 0], screenSize[ 1], true, true, true);
  7. newStage.initModality(Modality.NONE);
  8. //newStage.setMaximized(false);
  9. newStage.show();
  10. return newStage;
  11. }

四、总结

       以上就是本文的主要内容,本文主要通过对代码进行debug的方式进行深入调试,详细讲解了在启动过程中,各业务逻辑模块是怎么工作的,插件的读取到菜单的生成,最重要的核心技术应该是用过JAVA的反射技术来实现动态注册及调用。心动不如行动,喜欢的朋友可以学习起来,给自己充电加油。


转载:https://blog.csdn.net/yelangkingwuzuhu/article/details/128467278
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场