Spring+SpringMVC+MyBatis+easyUI整合进阶篇(一)设计一套好的RESTful API

写在前面的话

看了一下博客目录,距离上次更新这个系列的博文已经有两个多月,并不是因为不想继续写博客,由于中间这段时间更新了几篇其他系列的文章就暂时停止了,如今已经讲述的差不多,也就继续抽时间更新《Spring+SpringMVC+MyBatis+easyUI 整合》这个系列了。

github
也看到 github 上有人催更教程,这个真的是没想到,也谢谢你们的肯定和支持了。

由于《整合优化篇》中关于代码优化及数据层优化的文章占了较大的篇幅,导致遗漏了几篇原计划要更新在《整合优化篇》中的文章,关于 RESTful 的改造和缓存功能的整合并没有做,这段时间会补充进来。

理解 RESTful

REST(Representational State Transfer), 中文翻译叫 "表述性状态转移", 它首次出现在 2000 年 Roy Fielding 的博士论文中,Roy Fielding 是 HTTP 规范的主要编写者之一。他在论文中提到:"我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。REST 指的是一组架构约束条件和原则。" 如果一个架构符合 REST 的约束条件和原则,我们就称它为 RESTful 架构,REST 其实并没有创造新的技术、组件或服务,在我的理解中,它更应该是一种理念、一种思想,利用 Web 的现有特征和能力,更好地诠释和体现现有 Web 标准中的一些准则和约束。

看完这段理论性的介绍可能并不会使你对于 RESTful 有任何的想法,甚至只是一扫而过,那就通过实际的案例来讲解吧。

ssm 项目中有文章管理这个模块,文章列表页面删除文章请求的服务端 API 地址为:
http://ssm-demo.hanshuai.xin/article/delete.do,
这个 URL 并不是 RESTful 风格的 API,稍加修改,URL 变成:
http://ssm-demo.hanshuai.xin/article/delete/12,
这样是不是就是 RESTful 风格了?

首先,这两个 URL 都不是 RESTful API,因为这两个 URL 中都有 delete 的动作指示,RESTful API 是面向资源的架构,因此其 URL 就应该是一个资源,而且不应该包含任何动作,对于资源的具体操作类型应该由 HTTP 动词表示,而不应该是动词存在于 URL 中,delete 是一个动词,因此不符合该特点,对于文章删除功能其对应的 RESTful API 应该是:
[DELETE] http://ssm-demo.13blog.site/articles/12

常见的 RESTful 误区

再讲一下一开始接触 RESTful 时大家都可能存在的误区:

  • 一些伪静态的 URL,如 http://ssm-demo.13blog.site/contents/12, 我们可以通过浏览器访问该 URL 而获取信息,但是这并不代表着它就是 RESTful API。
  • URL 里含有 queryString 就不是 RESTful Api,如 http://ssm-demo.13blog.site/articles/?page=1&rows=10,RESTful API 可以包含 queryString。
  • HTTP + JSON = RESTful API,HTTP 和 JSON 不等于 RESTful,RESTful 特性更加丰富,不能将 RESTful 简单的等同于 HTTP 和 JSON。

良好 RESTful API 的设计原则

关于 RESTful API 设计的具体实现可以到我的 GitHub 中查看,以下为整理的一些设计原则:

基本原则一:URI

  • 应该将 API 部署在专用域名之下:ssm-demo.13blog.site;
  • URL 中尽量不用大写;
  • URI 中不应该出现动词, 动词应该使用 HTTP 方法表示但是如果无法表示, 也可使用动词, 例如:search 没有对应的 HTTP 方法, 可以在路径中使用 search, 更加直观;
  • URI 中的名词表示资源集合,使用复数形式;
  • URI 可以包含 queryString, 避免层级过深。

基本原则二:HTTP 动词

对于资源的具体操作类型,由 HTTP 动词表示,常用的 HTTP 动词有下面五个:

  • GET:从服务器取出资源(一项或多项)。
  • POST:在服务器新建一个资源。
  • PUT:在服务器更新资源(客户端提供改变后的完整资源)。
  • PATCH:在服务器更新资源(客户端提供改变的属性)。
  • DELETE:从服务器删除资源。

