Nop平台的代码生成器可以脱离Nop平台在其他项目中直接使用。作为示例,我为[bsin-pass-all-in-one]()这个开发框架写了一个示例性的代码生成器。
Bsin-PaaS(毕昇) 是一套企业级的低代码、零代码去中心化应用搭建平台,可帮助企业快速搭建有竞争力的业务中台、流程中台、业务前台。
参见
相比于EasyCode,maku-generator等常见代码生成工具,nop-cli要方便很多,而且它也很明显的体现了Nop平台的设计特点,展示了可逆计算理论的一种直观应用。
常见的代码生成工具都需要安装IDE插件或者部署一个独立应用,很难和DevOps流程集成在一起。而且如果不修改代码生成工具的代码,一般很难对配置和模板文件难以做细粒度的定制。本文以bsin-paas-all-in-one项目为例,演示如何使用nop-cli代码生成器来为第三方项目增加模型驱动的代码生成功能,并于Maven打包集成在一起使用。
架构特点
与其他的代码生成方案相比,nop-cli具有如下特点:
- 直接读取Excel格式的模型文件:可以与maven打包过程集成在一起,确保模型驱动是整个DevOps流程的一个有机组成部分。而一般的代码生成器要么使用IDE插件,要么需要单独部署应用,难以和DevOps集成。
- 强大的模板语言:使用Nop平台内置的Xpl模板语言进行代码生成,可以通过nop-idea-plugin插件进行断点调试,可以通过标签库来对常用的逻辑进行抽象,并可以通过Nop平台内置的delta定制机制对已有的模板进行差量化定制。Xpl模板内嵌的脚本语言类似JavaScript,并可以和Java语言无缝集成,性能也大幅优于FreeMarker模板语言。
- 模板数据驱动:无需编写Java代码,只要指定一个模板文件目录,调整模板目录结构即可控制代码生成过程中的嵌套循环和判断逻辑。例如控制某些条件满足的时候才生成对应文件。
- 差量定制:无需编程,通过增加差量模型文件即可为已有模型对象增加扩展属性,在Excel模型文件中可以对这些扩展属性进行配置。
- 自定义模型:Nop平台提供了通用的Excel模型读取机制,无需编程,只需要定义一个imp.xml结构描述文件,即可读取用户自定义的Excel模型,而不用限定只能使用平台内置的模型。
技术原理
Nop Platform 2.0是基于可逆计算原理从零开始构建的新一代低代码平台,它致力于克服低代码平台无法摆脱穷举法的困境,从理论层面超越组件技术,有效的解决粗粒度软件复用的问题。
Nop平台的代码生成器nop-cli可以独立于Nop平台单独使用。它的设计采用了增量式、数据驱动的代码生成方式。具体设计原理参见我的文章:
使用教程
将Nop平台的代码生成工具nop-cli集成到自己的项目中非常简单,只需要按照如下步骤执行。
1. 制作模板工程
首先建立一个模板工程,例如bsin-codegen-template。这个工程的作用是将一些模型文件打包成Java模块,其中并不包含任何Java代码。
关于代码生成语法的详细介绍,可以参见文档codegen.md
resources/_vfs- xgen后缀的文件表示将会根据此模板生成对应的文件。例如pom.xml.xgen生成pom.xml
- xrun后缀的文件表示会执行其中的Xpl模板代码,但是不会生成对应的文件
- 其他后缀表示直接原样拷贝
- @init.xrun是整个模板目录的初始化文件。当我们要渲染某个模板目录时,总会先执行目录下的@init.xpl来初始化模板执行的变量环境
条件判断
{varA.propB}{!a}{!!entityModel.tagSet.@biz}表示判断数据表的标签列表中是否包含biz标签,如果不包含,则最终返回false。因此,只有当明确标注了biz标签,才会为对应的数据实体生成Biz对象。
嵌套循环
@init.xrunbuilder对应于NestedLoopBuilder类,它是用于辅助创建嵌套循环对象的帮助类。
- defineGlobalVar定义在模板路径和模板代码中可以使用的全局变量
- defineLoopVar用于定义嵌套循环变量。例如上例中定义 entityModel = ormModel.entityModels。但我们在路径中写{entityModel.shortName}时,它实际表示会从ormModel获取到entityModel的列表,然后对每个entityModel执行模板渲染。
2. 配置exec-maven-plugin插件
将模板工程成功编译打包之后,可以通过exec-maven-plugin插件来使用这个模板工程。
exec-maven-plugin是Maven自带的插件。它可以动态执行指定Java类的main方法。通过以上配置,我们实际执行的是io.github.entropy-cloud:nop-cli这个包中的CodeGenTask类的main方法,传入两个参数:当前工程所在目录,以及待执行的模板目录名,例如precompile表示执行当前工程的precompile目录下的所有模板文件。
在bsin-demo/bsin-demo-codegen模块的precompile目录下,我们可以增加编写代码生成逻辑:
/bsin/templates/orm因为plugin的配置较为复杂,所以一般我们建立一个单独的xxx-codegen子模块,在它的pom文件中增加代码生成器的调用。然后其他模块只要在scope=test模式下引用xxxx-codegen模块即可确保codegen是第一个被编译的模块,它生成的代码在后续工程的编译过程中会被使用。
3. 制作Excel模型文件
在model目录下,我们创建一个Excel数据模型文件bsin-demo.orm.xlsx。orm.xlsx这个文件后缀表明该文件是ORM数据模型定义文件,将会应用orm.imp.xml这个导入模型来解析文件中的字段数据。
在这个Excel文件中,我们可以定义数据库表、字段、表关联、唯一键等各类信息。详细配置规则参见文档excel-model.md
逆向工程生成Excel模型文件
可以利用nop-cli工具从现有的数据库中导出数据模型。
- 在命令行中执行如下指令
shell java -jar nop-cli-2.0.0-BETA.1.jar reverse-db bsin -c=com.mysql.cj.jdbc.Driver --username=nop --password=nop_test --jdbcUrl="jdbc:mysql://127.0.0.1:3306/bsin?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC"以上指令表示连接到本地的MySQL数据库,导出bsin模式下的所有表定义。连接使用的用户名为nop,密码为nop_test。 在导出的Excel模型的基础上我们增加更多应用相关的配置,例如配置字段是否在前台显示,对应的数据域等。
3. 扩展已有模型
_vfs/_delta/default/nop/orm/imp/orm.imp.xml在Excel模型中我们就可以增加针对此变量的配置
在模板文件中,我们可以通过动态属性表达式来访问该扩展属性(参见模板文件 README.md.xgen)。
所有具有名字空间的属性都是扩展属性,不带名字空间的属性是模型对象本身具有的基础属性。
4. 增加自定义模型
除了使用内置的ORM模型之外,我们还可以根据业务需要设计新的领域模型。Nop平台内置的Excel解析器是一个非常灵活的领域模型转换器:它可以实现Tree结构的Excel数据文件和Tree结构的领域对象之间的双向转换。我们只需要定义一个imp.xml模型文件即可实现这种转换。在imp.xml文件中,我们只需要定义字段的结构,而不需要精确指定字段在Excel模板中的位置。也就是说,在Excel模型文件中字段的先后顺序是不重要的,我们可以随意调整字段的顺序,删除非必填的字段,增加新的自定义字段等。
在bsin-codegen-template模板工程中,提供了使用自定义模型的例子。
/_vfs/report/imp-model/_vfs/bsin/imp/bsin-api.imp.xml/bsin/templates/api它表示解析model/bsin-demo.bsin-api.xlsx模型文件,然后使用/bsin/templates/api模板目录下的模板去生成代码。