カテゴリ: Jakarta EE 更新日: 2026/02/02

JakartaEE サーブレットのスレッドセーフとフィルタ利用時の注意点を徹底解説!初心者でも安心の入門ガイド

Jakarta EE サーブレットのスレッドセーフとフィルタ利用時の注意点
Jakarta EE サーブレットのスレッドセーフとフィルタ利用時の注意点

先生と生徒の会話形式で理解しよう

生徒

「先生、JakartaEEのサーブレットって複数のユーザーが同時にアクセスしたらどうなるんですか?」

先生

「いい質問ですね。サーブレットはデフォルトでシングルトンとして動作するので、同じインスタンスに複数のスレッドが同時に入ってきます。つまりスレッドセーフを意識しないと予期しない不具合が起きるんです。」

生徒

「なるほど…。じゃあ、フィルタを使う場合も同じように気を付ける必要があるんですか?」

先生

「その通りです。サーブレットもフィルタもライフサイクルが似ているので、共通の注意点があるんです。具体的に見ていきましょう。」

1. JakartaEE サーブレットのスレッドセーフとは?

1. JakartaEE サーブレットのスレッドセーフとは?
1. JakartaEE サーブレットのスレッドセーフとは?

JakartaEE のサーブレットは、リクエストごとに新しいインスタンスが生成されるわけではなく、通常は一つのサーブレットインスタンスが再利用されます。そのため、同じサーブレットに対して同時に複数のユーザーがアクセスすると、複数のスレッドが並行して実行されることになります。これを「サーブレットのスレッドモデル」と呼びます。

もしサーブレット内でインスタンス変数を不用意に使うと、同時アクセスで変数が上書きされてしまい、データの整合性が失われる危険があります。これが「スレッドセーフでない状態」です。例えばログイン処理やセッション管理をインスタンス変数で持ってしまうと、ユーザーの情報が混ざってしまうケースが発生します。

2. サーブレットでスレッドセーフを確保する方法

2. サーブレットでスレッドセーフを確保する方法
2. サーブレットでスレッドセーフを確保する方法

サーブレットをスレッドセーフにするためには、次のポイントを守ることが大切です。

  • インスタンス変数を使わず、ローカル変数にデータを格納する
  • 必要な情報は HttpServletRequestHttpSession に保持する
  • 共有リソースを操作する場合は synchronized ブロックなどを用いて排他制御する

例えば次のコードは良くない例です。複数のユーザーが同時にアクセスすると message が上書きされてしまいます。


@WebServlet("/unsafe")
public class UnsafeServlet extends HttpServlet {
    private String message; // インスタンス変数に状態を持ってしまっている

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        message = "Hello " + req.getParameter("user");
        resp.getWriter().println(message);
    }
}

3. フィルタ利用時のスレッドセーフの注意点

3. フィルタ利用時のスレッドセーフの注意点
3. フィルタ利用時のスレッドセーフの注意点

JakartaEE の フィルタもサーブレットと同じようにシングルトンで管理されます。つまり、複数のリクエストが同時に同じフィルタインスタンスを通過するため、インスタンス変数の扱いには注意が必要です。

例えばログの記録やリクエストの検証などを行うフィルタはよく使われますが、状態を持たせると予期しない動作が起きます。ログの内容が別のユーザーに混ざることもあり得ます。


@WebFilter("/*")
public class UnsafeFilter implements Filter {
    private String user; // 危険なインスタンス変数

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        user = request.getParameter("user");
        System.out.println("User: " + user);
        chain.doFilter(request, response);
    }
}

このコードでは同時リクエスト時に user が上書きされ、ログに誤ったユーザー情報が出力される恐れがあります。解決策としては、必ずローカル変数を使うことが推奨されます。

4. フィルタで安全に状態を扱う方法

4. フィルタで安全に状態を扱う方法
4. フィルタで安全に状態を扱う方法

フィルタ内で必要な情報は、必ずメソッド内のローカル変数で保持しましょう。次の例のように書けば、同時リクエストでも安全に動作します。


@WebFilter("/*")
public class SafeFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String user = request.getParameter("user"); // ローカル変数で保持
        System.out.println("User: " + user);
        chain.doFilter(request, response);
    }
}

このようにフィルタでスレッドセーフを守ることで、ログや認証処理を安全に行うことができます。

5. サーブレットとフィルタで共通する設計上のポイント

5. サーブレットとフィルタで共通する設計上のポイント
5. サーブレットとフィルタで共通する設計上のポイント

JakartaEE サーブレットとフィルタのスレッドセーフを意識する上で、次のような共通点を押さえておくと安全です。

  • インスタンス変数でリクエストごとの状態を持たない
  • スレッド間で共有する必要がある場合は適切な排他制御を行う
  • スレッドローカル(ThreadLocal)を使うことで、一時的なスレッドごとのデータ管理も可能
  • ステートレスな設計を心掛けると安全で保守性も高くなる

特に初心者は「インスタンス変数を極力使わない」というルールを守るだけでも大きなトラブルを防げます。

6. 実務でよくあるスレッドセーフの落とし穴

6. 実務でよくあるスレッドセーフの落とし穴
6. 実務でよくあるスレッドセーフの落とし穴

実際の開発現場では、便利だからといってサーブレットやフィルタにキャッシュや一時的な値をインスタンス変数として持たせてしまうケースがよくあります。これがパフォーマンスの低下やデータの混在を引き起こす原因になります。

また、認証情報やユーザーIDなどをフィルタのインスタンス変数で持つと、セキュリティ事故につながることがあります。そのため、初心者はまず「状態を持たせない」ことを強く意識しましょう。

関連記事:
カテゴリの一覧へ
新着記事
New1
Jakarta EE
Jakarta EEとクラウドネイティブ開発の相性とは?初心者向けにわかりやすく解説
New2
Jakarta EE
JakartaEE JSPのリクエスト属性とスコープの基本を徹底解説!初心者向け入門ガイド
New3
Play Framework
Play Frameworkのビューテストを徹底解説!Twirlテンプレートの品質を高める方法
New4
Jakarta EE
JakartaEE フィルタで認証と認可を実装する方法を初心者向けに解説!サーブレットのセキュリティ入門
人気記事
No.1
Java&Spring記事人気No1
Jakarta EE
Jakarta EEとSpringの比較|どちらを選ぶべきか?初心者向けに徹底解説!
No.2
Java&Spring記事人気No2
Play Framework
Play Frameworkのビューを共通化!テンプレート間のインクルード方法を徹底解説
No.3
Java&Spring記事人気No3
Play Framework
Play Frameworkプロジェクト作成直後にやるべき初期設定ガイド!初心者でも安心
No.4
Java&Spring記事人気No4
Jakarta EE
Jakarta サーブレットのHttpServletRequestを徹底解説!初心者でもわかる基本操作と使い方
No.5
Java&Spring記事人気No5
Play Framework
Play Frameworkで多言語対応(i18n)を徹底解説!Twirlテンプレートでの使い方
No.6
Java&Spring記事人気No6
Play Framework
Play FrameworkでCSSやJavaScriptを読み込む方法を徹底解説!静的リソースの組み込みガイド
No.7
Java&Spring記事人気No7
Jakarta EE
Jakarta EEとJava EEアプリの互換性を完全解説!移行で困らないための基礎知識
No.8
Java&Spring記事人気No8
Jakarta EE
Jakarta EEの標準仕様とAPI一覧を完全解説!初心者でもわかるエンタープライズJavaの基本