• 一文教你处理SpringBoot统一返回格式


    背景

    相信大部分后端开发人员在日常开发中都需要和前端对接,当然前后端都是你自己一个人搞的话可以想怎么玩就怎么玩,但是我们还是要做到一定的规范性。在前后端分离的项目中后端返回的格式一定要友好,并且固定,不能经常变来变去,不然会对前端的开发人员带来很多的工作量。

    SpringBoot Controller 常见的返回格式

    String

    1. @PostMapping("/test")
    2. public String test(){
    3. return "Hello World";
    4. }
    5. 复制代码

    postman调用结果:

    自定义对象

    正常返回

    1. @PostMapping("/getUser")
    2. public ActionResult getUser(){
    3. User user = new User();
    4. user.setId(UUID.randomUUID().toString());
    5. user.setName("MrDong");
    6. user.setAge(20);
    7. return ActionResult.defaultOk(user);
    8. }
    9. 复制代码

    postman调用结果:

    错误返回

    1. @PostMapping("/error")
    2. public ActionResult error(){
    3. return ActionResult.defaultFail(1000,"服务器异常,请联系管理员");
    4. }
    5. 复制代码

    postman调用结果:

    定义返回对象

    我定义两个ActionResult这个对象来对返回值进行封装,可以根据自己公司实际情况修改:

    1. package com.wxd.entity;
    2. import com.wxd.enums.ResultCodeEnum;
    3. import lombok.Data;
    4. /**
    5. * @ClassName ActionResult
    6. * @Description 统一返回值封装
    7. * @Author Mr Dong
    8. * @Date 2022/7/26 14:51
    9. */
    10. @Data
    11. public class ActionResult {
    12. private Integer code;
    13. private String msg;
    14. private Integer count;
    15. private Object data;
    16. public static ActionResult defaultOk(Integer code, String msg, Integer count, Object data) {
    17. return new ActionResult(code, msg, count, data);
    18. }
    19. public static ActionResult defaultOk(Integer count, Object data) {
    20. return new ActionResult(ResultCodeEnum.RC200, count, data);
    21. }
    22. public static ActionResult defaultOk(Object data) {
    23. return new ActionResult(ResultCodeEnum.RC200, null, data);
    24. }
    25. public static ActionResult defaultOk() {
    26. return new ActionResult(ResultCodeEnum.RC200);
    27. }
    28. public static ActionResult defaultFail() {
    29. return new ActionResult(ResultCodeEnum.RC999);
    30. }
    31. public static ActionResult defaultFail(Integer code, String msg) {
    32. return new ActionResult(code, msg);
    33. }
    34. public static ActionResult defaultFail(ResultCodeEnum resultCodeEnum) {
    35. return new ActionResult(resultCodeEnum);
    36. }
    37. public ActionResult(Integer code, String msg, Integer count, Object data) {
    38. this.code = code;
    39. this.msg = msg;
    40. this.count = count;
    41. this.data = data;
    42. }
    43. public ActionResult(Integer code, String msg) {
    44. this.code = code;
    45. this.msg = msg;
    46. }
    47. public ActionResult(ResultCodeEnum resultCodeEnum) {
    48. this.code = resultCodeEnum.getCode();
    49. this.msg = resultCodeEnum.getMessage();
    50. }
    51. public ActionResult(ResultCodeEnum resultCodeEnum, Integer count, Object data) {
    52. this.code = resultCodeEnum.getCode();
    53. this.msg = resultCodeEnum.getMessage();
    54. this.count = count;
    55. this.data = data;
    56. }
    57. }
    58. 复制代码

    定义状态枚举

    1. package com.wxd.enums;
    2. /**
    3. * @author wxd
    4. * @version V1.0
    5. * @description ResultCodeEnum
    6. * @date 2022/8/10 13:35
    7. **/
    8. public enum ResultCodeEnum {
    9. /**
    10. * 操作成功
    11. */
    12. RC200(200, "操作成功"),
    13. /**
    14. * 未授权
    15. */
    16. RC401(401, "用户未授权"),
    17. /**
    18. * 请求被禁止
    19. */
    20. RC403(403, "请求被禁止"),
    21. /**
    22. * 服务异常
    23. */
    24. RC500(500, "服务器异常,请联系管理员"),
    25. /**
    26. * 操作失败
    27. */
    28. RC999(999, "操作失败"),
    29. RC1001(1001, "用户名密码错误"),
    30. RC1002(1002, "未授权的资源"),
    31. RC1003(1003, "未授权的资源"),
    32. RC1004(1004, "缺少请求参数异常"),
    33. RC1005(1005, "缺少请求体参数异常"),
    34. RC1006(1006, "参数绑定异常"),
    35. RC1007(1007, "方法参数无效异常");
    36. private Integer code;
    37. private String message;
    38. ResultCodeEnum(Integer code, String message) {
    39. this.code = code;
    40. this.message = message;
    41. }
    42. public Integer getCode() {
    43. return code;
    44. }
    45. public String getMessage() {
    46. return message;
    47. }
    48. }
    49. 复制代码

    统一处理返回值及异常

    实现原理:需要实现SpringBoot提供的ResponseBodyAdvice这个接口,完成统一返回值的封装及异常的处理。实现了这个接口之后,在Controller返回的时候只需要将对象直接返回,有些不需要返回值的可以直接返回void。

    1. package com.wxd.advice;
    2. import com.wxd.entity.ActionResult;
    3. import com.wxd.enums.ResultCodeEnum;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.springframework.core.MethodParameter;
    6. import org.springframework.http.HttpStatus;
    7. import org.springframework.http.MediaType;
    8. import org.springframework.http.converter.HttpMessageNotReadableException;
    9. import org.springframework.http.server.ServerHttpRequest;
    10. import org.springframework.http.server.ServerHttpResponse;
    11. import org.springframework.validation.BindException;
    12. import org.springframework.web.bind.MethodArgumentNotValidException;
    13. import org.springframework.web.bind.MissingServletRequestParameterException;
    14. import org.springframework.web.bind.annotation.ExceptionHandler;
    15. import org.springframework.web.bind.annotation.ResponseStatus;
    16. import org.springframework.web.bind.annotation.RestControllerAdvice;
    17. import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
    18. /**
    19. * @version: V1.0
    20. * @author: wxd
    21. * @description: 全局异常处理以及返回值的统一封装
    22. * @Date 2022/7/26 16:24
    23. */
    24. @RestControllerAdvice(value = "com.wxd.controller")
    25. @Slf4j
    26. public class ResponseAdvice implements ResponseBodyAdvice {
    27. @Override
    28. public boolean supports(MethodParameter methodParameter, Class aClass) {
    29. return true;
    30. }
    31. /**
    32. * 统一包装
    33. *
    34. * @param o
    35. * @param methodParameter
    36. * @param mediaType
    37. * @param aClass
    38. * @param serverHttpRequest
    39. * @param serverHttpResponse
    40. * @return
    41. */
    42. @Override
    43. public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
    44. /**
    45. * String、ActionResult不需要再包一层(不想包一层ActionResult对象的可以在这里把这个对象过滤掉)
    46. */
    47. if (o instanceof String || o instanceof ActionResult) {
    48. return o;
    49. }
    50. return ActionResult.defaultOk(o);
    51. }
    52. /**
    53. * 系统内部异常捕获
    54. *
    55. * @param e
    56. * @return
    57. */
    58. @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    59. @ExceptionHandler(value = Exception.class)
    60. public Object exceptionHandler(Exception e) {
    61. log.error("系统内部异常,异常信息", e);
    62. return ActionResult.defaultFail(ResultCodeEnum.RC500);
    63. }
    64. /**
    65. * 忽略参数异常处理器;触发例子:带有@RequestParam注解的参数未给参数
    66. *
    67. * @param e 忽略参数异常
    68. * @return ResponseResult
    69. */
    70. @ResponseStatus(HttpStatus.BAD_REQUEST)
    71. @ExceptionHandler(MissingServletRequestParameterException.class)
    72. public Object parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
    73. log.error("缺少Servlet请求参数异常", e);
    74. return ActionResult.defaultFail(ResultCodeEnum.RC1004);
    75. }
    76. /**
    77. * 缺少请求体异常处理器;触发例子:不给请求体参数
    78. *
    79. * @param e 缺少请求体异常
    80. * @return ResponseResult
    81. */
    82. @ResponseStatus(HttpStatus.BAD_REQUEST)
    83. @ExceptionHandler(HttpMessageNotReadableException.class)
    84. public Object parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
    85. log.error("参数请求体异常", e);
    86. return ActionResult.defaultFail(ResultCodeEnum.RC1005);
    87. }
    88. /**
    89. * 统一处理请求参数绑定错误(实体对象传参);
    90. *
    91. * @param e BindException
    92. * @return ResponseResult
    93. */
    94. @ResponseStatus(HttpStatus.BAD_REQUEST)
    95. @ExceptionHandler(BindException.class)
    96. public Object validExceptionHandler(BindException e) {
    97. log.error("方法参数绑定错误(实体对象传参)", e);
    98. return ActionResult.defaultFail(ResultCodeEnum.RC1006);
    99. }
    100. /**
    101. * 统一处理请求参数绑定错误(实体对象请求体传参);
    102. *
    103. * @param e 参数验证异常
    104. * @return ResponseResult
    105. */
    106. @ResponseStatus(HttpStatus.BAD_REQUEST)
    107. @ExceptionHandler({MethodArgumentNotValidException.class})
    108. public Object parameterExceptionHandler(MethodArgumentNotValidException e) {
    109. log.error("方法参数无效异常(实体对象请求体传参)", e);
    110. return ActionResult.defaultFail(ResultCodeEnum.RC1007);
    111. }
    112. }
    113. 复制代码

    void 无返回值

    有返回值


     

  • 相关阅读:
    大数据技术之 Kafka
    java对象与字节数组互转
    【从零开始学习 SystemVerilog】11.3、SystemVerilog 断言—— Concurrent Assertions(并发断言)
    为什么要停止在 SpringBoot 中使用字段注,改用构造器注入
    vue3项目经验分享
    Siri怎么重置主人声音
    UE4 GeoReferencing Plugin
    一年拿两证?初级会计和中级会计可以同时报考吗?
    MMoE论文中Synthetic Data生成代码(控制多任务学习中任务之间的相关性)
    java计算机毕业设计网络游戏管理网站源码+数据库+系统+lw文档+mybatis+运行部署
  • 原文地址:https://blog.csdn.net/m0_71777195/article/details/126284110