HTTPにはセッションという仕様は無いが、J2EE(サーブレット)ではセッション管理機能をサポートしている。
@Override public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { HttpSession session = req.getSession(true); //タイムアウト時間[秒] session.setMaxInactiveInterval(10 * 60); //値の取得 String value = (String)session.getAttribute("名前"); //値の保存 session.setAttribule("名前", "値"); }
getSession()で、HttpServletRequestからセッションのインスタンスを取得する。
getSession(true)は、セッションがまだ作られていない場合は新規にセッションを作る。
getSession(false)は、セッションが存在しない場合はnullを返す。
セッションを開始する画面ならtrue、セッション途中の画面ならfalseにして戻り値nullのエラーチェックをすべき。
セッションを破棄するには以下の様にする。
session.invalidate();
HttpSession#setAttribute()で、オブジェクトをセッションに保存できる。
指定できる値はObjectクラスなのでどんなクラスでも入れられる訳だが、シリアライズ可能にしておく必要がある。
セッションは破棄されない限りメモリ上に残り続けるので、多量のデータを保持するのは慎むべき。
(エンドユーザーがログアウトせずにブラウザーを閉じてしまったら、サーバー側でタイムアウトして破棄されるまでセッションは生きている。ユーザーとしての自分の行動を省みても、こんなケースは多いはず(苦笑)
これを全てとっておく必要があるのだから、かなりの量になるのが分かるだろう)
また、レプリケーションで共有される(共有の為のデータ転送
や保持容量にコストがかかる)ことを考えれば、やはりデータ量は少ない方がよい。
「クライアントからの要求が同一セッションであるかどうか」を識別する具体的な方法は、たぶんJavaEEサーバーの実装(TomcatやWebLogic)に任されている
。
が、ほとんどはクライアントとセッションIDをやりとりすることでセッションを認識している
と思われる。
その実現方法は、URLリライティングとクッキーの併用。実行時にリクエスト毎にどちらかの方式が使用されるが、どちらを使うのかはサーブレットによって隠蔽されている。
つまりHttpServletRequestやHttpServletResponseを使っていれば、勝手にやってくれる。
が、URLリライティングに関しては、プログラマーも気をつける必要がある。
つまり、生成するHTML内のリンク(URL)にセッションIDを埋め込むので、セッションを継続するURLかどうかを区別し、必要とするURLにはセッションIDを付加してやらなければならない。これは人間(プログラマー)にしか出来ない。
セッションIDを付与する方法に関しては、サーブレットでは専用のメソッドが用意されている。
@Override public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { PrintWriter out = res.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>サンプル</title>"); out.println("</head>"); out.println("<body>"); out.print("<a href=\""); out.print(res.encodeURL("/session_sample.jsp")); out.println("\">リンク</a>"); out.println("</body>"); out.println("</html>"); }
encodeURL()(リダイレクトの場合はencodeRedirectURL())を使うと、サーブレットが「URLリライティングが必要」と判断したときにはエンコードされる(URLが書き換えられる)し、「クッキーのみでいける」と判断したときにはURLはそのままとなる。
ちなみに、クッキーが扱えるかどうかはHttpServletRequest#isRequestedSessionIdFromCookie()で判断できる。
セッションIDはクライアントとサーバー間でやりとりされるが、実際にセッションデータを保持しているのはサーバー側。[2007-09-02]
データ(Javaのオブジェクト)自体はメモリやDB・ファイルに書き込まれて保存される。(具体的にどこに保存されるかは、APサーバーの設定による)
→保持方法
@Override public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { HttpSession session = req.getSession(true); }
メソッド | 状況 | 結果 |
---|---|---|
HttpServletRequest# getSession(true) |
セッションが無いとき | 新しくセッションが作られ、そのオブジェクトが返る。 |
セッションが有るとき | そのオブジェクトが返る。 | |
HttpServletRequest# getSession(false) |
セッションが無いとき | nullが返る。 |
セッションが有るとき | そのオブジェクトが返る。 | |
HttpSession# isNew() |
セッションが初めて作られたとき (まだクライアントへセッションIDを送っていないとき?) |
trueが返る。 |
クライアントがセッションを使えるとき (クライアントがセッションIDを返したとき?) |
falseが返る。 |
セッションを使う場合は、セッションレプリケーションの有無に気を配らなければならない。
たいてい、開発時はローカルのサーバー1台で動いていて上手く動作するが、本番環境の複数台構成(レプリケーションが行われてない)で初めて不具合が表面化することになる。しかも再現性は不安定…!