项目开发中,一般情况下对数据返回的格式可能会有一个统一的要求,一般会包括状态码、信息及数据三部分。举个例子,假设规范要求数据返回的结构如下所示:
{
"data":[{
"id":5,"userId":5,"name":"test1","articleCount":0}],"errorMessage":"","statusCode":"200"}
其中,data字段存储实际的返回数据;errorMessage存储当出现异常时的异常信息;statusCode存储处理码;一般用一个特殊的码如200来表示无异常;而出现异常时可以存储具体的异常码。
要返回这样的数据,最直接的做法当然是在每一个Controller中去处理,返回的数据本身就封装有处理码、数据、出现异常时的异常信息等字段。这样做导致的问题,就是每一个Controller向外暴露的方法都要创建一个返回的对象来封装这种处理,并在出现异常时捕获异常进行处理。
因此最好是能够统一处理这种转换,这样的话服务提供者就只需关注他原本就需要处理的事情:一是在无异常时返回数据本身;二是在出现异常时抛出合适的异常。
为达到统一处理的目的,需要针对两个场景做单独的处理:一是当无异常时,在原返回的数据基础上封装一层,将状态码等信息包含进来;二是当出现异常时,将异常信息进行封装然后返回给调用方。
1. 执行无异常时返回数据封装
在Spring Boot中,针对返回值的处理是在HandlerAdapter的returnValueHandlers中进行的。我们先尝试创建一个ReturnValueHandler对象实现HandlerMethodReturnValueHandler接口,然后通过WebMvcConfigurer中的addReturnValueHandlers将其添加。如下所示:
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Autowired
private RestReturnValueHandler restReturnValueHandler;
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
handlers.clear();
handlers.add(restReturnValueHandler);
}
}
其中RestReturnValueHanlder定义如下:
/**
* REST类型的返回值处理器
* 将REST的返回结果进行进一步的封装,如原本返回的是data,那么封装后将会是:
* {statusCode: '', errorMessage: '', exception: {}, data: data}
*
* @author LiuQI 2018/5/30 10:48
* @version V1.0
**/
@Component
public class RestReturnValueHandler implements HandlerMethodReturnValueHandler {