サーブレット&JSPの基本|フォームとサーブレットの連携

フォームで入力し、サーブレットで受け取る。画面とJavaをつなげてWebアプリケーションらしい動きを作ろう

フォームの作り方と、リクエストパラメータの取得方法を学んだら、次はそれらを組み合わせて実際に動くプログラムを作成してみましょう。

ここでは、フォームから入力された内容をサーブレットへ送信し、サーブレット側でリクエストパラメータを取得して、結果画面を表示する流れを作ります。

今回作成するのは、イベント参加申し込みのような簡単なプログラムです。実際にファイルやデータベースへ登録するわけではありませんが、フォームから送信された名前や参加区分をサーブレットで受け取り、入力内容に応じて成功メッセージまたはエラーメッセージを表示します。

このプログラムでは、JSPファイルで入力画面を作成し、サーブレットクラスで送信データを受け取ります。入力画面をJSPで作成しておくと、あとでJavaの処理を追加しやすくなります。ただし、現段階ではサーブレットとJSPの本格的な役割分担を深く考えすぎなくても大丈夫です。まずは、フォームとサーブレットがどのように連携するのかを手を動かして確認していきましょう。

今回作成するプログラムの全体像

今回のプログラムでは、最初に入力画面を表示します。利用者は名前を入力し、参加区分を選択して送信ボタンをクリックします。

送信されたデータは、POSTリクエストとしてサーブレットへ送られます。サーブレットは、リクエストパラメータを取得し、入力内容を確認します。

名前と参加区分がどちらも入力されていれば、申し込み完了のメッセージを表示します。どちらかが未入力であれば、エラーメッセージを表示します。

画面の流れ

画面内容
イベント参加入力画面名前と参加区分を入力する
申し込み結果画面 成功入力された名前と参加区分を使って完了メッセージを表示する
申し込み結果画面 失敗未入力の項目に応じてエラーメッセージを表示する

このように、フォームから送られた値によって、サーブレットが表示内容を切り替えます。

図1:イベント参加申し込みプログラムの画面遷移

この図から分かること

フォームを使ったWebアプリケーションでは、入力画面から結果画面へ移動する流れが生まれます。

利用者が名前と参加区分を入力して送信すると、入力データはリクエストパラメータとしてサーブレットへ送られます。サーブレットは、その値を取得して、入力内容が正しいかどうかを確認します。

名前と参加区分がそろっていれば成功画面を表示し、不足している項目があれば失敗画面を表示します。フォームとサーブレットを連携させることで、利用者の入力に応じた結果を返せるようになります。

プログラムの構成

今回のプログラムは、JSPファイルとサーブレットクラスを組み合わせて作成します。

JSPファイルは、イベント参加入力画面を表示します。サーブレットクラスは、フォームから送信されたデータを受け取り、結果画面をHTMLとして返します。

作成するファイル

ファイル保存場所役割
entry-form.jspsrc/main/webappイベント参加入力画面を表示する
EntryServlet.javaservletパッケージ入力データを受け取り、結果画面を表示する

プロジェクト名はstudyにします。

最初にブラウザからリクエストするのはentry-form.jspです。EntryServlet.javaを最初に直接実行するのではありません。

フォームとサーブレットの処理の流れ

entry-form.jspを実行すると、ブラウザにイベント参加入力画面が表示されます。

利用者がフォームに入力し、申し込むボタンをクリックすると、フォームのaction属性で指定されたEntryServletへリクエストが送られます。

このとき、method属性がpostなので、POSTリクエストとして送信されます。EntryServletではdoPostメソッドが実行され、request.getParameterで入力値を取得します。

処理の流れ

順番内容
1ブラウザでentry-form.jspをリクエストする
2入力画面がブラウザに表示される
3名前と参加区分を入力して送信する
4POSTリクエストでEntryServletへ送信される
5EntryServletのdoPostメソッドが実行される
6リクエストパラメータを取得する
7入力内容をチェックする
8成功または失敗の結果画面をレスポンスする

この流れを理解しておくと、フォームとサーブレットの役割分担が見えやすくなります。

図2:JSPフォームからサーブレットへ送信する構成

この図から分かること

今回のプログラムでは、entry-form.jspが入力画面を担当し、EntryServlet.javaが送信データの取得と結果表示を担当します。

