フォームからのデータをサーブレットで受け取る
8.4 フォームからのデータをサーブレットで受け取る
前節では、別画面から送信された入力データをJSPで受け取る方法について学習しました。本節では、別画面から送信された入力データをサーブレットで受け取る方法について学習します。
JSPではPOST送信データもGET送信データも同じように扱うことが可能でしたが、サーブレットの場合はPOST送信データとGET送信データではプログラムの動きが異なります。この点に注意して、学習していきましょう。
8.4.1 doGet()メソッドとdoPost()メソッド
これまで、サーブレットを作成する場合は、doGet()メソッドをオーバーライドしていました。このdoGet()メソッドは以下のような場合に実行されます。
・ ブラウザのアドレスバーに直接URLを入力して画面を表示した場合。
・ リンクをクリックして画面を表示した場合。
・ フォームの実行(submit)ボタンからGET送信で画面を表示した場合。
これまで作成したサーブレットでは、ブラウザのアドレスバーに直接URLを入力していたため、doGet()メソッドに処理を記述していましたが、POST送信で画面を表示する場合は、doGet()メソッドではなくdoPost()メソッドを利用します。
サーブレットへのアクセス方式と、呼び出されるメソッドの関係は次の表のようになります。
表 8.4.1:アクセス方法とサーブレットのメソッドの関係
8.4.2 送信データをサーブレットで扱う方法
Web画面からPOST送信されたデータをサーブレットで扱う場合、doGet()メソッドではなく、doPost()メソッドをオーバーライドします。HttpServletクラスからオーバーライドするメソッドなので、doGet()メソッド同様にメソッド名や引数などを正確に記述する必要があります。
書式:doPost()メソッド
また、送信されたデータを取得するには、JSPと同じようにgetParameter()メソッドを利用します。
サーブレットにおけるPOST送信アクセスとGET送信アクセスの違いは、doPost()メソッドが実行されるか、doGet()メソッドが実行されるかの違いだけで、実際の値の取得方法に違いはありません。
なお、サーブレットで実行するgetParameter()メソッドは、doPost()メソッドやdoGet()メソッドの引数に渡されてくるHttpServletRequestクラスの変数から利用することが可能です。
doPost()メソッドを利用するサーブレット
別画面(送信元)からPOST送信された入力データを送信先のサーブレットで受け取り、Webブラウザに表示します。doPost()メソッドが動作しデータが画面に表示されることを確認しましょう。
実行結果
アプリケーション構成
➢ postForm.jsp① 親フォルダの入力または選択 :web_basic/src/main/webapp/view/ch08
② ファイル名 :postForm.jsp
③ アクセスURL :http://localhost:8080/web_basic/view/ch08/postForm.jsp
<%@page contentType= "text/html; charset=UTF-8" %> <html> <head> <title>POST送信データを扱うサーブレット</title> </head> <body> <h2>POST送信フォーム</h2> <form action="<%= request.getContextPath() %>/PostReceiptServlet" method="post"> お名前:<input type="text" name="onamae"> <input type="submit" value="送信"> </form> </body> </html>
➢ PostReceiptServlet.java① ソース・フォルダ :web_basic/src/main/java
② パッケージ :ch08
③ 名前 :PostReceiptServlet
④ スーパークラス :jakarta.servlet.http.HttpServlet
⑤ アクセスURL :postForm.jspからの画面遷移でアクセスされる
package ch08; 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("/PostReceiptServlet") public class PostReceiptServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //パラメータの取得 String name = request.getParameter("onamae"); //画面出力 PrintWriter out = response.getWriter(); out.println("お名前は" + name + "さんですね。"); } }
解説
今回のプログラムは、データを入力するWeb画面の「postForm.jsp」と、データの受け取り先のサーブレット「PostReceiptServlet.java」の2つのファイルから構成されています。
データの送信元である「postForm.jsp」は、前節で作成した「jspForm.jsp」のPOST送信部分と全く同じ内容なので、ここでの説明は省略し、データの受け取り先の「PostReceiptServlet.java」の処理について説明を行います。
「PostReceiptServlet.java」では、今までのサーブレットとは異なり、15~16行目でdoPost()メソッドをオーバーライドしています。「postForm.jsp」からデータがPOST送信されているためdoPost()メソッドが呼び出され実行されます。
18行目では、送信されたデータの取得を行なっています。getParameter()メソッドを使用し引数に部品名を渡す処理は、前節で作成したJSPでの受け取り方法と全く変わりません。
このプログラムはPOST送信アクセスを前提に作成されているため、doGet()メソッドが存在しません。この状態でGET送信アクセスをするとエラーになってしまうので、注意が必要です。
試しに、「postForm.jsp」の9行目にある「method=”post”」を「method=”get”」に変えて実行してみましょう。
図 8.4.1:methodの変更
methodをgetに変更し実行すると、図のようにエラーが表示されます。このように、doPost()メソッドのみのサーブレットの場合は、GET送信アクセスを受けることができないので注意しておきましょう。
図 8.4.2:GETメソッドがサポートされていないエラー
次にdoGet()メソッドのみを使ったサーブレットの例も見てみましょう。
doGet()メソッドを利用するサーブレット
別画面(送信元)からGET送信された入力データを送信先のサーブレットで受け取り、Webブラウザに表示します。doGet()メソッドが動作しデータが画面に表示されることを確認しましょう。
実行結果
アプリケーション構成
➢ getForm.jsp① 親フォルダの入力または選択 :web_basic/src/main/webapp/view/ch08
② ファイル名 :getForm.jsp
③ アクセスURL :http://localhost:8080/web_basic/view/ch08/getForm.jsp
<%@page contentType= "text/html; charset=UTF-8" %> <html> <head> <title>GET送信データを扱うサーブレット</title> </head> <body> <h2>GET送信フォーム</h2> <form action="<%= request.getContextPath() %>/GetReceiptServlet" method="get"> お名前:<input type="text" name="onamae"> <input type="submit" value="送信"> </form> </body> </html>
➢ GetReceiptServlet.java① ソース・フォルダ :web_basic/src/main/java
② パッケージ :ch08
③ 名前 :GetReceiptServlet
④ スーパークラス :jakarta.servlet.http.HttpServlet
⑤ アクセスURL :getForm.jspからの画面遷移でアクセスされる
package ch08; 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("/GetReceiptServlet") public class GetReceiptServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //パラメータの取得 String name = request.getParameter("onamae"); //画面出力 PrintWriter out = response.getWriter(); out.println("お名前は" + name + "さんですね。"); } }
解説
このプログラムは、POST送信データを扱う「postForm.jsp」と「PostReceiptServlet.java」の2つのファイルをGET送信データを扱うように変更したものです。
15行目と16行目でdoPost()メソッドの代わりにdoGet()メソッドをオーバーライドしています
18行目では送信されたデータの取得を行なっています。getParameter()メソッドを使用し引数に部品名を渡す処理は、POST送信データの受け取り方法と全く変わりません。
このプログラムはGET送信アクセスを前提に作成されているため、doPost ()メソッドが存在しません。この状態でPOST送信アクセスをすると「PostReceiptServlet.java」と同様のエラーが発生します。
「PostReceiptServlet.java」で試した方法と同じように、「getForm.jsp」の9行目にある「method=”get”」を「method=”post”」に変えて実行してみましょう。
図 8.4.3:methodの変更
methodをpostに変更し実行すると、図のようにとエラーが表示されます。このようにdoGet()メソッドのみのサーブレットの場合は、POST送信アクセスを受けることができません。
図 8.4.4:GETメソッドがサポートされていないエラー
もし、POST送信とGET送信のどちらからもアクセスを受けて処理を行う必要がある場合は、どのように記述すれば良いでしょうか。次のプログラムは、doPost()メソッドとdoGet()メソッドの両方を使ったサーブレットの例です。
doPost()メソッドとdoGet()メソッドの両方を利用するサーブレット
別画面(送信元)からGET送信、もしくはPOST送信された入力データを送信先のサーブレットで受け取り、Webブラウザに表示します。どちらの送信方式であってもデータが画面に表示されることを確認しましょう。
アプリケーション構成
➢ commonForm1.jsp① 親フォルダの入力または選択 :web_basic/src/main/webapp/view/ch08
② ファイル名 :commonForm1.jsp
③ アクセスURL :http://localhost:8080/web_basic/view/ch08/commonForm1.jsp
<%@page contentType= "text/html; charset=UTF-8" %> <html> <head> <title>送信データを扱うサーブレット</title> </head> <body> <h2>POST送信フォーム</h2> <form action="<%= request.getContextPath() %>/CommonReceiptServlet1" method="post"> お名前:<input type="text" name="onamae"> <input type="submit" value="送信"> </form> <h2>GET送信フォーム</h2> <form action="<%= request.getContextPath() %>/CommonReceiptServlet1" method="get"> お名前:<input type="text" name="onamae"> <input type="submit" value="送信"> </form> <a href="<%= request.getContextPath() %>/CommonReceiptServlet1?onamae=kanda">リンクで送信</a> </body> </html>
➢ CommonReceiptServlet1.java① ソース・フォルダ :web_basic/src/main/java
② パッケージ :ch08
③ 名前 :CommonReceiptServlet1
④ スーパークラス :jakarta.servlet.http.HttpServlet
⑤ アクセスURL :commonForm1.jspからの画面遷移でアクセスされる
package ch08; 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("/CommonReceiptServlet1") public class CommonReceiptServlet1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //共通処理メソッドの呼び出し commonProcess(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //共通処理メソッドの呼び出し commonProcess(request, response); } //共通処理メソッド private void commonProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("onamae"); PrintWriter out = response.getWriter(); out.println("お名前は" + name + "さんですね。"); } }
実行結果
解説
このプログラムでは、以下の3つの方法でサーブレットを呼び出しています。
・ フォームの実行(submit)ボタンからPOST送信
・ フォームの実行(submit)ボタンからGET送信
・ リンクからのGET送信
「CommonReceiptServlet1.java」では、POST送信データとGET送信データのどちらからのアクセスでもプログラムが動くように、doPost()メソッドとdoGet()メソッドを実装しています。
この2つのメソッド内では、どちらもcommonProcess()メソッドを呼び出しています。
27行目から34行目に記述されたcommonProcess()メソッドでは、doPost()メソッドとdoGet()メソッドの共通処理である、データの取得と画面への出力を行なっています。
この共通処理を行うメソッドの名前は任意で設定して問題ありませんが、メソッド内で処理を行うために、引数にはHttpServletRequestオブジェクトとHttpServletResponseオブジェクトが必要になります。
このプログラムは以下のような構成をしています。
図 8.4.5:POSTデータを送信
このように、サーブレットで送信データを扱う場合は、サーブレットのどのメソッドが呼び出されるのかを考慮した作りが必要になりますので注意してください。
過去のTomcatでは日本語用に文字エンコード指定が必要過去のTomcatでは、ブラウザから入力された文字列もそのままの状態でWebサーバに送られているわけではなく、デフォルト文字コードである「ISO-8859-1(Latin1)」のデータに変換されてWebサーバ側に送信されていました。そのため、ブラウザからWebサーバに送るための設定を行なっていないプログラムでは、5章の時のように文字化けが発生してしまいました。 これを回避するために、受け取る際にも文字エンコーディングを指定する必要がありました。
5章で学習したresponse.setContentType()メソッドの文字エンコーディングは「出力する文字の文字コード」を指定するもので、このrequest.setCharacterEncoding()メソッドは「フォームから受け取るデータの文字コード」を指定するものです。2つの文字コードの設定は別であることに注意してください。 今回スクールが用意した環境構築資源では、request.setCharacterEncoding()メソッドを使う必要はありませんが、実際の業務で扱うプログラムでは登場しているかもしれないので、存在は覚えておいてください。また、Tomcat5~8では、GET送信でデータを送る場合、デフォルトの設定では「ISO-8859-1(Latin1)」でデコードされます。そのため、受け取り側のプログラム内でsetCharacterEncoding()メソッドで文字エンコーディングを指定してもデフォルトでは無視されてしまい、文字化けが発生していました。
このデフォルト設定を変更するには以下のファイルを編集する必要があります。なお、当スクールの環境ではすでに設定済みですので編集する必要はありません。
C:\usr\kis_java_pkg_2023\tomcat\8\conf\server.xml
このファイルはTomcatの動作を設定するためのファイルで、図の70行目にある「useBodyEncodingForURL=”true”」を指定することで、GET送信時の文字エンコーディングをsetCharacterEncoding()メソッドで指定できるようになっていました。