文章
问答
冒泡
spring MVC 下restful接口的返回值处理

在当前的主流环境下,大部分项目都是基于restful的接口来开发的。那么对于接口的返回形式很多时候就会有各种方式,比如说,要不要在最外层包装一层?其实这个主要是根据项目的情况来处理,就我个人而言,我觉得内部业务是不需要包装的,但是按照restful的风格,要么没有返回值,如果有返回值一定是一个Object,不要返回一个string这种就可以了。然而,如果是对外的接口给第三方使用之类的,还是包装一层比较好,毕竟最外层的几个基础字段更便于理解。

1.直接返回数据,用httpStatus表示成功与否
我们要返回这么一结果

{
  "title": "三国演义",
  "content": "测试"
}



在controller中直接返回对象即可

@GetMapping(value = "one")
public Article queryOne(){
    return Article.builder().title("三国演义").content("测试").build();
}



结果如下
image.png
在成功返回数据的时候,我们只要拿到这个结果就可以了,但是对于异常的处理,我们需要用httpStatus的值类判断。
定义一个错误对象

@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class ErrorResponse {
    private String code;
    private String message;
}



定义一个全局的异常捕获

@RestControllerAdvice
public class ErrorHandler {

    @ExceptionHandler(value = ApiException.class)
    public ErrorResponse error(ApiException ex, HttpServletResponse response){
        response.setStatus(460);
        return ErrorResponse.builder().code(ex.getCode()).message(ex.getMessage()).build();
    }
}



抛出一个异常试试

@GetMapping(value = "error")
public void error(){
    throw new ApiException("500","error message");
}

image1.png

这种方式,只需要在httpclient 使用response的拦截器处理下httpStatus值即可,如果是200则返回数据,如果不是则处理异常。

2.包装一层,所有的httpStatus 都是200,根据返回值的某字段来判断
另外一种方式,就是在返回的数据上包装一层,客户端根据success字段来判断请求是否成功。
首先,我们定义一个统一的返回对象,不管返回的是什么,泛型来解决。

@Data
public class DataResponse<T>  {
    private Boolean success;
    private T data;
}



写一个方法测试下

@GetMapping(value = "res/one")
public DataResponse<Article> queryOneRes(){
    Article article = Article.builder().title("三国演义").content("测试").build();
    DataResponse<Article> response = new DataResponse<>();
    response.setSuccess(true);
    response.setData(article);
    return response;
}



可以看到返回结果已经是被包装过的
image2.png
那么,如果全局都是要这种格式的,难道每个函数都要这么写嘛?ResponseBodyAdvice 可以帮我们做response的包装工作。

@RestControllerAdvice
public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {

    @ExceptionHandler(value = ApiException.class)
    public ErrorResponse error(ApiException ex, HttpServletResponse response){
        return ErrorResponse.builder().success(false).code(ex.getCode()).message(ex.getMessage()).build();
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return !Objects.equals(returnType.getParameterType(),ErrorResponse.class);
    }

    @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
            Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
            ServerHttpResponse response) {
        DataResponse<Object> response1 = new DataResponse<>();
        response1.setSuccess(true);
        response1.setData(body);
        return response1;
    }
}



此时再来看下方式一的两个返回值
image3.png
这样,我们就可以通过配置方法给所有的返回值加上包装。

spring boot
spring
restful

关于作者

落雁沙
非典型码农
获得点赞
文章被阅读