与Cookie不同,Cookie保存在客户端,而Session保存在服务器端。Cookie目的可以跟踪会话,也可以保存用户喜好或者保存用户名密码,Session用来跟踪会话。
当用户打开浏览器访问某个网站时,服务器就会在服务器的内存为该浏览器分配一个空间,该空间被这个浏览器独占,这个空间就是Session空间,该空间的数据默认保存30min,也可以修改。
Session也是以“名-值”的形式保存数据,其用法有:
(1)得到一个会话对象:HttpSession hs = request.getSession(true);
(2)给会话对象添加属性:hs.setAttribute(String name,Object val);
(3)得到某个属性:String name = hs.getAttribute(String name);
(4)删除某个属性:hs.removeAttribute(String name);
(5)得到服务器分配给该会话的ID:String id = hs.getId();
实现Session的方式有两种,一种是通过Cookie,另一种是通过URL重写。
方式一:如果浏览器支持Cookie,创建Session的时候会把SessionID保存在Cookie里。
/** * @(#)TestSession.java * *测试servlet中Session的用法 * @author * @version 1.00 2017/2/28 */ package com.chongqing; import javax.servlet.http.*; import java.io.*; import javax.servlet.ServletException; import java.util.Date; public class TestSession extends HttpServlet { //处理get请求 public void doGet(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException{ // getSession用于返回当前用户的Session //当参数为true,则如果“当前用户的Session”为空(第一次访问时)则创建一个新的Session返回 //当参数为false,则如果“当前用户的Session”为空,则返回null(即不自动创建会话对象) //req.getSession() 等同于 req.getSession(true), HttpSession mySession = req.getSession(true); res.setContentType("text/html;charset=gb2312"); PrintWriter out = res.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Session Info Servlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<h3>Session Infomation</h3>"); out.println("New Session:" + mySession.isNew() +"<br/>"); //判断Session是否为新创建的 out.println("Session Id:" + mySession.getId() + "<br>"); //获取Session的ID out.println("Session Create Time:" + new Date(mySession.getCreationTime()) + "<br>"); //获取Session创建时间 out.println("Session Last Access Time:" + new Date(mySession.getLastAccessedTime()) + "<br>"); //获取Session最新操作时间 out.println("<h3>Request Infomation</h3>"); out.println("Session Id From Request:" + req.getRequestedSessionId() + "<br>"); //是否从客户端获取了SessionID out.println("Session Id Via Cookie:" + req.isRequestedSessionIdFromCookie() + "<br>"); //判断SessionID是否通过Cookie方式获得 out.println("Session Id Via URL:" + req.isRequestedSessionIdFromURL() + "<br>"); //判断SessionID是否通过URL重写方式获得 out.println("Valid Session Id:" + req.isRequestedSessionIdValid() + "<br>"); //判断获取的SessionID是否有效 out.println("<a href=" + "testsession" + ">refresh</a>"); //刷新页面 out.println("</body>"); out.println("</html>"); out.close(); } public void doPost(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException{ this.doGet(req,res); } }运行的结果:
刷新一次后的结果:
方式二:如果浏览器不支持Cookie(即把Cookie禁用),必须通过自己编程使用URL重写的方式实现Session(通过res.ecnCodeURL()函数).
要在程序中每个想要实现Session的超链接加上enCodeURL函数,如:
out.println("<a href=" + response.encodeURL("SessionInfoServlet") + ">refresh</a>");
值得注意的是Session不像Cookie拥有路径访问的问题,同一个application下的Servlet/JSP可以共享同一个Session,前提是同一个客户端窗口。
最后是使用Session对之前用户管理系统进行改进的例子,在之前的用户管理系统中,如果直接输入Welcome界面的URL也可以进入到这个页面,下面通过Session来说明如何防止用户非法登录页面。
登录界面修改后的代码:
/** * @(#)HelloGen.java * *登录界面 * @author * @version 1.00 2017/2/23 */ package com.chongqing; import javax.servlet.http.*; import java.io.*; public class Login extends HttpServlet { //处理get请求 public void doGet(HttpServletRequest req,HttpServletResponse res){ //业务逻辑 try { //中文乱码 res.setContentType("text/html;charset=gbk"); PrintWriter pw = res.getWriter(); //返回登录界面 pw.println("<html>"); pw.println("<body>"); String info = req.getParameter("info"); if(null != info) { pw.println("<h1>用户名或者密码错误!<h1><br/>"); } pw.println("<h1>登录界面<h1>"); pw.println("<form action= logincl method=post>"); pw.println("用户名:<input type=text name=username><br>"); pw.println("密码:<input type=password name=passwd><br>"); pw.println("<input type=submit value=login><br>"); pw.println("</form>"); pw.println("</body>"); pw.println("</html>"); } catch (Exception ex) { ex.printStackTrace(); } } public void doPost(HttpServletRequest req,HttpServletResponse res){ this.doGet(req,res); } }
验证界面修改后的代码:
/** * @(#)HelloGen.java * *验证页面 * @author * @version 1.00 2017/2/23 */ package com.chongqing; import javax.servlet.http.*; import java.io.*; public class LoginCl extends HttpServlet { //处理get请求 public void doGet(HttpServletRequest req,HttpServletResponse res){ //业务逻辑 try { //接收用户名和密码 String u = req.getParameter("username"); String p = req.getParameter("passwd"); //验证 if(u.equals("zero")&&p.equals("123")){ //合法,添加Session并跳转到欢迎界面 HttpSession mySession = req.getSession(true); mySession.setMaxInactiveInterval(30); //指定Session存活的时间,单位是秒 mySession.setAttribute("usname",u); //在Session中添加一个属性 res.sendRedirect("wel");//写你要到的Servlet的URL }else{ //不合法 res.sendRedirect("login");//写你要到的Servlet的URL } } catch (Exception ex) { ex.printStackTrace(); } } public void doPost(HttpServletRequest req,HttpServletResponse res){ this.doGet(req,res); } }
欢迎界面修改后的代码:
/** * @(#)HelloGen.java * *欢迎界面 * @author * @version 1.00 2017/2/23 */ package com.chongqing; import javax.servlet.http.*; import java.io.*; public class wel extends HttpServlet { //处理get请求 public void doGet(HttpServletRequest req,HttpServletResponse res){ //首先判断Session中是否有登录时添加的属性 HttpSession mySession = req.getSession(true); String val = (String)mySession.getAttribute("usname"); try { if(null == val) { //返回登录界面 res.sendRedirect("login?info=error"); return; } PrintWriter pw = res.getWriter(); pw.println("Welcom!"); } catch (Exception ex) { ex.printStackTrace(); } } public void doPost(HttpServletRequest req,HttpServletResponse res){ this.doGet(req,res); } }
运行结果可以看出,如果直接输入欢迎界面的URL则被阻止进入并跳转到登录界面: