Tomcat之Session和Cookie大揭密(二)

本文探讨了Tomcat环境下JSP与Session的工作原理,包括JSP如何编译为Servlet、Session对象的自动创建机制及其与Servlet的区别。此外,还介绍了通过URL传递SessionID、关闭Cookie支持以及在IE中控制Cookie的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
三、Tomcat中的JSPSession

   
从本质上讲,JSP在运行时已经被编译成相应的Servlet了,因此,在JSPServletSession的使用方法应该差不多。但还是有一些细小的差别。

   
如果我们使用过JSP就会发现,在JSP中很多对象是不需要创建的,如outsession等。它们可以直接使用。如下面的JSP代码所示:

<!-- MyJSP.jsp -->

<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <!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=GB18030"> <title>Insert title here</title> </head> <body> <% out.println(session.getId()); %> </body> </html>
    在上面的JSP代码中直接使用了outsession。而并不象Servlet里一样用get方法来获得相应的对象实例。那么这是为什么呢?

   
由于JSP在第一次运行时是被编译成Servlet的,我们自然就会想到有可能是在编译JSP时自动创建了sessionout对象。下面我们就来验证这一点。首先需要查看一下JSP被编译成Servlet后的源代码。这非常简单,如果我们使用的是Tomcat,只需要在Tomcat的安装目录中的work中找相应的源程序即可。如一个名为MyJSP.jsp的文件首先被编译成MyJSP_jsp.java(这就是由JSP生成的Servlet源程序文件),然后再由javaMyJSP_jsp.java编译成MyJSP_jsp.class,最后Tomcat运行的就是MyJSP_jsp.class。如上面的JSP程序被编译成Servlet的部分源代码如下:

package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class MyJSP_jsp extends org.apache.jasper.runtime.HttpJspBase { ... ... ... ... public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { response.setContentType("text/html; charset=GB18030"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("/r/n"); out.write("<!DOCTYPE html PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/" /"http://www.w3.org/TR/html4/loose.dtd/">/r/n"); out.write("<html>/r/n"); out.write("/t<head>/r/n"); out.write("/t/t<meta http-equiv=/"Content-Type/" content=/"text/html; charset=GB18030/">/r/n"); out.write("/t/t<title>Insert title here</title>/r/n"); out.write("/t</head>/r/n"); out.write("/t<body>/r/n"); out.write("/t/t"); out.println(session.getId()); out.write("/r/n"); out.write("/r/n"); out.write("/t</body>/r/n"); out.write("</html>"); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
    我们可以看到上面的代码中的_jspService方法类似于HttpServlet中的service方法,在方法的开始部分首先建立了session、application、out等对象实例。然后将MyJSP.jsp中的HTML通过out输出到客户端。我们要注意上面的黑体字的语句:out.println(session.getId());JSP编译器自动将JSP中的<% ... %>中包含的Java代码原封不动地插入到_jspService中。由于是在创建对象实例后插入,因此,就可以直接使用session、out等对象了。

    如果我们想做进一步的实验,可以直接使用javac来编译MyJSP_jsp.java,为了方便其间,首先建立一个c.cmd文件,它的内容如下:
 
javac -classpath
D:/tools/apache-tomcat-6.0.13/lib/servlet-api.jar;D:/tools/apache-tomcat-6.0.13/lib/jsp-api.jar;D:/tools/apache-tomcat-6.0.13/lib/annotations-api.jar;D:/tools/apache-tomcat-6.0.13/lib/catalina.jar;D:/tools/apache-tomcat-6.0.13/lib/jasper.jar;D:/tools/apache-tomcat-6.0.13/lib/el-api.jar %1

    其中D:/tools/apache-tomcat-6.0.13是tomcat的安装目录,读者可以将其设为自己的机器上的tomcat安装目录

    在编译时可直接使用c  MyJSP_jsp.java进行编译,这时tomcat就直接运行我们编译生成的MyJSP_jsp.class了。

    从上面的代码我们还可以了解一点,在JSP无论使用还是不使用session,都会使用getSession方法创建一个Session对象,而Servlet必须显式地调用才会建立Session对象。

注:通过直接编译java文件运行jsp,需要清除一下tomcat的缓存,一般需要重启一下tomcat
四、随心所欲使用Session

(1) 使用url传递session id

    在上面讲过,在默认情况下session是依靠客户端的cookie来实现的。但如果客户端浏览器不支持cookie或将cookie功能关闭,那就就意味着无法通过cookie来实现session了。在这种情况下,我们还可以有另一种选择,就是通过url来传递session id。

    对于Tomcat来说,需要使用jsessionid作为key来传递session id。但具体如何传呢?可能有很多人认为会是如下的格式:

http://localhost:8080/test/MyJSP.jsp?jsessionid= D5A5C79F3C8E8653BC8B4F0860BFDBCD

    但实验上面的url并不好使。其实最直接的方法我们可以看一下Tomcat的源程序是如何写的,首先下载tomcat的源程序,然后找到CoyoteAdapter.java文件,并打开。在其中找到parseSessionId方法,这个方法是用来从url中提取Session id的。我们可以不必了解这个方法的全部代码,只看一下开头就可以。代码片段如下:

     ByteChunk uriBC = req.requestURI().getByteChunk();
     int semicolon = uriBC.indexOf(match, 0, match.length(), 0);
     if (semicolon > 0) {...}

    上面代码中的uriBC就是请求的url,第二行在这个url中查找match字符串,再在CoyoteAdapter.java中查找一个match字符串,match变量的初值如下:

    private static final String match =
        ";" + Globals. SESSION_PARAMETER_NAME + "=";

    从上面代码可以看出,match开头是一个";"字符,而SESSION_PARAMETER_NAME是一个常量,值就是"jsessionid",因此可以断定,MyJSP.jsp后跟的是";",并不是"?",因此,正确的url如下:
 
http://localhost:8080/test/MyJSP.jsp;jsessionid= D5A5C79F3C8E8653BC8B4F0860BFDBCD

    通过使用上述方法甚至可以在不同的机器上获得同一个session对象。

    在CoyoteAdapter.java文件中还有一个parseSessionCookiesId方法,这个方法将从HTTP请求头中提取session id。我们中postParseRequest方法中可以看到将调用的parseSessionId方法,在最后调用了parseSessionCookiesId方法,因此,我们可以断定,tomcat将考虑url中的session id,然后再读取Cookie字段中的session id。还有就是在postParseRequest方法的最后部分有一个response.sendRedirect(redirectPath);,在调完它后,就直接return了。而没有执行到parseSessionCookiesId,因此,使用重定向并不能通过HTTP头的cookie字段共享session。只能通过url来传递session id。

(2) 将tomcat的cookie支持关闭

如果我们只想使用url来支持session,可以直接将tomcat的cookie功能关闭。我们可
以修改conf中的context.xml文件,加入一个cookies="false"即可,内容如下:

<!-- The contents of this file will be loaded for each web application -->
<Context cookies = "false">
... ...
... ...
</Context>

   
重启tomcat后,就算客户端支持cookietomcat也不会考虑HTTP请求头的cookie字段。


(3) 
IE中控制Cookie

   
IE中也可以将Cookie关闭,启动IE,在工具->Internet选项->稳私->高级中选中"覆盖自动cookie处理"选项。并按图1选择:




                                   图1

    对于下面的选项"总是允许会话cookie",如果不选,在本机将允许会话cookie,也就是通过localhost访问,在远程将不允许会话cookie。我们也可以通过在工具->Internet选项->稳私->站点来对某个网站来允许和拒绝cookie。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值