JSPの概要とリクエスト処理パイプライン
JavaServer Pages(JSP)は、Webアプリケーションにおいて動的なHTMLコンテンツを生成するためのサーバーサイド技術です。拡張子 .jsp を持ち、静的なマークアップとJavaロジックを単一ファイル内で統合して記述できます。PHPやASPに類似した用途を持ちますが、Javaプラットフォームの堅牢性とスケーラビリティを利用点が異なります。
サーバー側の処理フロー
- クライアントブラウザが指定URLへGET/POSTリクエストを送信
- サーブレットコンテナがリクエストを受信し、対象のJSPファイルを対応するサーブレット(Javaクラス)に自動変換
- 変換されたソースコードをコンパイルし、インスタンスを生成
- 生成されたサーブレットがリクエストを処理し、最終的な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>");
独自タグの開発プロセス
SimpleTagSupportまたはTagSupportを継承し、doTag()メソッドで描画ロジックを実装- TAG LIBRARY DESCRIPTION(TLD)ファイルにXML形式でエントリポイントと属性制約を定義
- 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>