ServletContext
サーブレット コンテナー ( Apache Tomcatなど) が起動すると、すべての Web アプリケーションがデプロイされて読み込まれます。Web アプリケーションがロードされると、サーブレット コンテナーはServletContext1 回作成し、サーバーのメモリに保持します。Web アプリweb.xmlおよび含まれるすべてのweb-fragment.xmlファイルが解析され、見つかった 、および のそれぞれ<servlet>(<filter>または、および<listener>で注釈が付けられた各クラス) が 1 回インスタンス化され、サーバーのメモリにも保持され、. インスタンス化されたフィルタごとに、そのメソッドが新しい引数で呼び出され、関連する が含まれます。@WebServlet@WebFilter@WebListenerServletContextinit()FilterConfigServletContext
Servletに<servlet><load-on-startup>または@WebServlet(loadOnStartup)より大きい値がある場合0、そのinit()メソッドも起動時にServletConfig、関連する を含む新しい引数で呼び出されServletContextます。これらのサーブレットは、その値で指定された順序 ( 11 番目、22 番目など) で初期化されます。複数のサーブレットに同じ値が指定されている場合、それらの各サーブレットは、web.xml、web-fragment.xml、または@WebServletクラスローディングで表示される順序でロードされます。"load-on-startup" 値が存在しない場合、 HTTP リクエストがそのサーブレットに初めてヒットするinit()たびにメソッドが呼び出されます。
サーブレット コンテナが上記のすべての初期化手順を完了すると、関連する を含む引数を使用しServletContextListener#contextInitialized()て が呼び出されます。これにより、開発者はさらに別の、またはをプログラムで登録する機会が得られます。ServletContextEventServletContextServletFilterListener
サーブレット コンテナがシャットダウンすると、すべての 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-CookieJSESSIONID
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 を最も一致するスコープとして格納します。HttpServletRequestHttpSessionattribute
スレッドセーフ
そうは言っても、あなたの主な関心事はおそらくスレッドセーフです。これで、サーブレットとフィルターがすべてのリクエストで共有されることがわかりました。これは 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.
}
}
以下も参照してください。