您的位置:首页 > 其它

Servlet基础_0400_Session 原理探究

2011-09-28 20:27 423 查看
本文讨论Session

一.Session 是什么?

Session是服务器端的一片内存,能够往里面搁任何数据;Session的name必须是字符串,值可以是任何对象

二.Session的实现原理:

Session的实现方式有俩种:(企业常问)

a.如果客户端支持Cookie,则Session通过Cookie实现,将SessionId保存在Cookie里

b.如果客户端不支持Cookie,则必须通过编程实现,重写URL(encodingURL()方法)

a种实现方式:将sessionId存入Cookie,且存入临时的Cookie, 不需要设置时间,当浏览器关闭时,这个存有sessionId的Cookie立即消失,因为窗口关了,再也不会去访问这个Session了

b种实现方式:通过response.encodingURL()实现,即在每个需要使用Session的页面里的超链接都加上response.encodingURL("urlString");[encodingURL()的作用有两个,一个是转码,另一个是在url后面加上sessionID]

下面针对这两种实现方式做实验:

实验a.默认Cookie启用

//SessionInfoServlet.java

package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

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 SessionInfoServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter pw = response.getWriter();

HttpSession session = request.getSession(true);
pw.println("Session Information:"+"<br />");
pw.println("New Session:"+session.isNew()+"<br />");
pw.println("SessionId:"+session.getId()+"<br />");
pw.println("Session created time:"+new Date(session.getCreationTime())+"<br />");
pw.println("Session last access time:"+new Date(session.getLastAccessedTime())+"<br /><br />");

pw.println("Request Information:"+"<br />");
pw.println("SessionID from request:"+request.getAttribute("JSESSIONID")+"<br />");
pw.println("Session via Cookie:"+request.isRequestedSessionIdFromCookie()+"<br />");
pw.println("Session via written URL:"+request.isRequestedSessionIdFromUrl()+"<br />");
pw.println("Valid Session:"+request.isRequestedSessionIdValid()+"<br />");
pw.println("<a href='ShowCookies'>Show ALL Cookies</a>"+"<br />");
pw.println("<a href='"+response.encodeURL("SessionInfoServlet")+"'>refresh</a>");

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}

}


//ShowCookies.java

package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ShowCookies extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter pw = response.getWriter();
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for(int i=0;i<cookies.length;i++){
pw.println(cookies[i].getName()+"  :  "+cookies[i].getValue()+"<br />");
}
}else{
pw.println("没有Cookie!");
}

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}

}

1.配置好这两个页面,先确定浏览器的Cookie能够使用;然后访问SessionInfoServlet页面,输出如下内容:

Session Information:

New Session:true

SessionId:21BF726DBA2132F44A0514EA90DCAB66

Session created time:Wed Sep 28 20:43:04 CST 2011

Session last access time:Wed Sep 28 20:43:04 CST 2011

Request Information:

SessionID from request:null

Session via Cookie:false

Session via written URL:false

Valid Session:false

Show ALL Cookies[超链接]

refresh[超链接]

2.然后再次刷新,输出如下内容:

Session Information:

New Session:false

SessionId:21BF726DBA2132F44A0514EA90DCAB66

Session created time:Wed Sep 28 20:43:04 CST 2011

Session last access time:Wed Sep 28 20:43:04 CST 2011

Request Information:

SessionID from request:null

Session via Cookie:true

Session via written URL:false

Valid Session:true

Show ALL Cookies[超链接]

refresh[超链接]

3.以后再刷新,SessionID不变了,只有last access time变化了,其他的所有值都不变化了,session生效了,然后点击Show ALL Cookies,发现:

JSESSIONID : 21BF726DBA2132F44A0514EA90DCAB66

存在一个Cookie;说明了如果客户端没有禁用Cookie的话,Session直接以Cookie为基础实现,当在服务器端创建好一个Session后,服务器会为每隔浏览器指定一个SessionID,然后存在客户端的临时Cookie中,当客户端再次访问服务器时,服务器会验证客户端的SessionID,以找到原来的那个Session,这样就实现了Session

实验b.将Cookie禁用

1.先禁用Cookie(此功能必须要浏览器支持,这个实验跟浏览器有关,有的浏览器是禁不掉Cookie的,我用的是Opera[IE8,FireFox,Chrom好像都不行])

2.访问SessionInfoServlet页面,输出如下内容:

Session Information:

New Session:true

SessionId:7FA232B7C56545ABA6ADE42CE58665EC

