入力された値のチェックを行おう

8.5 入力された値のチェックを行おう

 Webアプリケーションの画面から入力されるパラメータは、必ずしも正しいデータが入力されるとは限りません。人の手で入力する情報はどんなに注意を払っていても間違えて入力される場合があります。また、悪質なユーザなどが、不正な情報を入力する可能性もあります。そのため、外部に公開するプログラムにおいては、入力されたパラメータのチェックを行う必要があります。
 まずは、入力チェックを行なっていないプログラムを作成し、実際にどのような問題が起きるかを確かめてみましょう。

入力パラメータのチェックを行なわないプログラム

 これは足し算を行うプログラムです。入力フォームに2つの数字を入力し、その計算結果を表示します。

実行結果

アプリケーション構成

① 親フォルダの入力または選択 :web_basic/view/ch08
② ファイル名 :additionForm1.jsp
③ アクセスURL :http://localhost:8080/web_basic/view/ch08/additionForm1.jsp

➢ additionForm1.jsp
<%@page contentType= "text/html; charset=UTF-8" %>

<html>
	<head>
		<title>入力チェックを行わないプログラム</title>
	</head>
	<body>
		<form action="<%= request.getContextPath() %>/AdditionReceiptServlet1" method="get">
			1つ目の数字:<input type="text" name="num1"><br>
			2つ目の数字:<input type="text" name="num2"><br>
						<input type="submit" value="計算">
		</form>
	</body>
</html>

① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch08
③ 名前 :AdditionReceiptServlet1
④ スーパークラス :javax.servlet.http.HttpServlet
⑤ アクセスURL :additionForm1.jspからの画面遷移でアクセスされる

➢ AdditionReceiptServlet1.java
package ch08;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class AdditionReceiptServlet1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {

		//入力データの取得
		String strNum1 = request.getParameter("num1");
		String strNum2 = request.getParameter("num2");

		//計算処理の実行
		int num1 = Integer.parseInt(strNum1);
		int num2 = Integer.parseInt(strNum2);
		int answer = num1 + num2;

		//文字コードの設定と画面表示
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.println(num1 + "+" + num2 + "の答えは" + answer + "です。");
	}
}
➢ web.xml
<servlet>
	<servlet-name>AdditionReceiptServlet1Mapping</servlet-name>
	<servlet-class>ch08.AdditionReceiptServlet1</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>AdditionReceiptServlet1Mapping</servlet-name>
	<url-pattern>/AdditionReceiptServlet1</url-pattern>
</servlet-mapping>

解説
 このプログラムは、13行目と14行目で入力された2つのパラメータを取得しています。
   13:String strNum1 = request.getParameter("num1");
   14:String strNum2 = request.getParameter("num2");

 取得された値はString型のため、17行目と18行目でint型へ変換しています。
   17:int num1 = Integer.parseInt(strNum1);
   18:int num2 = Integer.parseInt(strNum2);

 19行目ではint型へ変換した2つの値の足し算を行なっています。
   19:int answer = num1 + num2;

 24行目で、計算された結果を画面へ出力しています。
   24:out.println(num1 + "+" + num2 + "の答えは" + answer + "です。");

 このプログラムで重要な点は、入力するパラメータは足し算が可能な数字である必要があることと、入力のチェックを行なっていないことです。もし、このプログラムに何も入力されなかったり、数字以外の文字が入力されたりした場合、どうなってしまうでしょうか。
 入力チェックが行われていない場合に起きてしまう問題について以下の3つを行い、どのように画面に表示されるか見てみましょう。
 ① テキストボックスを空白のまま計算する。
 ② 値に文字を入力して計算する。
 ③ フォーム画面を使用せず、サーブレットに直接アクセスする。

① テキストボックスを空白のまま計算する。
 テキストボックスに値を入力せずに計算ボタンを押すと、以下のエラー画面が表示されます。
 この画面では、「java.lang.NumberFormatException: For input string: “”」と表示されています。テキストボックスは何も入力せずに送信すると「””(空文字)」が入っているものとして扱われるため、int型に変換できないエラーとしてNumberFormatExceptionが発生します。このエラーを回避するためには空白文字のチェックが必要です。

図 8.5.1:空白のまま計算するエラー

② 値に文字を入力して計算する。
 値に文字を入力し計算ボタンを押すと、空白で入力した場合と同じようにint型への変換ができないため、NumberFormatExceptionが発生します。このエラーを回避するためには、入力されたパラメータが数値に変換できるかどうかのチェックが必要です。

図 8.5.2:文字を入力し計算するエラー

