はじめに
株式会社Good Labでエンジニアをしている コータロー です。
日々、Java・SQL・Gitなどの技術情報や、新人エンジニア向けの学習ノウハウ、
AI活用についての情報を発信しています。
Good Labについて気になった方は、コーポレートサイトもぜひご覧ください。
▶コーポレートサイト
「Java用語、結局なんだっけ?」シリーズの第3回です。
| 回 | テーマ |
|---|---|
| #1 | 環境・基盤編 |
| #2 | DB接続編 |
| #3(本記事) | Web/サーバー編 |
| #4 | 例外・スレッド編 |
| #5 | モダンJava編 |
| #6 | フレームワーク編 |
| #7 | ビルド・運用編 |
今回は Web/サーバー編 です。Spring Boot 全盛の今でも、内部で動いているのは「サーブレット」と「Webコンテナ」。現場で必ず出てくる土台用語 を整理します。
この記事のゴール
- サーブレット・JSP・Tomcatの関係を説明できる
- WAR ファイルとは何か説明できる
- フィルタの役割を説明できる
- ステートフル / ステートレスを使い分けられる
全体像:ブラウザからJavaアプリまで
[ブラウザ]
↓ HTTPリクエスト
[Webコンテナ(Tomcat等)] ← サーバー本体
↓ サーブレット仕様に沿って渡す
[フィルタ] ← 前処理(認証、ログ等)
↓
[サーブレット / JSP] ← アプリ本体
↓ HTTPレスポンス
[ブラウザ]
これらの用語を7つに分けて解説します。
① サーブレット ― 「HTTPリクエストを処理するJavaクラス」
一言で言うと
HTTPリクエストを受け取り、HTTPレスポンスを返すJavaクラス です。
Web版の「main関数」のような役割を果たします。
概念コード(最小サンプル)
// ※ 実際のサーブレットは jakarta.servlet-api 依存が必要
public class UserServlet {
void service(HttpRequest request, HttpResponse response) {
if (request.getMethod().equals("GET")) {
response.setStatus(200);
response.setBody("User found: " + request.getParam("id"));
}
}
}
実際の HttpServlet を継承する書き方:
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String id = req.getParameter("id");
resp.setStatus(200);
resp.getWriter().write("User ID: " + id);
}
}
サーブレットは何が嬉しい?
- HTTPプロトコルの低レベルな部分(ヘッダ解析、Content-Length、Cookie等)を すべてコンテナ側がやってくれる
- 開発者は 「リクエストを受けて、レスポンスを返す」 ロジックだけ書けばよい
よくある誤解
- 「サーブレット = 古い技術、もう使わない」:Spring MVC や Spring Boot の内部は サーブレット仕様の上に乗っている。直接書かないだけで、間接的には現役。
- 「サーブレットは小さなアプリ」:「Servlet」は「Server-let(サーバーで動く小プログラム)」が由来だが、実体は普通のJavaクラス。
② JSP(JavaServer Pages) ― 「HTMLにJavaを埋め込むテンプレート」
一言で言うと
HTMLの中にJavaコードを書けるテンプレート技術です。
拡張子は .jsp。実行時にサーブレットに変換されます。
コード例
<%@ page contentType="text/html; charset=UTF-8" %>
<%
String name = (String) request.getAttribute("userName");
%>
<html>
<body>
<h1>こんにちは、<%= name %>さん</h1>
</body>
</html>
<% %> の中はJavaコード、<%= %> は「式の値を出力」という記号。
現代でJSPは使われている?
新規開発では ほとんど使われません。代わりに以下が主流:
| 用途 | 現代の選択肢 |
|---|---|
| サーバーサイドテンプレート | Thymeleaf、FreeMarker |
| API(JSONを返す) | Spring @RestController + Jackson |
| SPA(ブラウザ側で描画) | React、Vue、Angular |
ただし 既存のレガシー案件には大量に存在 するので、SES現場では今でも触ることがあります。
よくある誤解
- 「JSPはJavaScriptと同じもの」:全くの別物。JSPはサーバーサイド、JavaScriptはブラウザサイド。
- 「JSP内でビジネスロジックを書く」:アンチパターン。JSPは「表示専用」で、ロジックはサーブレット(または Controller)で書くのが正解。
③ Webコンテナ ― 「サーブレットを動かすサーバー」
一言で言うと
サーブレット仕様に従ってJavaのWebアプリを動かすサーバー です。
代表例は Tomcat。
何をしてくれる?
| 機能 | 説明 |
|---|---|
| HTTP受信 | ポートを開いてリクエストを受信 |
| マッピング | URLとサーブレットを紐付け(例:/users → UserServlet) |
| ライフサイクル管理 | サーブレットの初期化(init)・破棄(destroy) |
| スレッド管理 | 1リクエスト=1スレッドで並列処理 |
| JSP変換 |
.jsp をサーブレットに変換して実行 |
主なWebコンテナ
| 名前 | 概要 |
|---|---|
| Tomcat | 業界標準のOSS。Spring Boot にも組み込み版が同梱 |
| Jetty | 軽量・高速。組み込み用途で人気 |
| Undertow | Red Hat製。Spring Boot WebFlux等で採用 |
| GlassFish / WildFly | Java EE / Jakarta EE 対応のフルスタック |
Spring Boot は Tomcat を「内蔵」している
新人がよく混乱するのが「Spring Boot は Tomcat なしで動くのか?」という疑問。
答えは 「内蔵Tomcatで動いている」 です。
java -jar myapp.jar ← jarファイル1つで起動
↓ Spring Boot が内部的に Tomcat を起動
↓ Tomcat がサーブレットコンテナとして機能
↓ Spring の DispatcherServlet がリクエストを受ける
「サーバーにTomcatをインストール → WARをデプロイ」という昔のスタイルは、現代の新規案件ではほぼ無くなりました。
よくある誤解
- 「Tomcat = サーバーOS」:違う。Tomcatは JavaのプロセスとしてLinux/Windows上で動く。
- 「Spring Boot は Tomcat を置き換えた」:違う。Spring Boot は Tomcat を内蔵して使っている。
④ WARファイル ― 「Webアプリ用のJAR」
一言で言うと
Webアプリ専用のパッケージング形式 です。
JARとほぼ同じZIP形式ですが、WEB-INF/ などのWebアプリ固有のディレクトリ構造を含みます。
構造
myapp.war
├── WEB-INF/
│ ├── web.xml ← サーブレットの設定(古い形式)
│ ├── classes/ ← .class ファイル
│ │ └── com/example/UserServlet.class
│ └── lib/ ← 依存JARファイル
│ └── mysql-connector.jar
├── index.jsp
└── css/
└── style.css
JAR / WAR / EAR の使い分け
| 形式 | 用途 | 中身 |
|---|---|---|
| JAR | 通常のJavaライブラリ・アプリ |
.class + リソース |
| WAR | Webアプリ | JAR + WEB-INF/ + 静的ファイル |
| EAR | Enterprise Java(複数モジュール) | JAR + WAR + 設定 |
Spring Boot は WAR ではなく「実行可能JAR」
# 昔のJava EEスタイル
$ mvn package # → target/myapp.war
$ # Tomcatにデプロイ
# 現代のSpring Bootスタイル
$ mvn package # → target/myapp.jar(実行可能JAR)
$ java -jar target/myapp.jar
Spring Boot の「実行可能JAR」は 内部にTomcatごと含む ため、サーバーに別途Tomcatをインストールする必要がありません。
よくある誤解
-
「WAR と JAR は中身が違う」:構造は似ているが、
WEB-INF/の有無で区別される。 - 「Spring Boot はWARを作る」:通常は JAR を作る。設定変更でWARも作れるが、新規案件ではほぼJAR。
⑤ フィルタ ― 「リクエスト前後の共通処理」
一言で言うと
サーブレットに到達する前 / 後に共通処理を挟む仕組み です。
認証、ログ、文字コード変換などに使います。
図解
[ブラウザ]
↓
[フィルタ1: 認証チェック] ← 認証NGならここで弾く
↓
[フィルタ2: アクセスログ]
↓
[サーブレット / Controller] ← 本処理
↓
[フィルタ2: レスポンス記録]
↓
[フィルタ1: ヘッダ追加]
↓
[ブラウザ]
リクエスト時は 上から下 に通り、レスポンス時は 下から上 に戻ります。
コード例(イメージ)
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import java.io.IOException;
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, jakarta.servlet.ServletException {
// 前処理(認証チェック)
if (!isAuthenticated(req)) {
// 認証NG → ここで止める(次のフィルタやサーブレットを呼ばない)
return;
}
chain.doFilter(req, resp); // ← 次のフィルタ or サーブレットへ
// 後処理(レスポンスログなど)
}
private boolean isAuthenticated(ServletRequest req) {
// 実装
return true;
}
}
chain.doFilter を呼ばないと 後続のサーブレットに到達しない のがポイント。これで「認証NGなら処理を弾く」が実現できます。
よくある用途
| 用途 | 例 |
|---|---|
| 認証 | ログインしていないなら /login へリダイレクト |
| アクセスログ | URL・IP・処理時間を記録 |
| 文字コード | request.setCharacterEncoding("UTF-8") |
| CORS | レスポンスヘッダに Access-Control-Allow-Origin を追加 |
| 圧縮 | gzipで圧縮してレスポンス |
よくある誤解
- 「フィルタ = サーブレット」:違う。フィルタは 共通処理、サーブレットは 本処理。
-
「フィルタは1個しか付けられない」:複数チェインできる。順序は
web.xmlまたは@Orderで制御。
⑥ Webコンテナ vs アプリケーションサーバー ― 用語の整理
新人が混乱しやすい区別です。
| 用語 | 範囲 | 例 |
|---|---|---|
| Webコンテナ(サーブレットコンテナ) | サーブレット仕様だけ実装 | Tomcat、Jetty |
| アプリケーションサーバー | サーブレット + EJB + JMS + JTA など Jakarta EE 全体 | GlassFish、WildFly |
新規案件では Spring Boot + Tomcat(Webコンテナのみ) が圧倒的多数。
GlassFish や WildFly のようなフルスタックは、大規模なエンタープライズ案件で残っている程度です。
⑦ ステートフル / ステートレス ― 状態を持つか持たないか
一言で言うと
| 用語 | 意味 | 例 |
|---|---|---|
| ステートフル | サーバーが前回のやり取りを覚えている | セッションを使うログイン状態管理 |
| ステートレス | サーバーが何も覚えていない。毎回独立 | REST API(トークンを毎回送る) |
ステートフルの例(セッション)
// ログイン時
session.setAttribute("userId", 1234);
// 次のリクエスト
Long userId = (Long) session.getAttribute("userId"); // 覚えている
サーバー側にユーザーごとの状態(セッション)が保存されます。
ステートレスの例(JWT認証)
クライアント → サーバー
Authorization: Bearer <JWTトークン> ← 毎回送る
サーバーは JWT を検証するだけで、サーバー側に状態を保持しない
どちらを選ぶ?
| 観点 | ステートフル | ステートレス |
|---|---|---|
| スケーラビリティ | △(同じユーザーは同じサーバーに送る必要) | ◎(どのサーバーに送ってもOK) |
| 実装の単純さ | ◎ | △(トークン管理が必要) |
| マイクロサービス向き | △ | ◎ |
近年は マイクロサービス+ステートレス(JWT) がトレンドです。
よくある誤解
- 「ステートフル = データベースを使う」:違う。状態は サーバーのメモリ(セッション) に持つ。DB保存とは別。
- 「ステートレスならセッション不要」:その通り。ただし「ログイン状態の表現方法」は別途必要(JWT等)。
用語まとめ早見表
| 用語 | 一言で |
|---|---|
| サーブレット | HTTPを処理するJavaクラス(Web版のmain) |
| JSP | HTMLにJavaを埋め込むテンプレート(レガシー寄り) |
| Webコンテナ | サーブレットを動かすサーバー(Tomcat等) |
| WARファイル | Webアプリ用のJAR(WEB-INF/ を含む) |
| フィルタ | サーブレットの前後に挟む共通処理(認証、ログ等) |
| アプリサーバー | Webコンテナ + Jakarta EE 全体(GlassFish等) |
| ステートフル / ステートレス | サーバーが状態を持つか持たないか |
現場あるある誤解集
| ❌ 誤解 | ⭕ 正しい理解 |
|---|---|
| 「Spring Boot は Tomcat を不要にした」 | 内蔵Tomcatで動いている |
| 「JSP は今でも新規開発で使う」 | 新規ではほぼ使わない。Thymeleaf等に移行 |
| 「WAR と JAR は中身が全然違う」 | 構造は似ている。WEB-INF/ の有無で区別 |
| 「フィルタとサーブレットは同じ」 | フィルタは共通処理、サーブレットは本処理 |
| 「Tomcat = サーバーOS」 | Linux/Windows上で動くJavaプロセス |
| 「ステートレス = データを持たない」 | サーバー側に「状態」を持たないだけ。DBには持つ |
| 「web.xml が必須」 | Servlet 3.0以降は @WebServlet でアノテーション設定可 |
演習問題
問題1:Webコンテナとサーブレット ⭐
次の文章の空欄を埋めてください。
「ブラウザからHTTPリクエストが来ると、まず ___ がリクエストを受け取る。
その後、URLと対応する ___ にリクエストが渡され、Javaのコードが実行される。
___ では認証やログなどの共通処理を、本処理の前後に挟むことができる。」
模範解答
「ブラウザからHTTPリクエストが来ると、まず Webコンテナ(Tomcat等) がリクエストを受け取る。
その後、URLと対応する サーブレット にリクエストが渡され、Javaのコードが実行される。
フィルタ では認証やログなどの共通処理を、本処理の前後に挟むことができる。」
ポイント:「Webコンテナ → フィルタ → サーブレット」の流れを押さえる。Spring MVCも内部はこの仕組み。
問題2:JAR / WAR の使い分け ⭐
次のうち、WARファイル にパッケージングするのが適切なのはどれですか?
- A. 数学計算ライブラリ(他のJavaプロジェクトから使う)
- B. コマンドラインで動くバッチアプリ
- C. ブラウザからアクセスするWeb管理画面
- D. JUnit のテストランナー
模範解答
正解:C
解説:
-
C はWAR:Webアプリなので
WEB-INF/、サーブレット、JSP等が必要 → WARが適切 - A、B、D はJAR:Web機能不要なので通常のJARで十分
ポイント:Spring Boot の新規案件では、Webアプリでも 実行可能JAR を作るのが主流。WARはレガシーや、外部Tomcatにデプロイする要件がある場合のみ。
問題3:ステートフル vs ステートレス ⭐
次のうち、ステートレス な設計はどれですか?
- A. ログイン時にセッションにユーザーIDを保存し、次のリクエストで参照する
- B. リクエストごとにJWTトークンを送り、サーバー側で検証する
- C. サーバーのHashMapにユーザーごとのカート情報を保持する
- D. ユーザーがログインすると、サーバー側のメモリに認証情報を記憶する
模範解答
正解:B
解説:
- B はステートレス:JWTを毎回送り、サーバー側は 何も覚えていない。検証だけする。
- A、C、D は サーバー側がユーザーごとの状態を持っている ステートフル設計
ポイント:マイクロサービス・クラウドネイティブ時代では ステートレスがトレンド。複数サーバーで負荷分散しやすく、ある1台が落ちても他で処理を続けられる。
まとめ
Web/サーバー編の7用語のおさらいです。
- サーブレット:HTTPリクエストを処理するJavaクラス
- JSP:HTMLにJavaを埋め込むテンプレート(レガシー寄り)
- Webコンテナ(Tomcat等):サーブレットを動かすサーバー
-
WARファイル:Webアプリ用のJAR(
WEB-INF/を含む) - フィルタ:サーブレットの前後に挟む共通処理
- Webコンテナ vs アプリサーバー:仕様カバー範囲の違い
- ステートフル / ステートレス:状態を持つかどうか
Spring Boot を使っていても、内部はサーブレットの上に乗っている ことを理解しておくと、フレームワーク独自の動きにも対応しやすくなります。
次回予告
次回(#4)は 例外・スレッド編 です。
- checked / unchecked 例外の使い分け
- スレッド・synchronized・volatile
- デッドロックとは何か
を解説します。
参考
@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!