Java高级特性-泛型:泛型实战,封装统一的服务端响应类

在平时工作中,我们写代码可能都在堆增删改查,很少有机会加上 Java 的高级特性。比如,泛型,你一定在 Mybatis、Hibernate 这些持久化框架中用过。可轮到自己开发的时候,却发现这个东西简直鸡肋,完全用不上。

相信我,这种感觉很正常。因为开源框架往往要用同一套算法,来应对不同的数据结构,而 Java 的高级特性能减少重复代码,从而提高项目的可维护性。

然而,我们可能身处小公司,项目做完就直接交给客户了。你在最短时间完成工作就行,项目完全没有维护的必要。

但是,没有关系。这次我们来解锁泛型,用它来封装一个服务端返回类。

需求分析

不知道你有没有接手过一些老项目?那时候,SpringMVC 才刚刚出来,大家对代码规范也没概念。结果,碰上个这么方便的框架,后端开发人员就想也不想,直接把各种实体类返回给前端。

然而,时间一久,问题就来了。

首先,数据没法保证一致性。你请求某个接口的时候,如果传入的参数不同,得到的结果肯定也会不同。你看下面这个例子:

// 获取用户信息,正确返回
{
    "username": "jiarupc",
    "nickname": "法外狂徒、张三",
    "create_date": "2020-12-31 00:00:00"
}

// 获取用户信息,错误返回
{
    "msg": "缺少参数,请传入 token"
}

然后,前端没法处理。你想想看,一个接口如果有时候就返回一堆用户信息,有时候又只返回一条错误信息,这得写多少 if-else 判断呀?

最后,没法团队合作。如果碰上复杂的项目,最少也要几个人一起开发。这时候,要是返回格式没有一个标准,每个人都按照自己的想法随便写,那项目迟早得乱套。

事实上,在接手一些老项目时,你会经常看到这种情况。业务明明不复杂,但只要改了一点东西,好几个前端页面就白屏了。

这时候,如果你想根本解决问题,就必须封装统一服务端响应类。

设计-服务端响应类

服务端响应类有 2 个要点:返回值、错误码。

先来看返回值。在返回前端的时候,我们必须要有这 3 个信息:

  1. code,响应代码;
  2. data,响应数据;
  3. msg,响应信息;

其中,我们还要进一步设计响应代码,让它能适配更复杂的环境,这里给出几个常用的响应码,你也可以根据实际情况自己设计。

  1. 200-请求成功
  2. 101-执行错误
  3. 102-参数错误

整体的设计工作就完成了,看起来没啥技术含量,可值得你重视。软件开发中,有些工作虽然很简单,但影响重大,服务端响应类就是这样。

那么,接下来就是开发工作了。

开发-服务端响应类

首先,定义响应代码,我用的是枚举。

public enum ResponseCode {

    // 成功返回
    SUCCESS(200, "SUCCESS"),
    // 执行错误
    ERROR(101, "ERROR"),
    // 参数错误
    ILLEGAL_ARGUMENT(102, "ILLEGAL_ARGUMENT"));

    private final int code;
    private final String desc;

    ResponseCode(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    // 省略 getter 方法
}

然后,创建服务端响应类。其中,为了让 data-响应数据 适配更多的业务场景,我们用泛型来定义它。

public class ServerResponse implements Serializable {
    
    // 响应代码
    private int code;
    // 响应信息
    private String msg;
    // 响应数据
    private T data;

    /**
     * 构造方法
     */
    private ServerResponse(int code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    private ServerResponse(int code, T data) {
        this.code = code;
        this.data = data;
    }
    private ServerResponse(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    private ServerResponse(int code) {
        this.code = code;
    }

    /**
     * 请求成功
     * @param msg  返回信息
     * @param data 泛型数据
     * @param   返回数据,可以不填
     * @return 1.状态码(默认) 2.返回信息 3.泛型数据
     */
    public static  ServerResponse createSuccess(String msg, T data) {
        return new ServerResponse<>(ResponseCode.SUCCESS.getCode(), msg, data);
    }
    public static  ServerResponse createSuccess(T data) {
        return new ServerResponse<>(ResponseCode.SUCCESS.getCode(), data);
    }
    public static  ServerResponse createSuccess(String msg) {
        return new ServerResponse<>(ResponseCode.SUCCESS.getCode(), msg);
    }
    public static  ServerResponse createSuccess() {
        return new ServerResponse<>(ResponseCode.SUCCESS.getCode());
    }

    /**
     * 请求失败
     * @param code
     * @param msg
     * @return 1.状态码(自定义) 2.返回信息(自定义)
     */
    public static  ServerResponse createError(int code, String msg) {
        return new ServerResponse<>(code, msg);
    }
    public static  ServerResponse createError() {
        return new ServerResponse<>(ResponseCode.ERROR.getCode(), ResponseCode.ERROR.getDesc());
    }
    public static  ServerResponse createError(String msg) {
        return new ServerResponse<>(ResponseCode.ERROR.getCode(), msg);
    }

    
    // 省略 getter 方法
}

开发工作也完成了,接下来,我们可以做出规定,在 Controller 层Service 层中,返回数据必须是 ServerResponse,不许另起炉灶。

到了这儿,老项目的数据混乱问题,就被圆满解决了。

写在最后

泛型是 Java 的高级特性,但我们很少在工作中用到,但是没有关系。在老项目中,前后端交互没有统一的数据标准,这正好是机会。

为了解决这个问题,我们封装了统一的服务端返回类 ServerResponse,这其中 data-响应数据 用到了泛型,为的是适应更多的业务场景。

文章演示代码: 点击跳转

你可能感兴趣的:(java)