我有一个带有嵌入式 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(). 虽然jettybundle 不导入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。但这是不可能的,因为jettybundle 是由 3rd 方提供的,我不能修改它的Import-Package声明。
如何动态注册任意bundle提供的servlet?
PS:我不能使用“OSGi Http Service”,因为我必须使用 Jetty 的 8.1.1 WebSocketServlet。