はじめに
Servlet/JSP入門の 最終回 は 総合演習:掲示板アプリ(BBS) の作成です。
これまで9回にわたって学んできたServlet/JSPの知識を総動員して、実際に動く掲示板Webアプリケーションを一から作り上げます。
このアプリで使う技術
| 回 | 技術 | 使いどころ |
|---|---|---|
| ①② | Servlet, HTTP | コントローラー、リクエスト処理 |
| ③ | JSP | ビュー(画面表示) |
| ④ | フォーム処理 | メッセージ投稿フォーム |
| ⑤ | セッション | ユーザー名の保持 |
| ⑥ | MVCパターン | アプリ全体の設計 |
| ⑧ | EL式+JSTL | JSPの記述 |
| ⑨ | フィルター | 文字エンコーディング |
1. プロジェクト概要
掲示板アプリの機能
| 機能 | 説明 |
|---|---|
| メッセージ一覧表示 | 投稿されたメッセージを新しい順に表示 |
| メッセージ投稿 | 名前と本文を入力して投稿 |
| メッセージ削除 | 投稿済みメッセージを削除 |
| 名前の記憶 | セッションで前回入力した名前を保持 |
完成イメージ
┌─────────────────────────────────────────────┐
│ 掲示板 │
├─────────────────────────────────────────────┤
│ 名前: [田中太郎 ] │
│ メッセージ: │
│ [ ]│
│ [ ]│
│ [投稿する] │
├─────────────────────────────────────────────┤
│ #3 田中太郎 (2025/04/15 14:30) │
│ 今日はいい天気ですね! │
│ [削除] │
│─────────────────────────────────────────────│
│ #2 鈴木花子 (2025/04/15 14:25) │
│ Javaの勉強中です。 │
│ [削除] │
│─────────────────────────────────────────────│
│ #1 佐藤次郎 (2025/04/15 14:20) │
│ はじめまして! │
│ [削除] │
└─────────────────────────────────────────────┘
2. プロジェクト構成(MVCパターン)
BulletinBoard/
├── src/main/java/
│ ├── model/
│ │ ├── Message.java ← Model: メッセージデータ
│ │ └── MessageDAO.java ← Model: データアクセス
│ ├── servlet/
│ │ ├── MessageListServlet.java ← Controller: 一覧表示
│ │ ├── MessagePostServlet.java ← Controller: 投稿処理
│ │ └── MessageDeleteServlet.java← Controller: 削除処理
│ └── filter/
│ └── EncodingFilter.java ← Filter: 文字コード設定
├── src/main/webapp/
│ ├── WEB-INF/
│ │ ├── jsp/
│ │ │ ├── board.jsp ← View: 掲示板画面
│ │ │ └── error.jsp ← View: エラー画面
│ │ └── web.xml
│ └── css/
│ └── style.css ← スタイルシート
MVCの役割分担
ブラウザ
│
▼
[EncodingFilter] ← 文字コード設定
│
▼
[Servlet (Controller)] ← リクエスト処理、ビジネスロジック呼び出し
│ │
│ ▼
│ [MessageDAO (Model)] ← データの保存・取得
│ │
│ ▼
│ [Message (Model)] ← データを保持するJavaBean
│
▼
[JSP (View)] ← EL式+JSTLでHTMLを生成
│
▼
ブラウザ
3. Step 1: Model - Message クラス
メッセージを表すJavaBeanクラスを作成します。
Message.java
package model;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String author;
private String content;
private LocalDateTime postedAt;
// デフォルトコンストラクタ
public Message() {}
// パラメータ付きコンストラクタ
public Message(int id, String author, String content, LocalDateTime postedAt) {
this.id = id;
this.author = author;
this.content = content;
this.postedAt = postedAt;
}
// getter / setter
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getAuthor() { return author; }
public void setAuthor(String author) { this.author = author; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public LocalDateTime getPostedAt() { return postedAt; }
public void setPostedAt(LocalDateTime postedAt) { this.postedAt = postedAt; }
// フォーマット済みの日時を返すメソッド
public String getFormattedDate() {
if (postedAt == null) return "";
return postedAt.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"));
}
}
ポイント:
-
Serializableを実装しているのは、セッションに保存する可能性があるためです -
getFormattedDate()は EL式で${message.formattedDate}としてアクセスできます
4. Step 2: Model - MessageDAO クラス
データの保存・取得を管理するDAOクラスです。今回は ArrayList でメモリ上にデータを保持します(アプリを再起動するとデータは消えます)。
MessageDAO.java
package model;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MessageDAO {
// メッセージを保持するリスト(アプリ全体で共有)
private static final List<Message> messages = new ArrayList<>();
private static int nextId = 1;
// 初期データ(テスト用)
static {
messages.add(new Message(nextId++, "管理人", "掲示板へようこそ!ルールを守って楽しく使いましょう。",
LocalDateTime.of(2025, 4, 1, 9, 0)));
}
// 全件取得(新しい順)
public List<Message> findAll() {
List<Message> result = new ArrayList<>(messages);
Collections.reverse(result);
return result;
}
// IDで1件取得
public Message findById(int id) {
for (Message msg : messages) {
if (msg.getId() == id) {
return msg;
}
}
return null;
}
// 投稿
public synchronized void insert(String author, String content) {
Message msg = new Message(nextId++, author, content, LocalDateTime.now());
messages.add(msg);
}
// 削除
public synchronized boolean delete(int id) {
return messages.removeIf(msg -> msg.getId() == id);
}
// 件数取得
public int count() {
return messages.size();
}
}
ポイント:
-
staticフィールドでデータを保持しているため、すべてのリクエストで同じデータを参照できます -
synchronizedで排他制御し、同時アクセスでのデータ不整合を防いでいます - 実際のアプリケーションでは、ここをDBアクセスに置き換えます(第7回のJDBC連携参照)
5. Step 3: Filter - EncodingFilter
すべてのリクエスト・レスポンスにUTF-8を設定するフィルターです。
EncodingFilter.java
package filter;
import java.io.IOException;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
@Override
public void destroy() {}
}
6. Step 4: Controller - Servlet クラス
6.1 MessageListServlet.java(一覧表示)
掲示板のメインページを表示するServletです。
package servlet;
import java.io.IOException;
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;
import jakarta.servlet.http.HttpSession;
import model.Message;
import model.MessageDAO;
@WebServlet("/board")
public class MessageListServlet extends HttpServlet {
private MessageDAO dao = new MessageDAO();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// メッセージ一覧を取得
List<Message> messages = dao.findAll();
request.setAttribute("messages", messages);
request.setAttribute("messageCount", dao.count());
// セッションから前回の投稿者名を取得(フォームの初期値用)
HttpSession session = request.getSession();
String lastAuthor = (String) session.getAttribute("lastAuthor");
if (lastAuthor != null) {
request.setAttribute("lastAuthor", lastAuthor);
}
// エラーメッセージがあれば取得
String error = (String) session.getAttribute("error");
if (error != null) {
request.setAttribute("error", error);
session.removeAttribute("error");
}
// 成功メッセージがあれば取得
String success = (String) session.getAttribute("success");
if (success != null) {
request.setAttribute("success", success);
session.removeAttribute("success");
}
// JSPにフォワード
request.getRequestDispatcher("/WEB-INF/jsp/board.jsp").forward(request, response);
}
}
6.2 MessagePostServlet.java(投稿処理)
メッセージの投稿を処理するServletです。
package servlet;
import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import model.MessageDAO;
@WebServlet("/board/post")
public class MessagePostServlet extends HttpServlet {
private MessageDAO dao = new MessageDAO();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
// パラメータ取得
String author = request.getParameter("author");
String content = request.getParameter("content");
// バリデーション
if (author == null || author.trim().isEmpty()) {
session.setAttribute("error", "名前を入力してください。");
response.sendRedirect(request.getContextPath() + "/board");
return;
}
if (content == null || content.trim().isEmpty()) {
session.setAttribute("error", "メッセージを入力してください。");
response.sendRedirect(request.getContextPath() + "/board");
return;
}
// 文字数チェック
if (author.trim().length() > 20) {
session.setAttribute("error", "名前は20文字以内で入力してください。");
response.sendRedirect(request.getContextPath() + "/board");
return;
}
if (content.trim().length() > 500) {
session.setAttribute("error", "メッセージは500文字以内で入力してください。");
response.sendRedirect(request.getContextPath() + "/board");
return;
}
// メッセージを保存
dao.insert(author.trim(), content.trim());
// 投稿者名をセッションに保存(次回のフォーム初期値)
session.setAttribute("lastAuthor", author.trim());
session.setAttribute("success", "メッセージを投稿しました!");
// PRGパターン:POST後にリダイレクトでGET
response.sendRedirect(request.getContextPath() + "/board");
}
}
ポイント: PRGパターン(Post/Redirect/Get) を使っています。POST処理後にリダイレクトすることで、ブラウザの更新ボタンで二重投稿されることを防ぎます。
6.3 MessageDeleteServlet.java(削除処理)
メッセージの削除を処理するServletです。
package servlet;
import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import model.MessageDAO;
@WebServlet("/board/delete")
public class MessageDeleteServlet extends HttpServlet {
private MessageDAO dao = new MessageDAO();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
String idStr = request.getParameter("id");
if (idStr == null || idStr.isEmpty()) {
session.setAttribute("error", "削除対象が指定されていません。");
response.sendRedirect(request.getContextPath() + "/board");
return;
}
try {
int id = Integer.parseInt(idStr);
boolean deleted = dao.delete(id);
if (deleted) {
session.setAttribute("success", "メッセージを削除しました。");
} else {
session.setAttribute("error", "指定されたメッセージが見つかりませんでした。");
}
} catch (NumberFormatException e) {
session.setAttribute("error", "不正なIDが指定されました。");
}
response.sendRedirect(request.getContextPath() + "/board");
}
}
7. Step 5: View - JSPファイル
7.1 board.jsp(掲示板メイン画面)
EL式とJSTLを使ってHTMLを生成します。
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<%@ taglib prefix="fn" uri="jakarta.tags.functions" %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>掲示板</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">
</head>
<body>
<div class="container">
<header>
<h1>掲示板</h1>
<p class="subtitle">メッセージ数: ${messageCount}件</p>
</header>
<!-- エラーメッセージ -->
<c:if test="${not empty error}">
<div class="alert alert-error">
<c:out value="${error}" />
</div>
</c:if>
<!-- 成功メッセージ -->
<c:if test="${not empty success}">
<div class="alert alert-success">
<c:out value="${success}" />
</div>
</c:if>
<!-- 投稿フォーム -->
<section class="post-form">
<h2>メッセージを投稿</h2>
<form action="${pageContext.request.contextPath}/board/post" method="post">
<div class="form-group">
<label for="author">名前(20文字以内)</label>
<input type="text" id="author" name="author"
value="<c:out value='${lastAuthor}' />"
maxlength="20" required placeholder="名前を入力">
</div>
<div class="form-group">
<label for="content">メッセージ(500文字以内)</label>
<textarea id="content" name="content" rows="4"
maxlength="500" required placeholder="メッセージを入力"></textarea>
</div>
<button type="submit" class="btn btn-primary">投稿する</button>
</form>
</section>
<!-- メッセージ一覧 -->
<section class="message-list">
<h2>投稿一覧</h2>
<c:choose>
<c:when test="${not empty messages}">
<c:forEach var="msg" items="${messages}">
<article class="message-card">
<div class="message-header">
<span class="message-id">#${msg.id}</span>
<span class="message-author"><c:out value="${msg.author}" /></span>
<span class="message-date">${msg.formattedDate}</span>
</div>
<div class="message-content">
<c:out value="${msg.content}" />
</div>
<div class="message-actions">
<form action="${pageContext.request.contextPath}/board/delete"
method="post"
onsubmit="return confirm('このメッセージを削除しますか?');">
<input type="hidden" name="id" value="${msg.id}">
<button type="submit" class="btn btn-danger btn-sm">削除</button>
</form>
</div>
</article>
</c:forEach>
</c:when>
<c:otherwise>
<p class="no-messages">まだメッセージがありません。最初の投稿をしてみましょう!</p>
</c:otherwise>
</c:choose>
</section>
<footer>
<p>Servlet/JSP 掲示板アプリ - Java研修 総合演習</p>
</footer>
</div>
</body>
</html>
7.2 error.jsp(エラー画面)
<%@ page contentType="text/html; charset=UTF-8" isErrorPage="true" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>エラー</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">
</head>
<body>
<div class="container">
<h1>エラーが発生しました</h1>
<div class="alert alert-error">
<p>申し訳ありません。予期しないエラーが発生しました。</p>
<c:if test="${not empty pageContext.exception}">
<p>エラー内容: <c:out value="${pageContext.exception.message}" /></p>
</c:if>
</div>
<p><a href="${pageContext.request.contextPath}/board" class="btn btn-primary">掲示板に戻る</a></p>
</div>
</body>
</html>
8. Step 6: CSS スタイル
style.css
/* ===== リセット & ベース ===== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Helvetica Neue', Arial, 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', Meiryo, sans-serif;
background-color: #f5f5f5;
color: #333;
line-height: 1.6;
}
/* ===== コンテナ ===== */
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
/* ===== ヘッダー ===== */
header {
background-color: #2196F3;
color: white;
padding: 20px;
border-radius: 8px 8px 0 0;
margin-bottom: 0;
}
header h1 {
font-size: 24px;
}
.subtitle {
font-size: 14px;
opacity: 0.8;
margin-top: 5px;
}
/* ===== アラート ===== */
.alert {
padding: 12px 16px;
border-radius: 4px;
margin-bottom: 16px;
border: 1px solid;
}
.alert-error {
background-color: #ffebee;
color: #c62828;
border-color: #ef9a9a;
}
.alert-success {
background-color: #e8f5e9;
color: #2e7d32;
border-color: #a5d6a7;
}
/* ===== 投稿フォーム ===== */
.post-form {
background-color: white;
padding: 20px;
border: 1px solid #ddd;
margin-bottom: 20px;
}
.post-form h2 {
font-size: 18px;
margin-bottom: 16px;
color: #333;
}
.form-group {
margin-bottom: 12px;
}
.form-group label {
display: block;
font-weight: bold;
margin-bottom: 4px;
font-size: 14px;
color: #555;
}
.form-group input[type="text"],
.form-group textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
font-family: inherit;
transition: border-color 0.3s;
}
.form-group input[type="text"]:focus,
.form-group textarea:focus {
outline: none;
border-color: #2196F3;
box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.2);
}
/* ===== ボタン ===== */
.btn {
display: inline-block;
padding: 10px 20px;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
text-decoration: none;
transition: background-color 0.3s;
}
.btn-primary {
background-color: #2196F3;
color: white;
}
.btn-primary:hover {
background-color: #1976D2;
}
.btn-danger {
background-color: #f44336;
color: white;
}
.btn-danger:hover {
background-color: #d32f2f;
}
.btn-sm {
padding: 4px 12px;
font-size: 12px;
}
/* ===== メッセージ一覧 ===== */
.message-list {
margin-top: 20px;
}
.message-list h2 {
font-size: 18px;
margin-bottom: 16px;
color: #333;
}
.message-card {
background-color: white;
border: 1px solid #ddd;
border-radius: 4px;
padding: 16px;
margin-bottom: 12px;
transition: box-shadow 0.3s;
}
.message-card:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
font-size: 14px;
}
.message-id {
color: #999;
font-size: 12px;
}
.message-author {
font-weight: bold;
color: #2196F3;
}
.message-date {
color: #999;
font-size: 12px;
margin-left: auto;
}
.message-content {
font-size: 15px;
line-height: 1.7;
margin-bottom: 8px;
white-space: pre-wrap;
word-wrap: break-word;
}
.message-actions {
text-align: right;
}
.no-messages {
text-align: center;
color: #999;
padding: 40px;
font-size: 16px;
}
/* ===== フッター ===== */
footer {
text-align: center;
margin-top: 40px;
padding: 20px;
color: #999;
font-size: 12px;
}
9. Step 7: web.xml(エラーページ設定)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
version="6.0">
<!-- ウェルカムファイル(index.jspからServletへ転送) -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- エラーページ設定 -->
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/jsp/error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/WEB-INF/jsp/error.jsp</location>
</error-page>
</web-app>
index.jsp(プロジェクトルート直下に配置):
<%-- /board Servletへ転送 --%>
<% response.sendRedirect(request.getContextPath() + "/board"); %>
💡
<welcome-file>は静的ファイル名を指定する仕組みのため、Servletの URL パターン(/board)を直接指定しても動作しません。index.jspを経由してリダイレクトするのが一般的な方法です。
10. 動作確認
アプリの起動
- プロジェクトを右クリック → 実行 → サーバーで実行
- ブラウザで
http://localhost:8080/BulletinBoard/boardにアクセス
動作チェックリスト
| チェック項目 | 確認方法 |
|---|---|
| 初期メッセージが表示される | アクセス直後に管理人のメッセージが見える |
| メッセージが投稿できる | 名前と本文を入力して「投稿する」ボタン |
| 投稿が一覧に反映される | 新しいメッセージが一番上に表示される |
| 名前が記憶される | 投稿後、フォームの名前欄に前回の名前が入る |
| メッセージが削除できる | 削除ボタンで確認ダイアログ後に削除 |
| 空入力でエラーが出る | 名前やメッセージを空にして投稿 |
| 日本語が正しく表示される | 文字化けしない |
11. エラーハンドリング
バリデーションの流れ
ユーザー入力
│
├─ 名前が空 → エラーメッセージ → リダイレクト
├─ メッセージが空 → エラーメッセージ → リダイレクト
├─ 名前が20文字超 → エラーメッセージ → リダイレクト
├─ メッセージが500文字超 → エラーメッセージ → リダイレクト
└─ OK → 保存 → 成功メッセージ → リダイレクト
XSS対策
JSTLの <c:out> タグを使うことで、ユーザー入力のHTMLエスケープを行っています。
<!-- 安全: HTMLエスケープされる -->
<c:out value="${msg.content}" />
<!-- 危険: エスケープされない(使わないこと) -->
${msg.content}
12. 拡張アイデア
この掲示板アプリをベースに、以下の機能を追加してみましょう。
拡張1:ログイン機能
| 追加要素 | 説明 |
|---|---|
| ログイン画面 | ユーザー名とパスワードの入力フォーム |
| 認証処理 | DBまたはメモリ上のユーザーリストと照合 |
| セッション管理 | ログイン状態をセッションで管理 |
| 認証フィルター | 未ログインユーザーをリダイレクト |
| 自分の投稿のみ削除可能 | メッセージの投稿者とログインユーザーを比較 |
拡張2:返信機能
- メッセージに対する返信(親ID + 子メッセージ)
- スレッド形式の表示
拡張3:検索機能
- キーワードでメッセージを検索
- 投稿者名で絞り込み
拡張4:ページング
- 1ページあたりの表示件数を制限(例:10件)
- 「次へ」「前へ」のリンク
拡張5:データベース連携
MessageDAO を JDBC を使ったDB版に置き換えます(第7回参照)。
// Before: ArrayList版
private static final List<Message> messages = new ArrayList<>();
// After: DB版
public List<Message> findAll() {
String sql = "SELECT id, author, content, posted_at FROM messages ORDER BY id DESC";
// PreparedStatement で実行 ...
}
CREATE TABLE messages (
id INT AUTO_INCREMENT PRIMARY KEY,
author VARCHAR(20) NOT NULL,
content VARCHAR(500) NOT NULL,
posted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
全ソースコード一覧
最後に、このアプリのすべてのファイルを一覧にします。
| ファイル | 場所 | 役割 |
|---|---|---|
Message.java |
src/main/java/model/ |
メッセージのJavaBean |
MessageDAO.java |
src/main/java/model/ |
データアクセスオブジェクト |
MessageListServlet.java |
src/main/java/servlet/ |
一覧表示(GET /board) |
MessagePostServlet.java |
src/main/java/servlet/ |
投稿処理(POST /board/post) |
MessageDeleteServlet.java |
src/main/java/servlet/ |
削除処理(POST /board/delete) |
EncodingFilter.java |
src/main/java/filter/ |
文字エンコーディング設定 |
board.jsp |
src/main/webapp/WEB-INF/jsp/ |
掲示板メイン画面 |
error.jsp |
src/main/webapp/WEB-INF/jsp/ |
エラー画面 |
style.css |
src/main/webapp/css/ |
スタイルシート |
web.xml |
src/main/webapp/WEB-INF/ |
アプリ設定 |
まとめ
| 学んだこと | キーワード |
|---|---|
| MVCパターンの実践 | Model(Bean + DAO)、View(JSP)、Controller(Servlet) |
| フォーム処理 | POST送信、バリデーション、PRGパターン |
| セッション活用 | 名前の記憶、フラッシュメッセージ |
| EL式+JSTL | スクリプトレットなしのJSP |
| フィルター | 文字エンコーディングの一元管理 |
| エラーハンドリング | バリデーション、エラーページ、XSS対策 |
| CSS | Webアプリの見た目を整える |
シリーズ完結!
全10回のServlet/JSP入門シリーズをお読みいただきありがとうございました。
学習の振り返り
| 回 | テーマ | 主なスキル |
|---|---|---|
| ① | 環境構築とはじめてのServlet | Eclipse + Tomcat、@WebServlet、doGet |
| ② | HTTPリクエストとレスポンス | getParameter、ヘッダー、ステータスコード |
| ③ | JSPの基礎 | スクリプトレット、ディレクティブ、フォワード |
| ④ | フォーム処理(GET/POST) | HTML form、doPost、PRGパターン |
| ⑤ | セッション管理とCookie | HttpSession、Cookie、ログイン管理 |
| ⑥ | MVCパターン | Servlet + JSP の役割分担、リダイレクト |
| ⑦ | JDBC連携 | Connection、PreparedStatement、DAOパターン |
| ⑧ | EL式とJSTL | ${式}、c:if、c:forEach、fmt:formatDate |
| ⑨ | フィルターとリスナー | Filter、@WebFilter、ServletContextListener |
| ⑩ | 総合演習:掲示板アプリ | 全技術を統合したWebアプリ開発 |
次のステップ
このシリーズで学んだServlet/JSPの知識は、以下の学習の土台になります。
| ステップ | 内容 |
|---|---|
| Spring Boot | Servlet/JSPの上位フレームワーク。実務で最も使われる |
| JPA / MyBatis | JDBCの上位ORM。SQLを直接書かずにDB操作 |
| Thymeleaf | JSPの後継的なテンプレートエンジン |
| REST API | JSON形式のAPI開発 |
| セキュリティ | Spring Security、CSRF対策、XSS対策 |
Servlet/JSPの仕組みを理解していれば、Spring Bootなどのフレームワークが「何をしているのか」が見えるようになります。基礎をしっかり固めて、次のステップに進みましょう!
シリーズ一覧:Servlet/JSP入門
- 環境構築とはじめてのServlet
- HTTPリクエストとレスポンス
- JSPの基礎
- フォーム処理(GET/POST)
- セッション管理とCookie
- MVCパターン(Servlet + JSP)
- JDBC連携(データベース操作)
- EL式とJSTL
- フィルターとリスナー
- 👉 総合演習:掲示板アプリを作ろう(本記事)
著者: @kotaro_ai_lab
AI駆動開発やテック情報を毎日発信しています。フォローお気軽にどうぞ!