1

複数のサーブレットが事前初期化に一定量の同一のロジックを使用する Web アプリケーションがあります (ログの設定、セッション追跡など)。私がしたことはjavax.servlet.http.HttpServlet、具体的なサーブレット クラスとの間に中間レベルを導入することでした。

public abstract class AbstractHttpServlet extends HttpServlet {
    // ... some common things ...
}

その後:

public class MyServlet extends AbstractHttpServlet {
    // ... specialized logic ...
}

AbstractHttpServlet のデフォルト (かつ唯一の) コンストラクターで行うことの 1 つは、いくつかのプライベート メンバー変数を設定することです。この場合、それはセッション識別子として機能する UUID です。

public abstract class AbstractHttpServlet extends HttpServlet {
    private UUID sessionUuid;

    public AbstractHttpServlet() {
        super();
        this.sessionUuid = UUID.randomUUID();
        // ... there's more, but snipped for brevity ...
    }

    protected UUID getSessionUuid() {
        return this.sessionUuid;
    }
}

次に、 in を使用getSessionUuid()MyServletて、リクエスト内でセッション トラッキングを提供します。これは、たとえばロギングで、大きなログ ファイルをふるいにかけ、単一の HTTP 要求に関連するすべてのエントリを取得できるため、非常に便利です。原則として、セッション識別子は何でもかまいません。UUID を使用することを選択したのは、ランダムな ID を簡単に生成でき、異なるサーバー間の衝突、シードの問題、ログ ファイルを検索して長い文字列の一部として一致を検出することなどを心配する必要がないためです。

複数の実行がメンバー変数で同じ値を取得する理由はわかりませんsessionUuidが、実際にはそうであるように見えます。クラスのインスタンスが長期間にわたって複数のリクエストに再利用されているかのようです (サーバー プロセスが再起動されるまで)。

私の場合、クラスのインスタンス化のオーバーヘッドは、クラスによって行われる有用な作業に比べて小さいので、理想的には、Tomcat がリクエストごとに常に新しいクラス インスタンスを作成し、コンストラクターを毎回個別に実行するように強制したいと考えています。クラスに注釈を付けて、リクエストごとにインスタンス化されるようにすることは可能ですか? サーバー構成の変更を必要としない回答がはるかに優先されます。

それに失敗した場合、特定のサーブレットの実行につながるHTTP リクエストごとに何らかの初期化が行われるようにするdoGet()方法はありますか ( 、doPost()などの各 do*() メソッドで個別に行う以外に) ?

4

3 に答える 3

0

クラスのインスタンスが長期間にわたって複数のリクエストに再利用されているかのようです。

JVMごとに、任意の時点で Servlet クラスのインスタンスが常に 1 つ存在します。したがって、インスタンス変数はサーブレットではスレッドセーフではありません。サーブレットに対する各リクエストは、スレッドによって処理されます。service()内で宣言されたローカル変数は、スレッド セーフになりますdoPost()doGet()

  1. したがって、ロジックを他のクラスに移動し、サービス メソッド内でインスタンス化して、スレッド セーフな方法で使用できます。ThreadLocal オブジェクトを使用することもできます。

  2. SingleThreadModelを実装するための規定がありますが、これは非推奨です。そうするのは悪いだけでなくばかげています。

    サーブレットが一度に 1 つの要求のみを処理するようにします。このインターフェイスにはメソッドがありません。

    サーブレットがこのインターフェースを実装する場合、サーブレットのサービス メソッドで 2 つのスレッドが同時に実行されないことが保証されます。サーブレット コンテナーは、サーブレットの 1 つのインスタンスへのアクセスを同期するか、サーブレット インスタンスのプールを維持し、新しい要求をそれぞれ空きサーブレットにディスパッチすることによって、この保証を行うことができます。

  3. ServletRequestListenerを実装し、そこにロジックを配置することをお勧めします。

于 2013-07-03T09:36:06.390 に答える