OneCode 领域驱动设计(DDD)技术实践(一)

简介: OneCode-DSM(以下简称DSM)工具集是建立是以OneCode低代码引擎为基础专注于低代码建模应用的高阶建模工具。 在OneCode引擎中,出了为普通用户提供无代码的拖动设计器,低代码的业务逻辑编排器,之外还提供了供专业业务领域专家的使用的DSM建模工具。

  前言  

领域驱动设计(简称 ddd)概念来源于2004年著名建模专家Eric Evans 发表的他最具影响力的书籍:《领域驱动设计——软件核心复杂性应对之道》(Domain-Driven Design –Tackling Complexity in the Heart of Software),简称Evans DDD,领域驱动设计思想进入软件开发者的视野。在将近20年的发展中领域模型设计一直占据着非常重要的位置,但其直接面向业务场景的设计思想,更适合在具有特定业务场景的模型构建。在日常我们见到的DDD模型多数是具有特定业务背景的特定业务(Domain-Specific Modeling)特定领域建模工具。

      近两年,随着新一代WEB技术以及,微服务、中台技术,云原生应用的推广;领域驱动模型(DDD)再次成为软件设计领域的热点。 而低代码/无代码平台是进近几年持续高速发展的一个技术领域。

一,OneCode-工具集 简介

     OneCode-DSM(以下简称DSM)工具集是建立是以OneCode低代码引擎为基础专注于低代码建模应用的高阶建模工具。

     在OneCode引擎中,出了为普通用户提供无代码的拖动设计器,低代码的业务逻辑编排器,之外还提供了供专业业务领域专家的使用的DSM建模工具。

编辑切换为居中

OneCode-DSM 应用

(1)可视化设计器

      以可视化设计器引擎为主体的表单报表工具,在日常常用的表单报表中是以无代码的方式来实现业务流审批以及数据大屏展现设计,移动展现等应用。

编辑切换为居中

添加图片注释,不超过 140 字(可选)

(2)低代码服务集成工具

编辑切换为居中

添加图片注释,不超过 140 字(可选)

(3)DSM建模工具

编辑切换为居中

添加图片注释,不超过 140 字(可选)

二,OneCode-DSM工具

(1)工具组成概览

      DSM建模工具是OneCode建模的辅助工具,提供了资源库管理模块,领域模型构建模块,以及视图工厂配置模块。

编辑切换为居中

添加图片注释,不超过 140 字(可选)

   仓储模型模块,主要功能是辅助用户将用户的数据库,外部API接口,以及已有的“代码”应用通过转换器转变为可被DSM识别的资源部格式。

    领域模型模块是DSM核心工具,在领域模型中导入的资源会同具体场景下的值对象,场景菜单、通用域服务根据具体的业务场景完成领域模型的建模工作。

    视图工厂是领域模型的具体实现,在领域模型应用中建模输出的产物会通过出码工厂输出位视图应用,这些视图应用会通过视图工厂进一步加工处理输出为用户交互应用。

    (2)OneCode语言(注解)组成

编辑切换为居中

添加图片注释,不超过 140 字(可选)

       (3)建模流程

编辑切换为居中

添加图片注释,不超过 140 字(可选)

       三,仓储库建模


编辑切换为居中

添加图片注释,不超过 140 字(可选)

(1)通过数据库建模

              仓储工具中使用频率最高的是数据库的转换应用,用户通过数据库工具完成数据源配置。

编辑切换为居中

数据源配置


库表映射代码示例:

@DBTable(configKey="fdt",cname="领导信息",tableName="FDT_LINGDAO",primaryKey="uuid")@Repository(repositoryId="54fa1fd2-cae4-44b0-8387-f10f98bdd63c")publicinterfaceFdtLingdao  {       @Uid      @DBField(cnName="主键",dbFieldName="uuid")publicStringgetUuid();  publicvoidsetUuid(String  uuid);       @CustomAnnotation(caption="名称")      @DBField(cnName="名称",length=20,dbFieldName="test")  publicStringgetTest();  publicvoidsetTest(String  test);       @CustomAnnotation(caption="领导姓名")      @DBField(cnName="领导姓名",length=20,dbFieldName="name")  publicStringgetName();  publicvoidsetName(String  name);       @CustomAnnotation(caption="职务")      @DBField(cnName="职务",length=100,dbFieldName="duty")  publicStringgetDuty();  publicvoidsetDuty(String  duty);       @CustomAnnotation(caption="创建时间")      @DBField(cnName="创建时间",length=0,dbType=ColType.DATETIME,dbFieldName="createtime")  publicDategetCreatetime();  publicvoidsetCreatetime(Date  createtime);   }

