JavaServer Pages(JSP)の内部構造と動的レンダリング実装ガイド

JSPの概要とリクエスト処理パイプライン

JavaServer Pages(JSP)は、Webアプリケーションにおいて動的なHTMLコンテンツを生成するためのサーバーサイド技術です。拡張子 .jsp を持ち、静的なマークアップとJavaロジックを単一ファイル内で統合して記述できます。PHPやASPに類似した用途を持ちますが、Javaプラットフォームの堅牢性とスケーラビリティを利用点が異なります。

サーバー側の処理フロー

  1. クライアントブラウザが指定URLへGET/POSTリクエストを送信
  2. サーブレットコンテナがリクエストを受信し、対象のJSPファイルを対応するサーブレット(Javaクラス)に自動変換
  3. 変換されたソースコードをコンパイルし、インスタンスを生成
  4. 生成されたサーブレットがリクエストを処理し、最終的なHTMLレスポンスをクライアントへ返却

テンプレート内に埋め込む構文体系

スクリプトレット系エレメント

  • <% Java文 %>:ローカル変数の宣言や制御フローを含むコードブロック
  • <%= 評価式 %>:計算結果またはオブジェクトの文字列表現を出力ストリームへ直接書き込み
  • <! メンバ宣言 %>:生成されるサーブレットクラスのフィールドやメソッドを定義

ディレクティブ系エレメント

  • <%@ page import="パッケージ.クラス" contentType="text/html; charset=UTF-8" %>:ページ固有の設定や依存パッケージの読み込み
  • <%@ include file="共通ヘッダー.jsp" %>:コンパイル時に外部ファイルの内容をコピー&ペースト形式で埋め込み
  • <%@ taglib prefix="custom" uri="/WEB-INF/custom.tld" %>:独自またはサードパーティ製タグライブラリの名前空間を登録

標準アクション系エレメント

  • <jsp:forward page="遷移先.jsp" />:現在の処理を別のリソースへ内部的に引き継ぎ
  • <jsp:include page="パーツ.html" flush="true" />:実行タイミングで別リソースの結果を取得して挿入
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>JSP初期検証</title>
</head>
<body>
    <% 
        int processingCount = 7;
        String statusMessage = "System Ready";
    %>
    <p>Active Tasks: <%= processingCount %></p>
    <h2><%= statusMessage %></h2>
</body>
</html>

式言語と標準タグライブラリの活用

JSP 2.0で標準導入されたExpression Language(EL)は、括弧ドル記法を使用してBeanプロパティやスコープ変数を簡潔に参照できます。これによりテンプレート内の複雑なJava記述を大幅に削減し、表示層の可読性が向上します。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>EL演算検証</title></head>
<body>
    <c:set var="visitorId" value="User_9921" scope="request" />
    <p>Accessing session via: ${visitorId}</p>
    <p>Dynamic Greeting: Hello ${visitorId}, access granted.</p>
</body>
</html>

さらにJavaServer Pages Standard Tag Library(JSTL)を導入することで、条件分岐やコレクション繰り返しを純粋なXMLタグで完結させることができます。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>JSTLコレクション処理</title></head>
<body>
    <ul>
    <c:forEach var="itemIndex" begin="10" end="20" step="5">
        <li>Iteration Step: ${itemIndex}</li>
    </c:forEach>
    </ul>
</body>
</html>

状態維持とアーキテクチャ設計

ステートレスなHTTPプロコトル上でユーザー情報を維持するには、コンテナ管理下の HttpSession インスタンスが標準的に使用されます。同一クライアントIDに対してサーバー側でデータを永続化し、后续的なリクエストで復元できます。

HttpSession persistentSession = request.getSession(true);
persistentSession.setAttribute("activeOperator", "AdminUser_X");
out.println("<p>Verified Identity: " + persistentSession.getAttribute("activeOperator") + "</p>");

独自タグの開発プロセス

  1. SimpleTagSupport または TagSupport を継承し、doTag() メソッドで描画ロジックを実装
  2. TAG LIBRARY DESCRIPTION(TLD)ファイルにXML形式でエントリポイントと属性制約を定義
  3. JSP側で taglib ディレクティブ経由でネームスペースを解決し、カスタムタグを呼び出し

