Maven依賴
<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
<dependency>
<groupId>com.alibaba.cola</groupId>
<artifactId>cola-component-dto</artifactId>
</dependency>
請求
Query/Command
@Data
@EqualsAndHashCode(callSuper = true)
public class UserFindQry extends Query {
@Parameter(title = "姓名(模糊搜尋)")
private String name;
}
@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);
}
{
"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
- 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
<!-- 日誌記錄元件的日誌 -->
<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{
// ...
}
@Component
public class HeartbeatExe{
@Async
public void execute(){
// 獲取新物件
Heartbeat heartbeat = DomainFactory.create(Heartbeat.class);
//...
}
}