博客 / 詳情

返回

COLA常用組件

  • BiliBili視頻

Maven依賴

  • pom.xml

      <properties>
          <cola.components.version>5.0.0</cola.components.version>
      </properties>
    
      <!-- 版本管理 -->
      <dependencyManagement>
          <dependencies>
              <dependency>
                  <groupId>com.alibaba.cola</groupId>
                  <artifactId>cola-components-bom</artifactId>
                  <version>${cola.components.version}</version>
                  <type>pom</type>
                  <scope>import</scope>
              </dependency>
          </dependencies>
      </dependencyManagement>
    
      <!-- 組件 -->
      <dependencies>
          <dependency>
              <groupId>com.alibaba.cola</groupId>
              <artifactId>cola-component-dto</artifactId>
          </dependency>
          <dependency>
              <groupId>com.alibaba.cola</groupId>
              <artifactId>cola-component-exception</artifactId>
          </dependency>
          <dependency>
              <groupId>com.alibaba.cola</groupId>
              <artifactId>cola-component-catchlog-starter</artifactId>
          </dependency>
          <dependency>
              <groupId>com.alibaba.cola</groupId>
              <artifactId>cola-component-domain-starter</artifactId>
          </dependency>
          <dependency>
              <groupId>com.alibaba.cola</groupId>
              <artifactId>cola-component-extension-starter</artifactId>
          </dependency>
          <dependency>
              <groupId>com.alibaba.cola</groupId>
              <artifactId>cola-component-statemachine</artifactId>
          </dependency>
          <dependency>
              <groupId>com.alibaba.cola</groupId>
              <artifactId>cola-component-test-container</artifactId>
          </dependency>
    
        <!-- ruleengine -->
      </dependencies>

dto

  • 規範請求參數、規範響應結果,Api對接統一處理
        <dependency>
            <groupId>com.alibaba.cola</groupId>
            <artifactId>cola-component-dto</artifactId>
        </dependency>

請求

Query/Command

  • Query類中沒有任何字段,僅標識讀數據請求
@Data
@EqualsAndHashCode(callSuper = true)
public class UserFindQry extends Query {
    @Parameter(title = "姓名(模糊搜索)")
    private String name;
}
  • Command類中沒有任何字段,僅標識寫數據請求
@Data
@EqualsAndHashCode(callSuper = true)
public class UserAddCmd extends Command {
    @Schema(title = "姓名")
    @NotBlank(message = "name不能為空")
    private String name;

    @Schema(title = "性別")
    @NotEmpty(message = "sex不能為空")
    private Sex sex;

    @Schema(title = "密碼")
    @NotBlank(message = "password不能為空")
    private String password;
}

PageQuery

  • PageQuery是分頁請求,包含了分頁需要的字段

    • int pageIndex: 頁碼,默認1
    • int pageSize: 頁面大小,默認10
    • String orderBy: 排序字段
    • String orderDirection: 排序方向,"ASC"/"DESC"
    • String groupBy: 分組
    • boolean needTotalCount: 是否顯示總行數
@Data
@EqualsAndHashCode(callSuper = true)
public class UserPageQry extends PageQuery {
    @Parameter(description = "姓名")
    private String name;

    @Parameter(description = "性別")
    private Sex sex;
}

響應

  • Response是所有響應類的基類,理論上返回值都可以用Response
  • 但是建議寫成"SingleResponse<...>"這樣的子類,Swagger文檔生成的響應值更加明確,有利於團隊協作

    Response

  • 響應結果,所有響應的基類,即所有響應必定有以下字段
  • 其他系統對接時做統一解析

    • HTTP對接,使用狀態碼判斷結果
    • RPC對接,使用"success"判斷結果
    {
    "success": true,
    "errCode": "string",
    "errMessage": "string"
    }
  • 示例:無需返回值的結果

      public Response delete(Long id) {
          // 直接響應成功
          return Response.buildSuccess();
    
          // 可直接響應失敗,但一般用在異常處理中,配合響應碼使用
          // return Response.buildFailure("UNKNOWN_ERROR","錯誤信息");
      }

    SingleResponse

  • 返回一個對象,格式如下

    {
    "success": true,
    "errCode": null,
    "errMessage": null,
    "data": null
    }
  • 示例:返回用户詳情

      public SingleResponse<UserDetailCO> getDetail(Long id) {
          UserDetailCO detailCO = ...;
          // 返回一個對象結果
          return SingleResponse.of(detailCO);
      }

    MultiResponse

  • 返回列表,格式如下

    {
    "success": true,
    "errCode": null,
    "errMessage": null,
    "empty": true,
    "notEmpty": false,
    "data": []
    }
  • 示例:返回所有用户

      public MultiResponse<UserDetailCO> getAll() {
          List<UserDetailCO> allUser = userService.getAll();
          return MultiResponse.of(allUser);
      }

    PageResponse

  • 返回分頁信息,格式如下

    {
    "success": true,
    "errCode": null,
    "errMessage": null,
    "empty": true,
    "notEmpty": false,
    "pageIndex": 1,
    "pageSize": 10,
    "totalPages": 0,
    "totalCount": 0,
    "data": []
    }
  • 示例:返回用户分頁

      public PageResponse<UserPageCO> getPage(UserPageQry qry) {
          List<UserPageCO> list = ...;
          int totalCount = ...;
          return PageResponse.of(list, totalCount, qry.getPageSize(), qry.getPageIndex());
      }

exception

  • 官網定義:https://github.com/alibaba/COLA/tree/master/cola-components/cola-component-exception

    • BizException: 業務異常,有明確業務語義,不需要記錄Error日誌,不需要Retry

      • 如:請求參數錯誤,賬户餘額不足等
    • SysException: 已知的系統異常,需要記錄Error日誌,可以Retry

      • 如:數據庫無法連接,RPC調用失敗等
    • Exception: 未知的其它異常,需要完整的Error Stack日誌,可以Retry
        <dependency>
            <groupId>com.alibaba.cola</groupId>
            <artifactId>cola-component-exception</artifactId>
        </dependency>

