??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品亚洲mnbav网站
,在线综合亚洲欧洲综合网站,一本色道久久88亚洲精品综合
http://www.tkk7.com/Microhelp/category/1814.html君子博学而日参省乎己Q则智明而行无过也?/description>zh-cnWed, 28 Feb 2007 20:48:16 GMTWed, 28 Feb 2007 20:48:16 GMT60- session详解http://www.tkk7.com/Microhelp/articles/session.htmlMicrohelpMicrohelpThu, 17 Aug 2006 02:33:00 GMThttp://www.tkk7.com/Microhelp/articles/session.htmlhttp://www.tkk7.com/Microhelp/comments/64066.htmlhttp://www.tkk7.com/Microhelp/articles/session.html#Feedback0http://www.tkk7.com/Microhelp/comments/commentRss/64066.htmlhttp://www.tkk7.com/Microhelp/services/trackbacks/64066.htmlhttp://blog.tomxp.com/view/467.html
作者:郎云鹏(dev2dev ID: hippiewolfQ?br />
摘要Q虽然session机制在web应用E序中被采用已经很长旉了,但是仍然有很多h不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论session的工作机制ƈ且对在Java web application中应用session机制时常见的问题作出解答?br />
目录Q?br />一、术语session
二、HTTP协议与状态保?br />三、理解cookie机制
四、理解session机制
五、理解javax.servlet.http.HttpSession
六、HttpSession常见问题
七、跨应用E序的session׃n
八、ȝ
参考文?br />
一、术语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协议与状态保?br />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 />
q是一个询问接受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没有昄的用?lt;% @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序A
context.setAttribute("appA", session);
应用E序B
contextA = 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 />
关于作者:
郎云鹏(dev2dev ID: hippiewolfQ,软g工程师,从事J2EE开?br />电子邮gQlangyunpeng@yahoo.com.cn
地址Q大qY件园?1L技大厦A座大q博涵咨询服务有限公?br />
参考文档:
[1] Preliminary Specification http://wp.netscape.com/newsref/std/cookie_spec.html
[2] RFC2109 http://www.rfc-editor.org/rfc/rfc2109.txt
[3] RFC2965 http://www.rfc-editor.org/rfc/rfc2965.txt
[4] The Unofficial Cookie FAQ http://www.cookiecentral.com/faq/
[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869
[6] http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
[7] RFC2616 http://www.rfc-editor.org/rfc/rfc2616.txt

]]> - Java正则表达式详?/title>http://www.tkk7.com/Microhelp/articles/11074.htmlMicrohelpMicrohelpThu, 25 Aug 2005 08:09:00 GMThttp://www.tkk7.com/Microhelp/articles/11074.htmlhttp://www.tkk7.com/Microhelp/comments/11074.htmlhttp://www.tkk7.com/Microhelp/articles/11074.html#Feedback0http://www.tkk7.com/Microhelp/comments/commentRss/11074.htmlhttp://www.tkk7.com/Microhelp/services/trackbacks/11074.html
如果你曾l用qPerl或Q何其他内建正则表辑ּ支持的语aQ你一定知道用正则表达式处理文本和匚w模式是多么简单。如果你不熟悉这个术语,那么“正则表辑ּ”(Regular ExpressionQ就是一个字W构成的Ԍ它定义了一个用来搜索匹配字W串的模式? |
许多语言Q包括Perl、PHP、Python、JavaScript和JScriptQ都支持用正则表辑ּ处理文本Q一些文本编辑器用正则表辑ּ实现高“搜?替换”功能。那么Java又怎样呢?本文写作Ӟ一个包含了用正则表辑ּq行文本处理的Java规范需求(Specification RequestQ已l得到认可,你可以期待在JDK的下一版本中看到它? |
然而,如果现在需要用正则表辑ּQ又该怎么办呢Q你可以从Apache.org下蝲源代码开攄Jakarta-ORO库。本文接下来的内容先要地介绍正则表达式的入门知识Q然后以Jakarta-ORO APIZ介绍如何使用正则表达式? |
我们先从单的开始。假设你要搜索一个包含字W“cat”的字符Ԍ搜烦用的正则表达式就是“cat”。如果搜索对大小写不敏感Q单词“catalog”、“Catherine”、“sophisticated”都可以匚w。也是_ |
假设你在玩英文拼字游戏,惌扑և三个字母的单词,而且q些单词必须以“t”字母开_以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内宏V要构造出q个正则表达式,你可以用一个通配W——句点符号?”。这P完整的表辑ּ是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,q匹配“t#n”、“tpn”甚至“t n”,q有其他许多无意义的l合。这是因为句点符号匹配所有字W,包括I格、Tab字符甚至换行W: |
Z解决句点W号匚w范围q于q泛q一问题Q你可以在方括号Q“[]”)里面指定看来有意义的字符。此Ӟ只有Ҏ号里面指定的字符才参与匹配。也是_正则表达式“t[aeio]n”只匚w“tan”、“Ten”、“tin”和“ton”。但“Toon”不匚wQ因为在Ҏ号之内你只能匚w单个字符Q? |
如果除了上面匚w的所有单词之外,你还惌匚w“toon”,那么Q你可以使用“|”操作符。“|”操作符的基本意义就是“或”运。要匚w“toon”,使用“t(a|e|i|o|oo)n”正则表辑ּ。这里不能用方扩号Q因为方括号只允许匹配单个字W;q里必须使用圆括号?)”。圆括号q可以用来分l,具体请参见后面介l? |
表一昄了表C匹配次数的W号Q这些符L来确定紧靠该W号左边的符号出现的ơ数Q? |
假设我们要在文本文g中搜索美国的C会安全L。这个号码的格式?99-99-9999。用来匹配它的正则表辑ּ如图一所C。在正则表达式中Q连字符Q?”)有着Ҏ的意义,它表CZ个范_比如??。因此,匚wC会安全L中的q字W号Ӟ它的前面要加上一个{义字W“\”? |
图一Q匹配所?23-12-1234形式的社会安全号?/P> |
假设q行搜烦的时候,你希望连字符号可以出玎ͼ也可以不出现——即Q?99-99-9999?99999999都属于正的格式。这Ӟ你可以在q字W号后面加上“?”数量限定符P如图二所C: |
图二Q匹配所?23-12-1234?23121234形式的社会安全号?/P> |
下面我们再来看另外一个例子。美国汽车牌照的一U格式是四个数字加上二个字母。它的正则表辑ּ前面是数字部分“[0-9]{4}”,再加上字母部分“[A-Z]{2}”。图三显CZ完整的正则表辑ּ? |
“^”符L为“否”符受如果用在方括号内,“^”表CZ惌匚w的字W。例如,囑֛的正则表辑ּ匚w所有单词,但以“X”字母开头的单词除外? |
假设要从格式为“June 26, 1951”的生日日期中提取出月䆾部分Q用来匹配该日期的正则表辑ּ可以如图五所C: |
图五Q匹配所有Moth DD,YYYY格式的日?/P> |
新出现的“\s”符hI白W号Q匹配所有的I白字符Q包括Tab字符。如果字W串正确匚wQ接下来如何提取出月份部分呢Q只需在月份周围加上一个圆括号创徏一个组Q然后用ORO APIQ本文后面详l讨论)提取出它的倹{修改后的正则表辑ּ如图六所C: |
囑օQ匹配所有Month DD,YYYY格式的日期,定义月䆾gؓW一个组 |
为简便v见,你可以用一些ؓ常见正则表达式创建的快捷W号。如表二所C: |
例如Q在前面C会安全L的例子中Q所有出现“[0-9]”的地方我们都可以用“\d”。修改后的正则表辑ּ如图七所C: |
图七Q匹配所?23-12-1234格式的社会安全号?/P> |
有许多源代码开攄正则表达式库可供JavaE序员用,而且它们中的许多支持Perl 5兼容的正则表辑ּ语法。我在这里选用的是Jakarta-ORO正则表达式库Q它是最全面的正则表辑ּAPI之一Q而且它与Perl 5正则表达式完全兼宏V另外,它也是优化得最好的API之一? |
Jakarta-ORO库以前叫做OROMatcherQDaniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下蝲它? |
我首先将要介l用Jakarta-ORO库时你必d建和讉K的对象,然后介绍如何使用Jakarta-ORO API? |
首先Q创Z个Perl5Compilercȝ实例Qƈ把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实玎ͼ允许你把正则表达式编译成用来匚w的Pattern对象? |
要把正则表达式编译成Pattern对象Q调用compiler对象的compile()ҎQƈ在调用参C指定正则表达式。例如,你可以按照下面这U方式编译正则表辑ּ“t[aeio]n”: |
默认情况下,~译器创Z个大写敏感的模式(patternQ。因此,上面代码~译得到的模式只匚w“tin”、“tan”?“ten”和“ton”,但不匚w“Tin”和“taN”。要创徏一个大写不敏感的模式Q你应该在调用编译器的时候指定一个额外的参数Q? |
创徏好Pattern对象之后Q你可以通过PatternMatchercȝ该Pattern对象q行模式匚w? |
PatternMatcher对象ҎPattern对象和字W串q行匚w查。你要实例化一个Perl5Matchercdƈ把结果赋值给PatternMatcher接口。Perl5MatchercLPatternMatcher接口的一个实玎ͼ它根据Perl 5正则表达式语法进行模式匹配: |
使用PatternMatcher对象Q你可以用多个方法进行匹配操作,q些Ҏ的第一个参数都是需要根据正则表辑ּq行匚w的字W串Q? |
· boolean matches(String input, Pattern pattern)Q当输入字符串和正则表达式要_匚w时用。换句话_正则表达式必d整地描述输入字符丌Ӏ? |
· boolean matchesPrefix(String input, Pattern pattern)Q当正则表达式匹配输入字W串起始部分时用? |
· boolean contains(String input, Pattern pattern)Q当正则表达式要匚w输入字符串的一部分时用(卻I它必L一个子Ԍ? |
另外Q在上面三个Ҏ调用中,你还可以用PatternMatcherInput对象作ؓ参数替代String对象Q这Ӟ你可以从字符串中最后一ơ匹配的位置开始l进行匹配。当字符串可能有多个子串匚wl定的正则表辑ּӞ用PatternMatcherInput对象作ؓ参数很有用了。用PatternMatcherInput对象作ؓ参数替代StringӞ上述三个Ҏ的语法如下: |
· boolean matches(PatternMatcherInput input, Pattern pattern) |
· boolean matchesPrefix(PatternMatcherInput input, Pattern pattern) |
· boolean contains(PatternMatcherInput input, Pattern pattern) |
下面我们来看看Jakarta-ORO库的一些应用实例? |
dQ分析一个Web服务器日志文Ӟ定每一个用戯在网站上的时间。在典型的BEA WebLogic日志文g中,日志记录的格式如下: |
分析q个日志记录Q可以发玎ͼ要从q个日志文g提取的内Ҏ两项QIP地址和页面访问时间。你可以用分l符P圆括P从日志记录提取出IP地址和时间标记? |
首先我们来看看IP地址。IP地址?个字节构成,每一个字节的值在0?55之间Q各个字节通过一个句点分隔。因此,IP地址中的每一个字节有臛_一个、最多三个数字。图八显CZ为IP地址~写的正则表辑ּQ? |
IP地址中的句点字符必须q行转义处理Q前面加上“\”)Q因为IP地址中的句点h它本来的含义Q而不是采用正则表辑ּ语法中的Ҏ含义。句点在正则表达式中的特D含义本文前面已l介l? |
日志记录的时间部分由一Ҏ括号包围。你可以按照如下思\提取出方括号里面的所有内容:首先搜烦起始Ҏ号字W(“[”)Q提取出所有不过l束Ҏ号字W(“]”)的内容,向前L直至扑ֈl束Ҏ号字W。图九显CZq部分的正则表达式? |
现在Q把上述两个正则表达式加上分l符P圆括P后合q成单个表达式,q样可以从日志记录提取出IP地址和时间。注意,Z匚w? -”(但不提取它)Q正则表辑ּ中间加入了“\s-\s-\s”。完整的正则表达式如囑֍所C? |
现在正则表达式已l编写完毕,接下来可以编写用正则表辑ּ库的Java代码了? |
Z用Jakarta-ORO库,首先创徏正则表达式字W串和待分析的日志记录字W串Q? |
q里使用的正则表辑ּ与图十的正则表达式差不多完全相同Q但有一点例外:在Java中,你必d每一个向前的斜杠Q“\”)q行转义处理。图十不是Java的表CŞ式,所以我们要在每个“\”前面加上一个“\”以免出现编译错误。遗憄是,转义处理q程很容易出现错误,所以应该小心}慎。你可以首先输入未经转义处理的正则表辑ּQ然后从左到右依ơ把每一个“\”替换成“\\”。如果要复检Q你可以试着把它输出到屏q上? |
初始化字W串之后Q实例化PatternCompiler对象Q用PatternCompiler~译正则表达式创Z个Pattern对象Q? |
现在Q创建PatternMatcher对象Q调用PatternMatcher接口的contain()Ҏ查匹配情况: |
接下来,利用PatternMatcher接口q回的MatchResult对象Q输出匹配的l。由于logEntry字符串包含匹配的内容Q你可以看到cd下面的输出: |
下面一个Q务是分析HTML面内FONT标记的所有属性。HTML面内典型的FONT标记如下所C: |
在这U情况下Q我你用两个正则表辑ּ。第一个如囑֍一所C,它从字体标记提取出?face="Arial, Serif" size="+2" color="red"”? |
W二个正则表辑ּ如图十二所C,它把各个属性分割成名字-值对? |
现在我们来看看完成这个Q务的Java代码。首先创Z个正则表辑ּ字符Ԍ用Perl5Compiler把它们编译成Pattern对象。编译正则表辑ּ的时候,指定Perl5Compiler.CASE_INSENSITIVE_MASK选项Q得匹配操作不区分大小写? |
接下来,创徏一个执行匹配操作的Perl5Matcher对象? |
假设有一个Stringcd的变量htmlQ它代表了HTML文g中的一行内宏V如果html字符串包含FONT标记Q匹配器返回true。此Ӟ你可以用匚w器对象返回的MatchResult对象获得W一个组Q它包含了FONT的所有属性: |
接下来创Z个PatternMatcherInput对象。这个对象允怽从最后一ơ匹配的位置开始l进行匹配操作,因此Q它很适合于提取FONT标记内属性的名字-值对。创建PatternMatcherInput对象Q以参数形式传入待匹配的字符丌Ӏ然后,用匹配器实例提取出每一个FONT的属性。这通过指定PatternMatcherInput对象Q而不是字W串对象Qؓ参数Q反复地调用PatternMatcher对象的contains()Ҏ完成。PatternMatcherInput对象之中的每一ơP代将把它内部的指针向前移动,下一ơ检将从前一ơ匹配位|的后面开始? |
下面我们来看看另一个处理HTML的例子。这一ơ,我们假定Web服务器从widgets.acme.comUd了newserver.acme.com。现在你要修改一些页面中的链接: |
如果能够匚wq个正则表达式,你可以用下面的内Ҏ换图十三的链接: |
注意#字符的后面加上了$1。Perl正则表达式语法用$1?2{表C已l匹配且提取出来的组。图十三的表辑ּ把所有作Z个组匚w和提取出来的内容附加到链接的后面? |
现在Q返回Java。就象前面我们所做的那样Q你必须创徏试字符Ԍ创徏把正则表辑ּ~译到Pattern对象所必需的对象,以及创徏一个PatternMatcher对象Q?IMG src="file:///E:/DEVELOP/Language/JAVA/Articles/JS/CSDN技术中?20Java正则表达式详?files/01_7_31_4_v.jpg" border=0> |
接下来,用com.oroinc.text.regex包Utilcȝsubstitute()静态方法进行替换,输出l果字符Ԍ |
q个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象Q它军_了替换操作如何进行。本例用的是Perl5Substitution对象Q它能够q行Perl5风格的替换。第四个参数是想要进行替换操作的字符Ԍ最后一个参数允许指定是否替换模式的所有匹配子ԌUtil.SUBSTITUTE_ALLQ,或只替换指定的次数? |
【结束语?/B>在这文章中Q我Z介绍了正则表辑ּ的强大功能。只要正运用,正则表达式能够在字符串提取和文本修改中v到很大的作用。另外,我还介绍了如何在JavaE序中通过Jakarta-ORO库利用正则表辑ּ。至于最l采用老式的字W串处理方式Q用StringTokenizerQcharAtQ和substringQ,q是采用正则表达式,q就有待你自己决定了?/TD> |

]]> - ECLIPSE初试http://www.tkk7.com/Microhelp/articles/6655.htmlMicrohelpMicrohelpFri, 24 Jun 2005 02:07:00 GMThttp://www.tkk7.com/Microhelp/articles/6655.htmlhttp://www.tkk7.com/Microhelp/comments/6655.htmlhttp://www.tkk7.com/Microhelp/articles/6655.html#Feedback0http://www.tkk7.com/Microhelp/comments/commentRss/6655.htmlhttp://www.tkk7.com/Microhelp/services/trackbacks/6655.htmlECLIPSE 使用初步
1 集成lomboz?SPAN lang=EN-US>tomcat
|上有很多文?SPAN lang=EN-US>,不再赘诉,只要把相应的插g下蝲后解?SPAN lang=EN-US>,拯?SPAN lang=EN-US>eclipse对应的目录即?SPAN lang=EN-US>.如果安装正确在工具栏上有相应的图标(如图).