库表装载器CRUD代码示例:

@Aggregation(type =AggregationType.aggregationEntity,entityClass=FdtLingdao.class,rootClass=FdtLingdaoService.class)publicinterfaceFdtLingdaoService  {     @APIEventAnnotation(bindMenu ={CustomMenuItem.reload})    publicList<FdtLingdao>findAll()throwsJDSException;     publicList<FdtLingdao>findByWhere(String where)throwsJDSException;         @APIEventAnnotation(bindMenu ={CustomMenuItem.search})    publicList<FdtLingdao>find(FdtLingdao  fdtLingdao)throwsJDSException;        @APIEventAnnotation(bindMenu ={CustomMenuItem.add,CustomMenuItem.editor})    publicFdtLingdaogetFdtLingdaoInfo(String uuid)throwsJDSException;     @APIEventAnnotation(bindMenu ={CustomMenuItem.save}, callback ={CustomCallBack.ReloadParent,CustomCallBack.Close})    publicFdtLingdaoupdate(FdtLingdao  fdtLingdao)throwsJDSException;     @APIEventAnnotation(bindMenu ={CustomMenuItem.delete}, callback ={CustomCallBack.Reload})    publicBooleandelete(String uuid)throwsJDSException;}


(2)通过实体建模

  仓储实体实例

编辑切换为居中

添加图片注释,不超过 140 字(可选)

@Entity@Aggregation(type =AggregationType.aggregationRoot,sourceClass =Role.class, rootClass =Role.class)publicinterfaceRoleextends java.io.Serializable{        @MethodChinaName(cname ="角色标识")    @Uid    publicStringgetRoleId();     publicvoidsetRoleId(String roleId);     @MethodChinaName(cname ="名称")    @Caption    publicStringgetName();     publicvoidsetName(String name);     @MethodChinaName(cname ="角色类型")    publicRoleTypegetType();     publicvoidsetType(RoleType type);     @MethodChinaName(cname ="级数")    publicStringgetRoleNum();     publicvoidsetRoleNum(String num);         @MethodChinaName(cname ="系统ID")    @Pid    publicStringgetSysId();     publicvoidsetSysId(String sysId);     @MethodChinaName(cname ="人员")    @Ref(ref =RefType.m2m, view =ViewType.grid)    publicList<Person>getPersonList();     @MethodChinaName(cname ="部门")    @Ref(ref =RefType.m2m, view =ViewType.grid)    publicList<Org>getOrgList();     publicList<String>getOrgIdList();}

(3) 实体关系

编辑切换为居中

添加图片注释,不超过 140 字(可选)

     仓储建模的一个核心目的是将结构化的数据转变为面向对象的模式,而这其中非常重要的一点则是实体关系的处理,DSM设计中针对数据库表允许用户在导入数据库后再次进行实体关系建模,将数据库表按 1:1 ,1:N, N:N模型建立关系。完成建模后在出码的过程中会根据业务模板设定,进行实体模型的转变,在实体代码中以 @Ref 关系标签完成建模应用。

数据库模型关系

实体关系

实体注解配置

1:N

一对多

@Ref(ref = RefType.o2m)

N:N

多对多

@Ref(ref = RefType.m2m)

1:1

一对一

@Ref(ref = RefType.o2o)

引用

@Ref(ref = RefType.ref)

查找

@Ref(ref = RefType.)

  实体模型关系在基础的模型上根据仓储模型设计,独立扩展了

publicenumRefTypeimplementsIconEnumstype{   ref("引用","spafont spa-icon-c-databinder"),   o2m("一对多","spafont spa-icon-c-treeview"),   m2o("多对一","spafont spa-icon-alignwh"),   f2f("自循环","spafont spa-icon-cancel"),   o2o("一对一","spafont spa-icon-hmirror"),   find("查找","xui-icon-search"),   m2m("多对多","spafont spa-icon-alignwh");    privatefinalString imageClass;    privatefinalString name;     RefType(String name,String imageClass){        this.name = name;        this.imageClass = imageClass;    }}

(4) 仓储建模模板

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

(5)仓储模型常用注解

注解名称

用途

实例

@DBTable

数据库表映射配置

主要包含了,数据源标识,表名称以及主键信息

@DBTable(configKey="fdt",tableName="FDT_LINGDAO",primaryKey="uuid")

@DBField

数据库字段配置

@DBField(cnName="创建时间",length=0,dbType=ColType.DATETIME,dbFieldName="createtime")

@Uid

实体字段,在数据库实体中一般标识为主键,在DDD模型中作为唯一值

@Uid

@Pid

父级组件字段,通常在关系实体中用于标识父级对象的主键

@Pid

@CustomAnnotation

常用实体注解,注解属性中会包括,字段的展示类型,可读属性,展示注解等。

@CustomAnnotation(caption="职务")

@Caption

标题注解一般作用在表格行数据的展示中作为默认显示字段,如Person (人员对象中)会将name作为默认展示选项

@Caption

@Ref

实体关系属性

@Ref(ref = RefType.m2m, view = ViewType.grid)

@APIEventAnnotation

API服务注解,是对外服务的标识。添加该注解后,在后续的模型建模中会对应转换为Web API服务

@APIEventAnnotation(bindMenu = {CustomMenuItem.search})

三,领域建模

(1) 领域建模组成

编辑切换为居中

添加图片注释,不超过 140 字(可选)

   (2)领域建模原理

编辑切换为居中

模型渲染原理

        OneCode 本身基于JAVA语言体系,是在Java Spring 注解基础上的一套扩展子集,混合编译引擎器通过扩展注解构建完整的Domain模型,通过读取标准Spring 注解完成普通Web数据交付及调度过程。

示例注解说明:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

完整示例代码:

@Controller@RequestMapping("/admin/org/deparment/")@MethodChinaName(cname ="部门管理", imageClass ="bpmfont bpmgongzuoliuzuhuzicaidan")@Aggregation(sourceClass =IDeparmentService.class, rootClass =Org.class)publicinterfaceIDeparmentAPI{    @RequestMapping(method =RequestMethod.POST, value ="Persons")    @GridViewAnnotation()    @ModuleAnnotation(caption ="人员列表")    @APIEventAnnotation(bindMenu ={CustomMenuItem.treeNodeEditor})    @ResponseBody    public<KextendsIPersonGrid>ListResultModel<List<K>>getPersons(String orgId);     @RequestMapping(method =RequestMethod.POST, value ="loadChild")    @APIEventAnnotation(bindMenu ={CustomMenuItem.loadChild})    @ResponseBody    public<TextendsIDeparmentTree>ListResultModel<List<T>>loadChild(String parentId);     @MethodChinaName(cname ="部门信息")    @RequestMapping(method =RequestMethod.POST, value ="DeparmentInfo")    @NavGroupViewAnnotation(saveUrl ="admin.org.deparment.saveOrg")    @DialogAnnotation    @ModuleAnnotation(caption ="编辑部门信息", width ="600", height ="480")    @APIEventAnnotation(callback ={CustomCallBack.ReloadParent,CustomCallBack.Close}, bindMenu ={CustomMenuItem.editor})    @ResponseBody    public<KextendsIDeparmentNav>ResultModel<K>getDeparmentInfo(String orgId);     @MethodChinaName(cname ="添加部门")    @RequestMapping(method =RequestMethod.POST, value ="addDeparment")    @FormViewAnnotation()    @DialogAnnotation    @ModuleAnnotation(caption ="添加部门", width ="350", height ="260")    @APIEventAnnotation(bindMenu ={CustomMenuItem.add}, autoRun =true)    @ResponseBody    public<MextendsIAddDeparmentForm>ResultModel<M>addDeparment(String parentId);     @MethodChinaName(cname ="保存机构信息")    @RequestMapping(value ={"saveOrg"}, method ={RequestMethod.GET,RequestMethod.POST})    @APIEventAnnotation(callback ={CustomCallBack.ReloadParent,CustomCallBack.Close}, bindMenu ={CustomMenuItem.save})    public@ResponseBody    ResultModel<Boolean>saveOrg(@RequestBodyIAddDeparmentForm deparmentForm);     @MethodChinaName(cname ="删除部门")    @RequestMapping(value ={"delOrg"}, method ={RequestMethod.GET,RequestMethod.POST})    @APIEventAnnotation(callback ={CustomCallBack.Reload,CustomCallBack.ReloadParent}, bindMenu ={CustomMenuItem.delete})    public@ResponseBody    ResultModel<Boolean>delOrg(String orgId);     ;}

   (3)聚合配置

