写点什么

解答有关 REST 的十点疑惑

2008 年 5 月 22 日

在了解过 REST 之后,你肯定很想知道这个概念在你的实际应用当中究竟能派上多大用场。而且,假如你已经熟悉另一套完全不同的架构手法的话,那么你担心“ REST 或 REST 式 HTTP(RESTful HTTP),是否真的能在实践中派上用场,还是在介绍性的、‘Hello, World’级场景以外就不灵光了”是很正常的。我将在本文解答人们——尤其是那些深谙基于 SOAP/WSDL 的 Web 服务架构手法的人——开始研究 REST 时容易产生的关于 REST 的十点疑惑。

1. REST 也许适用于 CRUD,但并不适用于“真实的”业务逻辑

这是那些对 REST 的好处持怀疑态度的人最常见的反应。毕竟,要是你只能 create/read/update/delete,那你如何表达更复杂的应用语义呢?我已经在本系列介绍性的文章中探讨过这些被大家所关心的问题了,不过这方面绝对值得进一步讨论。

首先,HTTP 动词(verbs)——GET、PUT、POST 和DELETE——跟数据库的CRUD 操作并不是一一对应的。例如,POST 和PUT 都可用于创建新资源,它们的区别在于:PUT 请求是由客户端决定(被创建或更新的)资源的URI;而POST 请求是向一个“集合(collection)”或 “工厂(factory)”资源发出的,是由服务器来指派URI 的。不过无论怎样,我们回到那个问题:如何应付更复杂的业务逻辑呢?

任何返回一个结果 c 的计算 calc(a, b),都可被转换为一个标识其结果的 URI——例如 x = calc(2,3) 可被转换为http://example.com/calculation?a=2&b=3。初看,这仿佛是完全错误的 REST 式 HTTP 的用法——我们应当用 URIs 来标识资源(resources)而不是操作(operations),不是吗?没错,其实你就是这么做的:http://example.com/sum?augend=2&addend=3 标识的是一个资源,即2 加 3 的结果。在这一特定的(显然是精心设计的)示例中,用 GET 来获取计算结果可能是个好主意——毕竟它是可缓存的(cacheable),你可以引用它,而且该计算多半是安全的(safe)且代价很小的。

当然,在许多(即便称不上大多数)情况下,用 GET 来执行计算也许是会犯错的。别忘了,GET 应当是一个“安全的(safe)”操作,也就是说,假如客户端只是通过发出 GET 请求来跟随一个链接,那么它不承担任何义务(比如因使用你的服务而向你付费)或责任。所以,在许多其他情况下,“通过 POST 请求向服务器提供输入数据、以便服务器新建一个资源”是更合适的做法。服务器在响应该 POST 请求时,可以给出结果的 URI (而且有可能发起一个重定向把你转向过去)。这个结果接下来便可被重用、被加入书签、在获取时被缓存等等。你基本上可以将这一模型推广应用到任何产生结果的操作——这涵盖几乎你所能想到的所有操作。

2. 没有正式的契约与描述语言

从 RPC 到 CORBA,从 DCOM 到 Web 服务,我们已习惯于拥有一个“列出操作、名称及输入输出参数类型”的接口描述(interface description)了。没有接口描述语言的话,REST 怎么用呢?

就这一被十分频繁问到的问题,有三点答复。

首先,假如你决定用 XML(这是很普遍的做法)来配合 REST 式 HTTP 的话,那么各种现有的 XML 模式语言(schema languages)(如 DTD、XML Schema、 RELAX NG Schematron 等) 仍旧可供你使用。可以说,一个用 WSDL 描述的东西,常常有 95% 的内容并不是跟 WSDL 相关、而是跟你定义的 XML Schema 复杂类型(complex types)相关的。WSDL 所增加的,大部分是有关操作(operations)及其名称的——对于 REST 的统一接口(uniform interface)来说,描述这些是颇为无趣的,因为 GET、PUT、POST 和 DELETE 就是你所能使用的全部操作了。关于 XML Schema 的使用,这意味着,即便你依赖于一个 REST 式接口,你仍旧可使用你所偏爱的数据绑定工具(假如刚好你有的话)来为你偏爱的语言生成数据绑定代码。(回答还没结束,见下。)

