`
ericwzc
  • 浏览: 12039 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

HttpSession 是什么时候产生的?

    博客分类:
  • web
 
阅读更多

本文用实验来证明session在servlet和jsp技术是如何应用的。大家都知道session由容器产生和管理,那么是什么时候产生的呢?不用多说了,用代码来证明一切吧。

 

首先,我们创建一个sessionlistener 来跟踪每个session的轨迹。

 

public class MySessionListener implements HttpSessionListener {

	@Override
	public void sessionCreated(HttpSessionEvent arg0) {
		String id = arg0.getSession().getId();
		System.out.println("session with id " + id +" created");
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent arg0) {
		String id = arg0.getSession().getId();
		System.out.println("session with id " + id + "destroyed");
	}

}

 

修改web.xml使listerner生效

        <listener>
        	<listener-class>
        		org.eric.listeners.MySessionListener
        	</listener-class>
        </listener>

创建一个greet.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1" session="false"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Test Session</title>
</head>
<body>
	<a href="<%= response.encodeURL("/scwcd/greet.jsp") %>">request the same page again</a>
</body>
</html>

 

请注意,我的工程名叫scwcd, 为了看到效果,我们故意把jsp中session设为false, 因为默认是true的,也就是使用session.

现在我们清除浏览器的cookie,然后我们在firefox中打开firebug,选中net选项卡,然后发请求http://localhost/scwcd/greet.jsp

结果server端没有session with id... created 的输出,firebug 中response header中便找不到set-cookie, 如下

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 354
Date: Sat, 06 Apr 2013 06:52:31 GMT

 

这意味着server并没有开始我们的会话,换句话说server并不care我们究竟是谁,不管我们发多少次请求。

 

现在我们声明在server端使用session, 去掉session=“false”, 或者改session="true", 并且在浏览器端允许使用cookie. 再次发送请求,http://localhost/scwcd/greet.jsp, session真的出来了,

server端输出了,session with id 814E7FAFCEC4724831E1B3E5CAEF0096 created, 浏览器端查看reponse header, 如下

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=814E7FAFCEC4724831E1B3E5CAEF0096; Path=/scwcd/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 398
Date: Sat, 06 Apr 2013 06:57:06 GMT

 

我们的后面的请求都会带上cookie了,这样服务器就知道我们是谁了,不信?可以再发一次请求http://localhost/scwcd/greet.jsp,这次看request header, 发现红色的多出来了

 

GET /scwcd/greet.jsp HTTP/1.1
Host: localhost:8888
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: JSESSIONID=814E7FAFCEC4724831E1B3E5CAEF0096
Connection: keep-alive

 

Cookie 就是这样工作的,服务器端set-cookie之后,后面的每次请求都会加上cookie. 这样服务器端就知道他在跟谁对话了,这样就使得本来无状态的http协议变得似乎有状态了,cookie中的信息可以实现客户端与服务器端共享。然而,cookie不能滥用,其大小是有限制的,不能在里面放太多东西,当然仅仅放放我们的身份识别符sessionid还是绰绰有余了。

 

问题一, 如果上文中用的是servlet,而不是jsp会怎么样?

jsp归根到底是servlet,还是用实验来证明吧,创建servlet如下

 

public class MyServlet extends HttpServlet {

	public void init() {
		System.out.println("MyServlet initialized");
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		request.getSession();
         }
}

 

修改web.xml, 加入下面的内容

       <servlet>
            <servlet-name>MyServlet</servlet-name>
            <servlet-class>org.eric.MyServlet</servlet-class>
       </servlet>
        <servlet-mapping>
            <servlet-name>MyServlet</servlet-name>
            <url-pattern>/MyServlet</url-pattern>
        </servlet-mapping>

 

重新清除浏览器cookie, 发请求http://localhost/scwcd/MyServlet, 结果服务器端和客户端都显示session是被创建出来了。不难想到,服务器端得到我们的http请求, 其中自然可以获取jsessionid(不管是从querystring 获取还是cookie), 然后把根据这个id从容器维护的 session中找到对应的session对象。而getSession()这个方法如果找不到那个session对象,就会创建一个,并且告诉客户端对应的ID, 即jsessionid(请看问题二如有疑问). 对于我们清掉cookie后第一次请求,header中不包含cookie(jsessionid),浏览器无从知道我们还是老客户:),  所以就新建一个session来跟我们会话。

 

改改试试,上面的servlet 中改为request.getSession(false), 清掉浏览器cookie再发请求http://localhost/scwcd/MyServlet; 结果显示没有创建session. 因为getSession(false)方法如果找不到session对象,就返回null, 并不会新建session对象。

 

问题二, 听说如果浏览器禁用cookie,server端会修改url加上jsessionid, 来实现会话,那究竟是cookie呢还是先修改url呢, 即server端是如何知道浏览器端有没有禁用cookie的?

我们清掉浏览器端的cookie, 并且在浏览器禁用cookie, Firebug---Cookies---Deny cookies from localhost.

在greet.jsp改session=“true".  发请求http://localhost/scwcd/greet.jsp

response header, 结果 跟刚才一样, 包含set-cookie

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=1EFB388FE94172438DCC2B02378EE1DA; Path=/scwcd/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 398
Date: Sat, 06 Apr 2013 08:38:33 GMT

 

留心一下,返回的html页面,发现这行了吗?

<a href="/scwcd/greet.jsp;jsessionid=1EFB388FE94172438DCC2B02378EE1DA">request the same page again</a>

 

哈哈,服务器第一次应答就两招都用了,既设了cookie,又url上面加了jessionid.

点击那个request the same page again, 重新查看response Header,

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 398
Date: Sat, 06 Apr 2013 08:43:04 GMT

 

发现不同了吗,这次没有set-cookie 的header, 显然服务器已经知道了我们的浏览器不支持cookie,因为我们的这次请求中没有带cookie Header, 如下

GET /scwcd/greet.jsp;jsessionid=1EFB388FE94172438DCC2B02378EE1DA HTTP/1.1
Host: localhost:8888
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:8888/scwcd/greet.jsp
Connection: keep-alive

 

因为网站总是从一个页面通过连接导航到其他页面,所以服务器很容易通过两次请求判断出客户端是否支持cookie.

如果我们总是在禁用cookie的情况下,总是发相同的请求localhost:8888/scwcd/greet.jsp, 那服务器就每次都创建一个新session了, 例如连发两次请求,会看到server 端有这样的输出

session with id 38704BBDADF2288B06A1EA1A2FE65444 created
session with id 1EF1F1E07A1CBEEE23848E83AE63794B created

 

问题三:

关闭浏览器窗口,为什么原来的session 不见了?

改一下上面的servlet代码,

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		request.getSession();
		Cookie[] cks = request.getCookies();
		if (cks != null) {
			for (Cookie ck : cks) {
				if(ck.getName().equalsIgnoreCase("JSESSIONID")){
					System.out.println(ck.getMaxAge());
				}				
			}
		} 

	}

 

重新启用浏览器cookie, 清掉浏览器cookie,第一次请求http://localhost/scwcd/MyServlet 显示session with id 968AA6D2D673ED67A06ECA2B3F054644 created, 第二次请求相同的地址的时候发现maxage

输出结果为-1. 查一下Cookie的Javadoc就会发现原因

getMaxAge()
          Returns the maximum age of the cookie, specified in seconds, By default, -1 indicating the cookie will persist until browser shutdown.

  

如果想关掉浏览器后jsessionid 存在怎么办,很简单,我们自己改cookie即可,

		HttpSession session = request.getSession();
		if(session.isNew()){
			Cookie c = new Cookie("JSESSIONID", session.getId());
			c.setMaxAge(20 * 60);
			response.addCookie(c);
		}

 

 在servlet 3.0中就更便捷,直接改web.xml 即可

 

    <session-config>  
        <session-timeout>525600</session-timeout>   
        <cookie-config>  
            <max-age>31536000</max-age>  
        </cookie-config>  
    </session-config> 
 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics