【问题标题】:Deploy webapp in jetty in OSGI在 OSGI 的 jetty 中部署 webapp
【发布时间】:2023-07-11 01:18:01
【问题描述】:

在发布这个问题之前我已经搜索了很长时间,但没有找到令人满意的答案,作为前提我想说我宁愿不使用框架来完成以下任务,我唯一拥有的工具是 Felix、Jetty 和一个 Web 应用程序。

我有一个用 maven 管理的 webapp,我将它部署在 OSGI 环境之外的码头中,但现在我也想在 OSGI 中部署它,所以我正面临着典型的 OSGI 问题和原则,这里遵循我的理解,如果我错了,请告诉我:

  • 我可以离开 maven“战争”包装

  • 使用 apache.felix maven-bundle-plugin 创建 OSGI MANIFEST

  • 在 OSGI 中,应该在任何“webapp bundle”之前启动 jetty-bundle

  • webapp 包会有它的 WEB-INF/classes,但是,真正的 OSGI 风格,它不会有任何 WEB-INF/lib,因为它会发现它的依赖项是 OSGI 在别处捆绑

    如果你想添加元素,我感谢你,不幸的是,我发现只有文章可以快速转换捆绑包中的标准战争,但我真的对 OSGI 原则方面的工作很感兴趣,所以我更愿意遵守尽可能

【问题讨论】:

    标签: osgi apache-felix equinox


    【解决方案1】:

    首先,回答您更高级别的 OSGi 问题:

    • 我可以离开 maven“战争”包装

    是的,但这意味着您正在生成一个 WAR 文件,其中包含以下所有规则。因此,您最终可能会在某个时候与maven-war-plugin 抗争。

    • 使用 apache.felix maven-bundle-plugin 创建 OSGI MANIFEST

    我更喜欢使用bnd-maven-plugin,但两者都使用相同的库(bnd)。生成 OSGi 清单(而不是手动编写)是迈向成功的非常重要的一步。

    • 在 OSGI 中,应该在任何“webapp bundle”之前启动 jetty-bundle

    在编写良好的 OSGi 系统中,绝对没有启动顺序限制。在 Jetty 启动之前,您的 Web 应用程序将不可用,但哪个包先启动并不重要。

    webapp bundle 会有它的 WEB-INF/classes,但是,真正的 OSGI 风格,它不会有任何 WEB-INF/lib,因为它会在其他地方找到它的依赖作为 OSGI 包

    这取决于你。显然,要保持有效的 WAR 文件,类必须位于 WEB-INF/classes 中。 OSGi 可以解决这个问题(尽管您需要设置Bundle-Classpath),但这不是必需的。如果您想将它们放在/ 中,请继续。 OSGi 也支持嵌入式 JAR,但同样不是必需的。使用/ 作为类路径并使用Import-Package 引用库是OSGi 更惯用的用法。

    OSGi 中的 Servlet

    有一个支持 Web 应用程序的 OSGi 规范。它被称为 Web 应用程序规范,它是 OSGi 纲要规范的第 128 章。这是您可以从 OSGi 容器内部发布 servlet 的方法之一。然而,在 OSGi 中还有其他使用 Servlet 的方法。

    如果您只想使用 WAR 文件完成所有操作,请跳过,因为我将告诉您一个替代方案,您可能会发现它更容易/更好。

    如何在 OSGi 中部署 Servlet

    在 OSGi 中部署 servlet 的最佳和最简单的方法是使用 Http Whiteboard(OSGi 纲要第 140 章)。注册一个 servlet 非常简单,您只需将它发布为一个 OSGi 服务并使用它应该匹配的模式。例如,使用声明式服务时:

    @Component(property="osgi.http.whiteboard.servlet.pattern=/foo")
    public class MyServlet extends HttpServlet implements Servlet {
        ...
    }
    

    您还可以注册过滤器、侦听器和各种其他东西。像这样使用声明式服务可以通过注入其他 OSGi 包提供的服务来轻松地与它们进行交互。

    Apache Felix Http 服务很好,易于使用,该规范基于 Jetty 实现。

    如何部署 Web 应用程序包

    如果您真的想部署为 Web 应用程序包,那么需要注意一些事项。

    根据原始提交者的要求进行编辑

    1. 所有 servlet 的生命周期与 bundle 的生命周期完全相同,因此很难正确使用 OSGi 服务。在 Web 应用程序包中,如果 servlet 所依赖的服务丢失或不可用,您将无法限制其可见性。这可能会导致您依赖捆绑启动顺序,这很糟糕!
    2. 您必须在您的 OSGi 清单中设置额外的元数据,以确保 OSGi 可以处理 WAR 布局,并识别您的包进行处理。
      • Bundle-ClassPath:WEB-INF/classes[, WEB-INF/lib/foo.jar]
      • Web 上下文路径:
    3. Jetty 不是(据我所知)OSGi Web 应用程序规范的实现。您将需要一个实现(可以在 Jetty 上运行),例如 PAX-Web。
    4. OSGi Web 应用程序规范只定义了对 Servlet 2.5 的支持(任何更高的版本都是实现增值)。
    5. 许多人将 Web 应用程序包视为迁移路径,而不是最终目标。具有特殊的内部布局 (WEB-INF/classes) 并且通常遵循“胖 jar”模型意味着 Web 应用程序包通常具有有限的模块化,并且很难与其他工具一起使用。此外,它们无法与 OSGi 服务进行良好交互(参见第 1 点),这使得它们比诸如 OSGi Http 服务白板等模块化模式更难编写/维护。这意味着一些人(包括我自己)将 Web 应用程序包视为迁移到 OSGi 的“第一步”,最终使用 Http 服务白板。

    根据您的 Maven 构建的设置方式,您可能会发现有必要对 bnd 使用 -wab 指令。这让 bnd 将您的课程放入 WEB-INF/classes 并设置 Bundle-ClassPath

    【讨论】:

    • 真的很感谢@Tim,我可以请你用不同的词更好地解释我上一章的第四点吗?
    最近更新 更多