JavaWeb中Session对象的学习笔记
一、session简单介绍
在web开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。
二、session和cookie的主要区别
cookie是把用户的数据写给用户的浏览器。
session技术把用户的数据写到用户独占的session中。
session对象由服务器创建,开发人员可以调用request对象的getsession方法得到session对象。
三、session实现原理
3.1、服务器是如何实现一个session为一个用户浏览器服务的?
服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session id过来了,就会使用内存中与之对应的session为之服务。可以用如下的代码证明:
package xdp.gacl.session; import java.io.ioexception; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import javax.servlet.http.httpsession; public class sessiondemo1 extends httpservlet { public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { response.setcharacterencoding("utf=8"); response.setcontenttype("text/html;charset=utf-8"); //使用request对象的getsession()获取session,如果session不存在则创建一个 httpsession session = request.getsession(); //将数据存储到session中 session.setattribute("data", "孤傲苍狼"); //获取session的id string sessionid = session.getid(); //判断session是不是新创建的 if (session.isnew()) { response.getwriter().print("session创建成功,session的id是:"+sessionid); }else { response.getwriter().print("服务器已经存在该session了,session的id是:"+sessionid); } } public void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { doget(request, response); } }
第一次访问时,服务器会创建一个新的sesion,并且把session的id以cookie的形式发送给客户端浏览器,如下图所示:
点击刷新按钮,再次请求服务器,此时就可以看到浏览器再请求服务器时,会把存储到cookie中的session的id一起传递到服务器端了,如下图所示:
我猜想request.getsession()方法内部新创建了session之后一定是做了如下的处理
//获取session的id string sessionid = session.getid(); //将session的id存储到名字为jsessionid的cookie中 cookie cookie = new cookie("jsessionid", sessionid); //设置cookie的有效路径 cookie.setpath(request.getcontextpath()); response.addcookie(cookie);
四、浏览器禁用cookie后的session处理
4.1、ie8禁用cookie
工具->internet选项->隐私->设置->将滑轴拉到最顶上(阻止所有cookies)
4.2、解决方案:url重写
response.encoderedirecturl(java.lang.string url) 用于对sendredirect方法后的url地址进行重写。
response.encodeurl(java.lang.string url)用于对表单action和超链接的url地址进行重写
4.3、范例:禁用cookie后servlet共享session中的数据
indexservlet
package xdp.gacl.session; import java.io.ioexception; import java.io.printwriter; import java.util.linkedhashmap; import java.util.map; import java.util.set; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; //首页:列出所有书 public class indexservlet extends httpservlet { public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { response.setcontenttype("text/html;charset=utf-8"); printwriter out = response.getwriter(); //创建session request.getsession(); out.write("本网站有如下书:<br/>"); set<map.entry<string,book>> set = db.getall().entryset(); for(map.entry<string,book> me : set){ book book = me.getvalue(); string url =request.getcontextpath()+ "/servlet/buyservlet?id=" + book.getid(); //response. encodeurl(java.lang.string url)用于对表单action和超链接的url地址进行重写 url = response.encodeurl(url);//将超链接的url地址进行重写 out.println(book.getname() + " <a href='"+url+"'>购买</a><br/>"); } } public void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { doget(request, response); } } /** * @author gacl * 模拟数据库 */ 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; } }
buyservlet
package xdp.gacl.session; import java.io.ioexception; import java.util.arraylist; import java.util.list; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import javax.servlet.http.httpsession; public class buyservlet extends httpservlet { public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { 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()+"/servlet/listcartservlet"); system.out.println(url); response.sendredirect(url); } public void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { doget(request, response); } }
listcartservlet
package xdp.gacl.session; import java.io.ioexception; import java.io.printwriter; import java.util.list; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import javax.servlet.http.httpsession; public class listcartservlet extends httpservlet { public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, 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 servletexception, ioexception { doget(request, response); } }
在禁用了cookie的ie8下的运行效果如下:
演示效果
通过查看indexservlet生成的html代码可以看到,每一个超链接后面都带上了session的id,如下所示
//本网站有如下书: <br/>javaweb开发 <a href='/javaweb_session_study_20140720/servlet/buyservlet;jsessionid=96bdfb9d87a08d5ab1eaa2537cde2db2?id=1'>购买</a><br/> //spring开发 <a href='/javaweb_session_study_20140720/servlet/buyservlet;jsessionid=96bdfb9d87a08d5ab1eaa2537cde2db2?id=2'>购买</a><br/> // hibernate开发 <a href='/javaweb_session_study_20140720/servlet/buyservlet;jsessionid=96bdfb9d87a08d5ab1eaa2537cde2db2?id=3'>购买</a><br/> //struts开发 <a href='/javaweb_session_study_20140720/servlet/buyservlet;jsessionid=96bdfb9d87a08d5ab1eaa2537cde2db2?id=4'>购买</a><br/> //ajax开发 <a href='/javaweb_session_study_20140720/servlet/buyservlet;jsessionid=96bdfb9d87a08d5ab1eaa2537cde2db2?id=5'>购买</a><br/>
所以,当浏览器禁用了cookie后,就可以用url重写这种解决方案解决session数据共享问题。而且response. encoderedirecturl(java.lang.string url) 和response. encodeurl(java.lang.string url)是两个非常智能的方法,当检测到浏览器没有禁用cookie时,那么就不进行url重写了。我们在没有禁用cookie的火狐浏览器下访问,效果如下:
从演示动画中可以看到,浏览器第一次访问时,服务器创建session,然后将session的id以cookie的形式发送回给浏览器,response. encodeurl(java.lang.string url)方法也将url进行了重写,当点击刷新按钮第二次访问,由于火狐浏览器没有禁用cookie,所以第二次访问时带上了cookie,此时服务器就可以知道当前的客户端浏览器并没有禁用cookie,那么就通知response. encodeurl(java.lang.string url)方法不用将url进行重写了。
五、session对象的创建和销毁时机
5.1、session对象的创建时机
在程序中第一次调用request.getsession()方法时就会创建一个新的session,可以用isnew()方法来判断session是不是新创建的
范例:创建session
//使用request对象的getsession()获取session,如果session不存在则创建一个 httpsession session = request.getsession(); //获取session的id string sessionid = session.getid(); //判断session是不是新创建的 if (session.isnew()) { response.getwriter().print("session创建成功,session的id是:"+sessionid); }else { response.getwriter().print("服务器已经存在session,session的id是:"+sessionid); }
5.2、session对象的销毁时机
session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间,例如:
<?xml version="1.0" encoding="utf-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 设置session的有效时间:以分钟为单位--> <session-config> <session-timeout>15</session-timeout> </session-config> </web-app>
当需要在程序中手动设置session失效时,可以手工调用session.invalidate方法,摧毁session。
1 httpsession session = request.getsession();
2 //手工调用session.invalidate方法,摧毁session
3 session.invalidate();
以上就是本文的全部内容,希望对大家学习session有所帮助。