1217

Suppose, I have a webserver which holds numerous servlets. For information passing among those servlets I am setting session and instance variables.

Now, if 2 or more users send request to this server then what happens to the session variables?
Will they all be common for all the users or they will be different for each user?
If they are different, then how was the server able to differentiate between different users?

One more similar question, if there are n users accessing a particular servlet, then this servlet gets instantiated only the first time the first user accessed it or does it get instantiated for all the users separately?
In other words, what happens to the instance variables?

4

8 に答える 8

1909

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.xmlweb-fragment.xml、または@WebServletクラスローディングで表示される順序でロードされます。"load-on-startup" 値が存在しない場合、 HTTP リクエストがそのサーブレットに初めてヒットするinit()たびにメソッドが呼び出されます。

サーブレット コンテナが上記のすべての初期化手順を完了すると、関連する を含む引数を使用しServletContextListener#contextInitialized()て が呼び出されます。これにより、開発者はさらに別の、またはをプログラムで登録する機会が得られます。ServletContextEventServletContextServletFilterListener

サーブレット コンテナがシャットダウンすると、すべての Web アプリケーションがアンロードされ、destroy()初期化されたすべてのサーブレットとフィルタのメソッドがServlet呼び出さFilterListenerますServletContext。最後にServletContextListener#contextDestroyed()が呼び出され、ServletContext自体が破棄されます。

HttpServletRequestHttpServletResponse

サーブレット コンテナーは、特定のポート番号で HTTP 要求をリッスンする Web サーバーに接続されます (通常、ポート 8080 は開発時に使用され、ポート 80 は運用時に使用されます)。クライアント (たとえば、Web ブラウザを使用しているユーザー、またはプログラムで を使用URLConnectionしているユーザー) が HTTP 要求を送信すると、サーブレット コンテナーは新しい オブジェクトと オブジェクトを作成HttpServletRequestHttpServletResponse、それらをチェーンで定義さ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 ページ) が到着するまで有効です。他の場所では共有されません。
  • すべてServletFilterおよび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.
    } 
}

以下も参照してください。

于 2010-06-24T02:41:44.627 に答える
42

Session in Java servlets is the same as session in other languages such as PHP. It is unique to the user. The server can keep track of it in different ways such as cookies, url rewriting etc. This Java doc article explains it in the context of Java servlets and indicates that exactly how session is maintained is an implementation detail left to the designers of the server. The specification only stipulates that it must be maintained as unique to a user across multiple connections to the server. Check out this article from Oracle for more information about both of your questions.

Edit There is an excellent tutorial here on how to work with session inside of servlets. And here is a chapter from Sun about Java Servlets, what they are and how to use them. Between those two articles, you should be able to answer all of your questions.

于 2010-06-24T00:20:59.583 に答える
33

サーブレット コンテナ (Apache Tomcat など) が起動すると、何か問題が発生したり、コンテナ側のコンソールにエラーが表示されたりした場合は、web.xml ファイル (アプリケーションごとに 1 つだけ) から読み取ります。それ以外の場合は、すべての Web をデプロイしてロードしますweb.xml を使用してアプリケーションを作成します (デプロイメント記述子と呼ばれます)。

サーブレットのインスタンス化フェーズでは、サーブレット インスタンスの準備ができていますが、次の 2 つの情報が欠落しているため、クライアント要求を処理できません:
1: コンテキスト情報
2: 初期構成情報

サーブレット エンジンは、上記の不足している情報をカプセル化する servletConfig インターフェース オブジェクトを作成し、サーブレット エンジンは、servletConfig オブジェクト参照を引数として提供することにより、サーブレットの init() を呼び出します。init() が完全に実行されると、サーブレットはクライアント要求を処理する準備が整います。

Q) サーブレットの存続期間中に、インスタンス化と初期化が何回発生しますか??

A) 1 回だけ (クライアント要求ごとに新しいスレッドが作成される)、サーブレットの 1 つのインスタンスのみが任意の数のクライアント要求を処理します。つまり、1 つのクライアント要求を処理した後、サーバーは停止しません。他のクライアント要求を待ちます。つまり、CGI (クライアント要求ごとに新しいプロセスが作成される) の制限がサーブレットで克服されます (内部でサーブレット エンジンがスレッドを作成します)。

