SpringMVCとかServlet周りのメモ

Servletのライフサイクル

  1. サーブレットロード時(初回リクエスト時)にコンテナからinit()が呼び出される。
  2. リクエスト単位でservice()がコンテナから呼び出され、service()はリクエストの種別(GETとかPOST)に応じてdoXXX()を呼び出す。
  3. サーブレットのアンロード時にdestory()が呼び出される。

一応動作確認

package com.sample;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletTest extends HttpServlet {
    public ServletTest() {
    }

	public void init(ServletConfig config) throws ServletException {
		System.out.println("init()が呼び出されました");
	}

	public void destroy() {
		System.out.println("destory()が呼び出されました");
	}

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("service()が呼び出されました");
		super.service(request, response);
	}
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("doGet()が呼び出されました");
	}

}

SpringMVCでの処理順序
まずはorg.springframework.web.servlet.DispatcherServletからみてみる。
このクラスにはinit()/service()の両方が実装されてないので、親クラスをたどってみる。
階層関係はこんな感じ

java.lang.Object
  +- javax.servlet.GenericServlet
       +- javax.servlet.http.HttpServlet
             +- org.springframework.web.servlet.HttpServletBean
                     +- org.springframework.web.servlet.FrameworkServlet
                             +- org.springframework.web.servlet.DispatcherServlet

org.springframework.web.servlet.HttpServletBeanでfinal宣言された init() を見つけたので処理内容の確認。やってることは

  • Beanプロパティの設定
  • initServletBean()の呼び出し

の二つ。

initServletBean()の実装はこのクラスにはなく、サブクラスのFrameworkServletで行っている。こいつの処理内容は・・・

try {
    this.webApplicationContext = initWebApplicationContext();
    initFrameworkServlet();
}

initFrameworkServlet()については、サブクラスのほうにも処理の実体は存在しないので、カスタムのDispatcherを作った時に使うのかな?initWebApplicationContext()では

  • WebApplicationContextの生成
  • onRefresh()の呼び出し

などをやっている様子。

onRefresh()はDispatcherServletで処理が実装されていて、initStrategies()を呼び出す。
initStrategies()の処理は、

initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);

となっていて、ようやくResolverとかの見慣れたものが出てきました。
あとは、ApplicationContext周りの処理を勉強すればこの辺の流れはすっきり確認できそう。


続いて、service()が同処理されるか。
これは、FrameworkServlet内でdoXXXメソッドがprocessRequest()を呼び出すように処理されていて、このメソッド内で

  • doService()の呼び出し
  • webApplicationContext.publishEventの実行

を行っている。

doService()はDispatcherServlet内で実装されていて、さらにdoDispatch()を呼び出す仕組みとなっている。

処理の詳細はいまいちわかっていないが、全体像はぼんやりつかめた感じ