原文連結:
http://www.cnblogs.com/lxboy2009/p/5943759.html
會話可簡單了解為:使用者開一個浏覽器,點選多個超連結,通路伺服器多個web資源,然後關閉浏覽器,整個過程稱之為一個會話。
儲存會話資料的兩種技術:Cookie,Session
Cookie是用戶端技術,程式把每個使用者的資料以cookie的形式寫給使用者各自的浏覽器。當使用者使用浏覽器再去通路伺服器中的web資源時,就會帶着各自的資料去。這樣,web資源處理的就是使用者各自的資料了。
Session是伺服器端技術,利用這個技術,伺服器在運作時可以為每一個使用者的浏覽器建立一個其獨享的session對象,由于session為使用者浏覽器獨享,是以使用者在通路伺服器的web資源時,可以把各自的資料放在各自的session中,當使用者再去通路伺服器中的其它web資源時,其它web資源再從使用者各自的session中取出資料為使用者服務。
Cookie應用

//顯示使用者上次通路的時間
public class CookieDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.write("您上次通路時間是:");
//1.擷取使用者上次通路的時間,顯示
Cookie cookies[] = request.getCookies();
for(int i=0;cookies!=null && i<cookies.length;i++){
Cookie cookie = cookies[i];
if(cookie.getName().equals("lastAccessTime")){
long time = Long.parseLong(cookie.getValue());
Date date = new Date(time);
out.write(date.toLocaleString());
}
}
//2.把本次的時間以cookie的形式回寫給客戶機 (lastAccessTime)
Cookie cookie = new Cookie("lastAccessTime",System.currentTimeMillis()+"");
cookie.setMaxAge(100);//設定有效期,cookie将寫到硬碟上,不設定有效期,cookie的有效期是會話範圍,cookie僅存儲在浏覽器緩存中,浏覽器一關閉,cookie就沒了。
response.addCookie(cookie);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

Cookie細節:
1. 一個Cookie隻能辨別一種資訊,它至少含有一個辨別該資訊的名稱(NAME)和設定值(VALUE)。
2. 一個WEB站點可以給一個WEB浏覽器發送多個Cookie,一個WEB浏覽器也可以存儲多個WEB站點提供的Cookie。
3. 浏覽器一般隻允許存放300個Cookie,每個站點最多存放20個Cookie,每個Cookie的大小限制為4KB。
4. 如果建立了一個cookie,并将他發送到浏覽器,預設情況下它是一個會話級别的cookie(即存儲在浏覽器的記憶體中),使用者退出浏覽器之後即被删除。若希望浏覽器将該cookie存儲在磁盤上,則需要使用maxAge,并給出一個以秒為機關的時間。将最大時效設為0則是指令浏覽器删除該cookie。
5. 注意,删除cookie時,path必須一緻,否則不會删除
設定Session,與NET平台不同
String data = "abcd";
HttpSession session = request.getSession();
session.setAttribute("data", data);
取出Session
HttpSession session = request.getSession();
//session.invalidate(); 摧毀session
String data = (String) session.getAttribute("data");
response.getWriter().write(data);
session實作會話過程資料共享的原理:
Session是基于Cookie的、伺服器建立每個session的時候,會為每個session配置設定一個ID号,即 JSESSIONID,伺服器會以cookie的方式把session 的id号寫給浏覽器、是以session是基于cookie的。當浏覽器再次通路的時候,會帶着session id号的cookie過來 ,這就是session實作共享的原理。伺服器寫這個cookie的時候,是沒有寫有效期的,是以當浏覽器關閉的時候,cookie也就沒了,session也就結束了,即會話過程。
多浏覽器共享Session
由上面的分析可以,關閉浏覽器後,session将消失,那麼如何做到多浏覽器共享一個session呢(即關閉浏覽器後,再打開一個浏覽器後session還存在)?
隻要手動的寫入cookie,并設定有效期即可。用這個cookie來覆寫伺服器寫給浏覽器的。可以通過httpwatch來觀察伺服器寫給浏覽器的内容。
解決方案如下:名字必須是JSESSIONID,因為伺服器寫給浏覽器的cookie的名字就是這個 。
HttpSession session = request.getSession();
Cookie cookie = new Cookie("JSESSIONID",session.getId());
cookie.setMaxAge(30*60);
cookie.setPath("/day07");//因為伺服器寫給浏覽器的也有設定path,是以要想自己寫的cookie覆寫伺服器寫的,必須跟伺服器寫的一緻。
response.addCookie(cookie);
Session是基于Cookie的,那如果浏覽器禁用了cookie後怎麼辦? 會出現空指針異常。
因為禁用了cookie,伺服器寫cookie的時候,浏覽器會拒絕,下次再來通路的時候是沒有帶cookie的,而在背景有使用這個cookie,是以會出現空指針異常。
解決方法:不以cookie的方式把JSESSIONID帶給伺服器,而是把JSESSIONID以url的方式帶到伺服器,
即URL重寫:URL重寫解決了禁用cookie後,Session的共享問題。
String url = response.encodeRedirectURL("/day07/servlet/ListCartServlet"); //實作 url重寫
response.sendRedirect(url);
encodeRedirectURL方法會自動的在URL後面加上JSEEIONID的參數。
一般涉及到會話的超連結都要使用url重寫,來解決浏覽器禁用cookie的問題。
String url = "/day07/servlet/BuyServlet?id="+book.getId();
url = response.encodeURL(url); //得到重寫後的url
encodeURL
encodeRedirectURL
上面兩個都是url重寫,重定向的url重寫使用下面一個,其他的url重寫使用上面一個。
response. encodeRedirectURL(java.lang.String url)
用于對sendRedirect方法後的url位址進行重寫。
response. encodeURL(java.lang.String url)
用于對表單action和超連結的url位址進行重寫
URL重寫會自己判斷浏覽器是否禁用了cookie,如果沒有禁用cookie,不會在超連結後面加上JSESSIONID的參數帶給伺服器,隻有禁用了Cookie才會帶。
Session的失效時間可以在web.xml檔案中修改
<session-config>
<session-timeout>10</session-timeout> //10分鐘
</session-config>
session在10分鐘内沒有在被使用,伺服器就會摧毀session。
使用者登入儲存登入标記,存入session

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//request.getAttribute("username"); //從域中取username
String username = request.getParameter("username");
String password = request.getParameter("password");
//檢測使用者名和密碼在資料庫中是否存在
List<User> list = DB.getAll();
for(User user : list){
if(user.getUsername().equals(username) && user.getPassword().equals(password)){
//從資料庫中找到比對使用者,讓使用者登陸成功
request.getSession().setAttribute("user", user);
response.sendRedirect("/day07/index.jsp");
return;
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("使用者名或密碼錯誤!!");
}


//登出登陸使用者
public class LogoutServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(false);
if(session!=null){
session.removeAttribute("user");
}
response.sendRedirect("/day07/index.jsp");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

兩者差別:
request.getSession();如果伺服器記憶體中沒有session,伺服器會建立一個session,如果有session,會傳回該session
request.getSession(false);隻檢索伺服器記憶體中有沒有session,如果沒有也不建立session了,如果有,則傳回該sessio