编辑切换为居中

建模配置

编辑切换为居中

接口配置


编辑切换为居中

窗体配置


编辑切换为居中

执行事件传递

(4)聚合分类

编辑切换为居中

添加图片注释,不超过 140 字(可选)


(5)聚合根

       聚合根设计,通常来标识其独立的域应用,具有全局唯一性的特点。 在 通用域中,具有时间轴维度的对象描述,如工作流中的流程示例(ProcessInst)对象。在获取聚合根后,可以依据时间轴一次向前获取,流程定义对象,向后获取可以取得流程历史数据,而根据当前节点则可以获取权限,数据表单、业务示例状态的等等实体数据。

编辑切换为居中

流程示例聚合根配置

     流程实例聚合根源码

@Entity@MethodChinaName(cname ="流程实例")@Aggregation(type =AggregationType.aggregationRoot, sourceClass =ProcessInst.class, rootClass =ProcessInst.class)publicinterfaceProcessInstextends java.io.Serializable{    @MethodChinaName(cname ="流程实例UUID")    @Uid    publicStringgetProcessInstId();     @MethodChinaName(cname ="流程定义UUID")    @Pid    publicStringgetProcessDefId();         @MethodChinaName(cname ="流程定义版本UUID")    @Pid    publicStringgetProcessDefVersionId();     @MethodChinaName(cname ="流程实例名称")    publicStringgetName();        @MethodChinaName(cname ="紧急程度")    publicStringgetUrgency();        @MethodChinaName(cname ="流程实例状态")    publicProcessInstStatusgetState();       @MethodChinaName(cname ="流程实例副本数量")    publicintgetCopyNumber();          @MethodChinaName(cname ="程实例启动时间")    publicDategetStartTime();         @MethodChinaName(cname ="流程实例办结时间")    publicDategetEndTime();     @MethodChinaName(cname =" 流程实例时间限制")    publicDategetLimitTime();       @MethodChinaName(cname ="流程实例状态")    publicProcessInstStatusgetRunStatus();     @MethodChinaName(cname ="流程定义版本")    @Ref(ref =RefType.m2o, view =ViewType.grid)    publicProcessDefVersiongetProcessDefVersion()throwsBPMException;          @MethodChinaName(cname ="流程定义")    @Ref(ref =RefType.m2o, view =ViewType.dic)    publicProcessDefgetProcessDef()throwsBPMException;          @MethodChinaName(cname ="活动实例")    @Ref(ref =RefType.o2m, view =ViewType.grid)    publicList<ActivityInst>getActivityInstList()throwsBPMException;          @MethodChinaName(cname ="流程属性值", returnStr ="getWorkflowAttribute($R('attName'))", display =false)    publicObjectgetWorkflowAttribute(ProcessInstAtt name);        @MethodChinaName(cname ="权限属性值", returnStr ="getRightAttribute($R('attName'))", display =false)    publicObjectgetRightAttribute(ProcessInstAtt name);          @MethodChinaName(cname ="应用属性值", returnStr ="getAppAttribute($R('attName'))", display =false)    publicObjectgetAppAttribute(ProcessInstAtt name);        @MethodChinaName(cname ="定制属性值", returnStr ="getAttribute($R('attName'))", display =false)    publicStringgetAttribute(String name);          @MethodChinaName(cname ="取得流程中的所有属性值", returnStr ="getAllAttribute()", display =false)    @Ref(ref =RefType.o2m, view =ViewType.grid)    publicList<AttributeInst>getAllAttribute();     @MethodChinaName(cname ="个人定制属性值", returnStr ="getAttribute($R('personId'),$R('attName'))", display =true)    publicStringgetPersonAttribute(String personId,String name);        @MethodChinaName(cname ="设置定制属性", returnStr ="setAttribute($R('attName'),$R('value'))", display =false)    publicvoidsetAttribute(String name,String value)throwsBPMException;       @MethodChinaName(cname ="设置个人定制属性", returnStr ="setAttribute($R('personId'),$R('attName'),$R('value'))", display =false)    publicvoidsetPersonAttribute(String personId,String name,String value)throwsBPMException;          @MethodChinaName(cname ="更新流程实例名称(公文标题)", returnStr ="updateProcessInstUrgency($R('processInstName'))")    publicReturnTypeupdateProcessInstName(String name)            throwsBPMException;     @MethodChinaName(cname ="更新流程实例紧急程度", returnStr ="updateProcessInstUrgency($R('urgency'))")    publicReturnTypeupdateProcessInstUrgency(            String urgency)throwsBPMException;          @MethodChinaName(cname ="流程实例挂起", returnStr ="suspendProcessInst()", display =false)    publicReturnTypesuspendProcessInst()            throwsBPMException;     @MethodChinaName(cname ="继续流程实例", returnStr ="resumeProcessInst()", display =false)    publicReturnTyperesumeProcessInst()            throwsBPMException;         @MethodChinaName(cname ="取得活动的历史数据, 根据流程实例")    publicList<ActivityInstHistory>getActivityInstHistoryListByProcessInst()throwsBPMException;          @MethodChinaName(cname ="中止流程实例", returnStr ="abortProcessInst()", display =false)    publicReturnTypeabortProcessInst()            throwsBPMException;        @MethodChinaName(cname ="流程实例完成", returnStr ="completeProcessInst()", display =false)    publicReturnTypecompleteProcessInst()            throwsBPMException;          @MethodChinaName(cname ="删除流程实例", returnStr ="deleteProcessInst()", display =false)    publicReturnTypedeleteProcessInst()            throwsBPMException;          @MethodChinaName(cname ="获取表单数据")    publicDataMapgetFormValues()throwsBPMException;         @MethodChinaName(cname ="更新表单数据")    publicvoidupdateFormValues(DataMap dataMap)throwsBPMException;}


