我有一个带有嵌入式 Jetty 8.1.1 服务器的 OSGi 应用程序。
当我将我的应用程序作为单体运行(无 OSGi 环境)时,我可以通过调用org.eclipse.jetty.servlet.ServletContextHandler.addServlet(String className, String mapping)
方法成功注册 servlet。所以现在我正在尝试在 OSGi 环境中做同样的事情。
目标是编写一个 bundle ( servlet-extender
),它会在其他 bundle 启动时注册它们提供的 servlet(扩展模式)。因此,在我的应用程序启动后,(除其他外)只有两个基本包在运行:jetty
和servlet-extender
.
第一次尝试写servlet-extender
:
首先,我决定在MANIFEST.MF
提供 servlet 的包的文件中声明 servlet 及其映射。如果启动了这样的包,则servlet-extender
搜索它MANIFEST.MF
的 servlet 映射声明。如果找到任何 servlet 映射声明,则servlet-extender
调用上述ServletContextHandler.addServlet(...)
方法来实际注册 servlet。
虽然这个想法看起来不错,但类加载存在问题。事实上 Jetty 调用Class.forName("org.my.servlets.MyServletClass").newInstance()
. 虽然jetty
bundle 不导入org.my.servlets
包,但调用Class.forName("org.my.servlets.MyServletClass")
失败并显示ClassNotFoundException
.
第二次尝试写servlet-extender
:
我搜索了一些与 OSGi 中的类加载相关的文章。这给了我一个希望,我可以通过一些 OSGi 服务提供加载的 servlet 类来解决前面的问题。所以我ServletProvider
用方法创建了服务Map<Class<? extends Servlet>, String> getServlets()
(该方法只返回映射到某个上下文的 servlet 类)。然后我进行了修改servlet-extender
,使其不在MANIFEST.MF
. 它现在宁愿等到一些捆绑注册ServletProvider
实现。如果此类服务已在 OSGi 服务注册表中注册,则servlet-extender
调用其getServlets()
方法并尝试将返回的 servlet 类注册到jetty
. 虽然jetty
现在不需要调用Class.forName("org.my.servlets.MyServletClass")
它仍然必须调用servletClass.newInstance()
来实例化 servlet。不幸的是,它仍然失败了ClassNotFoundException
.
jetty
我知道如果捆绑包会导入包,这可以解决org.my.servlets
。但这是不可能的,因为jetty
bundle 是由 3rd 方提供的,我不能修改它的Import-Package
声明。
如何动态注册任意bundle提供的servlet?
PS:我不能使用“OSGi Http Service”,因为我必须使用 Jetty 的 8.1.1 WebSocketServlet。