Session created time:Wed Sep 28 20:55:55 CST 2011

Session last access time:Wed Sep 28 20:55:55 CST 2011

Request Information:

SessionID from request:null

Session via Cookie:false

Session via written URL:false

Valid Session:false

Show ALL Cookies[超链接]

refresh[超链接]

3.然后刷新,发现其内容的SessionID变化了:

Session Information:

New Session:true

SessionId:35247C4D2BC096F5C76122EA16DA9CBE

Session created time:Wed Sep 28 20:57:13 CST 2011

Session last access time:Wed Sep 28 20:57:13 CST 2011

Request Information:

SessionID from request:null

Session via Cookie:false

Session via written URL:false

Valid Session:false

Show ALL Cookies

refresh

而且不断刷新,不断变化,此时的Session功能没法用,也就是说在禁用Cookie的情况下,Session功能是没有办法基于Cookie实现的,那么怎么解决呢?

重写URL,在每一个超链接上都加上response.encodingURL("url");例如例子中的refresh,点击,发现超链接:http://localhost:8080/Servlet_0400_Session/servlet/SessionInfoServlet;jsessionid=35247C4D2BC096F5C76122EA16DA9CBE
后面跟了一个jsessionid=.....;这样同样能将SessionID传个服务器,服务器同样能找到那个Session,Session功能也就实现了。

总结:既然两种情况下都能实现Session,那么究竟使用那种方式实现呢?

在时间紧急的情况下,我们可以默认客户端的Cookie是启用的,很多大型的公司就这么干的,例如新浪等,你客户端就应该开开Cookie,不然我们写程序还不得累死?只有当你们开开了Cookie才能使用我们的服务;当然,时间充足的情况下,让程序更加健壮,更加完美,也也要加上response.encodingURL(".."),许多著名公司就是这么干的,每个需要使用Session页面的URL都添加上了,例如微软,sun,oracle等等。

三.Session和Cookie的区别和联系:

1.Session是存在服务器端的,大部分的Session应用是基于Cookie的,Session里面能够存放任何数据,Session能被一个浏览器的多个标签,多个页面共享,也能被子窗口共享,但不能被新的浏览器共享,因为这个临时的Cookie只存在与当前浏览器的内存中,而新的浏览器是不共用同一部分内存的

2.Cookie是客户端的一个文本文件,也有可能是浏览器内存的临时Cookie[不会写入文件],写入文件的Cookie能够被多个浏览器共享,且它存在一个过期时间,到期后会自动清除,它一般用于2周内自动登录之类的功能

3.Session不存在路径的问题,他能被同一个web应用程序任何页面使用;而Cookie存在路径问题,servlet/jsp只能访问它同一级路径或者其子路径

四.探讨Session为什么不存在路径问题[只讨论基于Cookie实现的Session功能]

由于Session是基于Cookie实现的,服务器只有拿到从客户端传来的SessionID才能找到那个Session,那么现在Cookie存在一个路径问题,我假设这个servlet/jsp在父路径下,岂不是访问不到Cookie,那么也就拿不到那个SessionID,Session功能岂不是实现不了?

下面我们来做一个实验:

1.将web.xml修改成如下内容://将SessionInfoServlet的路径放入servlet下,而ShowCookies放到父路径下,为了让ShowCookies访问不到那个Cookie

<?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"> 
<servlet>
<servlet-name>SessionInfoServlet</servlet-name>
<servlet-class>com.servlet.SessionInfoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionInfoServlet</servlet-name>
<url-pattern>/servlet/SessionInfoServlet</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>ShowCookies</servlet-name>
<servlet-class>com.servlet.ShowCookies</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowCookies</servlet-name>
<url-pattern>/ShowCookies</url-pattern>
</servlet-mapping>

</web-app>
2.先保证Cookie启用,访问http://localhost:8080/Servlet_0400_Session/servlet/SessionInfoServlet,然后访问 http://localhost:8080/Servlet_0400_Session/ShowCookies
,发现页面输出了:JSESSIONID : 21BF726DBA2132F44A0514EA90DCAB66,这个sessionID还是访问到了,也就是说服务器还是拿到了那个SessionID,难道这个Cookie不是存在servlet路径下,打开Cookie管理器,发现确实这个Cookie没有存在servlet子路径下,而是直接存在根目录下,原来如此,虽然SessionID是基于Cookie实现的,但他并不基于Cookie的路径,而是直接将其保存在根目录下[当然是在内存中]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: