李强

我们常说“在今天所有的不确定性当中,数字化是最大的确定性”,数字化一定会全面改造所有的行业更是确定的。在菜鸟九年的探索中,我们最大的感受是“未来,任何一个物流企业都会是一个技术公司,真正拉开差距的是:技术与实体产业的结合有多深”。菜鸟“简单极致,贴地疾飞”的技术文化也深刻体现了这一点——好的技术要能解决实际问题。数字化并不是简单地上线一个或几个系统,这是一个贴近业务持续迭代的过程,伴随着这个过程,我相信会诞生非常多的创新技术。

在本书中我看到了工程思维在推进技术创新的缩影,把难的问题转化为简单的问题,用成熟实用的技术分而解之。高性能的微服务框架、CDM、元数据、低代码、无代码等,都是当下非常热门的技术课题,Oinone把这一切都有机地结合起来,形成了一种具备先进理念的全新一代软件产品,每一个特性都贴合企业数字化遇到的实际问题。Oinone的产品设计,把“大道至简,软件自造”贯穿始终,用最简单的方式,帮助企业驾驭数字化,相信会给企业带来不一样的体验。

就跟本书提到的“「企业视角由内部管理转向业务在线、生态在线(协同)带来一系列新的诉求」这一大背景下,以及云、端等新技术的发展,对研发人员的需求越来越大,同时要求越来越高,低代码平台是提升研发效率,降低研发成本的核心手段”,低代码已经不是需不需要的问题,而是怎么选的问题。菜鸟网络自身也在推进自有低代码开发平台,我们有幸邀请本书作者陈鹏程来到菜鸟网络进行了分享交流,收获非常大。如您正在选型低代码开发平台,向您推荐这本书,低无一体的Oinone肯定会打动您。

菜鸟网络CTO李强(在宽)

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9206.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
史, 昂's avatar史, 昂数式管理员
Previous 2024年5月23日
Next 2024年5月23日

