记一次封装接口返回值问题(代码片段)

_瞳孔 _瞳孔     2022-11-29     277

关键词:

因为之前的封装都是一个Result然后三个成员code、msg和data,所以无论是否返回数据,返回结果都会有data,于是我为了完整,就做了如下修改:

Result.java:

import lombok.Data;

/**
 * 统一返回格式
 */
public class Result
    /**
     * 成功(无返回数据、默认成功信息)
     * @return Result<Void>
     */
    public static StandardResult<Void> success() 
        NoDataResult noDataResult = new NoDataResult();
        noDataResult.setCode(ResultCode.SUCCESS.getCode());
        noDataResult.setMsg(ResultCode.SUCCESS.getMessage());
        return noDataResult;
    

    /**
     * 成功(无返回数据、自定义成功信息)
     * @return Result<Void>
     */
    public static StandardResult<Void> success(String message) 
        NoDataResult noDataResult = new NoDataResult();
        noDataResult.setCode(ResultCode.SUCCESS.getCode());
        noDataResult.setMsg(message);
        return noDataResult;
    

    /**
     * 成功(有返回数据,默认成功信息)
     * @return Result<V>
     */
    public static <V> StandardResult<V> success(V data) 
        DataResult<V> dataResult = new DataResult<>();
        dataResult.code = ResultCode.SUCCESS.getCode();
        dataResult.msg = ResultCode.SUCCESS.getMessage();
        dataResult.data = data;
        return dataResult;
    

    /**
     * 成功(有返回数据,自定义成功信息)
     * @return Result<V>
     */
    public static <V> StandardResult<V> success(String message, V data) 
        DataResult<V> dataResult = new DataResult<>();
        dataResult.code = ResultCode.SUCCESS.getCode();
        dataResult.msg = message;
        dataResult.data = data;
        return dataResult;
    

    /**
     * 失败(默认错误信息)
     * @return Result<Void>
     */
    public static StandardResult<Void> failure() 
        NoDataResult noDataResult = new NoDataResult();
        noDataResult.setCode(ResultCode.FAILURE.getCode());
        noDataResult.setMsg(ResultCode.FAILURE.getMessage());
        return noDataResult;
    

    /**
     * 失败,使用已定义枚举
     */
    public static StandardResult<Void> failure(ResultCode resultCode) 
        NoDataResult noDataResult = new NoDataResult();
        noDataResult.setCode(resultCode.getCode());
        noDataResult.setMsg(resultCode.getMessage());
        return noDataResult;
    

    /**
     * 失败,使用自定义错误信息
     */
    public static StandardResult<Void> failure(String message) 
        NoDataResult noDataResult = new NoDataResult();
        noDataResult.setCode(ResultCode.FAILURE.getCode());
        noDataResult.setMsg(message);
        return noDataResult;
    

    /**
     * 失败,使用自定义错误码和错误信息
     */
    public static StandardResult<Void> failure(Integer code, String message) 
        NoDataResult noDataResult = new NoDataResult();
        noDataResult.setCode(code);
        noDataResult.setMsg(message);
        return noDataResult;
    

    /**
     * 无数据返回模板
     */
    @Data
    static class NoDataResult implements StandardResult<Void>
        private Integer code;
        private String msg;

        @Override
        public Void getData() 
            return null;
        
    

    /**
     * 有数据返回模板
     */
    @Data
    static class DataResult<V> implements StandardResult<V>
        private Integer code;
        private String msg;
        private V data;
    

ResultCode.java:

/**
 * 状态码类
 */
@Getter
@AllArgsConstructor
public enum ResultCode 
    // 默认成功提示
    SUCCESS(200, "success"),

    // 默认失败提示
    FAILURE(400, "fail"),

    /*
     * 非运行时异常(1000 - 1999)
     */
    PROGRAM_INSIDE_EXCEPTION(1000, "程序内部异常"),

    /*
     * 运行时异常——操作异常(2000 - 5999)
     */
    ILLEGAL_REQUEST_PARAMETER(2000, "非法请求参数"),

    /*
     * 运行时异常——风险异常(6000 - 9999)
     */
    ILLEGAL_REQUEST_ROUTE(6000, "非法路由请求");


    private final Integer code;

    private final String message;

因为是code、msg和data都变成了内部类的成员属性,所以类型都是Result.NoDataResultResult.DataResult之类的,我感觉很难看,于是我让两个内部类都实现一个接口,用以统一返回类型:
StandardResult.java:

public interface StandardResult<T> 
    Integer getCode();

    String getMsg();

    T getData();

这么封装貌似是没有问题的,测试也没有问题:


但由于我这个是微服务项目,在使用feign进行服务调用的时候,就开始报错了:


