当前位置:   article > 正文

springboot整合之统一结果返回_统一返回结果类

统一返回结果类

特别说明:本次项目整合基于idea进行的,如果使用Eclipse可能操作会略有不同,不过总的来说不影响。

springboot整合之如何选择版本及项目搭建

springboot整合之版本号统一管理 

springboot整合mybatis-plus+durid数据库连接池

springboot整合swagger

springboot整合mybatis代码快速生成

springboot整合之统一结果返回

springboot整合之统一异常处理

springboot整合之Validated参数校验 

springboot整合之logback日志配置

springboot整合pagehelper分页

springboot整合本地缓存

springboot整合redis + redisson

springboot整合elasticsearch

springboot整合rabbitMq

springboot整合canal实现缓存一致性

springboot整合springSecurity(前后端不分离版本)

一、为什么要对结果进行统一的返回

可能有很多小伙伴不理解为什么我们要对结果进行统一的返回,我们之前那种直接返回结果不也挺好的吗?

类似于上面这种,我们是直接就给接口调用方返回了用户信息,这样也不能说有问题,但是不够优雅。比如说现在用户请求参数错了,我们该怎么返回? 

 这样以来,接口调用方还要根据内容去判断我们的返回结果,如果说不同的错误返回的信息又是不一样的,比如现在这个返回“当前用户不存在,参数错误”,另一个接口返回“权限不足,请申请权限后操作!”,那这样对接口调用方来说简直就是痛苦面具。

所以为了我们的接口调用返回结果更加优雅,我们可以采取统一返回结果。我们在结果里面加上状态码,消息以及返回的数据。这样接口调用方就能够根据我们的返回状态码来判定结果的状态,然后根据状态去判定显示结果还是显示错误提示。这样就会显得优雅一点。具体实现也很简单。下面我们就一步一步来实现一下。

二、准备需要的目录结构

我们首先在项目里新建下面的几个包,以备后用。简单说明一下:common就是打算以后把公共的类就放到这里面来,enums就是放我们用到的枚举类,response就是放我们的返回结果类,utils存放工具类。

三、创建统一返回结果类

按照我们上面说的,这个类有三个成员属性,分别是:status用来标记请求状态,msg用来返回消息,如果成功就返回“OK”,失败就返回错误消息提示。data用来返回数据。这里面我还增加了一个常量 SUCCESS,用来表示200,表示请求成功的状态。定义为了public类型,后面方便我们在别的类调用。本来也打算把401,403,404,500这些常见的状态也都定义进来的。但是考虑了一下,打算把常见的错误状态做成枚举,避免大家重复定义,用起来更加简单方便一点。

  1. package com.example.springbootdemo.common.response;
  2. import com.example.springbootdemo.common.enums.ErrorCodeEnum;
  3. import io.swagger.annotations.ApiModel;
  4. import io.swagger.annotations.ApiModelProperty;
  5. import lombok.Data;
  6. /**
  7. * @description: Result 统一返回结果<br>
  8. * @date: 2022/12/27 0027 下午 1:09 <br>
  9. * @author: William <br>
  10. * @version: 1.0 <br>
  11. */
  12. @Data
  13. @ApiModel(value="统一返回结果对象", description="")
  14. public class Result {
  15. /**
  16. *操作成功
  17. */
  18. public static final int SUCCESS = 200;
  19. /**
  20. * 响应业务状态
  21. */
  22. @ApiModelProperty(value = "响应业务状态")
  23. private Integer status;
  24. /**
  25. * 响应消息
  26. */
  27. @ApiModelProperty(value = "响应消息")
  28. private String msg;
  29. /**
  30. * 响应中的数据
  31. */
  32. @ApiModelProperty(value = "响应中的数据")
  33. private Object data;
  34. /**
  35. * description: Result 默认无参构造<br>
  36. * @version: 1.0
  37. * @date: 2022/12/27 0027 下午 1:21
  38. * @author: William
  39. */
  40. public Result() {
  41. }
  42. /**
  43. * description: Result 只包含返回数据构造方法<br>
  44. * @version: 1.0
  45. * @date: 2022/12/27 0027 下午 1:22
  46. * @author: William
  47. * @param data 需要返回数据
  48. */
  49. public Result(Object data) {
  50. this.status = SUCCESS;
  51. this.msg = "OK";
  52. this.data = data;
  53. }
  54. /**
  55. * description: Result 包含所有参数的构造方法<br>
  56. * @version: 1.0
  57. * @date: 2022/12/27 0027 下午 1:23
  58. * @author: William
  59. * @param status 状态
  60. * @param msg 消息
  61. * @param data 数据
  62. */
  63. public Result(Integer status, String msg, Object data) {
  64. this.status = status;
  65. this.msg = msg;
  66. this.data = data;
  67. }
  68. public static Result ok() {
  69. return new Result(null);
  70. }
  71. public static Result ok(Object data) {
  72. return new Result(data);
  73. }
  74. /**
  75. * description: error 异常时返回方法<br>
  76. * @version: 1.0
  77. * @date: 2022/12/27 0027 下午 1:25
  78. * @author: William
  79. * @param errorCodeEnum 异常枚举对象
  80. * @return com.example.springbootdemo.common.response.Result
  81. */
  82. public static Result error(ErrorCodeEnum errorCodeEnum) {
  83. return new Result(errorCodeEnum.getValue(), errorCodeEnum.getMessage(), "");
  84. }
  85. public static Result build(Integer status, String msg) {
  86. return new Result(status, msg, null);
  87. }
  88. public static Result build(Integer status, String msg, Object data) {
  89. return new Result(status, msg, data);
  90. }
  91. }