(6)聚合实体

      聚合实体,通常用来描述独立实体机构,例如业务表单中单表或简单关联表关系。通常只包含简单的值关系,功能上也仅限于,查询列表、保存表单等简单应用。

编辑切换为居中

单表表单


代码示例

@Controller@RequestMapping("/test/fdtlingdaoservice/")@Aggregation(type=AggregationType.aggregationEntity,sourceClass=FdtLingdaoService.class)publicinterfaceFdtLingdaoAPI  {     @APIEventAnnotation(bindMenu=CustomMenuItem.search)     @RequestMapping(value="searchUrl")     @ModuleAnnotation     @GridViewAnnotation     @ResponseBody     public   ListResultModel<List<FindGridView>> find (FdtLingdao fdtLingdao);          @APIEventAnnotation(bindMenu={CustomMenuItem.add,CustomMenuItem.editor})     @RequestMapping(value="addPath")     @ModuleAnnotation     @FormViewAnnotation     @ResponseBody     public   ResultModel<GetFdtLingdaoInfoView> getFdtLingdaoInfo (String uuid);          @APIEventAnnotation(bindMenu=CustomMenuItem.save,callback={CustomCallBack.ReloadParent,CustomCallBack.Close})     @RequestMapping(value="update")     @ResponseBody     public   ResultModel<FdtLingdao> update (@RequestBodyFdtLingdao fdtLingdao);          @RequestMapping(value="findByWhere")     @ResponseBody     public   ListResultModel<List<FdtLingdao>> findByWhere (String where);          @APIEventAnnotation(bindMenu=CustomMenuItem.delete,callback=CustomCallBack.Reload)     @RequestMapping(value="delete")     @ResponseBody     public   ResultModel<Boolean> delete (String uuid);          @APIEventAnnotation(bindMenu=CustomMenuItem.reload)     @RequestMapping(value="dataUrl")     @ModuleAnnotation     @GridViewAnnotation     @ResponseBody     public   ListResultModel<List<FindAllGridView>> findAll ();         }


(6)动作菜单

动作菜单在DDD模型中并未定义,但在低代码应用却有着很重要的一席。

动作菜单建模中,主要将菜单展现与关联动作结合在一起。

编辑切换为居中

工作流发送菜单建模


菜单展现位置

编辑切换为居中

添加图片注释,不超过 140 字(可选)


编辑切换为居中

编辑器右键菜单

常用菜单注解

注解

位置

示例

@ToolBarMenu

容器顶部工具栏

@ToolBarMenu(hAlign = HAlignType.left, handler = false, menuClass = JavaRepositoryEditorTools.class)

@MenuBarMenu

顶部菜单栏

@MenuBarMenu(menuType = CustomMenuType.sub, caption = "新建", imageClass = "xuicon xui-uicmd-add", index = 5)

@BottomBarMenu

容器底部按钮栏

@BottomBarMenu(menuClass = CustomBuildAction.class)

@PageBar

分页栏

@PageBar(pageCount = 100)

@GridRowCmd

