一、Session的简单介绍
在web开发中,服务器可以为每个用户浏览器创建一个跟踪会话的session对象,注意:在默认情况下,一个浏览器独占一个session对象。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户对应的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。
二、Session和Cookie的主要区别
1.Cookie是把用户的数据写给用户的浏览器,以文本文件的格式存储在浏览器中。
2.Session技术把用户的数据写到用户独占的session中,Session存储在服务器端。Session对象由服务器创建,可以调用request对象的getSession方法得到session对象。
三、Session实现原理
服务器创建session出来后,会把session的id号,以cookie的形式回写给浏览器,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session的id过来了,就会使用服务器内存储的对应的session为之服务。
public class SessionDemo1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); HttpSession session=request.getSession(); session.setAttribute("data","会话"); String sessionId = session.getId(); //判断session是否是新创建的 if(session.isNew()) { response.getWriter().write("session创建成功,它的id是:" + sessionId); }else { response.getWriter().write("session已经存在,它的id是:"+sessionId); } } public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException { doGet(request,response); } }
运行结果:
在刚打开浏览器进入localhost:8080/Demo01_war_exploded这个站点时,session已经被创建,再进入localhost:8080/Demo01_war_exploded/SessionDemo1这个站点时,session就不是新创建的了,session已经存在。
找到浏览器存储的cookie,发现一个cookie中保存着session的id,说明session被创建时,通过cookie将session的id发送到浏览器:
在上面的代码中为该浏览器对应的session设置了值:session.setAttribute("data","会话"),新建一个取出这个值。
四、浏览器禁用Cookie后的session处理
浏览器禁用Cookie:
在禁用浏览器保存服务器端发来的cookie时,这时客户端就不知道session的id,客户端跳转到另一个页面时,就不能去访问服务器端的session共享里面的数据了。
这时可以用response.encodeRedirectURL(java.lang.String url)和response.encodeURL(java.lang.String url)两个方法重写sevlet中执行跳转的URL。
response.encodeRedirectURL(java.lang.String url) 用于对sendRedirect方法后的url地址,也就是重定向的url进行重写。
response.encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写。
示例:
public class SessionDemo3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter writer = response.getWriter(); request.getSession(); writer.write("本网站有如下书:<br/>"); //set只有键,键就是值,不允许重复。map是键值对,键不能重复。entrySet()把map里的值传到一个set里存放 Set<Map.Entry<String, Book>> set = DB.getAll().entrySet(); for (Map.Entry<String, Book> me : set) { Book book = me.getValue(); //request.getContextPath()返回的是这个web应用的url String url = request.getContextPath() + "/SessionDemo4?id=" + book.getId(); //response. encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写 url = response.encodeURL(url);//将超链接的url地址进行重写 writer.println(book.getName() + " <a href='" + url + "'>购买</a><br/>"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) { } } /** * 42 * @author gacl * 43 * 模拟数据库 * 44 */ class DB { private static Map<String, Book> map = new LinkedHashMap<String, Book>(); static { map.put("1", new Book("1", "javaweb开发")); map.put("2", new Book("2", "spring开发")); map.put("3", new Book("3", "hibernate开发")); map.put("4", new Book("4", "struts开发")); map.put("5", new Book("5", "ajax开发")); } public static Map<String, Book> getAll() { return map; } } class Book { private String id; private String name; public Book() { super(); } public Book(String id, String name) { super(); this.id = id; this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
SessionDemo3的界面:
对“购买”添加了超链接跳转到SessionDemo4,并将书的id传过去:String url = request.getContextPath() + "/SessionDemo4?id=" + book.getId();
再将超链接的url地址进行重写: response.encodeURL(url);
看一下SessionDemo3的页面源代码:
可以看出在超链接中添加上了session的id,这就能使通过超链接跳转过去的页面也能共享到session中的数据
跳转到SessionDemo4后,SessionDemo4通过url得到的书的id,通过id得到书的名字,将书的名字写到session中,然后SessionDemo4重定向SessionDemo5中:
public class SessionDemo4 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); String id = request.getParameter("id"); Book book = DB.getAll().get(id); //得到用户想买的书 HttpSession session = request.getSession(); List<Book> list = (List) session.getAttribute("list"); //得到用户用于保存所有书的容器 if (list == null) { list = new ArrayList<Book>(); session.setAttribute("list", list); } list.add(book); //response. encodeRedirectURL(java.lang.String url)用于对sendRedirect方法后的url地址进行重写 String url = response.encodeRedirectURL(request.getContextPath() + "/SessionDemo5"); System.out.println(url); response.sendRedirect(url); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { doGet(request, response); } }
在SessionDemo4中通过response.encodeRedirectURL(java.lang.String url)方法重写重定向于SessionDemo5的url:
String url = response.encodeRedirectURL(request.getContextPath() + "/SessionDemo5");
在SessionDemo5中读取session中的数据,显示购买了哪本书:
public class SessionDemo5 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); HttpSession session = request.getSession(); List<Book> list = (List) session.getAttribute("list"); if (list == null || list.size() == 0) { out.write("对不起,您还没有购买任何商品!!"); return; } //显示用户买过的商品 out.write("您买过如下商品:<br>"); for (Book book : list) { out.write(book.getName() + "<br/>"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { doGet(request, response); } }
在网址栏中可以看到重定向SessionDemo5的url中也添加了session的id,这也是为什么在浏览器禁用cookie的情况下,SessionDemo5还能共享session中的数据
在浏览器没有禁用Cookie的情况下,即使调用了response.encodeRedirectURL(java.lang.String url)和response.encodeURL(java.lang.String url)这两个方法,执行跳转的URL也不会被重写:
五、session对象的创建和销毁时机
1.在程序中第一次调用request.getSession()方法时就会创建一个新的Session,可以用isNew()方法来判断Session是不是新创建的。
2.session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间:
<!-- 设置Session的有效时间:以分钟为单位--> <session-config> <session-timeout>15</session-timeout> </session-config>
3.当需要在程序中设置Session失效时,可以调用session.invalidate方法,摧毁session。