13

私は、共通のオブジェクトを含む 1 つの jar と、共通の jar を使用したい 2 つの war webapps を含む ear パッケージを持っています。DispatcherServlet の ContextLoaderListener と webapp コンテキストを介してアプリケーション全体のコンテキストを使用するように構成をセットアップしました。

私のデモアプリのセットアップはおおよそ次のとおりです

  • common.jarapplicationContext.xmlbeanRefContext.xmlが含まれています。これらは、アプリケーション (ear) ワイド コンテキストであると想定されています。ファイルは以下のようなものです。共有名前空間は、共有 Bean が配置されている場所です。

アプリケーションコンテキスト

<beans>
    <!-- namespace etc declarations omitted -->
    <context:annotation-config />
    <context:component-scan base-package="study.spring.multicontext.shared" />
</beans>

beanRefContext.xml

<beans>
    <!-- namespace etc declarations omitted -->
<bean id="sharedContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
    <constructor-arg>
        <list>
            <value>classpath*:applicationContext.xml</value>
        </list>
    </constructor-arg>
</bean>
</beans>
  • webapp1以下のようなweb.xmlファイルを使用しwebapp2て個別の war としてパッケージ化された Spring MVC アプリケーションです。

    <web-app>
    
    <context-param>
      <param-name>parentContextKey</param-name>
      <param-value>sharedContext</param-value>
    </context-param>
    <context-param>
      <param-name>locatorFactorySelector</param-name>
      <param-value>classpath:beanRefContext.xml</param-value>
    </context-param>
    <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:applicationContext.xml</param-value>
    </context-param>
    
    <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <servlet>
        <servlet-name>dos</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/dos-servlet.xml</param-value>
        </init-param>
    
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    
    <servlet-mapping>
        <servlet-name>dos</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

およびxx-servlet.xmlは、webapp 固有のコンテキストと同様です。web名前空間は、コントローラーが配置されている場所です。

<beans>
    <!-- namespace etc declarations omitted -->

    <context:component-scan base-package="study.spring.multicontext.web"/>
    <mvc:annotation-driven />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

      <property name="suffix" value=".jsp"/>
    </bean>

</beans>
  • 共有 Bean は、Controller クラスの通常の方法で @Autowired です

    @Autowired
    MySharedBean mySharedBean
    
  • ear パッケージには wars と jar の両方が含まれており、構造は次のようになります。

    ear
     |
     |--common.jar
     |   |--META-INF
     |   |--applicationContext.xml
     |   |--beanRefContext.xml
     |
     |--webapp1.war
     |   |--WEB-INF
     |       |--xx-servlet.xml
     |       |--web.xml
     |
     |--webapp2.war
     |   |--WEB-INF
     |       |--xx-servlet.xml
     |       |--web.xml
    

問題は、Bean のインスタンスが 2 つ残っていることです。各 war には Controller が 1 つしかないため、Controller/webapp ごとに 1 つです。構成をいじってみましたが、何をしてもインスタンスが 0 個か 2 個しか取得できません。

メモリーダンプから Eclipse MAT で参照を確認したところ、実際には 4 つのインスタンスがありましたが、2 つが Spring 内部で使用されていると推測されます。とにかく、そこから、各コントローラーが独自のインスタンスを持っていることがはっきりとわかります。

私は、これはこれと同じくらい簡単であるべきだと言っている多くのブログ投稿、ディスカッション フォーラムなどを読みました。JNDIを提案する人もいますが、私が理解しているように、JNDIがなくても可能です。

そして、戦争を組み合わせて、瓶を中に束ねることはできません。このデモ アプリでは機能する可能性があるため、私が扱っている実際のケースではこれが許可されていません。

この問題に関するヘルプは大歓迎です。前もって感謝します。

Spring 2.X 用の2007 年の SpringSource の例。同じことを行いますが、構成が異なります。報奨金の説明に記載されているように、少し時代遅れで、Spring 3.X ベースのソリューションを探しています。

4

4 に答える 4

7

アプリケーションのコンテキスト階層に関する限り、Spring 2.x から 3.x に変更されたとは思いません。

私が知る限り、あなたの構成の問題は、あなたがapplicationContext.xmlロードしてsharedContextいることですcontext-param contextConfigLocation. .

同じファイルが 2 回 (親コンテキストで 1 回、Web アプリケーションのルート コンテキストで 1 回) ロードされるため、コピーが作成され、子コンテキストが作成されます。webapp は、親に存在するものではなく、作成したものを使用します。

同じ Bean xml を 2 回リロードしないように構成を変更すると、正常に動作するはずです。使用できますがparentContextKeycontextConfigLocationどちらも同じファイルをロードしません。

更新: 上記に加えて、共有 jar が wars に表示されるかどうかも確認する必要があります (同じインスタンスの共有が許可されている場合に表示されます)。ブログからサンプルを実行しようとしましたが、Java EE6 アプリケーションとしてデプロイしたときにうまくいきませんでした。これは、wars 内の ear jar の可視性のルールが Java EE5 から EE6 に変更されたためです。サンプルを Glass Fish の互換モードで実行すると、すべて期待どおりに動作します。

したがって、EAR / WAR をチェックして、実行しているサーブレット仕様を確認し、それに応じてサーバーがアプリケーションをデプロイしていることを確認してください。

Java EE 6 にアップグレードする必要がある場合は、最新の可視性ルールhttp://docs.oracle.com/cd/E19226-01/820-7688/gjjdt/index.htmlに従っていることを確認してください。warsのファイルをチェックしMANIFESTて、すべての ear jar が構成で明示的に言及されていることを確認しClass-Pathます。

お役に立てれば。

于 2013-04-25T19:58:48.537 に答える
2

同様の問題がありました。実験用に作成したこの単純な Maven の例 (2 つの WEB モジュールと親スプリング コンテキスト サービス モジュールを介して共有された EAR) を確認してください: war 間の共有スプリング コンテキストを使用した EAR

于 2014-02-26T14:33:47.327 に答える