2 创徏工程
FILE->NEW->PROJECT

选择Java Project,Next

填写工程名称,选择分开的源文g和输出文?SPAN lang=EN-US>.Next->Finish.
叛_src文g?SPAN lang=EN-US>,新徏一?SPAN lang=EN-US>package,名称?/FONT>world

工程l构可以在导航栏中看?SPAN lang=EN-US>(如图)

叛_world,新徏一?SPAN lang=EN-US>class,名称?SPAN lang=EN-US>Helloworld

选择菜单project,选择Build Automatically,保存后可以看到在bin文g多w出现相应?SPAN lang=EN-US>class文g.
?SPAN lang=EN-US>mainҎ中增加如下内?SPAN lang=EN-US>:
int testValue = 0;
System.out.println("Hello World");
testValue = testValue + 2;
System.out.println("testValue:" + testValue);
菜单run->run?/SPAN>

双击Configuration里的Java Application.点击Run按钮.可以看到Console里的输出如下:

3.断点试
双击W一句话左侧,或者右击选择Toggle Breakpoint.d断点.然后选择Debug.可以?SPAN lang=EN-US>F6逐步调试,可以观察testValue的?SPAN lang=EN-US>,和看?SPAN lang=EN-US>Console的输?SPAN lang=EN-US>.
4.Junit的?SPAN lang=EN-US>
首先我们l?SPAN lang=EN-US>HellocL加一?SPAN lang=EN-US>abs()ҎQ作用是q回l对?SPAN lang=EN-US>
public int abs(int n){
return n>0?n:(-n);
}
选中HelloWorld.javaQ右键点击,选择New->JUnit Test CaseQ?SPAN lang=EN-US>
Eclipse在询问是否添?/SPAN>junit.jar包之后,定后新Z?/SPAN>HelloworldTestc,用来试HelloworldcR?/SPAN>
选中setUp()?/SPAN>tearDown()Q然后点几Z?/SPAN>Next”:

