
【Sevlet/JSP】クライアント/サーバーモデルとWebアプリケーションの仕組み
2025-08-04はじめに
Webアプリケーション開発の基礎となるクライアント/サーバーモデルと、JSPがどのようにこのモデルの中で機能するかを理解することは、効果的なWebアプリケーションを作成する上で不可欠です。本記事では、既にHTTPプロトコルの基礎を理解している読者を対象に、JSPを用いたWebアプリケーション開発に必要なクライアント/サーバーモデルの詳細と、その内部動作について詳しく解説します。
第1章 クライアント/サーバーモデルの基本概念
1.1 クライアントとサーバーの役割分担
Webアプリケーションは、クライアント(ブラウザ)とサーバーの明確な役割分担に基づいて動作します。
- クライアントの主な役割:
- ユーザーインターフェースの提供
- ユーザー操作の受付
- サーバーへのリクエスト送信
- サーバーからのレスポンス表示
- サーバーの主な役割:
- クライアントからのリクエスト受信
- ビジネスロジックの実行
- データベースとの連携
- クライアントへのレスポンス生成
1.2 クライアント/サーバー間の通信フロー
一般的なJSPアプリケーションのリクエスト処理フロー:
- ユーザーがブラウザでURLを入力またはリンクをクリック
- ブラウザがDNSルックアップを行い、サーバーIPを解決
- HTTPリクエストがサーバーに送信
- Webサーバー(Apache Tomcatなど)がリクエストを受信
- JSPコンテナが該当JSPページを処理
- サーバーサイドでJavaコード実行
- データベースとの連携(必要な場合)
- HTML生成
- HTTPレスポンスとしてクライアントに返送
- ブラウザがHTMLをレンダリング
1.3 ステートレスな通信の特性
HTTPはステートレスプロトコルであり、各リクエストは独立して扱われます。この特性は、以下のようなJSP開発における重要な概念につながります。
- セッション管理の必要性:
HttpSession
オブジェクトを使用 - クッキーの利用: クライアント側に状態を保存
- URLリライティング: セッションIDをURLに埋め込む
第2章 JSPにおけるHTTPプロトコルの詳細実装
2.1 JSPのライフサイクルとHTTP
JSPページはリクエストごとに以下のライフサイクルを経ます:
- 変換フェーズ: JSPファイルがServletソースコードに変換
- コンパイルフェーズ: 生成されたServletがJavaクラスにコンパイル
- 実行フェーズ:
jspInit()
: 初期化_jspService()
: リクエスト処理(HTTPメソッドに応じて分岐)jspDestroy()
: 終了処理
2.2 HTTPリクエストの詳細解析
JSPで扱われるHTTPリクエストの主要コンポーネント:
リクエストラインの解析
<%
String method = request.getMethod(); // "GET", "POST" etc.
String uri = request.getRequestURI();
String protocol = request.getProtocol();
%>
ヘッダー情報の取得
<%
Enumeration headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = request.getHeader(name);
out.println(name + ": " + value + "
");
}
%>
クエリパラメータの処理
<%
// 単一パラメータ取得
String param = request.getParameter("paramName");
// 複数値パラメータ取得(チェックボックスなど)
String[] values = request.getParameterValues("multiParam");
%>
2.3 HTTPレスポンスの制御
JSPでのレスポンス制御方法:
ステータスコード設定
<% response.setStatus(HttpServletResponse.SC_OK); %>
<% response.sendError(HttpServletResponse.SC_NOT_FOUND, "ページが見つかりません"); %>
ヘッダー設定
<%
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", -1);
%>
コンテントタイプ設定
<%@ page contentType="text/html; charset=UTF-8" %>
リダイレクト処理
<% response.sendRedirect("newLocation.jsp"); %>
2.4 各種HTTPメソッドの実装例
GETメソッドの処理
<%@ page import="java.util.Map" %>
<%
if ("GET".equals(request.getMethod())) {
Map params = request.getParameterMap();
// GETパラメータ処理
}
%>
POSTメソッドの処理
<%
if ("POST".equals(request.getMethod())) {
String username = request.getParameter("username");
String password = request.getParameter("password");
// 認証処理など
}
%>
フォームの実装例
<form method="post" action="process.jsp">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="ログイン">
</form>
第3章 セッション管理と状態維持
3.1 セッションの基本概念
HTTPのステートレス性を克服するためのセッション管理:
<%
// セッション取得(存在しなければ新規作成)
HttpSession session = request.getSession(true);
// セッション属性設定
session.setAttribute("user", "username");
// セッション属性取得
String user = (String) session.getAttribute("user");
// セッション無効化
session.invalidate();
%>
3.2 セッション追跡のメカニズム
JSP/サーブレットコンテナは以下の方法でセッションを追跡:
- クッキーを使用 (JSESSIONID)
<%
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(60*60*24); // 1日
response.addCookie(cookie);
%>
- URLリライティング
<a href="<%= response.encodeURL("page.jsp") %>">リンク</a>
- 隠しフォームフィールド
<input type="hidden" name="jsessionid" value="<%= session.getId() %>">
3.3 セッションタイムアウト設定
web.xmlでの設定例:
<session-config>
<session-timeout>30</session-timeout> <!-- 分単位 -->
</session-config>
JSPページ内での設定:
<% session.setMaxInactiveInterval(1800); // 秒単位 %>
第4章 JSPの高度なHTTP機能
4.1 ファイルアップロード処理
<%@ page import="org.apache.commons.fileupload.*" %>
<%@ page import="org.apache.commons.fileupload.disk.*" %>
<%@ page import="org.apache.commons.fileupload.servlet.*" %>
<%@ page import="java.io.*" %>
<%
if (ServletFileUpload.isMultipartContent(request)) {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (!item.isFormField()) {
// ファイル処理
String fileName = new File(item.getName()).getName();
String filePath = "uploads/" + fileName;
item.write(new File(filePath));
}
}
}
%>
<form method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="アップロード">
</form>
4.2 クッキーの操作
<%
// クッキー作成
Cookie cookie = new Cookie("userPref", "darkMode");
cookie.setMaxAge(60*60*24*365); // 1年間有効
response.addCookie(cookie);
// クッキー読み取り
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
if ("userPref".equals(c.getName())) {
String value = c.getValue();
// テーマ設定などに使用
}
}
}
%>
4.3 HTTPキャッシュ制御
<%
// キャッシュ防止
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
// 条件付きGET処理
long lastModified = /* 最終更新日時を取得 */;
String ifModifiedSince = request.getHeader("If-Modified-Since");
if (ifModifiedSince != null &&
lastModified <= Long.parseLong(ifModifiedSince)) {
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
response.setDateHeader("Last-Modified", lastModified);
%>
第5章 実践的なJSPアプリケーションの構築
5.1 MVCアーキテクチャの実装
HTTPリクエストを効率的に処理するためのMVCパターン:
リクエスト → コントローラ(Servlet) → モデル(JavaBean) → ビュー(JSP) → レスポンス
コントローラの例 (Servlet)
@WebServlet("/user")
public class UserController extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
UserService service = new UserService();
List users = service.getAllUsers();
request.setAttribute("users", users);
request.getRequestDispatcher("/userList.jsp").forward(request, response);
}
}
JSPビューの例 (userList.jsp)
<%@ page import="java.util.List" %>
<%@ page import="com.example.User" %>
<%
List<User> users = (List<User>) request.getAttribute("users");
%>
<table>
<% for (User user : users) { %>
<tr>
<td><%= user.getId() %></td>
<td><%= user.getName() %></td>
</tr>
<% } %>
</table>
5.2 RESTfulなJSPアプリケーション
HTTPメソッドを活用した設計:
<%@ page import="javax.servlet.http.HttpServlet" %>
<%
String method = request.getMethod();
switch(method) {
case "GET":
// リソース表示
break;
case "POST":
// リソース作成
break;
case "PUT":
// リソース更新
break;
case "DELETE":
// リソース削除
break;
}
%>
5.3 エラーハンドリング
web.xmlでの設定:
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/error/general.jsp</location>
</error-page>
JSPでのエラーページ:
<%@ page isErrorPage="true" %>
<h1>エラーが発生しました</h1>
<p><%= exception.getMessage() %></p>
第6章 パフォーマンスとセキュリティ
6.1 HTTPパフォーマンス最適化
<%-- 静的リソースのキャッシュ --%>
<%
response.setHeader("Cache-Control", "public, max-age=31536000");
%>
<%-- 圧縮有効化 --%>
<%@ page import="java.util.zip.GZIPOutputStream" %>
<%
String acceptEncoding = request.getHeader("Accept-Encoding");
if (acceptEncoding != null && acceptEncoding.indexOf("gzip") != -1) {
response.setHeader("Content-Encoding", "gzip");
out = new JspWriter(new GZIPOutputStream(response.getOutputStream()));
}
%>
6.2 セキュリティ対策
CSRF対策
<%-- トークン生成 --%>
<%
String csrfToken = UUID.randomUUID().toString();
session.setAttribute("csrfToken", csrfToken);
%>
<%-- フォームに埋め込み --%>
<input type="hidden" name="csrfToken" value="<%= csrfToken %>">
<%-- トークン検証 --%>
<%
String sessionToken = (String) session.getAttribute("csrfToken");
String requestToken = request.getParameter("csrfToken");
if (sessionToken == null || !sessionToken.equals(requestToken)) {
throw new ServletException("CSRFトークンが無効です");
}
%>
XSS対策
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%
// JSTLのfn:escapeXmlを使用
String userInput = request.getParameter("input");
%>
${fn:escapeXml(userInput)}
SQLインジェクション対策
<%@ page import="java.sql.PreparedStatement" %>
<%
// PreparedStatementを使用
String username = request.getParameter("username");
PreparedStatement stmt = connection.prepareStatement(
"SELECT * FROM users WHERE username = ?");
stmt.setString(1, username);
ResultSet rs = stmt.executeQuery();
%>
まとめ
本記事では、JSPを用いたWebアプリケーション開発において重要なクライアント/サーバーモデルとHTTPプロトコルの詳細について解説しました。HTTPのステートレスな性質を理解し、セッション管理やクッキーを適切に扱うことで、効果的なWebアプリケーションを構築できます。また、MVCアーキテクチャの採用やRESTfulな設計、適切なエラーハンドリング、セキュリティ対策など、実践的なテクニックも紹介しました。
JSP開発においてHTTPプロトコルを深く理解することは、パフォーマンスの良い、安全で、ユーザーフレンドリーなアプリケーションを作成するための基礎となります。これらの知識を活用して、より高度なJSPアプリケーションの開発に挑戦してください。