【开发规范】替API接口制定统一的报文返回格式

人生之路不会是一帆风顺的,我们会遇上顺境,也会遇上逆境,在所有成功路上折磨你的,背后都隐藏着激励你奋发向上的动机,人生没有如果,只有后果与结果,成熟,就是用微笑来面对一切小事。

导读:本篇文章讲解 【开发规范】替API接口制定统一的报文返回格式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

实行前后端分离项目开发模式后,后端与前端之间的数据交互都变成了API接口的形式,这种项目模式将导致一个项目内拥有非常多的API接口。当然,即使采用 Spring Cloud 微服务开发模式,服务与服务之间的数据交互也是通过服务的对外API接口,API接口的数量也是非常可观的。

如果我们在项目开发初期不制定一份「统一的API接口的报文返回格式」,那么在一段时期的业务开发后项目内大概率会出现五花八门的API接口的报文返回格式,然后不仅会为跟前端同事联调增加不必要的工作量,还会对线上问题排查、项目更新迭代、项目重构等方面产生不可估量的负面影响。

因此,我们有必要在项目初期启动时就制定好一份合理的「统一的API接口的报文返回格式」,下面我将为大家提供了一份自己的实践示例,希望可以起到一个抛砖引玉的作用。

(1)定义一个返回报文格式:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

package cn.webuser.common.resp;

import cn.utils.DateUtils;

import lombok.Data;

import java.io.Serializable;

/**

* 返回报文格式

*

*/

@Data

public class Result<T> implements Serializable {

    private static final long serialVersionUID = -7656717461702492726L;

    /**

     * 返回码

     */

    private String code;

    /**

     * 返回描述

     */

    private String msg;

    /**

     * 返回tid

     */

    private String tid;

    /**

     * 时间

     */

    private String time;

    /**

     * 返回正文

     */

    private T data;

    public Result(BaseResultCode baseResultCode, String tid) {

        this(baseResultCode.code(), baseResultCode.msg(), tid);

    }

    public Result(String code, String msg, String tid) {

        this(code, msg, tid, null);

    }

    public Result(BaseResultCode baseResultCode, String tid, T data) {

        this(baseResultCode.code(), baseResultCode.msg(), tid, data);

    }

    public Result(String code, String msg, String tid, T data) {

        this.code = code;

        this.msg = msg;

        this.tid = tid;

        this.data = data;

        this.time = DateUtils.nowStr();

    }

}

在上面代码中,time 字段表示当前精确到秒的时间,通过一个内部的公共方法获取。

(2)定义API接口统一的返回状态码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

package cn.webuser.common.resp;

/**

* API接口返回状态码

*

*/

public enum BaseResultCode {

    /* 成功状态码 */

    SUCCESS(“0000”, “处理成功”),

    /* 参数错误:1001-1999 */

    PARAM_IS_INVALID(“1001”, “参数无效”),

    PARAM_IS_BLANK(“1002”, “参数为空”),

    PARAM_TYPE_BIND_ERROR(“1003”, “参数类型错误”),

    PARAM_NOT_COMPLETE(“1004”, “参数缺失”),

    PARAM_VALIDATION_FAILS(“1005”, “验签失败”),

    REFRESH_TOKEN_IS_INVALID(“1006”, “Refresh Token不可用”),

    /* 用户错误:2001-2999 */

    USER_NOT_LOGGED_IN(“2001”, “账号未登录”),

    USER_LOGIN_ERROR(“2002”, “账号名或密码错误”),

    USER_ACCOUNT_FORBIDDEN(“2003”, “账号已被禁用”),

    USER_ACCOUNT_IS_DEL(“2004”, “账号已注销”),

    USER_ACCOUNT_NOT_EXIST(“2005”, “账号不存在”),

    USER_ACCOUNT_HAS_EXISTED(“2006”, “账号已存在”),

    USER_ACCOUNT_NO_BALANCE(“2007”, “账户余额不足”),

    USER_ACCOUNT_IN_REVIEW(“2008”, “账号审核中”),

    USER_ACCOUNT_FALSE_REGISTER(“2009”, “账号审核未通过,请重新注册或联系管理员”),

    USER_PASSPORT_ERROR_TIMES_4(“2010”, “密码输入错误。如果输错次数超过4次,账户将被锁定”),

