﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-没有眼泪-随笔分类-web开发</title><link>http://www.blogjava.net/zhangchao/category/39039.html</link><description>Don't Cry!</description><language>zh-cn</language><lastBuildDate>Sun, 28 Jul 2013 08:28:57 GMT</lastBuildDate><pubDate>Sun, 28 Jul 2013 08:28:57 GMT</pubDate><ttl>60</ttl><item><title>get和post乱码解决</title><link>http://www.blogjava.net/zhangchao/archive/2013/07/27/402039.html</link><dc:creator>zhangchao</dc:creator><author>zhangchao</author><pubDate>Sat, 27 Jul 2013 08:56:00 GMT</pubDate><guid>http://www.blogjava.net/zhangchao/archive/2013/07/27/402039.html</guid><wfw:comment>http://www.blogjava.net/zhangchao/comments/402039.html</wfw:comment><comments>http://www.blogjava.net/zhangchao/archive/2013/07/27/402039.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/zhangchao/comments/commentRss/402039.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhangchao/services/trackbacks/402039.html</trackback:ping><description><![CDATA[<span style="font-family: Courier; ">在javaweb开发过程中get和post乱码是一个老生常谈的话题了，相信人人都遇到过。网上的文章也很多，但往往是看的越多就越糊涂，有些东西只有自己了然于心才能真正地明白。下面就写一篇文章，就乱码产生的过程分析一下。</span><br /><span class="Apple-style-span" style="font-family: Courier; ">为什么会产生乱码？<br /></span><span class="Apple-style-span" style="font-family: 宋体; "><span style="font-size:10.5pt;font-family:宋体;Times New Roman&quot;;"><br /><div><p style="margin-left:18.0pt;text-indent:-18.0pt;"><span><span style="font-family: Courier; ">1.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp; &nbsp;</span></span></span><span style="font-family: Courier; ">为什么会产生乱码？</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">因为浏览器不允许提交非</span><span style="font-family: Courier; ">ASCII</span><span style="font-family: Courier; ">字符，如果提交了非</span><span style="font-family: Courier; ">ASCII</span><span style="font-family: Courier; ">，则浏览器自动对其进行编码，将它们转换为</span><span style="font-family: Courier; ">ASCII</span><span style="font-family: Courier; ">字符。根据浏览器的不同，转换时使用的编码也不同，比如有些浏览器会使用</span><span style="font-family: Courier; ">utf-8</span><span style="font-family: Courier; ">进行编码，而有些会使用</span><span style="font-family: Courier; ">gbk</span><span style="font-family: Courier; ">进行编码。</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span><span style="font-family: Courier; ">2.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp; &nbsp;</span></span></span><span style="font-family: Courier; ">浏览器为什么不允许提交非</span><span style="font-family: Courier; ">ASCII</span><span style="font-family: Courier; ">字符？</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">以下是我个人观点，仅供参考。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">因为浏览器和服务器通信，传输的都是字节。而我们在页面提交的都是字符，所以浏览器底层就有一个将字符转换为字节的过程，这个过程涉及到编码，浏览器到底是用</span><span style="font-family: Courier; ">utf-8</span><span style="font-family: Courier; ">、</span><span style="font-family: Courier; ">gbk</span><span style="font-family: Courier; ">还是</span><span style="font-family: Courier; ">iso-8859-1</span><span style="font-family: Courier; ">将字符转换为字节呢？我想应该是</span><span style="font-family: Courier; ">iso-8859-1</span><span style="font-family: Courier; ">，因为这是西欧默认使用的编码。何况，也没有任何理由使用前两种编码格式。但是</span><span style="font-family: Courier; ">iso-8859-1</span><span style="font-family: Courier; ">编码是不能识别中文以及其他非</span><span style="font-family: Courier; ">ASCII</span><span style="font-family: Courier; ">字符的，所以如果字符中存在这类字符，那么将字符转换为字节的过程中势必会产生乱码。为了避免这种情况的发生，浏览器自动对非</span><span style="font-family: Courier; ">ASCII</span><span style="font-family: Courier; ">字符进行了编码，将这类字符转换为</span><span style="font-family: Courier; ">ASCII</span><span style="font-family: Courier; ">字符，这样就能避免乱码问题。</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span><span style="font-family: Courier; ">3.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp; &nbsp;</span></span></span><span style="font-family: Courier; ">GET</span><span style="font-family: Courier; ">和</span><span style="font-family: Courier; ">POST</span><span style="font-family: Courier; ">提交表单，分别根据什么对非</span><span style="font-family: Courier; ">ASCII</span><span style="font-family: Courier; ">字符进行编码？</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">GET</span><span style="font-family: Courier; ">：</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">情况比较复杂，不同浏览器也不一样，有的使用</span><span style="font-family: Courier; ">gbk</span><span style="font-family: Courier; ">，有的使用</span><span style="font-family: Courier; ">utf-8</span><span style="font-family: Courier; ">不好一概而论。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">POST</span><span style="font-family: Courier; ">：</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">浏览器会根据网页编码对表单中的数据编码。比如我们在</span><span style="font-family: Courier; ">jsp</span><span style="font-family: Courier; ">页面第一行所写的：</span><span style="font-family: Courier; ">&lt;%@page contentType="text/html;charset=UTF-8"%&gt;</span><span style="font-family: Courier; ">。那么这个网页响应给客户端后使用的就是</span><span style="font-family: Courier; ">utf-8</span><span style="font-family: Courier; ">编码，那么</span><span style="font-family: Courier; ">post</span><span style="font-family: Courier; ">时使用的也是这个编码。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">编码后的格式可以参考</span><span style="font-family: Courier; ">java</span><span style="font-family: Courier; ">中的</span><span style="font-family: Courier; ">URLEncoder.encode</span><span style="font-family: Courier; ">方法编码的结果。</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span><span style="font-family: Courier; ">4.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;</span></span></span><span style="font-family: Courier; ">服务器底层如何处理提交的数据。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">上面</span><span style="font-family: Courier; ">2</span><span style="font-family: Courier; ">已经提到，客户端和服务器端传输的是字节，那么服务器端接收到的原始数据就是字节。但是我们的程序通常需要从服务器获取字符，而不是字节，所以服务器端必须将字节转换为字符。这里也涉及编码，服务器采取什么编码方式将字节转换为字符？我想也是</span><span style="font-family: Courier; ">iso-8859-1</span><span style="font-family: Courier; ">，这样和客户端的编码方式一致，不会产生乱码，相当于一个还原字符的过程。这里有个问题，比如客户端发送：</span><span style="font-family: Courier; ">name=%D6%D0%B9%FA</span><span style="font-family: Courier; ">，那么服务器端还原后也是：</span><span style="font-family: Courier; ">name=%D6%D0%B9%FA</span><span style="font-family: Courier; ">。那么我们使用</span><span style="font-family: Courier; ">request.getParameter(&#8220;name&#8221;)</span><span style="font-family: Courier; ">如何能得到正确的值呢？难道要我们自己再进行转换？答案是：</span><span style="font-family: Courier; ">NO</span><span style="font-family: Courier; ">。根据</span><span style="font-family: Courier; ">Servlet</span><span style="font-family: Courier; ">规范，</span><span style="font-family: Courier; ">Servlet</span><span style="font-family: Courier; ">中获取数据的方法会按照指定的字符集解码。指定的字符集是什么？默认是</span><span style="font-family: Courier; ">iso-8859-1</span><span style="font-family: Courier; ">。正是因为使用了</span><span style="font-family: Courier; ">iso-8859-1</span><span style="font-family: Courier; ">解码我们发送的参数，导致了乱码的产生，这里才是产生乱码的源头。具体解码的过程可以看看</span><span style="font-family: Courier; ">java</span><span style="font-family: Courier; ">的</span><span style="font-family: Courier; ">URLDecode.decode</span><span style="font-family: Courier; ">方法。既然知道了产生乱码的原因是因为服务器默认使用</span><span style="font-family: Courier; ">iso-8859-1</span><span style="font-family: Courier; ">解码，那我们就得想办法更改服务器使用的解码编码。好在服务器已经提供给我们修改的方式了，我们可以在服务器中进行配置，比如</span><span style="font-family: Courier; ">Tomcat</span><span style="font-family: Courier; ">可以在</span><span style="font-family: Courier; ">server.xml</span><span style="font-family: Courier; ">中进行配置，比如：</span><span style="font-family: Courier; ">URIEncoding=</span><span style="font-family: Courier; ">"GBK"</span><span style="font-family: Courier; ">这样服务器就会使用gbk</span><span style="font-family: Courier; ">编码解码</span><span style="font-family: Courier; ">，这种方式主要针对</span><span style="font-family: Courier; ">GET</span><span style="font-family: Courier; ">提交的数据，对于</span><span style="font-family: Courier; ">POST</span><span style="font-family: Courier; ">更常用的是</span><span style="font-family: Courier; ">request.setCharacterEncoding(String charset)</span><span style="font-family: Courier; ">设置解码编码。</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span><span style="font-family: Courier; ">5.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;</span></span></span><span style="font-family: Courier; ">为了避免乱码，客户端应该如何做？</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">GET</span><span style="font-family: Courier; ">：</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">对于含有非</span><span style="font-family: Courier; ">ASCII</span><span style="font-family: Courier; ">字符的</span><span style="font-family: Courier; ">URL</span><span style="font-family: Courier; ">自己进行编码，比如使用</span><span style="font-family: Courier; ">javascript</span><span style="font-family: Courier; ">中的方法进行编码。这样就不需要浏览器为我们编码了，从而解决了浏览器编码的不确定性。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">POST</span><span style="font-family: Courier; ">：</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family: Courier; ">只要正确设置网页编码即可。</span></p></div></span></span><img src ="http://www.blogjava.net/zhangchao/aggbug/402039.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhangchao/" target="_blank">zhangchao</a> 2013-07-27 16:56 <a href="http://www.blogjava.net/zhangchao/archive/2013/07/27/402039.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入研究Servlet线程安全性问题</title><link>http://www.blogjava.net/zhangchao/archive/2009/05/31/279163.html</link><dc:creator>zhangchao</dc:creator><author>zhangchao</author><pubDate>Sun, 31 May 2009 02:06:00 GMT</pubDate><guid>http://www.blogjava.net/zhangchao/archive/2009/05/31/279163.html</guid><wfw:comment>http://www.blogjava.net/zhangchao/comments/279163.html</wfw:comment><comments>http://www.blogjava.net/zhangchao/archive/2009/05/31/279163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhangchao/comments/commentRss/279163.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhangchao/services/trackbacks/279163.html</trackback:ping><description><![CDATA[Servlet/JSP技术和ASP、PHP等相比，由于其多线程运行而具有很高的执行效率。由于Servlet/JSP默认是以多线程模式执行的，所
以，在编写代码时需要非常细致地考虑多线程的安全性问题。然而，很多人编写Servlet/JSP程序时并没有注意到多线程安全性的问题，这往往造成编写
的程序在少量用户访问时没有任何问题，而在并发用户上升到一定值时，就会经常出现一些莫明其妙的问题。
<p>　　Servlet的多线程机制</p>
<p>
Servlet体系结构是建立在Java多线程机制之上的，它的生命周期是由Web容器负责的。当客户端第一次请求某个Servlet
时，Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时，一般不会再实例化该
Servlet类，也就是有多个线程在使用这个实例。Servlet容器会自动使用线程池等技术来支持系统的运行，如图1所示。</p>
<p>　　<img src="http://www.feeten.cn/article/UploadPic/2009-1/200912181631955.jpg" onload="return imgresize(this);" onclick="javascript:window.open(this.src);" style="cursor: pointer;"  alt="" /></p>
<p>　　图1 Servlet线程池</p>
<p>　　这样，当两个或多个线程同时访问同一个Servlet时，可能会发生多个线程同时访问同一资源的情况，数据可能会变得不一致。所以在用Servlet构建的Web应用时如果不注意线程安全的问题，会使所写的Servlet程序有难以发现的错误。</p>
<p>　　Servlet的线程安全问题</p>
<p>　　Servlet的线程安全问题主要是由于实例变量使用不当而引起的，这里以一个现实的例子来说明。</p>
<code>Import javax.servlet. *;<br />
Import javax.servlet.http. *;<br />
Import java.io. *;<br />
Public class Concurrent Test extends HttpServlet {PrintWriter output;<br />
Public void service (HttpServletRequest request,<br />
HttpServletResponse response) throws ServletException, IOException {String username;<br />
Response.setContentType ("text/html; charset=gb2312");<br />
Username = request.getParameter ("username");<br />
Output = response.getWriter ();<br />
Try {Thread. sleep (5000); //为了突出并发问题，在这设置一个延时<br />
} Catch (Interrupted Exception e){}<br />
output.println("用户名:"+Username+"&lt;BR&gt;");<br />
}<br />
}</code>
<p>
该Servlet中定义了一个实例变量output，在service方法将其赋值为用户的输出。当一个用户访问该Servlet时，程序会正常的运
行，但当多个用户并发访问时，就可能会出现其它用户的信息显示在另外一些用户的浏览器上的问题。这是一个严重的问题。为了突出并发问题，便于测试、观察，
我们在回显用户信息时执行了一个延时的操作。假设已在web.xml配置文件中注册了该Servlet，现有两个用户a和b同时访问该Servlet（可
以启动两个IE浏览器，或者在两台机器上同时访问）,即同时在浏览器中输入：</p>
<p>　　a： http://localhost: 8080/servlet/ConcurrentTest? Username=a</p>
<p>　　b： http://localhost: 8080/servlet/ConcurrentTest? Username=b</p>
<p>　　如果用户b比用户a回车的时间稍慢一点，将得到如图2所示的输出：</p>
<p>　　<img src="http://www.feeten.cn/article/UploadPic/2009-1/200912181631627.jpg" onload="return imgresize(this);" onclick="javascript:window.open(this.src);" style="cursor: pointer;"  alt="" /></p>
<p>　　图2 a用户和b用户的浏览器输出</p>
<p>
从图2中可以看到，Web服务器启动了两个线程分别处理来自用户a和用户b的请求，但是在用户a的浏览器上却得到一个空白的屏幕，用户a的信息显示在用
户b的浏览器上。该Servlet存在线程不安全问题。下面我们就从分析该实例的内存模型入手,观察不同时刻实例变量output的值来分析使该
Servlet线程不安全的原因。</p>
<p>　　Java的内存模型JMM（Java Memory
Model）JMM主要是为了规定了线程和内存之间的一些关系。根据JMM的设计，系统存在一个主内存(Main
Memory)，Java中所有实例变量都储存在主存中，对于所有线程都是共享的。每条线程都有自己的工作内存(Working
Memory)，工作内存由缓存和堆栈两部分组成，缓存中保存的是主存中变量的拷贝，缓存可能并不总和主存同步，也就是缓存中变量的修改可能没有立刻写到
主存中；堆栈中保存的是线程的局部变量，线程之间无法相互直接访问堆栈中的变量。根据JMM，我们可以将论文中所讨论的Servlet实例的内存模型抽象
为图3所示的模型。</p>
<p>　　<img src="http://www.feeten.cn/article/UploadPic/2009-1/200912181631541.jpg" onload="return imgresize(this);" onclick="javascript:window.open(this.src);" style="cursor: pointer;"  alt="" /></p>
<p>　　图3 Servlet实例的JMM模型</p>
<p>　　下面根据图3所示的内存模型，来分析当用户a和b的线程（简称为a线程、b线程）并发执行时，Servlet实例中所涉及变量的变化情况及线程的执行情况，如图4所示。</p>
<table>
    <tbody>
        <tr>
            <td>调度时刻 </td>
            <td>a线程</td>
            <td>b线程</td>
        </tr>
        <tr>
            <td>T1</td>
            <td>访问Servlet页面</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>T2 </td>
            <td><br />
            </td>
            <td>访问Servlet页面</td>
        </tr>
        <tr>
            <td>T3 </td>
            <td>output=a的输出username=a休眠5000毫秒，让出CPU </td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>T4 </td>
            <td><br />
            </td>
            <td>output=b的输出（写回主存）username=b休眠5000毫秒，让出CPU</td>
        </tr>
        <tr>
            <td>T5 </td>
            <td>在用户b的浏览器上输出a线程的username的值,a线程终止。</td>
            <td>　</td>
        </tr>
        <tr>
            <td>T6</td>
            <td><br />
            </td>
            <td>在用户b的浏览器上输出b线程的username的值,b线程终止。</td>
        </tr>
    </tbody>
