§0. 有話先說
0.1 幾個概念
api-應用程式介面,最狹隘的定義,指的是我們程式里類或介面的方法,
rpc-局域網內部跨應用通信框架,常見的有dubbo、thrift、HSF、Feign,
rpcapi-基本上可以跟程式內部api一樣用法的api,
0.2 someword:
下面說的引數,包括請求引數和回傳引數,
- 方法的引數,通常不建議使用Object、Map,不易讀,
- 方法的引數,如果都用String,比如JSON字串或其他拼裝起來的字串,不易讀是一方面,同時,潛在問題更多,你品,
- rpcapi,建議自行處理例外,別拋給呼叫方,
- 方法的引數,使用列舉會提高可讀性 @see,
- ,,,
0.3 為什么有本文?
書接前文,rpcapi雖然可以像程式內部api一樣,支持java各種資料型別,可以像呼叫程式內部api一樣呼叫rpcapi,不過,所不同的是,rpcapi應該處理各種可能的例外情況,而不是拋出例外,這使得rpcapi與restapi一樣,不能只是回傳資料(資源),而應該對可能出現的例外情況進行判斷,比如引數合法性,資料是否存在,資料狀態,程式例外,等等,當沒有例外情況時,才回傳所需資料(資源),因此,就有了本文下文說的Result<T>,
§1. 請求引數
1.1 如果引數比較少,比如少于3個,可以顯式定義出來,比如
getEnterpriseById(String enterpriseId)
getEnterpriseById(String enterpriseId,ProductEnum product)
1.2 如果引數超過3個,建議定義一個DTO,rpc傳輸物件暫定統一命名為DTO,請求dto命名建議以ReqDTO結尾,當然,如果請求回應都使用相同的dto的話,就直接以DTO結尾也未嘗不可,比如
addEnterprise(EnterpriseDTO enterprise);
selectEnterprise(EnterpriseDTO enterprise);
§2. 回應引數
2.1 首先,回應引數統一使用Result<T>,即,回傳值統一使用泛型,Result<T>主要成員有3個:
- int code - 回應碼,成功統一是200. 對應的code列舉定義在ResultCodeEnum.java里
- String msg - 回應描述,尤其是當非200的情況下,需要指出錯誤資訊,
- T result - 回應資料,一般在code=200的情況下會設定result,
Result<T>相關操作方法后文贅述,
2.2 其次,對于回傳資料來說,同1.1、1.2所述,
2.2.1 如果比較單一,比如就回傳一個交易量,可以是Result<Integer> selectTransCount(...),
2.2.2 如果回傳資料比較復雜,可以定義一個DTO,回應dto命名建議以RespDTO結尾,當然,如果請求回應都使用相同的dto的話,就直接以DTO結尾也未嘗不可,
2.2.2.1 如果你不愿意定義一個dto物件,也行,
可以考慮回傳JSON物件(JSON物件哦,不是JSON字串),即Result<JSONObject>,
也可以考慮回傳Map物件,比如Result<Map<String,Object>>,瞧瞧,使用map,有些情況下,就不可避免的涉及到Object,使用Object來傳參或作為方法回傳值是大忌,與CV大法一樣多少都會令人詬病,
2.2.3 對于回傳集合的情況,當然也很簡單,無非就是Result<List<EnterpriseDTO>>了唄,
§3. 強大的Result<T>
Result<T>是一個泛型類,ResultCodeEnum定義了code的列舉項,它們定義在com.emax.zhenghe:zhenghe-rpcapistyle包里,
maven dependency依賴:
<dependency>
<groupId>com.emax.zhenghe</groupId>
<artifactId>zhenghe-rpcapistyle</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
|
Result<T>重要成員方法:
Result<T>主要操作方法是設定回傳結果的(這不是廢話嘛~),回傳分兩種,成功的回傳,錯誤的回傳,因此,Result<T>定義了兩類方法,public static Result<T> success(...)和public static Result<T> err(...), 當然,為了方便大家使用,方法多載是免不了的,詳細見下面串列,總有一款適合你!
▄︻┻┳═一 public static <T> Result<T> success()
▄︻┻┳═一 public static <T> Result<T> success(T data)
▄︻┻┳═一 public static <T> Result<T> success(T data, String msg)
▄︻┻┳═一 public Result<T> successWithMsg(String message)
▄︻┻┳═一 public static <T> Result<T> err(String msg)
▄︻┻┳═一 public static <T> Result<T> err(ResultCodeEnum code, String msg)
▄︻┻┳═一 public static <T> Result<T> err(int code, String msg)
這個class的實作代碼呢, 一睹芳容吧!
public class Result<T> implements Serializable { /** * 回傳代碼 */ private int code = 0; /** * 回傳處理訊息 */ private String message = "操作成功!"; /** * 回傳資料物件 data */ private T result; // 服務提供方的操作方法-----開始 public static <T> Result<T> success(T data){ return success(data, "成功"); } public static <T> Result<T> success(T data, String msg) { Result<T> r = new Result<>(); r.setSuccess(true); r.setCode(CommonConstant.SC_OK_200); r.setResult(data); return r; } public static <T> Result<T> success() { Result<T> r = new Result<>(); r.setSuccess(true); r.setCode(CommonConstant.SC_OK_200); r.setMessage("成功"); return r; } public Result<T> successWithMsg(String message){ this.message = message; this.code = CommonConstant.SC_OK_200; this.success = true; return this; } public static <T> Result<T> err(String msg) { return err(ResultCodeEnum.INTERNAL_SERVER_ERROR, msg); } public static <T> Result<T> err(ResultCodeEnum code, String msg) { return err(code.getCode(), StringUtils.isBlank(msg) ? code.getMsg() : msg); } public static <T> Result<T> err(int code, String msg) { Result<T> r = new Result<>(); r.setCode(code); r.setMessage(msg); r.setSuccess(false); return r; } // 服務提供方的操作方法-----結束 // 服務提供方的操作方法-----開始 // 客戶端接收到回應后,可以使用isSuccess來判斷是否成功,成功后,可以獲取回傳資料進行后續處理;不成功,則可以 getCode()和 getMessage()來記錄code和msg, public boolean isSuccess() { return code == ResultCodeEnum.SUCCESS.getCode(); } public int getCode() { return code; } public String getMessage() { return message; } public T getResult() { return this.result; } // 服務提供方的操作方法-----結束 }
對擴展開放
注意到了嗎?Result的code是int型別,不是上文提到的ResultCodeEnum列舉,
why?code定義成ResultCodeEnum當然是再好不過了,程式使用列舉要比數字易讀多了,為什么不這么做呢?——為了考慮擴展,試想,如果現有ResultCodeEnum的列舉項不滿足你的專案需要,你是不是要增加ResultCodeEnum列舉項?是的,那么,這時,就要去修改zhenghe-rpcapistyle的原始碼,而zhenghe-rpcapistyle在另一個專案里,隨著依賴zhenghe-rpcapistyle的專案的逐漸增多,ResultCodeEnum也許將變得尤其難于使用,
因此,如果zhenghe-rpcapistyle里ResultCodeEnum不滿足專案需要,大家可以在你的專案里自行定義一個ResultCodeEnum.java,或者可以在Constant里定義code(推薦前者),
§4. How to use?
如下testcase在zhenghe-rpcapistyle包里,可以幫助你快速了解并掌控Result<T>,
package com.emax.zhenghe.common.api.vo;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;
@Slf4j
public class ResultTest {
public static void main(String[] args) {
//Result里保存Long型數值
Result<Long> longResult = Result.success(5L, "");
System.out.println("longResult=" + longResult);
System.out.println(longResult.getCode() + "----");
longResult.setResult(1L);
System.out.println(longResult.getCode());
//Result里存盤資料集合
Result<List<Integer>> listResult = Result.success(Arrays.asList(1, 2, 4));
System.out.println(JSON.toJSONString(listResult.getResult()));
//如下Result相當于Result<Object>或Result<?>
Result objectResult = Result.success();
System.out.println("objectResult.getCode()=" + objectResult.getCode());
//在某些error情況下,Result要設定回應資料,
Result<Integer> integerResult = Result.err("sdfsda");
integerResult.setResult(1);
System.out.println("integerResult=" + integerResult);
//構造器初始化的Result物件,code的默認值是200(成功)
Result<Integer> newResult = new Result<>();
newResult.setCode(404);
newResult.setResult(Integer.MIN_VALUE);
System.out.println(newResult.getResult() + "---" + newResult.getCode());
}
}
|
下面,以一個簡單的示例來介紹rpc服務的實作類里如何使用Result<T>
@Override
public Result<Long> separateFeeQuery() {
Long count=0L;//todo:呼叫service讀庫
return Result.success(count);
}
|
又例如:
@Override
public Result addEnterprise(EnterpriseDTO enterprise) {
....
boolean ok = enterpriseService.save(po);
if (ok){
return Result.success();
} else {
return Result.err("資料保存失敗");
}
}
|
§5. 命名規范
方法命名可能還真不好統一,也不好立規范,
同樣rpcapi介面類名也是如此,比如可以統一以-Api結尾,也可以統一以-Service結尾,不過最好與工程里的Service區分開來,這樣便于程式理解,
就像上面§1提到的資料傳輸物件用DTO命名一樣,有的人說用VO比較好,仁者見仁智者見智吧,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/247329.html
標籤:其他
上一篇:rpc請求&回應引數規范
