JavaのWebアプリで一覧を表示するには?JSPでデータからHTMLを作る仕組み

最終更新日

Schoo Java入門 中級 第4回 Webアプリケーションの動作原理と画面連携

本記事は、Schooの「Java入門 中級【2026年版】」第4回「Webアプリケーションの動作原理と画面連携」に関連する補足記事です。商品などのデータが、Web画面の一覧になる仕組みを整理します。

商品が3件あれば3行、10件あれば10行。件数に合わせてHTMLを手書きする代わりに、JSPのfor文で1件ずつデータを取り出し、行のHTMLを作ります。さらにif文を使うと、在庫数に応じて「在庫あり」「売り切れ」のように表示内容を変えられます。

この記事ではServletが商品データを用意し、JSPが一覧のHTMLを作ります。授業資料と同じく、JSP内の <% ... %><%= ... %> を使って処理を追います。

Schoo コースページ:Java入門 中級【2026年版】

まず、完成する一覧と元のデータを対応させる

今回は「ノートが8個、ペンが0個、ファイルが3個」という3件の商品を表示します。0個なら「売り切れ」、1個以上なら「在庫あり」とする要件です。

図解:データ3件が、画面の3行になるまで
サーバー:Servletが用意した List<Product>
1つのProductに、商品名と在庫数がセットで入る
1件目のProduct
ノート / 在庫8個
2件目のProduct
ペン / 在庫0個
3件目のProduct
ファイル / 在庫3個
productsのリストをJSPへ渡す
サーバー:JSPの拡張for文を3回実行
1周ごとにProductを1件取り出し、同じ商品の名前と在庫数から <tr>…</tr> を1つ作る
1周目<tr> … ノート … 8 … 在庫あり … </tr> 2周目<tr> … ペン … 0 … 売り切れ … </tr> 3周目<tr> … ファイル … 3 … 在庫あり … </tr>
作ったHTMLをレスポンスとして送る
ブラウザ:商品一覧
商品一覧
全3件
商品名在庫数状態
ノート8在庫あり
ペン0売り切れ
ファイル3在庫あり

行の色は、データ・生成された行・画面の対応を示しています。ブラウザへJavaのfor文やif文が送られるわけではありません。

ServletとJSPはどちらもサーバー側で動きます。JSPの処理で作ったHTMLを受け取って、見える表にするのがブラウザです。図の色や枠は対応を示すためのもので、後のサンプルは装飾のないHTMLの表を返します。

JSPに書いたJavaは、どこで実行されるのか

まず、商品名を1つだけ出す小さな例で確認します。次はサーバーに置くJSPの一部分です。

<% String productName = "ノート"; %>
<p>商品名:<%= productName %></p>

<% ... %> の中ではJavaの処理を実行します。<%= ... %> は式の値をレスポンスへ出力する書き方です。この場合、サーバーで productName に「ノート」が入り、その値がHTMLの中に出力されます。

<p>商品名:ノート</p>

これがブラウザへ送られるHTMLです。ブラウザに String productName<%= productName %> が届いて、それをブラウザがJavaとして実行するわけではありません。

商品名と在庫数をProductクラスにまとめる

商品一覧の1行には、1件の商品に属する名前と在庫数を表示します。そのため、商品名と在庫数を1つのProductオブジェクトにまとめます。example パッケージに Product.java を作ります。

package example;

public class Product {
    private final String name;
    private final int stockCount;

    public Product(String name, int stockCount) {
        this.name = name;
        this.stockCount = stockCount;
    }

    public String getName() {
        return name;
    }

    public int getStockCount() {
        return stockCount;
    }
}

new Product("ノート", 8) は、「名前はノート、在庫数は8」という1件の商品を作ります。getName()getStockCount() を呼ぶと、その商品の名前と在庫数を取り出せます。

複数の商品は List<Product> に入れます。Productが商品1件、List<Product>が商品の一覧です。商品を追加したり並べ替えたりしても、名前と在庫数は同じオブジェクトの中で対応したまま扱えます。

Servletで商品のリストを用意し、JSPへ渡す

前の記事のServletはJavaの out.println() でHTMLを返していました。今回は表示部分を product-list.jsp に置き、Servletからデータを渡します。

example パッケージの ProductListServlet.java です。リストにProductを3件追加し、products という名前でJSPへ渡します。

