本文介绍工程的脚手架结构、依赖关系和相关Annotation注解。

工程脚手架结构

工程脚手架结构示例如下:

1

工程Module

Module 职责 说明
Entry 核心业务入口。 业务入口,当应用通过SpringCloud实现则Controller在该模块编写,通过Controller调用底层业务逻辑形成闭环。
App 业务调用入口。 Entry通过调用App层实现业务逻辑调用。App层需要负责调用Domain层业务逻辑,且将DTO与Domain Entity进行转换。
Domain 领域实现层:核心业务逻辑。 Domain层主要编写业务逻辑,业务通过建模后,业务逻辑通过Domain Entity和Domain Service来承载,因此是充血模型的方式来完成代码开发。

当涉及对外调用时,则通过调用Domain层定义的Repository Interface来完成,而具体外部访问的技术实现由Infrastructure实现。

Infrastructure 基础设施层:负责技术实现,包括访问DB、Cache、RPC、MQ等。 Domain会实现业务逻辑,而业务逻辑中涉及到技术实现的部分(例如:保存、RPC请求、MQ发送消息、缓存等)都通过Infrastructure在Repository Impl实现。

Infrastructure除了技术实现,还包括DO定义、DO与Domain Entity的互相转换,以及集成并调用外部服务的Client。

Starter 应用启动。 独立应用启动的包,方便启动方式插拔变更。
Client 商业能力、域服务接口定义。 外部应用集成的SDK,便于能力调用。在SDK中定义包括:商业能力、域服务接口定义、接口入参和返回值DTO、接口返回错误码定义、业务自定义异常定义等。
Extension 负责扩展点接口定义。 外部应用集成SDK,便于根据扩展点定义实现自定义扩展点业务逻辑。

Module依赖关系

Module之间的依赖关系详情如下图所示:

1

Module请求流向

Module请求流向详情如下图所示:

1

工程Annotation注解

BizWorks规范注解

注解 含义 常用属性 说明
@ApplicationService 应用服务注解
  • domain:业务域的编码
  • name:应用服务的名称
  • desc:应用服务的描述
加在接口上,声明该接口属于应用服务。
@DomainService 领域服务注解
  • domain:业务域的编码
  • name:领域服务的名称
  • desc:领域服务的描述
加在类上,声明该类属于领域服务。
@DomainObject 领域对象注解
  • domain:业务域的编码
  • name:领域对象的名称
  • desc:领域对象的描述
  • isAggregateRoot:是否聚合根(truefalse
加在类上,声明该类属于领域对象。
@ValueObject 值对象注解
  • domain:业务域的编码
  • name:值对象的名称
  • desc:值对象的描述
加在类上,声明该类属于值对象。
@StructureObject 结构对象注解
  • asset:业务域或者商业能力的编码
  • assetType:模型类型(商业能力还是业务域)
  • name:结构对象的名称
  • desc:结构对象的描述
加在类上,声明该类属于结构对象。
@ExtensionPoint 扩展点注解
  • domain:扩展点的编码
  • name:扩展点的名称
  • desc:扩展点的描述
加在方法上,声明该方法属于扩展点。
@Field 属性注解
  • name:字段的名称
  • value:字段的描述
加在属性上。
@Method 方法注解
  • name:方法的名称
  • value:方法的描述
加在方法上。
@Related 扩展点注解 to:扩展点指向的类 加在方法上,扩展点不独立存在,扩展点依附于应用服务。
@Parameter 参数注解
  • name:参数的名称
  • value:参数的描述
加在方法入参上。
@ReturnValue 返回值注解
  • name:方法的名称
  • value:方法的描述
当方法有返回值时加在方法上。

添加POM依赖

添加POM依赖示例如下:

<dependency>
      <groupId>com.alibaba.bizworks</groupId>
      <artifactId>core-specification</artifactId>
      <version>${bizworks-app-framework.version}</version>
</dependency>

 <dependency>
      <groupId>com.alibaba.bizworks</groupId>
     <artifactId>core-runtime-container</artifactId>
      <version>${bizworks-app-framework.version}</version>
</dependency>
Annotation注解示例
  • 应用服务@ApplicationService
    @PostMapping("/DemoAppService")
    @ApplicationService(domain = "DemoDomain" , name = "示例应用服务", desc = "示例应用服务描述")
    public interface DemoAppService {
    
        @ReturnValue(value = "SingleResponse结构验证", name = "SingleResponse结构验证")
        @Method(value = "创建用户", name = "创建用户")
        @PostMapping(value = "/createUser")
        SingleResponse createUser(@Parameter(value = "参数描述信息", name = "参数名", required = true)
                                             @Valid @RequestBody UserDTO userDTO);
    
      }
    }
    此示例中包含了@ApplicationService@ReturnValue@Method@Parameter注解的使用样例。
    说明 @ApplicationService注解中domain的属性值必须是建立的业务域的编码。本文中domain属性值的来源都必须遵循这个规则,同一个业务域domain属性值必须相同。
  • 应用服务的结构对象@StructureObject

    应用服务的出入参数若为Java对象,则该Java对象通常都应被标注为结构对象。

    @Getter
    @Setter
    @StructureObject(name = "用户对象DTO", desc = "用户对象DTO")
    public class UserDTO {
    
        @Field(value = "用户名", name = "用户名")
        private String username;
    
        @Field(value = "邮箱", name = "邮箱")
        private String email;
    }
    此示例中包含了@StructureObject@Field注解的使用样例。
    说明 @StructureObjectasset的属性值必须是建立的业务域的编码,且assetType = "MODULE_CENTER"
  • 领域对象@DomainObject(实体对象)及@ValueObject(值对象)
    @Data
    @DomainObject(domain = "DemoDomain", isAggregateRoot = true, name = "用户", desc = "用户")
    public class User extends BaseEntity {
    
        @Field(value = "用户名", name = "用户名")
        private String username;
    
        @Field(value = "邮箱", name = "邮箱")
        private String email;
    
    }
    @ValueObject(domain = "DemoDomain", name = "地址", desc = "地址")
    public class Address {
    
        @Field(value = "区域", name = "区域")
        private String region;
    
        @Field(value = "详细地址", name = "详细地址")
        private String detail;
    
    }

    此示例中包含了@DomainObject@ValueObject@Field注解的使用样例。

  • 领域服务@DomainService
    @DomainService(domain = "DemoDomain", name = "示例领域服务", desc = "示例领域服务描述")
    public class DemoDomainService {
    
        @ReturnValue(value = "返回值描述", name = "返回值名称")
        @Method(value = "关联用户地址", name = "关联用户地址")
        public SingleResponse bind(User user, Address address) {
            // 调用领域对象1.方法()
            // 调用领域对象2.方法()
            return SingleResponse.buildSuccess();
        }
    
    
    }

    此示例中包含了@DomainService@ReturnValue@Method@Parameter注解的使用样例。

  • 商业能力@BusinessCapabilityService
    @PostMapping("/DemoBizCapService")
    @BusinessCapabilityService(businessCapability = "DemoBizCap", desc = "示例商业能力服务描述 desc", name = "示例商业能力服务")
    public interface DemoBizCapService {
    
        @ReturnValue(value = "SingleResponse结构验证", name = "SingleResponse结构验证")
        @Method(value = "验证并激活用户", name = "验证并激活用户")
        @PostMapping(value = "/verifyAndActive")
        SingleResponse verifyAndActive(@Parameter(value = "参数描述信息", name = "参数名", required = true)
                                             @RequestBody UserInfoDTO userInfoDTO);
    
    
    }
    此示例中包含了@BusinessCapabilityService@ReturnValue@Method@Parameter注解的使用样例。
    说明 @BusinessCapabilityService 注解中businessCapability的属性值必须是建立的商业能力的编码,本文中businessCapability属性值的来源都必须遵循这个规则,同一个商业能力的businessCapability属性值必须相同。
  • 商业能力的结构对象@StructureObject

    商业能力服务的方法出入参数若为Java对象,该Java对象通常都应被标注为结构对象。商业能力的结构对象应用服务的结构对象没有区别,示例:略。

