电商商城定制开发如何优雅地写后端API接口

电商商城定制开发在移动互联网,分布式、电商商城定制开发盛行的今天,电商商城定制开发现在项目绝大部分都采电商商城定制开发用的微服务框架,电商商城定制开发前后端分离方式。前后端的工作职责越来越明确,现在的前端都称之为大前端,技术栈以及生态圈都已经非常成熟;以前后端人员瞧不起前端人员,那现在后端人员要重新认识一下前端,前端已经很成体系了

1.接口交互

前端和后端进行交互,前端按照约定请求URL路径,并传入相关参数,后端服务器接收请求,进行业务处理,返回数据给前端。

针对URL路径的风格,以及传入参数的公共请求头的要求(如:app_version,api_version,device等),这里就不介绍了,小伙伴们可以自行去了解,也比较简单。

着重介绍一下后端服务器如何实现把数据返回给前端?

2.返回格式

后端返回给前端我们采用json格式

  1. {
  2. "success": boolean,
  3. "code": int,
  4. "data": object,
  5. "msg": string
  6. }
  • success是否成功

最简单的判断,前端直接取该值判断是否操作成功,成功为true,失败为false

  • code状态码

当一个操作会因为多种因素失败的情况下,每种失败的原因进行设置不同的状态码。可以按照业务区分,例如用户的错误状态码在101-199之间,系统的错误状态码在201-299之间,可以按照自己的业务进行设置,我们参考下http状态码:

  1. 200 - 请求成功
  2. 301 - 资源(网页等)被永久转移到其它URL
  3. 404 - 请求的资源(网页等)不存在
  4. 500 - 内部服务器错误
  • data数据

这里是具体要返回的数据,数据格式可以为数组、对象、字符串等格式

  • msg消息

这个字段相对理解比较简单,就是发生错误时,如何友好的进行提示。一般的设计是和code状态码一起设计。如登陆失败> code:203,msg:登陆失败,账号或者密码有误

2.1.返回样例

这就是一个操作成功返回的例子

  1. {
  2. "success": true,
  3. "code": 1,
  4. "data": {"k": "v"},
  5. "msg": "操作成功"
  6. }

3.实现

3.1.定义状态码枚举类

  1. package com.niu.demo.util;
  2. /**
  3. * @description: 状态吗设置
  4. * @author: nxq email: niuxiangqian163@163.com
  5. * @createDate: 2020/12/21 7:46 下午
  6. * @updateUser: nxq email: niuxiangqian163@163.com
  7. * @updateDate: 2020/12/21 7:46 下午
  8. * @updateRemark:
  9. * @version: 1.0
  10. **/
  11. public enum ResultCode {
  12. /* 通用状态码 成功与失败 */
  13. SUCCESS(1,"ok"), FAILED(-1,"操作失败"),
  14. /* 参数错误 101 - 199*/
  15. PARAM_IS_INVALID(101,"参数无效"),
  16. PARAM_IS_BLANK(101,"参数为空"),
  17. /* 用户错误 201 - 299 */
  18. USER_NOT_LOGIN(201,"未登录"),
  19. USER_NOT_EXIST(202,"用户不存在"),
  20. USER_LOGIN_ERROR(203,"登陆失败,账号或者密码有误"),
  21. NOT_PERMISSION(204,"无权限访问"),
  22. /* 业务错误 301 - 399*/
  23. DATA_NOT_FOUND(301,"没有数据"),
  24. //.......更多
  25. ;
  26. private Integer code;
  27. private String msg;
  28. ResultCode(Integer code, String msg) {
  29. this.code=code;
  30. this.msg=msg;
  31. }
  32. public Integer getCode() {
  33. return code;
  34. }
  35. public String getMsg(){
  36. return msg;
  37. }
  38. }