列表行操作按钮栏

@GridRowCmd(tagCmdsAlign = TagCmdsAlign.left, menuClass = {AttachMentService.class})

@RightContextMenu

右键菜单栏

@RightContextMenu(menuClass = JavaViewPackageMenu.class)

@Controller@RequestMapping(value ={"/java/agg/context/"})@MenuBarMenu(menuType =CustomMenuType.component, caption ="菜单")@Aggregation(type =AggregationType.menu)publicclassJavaAggPackageMenu{     @RequestMapping(method =RequestMethod.POST, value ="paste")    @CustomAnnotation(imageClass ="spafont spa-icon-paste", index =1, caption ="粘贴")    @APIEventAnnotation(customRequestData ={RequestPathEnum.treeview,RequestPathEnum.sTagVar}, callback =CustomCallBack.TreeReloadNode)    public@ResponseBody    TreeListResultModel<List<JavaAggTree>>paste(String sfilePath,String packageName,String domainId,String projectName){        TreeListResultModel<List<JavaAggTree>> result =newTreeListResultModel<List<JavaAggTree>>();        try{            DSMFactory dsmFactory =DSMFactory.getInstance();            File desFile =newFile(sfilePath);            DomainInst domainInst = dsmFactory.getAggregationManager().getDomainInstById(domainId);            JavaSrcBean srcBean = dsmFactory.getTempManager().genJavaSrc(desFile, domainInst,null);            DSMFactory.getInstance().getBuildFactory().copy(srcBean, packageName);            result.setIds(Arrays.asList(newString[]{domainId +"|"+ packageName}));        }catch(Exception e){            e.printStackTrace();        }        return result;    }     @RequestMapping(method =RequestMethod.POST, value ="reLoad")    @CustomAnnotation(imageClass ="xuicon xui-refresh", index =1, caption ="刷新")    @APIEventAnnotation(customRequestData =RequestPathEnum.treeview, callback =CustomCallBack.TreeReloadNode)    public@ResponseBody    TreeListResultModel<List<JavaAggTree>>reLoad(String packageName,String domainId,String filePath){        TreeListResultModel<List<JavaAggTree>> result =newTreeListResultModel<List<JavaAggTree>>();        String id = domainId +"|"+ packageName;        result.setIds(Arrays.asList(newString[]{id}));        return result;    }     @RequestMapping(value ={"split"})    @Split    @CustomAnnotation(index =2)    @ResponseBody    publicResultModel<Boolean>split2(){        ResultModel<Boolean> result =newResultModel<Boolean>();        return result;    }     @RequestMapping(value ="UploadFile")    @APIEventAnnotation(autoRun =true)    @DialogAnnotation(width ="450", height ="380", caption ="上传JAVA文件")    @ModuleAnnotation    @FormViewAnnotation    @CustomAnnotation(caption ="上传", index =3, imageClass ="xui-icon-upload", tips ="上传")    public@ResponseBody    ResultModel<UPLoadFile>uploadFile(String domainId,String packageName){        ResultModel<UPLoadFile> resultModel =newResultModel<UPLoadFile>();        try{            UPLoadFile upLoadFile =newUPLoadFile(domainId, packageName);            resultModel.setData(upLoadFile);        }catch(Exception e){            e.printStackTrace();        }        return resultModel;    }     @RequestMapping(value ={"split"})    @Split    @CustomAnnotation(index =4)    @ResponseBody    publicResultModel<Boolean>split6(){        ResultModel<Boolean> result =newResultModel<Boolean>();        return result;    }     @RequestMapping(method =RequestMethod.POST, value ="newApp")    @CustomAnnotation(imageClass ="xuicon xui-uicmd-add", index =5)    @MenuBarMenu(menuType =CustomMenuType.sub, caption ="新建", imageClass ="xuicon xui-uicmd-add", index =5)    publicJavaAggNewMenugetJavaJarAction(){        returnnewJavaAggNewMenu();    }     @RequestMapping(method =RequestMethod.POST, value ="importAgg")    @CustomAnnotation(imageClass ="xuicon xui-uicmd-add", index =6)    @MenuBarMenu(menuType =CustomMenuType.sub, caption ="导入", imageClass ="spafont spa-icon-html", index =5)    publicJavaAggImportMenuimportAgg(){        returnnewJavaAggImportMenu();    }     @RequestMapping(value ={"split"})    @Split    @CustomAnnotation(index =7)    @ResponseBody    publicResultModel<Boolean>split7(){        ResultModel<Boolean> result =newResultModel<Boolean>();        return result;    }     @MethodChinaName(cname ="删除")    @RequestMapping(method =RequestMethod.POST, value ="delete")    @CustomAnnotation(imageClass ="xuicon xui-icon-minus", index =8)    @APIEventAnnotation(customRequestData =RequestPathEnum.treeview, callback =CustomCallBack.TreeReloadNode)    public@ResponseBody    TreeListResultModel<List<JavaAggTree>>delete(String domainId,String parentId,String filePath,String javaTempId){        TreeListResultModel<List<JavaAggTree>> result =newTreeListResultModel<List<JavaAggTree>>();        try{            File desFile =newFile(filePath);            DSMFactory dsmFactory =DSMFactory.getInstance();            DomainInst domainInst = dsmFactory.getAggregationManager().getDomainInstById(domainId);            if(desFile.exists()){                if(desFile.isDirectory()){                    JavaPackage javaPackage = domainInst.getPackageByFile(desFile);                    dsmFactory.getTempManager().deleteJavaPackage(javaPackage);                }else{                    JavaSrcBean srcBean = dsmFactory.getTempManager().genJavaSrc(desFile, domainInst, javaTempId);                    dsmFactory.getTempManager().deleteJavaFile(srcBean);                }            }             result.setIds(Arrays.asList(newString[]{parentId}));         }catch(JDSException e){            e.printStackTrace();        }         return result;    }     publicESDChromegetCurrChromeDriver(){        Object handleId =JDSActionContext.getActionContext().getParams("handleId");        ChromeDriver chrome =null;        if(handleId !=null){            chrome =ESDEditor.getInstance().getChromeDriverById(handleId.toString());        }        if(chrome ==null){            chrome =ESDEditor.getInstance().getCurrChromeDriver();        }        returnnewESDChrome(chrome);    }}