業務拋出異常

  • 使用COLA中的Assert拋出BizException異常
import com.alibaba.cola.exception.BizException;
import com.alibaba.cola.exception.SysException;
import com.alibaba.cola.exception.Assert;


// 直接拋出異常
throw new BizException("這裏寫業務錯誤信息");
throw new BizException("UNKNOWN_ERROR","這裏寫業務錯誤信息");

throw new SysException("這裏寫系統錯誤信息");
throw new SysException("SYSTEM_ERROR","這裏寫系統錯誤信息");

// Assert不通過時,拋出BizException異常
Assert.isFalse(user == null, "user不能為null");
// 自定義錯誤碼,默認錯誤碼是"BIZ_ERROR"
Assert.isFalse(user == null, "DATA_NOR_FOUND_ERROR", "user不能為null");

全局異常捕捉

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(BizException.class)
    public Response handleBizException(BizException e) {
        // 業務異常,無需記錄日誌
        return Response.buildFailure(e.getErrCode(), e.getMessage());
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(SysException.class)
    public Response handleSysException(SysException e) {
        // 已知系統異常,打印報錯信息
        log.warn("已知系統異常:{} {}", e.getErrCode(), e.getMessage());
        return Response.buildFailure(e.getErrCode(), e.getMessage());
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(Exception.class)
    public Response handleException(Exception e) {
        // 未知系統異常,打印堆棧信息
        log.error("未知系統異常: {}", e.getMessage(), e);
        return Response.buildFailure("UNKNOWN_ERROR", e.getMessage());
    }
}

catchlog-starter

  • 使用aop打印方法入參出參,以及耗時
  • 官方説明:https://github.com/alibaba/COLA/tree/master/cola-components/cola-component-catchlog-starter
  • @CatchAndLog註解在類上
  • 注意fastjson的版本,是fastjson的2.x版本,而不是fastjson2
        <!-- cola示例放在app包 -->
        <dependency>
            <groupId>com.alibaba.cola</groupId>
            <artifactId>cola-component-catchlog-starter</artifactId>
        </dependency>

        <!-- 打印日誌依賴fastjson-2.x版本,底層為fastjson2的兼容版本 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.51</version>
        </dependency>
  • 入口類增加掃描配置"com.alibaba.cola"
@SpringBootApplication(scanBasePackages = {"com.xxc.demo", "com.alibaba.cola"})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • start/resource/logback-spring.xml

    • 日誌級別為"DEBUG"
<!-- 日誌記錄組件的日誌 -->
<logger name="com.alibaba.cola.catchlog" level="DEBUG" />
  • 需要的類中註解

    • @CatchAndLog註解在類上,因為aop匹配使用@within(),匹配類註解
// 或者放在Controller層
@CatchAndLog    // aop匹配使用@within,匹配類註解
public class UserServiceImpl implements UserService{
    // ...
}
  • 打印日誌示例如下

    • 打印請求參數、響應解僱、耗時
# 正常響應日誌
DEBUG c.alibaba.cola.catchlog.CatchLogAspect   : START PROCESSING: UserServiceImpl.getPage(..)
DEBUG c.alibaba.cola.catchlog.CatchLogAspect   : REQUEST: {"pageIndex":1,"pageSize":10}
#...其他日誌
DEBUG c.alibaba.cola.catchlog.CatchLogAspect   : RESPONSE: {"data":{"current":1,"pages":0,"records":[{"age":18,"id":1,"name":"老王"},{"age":18,"id":2,"name":"老王"},{"age":0,"id":3,"name":"string"}],"size":10,"total":0},"success":true}
DEBUG c.alibaba.cola.catchlog.CatchLogAspect   : COST: 520ms


# 報錯日誌
DEBUG c.alibaba.cola.catchlog.CatchLogAspect   : START PROCESSING: UserServiceImpl.getPage(..)
DEBUG c.alibaba.cola.catchlog.CatchLogAspect   : REQUEST: {"pageIndex":1,"pageSize":10}
WARN c.alibaba.cola.catchlog.CatchLogAspect   : BIZ EXCEPTION : 故意報錯
ERROR c.alibaba.cola.catchlog.CatchLogAspect   : 故意報錯
# ...報錯堆棧
WARN c.a.c.catchlog.ApplicationContextHelper  : No bean found for com.alibaba.cola.catchlog.ResponseHandlerI
DEBUG c.alibaba.cola.catchlog.CatchLogAspect   : RESPONSE: {"errCode":"BIZ_ERROR","errMessage":"故意報錯","success":false}
DEBUG c.alibaba.cola.catchlog.CatchLogAspect   : COST: 227ms

domain-starter

  • 使用@Entity註解scope為"prototype"的Bean
  • DomainFactory實例化Bean
        <!-- cola archetypes生成 -->
        <dependency>
            <groupId>com.alibaba.cola</groupId>
            <artifactId>cola-component-domain-starter</artifactId>
        </dependency>
  • 入口類增加掃描配置"com.alibaba.cola"
@SpringBootApplication(scanBasePackages = {"com.xxc.demo", "com.alibaba.cola"})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 註解為@Entity,scope為"prototype"的Bean
import com.alibaba.cola.domain.Entity;

@Entity
public class Heartbeat{
    // ...
}
  • 使用DomainFactory實例化一個對象
@Component
public class HeartbeatExe{
    @Async
    public void execute(){
        // 獲取新對象
        Heartbeat heartbeat = DomainFactory.create(Heartbeat.class);
        //...
    }
}
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.