DispatcherServiceletとスプリングコンテナ作成プロセス


これに先立ち,DispatcherServiceletとは何か,Spring Binとその管理を担当するSpringコンテナについて理解した.
このセクションでは、DispatcherServiceletとスプリングコンテナの作成方法について説明します.

DispatcherServiceletの作成ポイント

DispatcherServletはTomcatによって実行されるサーブレットであり、Tabletコンテナ(Tomcat)がweb.xml配置技術者ファイルによってWebアプリケーションのサーブレットコンテキストを初期化する際に、オプションに従ってlazy loadingまたはpre loadingで生成される.

テンプレートコンテキスト



「サーブレットContext」は、複数のWebアプリケーションを1つの「猫」から別の「猫」に移動させるためのコンテキストであり、1つの「板」と「板」コンテナ間で対話するために使用されます.
各Webアプリケーションにはサーブレットコンテキストがあります.サーバハブを作成すると、コンテキストが作成され、終了時に消えます.[前の投稿Tomcatセクションを参照]

DispatcherServiceletの作成方法


DispatcherServiceletは、サーバコンテナがコンテキストを初期化するときに作成されることを示します.Tomcat内の各Webアプリケーションでは、単一の存在するサーブレットコンテキストを初期化する方法がいくつかあります.

1. web.xml導入技術者の設定


Webapp/WEB-INFディレクトリにweb.xmlを設定することにより、サーバコンテキストを初期化し、DispatcherServiceを生成する方法.

web.xml

...
...
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
...
...

Lazy Loadingの作成


Dispatcherサーブレットはサーブレットです.サーバがlazy loading 방식の場合、Tomcatの実行時にサーバインスタンスは作成されないため、最初は서블릿 컨테이너にDispatcherServiceletインスタンスはありません.最初にクライアントからリクエストを受信すると、サーバコンテナはDispatcherServiceletのオブジェクトを作成し、次のリクエストからモノトーンを使用します.

Pre Loadingの作成


テンプレートにload-on-startupオプションがある場合は、pre loadingでテンプレートインスタンスを作成し、テンプレートコンテキストを初期化するときにDispatcherServiceletインスタンスを事前に作成することを示します.servlet-context.xmlは、DispatcherServiceletの内部でのみ使用されるアプリケーションコンテキストを作成するためのプロファイルであり、次はスプリングコンテナ作成部である.

2.WebApplicationInitializerの実装


バージョン3.0から、web.xmlを必要とせずにサーバコンテキストの初期化を行うことができます.ServletContainerInitializer APIが用意されているため、フレームレベルで直接初期化することができます.
これもスプリングを使って起動した時にweb.xmlがなかった理由です…!
Springは、spring Webアプリケーションを最初に起動したときにServletContainerInitializerインタフェースを実装するクラスを検索し、初期化タスクを委任するWebApplicationInitializerを実装したクラスをWebモジュールに含む.
スプリングフレームプロジェクトを最初に作成する方法は、web.xmlである可能性があります.ServletContainerInitializer 구현체に変更できます.その方法は別でしょう.

WebApplicationInitializerインプリメンテーションjavaコード

public class WebInitializer implements WebApplicationInitializer{
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {        
        ...
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation("com.studyspring.basic.config");
        
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
        ...
        ...
    }    
}
このコードは私がweb.xmlフォーマットをServletContainerInitializerフォーマットに変更して作成したコードです.Tomcatのサーブレットコンテナが駆動されると、WebApplicationInitializerインタフェースを実装するクラスを検索し、onStartUpメソッドを呼び出してWebアプリケーションのサーブレットコンテキストを作成および初期化します.onStartUpメソッドを呼び出すと、DispatcherServletをダイナミックにSubetコンテキストに配置し、DispatcherServeretを生成するかどうかを確認できます.addメソッドは、subliteインスタンスをaddServletに動的に追加するメソッドです.servletContextコード部は、アプリケーションテキストを生成する意味として以下に説明する.

スプリングコンテナを作成するとき