    USER_PASSPORT_ERROR_LOCK(“2011”, “密码输入错误次数过多,账户已被锁定”),

    //手机号

    USER_PHONE_ERROR(“2101”, “手机号错误”),

    USER_PHONE_FORBIDDEN(“2102”, “手机号已被禁用”),

    USER_PHONE_NOT_EXIST(“2103”, “手机号未注册”),

    USER_PHONE_HAS_EXISTED(“2104”, “手机号已注册”),

    USER_PHONE_PWD_SIMPLE(“2105”, “密码应由6~20位字母、数字或符号两种或三种组成”),

    //验证码

    USER_CODE_TIMEOUT(“2201″,”验证码已失效,请重新获取”),

    USER_CODE_NULL(“2202″,”还未获取验证码,请重新获取”),

    USER_CODE_ERROR_MORE(“2203″,”验证码多次错误,请重新获取”),

    USER_CODE_COUNT_MORE(“2204″,”验证码发送次数过多,请明天重试”),

    USER_CODE_SEND_ERROR(“2205″,”验证码发送失败,请重新获取”),

    USER_CODE_VERIFY_ERROR(“2206″,”验证码校验失败!”),

    //修改密码

    USER_MODIFY_PWD_ERROR(“2301″,”原始密码错误”),

    USER_MODIFY_PWD2_ERROR(“2302″,”新密码不一致”),

    USER_MODIFY_PWD3_ERROR(“2303″,”修改密码失败”),

    /* 业务错误:3001-3999 */

    BUSINESS_INNER_ERROR(“3001”, “某业务出现问题”),

    /* 系统错误:4001-4999 */

    SYSTEM_INNER_ERROR(“4001”, “系统错误”),

    SYSTEM_IS_BUSY(“4002”, “系统繁忙,请稍后重试”),

    /* 数据错误:5001-59999 */

    DATA_NO_RESULTS(“5001”, “没有查询到结果”),

    DATA_IS_WRONG(“5002”, “数据有误”),

    DATA_ALREADY_EXISTED(“5003”, “数据已存在”),

    /* 接口错误:6001-6999 */

    INTERFACE_INNER_INVOKE_ERROR(“6001”, “内部系统接口调用异常”),

    INTERFACE_OUTER_INVOKE_ERROR(“6002”, “外部系统接口调用异常”),

    INTERFACE_FORBID_VISIT(“6003”, “该接口禁止访问”),

    INTERFACE_ADDRESS_INVALID(“6004”, “接口地址无效”),

    INTERFACE_REQUEST_TIMEOUT(“6005”, “接口请求超时”),

    INTERFACE_EXCEED_LOAD(“6006”, “接口负载过高”),

    /* 权限错误:7001-7999 */

    PERMISSION_NO_ACCESS(“7001”, “无访问权限”);

    private String code;

    private String msg;

    BaseResultCode(String code, String msg) {

        this.code = code;

        this.msg = msg;

    }

    public String code() {

        return this.code;

    }

    public String msg() {

        return this.msg;

    }

    /**

     * 通过 code 获取对应枚举对象

     */

    public static BaseResultCode fromCode(String code) {

        for (BaseResultCode item : BaseResultCode.values()) {

            if (item.code.equals(code)) {

                return item;

            }

        }

        return null;

    }

    /**

     * 通过 code 获取对应的状态码描述

     */

    public static String getMsgByCode(String code) {

        for (BaseResultCode item : BaseResultCode.values()) {

            if (item.code.equals(code)) {

                return item.msg;

            }

        }

        return null;

    }

//    /**

//     * 校验重复的code值

//     */

//    public static void main(String[] args) {

//        BaseResultCode[] resultCodes = BaseResultCode.values();

//        List<String> codeList = new ArrayList<>();

//

//        for (BaseResultCode resultCode : resultCodes) {

//            if (codeList.contains(resultCode.code)) {

//                System.out.println(resultCode.code);

//            } else {

//                codeList.add(resultCode.code());

//            }

//        }

//    }

}

(3)配置生成统一的API接口返回格式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

package cn.webuser.common.resp;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**

* 定义统一的API接口返回格式

*

*/

@Component

public class ResultUtils {

    @Autowired

    private TidGenerator autoTidGenerator;

    private static TidGenerator tidGenerator;

    @PostConstruct

