目录

springBoot统一响应类型3.2版本

springBoot统一响应类型3.2版本

前言:

通过实践而发现真理,又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识,又从理性认识而能动地指导革命实践,改造主观世界和客观世界。实践、认识、再实践、再认识,这种形式,循环往复以至无穷,而实践和认识之每一循环的内容,都比较地进到了高一级的程度。

简单回顾3.1版本的内容:

1:@ControllerAdvice提供了对全局统一响应支持

2:supports与beforBodyWrite关系,用一个三元写法,supports ? beforBodyWrite :异常

正片:

进行基于以下代码,进行更加全面的测试

@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 apiResultYOUYA.success("3.0全新版本",body);
    }
}

对supports和beforeBodyWrite打上断点

https://i-blog.csdnimg.cn/direct/a77de6bd984b44f9950ef324d6b82e2f.png

触发接口时,supports通过MethodParameter自动捕获接口类型

https://i-blog.csdnimg.cn/direct/2e0fdd1cbb4d45c8b5b39035bfd309cc.png

2.就是一个包的路径,不做过多内容

supports,通过MethodParameter获取接口类型,也就是说它并没有做过多的接口处理

spring web 是如何使用这个接口的呢?

https://i-blog.csdnimg.cn/direct/4e2fca87cdde4c51875466dfca521403.png

这个方法

AbstractJackson2HttpMessageConverter.class.isAssignableFrom(converterType)

https://i-blog.csdnimg.cn/direct/efebf2fe91424733ab821dca609fd19b.png

翻译:如下

  • 判断此 {@code Class} 对象所表示的类或接口是否与指定的 {@code Class} 参数所表示的类或接口相同,或是其父类或父接口。若是则返回 {@code true};否则返回 {@code false}。若此 {@code Class} 对象表示基本类型,则当且仅当指定的 {@code Class} 参数与此 {@code Class} 对象完全相同时返回 {@code true},否则返回 {@code false}。

结合代码

AbstractJackson2HttpMessageConverter.class.isAssignableFrom(converterType)

if( AbstractJackson2HttpMessageConverter.class  ? converterType)

?是代码这isAssignableFrom的判断逻辑

isAssignableFrom有两种判断逻辑

第一种:判断接口是否相同(继承的继承实现接口也算)

第二种:判断是否是同一个对象

Class<? extends HttpMessageConverter<?>>

https://i-blog.csdnimg.cn/direct/56d1ff0e5c2741ce85a1b6219df238ad.png

父的实现 等于 字的实现

也就是说,在官方的用法中,他们进行了接口判断,放回为true,那我们在实践开发中,也可以仿照官方写法

那就要回到开始,support究竟实现了什么?

判断了一下Class> converterType与AbstractJackson2HttpMessageConverter是否实现了同一个接口

第二个实现

https://i-blog.csdnimg.cn/direct/4f5d81b9edc743de88020e2ba852e9dd.png

经典的,继承的继承实现  越多于 我实现了

https://i-blog.csdnimg.cn/direct/543bd34a1db54032ac2d12ccaad392ac.png

不管它的逻辑是什么,最终返回的都是一个true OR false

怎么写都无所谓,只要结果为true就会运行beforeBodyWriteInternal方法

例如,用户没有vip,我们除了在业务层进行判断,还能在哪里进行判断呢?

supports这里进行判断,if(x != vip){ false },你查出数据又如何,我不给你看,无敌~~~~

常规写法是拦截器,业务判断,没想到把,还能通过限制响应完成

很显然,并不能通过在supports中进行业务判断

https://i-blog.csdnimg.cn/direct/e53410291a494c898c0b3f83c2520854.png

直接给false

https://i-blog.csdnimg.cn/direct/7cdd92ddc5824d7ab67a85d38dbb83d1.png

该成功还是成功

https://i-blog.csdnimg.cn/direct/704db775d3e44742946ae05f1ddfb910.png

所以得出结论

support只影响下面的beforeBodyWrite,不影响整个

https://i-blog.csdnimg.cn/direct/225809d000c04883a08ea3109b0388ab.png

    @Nullable
    public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        Iterator var6 = this.getMatchingAdvice(parameter, RequestBodyAdvice.class).iterator();

        while(var6.hasNext()) {
            RequestBodyAdvice advice = (RequestBodyAdvice)var6.next();
            if (advice.supports(parameter, targetType, converterType)) {
                body = advice.handleEmptyBody(body, inputMessage, parameter, targetType, converterType);
            }
        }

        return body;
    }

这段代码就是supports怎么连接beforeBodyWrite的

看见没,很简单的一个循环 + 判断,完成了spring web的响应配上一个注解,便可实现全局统一响应

总结:

supports只影响同一文件下的beforeBodyWrite,所以不要想着用这玩意限制vip用户

判断外面是循环,而不是循环在判断里面

supports ?beforeBodyWrite :异常