记一次封装接口返回值问题

博客讲述了在微服务项目中,为统一返回结果格式,作者创建了Result类及其内部类NoDataResult和DataResult,并实现StandardResult接口。然而,这种方式导致Feign调用时出现序列化问题。解决方案是在Feign接口中使用内部类具体类型,而非StandardResult。同时,讨论了在非微服务项目中如何封装返回结果。
摘要由CSDN通过智能技术生成

因为之前的封装都是一个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:

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值