当技术leader说要把接口设计成RESTful,我拒绝了

一、前言

最近准备重写公司一个旧项目,每次想起这个项目,内心总忍不住要吐槽一波,难受。具体细节就不说了,水平不一样,见仁见智,也不是本文的重点。就是此时,技术leader说要把接口设计成RESTful规范,我拒绝了,这东西适合当前业务开发吗?先后端对接麻烦吗?前端

这东西之前上学时就据说过,但工做也没看见有人彻底以此设计web

我也想遵照这传说中的规范,可现实不容许啊json

二、RESTful

REST(Representational State Transfer),直译为表现层资源转换,具体就不说了hhh,相关文章一大堆,但REST感受没有一个十分明确的标准,更趋向于一种接口设计风格,按照基本的约束条件进行开发设计。后端

三、基本接口命名

有人说RESTful API能够一会儿让别人知道这个url是干什么的,但说到底不就是取决于咱们的接口命名吗?接口作到见名知义,用良好的英文命名,不也能达到效果。因此,参考业界部分规范,我定义了以下命名。api

3.1 获取数据

拿通用的订单模块举例,最基础无非是两种场景-获取列表 or 获取详情数据结构

  1. 获取列表 /api/order/orderList
  2. 获取详情 /api/order/orderInfo

前面不加get?架构

  1. 以前我也加,时间久了总以为碍眼hhh,这里定义get,service层又定义一个相同或差很少的方法名,总以为在 重复命名
  2. 为了让接口路径更短更精简,干脆省略get,后面就约定以 list/info结尾就认为是获取数据信息了。

不学RESTful在数据实体后加s表示复数?app

  1. 对于后端 数据结构而言,List更合适
  2. 有些前端须要作列表展现,List翻译后更 见名知义
  3. 以s结尾的单词需加es就不说了,有些单词是单复数同行,若是加s我会以为这人英文语法不行啊,不加又像单数。因此为了统一,List最好

3.2 复杂业务场景

有时咱们的核心业务需求不定,相同的实体信息在不一样场景须要提供不一样的数据,其实到咱们后端就是根据不一样过滤条件查询出实体信息,有些所谓的RESTful规范说是在url后加参数信息,如:编辑器

/orders?state=finish&userId=123url

这也是我不喜欢RESTful的缘由之一,某些场景下,过滤信息是固定不变的,不能经过前端传参决定,并且url后带参数的传参也有弊端。

回到不一样场景不一样命名,最好能从产品用户角度出发,好比:

  1. 查看我全部订单 /api/order/myAllOrderLIst
  2. 获取已完成的订单 /api/order/finishiedOrderLIst
  3. 获取可开票的订单 /api/order/invoiceOrderList

3.3 增/改/删/其余非获取动做

  • addXXX - 增长
  • saveXXX -保存
  • updateXXX -修改更新
  • deleteXXX -删除
  • pushXXX -推送
  • payXXX -支付
  • ........

若是作后台管理系统这种项目,确实能够用list、info、save、update、delete一把梭了。每一个数据实体一定要有这些方法

3.4 myBatis-plus中良好的命名

myBatis-plus封装好了一些service、mapper方法,增删改查都有十分规范的命名。并且在相同的操做都有适合本身的命名。

动做 service mapper(dao)
save insert
remove delete
update update
get/list select

3.5 不一样版本的相同接口

有些接口须要兼容不一样的APP版本,若是增长字段不能知足,无可奈何需增长新的请求路径,可加个v一、v2版本前缀,原接口名不变,加个版本前缀还能够看到接口的历史修改,方便维护。

  • /api/order/v1/orderInfo
  • /api/order/v2/orderInfo

四、统一ApiRequest

4.1 Spring还自然支持RESTful规范

除了场景的GET、POST请求注解,Spring还有@PutMapping 、@PatchMapping、 @DeleteMapping 注解,标识不一样的请求方式。

不只如此,SpringMVC还支持参数绑定。

@RequestMapping(value = "/orders/{id}", method = RequestMethod.GET)
public void getById(HttpServletRequest request, @PathVariable("id") Long id){
    System.out.println(id);
}
复制代码

这....又给咱们提供一种获取参数的形式..............

4.2 自定义ApiRequest

既然拒绝了RESTful,那咱们规定,前端统一用json形式POST请求接口传递参数,后端拦截器拿到请求,自定义ApiRequst类,将请求信息(请求头/请求体)统一封装,这样先后端架构都保持统一,更有利于联调。

@Data
public class ApiRequest implements Serializable {
    private String appVersion;      //请求头-app版本号
    private Integer deviceType;     //请求头-设备类型
    private String deviceName;      //请求头-设备类型
    private String secret;
    private String token;
    private Map data;           //请求体-业务参数
}
复制代码

Controller层统一形式接收

/**
 * TestApi
 * @param apiRequest
 * @return
 */
@PostMapping(value = "/testList")
public ApiResponse testList(ApiRequest apiRequest) {
  Long id = apiRequest.getDataParamAsLong("id", 0L);
  String name = apiRequest.getDataParamAsString("name", "");
  return ApiReponse.ok();
}
复制代码

五、写在最后

其实我不并反对RESTful,仅仅想说出本身的想法。存在即合理嘛。我也曾经尝试过其规范,真是一把辛酸泪。我以为只有适合本身的业务,能提升开发效率、先后端沟通效率的,就是良好的规范,规范并无一个十分统一的参考

咦,好像还漏了接口返回结果Response没说吧,这在RESTful里貌似也有说起。

相关文章
相关标签/搜索