AnnotationConfigWebApplicationContextはスプリング管理が組み込まれた空き箱です.スプリングコンテナは、Application ContextDispatcherServletの時点で生成される.
2つのWebApplicationContextを使用して実装できます.
  • init
  • XmlWebApplicationContext
  • すなわち、DispatcherServicelet+スプリングコンテナを生成する方法は複数ある.
    1.AnnotationConfigWebApplicationContextを使用して+2457912を実施
    2.WebApplicationInitializerを使用して+2457912を実施
    3.XmlWebApplicationContext設定+2457912を使用
    4.WebApplicationInitializerを使用して+2457912を設定
    現在の主流はニンジンWebApplicationInitializer実装+Javaプロファイル方式です.スプリングスタートもこの形のようです.
    2番と3番について、実現方法を知りたいのですが、残りの応用はこれではあまり差がありません.

    WebApplicationInitializer実装+n o t i o n t i o n C o n f i g WebApplicationContext方式


    サーブレットContainerInitializerによって実装されるSpring Frameworkでは、サーバコンテキストを初期化し、DispacherServiceとApplicationContextの作成場所を表示します.
    public class WebInitializer implements WebApplicationInitializer{
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {        
            ...
            AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
            context.setConfigLocation("com.studyspring.basic.config");
            
            ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
            dispatcher.setLoadOnStartup(1);
            dispatcher.addMapping("/");
            ...
            ...
        }    
    }
    TomcatのSublitコンテナが起動すると、AnnotationConfigWebApplicationContextインタフェースを実装するクラスが検索され、web.xmlメソッドがWebアプリケーションのSublitコンテキストを作成および初期化するために呼び出されます.このコードでは、XmlWebApplicationContextスプリングコンテナが生成され、javaプロファイルの位置を指定し、スプリングコンテナが生成されます.
    その後、パラメータとしてweb.xmlを配置し、DispatcherServeretオブジェクトを作成し、AnnotationConfigWebApplicationContextをServertコンテキストに動的に追加することができます.

    WebApplicationInitializer設定+onStartUpを使用


    web.xml

    ...
    ...
    	<servlet>
    		<servlet-name>appServlet</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    ...
    ...

    servlet-context.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans ...>
    
    	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    	<!-- Enables the Spring MVC @Controller programming model -->
    	<annotation-driven />
    
    	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    	<resources mapping="/resources/**" location="/resources/" />
    
    	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<beans:property name="prefix" value="/WEB-INF/views/" />
    		<beans:property name="suffix" value=".jsp" />
    	</beans:bean>
    
    	<context:component-scan base-package="com.studyspring.basic" />
    
    
    
    </beans:beans>
    AnnotationConfigWebApplicationContextは、DispatcherServiceで使用されるWebApplicationContext Springコンテナを作成するためのプロファイルです.名前は必ずしもDispatcherServletではない.DispatcherServletセクションにプロファイルのパスが追加された場合、DispatcherServiceletはその初期化時にweb.xmlを使用してスプリングコンテナを作成します.XmlWebApplicationContextは何ですか、servlet-context.xmlは何ですかなど、以前の投稿[前の投稿]を参照してください.

    スプリングコンテナ階層


    基本的に、スプリングにはservlet-context.xmlが存在する.
    普通はそんなことは起こらないけど、web.xmlを変更すると、DispatcherServiceletは複数存在します.
    前述したように、DispatcherServiceletは初期化時にアプリケーションコンテキスト(スプリングコンテナ)を作成します.ここで使用するアプリケーションコンテキストはDispatcherServiceletでのみ使用できます.

    複数のDispatcherServicelet共有が必要なApplicationContextがある場合があります.このとき使用されるのは<init-param>です.

    web.xmlでリスナーを使用する

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app ...>
    
    	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>/WEB-INF/spring/root-context.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>
    
    	<!-- Processes application requests -->
    	<servlet>
    		<servlet-name>appServlet</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    
    	<servlet-mapping>
    		<servlet-name>appServlet</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
      ...
      ...
    </web-app>
    XmlWebApplicationContextは、シーケンスバッチコンテキスト内のすべてのシーケンスバッチによって共有される変数を宣言する役割を果たす.<annotation-driven/>で変数名を指定し、component-scanで値を指定することで、すべてのサーブレットが値を抽出して使用できます.DispatcherServletを使用して、ContextLoaderListenerに名前を付けて、グローバルコンテナの作成時に読み込むApplicationContextプロファイルのパスを指定します.ここのプロファイル名は<context-param>です.<param-name>はクライアント要求を必要としないが、コンテナ起動時に<param-value>のオブジェクトであり、シーケンスバッチコンテキストパラメータの<context-param>名を持つパラメータからプロファイルパスを読み出すことにより、シーケンスバッチコンテキスト内のすべてのシーケンスバッチが共有されるグローバルcontextConfigLocationを生成する.
    注意事項は上記のroot-context.xmlですが、ContextLoaderListenerを別途設定しない場合は、Pre-Loadingファイルの読み取りを基本的に試みます.ファイルがない場合は、スプリングコンテナが実行中にエラーが発生する可能性があります.

    WebApplicationInitializerインプリメンテーションでリスナーを使用する


    web.xmlのみならず、WebApplicationInitializerインプリメンテーションでContextLoaderListenerを使用することもできます.
    public class WebInitializer implements WebApplicationInitializer{
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {        
    
      	//각각 디스패처서블릿에서 사용할 ApplicationContext 여러개 생성
      	...
      	...
        	//DispacherServlet 여러개 생성 후 ApplicationContext 별도 지정
      	...
            ...
      	//공유할 ApplicationContext 별도 생성 및 리스너 등록
    	AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext(); 
     	rootAppContext.register(RootAppContext.class);
     	ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
     	servletContext.addListener(listener);
    
            ...
        }    
    }
    コンテナは必ずしも階層を構成するとは限らない.DispatcherServiceletが1つしかない場合は、別途登録がなくてもSpring MVCは正常に動作します.

    コンテナが階層になったとき。

    contextConfigLocation毎に単独で使用されるApplication Contextをゾーンコンテナと呼び、<conetxt-param>によって共有されるcontextConfigLoactionをグローバルコンテナと呼ぶ.
    空探索では領域コンテナを優先的に確認し,なければグローバルコンテナへ探索する.そのため、埋め方があればエリアコンテナを優先します.