ContextLoaderListenerかどうか?


122

標準のSpring Webアプリケーション(Rooまたは「Spring MVC Project」テンプレートで作成)は、ContextLoaderListenerおよびでweb.xmlを作成しますDispatcherServletなぜ彼らはを使用してDispatcherServlet、完全な構成をロードするだけではないのですか?

私は、ContextLoaderListenerを使用してWebに関連しないものをロードする必要があり、DispatcherServletを使用してWebに関連するもの(コントローラーなど)をロードすることを理解しています。この結果、2つのコンテキスト(親コンテキストと子コンテキスト)が生成されます。

バックグラウンド:

私はこの標準的な方法で数年間それをしていました。

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Handles Spring requests -->
<servlet>
    <servlet-name>roo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/spring/webmvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

これにより、2つのコンテキストとそれらの間の依存関係で問題が発生することがよくありました。以前は常に解決策を見つけることができました。これにより、ソフトウェアの構造/アーキテクチャが常に改善されると強く感じています。しかし今、私は両方の状況の出来事で問題に直面しています

-ただし、これにより、この2つのコンテキストパターンを再考し、私は自分自身に問いかけます。なぜ、この問題に自分を持ち込む必要があるのか​​、すべてのSpring構成ファイルを1つにロードしDispatcherServletContextLoaderListener完全に削除しないのはなぜですか。(まだ、異なる構成ファイルを使用しますが、コンテキストは1つだけです。)

削除しない理由はありますContextLoaderListenerか?


「これは多くの場合、2つのコンテキストとそれらの間の依存関係で問題を引き起こしました。」これは、依存性注入フレームワークが私たち自身の依存性注入よりも私たちの生活を困難にしていると私が思う方法の良い例です。
アンディ

1
@Andy-私はこの観点に同情していますが、両方のコンテキストが必要なユースケース(セキュリティフィルターとサーブレット間でオブジェクトを共有し、トランザクションを自動的に管理してビューの後で閉じるようにする)に気付かずにはいられませんリダイレクト先のレンダリングが完了しました)、フレームワークの助けなしでは達成するのは非常に困難です。これは主に、サーブレットAPIが明らかに依存性注入を処理するように設計されておらず、自分で実行しようとすると積極的に機能しないためです。
Periata Breatta 2016

@PeriataBreattaなるほど!さて、あなたがそれが異なるように設計されていたなら、Spring MVCのより良い代替案があると思いますか?とにかく人々はサーブレットAPIの完全な代替案を設計できたかもしれませんが...
Andy

@PeriataBreatta興味深いことに、約1年間HTTPリクエストのルーティングにExpressを使用してきたJSの世界では、「依存性注入」についての言及はほとんど見られず、Springフレームワークにまったく似ていません。
アンディ

回答:


86

あなたの場合、いいえ、ContextLoaderListenerとを保持する理由はありませんapplicationContext.xml。サーブレットのコンテキストのみでアプリが正常に機能する場合、それはそのままで、より簡単です。

はい、一般的に推奨されるパターンは、web以外のものをwebappレベルのコンテキストに維持することですが、それは弱い規則にすぎません。

webappレベルのコンテキストを使用する唯一の説得力のある理由は次のとおりです。

  • 複数のDispatcherServletサービスを共有する必要がある場合
  • Springワイヤードサービスにアクセスする必要があるレガシー/非Springサーブレットがある場合
  • あなたはサーブレットフィルタを持っている場合は、そのWebアプリケーション・レベルのコンテキストにフック(例えば春SecurityのDelegatingFilterProxyOpenEntityManagerInViewFilterなど)

これらはいずれも当てはまらないため、余分な複雑さは保証されません。

スケジュールされたタスク、JMS接続など、サーブレットのコンテキストにバックグラウンドタスクを追加するときは注意してください。に追加<load-on-startup>するのを忘れた場合web.xml、これらのタスクは、サーブレットに最初にアクセスするまで開始されません。


2
リスナーについては、Context Loaderリスナーによるコンテキスト作成が必要であるように見えます(IllegalStateException、WebApplicationContextが見つかりません、MultipartFilter、CharacterEncodingFilter、HiddenHttpMethodFilter、Spring Security DelegatingFilterProxyおよびOpenEntityManagerInViewFilterによってトリガーされます)。それを逆に行うのは良い考えですか?
ラルフ

@ラルフ:良いキャッチ、そのユースケースをリストに追加しました。DispatcherServlet設定なしで去ることに関して-あなたがそうしたなら、あなたはウェブインターフェースを持っていません。すべてのMVC要素をそこに入れる必要があります。
skaffman 2012年

2
@skaffman DelegatingFilterProxyでspring-securityを使用するときに2つのコンテキストを使用する必要があるのはなぜですか?私の場合、Spring-Security BeanとデフォルトのSpringコンテキストはいくつかのBeanを共有しています。したがって、彼らも同じコンテキストを共有する必要があります。または、Spring Security BeanをデフォルトのSpringコンテキストから除外する必要がありますか?
Matthias M

10

アプリケーションコンテキストを逆に構成することもできます。たとえば、OpenEntityManagerInViewFilterを機能させるためです。セットアップのContextLoaderListenerし、その後で、あなたのDispatcherServletを設定します。

<servlet>
    <servlet-name>spring-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value></param-value>
    </init-param>
</servlet>

contextConfigLocationパラメータの値が空であることを確認してください。


1
しかし、この構成の利点は何ですか?そして、「その逆」とはどういう意味ですか?
ラルフ

「skaffman」によるソリューションは、Webアプリケーションコンテキスト(サーブレット)のみを構成しました。ただし、そのアプローチでは、ソリューション自体で詳しく説明されているように、問題が発生します。「webappレベルのコンテキストを使用する唯一の説得力のある理由は、次のとおりです。」...「webbappレベルのコンテキストにフックするサーブレットフィルターがある場合(たとえばSpring SecurityのDelegatingFilterProxy、OpenEntityManagerInViewFilterなど)」1つのアプリケーションコンテキストXMLファイルのみを使用したい場合、私のソリューション(ContextLoaderListenerを介してXMLを指定)が望ましいと思います。
Gunnar Hillert 2013

コンテキストリスナーによって作成されたコンテキストでMVC Webコントローラーを使用できますか?
Ralph

1
はい。コントローラーは、コンテキストリスナーで指定されたcontext.xmlファイルに設定するだけです。これが機能する方法は、DispatcherServletが単に「親アプリケーションコンテキスト」(Context Listener)に参加することです。「contextConfigLocation」の値を空のままにすると、コンテキストリスナーによって指定されたcontext.xmlファイルが排他的に使用されます。
Gunnar Hillert、2013

1
あなたはあなたのコンテキストで<mvc:annotation-driven />を逃したと思います。@GunnarHillertソリューションは私のために働きます。
milbr 2014

10

Spring-MVCアプリケーションで行ったことを共有したいと思います。

  1. 上のwe-mvc-config.xmlI @Controllerでアノテートだけのクラスを追加しました:

    <context:component-scan base-package="com.shunra.vcat">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
  2. applicationContext.xml残りのすべてを追加したファイル:

    <context:component-scan base-package="com.shunra.vcat">
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>

はい、これは便利なパターンです。別の有用なパターンは、データベース処理Beanをアプリケーションコンテキスト(OpenSessionInViewFilterなどで必要になる可能性が高い)とフィルターまたはリスナーで特に必要なもの(たとえば、Spring Securityを使用するために必要な定義)に置くことです。
Periata Breatta 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.