扩展组件的概念在使用 Jmix 框架开发中扮演着非常重要的角色。我们将在本文探索什么是扩展组件以及 Jmix Studio 在扩展组件开发和应用程序模块化方面能给开发者带来什么帮助。

Jmix 中的扩展组件只是依赖库的一种稍微高级的说法,其中包含应用程序中可以使用的预编译代码和其他资源。我们使用特定的术语“扩展组件”强调这个库与一般的 Java 库不一样,扩展组件遵循特定的规则并使用一些 Jmix 的核心特性,能自动将提供的功能集成至主应用程序中。

然而最重要的一点是,扩展组件是一个全栈的库,可以包含实体、数据库结构和 UI 界面,能无缝地与主应用程序的数据模型和 UI 集成。因此,仅仅通过在 build.gradle 中添加扩展组件的依赖,就可以在项目中获得一个完整的子系统:数据存储在主程序的数据库中,UI 与主菜单集成。

当然,这并不是说扩展组件一定要是一个复杂的全栈项目。很多扩展组件只提供了一个 UI 功能,或者只提供框架中某些接口的另一种实现,例如 FileStorage。在这种情况下,扩展组件可以使用通用基础设施在 市场 上发布并轻松安装到项目中。

扩展组件开发

Jmix Studio 提供 “Single Module Add-on” 项目模板,可以快速开始扩展组件的开发。这个项目模板包含单一的功能模块和一个 Spring Boot Starter。

当开发一个可重用的扩展组件时,一般需要同时创建一个应用程序,用来演示组件的用法,或许也需要在应用程序中创建一些额外的自动测试用例,这些用例可能很难在组件本身中测试。

Studio 现在提供了一个功能来简化这种模块化系统的开发。在我们进一步了解这个功能之前,我们先看一下目前的开发流程。

一般来说,同时开发扩展组件和使用扩展组件的应用程序需要经常在两个项目之间切换。你需要更改扩展组件的代码,构建然后发布至本地 Maven 仓库。然后切换至应用程序项目,IDE 加载新的组件制件并重新建立索引。现在才能修改应用程序代码,测试并查看组件的改动。

如果同时开发应用程序和多个扩展组件,情况会更加糟糕。很可能,你的某些扩展组件之间会相互依赖,你需要在好几个项目之间切换,运行主程序前要发布多个组件才能确保已经加载需要的改动。如果失败了,所有这些步骤都得重来一遍。

可以看到,开发扩展组件的反馈回路远没有达到我们希望的理想状态,需要太多步骤才能看到最新改动。针对这种情况有一个显而易见的解决办法,那就是将扩展组件和主应用程序作为单一项目中的不同模块。这样做一方面 IDE 可以提供透明的代码重构,任何模块中的改动都是立即可见的。但是另一方面,扩展组件与应用程序的开发、测试、发布等所有的生命周期都变成了紧耦合状态,独立开发扩展组件库也已经变得不可能。

如果我们能在单独的项目中分别开发扩展组件和主应用程序,而仅在需要时将多个项目合并成一个,那不是更好吗?这样可以保持代码库的干净和可管理性,同时在重要的时间节点不会牺牲快速反馈环路,特别是在开发的早期阶段,跨项目改动非常频繁时。

因此,我们升级了 Jmix Studio 的功能,使用 Gradle 的 “复合构建(composite build)” 支持这一场景。

组合项目

Gradle 有几个帮助建立项目结构的功能,其中一个是 composite build。简单说就是在组合项目的 settings.gradle 中仅需使用 includeBuild 指令:

includeBuild '../addon1'
includeBuild '../addon2'
includeBuild '../myapp'

在一个复合构建中,Gradle 将制件(artifacts)之间的依赖替换为子项目之间的直接依赖,因此当扩展组件中有改动时,会直接影响依赖的扩展组件和主应用程序。IntelliJ IDEA 能完美地导入这种项目,支持 Gradle 识别出的依赖。这样一来,组合项目能提供透明的重构,免去了“发布至本地仓库”的麻烦步骤。

Jmix Studio 从 1.2 版开始支持组合项目,进一步提升了开发者的体验。

首先,使用模板能很方便地创建一个空的组合项目。然后可以添加子项目,子项目可以是新建的扩展组件或应用程序、从 VCS 检出的已有项目或者直接添加项目文件夹。

Studio 在 Jmix 工具窗口将组合项目和所有的子项目作为顶级节点展示:

你可以编辑所有子项目的通用属性:只需要在 Studio 询问需要编辑哪些项目时选择 All subprojects

通用属性包括制件仓库的设置和 Jmix 框架的版本。因此可以一次将所有子项目升级至新的 Jmix 版本。

对于大型复合项目,最有用的功能可能是支持在简易的对话框中配置子项目之间的依赖关系:

这里,orders 是一个扩展组件,依赖 staffcustomers 组件。根据在此对话框中所做的修改,Studio 会将依赖添加到子项目的 build.gradle 文件中,并配置扩展组件的 @JmixModule 注解。此外,还可以防止引入循环依赖。在下面的截图中,可以看到该对话框不允许 customers 组件依赖 orders ,因为 orders 已经依赖 customers

当新建项目元素,比如实体或界面时,Studio 会自动在 Jmix 工具窗口中选中当前的项目:

最后需要提及的一点是,Studio 能正确地将扩展组件中的改动热部署到正在运行的应用程序中。因此,如果启动应用程序,然后更改扩展组件提供的 UI 界面,则无需重启即可看到组件中的改动,就好像该界面是主应用程序的源码一样。

