【问题标题】:Is Implementing a HTTP, XML based CRUD Layer a good idea?实现基于 HTTP、XML 的 CRUD 层是个好主意吗?
【发布时间】:2010-11-18 05:12:00
【问题描述】:

我正在为应用程序创建一个 CRUD“层”。 这将是一个简单的 CRUD 应用程序,例如,存储用户信息、收藏链接等,而不对“事实类型”数据进行操作。它实际上只是存储应用程序的其他部分用来执行工作的用户、权限、规则、策略等内容。

总的来说,我希望从这项工作中获得三件事:

  • (a) 访问 CRUD 功能的单一入口点
  • (b) 能够使用任何“客户端”来使用 CRUD 层
  • (c) CRUD 的“简单”可扩展性,可以添加新对象和更改旧对象(添加新字段,没有其他内容被删除或更改)。典型的 CRUD 场景?

我在想我应该制作一个 Java 库,通过“REST-type-URL”(仅表示 REST-URL 方式,例如“users/delete/2”)向客户端公开它) 通过 HTTP 的 API。这样,我可以实现所有 3 个目标 - CRUD 层可以在 Linux 上,客户端可以在 Windows 上。

在 CRUD 层,我将使用各种东西来实现这一点:ORM、Web 服务器和其他工具。

似乎是正确的方法,但我不禁想,也许这种方法太理想化了,当我开始实施时可能行不通。

我是否正在考虑将一组 API 方法塞入 XML 片段的过于简单化的观点? (请注意,我不是在做 XML-RPC,而是这些 XML 片段将只是数据 - 并且 XML 将被发送到特定的 URL,例如 users/update/2,在确认之后将处理 XML XML 包含用户配置文件的信息)

我的想法是对的吗?这个想法有没有可能奏效?

任何帮助表示赞赏!

【问题讨论】:

  • 您知道,REST 与 URI 命名方案完全无关,也不存在“REST-URL-way”或“REST-type-URL”之类的东西。我认为您完全误解了 REST 的含义。

标签: xml orm rest crud


【解决方案1】:

是的,它会起作用。但是,您的分布式系统设计基于数据模型非常简单并将保持这种方式的假设。如果您正在构建的应用程序成功,您可以确定会添加新的需求并请求新的功能。

按照您的建议公开数据层,将您的客户端应用程序与数据模型紧密耦合,并且您对 http 的使用使得执行多请求事务变得非常困难。我知道你说过你不需要做多请求事务。不是今天,可能是明年?

此应用程序的预期寿命是多少?如果您说超过几年,那么我会重新考虑将数据层暴露给远程客户端的想法。 REST 的主要目标之一是将客户端和服务器应用程序解耦,以允许应用程序在很长一段时间内发展。如果您有多个客户端应用程序访问一个设计不正确的分布式服务,它可能会很快遇到令人讨厌的维护和版本控制问题。

编辑以回答 cmets 中有关客户需要了解模型的问题:

关于客户端如何与从服务器接收到的表示进行交互,您可以采取两个不同的方向。

  1. 您可以允许客户端明确了解表示中包含的数据内容。 IE。客户端知道某些 XML 元素中存在用户名和密码。但是,如果你这样做,你应该返回一个特定的媒体类型,例如应用程序/vnd.mycompany.user+xml。您不应使用 application/xml,因为它不会告诉客户端有关 XML 文档中的内容的任何信息。如果客户端知道“当您转到 url X 时”您会得到“一个包含元素 User 内的 UserName 和 Password 元素的 Xml 文档”,那么您就违反了 REST 的自描述约束。影响是您已将端点耦合到媒体类型,并且实际上将客户端耦合到该端点。 REST 的“超媒体约束”的目的是防止客户端和端点之间的耦合。
  2. 另一种方法是使用更通用的媒体类型,它只是旨在为客户端提供要显示给用户的内容,并向用户提供选项以允许客户端采取行动。 html 媒体类型允许您通过提供可用于在两个 div 标签中返回用户名和密码的标记语言来做到这一点。使用 html FORM 标签和 A 标签,客户端可以对该资源执行额外的操作。弄清楚如何以真正的 RESTful 方式使“用户”对象可能具有的所有可能操作可访问,这很棘手,需要相当多的经验,但最终结果是客户端和服务器的解耦非常好。以网络浏览器为例,您需要多久更新一次浏览器,因为网站更改了其内容。

第二个选项的问题在于,仅使用 HTML 最终用户体验往往会受到很大限制,这就是 Javascript 的用武之地。“可选”REST 限制之一是代码下载的使用。 Javascript 是从服务器加载的代码,用于在客户端启用其他行为。不幸的是,在我看来,它还为人们提供了创建返回 application/xml 的 RESTful Web 界面然后使用 javascript 来解释该通用格式的能力。该解决方案适用于使用 RESTful API 的网站的原始开发人员,因为如果 xml 文件的内容发生更改,则可以更改 javascript 并将其重新下载到浏览器,一切都很好。但是,对于访问此 API 且无法控制应用程序/xml 内容模型的任何其他第三方开发人员,他们的代码将变得非常脆弱,并且如果 API 内容更改,则可能会中断。询问任何为 Twitter 编写过任何类型客户端的人,他们的应用程序因 Twitter 更改内容而崩溃了多少次。

通过使用第一个选项并为内容提供特定的媒体类型,服务器开发人员可以引入一种名为 application/vnd.mycompany.userV2+xml 的新媒体类型,并且使用内容协商,现有客户端仍然可以接收原始媒体可以构建新的客户端来使用新的媒体类型。 url 保持不变,书签没有损坏,因为端点和媒体类型没有耦合。

