サーブレット&JSPの基本|ひとこと広場のエラーメッセージ表示と仕上げ

空の投稿をそのまま通さない。リクエストスコープでエラーメッセージを渡し、ひとこと広場を仕上げよう

前回の記事では、ひとこと広場の中心機能である投稿と閲覧の機能を作成しました。

メイン画面main.jspに投稿フォームを追加し、Main.javaのdoPostメソッドで投稿内容を受け取りました。そして、ログイン中の利用者名と投稿内容をもとにShortMessageインスタンスを作成し、アプリケーションスコープに保存されているmessageListへ追加しました。

これにより、ログインした利用者がひとことを投稿し、ほかの利用者の投稿も閲覧できるようになりました。

ただし、前回の状態では、空の投稿を送信しても、一覧に追加しないだけでした。利用者から見ると、投稿ボタンを押したのに何も起こらなかったように見えるため、少し分かりにくい画面になります。

そこで今回は、空のまま投稿した場合に、エラーメッセージを表示する機能を追加します。

空投稿時には、Main.javaでエラーメッセージを作成し、リクエストスコープに保存します。そして、フォワード先のmain.jspでそのエラーメッセージを取得し、画面に表示します。

エラーメッセージは、次の画面表示で一度だけ使えればよい情報です。そのため、セッションスコープやアプリケーションスコープではなく、リクエストスコープに保存するのが自然です。

この記事では、Main.javaのdoPostメソッドに空投稿時のelseブロックを追加し、main.jspにエラーメッセージの取得と表示処理を追加します。最後に、ひとこと広場全体で使ってきたServlet、JSP、スコープの役割も整理します。

今回追加する機能

今回追加するのは、空の投稿に対するエラーメッセージ表示です。

利用者が何も入力せずに投稿ボタンをクリックした場合、投稿は保存せず、メイン画面にメッセージを表示します。

追加する動き

状況処理
投稿内容が入力されているShortMessageを作成してmessageListへ追加する
投稿内容が空messageListへ追加せず、エラーメッセージを表示する
エラーメッセージの保存先リクエストスコープ
表示する画面main.jsp

今回表示するエラーメッセージは、次のような内容にします。

ひとことが入力されていません

このメッセージは、空投稿を送信した直後のmain.jspで表示できれば十分です。次のリクエストまで残す必要はありません。

そのため、保存先にはリクエストスコープを使います。

今回修正するファイル

今回の記事では、次の2つのファイルを修正します。

修正するファイル一覧

ファイル種類修正内容
Main.javaコントローラ空投稿時にエラーメッセージをリクエストスコープへ保存する
main.jspビューリクエストスコープからエラーメッセージを取得して表示する

Main.javaでは、doPostメソッドの入力値チェックにelseブロックを追加します。

main.jspでは、request.getAttributeでエラーメッセージを取得し、取得できた場合だけ表示します。

エラーメッセージ表示の全体像

空の投稿を送信した場合、処理は次のように進みます。

空投稿時の処理の流れ

順番内容
1main.jspで何も入力せず投稿ボタンをクリックする
2Main.javaへPOSTリクエストが送られる
3Main.javaのdoPostメソッドが実行される
4request.getParameter("text")で投稿内容を取得する
5textが空であることを確認する
6エラーメッセージをリクエストスコープに保存する
7main.jspへフォワードする
8main.jspでエラーメッセージを取得する
9エラーメッセージを画面に表示する

ポイントは、Main.javaからmain.jspへフォワードしていることです。

フォワードでは、同じリクエストが引き継がれます。そのため、Main.javaでリクエストスコープに保存したエラーメッセージを、main.jspで取得できます。

図1:空投稿時にエラーメッセージを表示する流れ

この図から分かること

空のまま投稿ボタンをクリックすると、Main.javaへPOSTリクエストが送られます。

Main.javaでは、投稿内容をtextとして取得し、文字が入力されているかを確認します。textが空の場合は、投稿リストには追加せず、エラーメッセージをリクエストスコープに保存します。

その後、main.jspへフォワードします。フォワードでは同じリクエストが引き継がれるため、main.jspからリクエストスコープのerrorMsgを取得できます。

main.jspでは、errorMsgが取得できた場合だけ、エラーメッセージを画面に表示します。

エラーメッセージにリクエストスコープを使う理由

エラーメッセージは、空投稿を送信した直後の画面で表示できれば十分です。

ログイン中ずっと残す必要はありません。また、すべての利用者で共有する必要もありません。

