1

Web サービス アプリケーションを Tomcat 6 (JDK 1.5 を使用) から Tomcat 7 (JDK 1.6 を使用) に移行する必要があります (実際には 7.0.27 でテストしています)。JAX-WS フレームワークは Metro 2.1 です。

私は 2 つの ServletContextListeners を使用しています。

  1. "WebAppListener" : アプリケーションを初期化します (構成、データベース接続のセットアップ...)。

  2. 「com.sun.xml.ws.transport.http.servlet.WSServletContextListener」: Web サービスを作成する Metro リスナー。

@PostConstruct メソッドが Web サービスで呼び出される前に、Web アプリを完全に初期化する必要があるため、順序は重要です。

Tomcat 6 では、これは見事に機能します。

INFO: Starting Servlet Engine: Apache Tomcat/6.0.36
mars 16, 2013 5:13:13 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive WSWebApp.war
************************ IN WebAppListener.contextInitialized ***********************
************************ IN WSMyWebService.postConstruct ****************************

ただし、Tomcat 7 でのまったく同じ戦争:

mars 16, 2013 6:45:24 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive C:\home\tomcat\webapps\WSWebApp.war
************************ IN WSMyWebService.postConstruct ****************************
************************ IN WebAppListener.contextInitialized ***********************

リスナーが呼び出される順序は、web.xml に表示される順序だと思いましたか?

Tomcat 7 でこの順序が変更されたのはなぜですか? しかし、もっと重要なことは、「Tomcat6」の注文を元に戻すにはどうすればよいですか?

ありがとう。

4

2 に答える 2

3

その答えは、サーブレット スペック 2.5 とサーブレット スペック 3.0 の違いにあります。

サーブレット仕様 2.5では、リスナーが呼び出される順序は、デプロイメント記述子 (web.xml) での宣言の順序によって定義されます。

SRV.10.3.3 リスナー登録。
Web コンテナーは、各リスナー クラスのインスタンスを作成し、アプリケーションによる最初の要求の処理の前にイベント通知用に登録します。Web コンテナーは、リスナー インスタンスが実装するインターフェースと、デプロイメント記述子に現れる順序に従って、リスナー インスタンスを登録します。Web アプリケーションの実行中、リスナーは登録順に呼び出されます。

サーブレット仕様 3.0では、リスナーが呼び出される順序は、デプロイメント記述子 (web.xml)の要素<absolute-ordering>によって定義されます。

8.2.3 web.xml、webfragment.xml、および注釈から記述子を組み立てます。
...
c。この仕様のリリースより前は、コンテキスト リスナーはランダムな順序で呼び出されていました

上記のバージョン 2.5 仕様で述べたように、これは私見では間違っています。:-)

Servlet 3.0 の時点で、リスナーは、以下に指定されているように、web.xml で宣言されている順序で呼び出されます
javax.servlet.ServletContextListener の実装は、宣言された順序でcontextInitialized メソッドで呼び出され、逆の順序で contextDestroyed メソッドで呼び出されます。

これはあなたが期待するようにまったく機能せず、私のトラブル、混乱、失われた週末の原因です. ;-) 以前と同じ順序ではありません (2.5 仕様)!

しかし、まだまだあります... (AHA の瞬間が近づいています!)

8.2.2 web.xml と web-fragment.xml の順序付け 仕様では、アプリケーション構成リソースを複数の構成ファイル (web.xml と web-fragment.xml) で構成することを許可しているため、ファイル内のいくつかの異なる場所から検出してロードすることができます。アプリケーション、注文の問題に対処する必要があります。
...
アプリケーション構成リソースが順序設定を表現できるようにするには、2 つのケースを考慮する必要があります。
1.絶対順序: web.xmlの<absolute-ordering>要素。a. この場合、以下のケース 2 で処理される順序設定は無視する必要があります。
2.相対順序付け: <ordering >web-fragment.xml 内の要素。a. web-fragment.xml には <ordering> 要素が含まれる場合があります。その場合、この要素には 0 個または 1 個の <before> 要素と 0 個または 1 個の <after> 要素が含まれている必要があります。これらの要素の意味を以下に説明します。

したがって、私の場合、次の 2 つのオプションがありました。

  1. バージョン 2.5 に固執する: これは Tomcat 6 および 7 でうまく機能しますが、問題を将来に移すだけです。
  2. 仕様のバージョン 3.0 に移行し、それに応じてデプロイメント記述子を調整します。

    • もちろん、web-app 要素のバージョンとスキーマを更新します。

    <web-app xmlns="http://java.sun.com/xml/ns/ javaee " xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http ://java.sun.com/xml/ns/ javaee http://java.sun.com/xml/ns/ javaee/web-app_3_0.xsd "
    version= "3.0" >

    • リスナーが処理される順序を定義する <absolute-ordering> 要素を追加します。

    <absolute-ordering> <name>bootstrap</name><name>ws</name><others/></absolute-ordering>
    <listener id="bootstrap ">
       <listener-class>lu.estiedi.ws. WebAppBootstrap</listener-class>
    </listener>
       <listener id="ws" >
    <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>

<others/>要素に注意してください。存在しない場合、名前のないリスナーは処理されません。

編集:

これは実際には問題を解決しません。昨日家で消えましたが、今朝職場で解決策が機能しませんでした. :-(

Metro はListeners の前に呼び出されるサービス プロバイダServletContainerInitializerを使用しているようです。

これが動作するはずの方法である場合、PosConstruct メソッドは常にリスナーの contextInitialized の前に呼び出されます。Web サービスが作成される前に、どこでアプリケーションを初期化するのでしょうか?

于 2013-03-17T14:05:39.470 に答える
0

これはリスナーの順序に関するものではなく、サーブレット仕様 3.0 の新機能に関するものであり、おそらく METRO のような JAX-WS 実装を使用しているという事実に関するものです。サーブレット仕様 3.0 (第 8.2.4 章) には、JAX-WS、JAX-RS、JSF などの実装など、サードパーティのプラグインまたは API をコンテナー (この場合は Tomcat) に追加する方法があります。広告 SCI (javax.servlet.ServletContainerInitializer) とも呼ばれます。つまり、METRO JAX-WS jar はこの方法を使用するため、web.xml 記述子ファイルにリスナー (com.sun.xml.ws.transport.http.servlet.WSServletContextListener) とサーブレット構成を追加することは必須ではありません。これは、sun-jaxws.xml ファイルを使用して ws エンドポイントを一覧表示し、ws クラスをインスタンス化してから、Web アプリケーションをデプロイし、リスナーの contextInitialized メソッドなどを実行します。

これを回避するには、Tomcat で SCI メカニズムを回避するための指示に従ってください: Tomcat の起動を高速化するにはどうすればよいですか?

Context 要素には、containerSciFilter という属性が存在します。これを使用して、SCI API を介して Tomcat にプラグインされるコンテナ提供の機能を無効にすることができます: WebSocket サポート (Tomcat 7 以降)、JSP サポート (Tomcat 8 以降)。

フィルタリングするクラス名は、Tomcat JAR の META-INF/services/javax.servlet.ServletContainerInitializer ファイルを調べることで検出できます。WebSocket サポートの名前は org.apache.tomcat.websocket.server.WsSci で、JSP サポートの名前は org.apache.jasper.servlet.JasperInitializer です。

JAX-WS で動作し、web.xml 構成を使用して Web サービスをデプロイするだけです。

于 2015-07-30T14:54:54.937 に答える