OSGi中使用后台运行的REST Web服务的网站

时间:2015-12-14 16:14:39

标签: java web jetty osgi restlet

我花了几天时间试图找出如何在OSGi中添加网站。

我使用Jetty扩展程序运行Restlet Web服务以使用Jetty作为连接器。此功能在多个URL下提供不同的资源。

但我还希望在系统上运行一个可供用户访问的小型网站。我想使用一些HTML,Javascript,CSS并提供一些图形和图片的当前数据状态。

我假设Jetty在后台运行,我可以在Jetty上部署这个网站,也可以在Javascript中调用Restlet提供的服务器资源。

除了restlet服务之外,显然没有任何效果。

我的问题是是否可以添加WAB捆绑包并期望它可以工作(因为Jetty在后台运行)?或者有没有更好的方法在OSGi中添加网站? 要么 我现在唯一的选择是,因为可以返回一个HTML表单作为表示,在HTML表单中添加我的所有javascript代码并将其作为对GET请求的响应发送(我相信这是一个烂摊子)。

所有东西都将在Raspberry pi中运行,因此我只能拥有非常小的空间。我正在使用Equinox,Restlet 2.3.0和Jetty 9.2.6。

我真的很感激,如果有人知道一个链接,我可以获得至少在OSGi中运行的示例页面的信息。我尝试过很多没有运气的事。

3 个答案:

答案 0 :(得分:2)

我建议你看看它是如何在Apache Karaf(https://github.com/apache/karaf)中完成的。有关Apache Karaf和WebContainers的更多信息,请访问:http://karaf.apache.org/manual/latest/users-guide/webcontainer.html

答案 1 :(得分:0)

事实上,Jetty通过其连接器功能在内部由Restlet使用。这样,动态注册应用程序是不方便的(而不是正确的方法)。

那就是说,Restlet非常灵活和动态。这意味着您可以以与WAB包类似的方式动态处理包含Restlet应用程序的包,即将它们附加到组件的虚拟主机。

以下是实现此目的的方法:

  • 创建一个捆绑包,使Restlet组件可用于OSGi容器。您应该利用FrameworkListener侦听器将所有连接器,转换器等都注册到Restlet引擎中:

    private Component component;
    
    public void start(BundleContext bundleContext) throws Exception {
        bundleContext.addFrameworkListener(new FrameworkListener() {
            component = new Component();
            (...)
            component.start();
        });
    }
    
    public void stop(BundleContext bundleContext) throws Exception {
        component.stop();
    }
    
  • 启动组件后,您可以查找容器中包含的包含Restlet应用程序的包。对于此类的每个捆绑包,您可以注册一个专用的OSGi服务,该服务使您要为组件注册的内部Restlet应用程序可用。

    ServiceReference[] restletAppRefs = bundleContext.getServiceReferences(
         "restletApplication",
                    null);
    
    if (restletAppsRefs != null) {
        for (ServiceReference restletAppRef : restletAppsRefs) {
            RestletApplicationService descriptor
                 = (RestletApplicationService) bundleContext
                   .getService(serviceReference);
            String path = descriptor.getPath();
            Application restletApplication = descriptor.getApplication();
    
            // Register the application against the component
            (...)
        }
    }
    

    根据组件注册应用程序

    try {
        VirtualHost virtualHost = getExistingVirtualHost(
                       component, hostDomain, hostPort);
        if (virtualHost == null) {
            virtualHost = new VirtualHost();
            virtualHost.setHostDomain(hostDomain);
            virtualHost.setHostPort(hostPort);
    
            component.getHosts().add(virtualHost);
        }
    
        Context context = component.getContext().createChildContext();
        virtualHost.setContext(context);
    
        virtualHost.attachDefault(application);
    
        component.updateHosts();
    
        application.start();
    } catch(Exception ex) {
        (...)
    }
    
  • 您还需要考虑OSGi的动态。我的意思是捆绑包可以在OSGi容器本身启动之后来去。你可以利用

    bundleContext.addServiceListener(new ServiceListener() {
        public void serviceChanged(ServiceEvent event) {
            if (isServiceClass(event, RestletApplicationService)) {
                int type = event.getType();
    
                if (type == ServiceEvent.REGISTERED) {
                    // Register the Restlet application against the component
                } else if (type == ServiceEvent.UNREGISTERING) {
                    // Unregister the Restlet application
                }
            }
        }
    });
    

希望它可以帮到你, 亨利

答案 2 :(得分:0)

有很多选择 - OSGi并没有对你能做的事情施加很多限制。如果你想使用OSGi的功能,那么这里有几个想法:

  • 一种选择是部署WAB。您需要确保您的框架具有必要的OSGi服务。仅仅因为某些捆绑包在内部使用Jetty,它并不遵循必要的OSGi服务正在运行。

bundle org.apache.felix.http.jetty确实提供了部署WAB所需的服务。 2.2.2版本在磁盘上为1.3MB,并嵌入了自己的Jetty副本。其他实现是可用的(例如Pax-Web,在Karaf中使用 - 也嵌入Jetty)

  • 另一种选择是直接使用OSGi Http服务(同样,您需要包含一个实现此服务的捆绑包(如提到的Felix)。对org.osgi.service.http.HttpService.registerResources()的调用将提供静态服务来自您的捆绑包中的内容。

如果这个额外的足迹是一个真正的问题,那么你可能想看看如何让Restlet使用OSGi http服务,而不是通过嵌入式Jetty提供它自己。

另一个选择是以Jetty为中心的观点。 Restlet的嵌入式Jetty可能未配置为从磁盘提供任意内容。您可以查看重新配置嵌入式Jetty来执行此操作,或者考虑将Restlet部署到“标准”中。 Jetty安装。我个人尝试后者。