相关推荐

  • 3.5.7.3 自定义布局

    布局是什么 在系统中,布局决定了母版内的页面元素,一个页面可以由多个组件进行组装,布局可以根据视图类型来替换。 默认布局范围: 图3-5-7-36 默认布局范围 作用场景 系统内置了多个布局组件,这些组件适用于全局、某个应用或某个页面,提供了灵活的布局定制选项。这些组件根据不同类型的视图进行了默认的组装,这也是选择了视图类型后,页面能够呈现的原因。当然,这些默认的组装是可以被覆盖、新增和添加新组件的。 使用registerLayout进行自定义布局 开发者在使用这些布局组件时,应该遵循公司的规范进行统一的调整。自定义布局组件的使用可通过 registerLayout 实现。registerLayout 的第一个参数是代表布局的 XML,第二个参数是不同的选项维度,默认包含以下维度: viewType: 视图类型 module: 视图模型所在模块 moduleName: 视图模型所在模块名称 model: 视图模型编码 modelName: 视图模型名称 viewName: 视图名称 actionName: 动作名称 inline: 是否内嵌视图(子视图特有) ttype: 模型字段类型(子视图特有) relatedTtype: 关联模型字段类型(子视图特有) field: 字段(子视图特有) 需要注意的是,动作可以是A模块下的a模型,这个动作可以打开B模块下的b模型的视图,module、moduleName、model、modelName应该填b模型对应的值,只不过大部分场景我们都是本模型的动作打开本模型的视图,所以这些场景拿动作所在模型填这些值也可以这些纬度也可以通过查看TS的定义查看 全局 在系统中,我们可以通过指定视图类型来决定某一类视图的全局布局。以表格为例,当第二个入参为 { viewType: ViewType.Table } 时,代表了替换了系统内所有表格的布局样式。 示例工程目录 以下是需关注的工程目录示例,main.ts更新导入./layout,layout/index.ts更新导出./tableLayout: 图3-5-7-37 全局纬度注册布局工程目录示例 示例代码 import {registerLayout, ViewType} from '@kunlun/dependencies' /** * 把系统内所有表格类型视图的全局动作放入搜索区域 * * 移动actionBar布局至外层 * <element widget="actionBar" slot="actionBar" slotSupport="action"> * <xslot name="actions" slotSupport="action" /> * </element> * */ const registerGlobalTableLayout = () => { return registerLayout(`<view type="TABLE"> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <pack widget="group"> <view type="SEARCH"> <element widget="search" slot="search" slotSupport="field" /> </view> </pack> <pack widget="group" slot="tableGroup"> <element widget="table" slot="table" slotSupport="field"> <element widget="expandColumn" slot="expandRow" /> <xslot name="fields" slotSupport="field" /> <element widget="rowActions" slot="rowActions" slotSupport="action" /> </element> </pack> </view>`, { viewType: ViewType.Table }) } registerGlobalTableLayout() 图3-5-7-38 全局纬度注册布局代码示例 效果 图3-5-7-39 全局纬度注册布局效果示例 应用 在系统中,我们可以通过指定视图类型和模块名称来替换某一类视图在特定模块下的全局布局。以表格为例,当第二个入参为 { viewType: ViewType.Table, moduleName: ‘resource’ } 时,代表了替换了资源应用下所有表格的布局样式,而其他应用仍使用默认布局 import {registerLayout, ViewType} from '@kunlun/dependencies' const registerModuleTableLayout = () => { return registerLayout(`<view type="TABLE"> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <pack widget="group"> <view type="SEARCH"> <element widget="search" slot="search" slotSupport="field" /> </view> </pack> <pack…

    2024年5月23日
    1.4K00
  • 3.3.4 模型的继承

    在我们的很多项目中,客户都是有个性化需求的,就像我们不能找到两件一模一样的东西,何况是企业的经营与管理思路,多少都会有差异。常规的方式只能去修改标准产品的逻辑来适配客户的需求。导致后续标品维护非常困难。而在介绍完这节以后是不是让你更加清晰认知到我们2.4.2【oinone独特性之每一个需求都可以是一个模块】一文中所表达的特性带来的好处呢? 一、继承方式 继承方式可以分为五种: 抽象基类ABSTRACT,只保存不希望为每个子模型重复键入的信息的模型,抽象基类模型不生成数据表存储数据,只供其他模型继承模型可继承域使用,抽象基类可以继承抽象基类。 扩展继承EXTENDS,子模型与父模型的数据表相同,子模型继承父模型的字段与函数。存储模型之间的继承默认为扩展继承。 多表继承MULTI_TABLE,父模型不变,子模型获得父模型的可继承域生成新的模型;父子模型不同表,子模型会建立与父模型的一对一关联关系字段(而不是交叉表),使用主键关联,同时子模型会通过一对一关联关系引用父模型的所有字段。多表继承父模型需要使用@Model.MultiTable来标识,子模型需要使用@Model.MultiTableInherited来标识。 代理继承PROXY,为原始模型创建代理,可以增删改查代理模型的实体数据,就像使用原始(非代理)模型一样。不同之处在于代理继承并不关注更改字段,可以更改代理中的元信息、函数和动作,而无需更改原始内容。一个代理模型必须仅能继承一个非抽象模型类。一个代理模型可以继承任意数量的没有定义任何模型字段的抽象模型类。一个代理模型也可以继承任意数量继承相同父类的代理模型。 临时继承TRANSIENT,将父模型作为传输模型使用,并可以添加传输字段。 二、继承约束 通用约束 对于扩展继承,查询的时候,父模型只能查询到父模型字段的数据,子模型可以查询出父模型及子模型的字段数据(因为派生关系所以子模型复刻了一份父模型的字段到子模型中)。 系统不会为抽象基类创建实际的数据库表,它们也没有默认的数据管理器,不能被实例化也无法直接保存,它们就是用来被继承的。抽象基类完全就是用来保存子模型们共有的内容部分,达到重用的目的。当它们被继承时,它们的字段会全部复制到子模型中。 系统不支持非jar包依赖模型的继承。 多表继承具有阻断效应,子模型无法继承多表继承父模型的存储父模型的字段,需要使用@Model.Advanced注解的inherited属性显示声明继承父模型的父模型。但是可以继承多表继承父模型的抽象父模型的字段。 可以使用@Model.Advanced的unInheritedFields和unInheritedFunctions属性设置不从父类继承的字段和函数。 跨模块继承约束 如果模型间的继承是跨模块继承,应该与模型所属模块建立依赖关系;如果模块间有互斥关系,则不允许建立模块依赖关系,同理模型间也不允许存在继承关系。 跨模块代理继承,对代理模型的非inJvm函数调用将使用远程调用方式;跨模块扩展(同表)继承将使用本地调用方式,如果是数据管理器函数,将直连数据源。 模型类型与继承约束 抽象模型可继承:抽象模型(Abstract) 临时模型可继承:抽象模型(Abstract)、传输模型(Transient) 存储模型可继承:抽象模型(Abstract)、存储模型(Store)、存储模型(多表,Multi-table Store),不可继承多个Store或Multi-table Store 多表存储模型(父)可继承:同扩展继承 多表存储模型(子)在继承单个Multi-table Store后可继承:抽象模型(Abstract)、存储模型(Store),不可继承多个Store 代理模型可继承: 抽象模型(Abstract),须搭配继承Store、Multi-table Store或Proxy 存储模型(Store),不可继承多个Store或Multi-table Store 存储模型(多表,Multi-table Store),不可继承多个Store或Multi-table Store 代理模型(Proxy),可继承多个Proxy,但多个父Proxy须继承自同一个Store或Multi-table Store,且不能再继承其他Store或Multi-table Store 同名字段以模型自身字段为有效配置,若模型自身不存在该字段,继承字段以第一个加载的字段为有效配置,所以在多重继承的情况下,未避免继承同名父模型字段的不确定性,在自身模型配置同名字段来确定生效配置。 三、继承的使用场景 模型的继承可以继承父模型的元信息、字段、数据管理器和函数 抽象基类 解决公用字段问题 扩展继承 解决开放封闭原则、跨模块扩展等问题 多表继承 解决多型派生类字段差异问题和前端多存储模型组合外观问题 代理继承 解决同一模型在不同场景下的多态问题(一表多态) 临时继承 解决使用现有模型进行数据传输问题 举例,前端多存储模型组合外观问题可通过多表继承的子模型,并一对一关联到关联模型,同时使用排除继承字段去掉不需要继承的字段。子模型通过默认模型管理器提供查询功能给前端,默认查询会查询子模型数据列表并在列表行内根据一对一关系查出关联模型数据合并,关联模型数据展现形态在行内是平铺还是折叠,在详情是分组还是选项卡可以自定义view进行配置 扩展继承 父子同表,模型在所有场景都有一致化的表现,意味着原模型被扩展成了新模型,父子模型的表名一致,模型编码不同,可覆盖父模型的模型管理器、数据排序规则、函数 多表继承 父子多表,父子间有隐式一对一关系,即父子模型都增加了一对一关联关系字段,同时父模型的字段被引用到子模型,且引用字段为只读字段,意味着子模型不可以直接更改父模型的字段值,子模型不继承父模型的模型管理器、数据排序规则、函数,子模型拥有自己的默认模型管理器、数据排序规则、函数。多表继承具有阻断效应,子模型无法自动多表继承父模型的存储父模型,需要显式声明多表继承父模型的存储父模型。 代理继承 代理模型继承并可覆盖父模型的模型管理器、数据排序规则、函数,同时可以使用排除继承字段和函数来达到不同场景不同视觉交互的效果。 图3-3-4-1 继承的使用场景 四、抽象基类(举例) 参考前文中3.3.2【模型的类型】一文中关于抽象模型的介绍 五、多表继承(举例) 场景设计如下 图3-3-4-2 多表继承设计场景 Step1 新建宠物品种、宠狗品种和萌猫品种模型 新建宠物品种模型,用@Model.MultiTable(typeField = "kind"),申明为可多表继承父类,typeField指定为kind字段 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.base.IdModel; @Model.MultiTable(typeField = "kind") @Model.model(PetType.MODEL_MODEL) @Model(displayName="品种",labelFields = {"name"}) public class PetType extends IdModel { public static final String MODEL_MODEL="demo.PetType"; @Field(displayName = "品种名") private String name; @Field(displayName = "宠物分类") private String kind; } 图3-3-4-3 多表继承示例代码 新建宠狗品种模型,用@Model.MultiTableInherited(type = PetDogType.KIND_DOG),申明以多表继承模式继承PetType,覆盖kind字段(用defaultValue设置默认值,用invisible = true设置为前端不展示),更多模块元数据以及模型字段元数据配置详见4.1.6【模型之元数据详解】一文 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.MultiTableInherited(type = PetDogType.KIND_DOG) @Model.model(PetDogType.MODEL_MODEL) @Model(displayName="宠狗品种",labelFields = {"name"}) public class PetDogType extends PetType { public static final String MODEL_MODEL="demo.PetDogType"; public static final String KIND_DOG="DOG"; @Field(displayName = "宠物分类",defaultValue = PetDogType.KIND_DOG,invisible = true) private String kind; } 图3-3-4-4 多表继承示例代码 新建萌猫品种模型,用@Model.MultiTableInherited(type = PetCatType.KIND_CAT),申明以多表继承模式继承PetType,覆盖kind字段(用defaultValue设置默认值,用invisible = true设置为前端不展示),并新增一个CatShapeEnum枚举类型的字段shape package pro.shushi.pamirs.demo.api.enumeration; import pro.shushi.pamirs.meta.annotation.Dict; import pro.shushi.pamirs.meta.common.enmu.BaseEnum; @Dict(dictionary = CatShapeEnum.DICTIONARY,displayName = "萌猫体型") public class CatShapeEnum extends BaseEnum<CatShapeEnum,Integer>…

    2024年5月23日
    1.7K00
  • 3.3.2 模型的类型

    本文会介绍不同类型模型以及其简单的应用场景,方便大家理解不同类型模型的用途 模型分为元模型和业务模型。元数据是指描述应用程序运行所必需的数据、规则和逻辑的数据集;元模型是指用于描述内核元数据的一套模式集合;业务模型是指用于描述业务应用元数据的一套模式集合。 元模型分为模块域、模型域和函数域三个域。域的划分规则是根据元模型定义数据关联关系的离散性来判断,离散程度越小越聚集到一个域。在4.1.4【模块元数据详解】一文中介绍的ModuleDefinition就是元模型。而我们在开发中涉及的就是业务模型 一、模型类型 抽象模型:往往是提供公共能力和字段的模型,它本身不会直接用于构建协议和基础设施(如表结构等)。 传输模型:用于表现层和应用层之间的数据交互,本身不会存储,没有默认的数据管理器,只有数据构造器。 存储模型:存储模型用于定义数据表结构和数据的增删改查(数据管理器)功能,是直接与连接器进行交互的数据容器。 代理模型:用于代理存储模型的数据管理器能力的同时,扩展出非存储数据信息的交互功能的模型。 二、模型定义种类 模型定义就是模型描述,不同定义类型,代表计算描述模型的元数据的规则不同 静态模型定义:模型元数据不持久化、不进行模型定义的计算(默认值、主键、继承、关联关系) 静态计算模型定义:模型元数据不持久化但初始化时进行模型定义计算获得最终的模型定义 动态模型定义:模型元数据持久化且初始化时进行模型定义计算获得最终的模型定义 静态模型定义需要使用@Model.Static进行注解;静态计算模型定义使用@Model.Static(compute=true)进行注解;动态模型定义不注解@Model.Static注解。 三、安装与更新 使用@Model.model来配置模型的不可变更编码。模型一旦安装,无法在对该模型编码值进行修改,之后的模型配置更新会依据该编码进行查找并更新;如果仍然修改该注解的配置值,则系统会将该模型识别为新模型,存储模型会创建新的数据库表,而原表将会rename为废弃表。 如果模型配置了@Base注解,表明在【oinone的设计器】中该模型配置不可变更;如果字段配置了@Base注解,表明在【oinone的设计器】中该字段配置不可变更。 四、基础配置 模型基类 所有的模型都需要继承以下模型中的一种,来表明模型的类型,同时继承以下模型的默认数据管理器(详见3.3.3模型的数据管理器一节)。 继承BaseModel,构建存储模型,默认无id属性。 继承BaseRelation,构建多对多关系模型,默认无id属性。 继承TransientModel,构建临时模型(传输模型),临时模型没有数据管理器,也没有id属性。 继承EnhanceModel,构建数据源为ElasticSearch的增强模型。 快捷继承 继承IdModel,构建主键为id的模型。继承IdModel的模型会数据管理器会增加queryById方法(根据id查询单条记录) 继承CodeModel,构建带有唯一编码code的主键为id的模型。可以使用@Model.Code注解配置编码生成规则。也可以直接覆盖CodeModel的generateCode方法或者自定义新增的前置扩展点自定义编码生成逻辑。继承CodeModel的模型会数据管理器会增加queryByCode方法(根据唯一编码查询单条记录) 继承VersionModel,构建带有乐观锁,唯一编码code且主键为id的模型。 继承IdRelation,构建主键为id的多对多关系模型。 模型继承关系图 图3-3-2-1 模型继承关系图 AbstractModel抽象基类是包含createDate创建时间、writeDate更新时间、createUid创建用户ID、writeUid更新用户ID、aggs聚合结果和activePks批量主键列表等基础字段的抽象模型。 TransientModel传输模型抽象基类是所有传输模型的基类,传输模型不存储,没有数据管理器。 TransientRelation传输关系模型是所有传输关系模型的基类,传输关系模型不存储,用于承载多对多关系,没有数据管理器。 BaseModel存储模型基类提供数据管理器功能,数据模型主键可以不是ID。 IdModel带id模型抽象基类,在BaseModel数据管理器基础之上提供根据ID查询、更新、删除数据的功能。 BaseRelation关系模型抽象基类用于承载多对多关系,是多对多关系的中间模型,数据模型主键可以不是ID。 IdRelation带id关系模型抽象基类,在BaseRelation数据管理器基础之上提供根据ID查询、更新、删除数据的功能。 CodeModel带code模型抽象基类,提供按配置生成业务唯一编码功能,根据code查询、更新、删除数据的功能。 EnhanceModel增强模型,提供全文检索能力。此模型会在4.1.25【框架之搜索引擎】一文中展开介绍。 五、抽象模型(举例) 抽象模型本身不会直接用于构建协议和基础设施(如表结构等),而是通过继承的机制供子模型复用其字段和函数。子模型可以是所有类型的模型。 比如demo模块要管理的一些公共模型字段,我们可以建一个AbstractDemoIdModel和AbstractDemoCodeModel,demo模块中的实体模型就可以继承它们。我们来为demo模块的模型统一增加一个数据状态这么一个字段,用做数据的生效与失效管理。 Step1 引入DataStatusEnum类 pamirs-demo-api的pom.xml包增加依赖,便于引入DataStatusEnum类,当然也可以自己建,这里只是oinone提供了统一的数据记录状态的枚举,以及相应的通用方法,这边就直接引入 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-core-common</artifactId> </dependency> 图3-3-2-2 引入通用类库 Step2 修改DemoModule DataStatusEnum枚举类本身也会做为数据字典,以元数据的方式被管理起来,当一个模块依赖另一个模块的元数据相关对象,则需要改模块的模块依赖定义。为DemoModule增加CommonModule的依赖注解 package pro.shushi.pamirs.demo.api; import org.springframework.stereotype.Component; import pro.shushi.pamirs.boot.base.ux.annotation.action.UxRoute; import pro.shushi.pamirs.boot.base.ux.annotation.navigator.UxHomepage; import pro.shushi.pamirs.core.common.CommonModule; import pro.shushi.pamirs.demo.api.model.PetShop; import pro.shushi.pamirs.meta.annotation.Module; import pro.shushi.pamirs.meta.base.PamirsModule; import pro.shushi.pamirs.meta.common.constants.ModuleConstants; @Component @Module( name = DemoModule.MODULE_NAME, displayName = "oinoneDemo工程", version = "1.0.0", dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE} ) @Module.module(DemoModule.MODULE_MODULE) @Module.Advanced(selfBuilt = true, application = true) @UxHomepage(@UxRoute(PetShop.MODEL_MODEL)) public class DemoModule implements PamirsModule { public static final String MODULE_MODULE = "demo_core"; public static final String MODULE_NAME = "DemoCore"; @Override public String[] packagePrefix() { return new String[]{ "pro.shushi.pamirs.demo"}; } } 图3-3-2-3 定义模块依赖 Step3 新建AbstractDemoCodeModel和AbstractDemoIdModel 并新增AbstractDemoIdModel和AbstractDemoCodeModel分别继承IdModel和CodeModel,实现IDataStatus接口不是必须的,刚好DataStatus有配套的通用逻辑,暂时也先加进去,具体使用会在本文的【代理模型】这段介绍 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.core.common.behavior.IDataStatus; import pro.shushi.pamirs.core.common.enmu.DataStatusEnum; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.annotation.sys.Base; import pro.shushi.pamirs.meta.base.common.CodeModel; import pro.shushi.pamirs.meta.enmu.ModelTypeEnum; @Base @Model.model(AbstractDemoCodeModel.MODEL_MODEL) @Model.Advanced(type = ModelTypeEnum.ABSTRACT) @Model(displayName = "AbstractDemoCodeModel") public abstract class AbstractDemoCodeModel extends CodeModel implements IDataStatus { public static final String MODEL_MODEL="demo.AbstractDemoCodeModel"; @Base @Field.Enum @Field(displayName = "数据状态",defaultValue = "DISABLED",required =…

    2024年5月23日
    1.9K00
  • 第2章 Oinone的技术独特性

    本章的主要目的是通过分析企业商业支撑软件的项目特性和关注点,找到企业软件发展的另一个本质变化——新技术流派的产生。在对“互联网架构做为最佳实践为何失效”的思考基础上,我们分析互联网中台架构的发展历史以及企业实际现状,找出其水土不服的原因。进而引出Oinone的低代码开发平台如何结合互联网架构并完成创新,以满足企业数字化转型的需求。 具体而言,本章包括以下内容: 企业软件发展的另一个本质变化:新技术流派的产生; 最佳实践为何失效?Oinone如何打造具有企业特色的互联网架构; Oinone独特性之源:元数据与设计原则; Oinone独特性之单体与分布式的灵活切换; Oinone独特性之每一个需求都是一个模块; Oinone独特性之低无一体。

    Oinone 7天入门到精通 2024年5月23日
    7.3K00
  • 3.3.6 枚举与数据字典

    枚举是大家在系统开发中经常用的一种类型,在oinone中也对枚举类型进行了支持,同时也做了相应的加强。希望通过本文能让大家对枚举的使用,有更全面的认知 一、枚举系统与数据字典 枚举是列举出一个有穷序列集的所有成员的程序。在元数据中,我们使用数据字典进行描述。 协议约定 枚举需要实现IEnum接口和使用@Dict注解进行配置,通过配置@Dict注解的dictionary属性来设置数据字典的唯一编码。前端使用枚举的displayName来展示,枚举的name来进行交互;后端使用枚举的value来进行交互(包括默认值设置也使用枚举的value)。 枚举会存储在元数据的数据字典表中。枚举分为两类:1.异常类;2.业务类。异常类枚举用于定义程序中的错误提示,业务类枚举用于定义业务中某个字段值的有穷有序集。 编程式用法 图3-3-6-1 编程式用法 如果一个字段的类型被定义为枚举,则该字段就可以使用该枚举来进行可选项约束(options)。该字段的可选项为枚举所对应数据字典的子集。 可继承枚举 继承BaseEnum可以实现java不支持的继承枚举。同时可继承枚举也可以用编程式动态创建枚举项。 可继承枚举也可以兼容无代码枚举。 图3-3-6-2 可继承枚举 二进制枚举 可以通过@Dict注解设置数据字典的bit属性或者实现BitEnum接口来标识该枚举值为2的次幂。 二、enum不可继承枚举(举例) 我们在介绍抽象基类中AbstractDemoCodeModel和AbstractDemoIdModel就引入了数据状态(DataStatusEnum)字段,并设置了必填和默认值为DISABLED。DataStatusEnum实现了IEnum接口,并用@Dict(dictionary = DataStatusEnum.dictionary, displayName = "数据状态")进行了注解。为什么不能继承呢?因为JAVA语言的限制导致enum是不可继承的 package pro.shushi.pamirs.core.common.enmu; import pro.shushi.pamirs.meta.annotation.Dict; import pro.shushi.pamirs.meta.common.enmu.IEnum; @Dict(dictionary = DataStatusEnum.dictionary, displayName = "数据状态") public enum DataStatusEnum implements IEnum<String> { DRAFT("DRAFT", "草稿", "草稿"), NOT_ENABLED("NOT_ENABLED", "未启用", "未启用"), ENABLED("ENABLED", "已启用", "已启用"), DISABLED("DISABLED", "已禁用", "已禁用"); public static final String dictionary = "partner.DataStatusEnum"; private String value; private String displayName; private String help; DataStatusEnum(String value, String displayName, String help) { this.value = value; this.displayName = displayName; this.help = help; } public String getValue() { return value; } public String getDisplayName() { return displayName; } public String getHelp() { return help; } } 图3-3-6-3 不可继承枚举 三、BaseEnum可继承枚举(举例) Step1 新增CatShapeExEnum继承CatShapeEnum枚举 package pro.shushi.pamirs.demo.api.enumeration; import pro.shushi.pamirs.meta.annotation.Dict; @Dict(dictionary = CatShapeExEnum.DICTIONARY,displayName = "萌猫体型Ex") public class CatShapeExEnum extends CatShapeEnum { public static final String DICTIONARY ="demo.CatShapeExEnum"; public final static CatShapeExEnum MID =create("MID",3,"中","中"); } 图3-3-6-4 新增CatShapeExEnum继承CatShapeEnum枚举 Step2 修改PetCatType的shape字段类型为CatShapeExEnum package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.demo.api.enumeration.CatShapeExEnum; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.MultiTableInherited(type = PetCatType.KIND_CAT) @Model.model(PetCatType.MODEL_MODEL) @Model(displayName="萌猫品种",labelFields = {"name"}) public class PetCatType extends PetType { public static final String MODEL_MODEL="demo.PetCatType"; public static final String KIND_CAT="CAT"; @Field(displayName = "宠物分类",defaultValue…

    2024年5月23日
    3.5K00

Leave a Reply

Please Login to Comment