3.2.创建返回结果类

  1. package com.niu.demo.util.core;
  2. import com.niu.demo.util.ResultCode;
  3. import java.io.Serializable;
  4. /**
  5. * @description: 响应类
  6. * @author: nxq email: niuxiangqian163@163.com
  7. * @createDate: 2020/12/21 7:37 下午
  8. * @updateUser: nxq email: niuxiangqian163@163.com
  9. * @updateDate: 2020/12/21 7:37 下午
  10. * @updateRemark:
  11. * @version: 1.0
  12. **/
  13. public class R<T> implements Serializable {
  14. private static final long serialVersionUID = 1L;
  15. private int code; //状态码
  16. private boolean success; //是否成功
  17. private String msg; //提示信息
  18. private T data; //数据
  19. public static <T> R<T> ok() {
  20. return restResult(null, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
  21. }
  22. public static <T> R<T> ok(T data) {
  23. return restResult(data, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
  24. }
  25. public static <T> R<T> ok(T data, String msg) {
  26. return restResult(data, ResultCode.SUCCESS.getCode(), msg);
  27. }
  28. public static <T> R<T> failed() {
  29. return restResult(null, ResultCode.FAILED.getCode(), ResultCode.FAILED.getMsg());
  30. }
  31. public static <T> R<T> failed(String msg) {
  32. return restResult(null, ResultCode.FAILED.getCode(), msg);
  33. }
  34. public static <T> R<T> failed(ResultCode resultCode) {
  35. return restResult(null, resultCode.getCode(), resultCode.getMsg());
  36. }
  37. public static <T> R<T> failed(Integer code,String msg) {
  38. return restResult(null, code, msg);
  39. }
  40. public static <T> R<T> failed(T data) {
  41. return restResult(data, ResultCode.FAILED.getCode(), ResultCode.SUCCESS.getMsg());
  42. }
  43. public static <T> R<T> failed(T data, String msg) {
  44. return restResult(data, ResultCode.FAILED.getCode(), msg);
  45. }
  46. public int getCode() {
  47. return code;
  48. }
  49. public void setCode(int code) {
  50. this.code = code;
  51. }
  52. public boolean isSuccess() {
  53. return success;
  54. }
  55. public void setSuccess(boolean success) {
  56. this.success = success;
  57. }
  58. public String getMsg() {
  59. return msg;
  60. }
  61. public void setMsg(String msg) {
  62. this.msg = msg;
  63. }
  64. public T getData() {
  65. return data;
  66. }
  67. public void setData(T data) {
  68. this.data = data;
  69. }
  70. private static <T> R<T> restResult(T data, int code, String msg) {
  71. R<T> apiResult = new R<>();
  72. apiResult.setCode(code);
  73. apiResult.setSuccess(code == 1);
  74. apiResult.setData(data);
  75. apiResult.setMsg(msg);
  76. return apiResult;
  77. }
  78. }

3.3.在控制器中使用

  1. @RequestMapping
  2. @RestController
  3. public class DemoController {
  4. @GetMapping("/test1")
  5. public R<Object> test1(){
  6. return R.ok();
  7. }
  8. @GetMapping("/test2")
  9. public R<String> test2(){
  10. return R.ok("uuid");
  11. }
  12. @GetMapping("/test3")
  13. public R<List<String>> test3(){
  14. List<String> list = new ArrayList<>();
  15. return R.ok(list);
  16. }
  17. @GetMapping("/test4")
  18. public R<Object> test4(){
  19. return R.failed();
  20. }
  21. @GetMapping("/test5")
  22. public R<Object> test5(){
  23. return R.failed("暂时不能进行修改");
  24. }
  25. @GetMapping("/test6")
  26. public R<Object> test6(){
  27. return R.failed(ResultCode.USER_LOGIN_ERROR);
  28. }
  29. @GetMapping("/test7")
  30. public R<Object> test7(){
  31. return R.failed(500,"内部错误,请联系管理员");
  32. }
  33. }

4.补充

这个方案还有没有别的优化空间,当然是有的。例如:每个接口都要返回下R这个类,其实最主要的数据还是R的data数据对象,可以优化一下只返回数据对象,在拦截器里再包装一下数据对象。

如果大家有更好的方式可以在评论区交流一下

 

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发