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号去,服务器发现客户机浏览器带sessionid过来了,就会使用内存中与之对应的session为之服务。可以用如下的代码证明:
复制代码
1packagexdp.gacl.session;
2
3importjava.io.IOException;
4importjavax.servlet.ServletException;
5importjavax.servlet.http.HttpServlet;
6importjavax.servlet.http.HttpServletRequest;
7importjavax.servlet.http.HttpServletResponse;
8importjavax.servlet.http.HttpSession;
9
10publicclassSessionDemo1extendsHttpServlet{
11
12publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
13throwsServletException,IOException{
14
15response.setCharacterEncoding("UTF=8");
16response.setContentType("text/html;charset=UTF-8");
17//使用request对象的getSession()获取session,如果session不存在则创建一个
18HttpSessionsession=request.getSession();
19//将数据存储到session中
20session.setAttribute("data","孤傲苍狼");
21//获取session的Id
22StringsessionId=session.getId();
23//判断session是不是新创建的
24if(session.isNew()){
25response.getWriter().print("session创建成功,session的id是:"+sessionId);
26}else{
27response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);
28}
29}
30
31publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
32throwsServletException,IOException{
33doGet(request,response);
34}
35}
复制代码
第一次访问时,服务器会创建一个新的sesion,并且把session的Id以cookie的形式发送给客户端浏览器,如下图所示:
点击刷新按钮,再次请求服务器,此时就可以看到浏览器再请求服务器时,会把存储到cookie中的session的Id一起传递到服务器端了,如下图所示:
我猜想request.getSession()方法内部新创建了Session之后一定是做了如下的处理
复制代码
1//获取session的Id
2StringsessionId=session.getId();
3//将session的Id存储到名字为JSESSIONID的cookie中
4Cookiecookie=newCookie("JSESSIONID",sessionId);
5//设置cookie的有效路径
6cookie.setPath(request.getContextPath());
7response.addCookie(cookie);
复制代码
四、浏览器禁用Cookie后的session处理
4.1、IE8禁用cookie
工具->internet选项->隐私->设置->将滑轴拉到最顶上(阻止所有cookies)
4.2、解决方案:URL重写
response.encodeRedirectURL(java.lang.Stringurl)用于对sendRedirect方法后的url地址进行重写。
response.encodeURL(java.lang.Stringurl)用于对表单action和超链接的url地址进行重写
4.3、范例:禁用Cookie后servlet共享Session中的数据
IndexServlet
复制代码
1packagexdp.gacl.session;
2
3importjava.io.IOException;
4importjava.io.PrintWriter;
5importjava.util.LinkedHashMap;
6importjava.util.Map;
7importjava.util.Set;
8importjavax.servlet.ServletException;
9importjavax.servlet.http.HttpServlet;
10importjavax.servlet.http.HttpServletRequest;
11importjavax.servlet.http.HttpServletResponse;
12
13//首页:列出所有书
14publicclassIndexServletextendsHttpServlet{
15
16publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
17throwsServletException,IOException{
18
19response.setContentType("text/html;charset=UTF-8");
20PrintWriterout=response.getWriter();
21//创建Session
22request.getSession();
23out.write("本网站有如下书: ");
24Set>set=DB.getAll().entrySet();
25for(Map.Entryme:set){
26Bookbook=me.getValue();
27Stringurl=request.getContextPath()+"/servlet/BuyServlet?id="+book.getId();
28//response.encodeURL(java.lang.Stringurl)用于对表单action和超链接的url地址进行重写
29url=response.encodeURL(url);//将超链接的url地址进行重写
30out.println(book.getName()+"购买 ");
31}
32}
33
34publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
35throwsServletException,IOException{
36doGet(request,response);
37}
38}
39
40
41/
42@authorgacl
43模拟数据库
44/
45classDB{
46privatestaticMapmap=newLinkedHashMap();
47static{
48map.put("1",newBook("1","javaweb开发"));
49map.put("2",newBook("2","spring开发"));
50map.put("3",newBook("3","hibernate开发"));
51map.put("4",newBook("4","struts开发"));
52map.put("5",newBook("5","ajax开发"));
53}
54
55publicstaticMapgetAll(){
56returnmap;
57}
58}
59
60classBook{
61
62privateStringid;
63privateStringname;
64
65publicBook(){
66super();
67}
68publicBook(Stringid,Stringname){
69super();
70this.id=id;
71this.name=name;
72}
73publicStringgetId(){
74returnid;
75}
76publicvoidsetId(Stringid){
77this.id=id;
78}
79publicStringgetName(){
80returnname;
81}
82publicvoidsetName(Stringname){
83this.name=name;
84}
85}
复制代码
BuyServlet
复制代码
1packagexdp.gacl.session;
2
3importjava.io.IOException;
4importjava.util.ArrayList;
5importjava.util.List;
6importjavax.servlet.ServletException;
7importjavax.servlet.http.HttpServlet;
8importjavax.servlet.http.HttpServletRequest;
9importjavax.servlet.http.HttpServletResponse;
10importjavax.servlet.http.HttpSession;
11
12publicclassBuyServletextendsHttpServlet{
13
14publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
15throwsServletException,IOException{
16Stringid=request.getParameter("id");
17Bookbook=DB.getAll().get(id);//得到用户想买的书
18HttpSessionsession=request.getSession();
19Listlist=(List)session.getAttribute("list");//得到用户用于保存所有书的容器
20if(list==null){
21list=newArrayList();
22session.setAttribute("list",list);
23}
24list.add(book);
25//response.encodeRedirectURL(java.lang.Stringurl)用于对sendRedirect方法后的url地址进行重写
26Stringurl=response.encodeRedirectURL(request.getContextPath()+"/servlet/ListCartServlet");
27System.out.println(url);
28response.sendRedirect(url);
29}
30
31publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
32throwsServletException,IOException{
33doGet(request,response);
34}
35
36}
复制代码
ListCartServlet
复制代码
1packagexdp.gacl.session;
2
3importjava.io.IOException;
4importjava.io.PrintWriter;
5importjava.util.List;
6importjavax.servlet.ServletException;
7importjavax.servlet.http.HttpServlet;
8importjavax.servlet.http.HttpServletRequest;
9importjavax.servlet.http.HttpServletResponse;
10importjavax.servlet.http.HttpSession;
11
12publicclassListCartServletextendsHttpServlet{
13
14publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
15throwsServletException,IOException{
16response.setContentType("text/html;charset=UTF-8");
17PrintWriterout=response.getWriter();
18HttpSessionsession=request.getSession();
19Listlist=(List)session.getAttribute("list");
20if(list==null||list.size()==0){
21out.write("对不起,您还没有购买任何商品!!");
22return;
23}
24
25//显示用户买过的商品
26out.write("您买过如下商品: ");
27for(Bookbook:list){
28out.write(book.getName()+" ");
29}
30}
31
32publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
33throwsServletException,IOException{
34doGet(request,response);
35}
36}
复制代码
通过查看IndexServlet生成的html代码可以看到,每一个超链接后面都带上了session的Id,1本网站有如下书: javaweb开发购买
2spring开发购买
3hibernate开发购买
4struts开发购买
5ajax开发购买
所以,当浏览器禁用了cookie后,就可以用URL重写这种解决方案解决Session数据共享问题。而且response.encodeRedirectURL(java.lang.Stringurl)和response.encodeURL(java.lang.Stringurl)是两个非常智能的方法,当检测到浏览器没有禁用cookie时,那么就不进行URL重写了。我们在没有禁用cookie的火狐浏览器下访问,
浏览器第一次访问时,服务器创建Session,然后将Session的Id以Cookie的形式发送回给浏览器,response.encodeURL(java.lang.Stringurl)方法也将URL进行了重写,当点击刷新按钮第二次访问,由于火狐浏览器没有禁用cookie,所以第二次访问时带上了cookie,此时服务器就可以知道当前的客户端浏览器并没有禁用cookie,那么就通知response.encodeURL(java.lang.Stringurl)方法不用将URL进行重写了。
五、session对象的创建和销毁时机
5.1、session对象的创建时机
在程序中第一次调用request.getSession()方法时就会创建一个新的Session,可以用isNew()方法来判断Session是不是新创建的
范例:创建session
复制代码
1//使用request对象的getSession()获取session,如果session不存在则创建一个
2HttpSessionsession=request.getSession();
3//获取session的Id
4StringsessionId=session.getId();
5//判断session是不是新创建的
6if(session.isNew()){
7response.getWriter().print("session创建成功,session的id是:"+sessionId);
8}else{
9response.getWriter().print("服务器已经存在session,session的id是:"+sessionId);
10}
复制代码
5.2、session对象的销毁时机
session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间,例如:
复制代码
1
2 3xmlns="http://session.com/xml/ns/javaee"
4xmlns:xsi="http://2001/XMLSchema-instance"
5xsi:schemaLocation="http://www.wang027.com/xml/ns/javaee
6http://session.com/xml/ns/javaee/web-app_2_5.xsd">
7
8
9
10index.jsp
11
12
13
14
1515
16
17
18
复制代码
当需要在程序中手动设置Session失效时,可以手工调用session.invalidate方法,摧毁session。
1HttpSessionsession=request.getSession();
2//手工调用session.invalidate方法,摧毁session
3session.invalidate();
|
|