还有两个不常用的 HTTP 动词:

  • HEAD:获取资源的元数据。
  • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。

例子:

文章管理模块:
  1. [POST] http://ssm-demo.13blog.site/articles // 新增
  2. [GET] http://ssm-demo.13blog.site/articles?page=1&rows=10 // 列表查询
  3. [PUT] http://ssm-demo.13blog.site/articles/12 // 修改
  4. [DELETE] http://ssm-demo.13blog.site/articles/12 // 删除

基本原则三:状态码(Status Codes)

处理请求后,服务端需向客户端返回的状态码和提示信息。

常见状态码(状态码可自行设计,只需开发者约定好规范即可)

  • 200:SUCCESS, 请求成功;
  • 401:Unauthorized, 无权限;
  • 403:Forbidden, 禁止访问;
  • 410:Gone, 无此资源;
  • 500:INTERNAL SERVER ERROR, 服务器发生错误。
    ...

基本原则四:错误处理

如果服务器发生错误或者资源不可达,应该向用户返回出错信息。

基本原则五:服务端数据返回

后端的返回结果最好使用 JSON 格式。

基本原则六:版本控制

  • 规范的 API 应该包含版本信息,在 RESTful API 中,最简单的包含版本的方法是将版本信息放到 url 中,如:
[GET]    http://ssm-demo.13blog.site/v1/articles?page=1&rows=10 
[PUT]    http://ssm-demo.13blog.site/v1/articles/12 
  • 另一种做法是,使用 HTTP header 中的 accept 来传递版本信息。

ssm 项目较为简单,因此暂时没有加入版本信息。

以下为参考内容,借鉴了一位博主关于安全原则的整理:

安全原则一:Authentication 和 Permission

Authentication 指用户认证,Permission 指权限机制,这两点是使 RESTful API 强大、灵活和安全的基本保障。

常用的认证机制是 Basic Auth 和 OAuth,RESTful API 开发中,除非 API 非常简单,且没有潜在的安全性问题,否则,认证机制是必须实现的,并应用到 API 中去。Basic Auth 非常简单,很多框架都集成了 Basic Auth 的实现,自己写一个也能很快搞定,OAuth 目前已经成为企业级服务的标配,其相关的开源实现方案非常丰富(更多)。

安全原则二:CORS

CORS 即 Cross-origin resource sharing,在 RESTful API 开发中,主要是为 js 服务的,解决 javascript 调用 RESTful API 时的跨域问题。

由于固有的安全机制,js 的跨域请求时是无法被服务器成功响应的。现在前后端分离日益成为 web 开发主流方式的大趋势下,后台逐渐趋向指提供 API 服务,为各客户端提供数据及相关操作,而网站的开发全部交给前端搞定,网站和 API 服务很少部署在同一台服务器上并使用相同的端口,js 的跨域请求时普遍存在的,开发 RESTful API 时,通常都要考虑到 CORS 功能的实现,以便 js 能正常使用 API。

目前各主流 web 开发语言都有很多优秀的实现 CORS 的开源库,我们在开发 RESTful API 时,要注意 CORS 功能的实现,直接拿现有的轮子来用即可。

安全原则三:SSL

http 改为 https,增强安全验证。

总结

以上做了一些简单的总结,可能并不是十分的准确,如有错误,希望能够指出我会及时修改,谢谢了。

推荐一下自己的达人课,感兴趣的朋友可以看一下:SSM 搭建精美实用的管理系统

gitchat

首发于我的个人博客,新的项目演示地址:perfect-ssm

如果有问题或者有一些好的创意,欢迎给我留言,也感谢向我指出项目中存在问题的朋友,具体的功能实现及代码逻辑将在之后的文章中介绍。

如果你想继续了解该项目可以查看整个系列文章Spring+SpringMVC+MyBatis+easyUI 整合系列文章, 也可以到我的GitHub 仓库或者开源中国代码仓库中查看源码及项目文档。