ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>av播放在线,亚洲精品一二,亚洲精品免费视频http://www.aygfsteel.com/wml/category/12663.htmlzh-cnTue, 27 Feb 2007 12:07:43 GMTTue, 27 Feb 2007 12:07:43 GMT60JSP 2.0 ç‰ÒŽ(gu¨©)€?/title><link>http://www.aygfsteel.com/wml/articles/59379.html</link><dc:creator>wml</dc:creator><author>wml</author><pubDate>Fri, 21 Jul 2006 03:08:00 GMT</pubDate><guid>http://www.aygfsteel.com/wml/articles/59379.html</guid><description><![CDATA[ <p align="left">期待已久的日子即ž®†åˆ°æ? 最新版<a >JavaServer Pages (JSP)</a>2.0规范卛_°†å’Œå…¶ä»–çš„J2EE 1.4一同发布。新的JSP版本有一个新的飞跃,采用了新的方式:(x¨¬)ç”׃ºŽæ–°çš„语言表达式(Expression LanguageåQŒä»¥ä¸‹ç®€¿UîCØ“(f¨´)ELåQ‰å’ŒJSP标准标签库(JSP Standard Tag Library ,以下½Ž€¿UîCØ“(f¨´)JSTLåQ‰è¿™ä¸¤ç§æ–°çš„æ–¹å¼åQŒåœ¨™åµé¢ä¸­ä¸éœ€è¦ç”¨java,对于开发一般的应用来说åQŒé‡ç”¨ä»£ç å˜å¾—更加容易。更具体来说åQŒJSP 2.0带来了以下的优点åQ?/p> <ul> <li>首次被JSTL 1.0引入的EL现在被合òq¶åˆ°JSP规范中,ž®±åƒåº”用template text一样地使用所有的标准的和定制的组件ã€? </li> <li>æ–°çš„EL已经被扩展,具备一个函数调用机åˆÓž¼ŒJSTL1.1整合了一¾pÕdˆ—¾lå¸¸éœ€è¦ä‹É用的函数ã€? </li> <li>新增加的变量和servlet 规范定义的错误处理机制被更好地组¾l‡è“v来。通过新增加的变量åQŒJSP error pages 现在可以提供更多的错误信息ã€? </li> <li>容噍因䨓(f¨´)更加严格的语法检查可以更å®ÒŽ(gu¨©)˜“地找出发生的错误ã€? </li> <li>所有的J2EE 1.4规范åQˆåŒ…括JSP 2.0 å’?Servlet 2.4åQ‰ï¼Œä¸ÞZº†å£°æ˜Žéƒ¨çÖv的规则描˜q°è€Œåº”用了XML schema。这æ ïL(f¨¥ng)š„好处之一是你现在可以通过ä»ÖM½•™åºåºåˆ—出web.xmlæ–‡äšg中的描述。JSP 2.0也增加了一些新的配¾|®é€‰é¡¹ç”¨äºŽéƒ¨çÖv描述åQŒå…è®?d¨¡ng)R€šè¿‡å…¨å±€çš„配¾|®æ¥ä»£æ›¿åŸÞZºŽæ¯é¡µçš„配¾|®ã€? </li> <li>ç”׃ºŽæ›´å…·ä¼¸ç¾ƒæ€§çš„规则和新的自定义action elementåQŒçŽ°åœ¨å°±åƒç¼–å†™XMLæ–‡äšgä¸€æ øP¼Œ¾~–写JSP™åµé¢å˜å¾—更加å®ÒŽ(gu¨©)˜“ã€? </li> <li>定制的标½{‘Öº“现在可以开发成一¾pÕdˆ—的标½{¾æ–‡ä»Óž¼ˆå…ähœ‰JSP元素的文本文ä»Óž¼‰åQŒæ ‡½{‘Ö¤„理器可以使用新的、简化的标签处理器的API。与此同æ—Óž¼Œæ–°è§„范加入了一些新的特性,比如åQšæ”¯æŒåœ¨jsp™åµé¢ä¸Šæ˜¾½CºåŠ¨æ€å±žæ€§åˆ—è¡¨å’Œå¯æ‰§è¡Œç‰‡æ–­å±žæ€§ã€?</li> </ul> <p align="left">在众多的书籍中,˜q™æ˜¯å¤´ä¸€ä¸ªè®²è§£JSP 2.0新特性的文章。在˜q™ä¸€éƒ¨åˆ†åQŒæˆ‘们将看到和EL相关的信息,其他的新ç‰ÒŽ(gu¨©)€§ç•™åˆ°åŽé¢ã€‚在˜q™é‡Œæˆ‘假定读者已¾lç†Ÿæ‚(zh¨¨n)‰JSP 1.2åQŒè€Œä¸”臛_°‘听说˜q‡JSTLã€?/p> <p align="left">你可能对˜q™æœ¬½W¬ä¸‰ç‰ˆçš„《JavaServer Pages》感兴趣。这本书中,我尽可能在细节上讲述所有的内容åQŒè€Œä¸”òq¶ä¸è®¤äØ“(f¨´)你对JSP或者JSTL了解一切。这本书预计åœ?003òq?2æœ?出版åQŒä½†æ˜¯ä½ çŽ°åœ¨å¯ä»¥åœ?a >http://www.amazon.com</a>、Barnes&NobleåQŒæˆ–者其他在¾U¿ä¹¦åº—预订ã€?/p> <p align="left"> <strong>EL(</strong> <strong>The Expression Language</strong> <strong>)</strong> <strong> </strong> </p> <p align="left">如果˜q‡åŽ»ä½¿ç”¨˜q‡JSTLåQŒé‚£ä¹ˆä½ å¯èƒ½å·²ç»ç†Ÿæ?zh¨¨n)‰äº†EL。EL在JSTL 1.0规范中被引入åQŒç”¨æ¥åœ¨˜qè¡ŒæœŸé—´å¯¹Java表达式中action element属性赋值提供另一¿Ué€‰æ‹©ã€‚当JSTL EL已经非常˜q…速的‹¹è¡Œèµäh¥æƒ…况下,˜q˜æ˜¯å­˜åœ¨ä¸€ä¸ªé—®é¢˜ï¼š(x¨¬) JSTL EL 表达式仅仅可以与JSTLå’Œcustom action一起ä‹É用,怎样才能使用非标准API对EL表达式求å€û|¼Ÿ</p> <p align="left">JSP 2.0ä¸?JSP容器自己可以理解EL表达式。这使你在所有过åŽÕdªèƒ½åº”用Java表达式的地方应用EL表达式成为可能,比如åQšæ ‡å‡†å’Œå®šåˆ¶action的属性å€û|¼Œæ¨¡æ¿æ–‡æœ¬ã€?/p> <p align="left">在我们看具体的例子前åQŒè®©æˆ‘们更进一步的看看什么是EL。EL是从JavaScript中获得启发的一¿Uè¯­­a€åQŒXPath(一¿Uç”¨æ¥è®¿é—®XML文档的语­a€)åQŒä½†æ˜¯EL在对变量的null值和执行更多数据¾cÕdž‹çš„自动类型è{换的处理上更加宽松。这些新ç‰ÒŽ(gu¨©)€§å¯¹äºŽweb应用非常重要åQŒåœ¨˜q™äº›åº”用中输入通常通过html表单的request parameter来得到。这些参数可能仅仅在某些è¯äh±‚下才能体现出来,而且‹¹è§ˆå™¨ç»å¸¸å°†request parameterä½œäØ“(f¨´)文本发送,然而应用程序经帔Rœ€è¦æŠŠä»–ä»¬ä½œäØ“(f¨´)æ•°å­—¾cÕdž‹ã€å¸ƒ?y¨­u)®”(d¨¡ng)类型(true 或è€?falseåQ‰æ¥ä½¿ç”¨ã€‚通过ELåQŒä½ æ ÒŽ(gu¨©)œ¬ž®±å¾ˆž®‘需要关心缺ž®‘某些参数的值或者类型è{换ã€?/p> <p align="left">一个EL表达式包含变量和操作½W¦ã€‚ä“Q何存储在某个JSP作用范围(如:(x¨¬)pageã€?request、session、application)çš„beanèƒ½è¢«ä½œäØ“(f¨´)一个EL变量来ä‹É用。另外,EL支持以下预定义的变量åQ?/p> <table cellspacing="0" cellpadding="0" border="1"> <tbody> <tr> <td> <p align="center"> <strong>变量名称</strong> </p> </td> <td> <p align="center"> <strong>说明</strong> </p> </td> </tr> <tr> <td valign="top"> <p align="left">pageScope</p> </td> <td> <p align="left">一个包含所有page scope范围的变量集å?(a java.util.Map)</p> </td> </tr> <tr> <td valign="top"> <p align="left">requestScope</p> </td> <td> <p align="left">一个包含所有request scope范围的变量集å?(a java.util.Map)</p> </td> </tr> <tr> <td valign="top"> <p align="left">sessionScope</p> </td> <td> <p align="left">一个包含所有session scope范围的变量集å?(a java.util.Map)</p> </td> </tr> <tr> <td valign="top"> <p align="left">applicationScope</p> </td> <td> <p align="left">一个包含所有application scope范围的变量集å?(a java.util.Map)</p> </td> </tr> <tr> <td valign="top"> <p align="left">param</p> </td> <td> <p align="left">一个包含所有请求参数的集合 (a java.util.Map)åQŒé€šè¿‡æ¯ä¸ªå‚数对应一个String值的方式赋å€?/p> </td> </tr> <tr> <td valign="top"> <p align="left">paramValues</p> </td> <td> <p align="left">一个包含所有请求参数的集合 (a java.util.Map)åQŒé€šè¿‡æ¯ä¸ªå‚数对应一个String数组的方式赋å€?/p> </td> </tr> <tr> <td valign="top"> <p align="left">header</p> </td> <td> <p align="left">一个包含所有请求的头信息的集合åQ?(a java.util.Map) ,通过每个头信息对应一个String值的方式赋å€?/p> </td> </tr> <tr> <td valign="top"> <p align="left">headerValues</p> </td> <td> <p align="left">一个包含所有请求的头信息的集合 (a java.util.Map) åQŒé€šè¿‡æ¯ä¸ªå¤´ä¿¡æ¯çš„值都保存在一个String数组的方式赋å€?/p> </td> </tr> <tr> <td valign="top"> <p align="left">cookie</p> </td> <td> <p align="left">一个包含所有请求的 cookie集合 (a java.util.Map)åQ?  通过每一个cookieåQˆjavax.servlet.http.CookieåQ‰å¯¹åº”一个cookie值的方式赋å€?/p> </td> </tr> <tr> <td valign="top"> <p align="left">initParam</p> </td> <td> <p align="left">一个包含所有应用程序初始化参数的集å?a java.util.Map) åQŒé€šè¿‡æ¯ä¸ªå‚数分别对应一个String值的方式赋å€?/p> </td> </tr> <tr> <td valign="top"> <p align="left">pageContext</p> </td> <td> <p align="left">一个javax.servlet.jsp.PageContext¾cȝš„实例, 用来提供讉K—®ä¸åŒçš„请求数æ?/p> </td> </tr> </tbody> </table> <p align="left">操作½W¦æ˜qîCº†ä½ å¯¹å˜é‡æ‰€æœŸæœ›çš„æ“ä½œã€‚如果你之前曄¡»ä½¿ç”¨˜q‡ä“Q何编½E‹è¯­­a€çš„话åQŒåœ¨EL表达式中所使用的操作符对你来说可能看è“v来很熟æ?zh¨¨n)‰ã€‚因为它们和那些在大多数语言中所支持的操作符一栗÷€?/p> <table cellspacing="0" cellpadding="0" border="1"> <tbody> <tr> <td> <p align="center"> <strong>Operator</strong> </p> </td> <td> <p align="center"> <strong>Description</strong> </p> </td> </tr> <tr> <td valign="top"> <p align="left">.</p> </td> <td> <p align="left">讉K—®ä¸€ä¸ªbean属性或è€?Map entry</p> </td> </tr> <tr> <td valign="top"> <p align="left">[]</p> </td> <td> <p align="left">讉K—®ä¸€ä¸ªæ•°¾l„或者链表元ç´?/p> </td> </tr> <tr> <td valign="top"> <p align="left">()</p> </td> <td> <p align="left">对子表达式分¾l„,用来改变赋值顺åº?/p> </td> </tr> <tr> <td valign="top"> <p align="left">? :</p> </td> <td> <p align="left">条äšg语句åQŒæ¯”å¦? <em>条äšg</em> ? <em>ifTrue</em> : <em>ifFalse</em>.如果条äšg为真åQŒè¡¨è¾‘Ö¼å€égØ“(f¨´)前者,反之为后è€?/p> </td> </tr> <tr> <td valign="top"> <p align="left">+</p> </td> <td> <p align="left">æ•°å­¦˜qç®—½W¦ï¼ŒåŠ æ“ä½?/p> </td> </tr> <tr> <td valign="top"> <p align="left">-</p> </td> <td> <p align="left">æ•°å­¦˜qç®—½W¦ï¼Œå‡æ“ä½œæˆ–者对一个值取å?/p> </td> </tr> <tr> <td valign="top"> <p align="left">*</p> </td> <td> <p align="left">æ•°å­¦˜qç®—½W¦ï¼Œä¹˜æ“ä½?/p> </td> </tr> <tr> <td valign="top"> <p align="left">/ or div</p> </td> <td> <p align="left">æ•°å­¦˜qç®—½W¦ï¼Œé™¤æ“ä½?/p> </td> </tr> <tr> <td valign="top"> <p align="left">% or mod</p> </td> <td> <p align="left">æ•°å­¦˜qç®—½W¦ï¼Œæ¨¡æ“ä½?取余)</p> </td> </tr> <tr> <td valign="top"> <p align="left">== or eq</p> </td> <td> <p align="left">逻辑˜qç®—½W¦ï¼Œåˆ¤æ–­½W¦å·å·¦å³ä¸¤ç«¯æ˜¯å¦ç›¸ç­‰åQŒå¦‚果相½{‰è¿”回trueåQŒå¦åˆ™è¿”回false</p> </td> </tr> <tr> <td valign="top"> <p align="left">!= or ne</p> </td> <td> <p align="left">逻辑˜qç®—½W¦ï¼Œåˆ¤æ–­½W¦å·å·¦å³ä¸¤ç«¯æ˜¯å¦ä¸ç›¸½{‰ï¼Œå¦‚果不相½{‰è¿”回trueåQŒå¦åˆ™è¿”回false</p> </td> </tr> <tr> <td valign="top"> <p align="left">< or lt</p> </td> <td> <p align="left">逻辑˜qç®—½W¦ï¼Œåˆ¤æ–­½W¦å·å·¦è¾¹æ˜¯å¦ž®äºŽåŒ™¾¹åQŒå¦‚果小于返回trueåQŒå¦åˆ™è¿”回false</p> </td> </tr> <tr> <td valign="top"> <p align="left">> or gt</p> </td> <td> <p align="left">逻辑˜qç®—½W¦ï¼Œåˆ¤æ–­½W¦å·å·¦è¾¹æ˜¯å¦å¤§äºŽåŒ™¾¹åQŒå¦‚果大于返回trueåQŒå¦åˆ™è¿”回false</p> </td> </tr> <tr> <td valign="top"> <p align="left"><= or le</p> </td> <td> <p align="left">逻辑˜qç®—½W¦ï¼Œåˆ¤æ–­½W¦å·å·¦è¾¹æ˜¯å¦ž®äºŽæˆ–者等于右边,如果ž®äºŽæˆ–者等于返回trueåQŒå¦åˆ™è¿”回false</p> </td> </tr> <tr> <td valign="top"> <p align="left">>= or ge</p> </td> <td> <p align="left">逻辑˜qç®—½W¦ï¼Œåˆ¤æ–­½W¦å·å·¦è¾¹æ˜¯å¦å¤§äºŽæˆ–者等于右边,如果大于或者等于返回trueåQŒå¦åˆ™è¿”回false</p> </td> </tr> <tr> <td valign="top"> <p align="left">&& or and</p> </td> <td> <p align="left">逻辑˜qç®—½W¦ï¼Œä¸Žæ“ä½œèµ‹ã€‚如果左右两边同为true˜q”回trueåQŒå¦åˆ™è¿”回false</p> </td> </tr> <tr> <td valign="top"> <p align="left">|| or or</p> </td> <td> <p align="left">逻辑˜qç®—½W¦ï¼Œæˆ–操作赋。如果左右两è¾ÒŽ(gu¨©)œ‰ä»ÖM½•ä¸€è¾¹äØ“(f¨´)true˜q”回trueåQŒå¦åˆ™è¿”回false</p> </td> </tr> <tr> <td valign="top"> <p align="left">! or not</p> </td> <td> <p align="left">逻辑˜qç®—½W¦ï¼Œéžæ“ä½œèµ‹ã€‚如果对true取运½Ž—返回falseåQŒå¦åˆ™è¿”回true</p> </td> </tr> <tr> <td valign="top"> <p align="left">empty</p> </td> <td> <p align="left">ç”¨æ¥å¯¹ä¸€ä¸ªç©ºå˜é‡å€ÆD¿›è¡Œåˆ¤æ–? null、一个空String、空数组ã€?½IºMap、没有条目的Collection集合</p> </td> </tr> <tr> <td valign="top"> <p align="left"> <em>func</em>(<em>args</em>)</p> </td> <td> <p align="left">调用æ–ÒŽ(gu¨©)³•, <em>func</em>是方法名åQ?em>args</em>是参敎ͼŒå¯ä»¥æ²¡æœ‰åQŒæˆ–者有一个、多个参æ•?参数间用逗号隔开</p> </td> </tr> </tbody> </table> <p align="left">一个EL表达式可以包含:(x¨¬)数字、文本(在单引号或者双引号之间åQ‰ã€å¸ƒ?y¨­u)®”(d¨¡ng)倹{€null倹{€?/p> <p align="left">因䨓(f¨´)一个EL表达式可以出现在静态文本出现的地方åQŒå› æ­¤ä½ å¿…须告诉JSP容器它应该被当作一个EL表达式来处理。你可以通过使用定界½W¦æ¥åšåˆ°˜q™ä¸€ç‚V€‚一个EL表达式æ€ÀL˜¯ä»¥â€?{ }”来标记åQˆä¸€ä¸ªâ€?”符号和一个左花括å?双™Š±æ‹¬å·åQ‰ã€‚这里有一个ELè¡¨è¾¾å¼ï¼Œå®ƒå°†ä¸€ä¸ªå‘½åäØ“(f¨´)amount的变量加5åQ?/p> <p align="left">${amount + 5}</p> <p align="left">如果你想要将5加到一个beançš„property上,可以使用property讉K—®æ“ä½œ½W¦ï¼š(x¨¬)</p> <p align="left">${order.amount + 5}</p> <p align="left">在当前这个指定的bean或者collection集合中,Property讉K—®æ“ä½œ½W¦ï¼ˆä¸€ä¸ªâ€?â€œç¬¦åøP¼‰å‘Šè¯‰ELåŽÕd¯»æ‰‘֐å­—䨓(f¨´)amountçš„propertyã€?/p> <p align="left">${order['amount'] + 5}</p> <p align="left">在[]之间的值必™åÀL˜¯ä¸€ä¸ªproperty的名字(ž®±åƒä¸Šé¢çš„例子中那样åQ‰æˆ–者是一个保存property名字的变量(或者是一个完整的EL子表辑ּåQ‰ã€?/p> <p align="left">EL表达式可以被用来赋值给ä»ÖM½•标准的或者定制的JSPè¡ŒäØ“(f¨´)属性(action attributeåQ‰ï¼Œ˜q™äº›è¡ŒäØ“(f¨´)属性被标记为可以接受动态å€û|¼ˆæˆ–者请求期间的属性å€û|¼Œž®Þp±¡å®ƒè¢«æ­£å¼è°ƒç”¨ä¸€æ øP¼‰åQ?/p> <p align="left"><c:out value="${order.amount + 5}"/></p> <p align="left">在JSP 2.0之前åQŒä½ ä¸å¾—不ä‹É用Java表达式去¾l™ä¸€ä¸ªå±žæ€§åŠ¨æ€èµ‹å€¹{€‚在˜q‡åŽ»çš„å¾ˆå¤šå¹´ä¸­ï¼Œ˜q™å·²¾læˆä¸ø™¯­æ³•æØœä¹Þqš„一个普遍根源ã€?/p> <p align="left">最后,EL表达式可以在™åµé¢ä¸­å’Œæ¨¡æ¿ç›´æŽ¥æ··åˆä½¿ç”¨ã€‚当你生成HTMLòq¶ä¸”需要设¾|®ä¸€ä¸ªåŠ¨æ€å€¼ç»™ä¸€ä¸ªå±žæ€§çš„æ—¶å€™ï¼Œ˜q™éžå¸¸æ–¹ä¾¿ï¼š(x¨¬)</p> <p align="left"><input name="firstName" value="${customer.firstName}"></p> <p align="left">JSP 1.2中,你不得不使用JSTLçš?lt;c:out>来实现同æ ïL(f¨¥ng)š„事情åQŒæœ€åŽæŠŠå„种不同¾cÕdž‹çš„å…ƒç´ æØœåˆè“v来,˜q™å¯¼è‡´ç¨‹åºç†è§£è“v来非常的困难åQ?/p> <p align="left"><input name="firstName" </p> <p align="left">value="<c:out value="${customer.firstName}"/>" ></p> <p align="left"> </p> <h3>æ–°JSTL 1.1 Tag Library 标识½W?/h3> <p>JSTL1.1发布的是一个初¾U§çš„版本åQŒä¸»è¦ç›®çš„æ˜¯ç”¨æ¥æ•´åˆJSTLå’ŒJSP2.0 。最明显的变化是JSTL1.0 “孪生函数库”(一¾l„库用来接受EL表达式,另外一¾l„用来接受JAVA表达式)åQŒè€Œå®ƒä»¬å·²¾lè¢«ä¸€¾l„既可以用于EL表达式也可以用于JAVA表达式的函数库所代替ã€?/p> <p>在JSTL 1.1中ä‹É用以下标识符:</p> <table cellspacing="0" cellpadding="0" border="1"> <tbody> <tr> <td> <p align="center"> <strong>åº?/strong> <strong> </strong> </p> </td> <td> <p align="center"> <strong>URI</strong> <strong> </strong> </p> </td> <td> <p align="center"> <strong>前缀</strong> <strong> </strong> </p> </td> </tr> <tr> <td> <p>Core</p> </td> <td> <p> <em>http://java.sun.com/jsp/jstl/core</em> </p> </td> <td> <p>c</p> </td> </tr> <tr> <td> <p>XML processing</p> </td> <td> <p> <em>http://java.sun.com/jsp/jstl/xml</em> </p> </td> <td> <p>x</p> </td> </tr> <tr> <td> <p>I18N formatting</p> </td> <td> <p> <em>http://java.sun.com/jsp/jstl/fmt</em> </p> </td> <td> <p>fmt</p> </td> </tr> <tr> <td> <p>Database access</p> </td> <td> <p> <em>http://java.sun.com/jsp/jstl/sql</em> </p> </td> <td> <p>sql</p> </td> </tr> <tr> <td> <p>Functions</p> </td> <td> <p> <em>http://java.sun.com/jsp/jstl/functions</em> </p> </td> <td> <p>fn</p> </td> </tr> </tbody> </table> <p>如果你曾¾lä‹É用过JSTL1.0åQŒä½ å¯èƒ½ä¼?x¨¬)注意到新的标识½W¦å’Œæ—§çš„ELåº“æ ‡è¯•ç¬¦ä¸€æ¨¡ä¸€æ øP¼Œé™¤äº†åŠ å…¥äº†â€?jsp pathâ€?element。你也可能注意到在JSTL1.1中有一个库åQŒåŒ…含了EL的函数。我们稍后就ä¼?x¨¬)看到ã€?/p> <h3>一个新的EL操作½W?/h3> <p>在JSP™åµé¢ä¸­ä¸€ä¸ªéžå¸¸æ™®éçš„需求就是:(x¨¬)å½“æŸä¸ªæ¡ä»¶äØ“(f¨´)真时åQŒè¦åœ¨ç½‘™åµä¸­åŒ…含一些文字。在JSP1.2å’ŒJSTL1.1中,用具有代表性的<c:if>来实玎ͼŒä½†æ˜¯˜q™æ ·åšéžå¸¸ç¹çã€‚JSP2.0增加了一个新的条件操作符用于ELåQŒä»¥æ›´åŠ ä¼˜é›…çš„æ–¹å¼æ¥å¤„ç†˜q™æ ·çš„æƒ…å†üc(di¨£n)€‚这个条件操作符存在于很多编½E‹è¯­­a€ä¸­ï¼ˆæ¯”如åQšJava,C,JavaScriptåQ?因此你可能以前就见过它。它判断一个布?y¨­u)®”(d¨¡ng)的条äšgåQŒå½“条äšg为真或者假æ—Óž¼Œåˆ†åˆ«å–不同的¾l“æžœã€?/p> <p>一个能清楚说明它如何工作的例子åQ?/p> <p><select name="artist"><br /><option value="1" ${param.artist == 1 ? 'selected' : ''}><br />Vesica Pisces<br /><option value="2" ${param.artist == 2 ? 'selected' : ''}><br />Cortical Control<br /><option value="3" ${param.artist == 3 ? 'selected' : ''}><br />Vida Vierra<br /></select> </p> <p>在这里,我ä‹É用了EL表达式和条äšg操作½W¦æ¥é€‰æ‹©æ˜¯å¦åŒ…含 html 中的 “selected”属性,只有½W¦åˆæ¡äšgçš?“optionâ€?才被æ·ÕdŠ  “selectedâ€?属性。如果条ä»Óž¼ˆparam.artist==1åQ‰äØ“(f¨´)真时åQŒå‰é¢çš„“selectedâ€?才被æ·ÕdŠ åˆ°ç½‘™åµä¸­åQ›å¦åˆ™å°±æ·ÕdŠ åŽé¢çš„ï¼ˆåœ¨è¿™é‡Œæ˜¯½Iºå­—½W¦ä¸² ‘’)到页面中ã€?/p> <h3>EL函数</h3> <p>当EL从JSTL规范中移到JSP规范中,它ä‹É用了一个如何进行函数调用的技巧。这个EL函数语法非常½Ž€å•:(x¨¬)æ–ÒŽ(gu¨©)³•名,紧接着在圆括号中有一¾l„参敎ͼš(x¨¬)</p><%@ taglib prefix="fn"<br />uri="http://java.sun.com/jsp/jstl/functions" %><br />${fn:length(myCollection)} <p>˜q™æ˜¯ä¸€ä¸ªå±žäºŽæ ‡½{‘Öº“中的函数,òq¶ä¸”函数名字在页面中所包含的前¾~€è¦æŒ‡å®štaglib库。在˜q™ä¸ªä¾‹å­ä¸­ï¼Œæˆ‘ä‹É用了前缀fn,˜q™æ˜¯JSTL function库默认的前缀ã€?/p><p>标签库描˜q°ç¬¦åQˆTag Library Descriptor,TLDåQ‰å°†å‡½æ•°åç§°æ˜ å°„åˆîC¸€ä¸ªç”±JAVA实现的静态方法中åQ?/p><function><br /><description><br />Returns the number of items in a collection or the number of characters in a string.<br /></description><br /><name>length</name><br /><function-class><br />org.apache.taglibs.standard.functions.Functions<br /></function-class><br /><function-signature><br />int length(java.lang.Object)<br /></function-signature><br /></function> <p>在这里最有趣的elementæ˜?lt;function-signature>。它包含一个函数返回类型的声明åQŒé™æ€çš„æ–ÒŽ(gu¨©)³•的名字,在圆括号中声明该æ–ÒŽ(gu¨©)³•所有参数的¾cÕdž‹åQˆå¯ä»¥æ²¡æœ‰å‚数或者有多个åQŒå‚数间用逗号间隔开åQ‰ã€‚返回值类型和参数¾cÕdž‹å¿…须是java的原始类型(ObjectåQ‰æˆ–者是其他合法¾cÕdž‹ã€?/p><p>˜q™ä¸ªé™æ€æ–¹æ³?length()在Jakarta Taglibs标准库中用类ä¼égºŽä¸‹é¢çš„代码实现的åQ?/p>public static int length(Object obj)<br />throws JspTagException {<br />if (obj == null)<br />return 0;<br />if (obj instanceof String)<br />return ((String)obj).length();<br />if (obj instanceof Collection)<br />return ((Collection)obj).size();<br />if (obj instanceof Map)<br />return ((Map)obj).size(); <p>int count = 0;<br />if (obj instanceof Iterator) {<br />Iterator iter = (Iterator) obj;<br />count = 0;<br />while (iter.hasNext()) {<br />count++;<br />iter.next();<br />}<br />return count;<br />}<br />if (obj instanceof Enumeration) {<br />Enumeration enum = (Enumeration) obj;<br />count = 0;<br />while (enum.hasMoreElements()) {<br />count++;<br />enum.nextElement();<br />}<br />return count;<br />}<br />try {<br />count = Array.getLength(obj);<br />return count;<br />} catch (IllegalArgumentException ex) {}<br />throw new JspTagException("Unsupported type"));<br />}</p><p>ž®±åƒä½ æ‰€çœ‹åˆ°çš„,在那里没有什么出奇的地方。它是一个常规的静态方法,˜q™ä¸ªå‡½æ•°ä¸­é€šè¿‡å¯¹è¿è¡ŒæœŸä¸­çš„参数¾cÕdˆ«çš„判断,扑ևºå‚数的长度ã€?/p><p>除了在这个方法中使用的length()æ–ÒŽ(gu¨©)³•åQŒJSTL1.1æ ‡ç­¾åº“è¿˜åŒ…å«äº†è®¸å¤šå…¶å®ƒç»å¸æ€‹É用的函数åQ?/p><table cellspacing="0" cellpadding="0" border="1"><tbody><tr><td><p align="center"><strong>函数</strong><strong></strong></p></td><td><p align="center"><strong>描述</strong><strong></strong></p></td></tr><tr><td valign="top"><p>fn:contains(string, substring)</p></td><td><p>如果参数string中包含参数substringåQŒè¿”回true</p></td></tr><tr><td valign="top"><p>fn:containsIgnoreCase(string, substring)</p></td><td><p>如果参数string中包含参数substringåQˆå¿½ç•¥å¤§ž®å†™åQ‰ï¼Œ˜q”回true</p></td></tr><tr><td valign="top"><p>fn:endsWith(string, suffix)</p></td><td><p>如果参数 string 以参数suffix¾l“å°¾åQŒè¿”回true</p></td></tr><tr><td valign="top"><p>fn:escapeXml(string)</p></td><td><p>ž®†æœ‰ç‰ÒŽ(gu¨©)®Šæ„ä¹‰çš„XML (å’ŒHTML)转换为对应的XML character entity codeåQŒåƈ˜q”回</p></td></tr><tr><td valign="top"><p>fn:indexOf(string, substring)</p></td><td><p>˜q”回参数substring在参数string中第一‹Æ¡å‡ºçŽ°çš„ä½ç½®</p></td></tr><tr><td valign="top"><p>fn:join(array, separator)</p></td><td><p>ž®†ä¸€ä¸ªç»™å®šçš„æ•°ç»„array用给定的间隔½W¦separatorä¸²åœ¨ä¸€èµøP¼Œ¾l„成一个新的字½W¦ä¸²òq¶è¿”回ã€?/p></td></tr><tr><td valign="top"><p>fn:length(item)</p></td><td><p>˜q”回参数item中包含元素的数量。参数Item¾cÕdž‹æ˜¯æ•°¾l„、collection或者String。如果是String¾cÕdž‹,˜q”回值是String中的字符数ã€?/p></td></tr><tr><td valign="top"><p>fn:replace(string, before, after)</p></td><td valign="top"><p>˜q”回一个String对象。用参数after字符串替换参数string中所有出现参数before字符串的地方åQŒåƈ˜q”回替换后的¾l“æžœ</p></td></tr><tr><td valign="top"><p>fn:split(string, separator)</p></td><td><p>˜q”回一个数¾l„,以参数separator 为分割符分割参数stringåQŒåˆ†å‰²åŽçš„æ¯ä¸€éƒ¨åˆ†ž®±æ˜¯æ•°ç»„的一个元ç´?/p></td></tr><tr><td valign="top"><p>fn:startsWith(string, prefix)</p></td><td><p>如果参数string以参数prefixå¼€å¤ß_(d¨¢)¼Œ˜q”回true</p></td></tr><tr><td valign="top"><p>fn:substring(string, begin, end)</p></td><td><p>˜q”回参数string部分字符ä¸? 从参数begin开始到参数end位置åQŒåŒ…括end位置的字½W?/p></td></tr><tr><td valign="top"><p>fn:substringAfter(string, substring)</p></td><td><p>˜q”回参数substring在参数string中后面的那一部分字符ä¸?/p></td></tr><tr><td valign="top"><p>fn:substringBefore(string, substring)</p></td><td><p>˜q”回参数substring在参数string中前面的那一部分字符ä¸?/p></td></tr><tr><td valign="top"><p>fn:toLowerCase(string)</p></td><td><p>ž®†å‚æ•°stringæ‰€æœ‰çš„å­—ç¬¦å˜äØ“(f¨´)ž®å†™åQŒåƈž®†å…¶˜q”回</p></td></tr><tr><td valign="top"><p>fn:toUpperCase(string)</p></td><td><p>ž®†å‚æ•°stringæ‰€æœ‰çš„å­—ç¬¦å˜äØ“(f¨´)大写åQŒåƈž®†å…¶˜q”回</p></td></tr><tr><td valign="top"><p>fn:trim(string)</p></td><td><p>去除参数string 首尾的空æ û|¼Œòq¶å°†å…¶è¿”å›?/p></td></tr></tbody></table><h3>¾l“束语:(x¨¬)</h3><p>在这½‹‡æ–‡ç« ä¸­åQŒæˆ‘从EL讲到JSTL1.1规范、EL新特色和JSTL 1.1函数库。接下来的部分我ž®†è¦å‘Šè¯‰ä½ ï¼š(x¨¬)关于JSP error-page的改˜q›å’Œå¢žå¼ºåQ?jsp:id 属性带来的益处åQ›æ–°çš„配¾|®å±žæ€§æ˜q°ç¬¦åQ›JSP2.0如何使JSP操作XML变得更加å®ÒŽ(gu¨©)˜“åQ›è‡ªå®šä¹‰æ ‡ç­¾åº“的新特性ã€?/p><p>如果你想要尝试JSP2.0的新ç‰ÒŽ(gu¨©)€§ï¼Œæˆ‘徏议你使用Apache Tomcat 5。它是最早实çŽîCº†JSP新规范的容器之一。在公布最¾lˆç‰ˆæœ¬çš„JSP 2.0规范之前åQŒä¸€ä¸ªè¢«æ ‡è®°ä¸ºâ€œstable”版本的Tomcat是不能被发布的。但是最新的beta版已¾lè¢«è¯å®žæ˜¯éžå¸¸ç¨³å®šçš„åQŒä¸è¦ç†ä¼?x¨¬)beta版的标记。Tomcat 5åœ?a >the Jakarta Project site</a>可以下蝲ã€?/p><img src ="http://www.aygfsteel.com/wml/aggbug/59379.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/wml/" target="_blank">wml</a> 2006-07-21 11:08 <a href="http://www.aygfsteel.com/wml/articles/59379.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转:(x¨¬)Javascript--æ–‡äšg操作http://www.aygfsteel.com/wml/articles/58033.htmlwmlwmlThu, 13 Jul 2006 09:49:00 GMThttp://www.aygfsteel.com/wml/articles/58033.html
一、功能实现核心:(x¨¬)FileSystemObject 对象
要在javascript中实现文件操作功能,主要ž®±æ˜¯ä¾é FileSystemobject对象ã€?br />二、FileSystemObject¾~–程
使用FileSystemObject 对象˜q›è¡Œ¾~–程很简单,一般要¾lè¿‡å¦‚下的步骤:(x¨¬) 创徏FileSystemObject对象、应用相å…Ïx–¹æ³•、访问对象相兛_±žæ€?ã€?
åQˆä¸€åQ‰åˆ›å»ºFileSystemObject对象
创徏FileSystemObject对象的代码只è¦?行:(x¨¬)
var fso = new ActiveXObject("Scripting.FileSystemObject");
上述代码执行后,fsož®±æˆä¸ÞZ¸€ä¸ªFileSystemObject对象实例ã€?
åQˆäºŒåQ‰åº”用相å…Ïx–¹æ³?
创徏对象实例后,ž®±å¯ä»¥ä‹É用对象的相关æ–ÒŽ(gu¨©)³•了。比如,使用CreateTextFileæ–ÒŽ(gu¨©)³•创徏一个文本文ä»Óž¼š(x¨¬)
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f1 = fso.createtextfile("c:\\myjstest.txt",true");
åQˆä¸‰åQ‰è®¿é—®å¯¹è±¡ç›¸å…›_±žæ€?
要访问对象的相关属性,首先要徏立指向对象的句柄åQŒè¿™ž®Þp¦é€šè¿‡get¾pÕdˆ—æ–ÒŽ(gu¨©)³•实现åQšGetDrive负责获取驱动器信息,GetFolder负责获取文äšg夹信息,GetFile负责获取文äšg信息。比如,指向下面的代码后åQŒf1ž®±æˆä¸ºæŒ‡å‘文件c:\test.txt的句柄:(x¨¬)
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f1 = fso.GetFile("c:\\myjstest.txt");
然后åQŒä‹É用f1讉K—®å¯¹è±¡çš„相兛_±žæ€§ã€‚比如:(x¨¬)
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f1 = fso.GetFile("c:\\myjstest.txt");
alert("File last modified: " + f1.DateLastModified);
执行上面最后一句后åQŒå°†æ˜„¡¤ºc:\myjstest.txt的最后修æ”ÒŽ(gu¨©)—¥æœŸå±žæ€§å€¹{€?
但有一点请注意åQšå¯¹äºŽä‹É用createæ–ÒŽ(gu¨©)³•建立的对象,ž®×ƒ¸å¿…再使用getæ–ÒŽ(gu¨©)³•获取对象句柄了,˜q™æ—¶ç›´æŽ¥ä½¿ç”¨createæ–ÒŽ(gu¨©)³•建立的句柄名¿U°å°±å¯ä»¥åQ?
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f1 = fso.createtextfile("c:\\myjstest.txt",true");
alert("File last modified: " + f1.DateLastModified);
三、操作驱动器åQˆDrivesåQ?
使用FileSystemObject对象来编½E‹æ“ä½œé©±åЍ噍åQˆDrivesåQ‰å’Œæ–‡äšg夹(F(tu¨¢n)oldersåQ‰å¾ˆå®ÒŽ(gu¨©)˜“åQŒè¿™ž®Þp±¡åœ¨Windowsæ–‡äšg‹¹è§ˆå™¨ä¸­å¯ÒŽ(gu¨©)–‡ä»¶è¿›è¡Œäº¤äº’æ“ä½œä¸€æ øP¼Œæ¯”如åQšæ‹·è´ã€ç§»åŠ¨æ–‡ä»¶å¤¹åQŒèŽ·å–æ–‡ä»¶å¤¹çš„å±žæ€§ã€?
åQˆä¸€åQ‰Drives对象属æ€?
Drive对象负责攉™›†¾pȝ»Ÿä¸­çš„物理或逻辑驱动器资源内容,它具有如下属性:(x¨¬)
l TotalSizeåQšä»¥å­—节åQˆbyteåQ‰äØ“(f¨´)单位计算的驱动器大小ã€?
l AvailableSpace或FreeSpaceåQšä»¥å­—节åQˆbyteåQ‰äØ“(f¨´)单位计算的驱动器可用½Iºé—´ã€?
l DriveLetteråQšé©±åŠ¨å™¨å­—æ¯ã€?
l DriveTypeåQšé©±åЍ噍¾cÕdž‹åQŒå–å€égØ“(f¨´)åQšremovableåQˆç§»åŠ¨ä»‹è´¨ï¼‰ã€fixedåQˆå›ºå®šä»‹è´¨ï¼‰ã€networkåQˆç½‘¾lœèµ„源)、CD-ROM或者RAM盘ã€?
l SerialNumberåQšé©±åŠ¨å™¨çš„ç³»åˆ—ç ã€?
l FileSystemåQšæ‰€åœ¨é©±åŠ¨å™¨çš„æ–‡ä»¶ç³»¾lŸç±»åž‹ï¼Œå–å€égØ“(f¨´)FAT、FAT32å’ŒNTFSã€?
l IsReadyåQšé©±åŠ¨å™¨æ˜¯å¦å¯ç”¨ã€?
l ShareNameåQšå…±äº«å¿U°ã€?
l VolumeNameåQšå·æ ‡å¿U°ã€?
l Pathå’ŒRootFolderåQšé©±åŠ¨å™¨çš„èµ\径或者根目录名称ã€?
åQˆäºŒåQ‰Drive对象操作例程
下面的例½E‹æ˜¾½Cºé©±åЍ噍C的卷标、æ€Õd®¹é‡å’Œå¯ç”¨½Iºé—´½{‰ä¿¡æ¯ï¼š(x¨¬)
var fso, drv, s ="";
fso = new ActiveXObject("Scripting.FileSystemObject");
drv = fso.GetDrive(fso.GetDriveName("c:\\"));
s += "Drive C:" + " - ";
s += drv.VolumeName + "\n";
s += "Total Space: " + drv.TotalSize / 1024;
s += " Kb" + "\n";
s += "Free Space: " + drv.FreeSpace / 1024;
s += " Kb" + "\n";
alert(s);
四、操作文件夹åQˆF(tu¨¢n)oldersåQ?
涉及(qi¨¢ng)到文件夹的操作包括创建、移动、删除以å?qi¨¢ng)获取相兛_±žæ€§ã€?
Folder对象操作例程 :
下面的例½E‹å°†¾lƒä¹ (f¨¤n)èŽ·å–çˆ¶æ–‡ä»¶å¤¹åç§°ã€åˆ›å»ºæ–‡ä»¶å¤¹ã€åˆ é™¤æ–‡ä»¶å¤¹ã€åˆ¤æ–­æ˜¯å¦äØ“(f¨´)根目录等操作åQ?
var fso, fldr, s = "";
// 创徏FileSystemObject对象实例
fso = new ActiveXObject("Scripting.FileSystemObject");
// 获取Drive 对象
fldr = fso.GetFolder("c:\\");
// 昄¡¤ºçˆ¶ç›®å½•名¿U?
alert("Parent folder name is: " + fldr + "\n");
// 昄¡¤ºæ‰€åœ¨drive名称
alert("Contained on drive " + fldr.Drive + "\n");
// 判断是否为根目录
if (fldr.IsRootFolder)
alert("This is the root folder.");
else
alert("This folder isn't a root folder.");
alert("\n\n");
// 创徏新文件夹
fso.CreateFolder ("C:\\Bogus");
alert("Created folder C:\\Bogus" + "\n");
// 昄¡¤ºæ–‡äšg夹基¼‹€åç§°åQŒä¸åŒ…含路径å?
alert("Basename = " + fso.GetBaseName("c:\\bogus") + "\n");
// 删除创徏的文件夹
fso.DeleteFolder ("C:\\Bogus");
alert("Deleted folder C:\\Bogus" + "\n");
五、操作文ä»Óž¼ˆF(tu¨¢n)ilesåQ?
å¯ÒŽ(gu¨©)–‡ä»¶è¿›è¡Œçš„æ“ä½œè¦æ¯”以上介绍的驱动器åQˆDriveåQ‰å’Œæ–‡äšg夹(F(tu¨¢n)olderåQ‰æ“ä½œå¤æ‚些åQŒåŸºæœ¬ä¸Šåˆ†äØ“(f¨´)以下两个¾cÕdˆ«åQšå¯¹æ–‡äšg的创建、拷贝、移动、删除操作和å¯ÒŽ(gu¨©)–‡ä»¶å†…容的创徏、添加、删除和è¯Õd–操作。下面分别详¾l†ä»‹¾lã€?
åQˆä¸€åQ‰åˆ›å»ºæ–‡ä»?
一共有3¿Uæ–¹æ³•可用于创徏一个空文本文äšgåQŒè¿™¿Uæ–‡ä»¶æœ‰æ—¶å€™ä¹Ÿå«åšæ–‡æœ¬‹¹ï¼ˆtext streamåQ‰ã€?
½W¬ä¸€¿Uæ˜¯ä½¿ç”¨CreateTextFileæ–ÒŽ(gu¨©)³•。代码如下:(x¨¬)
var fso, f1;
fso = new ActiveXObject("Scripting.FileSystemObject");
f1 = fso.CreateTextFile("c:\\testfile.txt", true);
½W¬äºŒ¿Uæ˜¯ä½¿ç”¨OpenTextFileæ–ÒŽ(gu¨©)³•åQŒåƈæ·ÕdŠ ä¸ŠForWriting属性,ForWritingçš„å€égØ“(f¨´)2。代码如下:(x¨¬)
var fso, ts;
var ForWriting= 2;
fso = new ActiveXObject("Scripting.FileSystemObject");
ts = fso.OpenTextFile("c:\\test.txt", ForWriting, true);
½W¬ä¸‰¿Uæ˜¯ä½¿ç”¨OpenAsTextStreamæ–ÒŽ(gu¨©)³•åQŒåŒæ ¯‚¦è®„¡½®å¥½ForWriting属性。代码如下:(x¨¬)
var fso, f1, ts;
var ForWriting = 2;
fso = new ActiveXObject("Scripting.FileSystemObject");
fso.CreateTextFile ("c:\\test1.txt");
f1 = fso.GetFile("c:\\test1.txt");
ts = f1.OpenAsTextStream(ForWriting, true);
åQˆäºŒåQ‰æ·»åŠ æ•°æ®åˆ°æ–‡äšg
当文件被创徏后,一般要按照“打开文äšgåQ?gt;填写数据åQ?gt;关闭文äšg”的步骤实现æ·ÕdŠ æ•°æ®åˆ°æ–‡ä»¶çš„ç›®çš„ã€?
打开文äšg可ä‹É用FileSystemObject对象的OpenTextFileæ–ÒŽ(gu¨©)³•åQŒæˆ–者ä‹É用File对象的OpenAsTextStreamæ–ÒŽ(gu¨©)³•ã€?
填写数据要ä‹É用到TextStream对象的Write、WriteLine或者WriteBlankLinesæ–ÒŽ(gu¨©)³•。在同是实现写入数据的功能下åQŒè¿™3者的区别在于åQšWriteæ–ÒŽ(gu¨©)³•不在写入数据末尾æ·ÕdŠ æ–°æ¢è¡Œç¬¦åQŒW(xu¨¦)riteLineæ–ÒŽ(gu¨©)³•要在最后添加一个新换行½W¦ï¼Œè€ŒW(xu¨¦)riteBlankLines则增加一个或者多个空行ã€?
关闭文äšg可ä‹É用TextStream对象的Closeæ–ÒŽ(gu¨©)³•ã€?
åQˆä¸‰åQ‰åˆ›å»ºæ–‡ä»¶åŠ(qi¨¢ng)æ·ÕdŠ æ•°æ®ä¾‹ç¨‹
下面的代码将创徏文äšg、添加数据、关闭文件几个步骤结合è“v来进行应用:(x¨¬)
var fso, tf;
fso = new ActiveXObject("Scripting.FileSystemObject");
// 创徏新文�
tf = fso.CreateTextFile("c:\\testfile.txt", true);
// 填写数据åQŒåƈ增加换行½W?
tf.WriteLine("Testing 1, 2, 3.") ;
// 增加3个空�
tf.WriteBlankLines(3) ;
// 填写一行,不带换行½W?
tf.Write ("This is a test.");
// 关闭文äšg
tf.Close();
åQˆå››åQ‰è¯»å–文件内å®?
从文本文件中è¯Õd–数据要ä‹É用TextStream对象的Read、ReadLine或ReadAll æ–ÒŽ(gu¨©)³•。Readæ–ÒŽ(gu¨©)³•用于è¯Õd–æ–‡äšg中指定数量的字符åQ›ReadLineæ–ÒŽ(gu¨©)³•è¯Õd–一整行åQŒä½†ä¸åŒ…括换行符åQ›ReadAllæ–ÒŽ(gu¨©)³•则读取文本文件的整个内容。读取的内容存放于字½W¦ä¸²å˜é‡ä¸­ï¼Œç”¨äºŽæ˜„¡¤ºã€åˆ†æžã€‚在使用Read或ReadLineæ–ÒŽ(gu¨©)³•è¯Õd–æ–‡äšg内容æ—Óž¼Œå¦‚果要蟩˜q‡ä¸€äº›éƒ¨åˆ†ï¼Œž®Þp¦ç”¨åˆ°Skip或SkipLineæ–ÒŽ(gu¨©)³•ã€?
下面的代码演½Cºæ‰“开文äšg、填写数据,然后è¯Õd–数据åQ?
var fso, f1, ts, s;
var ForReading = 1;
fso = new ActiveXObject("Scripting.FileSystemObject");
// 创徏文äšg
f1 = fso.CreateTextFile("c:\\testfile.txt", true);
// 填写一行数�
f1.WriteLine("Hello World");
f1.WriteBlankLines(1);
// 关闭文äšg
f1.Close();
// 打开文äšg
ts = fso.OpenTextFile("c:\\testfile.txt", ForReading);
// è¯Õd–æ–‡äšg一行内容到字符ä¸?
s = ts.ReadLine();
// 昄¡¤ºå­—符串信æ?
alert("File contents = '" + s + "'");
// 关闭文äšg
ts.Close();
åQˆäº”åQ‰ç§»åŠ¨ã€æ‹·è´å’Œåˆ é™¤æ–‡äšg
对于以上三种文äšg操作åQŒjavascript各有两种对应的方法:(x¨¬)File.Move æˆ?FileSystemObject.MoveFile用于¿UÕdŠ¨æ–‡äšgåQ›File.Copy æˆ?FileSystemObject.CopyFile用于拯‚´æ–‡äšgåQ›File.Delete æˆ?FileSystemObject.DeleteFile用于删除文äšgã€?
下面的代码演½Cºåœ¨é©±åЍ噍C的根目录下创å»ÞZ¸€ä¸ªæ–‡æœ¬æ–‡ä»Óž¼Œå¡«å†™ä¸€äº›å†…容,然后ž®†æ–‡ä»¶ç§»åŠ¨åˆ°\tmp目录下,再在目录\temp下面建立一个文件拷贝,最后删除这两个目录的文ä»Óž¼š(x¨¬)
var fso, f1, f2, s;
fso = new ActiveXObject("Scripting.FileSystemObject");
f1 = fso.CreateTextFile("c:\\testfile.txt", true);
// 写一�
f1.Write("This is a test.");
// 关闭文äšg
f1.Close();
// 获取C:\根目录下的文件句�
f2 = fso.GetFile("c:\\testfile.txt");
// ¿UÕdŠ¨æ–‡äšg到\tmp目录ä¸?
f2.Move ("c:\\tmp\\testfile.txt");
// 拯‚´æ–‡äšg到\temp目录ä¸?
f2.Copy ("c:\\temp\\testfile.txt");
// 获取文äšg句柄
f2 = fso.GetFile("c:\\tmp\\testfile.txt");
f3 = fso.GetFile("c:\\temp\\testfile.txt");
// 删除文äšg
f2.Delete();
f3.Delete();
六、结 �
通过以上对FileSystemObject的各¿Uå¯¹è±¡ã€å±žæ€§å’Œæ–ÒŽ(gu¨©)³•的介¾lå’Œ½CÞZ¾‹åQŒç›¸ä¿¡ä½ å·²ç»å¯¹å¦‚何ä‹É用javascript语言在页面中操作驱动器、文件和文äšgå¤ÒŽ(gu¨©)œ‰äº†æ¸…晰的认识。但是上˜q°æå?qi¨¢ng)的例程都非常简单,要全面、灵‹zÕdœ°æŽŒæ¡javascriptæ–‡äšg操作技术,˜q˜éœ€è¦å¤§é‡çš„实践¾lƒä¹ (f¨¤n)。而且˜q˜æœ‰ä¸€ç‚ÒŽ(gu¨©)é†’大å®Óž¼Œç”׃ºŽæ¶‰åŠ(qi¨¢ng)到在‹¹è§ˆå™¨ä¸­˜q›è¡Œæ–‡äšgè¯Õd†™˜q™æ ·çš„高¾U§æ“ä½œï¼Œå¯¹äºŽé»˜è®¤çš„æµè§ˆå™¨å®‰å…¨¾U§åˆ«è€Œè¨€åQŒåœ¨ä»£ç ˜qè¡Œå‰éƒ½ä¼?x¨¬)有一个信息提½Cºï¼Œ˜q™ç‚¹è¯·åœ¨å®žé™…环境中提½Cø™®¿é—®è€…注意ã€?


]]>
转:(x¨¬)session机制http://www.aygfsteel.com/wml/articles/55999.htmlwmlwmlFri, 30 Jun 2006 09:16:00 GMThttp://www.aygfsteel.com/wml/articles/55999.html
目录åQ?br />一、术语session
二、HTTP协议与状态保�br />三、理解cookie机制
四、理解session机制
五、理解javax.servlet.http.HttpSession
六、HttpSession常见问题
七、跨应用½E‹åºçš„sessionå…׃ín
八、æ€È»“
参考文�br />
一、术语session
在我的经验里åQŒsession˜q™ä¸ªè¯è¢«æ»¥ç”¨çš„程度大概仅‹Æ¡äºŽtransactionåQŒæ›´åŠ æœ‰­‘£çš„æ˜¯transaction与session在某些语境下的含义是相同的ã€?br />
sessionåQŒä¸­æ–‡ç»å¸¸ç¿»è¯‘䨓(f¨´)ä¼?x¨¬)话åQŒå…¶æœ¬æ¥çš„含义是指有始有¾lˆçš„一¾pÕdˆ—动作/消息åQŒæ¯”如打ç”?sh¨´)话时从拿è“vç”?sh¨´)话拨号到挂断ç”?sh¨´)话这中间的一¾pÕdˆ—˜q‡ç¨‹å¯ä»¥¿UîC¹‹ä¸ÞZ¸€ä¸ªÂ session。有时候我们可以看到这æ ïL(f¨¥ng)š„话“在一个浏览器ä¼?x¨¬)话期间åQ?..”,˜q™é‡Œçš„会(x¨¬)话一词用的就是其本义åQŒæ˜¯æŒ‡ä»Žä¸€ä¸ªæµè§ˆå™¨½H—口打开到关闭这个期闾b â‘ ã€‚æœ€æ··äØ•çš„æ˜¯â€œç”¨æˆøP¼ˆå®¢æˆ·ç«¯ï¼‰åœ¨ä¸€‹Æ¡ä¼š(x¨¬)话期间”这样一句话åQŒå®ƒå¯èƒ½æŒ‡ç”¨æˆïL(f¨¥ng)š„一¾pÕdˆ—动作åQˆä¸€èˆ¬æƒ…况下是同某个具体目的相关的一¾pÕdˆ—动作åQŒæ¯”如从ç™Õd½•åˆ°é€‰è´­å•†å“åˆ°ç»“è´¦ç™»å‡ø™¿™æ ·ä¸€ä¸ªç½‘上购物的˜q‡ç¨‹åQŒæœ‰æ—¶å€™ä¹Ÿè¢«ç§°ä¸ÞZ¸€ä¸ªtransactionåQ‰ï¼Œç„¶è€Œæœ‰æ—¶å€™ä¹Ÿå¯èƒ½ä»…仅是指一‹Æ¡è¿žæŽ¥ï¼Œä¹Ÿæœ‰å¯èƒ½æ˜¯æŒ‡å«ä¹‰â‘ ï¼Œå…¶ä¸­çš„差别只能靠上下文来推断②ã€?br />
然而当session一词与¾|‘络协议相关联时åQŒå®ƒåˆå¾€å¾€éšå«äº†â€œé¢å‘连接”和/或“保持状态”这样两个含义, “面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电(sh¨´)话,直到å¯ÒŽ(gu¨©)–¹æŽ¥äº†ç”?sh¨´)话通信才能开始,与此相对的是写信åQŒåœ¨ä½ æŠŠä¿¡å‘出去的时候你òq¶ä¸èƒ½ç¡®è®¤å¯¹æ–¹çš„地址是否正确åQŒé€šä¿¡æ¸ é“不一定能建立åQŒä½†å¯¹å‘ä¿¡äh来说åQŒé€šä¿¡å·²ç»å¼€å§‹äº†ã€‚“保持状态”则是指通信的一方能够把一¾pÕdˆ—的消息关联è“v来,使得消息之间可以互相依赖åQŒæ¯”如一个服务员能够认出再次光äÍ(f¨´)çš„è€é¡¾å®¢åÆˆä¸”è®°å¾—ä¸Š‹Æ¡è¿™ä¸ªé¡¾å®¢è¿˜?g¨°u)Ơ店里一块钱。这一¾cȝš„例子有“一个TCP session”或者 “一个POP3 session”③ã€?br />
而到了web服务器蓬勃发展的时代åQŒsession在web开发语境下的语义又有了新的扩展åQŒå®ƒçš„含义是指一¾cȝ”¨æ¥åœ¨å®¢æˆ·ç«¯ä¸ŽæœåŠ¡å™¨ä¹‹é—´ä¿æŒçŠ¶æ€çš„è§£å†³æ–ÒŽ(gu¨©)¡ˆâ‘£ã€‚有时候session也用来指˜q™ç§è§£å†³æ–ÒŽ(gu¨©)¡ˆçš„存储结构,如“把xxx保存在session 里”⑤。由于各¿Uç”¨äºŽweb开发的语言在一定程度上都提供了对这¿Uè§£å†Ïx–¹æ¡ˆçš„æ”¯æŒåQŒæ‰€ä»¥åœ¨æŸç§ç‰¹å®šè¯­è¨€çš„语境下åQŒsession也被用来指代该语­a€çš„è§£å†Ïx–¹æ¡ˆï¼Œæ¯”如¾lå¸¸æŠŠJava里提供的javax.servlet.http.HttpSession½Ž€¿UîCØ“(f¨´)sessionâ‘¥ã€?br />
鉴于˜q™ç§æ··äؕ已不可改变,本文中session一词的˜qç”¨ä¹Ÿä¼š(x¨¬)æ ÒŽ(gu¨©)®ä¸Šä¸‹æ–‡æœ‰ä¸åŒçš„含义,请大家注意分辨ã€?br />在本文中åQŒä‹É用中文“浏览器ä¼?x¨¬)话期间”来表达含义①,使用“session机制”来表达含义④,使用“session”表辑֐«ä¹‰â‘¤åQŒä‹É用具体的“HttpSession”来表达含义â‘?br />
二、HTTP协议与状态保æŒ?br />HTTP 协议本èín是无状态的åQŒè¿™ä¸ŽHTTP协议本来的目的是相符的,客户端只需要简单的向服务器è¯äh±‚下蝲某些文äšgåQŒæ— è®ºæ˜¯å®¢æˆ·ç«¯è¿˜æ˜¯æœåŠ¡å™¨éƒ½æ²¡æœ‰å¿…è¦çºªå½•å½¼æ­¤è¿‡åŽÈš„è¡ŒäØ“(f¨´)åQŒæ¯ä¸€‹Æ¡è¯·æ±‚之间都是独立的åQŒå¥½æ¯”一个顾客和一个自动售货机或者一个普通的åQˆéžä¼?x¨¬)员åˆÓž¼‰å¤§å–åœÞZ¹‹é—´çš„关系一栗÷€?br />
然而聪明(或者贪心?åQ‰çš„äºÞZ»¬å¾ˆå¿«å‘现如果能够提供一些按需生成的动态信息会(x¨¬)使web变得更加有用åQŒå°±åƒç»™æœ‰çº¿ç”?sh¨´)视加上ç‚Ò?gu¨©)’­åŠŸèƒ½ä¸€æ —÷€‚è¿™¿Uéœ€æ±‚一斚w¢˜q«ä‹ÉHTML逐步æ·ÕdŠ äº†è¡¨å•ã€è„šæœ¬ã€DOM½{‰å®¢æˆïL(f¨¥ng)«¯è¡ŒäØ“(f¨´)åQŒå¦ä¸€æ–šw¢åœ¨æœåŠ¡å™¨ç«¯åˆ™å‡ºçŽ°äº†CGI规范以响应客æˆïL(f¨¥ng)«¯çš„åŠ¨æ€è¯·æ±‚ï¼Œä½œäØ“(f¨´)传输载体的HTTP协议也添加了文äšg上蝲、 cookie˜q™äº›ç‰ÒŽ(gu¨©)€§ã€‚其中cookieçš„ä½œç”¨å°±æ˜¯äØ“(f¨´)了解决HTTP协议无状态的¾~ºé™·æ‰€ä½œå‡ºçš„努力。至于后来出现的session机制则是又一¿Uåœ¨å®¢æˆ·ç«¯ä¸ŽæœåŠ¡å™¨ä¹‹é—´ä¿æŒçŠ¶æ€çš„è§£å†³æ–ÒŽ(gu¨©)¡ˆã€?br />
让我们用几个例子来描˜qîC¸€ä¸‹cookieå’Œsession机制之间的区别与联系。笔者曾¾lå¸¸åŽÈš„一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠åQŒç„¶è€Œä¸€‹Æ¡æ€§æ¶ˆè´?杯咖啡的æœÞZ¼š(x¨¬)微乎其微åQŒè¿™æ—¶å°±éœ€è¦æŸ¿Uæ–¹å¼æ¥¾Uªå½•某位™å‘Ö®¢çš„æ¶ˆè´ÒŽ(gu¨©)•°é‡ã€‚想象一下其实也无外乎下面的几种æ–ÒŽ(gu¨©)¡ˆåQ?br />1、该店的店员很厉宻I¼Œèƒ½è®°ä½æ¯ä½é¡¾å®¢çš„æ¶ˆè´¹æ•°é‡åQŒåªè¦é¡¾å®¢ä¸€èµ°è¿›å’–啡店,店员ž®ÞqŸ¥é“该怎么对待了。这¿Uåšæ³•就是协议本íw«æ”¯æŒçŠ¶æ€ã€?br />2、发¾l™é¡¾å®¢ä¸€å¼ å¡ç‰‡ï¼Œä¸Šé¢è®°å½•着消费的数量,一般还有个有效期限。每‹Æ¡æ¶ˆè´ÒŽ(gu¨©)—¶åQŒå¦‚果顾客出½Cø™¿™å¼ å¡ç‰‡ï¼Œåˆ™æ­¤‹Æ¡æ¶ˆè´¹å°±ä¼?x¨¬)与以前或以后的消费相联¾p»è“v来。这¿Uåšæ³•就是在客户端保持状态ã€?br />3、发¾l™é¡¾å®¢ä¸€å¼ ä¼š(x¨¬)员卡åQŒé™¤äº†å¡å·ä¹‹å¤–什么信息也不纪录,每次消费æ—Óž¼Œå¦‚æžœ™å‘Ö®¢å‡ºç¤ºè¯¥å¡ç‰‡ï¼Œåˆ™åº—员在店里的纪录本上找到这个卡号对应的¾Uªå½•æ·ÕdŠ ä¸€äº›æ¶ˆè´¹ä¿¡æ¯ã€‚è¿™¿Uåšæ³•就是在服务器端保持状态ã€?br />
ç”׃ºŽHTTP协议是无状态的åQŒè€Œå‡ºäºŽç§¿Uè€ƒè™‘ä¹Ÿä¸å¸Œæœ›ä½¿ä¹‹æˆäØ“(f¨´)有状态的åQŒå› æ­¤ï¼ŒåŽé¢ä¸¤ç§æ–ÒŽ(gu¨©)¡ˆž®±æˆä¸ºçŽ°å®žçš„é€‰æ‹©ã€‚å…·ä½“æ¥è¯´cookie机制采用的是在客æˆïL(f¨¥ng)«¯ä¿æŒçŠ¶æ€çš„æ–ÒŽ(gu¨©)¡ˆåQŒè€Œsession机制采用的是在服务器端保持状态的æ–ÒŽ(gu¨©)¡ˆã€‚同时我们也看到åQŒç”±äºŽé‡‡ç”¨æœåŠ¡å™¨ç«¯ä¿æŒçŠ¶æ€çš„æ–ÒŽ(gu¨©)¡ˆåœ¨å®¢æˆïL(f¨¥ng)«¯ä¹Ÿéœ€è¦ä¿å­˜ä¸€ä¸ªæ ‡è¯†ï¼Œæ‰€ä»¥session机制可能需要借助于cookie机制来达åˆîC¿å­˜æ ‡è¯†çš„目的åQŒä½†å®žé™…上它˜q˜æœ‰å…¶ä»–选择ã€?br />
三、理解cookie机制 
cookie机制的基本原理就如上面的例子一æ ïL(f¨¥ng)®€å•,但是˜q˜æœ‰å‡ ä¸ªé—®é¢˜éœ€è¦è§£å†»I¼š(x¨¬)“会(x¨¬)员卡”如何分发;“会(x¨¬)员卡”的内容åQ›ä»¥å?qi¨¢ng)客户如何ä‹É用“会(x¨¬)员卡”ã€?br />
正统的cookie分发是通过扩展HTTP协议来实现的åQŒæœåŠ¡å™¨é€šè¿‡åœ¨HTTP的响应头中加上一行特ŒDŠçš„æŒ‡ç¤ºä»¥æ½Cºæµè§ˆå™¨æŒ‰ç…§æŒ‡ç¤ºç”Ÿæˆç›¸åº”çš„cookie。然而纯¾_¹çš„客户端脚本如JavaScript或者VBScript也可以生成cookieã€?br />
而cookie 的ä‹É用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器‹‚€(g¨¨)查所有存储的cookieåQŒå¦‚果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置åQŒåˆ™æŠŠè¯¥cookie附在è¯äh±‚资源的HTTPè¯äh±‚头上发送给服务器。意思是麦当劳的ä¼?x¨¬)员卡只能在麦当劳的店里出示åQŒå¦‚果某家分店还发行了自å·Þqš„ä¼?x¨¬)员卡,那么˜q›è¿™å®¶åº—的时候除了要出示麦当劳的ä¼?x¨¬)员卡,˜q˜è¦å‡ºç¤º˜q™å®¶åº—çš„ä¼?x¨¬)员卡ã€?br />
cookie的内容主要包括:(x¨¬)名字åQŒå€û|¼Œ˜q‡æœŸæ—‰™—´åQŒèµ\径和域ã€?br />其中域可以指定某一个域比如.google.comåQŒç›¸å½“于æ€Õdº—招牌åQŒæ¯”如宝‹zå…¬å¸ï¼Œä¹Ÿå¯ä»¥æŒ‡å®šä¸€ä¸ªåŸŸä¸‹çš„具体某台机器比如www.google.com或者f(xi¨¦)roogle.google.comåQŒå¯ä»¥ç”¨é£˜æŸ”来做比ã€?br />路径ž®±æ˜¯è·Ÿåœ¨åŸŸååŽé¢çš„URL路径åQŒæ¯”å¦?或è€?foo½{‰ç­‰åQŒå¯ä»¥ç”¨æŸé£˜æŸ”专柜做比ã€?br />路径与域合在一起就构成了cookie的作用范围ã€?br />如果不设¾|®è¿‡æœŸæ—¶é—ß_(d¨¢)¼Œåˆ™è¡¨½Cø™¿™ä¸ªcookie的生命期为浏览器ä¼?x¨¬)话期间åQŒåªè¦å…³é—­æµè§ˆå™¨½H—口åQŒcookiež®±æ¶ˆå¤×ƒº†ã€‚è¿™¿Uç”Ÿå‘½æœŸä¸ºæµè§ˆå™¨ä¼?x¨¬)话期的 cookie被称ä¸ÞZ¼š(x¨¬)话cookie。会(x¨¬)话cookie一般不存储在硬盘上而是保存在内存里åQŒå½“ç„¶è¿™¿Uè¡Œä¸ºåƈ不是规范规定的。如果设¾|®äº†˜q‡æœŸæ—‰™—´åQŒæµè§ˆå™¨ž®×ƒ¼š(x¨¬)把cookie保存到硬盘上åQŒå…³é—­åŽå†æ¬¡æ‰“å¼€‹¹è§ˆå™¨ï¼Œ˜q™äº›cookie仍然有效直到­‘…过讑֮šçš„过期时间ã€?br />
存储在硬盘上的cookie 可以在不同的‹¹è§ˆå™¨è¿›½E‹é—´å…׃ínåQŒæ¯”如两个IE½H—口。而对于保存在内存里的cookieåQŒä¸åŒçš„‹¹è§ˆå™¨æœ‰ä¸åŒçš„处理方式。对于IEåQŒåœ¨ä¸€ä¸ªæ‰“开的窗口上按 Ctrl-NåQˆæˆ–者从文äšg菜单åQ‰æ‰“开的窗口可以与原窗口共享,而ä‹É用其他方式新开的IE˜q›ç¨‹åˆ™ä¸èƒ½å…±äº«å·²¾læ‰“开的窗口的内存cookieåQ›å¯¹äºŽÂ Mozilla Firefox0.8åQŒæ‰€æœ‰çš„˜q›ç¨‹å’Œæ ‡½{ùN¡µéƒ½å¯ä»¥å…±äº«åŒæ ïL(f¨¥ng)š„cookie。一般来说是用javascriptçš„window.open打开的窗口会(x¨¬)与原½H—口å…׃ín内存cookie。浏览器对于ä¼?x¨¬)话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™æ˜¯ä½¿ç”¨HTTPLook˜q™ä¸ªHTTP Sniffer软äšg来俘èŽïL(f¨¥ng)š„HTTP通讯¾Uªå½•的一部分




