为什么?
前后端拆散的时代,如果没有对立的返回格局,给前端的后果各式各样,预计前端的小伙伴就要骂娘了。
咱们想对自定义异样抛出指定的状态码排查谬误,对系统的不可预知的异样抛出敌对一点的异样信息。
咱们想让接口对立返回一些额定的数据,例如接口执行的工夫等等。
...
所以嘛,不论是日常和前端小伙伴对接,还是和其余部门进行接口对接,都应该返回固定的格局。
本文给出一个简略通用的返回格局,小伙伴们有需要,能够基于此版本依据本人的业务需要丰盛返回格局。
返回数据格式如下,有趣味的小伙伴们能够持续往下看SpringBoot是怎么来实现的。
{ "status": true, "code": "0000", "msg": "", "data": { "id": 1, "deptId": 103, "userName": "admin", "nickName": "笑小枫", "userType": "00", "email": "xxf@163.com", "phone": "15888888888", "status": "0", "remark": "管理员" }}
怎么做?
首先创立一个测试的Controller,代码如下
package com.maple.demo.controller;import com.maple.demo.util.ResultJson;import lombok.Data;import lombok.RequiredArgsConstructor;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/** * @author 笑小枫 * @date 2022/07/15 */@RestController@RequiredArgsConstructor@RequestMapping("/example")public class TestResultController { @GetMapping("/testResult") public Test testResult() { Test test = new Test(); test.setName("笑小枫"); test.setAge(18); test.setRemark("大家好,我是笑小枫,喜爱我的小伙伴点个赞呗"); return test; } @GetMapping("/testResultJson") public ResultJson testResultJson() { Test test = new Test(); test.setName("笑小枫"); test.setAge(18); test.setRemark("大家好,我是笑小枫,喜爱我的小伙伴点个赞呗"); return new ResultJson(test); } @Data static class Test { private String name; private Integer age; private String remark; }}
咱们先看看这是调用返回的后果
{ "name": "笑小枫", "age": 18, "remark": "大家好,我是笑小枫,喜爱我的小伙伴点个赞"}
而后在util包下定义一个对立的返回格局类,代码如下
package com.maple.demo.util;import lombok.Data;/** * 对立返回信息包装类 * * @author 笑小枫 * @date 2022/07/15 */@Datapublic class ResultJson { private static final String SUCCESS_CODE = "0000"; /** * 成功失败的状态值,true:胜利;false:失败 * 这里返回编码为:“0000”,零碎就认为接口胜利;其余值,代表失败 */ private Boolean status; /** * 状态码 正确为0000 */ private String code; /** * 返回提示信息 */ private String msg; /** * 返回数据 */ private Object data; public ResultJson() { this.status = true; this.code = SUCCESS_CODE; this.msg = ""; } public ResultJson(Object data) { this.status = true; this.code = SUCCESS_CODE; this.msg = ""; this.data = data; } public ResultJson(String code, String msg) { this.status = SUCCESS_CODE.equals(code); this.code = code; this.msg = msg; } /** * 如果返回状态码非0000,且接口状态为胜利,请应用这个 * @param status 接口申请状态 * @param code 返回code值 * @param msg 返回音讯 * @param data 返回数据 */ public ResultJson(Boolean status, String code, String msg, Object data) { this.status = status; this.code = code; this.msg = msg; this.data = data; }}
一般版,代码侵入性强
这样咱们能够把后果对立放在ResultJson外面返回,代码如下
package com.maple.demo.controller;import com.maple.demo.util.ResultJson;import lombok.Data;import lombok.RequiredArgsConstructor;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/** * @author 笑小枫 * @date 2022/07/15 */@RestController@RequiredArgsConstructor@RequestMapping("/example")public class TestResultController { @GetMapping("/testResult") public Test testResult() { Test test = new Test(); test.setName("笑小枫"); test.setAge(18); test.setRemark("大家好,我是笑小枫,喜爱我的小伙伴点个赞呗"); return test; } /** * 一般的返回 */ @GetMapping("/testResultJson") public ResultJson testResultJson() { Test test = new Test(); test.setName("笑小枫"); test.setAge(18); test.setRemark("大家好,我是笑小枫,喜爱我的小伙伴点个赞呗"); return new ResultJson(test); } @Data static class Test { private String name; private Integer age; private String remark; }}
咱们看一下返回的后果
{ "status": true, "code": "0000", "msg": "", "data": { "name": "笑小枫", "age": 18, "remark": "大家好,我是笑小枫,喜爱我的小伙伴点个赞呗" }}
切面解决,代码无侵入
上述代码尽管实现了性能,但所有的返回后果都要解决,对代码有比拟强的侵入,Spring领有各种切面的反对,让咱们看看如何代码无侵入的实现这个性能。
最初创立一个配置类,增加@RestControllerAdvice
注解,代码如下
package com.maple.demo.config;import com.alibaba.fastjson.JSON;import com.maple.demo.util.ResultJson;import lombok.extern.slf4j.Slf4j;import org.jetbrains.annotations.NotNull;import org.springframework.core.MethodParameter;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.web.bind.annotation.RestControllerAdvice;import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;/** * 对返回后果对立进行解决,包含返回后果格局对立包装,返回异样对立解决 * * @author 笑小枫 * @date 2022/07/15 */@Slf4j@RestControllerAdvicepublic class RestResponseAdvice implements ResponseBodyAdvice<Object> { @Override public boolean supports(@NotNull MethodParameter returnType, @NotNull Class<? extends HttpMessageConverter<?>> converterType) { return true; } /** * 返回后果包装对立返回格局 * * @return 包装后的返回后果 */ @Override public Object beforeBodyWrite(Object body, @NotNull MethodParameter returnType, @NotNull MediaType selectedContentType, @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType, @NotNull ServerHttpRequest request, ServerHttpResponse response) { // 指定返回的后果为application/json格局 // 不指定,String类型转json后返回Content-Type是text/plain;charset=UTF-8 response.getHeaders().setContentType(MediaType.APPLICATION_JSON); ResultJson result = new ResultJson(body); // 若返回类型是ResultJson,则不进行批改 if (body == null) { if (returnType.getParameterType().isAssignableFrom(String.class)) { return JSON.toJSONString(result); } } else if (body instanceof ResultJson) { return body; } else if (body instanceof String) { return JSON.toJSONString(result); } return result; }}
这样就实现了对立后果的返回✌
咱们再申请文章最开始写的测试方法http://127.0.0.1:6666/testResult
看一下返回的后果
{ "status": true, "code": "0000", "msg": "", "data": { "name": "笑小枫", "age": 18, "remark": "大家好,我是笑小枫,喜爱我的小伙伴点个赞呗" }}
这样对立返回格局就实现了,对代码没有的侵入,原来的代码该怎么写还是怎么写,是不是很nice。
@RestControllerAdvice介绍
首先理解一下SpringBoot的@RestControllerAdvice
注解,它是Spring框架3.2新增的的注解
点进去这个注解源码,能够看到它是由@ControllerAdvice
和@ResponseBody
的组合注解
它通常用来定义@ExceptionHandler
,@InitBinder
以及@ModelAttribute
实用于所有办法@RequestMapping
的办法。
直白点说,这就是一个加强Controller的注解。次要实现以下三个方面的性能
- 全局异样解决
- 全局数据预处理
- 全局数据绑定
咱们看一下@RestControllerAdvice
注解的源码
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@ControllerAdvice@ResponseBodypublic @interface RestControllerAdvice { @AliasFor( annotation = ControllerAdvice.class ) String[] value() default {}; @AliasFor( annotation = ControllerAdvice.class ) String[] basePackages() default {}; @AliasFor( annotation = ControllerAdvice.class ) Class<?>[] basePackageClasses() default {}; @AliasFor( annotation = ControllerAdvice.class ) Class<?>[] assignableTypes() default {}; @AliasFor( annotation = ControllerAdvice.class ) Class<? extends Annotation>[] annotations() default {};}
应用@RestControllerAdvice
常做的两个性能的实现
- 返回对立格局的后果
- 异样对立解决
小结
好啦,本文就到这里了,咱们简略的总结一下,次要介绍了以下内容
- 为什么要返回对立的后果信息
- 手动封装对立的返回信息
- 应用@RestControllerAdvice主动封装返回信息
- 简略介绍@RestControllerAdvice注解
本文源码:https://github.com/hack-feng/maple-demo