选择要测试的Ҏ,在前面打?/SPAN>.

再在HelloWorldtest中添加测试代?/SPAN>:

点击Run as Junit,左侧D栏切换到Junit.如果试通过,ؓl色昄.
5.dtomcat应用E序

按照向导完成卛_.可以看到?/SPAN>server.xml中增加了如下内容:
<Context path="/testApp" reloadable="true" docBase="D:\eclipse\workspace\testApp" workDir="D:\eclipse\workspace\testApp\work\org\apache\jsp" />
如果叛_srcd包和cȝ?/SPAN>,保存后会自动d?/SPAN>classes?/SPAN>.
叛_testApp新徏文gindex.jsp,d如下内容:
<%@ page contentType="text/html;charset=GBK"%>
<html>
<head>
<title>
Helloworld
</title>
</head>
<body>
Helloworld!
</body>
</html>
然后启动tomcat,在浏览器中输?SPAN lang=EN-US>http://127.0.0.1:8080/testApp/index.jsp,卛_看到index的内容了.
如何创徏JAR?SPAN lang=EN-US>:
叛_工程,导出?SPAN lang=EN-US>JAR

]]>- 一个简单的STRUTS例子http://www.tkk7.com/Microhelp/articles/6651.htmlMicrohelpMicrohelpFri, 24 Jun 2005 01:38:00 GMThttp://www.tkk7.com/Microhelp/articles/6651.htmlhttp://www.tkk7.com/Microhelp/comments/6651.htmlhttp://www.tkk7.com/Microhelp/articles/6651.html#Feedback0http://www.tkk7.com/Microhelp/comments/commentRss/6651.htmlhttp://www.tkk7.com/Microhelp/services/trackbacks/6651.html阅读全文

]]> - 如何建立Tomcat的连接池http://www.tkk7.com/Microhelp/articles/6650.htmlMicrohelpMicrohelpFri, 24 Jun 2005 01:34:00 GMThttp://www.tkk7.com/Microhelp/articles/6650.htmlhttp://www.tkk7.com/Microhelp/comments/6650.htmlhttp://www.tkk7.com/Microhelp/articles/6650.html#Feedback0http://www.tkk7.com/Microhelp/comments/commentRss/6650.htmlhttp://www.tkk7.com/Microhelp/services/trackbacks/6650.html阅读全文

]]> - ANT的?/title>http://www.tkk7.com/Microhelp/articles/6648.htmlMicrohelpMicrohelpFri, 24 Jun 2005 01:23:00 GMThttp://www.tkk7.com/Microhelp/articles/6648.htmlhttp://www.tkk7.com/Microhelp/comments/6648.htmlhttp://www.tkk7.com/Microhelp/articles/6648.html#Feedback0http://www.tkk7.com/Microhelp/comments/commentRss/6648.htmlhttp://www.tkk7.com/Microhelp/services/trackbacks/6648.html1?SPAN style="FONT: 7pt 'Times New Roman'"> 下蝲ANT,解压 讄ANT_HOME压好的目录?SPAN lang=EN-US>
2?SPAN style="FONT: 7pt 'Times New Roman'"> 讄JAVA_HOME
3?SPAN style="FONT: 7pt 'Times New Roman'"> ?SPAN lang=EN-US>bin目录加入PATH环境变量
4?SPAN style="FONT: 7pt 'Times New Roman'"> ~写BUILD.XML文g?SPAN lang=EN-US>
<project name="MyProject" default="dist" basedir=".">
<description>
simple example build file
</description>
<!-- set global properties for this build -->
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init"
description="compile the source " >
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile"
description="generate the distribution" >
<!-- Create the distribution directory -->
<mkdir dir="${dist}/lib"/>
<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
<jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
</target>
<target name="clean"
description="clean up" >
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
</project>

]]> - Jdbcq接Mysqlhttp://www.tkk7.com/Microhelp/articles/6647.htmlMicrohelpMicrohelpFri, 24 Jun 2005 01:12:00 GMThttp://www.tkk7.com/Microhelp/articles/6647.htmlhttp://www.tkk7.com/Microhelp/comments/6647.htmlhttp://www.tkk7.com/Microhelp/articles/6647.html#Feedback0http://www.tkk7.com/Microhelp/comments/commentRss/6647.htmlhttp://www.tkk7.com/Microhelp/services/trackbacks/6647.html安装JDBC驱动MySQL Connector/J 3.1.6
下蝲:http://dev.mysql.com/downloads/index.html
解压后将其中的mysql-connector-java-3.1.6-bin.jar复制到D:\Tomcat 5.5\common\lib或者D:\Java\jdk1.5.0_01\jre\lib\ext或者其他地?则需要设|classpath指向该\?
试代码如下Q?/FONT>
<%@ page contentType="text/html;charset=GB2312"%>
<%@ page language="java" import="java.sql.*"%>
<%
String mySqlDriver = "org.gjt.mm.mysql.Driver";
String url = "jdbc:mysql://localhost/test";//数据库连?BR> Connection conn;
Class.forName(mySqlDriver);
conn = DriverManager.getConnection( url,"root","cleversoft");//用户名与密码
if(conn==null){
System.out.println("get Conn Error");
}
Statement stmt=conn.createStatement();
ResultSet rs=null;
rs=stmt.executeQuery("select * from newtable");
while(rs.next())
{//循环昄记录
%>
id:<%=rs.getString("id")%> name1:<%=rs.getString("name1")%> name2:(<%=rs.getString("name2")%>)
<%="<br>"%>
<%
}
rs.close();
stmt.close();
conn.close();
%>

]]> - Jdbcq接Sqlserverhttp://www.tkk7.com/Microhelp/articles/6646.htmlMicrohelpMicrohelpFri, 24 Jun 2005 01:06:00 GMThttp://www.tkk7.com/Microhelp/articles/6646.htmlhttp://www.tkk7.com/Microhelp/comments/6646.htmlhttp://www.tkk7.com/Microhelp/articles/6646.html#Feedback0http://www.tkk7.com/Microhelp/comments/commentRss/6646.htmlhttp://www.tkk7.com/Microhelp/services/trackbacks/6646.html
1、下载sqlserver驱动for jdbc
2、安装驱?BR>3、在C:\Program Files\Microsoft SQL Server 2000 Driver for JDBC下将三个jar文g拯到Tomcat\common\lib?BR>
试E序如下Q?BR><%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.sql.*"%>
<html>
<body>
<%Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs";
//pubsZ的数据库?nbsp;
String user="sa";
String password="sa";
Connection conn= DriverManager.getConnection(url,user,password);
Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
String sql="select * from test";
ResultSet rs=stmt.executeQuery(sql);
while(rs.next()) {%>
您的W一个字D内容ؓQ?lt;%=rs.getString(1)%>
您的W二个字D内容ؓQ?lt;%=rs.getString(2)%>
<%}%>
<%out.print("数据库操作成功,恭喜?);%>
<%rs.close();
stmt.close();
conn.close();
%>
</body>
</html>

]]>
վ֩ģ壺
AVƷ
|
þþƷҹɫA|
˳ƵƵ|
ŮþþŮ|
Ѹվ߹ۿ|
ĻƷƵ|
þþƷAV뽿ɫ|
պƵ|
ؼAƬëƬѿ|
Ļ|
˾þۺӰԺ|
ԻƵ30ӳ|
ҹAV|
һ|
ۺɫͼƬ|
Ƶ|
91þþƷֱ|
ӰĻ|
Ƶ߹ۿ|
98ƷȫѹۿƵ|
ţţ߾ƷƵۿ|
ëƬר|
ƷƷһ
|
AרAV|
Ѹ߹ۿ|
Ʒվ߹ۿѴý|
˳ɵӰվþ|
˵Ӱվwww|
ĻþƷѹۿ|
Ƶһ|
þþѵľƷ|
Ʒ˳վ|
ŮѾƷëƬ|
ѵӰվ|
ŷƵ|
ҹƷҹ³˿Ƭ|
þþþѹۿ|
ëƬѹۿƵ|
˾Ʒ|
þþùƷ|
һaȫƵëƬ|