1.当用户第一次使用session时(表示第一次请求服务器),服务器会创建session,
并创建一个Cookie,在Cookie中保存了session的id,发送给客户端。这样客户端就有了自己session的id了。但这个Cookie只在浏览器内存中存在,也就是说,在关闭浏览器窗口后,Cookie就会丢失,也就丢失了sessionId。
2.当用户第二次访问服务器时,会在请求中把保存了sessionId的Cookie发送给服务器,服务器通过sessionId查找session对象,然后给使用。也就是说,只要浏览器容器不关闭,无论访问服务器多少次,使用的都是同一个session对象。这样也就可以让多个请求共享同一个session了。
3.当用户关闭了浏览器窗口后,再打开浏览器访问服务器,这时请求中没有了sessionId,那么服务器会创建一个session,再把sessionId通过Cookie保存到浏览器中,也是一个新的会话开始了。原来的session会因为长时间无法访问而失效。
4.当用户打开某个服务器页面长时间没动作时,这样session会超时失效,当用户再有活动时,服务器通过用户提供的sessionId已经找不到session对象了,那么服务器还是会创建一个新的session对象,再把新的sessionId保存到客户端。这也是一个新的会话开始了。
Session的创建与删除
一个常见的错误是以为session在有客户端访问时就被创建,然而事实是直到某server端程序(如Servlet)调用HttpServletRequest.getSession(true) 或者 HttpServletRequest.getSession()这样的语句时才会被创建。
getSession():如果当前已经创建了session则为这个用户则直接返回这个sesoin的对象。如果没有则创建一个新的。
session在下列情况下被删除:
A.程序调用HttpSession.invalidate()
B.距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间(tomcat服务器默认30分钟)
C.服务器进程被停止
注意:关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效,不会使服务器端的session对象失效。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //创建session //如果当前已经创建了session,则为该请求返回一个session对象,如果没创建,就创建一个session HttpSession session=request.getSession(); System.out.println(session); System.out.println(session.getId());//获取sessionid //共享权限:一次会话 session.setAttribute("name", "zhangsan"); System.out.println(session.getAttribute("name")); }
Session的超时管理
WEB服务器无法判断当前的客户端浏览器是否还会继续访问,也无法检测客户端浏览器是否关闭,所以,即使客户已经离开或关闭了浏览器,WEB服务器还要保留与之对应的HttpSession对象。
随着时间的推移而不断增加新的访问客户端,WEB服务器内存中将会因此积累起大量的不再被使用的HttpSession对象,并将最终导致服务器内存耗尽。
WEB服务器采用“超时限制”的办法来判断客户端是否还在继续访问,如果某个客户端在一定的时间之内没有发出后续请求,WEB服务器则认为客户端已经停止了活动,结束与该客户端的会话并将与之对应的HttpSession对象变成垃圾。
如果客户端浏览器超时后再次发出访问请求,WEB服务器则认为这是一个新的会话的开始,将为之创建新的HttpSession对象和分配新的会话标识号。
会话的超时间隔可以在web.xml文件中设置,其默认值由Servlet容器定义。
<session-config>
<session-timeout>30</session-timeout>
</session-config>
HttpSession 的生命周期
是否浏览器访问服务端的任何一个 JSP 或 Servlet,服务器都会立即创建一个 HttpSession 对象呢?
若当前的 JSP(或 Servlet) 是客户端访问的当前 WEB 应用的第一个资源,且 JSP 的 page 指定的 session 属性值为 false, 则服务器就不会为 JSP 创建一个 HttpSession 对象;
若当前 JSP 不是客户端访问的当前 WEB 应用的第一个资源,且其他页面已经创建一个 HttpSession 对象,则当前 JSP 页面会返回一个会话的 HttpSession 对象,而不会创建一个新的 HttpSession对象。
对于 Serlvet 而言:若 Serlvet 是客户端访问的第一个 WEB 应用的资源,则只有调用了 request.getSession() 或 request.getSession(true) 才会创建 HttpSession 对象
session=“false“ 到底表示什么意思?
当前 JSP 页面禁用 session 隐含变量!
但可以使用其他的显式的 HttpSession 对象
避免表单的重复提交
调用 RequestDispatcher.forward() 方法,浏览器所保留的URL 是先前的表单提交的 URL,此时点击”刷新”, 浏览器将再次提交用户先前输入的数据,引起重复提交。
如果采用 HttpServletResponse.sendRedirct() 方法将客户端重定向到成功页面,将不会出现重复一条问题。
包含有FORM表单的页面必须通过一个服务器程序动态产生,服务器程序为每次产生的页面中的FORM表单都分配一个唯一的随机标识号,并在FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。
当用户提交FORM表单时,负责接收这一请求的服务器程序比较FORM表单隐藏字段中的标识号与存储在当前用户的Session域中的标识号是否相同,如果相同则处理表单数据,处理完后清除当前用户的Session域中存储的标识号。在下列情况下,服务器程序将忽略提交的表单请求:
当前用户的Session中不存在表单标识号
用户提交的表单数据中没有标识号字段
存储在当前用户的Session域中的表单标识号与表单数据中的标识号不同
浏览器只有重新向WEB服务器请求包含FORM表单的页面时,服务器程序才又产生另外一个随机标识号,并将这个标识号保存在Session域中和作为新返回的FORM表单中的隐藏字段值。
<body> <% //java代码 String uuid=UUID.randomUUID().toString().replace("-", ""); request.getSession().setAttribute("token", uuid); %> <hr> <form action="regServlet" method="post"> <input type="hidden" value="<%=uuid%>" name="token"> 用户名:<input type="text" name="name"><br> 密 码: <input type="password" name="pwd"><br> <input type="submit" value="注册"> </form> </body>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //已经调用数据库 //System.out.println("注册成功"); //获取用户提交的token String token=request.getParameter("token"); //获取session中的token HttpSession session=request.getSession(); String sToken=(String) session.getAttribute("token"); //验证是否重复提交 if(token.equals(sToken)){ System.out.println("注册成功!"); session.removeAttribute("token"); }else{ System.out.println("表单重复提交了"); response.sendRedirect(request.getContextPath()+"/index.jsp"); } //request.getRequestDispatcher("/index.jsp").forward(request, response); }
1.表单重复提交问题:
1).在表单中请求了一个servlet,而servlet又通过请求转发的方式转发给另一个jsp页面,当我再次刷新的时候,地址栏
还是原来请求servlet的地址栏,这样就出现了表单重复提交的问题。重定向不会出现表单重复提交问题。2).在响应页面未完成响应时,多次点了提交按钮
3)点击浏览器后退,再次点击提交