用配置文件替代注解

采用以上注解的添加方式其实已经可以实现业务域商业能力的扫描上报。但是如果不希望在代码注解里标注业务域商业能力编码类型,您可以采用配置文件的方式来描述这部分信息。在如下图所示位置(启动Module的resources/bizworks路径下),添加modules.yaml文件。1
modules.yaml文件样例如下:
---
bizworks:
  modules:
  - type: "MODULE_CENTER"
    code: "ExtendsDoamin"
    packages:
    - "com.alibaba.bizworks.testapp11.businessdomain.extendsdoamin"
  - type: "BUSINESS_CAPABILITY"
    code: "BindBiz03"
    packages:
    - "com.alibaba.bizworks.testapp11.businesscapability.bindbiz03"
关于modules.yaml属性的含义,请参见下表:
参数 含义 说明
type 类型 业务域:MODULE_CENTER 商业能力:BUSINESS_CAPABILITY。
code 编码 业务域或商业能力的编码。
packages 包路径 代码扫描的包路径。

配置BWAF日志组件

BWAF框架日志打印需要添加如下依赖:
<dependency>
  <groupId>com.alibaba.bizworks</groupId>
  <artifactId>logging</artifactId>
  <version>${bizworks-app-framework.version}</version>
</dependency>
添加依赖后,重启服务,发起请求,即可查看到BWAF相关日志输出。1

配置本地调试BWAF参数

在本地调试的时候,为了您的项目可以正常运行,需要添加以下配置。
bizworks:
#此处配置为该工程的applicationCode。
  appId: myAppId                            # 应用ID(仅本地运行时需要配置,平台部署时由平台注入环境变量)。
  bizId: myBizId                            # 业务身份 (中心应用一般不需要配置该项)。
  appVersion: 1.0.6                         # 应用版本(仅本地运行时需要配置,平台部署时由平台注入环境变量)。
  tenantId: myTenantId                      # 租户ID(仅本地运行时需要配置,平台部署时由平台注入环境变量)。
  envId: myProject.myEnv                    # 环境ID ${项目ID}.{环境ID}(仅本地运行时需要配置,平台部署时由平台注入环境变量)。
  endpoint: bw.app.bizworks.cn              # 应用本身的Endpoint(仅本地运行时需要配置,平台部署时由平台注入环境变量)。
  extensionPointRegistryServer: bizworks-registry.bizworks.svc.cluster.local  # 扩展点注册中心地址。
  projectId: national-tobacco-project       # 当前项目ID(仅本地运行时需要配置,平台部署时由平台注入环境变量)。