2013-03-16 65 views
1

之前叫我需要遷移Web服務從Tomcat 6(使用JDK 1.5)(使用JDK 1.6)應用到Tomcat 7(實際測試中的7.0.27)。 JAX-WS框架是Metro 2.1。Web服務的PostConstruct servlet上下文監聽器的contextInitialized

我用兩個的ServletContextListener:

  1. 「WebAppListener」:初始化應用程序(配置,數據庫連接設置...)。

  2. 「com.sun.xml.ws.transport.http.servlet.WSServletContextListener」:創建Web服務的Metro偵聽器。

的順序很重要,因爲我需要調用我的Web服務@PostConstruct方法之前,我的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」訂單恢復正常?

謝謝。

+0

這個相關的問題http://stackoverflow.com/questions/178562/how-to-determine-the-order-of-listeners-in-web-xml似乎證實了聽衆被調用的順序是由web.xml定義 – estiedi 2013-03-17 07:27:39

+0

Servlet 3.0規範說:11.3.2部署聲明: 監聽器類是在Web應用程序部署描述符中使用 監聽器元素聲明的。 **它們按類名列出,並按 的調用順序排列** – estiedi 2013-03-17 07:39:07

+0

創建一個包含兩個偵聽器的簡單Web應用程序。 Tomcat 7的行爲正確:偵聽器按照web.xml的順序調用,並且在反轉訂單時,調用順序也會反轉。 – estiedi 2013-03-17 08:03:06

回答

2

答案在於Servlet規範2.5和Servlet規範3.0的區別。

servlet規範2.5,其中聽衆被稱爲是由它們在部署描述符聲明(web.xml)中的次序所定義的順序:

SRV.10.3.3偵聽器註冊。
Web容器創建每個偵聽器類的 實例,並在 應用程序處理第一個請求之前通知事件 。 Web容器根據它們實現的接口以及它們在部署描述符中出現的順序 來註冊偵聽器實例 。在執行Web應用程序 期間,偵聽器按其註冊順序調用。

8.2:

servlet規範3.0,其中聽衆的調用順序被元件<絕對排序>在部署描述符(web.xml)中所定義.3從web.xml,webfragment.xml和註釋中組裝描述符。
......
c。 在此規範發佈之前, 上下文偵聽器以隨機順序被調用。

這是錯誤的恕我直言,如上面在版本2.5規範中所述。我
::-)

作爲的Servlet 3.0, 聽衆在其中它們在 聲明web.xml中所指定的以下順序調用。 javax.servlet.ServletContextListener的實現在它們的 contextInitialized方法上按012,聲明爲的順序調用,並且以相反的順序在contextDestroyed方法中調用。

這並不是在所有工作像你期望的,是我的麻煩,混亂的根源和失去的週末。 ;-) 這是不一樣的順序(2.5規範)!

但是,還有更多...(果酸時刻臨近了!)

8.2.2訂購的web.xml和web-fragment.xml之 由於該規範允許應用程序配置資源 由多個配置文件(web.xml和 web-fragment.xml)組成,發現並從應用程序中的幾個不同的 位置加載,排序問題必須爲 。
...
必須考慮兩種情況,以允許應用程序配置 資源表示其排序偏好。
1. 絕對排序:一個<絕對排序在web.xml >元件。一個。在這種情況下,必須忽略下面情況2下的 處理的訂購首選項。
2. 相對排序:一個<訂貨>元件捲筒紙fragment.xml之內。一個。一個web-fragment.xml可能會有一個<元素,它的順序爲> 。如果是這樣,則該元素必須在> 元素之前包含零個或一個<元素,並且在>元素之後必須包含零或一個<。下面解釋這些元素 的含義。

所以,在我的情況,我有兩個選擇:

  1. 棒與2.5版:這非常適用在Tomcat 6和第7,但僅移動問題未來。
  2. 遷移到規範的3.0版本,並相應地調整自己的部署描述符:

    • 更新,當然在web-app元素的版本和模式,:

    < web應用程序的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/的JavaEEhttp://java.sun.com/xml/ns/的JavaEE /網絡app_3_0.xsd
    版本= 」3.0「 >

    • 添加<絕對排序>元件限定的順序,其中聽衆應被處理:

    <絕對排序> <名>引導< /名稱> <名> WS < /名稱> <人/ > < /絕對排序>
    <聽衆ID = 「引導」 >
        <聽衆級> lu.estiedi.ws.WebAppBootstrap < /監聽級>
    < /聽衆>
        <聽者ID = 「WS」 >
    < 監聽級> com.sun.xml.ws.transport .http.servlet.WSServletContextListener < /監聽級>
    < /聽衆>

注意< others/> element:如果它不存在,那麼未命名的偵聽器將不會被處理。

編輯:

這實際上並沒有解決問題。 昨天在家裏消失了,但今天早上在工作中解決方案沒有奏效。 :-(

它看起來像地鐵使用服務提供商ServletContainerInitializer,這是聽衆之前調用。

如果這是它應該工作的方式,那麼PosConstruct方法總是叫在contextInitialized的聽衆面前。 我們在哪裏初始化我們的應用程序,然後,創建Web服務過嗎?

0

這是不是聽衆的秩序,它是關於servlet的一個新特色規格3.0次事實上,你可能正在使用像METRO這樣的JAX-WS實現。 在servlets spec 3.0中(第8.2章。4)有一種方法可以將第三方插件或API添加到容器(本例中爲Tomcat),例如JAX-WS,JAX-RS,JSF等實現。它也被稱爲廣告SCI(javax.servlet.ServletContainerInitializer)。 簡而言之,METRO JAX-WS jars使用這種方式,所以在您的web.xml描述符文件中添加監聽器(com.sun.xml.ws.transport.http.servlet.WSServletContextListener)和servlet配置不是強制性的。它使用sun-jaxws.xml文件列出ws端點並在部署web應用程序和執行之前實例化ws類,例如,偵聽器的contextInitialized方法。

爲了避免這種情況,只要按照說明,以避免在Tomcat中SCI機制:How do I make Tomcat startup faster?

存在着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服務。