写在前面的话

这个问题看起来就显得有些萌,或者说类似的问题都有些不靠谱,世上哪有那么多一定的事情,做开发都不一定做多久呢,所以说如果你有这个疑问的话是真真有点儿不着调,不过可能也就是随口一问吧,没有深究的必要。既然有人问这个,那么就再用一篇文章谈谈RESTful吧,既然谈,就不能只是谈其优点,也不能一味的吹捧,也讲一下自己的一些理解和不足的地方。

规范、易读、简洁?

Spring+SpringMVC+MyBatis+easyUI整合进阶篇(一)设计一套好的RESTful API
Spring+SpringMVC+MyBatis+easyUI整合进阶篇(二)RESTful API实战笔记(接口设计及Java后端实现)
Spring+SpringMVC+MyBatis+easyUI整合进阶篇(三)使用ajax方法实现form表单的提交
Spring+SpringMVC+MyBatis+easyUI整合进阶篇(四)RESTful API实战笔记(前端代码修改)
前文中已经谈了RESTful不少的优点,也做了代码更新,首先,REST强调HTTP应当以资源为中心,并且规范了资源URI的风格;规范了HTTP请求动作(PUT,POST等)的使用,具有对应的语义;遵循REST规范的Web应用将会获得下面好处:URL具有很强可读性的,具有自描述性;资源描述与视图的松耦合;可提供OpenAPI,便于第三方系统集成,提高互操作性;如果提供无状态的服务接口,可提高应用的水平扩展性;

总结下来:规范、易读,但是这两个优点也带来一些不尽如人意的"反效果":

  • 因为RESTful规范较为明确且有一定的"强制性",这种限制反而导致设计uri变得复杂了,尤其是复杂的关系,操作,资源集合,硬性套用rest原则设计非常困难。
  • 对于RESTful的争论无处不在,都在讨论正确性和规范性,即使和同事之间也会有类似的争执,当我们在争论Restful风格到底如何设计才是正宗时,发现心中的困惑不仅没有降低,反而增加了。
  • RESTful思想及其所倡导的规范很正确,但是使用者的行为太刻意了反而导致这个东西变了味道,争来争去就是为了证明自己的理解和使用最"正宗"。

RESTful中的模棱两可

前一个段落可能有些过于概念化了,还是举一些具体的例子吧。

案例一

其实,RESTful中也存在着许多的模棱两可,也有很多不是那么让开发人员舒服的地方,有人会去纠结查询、增加、修改、删除(对应的方法就是get、post、put、delete),个人认为这并不完全正确,因为这个想法把开发工作中的业务场景过于简单化和模板化了,我们开发的功能就只实现这四类操作吗、如果遇到一些不能完全对应上这四种方式的业务该怎么办呢?

  • 发短信、支付、用户登录认证,该用get、post、put、delete中的哪一个HTTP动词?
  • login和logout应该怎么REST化?
  • 验证码发送该如何定义uri?

类似的问题还有很多,感觉很多朋友会遇到类似的问题,心里面也有一些不确定该如何去做,其实在理解了REST后,这些并不是什么无解的难题,只是思维方式要转换一下: login和logout其实只是对session资源或者cookie资源的创建和删除;业务的uri如何选择HTTP动词也要灵活变通,规范是死的,人是活的,按照自己的理解去做,如果后期发现错误即使纠正就好了。不过,虽然API如何编写是开发者的自由,但如果一个API在url里放一堆动词、资源设计混乱、各种乱用HTTP Method和Status Code,就太不像话了,规范嘛还是要遵守的,说了这么多理解上的偏差,其实代码质量才是最重要的,有些手段其实只是让代码看起来比较优雅的手段而已。

案例二

以上是针对于RESTful理解和设计上的一个例子,具体工作中还有其他的例子吗?也是很多的,比如,比较棘手的一个问题:跨域资源共享 CORS。

在实际进行跨域请求时,经常会遇到类似 No 'Access-Control-Allow-Origin' header is present on the requested resource.这样的报错:

这个问题并不是因为RESTful引起的,也不能通过修改RESTful的规范去解决,举这个例子的原因是因为在接口的RESRful化时也遇到过这个问题,解决办法就不在本文中列举了,有兴趣的朋友可以看一下跨域资源共享 CORS 详解这篇文章,以后有时间会把解决方案整理出来的。

一些需要重视的安全性问题

当然,不止是以上的两个问题,前一个段落主要是讲述了一下理解和具体使用上的问题,这一段讲一下可能引发的安全性问题。

遗漏了对资源从属关系的检查

一个典型的RESTful的URL会用资源名加上资源的id编号来标识其唯一性,就像这样:/users/{userid},例如:/users/100

一般而言用户只能查看自己的用户信息,而不允许查看其它用户的信息。在这种情况下,攻击者很可能会尝试把这个URL里面的USER ID从100修改为其他数值,以期望应用返回指定用户的信息。不过由于这个安全风险太显而易见,绝大多数应用都会对当前请求者的身份进行校验,看其是否是编号为100的用户,校验成功才返回URL中指定的用户信息,否则会拒绝当前请求。

不经意间泄露的业务信息

以查看用户信息的RESTful URL为例:/users/100。由于用户ID是一个按序递增的数字,因此攻击者既可以通过ID知道目前应用中的用户规模,也可以分别在月初和月末的时候注册一个用户,并对比两个用户的ID即可知道当前这个月有多少新增用户。同理,如果订单号也是按序自增的数字,攻击者可以了解到一定时间范围内的订单量。

这类ID并不会给应用造成任何技术上的威胁,只是通过ID泄露出来的信息对于你的业务而言可能非常敏感。解决办法是不使用按序递增的数字作为ID,而是使用具有随机性、唯一性、不可预测性的值作为ID,最常见的做法就是使用UUID。

参考RESTful架构风格下的4大常见安全问题

选择适合自己的方式

Spring+SpringMVC+MyBatis+easyUI整合进阶篇(五)记录一下从懵懂到理解RESTful的过程
前一篇博客中也提到了很多其他的方式,比如传统的MVC开放形式,比如webservice,比如rpc调用,RESTful也只是其中的一种而已,这些选项中并没有高下之分,无非是多种约定俗成的标准,传统MVC开发着舒服就按MVC模式来开发,习惯用RPC就用RPC,能理解和接受REST就用REST。

前几篇文章中描述了RESTful那么多的优点,现在又说大可不必使用,前文又提到RESTful是好的设计实践,现在又是另外一种说法,不是自相矛盾吗?

这是我的文章,我肯定要按照我的一些想法写啊,可能有不对的地方,前文中提到的是好的设计实践也是我的个人想法和理解,这篇的开头就说了,不能只谈优点,所以又列举了一些不足吧,我写文章不是挑口水,很没必要,选择适合自己的技术和规范就好。

套用网络上比较流行的一句话:

听了很多道理却依然过不好一生。

作为一名开发人员,自己动手去实践才是硬道理,别人说什么都不要全盘接受,你要想想适不适合你,适不适合你目前做的项目,鞋合不合适只有脚知道,just do it!

结语

优点也好,缺点也罢,虽然看似也总结了不少,但都是个人见解,肯定还有一些遗漏的地方没有讲清楚,还请见谅。

回答文章一开始的问题,是不是一定要用呢?是不是一定要遵循其规则呢?如果不能解决你所面对的问题,不能提高和提升代码质量、提升工作效率,其实大可不必如此介怀,不用就是了。

首发于我的个人博客,编辑于2017年10月13日晚11:37分。

