第2章: JSPの基本理解

JSPの基本概念と動作原理

この章で学ぶこと
  • JSPの基本概念と役割を深く理解する
  • JSPファイルの処理フローと実行メカニズムを学ぶ
  • JSPの主要な構文要素とその使い方を修得する
  • 簡単なJSPファイルの作成から実行までの流れを理解する
  • JSPとHTMLの関係性と組み合わせ方を学ぶ
  • JSP開発における基本的なベストプラクティスを習得する

2.1 JSPとは何か

JSP(JavaServer Pages)は、動的なWebコンテンツを生成するためのJavaベースのサーバーサイド技術です。HTMLテンプレートにJavaコードを組み込むことで、データベースの内容やユーザーの入力に応じて変化するWebページを作成できます。

2.1.1 JSPの位置づけ

Web開発技術の中でのJSPの位置づけを理解しましょう:

flowchart TB subgraph CLIENT["クライアントサイド"] C1["HTML/CSS"] C2["JavaScript"] C3["ブラウザ"] end subgraph SERVER["サーバーサイド"] S1["JSP"] S2["Java/JDBC"] S3["Apache Tomcat"] end subgraph DATABASE["データ層"] D1[("データベース")] end CLIENT -->|"HTTPリクエスト"| SERVER SERVER -->|"HTML/CSS/JavaScript"| CLIENT SERVER --> DATABASE DATABASE --> SERVER

2.1.2 静的コンテンツと動的コンテンツの違い

Webページは大きく静的コンテンツと動的コンテンツに分類されます:

項目 静的コンテンツ 動的コンテンツ(JSP)
内容 固定された内容 リクエストに応じて変化
処理場所 ブラウザ(クライアント) Webサーバー(サーバー)
データベース連携 不可 可能
ユーザー認証 不可 可能
会社概要、お知らせページ ログイン画面、商品一覧、検索結果

2.2 JSPの処理フローと実行メカニズム

JSPがブラウザに表示されるまでの詳細な処理フローを理解することは、JSP開発において非常に重要です。

2.2.1 JSPの処理段階

JSPファイルが実行される際は、以下の段階を経て処理されます:

flowchart TD A["①ブラウザから
JSPリクエスト"] --> B["②Tomcatが
JSPファイル受信"] B --> C["③JSPファイルを
Javaサーブレットに変換"] C --> D["④Javaサーブレットを
バイトコードにコンパイル"] D --> E["⑤バイトコードを実行"] E --> F["⑥HTML出力生成"] F --> G["⑦HTMLを
ブラウザに送信"] G --> H["⑧ブラウザで
Webページ表示"]
実習 2-1: JSP変換プロセスの確認

JSPがどのようにJavaサーブレットに変換されるかを実際に確認します。

手順
  1. 以下のJSPファイルをsample.jspとして作成
  2. Tomcatにデプロイしてブラウザでアクセス
  3. Tomcatのworkディレクトリ内で生成されたJavaファイルを確認
  4. JSPがどのようにJavaコードに変換されているかを観察
sample.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>JSP変換テスト</title>
</head>
<body>
    <h1>JSP変換の確認</h1>
    <p>現在の日時: <%= new java.util.Date() %></p>
    <p>計算結果: <%= 10 + 5 %></p>
</body>
</html>
期待される結果

Tomcatのwork/Catalina/localhost/[アプリ名]/org/apache/jsp/フォルダ内にsample_jsp.javaファイルが生成され、JSPコードがJavaサーブレットコードに変換されていることを確認できます。

2.3 JSPの主要な構文要素

JSPには、HTMLと組み合わせてJavaコードを記述するための特殊な構文要素があります。これらの要素を理解することで、効果的なJSPアプリケーションを開発できます。

2.3.1 JSP構文要素の分類

JSPの構文要素は以下のように分類されます:

flowchart TB A["JSP構文要素"] --> B["スクリプト要素"] A --> C["ディレクティブ"] A --> D["アクション要素"] A --> E["コメント"] B --> B1["スクリプトレット <% ... %>"] B --> B2["式 <%= ... %>"] B --> B3["宣言 <%! ... %>"] C --> C1["page ディレクティブ"] C --> C2["include ディレクティブ"] C --> C3["taglib ディレクティブ"] D --> D1["jsp:useBean"] D --> D2["jsp:include"] D --> D3["jsp:forward"]

2.3.2 基本的なスクリプト要素

最も基本となるスクリプト要素について学習しましょう:

構文要素 記法 用途
式(Expression) <%= ... %> 値をHTMLに出力 <%= new Date() %>
スクリプトレット <% ... %> Javaコードの実行 <% int x = 10; %>
宣言 <%! ... %> メソッド・変数宣言 <%! int counter = 0; %>
コメント <%-- ... --%> JSP専用コメント <%-- これはコメント --%>
実習 2-2: 基本構文要素の活用

JSPの基本的な構文要素を使用して、動的なコンテンツを生成するページを作成します。

手順
  1. 以下のJSPファイルをbasic-syntax.jspとして作成
  2. 各構文要素がどのように動作するかを確認
  3. ブラウザでページを複数回リロードして動的要素を観察
basic-syntax.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%!
    // 宣言: クラスレベルの変数とメソッド
    private int pageViewCount = 0;
    
    public String getGreeting(String name) {
        return "こんにちは、" + name + "さん!";
    }
%>
<%
    // スクリプトレット: 処理ロジック
    pageViewCount++;
    java.util.Date currentTime = new java.util.Date();
    String userAgent = request.getHeader("User-Agent");
    String browserType = "不明";
    
    if (userAgent != null) {
        if (userAgent.contains("Chrome")) {
            browserType = "Chrome";
        } else if (userAgent.contains("Firefox")) {
            browserType = "Firefox";
        } else if (userAgent.contains("Safari")) {
            browserType = "Safari";
        }
    }
%>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>JSP基本構文の練習</title>
    <style>
        body { font-family: 'Noto Sans JP', sans-serif; margin: 40px; }
        .info-box { background: #f0f8ff; padding: 15px; border-radius: 5px; margin: 10px 0; }
    </style>
</head>
<body>
    <h1>JSP基本構文デモ</h1>
    
    <div class="info-box">
        <h2>式(Expression)の例</h2>
        <p>現在の日時: <%= currentTime %></p>
        <p>メソッド呼び出し: <%= getGreeting("JSP学習者") %></p>
        <p>計算結果: <%= 25 * 4 + 10 %></p>
    </div>
    
    <div class="info-box">
        <h2>宣言とスクリプトレットの例</h2>
        <p>このページの表示回数: <%= pageViewCount %></p>
        <p>使用ブラウザ: <%= browserType %></p>
    </div>
    
    <div class="info-box">
        <h2>条件分岐の例</h2>
        <%
            java.util.Calendar cal = java.util.Calendar.getInstance();
            int hour = cal.get(java.util.Calendar.HOUR_OF_DAY);
        %>
        <p>
            <% if (hour < 12) { %>
                おはようございます!
            <% } else if (hour < 18) { %>
                こんにちは!
            <% } else { %>
                こんばんは!
            <% } %>
            現在は<%= hour %>時です。
        </p>
    </div>
    
    <%-- JSPコメント: この部分はブラウザに送信されません --%>
    <!-- HTMLコメント: この部分はブラウザに送信されます -->
</body>
</html>
期待される結果

ページが表示され、現在時刻、ページ表示回数、ブラウザ情報、時間帯に応じた挨拶などが動的に生成されます。ページを更新すると表示回数が増加することを確認できます。

2.4 JSPとHTMLの関係性

JSPは本質的にHTMLテンプレートにJavaコードを組み込む技術です。HTMLの知識を活用しながら、動的要素を追加する方法を理解しましょう。

2.4.1 HTMLテンプレート + Javaコード

JSPページは以下のような構造を持ちます:

flowchart TB A["JSPページ"] --> B["HTMLテンプレート部分"] A --> C["Javaコード部分"] B --> B1["静的コンテンツ
(HTML, CSS, JavaScript)"] C --> C1["動的コンテンツ生成
(データベース, 計算, 条件分岐)"] B1 --> D["統合されたHTML出力"] C1 --> D

2.4.2 効果的なHTMLとJSPの組み合わせ

保守性と可読性を高めるためのベストプラクティス:

  • 関心の分離:デザイン(HTML/CSS)とロジック(Java)を適切に分離
  • 可読性の重視:HTMLの構造を壊さないJavaコード配置
  • 再利用性:共通部分はインクルードファイルとして分離
  • セキュリティ:ユーザー入力の適切なエスケープ処理

2.5 JSPファイルの作成から実行までの流れ

実際のJSPファイルを作成し、Tomcatで実行するまでの具体的な手順を学習します。

実習 2-3: 完全なJSPページの作成

HTML、CSS、Javaコードを組み合わせた実用的なJSPページを作成します。

手順
  1. 以下のJSPファイルをcomplete-example.jspとして作成
  2. Webアプリケーションとしてデプロイ
  3. ブラウザで動作確認
  4. 各機能がどのように実装されているかを分析
complete-example.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*, java.text.*" %>
<%!
    // ユーティリティメソッドの宣言
    public String formatNumber(double number) {
        DecimalFormat df = new DecimalFormat("#,##0.00");
        return df.format(number);
    }
    
    public String getColorByValue(double value) {
        if (value > 70) return "success";
        if (value > 40) return "warning"; 
        return "danger";
    }
%>
<%
    // サンプルデータの生成
    String[] products = {"ノートPC", "マウス", "キーボード", "モニター", "プリンター"};
    double[] prices = {89800.0, 2980.0, 5780.0, 34800.0, 15600.0};
    int[] stocks = {15, 120, 89, 25, 8};
    
    double totalValue = 0;
    for (int i = 0; i < products.length; i++) {
        totalValue += prices[i] * stocks[i];
    }
    
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    String currentDateTime = sdf.format(new Date());
%>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>商品在庫管理システム</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .header-info { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }
    </style>
</head>
<body>
    <div class="container-fluid">
        <div class="row header-info text-white p-3 mb-4">
            <div class="col">
                <h1 class="h3">商品在庫管理システム</h1>
                <p class="mb-0">最終更新: <%= currentDateTime %></p>
            </div>
        </div>
        
        <div class="row">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">在庫一覧</h5>
                    </div>
                    <div class="card-body p-0">
                        <table class="table table-striped mb-0">
                            <thead class="table-dark">
                                <tr>
                                    <th>商品名</th>
                                    <th>単価</th>
                                    <th>在庫数</th>
                                    <th>在庫価値</th>
                                    <th>状態</th>
                                </tr>
                            </thead>
                            <tbody>
                                <% for (int i = 0; i < products.length; i++) { %>
                                <tr>
                                    <td><%= products[i] %></td>
                                    <td>¥<%= formatNumber(prices[i]) %></td>
                                    <td>
                                        <span class="badge bg-<%= getColorByValue(stocks[i]) %>">
                                            <%= stocks[i] %>個
                                        </span>
                                    </td>
                                    <td>¥<%= formatNumber(prices[i] * stocks[i]) %></td>
                                    <td>
                                        <% if (stocks[i] < 10) { %>
                                            <span class="badge bg-danger">要発注</span>
                                        <% } else if (stocks[i] < 30) { %>
                                            <span class="badge bg-warning">注意</span>
                                        <% } else { %>
                                            <span class="badge bg-success">良好</span>
                                        <% } %>
                                    </td>
                                </tr>
                                <% } %>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
            
            <div class="col-md-4">
                <div class="card mb-3">
                    <div class="card-header">
                        <h5 class="mb-0">サマリー情報</h5>
                    </div>
                    <div class="card-body">
                        <h6>総在庫価値</h6>
                        <p class="h4 text-primary">¥<%= formatNumber(totalValue) %></p>
                        
                        <h6>商品カテゴリ数</h6>
                        <p class="h4 text-info"><%= products.length %>種類</p>
                        
                        <h6>要発注商品</h6>
                        <p class="h4 text-warning">
                            <% 
                                int lowStockCount = 0;
                                for (int stock : stocks) {
                                    if (stock < 10) lowStockCount++;
                                }
                            %>
                            <%= lowStockCount %>商品
                        </p>
                    </div>
                </div>
                
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">システム情報</h5>
                    </div>
                    <div class="card-body">
                        <small class="text-muted">
                            サーバー時刻: <%= new Date() %><br>
                            JSP バージョン: 3.1<br>
                            文字エンコーディング: UTF-8
                        </small>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
期待される結果

商品在庫管理システムのような実用的なWebページが表示されます。商品一覧テーブル、在庫状況の色分け表示、サマリー情報など、動的に生成されたコンテンツを確認できます。

2.6 JSP開発のベストプラクティス

保守性が高く、セキュアなJSPアプリケーションを開発するための重要な原則を学びます。

2.6.1 コードの分離と構造化

避けるべき書き方

JSPファイル内に大量のJavaコードを記述することは、以下の問題を引き起こします:

  • 保守性の低下
  • デザイナーとプログラマーの協業困難
  • テストの複雑化
  • セキュリティリスクの増大

2.6.2 推奨される開発アプローチ

JSP開発における推奨パターン:

  • MVC(Model-View-Controller)パターン:ロジックとプレゼンテーションを分離
  • JavaBeans活用:データの管理と受け渡しに専用クラスを使用
  • EL(Expression Language):JSPコード内のJava記述を最小化
  • JSTL(JSP Standard Tag Library):標準タグライブラリを活用
  • 適切なコメント:保守性向上のための文書化
理解度確認クイズ
  1. JSPファイルが実行されてブラウザに表示されるまでの処理段階を順序立てて説明してください。
  2. JSPの式(<%= ... %>)とスクリプトレット(<% ... %>)の違いを、具体的な使用例とともに説明してください。
  3. 宣言(<%! ... %>)を使用する場面と、通常のスクリプトレット内での変数宣言との違いを説明してください。
  4. 静的コンテンツと動的コンテンツの特徴を比較し、JSPがどちらに分類されるかその理由とともに説明してください。
  5. JSP開発において「関心の分離」が重要な理由を、保守性の観点から説明してください。
解答例
  1. ①ブラウザからJSPリクエスト → ②TomcatがJSPファイル受信 → ③JSPをJavaサーブレットに変換 → ④Javaサーブレットをバイトコードにコンパイル → ⑤バイトコード実行 → ⑥HTML出力生成 → ⑦HTMLをブラウザに送信 → ⑧ブラウザでWebページ表示
  2. 式(<%= new Date() %>)は値を直接HTML出力に出力するために使用し、スクリプトレット(<% int x = 10; %>)は変数宣言や制御構造などの処理ロジックを記述するために使用します。
  3. 宣言(<%! %>)はクラスレベルの変数やメソッドを定義するために使用し、サーブレット全体で共有されます。スクリプトレット内の変数はメソッドレベルのローカル変数として機能します。
  4. 静的コンテンツは固定された内容でクライアント側で処理されますが、動的コンテンツはリクエストに応じて変化し、サーバー側で処理されます。JSPは動的コンテンツに分類され、データベース連携やユーザー入力に応じたコンテンツ生成が可能です。
  5. 関心の分離により、デザイン(HTML/CSS)とロジック(Java)を適切に分離することで、各専門分野の開発者が独立して作業でき、コードの可読性・保守性・テスタビリティが向上します。

2.7 まとめ

この章では、JSPの基本概念と動作原理について学習しました。

  • JSPの役割理解:動的Webコンテンツ生成技術としての位置づけ
  • 処理フロー把握:JSPからHTMLが生成される詳細なプロセス
  • 基本構文習得:式、スクリプトレット、宣言の使い方
  • 実践的活用:HTMLとJavaコードを組み合わせた実用例
  • 開発原則理解:保守性の高いJSPアプリケーション開発のベストプラクティス

次章では、スクリプトレットと式について、より詳細で実践的な使用方法を学習していきます。