以前にこれらのフォーラムでこの基本的な質問が尋ねられたのを見たことがありますが、どの回答も私の問題を解決していないようです。とにかく、コアSpringビジネスレイヤー、SpringMVC、およびSpring-Quartzで構成される小さなSpring Webアプリがあります(関連性はないと思いますが、MyBatisも使用しています)。私のSpringライブラリはすべて3.1.3です
問題は、アプリを Tomcat 6 にデプロイすると、通常、ルート アプリケーション コンテキストと Web アプリケーション コンテキストがそれぞれ 2 回初期化されることです。これはログを見ると明らかであり、私の Quartz ジョブが 1 回起動するはずのときに 2 回起動しているという事実からも明らかです (後者の点が、これが単なる理論上の問題ではない理由です)。
アプリケーションのコンテキストをすべて整理したと思っていましたが、明らかに何かが欠けているに違いありません。私の一般的なアプローチは次のとおりです。
- 基本的な Spring 構成をspring-biz-context.xmlのクラスパスに配置します (つまり、WEB-INF/classes/com/me/config に配置されます)。
- クラスパスのspring-quartz-context.xmlにSpring Quartz 構成を配置します (つまり、WEB-INF/classes/com/me/config にも配置されます)。
- applicationContext.xmlファイルを WEB-INF に配置します。上記の 2 つの XML ファイルをインポートするだけです
- web.xmlでContextLoaderListener を宣言して、webapp が上記のapplicationContext.xmlファイルを検索し、ルート コンテキストを初期化するようにします。
- web.xmlでUsMainというサーブレット (タイプ DispatcherServlet) を宣言します。
- WEB-INF 内にUsMain-servlet.xmlファイルを作成し、Web アプリケーション コンテキスト用の最小限のものをいくつか含めます。
以下は私の設定ファイルです。
UsMain-servlet.xml
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:resources mapping="/rsc/**" location="/rsc/" cache-period="31556926"/>
<mvc:annotation-driven />
<context:component-scan base-package="com.me.controllers" />
web.xml
<web-app ... version="2.5">
...
<servlet>
<servlet-name>UsMain</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>UsMain</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
applicationContext.xml
<import resource="classes/com/me/config/spring-biz-context.xml" />
<import resource="classes/com/me/config/spring-quartz-context.xml" />
以下は、Tomcat の起動時に2 回表示されるログ行のサンプルです。
2013-11-07 05:18:27 [main] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
2013-11-07 05:18:27 [main] INFO org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Thu Nov 07 05:18:27 UTC 2013]; root of context hierarchy
2013-11-07 05:18:27 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/applicationContext.xml]
2013-11-07 05:18:35 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/classes/com/me/config/spring-biz-context.xml]
... bunch of stuff ...
2013-11-07 05:18:38 [main] INFO org.springframework.web.context.support.XmlWebApplicationContext - Refreshing WebApplicationContext for namespace 'UsMain-servlet': startup date [Thu Nov 07 05:18:38 UTC 2013]; parent: Root WebApplicationContext
2013-11-07 05:18:38 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/UsMain-servlet.xml]
赤いニシンである場合とそうでない場合があるもう1つのこと...コードまたは構成ファイルを何らかの方法で変更し、WARファイルを再パッケージ化してからTomcatを停止し、WARをwebapps /にコピーしてTomcatを起動すると、アプリのコンテキストは 1 回だけ読み込まれます (イェイ!)。しかし、その後 Tomcat を再起動すると、この問題が発生します。
編集
私がこの問題を調査し続けるにつれて、「ニシンかもしれないし、そうでないかもしれない」ということが重要な要素のようです. 実際、これは Spring よりも Tomcat に関する問題かもしれません。
Tomcat を再起動する前に、デプロイされた webapp のサブディレクトリを webapps/ ディレクトリ内から削除すると、問題は発生しません。Tomcat を再起動する前にサブディレクトリをそのままにしておくと、問題が発生します。
つまり、webapp を MyApp.war にパッケージ化し、その WAR を Tomcat の webapps/ ディレクトリに貼り付けます。Tomcat が起動すると、WAR が解凍され、webapps/MyApp/ サブディレクトリが作成されます。初めて、物事はうまくいきます。しかし、Tomcat を再起動すると、問題が発生します。webapps/MyApp/ を削除してからTomcat を再起動すると、問題なく動作します。
それで、ある意味で、問題は解決されます。しかし、何が起こっているかについてのアイデアは依然として非常に役立ちます。私の知る限り、これは Tomcat/webapps が意図した動作ではありません。