接口规范

基础接口规范前言

该接口规范旨在达到以下目的

  • 接口请求参数规范
  • 接口响应参数规范
  • 请求参数校验规范
  • 通用异常处理规范

适用场景

  • 模块间服务接口调用
  • 前端 REST 服务接口调用

接口返回值规范

接口交互响应封装规范

所有对外接口必须使用 Result Bean 封装响应结果

响应基类BaseResult

public class BaseResult<T> implements IResult {
private Boolean isSuccess;// 本次调用是否成功
private IStatusCode code;// 状态编码
private String message = "";//
private String stackTrace = "";

...
}

普通响应实现

public class ResultMsg<T> extends BaseResult<T>{

private T data = null; // 返回数据
/**成功,有结果数据 * @param data */
public ResultMsg(T result){
this.setIsSuccess(true);
this.setData(result);
}
...
}

分页响应实现

public class PageResult<T> extends BaseResult<T>{
private PageList<T> data;
/**
* 返回成功的分页结果
* @param data
*/
public PageResult(PageList<T> data) {
this.setIsSuccess(true);
this.data = data;
}
...

响应码规范

响应需要有对应的响应码,对于业务异常、系统可预知异常需要定义好异常码,并使用 包装异常 ,不同模块需要定义自身的异常枚举,并实现接口IStatusCode

/**
* @说明 系统状态码定义抽象接口<br>
* 子模块或者系统需要定义自己的系统状态码<br>
* @StatusCode 为基础模块定义的基本码值,1~500 目前已经被占用
* @author jeef
*
*/
public interface IStatusCode {
/**
* 状态码
* @return
*/
public String getCode() ;
/**
* 异常信息
* @return
*/
public String getMsg() ;

/**
* 系统编码
* @return
*/
public String getSystem() ;

}

基础响应码实现

/**
* @说明 基础系统状态码定义
*/
public enum StatusCode implements IStatusCode{

SUCCESS("200","成功"),
SYSTEM_ERROR("500","系统异常"),
TIMEOUT("401","访问超时"),
NO_ACCESS("403","访问受限"),
PARAM_ILLEGAL("100","参数校验不通过");

private String code;
private String msg;
private String system;

StatusCode(String code,String msg){
this.setCode(code);
this.setMsg(msg);
this.setSystem("BASE");
}

public String getCode() {
return code;
}
....
}

接口请求入参规范

请求入参RequestDto

/**
* @说明 用于系统交互请求参数使用
* @param data<E> 假如参数为某个bean,则使用该对象,比如传递一个订单对象。
*/
public class RequestDto<E> {
private RequestHead head;
/**
* 参数为某个bean时使用
*/
private E data;
}

普通参数请求入参 RequestParam

/**
* @说明 普通参数请求
* @param params 用于请求参数的存放
*/
public class RequestParam {
/**
* 请求头
*/
private RequestHead head;
/**
* 请求参数
*/
private Map<String,Object> params = new HashMap<String,Object>();
}

分页请求入参 RequestPage

/**
* @说明 分页请求
* @author Administrator
*
*/
public class RequestPage extends RequestParam{

//当前页
private int pageNo = 1;
private int pageSize = 20;
private List<FieldSort> orders = new ArrayList<FieldSort>();

public RequestPage() {

}
public RequestPage(int pageNo, int pageSize) {
super();
this.pageNo = pageNo;
this.pageSize = pageSize;
}
}

异常定义规范

AgileBPM 异常定义均在 com.dstz.base.api.exception 包,各个业务模块不需要定义特殊的异常类,均通过异常码来标识异常!
异常分三种,业务消息 BusinessMessage 、业务异常 BusinessException、系统异常BusinessError

业务消息不会记录异常堆栈、日志 ,会直接提示到前端用户错误信息
其他则会详细记录请求信息、堆栈信息,并返回异常码,不会返回具体异常信息

业务消息异常

业务异常 BusinessMessage,通常为直接通知用户 业务消息,通常用于业务代码反馈,非系统异常!
如,保存用户时,后端校验 账号已存在 ,可以直接抛出业务异常 BusinessMessage ,并返回定义好的状态码

普通异常

BusinessException 业务逻辑异常,常常为可预料异常,此异常常常是开发时,非法操作信息提示 比如 流程表单丢失!

系统异常

BusinessError 系统异常,常常用于强制捕获的异常的包装,比较严重异常

请求统一异常捕获说明

使用介绍

当我们需要对一个请求接口的异常情况进行统一处理的时候,可以使用该注解
当方法体出现异常时,会包装标准的异常 resultMsg 进行反馈给调用者,并记录日志

比如前端请求、RPC调用者等一些场景,省去了我们异常捕获的动作,也规范对于前端的响应
Rest 请求 稍后会添加全局异常处理、目前还没有添加

   @CatchErr("获取用户失败")
public ResultMsg<User> getUserInfoByName(String userName){
if(StringUtils.isEmpty(userName)){
throw new BusinessException("查询用户,账户不能为空。");
}

ResultMsg<User> msg = new ResultMsg<User>(new User(userName, userName+"account"));
return msg;
}

注解CatchErr介绍

/**
* @描述 <p>如果该注解的方法出现异常,则会反馈标准的异常结果【ResultMsg.java】给前端或者服务调用方</p>
* @提示 <p>使用该注解需要注意事物问题更多信息请查看ErrAspect.java</p>
*
* @param write2response 是否写入到response 用于http请求中,方法会从入参中获取response,然后写入resultMsg<br>
* @param needStackTrace 是否需要反馈异常堆栈信息,默认不反馈堆栈异常,但是堆栈异常会进行日志记录
* @param value 方法体异常描述
* @create 2017-11-19 20:31:00
* @author jeff
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CatchErr {
String value() default "";
boolean write2response() default false ;
boolean needStackTrace() default false;
}

请求参数校验介绍

请求参数校验使用的 javax validate hibernate-validator 的一个实现

@CatchErr
@ParamValidate
public PageResult<String> getRolesByUser(User user){

List<String> roles = Arrays.asList("1,2,3,4,5,6,7,8,9".split(","));
PageList<String> pageList = new PageList<String>(2, 10, 100, roles);

PageResult<String> msg = new PageResult<String>(pageList);

return msg;
}
public class User {
@NotBlank(message = "姓名不能为空")
private String name = "";
@NotBlank(message = "账号不能为空")
private String account = "";
...
}

ParamValidate 会对user对象进行校验

校验不通过则会反馈标准的resultMsg给调用者

引入CatchErr、@ParamValidate 注意事项

需注意必须在 springMVC的配置页配置 注解拦截器
否则将无法在controller层拦截处理异常

<aop:aspectj-autoproxy proxy-target-class="true"/>

其他说明

前端一些配套js

对jQuery进行扩展增加一些公共的 result 解析方法,用来提示系统错误,如 util.js getResultData 方法

/**
* @说明 获取请求响应的数据
* @失败 默认toast 提示错误信息
* @成功 不展示成功信息自己处理
*/
getResultData : function(defer,fn){
defer.then(function(result){
if(!result.isok){
toast.error(result.message);
console.error(result.stackTrace);
return;
}
//返回结果
fn(result.data);

},function(status){
alert("加载失败!"+status);
}
);
},

前端如此使用

   var defer=baseService.get(dataUrl);
$.getResultData(defer,function(data){
//这里直接使用data
});