如果您看到提供 URL 列表和从这些 url 返回的内容的 API 文档,那么这些开发人员很可能没有获得 REST,也不会获得 RESTful 接口提供的好处。但具有讽刺意味的是,受害最大的并不是那些开发人员,而是尝试与 API 交互的第 3 方!

【讨论】:

  • 我了解有关未来需求的要点,因此将不得不重新考虑事务等。但是关于从客户端解耦数据 - 客户端需要访问模型 - 例如,用户记录由用户名、用户名、密码组成。表示用户 object 的 XML 片段(不是作为 XML 的实际数据库记录)将 必须 可供客户端访问,对吗?
  • 非常感谢您花时间解释,真的很有帮助!
【解决方案2】:

如果您想从多个客户端访问 CRUD 功能,这是一个好主意。一段时间以来,我们一直在做这样的事情。一些可能对您有所帮助的实现细节。

  1. 简单的 HTTP 调用就足够了,不要打扰 REST。要成为 RESTful,您必须遵循诸如(GET 用于读取,PUT 用于创建等)之类的规则。只需使用 GET 即可在浏览器中轻松测试。我们使用 XSLT 将响应格式化为 HTML 表格。

  2. 我们使用一种 XML 模式来处理所有响应。它基本上是 SQL 结果的 XML 表示,它应该足够灵活以处理多个结果集、受影响的行、错误响应、返回代码等。

  3. 拥有 XML 的 JSON 表示形式,以便在 Javascript 中更容易处理。

  4. 我们还添加了一个 SQL 后门,因此可以将任意 SQL 语句发送到数据库。这对于调试非常方便。这种呼叫需要一些安全性。我们只将它暴露给办公网络。

【讨论】:

  • REST 与 GET for READ 等无关。这只是正确的 HTTP 用法。
  • @wahnfrieden 这就是为什么我尽量避免使用 REST 术语,因为很多人将它与正确的 HTTP 动词用法联系起来。见rgoarchitects.com/nblog/2009/06/23/CRUDIsBadForREST.aspx
  • @Zhihong 我很困惑-您似乎在回答中自己犯了那个错误。另外,我不同意那篇文章——我认为 REST 可以适用于 CRUD。没错,很多人错误地认为这就是它的全部好处,或者 CRUD 是 REST 的约束。
【解决方案3】:

对于纯数据层,您是否考虑过事务支持?

  • 您需要支持事务吗?如果是这样,它们将如何实施?
  • 事务是否会跨越多个 HTTP 请求? (我认为对于纯 REST 实现,您将多次调用非平凡的操作。)例如借记一个帐户并贷记另一个帐户。
  • 谁来控制交易?

如果现在不需要事务控制,您是否认为将来需要它?这将如何影响您的设计?

问题多于答案。 :) 但值得深思。

更新:

我将使用您选择的语言(在您的情况下为 Java)和您需要的任何其他库(例如 ORM)创建标准数据访问层。如果您已经有数据访问层设计,我会遵循它以保持应用程序简单。如果您想在外部(对各种客户端)公开它,我会在我称之为服务/业务层的地方执行此操作(如果功能很简单,没有重用的潜力,那么将两者折叠到一个实现可能是可以的)。在那里,您将处理任何安全性(身份验证、授权等)、数据验证,并可能在内部数据表示和外部表示之间执行任何映射。然后,您可以根据基于 URL 的 API 公开您的服务。这使您在实际数据访问实现和接口之间有了一些分离。

也许我们谈论的是同一件事,但我们的语义不同。

【讨论】:

  • 好问题 - 将使用数据库层 (ORM) 的事务,但发送到 URL 的每个请求都将是一个“事务” - 它不会跨越多个 HTTP 请求。这将是一个简单的 CRUD 应用程序,例如,存储用户信息、收藏链接等,而不对“事实类型”数据进行操作。它实际上只是存储应用程序的其他部分用来执行工作的用户、权限、规则、策略等内容。
  • 应用程序的其他部分会使用 CRUD 层吗?还是其他设计?如果您已经有了设计,那么重复使用它而不是新的 CRUD 层是否有意义?
  • 应用程序的其他部分将使用CRUD层;它已经有 CRUD,但是以一种非常糟糕的方式实现(作为 C++ 对象,一些加载列表并从列表中返回请求;其他人直接为每个请求查询表等)并且因为这个产品是随着业务的增长,我们需要一种更好的方式来管理 CRUD。
【解决方案4】:

如果您正在寻找 Java 解决方案,我建议您查看 Restlets。 您几乎混合了 XML-RPC 和 REST 风格的架构。 Here 是 RPC 和 REST 的区别。
如果您想以 RESTful 方式执行,则应使用 URI 来确定操作和参数,而不是传递 XML。

【讨论】:

  • 是的,我将使用 RESTful 方式的 URL,很抱歉造成混淆。让我更新一下我的问题。
  • 但是您说所有的通信都将使用 XML。 “所有通信都是通过描述要采取的行动的 XML 片段进行的。” - 从你的问题。在 RESTful 架构中,URI 只是一种资源。返回的数据可以是 XML,但请求本身不是 XML。如果请求本身是 XML,那么它是 RPC 而不是 REST。
  • 我没有正确解释自己,抱歉。
  • 无需道歉。现在你知道区别了。你在正确的轨道上。
  • REST 接口是客户端应用程序随行的 Internet 媒体类型的超链接 Web。要意识到的关键是媒体类型本身定义了哪些链接存在并且可以被遍历。用于遍历链接的 url 与客户端有些无关。
猜你喜欢
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 2020-05-09
  • 1970-01-01
  • 2010-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多