文档章节

我为什么反对RESTful

Sel8616
 Sel8616
发布于 2015/11/28 14:39
字数 1661
阅读 486
收藏 1

我反对RESTful

并不是说RESTful完全错误,只是不赞成它的理念。

个人观点,不喜勿喷!学识有限,浅谈辄止!

首先,看个小程序。对于下面这个类,我们现在期望pid只读。

class User
{
    private String name;//姓名
    private String pid;//身份证号
    ...

    public User(String newName,String newPid)
    {
        name = newName;
        pid = newPid;
    }
}

方法一:增加getter

public String getPid()
{
    return pid;
}

方法二:同时增加getter/setter

public void setPid(String newPid)
{
    throw new Exception("Sorry!不让改!");
}
public String getPid()
{
    return pid;
}

不知大家采用哪种??

再举个例子,如果你有一间房子,你永远不打算从南面走出去。那么,你是在南边装扇门并永远锁上,还是干脆不在南墙上装门?

其实我想说的是————对于一个系统(或干脆就指一台服务器)而言,对外提供的应该是‘经过包装的有限服务’,而不能把所有资源全盘托出,让使用者自选操作。

HTTP作为网络协议,它的设计目标是处理静态资源(从最早的纯html页面,到后来广泛支持各种文件),随着web应用的需求越来越复杂,出现了动态网站,而动态资源仍然是由应用服务器生成静态资源经HTTP协议转发的。

原来的web服务器,直接基于OS和文件系统操作静态资源,因而使用GET/POST/DELETE/PUT来表示对资源的操作;而应用服务器,相当于前端逻辑与数据资源的中间件,对资源的处理是应用程序的工作,CRUD是接口内部实现中考虑的问题,应当保持在应用程序内部。

接口的设计应只考虑当前业务功能是什么(报名/下单/改签/..),一项具体的业务需求是一个短语或一句话,深层次已经包含了目标资源和对应操作,请求业务时无需再额外描述“增删改查”的概念。由于系统服务的包装性,资源不可直接外露,所以API中URI的实际作用应该是USI(Uniform Service Identifier)。

####RESTful的问题就在于,它是面向资源的,而不是面向服务的。

  • 最现实的问题就是————对于任一个URI,开发者都要判断HttpMethod,对于不支持的动作都要返回一个405或自定义消息。这,难道不是一件很无聊的事情么?
  • 最重要的问题还是————上面说到的,系统应该严格控制对内部资源的访问,以服务的方式对外提供访问接口,主动屏蔽不支持的操作,而不是遇到不支持的操作再报错。

诚然,RESTful只是一种风格,并没有改变程序功能。是否使用RESTful,最终实现的逻辑可能完全一致;但从系统设计角度看,形式化的东西也很重要。

###————————————————————

退一步讲,姑且不说上面的问题,RESTful本身也是先天不足的————因为HTTP在web应用方面是先天不足的,并且HTTP的设计比较简单,其报头主要用于描述HTTP通信参数和状态,而RESTful使用HTTP动词和状态码来表示业务逻辑,无法避免语义冲突和表达能力弱的问题。

冲突是因为:前端收到的状态码,可能是HTTP协议直接返回的,也可能是应用逻辑返回的。我们做过一个项目,经理要求必须用HTTP状态表示业务请求结果。我极力反对,但不被采纳。结果:404被用来表示“您查询的××不存在”,而Server宕机或接口不匹配时,APP收到的结果也是这个;405/407/410直接被HttpURLConnection抛IOException。 并且标准状态码那么少,遇到复杂些的项目,也不够用啊。当然,可以自定义状态码,但是业务逻辑侵入网络协议绝不是一个好办法。还是使用自定义Header或自定义消息格式靠谱,虽然使用头部字段也触碰了HTTP协议,但自定义头本来就是留给应用作扩展的,并不会干扰协议工作)