‹¹è§ˆå™¨åœ¨å†æ¬¡è®‰K—®goolge的资源时自动向外发送cookie




使用Firefox可以很容易的观察现有的cookieçš„å€?br />使用HTTPLook配合F(tu¨¢n)irefox可以很容易的理解cookie的工作原理ã€?br />



IE也可以设¾|®åœ¨æŽ¥å—cookie前询é—?br />



˜q™æ˜¯ä¸€ä¸ªè¯¢é—®æŽ¥å—cookie的对话框ã€?br />
四、理解session机制
session机制是一¿UæœåŠ¡å™¨ç«¯çš„æœºåˆ¶åQŒæœåŠ¡å™¨ä½¿ç”¨ä¸€¿Uç±»ä¼égºŽæ•£åˆ—表的¾l“æž„åQˆä¹Ÿå¯èƒ½ž®±æ˜¯ä½¿ç”¨æ•£åˆ—表)来保存信息ã€?br />
å½“ç¨‹åºéœ€è¦äØ“(f¨´)某个客户端的è¯äh±‚创徏一个session的时候,服务器首先检查这个客æˆïL(f¨¥ng)«¯çš„请求里是否已包含了一个session标识 - ¿UîCØ“(f¨´) session idåQŒå¦‚果已包含一个session id则说明以前已¾läØ“(f¨´)此客æˆïL(f¨¥ng)«¯åˆ›å¾˜q‡sessionåQŒæœåС噍ž®±æŒ‰ç…§session id把这个 session‹‚€(g¨¨)索出来ä‹É用(如果‹‚€(g¨¨)索不刎ͼŒå¯èƒ½ä¼?x¨¬)æ–°å»ÞZ¸€ä¸ªï¼‰åQŒå¦‚果客æˆïL(f¨¥ng)«¯è¯äh±‚不包含session idåQŒåˆ™ä¸ºæ­¤å®¢æˆ·ç«¯åˆ›å»ÞZ¸€ä¸ªsessionòq¶ä¸”生成一个与此session相关联的session idåQŒsession id的值应该是一个既不会(x¨¬)重复åQŒåˆä¸å®¹æ˜“被扑ֈ°è§„律以仿造的字符ä¸ÔŒ¼Œ˜q™ä¸ªÂ session idž®†è¢«åœ¨æœ¬‹Æ¡å“åº”中˜q”回¾l™å®¢æˆïL(f¨¥ng)«¯ä¿å­˜ã€?br />
保存˜q™ä¸ªsession id的方式可以采用cookieåQŒè¿™æ ·åœ¨äº¤äº’˜q‡ç¨‹ä¸­æµè§ˆå™¨å¯ä»¥è‡ªåŠ¨çš„æŒ‰ç…§è§„åˆ™æŠŠ˜q™ä¸ªæ ‡è¯†å‘挥¾l™æœåŠ¡å™¨ã€‚ä¸€èˆ¬è¿™ä¸ªcookie的名字都是类ä¼égºŽSEEESIONIDåQŒè€Œã€‚比如weblogic对于web应用½E‹åºç”Ÿæˆçš„cookieåQŒJSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764åQŒå®ƒçš„名字就是 JSESSIONIDã€?br />
ç”׃ºŽcookie可以被äh为的¼›æ­¢åQŒå¿…™åÀLœ‰å…¶ä»–机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一¿UæŠ€æœ¯å«åšURL重写åQŒå°±æ˜¯æŠŠsession id直接附加在URL路径的后面,附加方式也有两种åQŒä¸€¿Uæ˜¯ä½œäØ“(f¨´)URL路径的附加信息,表现形式ä¸?a href="http://...../xxx;jsessionid=">http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
另一¿Uæ˜¯ä½œäØ“(f¨´)查询字符串附加在URL后面åQŒè¡¨çްåÅžå¼äØ“(f¨´)http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
˜q™ä¸¤¿Uæ–¹å¼å¯¹äºŽç”¨æˆäh¥è¯´æ˜¯æ²¡æœ‰åŒºåˆ«çš„,只是服务器在解析的时候处理的方式不同åQŒé‡‡ç”¨ç¬¬ä¸€¿Uæ–¹å¼ä¹Ÿæœ‰åˆ©äºŽæŠŠsession id的信息和正常½E‹åºå‚数区分开来ã€?br />ä¸ÞZº†åœ¨æ•´ä¸ªäº¤äº’过½E‹ä¸­å§‹ç»ˆä¿æŒçŠ¶æ€ï¼Œž®±å¿…™åÕdœ¨æ¯ä¸ªå®¢æˆ·ç«¯å¯èƒ½è¯·æ±‚的路径后面都包含这个session idã€?br />
另一¿UæŠ€æœ¯å«åšè¡¨å•隐藏字ŒDüc(di¨£n)€‚就是服务器ä¼?x¨¬)自动修改表单,æ·ÕdŠ ä¸€ä¸ªéšè—å­—ŒDµï¼Œä»¥ä¾¿åœ¨è¡¨å•提交时能够把session id传递回服务器。比如下面的表单
http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869