ブラウザから最初にアクセスするのはentry-form.jspです。フォームの送信ボタンをクリックすると、action属性で指定されたEntryServletへPOSTリクエストが送られます。

EntryServletでは、doPostメソッドが実行されます。その中でrequest.getParameterを使って名前や参加区分を取得し、入力内容に応じた結果HTMLを作成してブラウザへ返します。

入力画面のJSPファイルを作成する

まず、イベント参加入力画面を表示するJSPファイルを作成します。

studyプロジェクトのsrc/main/webapp直下に、entry-form.jspを作成します。

このJSPファイルには、名前を入力するテキストボックス、参加区分を選ぶラジオボタン、申し込み用の送信ボタンを配置します。

イベント参加入力画面のJSPファイルの例

ファイル名: entry-form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>イベント参加申し込み</title>
</head>
<body>
<form action="EntryServlet" method="post">
名前:<br>
<input type="text" name="name"><br>
参加区分:<br>
一般参加<input type="radio" name="ticket" value="general">
学生参加<input type="radio" name="ticket" value="student"><br>
<input type="submit" value="申し込む">
</form>
</body>
</html>

ブラウザの表示例

このJSPファイルは、フォームを表示するための画面です。現時点ではJavaの処理はほとんど書いていませんが、JSPファイルとして作成しておくことで、あとでJavaのコードを追加しやすくなります。

entry-form.jspのポイント

entry-form.jspで特に大切なのは、formタグのaction属性、method属性、各部品のname属性です。

entry-form.jspの主な設定

記述役割
action="EntryServlet"送信先としてEntryServletを指定する
method="post"POSTリクエストで送信する
name="name"名前入力欄の識別名
name="ticket"参加区分ラジオボタンの識別名
value="general"一般参加を選んだときに送信される値
value="student"学生参加を選んだときに送信される値
type="submit"送信ボタンを作成する

formタグの中にある部品だけが送信対象になります。

名前のテキストボックスにはname属性としてnameを指定しています。参加区分のラジオボタンは、どちらもname属性をticketにしています。同じname属性にすることで、一般参加と学生参加が1つの選択肢グループになります。

利用者が学生参加を選んだ場合、送信される値は画面上の学生参加という文字ではなく、value属性に指定したstudentです。

サーブレットクラスを作成する

次に、フォームから送信された値を受け取るサーブレットクラスを作成します。

studyプロジェクトのservletパッケージにEntryServlet.javaを作成します。

Eclipseでサーブレットクラスを新規作成するときは、doGetではなくdoPostにチェックを入れます。今回のフォームではmethod属性にpostを指定しているため、送信時にはPOSTリクエストが送られます。そのため、サーブレット側ではdoPostメソッドを用意する必要があります。

サーブレット作成時の設定

項目内容
パッケージservlet
クラス名EntryServlet
URLパターン/EntryServlet
作成するメソッドdoPost

EntryServletは、フォームから送られたnameとticketを取得し、未入力チェックを行います。

結果画面をレスポンスするサーブレットクラス

EntryServlet.javaでは、まずrequest.setCharacterEncodingで文字コードを指定します。

次に、request.getParameterを使って、nameとticketの値を取得します。

そのあと、未入力チェックを行います。名前が入力されていなければ、名前が入力されていませんというエラーメッセージを追加します。参加区分が選択されていなければ、参加区分が選択されていませんというエラーメッセージを追加します。

両方が入力されている場合は、ticketの値を画面表示用の日本語に変換して、申し込み完了メッセージを作成します。

申し込み結果画面をレスポンスするサーブレットクラスの例

ファイル名: EntryServlet.java

package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

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

    protected void doPost(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {

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

        // リクエストパラメータをチェック
        String errorMsg = "";
        if (name == null || name.length() == 0) {
            errorMsg += "名前が入力されていません<br>";
        }

        if (ticket == null || ticket.length() == 0) {
            errorMsg += "参加区分が選択されていません<br>";
        } else {
            if (ticket.equals("general")) {
                ticket = "一般参加";
            } else if (ticket.equals("student")) {
                ticket = "学生参加";
            }
        }

        // 表示するメッセージを設定
        String msg = name + "さん(" + ticket + ")の申し込みを受け付けました";
        if (errorMsg.length() != 0) {
            msg = errorMsg;
        }

        // HTMLを出力
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<meta charset=\"UTF-8\">");
        out.println("<title>イベント参加申し込み結果</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<p>" + msg + "</p>");
        out.println("</body>");
        out.println("</html>");
    }
}