package example;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/products")
public class ProductListServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
            throws ServletException, IOException {
        List<Product> products = new ArrayList<>();
        products.add(new Product("ノート", 8));
        products.add(new Product("ペン", 0));
        products.add(new Product("ファイル", 3));

        request.setAttribute("products", products);

        request.getRequestDispatcher("/product-list.jsp")
               .forward(request, response);
    }
}

List<Product> は変数の型で、「Productを要素として持つリスト」を表します。new ArrayList<>() で実際のリストを作り、add() で商品を1件ずつ追加しています。ここでは画面表示の流れに集中するため、データベースを使わずServletでデータを用意します。

  • setAttribute():Javaのデータに名前を付けて、同じリクエストの中で使えるようにする。
  • forward():サーバー内で処理をJSPへ引き継ぐ。JSPは渡されたデータを使ってHTMLを作る。

ブラウザがアクセスするURLは /lesson04/products です。/lesson04 はこの例のアプリの配置先です。JSPは src/main/webapp/product-list.jsp に置き、Servletから /product-list.jsp へ転送します。forward() はブラウザへ移動先を通知する処理ではないため、アドレス欄のURLは変わりません。

この配置ではJSPのURLも公開されますが、このサンプルの確認はServletのURLから行います。/lesson04/product-list.jsp を直接開いてもServletが実行されず、表示に必要な products が渡されないためです。

JSPで商品のリストを受け取る:getParameter()との違い

<%@ page import="java.util.List, example.Product" %>
<%
List<Product> products =
    (List<Product>) request.getAttribute("products");
%>

ここで使うのは getAttribute() です。Servletの setAttribute() に指定した名前と合わせて、商品のリストを取り出しています。戻り値の型は Object なので、List<Product> にキャストして受け取ります。先頭の page import は、このJSPで使うListとProductを指定しています。

このキャストでは、リストの各要素がProductであることまでは実行時に検査されないため、コンパイル時に「未チェックのキャスト」の警告が出ることがあります。Servlet側でProductのリストを渡し、JSP側で同じ型として受け取る約束を揃える必要があります。

用途取得するメソッド今回の値
ブラウザから送られたフォームなどの値を読むgetParameter()String 型の入力値
Servletがサーバー内で渡したデータを読むgetAttribute()商品のリスト List<Product>

前の記事の「リクエストの入力値は基本的に文字列として取得する」は、getParameter() の話です。今回はブラウザから商品のリストが送られてくるのではなく、ServletがJavaで作ったリストをJSPに渡しています。

JSP全体:1周につき商品の行を1つ作る

src/main/webapp/product-list.jsp に置くコードです。表の外枠と見出しは1回だけ出力し、データの行をfor文の中に置きます。

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="java.util.List, example.Product" %>
<%
List<Product> products =
    (List<Product>) request.getAttribute("products");
%>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>商品一覧</title>
</head>
<body>
    <h1>商品一覧</h1>
    <p>全<%= products.size() %>件</p>

    <table>
        <thead>
            <tr><th>商品名</th><th>在庫数</th><th>状態</th></tr>
        </thead>
        <tbody>
        <% for (Product product : products) { %>
            <%
            // 商品名をHTMLの文字として表示するための変換
            String displayName = product.getName()
                .replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;");
            %>
            <tr>
                <td><%= displayName %></td>
                <td><%= product.getStockCount() %></td>
                <td>
                <% if (product.getStockCount() > 0) { %>
                    在庫あり
                <% } else { %>
                    売り切れ
                <% } %>
                </td>
            </tr>
        <% } %>
        </tbody>
    </table>

    <% if (products.isEmpty()) { %>
        <p>表示する商品がありません。</p>
    <% } %>
</body>
</html>

このJSPは、上のServletから products という名前でProductのリストを受け取ることを前提にしています。products.size() は商品数です。for (Product product : products) で1件ずつ取り出し、各周回の product から名前と在庫数を読みます。3件なら <tr> から </tr> までが3回出力されます。

図解:for文の「中」にあるHTMLが繰り返される
最初に1回出力
<table>
ここからここまでを、データの件数分繰り返す
<% for (Product product : products) { %>
<tr>
  <td>商品の値</td>
  <td>在庫数</td>
</tr>
<% } %>
最後に1回出力
</table>

