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台で動いていて上手く動作するが、本番環境の複数台構成(レプリケーションが行われてない)で初めて不具合が表面化することになる。しかも再現性は不安定…!