前言:
通过实践而发现真理,又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识,又从理性认识而能动地指导革命实践,改造主观世界和客观世界。实践、认识、再实践、再认识,这种形式,循环往复以至无穷,而实践和认识之每一循环的内容,都比较地进到了高一级的程度。
简单回忆:
基础统一响应1.0
/** * 基础统一响应类 * @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; } }
在1.0的基础上,进行优化加工
/** * 统一响应类实例化工具 */ 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<>(NO,message); } }
在1.0,2.0的基础上进行迭代后的全局响应
@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); } }
3.0完成全局统一响应(无论成功还是失败)
正片:
通过不断的测试,重启,从而发现真理
测试方法:不断修改变量,简称量变产生质变
测试代码
@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); } }
第一轮测试:删除注解——@ControllerAdvice
测试结果:返回值为api接口类型
对比带有@ControllerAdvice的结果
结论:@ControllerAdvice具有覆盖默认接口类型的作用
我们还原最初的全局配置
@ControllerAdvice public class GlobalApiResult implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { //false -> true 用于测试,正式的时需要修改 return false; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { //第二步: 将body传入统一响应工具类中的默认成功响应 return null; } }
实现接口后的最原始状态
第二轮测试:带有@ControllerAdvice的测试
与删除@ControllerAdvice的测试的无差别
结论:@ControllerAdvice不具有覆盖默认接口类型的作用
第三轮测试:将实现中的boolean support 的返回值 false改为true
@ControllerAdvice public class GlobalApiResult implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { //false -> true 用于测试,正式的时需要修改 return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { //第二步: 将body传入统一响应工具类中的默认成功响应 return null; } }
测试结果:无返回值,无响应类型
结论:boolean support 符合真理
真理:当第一个函数 support 的返回值为true,运行第二个函数beforeBodyWrite,当前第二个函数的返回值为null,所以无响应
第四轮测试:保持第三轮测试代码,删除注解@ControllerAdvice
测试结果:
结论:@ControllerAdvice 很重要,没有它,下面的代码无用,@ControllerAdvice提供了对全局统一响应支持
第五轮测试:在第一个函数上打上断点
测试结果:
但是我们可以根据测试找到对应它的作用
这个方法读取了接口的基本信息
第一个参数:返回类型
第二个参数:转换器类型
第一个参数的类型如图
总体来看,返回类型是指api接口的返回类型
第二个参数:
它展示的是MappingJackson2HttpMessageConverter类的具体路径,包
结论:
boolean support的两个形参
第一个参数:returnType 为接口的基本信息
第二个参数:ConverterType为MappingJackson2HttpMessageConverter的基本信息
第六轮测试:给beforBodywrite打上断点
测试过程:
第一步:发送请求至接口
support的形成拿到两个数值
第一个参数:returnType 为api接口的基本信息
第二个参数:ConverterType为MappingJackson2HttpMessageConverter的基本信息
没变化
返回值为ture进行下一步
/** * HttpMessageConverter转换之前进行的操作 * @param body 要转换的body * @param returnType 返回类型 * @param selectedContentType 根据请求头协商的ContentType * @param selectedConverterType 自动选择的转换器类型 * @param request 当前请求 * @param response 当前响应 * @return 修改后的响应内容 */
默认
我们一条一条对
首先body
和我们的mapper映射后的结果一模一样,换一句话说,它的结果就是我们调用查询数据库后的返回结果,用专业术语叫响应体,不专业的叫查询业务返回值
returnType和support一模一样
selectedContentType
selectedConverterType
翻译:查询内容类型,查询转换器类型
查询转换器类型和support一模一样
也就是说support的两个参数和beforeBodyWrite的一模一样
beforeBodyWrite多了四个参数
分别是响应体,内容类型,请求,响应
第七轮测试
将响应体作为返回值
@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 业务层接口返回值
* @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 body;
}
}
测试
结论:beforBodyWrite的返回值为控制类的响应体
总结:
@ControllerAdvice提供了对全局统一响应支持
supports与beforBodyWrite相关联