ブラウザの表示例

このサーブレットでは、doPostメソッドの中でフォームから送られた値を受け取ります。

フォーム側のmethod属性がpostなので、EntryServletではdoPostメソッドを作成します。doGetメソッドではありません。

リクエストパラメータの取得

EntryServlet.javaでは、次の処理でリクエストパラメータを取得しています。

request.setCharacterEncoding("UTF-8")で文字コードを指定し、その後にrequest.getParameterで値を取り出しています。

取得しているリクエストパラメータ

取得する値フォーム側のname属性サーブレット側の取得
名前namerequest.getParameter("name")
参加区分ticketrequest.getParameter("ticket")

getParameterに指定する名前は、フォーム部品のname属性と一致している必要があります。

フォーム側がnameであれば、サーブレット側もnameを指定します。フォーム側がticketであれば、サーブレット側もticketを指定します。

ここが一致していないと、値を取得できず、nullになることがあります。

未入力チェックの考え方

フォームでは、利用者が何も入力しないまま送信することがあります。

そのため、サーブレット側ではリクエストパラメータを取得したあと、値が正しく入っているかを確認します。

今回の例では、次の2つをチェックしています。

チェック項目条件エラーメッセージ
名前nullまたは文字数が0名前が入力されていません
参加区分nullまたは文字数が0参加区分が選択されていません

nameがnullの場合は、nameというリクエストパラメータ自体が送られていないことを表します。

name.length()が0の場合は、リクエストパラメータは送られてきているものの、入力欄が空だったことを表します。

この両方を確認することで、未入力の状態を判定できます。

ラジオボタンの値を表示用に変換する

フォームのラジオボタンでは、画面に表示される文字と、サーバへ送信される値が異なる場合があります。

entry-form.jspでは、画面には一般参加、学生参加と表示していますが、送信される値はgeneralまたはstudentです。

そのため、EntryServlet.javaでは、送信された値を表示用の日本語に変換しています。

ラジオボタンの送信値と表示文字

画面の選択肢value属性サーブレットでの表示用文字
一般参加general一般参加
学生参加student学生参加

今回の例では、value属性の値と表示用の文字がほぼ対応していますが、実際のプログラムでは、value属性には英数字の管理用コードを使い、画面表示では利用者に分かりやすい日本語へ変換することがあります。

結果メッセージを作成する

未入力がない場合は、次のような申し込み完了メッセージを作成します。

青山直人さん(学生参加)の申し込みを受け付けました

未入力がある場合は、完了メッセージではなくエラーメッセージを表示します。

表示メッセージの切り替え

状態表示される内容
名前と参加区分が入力されている申し込み完了メッセージ
名前が未入力名前が入力されていません
参加区分が未選択参加区分が選択されていません
両方とも未入力2つのエラーメッセージ

errorMsgに文字列が入っている場合は、入力に問題があったということです。そのため、msgにはerrorMsgを代入します。

errorMsgが空であれば、入力内容に問題がないため、申し込み完了メッセージを表示します。

図3:フォームとサーブレットで一致させる4つのポイント

この図から分かること

フォームとサーブレットを連携させるには、対応させるべきポイントがあります。

action属性は、サーブレットのURLパターンと一致させます。method属性は、サーブレットの実行メソッドと一致させます。HTML側の文字コードは、request.setCharacterEncodingの指定とそろえます。フォーム部品のname属性は、request.getParameterに指定する名前と一致させます。

この4つの対応がずれていると、404ページ、405ページ、文字化け、nullなどの問題が起こりやすくなります。

プログラムを実行する

entry-form.jspとEntryServlet.javaが作成できたら、プログラムを実行します。

最初に実行するのは、入力画面であるentry-form.jspです。

ブラウザのアドレスバーに次のURLを入力します。

http://localhost:8080/study/entry-form.jsp

または、Eclipseのパッケージ・エクスプローラーでentry-form.jspを選択し、右クリックして 実行 → サーバーで実行 を選択します。

実行手順

手順操作
1Tomcat11(Java25)が起動していることを確認する
2entry-form.jspをブラウザまたはEclipseで実行する
3名前を入力する
4参加区分を選択する
5申し込むボタンをクリックする
6結果画面が表示されることを確認する

名前と参加区分を入力して送信すると、成功メッセージが表示されます。

どちらかを入力しないまま送信すると、対応するエラーメッセージが表示されます。

EntryServlet.javaを最初に実行しない

今回のプログラムでは、EntryServlet.javaを最初に直接実行しないように注意します。

EntryServlet.javaにはdoPostメソッドだけを作成しています。ブラウザのアドレスバーにURLを直接入力してEntryServletへアクセスすると、GETリクエストになります。

しかし、EntryServletにはdoGetメソッドがないため、直接実行すると405ページが表示されることがあります。

最初に実行するファイル

対象最初に実行するか
entry-form.jsp実行する
EntryServlet.java最初に直接実行しない

EntryServletは、entry-form.jspのフォームからPOSTリクエストを受け取るためのサーブレットです。

そのため、まずentry-form.jspを表示し、フォームの申し込むボタンからEntryServletへ送信します。

フォームとサーブレットで一致させる4つのポイント

フォームを使ったプログラムでは、送信元のフォームと送信先のサーブレットの間で、必ず一致させるべきポイントがあります。

一致させるポイント

番号送信元のフォーム送信先のサーブレットクラス
1action属性サーブレットクラスのURLパターン
2method属性サーブレットクラスの実行メソッド
3HTMLの文字コードsetCharacterEncodingの引数
4各部品のname属性getParameterの引数

今回のentry-form.jspとEntryServlet.javaでは、次のように対応しています。

対応フォーム側サーブレット側
送信先action="EntryServlet"@WebServlet("/EntryServlet")
送信方法method="post"doPost
文字コードcontentTypeとpageEncodingでUTF-8request.setCharacterEncoding("UTF-8")
名前name="name"request.getParameter("name")
参加区分name="ticket"request.getParameter("ticket")

この対応関係を確認できれば、フォーム送信のトラブルをかなり見つけやすくなります。

4つのポイントがずれた場合に起こる問題

フォームとサーブレットの対応がずれていると、さまざまな問題が発生します。

よくある問題

ずれているポイント起こりやすい問題
action属性とURLパターンが一致していない送信ボタンを押すと404ページが表示される
method属性と実行メソッドが一致していない送信ボタンを押すと405ページが表示される
文字コードが一致していない取得した値が文字化けする
name属性とgetParameterの引数が一致していない取得した値がnullになる

404ページが表示される場合は、送信先が見つかっていない可能性があります。action属性と@WebServletのURLパターンを確認しましょう。

405ページが表示される場合は、リクエストメソッドに対応する実行メソッドがない可能性があります。method属性がpostならdoPost、method属性がgetならdoGetを用意します。

文字化けする場合は、JSPやHTMLの文字コードと、サーブレット側のsetCharacterEncodingの指定を確認します。

値がnullになる場合は、フォーム部品のname属性とgetParameterの引数が一致しているかを確認します。

動作確認で見るポイント

プログラムを実行したら、成功する場合だけでなく、未入力の場合も確認しておくと理解が深まります。

確認パターン

入力内容期待される結果
名前と参加区分を入力する申し込み完了メッセージが表示される
名前を空にする名前が入力されていませんと表示される
参加区分を選択しない参加区分が選択されていませんと表示される
名前も参加区分も空にする2つのエラーメッセージが表示される

フォームは、利用者が必ず正しく入力してくれるとは限りません。

そのため、サーブレット側で入力内容を確認し、未入力があれば分かりやすいメッセージを返すことが大切です。

フォーム連携で確認したいこと

フォームとサーブレットの連携では、JSPファイル、HTMLのフォーム、サーブレットクラスの3つをまとめて確認します。

確認項目

確認項目内容
JSPファイルの保存場所entry-form.jspがsrc/main/webappにあるか
実行するURLhttp://localhost:8080/study/entry-form.jspになっているか
action属性EntryServletになっているか
method属性postになっているか
URLパターン@WebServlet("/EntryServlet")になっているか
実行メソッドdoPostが作成されているか
文字コードUTF-8でそろっているか
name属性nameとticketが指定されているか
getParameternameとticketを指定しているか

フォームの見た目が正しく表示されても、送信先や受け取り側の指定がずれていると、正しく連携できません。

入力画面、送信データ、サーブレット側の取得処理を1つの流れとして確認することが、フォーム連携を理解するための大切なポイントです。