web-dev-qa-db-ja.com

サーブレットの各インスタンスとサーブレットのサーブレットの各スレッドの違いは?

サーブレットクラスのインスタンスが複数ありますか? 「サーブレットの各インスタンス」と聞きましたが、これについて詳しく説明してください。

83
giri

サーブレットコンテナが起動すると、次のようになります。

  1. web.xml;を読み取ります
  2. クラスパスで宣言されたサーブレットを見つけます。そして
  3. 各サーブレットを一度だけロードしてインスタンス化します

大体、このように:

String urlPattern = parseWebXmlAndRetrieveServletUrlPattern();
String servletClass = parseWebXmlAndRetrieveServletClass();
HttpServlet servlet = (HttpServlet) Class.forName(servletClass).newInstance();
servlet.init();
servlets.put(urlPattern, servlet); // Similar to a map interface.

これらのサーブレットはメモリに保存され、リクエストURLがサーブレットの関連url-patternと一致するたびに再利用されます。次に、サーブレットコンテナは次のようなコードを実行します。

for (Entry<String, HttpServlet> entry : servlets.entrySet()) {
    String urlPattern = entry.getKey();
    HttpServlet servlet = entry.getValue();
    if (request.getRequestURL().matches(urlPattern)) {
        servlet.service(request, response);
        break;
    }
}

GenericServlet#service() は、 doGet() に基づいて、doPost()HttpServletRequest#getMethod()などのどれを呼び出すかを決定します。

ご覧のとおり、servletcontainerはすべてのリクエストに対して同じサーブレットインスタンスを再利用します。つまり、サーブレットはすべてのリクエストで共有されます。そのため、サーブレットコードをスレッドセーフな方法で記述することが非常に重要です。これは実際には単純です。ただ、notリクエストまたはセッションスコープのデータをサーブレットインスタンス変数として割り当てますが、ローカルメソッドとして変数。例えば。

public class MyServlet 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.
    } 
}
186
BalusC

いいえ、複数のクライアントからの複数のリクエストに再利用されるサーブレットのインスタンスは1つだけです。これは、2つの重要なルールにつながります。

  • コンテキストパラメータから取得されることが多いアプリケーション全体の値を除き、サーブレットでインスタンス変数を使用しないでください。
  • サーブレットでメソッドsynchronizedを作成しないでください

(サーブレットフィルターとjspについても同様)

30
Bozho

Java Servlet Specification Version 3.0(pp。6-7)によれば、サーブレットがJVMごとに複数のインスタンスが存在する可能性のあるSingleThreadModelをサーブレットが実装しない限り、JVMごとに宣言ごとに1つのインスタンスが存在します。 。

11

既にいくつかの良い答えがありますが、それらのいずれもJava分散環境にデプロイされたWebアプリケーションについては言及していません。これは実際に単一サーブレットの複数インスタンスが作成される実用的なシナリオです。分散環境では、要求を処理するマシンのクラスターがあり、要求はこれらのマシンのいずれかに送信できます。これらの各マシンは要求を処理できる必要があるため、すべてのマシンはそのJVMにMyAwesomeServletのインスタンスを持っている必要があります。

そのため、SingleThreadModelを実装しない限り、正しいステートメントは、すべてのサーブレットのJVMごとに1つのインスタンスのみが存在することになります。

簡単な言葉で言うと、SingleThreadModelはServletのインスタンスごとに1つのスレッドだけを持っている必要があるため、基本的にリクエストを処理するために来るリクエストごとに1つのインスタンスを作成する必要があります。サーブレットオブジェクトの作成と初期化は、リクエストを処理する準備が整うまでに時間がかかるため、良い方法と見なされます。

6
Saurabh Patil

サーブレットクラスの複数のインスタンスは存在できません。サーブレットのインスタンスが1つでも、複数のリクエストを処理できます。したがって、クラスレベルの変数を使用しないのが賢明です。

5
fastcodejava

(単なるライブラリではなく)実際のJavaScriptを知っている人にとっては、サーブレットは関数オブジェクトとして見ることができます。機能的なオブジェクトとして、それらの主なタスクは何らかの情報を保存するではなく何かをするである。 Javaクラスメソッドがそのクラスのすべてのインスタンス間で共有されるという同じ原理で、このようなすべての機能オブジェクトの複数のインスタンスをインスタンス化する必要はありません。

4
lcn