还看到有人提出RESTful最好实现Hypermedia API(http://my.oschina.net/u/2337119/blog/532450) ————这也不是一个好点子。一个系统应当严控业务接口的开放程度,API应提前绑定在远端。如果“你”不知道“我”这里有哪些服务可用,那么“你”就不应该来访问“我”,因为这样的“你”应该不是一个正常的访问者,否则,“你”应当知道系统服务列表,并确切地知道每一项业务对应的具体API。上文中和github的API作比较,是错误的。Github是开放平台,本来就是面向开发者、方便开发者的,API本身就是开发者需要查询的信息,需另当别论。

可能有人会说,API的调用者其实是系统框架内的远端APP、页面或软件,RESTful使用HTTPS可以实现安全通信,相当于这样的API是工作在系统内部,资源直接可见不成问题。对此,我也是反对的。曾经的DES很安全,后来不行了;曾经我们以为MD5没问题,后来也被质疑了;现在SSL也已滴过血了,尽管暂时还算安全,谁知道哪天就挂了......绝对的网络安全是不存在的;并且SSL实现的是通信安全,不会保证远端的应用没有被绑架。一个可靠的、健壮的系统,不能把自身的安全完全寄托在第三方身上,必须要以自己为主,该采取的策略和措施一样不能少。


RESTful的诞生源于:开发人员希望Web service和app开发的基础架构和部分通用逻辑能够标准化。这个愿望并没有错,但我认为人们在HTTP协议上打算盘却是错误的。这只能是对上述期望的一次尝试,一次使用现有工具“将就着”实现理想中新工具功能的尝试。RESTful能否最终标准化,将来应该会有正式的、完善的新协议来取代RESTful以及HTTP,或许就叫做WASP吧。 [Web Application Service Protocol]


© 著作权归作者所有

Sel8616

Sel8616

粉丝 12
博文 2
码字总数 1851
作品 1
成都
私信 提问
加载中

评论(1)

滴滴丶哔哔
滴滴丶哔哔
非常不错。
一个 16年毕业生所经历的 PHP 面试

前言:有收获的话请加颗小星星,没有收获的话可以 反对 没有帮助 举报三连 有心的同学应该会看到我这个noteBook下面的其它知识,希望对你们有些许帮助。 本文地址 时间点:2017-11 一个16年毕...

醉大侠
2017/12/17
0
0
一个16年毕业生所经历的php面试

前言:有收获的话请加颗小星星,没有收获的话可以 反对 没有帮助 举报三连 有心的同学应该会看到我这个noteBook下面的其它知识,希望对你们有些许帮助。 本文地址 时间点:2017-11 一个16年毕...

OMGZui
2017/11/22
0
0
请问用restful方式访问saveUser的RequestMapping上没有路径,url访问controller是怎么找到这个方法的?

不用restful方式RequestMapping有个value作为路径,可以根据路径访问。用了restful方式为什么没有路径(value)也可以访问呢?

NaviaJin
2017/06/13
358
1
javax.ws.rs的小疑惑

javax.ws.rs中的API里面提到了: High-level interfaces and annotations used to create RESTful service resources. 这些与 spring 中的 restful有啥区别呢?或者 apache cxf 中的有啥区别......

徐建兴
2015/01/13
361
1
HBASE 的restful api ,哪家公司正在使用

HBASE 的restful api ,哪家公司正在使用 HBASE 的restful api ,哪家公司正在使用 我想查询这种格式的,不知道为什么怎么试都不行

天池番薯
2015/10/21
277
0

没有更多内容

加载失败,请刷新页面

加载更多

Rails中的ERB中的<%,<%=,<%#和-%>有什么区别?

能否请您描述一下ERB文件中使用的以下字符的用法: <% %><%= %><% -%><%# %> 每个有什么用? #1楼 Rails默认不使用stdlib的ERB ,而是使用erubis 。 资料来源: 该开发人员的评论 ...

javail
36分钟前
72
0
九型人格测试,看游戏人物性格制作

作为一个资深的宅男&游戏玩家,也算阅人无数,额,具体的说,应该是阅游戏里的人物角色无数,游戏中不管是NPC,还是玩家扮演的角色,都有这个人物自己的性格,根据剧情,我们可以判断出这个人...

蛤蟆丸子
43分钟前
50
0
聊聊skywalking的MemoryProvider

序 本文主要研究一下skywalking的MemoryProvider MemoryProvider skywalking-6.6.0/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/memory/MemoryPro......

go4it
44分钟前
33
0
ServiceLoader

1: ServiceLoader 使用简介 java 优雅地获取接口实现 2:Java ServiceLoader使用和解析 3:spring-boot-starter原理及实现方法...

whoisliang
47分钟前
48
0
SpringCloud Feign 配置token请求

相关依赖引入 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> ......

IT-Mamba
50分钟前
55
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部