当前位置: 代码网 > it编程>编程语言>Java > Spring Boot 统一数据返回格式的解决方案

Spring Boot 统一数据返回格式的解决方案

2024年05月18日 Java 我要评论
实现统一数据格式统⼀的数据返回格式使⽤ @controlleradvice 和 responsebodyadvice 的⽅式实现;@controlleradvice : 表⽰控制器通知类.比如:添加类

实现统一数据格式

统⼀的数据返回格式使⽤ @controlleradvice 和 responsebodyadvice 的⽅式实现;
@controlleradvice : 表⽰控制器通知类.
比如:添加类 responseadvice , 实现 responsebodyadvice 接⼝, 并在类上添加
@controlleradvice 注解.

import com.example.demo.model.result;
import org.springframework.core.methodparameter;
import org.springframework.http.mediatype;
import org.springframework.http.server.serverhttprequest;
import org.springframework.http.server.serverhttpresponse;
import org.springframework.web.bind.annotation.controlleradvice;
import org.springframework.web.servlet.mvc.method.annotation.responsebodyadvice;
@controlleradvice
public class responseadvice implements responsebodyadvice {
    @override
    public boolean supports(methodparameter returntype, class convertertype) {
        return true;
    }
    @override
    public object beforebodywrite(object body, methodparameter returntype,
                                  mediatype selectedcontenttype, class selectedconvertertype,
                                  serverhttprequest request, serverhttpresponse response) {
        return result.success(body); //返回 result 类型的数据
    }
}

 supports⽅法: 判断是否要执⾏beforebodywrite⽅法. true为执⾏, false不执⾏. 通过该⽅法可以 选择哪些类或哪些⽅法的response要进⾏处理, 其他的不进⾏处理.

beforebodywrite⽅法:对response⽅法进⾏具体操作处理.

 测试 

 写一些不同的返回结果,看看哪些会出现问题!

import com.example.demo.model.bookinfo;
import com.example.demo.model.result;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.responsebody;
import org.springframework.web.bind.annotation.restcontroller;
@restcontroller
@requestmapping("/test")
public class testcontroller {
    @requestmapping("/t1")
    public integer t1() {
        return 12334;
    }
    @requestmapping("/t2")
    public string t2() {
        return "hello";
    }
    @requestmapping("/t3")
    public boolean t3() {
        return true;
    }
    @requestmapping("/t4")
    public bookinfo t4() {
        return new bookinfo();
    }
    @requestmapping("/t5")
    public result t5() {
        return result.success("success");
    }
}

1.返回结果为integer,可以正确响应.

2.返回结果为string,结果显示内部错误.

 控制台查看日志:

3.返回结果为boolean,可以正常响应.

 4.返回结果为bookinfo对象,可以正常响应.

5.返回结果为result,发现又进行了一次封装.

 问题:1.返回结果为string,不能正常进行处理了;2.返回结果为result,又多进行了一次封装.

 原因分析

这时候就会非常纳闷了,为什么就处理string的时候会出错呢?就不得不去看源码分析了.

springmvc (也就是在初始化时) 默认会注册⼀些⾃带的 httpmessageconverter (转换器) (从先后顺序排列分别为 bytearrayhttpmessageconverter , stringhttpmessageconverter , sourcehttpmessageconverter , sourcehttpmessageconverter , allencompassingformhttpmessageconverter )

 这些转换器是有先后顺序的,是用arraylist存储的.会根据我们的返回结果挨个判断使用哪个转换器!!!

此时,就会发现问题就出现在 stringhttpmessageconverter.

处理的内容主要是在abstractmessageconvertermethodprocessor 中 会有一个writewithmessageconverters()方法.

通过getadvice()拿到了beforbodywrite 就会对body进行处理,处理完之后并没有结束(body变成了result类型),此时,也并没有出错。会继续执行((httpmessageconverter) converter).write(body, selectedmediatype, outputmessage).

 由于 stringhttpmessageconverter 重写了adddefaultheaders⽅法, 所以会执⾏⼦类的⽅法

然⽽⼦类 stringhttpmessageconverter 的adddefaultheaders⽅法定义接收参数为string, 此

时t为result类型, 所以出现类型不匹配" result cannot be cast to java.lang.string "的异常.

 解决方案

1.当返回结果为result时,就直接返回body.

2.当返回结果为string时,采用springboot内置提供的jackson来实现信息的序列化 

@controlleradvice
public class responseadvice implements responsebodyadvice {
    @autowired
    private objectmapper objectmapper;
    @override
    public boolean supports(methodparameter returntype, class convertertype) {
        return true;
    }
    @sneakythrows
    @override
    public object beforebodywrite(object body, methodparameter returntype,
                                  mediatype selectedcontenttype, class selectedconvertertype,
                                  serverhttprequest request, serverhttpresponse response) {
        //body 是返回的结果
        //当返回结果为result类型时,就直接返回body
        if (body instanceof result) {
            return body;
        }
        //返回结果为string类型, 使⽤springboot内置提供的jackson来实现信息的序列化
        if (body instanceof string) {
            return objectmapper.writevalueasstring(result.success(body));
        }
        return result.success(body); //返回 result 类型的数据
    }
}

到此这篇关于spring boot 统一数据返回格式 分析 和 处理的文章就介绍到这了,更多相关spring boot 统一数据返回格式内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com