(7)通用域

通用域将系统中常用服务进行了独立分类可以在工程构建时导入进来。

编辑切换为居中

通用域管理

(8)API服务接口

 api服务接口是手工代码接入的域服务,在普通java类上加上聚和接口后会统一归类到该类型管理。


(9)领域模型常用注解

注解名称

用途

实例

@RequestMapping

直接使用的SpringMvc注解用于将当前方法标识为,web可访问

@RequestMapping(value = {"AggAPITree"}, method = {RequestMethod.GET, RequestMethod.POST})

@ModuleAnnotation

视图标识,在方法上标识改注解后会被模型编译器识别为视图模型将其内部对象渲染为视图。

@ModuleAnnotation(dynLoad = true, imageClass = "spafont spa-icon-moveforward", caption = "模块授权")

@ResponseBody

直接使用的SpringMvc注解,标识为JSON数据返回

@ResponseBody

@DialogAnnotation

添加该标识时,当前端路由到当前方法时,以独立窗口的方式返回

@DialogAnnotation(width = "850", height = "750")

@Aggregation

领域标识,在类注解中添加该标识,会被DSM引擎自动索引并根据注解中指定类型加载到相关的实体列表中

@Aggregation(type = AggregationType.customDomain,

sourceClass = PersonService.class,

rootClass = Person.class)

@*Domain

通用域标识

@OrgDomain

@BpmDomain

@VfsDomain

@MsgDomain

@NavDomain

@*TreeView

树形注解包括了,导航树、弹出字典树,折叠分组树等注解集合

@TreeViewAnnotation

@NavTreeViewAnnotation

@NavFoldingTreeViewAnnotation

@PopTreeViewAnnotation

@GridViewAnnotation

数据列表注解

@GalleryView*Annotation

详情图形混合注解

@GalleryViewAnnotation

@NavGalleryViewAnnotation

@*TabsViewAnnotation

Tab切换页

@TabsViewAnnotation

@NavTabsViewAnnotation

@NavFoldingTabsViewAnnotation

@PopMenuViewAnnotation

菜单导航

@PopMenuViewAnnotation

@NavGroupViewAnnotation

分组表单

@NavGroupViewAnnotation

@FormViewAnnotation

表单注解

@FormViewAnnotation

@*ButtonViewsViewAnnotation

按钮栏视图

@ButtonViewsAnnotation

@NavButtonViewsAnnotation

后续章节内容介绍

在下一章节中,我们将重点介绍,OneCode视图工厂以及,模块组装,权限设定、菜单应用等相关工具使用。

