竹形誠司 ブログ
Java+MySQL+Tomcat    »トピック一覧
掲示板へのスパムが多いため、「ご質問」のコーナーはユーザー登録制とさせていただきました。お手数ですが、上の「新規ユーザーの登録」メニューより登録をお願いします。
帳票Web
アプリケーション

受注開発始めました
詳しくは こちら
竹形 誠司 著/ラトルズ刊
JSP帳票アプリケーション実践開発入門
JSP帳票アプリケーション
実践開発入門

JSP業務アプリケーション短期開発入門
JSP業務アプリケーション
短期開発入門

Java+MySQL+Tomcatで始めるWebアプリケーション構築入門
Java+MySQL+Tomcatで始めるWebアプリケーション構築入門

Java+MySQL+Tomcatで作る掲示板とブログ
Java+MySQL+Tomcatで作る
掲示板とブログ
JSPでセッション変数に代入した値が他のページに反映されないのはなぜか?
by 竹形 誠司[takegata]
JSPではuseBeanというアクションを使ってセッションを通じてアクセス可能なオブジェクトを作成することができます。たとえば、
<jsp:useBean class="jp.veltec.User" id="user" scope="session"/>
とすれば、Userクラスからuserという名前のオブジェクトが作成され、このオブジェクトをJSPコードの中で使用できます。セッションを通じて有効なオブジェクトを作るには、上記のようにscope="session"を指定します。これにより、あるページのuserと別のページのuserが同じオブジェクトを参照するようになります。たとえば、あるページでuser.setName("xxx")のようなメソッドでオブジェクトにユーザ名をセットし、別のページでuser.getName()のなどのメソッドでユーザ名を表示することができます。

しかし、このuser変数に別のオブジェクトの参照を代入しても、別のページでそのオブジェクトを参照することはできません。たとえば、次のようなコードを考えてみましょう。
<jsp:useBean class="jp.veltec.User" id="user" scope="session"/>
<%
user.setName("一朗");    //step1
user = new User();            //step2
user.setName("二郎");    //step3
%>
step1でuserに"一朗"という名前を設定し、step2でuserに新しいオブジェクトを代入し、step3で新しいuserに"二郎"という名前を設定しています。さて、他のページでuserオブジェクトから名前を取り出すと"一朗"でしょうか、"二郎"でしょうか。答えは"一朗"です。なぜでしょう。

scope="session"の指定からは、userという変数が各ページより上の階層に作られるような構造をイメージしてしまいそうですが、実際にはそうではありません。useBeanで作られたuserは、あくまで「そのページだけ」で有効な変数で、セッション上のオブジェクトへの参照がその都度コピーされるのです。つまり、隣のページのuserとは、名前が同じ別の変数なのです。これは、JSPからJavaに変換されたソース(Tomcatのworkフォルダの中にあります)を見ると分かります。上の例のuseBeanアクションは次のようなコードに展開されています。

jp.veltec.invoice.User user = null;
  synchronized (session) {
  user =
  (jp.veltec.invoice.User) _jspx_page_context
      .getAttribute("user", javax.servlet.jsp.PageContext.SESSION_SCOPE);
  if (user == null){
    user = new jp.veltec.invoice.User();
    _jspx_page_context.setAttribute("user", user, javax.servlet.jsp.PageContext.SESSION_SCOPE);
  }
}
最初の行でuserという変数を宣言し、その後のブロックでセッション上に置かれたuserオブジェクトを探し(getAttribute)、見つかればその参照をuser変数に代入し、見つからなければセッション上に新たなオブジェクトを作ってその参照を代入しています。これをページごとに行っているので、useBeanでuser変数を作った後に何かを代入しても、他のページには反映されないわけです。

しかし、セッション上のオブジェクトを入れ替えることができないわけではありません。これにはsessionオブジェクトのsetAttributeメソッドを使います。次に例を示します。

<jsp:useBean class="jp.veltec.User" id="user" scope="session"/>
<%
user.setName("一朗");    //step1
user = new User();            //step2
user.setName("二郎");    //step3
session.setAttribute("user",user);
%>
こうすれば他のページでも新しいuserオブジェクトが参照されるようになり、名前を取得すると"二郎"になります。

※実は、私自身が何度もうっかりハマっているので忘れないように書きました。

投稿:竹形 誠司[takegata]/2011年 05月 19日 06時 53分 /更新:2011年 05月 19日 07時 07分