</table>
<p>　　图4 Servlet实例的线程调度情况</p>
<p>
从图4中可以清楚的看到，由于b线程对实例变量output的修改覆盖了a线程对实例变量output的修改，从而导致了用户a的信息显示在了用户b的
浏览器上。如果在a线程执行输出语句时，b线程对output的修改还没有刷新到主存，那么将不会出现图2所示的输出结果，因此这只是一种偶然现象，但这
更增加了程序潜在的危险性。</p>
<p>　　设计线程安全的Servlet</p>
<p>　　通过上面的分析，我们知道了实例变量不正确的使用是造成Servlet线程不安全的主要原因。下面针对该问题给出了三种解决方案并对方案的选取给出了一些参考性的建议。</p>
<p>　　1、实现 SingleThreadModel 接口</p>
<p>
该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不
会有两个线程被同时执行，当然也就不存在线程安全的问题。这种方法只要将前面的Concurrent Test类的类头定义更改为：</p>
<code>Public class Concurrent Test extends HttpServlet implements SingleThreadModel {<br />
&#8230;&#8230;&#8230;&#8230;<br />
}</code>
<p>　　2、同步对共享数据的操作</p>
<p>　　使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段，在本论文中的Servlet可以通过同步块操作来保证线程的安全。同步后的代码如下：</p>
<code>&#8230;&#8230;&#8230;&#8230;<br />
Public class Concurrent Test extends HttpServlet { &#8230;&#8230;&#8230;&#8230;<br />
Username = request.getParameter ("username");<br />
Synchronized (this){<br />
Output = response.getWriter ();<br />
Try {<br />
Thread. Sleep (5000);<br />
} Catch (Interrupted Exception e){}<br />
output.println("用户名:"+Username+"&lt;BR&gt;");<br />
}<br />
}<br />
}</code>
<p>　　3、避免使用实例变量</p>
<p>　　本实例中的线程安全问题是由实例变量造成的，只要在Servlet里面的任何方法里面都不使用实例变量，那么该Servlet就是线程安全的。</p>
<p>　　修正上面的Servlet代码，将实例变量改为局部变量实现同样的功能，代码如下：</p>
<code>&#8230;&#8230;<br />
Public class Concurrent Test extends HttpServlet {public void service (HttpServletRequest request, HttpServletResponse<br />
Response) throws ServletException, IOException {<br />
Print Writer output;<br />
String username;<br />
Response.setContentType ("text/html; charset=gb2312");<br />
&#8230;&#8230;<br />
}<br />
}</code>
<p>
对上面的三种方法进行测试，可以表明用它们都能设计出线程安全的Servlet程序。但是，如果一个Servlet实现了
SingleThreadModel接口，Servlet引擎将为每个新的请求创建一个单独的Servlet实例，这将引起大量的系统开销。
SingleThreadModel在Servlet2.4中已不再提倡使用；同样如果在程序中使用同步来保护要使用的共享的数据，也会使系统的性能大大
下降。这是因为被同步的代码块在同一时刻只能有一个线程执行它，使得其同时处理客户请求的吞吐量降低，而且很多客户处于阻塞状态。另外为保证主存内容和线
程的工作内存中的数据的一致性，要频繁地刷新缓存,这也会大大地影响系统的性能。所以在实际的开发中也应避免或最小化 Servlet
中的同步代码；在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。从Java
内存模型也可以知道，方法中的临时变量是在栈上分配空间，而且每个线程都有自己私有的栈空间，所以它们不会影响线程的安全。</p>
<p>　　小结</p>
<p>
Servlet的线程安全问题只有在大量的并发访问时才会显现出来，并且很难发现，因此在编写Servlet程序时要特别注意。线程安全问题主要是由实
例变量造成的,因此在Servlet中应避免使用实例变量。如果应用程序设计无法避免使用实例变量，那么使用同步来保护要使用的实例变量，但为保证系统的
最佳性能，应该同步可用性最小的代码路径。</p>
<p><br />
</p>
原文出处:http://www.feeten.cn/html/jsp/01/20090102181631103402.html<br />
作者:佚名
<img src ="http://www.blogjava.net/zhangchao/aggbug/279163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhangchao/" target="_blank">zhangchao</a> 2009-05-31 10:06 <a href="http://www.blogjava.net/zhangchao/archive/2009/05/31/279163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>session cookie详解.</title><link>http://www.blogjava.net/zhangchao/archive/2009/04/14/265643.html</link><dc:creator>zhangchao</dc:creator><author>zhangchao</author><pubDate>Tue, 14 Apr 2009 15:59:00 GMT</pubDate><guid>http://www.blogjava.net/zhangchao/archive/2009/04/14/265643.html</guid><wfw:comment>http://www.blogjava.net/zhangchao/comments/265643.html</wfw:comment><comments>http://www.blogjava.net/zhangchao/archive/2009/04/14/265643.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhangchao/comments/commentRss/265643.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhangchao/services/trackbacks/265643.html</trackback:ping><description><![CDATA[<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Word.Document" />
<meta name="Generator" content="Microsoft Word 11" />
<meta name="Originator" content="Microsoft Word 11" />
<link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml" /><o:smarttagtype namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="chmetcnv" downloadurl=""></o:smarttagtype><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:PunctuationKerning/>
<w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:SpaceForUL/>
<w:BalanceSingleByteDoubleByteWidth/>
<w:DoNotLeaveBackslashAlone/>
<w:ULTrailSpace/>
<w:DoNotExpandShiftReturn/>
<w:AdjustLineHeightInTable/>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:UseFELayout/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles deflockedstate="false" latentstylecount="156">
</w:LatentStyles>
</xml><![endif]--><!--[if !mso]><object classid="clsid:38481807-CA0E-42D2-BF39-B33AF135CC4D" id="ieooui"></object>
<style>
st1\:*{behavior:url(#ieooui) }
</style>
<![endif]--><style>
<!-- /* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"\@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
pre
{margin:0cm;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:宋体;
mso-bidi-font-family:宋体;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
</style>
<![endif]--><span style="font-size: 10.5pt;">通常所说的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">实际上可以分为</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">2</span><span style="font-size: 10.5pt;">种</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">一种是由</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">Cookie</span><span style="font-size: 10.5pt;">对象产生的保存在客户端硬盘上的持久化的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie,</span><span style="font-size: 10.5pt;">另一种就是由</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session</span><span style="font-size: 10.5pt;">对象产生的保存在浏览器内存里的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie.session cookie</span><span style="font-size: 10.5pt;">的组成是形如</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">: JSESSIONID=0EB8CEDE<st1:chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="30" unitname="a" w:st="on">030A</st1:chmetcnv>4B6FB5366317D8BF1978(tomcat</span><span style="font-size: 10.5pt;">下</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">).<o:p></o:p></span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">Session cookie</span><span style="font-size: 10.5pt;">何时产生</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">?</span><span style="font-size: 10.5pt;">当新创建一个</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session</span><span style="font-size: 10.5pt;">对象时产生</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie.</span><span style="font-size: 10.5pt;">当使用</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">request.getSession()</span><span style="font-size: 10.5pt;">或</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">request.getSession(true)</span><span style="font-size: 10.5pt;">方法时</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">如果请求范围内根据</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">jsessionid</span><span style="font-size: 10.5pt;">能够找到一个对应的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session</span><span style="font-size: 10.5pt;">对象</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">则不产生</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie</span><span style="font-size: 10.5pt;">也不返回给客户端保存</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">找不到则新创建一个</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie</span><span style="font-size: 10.5pt;">并生成一个形如</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">JSESSIONID=0EB8CEDE<st1:chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="30" unitname="a" w:st="on">030A</st1:chmetcnv>4B6FB5366317D8BF1978(tomcat</span><span style="font-size: 10.5pt;">下</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">)</span><span style="font-size: 10.5pt;">的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie</span><span style="font-size: 10.5pt;">并放在本次响应头信息中返回给客户端保存</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">客户端之前保存的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie</span><span style="font-size: 10.5pt;">也将被这个</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie</span><span style="font-size: 10.5pt;">所代替</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">.</span><span style="font-size: 10.5pt;">与</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie</span><span style="font-size: 10.5pt;">不同的是</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">如果服务器端明确使用</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">Cookie</span><span style="font-size: 10.5pt;">类来生成的持久化</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">将在每次响应中返回给客户端保存</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">不管客户端是否存在这个</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie.</span><span style="font-size: 10.5pt;">当浏览器接受</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">后</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">(</span><span style="font-size: 10.5pt;">不管是持久化</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">还是</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie),</span><span style="font-size: 10.5pt;">在对同一站点进行访问时</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">会自动把这些</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">信息放在请求头信息中一起发送给服务器端</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">.</span><span style="font-size: 10.5pt;">这样服务器端就能得到这些</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">来跟踪会话</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">.</span><span style="font-size: 10.5pt;">向服务器端发送</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">这个过程对用户来是完全透明的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">是浏览器自动进行的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">.<o:p></o:p></span>
<pre><span style="font-size: 10.5pt;">以上讨论是在浏览器接受</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">的情况下</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">下面谈谈浏览器禁用</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">的情况</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">.<o:p></o:p></span></pre>
<pre><span style="font-size: 10.5pt;">如果浏览器禁用了</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie,</span><span style="font-size: 10.5pt;">那么浏览器不会接收保存服务器端存在响应头中的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">信息</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">(ie6</span><span style="font-size: 10.5pt;">有</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">bug,</span><span style="font-size: 10.5pt;">会保存</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session cookie).</span><span style="font-size: 10.5pt;">浏览器再次访问同一站点时</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">请求头信息里也不会携带任何</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">信息的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">(</span><span style="font-size: 10.5pt;">因为浏览器根禁止了该功能</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">).</span><span style="font-size: 10.5pt;">正因如此</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">服务器端接收不到客户端的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt;">信息</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">也就无法识别客户端的身份</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">从而把它当作一个新的客户对待</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt;">也就会丢失以前的会话信息</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">.</span><span style="font-size: 10.5pt;">在这种情况下服务器端使用</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">request.getSession()</span><span style="font-size: 10.5pt;">或</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">request.getSession(true)</span><span style="font-size: 10.5pt;">方法时将会重新创建一个</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session.<o:p></o:p></span></pre>
<span style="font-size: 10.5pt; font-family: 宋体;">那么如何在用户禁用了</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt; font-family: 宋体;">的情况下维护会话呢</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">?</span><span style="font-size: 10.5pt; font-family: 宋体;">以上讨论我们已经知道</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt; font-family: 宋体;">服务器端判断是新的会话还是旧的会话是根据请求头中是否有一个</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">jsessionid</span><span style="font-size: 10.5pt; font-family: 宋体;">的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">.</span><span style="font-size: 10.5pt; font-family: 宋体;">由于浏览器禁用了</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">cookie</span><span style="font-size: 10.5pt; font-family: 宋体;">从而不会自动向服务器发送这个参数</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt; font-family: 宋体;">那么要维持会话就需要我们自己每次服务器发送请求时带上这个参数</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">.url</span><span style="font-size: 10.5pt; font-family: 宋体;">重写正是这样一种技术</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt; font-family: 宋体;">只要在我们的代码中把所有向服务器发送请求的地方用</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">response.encodeRedirectUrl(String
arg0)</span><span style="font-size: 10.5pt; font-family: 宋体;">包装一下</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">,</span><span style="font-size: 10.5pt; font-family: 宋体;">这样我们请求的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">url</span><span style="font-size: 10.5pt; font-family: 宋体;">就会自动加上当前</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">session</span><span style="font-size: 10.5pt; font-family: 宋体;">对象产生的</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">jsessionid.</span><span style="font-size: 10.5pt; font-family: 宋体;">服务器端也能取得这个值从而识别客户端</span><span style="font-size: 10.5pt; font-family: &quot;Courier New&quot;;" lang="EN-US">.</span>
<img src ="http://www.blogjava.net/zhangchao/aggbug/265643.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhangchao/" target="_blank">zhangchao</a> 2009-04-14 23:59 <a href="http://www.blogjava.net/zhangchao/archive/2009/04/14/265643.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>