这个(no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information,我经过查阅资料发现,是因为feign做调用的说话返回值类型不能被反序列化,而我为了类型统一,就实现了StandardResult接口,因此无法被序列化,我也想不出来怎么既可以统一返回类型又可以被序列化,于是只能在feign api内使用内部类类型:


其余地方都使用StandardResult:

注意,如果要使用内部类进行类型约束,需要将Result类中的内部类访问权限改为public:


当然如果不是微服务项目的话,可以直接使用我上面发的封装,如果是微服务项目就得注意我说的那几个修改点

如果有兴趣了解更多相关内容,欢迎来我的个人网站看看:瞳孔的个人网站

记一次dotnet拆分包,并希望得大佬指点(代码片段)

记一次dotnet拆分包,并希望得大佬指点之前做了一个用于excel导入导出的包,定义了一些接口,然后基于NPOIEPPlusMiniExcel做了三种实现接口大概长下面这样(现在可以在接口里面写静态函数了!)publicinterfaceIExcelReader//根据一些条件返回下... 查看详情

记一次工作中vue中mounted请求接口返回值和vue的data域中属性不一致的后果

记一次工作中vue中mounted请求接口返回值和vue的data域中属性不一致的坑当时需求:就是当时在这个页面中,就是本次补差余额只要变化,就会显示当前的时间。当时处理的是使用change方法监听这个输入框的变化(其实也可以使用w... 查看详情

记一次接口授权导致的500异常排查(代码片段)

有一个导出的接口通过postman调用是返回正常的响应体,但是发布到测试环境,通过浏览器请求时,会返回500通过浏览器请求通过Postman请求开始排查整个链路为nginx->springcloudgateway->业务服务首先从业务服务开始排... 查看详情

记一次netty追源码找bug过程(代码片段)

前言在一次使用一个netty封装的框架时,遇到了问题。由于对netty的原理不熟悉,所以只能瞎猫碰死耗子,一点儿一点儿找原因。最后很费力的找到了问题所在。下面复盘一下通过源码找问题的过程,总结一下哪里... 查看详情

记一次接口性能优化实践总结:优化接口性能的八个建议(代码片段)

前言最近对外接口偶现504超时问题,原因是代码执行时间过长,超过nginx配置的15秒,然后真枪实弹搞了一次接口性能优化。在这里结合优化过程,总结了接口优化的八个要点,希望对大家有帮助呀~数据量比较大,批量操作数据... 查看详情

记一次socket.io的debug记录(代码片段)

背景:  项目开发客服聊天系统,使用socket.io进行开发,前端采用vue-element-admin,后端语言php,项目在本地运行功能正常,但是发布到测试环境的时候,socket的连接一直不成功,可以成功返回socketid,但是请求时并没有将sid作... 查看详情

unity实用技能记一次失败的蓝图接口开发失败经验(代码片段)

本来想写一个批量控制widget开关的接口,想写一个像append一样的可加pin的接口首先还是找到这个接口得代码可以看到关键的点就是CommutativeAssociativeBinaryOperator="true"就是这个,标记这个接口是可以加pin的。接下来就是照着... 查看详情

记一次grpc接口压力测试&性能调优(代码片段)

〇、经验总结:如果在压测过程中,压力始终上不去,可以考虑是施压机器并发上不去,或者被压机器请求处理不过来。施压上不去或者被压机器请求处理不过来,是因为机器CPU瓶颈?内存瓶颈?端口数量瓶颈?逐步排查定位。... 查看详情

接swagger很傻x的一次教训(代码片段)

这两天在搭建项目用到了swagger,遇到了不少坑,可以说是完全没必要踩到的坑,却让我浪费了许久时间,确实很难受,记录下来,以此为教训!先说明下:版本号为:springboot2.x、swagger2.7+我遇到了很多问题,第一个:上面那个... 查看详情

记一次mybatis返回自增主键的低级错误!(代码片段)

<insertid="insert"useGeneratedKeys="true"keyColumn="USER_ID"keyProperty="userId"parameterType="xxx.User">代码如上一切配置都没问题,然后我通过如下代码获取IDintuserId=baseDao.insert(user);结果返回的... 查看详情

记一次阿里面试(代码片段)

过了电面,但是现场面试时遇到一个"变态"面试官,挂了。当然也确实是自己实力还不够,他问了很多数据库事务的问题,问我有没有研究过某个rpc框架的源码。最后是一道多线程编程题,我太紧张没有... 查看详情

记一次es事故(代码片段)

从报警来看,业务报接口超时,同时es错误日志也会提示:Causedby:org.elasticsearch.common.util.concurrent.EsRejectedExecutionException:rejectedexecutionoforg.elasticsearch.transport.TcpTransport$RequestHandle 查看详情

记一次mysql注入绕过(代码片段)

来源于今天一位朋友叫我帮忙看的题目查看源码发现提示存在过滤且,limit参数只能为单个数字fuzz一下sql注入关键字看看都过滤了哪些字符直接在class参数插入exp(100)回显正常,插入exp(1000)发现返回databaseerror;说明此... 查看详情

记一次mysql注入绕过(代码片段)

来源于今天一位朋友叫我帮忙看的题目查看源码发现提示存在过滤且,limit参数只能为单个数字fuzz一下sql注入关键字看看都过滤了哪些字符直接在class参数插入exp(100)回显正常,插入exp(1000)发现返回databaseerror;说明此... 查看详情

记一次cmsgc导致fullgc时间开销很大的排查(代码片段)

记一次CMSGC导致FULLGC时间开销很大的排查背景定位分析过程第一次尝试解决方案CMSGC收集器分析了解CMS收集原理优缺点分析总结分析根因解决方案背景服务接入注册中心后,就会有实例健康检查,通过ip+port的方式访问... 查看详情

记一次cmsgc导致fullgc时间开销很大的排查(代码片段)

记一次CMSGC导致FULLGC时间开销很大的排查背景定位分析过程第一次尝试解决方案CMSGC收集器分析了解CMS收集原理优缺点分析总结分析根因解决方案背景服务接入注册中心后,就会有实例健康检查,通过ip+port的方式访问... 查看详情

记一次springboot搭建过程(代码片段)

遇到的问题如下:1.SpringBoot正常启动后,访问Controller报404问题描述:springboot正常启动,通过http://localhost:8000/hello/first访问,一直报404原因:在搭建完项目之后,Application类是放在com.example.hello的包下面,而Controller类是放置在com.e... 查看详情

记一次echarts地图百度坐标使用(代码片段)

由于工作原因,需要用到echarts的中国地图图表,像往常一样引入ecchart.js 然后。。。悲催,地图不加载,经过跟踪代码,发现地图接口报错,echart.js报了地图js的错误,发现没有引用china.js 由于这次引用的echarts的版本为3.... 查看详情