总之,可以说 Gradle 的复合构建功能以及 IntelliJ IDEA 和 Jmix Studio 对其的支持,使开发人员可以像开发单一多模块应用程序一样开发大型扩展组件和应用程序的组合项目。同时,开发人员可以随时将扩展组件从组合项目中剥离,作为一个完全独立的项目继续维护。

如何有效地开发 Jmix 扩展组件的更多相关文章

  1. Android开发——构建自定义组件

    Android中,你的应用程序程序与View类组件有着一种固定的联系,例如按钮(Button). 文本框(TextView), 可编辑文本框(EditText), 列表框(ListView), 复选框 ...

  2. easyui基于 layui.laydate日期扩展组件

    本人后端开发码农一个,公司前端忙的一逼,项目使用的是easyui组件,其自带的datebox组件使用起来非常不爽,主要表现在 1.自定义显示格式很麻烦 2.选择年份和月份用户体验也不好 网上有关于和M ...

  3. 手把手教你使用Vue/React/Angular三大框架开发Pagination分页组件

    DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师.官方网站:devui.designNg组件库:ng-devui(欢迎S ...

  4. script标签引入vue方式开发如何写组件

    title: script标签引入vue方式开发如何写组件 date: 2020-05-08 sidebarDepth: 2 tags: vue 组件 script 标签 categories: vu ...

  5. 微信小程序使用weui扩展组件踩坑

    最近在做微信小程序,引入weui的时候踩坑了好久,这里记录一下遇到的问题. 微信官方文档给了两种weui引入方式: 通过 useExtendedLib 扩展库 的方式引入,这种方式引入的组件将不会计入 ...

  6. Vue基础语法-数据绑定、事件处理和扩展组件等知识详解(案例分析,简单易懂,附源码)

    前言: 本篇文章主要讲解了Vue实例对象的创建.常用内置指令的使用.自定义组件的创建.生命周期(钩子函数)等.以及个人的心得体会,汇集成本篇文章,作为自己对Vue基础知识入门级的总结与笔记. 其中介绍 ...

  7. winform快速开发平台 -> 工作流组件(仿GooFlow)

    对于web方向的工作流,一直在用gooflow对于目前我的winform开发平台却没有较好的工作流组件.  针对目前的项目经验告诉我们.一个工作流控件是很必要的. 当然在winform方面的工作流第三 ...

  8. winform快速开发平台 -> 基础组件之分页控件

    一个项目控件主要由及部分的常用组件,当然本次介绍的是通用分页控件. 处理思想:我们在处理分页过程中主要是针对数据库操作. 一般情况主要是传递一些开始位置,当前页数,和数据总页数以及相关关联的业务逻辑. ...

  9. android开发之自定义组件

    android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...

随机推荐

  1. C语言函数调用栈

    C语言函数调用栈 栈溢出(stack overflow)是最常见的二进制漏洞,在介绍栈溢出之前,我们首先需要了解函数调用栈. 函数调用栈是一块连续的用来保存函数运行状态的内存区域,调用函数(calle ...

  2. Codeforces Round #746

    挺喜欢这场题目的 A: 水,不写了 B: Hemose Shopping 嘲讽自己一下啦~真的是caii 题意:一个数列,我们通过交换两个点(两点满足距离大于等于\(x\)),问能否排序成功. 思路: ...

  3. 我熬夜读完这份“高分宝典”,竟4面拿下字节跳动offer

    前言 怎样的契机? 实际上,目前毕业已经两年时间了,在大学时就已经开始关注字节跳动的发展.一开始,我是电气自动化专业的,大二清楚目标之后就转计算机了,大四进了一家小型的互联网公司实习,具体就不说哪家了 ...

  4. springcloud-- Alibaba-nacos--支持的几种服务消费方式

    通过<Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现>一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBal ...

  5. 记一次前端CryptoJS AES解密

    1.背景 业务需求,需要联动多个平台,涉及到各平台的模拟登录. 已知加密前明文且正常登录.(无验证码要求) 某平台验证验证方式为.\login接口POST一串json字符串 { "accou ...

  6. C#和Java,究竟选哪个方向?我只说事实,你自己分析……

    好久没到园子里面逛了,回来看了看,.NET有点式微呀?Java/Spring/Linux--比以前多了很多,为什么?博客园可是.NET的大本营了呀! 好吧,我承认,飞哥也动摇了,去年在ASP.NET的 ...

  7. 阶段性总结 GDOI 2022 PJ

    阶段性总结 GDOI 2022 PJ 比赛经过 Day ? ~ Day -1 半停课集训,补了很多东西,但是之前漏得太多了,结果是还有很多题没改 打了若干场 AtCoder ,承认自己思维的不足,训练 ...

  8. 001 手把手用Git,Git从入门到上传本地项目到Github,看这篇就够了

    安装git 下载Git 下载好后,一路next即可 安装好后,打开Git bash,进行配置 首先配置自己的身份 git config --global user.name "Name&qu ...

  9. Python中的类变量和成员变量

    类变量 定义 在类里面定义,且不位于构造或者成员函数里面,同时没有" self. " 的前缀:或者在类外定义,用 类名.类变量名 来新增加类变量. 使用 两种使用方法: (1)类名 ...

  10. 1.3 操作系统的第三个功能——存储管理功能 -《zobolの操作系统学习札记》

    1.3 操作系统的第三个功能--存储管理功能 作者zobol:关于操作系统概论-存储管理功能,我给出下列问题: 目录 1.3 操作系统的第三个功能--存储管理功能 问1:操作系统的文件管理系统主要是负 ...