Spring Boot 统一接口返回结果

参考

代码示例

  1. 定义返回结果枚举类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public enum ResultEnum {

    SUCCESS(200, "成功"),

    FAIL(500, "失败");

    private final int code;

    private String msg;

    ResultEnum(int code, String msg) {
    this.code = code;
    this.msg = msg;
    }

    public int getCode() {
    return code;
    }

    public String getMsg() {
    return msg;
    }

    public void setMsg(String msg) {
    this.msg = msg;
    }
    }
  2. 定义统一返回结果类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    public class Result<T> {
    private final Integer code;
    private final String msg;
    private T data;


    public Result(int code, String msg) {
    this.code = code;
    this.msg = msg;
    }


    /**
    * 创建成功返回结果
    *
    * @param data 返回数据
    * @param <T> 返回数据类型
    * @return 返回结果
    */
    public static <T> Result<T> success(T data) {
    ResultEnum resultEnum = ResultEnum.SUCCESS;
    return Result.create(resultEnum, data);
    }

    /**
    * 创建失败返回结果
    *
    * @param data 返回数据
    * @param msg 消息
    * @param <T> 返回数据类型
    * @return 返回结果
    */
    public static <T> Result<T> fail(T data, String msg) {
    ResultEnum resultEnum = ResultEnum.FAIL;
    resultEnum.setMsg(msg);
    return Result.create(resultEnum, data);
    }

    /**
    * 创建失败返回结果
    *
    * @param data 返回数据
    * @param <T> 返回数据类型
    * @return 返回结果
    */
    public static <T> Result<T> fail(T data) {
    ResultEnum resultEnum = ResultEnum.FAIL;
    return Result.create(resultEnum, data);
    }

    /**
    * 创建返回结果
    *
    * @param resultEnum 返回结果枚举
    * @param data 返回数据
    * @param <T> 返回数据类型
    * @return 返回结果
    */
    public static <T> Result<T> create(ResultEnum resultEnum, T data) {
    Result<T> result = new Result<T>(resultEnum.getCode(), resultEnum.getMsg());
    result.setData(data);
    return result;
    }


    public int getCode() {
    return code;
    }

    public String getMsg() {
    return msg;
    }

    public T getData() {
    return data;
    }

    public void setData(T data) {
    this.data = data;
    }
    }
  3. 统一返回结果拦截器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.MethodParameter;
    import org.springframework.core.annotation.Order;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.server.ServerHttpRequest;
    import org.springframework.http.server.ServerHttpResponse;
    import org.springframework.lang.NonNull;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

    /**
    * Created with IntelliJ IDEA.
    *
    * @author Administrator
    * Date: 2025/1/15
    * Time: 09:15
    * Description:SpringBoot优雅的统一返回格式
    */
    @RestControllerAdvice
    @Order(AdviceOrdered.GLOBAL_RESPONSE_HANDLER)
    public class RestfulResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Autowired
    private ObjectMapper objectMapper;
    /**
    * @param returnType the return type
    * @param converterType the selected converter type
    * @return 判断是否拦截
    */
    @Override
    public boolean supports(@NonNull MethodParameter returnType, @NonNull Class<? extends HttpMessageConverter<?>> converterType) {
    return true;
    }

    /**
    * @param o the body to be written
    * @param returnType the return type of the controller method
    * @param selectedContentType the content type selected through content negotiation
    * @param selectedConverterType the converter type selected to write to the response
    * @param request the current request
    * @param response the current response
    * @return 最终返回对象
    */
    @Override
    public Object beforeBodyWrite(Object o, @NonNull MethodParameter returnType, @NonNull MediaType selectedContentType, @NonNull Class<? extends HttpMessageConverter<?>> selectedConverterType, @NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response) {

    //如果Controller返回String的话,SpringBoot不会帮我们自动封装而直接返回,因此我们需要手动转换成json。
    if (o instanceof String) {
    try {
    return objectMapper.writeValueAsString(Result.success(o));
    } catch (JsonProcessingException e) {
    throw new RuntimeException(e);
    }
    }

    //如果返回的结果是R对象,即已经封装好的,直接返回即可。
    //如果不进行这个判断,后面进行全局异常处理时会出现错误
    if (o instanceof Result<?>) {
    return o;
    }

    //如果返回的是错误,则返回失败
    if (o instanceof Exception) {
    return Result.fail(o);
    }

    return Result.success(o);
    }
    }

即使我们配置了全局接口统一,当出现404 not found等4xx错误时,依然会出现意外情况:查看