广告
返回顶部
首页 > 资讯 > 精选 >SpringBoot如何统一后端返回格式
  • 727
分享到

SpringBoot如何统一后端返回格式

2023-06-20 16:06:10 727人浏览 泡泡鱼
摘要

这篇文章主要讲解了“SpringBoot如何统一后端返回格式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“springBoot如何统一后端返回格式”吧!目录为什么要对SpringBoot返回

这篇文章主要讲解了“SpringBoot如何统一后端返回格式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“springBoot如何统一后端返回格式”吧!

目录
  • 为什么要对SpringBoot返回统一的标准格式

    • 第一种:返回 String

    • 第二种:返回自定义对象

    • 第三种:接口异常

  • 定义返回标准格式

    • 高级实现方式

      • 接口异常问题

        • SpringBoot为什么需要全局异常处理器

          • 体验效果

            • 全局异常接入返回的标准格式

              今天我们来聊一聊在基于SpringBoot前后端分离开发模式下,如何友好的返回统一的标准格式以及如何优雅的处理全局异常。

              首先我们来看看为什么要返回统一的标准格式?

              为什么要对SpringBoot返回统一的标准格式

              在默认情况下,SpringBoot的返回格式常见的有三种:

              第一种:返回 String

              @GetMapping("/hello")public String getStr(){  return "hello,javadaily";}

              此时调用接口获取到的返回值是这样:

              hello,javadaily

              第二种:返回自定义对象

              @GetMapping("/aniaml")public Aniaml getAniaml(){  Aniaml aniaml = new Aniaml(1,"pig");  return aniaml;}

              此时调用接口获取到的返回值是这样:

              {  "id": 1,  "name": "pig"}

              第三种:接口异常

              @GetMapping("/error")public int error(){    int i = 9/0;    return i;}

              此时调用接口获取到的返回值是这样:

              {  "timestamp": "2021-07-08T08:05:15.423+00:00",  "status": 500,  "error": "Internal Server Error",  "path": "/wrong"}

              基于以上种种情况,如果你和前端开发人员联调接口她们就会很懵逼,由于我们没有给他一个统一的格式,前端人员不知道如何处理返回值。

              还有甚者,有的同学比如小张喜欢对结果进行封装,他使用了Result对象,小王也喜欢对结果进行包装,但是他却使用的是Response对象,当出现这种情况时我相信前端人员一定会抓狂的。

              所以我们项目中是需要定义一个统一的标准返回格式的。

              定义返回标准格式

              一个标准的返回格式至少包含3部分:

              • status 状态值:由后端统一定义各种返回结果的状态码

              • message 描述:本次接口调用的结果描述

              • data 数据:本次返回的数据

              {  "status":"100",  "message":"操作成功",  "data":"hello,javadaily"}

              当然也可以按需加入其他扩展值,比如我们就在返回对象中添加了接口调用时间

              timestamp: 接口调用时间

              定义返回对象

              @Datapublic class ResultData<t> {    private int status;  private String message;  private T data;  private long timestamp ;  public ResultData (){    this.timestamp = System.currentTimeMillis();  }  public static <t> ResultData<t> success(T data) {    ResultData<t> resultData = new ResultData<>();    resultData.setStatus(ReturnCode.RC100.getCode());    resultData.setMessage(ReturnCode.RC100.getMessage());    resultData.setData(data);    return resultData;  }  public static <t> ResultData<t> fail(int code, String message) {    ResultData<t> resultData = new ResultData<>();    resultData.setStatus(code);    resultData.setMessage(message);    return resultData;  }}

              定义状态码

              public enum ReturnCode {        RC100(100,"操作成功"),        RC999(999,"操作失败"),        RC200(200,"服务开启限流保护,请稍后再试!"),        RC201(201,"服务开启降级保护,请稍后再试!"),        RC202(202,"热点参数限流,请稍后再试!"),        RC203(203,"系统规则不满足要求,请稍后再试!"),        RC204(204,"授权规则不通过,请稍后再试!"),        RC403(403,"无访问权限,请联系管理员授予权限"),        RC401(401,"匿名用户访问无权限资源时的异常"),        RC500(500,"系统异常,请稍后重试"),    INVALID_TOKEN(2001,"访问令牌不合法"),    ACCESS_DENIED(2003,"没有权限访问该资源"),    CLIENT_AUTHENTICATioN_FAILED(1001,"客户端认证失败"),    USERNAME_OR_PASSWord_ERROR(1002,"用户名或密码错误"),    UNSUPPORTED_GRANT_TYPE(1003, "不支持的认证模式");        private final int code;        private final String message;    ReturnCode(int code, String message){        this.code = code;        this.message = message;    }    public int getCode() {        return code;    }    public String getMessage() {        return message;    }}

              统一返回格式

              @GetMapping("/hello")public ResultData<string> getStr(){return ResultData.success("hello,javadaily");}

              此时调用接口获取到的返回值是这样:

              {  "status": 100,  "message": "hello,javadaily",  "data": null,  "timestamp": 1625736481648,  "httpstatus": 0}

              这样确实已经实现了我们想要的结果,我在很多项目中看到的都是这种写法,在Controller层通过ResultData.success()对返回结果进行包装后返回给前端。

              看到这里我们不妨停下来想想,这样做有什么弊端呢?

              最大的弊端就是我们后面每写一个接口都需要调用ResultData.success()这行代码对结果进行包装,重复劳动,浪费体力;而且还很容易被其他老鸟给嘲笑。

              所以呢我们需要对代码进行优化,目标就是不要每个接口都手工制定ResultData返回值。

              高级实现方式

              要优化这段代码很简单,我们只需要借助SpringBoot提供的ResponseBodyAdvice即可。

              ResponseBodyAdvice的作用:拦截Controller方法的返回值,统一处理返回值/响应体,一般用来统一返回格式,加解密,签名等等。

              先来看下ResponseBodyAdvice源码

              public interface ResponseBodyAdvice<t> {    boolean supports(MethodParameter var1, Class<!--? extends HttpMessageConverter<?-->> var2);      @Nullable    T beforeBodyWrite(@Nullable T var1, MethodParameter var2, MediaType var3, Class<!--? extends HttpMessageConverter<?-->> var4, ServerHttpRequest var5, ServerHttpResponse var6);}

              我们只需要编写一个具体实现类即可

              @RestControllerAdvicepublic class ResponseAdvice implements ResponseBodyAdvice<object> {    @Autowired    private ObjectMapper objectMapper;    @Override    public boolean supports(MethodParameter methodParameter, Class<!--? extends HttpMessageConverter<?-->> aClass) {        return true;    }    @SneakyThrows    @Override    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<!--? extends HttpMessageConverter<?-->> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {        if(o instanceof String){            return objectMapper.writeValueAsString(ResultData.success(o));        }                return ResultData.success(o);    }}

              需要注意两个地方:

              @RestControllerAdvice注解

              @RestControllerAdvice@RestController注解的增强,可以实现三个方面的功能:

              • 全局异常处理

              • 全局数据绑定全

              • 局数据预处理

              String类型判断

              if(o instanceof String){  return objectMapper.writeValueAsString(ResultData.success(o));}

              这段代码一定要加,如果Controller直接返回String的话,SpringBoot是直接返回,故我们需要手动转换成JSON

              经过上面的处理我们就再也不需要通过ResultData.success()来进行转换了,直接返回原始数据格式,SpringBoot自动帮我们实现包装类的封装。

              @GetMapping("/hello")public String getStr(){    return "hello,javadaily";}

              此时我们调用接口返回的数据结果为:

              @GetMapping("/hello")public String getStr(){  return "hello,javadaily";}

              是不是感觉很完美,别急,还有个问题在等着你呢。

              接口异常问题

              此时有个问题,由于我们没对Controller的异常进行处理,当我们调用的方法一旦出现异常,就会出现问题,比如下面这个接口

              @GetMapping("/wrong")public int error(){    int i = 9/0;    return i;}

              返回的结果为:

              SpringBoot如何统一后端返回格式

              这显然不是我们想要的结果,接口都报错了还返回操作成功的响应码,前端看了会打人的。

              别急,接下来我们进入第二个议题,如何优雅的处理全局异常。

              SpringBoot为什么需要全局异常处理器

              不用手写try...catch,由全局异常处理器统一捕获

              使用全局异常处理器最大的便利就是程序员在写代码时不再需要手写try...catch了,前面我们讲过,默认情况下SpringBoot出现异常时返回的结果是这样:

              {  "timestamp": "2021-07-08T08:05:15.423+00:00",  "status": 500,  "error": "Internal Server Error",  "path": "/wrong"}

              这种数据格式返回给前端,前端是看不懂的,所以这时候我们一般通过try...catch来处理异常

              @GetMapping("/wrong")public int error(){    int i;    try{        i = 9/0;    }catch (Exception e){        log.error("error:{}",e);        i = 0;    }    return i;}

              我们追求的目标肯定是不需要再手动写try...catch了,而是希望由全局异常处理器处理。

              对于自定义异常,只能通过全局异常处理器来处理

              @GetMapping("error1")public void empty(){throw  new RuntimeException("自定义异常");}

              当我们引入Validator参数校验器的时候,参数校验不通过会抛出异常,此时是无法用try...catch捕获的,只能使用全局异常处理器。

              SpringBoot集成参数校验请参考这篇文章SpringBoot开发秘籍 - 集成参数校验及高阶技巧

              如何实现全局异常处理器

              @Slf4j@RestControllerAdvicepublic class RestExceptionHandler {        @ExceptionHandler(Exception.class)    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)    public ResultData<string> exception(Exception e) {        log.error("全局异常信息 ex={}", e.getMessage(), e);        return ResultData.fail(ReturnCode.RC500.getCode(),e.getMessage());    }}

              有三个细节需要说明一下:

              • @RestControllerAdvice,RestController的增强类,可用于实现全局异常处理器

              • @ExceptionHandler,统一处理某一类异常,从而减少代码重复率和复杂度,比如要获取自定义异常可以@ExceptionHandler(BusinessException.class)

              • @ResponseStatus指定客户端收到的http状态码

              体验效果

              这时候我们调用如下接口:

              @GetMapping("error1")public void empty(){    throw  new RuntimeException("自定义异常");}

              返回的结果如下:

              {  "status": 500,  "message": "自定义异常",  "data": null,  "timestamp": 1625795902556}

              基本满足我们的需求了。

              但是当我们同时启用统一标准格式封装功能ResponseAdviceRestExceptionHandler全局异常处理器时又出现了新的问题:

              {  "status": 100,  "message": "操作成功",  "data": {    "status": 500,    "message": "自定义异常",    "data": null,    "timestamp": 1625796167986  },  "timestamp": 1625796168008}

              此时返回的结果是这样,统一格式增强功能会给返回的异常结果再次封装,所以接下来我们需要解决这个问题。

              全局异常接入返回的标准格式

              要让全局异常接入标准格式很简单,因为全局异常处理器已经帮我们封装好了标准格式,我们只需要直接返回给客户端即可。

              @SneakyThrows@Overridepublic Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<!--? extends HttpMessageConverter<?-->> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {  if(o instanceof String){    return objectMapper.writeValueAsString(ResultData.success(o));  }  if(o instanceof ResultData){    return o;  }  return ResultData.success(o);}

              关键代码:

              if(o instanceof ResultData){  return o;}

              如果返回的结果是ResultData对象,直接返回即可。

              这时候我们再调用上面的错误方法,返回的结果就符合我们的要求了。

              {  "status": 500,  "message": "自定义异常",  "data": null,  "timestamp": 1625796580778}

              好了,今天的文章就到这里了,希望通过这篇文章你能掌握如何在你项目中友好实现统一标准格式到返回并且可以优雅的处理全局异常。

              GitHub地址:https://github.com/jianzh6/cloud-blog/

              感谢各位的阅读,以上就是“SpringBoot如何统一后端返回格式”的内容了,经过本文的学习后,相信大家对SpringBoot如何统一后端返回格式这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

              --结束END--

              本文标题: SpringBoot如何统一后端返回格式

              本文链接: https://www.lsjlt.com/news/298192.html(转载时请注明来源链接)

              有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

              本篇文章演示代码以及资料文档资料下载

              下载Word文档到电脑,方便收藏和打印~

              下载Word文档
              猜你喜欢
              • SpringBoot如何统一后端返回格式
                这篇文章主要讲解了“SpringBoot如何统一后端返回格式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringBoot如何统一后端返回格式”吧!目录为什么要对SpringBoot返回...
                99+
                2023-06-20
              • 详解SpringBoot如何统一后端返回格式
                目录为什么要对SpringBoot返回统一的标准格式第一种:返回 String第二种:返回自定义对象第三种:接口异常定义返回标准格式高级实现方式接口异常问题SpringBoot为什么...
                99+
                2022-11-12
              • SpringBoot怎么实现统一后端返回格式
                这篇文章主要介绍“SpringBoot怎么实现统一后端返回格式”,在日常操作中,相信很多人在SpringBoot怎么实现统一后端返回格式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot怎么实...
                99+
                2023-06-30
              • 详解SpringBoot如何实现统一后端返回格式
                目录1.为什么要对SpringBoot返回统一的标准格式1.1 返回String1.2 返回自定义对象1.3 接口异常2.定义返回对象3.定义状态码4.统一返回格式5.高级实现方式5...
                99+
                2022-11-13
              • 详解SpringBoot 统一后端返回格式的方法
                目录为什么要对SpringBoot返回统一的标准格式定义返回标准格式定义返回对象定义状态码统一返回格式高级实现方式接口异常问题SpringBoot为什么需要全局异常处理器如何实现全局...
                99+
                2022-11-13
              • SpringBoot全局Controller返回值格式统一
                目录一、返回值格式统一1.返回值介绍2.基础类功能3.基础实现二、附录说明一、返回值格式统一 1.返回值介绍 在使用controller对外提供服务的时候,很多时候都需要统一返回值格...
                99+
                2022-11-12
              • 一文学会处理SpringBoot统一返回格式
                目录背景SpringBoot Controller 常见的返回格式String自定义对象正常返回错误返回定义返回对象定义状态枚举统一处理返回值及异常void 无返回值有返回值背景 相...
                99+
                2022-11-13
                SpringBoot统一返回格式  统一返回格式
              • SpringBoot统一返回格式的方法详解
                目录前言1. 直接返回结果2. 约定返回格式3. 返回统一格式结果4. 切片封装统一格式编写注解编写ControllerAdvice见证奇迹的时刻到了5. 自定义返回格式场景1:返回...
                99+
                2022-11-13
              • SpringBoot统一返回JSON格式实现方法详解
                目录定义JSON格式定义JavaBean字段定义返回体类Result实体返回测试统一返回JSON格式进阶全局处理(@RestControllerAdvice)@ResponseBod...
                99+
                2023-02-03
                SpringBoot返回JSON格式 SpringBoot无侵入式返回JSON格式
              • SpringBoot中怎么统一全局Controller返回值格式
                这期内容当中小编将会给大家带来有关SpringBoot中怎么统一全局Controller返回值格式,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、返回值格式统一1.返回值介绍在使用controller对...
                99+
                2023-06-20
              • SpringBoot如何返回Json数据格式
                目录一、@RestController 注解二、Jackson1、对象、List、Map 转换为Json格式2、Jackson 的配置类三、FastjsonFastjson 配置类四...
                99+
                2023-03-22
                SpringBoot返回Json 返回Json数据格式 SpringBoot返回Json数据
              • 关于springboot的接口返回值统一标准格式
                目录一、目标二、为什么要对springboot的接口返回值统一标准格式第一种格式:response为String第二种格式:response为Objct第三种格式:response为...
                99+
                2022-11-13
              • SpringBoot返回统一的JSON标准格式实现步骤
                期望返回的JSON格式如下 { "code": 200, "msg": "操作成功", "data": "hello jenkins" } 实现步骤如下 1.自定义...
                99+
                2022-11-12
              • 怎么在SpringBoot中统一api的返回风格
                怎么在SpringBoot中统一api的返回风格?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。例如{ "code": 200,&nb...
                99+
                2023-06-07
              • SpringBoot如何实现统一封装返回前端结果集
                这篇文章主要介绍了SpringBoot如何实现统一封装返回前端结果集的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringBoot如何实现统一封装返回前端结果集文章都会有所收获,下面我们一起来看看吧。我们如...
                99+
                2023-07-02
              • API接口统一格式返回的方法
                本篇内容介绍了“API接口统一格式返回的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!接口交互前端和后端进行交互,前端按照约定请求URL...
                99+
                2023-06-27
              • 如何设计API接口实现统一格式返回
                这篇文章给大家介绍如何设计API接口实现统一格式返回,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。前言在移动互联网,分布式、微服务盛行的今天,现在项目绝大部分都采用的微服务框架,前后端分离方式,(题外话:前后端的工作职...
                99+
                2023-06-05
              • 后端接口返回文件流格式、前端如何实现文件下载导出呢?
                在项目开发过程中,难免会需要实现文件下载功能,记录下自己实际开发过程过程中遇到两种实现的方式。一种:后端直接返回加密url ,前端解密后直接使用 a标签下载就可以,这种方法相等比较简单,另一种:后端接...
                99+
                2023-09-02
                前端 java javascript
              • 后端java 如何返回给前端 JSON数据
                后端java 如何返回给前端 JSON数据 JSON数据 var data = [ { checkinginTime: '2023-04-23', ip: '111' }, { checkinginTime: '20...
                99+
                2023-08-20
                java 前端 json
              • .NetCore Web Api怎么用ActionFilterAttribute统一接口返回值格式
                本文小编为大家详细介绍“.NetCore Web Api怎么用ActionFilterAttribute统一接口返回值格式”,内容详细,步骤清晰,细节处理妥当,希望这篇“.NetCore Web Ap...
                99+
                2023-06-29
              软考高级职称资格查询
              编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
              • 官方手机版

              • 微信公众号

              • 商务合作