六、HttpSession常见问题
åQˆåœ¨æœ¬å°èЂ䏭sessionçš„å«ä¹‰äØ“(f¨´)⑤和⑥的混合åQ?br />

1、session在何时被创徏
一个常见的误解是以为session在有客户端访问时ž®Þp¢«åˆ›å¾åQŒç„¶è€Œäº‹å®žæ˜¯ç›´åˆ°æŸserver端程序调用 HttpServletRequest.getSession(true)˜q™æ ·çš„语句时才被创徏åQŒæ³¨æ„å¦‚æžœJSP没有昄¡¤ºçš„ä‹É用Â?!--page session="false--> 关闭sessionåQŒåˆ™JSPæ–‡äšg在编译成Servletæ—¶å°†ä¼?x¨¬)自动加上这样一条语句 HttpSession session = HttpServletRequest.getSession(true);˜q™ä¹Ÿæ˜¯JSP中隐含的 session对象的来历ã€?br />
ç”׃ºŽsessionä¼?x¨¬)消耗内存资源,因此åQŒå¦‚果不打算使用sessionåQŒåº”该在所有的JSP中关闭它ã€?br />
2、session何时被删é™?br />¾l¼åˆå‰é¢çš„讨论,session在下列情况下被删除a.½E‹åºè°ƒç”¨HttpSession.invalidate();或b.距离上一‹Æ¡æ”¶åˆ°å®¢æˆïL(f¨¥ng)«¯å‘送的session idæ—‰™—´é—´éš”­‘…过了session的超时设¾|?或c.服务器进½E‹è¢«åœæ­¢åQˆéžæŒä¹…sessionåQ?br />
3、如何做到在‹¹è§ˆå™¨å…³é—­æ—¶åˆ é™¤session
严格的讲åQŒåšä¸åˆ°˜q™ä¸€ç‚V€‚可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进½E‹è¿™äº›éžå¸¸è§„手段仍然无能为力ã€?br />
4、有个HttpSessionListener是怎么回事
ä½ å¯ä»¥åˆ›å»ø™¿™æ ïL(f¨¥ng)š„listeneråŽÈ›‘控session的创建和销毁事ä»Óž¼Œä½¿å¾—在发生这æ ïL(f¨¥ng)š„事äšg时你可以做一些相应的工作。注意是session的创建和销毁动作触发listeneråQŒè€Œä¸æ˜¯ç›¸åã€‚类似的与HttpSession有关的listener˜q˜æœ‰Â HttpSessionBindingListeneråQŒHttpSessionActivationListener和 HttpSessionAttributeListenerã€?br />
5、存攑֜¨session中的对象必须是可序列化的å?br />ä¸æ˜¯å¿…éœ€çš„ã€‚è¦æ±‚å¯¹è±¡å¯åºåˆ—åŒ–åªæ˜¯äØ“(f¨´)了session能够在集¾Ÿ¤ä¸­è¢«å¤åˆ¶æˆ–者能够持久保存或者在必要时server能够暂时把session交换出内存。在 Weblogic Serverçš„session中放¾|®ä¸€ä¸ªä¸å¯åºåˆ—化的对象在控制åîC¸Šä¼?x¨¬)æ”¶åˆîC¸€ä¸ªè­¦å‘Šã€‚我所用过的某个iPlanet版本如果 session中有不可序列化的对象åQŒåœ¨session销毁时ä¼?x¨¬)有一个ExceptionåQŒå¾ˆå¥‡æ€ªã€?br />
6、如何才能正¼‹®çš„应付客户端禁止cookie的可能æ€?br />å¯ÒŽ(gu¨©)‰€æœ‰çš„URL使用URL重写åQŒåŒ…括超链接åQŒformçš„actionåQŒå’Œé‡å®šå‘çš„URLåQŒå…·ä½“做法参见[6]
http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

7、开两个‹¹è§ˆå™¨çª—口访问应用程序会(x¨¬)使用同一个session˜q˜æ˜¯ä¸åŒçš„session
参见½W¬ä¸‰ž®èЂ坹cookie的讨论,对session来说是只认id不认人,因此不同的浏览器åQŒä¸åŒçš„½H—口打开方式以及(qi¨¢ng)不同的cookie存储方式都会(x¨¬)对这个问题的½{”案有媄响ã€?br />
8、如何防止用æˆäh‰“开两个‹¹è§ˆå™¨çª—口操作导致的sessionæ··äØ•
˜q™ä¸ªé—®é¢˜ä¸Žé˜²æ­¢è¡¨å•多‹Æ¡æäº¤æ˜¯¾cÖM¼¼çš„,可以通过讄¡½®å®¢æˆ·ç«¯çš„令牌来解冟뀂就是在服务器每‹Æ¡ç”Ÿæˆä¸€ä¸ªä¸åŒçš„id˜q”回¾l™å®¢æˆïL(f¨¥ng)«¯åQŒåŒæ—¶ä¿å­˜åœ¨session里,客户端提交表单时必须把这个id也返回服务器åQŒç¨‹åºé¦–先比较返回的id与保存在session里的值是否一è‡ß_(d¨¢)¼Œå¦‚果不一致则说明本次操作已经被提交过了。可以参看《J2EE核心模式》关于表½Cºå±‚模式的部分。需要注意的是对于ä‹É用javascript window.open打开的窗口,一般不讄¡½®˜q™ä¸ªidåQŒæˆ–者ä‹É用单独的idåQŒä»¥é˜²ä¸»½H—口无法操作åQŒå¾è®®ä¸è¦å†window.open打开的窗口里做修æ”ÒŽ(gu¨©)“ä½œï¼Œ˜q™æ ·ž®±å¯ä»¥ä¸ç”¨è®¾¾|®ã€?br />
9ã€äØ“(f¨´)什么在Weblogic Server中改变session的值后要重新调用一‹Æ¡session.setValue
做这个动作主要是ä¸ÞZº†åœ¨é›†¾Ÿ¤çŽ¯å¢ƒä¸­æç¤ºWeblogic Server session中的值发生了改变åQŒéœ€è¦å‘其他服务器进½E‹å¤åˆ¶æ–°çš„session倹{€?br />
10ã€äØ“(f¨´)什么session不见äº?br />排除session正常失效的因素之外,服务器本íw«çš„可能性应该是微乎其微的,虽然½W”者在iPlanet6SP1加若òq²è¡¥ä¸çš„Solaris版本上倒也遇到˜q‡ï¼›‹¹è§ˆå™¨æ’件的可能性次之,½W”者也遇到˜q?721插äšg造成的问题;理论上防火墙或者代理服务器在cookie处理上也有可能会(x¨¬)出现问题ã€?br />出现˜q™ä¸€é—®é¢˜çš„大部分原因都是½E‹åºçš„é”™è¯¯ï¼Œæœ€å¸¸è§çš„å°±æ˜¯åœ¨ä¸€ä¸ªåº”ç”¨ç¨‹åºä¸­åŽ»è®¿é—®å¦å¤–ä¸€ä¸ªåº”ç”¨ç¨‹åºã€‚æˆ‘ä»¬åœ¨ä¸‹ä¸€èŠ‚è®¨è®ø™¿™ä¸ªé—®é¢˜ã€?br />
七、跨应用½E‹åºçš„sessionå…׃ín

常常有这æ ïL(f¨¥ng)š„æƒ…况åQŒä¸€ä¸ªå¤§™å¹ç›®è¢«åˆ†å‰²æˆè‹¥å¹²ž®é¡¹ç›®å¼€å‘,ä¸ÞZº†èƒ½å¤Ÿäº’不òq²æ‰°åQŒè¦æ±‚每个小™å¹ç›®ä½œäØ“(f¨´)一个单独的web应用½E‹åºå¼€å‘,可是åˆîCº†æœ€åŽçªç„¶å‘现某几个ž®é¡¹ç›®ä¹‹é—´éœ€è¦å…±äº«ä¸€äº›ä¿¡æ¯ï¼Œæˆ–者想使用session来实现SSO(single sign on)åQŒåœ¨session中保存login的用户信息,最自然的要求是应用½E‹åºé—´èƒ½å¤Ÿè®¿é—®å½¼æ­¤çš„sessionã€?br />
然而按照Servlet规范åQŒsession的作用范围应该仅仅限于当前应用程序下åQŒä¸åŒçš„应用½E‹åºä¹‹é—´æ˜¯ä¸èƒ½å¤Ÿäº’相讉K—®å¯ÒŽ(gu¨©)–¹çš„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 />
æ ÒŽ(gu¨©)®˜q™ä¸ªç‰ÒŽ(gu¨©)€§ï¼Œæˆ‘们可以推测Tomcat中session的内存结构大致如下ã€?br />
½W”者以前用˜q‡çš„iPlanet也采用的是同æ ïL(f¨¥ng)š„æ–¹å¼åQŒä¼°è®¡SunONE与iPlanet之间不会(x¨¬)有太大的差别。对于这¿Uæ–¹å¼çš„æœåŠ¡å™¨ï¼Œè§£å†³çš„æ€èµ\很简单,实际实行èµäh¥ä¹Ÿä¸éš¾ã€‚要么让所有的应用½E‹åºå…׃ín一个session idåQŒè¦ä¹ˆè®©åº”用½E‹åºèƒ½å¤ŸèŽ·å¾—å…¶ä»–åº”ç”¨½E‹åºçš„session idã€?br />
iPlanet中有一¿Uå¾ˆ½Ž€å•çš„æ–ÒŽ(gu¨©)³•来实现共享一个session idåQŒé‚£ž®±æ˜¯æŠŠå„个应用程序的cookie路径都设ä¸?åQˆå®žé™…上应该æ˜?NASAppåQŒå¯¹äºŽåº”用程序来讲它的作用相当于根)ã€?br />
/NASApp

需要注意的是,操作å…׃ínçš„session应该遵åó@一些编½E‹çº¦å®šï¼Œæ¯”如在session attribute名字的前面加上应用程序的前缀åQŒä‹É得 setAttribute("name", "neo")变成setAttribute("app1.name", "neo")åQŒä»¥é˜²æ­¢å‘½å½Iºé—´å†²çªåQŒå¯¼è‡´äº’相覆盖ã€?br />

在Tomcat中则没有˜q™ä¹ˆæ–¹ä¾¿çš„选择。在Tomcat版本3上,我们˜q˜å¯ä»¥æœ‰ä¸€äº›æ‰‹ŒD‰|¥å…׃ínsession。对于版æœ?以上的TomcatåQŒç›®å‰ç¬”者尚未发现简单的办法。只能借助于第三方的力量,比如使用文äšg、数据库、JMS或者客æˆïL(f¨¥ng)«¯cookieåQŒURL参数或者隐藏字ŒD늭‰æ‰‹æ®µã€?br />
我们再看一下Weblogic Server是如何处理session的�br />

  

从截屏画面上可以看到Weblogic Serverå¯ÒŽ(gu¨©)‰€æœ‰çš„应用½E‹åºè®„¡½®çš„cookieçš„èµ\径都æ˜?åQŒè¿™æ˜¯ä¸æ˜¯æ„å‘³ç€åœ¨Weblogic Server中默认的ž®±å¯ä»¥å…±äº«session了呢åQŸç„¶è€Œä¸€ä¸ªå°å®žéªŒå›_¯è¯æ˜Žå³ä‹É不同的应用程序ä‹É用的是同一个sessionåQŒå„个应用程序仍然只能访问自己所讄¡½®çš„那些属性。这说明Weblogic Server中的session的内存结构可能如ä¸?br />



对于˜q™æ ·ä¸€¿Uç»“构,在 session机制本èín上来解决sessionå…׃ín的问题应该是不可能的了。除了借助于第三方的力量,比如使用文äšg、数据库、JMS或者客æˆïL(f¨¥ng)«¯Â cookieåQŒURL参数或者隐藏字Œ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™ç§ç”¨æ³•不可¿UÀL¤åQŒå› ä¸ºæ ¹æ®ServletContextçš„JavaDocåQŒåº”用服务器可以处于安全的原因对于context.getContext("/appA");˜q”回½Iºå€û|¼Œä»¥ä¸Šåšæ³•在Weblogic Server 8.1中通过ã€?br />
那么Weblogic Serverä¸ÞZ»€ä¹ˆè¦æŠŠæ‰€æœ‰çš„应用½E‹åºçš„cookie路径都设ä¸?å‘¢ï¼ŸåŽŸæ¥æ˜¯äØ“(f¨´)了SSOåQŒå‡¡æ˜¯å…±äº«è¿™ä¸ªsession的应用程序都可以å…׃ín认证的信息。一个简单的实验ž®±å¯ä»¥è¯æ˜Žè¿™ä¸€ç‚¹ï¼Œä¿®æ”¹é¦–å…ˆç™Õd½•的那个应用程序的描述½W¦weblogic.xmlåQŒæŠŠcookie路径修改ä¸?appA 讉K—®å¦å¤–一个应用程序会(x¨¬)重新要求ç™Õd½•åQŒå³ä½¿æ˜¯åè¿‡æ¥ï¼Œå…ˆè®¿é—®cookie路径ä¸?的应用程序,再访问修改过路径的这个,虽然不再提示ç™Õd½•åQŒä½†æ˜¯ç™»å½•的用户信息也会(x¨¬)丢失。注意做˜q™ä¸ªå®žéªŒæ—¶è®¤è¯æ–¹å¼åº”该ä‹É用FORMåQŒå› ä¸ºæµè§ˆå™¨å’Œweb服务器对basic认证方式有其他的处理方式åQŒç¬¬äºŒæ¬¡è¯äh±‚的认证不是通过 session来实现的。具体请参看[7] secion 14.8 AuthorizationåQŒä½ å¯ä»¥ä¿®æ”¹æ‰€é™„çš„½CÞZ¾‹½E‹åºæ¥åš˜q™äº›è¯•验ã€?br />
八、æ€È»“
session机制本èínòq¶ä¸å¤æ‚åQŒç„¶è€Œå…¶å®žçŽ°å’Œé…¾|®ä¸Šçš„灵‹zÀL€§å´ä½¿å¾—具体情况复杂多变。这也要求我们不能把仅仅某一‹Æ¡çš„¾léªŒæˆ–者某一个浏览器åQŒæœåŠ¡å™¨çš„ç»éªŒå½“ä½œæ™®éé€‚ç”¨çš„ç»éªŒï¼Œè€Œæ˜¯å§‹ç»ˆéœ€è¦å…·ä½“æƒ…å†µå…·ä½“åˆ†æžã€?br />摘要åQšè™½ç„¶session机制在web应用½E‹åºä¸­è¢«é‡‡ç”¨å·²ç»å¾ˆé•¿æ—‰™—´äº†ï¼Œä½†æ˜¯ä»ç„¶æœ‰å¾ˆå¤šäh不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论sessionçš„å·¥ä½œæœºåˆ¶åÆˆä¸”å¯¹åœ¨Java web application中应用session机制时常见的问题作出解答ã€?

]]>
转:(x¨¬)JAVA字符é›?/title><link>http://www.aygfsteel.com/wml/articles/55985.html</link><dc:creator>wml</dc:creator><author>wml</author><pubDate>Fri, 30 Jun 2006 08:49:00 GMT</pubDate><guid>http://www.aygfsteel.com/wml/articles/55985.html</guid><description><![CDATA[ <p align="left"> <strong>1. 概述</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">本文主要包括以下几个斚w¢åQšç¼–码基本知识,javaåQŒç³»¾lŸèÊYä»Óž¼ŒurlåQŒå·¥å…¯‚ÊYä»¶ç­‰ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">在下面的描述中,ž®†ä»¥"中文"ä¸¤ä¸ªå­—äØ“(f¨´)例,¾læŸ¥è¡¨å¯ä»¥çŸ¥é“å…¶GB2312¾~–码æ˜?<u>d6d0 cec4</u>"åQŒUnicode¾~–码ä¸?<u>4e2d 6587</u>"åQŒUTF¾~–码ž®±æ˜¯"<u>e4b8ad e69687</u>"。注意,˜q™ä¸¤ä¸ªå­—没有iso8859-1¾~–码åQŒä½†å¯ä»¥ç”¨iso8859-1¾~–码æ?表示"ã€?</p> <p class="1"> <strong>2. ¾~–码基本知识</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">最早的¾~–码是iso8859-1åQŒå’Œascii¾~–ç ç›æ€¼¼ã€‚但ä¸ÞZº†æ–¹ä¾¿è¡¨ç¤ºå„种各样的语­a€åQŒé€æ¸å‡ºçŽ°äº†å¾ˆå¤šæ ‡å‡†ç¼–ç ï¼Œé‡è¦çš„æœ‰å¦‚ä¸‹å‡ ä¸ªã€?</p> <p class="2"> <strong>2.1. iso8859-1</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">属于单字节编码,最多能表示的字½W¦èŒƒå›´æ˜¯0-255åQŒåº”用于英文¾pÕdˆ—。比如,字母'a'çš„ç¼–ç äØ“(f¨´)0x61=97ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">很明显,iso8859-1¾~–码表示的字½W¦èŒƒå›´å¾ˆ½H„,无法表示中文字符。但是,ç”׃ºŽæ˜¯å•字节¾~–码åQŒå’Œè®¡ç®—机最基础的表½Cºå•位一è‡ß_(d¨¢)¼Œæ‰€ä»¥å¾ˆå¤šæ—¶å€™ï¼Œä»æ—§ä½¿ç”¨iso8859-1¾~–码来表½Cºã€‚而且在很多协议上åQŒé»˜è®¤ä‹É用该¾~–码。比如,虽然"中文"两个字不存在iso8859-1¾~–码åQŒä»¥gb2312¾~–码ä¸ÞZ¾‹åQŒåº”该是"<u>d6d0 cec4</u>"两个字符åQŒä‹É用iso8859-1¾~–码的时候则ž®†å®ƒæ‹†å¼€ä¸?个字节来表示åQ?<u>d6 d0 ce c4</u>"åQˆäº‹å®žä¸ŠåQŒåœ¨˜q›è¡Œå­˜å‚¨çš„æ—¶å€™ï¼Œä¹Ÿæ˜¯ä»¥å­—èŠ‚äØ“(f¨´)单位处理的)。而如果是UTF¾~–码åQŒåˆ™æ˜?个字èŠ?<u>e4 b8 ad e6 96 87</u>"。很明显åQŒè¿™¿Uè¡¨½Cºæ–¹æ³•还需要以另一¿Uç¼–ç äØ“(f¨´)基础ã€?</p> <p class="2"> <strong>2.2. GB2312/GBK</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">˜q™å°±æ˜¯æ±‰å­çš„国标码,专门用来表示汉字åQŒæ˜¯åŒå­—节编码,而英文字母和iso8859-1一è‡ß_(d¨¢)¼ˆå…¼å®¹iso8859-1¾~–码åQ‰ã€‚其中gbk¾~–码能够用来同时表示¾Jä½“å­—å’Œ½Ž€ä½“å­—åQŒè€Œgb2312只能表示½Ž€ä½“å­—åQŒgbk是兼容gb2312¾~–码的ã€?</p> <p class="2"> <strong>2.3. unicode</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">˜q™æ˜¯æœ€¾lŸä¸€çš„编码,可以用来表示所有语­a€çš„å­—½W¦ï¼Œè€Œä¸”是定长双字节åQˆä¹Ÿæœ‰å››å­—节的)¾~–码åQŒåŒ…括英文字母在内。所以可以说它是不兼容iso8859-1¾~–码的,也不兼容ä»ÖM½•¾~–码。不˜q‡ï¼Œç›¸å¯¹äºŽiso8859-1¾~–码来说åQŒuniocode¾~–码只是在前面增加了一ä¸?字节åQŒæ¯”如字æ¯?a'ä¸?<u>00 61</u>"ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">需要说明的是,定长¾~–码便于计算机处理(注意GB2312/GBK不是定长¾~–码åQ‰ï¼Œè€Œunicode又可以用来表½Cºæ‰€æœ‰å­—½W¦ï¼Œæ‰€ä»¥åœ¨å¾ˆå¤šè½¯äšg内部是ä‹É用unicode¾~–码来处理的åQŒæ¯”如javaã€?</p> <p class="2"> <strong>2.4. UTF</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">考虑到unicode¾~–码不兼容iso8859-1¾~–码åQŒè€Œä¸”å®ÒŽ(gu¨©)˜“占用更多的空é—ß_(d¨¢)¼š(x¨¬)因䨓(f¨´)对于英文字母åQŒunicode也需要两个字节来表示。所以unicode不便于传输和存储。因此而äñ”生了utf¾~–码åQŒutf¾~–码兼容iso8859-1¾~–码åQŒåŒæ—¶ä¹Ÿå¯ä»¥ç”¨æ¥è¡¨ç¤ºæ‰€æœ‰è¯­­a€çš„å­—½W¦ï¼Œä¸è¿‡åQŒutf¾~–码是不定长¾~–码åQŒæ¯ä¸€ä¸ªå­—½W¦çš„长度ä»?-6个字节不½{‰ã€‚另外,utf¾~–码自带½Ž€å•的校验功能。一般来è®ÔŒ¼Œè‹±æ–‡å­—母都是用一个字节表½Cºï¼Œè€Œæ±‰å­—ä‹É用三个字节ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">注意åQŒè™½ç„¶è¯´utfæ˜¯äØ“(f¨´)了ä‹É用更ž®‘çš„½Iºé—´è€Œä‹É用的åQŒä½†é‚£åªæ˜¯ç›¸å¯¹äºŽunicode¾~–码来说åQŒå¦‚果已¾lçŸ¥é“是汉字åQŒåˆ™ä½¿ç”¨GB2312/GBK无疑是最节省的。不˜q‡å¦ä¸€æ–šw¢åQŒå€¼å¾—说明的是åQŒè™½ç„¶utf¾~–码å¯ÒŽ(gu¨©)±‰å­—ä‹Éç”?个字节,但即使对于汉字网™åµï¼Œutf¾~–码也会(x¨¬)比unicode¾~–码节省åQŒå› ä¸ºç½‘™åµä¸­åŒ…含了很多的英文字符ã€?</p> <p class="1"> <strong>3. java对字½W¦çš„处理</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">在java应用软äšg中,ä¼?x¨¬)有多处涉å?qi¨¢ng)到字½W¦é›†¾~–码åQŒæœ‰äº›åœ°æ–šwœ€è¦è¿›è¡Œæ­£¼‹®çš„讄¡½®åQŒæœ‰äº›åœ°æ–šwœ€è¦è¿›è¡Œä¸€å®šç¨‹åº¦çš„处理ã€?</p> <p class="2"> <strong>3.1. getBytes(charset)</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">˜q™æ˜¯java字符串处理的一个标准函敎ͼŒå…¶ä½œç”¨æ˜¯ž®†å­—½W¦ä¸²æ‰€è¡¨ç¤ºçš„å­—½W¦æŒ‰ç…§charset¾~–码åQŒåƈ以字节方式表½Cºã€‚注意字½W¦ä¸²åœ¨java内存中æ€ÀL˜¯æŒ‰unicode¾~–码存储的。比å¦?中文"åQŒæ­£å¸¸æƒ…况下åQˆå³æ²¡æœ‰é”™è¯¯çš„æ—¶å€™ï¼‰å­˜å‚¨ä¸?<u>4e2d 6587</u>"åQŒå¦‚æžœcharsetä¸?gbk"åQŒåˆ™è¢«ç¼–ç äØ“(f¨´)"<u>d6d0 cec4</u>"åQŒç„¶åŽè¿”回字èŠ?<u>d6 d0 ce c4</u>"。如果charsetä¸?utf8"则最后是"<u>e4 b8 ad e6 96 87</u>"。如果是"iso8859-1"åQŒåˆ™ç”׃ºŽæ— æ³•¾~–码åQŒæœ€åŽè¿”å›?"<u>3f 3f</u>"åQˆä¸¤ä¸ªé—®åøP¼‰ã€?</p> <p class="2"> <strong>3.2. new String(charset)</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">˜q™æ˜¯java字符串处理的另一个标准函敎ͼŒå’Œä¸Šä¸€ä¸ªå‡½æ•°çš„作用相反åQŒå°†å­—节数组按照charset¾~–码˜q›è¡Œ¾l„合识别åQŒæœ€åŽè{æ¢äØ“(f¨´)unicode存储。参考上˜q°getBytes的例子,"gbk" å’?utf8"都可以得出正¼‹®çš„¾l“æžœ"<u>4e2d 6587</u>"åQŒä½†iso8859-1最后变成了"<u>003f 003f</u>"åQˆä¸¤ä¸ªé—®åøP¼‰ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">因䨓(f¨´)utf8可以用来表示/¾~–码所有字½W¦ï¼Œæ‰€ä»¥new String( str.getBytes( "utf8" ), "utf8" ) === stråQŒå³å®Œå…¨å¯é€†ã€?</p> <p class="2"> <strong>3.3. setCharacterEncoding()</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">该函数用来设¾|®httpè¯äh±‚或者相应的¾~–码ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">对于requeståQŒæ˜¯æŒ‡æäº¤å†…容的¾~–码åQŒæŒ‡å®šåŽå¯ä»¥é€šè¿‡getParameter()则直接获得正¼‹®çš„字符ä¸ÔŒ¼Œå¦‚果不指定,则默认ä‹É用iso8859-1¾~–码åQŒéœ€è¦è¿›ä¸€æ­¥å¤„理。参见下˜q?表单输入"。值得注意的是在执行setCharacterEncoding()之前åQŒä¸èƒ½æ‰§è¡Œä“Q何getParameter()。java doc上说明:(x¨¬)This method must be called prior to reading request parameters or reading input using getReader()。而且åQŒè¯¥æŒ‡å®šåªå¯¹POSTæ–ÒŽ(gu¨©)³•有效åQŒå¯¹GETæ–ÒŽ(gu¨©)³•无效。分析原因,应该是在执行½W¬ä¸€ä¸ªgetParameter()的时候,javaž®†ä¼š(x¨¬)按照¾~–码分析所有的提交内容åQŒè€ŒåŽ¾l­çš„getParameter()不再˜q›è¡Œåˆ†æžåQŒæ‰€ä»¥setCharacterEncoding()无效。而对于GETæ–ÒŽ(gu¨©)³•提交表单是,提交的内容在URL中,一开始就已经按照¾~–码分析所有的提交内容åQŒsetCharacterEncoding()自然ž®±æ— æ•ˆã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">对于responseåQŒåˆ™æ˜¯æŒ‡å®šè¾“出内容的¾~–码åQŒåŒæ—Óž¼Œè¯¥è®¾¾|®ä¼š(x¨¬)传递给‹¹è§ˆå™¨ï¼Œå‘Šè¯‰‹¹è§ˆå™¨è¾“出内å®ÒŽ(gu¨©)‰€é‡‡ç”¨çš„编码ã€?</p> <p class="2"> <strong>3.4. 处理˜q‡ç¨‹</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">下面分析两个有代表性的例子åQŒè¯´æ˜Žjava对编码有关问题的处理æ–ÒŽ(gu¨©)³•ã€?</p> <p class="3"> <strong>3.4.1. 表单输入</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">User input<u>  *(gbk:d6d0 cec4)  </u>browser<u>  *(gbk:d6d0 cec4)  </u>web server<u>  iso8859-1(00d6 00d 000ce 00c4)  </u>classåQŒéœ€è¦åœ¨class中进行处理:(x¨¬)getbytes("iso8859-1")ä¸?u>d6 d0 ce c4</u>åQŒnew String("gbk")ä¸?u>d6d0 cec4</u>åQŒå†…存中以unicode¾~–ç åˆ™äØ“(f¨´)<u>4e2d 6587</u>ã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 43pt; TEXT-INDENT: -21pt; tab-stops: list 43.0pt"> <span style="FONT-SIZE: 11pt; FONT-FAMILY: Wingdings">l</span> 用户输入的编码方式和™åµé¢æŒ‡å®šçš„编码有养I¼Œä¹Ÿå’Œç”¨æˆ·çš„æ“ä½œç³»¾lŸæœ‰å…»I¼Œæ‰€ä»¥æ˜¯ä¸ç¡®å®šçš„åQŒä¸Šä¾‹ä»¥gbkä¸ÞZ¾‹ã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 43pt; TEXT-INDENT: -21pt; tab-stops: list 43.0pt"> <span style="FONT-SIZE: 11pt; FONT-FAMILY: Wingdings">l</span> 从browser到web serveråQŒå¯ä»¥åœ¨è¡¨å•中指定提交内å®ÒŽ(gu¨©)—¶ä½¿ç”¨çš„å­—½W¦é›†åQŒå¦åˆ™ä¼š(x¨¬)使用™åµé¢æŒ‡å®šçš„编码。而如果在url中直接用?的方式输入参敎ͼŒåˆ™å…¶¾~–码往往是操作系¾lŸæœ¬íw«çš„¾~–码åQŒå› ä¸ø™¿™æ—¶å’Œ™åµé¢æ— å…³ã€‚上˜qîC»æ—§ä»¥gbk¾~–码ä¸ÞZ¾‹ã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 43pt; TEXT-INDENT: -21pt; tab-stops: list 43.0pt"> <span style="FONT-SIZE: 11pt; FONT-FAMILY: Wingdings">l</span> Web server接收到的是字节流åQŒé»˜è®¤æ—¶åQˆgetParameteråQ‰ä¼š(x¨¬)以iso8859-1¾~–码处理之,¾l“果是不正确的,所以需要进行处理。但如果预先讄¡½®äº†ç¼–码(通过request. setCharacterEncoding ()åQ‰ï¼Œåˆ™èƒ½å¤Ÿç›´æŽ¥èŽ·å–åˆ°æ­£ç¡®çš„ç»“æžœã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 43pt; TEXT-INDENT: -21pt; tab-stops: list 43.0pt"> <span style="FONT-SIZE: 11pt; FONT-FAMILY: Wingdings">l</span> 在页面中指定¾~–码是个好习(f¨¤n)惯,否则可能失去控制åQŒæ— æ³•指定正¼‹®çš„¾~–码ã€?</p> <p class="3"> <strong>3.4.2. æ–‡äšg¾~–译</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">假设文äšg是gbk¾~–码保存的,而编译有两种¾~–码选择åQšgbk或者iso8859-1åQŒå‰è€…是中文windows的默认编码,后者是linux的默认编码,当然也可以在¾~–译时指定编码ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">Jsp<u>  *(gbk:d6d0 cec4)  </u>java file<u>  *(gbk:d6d0 cec4)  </u>compiler read<u>  uincode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  </u>compiler write<u>  utf(gbk: e4b8ad e69687; iso8859-1: *)  </u>compiled file<u>  unicode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  </u>class。所以用gbk¾~–码保存åQŒè€Œç”¨iso8859-1¾~–译的结果是不正¼‹®çš„ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">class<u>  unicode(4e2d 6587)  </u>system.out / jsp.out<u>  gbk(d6d0 cec4)  </u>os console / browserã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 43pt; TEXT-INDENT: -21pt; tab-stops: list 43.0pt"> <span style="FONT-SIZE: 11pt; FONT-FAMILY: Wingdings">l</span> æ–‡äšg可以以多¿Uç¼–码方式保存,中文windows下,默认为ansi/gbkã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 43pt; TEXT-INDENT: -21pt; tab-stops: list 43.0pt"> <span style="FONT-SIZE: 11pt; FONT-FAMILY: Wingdings">l</span> ¾~–译器读取文件时åQŒéœ€è¦å¾—到文件的¾~–码åQŒå¦‚果未指定åQŒåˆ™ä½¿ç”¨¾pȝ»Ÿé»˜è®¤¾~–码。一般classæ–‡äšgåQŒæ˜¯ä»¥ç³»¾lŸé»˜è®¤ç¼–码保存的åQŒæ‰€ä»¥ç¼–译不ä¼?x¨¬)出问题åQŒä½†å¯¹äºŽjspæ–‡äšgåQŒå¦‚果在中文windows下编辑保存,而部¾|²åœ¨è‹±æ–‡linux下运è¡?¾~–译åQŒåˆ™ä¼?x¨¬)出现问题。所以需要在jspæ–‡äšg中用pageEncoding指定¾~–码ã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 43pt; TEXT-INDENT: -21pt; tab-stops: list 43.0pt"> <span style="FONT-SIZE: 11pt; FONT-FAMILY: Wingdings">l</span> Java¾~–译的时候会(x¨¬)转换成统一的unicode¾~–码处理åQŒæœ€åŽä¿å­˜çš„æ—¶å€™å†è½¬æ¢ä¸ºutf¾~–码ã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 43pt; TEXT-INDENT: -21pt; tab-stops: list 43.0pt"> <span style="FONT-SIZE: 11pt; FONT-FAMILY: Wingdings">l</span> 当系¾lŸè¾“出字½W¦çš„æ—¶å€™ï¼Œä¼?x¨¬)按指定¾~–码输出åQŒå¯¹äºŽä¸­æ–‡windows下,System.outž®†ä‹É用gbk¾~–码åQŒè€Œå¯¹äºŽresponseåQˆæµè§ˆå™¨åQ‰ï¼Œåˆ™ä‹É用jspæ–‡äšg头指定的contentTypeåQŒæˆ–è€…å¯ä»¥ç›´æŽ¥äØ“(f¨´)response指定¾~–码。同æ—Óž¼Œä¼?x¨¬)告诉browser¾|‘页的编码。如果未指定åQŒåˆ™ä¼?x¨¬)ä‹É用iso8859-1¾~–码。对于中文,应该为browser指定输出字符串的¾~–码ã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 43pt; TEXT-INDENT: -21pt; tab-stops: list 43.0pt"> <span style="FONT-SIZE: 11pt; FONT-FAMILY: Wingdings">l</span> browser昄¡¤º¾|‘页的时候,首先使用response中指定的¾~–码åQˆjspæ–‡äšg头指定的contentType最¾lˆä¹Ÿåæ˜ åœ¨response上)åQŒå¦‚果未指定åQŒåˆ™ä¼?x¨¬)ä‹É用网™åµä¸­meta™åÒŽ(gu¨©)Œ‡å®šä¸­çš„contentTypeã€?</p> <p class="2"> <strong>3.5. 几处讄¡½®</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">对于web应用½E‹åºåQŒå’Œ¾~–码有关的设¾|®æˆ–者函数如下ã€?</p> <p class="3"> <strong>3.5.1. jsp¾~–译</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">指定文äšg的存储编码,很明显,该设¾|®åº”该置于文件的开头。例如:(x¨¬)<%@page pageEncoding="GBK"%>。另外,对于一般classæ–‡äšgåQŒå¯ä»¥åœ¨¾~–译的时候指定编码ã€?</p> <p class="3"> <strong>3.5.2. jsp输出</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">指定文äšg输出到browser是ä‹É用的¾~–码åQŒè¯¥è®„¡½®ä¹Ÿåº”该置于文件的开头。例如:(x¨¬)<%@ page contentType="text/html; charset= GBK" %>。该讄¡½®å’Œresponse.setCharacterEncoding("GBK")½{‰æ•ˆã€?</p> <p class="3"> <strong>3.5.3. meta讄¡½®</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">指定¾|‘页使用的编码,该设¾|®å¯¹é™æ€ç½‘™åµå°¤å…¶æœ‰ä½œç”¨ã€‚因为静态网™å‰|— æ³•采用jsp的设¾|®ï¼Œè€Œä¸”也无法执行response.setCharacterEncoding()。例如:(x¨¬)<META http-equiv="Content-Type" content="text/html; charset=GBK" /> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">如果同时采用了jsp输出和meta讄¡½®ä¸¤ç§¾~–码指定方式åQŒåˆ™jsp指定的优先。因为jsp指定的直接体现在response中ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">需要注意的是,apache有一个设¾|®å¯ä»¥ç»™æ— ç¼–码指定的¾|‘页指定¾~–码åQŒè¯¥æŒ‡å®š½{‰åŒäºŽjsp的编码指定方式,所以会(x¨¬)覆盖静态网™åµä¸­çš„meta指定。所以有人徏议关闭该讄¡½®ã€?</p> <p class="3"> <strong>3.5.4. form讄¡½®</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">当浏览器提交表单的时候,可以指定相应的编码。例如:(x¨¬)<form accept-charset= "gb2312">。一般不必不使用该设¾|®ï¼Œ‹¹è§ˆå™¨ä¼š(x¨¬)直接使用¾|‘页的编码ã€?</p> <p class="1"> <strong>4. ¾pȝ»Ÿè½¯äšg</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">下面讨论几个相关的系¾lŸèÊYä»¶ã€?</p> <p class="2"> <strong>4.1. mysql数据åº?/strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">很明显,要支持多语言åQŒåº”该将数据库的¾~–码讄¡½®æˆutf或者unicodeåQŒè€Œutf更适合与存储。但是,如果中文数据中包含的英文字母很少åQŒå…¶å®žunicodeæ›´äØ“(f¨´)适合ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">数据库的¾~–码可以通过mysql的配¾|®æ–‡ä»¶è®¾¾|®ï¼Œä¾‹å¦‚default-character-set=utf8。还可以在数据库链接URL中设¾|®ï¼Œä¾‹å¦‚åQ?useUnicode=true&characterEncoding=UTF-8。注意这两者应该保持一è‡ß_(d¨¢)¼Œåœ¨æ–°çš„sql版本里,在数据库链接URL里可以不˜q›è¡Œè®„¡½®åQŒä½†ä¹Ÿä¸èƒ½æ˜¯é”™è¯¯çš„设¾|®ã€?</p> <p class="2"> <strong>4.2. apache</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">appache和编码有关的配置在httpd.conf中,例如AddDefaultCharset UTF-8。如前所˜qŽÍ¼Œè¯¥åŠŸèƒ½ä¼š(x¨¬)ž®†æ‰€æœ‰é™æ€é¡µé¢çš„¾~–码讄¡½®ä¸ºUTF-8åQŒæœ€å¥½å…³é—­è¯¥åŠŸèƒ½ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">另外åQŒapache˜q˜æœ‰å•独的模块来处理¾|‘页响应å¤ß_(d¨¢)¼Œå…¶ä¸­ä¹Ÿå¯èƒ½å¯¹¾~–码˜q›è¡Œè®„¡½®ã€?</p> <p class="2"> <strong>4.3. linux默认¾~–码</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">˜q™é‡Œæ‰€è¯´çš„linux默认¾~–码åQŒæ˜¯æŒ‡è¿è¡Œæ—¶çš„环境变量。两个重要的环境变量是LC_ALLå’ŒLANGåQŒé»˜è®¤ç¼–码会(x¨¬)影响到java URLEncode的行为,下面有描˜q°ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">廸™®®éƒ½è®¾¾|®äØ“(f¨´)"zh_CN.UTF-8"ã€?</p> <p class="2"> <strong>4.4. 其它</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">ä¸ÞZº†æ”¯æŒä¸­æ–‡æ–‡äšg名,linux在加载磁盘时应该指定字符集,例如åQšmount /dev/hda5 /mnt/hda5/ -t ntfs -o iocharset=gb2312ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">另外åQŒå¦‚前所˜qŽÍ¼Œä½¿ç”¨GETæ–ÒŽ(gu¨©)³•提交的信息不支持request.setCharacterEncoding()åQŒä½†å¯ä»¥é€šè¿‡tomcat的配¾|®æ–‡ä»¶æŒ‡å®šå­—½W¦é›†åQŒåœ¨tomcatçš„server.xmlæ–‡äšg中,形如åQ?lt;Connector ... URIEncoding="GBK"/>。这¿Uæ–¹æ³•å°†¾lŸä¸€è®„¡½®æ‰€æœ‰è¯·æ±‚,而不能针对具体页面进行设¾|®ï¼Œä¹Ÿä¸ä¸€å®šå’Œbrowserä½¿ç”¨çš„ç¼–ç ç›¸åŒï¼Œæ‰€ä»¥æœ‰æ—¶å€™åÆˆä¸æ˜¯æ‰€æœŸæœ›çš„ã€?</p> <p class="1"> <strong>5. URL地址</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">URL地址中含有中文字½W¦æ˜¯å¾ˆéº»çƒ¦çš„åQŒå‰é¢æ˜q°è¿‡ä½¿ç”¨GETæ–ÒŽ(gu¨©)³•提交表单的情况,使用GETæ–ÒŽ(gu¨©)³•æ—Óž¼Œå‚æ•°ž®±æ˜¯åŒ…含在URL中ã€?</p> <p class="2"> <strong>5.1. URL¾~–码</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">对于URL中的一些特ŒDŠå­—½W¦ï¼Œ‹¹è§ˆå™¨ä¼š(x¨¬)自动˜q›è¡Œ¾~–码。这些字½W¦é™¤äº?/?&"½{‰å¤–åQŒè¿˜åŒ…括unicode字符åQŒæ¯”如汉子。这时的¾~–码比较ç‰ÒŽ(gu¨©)®Šã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">IE有一个选项"æ€ÀL˜¯ä½¿ç”¨UTF-8发送URL"åQŒå½“该选项有效æ—Óž¼ŒIEž®†ä¼š(x¨¬)对特ŒDŠå­—½W¦è¿›è¡ŒUTF-8¾~–码åQŒåŒæ—¶è¿›è¡ŒURL¾~–码。如果改选项无效åQŒåˆ™ä½¿ç”¨é»˜è®¤¾~–码"GBK"åQŒåƈ且不˜q›è¡ŒURL¾~–码。但是,对于URL后面的参敎ͼŒåˆ™æ€ÀL˜¯ä¸è¿›è¡Œç¼–码,相当于UTF-8选项无效。比å¦?中文.html?a=中文"åQŒå½“UTF-8选项有效æ—Óž¼Œž®†å‘送链æŽ?%<u>e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87</u>"åQ›è€ŒUTF-8选项无效æ—Óž¼Œž®†å‘送链æŽ?<u>\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87</u>"。注意后者前面的"中文"两个字只æœ?个字节,而前者却æœ?8个字节,˜q™ä¸»è¦æ—¶URL¾~–码的原因ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">当web serveråQˆtomcatåQ‰æŽ¥æ”¶åˆ°è¯¥é“¾æŽ¥æ—¶åQŒå°†ä¼?x¨¬)进行URL解码åQŒå³åŽÀLމ"%"åQŒåŒæ—¶æŒ‰ç…§ISO8859-1¾~–码åQˆä¸Šé¢å·²¾læ˜qŽÍ¼Œå¯ä»¥ä½¿ç”¨URLEncoding来设¾|®æˆå…¶å®ƒ¾~–码åQ‰è¯†åˆ«ã€‚上˜qîC¾‹å­çš„¾l“果分别æ˜?<u>\ue4\ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87</u>"å’?<u>\u4e\u2d\u65\u87.html?a=\u4e\u2d\u65\u87</u>"åQŒæ³¨æ„å‰è€…前面的"中文"两个字恢复成äº?个字½W¦ã€‚这里用"\u"åQŒè¡¨½Cºæ˜¯unicodeã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 22pt">所以,ç”׃ºŽå®¢æˆ·ç«¯è®¾¾|®çš„不同åQŒç›¸åŒçš„链接åQŒåœ¨æœåŠ¡å™¨ä¸Šå¾—åˆ°äº†ä¸åŒç»“æžœã€‚è¿™ä¸ªé—®é¢˜ä¸ž®‘äh都遇刎ͼŒå´æ²¡æœ‰å¾ˆå¥½çš„解决办法。所以有的网站会(x¨¬)廸™®®ç”¨æˆ·ž®è¯•关闭UTF-8选项。不˜q‡ï¼Œä¸‹é¢ä¼?x¨¬)描˜qîC¸€ä¸ªæ›´å¥½çš„处理办法ã€?</p> <p class="2"> <strong>5.2. rewrite</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">熟æ?zh¨¨n)‰çš„äh都知道,apache有一个功能强大的rewrite模块åQŒè¿™é‡Œä¸æè¿°å…¶åŠŸèƒ½ã€‚éœ€è¦è¯´æ˜Žçš„æ˜¯è¯¥æ¨¡å—ä¼?x¨¬)自动将URL解码åQˆåŽ»é™?åQ‰ï¼Œå›_®Œæˆä¸Š˜q°web serveråQˆtomcatåQ‰çš„部分功能。有相关文档介绍说可以ä‹É用[NE]参数来关闭该功能åQŒä½†æˆ‘è¯•éªŒåÆˆæœªæˆåŠŸï¼Œå¯èƒ½æ˜¯å› ä¸ºç‰ˆæœ¬ï¼ˆæˆ‘ä‹É用的是apache 2.0.54åQ‰é—®é¢˜ã€‚另外,当参æ•îC¸­å«æœ‰"?& "½{‰ç¬¦åïL(f¨¥ng)š„æ—¶å€™ï¼Œè¯¥åŠŸèƒ½å°†å¯ÆD‡´¾pȝ»Ÿå¾—不到正常结果ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">rewrite本èínä¼ég¹Žå®Œå…¨æ˜¯é‡‡ç”¨å­—节处理的方式åQŒè€Œä¸è€ƒè™‘字符串的¾~–码åQŒæ‰€ä»¥ä¸ä¼?x¨¬)带来编码问题ã€?</p> <p class="2"> <strong>5.3. URLEncode.encode()</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">˜q™æ˜¯Java本èín提供对的URL¾~–码函数åQŒå®Œæˆçš„工作和上˜q°UTF-8é€‰é¡¹æœ‰æ•ˆæ—¶æµè§ˆå™¨æ‰€åšçš„å·¥ä½œç›æ€¼¼ã€‚值得说明的是åQŒjava已经不赞成不指定¾~–码来ä‹É用该æ–ÒŽ(gu¨©)³•åQˆdeprecatedåQ‰ã€‚应该在使用的时候增加编码指定ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">当不指定¾~–码的时候,该方法ä‹É用系¾lŸé»˜è®¤ç¼–码,˜q™ä¼š(x¨¬)坯D‡´è½¯äšg˜qè¡Œ¾l“果得不¼‹®å®šã€‚比如对äº?中文"åQŒå½“¾pȝ»Ÿé»˜è®¤¾~–码ä¸?gb2312"æ—Óž¼Œ¾l“æžœæ˜?%<u>4e%2d%65%87</u>"åQŒè€Œé»˜è®¤ç¼–ç äØ“(f¨´)"UTF-8"åQŒç»“果却æ˜?%<u>e4%b8%ad%e6%96%87</u>"åQŒåŽ¾l­ç¨‹åºå°†éš¾ä»¥å¤„理。另外,˜q™å„¿è¯´çš„¾pȝ»Ÿé»˜è®¤¾~–码是由˜qè¡Œtomcat时的环境变量LC_ALLå’ŒLANG½{‰å†³å®šçš„åQŒæ›¾¾lå‡ºçŽ°è¿‡tomcat重启后就出现ä¹Þq çš„é—®é¢˜ï¼Œæœ€åŽæ‰éƒé—·çš„å‘çŽ°æ˜¯å› äØ“(f¨´)修改修改了这两个环境变量ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">廸™®®¾lŸä¸€æŒ‡å®šä¸?UTF-8"¾~–码åQŒå¯èƒ½éœ€è¦ä¿®æ”¹ç›¸åº”çš„½E‹åºã€?</p> <p class="2"> <strong>5.4. 一个解å†Ïx–¹æ¡?/strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">上面说è“v˜q‡ï¼Œå› äØ“(f¨´)‹¹è§ˆå™¨è®¾¾|®çš„不同åQŒå¯¹äºŽåŒä¸€ä¸ªé“¾æŽ¥ï¼Œweb server收到的是不同内容åQŒè€ŒèÊYä»¶ç³»¾lŸæœ‰æ— æ³•知道˜q™ä¸­é—´çš„区别åQŒæ‰€ä»¥è¿™ä¸€åè®®ç›®å‰˜q˜å­˜åœ¨ç¼ºé™—÷€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">针对具体问题åQŒä¸åº”è¯¥ä¾¥å¹¸è®¤äØ“(f¨´)所有客æˆïL(f¨¥ng)š„IE讄¡½®éƒ½æ˜¯UTF-8有效的,也不应该¾_—暴的徏议用户修改IE讄¡½®åQŒè¦çŸ¥é“åQŒç”¨æˆ·ä¸å¯èƒ½åŽ»è®°ä½æ¯ä¸€ä¸ªweb server的设¾|®ã€‚所以,接下来的解决办法ž®±åªèƒ½æ˜¯è®©è‡ªå·Þqš„½E‹åºå¤šä¸€ç‚ÒŽ(gu¨©)™ºèƒ½ï¼š(x¨¬)æ ÒŽ(gu¨©)®å†…容来分析编码是否UTF-8ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">比较òq¸è¿çš„æ˜¯UTF-8¾~–码相当有规律,所以可以通过分析传输˜q‡æ¥çš„链接内容,来判断是否是正确的UTF-8字符åQŒå¦‚果是åQŒåˆ™ä»¥UTF-8处理之,如果不是åQŒåˆ™ä½¿ç”¨å®¢æˆ·é»˜è®¤¾~–码åQˆæ¯”å¦?GBK"åQ‰ï¼Œä¸‹é¢æ˜¯ä¸€ä¸ªåˆ¤æ–­æ˜¯å¦UTF-8的例子,如果你了解相应规律,ž®±å®¹æ˜“理解ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">public static boolean isValidUtf8(byte[] b,int aMaxCount){ </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">       int lLen=b.length,lCharCount=0; </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">       for(int i=0;i<lLen && lCharCount<aMaxCount;++lCharCount){ </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">              byte lByte=b[i++];//to fast operation, ++ now, ready for the following for(;;) </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">              if(lByte>=0) continue;//>=0 is normal ascii </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">              if(lByte<(byte)0xc0 || lByte>(byte)0xfd) return false; </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">              int lCount=lByte>(byte)0xfc?5:lByte>(byte)0xf8?4 </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">                     :lByte>(byte)0xf0?3:lByte>(byte)0xe0?2:1; </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">              if(i+lCount>lLen) return false; </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">              for(int j=0;j<lCount;++j,++i) if(b[i]>=(byte)0xc0) return false; </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">       } </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">       return true; </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">} </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">相应圎ͼŒä¸€ä¸ªä‹É用上˜q°æ–¹æ³•的例子如下åQ?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">public static String getUrlParam(String aStr,String aDefaultCharset) </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">throws UnsupportedEncodingException{ </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">       if(aStr==null) return null; </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">       byte[] lBytes=aStr.getBytes("ISO-8859-1"); </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">       return new String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset); </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">} </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">不过åQŒè¯¥æ–ÒŽ(gu¨©)³•ä¹Ÿå­˜åœ¨ç¼ºé™øP¼Œå¦‚下两方面:(x¨¬) </p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt; tab-stops: list 42.0pt"> <span style="FONT-FAMILY: Wingdings">l</span> 没有包括对用户默认编码的识别åQŒè¿™å¯ä»¥æ ÒŽ(gu¨©)®è¯äh±‚信息的语­a€æ¥åˆ¤æ–­ï¼Œä½†ä¸ä¸€å®šæ­£¼‹®ï¼Œå› äØ“(f¨´)我们有时候也ä¼?x¨¬)输入一些韩文,或者其他文字ã€?</p> <p class="MsoBodyTextIndent" style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt; tab-stops: list 42.0pt"> <span style="FONT-FAMILY: Wingdings">l</span> 可能ä¼?x¨¬)错误判断UTF-8字符åQŒä¸€ä¸ªä¾‹å­æ˜¯"学习(f¨¤n)"两个字,其GBK¾~–码æ˜? <u>\xd1\xa7\xcf\xb0</u>"åQŒå¦‚æžœä‹É用上˜q°isValidUtf8æ–ÒŽ(gu¨©)³•判断åQŒå°†˜q”回true。可以考虑使用更严格的判断æ–ÒŽ(gu¨©)³•åQŒä¸˜q‡ä¼°è®¡æ•ˆæžœä¸å¤§ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">有一个例子可以证明google也遇åˆîCº†ä¸Šè¿°é—®é¢˜åQŒè€Œä¸”也采用了和上˜q°ç›¸ä¼¼çš„处理æ–ÒŽ(gu¨©)³•åQŒæ¯”如,如果在地址栏中输入"<a ><font color="#002c99">http://www.google.com/search?hl=zh-CN&newwindow=1&q=学习(f¨¤n)</font></a>"åQŒgooglež®†æ— æ³•æ­£¼‹®è¯†åˆ«ï¼Œè€Œå…¶ä»–汉字一般能够正常识别ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">最后,应该补充说明一下,如果不ä‹É用rewrite规则åQŒæˆ–者通过表单提交数据åQŒå…¶å®žåƈ不一定会(x¨¬)遇到上述问题åQŒå› ä¸ø™¿™æ—¶å¯ä»¥åœ¨æäº¤æ•°æ®æ—¶æŒ‡å®šå¸Œæœ›çš„¾~–码。另外,中文文äšg名确实会(x¨¬)带来问题åQŒåº”该è°}æ…Žä‹É用ã€?</p> <p class="1"> <strong>6. 其它</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">下面描述一些和¾~–码有关的其他问题ã€?</p> <p class="2"> <strong>6.1. SecureCRT</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">除了‹¹è§ˆå™¨å’ŒæŽ§åˆ¶åîC¸Ž¾~–码有关外,一些客æˆïL(f¨¥ng)«¯ä¹Ÿå¾ˆæœ‰å…³¾p…R€‚比如在使用SecureCRT˜qžæŽ¥linuxæ—Óž¼Œåº”该让SecureCRT的显½Cºç¼–码(不同的sessionåQŒå¯ä»¥æœ‰ä¸åŒçš„编码设¾|®ï¼‰å’Œlinux的编码环境变量保持一致。否则看到的一些帮助信息,ž®±å¯èƒ½æ˜¯ä¹Þq ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">另外åQŒmysql有自å·Þqš„¾~–码讄¡½®åQŒä¹Ÿåº”该保持和SecureCRT的显½Cºç¼–码一致。否则通过SecureCRT执行sql语句的时候,可能无法处理中文字符åQŒæŸ¥è¯¢ç»“果也ä¼?x¨¬)出çŽîCؕ码ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">对于Utf-8æ–‡äšgåQŒå¾ˆå¤šç¼–辑器åQˆæ¯”如记事本åQ‰ä¼š(x¨¬)åœ¨æ–‡ä»¶å¼€å¤´å¢žåŠ ä¸‰ä¸ªä¸å¯è§çš„æ ‡å¿—å­—èŠ‚ï¼Œå¦‚æžœä½œäØ“(f¨´)mysql的输入文ä»Óž¼Œåˆ™å¿…™å»è¦åŽÀLމ˜q™ä¸‰ä¸ªå­—½W¦ã€‚(用linuxçš„vi保存可以åŽÀLމ˜q™ä¸‰ä¸ªå­—½W¦ï¼‰ã€‚一个有­‘£çš„现象是,在中文windows下,创徏一个新txtæ–‡äšgåQŒç”¨è®îCº‹æœ¬æ‰“å¼€åQŒè¾“å…?˜qžé€?两个字,保存åQŒå†æ‰“å¼€åQŒä½ ä¼?x¨¬)发çŽîC¸¤ä¸ªå­—没了åQŒåªç•™ä¸‹ä¸€ä¸ªå°é»‘点ã€?</p> <p class="2"> <strong>6.2. ˜q‡æ×o(h¨´)å™?/strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">如果需要统一讄¡½®¾~–码åQŒåˆ™é€šè¿‡filter˜q›è¡Œè®„¡½®æ˜¯ä¸ªä¸é”™çš„选择。在filter class中,可以¾lŸä¸€ä¸ºéœ€è¦çš„è¯äh±‚或者回应设¾|®ç¼–码。参加上˜q°setCharacterEncoding()。这个类apache已经¾l™å‡ºäº†å¯ä»¥ç›´æŽ¥ä‹É用的例子SetCharacterEncodingFilterã€?</p> <p class="2"> <strong>6.3. POSTå’ŒGET</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">很明显,以POST提交信息æ—Óž¼ŒURL有更好的可读性,而且可以方便的ä‹É用setCharacterEncoding()来处理字½W¦é›†é—®é¢˜ã€‚但GETæ–ÒŽ(gu¨©)³•形成的URL能够更容易表辄¡½‘™å늚„实际内容åQŒä¹Ÿèƒ½å¤Ÿç”¨äºŽæ”¶è—ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">从统一的角度考虑问题åQŒå¾è®®é‡‡ç”¨GETæ–ÒŽ(gu¨©)³•åQŒè¿™è¦æ±‚在程序中获得参数是进行特ŒDŠå¤„理,而无法ä‹É用setCharacterEncoding()的便利,如果不考虑rewriteåQŒå°±ä¸å­˜åœ¨IEçš„UTF-8问题åQŒå¯ä»¥è€ƒè™‘通过讄¡½®URIEncoding来方便获取URL中的参数ã€?</p> <p class="2"> <strong>6.4. ½Ž€¾Jä½“¾~–码转换</strong> </p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">GBK同时包含½Ž€ä½“å’Œ¾Jä½“¾~–码åQŒä¹Ÿž®±æ˜¯è¯´åŒä¸€ä¸ªå­—åQŒç”±äºŽç¼–码不同,在GBK¾~–码下属于两个字。有时候,ä¸ÞZº†æ­£ç¡®å–得完整的结果,应该ž®†ç¹ä½“å’Œ½Ž€ä½“进行统一。可以考虑ž®†UTF、GBK中的所有繁体字åQŒè{æ¢äØ“(f¨´)相应的简体字åQŒBIG5¾~–码的数据,也应该è{化成相应的简体字。当ç„Óž¼Œä»æ—§ä»¥UTF¾~–码存储ã€?</p> <p class="MsoBodyTextIndent" style="TEXT-INDENT: 21pt">例如åQŒå¯¹äº?语言 語言"åQŒç”¨UTF表示ä¸?<u>\x</u><u>E8\xAF\xAD\xE8\xA8\x80 \xE8\xAA\x9E\xE8\xA8\x80</u>"åQŒè¿›è¡Œç®€¾Jä½“¾~–码转换后应该是两个相同çš?"<u>\x</u><u>E8\xAF\xAD\xE8\xA8\x80></u>"ã€?</p> <img src ="http://www.aygfsteel.com/wml/aggbug/55985.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/wml/" target="_blank">wml</a> 2006-06-30 16:49 <a href="http://www.aygfsteel.com/wml/articles/55985.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> Ö÷Õ¾Ö©Öë³ØÄ£°å£º <a href="http://" target="_blank">ÀóÆÖÏØ</a>| <a href="http://" target="_blank">×ñ»¯ÊÐ</a>| <a href="http://" target="_blank">ºþÖÝÊÐ</a>| <a href="http://" target="_blank">ºôÂ×±´¶ûÊÐ</a>| <a href="http://" target="_blank">³çÎÄÇø</a>| <a href="http://" target="_blank">ÆÖ½­ÏØ</a>| <a href="http://" target="_blank">ÔúêãÌØÆì</a>| <a href="http://" target="_blank">»³¼¯ÏØ</a>| <a href="http://" target="_blank">»ÆÉ½ÊÐ</a>| <a href="http://" target="_blank">Ê®ÑßÊÐ</a>| <a href="http://" target="_blank">¸§ËÉÏØ</a>| <a href="http://" target="_blank">¾«ºÓÏØ</a>| <a href="http://" target="_blank">ÎäÚìÏØ</a>| <a href="http://" target="_blank">·áÔ­ÊÐ</a>| <a href="http://" target="_blank">µÂÇìÏØ</a>| <a href="http://" target="_blank">ÎͰ²ÏØ</a>| <a href="http://" target="_blank">ÚüÖÝÊÐ</a>| <a href="http://" target="_blank">½Á¼ÏØ</a>| <a href="http://" target="_blank">ÄþÑôÏØ</a>| <a href="http://" target="_blank">³±ÖÝÊÐ</a>| <a href="http://" target="_blank">Ä«ÓñÏØ</a>| <a href="http://" target="_blank">Í­É½ÏØ</a>| <a href="http://" target="_blank">ÒÁ´ºÊÐ</a>| <a href="http://" target="_blank">±£¾¸ÏØ</a>| <a href="http://" target="_blank">Ö麣ÊÐ</a>| <a href="http://" target="_blank">н®</a>| <a href="http://" target="_blank">·½ÕýÏØ</a>| <a href="http://" target="_blank">ÁÙÇåÊÐ</a>| <a href="http://" target="_blank">ÄÏÕÙÏØ</a>| <a href="http://" target="_blank">½ðÌÃÏØ</a>| <a href="http://" target="_blank">ʯÊ×ÊÐ</a>| <a href="http://" target="_blank">ÃÉÉ½ÏØ</a>| <a href="http://" target="_blank">ÁÙëÔÏØ</a>| <a href="http://" target="_blank">ÌúÁëÏØ</a>| <a href="http://" target="_blank">ÁéÊÙÏØ</a>| <a href="http://" target="_blank">¸ßÌ¨ÏØ</a>| <a href="http://" target="_blank">ËçÄþÏØ</a>| <a href="http://" target="_blank">Û°³ÇÏØ</a>| <a href="http://" target="_blank">ʯÃÞÏØ</a>| <a href="http://" target="_blank">ËÄ×ÓÍõÆì</a>| <a href="http://" target="_blank">Ê©µéÏØ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>