基础接口规范前言 该接口规范旨在达到以下目的
接口请求参数规范 
接口响应参数规范 
请求参数校验规范 
通用异常处理规范 
 
适用场景
接口返回值规范 所有对外服务接口必须使用 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 Integer pageSize = 0;//分页大小     private Integer page = 1;//当前页     private Integer total = 0;//总条数     private List rows = null;//分页列表数据     ... 
 
响应码规范  响应需要有对应的响应码,对于业务异常、系统可预知异常需要定义好异常码,并使用 包装异常 ,不同模块需要定义自身的异常枚举,并实现接口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; 	} 	.... } 
 
异常定义规范 AgileBPM 异常定义均在 com.dstz.base.api.exception 包,各个业务模块不需要定义特殊的异常类,均通过异常码来标识异常! 异常分三种
业务消息 BusinessMessage 
业务异常 BusinessException 
系统异常BusinessError 
 
业务消息异常 通常为直接通知用户 业务消息,通常用于业务代码反馈,非系统异常! 如,保存用户时,后端校验 账号已存在 ,可以直接抛出业务异常 BusinessMessage ,并返回定义好的状态码
普通异常 业务逻辑异常,常常为可预料异常情况的抛出或者非法操作的信息提示。比如: 流程表单丢失!
系统异常 BusinessError  系统异常,常常用于强制捕获的异常的包装,是相对紧急程度高或者比较严重异常
所有异常均会中断事务,业务消息不会记录异常堆栈、日志 ,会直接提示到前端用户错误信息 其他则会详细记录请求信息、堆栈信息,并返回异常码,不会返回具体异常信息,前端应给予“系统服务异常”的提示
 
请求异常捕获与校验 当我们需要对一个请求接口的异常情况进行统一处理的时候,可以使用该注解 当方法体出现异常时,会包装标准的异常 resultMsg 进行反馈给调用者,并记录日志
比如前端请求、RPC 调用者等一些场景,省去了我们异常捕获的动作,也规范对于前端的响应 Rest 当然也可以对Controller层全局异常处理,但目前我们没这么做。
eg:@CatchErr("保存用户失败") @ParamValidate public  ResultMsg<String> saveUser(@RequestBody User user){ 	if (userManager.isUserExist(user)){ 		throw new BusinessMessage("用户在系统中已存在!"); 	}  	// do save  	return getSuccessResult(user.getId(), "保存成功"); } 
注解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 validate3.0规范  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 });