3件なら表が3つできるのではなく、1つの表にデータの行が3つできます。図では見出し行などを省略しています。

%> が出てきても、for文そのものが終わるわけではありません。%> はJavaを書く区間の終わり、} はfor文やif文のブロックの終わりです。Javaの波括弧の対応で、どのHTMLが繰り返されるかを読んでください。

if文で、各商品の表示を分ける

<% if (product.getStockCount() > 0) { %>
    在庫あり
<% } else { %>
    売り切れ
<% } %>

if文は拡張for文の中にあるため、取り出した商品ごとに判定します。ペンのProductでは product.getStockCount() が0なので、HTMLへ出力されるのは「売り切れ」です。この行に「在庫あり」は出力されません。

拡張for文の周回productの商品名在庫数出力する状態
1周目ノート8在庫あり
2周目ペン0売り切れ
3周目ファイル3在庫あり

ブラウザへ届くHTMLを見比べる

生成される表の部分は次のようになります。読みやすいように空白と改行を整えています。JSPにあったfor文やif文がなくなり、処理結果の値とHTMLだけになっている点に注目してください。

<table>
    <thead>
        <tr><th>商品名</th><th>在庫数</th><th>状態</th></tr>
    </thead>
    <tbody>
        <tr>
            <td>ノート</td><td>8</td><td>在庫あり</td>
        </tr>
        <tr>
            <td>ペン</td><td>0</td><td>売り切れ</td>
        </tr>
        <tr>
            <td>ファイル</td><td>3</td><td>在庫あり</td>
        </tr>
    </tbody>
</table>

ブラウザは、このHTMLの <table><tr><td> を読み、表として表示します。Javaの繰り返し処理が完了した結果を表示しているので、通信がないままブラウザ上でJavaのfor文が回り続けることはありません。

データを増やすと、JSPを書き足さなくても行が増える

Servletの3件目の追加処理の後、setAttribute() より前に次の1行を追加して再実行します。JSPのfor文は変更しません。

products.add(new Product("ふせん", 12));

products.size() が4になるので、「ふせん・12・在庫あり」の行が追加されます。商品名と在庫数はProductとして一緒に追加します。一覧の各行を同じ書式で出すため、件数が変わるたびにHTMLを書き足す必要がありません。

new ArrayList<>() で作ったリストに何も追加せず渡した場合は、拡張for文が0回となり、商品の行は出力されません。products.isEmpty() がtrueになり、表の下に「表示する商品がありません。」と表示します。データを変えた結果を確認するには、アプリに変更を反映してページを再読み込みします。

商品名を出力する前にHTML用の変換をする理由

サンプルの displayName は、商品名に含まれる &<> をHTML用に変換した値です。例えば「A&Bノート」はHTML上では A&amp;Bノート と出力し、画面では元の「A&Bノート」と表示します。

<%= ... %> はHTML用の変換を自動では行いません。データベースや入力フォームの文字列を表示する場合にも、HTMLのタグではなく文字として表示する処理が必要です。ここでの3文字の変換は <td> の中などの通常のテキスト表示用で、URL・HTML属性・JavaScriptへの埋め込みにそのまま使うものではありません。

確認問題

本文のServletの商品データを、次の内容に変更したとします。JSPはそのまま使い、在庫数は0以上とします。

List<Product> products = new ArrayList<>();
products.add(new Product("ノート", 2));
products.add(new Product("ペン", 0));
products.add(new Product("ふせん", 1));
  1. ブラウザに表示される3行の「商品名・在庫数・状態」を書いてください。
  2. ペンの行について、ブラウザへ送られる <tr> から </tr> までのHTMLを書いてください。
  3. 「0個なら売り切れ、1〜2個なら残りわずか、3個以上なら在庫あり」と表示を変えます。JSPのif文を書き換えてください。
  4. 空の商品のリストを渡した場合、商品の行は何行になり、このサンプルでは何と表示されますか。

演習後の確認:こちらのページを使って、自分で考えた内容を見直せます。

まとめ

  • Servletが用意したデータをJSPへ渡し、JSPがブラウザに送るHTMLを作る。
  • JSPのfor文の中に1件分の行を書くと、件数に応じて行が出力される。
  • if文を行の中に置くと、データごとに表示内容を分けられる。
  • ブラウザが受け取るのは、Javaのコードではなく処理結果のHTML。

関連する記事

シェアする