前言:起于环境,先于实践,源于变化,升于思考,再于实践,形于总结——实践至上!
简单回顾:
java">/** * 基础统一响应类 * @param <T> */ @Data public class apiResult<T> { private int code; private String message; private T data; /** * 带有data返回的构造函数 * @param code * @param message * @param data */ public apiResult(int code, String message, T data) { this.code = code; this.message = message; this.data = data; } /** * 不带data的构造函数 * @param code * @param message */ public apiResult(int code,String message){ this.code = code; this.message = message; } }
加工类
java">/** * 统一响应类实例化工具 */ public class apiResultYOUYA { //http成功状态码 private static final int OK = HttpStatus.OK.value(); //隔着报错状态码 private static int NO = HttpStatus.INTERNAL_SERVER_ERROR.value(); //基本成功响应 public static <T>apiResult<T> success(T data){ return new apiResult<>(OK,"操作成功",data); } //自定义信息成功响应 public static <T>apiResult<T> success(String message,T data){ return new apiResult<>(OK,message,data); } //基础失败响应 public static <T>apiResult<T> error(){ return new apiResult<>(NO,"系统错误,请联系管理员"); } //自定义信息失败响应 public static <T>apiResult<T> error(String message){ return new apiResult<>(431,message); } }
测试控制类
java"> @GetMapping("/id") public apiResult<UserPageEntity> id(int id){ UserPageEntity userPage = userPageServer.UserByID(id); if (userPage == null) { return apiResultYOUYA.error("老登,没有这一号人,是不是记错了"); } return apiResultYOUYA.success("成功查询,老登",userPage);
虽然不规范,但是能用
这是我们上一期对方法不生效的解释:我们并没用统一响应覆盖掉的异常报错,这只是简单的响应返回,我们响应统一覆盖掉异常报错才能做到解决
这是因为作者没有重新编译导致的问题,但是这破AI居然认可了我们这种说法,也是没谁了,最后是如何排查出问题的呢?
后来作者写3.0的内容时,顺手刷新了一下,成了
越小的错误,产生越大的bug
正片:
全局统一响应基础三步走
第一步:打上注解@ControllerAdvice
第二步:实现ResponseBodyAdvice<object>接口
第三步:重写方法
java">@ControllerAdvice public class GlobalApiResult implements ResponseBodyAdvice<Object> { /** * 此Advice是否使用于该返回类型和Converter类型(意思是可以配置多个哦) * @param returnType 返回类型(这里可以获取很多东西, 别被名字误导了) * @param converterType 自动选择的转换器类型 * @return 返回true表示将会走接下来的方法(beforeBodyWrite), 否则不会 */ @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { return false; } /** * HttpMessageConverter转换之前进行的操作 * @param body 要转换的body * @param returnType 返回类型 * @param selectedContentType 根据请求头协商的ContentType * @param selectedConverterType 自动选择的转换器类型 * @param request 当前请求 * @param response 当前响应 * @return 修改后的响应内容 */ @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { return null; } }
三步走完后,我们获取到一个基础的全局响应配置,接下在这两个方法中做文章,便可实现全局统一响应
自定义全局响应:
第一步:先将supports改为true
第二步:将body传入至我们的统一响应工具类中
java"> @ControllerAdvice public class GlobalApiResult implements ResponseBodyAdvice<Object> { /** * 此Advice是否使用于该返回类型和Converter类型(意思是可以配置多个哦) * @param returnType 返回类型(这里可以获取很多东西, 别被名字误导了) * @param converterType 自动选择的转换器类型 * @return 返回true表示将会走接下来的方法(beforeBodyWrite), 否则不会 */ @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { //false -> true 用于测试,正式的时需要修改 return true; } /** * HttpMessageConverter转换之前进行的操作 * @param body 要转换的body * @param returnType 返回类型 * @param selectedContentType 根据请求头协商的ContentType * @param selectedConverterType 自动选择的转换器类型 * @param request 当前请求 * @param response 当前响应 * @return 修改后的响应内容 */ @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { //第二步: 将body传入统一响应工具类中的默认成功响应 return apiResultYOUYA.success(body); } }
修改我们的测试controller
java">@RestController public class test { @Resource UserPageServer userPageServer; /** * 自定义响应信息的运用 * * @param id * @return */ @GetMapping("/id") public UserPageEntity id(int id){ return userPageServer.UserByID(id); }
运行测试结果
运行前,先使用maven的claen生命周期,再编译运行,避免同上面一模一样的错误
来一个完整的增删改查,再体验体验
java">@RestController @RequestMapping("/test") public class test { @Resource UserPageServer userPageServer; @GetMapping("/id") public UserPageEntity id(int id) { return userPageServer.UserByID(id); } @PostMapping("/insert") public int insert(@RequestBody UserPageEntity userPageEntity) { return userPageServer.UserInsert(userPageEntity); } @PostMapping("/update") public int update(@RequestBody UserPageEntity userPageEntity) { return userPageServer.UserUpdate(userPageEntity); } @PostMapping("/delete") public int delete(@RequestBody Long[] id) { return userPageServer.USerDelete(id); } }
经典永不过时
测试
无效新增
有效新增
有效查询
无效查询
无效删除
有效删除
无效更新
有效更新
经典CRUD下来,发现没,响应成功的还好说,没响应成功也套用了,也是完成了我们的目标
全局响应了
全局统一响应(无论对错)
那如果配合上局部呢?
就会因为类型的问题导致,那就修改类型
java"> @GetMapping("/id") public apiResult<UserPageEntity> id(int id) { UserPageEntity userPageEntity = userPageServer.UserByID(id); if (userPageEntity == null) { return apiResultYOUYA.error("没有该用户,老登"); } return apiResultYOUYA.success("查询成功了,老登", userPageEntity); }
局部和全局无法同时纯在,局部>全局,就和交通法一样,地方 大于 全国
除了上面两个例子还有很多,全局作用域和局部作用域
在js中更容易体现,java还有报错
小结:如何快速达到真 · 全局统一响应(无论成功还是失败)
java">@ControllerAdvice public class GlobalApiResult implements ResponseBodyAdvice<Object> { /** * 此Advice是否使用于该返回类型和Converter类型(意思是可以配置多个哦) * @param returnType 返回类型(这里可以获取很多东西, 别被名字误导了) * @param converterType 自动选择的转换器类型 * @return 返回true表示将会走接下来的方法(beforeBodyWrite), 否则不会 */ @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { //false -> true 用于测试,正式的时需要修改 return true; } /** * HttpMessageConverter转换之前进行的操作 * @param body 要转换的body * @param returnType 返回类型 * @param selectedContentType 根据请求头协商的ContentType * @param selectedConverterType 自动选择的转换器类型 * @param request 当前请求 * @param response 当前响应 * @return 修改后的响应内容 */ @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { //第二步: 将body传入统一响应工具类中的默认成功响应 return apiResultYOUYA.success(body); } }
第二阶段:
打上断点,测试这个方法起到的作用
当我们触发查询接口时,他自动的触发了这个方法
自动获取了接口的这6个参数
发现没,这个方法自动归类了,不知道是真是假,所以我们修改一下内容进行测试
原来如此,所谓的统一响应的来源是这个,spring web的响应内容就是由这三个大部分组成的,所谓的统一,是对接口的统一,而不是对响应内容的统一
此统一非响应统一,原因是,响应早已经是统一的了
再来一轮测试
javascript"> @GetMapping("/id")
public UserPageEntity id(int id) {
return userPageServer.UserByID(id);
}
修改测试接口
通过不断的测试,测试,修改内容,作者发现了惊天的秘密(别人早在文档里就写了,你算什么发现!!!!)
下一期说明发现!