四、创建统一异常枚举类

  1. package com.example.springbootdemo.common.enums;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Getter;
  4. import lombok.NoArgsConstructor;
  5. /**
  6. * description: 错误信息枚举类规定:编写时按照模块分类,每个模块写到一起,便于修改和维护返回状态根据Http状态码定义来 <br>
  7. * @version: 1.0
  8. * @date: 2022/12/27 0027 下午 1:18
  9. * @author: William
  10. */
  11. @NoArgsConstructor
  12. @Getter
  13. @AllArgsConstructor
  14. public enum ErrorCodeEnum {
  15. //公共模块
  16. UNAUTHORIZED(401,"未认证"),
  17. FORBIDDEN(401,"未授权"),
  18. ILLEGAL_VALUE(404,"参数非法"),
  19. OPERATION_FAILED(404,"操作失败");
  20. int value;
  21. String message;
  22. }

五、修改测试接口

到上面第四步完成我们的统一结果返回就算封装好了,接下来我们就能够使用我们自己定义的统一返回结果类了。我们来修改一下userController,把之前的返回字符串改为返回同意结果返回。

这里有个点跟大家讲一下,因为我这就是demo,并不是真正的业务,我就把查询用户放到了controller里面了,如果是正式项目,大家把查询还是要放到业务层service里面去做。

  1. package com.example.springbootdemo.controller;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import com.example.springbootdemo.common.enums.ErrorCodeEnum;
  4. import com.example.springbootdemo.common.response.Result;
  5. import com.example.springbootdemo.entity.User;
  6. import com.example.springbootdemo.service.UserService;
  7. import com.example.springbootdemo.vo.UserVo;
  8. import io.swagger.annotations.Api;
  9. import io.swagger.annotations.ApiOperation;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.web.bind.annotation.GetMapping;
  12. import org.springframework.web.bind.annotation.PathVariable;
  13. import org.springframework.web.bind.annotation.RequestMapping;
  14. import org.springframework.web.bind.annotation.RestController;
  15. /**
  16. * <p>
  17. * 前端控制器
  18. * </p>
  19. *
  20. * @author William
  21. * @since 2022-12-27
  22. */
  23. @Api(tags = "用户相关接口")
  24. @RestController
  25. @RequestMapping("/user")
  26. public class UserController {
  27. @Autowired
  28. private UserService userService;
  29. /**
  30. * description: userInfo 过根据用户ID获取用户信息<br>
  31. * @version: 1.0
  32. * @date: 2022/12/27 0027 下午 2:30
  33. * @author: William
  34. * @param id 用户ID
  35. * @return com.example.springbootdemo.common.response.Result
  36. */
  37. @ApiOperation(value = "根据用户ID获取用户信息")
  38. @GetMapping("/{id}")
  39. public Result userInfo(@PathVariable("id") Integer id){
  40. if(id == null || id <= 0){
  41. return Result.error(ErrorCodeEnum.ILLEGAL_VALUE);
  42. }
  43. User user = userService.getById(id);
  44. if(user == null){
  45. return Result.error(ErrorCodeEnum.ILLEGAL_VALUE);
  46. }
  47. return Result.ok(user);
  48. }
  49. }

六、启动测试

操作完成后我们就可以启动测试了。

 启动成功,接下来我们打开swagger来测试一把。首先我们输入一个不存在的用户试一下(我这里把前两条数据给删除了,所以输入1和2是不存在的,你们看一下自己的数据库进行测试就好)

 可以看到当前的结果是

{
  "status": 404,
  "msg": "参数非法",
  "data": ""
}

