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

JSP和Servlet中的Cookie

阅读更多

一、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

分享到:
评论

相关推荐

    jsp+servlet+Cookie实现记住密码功能

    开发者可能在JSP中定义了登录表单,在Servlet中实现了验证和Cookie操作,在CSS和JS中处理了页面的样式和交互。 总之,通过JSP、Servlet和Cookie的组合,开发者可以创建一个具备记住密码功能的登录系统,提高用户的...

    servlet中的Cookie的使用

    因此,应避免在Cookie中存储敏感信息,使用HTTPS协议确保通信安全,并定期更新Cookie的值以防止会话固定攻击。 总结,本示例通过Servlet和Cookie展示了如何在Java Web应用中实现用户登录信息的持久化,以实现自动...

    Jsp+Servlet+Cookie实现记住密码,自动登录,防止表单提交,记录登录次数

    当用户再次访问网站且Cookie存在时,服务器可以解析Cookie中的信息,验证其有效性,然后直接登录用户,而无需用户再次输入凭证。这通常涉及一个后端服务,例如Servlet,它接收请求,解析Cookie数据,与数据库中的...

    jsp和servlet之中的session详细介绍

    本文将深入探讨JSP和Servlet中的session概念,以及它们如何在Web应用程序中实现状态管理。HTTP协议本身是无状态的,这意味着每次客户端(浏览器)向服务器发送请求时,服务器无法识别请求是否来自同一个会话。为了...

    林学良Jsp&Servlet学习笔记

    **JSP(Java Server Pages)与Servlet是Java Web开发中的两个核心技术,它们在构建动态网页和处理客户端请求方面起着至关重要的作用。** **JSP技术:** JSP是一种服务器端脚本语言,用于创建动态网页。它允许开发者...

    jsp+servlet+javabean实现网上商城项目完整源码

    《基于JSP、Servlet和JavaBean的网上商城项目详解》 网上商城项目是现代电子商务的重要组成部分,它将传统的购物体验与互联网技术相结合,为用户提供便捷的在线购物平台。本项目利用JSP、Servlet和JavaBean技术实现...

    基于jsp,servlet技术开发的博客系统

    在IT领域,Java Server Pages(JSP)和Servlet是Web应用程序开发中的核心技术,它们被广泛用于构建动态、交互式的Web应用程序,如博客系统。JSP和Servlet的结合使用可以实现视图与控制逻辑的分离,提高代码的可维护...

    基于JSP+Servlet图书管理系统

    在JSP+Servlet架构中,Model表示业务逻辑和数据模型,View是用户界面,Controller是Servlet,负责协调Model和View。图书管理系统遵循此模式,使得代码结构清晰,易于维护。 6. **JDBC(Java Database Connectivity...

    jsp和servlet知识点总结

    综上所述,JSP和Servlet在Web开发中扮演着互补的角色,JSP专注于视图展示,Servlet负责逻辑控制。了解和熟练掌握它们的特性及用法,对于构建高效、健壮的Web应用程序至关重要。在实际项目中,常常结合MVC设计模式,...

    JSP-Servlet学习笔记第2版.pdf

    10. JSP和Servlet的高级特性:比如会话跟踪、cookie处理、过滤器、监听器、MVC模式等。 11. 实际开发中遇到的问题及其解决方案:例如,处理请求中文乱码问题、在开发中如何分层以及代码的组织和管理。 以上就是...

    servlet+cookie和Session

    总结来说,Servlet是Web应用的基石,它结合HttpServletRequest和HttpServletResponse处理请求和响应,通过Cookie和Session管理会话,与JSP协同工作呈现动态内容。而Filter、文件上传和下载等特性则扩展了Servlet的...

    jsp/servlet阶段测试

    本资源总结了jsp和servlet的阶段性测试,涵盖了servlet和jsp的基础知识点,包括servlet的生命周期、jsp的隐含对象、Filter的用途、Listener的类型、Request、Session和Application的区别等。 1. Servlet的生命周期...

    《Jsp&Servlet入门级项目全程实录》源码

    在IT行业中,JSP(JavaServer Pages)和Servlet是用于构建动态Web应用程序的两种核心技术,尤其在企业级Java开发中广泛应用。《Jsp&Servlet入门级项目全程实录》源码是一个非常适合初学者深入理解这两门技术的实践...

    jsp+servlet做的连连看

    【描述】中的关键点在于如何将学习到的JSP和Servlet技术结合起来实现一个连连看游戏。JSP(JavaServer Pages)是用于开发动态网页的技术,它允许开发者在HTML页面中嵌入Java代码,使得网页与服务器之间的交互变得...

    基于jsp,servlet的网上商城项目

    在这个基于JSP和Servlet的网上商城项目中,我们将深入探讨如何利用这些技术实现一个功能完备的电子商务平台。 **一、JSP与Servlet基础** JSP是一种服务器端的技术,它允许开发者在HTML页面中嵌入Java代码,以方便...

    jsp+servlet 校园门户网站

    【标题】"jsp+servlet 校园门户网站"所涉及的知识点主要集中在Java Web开发领域,尤其是JSP(JavaServer Pages)和Servlet技术的应用。这两者是构建动态网站的重要工具,通常一起使用以实现数据交互和页面展示。 **...

    音乐网站JSP+SERVLET

    【音乐网站JSP+SERVLET】是一种基于Java技术的Web开发模式,广泛应用于构建动态音乐分享和播放平台。在这一领域,JSP(JavaServer Pages)和Servlet是两个核心组件,它们共同构成了服务器端的处理逻辑。 **JSP** 是...

    jsp+servlet+mysql写的简易购物网站系统代码

    10. **session和cookie**:在用户登录和购物车功能中,session和cookie常用于跟踪用户状态,如保存用户登录信息和购物车数据。 总结起来,这个“jsp+servlet+mysql写的简易购物网站系统代码”是一个典型的Java Web...

    JSP 在servlet中使用session

    在Java Web开发中,JSP(JavaServer Pages)和Servlet是两种常见的技术,它们用于创建动态网页和处理HTTP请求。Session技术则是在客户端与服务器之间维护状态的一种方式,尤其适用于多页面间的用户信息共享。本篇...

    jsp+servlet 购物车完整

    【标题】"jsp+servlet 购物车完整"是一个基于Java Web技术实现的购物车系统,它结合了JSP(JavaServer Pages)和Servlet,以及可能使用的JavaBean组件,来构建一个用户友好的交互界面和后端处理逻辑。这个项目可能...

Global site tag (gtag.js) - Google Analytics