在分层体系结构中,应用层如何了解 Web URL?



我目前正在开发使用分层体系结构(Web/应用程序/基础结构/域)的.NET 5应用程序。如果我要遵循洋葱/干净的架构模式,依赖项应该只向一个方向流动,例如:

Web -> 应用程序 ->基础结构 ->

域我现在发现自己需要从应用程序层发送几封包含特定前端 URL 的电子邮件。这意味着应用程序层将了解 Web 层,从而中断依赖流。

示例用例流程为:

  1. 用户发出请求,由 Web 层中的控制器处理
  2. 控制器调用应用程序层上的处理程序
  3. 应用程序层使用基础结构层的电子邮件服务发送电子邮件

在步骤#3中,我在应用程序层,但需要Web URL来构造电子邮件正文。

如何解决此问题?

我最近在我的组织内解决了这个问题。在我们的例子中,我们有一个由整个公司使用的API"市场",然后是一个紧密集成的客户端使用的反向代理,最后是API容器的内部负载均衡器。

这是我的 Web 层和应用程序层不应该知道的 3 层 URL 知识(即使在 Web 层也不应该知道这一点,因为这会使我们的 Web 层承担不止一个责任,而不仅仅是一个路由器(例如通过 Mediatr))。

在基础结构中使用重写器

这就是Z. Danev的答案。这有效,但您必须维护每个层的所有规则,并且每个重写都可能增加开销。此外,这些规则可能会变得棘手,具体取决于您返回的数据的复杂性。

不过,这是一个有效的解决方案。根据您的组织,这可能是一件容易的事情,也可能是一件困难的事情,因为它由其他团队维护,需要工作票证等等才能完成工作。

好吧,如果你不能或不想这样做,那么...

应用层依赖反转和模式

免责声明:此解决方案非常适合我们,但它确实有一个缺点:在某种程度上,您必须维护了解上述层的内容。所以警告空洞。

我上面描述的情况与您的问题大致相似,尽管可能更复杂(您可以做同样的事情,但简化它)。在不违反体系结构原则的情况下,您需要提供一个接口(或多个接口),该接口可以作为应用程序服务注入到应用程序层中。

我们调用了我们的ILinkBuilderService,并创建了一个LinkBuilderService,该本身可以通过具有单个ILinkBuilder实现的 DI 容器进行连接。这些实现中的每一个都可以是MarketPlaceBuilderGatewayBuilder等,并将根据从最外层代理到最内层的责任链和策略模式进行排列。

通过这种方式,构建器检查 Web 上下文(标头、请求等),以确定哪个应该处理构建链接的责任。您的应用程序层(例如您的电子邮件发件人)只需使用关键数据调用链接构建服务接口,这用于生成面向客户端的 URL,而无需将应用程序层暴露给 Web 上下文。

在不涉及太多细节的情况下,这些构建器会在 HTTP 请求到达每个端点时检查 X-Forwarded-For、自定义标头以及代理提供的其他详细信息。责任链是关键,因为它允许应用程序层生成正确的URL,无论请求来自哪个层

那么,这如何不打破单向流动呢?

好吧,您将这些构建器单向推送到您的应用程序层。从技术上讲,它们确实会回到 Web 层以获取上下文,但这是封装的。这没关系,不会违反您的架构。这就是依赖反转的全部意义所在。

请考虑在 Web 基础结构级别(例如网关或负载均衡器)配置"已知 URL",以便在电子邮件中包含"mycompany.com/user-action-1",这将转换为 Web 应用的正确终结点。

最新更新