1. 概要

このチュートリアルでは、サーブレットとサーブレットコンテナとは何か、およびそれらがどのように機能するかを概念的に理解します

また、リクエスト、レスポンス、セッションオブジェクト、共有変数、マルチスレッドのコンテキストでも表示されます。

2. サーブレットとそのコンテナとは

サーブレットは、Web開発に使用されるJEEフレームワークのコンポーネントです。 これらは基本的に、コンテナの境界内で実行されるJavaプログラムです。 全体として、は、要求を受け入れ、処理し、応答を返送する責任があります Javaサーブレットの概要は、主題の基本的な理解を提供します。

それらを使用するには、最初にサーブレットを登録して、JEEまたはSpringベースのコンテナが起動時にそれらを取得できるようにする必要があります。 最初に、コンテナは init()メソッドを呼び出すことによってサーブレットをインスタンス化します。

初期化が完了すると、サーブレットは着信要求を受け入れる準備が整います。 その後、コンテナはこれらのリクエストをサーブレットの service()メソッドで処理するように指示します。 その後、HTTPリクエストタイプに基づいて、 doGet() doPost()などの適切なメソッドにリクエストをさらに委任します。

destroy()を使用すると、コンテナはサーブレットを破棄し、着信要求を受け入れることができなくなります。 このinit-service-destroyのサイクルをサーブレットのライフサイクルと呼びます

次に、 ApacheTomcatJettyなどのコンテナーの観点からこれを見てみましょう。 起動時に、ServletContextのオブジェクトを作成します。 ServletContext の役割は、サーバーまたはコンテナーのメモリーとして機能し、 web.xmlまたは同等の注釈。 コンテナを停止または終了するまで、ServletContextはコンテナにとどまります。

ただし、ここではservletのload-on-startupパラメータが重要な役割を果たします。 このパラメーターの値がゼロより大きい場合にのみ、サーバーは起動時にパラメーターを初期化します。 このパラメータが指定されていない場合、リクエストが初めてサーブレットにヒットしたときに、サーブレットの init()が呼び出されます。

3. 要求、応答、およびセッション

前のセクションでは、要求の送信と応答の受信について説明しました。これは、基本的にクライアントサーバーアプリケーションの基礎です。 それでは、サーブレットに関してそれらを詳しく見ていきましょう。

この場合、要求はHttpServletRequestで表され、応答はHttpServletResponseで表されます。

ブラウザやcurlコマンドなどのクライアントがリクエストを送信するたびに、コンテナは新しいHttpServletRequestおよびHttpServletResponseオブジェクトを作成します。 次に、これらの新しいオブジェクトをサーブレットのserviceメソッドに渡します。 このメソッドは、 HttpServletRequest のメソッド属性に基づいて、どのdoXXXメソッドを呼び出すかを決定します。

メソッドに関する情報とは別に、リクエストオブジェクトには、ヘッダー、パラメーター、本文などの他の情報も含まれます。 同様に、 HttpServletResponse オブジェクトにもヘッダー、パラメーター、本文が含まれています。これらは、サーブレットのdoXXXメソッドで設定できます。

これらのオブジェクトは短命です。 クライアントが応答を返すと、サーバーは要求オブジェクトと応答オブジェクトにガベージコレクションのマークを付けます。

次に、後続のクライアント要求または接続の間の状態をどのように維持しますか? HttpSessionがこの謎の答えです。

これは基本的にオブジェクトをユーザーセッションにバインドするため、特定のユーザーに関連する情報を複数のリクエストにわたって永続化できます。 これは通常、Cookieの概念を使用して、特定のセッションの一意の識別子としてJSESSIONIDを使用して実現されます。 セッションのタイムアウトは、web.xmlで指定できます。

<session-config>
    <session-timeout>10</session-timeout>
</session-config>

これは、セッションが10分間アイドル状態だった場合、サーバーはそれを破棄することを意味します。 それ以降のリクエストは、新しいセッションを作成します。

4. サーブレットがデータを共有する方法

サーブレットが必要なスコープに基づいてデータを共有する方法はさまざまです。

前のセクションで見たように、オブジェクトが異なれば寿命も異なります。 HttpServletRequestおよびHttpServletResponseオブジェクトは、1つのサーブレット呼び出しの間にのみ存在します。 HttpSession は、アクティブでタイムアウトしていない限り存続します。

ServletContextの寿命は最長です。これはWebアプリケーションで生まれ、アプリケーション自体がシャットダウンしたときにのみ破棄されます。 サーブレット、フィルタ、およびリスナーのインスタンスはコンテキストに関連付けられているため、Webアプリケーションが稼働している限り、これらのインスタンスも存続します。

したがって、すべてのサーブレット間でデータを共有する必要がある場合、たとえば、サイトへの訪問者の数をカウントする場合は、変数をServletContextに配置する必要があります。 セッション内でデータを共有する必要がある場合は、それをセッションスコープに保存します。 この場合、ユーザーの名前が例になります。

最後に、リクエストペイロードなど、単一のリクエストのデータに関連するリクエストスコープがあります。

5. マルチスレッドの処理

複数のHttpServletRequestオブジェクトは、各リクエストがサーブレットインスタンスの独自のスレッドで動作するように、サーブレットを相互に共有します。

スレッドセーフの観点からを効果的に意味するのは、リクエストまたはセッションスコープのデータをサーブレットのインスタンス変数として割り当ててはならないということです。

たとえば、次のスニペットについて考えてみましょう。

public class ExampleThree extends HttpServlet {
    
    private String instanceMessage;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        String message = request.getParameter("message");
        instanceMessage = request.getParameter("message");
        request.setAttribute("text", message);
        request.setAttribute("unsafeText", instanceMessage);
        request.getRequestDispatcher("/jsp/ExampleThree.jsp").forward(request, response);
    }
}

この場合、セッション内のすべてのリクエストは instanceMessage を共有しますが、messageは特定のリクエストオブジェクトに固有です。 その結果、同時リクエストの場合、instanceMessageのデータに一貫性がなくなる可能性があります。

6. 結論

このチュートリアルでは、サーブレット、そのコンテナ、およびサーブレットが中心となるいくつかの重要なオブジェクトに関するいくつかの概念について説明しました。 また、サーブレットがデータを共有する方法と、マルチスレッドがサーブレットに与える影響についても説明しました。

いつものように、ソースコードはGitHubから入手できます。