章节预览:

视图工厂,最终面向用户的展现方式,在建模中通常会有相关的服务通过聚合实体与关系完成初步的视图构建。

编辑切换为居中

视图工厂组成

        在领域工厂中,更多是将贫血性的基础实体对象进行聚合分类整理,形成更利于业务理解与操作的充血模型,并且通过在其接口模型上扩展注解的方式实现其低耦合应用。视图工厂中仍然延续这一风格设计将普通单一的组件通过,后端JAVA代码的聚合将常用功能以及辅助组件进行业务封装形成独立的视图组件。

常用列表功能

编辑切换为居中

常用配置


列表信息配置

编辑切换为居中

添加图片注释,不超过 140 字(可选)


相关文章
|
6月前
|
领域建模
架构设计 DDD领域建模 核心概念
【1月更文挑战第6天】架构设计 DDD领域建模 核心概念
|
设计模式 缓存 自然语言处理
DDD领域驱动设计如何进行工程化落地
DDD领域驱动设计到底如何进行实际的工程化落地,为什么要进行领域分层?本文主要围绕DDD领域分层,设计了可落地的工程结构。
DDD领域驱动设计如何进行工程化落地
|
1月前
|
存储 前端开发 API
DDD领域驱动设计实战-分层架构
DDD分层架构通过明确各层职责及交互规则,有效降低了层间依赖。其基本原则是每层仅与下方层耦合,分为严格和松散两种形式。架构演进包括传统四层架构与改良版四层架构,后者采用依赖反转设计原则优化基础设施层位置。各层职责分明:用户接口层处理显示与请求;应用层负责服务编排与组合;领域层实现业务逻辑;基础层提供技术基础服务。通过合理设计聚合与依赖关系,DDD支持微服务架构灵活演进,提升系统适应性和可维护性。
|
3月前
|
缓存 架构师 中间件
成为工程师 - 如何做DDD领域驱动设计?
成为工程师 - 如何做DDD领域驱动设计?
|
架构师 算法 测试技术
小团队也能做DDD-中篇
小团队也能做DDD-中篇
231 0
|
消息中间件 JavaScript 小程序
领域驱动设计(DDD)的几种典型架构介绍
领域驱动设计(DDD)的几种典型架构介绍
|
Java API 领域建模
领域驱动设计(DDD)-简单落地
一、序言     领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。在本文中的实战示例可能会与常见的DDD规则方法不太一样,是简单、入门级别,新手可以快速实践版的DDD。如果不熟悉DDD设计思想可看下基础思想篇 二、设计阶段     领域建模设计阶段常见的方法有 四色建模法、EventSourcing等 推荐一篇博文正确理解领域建
12165 1
|
存储 开发框架 Java
「软件设计」权威领域驱动设计(DDD)简介
「软件设计」权威领域驱动设计(DDD)简介
|
设计模式 领域建模 数据库
DDD领域驱动设计落地实践系列:初识DDD
笔者在经历的很多项目中都使用了DDD领域驱动设计进行架构设计,尤其是在业务梳理、中台规划以及微服务划分等方面,DDD是重要的架构设计方法论,对平时的架构设计有非常好的指导作用。从本文开始笔者将通过一系列的文章阐述自己对于DDD的理解以及如何在项目实战中落地实践DDD。本文作为系列文章的开端,主要和大家聊聊DDD的一些基本概念以及常用方法。
DDD领域驱动设计落地实践系列:初识DDD
|
敏捷开发 监控 架构师
DDD 领域驱动设计落地实践系列:微服务拆分之道
在前面的两篇文章中,笔者给大家介绍了 DDD 核心思想、重要概念以及如何进行 DDD 进行微服务实践的大致过程,后续的文章中将逐渐深入 DDD 的实践细节,包括领域模型与代码模型的映射以及具体的微服务设计实例等。当下微服务盛行,微服务架构解决了单点系统的可用性问题、突破单节点服务的性能瓶颈同时提升了整个系统的稳定性。因此各大公司纷纷转向微服务架构,但是在实际的微服务拆分过程中也会遇到不少的问题。而 DDD 中的领域模型构建以及边界上下文的划分天然的和微服务划分有着异曲同工之妙,因此结合 DD 领域驱动设计来进行微服务拆分是一种比较好的微服务拆分方案。那么今天就和大家聊聊怎么进行微服务拆分。
DDD 领域驱动设计落地实践系列:微服务拆分之道