プロが教える店舗&オフィスのセキュリティ対策術

現在サーブレットについて勉強しているものです。

身近に聞ける人がおらず、お手数ですがご教授願います。

分からないところは、JSPでテキストフィールドがあるページを作成し、そこに何も入れないまま送信した場合の動作についてです。

以下に載せているサンプルAの通りに作成し、何も入れないで送信したところ、if( (numberStr == null) || (numberStr.length() == 0) )の条件文の中の処理が走るようで、”何かいれて”というメッセージが表示されるのを確認しております。

しかし、私が作成したファイルを使い、テキストフィールドに何も入れないまま送信した場合はエクセプション画面(例外レポート)に飛んでしまいます。

同じ条件を使い、同じように表示させているつもりなのですが、私が作成したソースが上手くいかず、参考書のソースが上手く動作している理由がどうしてもわかりません。

恐らくソースを見た方が早い、という方が多いと思いますので、見栄えは悪いのですが、ソースを張らせていただきます。

また、入力文字数の制限より、import等は全て削除しました。

また、何も入力しない場合に用いられている、try、catchの必要性についても、いまいち分かりません。
ifとelseで全て網羅するようにせず、なぜtry,catchを使うのでしょうか?

ご存じの方、いらっしゃいましたら、是非教えて下さい。



サンプルA-start---------------------------------------------------------------------
public class GuessServlet extends HttpServlet {

/* 当たりの数字をランダムに決定 */
private int hit = new Random().nextInt(10);

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

/* jspファイルで入力した数字をひっぱってくる */
String numberStr = request.getParameter("number");
int input = Integer.parseInt(numberStr);

response.setContentType("text/plain; charset=Windows-31J");
PrintWriter out = response.getWriter();

if( (numberStr == null) || (numberStr.length() == 0) )
{
request.setAttribute("msg","何か入れて");
RequestDispatcher dispatcher = request.getRequestDispatcher("/reqattr/guess.jsp");
dispatcher.forward( request, response);
}
else if(hit == input)
{
request.setAttribute("msg","当たり。数字=" + input);
RequestDispatcher dispatcher = request.getRequestDispatcher("/reqattr/guess_hit.jsp");
dispatcher.forward( request, response);
}
else{
request.setAttribute("msg","はずれ。数字=" + input);
RequestDispatcher dispatcher = request.getRequestDispatcher("/reqattr/guess.jsp");
dispatcher.forward( request, response);
}
}
}

サンプルA-end---------------------------------------------------------------------



私のソース-start---------------------------------------------------------------------

public class GuessServlet extends HttpServlet {

/* 当たりの数字をランダムに決定 */
private int hit = new Random().nextInt(10);

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

/* jspファイルで入力した数字をひっぱってくる */
String numberStr = request.getParameter("number");

String error = null;
int number = -1;

if( (numberStr == null) || (numberStr.length() == 0) )
{
error = "何か入れて";
}

if(error == null)
{
try{
number = Integer.parseInt(numberStr);
if(number < 0 || 9 < number)
{
error = "0~9を入れて";
}
}
catch(NumberFormatException e)
{
error ="数字を入れてください";
}
}

String path;

if(error != null)
{
request.setAttribute("msg", error);
path = "/reqattr/guess.jsp";
}
else
{
if(hit == number)
{
request.setAttribute("msg","当たり。数字=" + number);
path = "/reqattr/guess_hit.jsp";
}
else
{
request.setAttribute("msg","はずれ。数字=" + number);
path = "/reqattr/guess.jsp";
}
}
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
dispatcher.forward( request, response);
}
}

私のソース-end---------------------------------------------------------------------

A 回答 (3件)

補足にある認識で間違っていません。



例外が発生したとき、原因がよくわからなかったら
とりあえずエラーメッセージや例外名で検索してみるといいですよ。
特殊なものでなければ、なにかしらのページが見つかると思います。

今回であれば、
java.lang.NumberFormatException: For input string: ""
とか、
java.lang.NumberFormatException
などで。

ただ、まずはエラーメッセージをちゃんと読むことが大事です。
今回も
>For input string: ""
から、なんとなくでも「入力が空文字なのがいけない」っていうのが分かるようになると
自分で解決できるようになっていくのではないかと思います。
    • good
    • 0
この回答へのお礼

yamada_g様

ありがとうございました!
おかげさまで、かなり理解が深まりました。何度お礼を言っても言い足りないくらいです。

質問内容に誤記があったにも関わらず、見ず知らずの私へご親切に何度も回答していただき、非常に嬉しかったです。
教わったことを活かし、今後もJAVAへの理解を深めていきたいと思います。

今後、またお世話になるかもしれませんが、その際はよろしくお願いします。

ありがとうございました。

お礼日時:2011/05/21 12:34

もう一度確認して欲しいのですが、本当に"私のソース"と書いてある方(下に記載されているほうのソース)で


おっしゃるような例外が発生しますか?
当方の環境でそのまま動かしてみても問題ないですが。

先ほども書いたとおり、サンプルとなっている方のソースでは
>/* jspファイルで入力した数字をひっぱってくる */
>String numberStr = request.getParameter("number");
>int input = Integer.parseInt(numberStr);
の3行目でNumberFormatExceptionが発生します。
これって補足にあるスタックとレースの内容と一致していますよね。
try~catchについての補足を読んでも、サンプルとKoh1111さんが書いたソースが逆になっているように思います。