③ フォーム画面を使用せず、サーブレットに直接アクセスする。
 フォームを使用せず、サーブレットに直接アクセスするために、以下のURLをブラウザのアドレスバーに入力しましょう。
 http://localhost:8080/web_basic/AdditionReceiptServlet1

 直接サーブレットにアクセスすると、URLの後ろにパラメータが付かないため、getParameter()メソッドを使用した際にデータが無いものとして「null」が変数に代入されます。null値もint型への変換ができないため、NumberFormatExceptionが発生します。このエラーを回避するには、入力されたパラメータがあるかどうかをチェックする必要があります。

図 8.5.3:ダイレクトアクセスによるエラー

 このように、入力チェックを行わないと、想定外のことが実行された場合にすぐにエラーが発生してしまうので、入力チェックは非常に重要です。

入力パラメータのチェックを行なうプログラム

 AdditionReceiptServlet1.javaに入力チェックを追加したプログラムです。数字以外のパラメータが入力されたときに、メッセージを表示します。

実行結果(空文字)

実行結果(文字)

実行結果(ダイレクトアクセス)

アプリケーション構成

① 親フォルダの入力または選択 :web_basic/view/ch08
② ファイル名 :additionForm2.jsp
③ アクセスURL :http://localhost:8080/web_basic/view/ch08/additionForm2.jsp

➢ additionForm2.jsp
<%@page contentType= "text/html; charset=UTF-8" %>

<html>
	<head>
		<title>入力チェックを行うプログラム</title>
	</head>
	<body>
		<form action="<%= request.getContextPath() %>/AdditionReceiptServlet2" method="get">
			1つ目の数字:<input type="text" name="num1"><br>
			2つ目の数字:<input type="text" name="num2"><br>
						<input type="submit" value="計算">
		</form>
	</body>
</html>

① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch08
③ 名前 :AdditionReceiptServlet2
④ スーパークラス :javax.servlet.http.HttpServlet
⑤ アクセスURL :additionForm2.jspからの画面遷移でアクセスされる

➢ AdditionReceiptServlet2.java
package ch08;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class AdditionReceiptServlet2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
 	throws ServletException, IOException {
 
 		String strNum1 = request.getParameter("num1");	//入力パラメータの取得
 		String strNum2 = request.getParameter("num2");	//入力パラメータの取得
 		String message = null; 				//エラーメッセージ用変数
 		int answer = 0;						//計算結果用変数
 
 		//入力チェック
 		if(strNum1 == null || strNum2 == null){
 			//ダイレクトアクセス時のエラー設定
 			message = "フォーム画面から入力してね。";
 		}else if(strNum1.equals("") || strNum2.equals("")){
 			//空白の場合のエラー設定
 			message = "何も入力されていませんよ。";
 		}else{
 			try{
 				int num1 = Integer.parseInt(strNum1);
 				int num2 = Integer.parseInt(strNum2);
 				answer = num1 + num2;
 
 			}catch(NumberFormatException e){
 				//文字が入力された場合のエラー設定
 				message = "数字を入力してね。";
 			}
 		}
 
 		response.setContentType("text/html; charset=UTF-8");
 		PrintWriter out = response.getWriter();
 
 		if(message == null){
 			out.println(strNum1 + "+" + strNum2 + "の答えは" + answer + "です。");
 		}else{
 			out.println(message);
 		}
 	}
 }
➢ web.xml
<servlet>
	<servlet-name>AdditionReceiptServlet2Mapping</servlet-name>
	<servlet-class>ch08.AdditionReceiptServlet2</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>AdditionReceiptServlet2Mapping</servlet-name>
	<url-pattern>/AdditionReceiptServlet2</url-pattern>
</servlet-mapping>

解説
 このプログラムは、AdditionReceiptServlet1.javaに入力チェックを追加したものです。
 AdditionReceiptServlet2.javaでは、18行目から23行目で入力パラメータの必須チェックを行なっていて、18行目から20行目はパラメータがnullだった場合(ダイレクトアクセスの場合)の処理です。
   18:if(strNum1 == null || strNum2 == null){
   20: message = "フォーム画面から入力してね。";

 21行目から23行目はパラメータが空文字の場合の処理です。
   21:}else if(strNum1.equals("") || strNum2.equals("")){
   23: message = "何も入力されていませんよ。";

 24行目から34行目までのelseブロックは、パラメータが取得できた場合の処理です。ただし、パラメータが取得できた場合でも、そのパラメータが数値に変換できない可能性があるため、try-catch文を利用してNumberFormatExceptionの例外処理を行なっています。
   24:}else{
   25: try{
   26: int num1 = Integer.parseInt(strNum1);
   27: int num2 = Integer.parseInt(strNum2);
   28: answer = num1 + num2;
   29:
   30: }catch(NumberFormatException e){
   32: message = "数字を入力してね。";
   33: }
   34:}

 この3つの入力チェックを追加することで、数字以外の文字や空文字が入力された場合や、ダイレクトにアクセスされてしまった場合でも、プログラムがエラーにならずに済みます。


NEXT>> 8.6 本章のまとめ