そのため、リクエストスコープに保存します。

エラーメッセージとスコープの関係

スコープ今回のエラーメッセージに向いているか理由
リクエストスコープ向いているフォワード先のmain.jspで一度だけ使えばよい
セッションスコープ向いていないログイン中ずっと残る必要がない
アプリケーションスコープ向いていない全ユーザーで共有してはいけない

エラーメッセージをセッションスコープに保存すると、次の画面でも残ってしまう可能性があります。

また、アプリケーションスコープに保存すると、ほかの利用者にも同じエラーメッセージが見えてしまう可能性があります。

今回のように、1回の画面表示だけで使う情報は、リクエストスコープに保存するのが分かりやすい使い方です。

Main.javaで空投稿を判定する

前回のMain.javaでは、投稿内容が空でない場合だけmessageListに追加していました。

今回の記事では、空だった場合のelseブロックを追加します。

入力値チェックの分岐

条件処理
textがnullではなく、文字数が0ではない投稿として登録する
textがnull、または文字数が0エラーメッセージをリクエストスコープに保存する

Main.javaでは、次の条件で投稿内容が入力されているかを確認します。

text != null && text.length() != 0

この条件に当てはまる場合は、投稿処理を行います。

当てはまらない場合は、elseブロックでエラーメッセージを保存します。

リクエストスコープにエラーメッセージを保存する

エラーメッセージは、request.setAttributeを使ってリクエストスコープに保存します。

今回の属性名はerrorMsgにします。

保存する内容

項目内容
属性名errorMsg
保存するインスタンスStringインスタンス
メッセージひとことが入力されていません
保存先リクエストスコープ

Main.javaでは、次のように保存します。

request.setAttribute("errorMsg",
"ひとことが入力されていません");

この処理により、フォワード先のmain.jspでerrorMsgを取得できるようになります。

ひとことに関するリクエストを処理するコントローラを修正する

Main.javaのdoPostメソッドに、空投稿時のエラーメッセージ保存処理を追加します。

ここでは、前回までに作成したdoGetメソッドも含めた形で確認します。

ひとことに関するリクエストを処理するコントローラを修正した例

ファイル名: Main.java

package servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
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.PostMessageLogic;
import model.ShortMessage;
import model.User;

@WebServlet("/Main")
public class Main extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @SuppressWarnings("unchecked")
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {

        // ひとことリストをアプリケーションスコープから取得
        ServletContext application = this.getServletContext();

        List<ShortMessage> messageList =
                (List<ShortMessage>)
                        application.getAttribute("messageList");

        // 取得できなかった場合は、ひとことリストを新規作成して
        // アプリケーションスコープに保存
        if (messageList == null) {
            messageList = new ArrayList<>();
            application.setAttribute("messageList", messageList);
        }

        // ログインしているか確認するため、
        // セッションスコープからユーザー情報を取得
        HttpSession session = request.getSession();

        User loginUser =
                (User) session.getAttribute("loginUser");

        if (loginUser == null) {
            // ログインしていない場合はトップ画面へリダイレクト
            response.sendRedirect("index.jsp");
            return;

        } else {
            // ログイン済みの場合はメイン画面へフォワード
            RequestDispatcher dispatcher =
                    request.getRequestDispatcher(
                            "WEB-INF/jsp/main.jsp");
            dispatcher.forward(request, response);
        }
    }

    @SuppressWarnings("unchecked")
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {

        // リクエストパラメータの取得
        request.setCharacterEncoding("UTF-8");
        String text = request.getParameter("text");

        // 入力値チェック
        if (text != null && text.length() != 0) {

            // アプリケーションスコープに保存されたひとことリストを取得
            ServletContext application = this.getServletContext();

            List<ShortMessage> messageList =
                    (List<ShortMessage>)
                            application.getAttribute("messageList");

            // セッションスコープに保存されたユーザー情報を取得
            HttpSession session = request.getSession();

            User loginUser =
                    (User) session.getAttribute("loginUser");

            // ひとことを作成してひとことリストに追加
            ShortMessage message =
                    new ShortMessage(loginUser.getName(), text);

            PostMessageLogic postMessageLogic =
                    new PostMessageLogic();
            postMessageLogic.execute(message, messageList);

            // アプリケーションスコープにひとことリストを保存
            application.setAttribute("messageList", messageList);

        } else {
            // エラーメッセージをリクエストスコープに保存
            request.setAttribute("errorMsg",
                    "ひとことが入力されていません");
        }

        // メイン画面にフォワード
        RequestDispatcher dispatcher =
                request.getRequestDispatcher("WEB-INF/jsp/main.jsp");
        dispatcher.forward(request, response);
    }
}

Main.javaは、servletパッケージに作成済みのファイルを修正します。

今回追加した大切な部分は、doPostメソッドのelseブロックです。

投稿内容が空の場合、ShortMessageインスタンスは作成しません。messageListにも追加しません。その代わり、errorMsgという属性名でエラーメッセージをリクエストスコープに保存します。

Main.javaの修正ポイント

今回の修正では、投稿できる場合とできない場合の処理を分けています。

doPostメソッドの分岐

分岐内容
if側投稿内容が入力されているため、ShortMessageを作成してmessageListへ追加する
else側投稿内容が空のため、エラーメッセージをリクエストスコープへ保存する

空投稿時にmessageListへ追加しないことで、空の投稿が一覧に表示されることを防げます。

さらに、エラーメッセージを表示することで、利用者に何が起こったのかを伝えられます。

何も表示されない状態よりも、ひとことが入力されていませんと表示されたほうが、利用者にとって分かりやすい画面になります。

図2:リクエストスコープでエラーメッセージを渡す

この図から分かること

Main.javaで作成したエラーメッセージは、リクエストスコープに保存します。

その後、main.jspへフォワードすると、同じリクエストが引き継がれます。そのため、main.jspではrequest.getAttribute("errorMsg")でエラーメッセージを取得できます。

リクエストスコープは、フォワード先のJSPで一度だけ使いたい情報に向いています。

今回のエラーメッセージは、空投稿を送信した直後の画面で表示できればよいため、リクエストスコープが適しています。

main.jspでエラーメッセージを取得する

次に、main.jspを修正します。

main.jspでは、リクエストスコープからerrorMsgを取得します。

main.jspで追加する処理

処理内容
request.getAttribute("errorMsg")リクエストスコープからエラーメッセージを取得する
StringへキャストObject型からString型に変換する
errorMsg != nullメッセージがある場合だけ表示する

request.getAttributeの戻り値はObject型です。

そのため、String型の変数に入れるには、Stringへキャストします。

String errorMsg =
(String) request.getAttribute("errorMsg");

このように取得したerrorMsgがnullでなければ、画面に表示します。

エラーメッセージがあるときだけ表示する

通常の画面表示や、正しく投稿できた場合には、errorMsgは保存されていません。

そのため、main.jspでerrorMsgを取得してもnullになります。

errorMsgがnullのまま表示しようとすると、不要な表示や分かりにくい画面になる可能性があります。

そこで、次のようにif文で確認してから表示します。