MVCパターンとの統合戦略

大規模アプリケーションでは、サーブレットをフロントコントローラーまたはアクションハンドラーとし、JavaBeansやDAOクラスによるデータ加工(Model)、そしてJSPによるUI描画(View)を明確に分離します。この構造により表示レイアウトの変更がサーブレットロジックに影響を与えず、チーム開発での並列作業効率が高まります。

認証ワークフローの実装例

以下は基本的なログイン・登録機能を備えたWebアプリのディレクトリ構成と対応ファイル群です。

├── WEB-INF/
│   ├── web.xml
│   └── lib/standard.jar, jstl-api.jar
├── views/
│   ├── home.jsp
│   ├── loginPage.jsp
│   ├── signupPage.jsp
│   └── secureArea/welcomeView.jsp
└── src/com/demo/web/
    ├── CredentialValidator.java
    └── AccountCreator.java

表示側テンプレート

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head><title>メイン入口</title></head>
<body>
    <header><h1>システムポータル</h1></header>
    <nav>
        <a href="loginPage.jsp">認証画面へ</a> | 
        <a href="signupPage.jsp">新規アカウント作成</a>
    </nav>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head><title>認証入力</title></head>
<body>
    <form action="CredentialValidator" method="post">
        <label for="inpUid">識別子:</label>
        <input type="text" id="inpUid" name="inpUid" required/><br/>
        
        <label for="inpPwd">認証鍵:</label>
        <input type="password" id="inpPwd" name="inpPwd" required/><br/>
        
        <button type="submit">認証実行</button>
    </form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head><title>登録フォーム</title></head>
<body>
    <form action="AccountCreator" method="post">
        <label for="newUid">新規識別子:</label>
        <input type="text" id="newUid" name="newUid" required/><br/>
        
        <label for="newPwd">パスワード設定:</label>
        <input type="password" id="newPwd" name="newPwd" required/><br/>
        
        <button type="submit">登録確定</button>
    </form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page import="javax.servlet.http.HttpSession" %>
<%
    HttpSession verifySession = request.getSession(false);
    String verifiedAgent = (verifySession != null) ? (String) verifySession.getAttribute("loggedInUser") : null;
    if (verifiedAgent == null) {
        response.sendRedirect("loginPage.jsp");
        return;
    }
%>
<html>
<head><title>認可済みエリア</title></head>
<body>
    <h1>アクセス許可: <%= verifiedAgent %></h1>
    <a href="logoutAction.do">セッション切断</a>
</body>
</html>

バックエンドサーブレット

package com.demo.web;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class CredentialValidator extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String submittedId = req.getParameter("inpUid");
        String submittedKey = req.getParameter("inpPwd");

        boolean authenticationResult = (submittedId != null && submittedKey != null) 
                                     && submittedId.length() > 0 && submittedKey.length() > 0;

        if (authenticationResult) {
            HttpSession sessionObj = req.getSession(true);
            sessionObj.setAttribute("loggedInUser", submittedId);
            resp.sendRedirect("secureArea/welcomeView.jsp");
        } else {
            resp.sendRedirect("loginPage.jsp");
        }
    }
}
package com.demo.web;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class AccountCreator extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String incomingId = req.getParameter("newUid");
        String incomingSec = req.getParameter("newPwd");

        if (incomingId != null && !incomingId.isEmpty()) {
            HttpSession newSession = req.getSession(true);
            newSession.setAttribute("loggedInUser", incomingId);
            resp.sendRedirect("secureArea/welcomeView.jsp");
        } else {
            resp.sendRedirect("signupPage.jsp");
        }
    }
}
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="3.1">
    <servlet>
        <servlet-name>CredentialValidator</servlet-name>
        <servlet-class>com.demo.web.CredentialValidator</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CredentialValidator</servlet-name>
        <url-pattern>/CredentialValidator</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>AccountCreator</servlet-name>
        <servlet-class>com.demo.web.AccountCreator</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>AccountCreator</servlet-name>
        <url-pattern>/AccountCreator</url-pattern>
    </servlet-mapping>
</web-app>

タグ: JSP Expression Language JSTL サーブレットコンテナ HttpSession

6月2日 18:34 投稿