我们在做Restful服务接口规范时,通常都希望返回的结果有一个统一的格式,譬如在返回结果中定义固定的三个属性,比如下面的结构:
@ApiModelProperty(value = "结果编码,0:成功,其他:错误编码。")
int getCode();
@ApiModelProperty(value = "code=0:消息:code!=0:错误信息。")
String getMessage();
@ApiModelProperty(value = " Json 格式的数据内容,根据业务的需要定义;前端可以通过在线调试查看详细信息。")
Object getData();
但是这样做每个接口的返回结果都变成这个结构,就无法知道接口实际返回结果的内容了(就是data的结构),这里分享一个优雅的解决方案。
定义注解
声明一个自定义注解WrapUpResponseBody用来替代ResponseBody注解。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WrapUpResponseBody {
/**
* 用来指定 封装类别
* @return String contentType
*/
WrapUpContentType contentType () default WrapUpContentType.DATA;
}
定义一个 Handler MethodReturnValueHandler类用来统一结果的格式,自动添加上code和message。
public class WrapUpResponseBodyReturnValueHandler implements HandlerMethodReturnValueHandler {
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWeb request webRequest)
throws IO Exception , HttpMessageNotWritableException {
mavContainer.setRequestHandled(true);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// Try even with null return value. WrapUpResponseBodyAdvice could get involved.
writeWithMessageConverters(returnValue, returnType, outputMessage);
}
}
异常结果处理
上面的方式只能统一处理正确返回结果的情况,如果想返回错误信息如何处理呢;可以通过统一的异常处理来解决。
定义一个统一的异常数据结构,包括错误代码和信息。
public class ObjectException extends RuntimeException {
//错误号
protected int exceptionCode;
//用于跟踪的数据,可以放到返回结果的data中
private Object objectData;
}
@ExceptionHandler
public void exceptionHandler(Exception ex, HttpServletRequest request, HttpServletResponse response)
throws IOException {
........
//responseData 含有code、message、data属性
//在同一个异常处理中返回符合标准的数据格式
ResponseMapData responseData =
new ResponseMapData(objex.getExceptionCode(),
ObjectException.extortExceptionOriginMessage(objex));
responseData.addResponseData("trace",ObjectException.extortExceptionTraceMessage(objex));
responseData.addResponseData("object",objex.getObjectData());
JsonResultUtils.writeResponseDataAsJson(responseData, response);
.......
}
如何返回其他格式的结果
但有时需要返回数据流比如文件,或者和和第三方约定的接口格式和这个标准格式不一致怎么办,这是可以利用注解的contentType内容类别属性:
/**
* 包装器内容类别
*/
public enum WrapUpContentType {
DATA, // json data,默认属性,返回json格式的数据
RAW, // 返回函数返回值的元素数据,如果不是String类型,转换为String类型,非标量类型转换为json, 等价于 @RespondBody
JAVASCRIPT, // 返回脚本
IMAGE, // 返回图片流
XML, //将对象转换为xml返回
HTML , // 返回html文本
FILE, // 返回文件流
MAP_DICT // 将对象中的 DictionaryMap 注解 映射为 对应的字段添加到json
}
总结
通过注解和异常来统一处理返回结果的格式,这样接口方法就可以根据实际情况返回结果数据,不会影响单元测试,并且开发人员不需要知道接口的数据包装形式。
南大先腾开源框架:
free date personal dating ads dating services
free date personal dating ads dating services