大家好,我是飘渺。今天我们就来说说在SpringBoot基于前后端分离的开发模式下,如何友好的返回一个统一的标准格式,如何优雅的处理全局异常。首先我们来看一下为什么要返回一个统一的标准格式?为什么要给SpringBoot返回一个统一的标准格式?默认情况下,SpringBoot常见的返回格式有三种:第一种:returnString@GetMapping("/hello")publicStringgetStr(){return"hello,javadaily";}此时调用接口获取的返回值如下:hello,javadaily第二种:返回自定义对象@GetMapping("/aniaml")publicAniamlgetAniaml(){Aniamlaniaml=newAniaml(1,"pig");returnaniaml;}这时候通过获取的返回值调用接口如下:{"id":1,"name":"pig"}第三种:接口异常@GetMapping("/error")publicintererror(){inti=9/0;returni;}此时调用接口得到的返回值如下:{"timestamp":"2021-07-08T08:05:15.423+00:00","status":500,"error":"InternalServerError","path":"/wrong"}基于以上情况,如果你和前端开发人员共同调试界面,他们会很迷茫,因为我们没有给他一个统一的格式,前端人员不知道如何处理返回值UE。更有什者,有些同学,比如小张,喜欢把成绩包装起来。他用的是Result对象,小王也喜欢对结果进行封装,但是他用的是Response对象。遇到这种情况,相信前端人员一定是疯了。因此,我们需要在我们的项目中定义一个统一的标准返回格式。定义返回标准格式一个标准的返回格式至少包括3部分:status状态值:后台统一定义各种返回结果的状态码messagedescription:本次接口调用的结果描述datadata:本次返回的数据.{"status":"100","message":"操作成功","data":"hello,javadaily"}当然也可以根据需要添加其他扩展值,比如我们添加的接口返回对象中的调用时间4.timestamp:接口调用时间定义返回对象@DatapublicclassResultData{/**结果状态,见ResultData.java*/privateintstatus;privateStringmessage;privateTdata;privatelongtimestamp;publicResultData(){this.timestamp=System.currentTimeMillis获取特定状态码();}publicstaticResultDatasuccess(Tdata){ResultDataresultData=newResultData<>();resultData.setStatus(ReturnCode.RC100.getCode());resultData.setMessage(ReturnCode.RC100.getMessage());resultData.setData(data);returnresultData;}publicstaticResultDatafail(intcode,Stringmessage){ResultDataresultData=newResultData<>();resultData.setStatus(code);resultData.setMessage(message);returnresultData;}}定义状态码publicenumReturnCode{/**操作成功**/RC100(100,"操作成功ded"),/**操作失败**/RC999(999,"操作失败"),/**服务限流**/RC200(200,"服务已开启限流保护,请稍后再试!"),/**服务降级**/RC201(201,"服务已开启降级保护,请稍后再试!"),/**热点参数currentlimiting**/RC202(202,"热点参数限流,请稍后再试!"),/**系统规则不符合要求**/RC203(203,"系统规则不符合要求requirements,pleasetryagainlater!"),/**授权规则失败**/RC204(204,"授权规则失败,请稍后重试!"),/**access_denied**/RC403(403,"无法访问权限,请联系管理管理员授予的权限"),/**access_denied**/RC401(401,"匿名用户未经许可访问资源时异常"),/**服务异常**/RC500(500,"系统异常,请稍后再试Try"),INVALID_TOKEN(2001,"访问令牌无效"),ACCESS_DENIED(2003,"您无权访问此资源"),CLIENT_AUTHENTICATION_FAILED(1001,"客户端认证失败"),USERNAME_OR_PASSWORD_ERROR(1002,"用户名或密码错误"),UNSUPPORTED_GRANT_TYPE(1003,"不支持的认证方式");/**自定义状态码**/privatefinalintcode;/**自定义说明**/privatefinalStringmessage;ReturnCode(intcode,Stringmessage){this.code=code;this.message=message;}publicintgetCode(){returncode;}publicStringgetMessage(){returnmessage;}}统一返回格式@GetMapping("/hello")publicResultDatagetStr(){returnResultData.success("你好,javadaily");}此时调用接口得到的返回值如下:{"status":100,"message":"hello,javadaily","data":null,"timestamp":1625736481648,"httpStatus":0}这样确实达到了我们想要的结果,在很多项目中看到过这种写法,在Controller层,通过ResultData.success()将返回的结果打包返回给前端,看这里我们不妨停下来想一想,这样做的缺点是什么?最大的缺点就是我们每次写接口都需要调用ResultData.success()这行代码来打包结果,重复劳动和浪费精力;而且很容易被其他人利用老鸟笑。所以我们需要优化代码代码,我们只需要使用SpringBoot提供的ResponseBodyAdvice即可。vice功能:拦截Controller方法的返回值,对返回值/响应体进行统一处理,一般用于统一返回格式、加解密、签名等。我们先看ResponseBodyAdvice的源码:publicinterfaceResponseBodyAdvice{/***advice功能是否支持*true支持,false不支持*/booleansupports(MethodParametervar1,Class>var2);/***对返回的数据进行处理*/@NullableTbeforeBodyWrite(@NullableTvar1,MethodParametervar2,MediaTypevar3,Class>var4,ServerHttpRequestvar5,ServerHttpResponsevar6);}我们只需要写一个具体的实现类即可/***@authorjam*@date2021/7/810:10上午*/@RestControllerAdvicepublicclassResponseAdviceimplementsResponseBodyAdvice