在web应用中打开浏览器访问一个网站,登录,浏览,到关闭浏览器,称为是一个会话。由于Http协议是无状态的,因此用户在动态页面交互信息需要一些能够保存用户信息的数据结构。这个保存用户浏览数据的数据结构有两种,一种是Cookie,保存在客户端;一种是Session,保存在服务器端。Session可以在浏览器最后一次访问之后保存30分钟,当然这个值也是可以在web.xml文件中配置的,Session的销毁一方面可以是30分钟内没有再次访问,另一方面可以是手动的销毁。30分钟无访问就将Session销毁时由于Session存在于服务器端,会占用服务器的资源,因此超时销毁是很必要的。
保存在客户端的Cookie可以设置有效期,在有效期内浏览器携带响应路径下的Cookie访问服务器,服务器就可以获取用户之前的访问信息了。Session本质上是基于Cookie的,由于当服务器为浏览器创建Session之后会为每一个Session设置一个唯一的ID,用于区分不同访问者。这个SessionID就通过Cookie的形式发送给浏览器,之后每次浏览器访问服务器指定路径的资源的时候就会带着这个Cookie,服务器根据Cookie总的ID找到先前创建的Session,然后从Session中获取数据。
但是这个向浏览器写数据的Cookie是没有设置有效期的,一旦当前浏览器关闭,那么再次打开浏览器访问之前的网站,由于Cookie失效了,服务器端的Session即使是生命周期还没结束也是无法获取和使用的。
解决办法是自己生成一个Cookie将Session的ID写入,然后将写入了SessionID的且设置了有效期的Cookie写回给浏览器
创建:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 浏览器访问的时候使用getSession()为其创建Session
HttpSession session = request.getSession();
String sessionID = session.getId();
// Session的ID名称为JSESSIONID,可以通过HTTPWatch查看
Cookie cookie = new Cookie("JSESSIONID", sessionID);
cookie.setPath("/curpath"); // 设置cookie的路径
cookie.setMaxAge(30 * 60); // 设置的有效时间长度是session的存在时间 半个小时
response.addCookie(cookie);
session.setAttribute("mydata", "hello world");
}
获取:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(false); // 只获取不创建
String data = null;
if(session != null) // 判断是否获取了Session
data = (String) session.getAttribute("mydata");
<span style="white-space:pre"> </span>// Servlet中解决乱码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter pwriter = response.getWriter();
pwriter.write("获取的数据是: " + data);
}
另外一种无法使用已经存在的Session的情形是用户浏览器将Cookie禁止了,那么Session的ID自然是无法发送给浏览器,进而也就没办法继续使用Session了。
解决这种问题可以采用URL重写的方式,每次点击链接的时候浏览器都会讲Session的ID发送给服务器,服务器就取用相应的Session并获取信息。但是在重写URL之前一定要先获取Session。
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter pwriter = response.getWriter();
<span style="white-space:pre"> </span>// 在进行URL重写的时候必须先创建Session
request.getSession();
// 然后重写URL,将Session的ID以URL的形式传递给服务器
// 以解决用户浏览器禁止Cookie导致的Session无法获取的问题
String url1 = response.encodeURL("/curpath/servlet/SessionDemo01");
String url2 = response.encodeURL("/curpath/servlet/SessionDemo02");
pwriter.write("<a href = '" + url1 + "'>发送</a><br/>");
pwriter.write("<a href = '" + url2 + "'>接收</a><br/>");
}
当然两种方法是可以一起使用的,getSession()方法会依次对从Cookie和URL中获取SessionID,而且如果Cookie没有被禁用,那么就不会再将SessionID追加到URL上。
两篇深入讲解Session原理的博文:
http://ywj-316.iteye.com/blog/722941