??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV成人精品日韩一区,亚洲美日韩Av中文字幕无码久久久妻妇 ,亚洲国产精品乱码在线观看97http://m.tkk7.com/codefans/zh-cnTue, 13 May 2025 14:55:42 GMTTue, 13 May 2025 14:55:42 GMT6009q的一?/title><link>http://m.tkk7.com/codefans/archive/2009/02/04/253315.html</link><dc:creator>春雷的博?/dc:creator><author>春雷的博?/author><pubDate>Wed, 04 Feb 2009 13:07:00 GMT</pubDate><guid>http://m.tkk7.com/codefans/archive/2009/02/04/253315.html</guid><wfw:comment>http://m.tkk7.com/codefans/comments/253315.html</wfw:comment><comments>http://m.tkk7.com/codefans/archive/2009/02/04/253315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/codefans/comments/commentRss/253315.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/codefans/services/trackbacks/253315.html</trackback:ping><description><![CDATA[  一q又q去了,习惯上我q是使用阴历来判别一q_元旦q后Q我q没有想Cq又q去了,但是q完春节Q这U感觉就H然特别强烈hQ呵呵,时候养成的习惯Q不是说变就能改变的?br />    在一月䆾怎么说呢Q上半个月感觉特别篏Qh也特别敏感,易怒。下半个月,q是相对比较L的心态,q是犒劌己吧。第一二周主要是准备工作汇报材料,一h没日没夜地干Q就Z把工作汇报整Q?q额外新增了许多功能Q光说短信吧Q?短短3天,集成进了系l,q个不容易啊Q每个h都铆了Ԍx点色彩出来,当然我其实也知道Q我说过12月会L一点,但是12月䆾没有Lq,然后我又?月䆾会轻松一点,接着是更篏得一月䆾Q自׃感觉惭愧啊,目本来工作量太多是一斚wQ但是更多的Q我q是认ؓQ管理上面还是存在很大问题,没有预见C个重大问题,W一Q框架的严重不Q第二,人员培训严重不Q当时对框架依赖E度q高Q?其实框架在后面几ơ致命的变动Q给pȝ带来的修改工作量非同一般啊Q对人员的水q估计过高,也是把所有h包括自己弄得很惨的一个重要原因,以ؓl过前面的一个小目Qh员水q_该都有很大的提高Q满一般的目需求问题不是很大的Q但是实际情况告诉我Q从一个不懂编E到熟练工, l对不是一y而就的,q是劳动强度很大的ȝQ那也需要很长时间的Q至也需要一Cq。我们只用了2个月Q就是学了九阳功也没有那么快啊。当然所有的一切责dlv来,是目理的失败,风险识别错误Q一开始的风险识别只是考虑旉紧,业务不熟l,Ҏ没有考虑Ch员的技术水qI所以后面对质量的忽视的默许Q对人员培养的中断, 直接D了最后的一个大泥潭Q当然我们现在是甲方Q这个蟩蚤还是得自己摘掉的,因ؓ你不是干一就Ch的阿?br />   在汇报后Q就开始进行年lȝQ?呵呵Q因为有很多感想Q计划的三千字,L的就辑ֈQ写得时候根本就没有考虑q达C?br /> <br /> 针对需要改q的内容也写了很多,有几点特别重要,W一Q千万不要深度参与到目的开发中去,因ؓq样你害了所有hQ没有统{安排,必然D更多的问题和混ؕQ而且q些内容q早要交接出ȝQ那么,别h接手q是很痛苦,所以从一开始就要把握好自己。第二,计划很重要,计划要仔l考虑Q不是一拍脑袋,计划出来,完成了很多电子表|但是q没有用Q有用的计划应该是讨论出来的Q是仔细思考,全盘考虑的结果。最后,计划始终只是计划Q还需要不断跟q,q样才能逐步D目标?br /> <br /> 下月q有一些计划,主要一个是制定目理规范Q很多时候做到有章可循还是比较好的,最佛_践不一定完全适合你,但是你总能受点启发吧。日U月累,不就形成了一个所以得l验了吗Q打游戏q讲I经验值呢Q做事ؓ什么就要拒l经验呢?br /> W二个,q要把现在的内容消化Q现在内容很多,但老实_需要花力气整合Q而且q有些核心功能都不是特别E_Q也急切需要稳定。现在一堆所谓的重构Q?但是我一直知道有一句话Q没有最好,只有最合适。其实对于Y件也是这P优化是没有止境的Q但是我们也要有一个度Q再q三个月Q回q头来看Q现在的很多功能和代码又会有点像狗屎Q因Zq步了。是不是我们再花力气把它们都重构一下呢Q不一定。首先用户对于你的修Ҏ否认Z定需要,用的q蛮好的Q也ȝl我一个更换的理由吧, M能说厂家都从n70换到n73Q?我就要换吧。其ơ,你的旉和精力允怽q样做吗Q但是ƈ不是代表我们׃么都不做Q一直拒l新事物Q这h么能从量变到质变呢Q不质变Q不适应新情况了L要被淘汰的吧Q比如小灵通?<br /> <br /> 所以我x们每个h都要习惯改变Q但是要抓住本质Q有一句话“要么改变Q要么被改变”?br /> <br /> <img src ="http://m.tkk7.com/codefans/aggbug/253315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/codefans/" target="_blank">春雷的博?/a> 2009-02-04 21:07 <a href="http://m.tkk7.com/codefans/archive/2009/02/04/253315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>防止~存http://m.tkk7.com/codefans/archive/2006/01/12/27724.html春雷的博?/dc:creator>春雷的博?/author>Thu, 12 Jan 2006 04:40:00 GMThttp://m.tkk7.com/codefans/archive/2006/01/12/27724.htmlhttp://m.tkk7.com/codefans/comments/27724.htmlhttp://m.tkk7.com/codefans/archive/2006/01/12/27724.html#Feedback0http://m.tkk7.com/codefans/comments/commentRss/27724.htmlhttp://m.tkk7.com/codefans/services/trackbacks/27724.html 1, 使用java提供的方法,在jsp或者servlet中都可以
<%
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
%>
2, 使用HTML标记Q如下面Q?
<HEAD>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="0">
</HEAD>  


]]>
int、char、double与byte怺转换的程?/title><link>http://m.tkk7.com/codefans/archive/2005/11/25/21411.html</link><dc:creator>春雷的博?/dc:creator><author>春雷的博?/author><pubDate>Fri, 25 Nov 2005 04:42:00 GMT</pubDate><guid>http://m.tkk7.com/codefans/archive/2005/11/25/21411.html</guid><wfw:comment>http://m.tkk7.com/codefans/comments/21411.html</wfw:comment><comments>http://m.tkk7.com/codefans/archive/2005/11/25/21411.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/codefans/comments/commentRss/21411.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/codefans/services/trackbacks/21411.html</trackback:ping><description><![CDATA[转蝲  <A >http://www.matrix.org.cn/thread.shtml?forum_id=19&view_id=919</A><BR>int、char、double与byte怺转换的程?BR>//整数到字节数l的转换<BR>  public static byte[] intToByte(int number) {<BR>    int temp = number;<BR>    byte[] b=new byte[4];<BR>    for (int i=b.length-1;i>-1;i--){<BR>      b[i] = new Integer(temp&0xff).byteValue();      //最高位保存在最低位<BR>      temp = temp >> 8;       //向右U??BR>    }<BR>    return b;<BR>  }<BR><BR>  //字节数组到整数的转换<BR>  public static int byteToInt(byte[] b) {<BR>    int s = 0;<BR>    for (int i = 0; i < 3; i++) {<BR>      if (b[i] >= 0)<BR>        s = s + b[i];<BR>      else<BR><BR><BR>        s = s + 256 + b[i];<BR>      s = s * 256;<BR>    }<BR>    if (b[3] >= 0)       //最后一个之所以不乘,是因为可能会溢出<BR>      s = s + b[3];<BR>    else<BR>      s = s + 256 + b[3];<BR>    return s;<BR>  }<BR><BR>  //字符到字节{?BR>  public static byte[] charToByte(char ch){<BR>    int temp=(int)ch;<BR>    byte[] b=new byte[2];<BR>    for (int i=b.length-1;i>-1;i--){<BR>      b[i] = new Integer(temp&0xff).byteValue();      //最高位保存在最低位<BR>      temp = temp >> 8;       //向右U??BR>    }<BR>    return b;<BR>  }<BR><BR>  //字节到字W{?BR><BR><BR>  public static char byteToChar(byte[] b){<BR>    int s=0;<BR>    if(b[0]>0)<BR>      s+=b[0];<BR>    else<BR>      s+=256+b[0];<BR>    s*=256;<BR>    if(b[1]>0)<BR>      s+=b[1];<BR>    else<BR>      s+=256+b[1];<BR>    char ch=(char)s;<BR>    return ch;<BR>  }<BR><BR>  //点到字节{?BR>  public static byte[] doubleToByte(double d){<BR>    byte[] b=new byte[8];<BR>    long l=Double.doubleToLongBits(d);<BR>    for(int i=0;i<b.length;i++){<BR>      b[i]=new Long(l).byteValue();<BR>      l=l>>8;<BR><BR><BR>    }<BR>    return b;<BR>  }<BR><BR>  //字节到Q点{?BR>  public static double byteToDouble(byte[] b){<BR>    long l;<BR><BR>    l=b[0];<BR>    l&=0xff;<BR>    l|=((long)b[1]<<8);<BR>    l&=0xffff;<BR>    l|=((long)b[2]<<16);<BR>    l&=0xffffff;<BR>    l|=((long)b[3]<<24);<BR>    l&=0xffffffffl;<BR>    l|=((long)b[4]<<32);<BR>    l&=0xffffffffffl;<BR><BR>    l|=((long)b[5]<<40);<BR>    l&=0xffffffffffffl;<BR>    l|=((long)b[6]<<48);<BR><BR><BR>    l|=((long)b[7]<<56);<BR>    return Double.longBitsToDouble(l);<BR>  }<BR><BR>--<BR><img src ="http://m.tkk7.com/codefans/aggbug/21411.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/codefans/" target="_blank">春雷的博?/a> 2005-11-25 12:42 <a href="http://m.tkk7.com/codefans/archive/2005/11/25/21411.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 多线E入门大?/title><link>http://m.tkk7.com/codefans/archive/2005/11/23/21165.html</link><dc:creator>春雷的博?/dc:creator><author>春雷的博?/author><pubDate>Wed, 23 Nov 2005 10:27:00 GMT</pubDate><guid>http://m.tkk7.com/codefans/archive/2005/11/23/21165.html</guid><wfw:comment>http://m.tkk7.com/codefans/comments/21165.html</wfw:comment><comments>http://m.tkk7.com/codefans/archive/2005/11/23/21165.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/codefans/comments/commentRss/21165.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/codefans/services/trackbacks/21165.html</trackback:ping><description><![CDATA[  <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD>先从U程的创?U程的创Z共有两种形式:<BR><BR>--------------------------------------------------------------------------------<BR><BR>    一U是l承自Threadc?Thread cL一个具体的c?即不是抽象类,该类装了线E的行ؓ.要创Z个线E?E序员必dZ个从 Thread cd出的新类.E序员通过覆盖 Thread ?run() 函数来完成有用的工作.用户q不直接调用此函?而是通过调用 Thread ?start() 函数,该函数再调用 run().<BR>    <BR>    例如: <BR><BR>    public class Test extends Thread{<BR>      public Test(){<BR>      }<BR>      public static void main(String args[]){<BR>        Test t1 = new Test();<BR>        Test t2 = new Test();<BR>        t1.start();<BR>        t2.start();<BR>      }<BR>      public void run(){<BR>        //do thread's things<BR>      }<BR>    }<BR><BR>--------------------------------------------------------------------------------<BR><BR>    <BR>    另一U是实现Runnable接口,此接口只有一个函?run(),此函数必ȝ实现了此接口的类实现.<BR>    <BR>    例如: <BR><BR>    public class Test implements Runnable{<BR>      Thread thread1;<BR>      Thread thread2;<BR>      public Test(){<BR>        thread1 = new Thread(this,"1");<BR>        thread2 = new Thread(this,"2");<BR>      }<BR>      public static void main(String args[]){<BR>        Test t = new Test();<BR>        t.startThreads();<BR>      }<BR>      public void run(){<BR>        //do thread's things<BR>      }<BR>      public void startThreads(){<BR>        thread1.start();<BR>        thread2.start();<BR>      }<BR>    }<BR><BR>    两种创徏方式看v来差别不?但是弄不清楚的话,也许会将你的E序弄得一团糟.两者区别有以下几点:<BR><BR>1.当你想承某一其它cL,你只能用后一U方?<BR><BR>2.W一U因为承自Thread,只创Z自n对象,但是在数量上,需要几个线E?得创徏几个自n对象;W二U只创徏一个自w对?却创建几个Thread对象.而两U方法重大的区别在于此,请你考虑:如果你在W一U里创徏C自n对象q且start()?你会发现好像synchronized不v作用?已经加锁的代码块或者方法居然同时可以有几个U程q去,而且同样一个变?居然可以有好几个U程同时可以L改它.(例如下面的代?q是因ؓ,在这个程序中,虽然你v了数个线E?可是你也创徏了数个对?而且,每个U程对应了每个对象也是?每个U程更改和占有的对象都不一?所以就出现了同时有几个U程q入一个方法的现象,其实,那也不是一个方?而是不同对象的相同的Ҏ.所?q时候你要加锁的?只能方法或者变量声明ؓ静?static加上?你就会发?U程又能住Ҏ?同时不可能有两个U程q入同样一个方?那是因ؓ,现在不是每个对象都拥有一个方法了,而是所有的对象共同拥有一个方?q个Ҏ是静态方?<BR><BR>    而你如果用第二种Ҏ使用U程的话,׃会有上述的情?因ؓ此时,你只创徏了一个自w对?所?自n对象的属性和Ҏ对于U程来说是共有的.<BR><BR>    因此,我徏?最好用后一U方法来使用U程.<BR><BR>public class mainThread extends Thread{<BR>  int i=0;<BR>  public static void main(String args[]){<BR>    mainThread m1 = new mainThread();<BR>    mainThread m2 = new mainThread();<BR>    mainThread m3 = new mainThread();<BR>    mainThread m4 = new mainThread();<BR>    mainThread m5 = new mainThread();<BR>    mainThread m6 = new mainThread();<BR>    m1.start();<BR>    m2.start();<BR>    m3.start();<BR>    m4.start();<BR>    m5.start();<BR>    m6.start();<BR>  }<BR>  public synchronized void t1(){<BR>    i=++i;<BR>    try{<BR></TD></TR></TBODY></TABLE> <P>Thread.sleep(500);<BR>    }<BR>    catch(Exception e){}<BR>    //每个U程都进入各自的t1()Ҏ,分别打印各自的i<BR>    System.out.println(Thread.currentThread().getName()+" "+i);<BR>  }<BR>  public void run(){<BR>    synchronized(this){<BR>      while (true) {<BR>        t1();<BR>      }<BR>    }<BR>  }<BR>}<BR><BR>--------------------------------------------------------------------------------<BR><BR>    下面我们来讲synchronized?U用法吧:<BR><BR>    1.Ҏ声明时?攑֜范围操作W?public{?之后,q回cd声明(void{?之前.即一ơ只能有一个线E进入该Ҏ,其他U程要想在此时调用该Ҏ,只能排队{?当前U程(是在synchronizedҎ内部的线E?执行完该Ҏ?别的U程才能q入.<BR><BR>      例如:<BR><BR>      public synchronized void synMethod() {<BR>        //Ҏ?BR>      }<BR><BR>    2.Ҏ一代码块?synchronized后跟括号,括号里是变量,q样,一ơ只有一个线E进入该代码?例如:<BR><BR>      public int synMethod(int a1){<BR>        synchronized(a1) {<BR>          //一ơ只能有一个线E进?BR>        }<BR>      }<BR>    3.synchronized后面括号里是一对象,此时,U程获得的是对象?例如:<BR><BR>public class MyThread implements Runnable {<BR>  public static void main(String args[]) {<BR>    MyThread mt = new MyThread();<BR>    Thread t1 = new Thread(mt, "t1");<BR>    Thread t2 = new Thread(mt, "t2");<BR>    Thread t3 = new Thread(mt, "t3");<BR>    Thread t4 = new Thread(mt, "t4");<BR>    Thread t5 = new Thread(mt, "t5");<BR>    Thread t6 = new Thread(mt, "t6");<BR>    t1.start();<BR>    t2.start();<BR>    t3.start();<BR>    t4.start();<BR>    t5.start();<BR>    t6.start();<BR>  }<BR><BR>  public void run() {<BR>    synchronized (this) {<BR>      System.out.println(Thread.currentThread().getName());<BR>    }<BR>  }<BR>} <BR><BR><BR>    对于3,如果U程q入,则得到对象锁,那么别的U程在该cL有对象上的Q何操作都不能q行.在对象使用锁通常是一U比较粗p的Ҏ.Z么要整个对象都上锁,而不允许其他U程短暂C用对象中其他同步Ҏ来访问共享资?如果一个对象拥有多个资?׃需要只Z让一个线E用其中一部分资源,将所有线E都锁在外面.׃每个对象都有?可以如下所CZ用虚拟对象来上锁:<BR><BR>class FineGrainLock {<BR><BR>   MyMemberClass x, y;<BR>   Object xlock = new Object(), ylock = new Object();<BR><BR>   public void foo() {<BR>      synchronized(xlock) {<BR>         //access x here<BR>      }<BR><BR>      //do something here - but don't use shared resources<BR><BR>      synchronized(ylock) {<BR>         //access y here<BR>      }<BR>   }<BR><BR>   public void bar() {<BR>      synchronized(this) {<BR>         //access both x and y here<BR>      }<BR>      //do something here - but don't use shared resources<BR>   }<BR>}<BR><BR><BR><BR>    4.synchronized后面括号里是c?例如:<BR><BR>class ArrayWithLockOrder{<BR>  private static long num_locks = 0;<BR>  private long lock_order;<BR>  private int[] arr;<BR><BR>  public ArrayWithLockOrder(int[] a)<BR>  {<BR>    arr = a;<BR>    synchronized(ArrayWithLockOrder.class) {//-----------------------------------------q里<BR>      num_locks++;             // 锁数?1.<BR>      lock_order = num_locks;  // 为此对象实例讄唯一?lock_order.<BR>    }<BR>  }<BR>  public long lockOrder()<BR>  {<BR>    return lock_order;<BR>  }<BR>  public int[] array()<BR>  {<BR>    return arr;<BR>  }<BR>}<BR><BR>class SomeClass implements Runnable<BR></P> <P>{<BR>  public int sumArrays(ArrayWithLockOrder a1,<BR>                       ArrayWithLockOrder a2)<BR>  {<BR>    int value = 0;<BR>    ArrayWithLockOrder first = a1;       // 保留数组引用的一?BR>    ArrayWithLockOrder last = a2;        // 本地副本.<BR>    int size = a1.array().length;<BR>    if (size == a2.array().length)<BR>    {<BR>      if (a1.lockOrder() > a2.lockOrder())  // 定q设|对象的锁定<BR>      {                                     // 序.<BR>        first = a2;<BR>        last = a1;<BR>      }<BR>      synchronized(first) {              // 按正的序锁定对象.<BR>        synchronized(last) {<BR>          int[] arr1 = a1.array();<BR>          int[] arr2 = a2.array();<BR>          for (int i=0; i<size; i++)<BR>            value += arr1[i] + arr2[i];<BR>        }<BR>      }<BR>    }<BR>    return value;<BR>  }<BR>  public void run() {<BR>    //...<BR>  }<BR>}<BR><BR><BR><BR>    对于4,如果U程q入,则线E在该类中所有操作不能进?包括静态变量和静态方?实际?对于含有静态方法和静态变量的代码块的同步,我们通常?来加?<BR><BR>以上4U之间的关系:<BR><BR>    锁是和对象相兌?每个对象有一把锁,Z执行synchronized语句,U程必须能够获得synchronized语句中表辑ּ指定的对象的?一个对象只有一把锁,被一个线E获得之后它׃再拥有这把锁,U程在执行完synchronized语句?获得锁交还l对?<BR>    在方法前面加上synchronized修饰W即可以一个方法声明ؓ同步化方?同步化方法在执行之前获得一个锁.如果q是一个类Ҏ,那么获得的锁是和声明Ҏ的类相关的Classcd象的?如果q是一个实例方?那么此锁是this对象的锁.<BR><BR>--------------------------------------------------------------------------------<BR><BR>  下面谈一谈一些常用的Ҏ:<BR><BR>  wait(),wait(long),notify(),notifyAll(){方法是当前cȝ实例Ҏ,<BR>    <BR>        wait()是持有对象锁的U程释放?<BR>        wait(long)是持有对象锁的U程释放锁时间ؓlong(毫秒)?再次获得?wait()和wait(0){h;<BR>        notify()是唤醒一个正在等待该对象锁的U程,如果{待的线E不止一?那么被唤醒的U程由jvm定;<BR>        notifyAll是唤醒所有正在等待该对象锁的U程.<BR>        在这里我也重申一?我们应该优先使用notifyAll()Ҏ,因ؓ唤醒所有线E比唤醒一个线E更Ҏ让jvm扑ֈ最适合被唤醒的U程.<BR><BR>    对于上述Ҏ,只有在当前线E中才能使用,否则报运行时错误java.lang.IllegalMonitorStateException: current thread not owner.<BR><BR>--------------------------------------------------------------------------------<BR><BR>    下面,我谈一下synchronized和wait(),notify(){的关系:<BR><BR>1.有synchronized的地方不一定有wait,notify<BR><BR>2.有wait,notify的地方必有synchronized.q是因ؓwait和notify不是属于U程c?而是每一个对象都h的方?而且,q两个方法都和对象锁有关,有锁的地?必有synchronized.<BR><BR>另外,h意一?如果要把notify和waitҎ攑֜一L的话,必须先调用notify后调用wait,因ؓ如果调用完wait,该线E就已经不是current thread?如下?<BR><BR>/**<BR>* Title:        Jdeveloper's Java Projdect<BR>* Description:  n/a<BR>* Copyright:    Copyright © 2001<BR>* Company:      soho  <A target=_blank><FONT color=#000000>http://www.ChinaJavaWorld.com</FONT></A><BR>* @author jdeveloper@21cn.com<BR>* @version 1.0<BR>*/<BR>import java.lang.Runnable;<BR>import java.lang.Thread;<BR><BR>public class DemoThread<BR>    implements Runnable {<BR><BR>  public DemoThread() {<BR>    TestThread testthread1 = new TestThread(this, "1");<BR></P> <P>TestThread testthread2 = new TestThread(this, "2");<BR><BR>    testthread2.start();<BR>    testthread1.start();<BR><BR>  }<BR><BR>  public static void main(String[] args) {<BR>    DemoThread demoThread1 = new DemoThread();<BR><BR>  }<BR><BR>  public void run() {<BR><BR>    TestThread t = (TestThread) Thread.currentThread();<BR>    try {<BR>      if (!t.getName().equalsIgnoreCase("1")) {<BR>        synchronized (this) {<BR>          wait();<BR>        }<BR>      }<BR>      while (true) {<BR><BR>        System.out.println("@time in thread" + t.getName() + "=" +<BR>                           t.increaseTime());<BR><BR>        if (t.getTime() % 10 == 0) {<BR>          synchronized (this) {<BR>            System.out.println("****************************************");<BR>            notify();<BR>            if (t.getTime() == 100)<BR>              break;<BR>            wait();<BR>          }<BR>        }<BR>      }<BR>    }<BR>    catch (Exception e) {<BR>      e.printStackTrace();<BR>    }<BR>  }<BR><BR>}<BR><BR>class TestThread<BR>    extends Thread {<BR>  private int time = 0;<BR>  public TestThread(Runnable r, String name) {<BR>    super(r, name);<BR>  }<BR><BR>  public int getTime() {<BR>    return time;<BR>  }<BR><BR>  public int increaseTime() {<BR>    return++time;<BR>  }<BR><BR>}<BR><BR>    下面我们用生产?消费者这个例子来说明他们之间的关p?<BR><BR>    public class test {<BR>  public static void main(String args[]) {<BR>    Semaphore s = new Semaphore(1);<BR>    Thread t1 = new Thread(s, "producer1");<BR>    Thread t2 = new Thread(s, "producer2");<BR>    Thread t3 = new Thread(s, "producer3");<BR>    Thread t4 = new Thread(s, "consumer1");<BR>    Thread t5 = new Thread(s, "consumer2");<BR>    Thread t6 = new Thread(s, "consumer3");<BR>    t1.start();<BR>    t2.start();<BR>    t3.start();<BR>    t4.start();<BR>    t5.start();<BR>    t6.start();<BR>  }<BR>}<BR><BR>class Semaphore<BR>    implements Runnable {<BR>  private int count;<BR>  public Semaphore(int n) {<BR>    this.count = n;<BR>  }<BR><BR>  public synchronized void acquire() {<BR>    while (count == 0) {<BR>      try {<BR>        wait();<BR>      }<BR>      catch (InterruptedException e) {<BR>        //keep trying<BR>      }<BR>    }<BR>    count--;<BR>  }<BR><BR>  public synchronized void release() {<BR>    while (count == 10) {<BR>      try {<BR>        wait();<BR>      }<BR>      catch (InterruptedException e) {<BR>        //keep trying<BR>      }<BR>    }<BR>    count++;<BR>    notifyAll(); //alert a thread that's blocking on this semaphore<BR>  }<BR><BR>  public void run() {<BR>    while (true) {<BR>      if (Thread.currentThread().getName().substring(0,8).equalsIgnoreCase("consumer")) {<BR>        acquire();<BR>      }<BR>      else if (Thread.currentThread().getName().substring(0,8).equalsIgnoreCase("producer")) {<BR>        release();<BR>      }<BR>      System.out.println(Thread.currentThread().getName() + " " + count);<BR>    }<BR>  }<BR>}<BR><BR>       生者生?消费者消?一般没有冲H?但当库存??消费者要消费是不行的,但当库存Z?q里?0)?生者也不能生.请好好研M面的E序,你一定会比以前进步很?<BR><BR>      上面的代码说明了synchronized和wait,notify没有l对的关p?在synchronized声明的方?代码块中,你完全可以不用wait,notify{方?但是,如果当线E对某一资源存在某种争用的情况下,你必适时得将U程攑օ{待或者唤?</P> <P> </P> <P> </P> <P>Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-</P> <P>在java中,每个对象只有一个相应的monitorQ一个mutexQ而每一个monitor都可以有多个“doors”可以进入,卻I同一个monitor中被守护的代码可以在不同的地方,因ؓ同一个对象可以出现在不同的代码段Q只要mutex锁定的对象是同一个,每个入口都用Synchronized关键字表明,当一个线E通过了Synchronized关键字,它就所住了该monitor所有的doors。因此是mutex定义了monitor而不是代码?</P> <P>另外Qwait和notify、notifyAll都是Object的方法,使用wait必须是The current thread must own this object's monitor<BR>wait<BR>public final void wait()<BR>                throws InterruptedExceptionCauses current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0). <BR>The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution. </P> <P>This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor. </P> <P><BR>Throws: <BR>IllegalMonitorStateException - if the current thread is not the owner of the object's monitor. <BR>InterruptedException - if another thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.<BR>See Also:<BR>notify(), notifyAll()</P> <P>A thread becomes the owner of the object's monitor in one of three ways: </P> <P>By executing a synchronized instance method of that object. <BR>By executing the body of a synchronized statement that synchronizes on the object. <BR>For objects of type Class, by executing a synchronized static method of that class. <BR>Only one thread at a time can own an object's monitor. <BR></P> <P>   </P><img src ="http://m.tkk7.com/codefans/aggbug/21165.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/codefans/" target="_blank">春雷的博?/a> 2005-11-23 18:27 <a href="http://m.tkk7.com/codefans/archive/2005/11/23/21165.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2005.11.14http://m.tkk7.com/codefans/archive/2005/11/15/19924.html春雷的博?/dc:creator>春雷的博?/author>Tue, 15 Nov 2005 08:54:00 GMThttp://m.tkk7.com/codefans/archive/2005/11/15/19924.htmlhttp://m.tkk7.com/codefans/comments/19924.htmlhttp://m.tkk7.com/codefans/archive/2005/11/15/19924.html#Feedback0http://m.tkk7.com/codefans/comments/commentRss/19924.htmlhttp://m.tkk7.com/codefans/services/trackbacks/19924.html

]]>
最q找C个很不错介绍session的文?http://m.tkk7.com/codefans/archive/2005/09/06/12255.html春雷的博?/dc:creator>春雷的博?/author>Tue, 06 Sep 2005 13:37:00 GMThttp://m.tkk7.com/codefans/archive/2005/09/06/12255.htmlhttp://m.tkk7.com/codefans/comments/12255.htmlhttp://m.tkk7.com/codefans/archive/2005/09/06/12255.html#Feedback0http://m.tkk7.com/codefans/comments/commentRss/12255.htmlhttp://m.tkk7.com/codefans/services/trackbacks/12255.html

 

关键?Session
 标题QSession详解 
--------------------------------------------------------------------------------
[评论]

作者:郎云鹏(dev2dev ID: hippiewolfQ?BR>
摘要Q虽然session机制在web应用E序中被采用已经很长旉了,但是仍然有很多h不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论session的工作机制ƈ且对在Java web application中应用session机制时常见的问题作出解答?BR>
目录Q?BR>一、术语session
二、HTTP协议与状态保?BR>三、理解cookie机制
四、理解session机制
五、理解javax.servlet.http.HttpSession
六、HttpSession常见问题
七、跨应用E序的session׃n
八、ȝ
参考文?BR>
一、术语session
在我的经验里Qsessionq个词被滥用的程度大概仅ơ于transactionQ更加有的是transaction与session在某些语境下的含义是相同的?BR>
sessionQ中文经常翻译ؓ会话Q其本来的含义是指有始有l的一pd动作/消息Q比如打电话时从拿v电话拨号到挂断电话这中间的一pdq程可以UCZ?session。有时候我们可以看到这L话“在一个浏览器会话期间Q?..”,q里的会话一词用的就是其本义Q是指从一个浏览器H口打开到关闭这个期?①。最混ؕ的是“用P客户端)在一ơ会话期间”这样一句话Q它可能指用L一pd动作Q一般情况下是同某个具体目的相关的一pd动作Q比如从d到选购商品到结账登样一个网上购物的q程Q有时候也被称Z个transactionQ,然而有时候也可能仅仅是指一ơ连接,也有可能是指含义①,其中的差别只能靠上下文来推断②?BR>
然而当session一词与|络协议相关联时Q它又往往隐含了“面向连接”和/或“保持状态”这样两个含义, “面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电话,直到Ҏ接了电话通信才能开始,与此相对的是写信Q在你把信发出去的时候你q不能确认对方的地址是否正确Q通信渠道不一定能建立Q但对发信h来说Q通信已经开始了。“保持状态”则是指通信的一方能够把一pd的消息关联v来,使得消息之间可以互相依赖Q比如一个服务员能够认出再次光的老顾客ƈ且记得上ơ这个顾客还Ơ店里一块钱。这一cȝ例子有“一个TCP session”或?“一个POP3 session”③?BR>
而到了web服务器蓬勃发展的时代Qsession在web开发语境下的语义又有了新的扩展Q它的含义是指一cȝ来在客户端与服务器之间保持状态的解决Ҏ④。有时候session也用来指q种解决Ҏ的存储结构,如“把xxx保存在session 里”⑤。由于各U用于web开发的语言在一定程度上都提供了对这U解x案的支持Q所以在某种特定语言的语境下Qsession也被用来指代该语a的解x案,比如l常把Java里提供的javax.servlet.http.HttpSessionUCؓsession⑥?BR>
鉴于q种混ؕ已不可改变,本文中session一词的q用也会Ҏ上下文有不同的含义,请大家注意分辨?BR>在本文中Q用中文“浏览器会话期间”来表达含义①,使用“session机制”来表达含义④,使用“session”表辑֐义⑤Q用具体的“HttpSession”来表达含义?BR>
二、HTTP协议与状态保?BR>HTTP 协议本n是无状态的Q这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器h下蝲某些文gQ无论是客户端还是服务器都没有必要纪录彼此过ȝ行ؓQ每一ơ请求之间都是独立的Q好比一个顾客和一个自动售货机或者一个普通的Q非会员Ӟ大卖Z间的关系一栗?BR>
然而聪明(或者贪心?Q的Z很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用Q就像给有线电视加上Ҏ功能一栗这U需求一斚wqHTML逐步d了表单、脚本、DOM{客L行ؓQ另一斚w在服务器端则出现了CGI规范以响应客L的动态请求,作ؓ传输载体的HTTP协议也添加了文g上蝲?cookieq些Ҏ。其中cookie的作用就是ؓ了解决HTTP协议无状态的~陷所作出的努力。至于后来出现的session机制则是又一U在客户端与服务器之间保持状态的解决Ҏ?BR>
让我们用几个例子来描qC下cookie和session机制之间的区别与联系。笔者曾l常ȝ一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠Q然而一ơ性消?杯咖啡的Z微乎其微Q这时就需要某U方式来U录某位֮的消Ҏ量。想象一下其实也无外乎下面的几种ҎQ?BR>1、该店的店员很厉宻I能记住每位顾客的消费数量Q只要顾客一走进咖啡店,店员q道该怎么对待了。这U做法就是协议本w支持状态?BR>2、发l顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每ơ消ҎQ如果顾客出C张卡片,则此ơ消费就会与以前或以后的消费相联pv来。这U做法就是在客户端保持状态?BR>3、发l顾客一张会员卡Q除了卡号之外什么信息也不纪录,每次消费Ӟ如果֮出示该卡片,则店员在店里的纪录本上找到这个卡号对应的U录d一些消费信息。这U做法就是在服务器端保持状态?BR>
׃HTTP协议是无状态的Q而出于种U考虑也不希望使之成ؓ有状态的Q因此,后面两种Ҏ成为现实的选择。具体来说cookie机制采用的是在客L保持状态的ҎQ而session机制采用的是在服务器端保持状态的Ҏ。同时我们也看到Q由于采用服务器端保持状态的Ҏ在客L也需要保存一个标识,所以session机制可能需要借助于cookie机制来达C存标识的目的Q但实际上它q有其他选择?BR>
三、理解cookie机制 
cookie机制的基本原理就如上面的例子一L单,但是q有几个问题需要解冻I“会员卡”如何分发;“会员卡”的内容Q以及客户如何用“会员卡”?BR>
正统的cookie分发是通过扩展HTTP协议来实现的Q服务器通过在HTTP的响应头中加上一行特D的指示以提C浏览器按照指示生成相应的cookie。然而纯_的客户端脚本如JavaScript或者VBScript也可以生成cookie?BR>
而cookie 的用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器查所有存储的cookieQ如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置Q则把该cookie附在h资源的HTTPh头上发送给服务器。意思是麦当劳的会员卡只能在麦当劳的店里出示Q如果某家分店还发行了自q会员卡,那么q这家店的时候除了要出示麦当劳的会员卡,q要出示q家店的会员卡?BR>
cookie的内容主要包括:名字Q|q期旉Q\径和域?BR>其中域可以指定某一个域比如.google.comQ相当于d招牌Q比如宝z公司,也可以指定一个域下的具体某台机器比如www.google.com或者froogle.google.comQ可以用飘柔来做比?BR>路径是跟在域名后面的URL路径Q比?或?foo{等Q可以用某飘柔专柜做比?BR>路径与域合在一起就构成了cookie的作用范围?BR>如果不设|过期时_则表C个cookie的生命期为浏览器会话期间Q只要关闭浏览器H口Qcookie消׃。这U生命期为浏览器会话期的 cookie被称Z话cookie。会话cookie一般不存储在硬盘上而是保存在内存里Q当然这U行为ƈ不是规范规定的。如果设|了q期旉Q浏览器׃把cookie保存到硬盘上Q关闭后再次打开览器,q些cookie仍然有效直到过讑֮的过期时间?BR>
存储在硬盘上的cookie 可以在不同的览器进E间׃nQ比如两个IEH口。而对于保存在内存里的cookieQ不同的览器有不同的处理方式。对于IEQ在一个打开的窗口上?Ctrl-NQ或者从文g菜单Q打开的窗口可以与原窗口共享,而用其他方式新开的IEq程则不能共享已l打开的窗口的内存cookieQ对?Mozilla Firefox0.8Q所有的q程和标{N都可以共享同Lcookie。一般来说是用javascript的window.open打开的窗口会与原H口׃n内存cookie。浏览器对于会话cookie的这U只认cookie不认人的处理方式l常l采用session机制的web应用E序开发者造成很大的困扰?BR>
下面是一个goolge讄cookie的响应头的例?BR>HTTP/1.1 302 Found
Location: http://www.google.com/intl/zh-CN/
Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Content-Type: text/html




q是使用HTTPLookq个HTTP Sniffer软g来俘LHTTP通讯U录的一部分




览器在再次讉Kgoolge的资源时自动向外发送cookie

 


使用Firefox可以很容易的观察现有的cookie的?BR>使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理?BR>



IE也可以设|在接受cookie前询?BR>
 


q是一个询问接受cookie的对话框?BR>
四、理解session机制
session机制是一U服务器端的机制Q服务器使用一U类g散列表的l构Q也可能是使用散列表)来保存信息?BR>
当程序需要ؓ某个客户端的h创徏一个session的时候,服务器首先检查这个客L的请求里是否已包含了一个session标识 - UCؓ session idQ如果已包含一个session id则说明以前已lؓ此客L创徏qsessionQ服务器按照session id把这?session索出来用(如果索不刎ͼ可能会新Z个)Q如果客Lh不包含session idQ则为此客户端创Z个sessionq且生成一个与此session相关联的session idQsession id的值应该是一个既不会重复Q又不容易被扑ֈ规律以仿造的字符Ԍq个 session id被在本ơ响应中q回l客L保存?BR>
保存q个session id的方式可以采用cookieQ这样在交互q程中浏览器可以自动的按照规则把q个标识发挥l服务器。一般这个cookie的名字都是类gSEEESIONIDQ而。比如weblogic对于web应用E序生成的cookieQJSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764Q它的名字就?JSESSIONID?BR>
׃cookie可以被h为的止Q必L其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一U技术叫做URL重写Q就是把session id直接附加在URL路径的后面,附加方式也有两种Q一U是作ؓURL路径的附加信息,表现形式为http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
另一U是作ؓ查询字符串附加在URL后面Q表现Ş式ؓhttp://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
q两U方式对于用h说是没有区别的,只是服务器在解析的时候处理的方式不同Q采用第一U方式也有利于把session id的信息和正常E序参数区分开来?BR>Z在整个交互过E中始终保持状态,必d每个客户端可能请求的路径后面都包含这个session id?BR>
另一U技术叫做表单隐藏字Dc就是服务器会自动修改表单,d一个隐藏字D,以便在表单提交时能够把session id传递回服务器。比如下面的表单
<form name="testform" action="/xxx">
<input type="text">
</form>
在被传递给客户端之前将被改写成
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>
q种技术现在已较少应用Q笔者接触过的很古老的iPlanet6(SunONE应用服务器的前n)׃用了q种技术?BR>实际上这U技术可以简单的用对action应用URL重写来代ѝ?BR>
在谈论session机制的时候,常常听到q样一U误解“只要关闭浏览器Qsession消׃”。其实可以想象一下会员卡的例子,除非֮d对店家提出销卡,否则店家l对不会L删除֮的资料。对session来说也是一LQ除非程序通知服务器删除一个sessionQ否则服务器会一直保留,E序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会d在关闭之前通知服务器它要关闭Q因此服务器Ҏ不会有机会知道浏览器已经关闭Q之所以会有这U错觉,是大部分session机制都用会话cookie来保存session idQ而关闭浏览器后这?session id消׃Q再ơ连接服务器时也无法找到原来的session。如果服务器讄的cookie被保存到盘上,或者用某U手D|写浏览器发出的HTTPh_把原来的session id发送给服务器,则再ơ打开览器仍然能够找到原来的session?BR>
恰恰是由于关闭浏览器不会Dsession被删除,q服务器ؓseesion讄了一个失效时_当距dL上一ơ用session的时间超q这个失效时间时Q服务器可以认为客L已经停止了活动,才会把session删除以节省存储空间?BR>
五、理解javax.servlet.http.HttpSession
HttpSession是Javaq_对session机制的实现规范,因ؓ它仅仅是个接口,具体到每个web应用服务器的提供商,除了对规范支持之外,仍然会有一些规范里没有规定的细微差异。这里我们以BEA的Weblogic Server8.1作ؓ例子来演C?BR>
首先QWeblogic Server提供了一pd的参数来控制它的HttpSession的实玎ͼ包括使用cookie的开关选项Q用URL重写的开关选项Qsession持久化的讄Qsession失效旉的设|,以及针对cookie的各U设|,比如讄cookie的名字、\径、域Q?cookie的生存时间等?BR>
一般情况下Qsession都是存储在内存里Q当服务器进E被停止或者重启的时候,内存里的session也会被清I,如果讄了session的持久化Ҏ,服务器就会把session保存到硬盘上Q当服务器进E重新启动或q些信息能够被再次使用Q?Weblogic Server支持的持久性方式包括文件、数据库、客Lcookie保存和复制?BR>
复制严格说来不算持久化保存,因ؓsession实际上还是保存在内存里,不过同样的信息被复制到各个cluster内的服务器进E中Q这样即使某个服务器q程停止工作也仍然可以从其他q程中取得session?BR>
cookie生存旉的设|则会媄响浏览器生成的cookie是否是一个会话cookie。默认是使用会话cookie。有兴趣的可以用它来试验我们在第四节里提到的那个误解?BR>
cookie的\径对于web应用E序来说是一个非帔R要的选项QWeblogic Server对这个选项的默认处理方式得它与其他服务器有明昄区别。后面我们会专题讨论?BR>
关于session的设|参考[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869

六、HttpSession常见问题
Q在本小节中session的含义ؓ⑤和⑥的混合Q?BR>

1、session在何时被创徏
一个常见的误解是以为session在有客户端访问时p创徏Q然而事实是直到某server端程序调?HttpServletRequest.getSession(true)q样的语句时才被创徏Q注意如果JSP没有昄的?nbsp;<% @page session="false"%> 关闭sessionQ则JSP文g在编译成Servlet时将会自动加上这样一条语?HttpSession session = HttpServletRequest.getSession(true);q也是JSP中隐含的 session对象的来历?BR>
׃session会消耗内存资源,因此Q如果不打算使用sessionQ应该在所有的JSP中关闭它?BR>
2、session何时被删?BR>l合前面的讨论,session在下列情况下被删除a.E序调用HttpSession.invalidate();或b.距离上一ơ收到客L发送的session id旉间隔过了session的超时设|?或c.服务器进E被停止Q非持久sessionQ?BR>
3、如何做到在览器关闭时删除session
严格的讲Q做不到q一炏V可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进E这些非常规手段仍然无能为力?BR>
4、有个HttpSessionListener是怎么回事
你可以创Llistenerȝ控session的创建和销毁事Ӟ使得在发生这L事g时你可以做一些相应的工作。注意是session的创建和销毁动作触发listenerQ而不是相反。类似的与HttpSession有关的listenerq有 HttpSessionBindingListenerQHttpSessionActivationListener?HttpSessionAttributeListener?BR>
5、存攑֜session中的对象必须是可序列化的?BR>不是必需的。要求对象可序列化只是ؓ了session能够在集中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存。在 Weblogic Server的session中放|一个不可序列化的对象在控制C会收C个警告。我所用过的某个iPlanet版本如果 session中有不可序列化的对象Q在session销毁时会有一个ExceptionQ很奇怪?BR>
6、如何才能正的应付客户端禁止cookie的可能?BR>Ҏ有的URL使用URL重写Q包括超链接Qform的actionQ和重定向的URLQ具体做法参见[6]
http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

7、开两个览器窗口访问应用程序会使用同一个sessionq是不同的session
参见W三节对cookie的讨论,对session来说是只认id不认人,因此不同的浏览器Q不同的H口打开方式以及不同的cookie存储方式都会对这个问题的{案有媄响?BR>
8、如何防止用h开两个览器窗口操作导致的session混ؕ
q个问题与防止表单多ơ提交是cM的,可以通过讄客户端的令牌来解冟뀂就是在服务器每ơ生成一个不同的idq回l客LQ同时保存在session里,客户端提交表单时必须把这个id也返回服务器Q程序首先比较返回的id与保存在session里的值是否一_如果不一致则说明本次操作已经被提交过了。可以参看《J2EE核心模式》关于表C层模式的部分。需要注意的是对于用javascript window.open打开的窗口,一般不讄q个idQ或者用单独的idQ以防主H口无法操作Q徏议不要再window.open打开的窗口里做修Ҏ作,q样可以不用设|?BR>
9、ؓ什么在Weblogic Server中改变session的值后要重新调用一ơsession.setValue
做这个动作主要是Z在集环境中提示Weblogic Server session中的值发生了改变Q需要向其他服务器进E复制新的session倹{?BR>
10、ؓ什么session不见?BR>排除session正常失效的因素之外,服务器本w的可能性应该是微乎其微的,虽然W者在iPlanet6SP1加若q补丁的Solaris版本上倒也遇到q;览器插件的可能性次之,W者也遇到q?721插g造成的问题;理论上防火墙或者代理服务器在cookie处理上也有可能会出现问题?BR>出现q一问题的大部分原因都是E序的错误,最常见的就是在一个应用程序中去访问另外一个应用程序。我们在下一节讨个问题?BR>
七、跨应用E序的session׃n

常常有这L情况Q一个大目被分割成若干项目开发,Z能够互不q扰Q要求每个小目作ؓ一个单独的web应用E序开发,可是C最后突然发现某几个项目之间需要共享一些信息,或者想使用session来实现SSO(single sign on)Q在session中保存login的用户信息,最自然的要求是应用E序间能够访问彼此的session?BR>
然而按照Servlet规范Qsession的作用范围应该仅仅限于当前应用程序下Q不同的应用E序之间是不能够互相讉KҎ的session的。各个应用服务器从实际效果上都遵守了q一规范Q但是实现的l节却可能各有不同,因此解决跨应用程序session׃n的方法也各不相同?BR>
首先来看一下Tomcat是如何实现web应用E序之间session的隔ȝQ从 Tomcat讄的cookie路径来看Q它对不同的应用E序讄的cookie路径是不同的Q这样不同的应用E序所用的session id是不同的Q因此即使在同一个浏览器H口里访问不同的应用E序Q发送给服务器的session id也可以是不同的?BR>

  

Ҏq个Ҏ,我们可以推测Tomcat中session的内存结构大致如下?BR>

 

W者以前用q的iPlanet也采用的是同L方式Q估计SunONE与iPlanet之间不会有太大的差别。对于这U方式的服务器,解决的思\很简单,实际实行h也不难。要么让所有的应用E序׃n一个session idQ要么让应用E序能够获得其他应用E序的session id?BR>
iPlanet中有一U很单的Ҏ来实现共享一个session idQ那是把各个应用程序的cookie路径都设?Q实际上应该?NASAppQ对于应用程序来讲它的作用相当于根)?BR><session-info>
<path>/NASApp</path>
</session-info>

需要注意的是,操作׃n的session应该遵@一些编E约定,比如在session attribute名字的前面加上应用程序的前缀Q?setAttribute("name", "neo")变成setAttribute("app1.name", "neo")Q以防止命名I间冲突Q导致互相覆盖?BR>

在Tomcat中则没有q么方便的选择。在Tomcat版本3上,我们q可以有一些手D|׃nsession。对于版?以上的TomcatQ目前笔者尚未发现简单的办法。只能借助于第三方的力量,比如使用文g、数据库、JMS或者客LcookieQURL参数或者隐藏字D늭手段?BR>
我们再看一下Weblogic Server是如何处理session的?BR>

  

从截屏画面上可以看到Weblogic ServerҎ有的应用E序讄的cookie的\径都?Q这是不是意味着在Weblogic Server中默认的可以共享session了呢Q然而一个小实验卛_证明即不同的应用程序用的是同一个sessionQ各个应用程序仍然只能访问自己所讄的那些属性。这说明Weblogic Server中的session的内存结构可能如?BR>

 

对于q样一U结构,?session机制本n上来解决session׃n的问题应该是不可能的了。除了借助于第三方的力量,比如使用文g、数据库、JMS或者客L cookieQURL参数或者隐藏字D늭手段Q还有一U较为方便的做法Q就是把一个应用程序的session攑ֈServletContext中,q样另外一个应用程序就可以从ServletContext中取得前一个应用程序的引用。示例代码如下,

应用E序A
context.setAttribute("appA", session); 

应用E序B
contextA = context.getContext("/appA");
HttpSession sessionA = (HttpSession)contextA.getAttribute("appA"); 

值得注意的是q种用法不可ULQ因为根据ServletContext的JavaDocQ应用服务器可以处于安全的原因对于context.getContext("/appA");q回I|以上做法在Weblogic Server 8.1中通过?BR>
那么Weblogic ServerZ么要把所有的应用E序的cookie路径都设?呢?原来是ؓ了SSOQ凡是共享这个session的应用程序都可以׃n认证的信息。一个简单的实验可以证明这一点,修改首先d的那个应用程序的描述Wweblogic.xmlQ把cookie路径修改?appA 讉K另外一个应用程序会重新要求dQ即使是反过来,先访问cookie路径?的应用程序,再访问修改过路径的这个,虽然不再提示dQ但是登录的用户信息也会丢失。注意做q个实验时认证方式应该用FORMQ因为浏览器和web服务器对basic认证方式有其他的处理方式Q第二次h的认证不是通过 session来实现的。具体请参看[7] secion 14.8 AuthorizationQ你可以修改所附的CZE序来做q些试验?BR>
八、ȝ
session机制本nq不复杂Q然而其实现和配|上的灵zL却使得具体情况复杂多变。这也要求我们不能把仅仅某一ơ的l验或者某一个浏览器Q服务器的经验当作普遍适用的经验,而是始终需要具体情况具体分析?BR>
关于作者:
郎云鹏(dev2dev ID: hippiewolfQ,软g工程师,从事J2EE开?BR>电子邮gQlangyunpeng@yahoo.com.cn
地址Q大qY件园?1L技大厦A座大q博涵咨询服务有限公?BR>
参考文档:
[1] Preliminary Specification http://wp.netscape.com/newsref/std/cookie_spec.html
[2] RFC2109 http://www.rfc-editor.org/rfc/rfc2109.txt
[3] RFC2965 http://www.rfc-editor.org/rfc/rfc2965.txt
[4] The Unofficial Cookie FAQ http://www.cookiecentral.com/faq/
[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869
[6] http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
[7] RFC2616 http://www.rfc-editor.org/rfc/rfc2616.txt



]]>
?/title><link>http://m.tkk7.com/codefans/archive/2005/08/25/11142.html</link><dc:creator>春雷的博?/dc:creator><author>春雷的博?/author><pubDate>Thu, 25 Aug 2005 15:03:00 GMT</pubDate><guid>http://m.tkk7.com/codefans/archive/2005/08/25/11142.html</guid><wfw:comment>http://m.tkk7.com/codefans/comments/11142.html</wfw:comment><comments>http://m.tkk7.com/codefans/archive/2005/08/25/11142.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/codefans/comments/commentRss/11142.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/codefans/services/trackbacks/11142.html</trackback:ping><description><![CDATA[vc6.0 使用ado存取mysql5.0 的decimalcd的时候有问题?BR>在多U程中用CSocket的时候要注意了,必须是从CWndThreadz的UI Thread?img src ="http://m.tkk7.com/codefans/aggbug/11142.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/codefans/" target="_blank">春雷的博?/a> 2005-08-25 23:03 <a href="http://m.tkk7.com/codefans/archive/2005/08/25/11142.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>贺我的博客开通了.http://m.tkk7.com/codefans/archive/2005/07/26/8492.html春雷的博?/dc:creator>春雷的博?/author>Tue, 26 Jul 2005 08:42:00 GMThttp://m.tkk7.com/codefans/archive/2005/07/26/8492.htmlhttp://m.tkk7.com/codefans/comments/8492.htmlhttp://m.tkk7.com/codefans/archive/2005/07/26/8492.html#Feedback0http://m.tkk7.com/codefans/comments/commentRss/8492.htmlhttp://m.tkk7.com/codefans/services/trackbacks/8492.html

]]>
վ֩ģ壺 Ļ99| ޳AvƬɫҹ| 2021â| þøݾƷԴվ| ղϵ| վѴȫպ| ߹ۿѲ| avһ| պһ| av÷ۺ| Ļ1515hmѹ| kk4kkƵëƬ| ޹ƷԲAV| ҹžƵ߹ۿ| ޺ݺady޾Ʒ| ɫվ| ޹˾Ʒþþùһ | AVվ߹ۿ| Ůֻwwwվ| Ʒһ߹ۿ| վ| þþþAV| ƷƵ| Ʒһ| Ļ벻Ӱ| ŮƵ| þþƷվ| 69ʽƵ| avav߲| ŷAVӰ߹ۿ | ɫ|| Ļ߾ƷӰ| ߹ۿѻվ| ޹˾Ʒ| JIZZJIZZйٸ| ߹ۿվڵ| AVɫ߹ۿ| AVһ| һƵѹۿ| ˾޾ƷӰԺ| ĻӰӾƷվ|