0.1 幾個概念html
api-應用程序接口,最狹隘的定義,指的是咱們程序裏類或接口的方法。java
rpc-局域網內部跨應用通訊框架。常見的有dubbo、thrift、HSF、Feign。json
rpcapi-基本上能夠跟程序內部api同樣用法的api。api
0.2 someword:框架
下面說的參數,包括請求參數和返回參數。maven
0.3 爲何有本文?ide
書接前文,rpcapi雖然能夠像程序內部api同樣,支持java各類數據類型,能夠像調用程序內部api同樣調用rpcapi。不過,所不一樣的是,rpcapi應該處理各類可能的異常狀況,而不是拋出異常。這使得rpcapi與restapi同樣,不能只是返回數據(資源),而應該對可能出現的異常狀況進行判斷,好比參數合法性,數據是否存在,數據狀態,程序異常,等等,當沒有異常狀況時,才返回所需數據(資源)。所以,就有了本文下文說的Result<T>。this
1.1 若是參數比較少,好比少於3個,能夠顯式定義出來。好比spa
getEnterpriseById(String enterpriseId)rest
getEnterpriseById(String enterpriseId,ProductEnum product)
1.2 若是參數超過3個,建議定義一個DTO。rpc傳輸對象暫定統一命名爲DTO。請求dto命名建議以ReqDTO結尾。固然,若是請求響應都使用相同的dto的話,就直接以DTO結尾也何嘗不可。好比
addEnterprise(EnterpriseDTO enterprise);
selectEnterprise(EnterpriseDTO enterprise);
2.1 首先,響應參數統一使用Result<T>。即,返回值統一使用泛型。Result<T>主要成員有3個:
Result<T>相關操做方法後文贅述。
2.2 其次,對於返回數據來講,同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>>了唄。
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的實現代碼呢, 一睹芳容吧!
對擴展開放
注意到了嗎?Result的code是int類型,不是上文提到的ResultCodeEnum枚舉。
why?code定義成ResultCodeEnum固然是再好不過了,程序使用枚舉要比數字易讀多了。爲何不這麼作呢?——爲了考慮擴展。試想,若是現有ResultCodeEnum的枚舉項不知足你的項目須要,你是否是要增長ResultCodeEnum枚舉項?是的,那麼,這時,就要去修改zhenghe-rpcapistyle的源碼,而zhenghe-rpcapistyle在另外一個項目裏。隨着依賴zhenghe-rpcapistyle的項目的逐漸增多,ResultCodeEnum也許將變得尤爲難於使用。
所以,若是zhenghe-rpcapistyle裏ResultCodeEnum不知足項目須要,你們能夠在你的項目裏自行定義一個ResultCodeEnum.java,或者能夠在Constant裏定義code(推薦前者)。
以下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(
"數據保存失敗"
);
}
}
|
方法命名可能還真很差統一,也很差立規範。
一樣rpcapi接口類名也是如此,好比能夠統一以-Api結尾,也能夠統一以-Service結尾,不過最好與工程裏的Service區分開來,這樣便於程序理解。
就像上面§1提到的數據傳輸對象用DTO命名同樣,有的人說用VO比較好,仁者見仁智者見智吧。