有人提了一个问题:一定要RESTful吗?的更多相关文章

  1. 给JDK提的一个bug(关于AbstractQueuedSynchronizer.ConditionObject)

    1. 背景 之前读JUC的AQS源码,读到Condition部分,我当时也写了一篇源码阅读文章--(AbstractQueuedSynchronizer源码解读--续篇之Condition)[http ...

  2. 构建一个基于 Spring 的 RESTful Web Service

    本文详细介绍了基于Spring创建一个“hello world” RESTful web service工程的步骤. 目标 构建一个service,接收如下HTTP GET请求: http://loc ...

  3. Apache CXF实现Web Service(2)——不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service

    实现目标 http://localhost:9000/rs/roomservice 为入口, http://localhost:9000/rs/roomservice/room为房间列表, http: ...

  4. 为什么一个Http Header中的空格会被骇客利用 - HTTP request smuggling

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  5. Redis Cluster架构优化

    Redis Cluster架构优化 在<全面剖析Redis Cluster原理和应用>中,我们已经详细剖析了现阶段Redis Cluster的缺点: 无中心化架构 Gossip消息的开销 ...

  6. Neutron 理解 (4): Neutron OVS OpenFlow 流表 和 L2 Population [Netruon OVS OpenFlow tables + L2 Population]

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  7. FIN_WAIT1 能持续多久?你知道吗

    FIN_WAIT1 能持续多久?你知道吗 2016-01-12 运维帮 原文:http://blogread.cn/it/article/7215?f=wb&luicode=10000359 ...

  8. [转]把项目从VS2005升级到VS2013

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://rangercyh.blog.51cto.com/1444712/1394348 ...

  9. 关于FIN_WAIT1

    前些天,一堆人在 TCPCopy 社区里闲扯蛋,有人提了一个问题:FIN_WAIT1 能持续多久?引发了一场讨论,期间我得到斌哥和多位朋友的点化,受益良多. 让我们热热身,通过一张旧图来回忆一下 TC ...

随机推荐

  1. 软件工程(GZSD2015)第三次作业提交进度

    第三次作业题目请查看这里:软件工程(GZSD2015)第三次作业 开始进入第三次作业提交进度记录中,童鞋们,虚位以待哈... 2015年4月19号 徐镇.尚清丽,C语言 2015年4月21号 毛涛.徐 ...

  2. 团队作业8——第二次项目冲刺(Beta阶段)--第五天

    一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 学号 成员 贡献比 201421123001 廖婷婷 15% 201421123002 翁珊 16% 201421123004 ...

  3. 201521123071 《JAVA程序设计》第二周学习总结

    1. 本周学习总结 在本周的学习中,主要学习了书上的String类以及Math类等知识,但是书上学到的东西只是理论,实际打起代码来的时候会学习到更多,比如在PTA上就有学习到StringBuilder ...

  4. 201521123025 《Java程序设计》第1周学习总结

    1. 本章学习总结 (1)对JAVA的历史有了初步了解 (2)学会安装JDK和设置JAVA_HOME,PATH,CLASSPATH环境变量 (3)范围:JDK>JRE>JVM 2. 书面作 ...

  5. Ubuntu下Java开发环境搭建(eclipse)

    最近把工作环境转移到了Ubuntu Kylin下,发现在这下面Java环境还是很方便的.然而也经历了一些摸索的过程,故作文以记之. 一/开发前准备 安装系统/配置软件源,这部分内容没什么需要注意的.O ...

  6. java第十四次作业

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  7. 201521123060 《Java程序设计》第9周学习总结

    1.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2.书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1截图你的提交结果(出现学号) 1.2自己以前编写 ...

  8. POJ--3258 River Hopscotch (最小值最大化C++)

    River Hopscotch Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15273   Accepted: 6465 ...

  9. Maven第四篇【私有仓库、上传jar包、引用私服jar包、上传本地项目到私服】

    搭建私有服务器 前面已经说过了,我们使用Maven的使用,如果需要导入相对应的jar包,Maven首先会在我们的本地仓库中寻找->私有仓库->中心仓库- 然而,我们的本地仓库常常没有想要的 ...

  10. 纳税服务系统【信息发布管理、Ueditor、异步信息交互】

    需求分析 我们现在来到了纳税服务系统的信息发布管理模块,首先我们跟着原型图来进行需求分析把: 一些普通的CRUD,值得一做的就是状态之间的切换了.停用和发布切换. 值得注意的是:在信息内容中,它可以带 ...