博客 / 詳情

返回

COLA各模塊理解

  • COLA架構使用過程中對各模塊的一些理解
  • BiliBili視頻:https://www.bilibili.com/video/BV1Kw4m1e7oX/

domain

  • 與傳統結構最大的不同,就是領域層
  • 領域層的作用是讓我們使用面相對象的思想去編寫領域對象

    面相對象

  • 初學Java時,一直在強調Java是面相對象語言
  • 對象有屬性和方法(行為)

    public class Dog {
      String name;
      int age;
    
      void eat() {
      }
    
      void run() {
      }
    }

    面相表格

  • 工作一段時間後,感覺較面向表格更為貼切
  • 從數據庫獲取一行數據,修改某些屬性,再保存回去

    • 包含大量膠水代碼,無法複用
    @Data
    public class User {
      private Long id;
      private String name;
      private Integer age;
      private String password;
    }
    public class UserService {
      @Autowired
      private UserMapper userMapper;
    
      public void changeInfo(Long id) {
          User user = userMapper.selectById(id);
          user.setName("張三");
          user.setAge(18);
          user.setPassword(getMd5("123456"));
          userMapper.updateById(user);
      }
    
      private String getMd5(String password) {
          return password + "-md5"; // 模擬
      }
    }

    領域對象

  • 領域對象其實是迴歸面向對象的做法
  • 將邏輯內聚到領域對象中

    @Data
    public class User {
      private Long id;
      private String name;
      private Integer age;
      private String password;
    
      public void changeInfo(String name, Integer age, String password) {
          this.name = name;
          this.age = age;
          this.password = getMd5(password);
      }
    
      private String getMd5(String password) {
          return password + "-md5"; // 模擬
      }
    }
  • 減少膠水代碼,更易複用

    public class UserService {
      @Autowired
      private UserGateway gateway;
    
      public void changeInfo(Long id) {
          User user = gateway.get(id);
          user.changeInfo("張三", 18, "12345");
          gateway.save(user);
      }
    }

    領域對象與數據對象

  • 領域對象和數據對象為什麼分開?為什麼不合在一起,寫個充血的數據對象,當做領域模型?
  • 職責單一,各司其職,更利於維護

    代碼實例

  • 領域對象中,只需要處理好自己的邏輯

    @Data
    public class User {
      private Long id;
      private String name;
      private List<String> roles; // 權限列表
    
      public User(String name) {
          this.name = name;
          this.roles = new ArrayList<>();
      }
    
      public void addRole(String role) {
          this.roles.add(role);
      }
    }
  • 在數據對象中,考慮如何存儲,如"roles"可以用不同方式存儲

    • json字符串
    • ","逗號隔開的字符串
    • 一對多的關聯表
    // 數據對象
    @Data
    @TableName("user")
    public class UserDO {
      @TableId(type = IdType.AUTO)
      private Long id;
      private String name;
      private String rolesJson; // 轉換為json字符串
    }
  • 領域對象和數據對象間使用轉換器執行轉換

    • 可使用"MapStruce"和"FastJson"實現
    @Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
    public interface UserConvertor {
    
      @Mapping(target = "rolesJson", expression = "java(map(entity.getRoles()))")
      UserDO toDataObject(User entity);
    
      @Mapping(target = "roles", expression = "java(map(dataObject.getRolesJson()))")
      User toEntity(UserDO dataObject);
    
      default String map(List<String> roles) {
          return JSON.toJSONString(roles);
      }
    
      default List<String> map(String rolesJson) {
          return JSON.parseArray(rolesJson, String.class);
      }
    }
  • 當業務拓展時,Role需要增加字段做更多功能,用户表裏的roles由Json變更為Role子數據表
  • 這樣的設計能夠儘可能減少代碼修改

    反例

  • 如果省略領域模型,直接將數據模型寫成充血模型

    • 好消息:減少代碼量,減少類
    • 壞消息:不好維護,屎山代碼
    @Data
    @TableName("user")
    public class UserEntity {
      @TableId(type = IdType.AUTO)
      private Long id;
      private String name;
    
      @TableField(exist = false)
      private List<String> roles; // 字段不映射數據表
    
      private String rolesJson;   // 存儲字段
    
      public UserEntity(String name) {
          this.name = name;
          this.roles = new ArrayList<>();
          this.rolesJson = "[]";
      }
    
      public void addRole(String role) {
          this.roles.add(role);
          this.rolesJson = JSON.toJSONString(this.roles);
      }
    }

    client

  • client層主要用於微服務架構
  • 非常適合與Dubbo搭配使用

    client接口定義

  • client層的api中編寫服務接口

    public interface UserServiceI{
      // 略
    }

    cleint打包發佈私有Maven

  • pom.xml
  • 設置Maven私有倉庫(Nexus3)配置

      <dependencies>...略</dependencies>
      <build>...略</build>
    
      <distributionManagement>
          <repository>
              <id>maven-releases</id>
              <name>maven-releases</name>
              <url>${這裏填寫從nexus頁面上覆制的maven-releases的url}</url>
          </repository>
          <snapshotRepository>
              <id>maven-snapshots</id>
              <name>maven-snapshots</name>
              <url>${這裏填寫從nexus頁面上覆制的maven-snapshots的url}</url>
          </snapshotRepository>
      </distributionManagement>
  • maven-settings.xml
  • 私有倉庫配置

    <?xml version="1.0" encoding="UTF-8"?>
    
    <settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
      <servers>
          <server>
              <id>maven-releases</id>
              <username>admin</username>
              <password>${密碼}</password>
          </server>
          <server>
              <id>maven-snapshots</id>
              <username>admin</username>
              <password>${密碼}</password>
          </server>
      </servers>
    </settings>
  • deploy.sh
  • maven打包腳本
  • 使用maven的容器鏡像,執行打包腳本

    # 複製maven配置文件
    cp maven-settings.xml /usr/share/maven/conf/settings.xml
    # 執行maven
    mvn deploy -pl cola-springboot-demo-client -am

    app層接口實現

  • app層,編寫實現類
  • 註冊為Dubbo服務

    @Service
    @DubboService    // 註冊為Dubbo服務
    public class UserServiceImpl implements UserServiceI{
      // 略
    }

    其他微服務RPC調用

  • 其他項目從私有Maven倉庫中加載client的接口及入參出參

    <dependency>
      <groupId>com.xxc</groupId>
      <artifactId>cola-springboot-demo-client</artifactId>
      <version>1.0.0</version>
    </dependency>
  • 在需要的地方調用,如

    • App層的Executor調用
    • infrastructure層的網關實現類中調用
    @Component
    public class XxxExe{
      @DubboReference
      private UserServiceI userService;
    
      public void execute(){
          // 略
      }
    }
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.