Q) セッションのコンセプトはどのように機能しますか?

A) getSession() が HttpServletRequest オブジェクトで呼び出されるたびに

ステップ 1 : 受信セッション ID について要求オブジェクトが評価されます。

ステップ 2 : ID が使用できない場合、新しい HttpSession オブジェクトが作成され、対応するセッション ID が生成されます (つまり、HashTable の) セッション ID が httpservlet 応答オブジェクトに格納され、HttpSession オブジェクトの参照がサーブレット (doGet/doPost) に返されます。 .

ステップ 3 : ID が使用可能な場合、新しいセッション オブジェクトが作成されない場合 セッション ID は、リクエスト オブジェクトから取得され、セッション ID をキーとしてセッションのコレクション内で検索が行われます。

検索が成功すると、セッション ID が HttpServletResponse に格納され、既存のセッション オブジェクト参照が UserDefineservlet の doGet() または doPost() に返されます。

ノート:

1) 制御がサーブレット コードからクライアントに移るとき、セッション オブジェクトがサーブレット コンテナ、つまりサーブレット エンジンによって保持されていることを忘れないでください。

2) マルチスレッドの実装は、サーブレット開発者に任されています。つまり、クライアントの複数の要求を処理するため、マルチスレッド コードを気にする必要はありません。

短縮形:

サーブレットは、アプリケーションの起動時 (サーブレット コンテナーにデプロイされる) に作成されるか、最初にアクセスされたときに (開始時のロード設定に応じて) サーブレットがインスタンス化されるときに作成され、サーブレットの init() メソッドが呼び出されます。次に、サーブレット (その唯一のインスタンス) がすべての要求を処理します (その service() メソッドは複数のスレッドによって呼び出されます)。そのため、同期を行うことはお勧めできません。また、アプリケーションがアンデプロイされたとき (サーブレット コンテナーが停止したとき)、 destroy() メソッドが呼び出されるときは、サーブレットのインスタンス変数を避ける必要があります。

于 2012-02-22T12:54:18.117 に答える
21

セッション-クリス・トンプソンが言ったこと。

インスタンス化-サーブレットは、コンテナがサーブレットにマップされた最初のリクエストを受信したときにインスタンス化されます(サーブレットが起動時に<load-on-startup>要素を使用してロードするように構成されている場合を除くweb.xml)。同じインスタンスが後続のリクエストを処理するために使用されます。

于 2010-06-24T00:27:46.483 に答える
13

サーブレット仕様JSR-315は、サービス (および doGet、doPost、doPut など) メソッドでの Web コンテナーの動作を明確に定義しています (2.3.3.1 マルチスレッドの問題、ページ 9)。

サーブレット コンテナは、サーブレットのサービス メソッドを通じて同時リクエストを送信できます。リクエストを処理するために、サーブレット開発者は、サービス メソッドで複数のスレッドによる同時処理を適切に準備する必要があります。

推奨されていませんが、開発者にとっての代替手段は、SingleThreadModel インターフェイスを実装することです。このインターフェイスでは、サービス メソッドで一度に 1 つの要求スレッドのみが存在することをコンテナーに保証する必要があります。サーブレット コンテナーは、サーブレットで要求をシリアル化するか、サーブレット インスタンスのプールを維持することで、この要件を満たすことができます。サーブレットが配布可能としてマークされた Web アプリケーションの一部である場合、コンテナーは、アプリケーションが配布される各 JVM でサーブレット インスタンスのプールを維持できます。

SingleThreadModel インターフェイスを実装しないサーブレットの場合、サービス メソッド (または HttpServlet 抽象クラスのサービス メソッドにディスパッチされる doGet や doPost などのメソッド) が synchronized キーワードで定義されている場合、サーブレット コンテナーはインスタンス プール アプローチを使用できません。 、ただし、それを介してリクエストをシリアル化する必要があります。パフォーマンスに悪影響を与えるため、このような状況ではサービス メソッド (またはサービス メソッドにディスパッチされたメソッド) を同期しないことを強くお勧めします。

于 2014-03-05T11:41:57.033 に答える