ServletContext
サーブレット コンテナー ( Apache Tomcatなど) が起動すると、すべての Web アプリケーションがデプロイされて読み込まれます。Web アプリケーションがロードされると、サーブレット コンテナーはServletContext
1 回作成し、サーバーのメモリに保持します。Web アプリweb.xml
および含まれるすべてのweb-fragment.xml
ファイルが解析され、見つかった 、および のそれぞれ<servlet>
(<filter>
または、および<listener>
で注釈が付けられた各クラス) が 1 回インスタンス化され、サーバーのメモリにも保持され、. インスタンス化されたフィルタごとに、そのメソッドが新しい引数で呼び出され、関連する が含まれます。@WebServlet
@WebFilter
@WebListener
ServletContext
init()
FilterConfig
ServletContext
Servlet
に<servlet><load-on-startup>
または@WebServlet(loadOnStartup)
より大きい値がある場合0
、そのinit()
メソッドも起動時にServletConfig
、関連する を含む新しい引数で呼び出されServletContext
ます。これらのサーブレットは、その値で指定された順序 ( 1
1 番目、2
2 番目など) で初期化されます。複数のサーブレットに同じ値が指定されている場合、それらの各サーブレットは、web.xml
、web-fragment.xml
、または@WebServlet
クラスローディングで表示される順序でロードされます。"load-on-startup" 値が存在しない場合、 HTTP リクエストがそのサーブレットに初めてヒットするinit()
たびにメソッドが呼び出されます。
サーブレット コンテナが上記のすべての初期化手順を完了すると、関連する を含む引数を使用しServletContextListener#contextInitialized()
て が呼び出されます。これにより、開発者はさらに別の、またはをプログラムで登録する機会が得られます。ServletContextEvent
ServletContext
Servlet
Filter
Listener
サーブレット コンテナがシャットダウンすると、すべての Web アプリケーションがアンロードされ、destroy()
初期化されたすべてのサーブレットとフィルタのメソッドがServlet
呼び出さFilter
れListener
ますServletContext
。最後にServletContextListener#contextDestroyed()
が呼び出され、ServletContext
自体が破棄されます。
HttpServletRequest
とHttpServletResponse
サーブレット コンテナーは、特定のポート番号で HTTP 要求をリッスンする Web サーバーに接続されます (通常、ポート 8080 は開発時に使用され、ポート 80 は運用時に使用されます)。クライアント (たとえば、Web ブラウザを使用しているユーザー、またはプログラムで を使用URLConnection
しているユーザー) が HTTP 要求を送信すると、サーブレット コンテナーは新しい オブジェクトと オブジェクトを作成HttpServletRequest
しHttpServletResponse
、それらをチェーンで定義さFilter
れたもの、そして最終的にはServlet
インスタンスに渡します。
フィルターの場合、doFilter()
メソッドが呼び出されます。サーブレット コンテナのコードが を呼び出すchain.doFilter(request, response)
と、リクエストとレスポンスは次のフィルタに進むか、残りのフィルタがない場合はサーブレットにヒットします。
サーブレットの場合、service()
メソッドが呼び出されます。デフォルトでは、このメソッドは に基づいてどのdoXxx()
メソッドを呼び出す かを決定しrequest.getMethod()
ます。決定されたメソッドがサーブレットに存在しない場合、HTTP 405 エラーが応答で返されます。
リクエスト オブジェクトは、HTTP リクエストに関するすべての情報 ( URL、ヘッダー、クエリ文字列、本文など) へのアクセスを提供します。応答オブジェクトは、HTTP 応答を希望どおりに制御および送信する機能を提供します。たとえば、ヘッダーと本文 (通常は JSP ファイルから生成された HTML コンテンツを使用) を設定できます。HTTP 応答がコミットされて終了すると、要求オブジェクトと応答オブジェクトの両方がリサイクルされ、再利用できるようになります。
HttpSession
クライアントが初めて webapp にアクセスしたとき、および/またはHttpSession
を介して を初めて取得したときrequest.getSession()
、サーブレット コンテナは新しいHttpSession
オブジェクトを作成し、長い一意の ID ( で取得できますsession.getId()
) を生成し、それをサーバーのメモリー。また、サーブレット コンテナは、HTTP 応答Cookie
のヘッダーに a を名前として設定し、一意のセッション ID を値として設定します。Set-Cookie
JSESSIONID
HTTP Cookie 仕様(適切な Web ブラウザーと Web サーバーが準拠する必要がある契約)に従って、クライアント (Web ブラウザー) は、Cookie が有効である限り、ヘッダー内の後続の要求でこのCookieCookie
を送り返す必要があります (つまり、一意の ID は有効期限が切れていないセッションを参照し、ドメインとパスが正しい必要があります)。ブラウザーに組み込まれている HTTP トラフィック モニターを使用して、Cookie が有効であることを確認できます (Chrome / Firefox 23 以降 / IE9 以降で F12 を押し、 [ネット/ネットワーク] タブを確認します)。サーブレット コンテナーはCookie
、すべての着信 HTTP 要求のヘッダーで名前付きの Cookie の存在を確認し、JSESSIONID
その値 (セッション ID) を使用してHttpSession
サーバーのメモリから関連付けを取得します。
は、 で指定されたタイムアウト値( の設定HttpSession
) を超えてアイドル状態になる (つまり、要求で使用されなくなる) まで、存続します。タイムアウト値のデフォルトは 30 分です。そのため、クライアントが指定された時間より長く Web アプリにアクセスしない場合、サーブレット コンテナーはセッションを破棄します。後続のすべてのリクエストは、Cookie が指定されていても、同じセッションにアクセスできなくなります。サーブレット コンテナが新しいセッションを作成します。<session-timeout>
web.xml
クライアント側では、ブラウザー インスタンスが実行されている限り、セッション Cookie は存続します。そのため、クライアントがブラウザー インスタンス (すべてのタブ/ウィンドウ) を閉じると、セッションはクライアント側で破棄されます。新しいブラウザー インスタンスでは、セッションに関連付けられた Cookie は存在しないため、送信されなくなります。これにより、まったく新しいHttpSession
が作成され、まったく新しいセッション Cookie が使用されます。
手短に
- Web アプリが存続する
ServletContext
限り存続します。これは、すべてのセッションのすべてのリクエストで共有されます。
HttpSession
クライアントが同じブラウザー インスタンスを使用して Web アプリと対話している限り、 は存続し、サーバー側でセッションがタイムアウトしていません。これは、同じセッション内のすべてのリクエスト間で共有されます。
HttpServletRequest
とはHttpServletResponse
、サーブレットがクライアントから HTTP 要求を受信してから、完全な応答 (Web ページ) が到着するまで有効です。他の場所では共有されません。
- すべて
Servlet
、Filter
およびListener
インスタンスは、Web アプリが存続する限り存続します。これらは、すべてのセッションのすべてのリクエストで共有されます。
- で定義
attribute
され、ServletContext
問題のオブジェクトが存在する限り存続します。オブジェクト自体は、JSF、CDI、Spring などの Bean 管理フレームワークの「スコープ」を表します。これらのフレームワークは、スコープ付き Bean を最も一致するスコープとして格納します。HttpServletRequest
HttpSession
attribute
スレッドセーフ
そうは言っても、あなたの主な関心事はおそらくスレッドセーフです。これで、サーブレットとフィルターがすべてのリクエストで共有されることがわかりました。これは Java の優れた点です。Java はマルチスレッド化されており、異なるスレッド (HTTP リクエストと読みます) が同じインスタンスを利用できます。そうしないと、再作成するにはコストがかかりすぎinit()
てdestroy()
、すべてのリクエストに対してそれらが作成されます。
また、サーブレットまたはフィルタのインスタンス変数として、リクエストまたはセッション スコープのデータを割り当ててはならないことに注意してください。これは、他のセッションの他のすべてのリクエスト間で共有されます。それはスレッドセーフではありません!以下の例は、これを示しています。
public class ExampleServlet extends HttpServlet {
private Object thisIsNOTThreadSafe;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object thisIsThreadSafe;
thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
}
}
以下も参照してください。