第二,问问你自己需要描述做什么。最常见(尽管并非唯一)的用例(use case)是:描述被用来给接口生成桩(stubs)和骨架(skeletons)代码。它通常不是文档(documentation),因为 WSDL 格式的描述并不是告诉你操作的语义——它只是告诉你操作的名称。你得通过一些人类可读的文档来了解如何调用它。典型的 REST 做法是,你应提供 HTML 格式的文档,其中可能包含指向你的资源的直接链接(direct links)。如果你采取提供多个表示(multiple representations)的做法的话,那么你可以真正拥有自文档化的(self-documenting)资源——你只要在浏览器中对一个资源做 HTTP GET 请求,就可以得到一个 HTML 文档,其中不但包含数据,还包含你可以对它执行的操作(HTTP 动词)的列表以及它接受和返回的内容类型(content types)。

最后,假如你坚持为你的 REST 式服务(RESTful service)使用描述语言,那么你可以使用 WADL(Web Application Description Language,Web 应用描述语言),或适当地使用 WSDL 2.0 (其制定者声称它也可以描述 REST 式服务)。不过,WADL 和 WSDL 2 在描述超媒体(hypermedia)方面均无帮助——而且考虑到这是 REST 的核心方面之一,我不太确信它们是否充分有用。

3. 谁真会把他们应用中如此多的实现细节暴露出来?

另一个普遍关心的问题是,资源太低层(low-level),暴露了那些不应暴露出来的实现细节。说到底,这不就把“按有意义的方式来运用资源”的担子加到客户端(消费者)的身上了吗?

简单的回答是:不。一个资源的 GET、PUT 或其他方法的实现,可以跟一个“服务”或 RPC 操作的实现复杂程度相当。应用 REST 设计原则,并不是说你必须把下层数据模型(underlying data model)中的各项暴露出来——它只意味着,你采用以数据为中心的(data-centric)方式、而不是以操作为中心的(operation-centric)方式把业务逻辑暴露出来。

一个相关的关切是,不支持对资源的直接访问将增加安全性。这是由“通过隐匿得到安全(security by obscurity)”这条陈旧的谬论得出的结论。人们可以这样反驳:其实恰恰相反,如果你隐瞒你通过特定于应用的协议访问哪些资源,你将无法利用基础设施(infrastructure)来保护它们。通过为有意义的资源指派单独的 URI,你可以利用 Apache 的安全规则(以及重写逻辑、日志和统计等)对不同资源采取不同处理。把这些明确化了,你的安全性将得到提升,而不是降低。

4. REST 只能配合 HTTP 使用,它不是传输协议无关的

首先,毫无疑问,HTTP不是一种传输协议(transport protocol),而是一种应用协议(application protocol)。它采用 TCP 作为下层传输(underlying transport),但它拥有自己的语义(否则它就没什么用处了)。仅将 HTTP 作为传输,是不恰当的。

第二,抽象未必总是好事。Web 服务的做法,是试图把许多大不相同的技术隐藏在单个抽象层背后——但这容易引发抽象泄露(leak)。例如,通过 JMS 和通过 HTTP 请求发送消息存在着巨大的不同,试图把各种存在极大差异的技术弱化为它们的最基本共通特性是毫无益处的。 打个比方,如果要创建一个通用抽象(common abstraction),把一个关系数据库和一个文件系统隐藏在一个通用 API 之后,当然这可以去做,但一旦你涉及到解决像查询这样的问题时,该抽象的问题就显露出来了。