<% if (errorMsg != null) { %>

表示条件

errorMsgの状態画面表示
nullではないエラーメッセージを表示する
null何も表示しない

このようにすることで、空投稿時だけエラーメッセージが表示されます。

メイン画面を出力するビューを修正する

main.jspに、エラーメッセージの取得と表示を追加します。

メイン画面を出力するビューを修正した例

ファイル名: main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<%@ page import="model.User, model.ShortMessage, java.util.List" %>
<%
    // セッションスコープに保存されたユーザー情報を取得
    User loginUser =
            (User) session.getAttribute("loginUser");

    // アプリケーションスコープに保存されたひとことリストを取得
    List<ShortMessage> messageList =
            (List<ShortMessage>)
                    application.getAttribute("messageList");

    // リクエストスコープに保存されたエラーメッセージを取得
    String errorMsg =
            (String) request.getAttribute("errorMsg");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ひとこと広場</title>
</head>
<body>
<h1>ひとこと広場メイン</h1>

<p>
<%= loginUser.getName() %>さん、ログイン中
<a href="Logout">ログアウト</a>
</p>

<p><a href="Main">更新</a></p>

<form action="Main" method="post">
<input type="text" name="text">
<input type="submit" value="投稿">
</form>

<% if (errorMsg != null) { %>
<p><%= errorMsg %></p>
<% } %>

<% for (ShortMessage message : messageList) { %>
<p><%= message.getUserName() %>:<%= message.getText() %></p>
<% } %>

</body>
</html>

main.jspは、src/main/webapp/WEB-INF/jspディレクトリにあるファイルを修正します。

今回追加したのは、リクエストスコープからerrorMsgを取得する処理と、errorMsgがnullでない場合だけ表示する処理です。

main.jspの修正ポイント

main.jspでは、3つのスコープから情報を取得しています。

main.jspで取得している情報

取得する情報取得元用途
loginUserセッションスコープログイン中の利用者名を表示する
messageListアプリケーションスコープ投稿一覧を表示する
errorMsgリクエストスコープ空投稿時のエラーメッセージを表示する

この画面では、3種類のスコープを使い分けています。

ログイン中の利用者は、ユーザーごとに管理する情報なのでセッションスコープから取得します。

投稿一覧は、全ユーザーで共有する情報なのでアプリケーションスコープから取得します。

エラーメッセージは、今回のリクエストだけで使う一時的な情報なのでリクエストスコープから取得します。

3つのスコープが同じ画面で使われる

ひとこと広場のmain.jspは、ServletとJSPの学習にとてもよい画面です。

なぜなら、1つの画面の中で、リクエストスコープ、セッションスコープ、アプリケーションスコープを使い分けているからです。

main.jspでのスコープの使い分け

スコープ使う情報理由
リクエストスコープerrorMsg空投稿時の画面表示で一度だけ使う
セッションスコープloginUserログイン中の利用者ごとに必要
アプリケーションスコープmessageListすべての利用者で投稿一覧を共有する

同じJSP内であっても、情報の性質によって保存先が変わります。

どの情報を、誰が、いつまで使うのかを考えると、適切なスコープを選びやすくなります。

図3:main.jspで使う3つのスコープ

この図から分かること

main.jspでは、3つのスコープから情報を取得しています。

リクエストスコープからは、空投稿時のエラーメッセージを取得します。これは一度だけ表示できればよい情報です。

セッションスコープからは、ログイン中の利用者情報を取得します。これはユーザーごとに管理する情報です。

アプリケーションスコープからは、投稿一覧であるmessageListを取得します。これはすべての利用者で共有する情報です。

このように、情報の性質に合わせてスコープを使い分けることで、画面表示とデータ管理を整理できます。

エラーメッセージ表示の動作確認

ここまで作成できたら、エラーメッセージ表示の動作を確認します。

エラーメッセージを確認する手順

手順内容
1ブラウザでhttp://localhost:8080/Hiroba/へアクセスする
2任意の利用者名とパスワード1234でログインする
3ログイン結果画面からひとこと投稿・閲覧へをクリックする
4メイン画面で入力欄を空のまま投稿ボタンをクリックする
5ひとことが入力されていませんと表示されることを確認する

空の投稿を送信したときに、投稿一覧へ空行が追加されず、エラーメッセージだけが表示されれば正しく動作しています。

ブラウザの表示例

正常な投稿も確認する

エラーメッセージを追加したあとも、通常の投稿ができることを確認します。

通常投稿の確認手順

手順内容
1メイン画面の入力欄に今日はJSPを復習しましたと入力する
2投稿ボタンをクリックする
3投稿一覧に利用者名:今日はJSPを復習しましたと表示されることを確認する
4エラーメッセージが表示されていないことを確認する

投稿内容が入力されている場合は、Main.javaのif側の処理が実行されます。

そのため、ShortMessageインスタンスが作成され、messageListの先頭へ追加されます。

ブラウザの表示例

複数ユーザーで投稿が共有されることを確認する

ひとこと広場では、messageListをアプリケーションスコープに保存しています。

そのため、別の利用者でログインしても、同じ投稿一覧を閲覧できます。

複数ユーザーでの確認

手順内容
1ユーザーAでログインしてひとことを投稿する
2ユーザーAをログアウトする
3ブラウザを閉じる
4ユーザーBでログインする
5ユーザーAの投稿が表示されることを確認する
6ユーザーBでひとことを投稿する
7ユーザーBの投稿が一覧の一番上に表示されることを確認する

投稿一覧がユーザーをまたいで表示されれば、アプリケーションスコープのmessageListが正しく共有されています。

ブラウザの表示例

投稿リストの有効期間に注意する

投稿一覧はアプリケーションスコープに保存しています。

アプリケーションスコープは、Webアプリケーションが動いている間だけ利用できる保存領域です。

そのため、ブラウザを閉じても投稿一覧が残る場合がありますが、サーバを停止したり再起動したりすると、投稿一覧は消えます。

投稿一覧が残る場合と消える場合

操作投稿一覧の状態
画面を更新する残る
ブラウザを閉じて再度ログインするWebアプリケーションが動いていれば残る
別の利用者でログインするWebアプリケーションが動いていれば表示される
サーバを停止する消える
サーバを再起動する消える
Webアプリケーションが再読み込みされる消えることがある

今回は、ファイルやデータベースに投稿を保存していません。

そのため、サーバを再起動したあとも投稿を残したい場合は、別の保存方法が必要になります。ただし、このアプリケーションでは、ServletとJSP、スコープの基本を学習することが目的なので、アプリケーションスコープで投稿一覧を管理します。

スコープに保存したインスタンスの変更について

今回のMain.javaでは、アプリケーションスコープから取得したmessageListにShortMessageインスタンスを追加しています。

ここで大切なのは、getAttributeで取得したインスタンスの内容を変更すると、スコープ内のインスタンスにも変更が反映されるという点です。

これは、Javaではインスタンスを参照して扱うためです。

messageListの変更イメージ

操作内容
application.getAttribute("messageList")アプリケーションスコープ内のmessageListを参照する
messageList.add(0, message)参照しているリストにShortMessageを追加する
application.setAttribute("messageList", messageList)更新後のリストを保存し直す

実際には、getAttributeで取得したmessageListにaddした時点で、アプリケーションスコープ内のリストにも投稿が追加されています。

そのため、今回のようにapplication.setAttribute("messageList", messageList)を再度実行しなくても、同じ結果になる場合があります。

ただし、学習段階では、取得する、変更する、保存するという流れで理解しておくと、スコープに対する操作が整理しやすくなります。

ひとこと広場で使った主な技術

ひとこと広場では、これまで学習してきたServletとJSPの重要な内容を組み合わせました。

使用した主な技術

技術使った場面
JSPトップ画面、ログイン結果画面、メイン画面、ログアウト画面の表示
Servletログイン処理、メイン画面表示、投稿処理、ログアウト処理
JavaBeansUser、ShortMessageとして情報をまとめる
フォームログイン情報や投稿内容を送信する
GET画面表示やリンクによるリクエスト
POSTログイン情報や投稿内容の送信
フォワードサーブレットからWEB-INF内のJSPへ処理を渡す
リダイレクト未ログイン時にトップ画面へ戻す
リクエストスコープエラーメッセージを一時的に渡す
セッションスコープログイン中の利用者情報を保存する
アプリケーションスコープ全ユーザーの投稿一覧を共有する
ArrayList複数の投稿をリストとして管理する

ひとこと広場はシンプルなアプリケーションですが、Webアプリケーション開発の基本が多く含まれています。

1つずつの技術を別々に見るだけでなく、それらを組み合わせて動かすことで、ServletとJSPの理解が深まります。

GETとPOSTの使い分け

ひとこと広場では、Main.javaがGETとPOSTの両方に対応しています。

Main.javaの役割

リクエスト方法実行されるメソッド処理内容
GETdoGetメイン画面を表示する
POSTdoPostひとこと投稿を処理する

画面を表示したいときはGETを使います。

入力された内容を送信して処理したいときはPOSTを使います。

Main.javaは、同じURLパターン/Mainであっても、リクエスト方法によって異なる処理を行います。

このように、1つのサーブレットがGETとPOSTで別の役割を持つ構成は、Servlet学習の大切なポイントです。

フォワードとリダイレクトの使い分け

ひとこと広場では、フォワードとリダイレクトも使い分けています。

使い分けの例

処理使用する方法理由
Login.javaからloginResult.jspへ移動フォワードサーブレットの処理結果をJSPで表示するため
Main.javaからmain.jspへ移動フォワードメイン画面をJSPで表示するため
Logout.javaからlogout.jspへ移動フォワードログアウト後の画面をJSPで表示するため
未ログイン時にindex.jspへ戻すリダイレクトURLと画面を一致させるため

フォワードは、サーバ内部でJSPへ処理を渡すときに使います。

リダイレクトは、ブラウザに別のURLへアクセスし直してもらいたいときに使います。

未ログインでMainへ直接アクセスされた場合は、トップ画面へ戻ってログインし直してもらう流れが自然です。そのため、リダイレクトを使っています。

ひとこと広場のファイル構成

最後に、ひとこと広場で作成した主なファイルを整理しておきます。

主なファイル一覧

ファイル保存場所役割
User.javasrc/main/java/model利用者名とパスワードを保持する
ShortMessage.javasrc/main/java/model投稿者名と投稿内容を保持する
LoginLogic.javasrc/main/java/modelログイン判定を行う
PostMessageLogic.javasrc/main/java/modelひとことをリストへ追加する
Login.javasrc/main/java/servletログインリクエストを処理する
Main.javasrc/main/java/servletメイン画面表示と投稿処理を行う
Logout.javasrc/main/java/servletログアウト処理を行う
index.jspsrc/main/webappトップ画面を表示する
loginResult.jspsrc/main/webapp/WEB-INF/jspログイン結果画面を表示する
main.jspsrc/main/webapp/WEB-INF/jspメイン画面を表示する
logout.jspsrc/main/webapp/WEB-INF/jspログアウト画面を表示する

Hirobaでは、モデル、ビュー、コントローラを分けて作成しています。

モデルはmodelパッケージに作成し、サーブレットはservletパッケージに作成します。

JSPのうち、ブラウザから直接アクセスするトップ画面index.jspはsrc/main/webappに置きます。サーブレットからフォワードして表示するloginResult.jsp、main.jsp、logout.jspはWEB-INF/jspに置きます。

仕上げの動作確認

すべての機能がそろったら、ひとこと広場全体を通して動作確認します。

全体確認の手順

手順内容
1http://localhost:8080/Hiroba/へアクセスする
2任意の利用者名とパスワード1234でログインする
3ログイン成功画面が表示されることを確認する
4ひとこと投稿・閲覧へリンクをクリックする
5メイン画面が表示されることを確認する
6ひとことを投稿し、一覧に表示されることを確認する
72件目を投稿し、新しい投稿が上に表示されることを確認する
8空のまま投稿し、エラーメッセージが表示されることを確認する
9ログアウトリンクをクリックする
10ログアウトしましたと表示されることを確認する
11トップへリンクからトップ画面へ戻る
12ログアウト後にhttp://localhost:8080/Hiroba/Mainへ直接アクセスする
13トップ画面へ戻されることを確認する

この流れが確認できれば、ログイン、メイン画面表示、投稿、閲覧、エラー表示、ログアウトまで一通り動作しています。

うまく動かないときに確認するポイント

エラーが出た場合は、どのファイルで、どの処理がうまくいっていないのかを落ち着いて確認しましょう。

よく確認したいポイント

症状確認する内容
トップ画面が表示されないURLがhttp://localhost:8080/Hiroba/になっているか
ログインできないパスワードが1234になっているか
Loginが見つからないindex.jspのformタグのaction属性がLoginになっているか
メイン画面へ進めないLogin.javaでloginUserをセッションスコープに保存しているか
Mainが404になるMain.javaの@WebServletが/Mainになっているか
投稿内容が取得できないinputタグのname属性とrequest.getParameter("text")が一致しているか
投稿一覧が表示されないmessageListをアプリケーションスコープから取得しているか
空投稿時にメッセージが出ないMain.javaでrequest.setAttribute("errorMsg", ...)を実行しているか
JSPでエラーになるpageディレクティブで必要なクラスをimportしているか
ログアウトできないLogout.javaでsession.invalidateを実行しているか

Webアプリケーション開発では、エラーが出ることは珍しくありません。

大切なのは、画面、サーブレット、モデル、スコープのどこで値が止まっているのかを順番に確認することです。

ファイル名、URLパターン、formタグのaction属性、inputタグのname属性、getParameterの引数、setAttributeとgetAttributeの属性名がそろっているかを確認すると、原因を見つけやすくなります。

ひとこと広場を作り終えたあとに意識したいこと

ひとこと広場は、学習用としてシンプルに作ったWebアプリケーションです。

実際のWebアプリケーションでは、さらに多くの機能や対策が必要になります。

たとえば、ユーザー情報をデータベースで管理したり、投稿内容を永続保存したり、入力値をより厳密にチェックしたりする必要があります。

しかし、今回のひとこと広場には、ServletとJSPでWebアプリケーションを作るうえで大切な基本が詰まっています。

ログイン情報をセッションスコープに保存すること、投稿一覧をアプリケーションスコープで共有すること、エラーメッセージをリクエストスコープで渡すこと、そしてサーブレットとJSPで役割を分担することです。

これらの流れを一度作って終わりにせず、何度か作り直してみると、どのファイルが何を担当しているのかが自然に整理されていきます。

最初はエラーが多くても、1つずつ修正しながら完成まで進めることで、ServletとJSPの基礎力がしっかり身についていきます。