`

jsp_cookies_转转转

    博客分类:
  • java
阅读更多

JSP和Servlet中的Cookie

文章分类:Web前端

一、JSPServlet 中的Cookie  

    
由于HTTP 协议是无状态协议(虽然Socket 连接是有状态的,但每次用HTTP 协议进行数据传输后就关闭的Socket 连接,因此,HTTP 协议并不会保存上一次的状态),因此,如果要保存某些HTTP 请求过程中所产生的数据,就必须要有一种类似全局变量的机制保证数据在不同的HTTP 请求之间共享。这就是下面要讲的SessionCookie


    Cookie
是通过将数据保存在客户端的硬盘 (永久Cookie )或内存 (临时Cookie )中来实现数据共享的一种机制。在Windows 下,保存在这些Cookie 数据的目录一般是C:\Documents and Settings\Administrator\Cookies 。每一个Cookie 有一个超时时间,如果超过了这个时间,Cookie 将自动失效。可按如下方法来设置Cookie 的超时时间:

    
Cookie cookie = 
new
 Cookie("key","value");
cookie.setMaxAge(3600);  

// Cookie
的超时间为3600
秒,也就是1
小时
    
response.addCookie(cookie);
 

如果不使用setMaxAge 方法,Cookie 的超时时间为-1 ,在这种情况下,Cookie 就是临时Cookie ,也就是说这种Cookie 实际上并不保存在客户端硬盘上,而是保存在客户端内存中的。读者可以在JSP 中运行如下代码,看看是否会在上面提到的保存cookie 的目录中生成cookie 文件:

 
Cookie cookie = 
new
 Cookie("key","value");
response.addCookie(cookie);
 

实际上使用setMaxAge 将超时时间设为任意的负数都会被客户端浏览器认为是临时

Cookie ,如下面的代码将在客户端内存中保存一个临时Cookie

Cookie cookie = 
new
 Cookie("key","value");
cookie.setMaxAge(-100);  

// 
cookie
设为临时Cookie

    
response.addCookie(cookie);
 

如果第一次将Cookie 写入客户端(不管是硬盘还是内存),在同一台机器上第二次访问

该网站的jsp 页面时,会自动将客户端的cookie 作为HTTP 请求头的Cookie 字段值传给服务端,如果有多个Cookie ,中间用";" 隔开。如下面的HTTP 请求头所示:

 

GET /test/First.jsp HTTP/1.1

HOST:localhost

...

Cookie:key1=value1;key2=value2

...

...

    
我们可以在JSP 中使用如下的Java 代码来输出Cookie 字段的值:

     out.println(request.getHeader("Cookie"));

 

如果在Servlet 中输出,必须得使用如下语句得到out ,才能向客户端浏览器输出数据:


       PrintWriter out = response.getWriter();

    
虽然永久Cookie 和临时Cookie 在第二次向服务端发出HTTP 请求时生成Cookie 字段,但它们还是有一定的区别的。永久Cookie 在任意新开启的IE 窗口都可以生成Cookie 。而临时Cookie 由于只保存在当前IE 窗口,因此,在新开启的IE 窗口,是不能生成Cookie 字段的,也就是说,新窗口和旧窗口是不能共享临时Cookie 的。使用重定向机制弹出的新窗口也无法和旧窗口共享临时Cookie 。但在同一个窗口可以。如在一个IE 窗口输入http://localhost:8080/test/first.jsp ,向内存写入一个临时Cookie 后,在同一个IE 窗口输入http://localhost:8080/test/second.jsp ,浏览器在向服务端发送HTTP 请求时,自动将当前浏览器的临时Cookie( 也就是first.jsp 所创建的Cookie) 和永久Cookie 作为HTTP 请求头的Cookie 字段值发送给服务端。但是如果新启一个IE 窗口,由于新IE 窗口没有这个临时Cookie ,因此,second.jsp 只发送了保存在硬盘上的永久Cookie

 

二、Tomcat 中的ServletSession

    
由于Cookie 数存在保存在客户端,这样对于一些敏感数据会带来一些风险。而且Cookie 一般只能保存字符串等简单数据。并且大小限制在4KB 。如果要保存比较复杂的数据,Cookie 可能显得有些不合适。基于这些原因,我们自然会想到在服务端采用这种类似Cookie 的机制来存储 数据。这就是我们这节要讲的会话(Session) 。而在一个客户端和服务端的会话中所有的页面可以共享为这个会话所建立的Session

    
那么什么是会话呢?有很多人认为会话就是在一台机器上客户端浏览器访问某个域名所指向的服务端程序,就建立了一个客户端到服务端的会话。然后关闭客户端浏览器,会话就结束。其实这并不准确。


    
首先让我们先来看看Session 的原理。SessionCookie 类似。所不同的是它是建立在服务端的对象。每一个Session 对象一个会话。也许很多读者看到这会有一个疑问。Session 是如何同客户端联系在一起的呢?很多人在使用Session 时并没有感觉到这一点。其实这一切都是Web服务器 ,如Tomcat 一手包办的。那么Web服务器 又是如何识别通过HTTP 协议进行连接的客户端的呢?这就要用到第一节中所讲的Cookie 。在一般情况下,Session 使用了临时Cookie 来识别某一个Session 是否属于某一个会话。在本文中以Tomcat 为例来说明Session 是如何工作的。

    
让我们先假设某一个客户端第一次访问一个Servlet ,在这个Servlet 中使用了getSession 来得到一个Session 对象,也就是建立了一个会话,这个Servlet 的代码如下:

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public
 
class
 First extends HttpServlet
{
public
 
void
 doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html");
HttpSession session = request.getSession();
session.setAttribute("key", "mySessionValue");
PrintWriter 
out
 = response.getWriter();
out
.println("The session has been generated!");
out
.flush();
out
.close();
}
}
 

对于服务端的First 来说,getSession 方法主要做了两件事:

    1.  从客户端的HTTP 请求头的Cookie 字段中获得一个寻找一个JSESSIONIDkey ,这个key 的值是一个唯一字符串,类似于D5A5C79F3C8E8653BC8B4F0860BFDBCD 

    
2. 
如果Cookie 中包含这个JSESSIONID ,将key 的值取出,在TomcatSession Map (用于保存Tomcat 自启动以来的所有创建的Session )中查找,如果找到,将这个Session 取出,如果未找到,创建一个HttpSession 对象,并保存在Session Map 中,以便下一次使用这个Key 来获得这个Session

 

在服务器向客户端发送响应信息时,如果是新创建的HttpSession 对象,在响应HTTP

头中加了一个Set-Cookie 字段,并将JSESSIONID 和相应的值反回给客户端。如下面的HTTP 响应头:

 

HTTP/1.1 200 OK

...

Set-Cookie: JSESSIONID=D5A5C79F3C8E8653BC8B4F0860BFDBCD

...


    
对于客户端浏览器来说,并不认识哪个Cookie 是用于Session 的,它只是将相应的临时Cookie 和永久Cookie 原封不动地放到请求HTTP 头的Cookie 字段中,发送给服务器。如果在IE 中首次访问服务端的First ,这时在当前IE 窗口并没有临时Cookie ,因此,在请求HTTP 头中就没有Cookie 字段,所以First 在调用getSession 方法时就未找到JSESSIONID ,因此,就会新建一个HttpSession 对象。并在Set-Cookie 中将这个JSESSIONID 返回。接下来我们使用另外一个ServletSecond 来获得在First 中所设置的Session 数据。Second 的代码如下:

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public
 
class
 Second extends HttpServlet
{
public
 
void
 doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html");
HttpSession session = request.getSession();
PrintWriter 
out
 = response.getWriter();
out
.println(session.getAttribute("key"));
out
.flush();
out
.close();
}
}
 

      如果在同一个窗口来调用Second 。这时客户端已经有了一个临时Cookie ,就是JSESSIONID ,因此,会将这个Cookie 放到HTTP 头的Cookie 字段中发送给服务端。服务端在收到这个HTTP 请求时就可以从Cookie 中得到JSESSIONID 的值,并从Session Map 中找到这个Session 对象,也就是getSession 方法的返回值。因此, 从技术层面上来说,所有拥有同一个Session ID 的页面都应该属于同一个会话。

    
如果我们在一个新的IE 窗口调用Second ,并不会得到mySessionValue 。因为这时SecondFirst 拥有了不同的Session ID ,因此,它们并不属于同一个会话。讲到这,也许很多读者眼前一亮。既然拥有同一个Session ID ,就可以共享Session 对象,那么我们可不可以使用永久Cookie 将这个Session ID 保存在Cookie 文件中,这样就算在新的IE 窗口,也可以共享Session 对象了。答案是肯定的。下面是新的First 代码:

 

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public
 
class
 First extends HttpServlet
{
public
 
void
 doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html");
HttpSession session = request.getSession();
session.setMaxInactiveInterval(3600);
Cookie cookie = 
new
 Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(3600);
response.addCookie(cookie);
session.setAttribute("key", "mySessionValue");
PrintWriter 
out
 = response.getWriter();
out
.println("The session has been generated!");
out
.flush();
out
.close();
}
}
 

在上面的代码中使用了Cookie 对象将JSESSIONID 写入了Cookie 文件,并使用setMaxAge 方法将Cookie 超时时间设为3600 秒(1 小时)。这样只要访问过First ,从访问时间算起,在1 小时之内,在本机的任何IE 窗口调用Second 都会得到"mySessionValue" 字符串。

 

三三、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 方法,在方法的开始部分首先建立了sessionapplicationout 等对象实例。然后将MyJSP.jsp 中的HTML 通过out 输出到客户端。我们要注意上面的黑体字的语句:out.println(session.getId()); JSP 编译器自动将JSP 中的<% ... %> 中包含的Java 代码原封不动地插入到_jspService 中。由于是在创建对象实例后插入,因此,就可以直接使用sessionout 等对象了。

    
如果我们想做进一步的实验,可以直接使用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.13tomcat 的安装目录,读者可以将其设为自己的机器上的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) 
tomcatcookie 支持关闭


如果我们只想使用url 来支持session ,可以直接将tomcatcookie 功能关闭。我们可

以修改conf 中的context.xml 文件,加入一个cookies="false" 即可,内容如下:

<!-- The contents of this file will be loaded for each web application -->

<Context cookies = "false">

... ...

... ...

</Context>

    
重启tomcat 后,就算客户端支持cookietomcat 也不会考虑HTT

分享到:
评论

相关推荐

    Java_Servlet_And_JSP_Cookbook.rar

    此外,实战部分可能会涵盖常见问题的解决方案,如处理表单提交、文件上传下载、会话管理、cookies的应用,以及与数据库的交互,如使用JDBC进行数据访问。还有可能讨论到Spring MVC框架,它是Java Web开发中的主流...

    JSP源码 泉城JSP播客系统_video.rar

    【标题】"JSP源码 泉城JSP播客系统_video.rar" 指的是一份基于JSP技术开发的播客系统源代码。播客系统是一种在线视频分享平台,用户可以上传、观看和分享视频内容。在这个系统中,JSP(JavaServer Pages)作为服务器...

    w3school_Java&JSP;教程

    **JSPCookies处理** Cookies 用于存储客户端的状态信息,如登录状态、用户偏好等。 **JSPSession** Session 对象用于跨多个页面维护用户的状态信息。 **JSP文件上传** 处理文件上传涉及到接收来自客户端的文件...

    jsp九大内置对象讲解

    JSP九大内置对象详解 JSP(Java Server Pages)是一种基于Java技术的服务器端编程语言,用于创建动态网页。JSP九大内置对象是JSP技术中非常重要的一部分,它们是JSP引擎提供的一些预定义的对象,用于帮助开发者快速...

    JSP实现留言板功能

    这需要在JSP页面中进行权限判断,可能涉及会话(session)管理和cookies。 8. **Servlet与JSP分离** 为了提高代码可维护性和遵循MVC(Model-View-Controller)设计模式,通常将业务逻辑(Model)和视图(View)...

    JSP小项目源码汇总.rar

    5. 实践文件上传下载、会话管理、cookies等Web开发常见功能。 6. 学习如何调试和优化JSP程序。 总之,"JSP小项目源码汇总"是一份宝贵的教育资源,对于希望提升Java Web技能的新手来说,它是深入实践和理论学习的...

    jsp经典面试题!!!

    12、如果 BROWSER 已关闭了 COOKIES,在 JSP 中我如何打开SESSION 来跟踪? 可以使用URL重写来跟踪会话,例如:&lt;%@ page session="true" %&gt; (100); session.putValue("num",num); String url =response.encodeUrl(...

    applet与jsp的交互

    3. **利用cookies**:Applet和JSP可以通过设置和读取cookies来共享数据。Applet可以设置cookies,然后JSP在处理请求时读取这些cookies。 4. **使用URLConnection**:Applet可以通过`URLConnection`打开与JSP的连接...

    JSP购物网站代码JSP购物网站代码

    【JSP购物网站代码详解】 JSP(JavaServer Pages)是一种基于Java技术的服务器端脚本语言,用于创建动态网页。在"JSP购物网站代码"这个项目中,我们可以深入理解如何利用JSP来构建一个功能完备的在线购物平台。JSP...

    JSP实现的网页特效(很多)

    9. **cookies和session管理**:JSP可以方便地读取、设置、删除cookies,以及管理session,用于跟踪用户状态和个性化设置。 10. **图表展示**:通过集成像JFreeChart这样的库,JSP能够生成各种统计图表,帮助用户...

    JSP基础札记笔记

    - **读取Cookie**:通过`request.getCookies()`方法获取客户端发送过来的所有Cookie。 #### 第六讲:内置对象--out、pageContext - **out对象**:用于输出文本到客户端。 - **pageContext对象**:提供了一个统一的...

    关于jsp语法和练习

    JSP中,要获取HttpServletRequest对象中的所有Cookie,应使用`request.getCookies()`方法。这个方法返回一个Cookie数组,包含了请求中携带的所有Cookie。 2. **创建JavaBean**: 在JSP中使用`jsp:useBean`标签来...

    JSP源码包.rar

    6. **CHAPTER10.rar** - 可能是关于第十章的实例,可能包括了会话跟踪、cookies的使用,以及用户认证和授权的实现。 7. **CHAPTER06.rar** - 可能是第六章的代码,可能讲解了JSP与EJB(Enterprise JavaBeans)的...

    登录模块代码JSP+MySQL

    Cookie[] c = request.getCookies(); for (int i = 0; i ; i++) { if ("username".equals(c[i].getName())) { C_username = c[i].getValue(); } if ("password".equals(c[i].getName())) { C_password = c[i]....

    JSP从入门到精通 (适合初学者)

    4. **会话管理**:利用Cookies和Session管理用户会话状态。 5. **错误处理**:设计错误页面,处理异常情况。 #### 六、进阶话题 1. **MVC架构**:学习如何使用Model-View-Controller模式构建应用程序。 2. **框架...

    Servlet和JSP技术简述(英文翻译)

    【Servlet和JSP技术概述】 Servlet和JSP(JavaServer Pages)是Java平台上的两种核心技术,主要用于构建动态Web应用程序。它们在Web开发中的角色至关重要,尤其在处理客户端请求和生成响应方面。以下是对Servlet和...

    jsp基础速成精华讲解

    读取Cookie时,可以使用`request.getCookies()`获取所有的Cookie对象。 ```java Cookie cookie = new Cookie("name", "zhangsan"); cookie.setMaxAge(24 * 60 * 60); // 设置有效期为24小时 response.addCookie...

    servlet/jsp深入详解源代码

    `ch06`可能涉及请求和响应对象,`ch07`可能讲解了会话管理和cookies;`ch10`和`ch11`可能涉及到了Servlet的过滤器和监听器;`ch12`可能涵盖了JSP的基础语法;`ch15`至`ch19`可能讲解了更高级的主题,如EL...

    网上书店 JSP做的

    可以通过session来跟踪用户状态,使用cookies存储用户登录信息。同时,应确保敏感操作(如支付、修改个人信息)只能由已认证用户执行。 **7. 页面跳转** 在JSP中,可以使用`response.sendRedirect()`或`request....

Global site tag (gtag.js) - Google Analytics