JSTLとは何か
JavaServer Pages Standard Tag Library(JSTL)は、JSPでよく使用される機能をタグ形式で提供する標準ライブラリです。JSTLを使用することで、スクリプトレット(<% … %>)に依存せず、より読みやすく保守性の高いJSPページを作成できます。
JSTL(JavaServer Pages Standard Tag Library)は、JSPで使用できる標準タグライブラリです。Javaのスクリプトコードを直接記述する機会を減らし、HTMLに近い分かりやすい記述ができます。

また、画面表示(プレゼンテーション)と処理(ロジック)を分離しやすくなるため、保守性の高いWebアプリケーションを作成できます。JSTLは用途ごとに5つのカテゴリのタグライブラリで構成されており、独自のカスタムタグを作成する場合と比べて学習コストが低く、手軽に利用できる点も特徴です。特にCoreタグライブラリは、JSTLの中でも最も基本的で頻繁に使用されるタグセットです。
JSTL Coreタグライブラリの基本
JSTL Coreタグライブラリとは、JSTLの中でも最も基本的な機能を提供するタグライブラリです。条件分岐(if)、繰り返し処理(forEach)、変数の操作(set・remove)、画面遷移(redirect・url)など、Webアプリケーションでよく使用する基本的な処理をタグだけで記述できます。
JSTLの導入
JSTL(今回はCoreタグライブラリ)を使用するには、まずJSPページでタグライブラリを宣言する必要があります。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
この宣言により、c:というプレフィックス(接頭辞)でCoreタグライブラリのタグを使用できるようになります。プレフィックスとはこのタグはJSTL Coreタグライブラリのタグですという目印の役割を持っています。
JSTLを利用すると、HTMLに近い読みやすいコードになり、画面表示と処理を分離しやすくなるため、保守性の高いWebアプリケーションを作成できます。そのため、現在ではスクリプトレットではなくJSTLの利用が推奨されています。
以下ではスクリプトレットとJSTLの使用の違いを検証します。
変数操作タグ
<c:set> – 変数の設定
スクリプトレットでの変数設定
<% request.setAttribute("message", "Hello World!"); %>
JSTLを使用した場合
<c:set>タグは、JSTLで変数や属性に値を設定するためのタグです。var属性には作成する変数名を指定し、value属性には設定する値を指定します。また、scope属性では変数を保存する範囲(スコープ)を指定でき、page、request、session、applicationの4種類から選択します。
<c:set var="message" value="Hello World!" scope="request"/>
例えば、<c:set var=”message” value=”Hello World!” scope=”request”/>と記述すると、requestスコープにmessageという名前で”Hello World!”という値が保存されます。
<c:remove> – 変数の削除
スクリプトレットでの変数削除
<% request.removeAttribute("message"); %>
JSTLを使用した場合
<c:remove var="message" scope="request"/>
条件分岐タグ
<c:if> – 単純な条件分岐
スクリプトレットでの条件分岐
<% if(user.isAdmin()) { %>
管理者メニューを表示
<% } %>
JSTLを使用した場合
<c:if>タグは、指定した条件が真(true)の場合にだけ、タグ内の内容を表示するためのタグです。条件はtest属性に指定し、EL(Expression Language)を使用して記述します。
<c:if test="${user.admin}">
<p>管理者メニューを表示</p>
</c:if>
例えば、<c:if test=”${user.admin}”>と記述すると、userのadminプロパティがtrueの場合にのみ、「管理者メニューを表示」という内容が画面に表示されます。スクリプトレットのif文と同じ役割を持ちますが、Javaコードを直接記述する必要がないため、HTMLに近い読みやすいコードになります。
<c:choose>, <c:when>, <c:otherwise> – 複雑な条件分岐
スクリプトレットでのswitch文
<%
switch(status) {
case 1:
%>
ステータス: 新規
<%
break;
case 2:
%>
ステータス: 処理中
<%
break;
default:
%>
ステータス: 不明
<% } %>
JSTLを使用した場合
<c:choose>
<c:when test="${status == 1}">
<p>ステータス: 新規</p>
</c:when>
<c:when test="${status == 2}">
<p>ステータス: 処理中</p>
</c:when>
<c:otherwise>
<p>ステータス: 不明</p>
</c:otherwise>
</c:choose>
ループ処理タグ
<c:forEach> – コレクションの反復処理
スクリプトレットでのループ
<ul>
<%
List<String> items = (List<String>)request.getAttribute("items");
for(String item : items) {
%>
<li><%= item %></li>
<% } %>
</ul>
JSTLを使用した場合
<c:forEach>タグは、リストや配列などのコレクションを繰り返し処理するためのタグです。items属性には繰り返し処理の対象となるコレクションを指定し、var属性には各要素を受け取る変数名を指定します。また、varStatus属性を指定すると、現在の繰り返し回数や先頭・末尾かどうかなどのループ状態を取得できます。
<ul>
<c:forEach items="${items}" var="item">
<li>${item}</li>
</c:forEach>
</ul>
例えば、<c:forEach items=”${items}” var=”item”>と記述すると、itemsに格納された要素を1つずつitemに取り出して処理します。この例では、各要素を<li>タグで表示し、リストとして画面に出力しています。
インデックスを使ったループ
スクリプトレットでのインデックスループ
<% for(int i=1; i<=10; i++) { %>
アイテム <%= i %>
<% } %>
JSTLを使用した場合
<c:forEach var="i" begin="1" end="10">
<p>アイテム ${i}</p>
</c:forEach>
URL関連タグ
<c:url> – URLの構築
スクリプトレットでのURL構築
<a href="<%= response.encodeURL("products.jsp?id=" + productId) %>">商品詳細</a>
JSTLを使用した場合
<a href="<c:url value='products.jsp'>
<c:param name='id' value='${productId}'/></c:url>">商品詳細
</a>
<c:redirect> – リダイレクト
スクリプトレットでのリダイレクト
<% response.sendRedirect("home.jsp"); %>
JSTLを使用した場合
<c:redirect url="home.jsp"/>
例外処理タグ
<c:catch> – 例外処理
スクリプトレットでの例外処理
<%
try {
someRiskyOperation();
} catch(Exception e) {
out.println("エラーが発生しました: " + e.getMessage());
}
%>
JSTLを使用した場合
<c:catch var="exception">
<% someRiskyOperation(); %>
</c:catch>
<c:if test="${not empty exception}">
<p>エラーが発生しました: ${exception.message}</p>
</c:if>
JSTL Coreタグの応用例
テーブル表示の例
スクリプトレットを使用した場合
<table>
<tr>
<th>ID</th>
<th>名前</th>
<th>価格</th>
</tr>
<%
List<Product> products = (List<Product>)request.getAttribute("products");
for(Product p : products) {
%>
<tr>
<td><%= p.getId() %></td>
<td><%= p.getName() %></td>
<td class="<%= p.getPrice() > 1000 ? "expensive" : "" %>">
<%= p.getPrice() %>円
</td>
</tr>
<% } %>
</table>
JSTLを使用した場合
<table>
<tr>
<th>ID</th>
<th>名前</th>
<th>価格</th>
</tr>
<c:forEach items="${products}" var="product">
<tr>
<td>${product.id}</td>
<td>${product.name}</td>
<td class="<c:if test='${product.price > 1000}'>expensive</c:if>">
${product.price}円
</td>
</tr>
</c:forEach>
</table>
ページネーションの例
<div class="pagination">
<c:if test="${currentPage > 1}">
<a href="<c:url value='products.jsp'>
<c:param name='page' value='${currentPage - 1}'/>
</c:url>">前へ</a>
</c:if>
<c:forEach var="i" begin="1" end="${totalPages}">
<c:choose>
<c:when test="${i == currentPage}">
<span class="current">${i}</span>
</c:when>
<c:otherwise>
<a href="<c:url value='products.jsp'>
<c:param name='page' value='${i}'/>
</c:url>">${i}</a>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${currentPage < totalPages}">
<a href="<c:url value='products.jsp'>
<c:param name='page' value='${currentPage + 1}'/>
</c:url>">次へ</a>
</c:if>
</div>
JSTL使用時のベストプラクティス
スクリプトレットとの使い分け
JSTLは、画面に表示するための処理を記述するためのタグライブラリです。そのため、条件分岐や繰り返し処理などの表示ロジックはJSTLで記述するのが基本です。一方で、データベースへのアクセスや複雑な計算、業務ルールの判定などのビジネスロジックは、JSPに記述せず、ServletやJavaクラスで処理を行います。このように役割を分けることで、画面と処理が明確に分離され、保守しやすいWebアプリケーションになります。
適切なスコープを選択する
<c:set>で変数を作成する際は、必要最小限のスコープを選択することが重要です。特に指定しない場合はpageスコープが使用され、そのJSPページ内でのみ利用できます。複数の画面で共有する必要がある場合のみrequestやsession、applicationスコープを使用し、不必要に広いスコープを指定しないようにしましょう。不要なスコープを使用すると、予期しない値の上書きやメモリの無駄につながる可能性があります。
タグのネストは深くしすぎない
JSTLでは、<c:if>や<c:forEach>を組み合わせて記述できますが、タグのネストが深くなるほどコードが読みづらくなります。複雑な条件分岐や繰り返し処理が必要な場合は、JSPだけで解決しようとせず、ServletやJavaクラスで必要なデータを準備してからJSPへ渡すようにしましょう。可読性を保つことが、保守しやすいプログラムにつながります。
varStatusを活用する
<c:forEach>のvarStatus属性を利用すると、ループの状態を取得できます。例えば、現在の繰り返し回数を表すcount、0から始まるインデックスを表すindex、最初の要素かどうかを表すfirst、最後の要素かどうかを表すlastなどを利用できます。
これらを活用すると、偶数行と奇数行で背景色を切り替えたり、行番号を表示したりする処理を簡単に実装できます。
<c:forEach items="${items}" var="item" varStatus="status">
${status.index}
${item}
</c:forEach>
HTMLとの混在を分かりやすく記述する
JSTLはHTMLの中に記述するため、HTMLタグとJSTLタグが混在します。そのため、インデントを統一し、タグの対応関係が分かりやすいように記述することが大切です。また、処理の意図が分かりにくい箇所には適切なコメントを追加すると、後からコードを読む人が理解しやすくなります。読みやすいコードを書くことは、チーム開発や長期的な保守において非常に重要です。
JSTLのデバッグ方法
- 変数の内容を出力
<c:out value="${variable}" default="nullです"/>
- varStatusを利用したループデバッグ
<c:forEach items="${items}" var="item" varStatus="status">
<!-- ${status.index}: ${item} -->
</c:forEach>
- 例外情報の取得
<c:catch var="error">
<!-- 問題が発生する可能性のあるコード -->
</c:catch>
<c:if test="${not empty error}">
<p>エラーが発生しました: ${error.message}</p>
</c:if>
JSTL Coreタグライブラリの全タグ一覧
| タグ | 説明 | 主な属性 |
|---|---|---|
<c:out> | 式の結果を出力 | value, default, escapeXml |
<c:set> | 変数を設定 | var, value, scope |
<c:remove> | 変数を削除 | var, scope |
<c:catch> | 例外をキャッチ | var |
<c:if> | 条件分岐 | test, var, scope |
<c:choose> | 複数条件分岐のコンテナ | – |
<c:when> | choose内の条件分岐 | test |
<c:otherwise> | choose内のデフォルト処理 | – |
<c:forEach> | コレクションまたは固定回数のループ | items, var, begin, end, step, varStatus |
<c:forTokens> | 文字列のトークン分割ループ | items, delims, var, varStatus |
<c:import> | 外部リソースのインクルード | url, var |
<c:url> | URLを構築 | value, var, scope |
<c:redirect> | リダイレクト | url |
<c:param> | URLにパラメータ追加 | name, value |
まとめ
JSTL Coreタグライブラリを活用することで、JSPページからスクリプトレットを大幅に減らし、より読みやすく保守性の高いコードを記述できます。特に条件分岐やループ処理などの制御構造を、HTMLライクなタグ形式で記述できることが最大の利点です。
JSTLを効果的に使用するポイントは以下の通りです。
- 表示ロジックに集中し、ビジネスロジックはServletやJavaクラスに分離
- 適切なタグを選択し、ネストを深くしすぎない
- varStatusなどの便利な機能を活用
- URL構築やリダイレクトなどの定型処理を簡潔に記述
JSTL Coreタグライブラリをマスターしたら、次はEL式(Expression Language)を学ぶことで、さらにJSPの記述を簡潔にできます。また、JSTLには他にもフォーマット処理やXML処理、データベースアクセスなどの機能を提供するタグライブラリがありますので、必要に応じて学習を進めてください。