最后,正如 Mark Baker 曾说过的:“协议无关性是一个缺陷,而不是一个特性”。虽然这给人的最初感觉是比较奇怪,但你要知道,真正的协议无关性(protocol independence)是不可能实现的——你所能做的只是决定依赖于哪一种协议。依赖于一种得到了广泛采纳和官方标准化的协议(如 HTTP)根本不是问题,而且它还得到了比试图取代它的抽象更广泛的普及与支持。

5. 没有实际的、明确且一致的指南教你如何设计 REST 式应用

REST 式设计在许多方面均没有“官方”最佳实践和“如何按符合 REST 原则的方式、用 HTTP 解决一个特定问题”的标准方式。毋庸置疑,这是会逐渐得到改善的。尽管如此,REST 具体表达了比基于 WSDL/SOAP 的 Web 服务更多的应用概念。换言之,虽然该批评对 REST 有很大价值,但这一批评更适用于其替换技术(它们基本上没有向你提供任何建议)。

有时,这种疑虑以“连 REST 专家们都无法就具体怎么做达成一致”的形式出现。但一般说来,情况并不是这样——举个例子,我比较相信我数周前在这里讲述的核心概念尚未(而且也不会)遭到REST 圈内人士(假定存在这个圈子的话)的质疑,这并不是因为那是一篇特别好的文章,而是因为人们在做过更深入的了解以后便能达成许多共识。假如你有机会做个实验的话,可以试试看,是让五位SOA 支持者在某方面达成一致更容易,还是让五位REST 支持者在某方面达成一致更容易。根据我个人的过往经验和长期参与数个SOA 与REST 讨论组的经历来看,我倾向于相信后者更加容易。

6. REST 不支持事务

“事务(transaction)”一词存在着多种不同解释,不过人们一般所说的事务,指的是数据库里的 ACID 这种。在一个 SOA 环境中——无论是否基于 Web 服务或 HTTP——各个服务(或系统、或 Web 应用)的实现仍然有可能与一个支持事务的数据库进行交互:这无需很大改变,假如你不用显式创建事务的话(除非你的服务运行在一个 EJB 容器或其他可以为你处理事务创建的环境中)。如果你与多个资源交互,情况也一样。

如果你打算把事务组合(或者创建)为一个更大的单元,情况将有所不同。在 Web 服务环境中,至少有一种办法可以做到跟人们所熟知的(比如 Java EE 环境所支持的)两阶段提交(2PC)相似:即采用 WS-Atomic Transaction (WS-AT),它是 WS-Coordination 标准族中的成员。本质上,WS-AT 所实现的是跟 XA 规定的两阶段提交协议非常相似或相同的。这意味着,你的事务上下文(transaction context)将用 SOAP 报头来传播,而你的实现(implementation)将负责确保资源管理器进入现有事务。本质上,跟 EJB 开发者所熟悉的模型一样——你的分布式事务跟本地事务一样是原子性的。

关于 SOA 环境中的原子事务(atomic transactions),有很多看法或反对意见:

  • 松耦合与事务(尤其是 ACID 那样的)根本格格不入。比如“跨越多个独立系统来协调提交,会在它们之间造成紧耦合”就充分说明了这一点。
  • 为了进行这种协调,需要对所有服务进行中央控制——而跨越企业边界进行两阶段提交事务是不可能或基本无法做到的。
  • 支持这种事务所需的基础设施(infrastructure)通常极为昂贵和复杂。

很大程度上,在 SOA 或 REST 环境中需要 ACID 事务,其实是一种设计异味(design smell)——你很可能已经为你的服务或资源采用了错误的模型。当然,原子事务只是一种类型的事务——除此以外还有扩展的事务模型,也许它更适合松耦合系统。不过,即便在 Web 服务阵营里,它们也没得到较多采纳。

7. REST 是不可靠的

常有人指出,REST 式 HTTP 里没有与 WS-ReliableMessaging 对等的特性,于是许多人便断定,REST 不能应用于讲究可靠性(reliability)的场合(那就是说差不多所有跟业务场景相关的系统)。但很多时候,你不一定需要一个处理消息递送(message delivery)的基础设施组件(infrastructure component),相反,你需要知道一个消息是否已被递送。