    public void init(){

        tidGenerator = autoTidGenerator;

    }

    /**

     * 返回一个可用的TID

     */

    public static String nextTid(){

        return tidGenerator.nextTid();

    }

    /**

     * 返回成功标识

     * @param tid TID

     */

    public static Result<Object> success(String tid) {

        return new Result<>(BaseResultCode.SUCCESS, tid);

    }

    /**

     * 返回成功标识

     * @param tid TID

     * @param data 数据域

     */

    public static <T> Result<T> success(String tid, T data) {

        return new Result<>(BaseResultCode.SUCCESS, tid, data);

    }

    /**

     * 返回默认的系统错误

     * @param tid TID

     */

    public static Result<Object> error(String tid) {

        return new Result<>(BaseResultCode.SYSTEM_INNER_ERROR, tid);

    }

    /**

     * 返回默认的系统错误

     * @param tid TID

     * @param data 数据域

     */

    public static <T> Result<T> error(String tid, T data) {

        return new Result<>(BaseResultCode.SYSTEM_INNER_ERROR, tid, data);

    }

    /**

     * 返回指定错误

     * @param errorCode 指定错误码

     * @param tid TID

     */

    public static <T> Result<T> error(BaseResultCode errorCode, String tid) {

        return new Result<>(errorCode, tid);

    }

    /**

     * 返回指定错误

     * @param errorCode 指定错误码

     * @param tid TID

     * @param data 数据域

     */

    public static <T> Result<T> error(BaseResultCode errorCode, String tid, T data) {

        return new Result<>(errorCode, tid, data);

    }

    /**

     * 返回指定错误

     * @param code 指定错误码

     * @param msg 指定错误描述

     * @param tid TID

     */

    public static Result<Object> error(String code, String msg, String tid) {

        return new Result<>(code, msg, tid);

    }

    /**

     * 返回指定错误

     * @param code 指定错误码

     * @param msg 指定错误描述

     * @param tid TID

     * @param data 数据域

     */

    public static <T> Result<T> error(String code, String msg, String tid, T data) {

        return new Result<>(code, msg, tid, data);

    }

}

(4)配置并使用

参数配置:

1

2

3

4

#配置当前服务的tid生成工具类

tid:

  machine:

    id: 1

加载配置:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

package cn.config;

import cn.zifangsky.common.TidGenerator;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

/**

* 配置TID生成工具类

*

*/

@Configuration

public class TidGeneratorConfig {

    @Value(“${tid.machine.id}”)

    private Long tidMachineId;

    @Bean

    public TidGenerator tidGenerator(){

        return new TidGenerator(tidMachineId);

    }

}

(5)测试用例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

/**

* 查询当前用户的基本信息

* @param request request

* @return java.util.Map<java.lang.String,java.lang.Object>

*/

@RequestMapping(value = “/user/selectUserInfo”, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

public Result<Object> selectUserInfo(HttpServletRequest request){

    String tid = ResultUtils.nextTid();

    log.info(String.format(“正在请求「/user/selectUserInfo」接口,tid=[%s]”, tid));

    Map<String,Object> dataMap = new HashMap<>(4);

    try {

        HttpSession session = request.getSession();

        SysUser user = (SysUser) session.getAttribute(Constants.SESSION_USER);

        UserInfo userInfo = new UserInfo();

        BeanUtils.copyProperties(user, userInfo);

        dataMap.put(“user_info”, userInfo);

        return ResultUtils.success(tid, dataMap);

    }catch (Exception e){

        log.error(“查询当前用户的基本信息出现异常:”, e);

        return ResultUtils.error(tid);

    }

}

调用接口后返回数据如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

{

    “code”: “0000”,

    “msg”: “处理成功”,

    “tid”: “A529QsGkSiO0”,

    “time”: “2020-11-17 13:50:31”,

    “data”: {

        “user_info”: {

            “username”: “admin”,

            “name”: “超级管理员”,

            “phone”: “12345678909”,

            “email”: “”,

            “userType”: 1,

            “institutionId”: null,

            “status”: 0,

            “isDel”: false,

            “loginIp”: “127.0.0.1”,

            “loginTime”: “2020-11-17 13:49:59”,

            “creator”: null,

            “createTime”: “2017-08-10 00:00:01”

        }

    }

}

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

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/124467.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!