Session浅谈
在web开发中,服务器可以为每个用户浏览器创建一个会话对象(Session对象),注意,一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以将用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其他程序时,其他程序可以从用户的session中取出该用户的数据,为用户服务
Session和Cookie的区别
Cookie是将用户的数据写给用户的浏览器,cookie用于在客户端保存用户信息
Session是将用户的数据写到用户独占的Session中,session用于在服务器端保存用户信息
PS:Servlet中的Session和JSP中的Session的关系
这两个session都是javax.servlet.http.HttpSession类的实例,本质上他们是一样的,servlet中需要通过request.getSession()来获取session对象,而JSP中可以直接使用,每个用户对应一个session对象。
Session对象由服务器创建,开发人员可以调用request的getSession方法得到session对象
session的生:request.getSession() 注意:request.getSession(false) 是只获取不创建session
request.getSession(); //服务器会首先检测有没有带cookie过来的session,如果有则获取session,如果发现浏览器禁用了cookie,再检测有没有带重写URL的session,有获取,上述两个都没有带过来,就会创建新的session
session的死:如果session在30分钟不被使用(不管关不关浏览器) 会自动摧毁session 另外在web.xml文件中也可以配置session的失效时间
用配置的方式摧毁session:
<session-config>
<session-timeout>10</session-timeout> <!-- 10分钟内不使用自动销毁 -->
</session-config>
用代码的方式摧毁session:
session.invalidate(); //调用该方法来摧毁session
session的实现原理
session的具体实现基于cookie
request.getSession()首先用于判断服务器是否有创建session,如果没有,则创建一个session,每个session创建的时候都会有个ID值,服务器将该ID值以cookie的方式回写给浏览器,再次访问另一个程序时,cookie会带着该session的ID,所以,第二次在获取session的时候,不会创建session,而是会获取到该cookie所带的ID值对应的session。
但是该cookie没有设置有效期,所以关闭浏览器后,session也将失效。为了解决该问题,需要重写cookie,并设置该cookie的生命周期,值得一提的是,保存sessionID的cookie是一个固定的cookie,该cookie的名称为JSESSIONID,所以可以通过创建这个Cookie覆盖原来的cookie
String cookieId = session.getId(); //获取session的ID值
Cookie cookie = new Cookie("JSESSIONID",cookieId); //重新创建该cookie,覆盖原来没有生命周期的cookie
cookie.setMaxAge(30*60); //设置cookie的生命周期为半个小时
cookie.setPath("/servlet");
response.addCookie(cookie); //服务器回写cookie给浏览器 覆盖之前系统的同名但无生命长度的cookie
上述代码的作用是,
当首次打开浏览器,访问一个名称为SessionBuy的servlet
public class SessionBuy extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(); //首次访问服务器,服务器创建session并将sessionID回写给cookie
session.setAttribute("product", "洗衣机"); //设置session的值
}
}
再次访问另一个名称为sessionPay的servlet
public class SessionPay extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession(false); //给句cookie带过来的sessionID获取相应的session
out.print("您购买的额商品是: "+session.getAttribute("product")); //输出session的值
}
}
访问两个servlet的页面index.html
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
</head>
<body>
<a href='/servlet/servlet/SessionBuy'>购买</a>
<a href='/servlet/servlet/SessionPay'>付款</a>
</body>
</html>
上述代码存在的一个问题是,创建的携带sessionID的cookie是系统默认创建的cookie,该cookie的没有setMaxAge(),即该cookie没有生命长度,一旦关闭浏览器,打开一个新的浏览器,该cookie已经不存在,下次通过sessionPay的servlet去获取session个的值时,由于此时cookie已经失效,所以获取不到session的数据
1.访问index.html页面
2.点击购买链接,访问SessionBuy
3.返回index.html,点击付款链接,将会显示购买的商品为 洗衣机
4.关闭浏览器 重新打开一个新的浏览器,点击付款链接 发现显示购买商品为 null
即先点击购买,会创建session,并自动创建一个sessionID, 该sessionID赋值给一个叫JSESSIONID的cookie,并将该cookie回写给浏览器,当再点击付款时,服务器会根据该浏览器的名称为JSESSIONID的cookie带过来的sessionid,获得购买时创建的session,并打印该session所带的值。但是JSESSIONID这个cookie是系统自己生成的,它的MaxAge值为0,也就是说当关闭浏览器重新打开一个浏览器,该cookie就不再生效,这时候直接点击付款,会发现显示的值为null。
为了解决关闭浏览器,重新打开浏览器再次获取session的值的问题,需要重新并覆盖创建系统的默认cookie,该该cookie设置一个生命周期,这样就解决了上述问题。
1.访问index.html页面
2.点击购买链接,访问SessionBuy
3.返回index.html,点击付款链接,将会显示购买的商品为 洗衣机
4.关闭浏览器 重新打开一个新的浏览器,点击付款链接 发现显示购买的商品还是 洗衣机
5.说明此时的cookie还在生效 上述问题得以解决将上述SessionBuy的servlet的代码增加红色部分:
public class SessionBuy extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
String cookieId = session.getId(); //获取cookie携带的sessionID
Cookie cookie = new Cookie("JSESSIONID",cookieId); //覆盖系统默认的cookie,该cookie的名称为JSESSIONID
cookie.setMaxAge(30*60); //设置该cookie的存活期为半个小时,关闭浏览器再次打开浏览器该cookie依然存在
cookie.setPath("/servlet");
response.addCookie(cookie); //将服务器该cookie回写给浏览器
session.setAttribute("product", "洗衣机");
}
}
URL重写
session的实现机制是cookie,通过cookie携带sessionID来标识session,但是如果浏览器禁用了cookie,该怎么办?我们需要想办法将sessionID通过另一个介质带给浏览器,这时候就需要一个新的技术,URL重写,即将sessionID加在超链接的后面
在上述代码的基础上加一个新的servlet
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("utf-8");response.setContentType("text/html");
PrintWriter out = response.getWriter();
request.getSession(); //创建session
String url1 = response.encodeURL("SessionBuy"); //URL重写 通过该方法给URL后面添加一个ID
String url2 = response.encodeURL("SessionPay");
out.print("<a href='"+url1+"'>购买</a> ");
out.print("<a href='"+url2+"'>结账</a>");
}
URL重写 无法解决 4.关闭浏览器 重新打开一个新的浏览器,点击付款链接 发现显示购买商品为 null 这个问题
学习笔记 多有不足!!!