通常,收到一个响应消息——比方说 HTTP 里的 200 OK——表明你知道你的通信伙伴已经收到请求。但如果你没有收到响应消息,那问题就来了:你不知道是你的请求没有到达另一端,还是已经收到了(触发了某些处理)、但响应消息丢失了。

确保请求消息抵达另一端的最简单的做法,就是把消息重发一遍——当然,仅当接受方有能力处理重复消息(比如通过忽略它们)时才可以这么做。这种能力被称作幂等性(idempotency)。HTTP 确保 GET、PUT 和 DELETE 是幂等的(idempotent )——如果你的应用实现得当的话,那么客户端在没有收到响应时只需把请求重发一遍即可。但 POST 消息不是幂等的——至少在 HTTP 规范里没有保证。对此你有多种选择:要么改用 PUT(如果你的语义可以映射上去的话),采用 Joe Gregorio 描述的一种常见的最佳实践;要么采纳一种致力于统一有关做法的提案(例如 Mark Nottingham 的 POE(POST Once Exactly) Yaron Goland 的 SOA-Rity Bill de hóra 的 HTTPLR )。

就我个人而言,我倾向于上述第一种做法——即把可靠性问题转嫁到应用设计方面,不过对此存在多种不同看法。

尽管这些方案均解决了相当一部分可靠性问题,但没有(或至少就我所知没有)一个能支持消息递送承诺,比如按序递送一系列 HTTP 请求和响应。不过值得一提的是,许多现有的 SOAP/WSDL 方案没有依靠 WS-ReliableMessaging(或其前身)也勉强应付了。

8. 不支持发布 / 订阅

本质上,REST 基于的是一种客户端 - 服务器模型(client-server model),HTTP 总把客户端和服务器称为通信端点(endpoints of communication)。客户端通过发送请求和接受响应的方式与服务器进行交互。在发布 / 订阅模型(publish/subscribe model)中,客户订阅特定种类的信息,然后每当有新信息出现时它就会得到通知。REST 式 HTTP 环境怎么可能支持发布 / 订阅呢?

寻找理想的例子并不难,聚合(syndication)就是一个。 RSS Atom Syndication 都是聚合的例子。客户端通过“向一个代表变更集合(collection of changes)的资源发出 HTTP 请求”来查询新信息,如获取特殊分类或定时轮询。这搞不好会相当低效,但实际上并没有,因为 GET 是 Web 上最优化的操作。其实,你可以很容易想象,要是一个受欢迎的博客服务器主动把各个变更通知各订阅者的话,那么它应该可以在可伸缩性方面得到很大提高。轮流通知(notification by polling)具有极好的可伸缩性。

你可以将这一聚合模型(syndication model)推广应用到你的各个应用资源——例如,为用户资源或账目审计追踪记录的变更提供 Atom 提要(feed)。除了可以满足任意数量应用的订阅需求,你还可以用提要阅读器(feed reader)来查看这些提要(feeds),就像在浏览器里查看一个资源的 HTML 表示(representation)一样。

当然,在某些情况下这就不合适了。比如,对于软实时(soft real-time)需求,采用其他技术也许更为合适。但在许多情况下,由聚合模型赢得的松耦合(loose coupling)、可伸缩性(scalability)与通知(notification),整体上是相当不错的。

9. 无异步交互

在 HTTP 的请求 / 响应模型之下,如何实现异步通信?同样地,我们应注意到人们在谈及异步性(asynchronicity)时常常指的是不同方面。有人指的是编程模型,它可以是跟线上交互(wire interactions)无关的阻塞或非阻塞模型。这不是我们所关心的。但假如你把一个请求从客户端(用户)递送到服务器端(提供者)的过程需花费数小时,这怎么办呢?用户如何知道处理有没有结束?