这样看起来是不是就舒服多了。然后我们再来看一下正常的

 怎么样是不是体验感一下就上来了。

七、遗留问题解决

。。。突然返现一个严重的问题,就是大家有没有发现我们竟然把用户密码给返回出来了!!!这岂不是要出大问题。我们在返回用户数据的时候一定要格外的小心,因为一不小心就会发生用户信息泄露的事故。这里我们来改造一下吧。我们现在先假设前端只需要返回id和userName.

因为等下我们需要将用户信息copy到userVo中,所以我们需要用到一个工具类,这里我给大家推荐一个我觉得非常好用的工具类,那就是hutool工具包,相信不少小伙伴都用过。两个字好用!!但是有一个问题就是这个里面工具类非常的多,如果有代码洁癖那么不太建议引入。可以自己按照要求来写就好。像我们经常用到的框架或者中间件,感兴趣的小伙伴可以研究一下源码,你会发现他们基本上都是自己封装工具类,不会引入其他jar包。这样主要是为了框架更加轻量级,不需要引入其他jar包即可使用,还有就是用到什么就封装什么,不会导致项目里面存在没有用的代码。减少代码打包的体积,以及运行的速度。言归正传,我们还是先把我们的问题给解决了。

1.引入hutool工具包

  1. <hutool.version>5.8.7</hutool.version>
  2. <!--hutool工具-->
  3. <dependency>
  4. <groupId>cn.hutool</groupId>
  5. <artifactId>hutool-all</artifactId>
  6. <version>${hutool.version}</version>
  7. </dependency>

2.新建UserVo类

  1. package com.example.springbootdemo.vo;
  2. import io.swagger.annotations.ApiModel;
  3. import io.swagger.annotations.ApiModelProperty;
  4. import lombok.Data;
  5. import java.io.Serializable;
  6. /**
  7. * @description: UserVo <br>
  8. * @date: 2022/12/27 0027 下午 2:39 <br>
  9. * @author: William <br>
  10. * @version: 1.0 <br>
  11. */
  12. @Data
  13. @ApiModel(value = "用户信息对象")
  14. public class UserVo implements Serializable {
  15. /**
  16. * 用户ID
  17. */
  18. @ApiModelProperty(value = "用户ID")
  19. private Long id;
  20. /**
  21. * 用户名
  22. */
  23. @ApiModelProperty(value = "用户名")
  24. private String userName;
  25. }

3.修改测试类

  1. package com.example.springbootdemo.controller;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import com.example.springbootdemo.common.enums.ErrorCodeEnum;
  4. import com.example.springbootdemo.common.response.Result;
  5. import com.example.springbootdemo.entity.User;
  6. import com.example.springbootdemo.service.UserService;
  7. import com.example.springbootdemo.vo.UserVo;
  8. import io.swagger.annotations.Api;
  9. import io.swagger.annotations.ApiOperation;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.web.bind.annotation.GetMapping;
  12. import org.springframework.web.bind.annotation.PathVariable;
  13. import org.springframework.web.bind.annotation.RequestMapping;
  14. import org.springframework.web.bind.annotation.RestController;
  15. /**
  16. * <p>
  17. * 前端控制器
  18. * </p>
  19. *
  20. * @author William
  21. * @since 2022-12-27
  22. */
  23. @Api(tags = "用户相关接口")
  24. @RestController
  25. @RequestMapping("/user")
  26. public class UserController {
  27. @Autowired
  28. private UserService userService;
  29. /**
  30. * description: userInfo 过根据用户ID获取用户信息<br>
  31. * @version: 1.0
  32. * @date: 2022/12/27 0027 下午 2:30
  33. * @author: William
  34. * @param id 用户ID
  35. * @return com.example.springbootdemo.common.response.Result
  36. */
  37. @ApiOperation(value = "根据用户ID获取用户信息")
  38. @GetMapping("/{id}")
  39. public Result userInfo(@PathVariable("id") Integer id){
  40. if(id == null || id <= 0){
  41. return Result.error(ErrorCodeEnum.ILLEGAL_VALUE);
  42. }
  43. User user = userService.getById(id);
  44. if(user == null){
  45. return Result.error(ErrorCodeEnum.ILLEGAL_VALUE);
  46. }
  47. UserVo userVo = new UserVo();
  48. BeanUtil.copyProperties(user, userVo);
  49. return Result.ok(userVo);
  50. }
  51. }

OK,我们再来重新启动测试一把。

 可以看到,现在就只返回了需要的信息。

好了,到这里我们的统一返回结果就OK了。如果文章对你有所帮助的话,点赞关注一波吧~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/183984
推荐阅读
相关标签
  

闽ICP备14008679号