如何有效地开发 Jmix 扩展组件
扩展组件的概念在使用 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 是一个扩展组件,依赖 staff 和 customers 组件。根据在此对话框中所做的修改,Studio 会将依赖添加到子项目的 build.gradle 文件中,并配置扩展组件的 @JmixModule 注解。此外,还可以防止引入循环依赖。在下面的截图中,可以看到该对话框不允许 customers 组件依赖 orders ,因为 orders 已经依赖 customers:

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

最后需要提及的一点是,Studio 能正确地将扩展组件中的改动热部署到正在运行的应用程序中。因此,如果启动应用程序,然后更改扩展组件提供的 UI 界面,则无需重启即可看到组件中的改动,就好像该界面是主应用程序的源码一样。
总之,可以说 Gradle 的复合构建功能以及 IntelliJ IDEA 和 Jmix Studio 对其的支持,使开发人员可以像开发单一多模块应用程序一样开发大型扩展组件和应用程序的组合项目。同时,开发人员可以随时将扩展组件从组合项目中剥离,作为一个完全独立的项目继续维护。
如何有效地开发 Jmix 扩展组件的更多相关文章
- Android开发——构建自定义组件
Android中,你的应用程序程序与View类组件有着一种固定的联系,例如按钮(Button). 文本框(TextView), 可编辑文本框(EditText), 列表框(ListView), 复选框 ...
- easyui基于 layui.laydate日期扩展组件
本人后端开发码农一个,公司前端忙的一逼,项目使用的是easyui组件,其自带的datebox组件使用起来非常不爽,主要表现在 1.自定义显示格式很麻烦 2.选择年份和月份用户体验也不好 网上有关于和M ...
- 手把手教你使用Vue/React/Angular三大框架开发Pagination分页组件
DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师.官方网站:devui.designNg组件库:ng-devui(欢迎S ...
- script标签引入vue方式开发如何写组件
title: script标签引入vue方式开发如何写组件 date: 2020-05-08 sidebarDepth: 2 tags: vue 组件 script 标签 categories: vu ...
- 微信小程序使用weui扩展组件踩坑
最近在做微信小程序,引入weui的时候踩坑了好久,这里记录一下遇到的问题. 微信官方文档给了两种weui引入方式: 通过 useExtendedLib 扩展库 的方式引入,这种方式引入的组件将不会计入 ...
- Vue基础语法-数据绑定、事件处理和扩展组件等知识详解(案例分析,简单易懂,附源码)
前言: 本篇文章主要讲解了Vue实例对象的创建.常用内置指令的使用.自定义组件的创建.生命周期(钩子函数)等.以及个人的心得体会,汇集成本篇文章,作为自己对Vue基础知识入门级的总结与笔记. 其中介绍 ...
- winform快速开发平台 -> 工作流组件(仿GooFlow)
对于web方向的工作流,一直在用gooflow对于目前我的winform开发平台却没有较好的工作流组件. 针对目前的项目经验告诉我们.一个工作流控件是很必要的. 当然在winform方面的工作流第三 ...
- winform快速开发平台 -> 基础组件之分页控件
一个项目控件主要由及部分的常用组件,当然本次介绍的是通用分页控件. 处理思想:我们在处理分页过程中主要是针对数据库操作. 一般情况主要是传递一些开始位置,当前页数,和数据总页数以及相关关联的业务逻辑. ...
- android开发之自定义组件
android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...
随机推荐
- 用c++语言socket库函数实现服务端客户端聊天室
客户端 /* * 程序名:client.cpp,此程序用于演示socket的客户端 * 作者:C语言技术网(www.freecplus.net) 日期:20190525 */ #include < ...
- Spring Boot下Spring Batch入门实例
一.About Spring Batch是什么能干什么,网上一搜就有,但是就是没有入门实例,能找到的例子也都是2.0的,看文档都是英文无从下手~~~,使用当前最新的版本整合网络上找到的例子. 关于基础 ...
- 101_Power Pivot DAX 累计至今,历史累计至今
焦棚子的文章目录 一.背景 DAX中已经有诸如YTD,QTD,MTD时间智能函数.用起来也比较方便. 但很多时候需要看历史累计至今的数据,需要自己根据实际情况写dax. 今天抛砖引玉,写一个示例. 二 ...
- .NET Core中JWT+Auth2.0实现SSO,附完整源码(.NET6)
一.简介 单点登录(SingleSignOn,SSO) 指的是在多个应用系统中,只需登录一次,就可以访问其他相互信任的应用系统. JWT Json Web Token,这里不详细描述,简单说是一种认证 ...
- 【Java面试】说说你对Spring MVC的理解
一个工作了7年的粉丝,他说在面试之前,Spring这块的内容准备得很充分. 而且各种面试题也刷了,结果在面试的时候,面试官问:"说说你对Spring MVC的理解". 这个问题一下 ...
- conda创建/移除虚拟环境
conda创建python虚拟环境 前言 conda常用的命令: conda list 查看安装了哪些包. conda env list 或 conda info -e 查看当前存在哪些虚拟环境 co ...
- SpringCloud微服务实战——搭建企业级开发框架(四十一):扩展JustAuth+SpringSecurity+Vue实现多租户系统微信扫码、钉钉扫码等第三方登录
前面我们详细介绍了SSO.OAuth2的定义和实现原理,也举例说明了如何在微服务框架中使用spring-security-oauth2实现单点登录授权服务器和单点登录客户端.目前很多平台都提供了单 ...
- 【Java面试】TCP协议为什么要设计三次握手?
一个工作5年的粉丝,最近去面试了很多公司,每次都被各种技术原理题问得语无伦次. 由于找了快1个月时间的工作,有点焦虑,来向我求助. 我能做的只是保证每天更新一个面试题,然后问他印象最深刻的一个面试题是 ...
- vscode常用插件快捷键
俗话说,工欲善其事必先利其器,我们码农的器是什么尼?没错,就是我们亲爱的IDE,前端开发者最爱的编辑器应该是vscode了吧.但是我们要怎么去锋利它尼?不外乎就是熟悉它的使用方法.快捷键以及第三方的插 ...
- Vue回炉重造之封装防刷新考试倒计时组件
<!-- 考试倒计时组件 --> <template> <div class="time"> <p>00:{{timerCount2 ...