HTTP 有一个专门的响应代码 202 Accepted,它的意思是“请求已被接受处理,但处理还没有结束”。显然,这正是你所需要的。至于处理结果,有多种办法:服务器可以返回一个资源的 URI,然后客户端通过向该 URI 发送 GET 请求来访问结果(尽管在专门为一个请求创建资源时采用响应代码 201 Created 更为恰当)。或者,客户端可以提供一个 URI,并期待服务器在处理完成后把结果 POST 上去。

10. 缺少工具

最后一点,人们常常抱怨缺少用于支持 REST 式 HTTP 开发的工具。正如我在第二点里提到的,在数据方面其实不是这样——你可以使用你熟悉的数据绑定与其他数据 APIs,因为这与方法数量和调用它们的方式无关。至于普通的 HTTP 与 URI 支持,现在所有的编程语言、框架及工具包都能提供立即支持。最后,厂商们正在为“用它们的框架进行更便捷的 REST 式 HTTP 开发”提供越来越多的支持,例如 Sun 的 JAX-RS(JSR 311)、微软的.NET 3.5 及 ADO.NET 数据服务框架里对 REST 的支持。

总结

那么,REST 及其最常见的实现——HTTP——理想吗?当然不。世界上没有在所有情况下都理想的东西,而且很多时候即便在单个情况下都未必能够理想。我已经避免了许多相当合理、但需要更复杂解答的问题领域,比如基于消息的安全、部分更新以及批处理等,我承诺将在后续文章中讨论这些问题。希望我已经解答了你的一些疑惑——假如我遗漏了你最关心的问题,欢迎在此发表评论。

Stefan Tilkov 是 InfoQ SOA 社区的首席编辑,以及位于德国 / 瑞士的 innoQ 公司的合伙人、首席顾问和主要 REST 狂热主义者。

查看英文原文: http://www.infoq.com/articles/tilkov-rest-doubts


译者简介:徐涵,中文 W3C 技术推广网站 W3China(w3china.org) 创始人,开放翻译计划(transwiki.org) 发起人,W3C 特邀专家。2005 年毕业于东南大学,获计算机硕士学位。2003 年创办中文W3C 技术推广网站W3China(w3china.org),2004 年发起开放翻译计划(transwiki.org)致力于W3C 技术文档的翻译,2006 年翻译出版国内首本中文SOA 专著《Understanding SOA with Web Services 中文版》(荣获2006 年度CSDN 读书频道SOA 先锋奖,入选China-pub 2006 年度好书榜),2008 年翻译出版REST 专著《RESTful Web Services 中文版》 。研究兴趣包括:Web Architecture、Semantic Web、Web Services、SOA、Social Network 等。联系方式: hanxu@w3china.org 。参与 InfoQ 中文站内容建设,请邮件至 editors@cn.infoq.com

2008 年 5 月 22 日 20:1310410
用户头像

发布了 63 篇内容, 共 22.2 次阅读, 收获喜欢 5 次。

关注

评论

