3

Jetty8.1.1サーバーが組み込まれたOSGiアプリケーションがあります。

アプリケーションをモノリット(OSGi環境なし)として実行すると、org.eclipse.jetty.servlet.ServletContextHandler.addServlet(String className, String mapping)メソッドを呼び出すことでサーブレットを正常に登録できます。だから今、私はOSGi環境で同じことをしようとしています。

目標は、servlet-extender起動時に他のバンドルによって提供されるサーブレットを登録するバンドル()を作成することです(エクステンダーパターン)。したがって、私のアプリケーションが起動した後、(とりわけ)実行されている必須のバンドルは2つだけです:jettyservlet-extender

書き込みの最初の試みservlet-extender

MANIFEST.MF最初に、サーブレットを提供するバンドルのファイルで、マッピングを使用してサーブレットを宣言することにしました。そのようなバンドルが開始されると、サーブレットマッピング宣言をservlet-extender検索します。MANIFEST.MFサーブレットマッピング宣言が見つかった場合はservlet-extender、前述のServletContextHandler.addServlet(...)メソッドを呼び出して実際にサーブレットを登録します。

アイデアは問題ないように見えましたが、クラスの読み込みに問題があります。実際、Jettyはを呼び出しますClass.forName("org.my.servlets.MyServletClass").newInstance()。バンドルはパッケージをインポートしませんが、呼び出しはjettyで失敗します。org.my.servletsClass.forName("org.my.servlets.MyServletClass")ClassNotFoundException

2回目の書き込みの試みservlet-extender

OSGiでのクラスのロードに関連するいくつかの記事を検索しました。これは、いくつかのOSGiサービスを介してロードされたサーブレットクラスを提供することにより、以前の問題を解決できるという希望を私に与えました。そこで、メソッドServletProviderを使用してサービスを作成しましたMap<Class<? extends Servlet>, String> getServlets()(メソッドは、コンテキストにマップされたサーブレットクラスを返すだけです)。次にservlet-extender、でサーブレットマッピングを検索しないように変更しましたMANIFEST.MFServletProviderバンドルが実装を登録するまで待つようになりました。そのようなサービスがOSGiサービスレジストリに登録されている場合servlet-extenderは、そのメソッドを呼び出して、getServlets()返されたサーブレットクラスをに登録しようとしますjettyjetty今は呼び出す必要はありませんが、サーブレットをインスタンス化Class.forName("org.my.servlets.MyServletClass")するために呼び出す必要があります。servletClass.newInstance()そして残念ながらそれはまだ失敗しますClassNotFoundException

バンドルがパッケージjettyをインポートする場合、これは解決できることを理解しています。ただし、バンドルがサードパーティによって提供されてorg.my.servletsいる間はこれは不可能であり、その宣言を変更することはできません。jettyImport-Package

任意のバンドルによって提供されるサーブレットを動的に登録するにはどうすればよいですか?

PS:Jettyの8.1.1 WebSocketServletを使用する必要があるため、「OSGiHttpService」を使用できません。

4

3 に答える 3

2

Q:サーブレットを宣言的に登録する方法については、まだ興味があります。サーブレットクラス名を使用します。出来ますか?

A:はい:)

最初に考えられる解決策:桟橋マニフェストの変更が許可されている場合は、マニフェストに「DynamicImport-Package:*」を追加できます。これにより、カスタム組織に依存せずに、任意のクラスをロードできるようになります。 .my.servletsパッケージ。もちろん、これはOSGiにとって一般的に悪い習慣であることに注意してください。

2番目に考えられる解決策:突堤はそのままです。最初の試行と同様に、マニフェストに宣言的にサーブレットを含むサーブレットバンドルリスト。ここで重要なのはサーブレットエクステンダーです。サーブレットを作成し、サーブレットに登録します。このクラスローディングの問題全体について重要なことは、サーブレットオブジェクトの作成は、クラスローダー(この場合はサーブレットエクステンダーのクラスローダー)がサーブレットのクラスにアクセスできる場所で実行する必要があるということです。 MFを変更できないため、これは突堤では発生しません。ただし、サーブレットエクステンダーのMFを完全に制御できますよね?

org.my.servletsをインポートすることもできます(将来どのサーブレットをインストールする必要があるかを予測できないため、お勧めしません)。

または、MFで「DynamicImport-Package:*」を使用します(一般的には推奨されない方法です;))

または(推奨)エクステンダーは、サーブレットjarのクラスローダーを使用してサーブレットjarからクラスをロードします-Bundle loadClass()メソッドを使用します(org.osgi.framework.Bundleを参照)。これにより、クラスが正しくロードされます。これはセキュリティ制限の対象となる可能性があることに注意してください。

于 2012-05-30T10:09:41.983 に答える
1

これを自分で行う必要はありません。まさにこの機能を提供するpax-webがすでにあります。http://team.ops4j.org/wiki/display/paxweb/Pax+Webを参照してください

PaxWebはApacheKarafでも利用できます。そこで、feature:installhttp-whiteboardを使用してインストールできます。

あなたがそれを自分でやりたいのなら、あなたはpaxwebのコードを見ることができます。そこでの概念は、サーブレットをOSGiサービスとして登録するだけです。サービスプロパティを使用すると、登録するhttpパスなどのパラメータを指定できます。

于 2012-05-27T12:03:44.677 に答える
0

ServletContextHandler最近、Jettyの8.1.1にメソッドがあることに気づきましたaddServlet(ServletHolder, String)。前述のservlet-extenderように変更して、次のようにサーブレットを登録するようにしました。

 public void servletProviderRegistered(ServletProvider servletProvider) {
     Map<? extends HttpServlet, String> servlets = servletProvider.getServlets();
     for (Entry<? extends HttpServlet, String> entry : servlets.entrySet()) {
         HttpServlet servletInstance = entry.getKey();
         String mapping mapping = entry.getValue();
         ServletHolder servletHolder = new ServletHolder(servletInstance);
         servletContextHandler.addServlet(servletHolder, mapping);
     }
 }

このアプローチを使用すると、Jettyは呼び出す必要がないClass.forName("org.my.servlets.MyServletClass").newInstance()ので、今は取得できませんClassNotFoundException

これは私の問題の解決策であるため、サーブレットを宣言的に登録する方法についてはまだ興味があります。サーブレットクラス名を使用します出来ますか?

于 2012-05-28T12:57:46.497 に答える