最近のWebアプリケーションでは、純粋なJsp/Servletを見なくなりました。

いろいろなWebアプリケーションのフレームワークが出ています。

それはさておき、Servlet における危険なコードについて見ていきます。


下記の本は本当に良い書籍でWebアプリケーションについてハマリやすい

罠について解説しています。ぜひお求めになってはどうでしょうか?

バグ攻略で極めるWeb開発のツボ 現場で必要不可欠なバッドノウハウ/山城 拓明
¥2,940
Amazon.co.jp
この本の第4章についてもう少しブレークダウンして見てみます。


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


public class TestServlet extends HttpServlet {


private Integer amount = 0;


protected void service(HttpServletRequest request

, HttpServletResponse response)

throws ServletException, IOException {


response.getWriter().print("<html><head><title>title</title></head><body>");


amount = amount + new Integer(100);

response.getWriter().println("Amount =>" + amount + "yen");

response.getWriter().print("</body></html>");


}

}


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


サーブレットにアクセスした結果


Amount =>100yen



もう一回押してみます。



Amount =>200yen



どんどん値が増えていきます。


複数のブラウザを起動してアクセスしても同様です。


サーブレットでフィールド変数を宣言するときに初期化しても無駄で、サーバを再起動するまで

フィールド変数の値は保持されていることがわかります。


今度はアクセスするタイミングで金額が変わるサーブレットを見ていきます。


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


public class TestServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  private Integer amount = 0;

  protected void service(HttpServletRequest request

                 ,HttpServletResponse response)

                 throws ServletException, IOException {
   response.getWriter().print("<html><head><title>title</title></head><body>");

   amount = 0;

  try {
     Thread.sleep(2 * 1000);
  } catch (InterruptedException e) {
  // TODO 自動生成された catch ブロック
    e.printStackTrace();
  }

  amount = amount + new Integer(100);

  try {
    Thread.sleep(3 * 1000);
  } catch (InterruptedException e) {
    // TODO 自動生成された catch ブロック
    e.printStackTrace();
  }

  response.getWriter().println("Amount =>" + amount + "yen");

  response.getWriter().print("</body></html>");
}

}


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


時間を空けてアクセスした場合の出力結果は


   Amount =>100yen


です。


しかし、更新ボタンを連打したり、複数のブラウザからすばやくアクセスすると


   Amount =>200yen


   Amount =>300yen


などになってしまいます。


1つ目のスレッドがAmountを得た後に、2つ目のスレッドがsleep中だと、

printされるときに+100されます。


もしかすると、昔エンジニアだった人から指導を受けたときに、

  

   フィールド変数は NULL or 0 で初期化しなさい! 


とか 言われることがありましたけど、あれが勘違いを引き起こす原因なのでしょうか?



アクセスするタイミングによって、出たり出なかったりする再現性の低い不具合は


本番環境に乗ってしまう可能性があるので十分注意が必要です。


バグ攻略で極めるWeb開発のツボ 現場で必要不可欠なバッドノウハウ/山城 拓明
¥2,940
Amazon.co.jp

この本には、他にも


 ・文字化け

 ・セキュリティ対策

 ・ブラウザ&HTML


についてのバグとその対処方法についても丁寧に書いてあります。

オススメの一冊です。




プロパーさんに納品してもらったサーブレットに定数以外の

フィールド変数が書きまくってあると、なぜか動悸がす

お悩みの方は↓をクリック



人気ブログランキングへ