【问题标题】:Where should I wrap my REST Response, the controller or the service?我应该在哪里包装我的 REST 响应、控制器或服务?
【发布时间】:2014-03-21 22:20:18
【问题描述】:

我正在 Spring MVC 中构建一个具有控制器层和服务层的 Web 应用程序。我的响应被包装在一个自定义包装器中,其中包括有效负载和关于调用结果的元数据(有效负载是否成功,仅包括部分数据等),以便我可以返回 HTTP 200 并让元数据向客户端描述调用的结果。

最初我将响应包装在被调用的服务中,并让控制器传递响应。但是,当我需要从其他服务调用我的服务时,这种模式效果不佳,因为我必须首先解包数据,对其进行一些处理,然后再次将其打包并将其发送回控制器。因此,我开始在控制器中构建响应。

问题是我想让我的控制器尽可能小,以便它们作为 url 到服务的映射清晰易读。

控制器是构建 REST 响应包装器的合适位置,还是应该将其留给服务?

【问题讨论】:

    标签: spring rest spring-mvc wrapper


    【解决方案1】:

    通过将与 HTTP 相关的部分放入控制器中,您将获得更好的关注点分离。这就是我实现 Spring Web 服务的方式,它对我来说效果很好。根据我的经验,当这些分离到位时,重构服务变得非常容易。

    您提到您希望控制器尽可能小。控制器往往非常简单,而服务代码往往更复杂。因此,您可能会发现您的服务代码更易于维护,而只需在控制器中拥有更多代码就可以了。复杂度分布更均匀。

    以下是将与 HTTP 相关的代码放入控制器的其他一些方法。

    • 异常处理 - 您可能不想通过在返回的对象中放置特殊标志来处理错误,但这就是 HTTP 的工作方式。 Spring MVC 通过@ExceptionHandler 注解提供了一个很好的机制,用于在失败时返回 HTTP 错误。这种分离带来了难以置信的好处。

    • HTTP 标头 - 有时响应对象的一部分比响应 JSON 的一部分更适合作为 HTTP 标头。您的内部客户端在 POJO 上进行操作要比知道他们必须从 HTTP 标头中提取一些信息要容易得多。

    • 返回列表 - 有时 API 应该只返回一个列表。但是,作为一项规则,我从不从 HTTP 服务返回 JSON 数组作为根 JSON 对象。如果您需要返回的不仅仅是一个列表,那么重构内部代码比创建新 URL 或破坏现有客户端要容易得多。您可以在控制器级别将列表包装在 JSON 对象中。

    • Spring 解耦 - 我们的服务不依赖于 Spring 框架。一个常见的例外是 RestTemplate,它不是 Spring MVC 的一部分。如果我们愿意,我们的 代码 可以很容易地转换到另一个 Web 框架。 (并不是说不会有其他大的变化,比如我们的应用程序上下文)。

    我只遇到过一种情况,我不得不进一步模糊这些界限。那是我需要区分200(OK)和201(Created)的时候。控制器代码经常调用一个服务方法,否则它不会返回任何东西(它只会在失败时抛出异常)。我不得不向这些添加返回值以区分更新和创建。它不会使内部客户端代码更复杂,因为调用者可以忽略返回值。但是只为控制器提供返回对象似乎不太理想。

    【讨论】:

      【解决方案2】:

      控制器是构建 REST 响应包装器的合适位置,还是应该将其留给服务?

      是的,这就是具有不同层次的意义:分离出不同的关注点。 控制器只是服务层的一个 - 尽管大多数时候是唯一的 - 消费者。无论消费者如何处理其数据,服务都必须不知道。想想Meta-Services 消费和处理多个服务的数据。如果这些服务将接收打包的数据,他们将不得不解包数据才能处理。这是糟糕设计的标志。

      控制器(在 Spring @Controller 下)是 Web 世界的接口。这是以您想要的任何格式包装数据的正确位置:它通过网络传输,因此它必须以一种或另一种方式包装。消费者期望包装数据。

      所以你有控制器,它启动检索并包装检索数据的结果和服务:关注点的明确分离。

      【讨论】:

        【解决方案3】:

        考虑以下情况:假设您的数据的一些新外部消费者需要与您在 REST 控制器中返回的完全相同的数据(假设您返回的是 JSON),但只能处理 XML。 你更愿意做什么?编写一个新的服务层,如果您当前的服务层返回 JSON,则返回 XML,或者只编写一个新的控制器方法,从通用服务层返回 XML?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-22
          相关资源
          最近更新 更多