发布
暂无评论
  • WSDL 2.0 被批准成为 W3C 官方推荐

    2007年6月27日,WSDL 2.0最终被批准成为万维网联盟(W3C)官方推荐。Web服务描述工作组已在这些标准上工作超过了6年。该推荐预定于2006年12月31日到期,但是后来又得以延期至今年的6月30号。

  • REST 的业务用例

    Justin Cormack的一篇博文引发了关于RESTful架构在企业里的采用或缺失的热烈讨论。

  • 加餐 | MySQL XA 是如何实现分布式事务的?

    MySQL XA性能不高,适合在并发性能要求不高的场景中使用。

    2020 年 6 月 22 日

  • REST – 善,恶,丑

    关于REST的优势与缺点在业界的开发者中间引起了无尽的争论。Arnon Rotem-Gal-Oz的一篇新帖子提供了关于REST的“善”与“恶”两方面的思考。

  • 程序员练级攻略:微服务

    微服务中有很多很不错的想法和理念,所以学习微服务是每一个技术人员迈向卓越的架构师的必经之路。

    2018 年 7 月 19 日

  • 虚拟研讨会:如何设计好的 RESTful API?

    设计好RESTful API对于软件架构的扩展性和伸缩性、消费者的体验起着至关重要的作用。如何设计好的RESTful API呢?我们一起来听听一线专家们的实践经验。

  • 深入浅出 REST

    在这篇文章里,Stefan Tilkov对REST(表述性状态转移)——万维网背后的架构——做了一次非常实用的介绍,主要包括可确认的资源、链接和超媒体、标准方法、多重描述以及无状态通信等。

  • 可编程的互联网世界

    这一讲我们希望给大家呈现的是应用程序的全貌。当然,我们现在看到的仍然是非常高维的样子。

    2019 年 6 月 5 日

  • 67 丨 Swift 中的协议

    2019 年 10 月 29 日

  • unREST 是新的 REST 吗?

    Jean-Jacques Dubray在他最近的一篇文章中讨论了为什么我们应该跳出REST的圈子,也许应该同意在很多目前正使用REST的领域中,REST其实并不适用。在试图描绘他认为的发展方向时,他提出了unREST,即3条设计成功API的简单规则。

  • 应该如何理解请求方法?

    所谓的“请求方法”,它的实际含义就是客户端发出了一个“动作指令”,要求服务器端对URI定位的资源执行这个动作。

    2019 年 6 月 19 日

  • 你能写出正确的网址吗?

    只要你清楚了URI的格式,就能够轻易地“破解”地址栏里各式各样的长串字符了。

    2019 年 6 月 21 日

  • CRUD 不适合 REST 吗?

    Arnon Rotem-Gal-Oz在他的新博文中指出REST不只是一组标准和API,只有遵循REST的架构原则才能享受它的全部好处。

  • REST 和分布式事务

    最近关于分布式事务及其在REST世界的位置的话题再次火热登场。很多人表明他们正在思考将事务与REST结合起来,或者正在进行中,然而还有一些人,包括Roy Fielding,认为这两个事物本就不该一起出现。

  • REST 反模式

    在本文中,Stefan Tilkov讲解了一些经常出现在自称“符合REST式设计”的应用中的反模式(比如:全部采用GET或POST,忽视缓存及响应代码,误用cookies,忘记超媒体与MIME类型,以及破坏自描述性等),并给出了避免这些反模式的对策。

  • Internet 比 REST 更基本吗?

    REST是否优于WS-*的争论已经僵持一段时间了,没有明显的赢家。然而,Ganesh Prasad试图给争论火上浇油,并举例说明他始终不认为REST是最基本和可扩展的方法。

  • 如何度量应用的 RESTful 成熟度?

    继“REST还是WS-*”和“SOA死了么”之类论战之后,战场已经悄然转换,“如何度量一个应用的RESTful程度”或“一个RESTFul系统的成熟度”变成新一轮论战的焦点。其中一个被频繁提及的方法是Richardson成熟度模型。然而,这一方法合适与否,社区里同样不乏反对的声音。

  • RESTful 世界里的 Cool URI

    假想一下,如果要以最小的集成代价实现一个分布在全世界范围的信息空间,用它来共享机器可识别的数据,会怎么样?这是关于REST的吗?不是的。根据 SWEO的说法,这跟语义网有关。那些Cool URI有助于实现这种方式。所以,去看看RESTful SOA URI是不是也很“酷”可能是值得的。

  • 支持 REST 设计的 WCF Web 编程模型

    在MIX07大会上Don Box和Steve Maine的“浏览可编程Web”联合演讲中,他们介绍了即将随Visual Studio Orcas一同发布的WCF Web编程模型。在统一的WCF编程模型下,Web编程模型从而可以支持Web服务REST化设计的功能。

  • 在 REST/Ajax 架构中减少服务器负载和网络流量

    在developerWorks上的一篇短文向我们展示了如何为Ajax/REST架构减少网络流量和服务器处理,但是本文的可贵之处在于,他们有效利用了HTTP 304状态码,而不是推荐使用一些更加复杂的解决方案。

