??xml version="1.0" encoding="utf-8" standalone="yes"?>youjizz在线播放,亚洲成a人v欧美综合天堂,亚洲欧美日韩国产综合精品二区 http://www.aygfsteel.com/dwys0343/category/19023.html技术整?/description>zh-cn Wed, 28 Feb 2007 03:18:45 GMT Wed, 28 Feb 2007 03:18:45 GMT 60 装饰Servlet Request对象 http://www.aygfsteel.com/dwys0343/articles/92941.html特兰克斯 特兰克斯 Wed, 10 Jan 2007 08:12:00 GMT http://www.aygfsteel.com/dwys0343/articles/92941.html http://www.aygfsteel.com/dwys0343/comments/92941.html http://www.aygfsteel.com/dwys0343/articles/92941.html#Feedback 0 http://www.aygfsteel.com/dwys0343/comments/commentRss/92941.html http://www.aygfsteel.com/dwys0343/services/trackbacks/92941.html
版权声明Q可以Q意{载,转蝲时请务必以超链接形式标明文章原始出处和作者信息及本声?br />英文原文地址Q?br />http://dev2dev.bea.com/pub/a/2005/05/decorators.html 中文地址 http://www.matrix.org.cn/resource/article/43/43603_Servlet_Request.html 关键词:Servlet Request filter Decorator
摘要
装饰模式是Erich Gamma{h所著的《设计模式:可利用面向对象Y件的基础》一书中众多模式之一。一般来_此模式在设计Swing的程序员中比较流行,他们用它来改qY件。今天,即有许多程序是ZWeb应用的,装饰模式仍有用武之地Q在J2EE的环境下也有使用的h倹{?br />本文说明了如何将装饰模式应用到servlet request对象上。首先,提出了一个与servlet filter有关的问题,q解释了随之而引入的装饰模式。然后,讨论了如何在servlet环境下用此模式Qƈ列出了用此模式的几个比较有名的Zservlet的项目。最后,文章通过实现一个删除空白符的filter例子Q演CZ装饰模式在servlet中的使用?br />?br /> Servlet规范中所引入的filter令h心动不已Q因为它引入了一个功能强大的拦截模式。Filter是这样一UJava对象Q它能在request到达servlet的服务方法之前拦截HttpServletRequest对象Q而在服务Ҏ转移控制后又能拦截HttpServletResponse对象。你可以使用filter来实现特定的dQ比如验证用戯入,以及压羃web内容。但你拟富有成效C用过滤器的念头却被你不能改变HttpServletRequest对象的参数的现实扫了_因ؓjava.util.Map所包装的HttpServletRequest对象的参数是不可改变的。这极大地羃减了filter的应用范围。至在一半的旉里,你希望可以改变准备传送给filter的对象。如果在HttpServletRequest对象到达Struts的action servlet之前Q我们可以通过一个filter用戯入的多余I格LQ难道不是更妙吗?q样的话Q你׃必等到在Struts的action表单验证Ҏ中才q行q项工作了?br />q运的是Q尽你不能改变不变对象本nQ但你却可以通过使用装饰模式来改变其状态?br /> 装饰模式 在承中Q你可以通过l承一个父cdƈ覆盖你希望改变的Ҏ来改变对象状态。然而,如果q个对象是由E序的另一个子模块Q例如对象工? (q里所说的工厂是工厂模式中的术语,下同。译者注) 或是servlet容器所产生的,l承无能ؓ力了?br />装饰模式可用来增加一个现有对象的功能Q或是改变其状态。与其用承方式来扩展此类Q这个模式将一个对象包装成另外一个对象。图1是装饰模式的UMLcd?br /> ?Q装饰模?br /> 在图1中,Component是一个接口,其具体实现是ConcreteComponent。要改变Component的状态,你可以修改ConcreteComponent或是扩展? (通过l承或实现接口的方式Q译者注)。然而,如果ConcreteComponent来自于一个工厂,你却无计可施。你所能做的,是创徏一个同为实CComponent接口的装饰类。在?中,q个装饰cȝ角色qDecorator来扮演,在程序中通常表现为接口或抽象cRDecoratorcȝ一个特性就是,它有一个接收Component对象的构造方法。你拟装饰的对象传递给q个构造方法。在本例中,q个对象是从工厂获得的ConcreteComponent对象。通过此装饰对象传递给Decorator的一个类变量Q你可以讉KDecorator中的MҎ。这׃你得以改变对象的状态了?br />?中的DecoratorcM一定是接口或抽象类。如果你的程序不是很复杂Q你可以其转化Z个具体的DecoratorcR?br />举个例子Q考虑q样一个简单的消息传递程序,其主要部分是Messenger接口及其实现cMessengerImpl。让我们假设MessengerImpl对象来自于一个工厂,因此你不能改变其状态。如果你准备增加或改变Messenger对象的功能,你可以创Z个MessengerDecoratorcR图2是此例子的类图?br /> ?QMessenger装饰c?br /> 我们来看E序的代码。列?l出了Messenger接口的代码,列表2是MessengerImplcȝ代码?br /> 列表1QMessenger接口 public interface Messenger { public String getMessage();} 列表2QMessengerImplc?br /> Messenger对象׃个名为MessengerFactory的工厂创建,如列?所C?br /> 列表3QMessengerFactoryc?br /> public class MessengerFactory { public static Messenger getMessenger() { return new MessengerImpl("secrets"); }} Ҏ一个所创徏的Messenger对象Q此工厂通过某个未知的操作,初始化了getMessage()Ҏ所q回的字W串。换句话_你不能自己创建Messenger对象?br />在程序中QMessenger对象的主要用途是被传递给一个名为Util的类中的broadcast()静态方法。列?是Utilcȝ代码?br /> 列表4QUtilc?br /> public class Util { public static void broadcast(Messenger messenger) { System.out.print(messenger.getMessage()); } // other methods here} 在你自己的类中,你可能会有这L代码Q?br /> Messenger messenger = MessengerFactory.getMessenger();Util.broadcast(messenger); 假设你希望对broadcast()Ҏ所打印出的消息做一改动。你拟将其{为大写,怎么做?表面上看Q你可以l承MessengerQ实例化其子c,q将q回的对象传lUtil.broadcast()。但是,q种做法毫无意义Q因为只有工厂才知道如何初始化Messenger对象Qƈ通过其getMessage()Ҏq回正确的倹{?br />使用装饰模式Q你可以创徏一个MessengerDecoratorc,如列?所C?br /> 列表5QMessengerDecoratorc?br /> public class MessengerDecorator implements Messenger { private Messenger messenger; public MessengerDecorator(Messenger messenger) { this.messenger = messenger; } public String getMessage() { return messenger.getMessage().toUpperCase(); }} 因ؓMessengerDecorator实现了MessengerQUtil.broadcast()接受一个MessengerDecorator的实例。然而,MessengerDecorator不仅仅是一个接口的实现Q它q是一个MessengerImpl对象的装饰器。正因如此,MessengerDecorator必L一个接收拟被装饰的Messenger对象的构造方法?br />如列?所C,q个构造方法将参数传给变量。你现在可以覆盖MessengerDecorator中的getMessage()ҎQ以便将消息转ؓ大写后再打印出来。因Z持有原来Messenger对象的引用,你可以这样写getMessage()ҎQ?br /> public String getMessage() { return this.messenger.getMessage().toUpperCase();} MessengerDecorator中的getMessage()Ҏq回原始消息的大写版本?br />在你的类中,像往怸P你得C个Messenger对象QƈDecorator传给Util.broadcast()?br /> Messenger messenger = factory.getMessenger();Util.broadcast(new MessengerDecorator(messenger)); 你ƈ不将原始对象传给原先的目标,相反Q你其传给了该对象的装饰器?br /> 应用装饰模式于Servlet 以上Messengercȝ例子与servlet容器所构造的ServletRequest对象是一L。当收到一个HTTPhӞservlet容器׃创徏ServletRequest对象及ServletResponse对象Q分别是ServletRequestImpl及ServletResponseImpl的实例)Qƈ这两个对象传递给特定的servlet服务Ҏ。现在,如果你ؓServletRequest创徏一个装饰角Ԍq将其传lservlet服务ҎQ你应用了装饰模式?br />对ServletRequest很容易应用装饰模式,因ؓservlet API已经为其提供了一个包装类QServletRequestWrapper。图3是一个servlet装饰模式的类图?br /> ?QServlet API中的装饰模式 ?中的HTTP版本的类囑֦?所C。别多的cL晕了_只管注意虚线框中的三个类p了:HttpServletRequest, HttpServletRequestImpl, HttpServletRequestWrapper?br /> ?QServlet API (HTTP)的装饰模?br /> 情况与前面所举例子类伹{你拥有一个ServletRequest的实玎ͼ而它是由servlet容器产生的。你可以使用所提供的ServletRequestWrapper来装饰这些ServletRequest对象?br />q个模式很简单,在实际应用中可以z上用场。实际上Q一些很有名的应用就使用了此模式。这些应用包括: Struts - Struts是当前开发Java Web应用最受欢q的ZMVC(模型-视图-控制)模式的框架。Struts提供了相当于ServletRequest包装cȝorg.apache.struts.upload.MultipartRequestWrappercR? MultipartRequestWrapper覆盖了getParameter()QgetParameterNames()Q及getParameterValues(){方法来实现文g上传?br /> Apache Beehive ?C q个源于BEA的WebLogic专题组的开源项目,构徏于Struts之上Qƈ化了web应用及web服务的开发。与ServletRequest包装cMPorg.apache.beehive.netui.pageflow.internal包中的PageFlowRequestWrappercL助于LApache Beehive应用的页处理?br />现在Q让我们来看看,如何~写自己的HttpServletRequest装饰cR?br /> 一个删除空白字W的Filter 本节以上的理论投入实际使用Q通过实现一个删除空白字W的filterQ来演示如何使用javax.servlet.http.HttpServletRequestWrappercL装饰HttpServletRequest对象。在本例中,q个filter删除所传来的参C多余的空白字W?br />q在许多servlet/JSP应用中是很有用的Q包括Struts及JavaServer Faces{应用。例如,Struts通过调用HttpServletRequest对象的getParameterValues()对象来处理action表单。通过覆盖装饰cM此方法,你可以改变当前HttpServletRequest对象的状态?br />要创建HttpServletRequest的装饰类Q你需要承HttpServletRequestWrapperq且覆盖你希望改变的Ҏ。列?中,MyRequestWrappercd删除getParameterValues()Ҏq回值的多余I白字符?br /> 列表5QHttpServerletRequest装饰c?br /> 列表6演示了如何蝲获Httphq装饰HttpServletRequest对象。[i]列表6Q删除空白符的filter 列表6演示了如何蝲获Httphq装饰HttpServletRequest对象?br /> [i]列表6Q删除空白符的filter q个E序使用了列?所C的filter来修整用戯入。要使用q个filterQ你需要在web.xml文g中如下设|filter及filter-mapping的元素?br /> <filter> <filter-name>TrimmerFilter</filter-name> <filter-class>trimmer.filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>TrimmerFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> 要测试这个filterQ启动这个应用后Q在表单中输入一些|提交表单Q看看这个filter是如何修整输入数值的。这是一个实用的装饰模式的应用?br />结 Servlet filter可以在调用一个servlet的服务方法后Q拦载或加工HTTPh。尽这非常׃hQ但其实际用却有所限制Q因Z不能改变HttpServletRequest对象?br />q时候装饰模式派上了用场。本文演CZ如何通过应用装饰模式来“修改”HttpServletRequest对象Q从而你的servlet filter更加有用。在上面filter例子中,filter改了request参数中的用户输入Q而这一点,如果没有装饰request对象Q你是无论如何也不可能做到的?br /> Budi Kurniawan是一个高UJ2EE的架构师。他q是《Tomcat如何工作Q教你如何开发自qServlet容器? (”How Tomcat Works: A Guide to Developing Your Own Servlet Container? 以及《Struts设计与编E指南?”Struts Design and Programming :A Tutorial? q两本书的作者,它们均由BrainySoftwar.com出版?/div>
]]> 关于Java Servlet的Filter 技?/title> http://www.aygfsteel.com/dwys0343/articles/92933.html特兰克斯 特兰克斯 Wed, 10 Jan 2007 07:58:00 GMT http://www.aygfsteel.com/dwys0343/articles/92933.html http://www.aygfsteel.com/dwys0343/comments/92933.html http://www.aygfsteel.com/dwys0343/articles/92933.html#Feedback 0 http://www.aygfsteel.com/dwys0343/comments/commentRss/92933.html http://www.aygfsteel.com/dwys0343/services/trackbacks/92933.html
作? 李文?
Filter 技术是servlet 2.3 新增加的功能.servlet2.3是sun公司?000q?0月发布的,它的开发者包括许多个人和公司团体,充分体现了sun公司所倡导的代码开放性原?׃众多的参与者的共同努力,servlet2.3比以往功能都强大了许多,而且性能也有了大q提? 它新增加的功能包? 1. 应用E序生命周期事g控制; 2. 新的国际? 3. 澄清了类的装载规? 4. 新的错误及安全属? 5. 不赞成用HttpUtils c? 6. 各种有用的方? 7. 阐明q扩展了几个servlet DTD; 8. filter功能. 其中最重要的就是filter功能.它用户可以改变一个request和修改一个response. Filter 不是一个servlet,它不能生一个response,它能够在一个request到达servlet之前预处理request,也可以在dservlet时处理response.换种说法,filter其实是一个”servlet chaining?servlet ?.一个filter 包括: 1. 在servlet被调用之前截? 2. 在servlet被调用之前检查servlet request; 3. Ҏ需要修改request头和request数据; 4. Ҏ需要修改response头和response数据; 5. 在servlet被调用之后截? 你能够配|一个filter C个或多个servlet;单个servlet或servletl能够被多个filter 使用.几个实用的filter 包括:用户辨认filter,日志filter,审核filter,加密filter,W号filter,能改变xml内容的XSLT filter{? 一个filter必须实现javax.servlet.Filter接口q定义三个方? 1.void setFilterConfig(FilterConfig config) //讄filter 的配|对? 2. FilterConfig getFilterConfig() //q回filter的配|对? 3. void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) //执行filter 的工? 服务器每ơ只调用setFilterConfigҎ一ơ准备filter 的处?调用doFilterҎ多次以处理不同的h.FilterConfig接口有方法可以找到filter名字及初始化参数信息.服务器可以设|FilterConfig为空来指明filter已经l结. 每一个filter从doFilter()Ҏ中得到当前的request及response.在这个方法里,可以q行M的针对request及response的操?(包括攉数据,包装数据{?.filter调用chain.doFilter()Ҏ把控制权交给下一个filter.一个filter在doFilter()Ҏ中结?如果一个filter惛_止request处理而获得对response的完全的控制,那它可以不调用下一个filter. 一个filter可以包装request 或response以改变几个方法和提供用户定制的属?Api2.3提供了HttpServletRequestWrapper 和HttpServletResponseWrapper来实?它们能分z最初的request和response.如果要改变一个方法的Ҏ?必须l承wapper和重写方?下面是一D늮单的日志filter用来记录所有request的持l时? public class LogFilter implements Filter { FilterConfig config; public void setFilterConfig(FilterConfig config) { this.config = config; } public FilterConfig getFilterConfig() { return config; } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { ServletContext context = getFilterConfig().getServletContext(); long bef = System.currentTimeMillis(); chain.doFilter(req, res); // no chain parameter needed here long aft = System.currentTimeMillis(); context.log("Request to " + req.getRequestURI() + ": " + (aft-bef)); } } 当server调用setFilterConfig(),filter保存config信息.在doFilter()Ҏ中通过config信息得到servletContext.如果要运行这个filter,必须去配|到web.xml?以tomcat4.01Z: <filter> <filter-name> log //filter 名字 </filter-name> <filter-class> LogFilter //filter class(上例的servlet) </filter-class> </filter> <filter-mapping> <filter-name>log</filter-name> <servletname>servletname</servlet-name> </filter-mapping> <servlet> <servlet-name>servletname</servletname> <servletclass>servletclass</servlet-class> </servlet> <servlet-mapping> <servlet-name>servletname</servlet-name> <url-pattern>*</url-pattern> </servlet-mapping> 把这个web.xml攑ֈweb-inf?详请参考tomcat帮助文档). 当每ơ请求一个request?如index.jsp),先到LogFilter中去q调用doFilter()Ҏ,然后才到各自的servlet中去.如果是一个简单的servlet(只是一个页?无Q何输?,那么可能的输出是: Request to /index.jsp: 10
Servlet和Filter的url匚w以及url-pattern详解
一Qservlet容器对url的匹配过E: 当一个请求发送到servlet容器的时候,容器先会请求的url减去当前应用上下文的路径作ؓservlet的映urlQ比如我讉K的是http://localhost/test/aaa.html Q我的应用上下文是testQ容器会?a href="http://localhost/test">http://localhost/test LQ剩下的/aaa.html部分拿来做servlet的映匹配。这个映匹配过E是有顺序的Q而且当有一个servlet匚w成功以后Q就不会ȝ会剩下的servlet了(filter不同Q后文会提到Q。其匚w规则和顺序如下: 1. _路径匚w。例子:比如servletA 的url-pattern为?testQservletB的url-pattern为?* Q这个时候,如果我访问的url?a href="http://localhost/test">http://localhost/test Q这个时候容器就会先 q行_路径匚wQ发?test正好被servletA_匚wQ那么就去调用servletAQ也不会ȝ会其他的servlet了?br />2. 最长\径匹配。例子:servletA的url-pattern?test/*Q而servletB的url-pattern?test/a/*Q此时访?a href="http://localhost/test/a">http://localhost/test/a Ӟ容器会选择路径最长的servlet来匹配,也就是这里的servletB?br />3. 扩展匚wQ如果url最后一D包含扩展,容器会Ҏ扩展选择合适的servlet。例子:servletA的url-patternQ?.action 4. 如果前面三条规则都没有找C个servletQ容器会Ҏurl选择对应的请求资源。如果应用定义了一个default servletQ则容器会将h丢给default servletQ什么是default servletQ后面会Ԍ?br /> Ҏq个规则表,p很清楚的知道servlet的匹配过E,所以定义servlet的时候也要考虑url-pattern的写法,以免出错?br /> 对于filterQ不会像servlet那样只匹配一个servletQ因为filter的集合是一个链Q所以只会有处理的顺序不同,而不会出现只选择一个filter。Filter的处理顺序和filter-mapping在web.xml中定义的序相同?br /> 二,url-pattern详解 在web.xml文g中,以下语法用于定义映射Q?br />l 以?’开头和以?*”结是用来做路径映射的?br />l 以前~?.”开头的是用来做扩展映射的?br />l ?” 是用来定义default servlet映射的?br />l 剩下的都是用来定义详l映的。比如: /aa/bb/cc.action 所以,Z么定义?*.action”这样一个看h很正常的匚w会错Q因个匹配即属于路径映射Q也属于扩展映射Q导致容器无法判断?/p>
]]>Session详解 http://www.aygfsteel.com/dwys0343/articles/92336.html特兰克斯 特兰克斯 Mon, 08 Jan 2007 04:26:00 GMT http://www.aygfsteel.com/dwys0343/articles/92336.html http://www.aygfsteel.com/dwys0343/comments/92336.html http://www.aygfsteel.com/dwys0343/articles/92336.html#Feedback 0 http://www.aygfsteel.com/dwys0343/comments/commentRss/92336.html http://www.aygfsteel.com/dwys0343/services/trackbacks/92336.html 发表?2006-03-13 02:58:27 作?郎云?hippiewolf 来源:bea
摘要:
虽然session机制在web应用E序中被采用已经很长旉了,但是仍然有很多h不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论session的工作机制ƈ且对在Java web application中应用session机制时常见的问题作出解答?一、术语session 在我的经验里Qsessionq个词被滥用的程度大概仅ơ于transactionQ更加有的是transaction与session在某些语境下的含义是相同的?br /> sessionQ中文经常翻译ؓ会话Q其本来的含义是指有始有l的一pd动作/消息Q比如打电话时从拿v电话拨号到挂断电话这中间的一pdq程可以UCZ?session。有时候我们可以看到这L话“在一个浏览器会话期间Q?..”,q里的会话一词用的就是其本义Q是指从一个浏览器H口打开到关闭这个期?①。最混ؕ的是“用P客户端)在一ơ会话期间”这样一句话Q它可能指用L一pd动作Q一般情况下是同某个具体目的相关的一pd动作Q比如从d到选购商品到结账登样一个网上购物的q程Q有时候也被称Z个transactionQ,然而有时候也可能仅仅是指一ơ连接,也有可能是指含义①,其中的差别只能靠上下文来推断②?br /> 然而当session一词与|络协议相关联时Q它又往往隐含了“面向连接”和/或“保持状态”这样两个含义, “面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电话,直到Ҏ接了电话通信才能开始,与此相对的是写信Q在你把信发出去的时候你q不能确认对方的地址是否正确Q通信渠道不一定能建立Q但对发信h来说Q通信已经开始了。“保持状态”则是指通信的一方能够把一pd的消息关联v来,使得消息之间可以互相依赖Q比如一个服务员能够认出再次光的老顾客ƈ且记得上ơ这个顾客还Ơ店里一块钱。这一cȝ例子有“一个TCP session”或?“一个POP3 session”③?br /> 而到了web服务器蓬勃发展的时代Qsession在web开发语境下的语义又有了新的扩展Q它的含义是指一cȝ来在客户端与服务器之间保持状态的解决Ҏ④。有时候session也用来指q种解决Ҏ的存储结构,如“把xxx保存在session 里”⑤。由于各U用于web开发的语言在一定程度上都提供了对这U解x案的支持Q所以在某种特定语言的语境下Qsession也被用来指代该语a的解x案,比如l常把Java里提供的javax.servlet.http.HttpSessionUCؓsession⑥?br /> 鉴于q种混ؕ已不可改变,本文中session一词的q用也会Ҏ上下文有不同的含义,请大家注意分辨?br />在本文中Q用中文“浏览器会话期间”来表达含义①,使用“session机制”来表达含义④,使用“session”表辑义⑤Q用具体的“HttpSession”来表达含义?br />二、HTTP协议与状态保?/font> HTTP 协议本n是无状态的Q这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器h下蝲某些文gQ无论是客户端还是服务器都没有必要纪录彼此过ȝ行ؓQ每一ơ请求之间都是独立的Q好比一个顾客和一个自动售货机或者一个普通的Q非会员Ӟ大卖Z间的关系一栗?br /> 然而聪明(或者贪心?Q的Z很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用Q就像给有线电视加上Ҏ功能一栗这U需求一斚wqHTML逐步d了表单、脚本、DOM{客L行ؓQ另一斚w在服务器端则出现了CGI规范以响应客L的动态请求,作ؓ传输载体的HTTP协议也添加了文g上蝲?cookieq些Ҏ。其中cookie的作用就是ؓ了解决HTTP协议无状态的~陷所作出的努力。至于后来出现的session机制则是又一U在客户端与服务器之间保持状态的解决Ҏ?br /> 让我们用几个例子来描qC下cookie和session机制之间的区别与联系。笔者曾l常ȝ一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠Q然而一ơ性消?杯咖啡的Z微乎其微Q这时就需要某U方式来U录某位֮的消Ҏ量。想象一下其实也无外乎下面的几种ҎQ?br />1、该店的店员很厉宻I能记住每位顾客的消费数量Q只要顾客一走进咖啡店,店员q道该怎么对待了。这U做法就是协议本w支持状态?br />2、发l顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每ơ消ҎQ如果顾客出C张卡片,则此ơ消费就会与以前或以后的消费相联pv来。这U做法就是在客户端保持状态?br />3、发l顾客一张会员卡Q除了卡号之外什么信息也不纪录,每次消费Ӟ如果֮出示该卡片,则店员在店里的纪录本上找到这个卡号对应的U录d一些消费信息。这U做法就是在服务器端保持状态?br /> ׃HTTP协议是无状态的Q而出于种U考虑也不希望使之成ؓ有状态的Q因此,后面两种Ҏ成为现实的选择。具体来说cookie机制采用的是在客L保持状态的ҎQ而session机制采用的是在服务器端保持状态的Ҏ。同时我们也看到Q由于采用服务器端保持状态的Ҏ在客L也需要保存一个标识,所以session机制可能需要借助于cookie机制来达C存标识的目的Q但实际上它q有其他选择?br />三、理解cookie机制 cookie机制的基本原理就如上面的例子一L单,但是q有几个问题需要解冻I“会员卡”如何分发;“会员卡”的内容Q以及客户如何用“会员卡”?br /> 正统的cookie分发是通过扩展HTTP协议来实现的Q服务器通过在HTTP的响应头中加上一行特D的指示以提C浏览器按照指示生成相应的cookie。然而纯_的客户端脚本如JavaScript或者VBScript也可以生成cookie?br /> 而cookie 的用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器查所有存储的cookieQ如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置Q则把该cookie附在h资源的HTTPh头上发送给服务器。意思是麦当劳的会员卡只能在麦当劳的店里出示Q如果某家分店还发行了自q会员卡,那么q这家店的时候除了要出示麦当劳的会员卡,q要出示q家店的会员卡?br /> cookie的内容主要包括:名字Q|q期旉Q\径和域?br />其中域可以指定某一个域比如.google.comQ相当于d招牌Q比如宝z公司,也可以指定一个域下的具体某台机器比如www.google.com或者froogle.google.comQ可以用飘柔来做比?br />路径是跟在域名后面的URL路径Q比?或?foo{等Q可以用某飘柔专柜做比?br />路径与域合在一起就构成了cookie的作用范围?br />如果不设|过期时_则表C个cookie的生命期为浏览器会话期间Q只要关闭浏览器H口Qcookie消׃。这U生命期为浏览器会话期的 cookie被称Z话cookie。会话cookie一般不存储在硬盘上而是保存在内存里Q当然这U行为ƈ不是规范规定的。如果设|了q期旉Q浏览器׃把cookie保存到硬盘上Q关闭后再次打开览器,q些cookie仍然有效直到过讑֮的过期时间?br /> 存储在硬盘上的cookie 可以在不同的览器进E间׃nQ比如两个IEH口。而对于保存在内存里的cookieQ不同的览器有不同的处理方式。对于IEQ在一个打开的窗口上?Ctrl-NQ或者从文g菜单Q打开的窗口可以与原窗口共享,而用其他方式新开的IEq程则不能共享已l打开的窗口的内存cookieQ对?Mozilla Firefox0.8Q所有的q程和标{N都可以共享同Lcookie。一般来说是用javascript的window.open打开的窗口会与原H口׃n内存cookie。浏览器对于会话cookie的这U只认cookie不认人的处理方式l常l采用session机制的web应用E序开发者造成很大的困扰?br /> 下面是一个goolge讄cookie的响应头的例?br />HTTP/1.1 302 Found Location: http://www.google.com/intl/zh-CN/ Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com Content-Type: text/html q是使用HTTPLookq个HTTP Sniffer软g来俘LHTTP通讯U录的一部分 览器在再次讉Kgoolge的资源时自动向外发送cookie 用Firefox可以很容易的观察现有的cookie的?br />使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理?br /> IE也可以设|在接受cookie前询?br />四、理解session机制 session机制是一U服务器端的机制Q服务器使用一U类g散列表的l构Q也可能是使用散列表)来保存信息?br /> 当程序需要ؓ某个客户端的h创徏一个session的时候,服务器首先检查这个客L的请求里是否已包含了一个session标识 - UCؓ session idQ如果已包含一个session id则说明以前已lؓ此客L创徏qsessionQ服务器按照session id把这?session索出来用(如果索不刎ͼ可能会新Z个)Q如果客Lh不包含session idQ则为此客户端创Z个sessionq且生成一个与此session相关联的session idQsession id的值应该是一个既不会重复Q又不容易被扑ֈ规律以仿造的字符Ԍq个 session id被在本ơ响应中q回l客L保存?br /> 保存q个session id的方式可以采用cookieQ这样在交互q程中浏览器可以自动的按照规则把q个标识发挥l服务器。一般这个cookie的名字都是类gSEEESIONIDQ而。比如weblogic对于web应用E序生成的cookieQJSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764Q它的名字就?JSESSIONID?br /> ׃cookie可以被h为的止Q必L其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一U技术叫做URL重写Q就是把session id直接附加在URL路径的后面,附加方式也有两种Q一U是作ؓURL路径的附加信息,表现形式为http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764 另一U是作ؓ查询字符串附加在URL后面Q表现Ş式ؓhttp://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764 q两U方式对于用h说是没有区别的,只是服务器在解析的时候处理的方式不同Q采用第一U方式也有利于把session id的信息和正常E序参数区分开来?br />Z在整个交互过E中始终保持状态,必d每个客户端可能请求的路径后面都包含这个session id?br /> 另一U技术叫做表单隐藏字Dc就是服务器会自动修改表单,d一个隐藏字D,以便在表单提交时能够把session id传递回服务器。比如下面的表单<form name="testform" action="/xxx"> <input type="text"> </form> 在被传递给客户端之前将被改写成<form name="testform" action="/xxx"> <input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"> <input type="text"> </form> q种技术现在已较少应用Q笔者接触过的很古老的iPlanet6(SunONE应用服务器的前n)׃用了q种技术?br />实际上这U技术可以简单的用对action应用URL重写来代ѝ?br /> 在谈论session机制的时候,常常听到q样一U误解“只要关闭浏览器Qsession消׃”。其实可以想象一下会员卡的例子,除非֮d对店家提出销卡,否则店家l对不会L删除֮的资料。对session来说也是一LQ除非程序通知服务器删除一个sessionQ否则服务器会一直保留,E序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会d在关闭之前通知服务器它要关闭Q因此服务器Ҏ不会有机会知道浏览器已经关闭Q之所以会有这U错觉,是大部分session机制都用会话cookie来保存session idQ而关闭浏览器后这?session id消׃Q再ơ连接服务器时也无法找到原来的session。如果服务器讄的cookie被保存到盘上,或者用某U手D|写浏览器发出的HTTPh_把原来的session id发送给服务器,则再ơ打开览器仍然能够找到原来的session?br /> 恰恰是由于关闭浏览器不会Dsession被删除,q服务器ؓseesion讄了一个失效时_当距dL上一ơ用session的时间超q这个失效时间时Q服务器可以认为客L已经停止了活动,才会把session删除以节省存储空间?br />五、理解javax.servlet.http.HttpSession HttpSession是Javaq_对session机制的实现规范,因ؓ它仅仅是个接口,具体到每个web应用服务器的提供商,除了对规范支持之外,仍然会有一些规范里没有规定的细微差异。这里我们以BEA的Weblogic Server8.1作ؓ例子来演C?br /> 首先QWeblogic Server提供了一pd的参数来控制它的HttpSession的实玎ͼ包括使用cookie的开关选项Q用URL重写的开关选项Qsession持久化的讄Qsession失效旉的设|,以及针对cookie的各U设|,比如讄cookie的名字、\径、域Q?cookie的生存时间等?br /> 一般情况下Qsession都是存储在内存里Q当服务器进E被停止或者重启的时候,内存里的session也会被清I,如果讄了session的持久化Ҏ,服务器就会把session保存到硬盘上Q当服务器进E重新启动或q些信息能够被再次使用Q?Weblogic Server支持的持久性方式包括文件、数据库、客Lcookie保存和复制?br /> 复制严格说来不算持久化保存,因ؓsession实际上还是保存在内存里,不过同样的信息被复制到各个cluster内的服务器进E中Q这样即使某个服务器q程停止工作也仍然可以从其他q程中取得session?br /> cookie生存旉的设|则会媄响浏览器生成的cookie是否是一个会话cookie。默认是使用会话cookie。有兴趣的可以用它来试验我们在第四节里提到的那个误解?br /> cookie的\径对于web应用E序来说是一个非帔R要的选项QWeblogic Server对这个选项的默认处理方式得它与其他服务器有明昄区别。后面我们会专题讨论?br /> 关于session的设|参考[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869六、HttpSession常见问题 Q在本小节中session的含义ؓ⑤和⑥的混合Q?br /> 1、session在何时被创徏 一个常见的误解是以为session在有客户端访问时p创徏Q然而事实是直到某server端程序调?HttpServletRequest.getSession(true)q样的语句时才被创徏Q注意如果JSP没有昄的?<% @page session="false"%> 关闭sessionQ则JSP文g在编译成Servlet时将会自动加上这样一条语?HttpSession session = HttpServletRequest.getSession(true);q也是JSP中隐含的 session对象的来历?br /> ׃session会消耗内存资源,因此Q如果不打算使用sessionQ应该在所有的JSP中关闭它?br /> 2、session何时被删?br />l合前面的讨论,session在下列情况下被删除a.E序调用HttpSession.invalidate();或b.距离上一ơ收到客L发送的session id旉间隔过了session的超时设|?或c.服务器进E被停止Q非持久sessionQ?br /> 3、如何做到在览器关闭时删除session 严格的讲Q做不到q一炏V可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进E这些非常规手段仍然无能为力?br /> 4、有个HttpSessionListener是怎么回事 你可以创Llistenerȝ控session的创建和销毁事Ӟ使得在发生这L事g时你可以做一些相应的工作。注意是session的创建和销毁动作触发listenerQ而不是相反。类似的与HttpSession有关的listenerq有 HttpSessionBindingListenerQHttpSessionActivationListener?HttpSessionAttributeListener?br /> 5、存攑֜session中的对象必须是可序列化的?br />不是必需的。要求对象可序列化只是ؓ了session能够在集中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存。在 Weblogic Server的session中放|一个不可序列化的对象在控制C会收C个警告。我所用过的某个iPlanet版本如果 session中有不可序列化的对象Q在session销毁时会有一个ExceptionQ很奇怪?br /> 6、如何才能正的应付客户端禁止cookie的可能?br />Ҏ有的URL使用URL重写Q包括超链接Qform的actionQ和重定向的URLQ具体做法参见[6] http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770 7、开两个览器窗口访问应用程序会使用同一个sessionq是不同的session 参见W三节对cookie的讨论,对session来说是只认id不认人,因此不同的浏览器Q不同的H口打开方式以及不同的cookie存储方式都会对这个问题的{案有媄响?br /> 8、如何防止用h开两个览器窗口操作导致的session混ؕ q个问题与防止表单多ơ提交是cM的,可以通过讄客户端的令牌来解冟뀂就是在服务器每ơ生成一个不同的idq回l客LQ同时保存在session里,客户端提交表单时必须把这个id也返回服务器Q程序首先比较返回的id与保存在session里的值是否一_如果不一致则说明本次操作已经被提交过了。可以参看《J2EE核心模式》关于表C层模式的部分。需要注意的是对于用javascript window.open打开的窗口,一般不讄q个idQ或者用单独的idQ以防主H口无法操作Q徏议不要再window.open打开的窗口里做修Ҏ作,q样可以不用设|?br /> 9、ؓ什么在Weblogic Server中改变session的值后要重新调用一ơsession.setValue 做这个动作主要是Z在集环境中提示Weblogic Server session中的值发生了改变Q需要向其他服务器进E复制新的session倹{?br /> 10、ؓ什么session不见?br />排除session正常失效的因素之外,服务器本w的可能性应该是微乎其微的,虽然W者在iPlanet6SP1加若q补丁的Solaris版本上倒也遇到q;览器插件的可能性次之,W者也遇到q?721插g造成的问题;理论上防火墙或者代理服务器在cookie处理上也有可能会出现问题?br />出现q一问题的大部分原因都是E序的错误,最常见的就是在一个应用程序中去访问另外一个应用程序。我们在下一节讨个问题?br />七、跨应用E序的session׃n 常常有这L情况Q一个大目被分割成若干项目开发,Z能够互不q扰Q要求每个小目作ؓ一个单独的web应用E序开发,可是C最后突然发现某几个项目之间需要共享一些信息,或者想使用session来实现SSO(single sign on)Q在session中保存login的用户信息,最自然的要求是应用E序间能够访问彼此的session?br /> 然而按照Servlet规范Qsession的作用范围应该仅仅限于当前应用程序下Q不同的应用E序之间是不能够互相讉KҎ的session的。各个应用服务器从实际效果上都遵守了q一规范Q但是实现的l节却可能各有不同,因此解决跨应用程序session׃n的方法也各不相同?br /> 首先来看一下Tomcat是如何实现web应用E序之间session的隔ȝQ从 Tomcat讄的cookie路径来看Q它对不同的应用E序讄的cookie路径是不同的Q这样不同的应用E序所用的session id是不同的Q因此即使在同一个浏览器H口里访问不同的应用E序Q发送给服务器的session id也可以是不同的?br /> Ҏq个Ҏ,我们可以推测Tomcat中session的内存结构大致如下?br /> W者以前用q的iPlanet也采用的是同L方式Q估计SunONE与iPlanet之间不会有太大的差别。对于这U方式的服务器,解决的思\很简单,实际实行h也不难。要么让所有的应用E序׃n一个session idQ要么让应用E序能够获得其他应用E序的session id?br /> iPlanet中有一U很单的Ҏ来实现共享一个session idQ那是把各个应用程序的cookie路径都设?Q实际上应该?NASAppQ对于应用程序来讲它的作用相当于根)?br /><session-info> <path>/NASApp</path> </session-info> 需要注意的是,操作׃n的session应该遵@一些编E约定,比如在session attribute名字的前面加上应用程序的前缀Q?setAttribute("name", "neo")变成setAttribute("app1.name", "neo")Q以防止命名I间冲突Q导致互相覆盖?br /> 在Tomcat中则没有q么方便的选择。在Tomcat版本3上,我们q可以有一些手D|׃nsession。对于版?以上的TomcatQ目前笔者尚未发现简单的办法。只能借助于第三方的力量,比如使用文g、数据库、JMS或者客LcookieQURL参数或者隐藏字D늭手段?br /> 我们再看一下Weblogic Server是如何处理session的?br /> 从截屏画面上可以看到Weblogic ServerҎ有的应用E序讄的cookie的\径都?Q这是不是意味着在Weblogic Server中默认的可以共享session了呢Q然而一个小实验卛_证明即不同的应用程序用的是同一个sessionQ各个应用程序仍然只能访问自己所讄的那些属性。这说明Weblogic Server中的session的内存结构可能如?br /> 对于q样一U结构,?session机制本n上来解决session׃n的问题应该是不可能的了。除了借助于第三方的力量,比如使用文g、数据库、JMS或者客L cookieQURL参数或者隐藏字D늭手段Q还有一U较为方便的做法Q就是把一个应用程序的session攑ֈServletContext中,q样另外一个应用程序就可以从ServletContext中取得前一个应用程序的引用。示例代码如下, 应用E序Acontext.setAttribute("appA", session); 应用E序BcontextA = context.getContext("/appA"); HttpSession sessionA = (HttpSession)contextA.getAttribute("appA"); 值得注意的是q种用法不可ULQ因为根据ServletContext的JavaDocQ应用服务器可以处于安全的原因对于context.getContext("/appA");q回I|以上做法在Weblogic Server 8.1中通过?br /> 那么Weblogic ServerZ么要把所有的应用E序的cookie路径都设?呢?原来是ؓ了SSOQ凡是共享这个session的应用程序都可以׃n认证的信息。一个简单的实验可以证明这一点,修改首先d的那个应用程序的描述Wweblogic.xmlQ把cookie路径修改?appA 讉K另外一个应用程序会重新要求dQ即使是反过来,先访问cookie路径?的应用程序,再访问修改过路径的这个,虽然不再提示dQ但是登录的用户信息也会丢失。注意做q个实验时认证方式应该用FORMQ因为浏览器和web服务器对basic认证方式有其他的处理方式Q第二次h的认证不是通过 session来实现的。具体请参看[7] secion 14.8 AuthorizationQ你可以修改所附的CZE序来做q些试验?br />八、ȝ session机制本nq不复杂Q然而其实现和配|上的灵zL却使得具体情况复杂多变。这也要求我们不能把仅仅某一ơ的l验或者某一个浏览器Q服务器的经验当作普遍适用的经验,而是始终需要具体情况具体分析?br />摘要Q虽然session机制在web应用E序中被采用已经很长旉了,但是仍然有很多h不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论session的工作机制ƈ且对在Java web application中应用session机制时常见的问题作出解答?img src ="http://www.aygfsteel.com/dwys0343/aggbug/92336.html" width = "1" height = "1" /> ]]>
վ֩ģ壺
ԭ |
|
ǿ |
|
ɽ |
ɽ |
â |
|
|
ƽ |
|
|
|
|
Ϫ |
|
ɽ |
|
|
|
|
Ͻ |
|
ػʵ |
ػ |
|
|
ƽ |
첼 |
|
|
|
ʯ |
|
˲ |
|
|
|
|
|
|