とりあえず、なぜ記載の例外が発生するかというと、
Integer.parseIntメソッドは引数に整数に変換できない文字列を渡すとNumberFormatExceptionを投げる仕様です。
http://java.sun.com/javase/ja/6/docs/ja/api/java …
「number」に何も入力がないときには、
Integer.parseInt(null);
を実行することになります。なので上記例外が発生します。

「私のソース」と書いてある方では、
>if( (numberStr == null) || (numberStr.length() == 0) )
で「number」が入力されているかを確認し、入力されているときだけInterger.parseInt()するようになっています。
ですので例外が発生しません。


「私のソース」にあるtry~catchについてですが、
1.仮にtry~catchを使わないとしたら入力された文字列が全て数字であるか等を確認する必要があります。
2.try~cathcの場合は、Integer.parseInt()を実行してNumberFormatExceptionが発生したら数字ではないと判断できます。
自分はとっては2.の方法で済むならそっちの方が楽だと思いますがいかがでしょうか。
>if文で全ての状態を網羅するのではなく
の意味がはっきりと分からなかったのですが、一度に全ての条件をチェックする必要はなくて
ここでは「入力された値が数値であるか」「その数値は0~9であるか」を確認する処理をするっていうことだと思います。
「入力があるかないか」は他の箇所で別にやればいいと思いますし。
実際「私のソース」ではそうなっていますね。

なんかダラダラと長くなってしまいましたが、参考になれば幸いです。
    • good
    • 0
この回答へのお礼

yamada_g様

ご回答いただき、ありがとうございます。

申し訳ありません!
おっしゃる通り、「私のソース」と「サンプル」を逆に書いておりました。混乱させてしまい、非常に申し訳ありませんでした。

また、今後、例外発生時は例外画面にあるメッセージを元に、先ほど回答の中にあったHPで確認するように致します。例外発生時の画面からどのように追って行けばいいのかが今回のことで、なんとなく解ったので、今後活かします。



例外発生の理由についても、分かりやすく教えて頂き、ありがとうございます。もしよければ、私なりに理解した内容を記載させていただきますので、この認識で合っているか、確認させて下さい。



・例外が発生する原因
「Integer.parseInt」を実行時、引数の「文字列の形式」が正しくないため。

・テキストフィールドに何も入れないで送信した場合、「Integer.parseInt」関数内では「文字列の形式」が正しくないとみなし、例外を発生させる。

・例外発生画面を出さない方法
try,catch(finally)を使い、例外時の動作を規定すること。

・”try,catchを使用しているソース”
「Integer.parseInt」関数の引数に「文字列の形式」が正しくないものを与えたため、例外が発生していたが、「例外が発生するかもしれない処理」としてtryに記載し、tryで発生した種類の例外と一致するもの(NumberFormatException)がcatch条件として書かれていたため、その例外画面を出さず、catch条件内の例外発生時の処理がされたため、例外画面は出ない。

そのため、例えば"a"や" "を入力した場合はNumberFormatExceptionが発生してはいるが、catch内で例外時の処理として実装されていた内容を行うだけで、例外画面はでない。

また、何も入力しない場合はif( (numberStr == null) || (numberStr.length() == 0) )条件の(numberStr.length() == 0)が真となるため、そもそも例外は発生しない。(ソース構造上Integer.parseIntが動作するところまでいかない)

・”try,catchを使用していないソース”
「Integer.parseInt」関数の引数に「文字列の形式」が正しくないものを与えたため、例外が発生し、例外画面がでる。




というのが私なりの理解なのですが、合っているでしょうか…?

お礼日時:2011/05/20 20:55

見た感じは「number」の値がnullでも問題ないように見えますけどね。


むしろ、サンプルの場合だと
>int input = Integer.parseInt(numberStr);
でNumberFormatExceptionが発生すると思いますけど。

文字数制限で例外の内容を書けなかったのだと思いますが、
本当に「numberがnullだから」発生している例外なのでしょうか?

>また、何も入力しない場合に用いられている、try、catchの必要性についても、いまいち分かりません。
これは、どの部分のことを言っているのか分かりませんでした。
記載のコードで言えば、try~catchしているのは何かしら入力されている場合だけですよね。
    • good
    • 0
この回答へのお礼

yamada_g様

ご回答いただき、ありがとうございます。
私の知識不足で、例外画面から例外の原因を探る、ということがわかりませんでした。
以下が例外画面での項目となります。見る限り入力が「””」であるためのエラーと思われます。

サンプルAでも同じようにして使っているのに、なぜ私が作成したソースでは例外になるのかがやはり分かりません…。

try,catchについて、説明不足で申し訳ありません。サンプルAに記載がある部分であり、if文で全ての状態を網羅するのではなく、なぜtry,catchを記述するのかが分からないという意味で質問させていただきました。





----------------------------------------------------------------------------------

type 例外レポート

メッセージ

説明 The server encountered an internal error () that prevented it from fulfilling this request.

例外

java.lang.NumberFormatException: For input string: ""
java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
java.lang.Integer.parseInt(Integer.java:470)
java.lang.Integer.parseInt(Integer.java:499)
reqattr.GuessServlet.doGet(GuessServlet.java:24)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.apache.catalina.servlets.InvokerServlet.serveRequest(InvokerServlet.java:404)
org.apache.catalina.servlets.InvokerServlet.doGet(InvokerServlet.java:136)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
filter.DebugFilter.doFilter(DebugFilter.java:37)
filter.EncodingFilter2.doFilter(EncodingFilter2.java:31)


注意 原因のすべてのスタックトレースは、Apache Tomcat/6.0.26のログに記録されています

お礼日時:2011/05/20 17:06

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!