发现更多内容

JVM调优不知道怎么回答,阿里总结四大模块,学不会就背过来

小Q

Java 学习 架构 面试 JVM

了不起!靠技术脱贫,他们只用了短短两年!

华为云开发者社区

人工智能 华为 技术

关于Redis分布式锁这一篇应该是讲的最好的了,赶紧收藏起来

比伯

Java 编程 架构 面试 技术宅

网咯请求中的 connectTimeout 和 soTimeout

不在调上

operator-sdk & kubebuilder

QiyihaoLabs

k8s operator-sdk kubebuilder crd

P8架构挑战:七大专题1425页考点,你能成功吗?

小Q

Java 学习 程序员 架构 面试

数据库面试要点:关于MySQL数据库千万级数据查询和存储

华为云开发者社区

数据库 sql 存储

只需三步!慢日志去无踪

数据君

数据库

Java架构速成笔记:七大专题,1425页考点,挑战P8岗

Java架构追梦

Java 学习 面试 java架构

得不到提升的开发老鸟,试试这3个方法,让你事半功倍!

Linux服务器开发

程序员 互联网人 后端开发 底层应用开发 Linux服务器开发

Redis为什么这么快?

数据君

redis

安装MySQL后,需要调整的10个性能配置项

Simon

MySQL percona server

电信新报告 | 数字化转型:搁置还是加速?

VoltDB

5G安全 通信 电子信息

英特尔携手德晟达、游密,发布云会议终端解决方案,打造视听新体验

intel001

没有它你的DevOps是玩不转的,你信不?

华为云开发者社区

容器 DevOps 微服务

Java“基础-中级-高级”程序员面试大全

Crud的程序员

Java java程序员 java基础

开发实践丨用小熊派STM32开发板模拟自动售货机

华为云开发者社区

物联网 小熊派 开发板

一文教你看懂缓存穿透、击穿、雪崩、降级等异常

鄙人薛某

Java 缓存 后端 缓存击穿 缓存雪崩

不满意社区的轮子,我们自创了一套 React Hooks 风格的数据加载方案

LeanCloud

API React Hooks

企业面临大危机,CRM崩溃告急,程序员竟用特殊手段化解危机!

Learun

敏捷开发 CRM

你可能不用,但你必须要会!面试必备的Java多线程知识点总结(思维导图+源码笔记),已整理成PDF版文档

Java成神之路

Java 程序员 架构 面试 编程语言

2年Java外包经验程序员的逆袭之路,4面阿里斩获P6级offer的面经总结。

Java成神之路

Java 程序员 架构 面试 编程语言

业务中台建设-数据

孝鹏

架构 中台 数据 赋能

关于Kubernetes和Docker关系的八个问题

杨明越

终于拿到蚂蚁金服Offer!!!分享一下全程面试题和面试经验!

小Q

Java 学习 编程 架构 面试

连续肝了好几天,终于把Java面试最重要的必备知识【Spring知识点】总结整理出来了。

Java成神之路

Java 程序员 架构 面试 编程语言

阿里P9架构师推荐的Spring领域巅峰之作《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》,带你深入解析Spring架构与设计原理

Java成神之路

Java 程序员 架构 面试 编程语言

23种设计模式与六大原则看了又忘,忘了又看?是你看的方法不对!

Java成神之路

Java 程序员 架构 面试 编程语言

时序数据库DolphinDB与Druid的对比测试

DolphinDB

数据分析 时序数据库 Druid 数据库选择 DolphinDB

甲方日常 65

句子

工作 随笔杂谈 日常

话题讨论 | 立一个近期的flag,你会想到什么?

xcbeyond

话题讨论

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

解答有关REST的十点疑惑-InfoQ