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比较好,仁者见仁智者见智吧。