﻿<?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-彪悍的人生不需要解释</title><link>http://www.blogjava.net/baixch/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 14 Jun 2026 00:37:03 GMT</lastBuildDate><pubDate>Sun, 14 Jun 2026 00:37:03 GMT</pubDate><ttl>60</ttl><item><title>GC,Reference,Finalize,Dispose</title><link>http://www.blogjava.net/baixch/archive/2008/11/18/GCReferenceFinalizeDispose.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Tue, 18 Nov 2008 06:50:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/11/18/GCReferenceFinalizeDispose.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/241146.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/11/18/GCReferenceFinalizeDispose.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/241146.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/241146.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 当一个对象实例不被强引用strongly reachable时，GC的某次运行就有可能扫描到该对象。这时GC会检查该对象是否softreference reachable，如果是，则尽可能放它一马，一笑而过，但如果放过去就会引起out of memory error，则就要处理该对象。处理过程首先要检查是否实现了finalize方法的对象，如果是则标记finalizable，并导致Finalizer系统线程（setDaemon(true)，Thread.MAX_PRIORITY - 2）在后续巡检中对此对象调用finalize方法。执行完finalize方法后如果在此后某次的GC运行中再次被发现softreference reachable，则此时导致clear softreference，并释放内存，最后归到softreference-queue中。&nbsp;&nbsp;<a href='http://www.blogjava.net/baixch/archive/2008/11/18/GCReferenceFinalizeDispose.html'>阅读全文</a><img src ="http://www.blogjava.net/baixch/aggbug/241146.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-11-18 14:50 <a href="http://www.blogjava.net/baixch/archive/2008/11/18/GCReferenceFinalizeDispose.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA InputMethod输入实现纪要</title><link>http://www.blogjava.net/baixch/archive/2008/11/14/240539.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Fri, 14 Nov 2008 07:15:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/11/14/240539.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/240539.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/11/14/240539.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/240539.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/240539.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;JAVA InputMethod 输入实现纪要Jre1.7对输入法的支持使得java开发者能够方便地使用JAVA编写输入法，并整合适配了本地输入法，然后提供出一个在所有输入法中切换的菜单界面，并在以后的编辑文本过程中实现了一个高效的事件处理框架，最终实现了方便地利用输入法进行输入的用户体验。一．编写Java输入法及切换输入法支持。利用JAVA编写输入法只需实现两个核心接...&nbsp;&nbsp;<a href='http://www.blogjava.net/baixch/archive/2008/11/14/240539.html'>阅读全文</a><img src ="http://www.blogjava.net/baixch/aggbug/240539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-11-14 15:15 <a href="http://www.blogjava.net/baixch/archive/2008/11/14/240539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA MouseEvent实现纪要</title><link>http://www.blogjava.net/baixch/archive/2008/10/30/237557.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Thu, 30 Oct 2008 03:33:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/10/30/237557.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/237557.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/10/30/237557.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/237557.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/237557.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;JAVA MouseEvent实现纪要Jre1.7鼠标事件以MouseEvent类封装。共有如下8种：/**&nbsp;&nbsp;&nbsp;&nbsp; *The"mouseclicked"event.This&lt;code&gt;MouseEvent&lt;/code&gt;&nbsp;&nbsp;&nbsp;&nbsp; *occurswhenamouse...&nbsp;&nbsp;<a href='http://www.blogjava.net/baixch/archive/2008/10/30/237557.html'>阅读全文</a><img src ="http://www.blogjava.net/baixch/aggbug/237557.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-10-30 11:33 <a href="http://www.blogjava.net/baixch/archive/2008/10/30/237557.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Focus实现纪要三</title><link>http://www.blogjava.net/baixch/archive/2008/10/29/237408.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Wed, 29 Oct 2008 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/10/29/237408.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/237408.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/10/29/237408.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/237408.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/237408.html</trackback:ping><description><![CDATA[&nbsp;
<p style="text-align: center" align="center"><strong>Java Focus</strong><strong><span style="font-family: 宋体">实现纪要三</span></strong></p>
<p><span style="font-family: 宋体">特别注意：按</span>java<span style="font-family: 宋体">给出的</span>Focus<span style="font-family: 宋体">实现规范，</span>jre1.7<span style="font-family: 宋体">保证实现如下几点：</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; text-align: left" align="left">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Focus_Gained,Focus_Lost<span style="font-family: 宋体">事件的序列。即如果在</span>EDT<span style="font-family: 宋体">中，应用程序查询</span>currentFocusOwner<span style="font-family: 宋体">，</span>=A<span style="font-family: 宋体">，此后</span>=B<span style="font-family: 宋体">，则中间一定按顺序收到</span>A Lost<span style="font-family: 宋体">，</span>B Gain.<span style="font-family: 宋体">这主要通过</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DefaultKeyboardFocusManager.dispatchEvent</span><span style="font-size: 10pt; color: black; font-family: 宋体">时，尤其是处理</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Gained(PreparedFocusGained)</span><span style="font-size: 10pt; color: black; font-family: 宋体">时，如果发现</span>currentFocusOwner!=null<span style="font-family: 宋体">，说明尚未得到</span>Lost<span style="font-family: 宋体">，则会主动生成一个</span>Lost<span style="font-family: 宋体">发布，处理后继续处理</span>Gained<span style="font-family: 宋体">。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; text-align: left" align="left">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">如果是在同一个重量级组件间做轻量级组件间切换，每一个</span>focus event<span style="font-family: 宋体">实例上可以获取到准确的</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">opposite</span><span style="font-size: 10pt; color: #0000c0; font-family: 宋体">，</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">source.</span><span style="font-family: 宋体">这主要通过</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DefaultKeyboardFocusManager.dispatchEvent</span><span style="font-size: 10pt; color: black; font-family: 宋体">和</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager.retargetEvent</span><span style="font-size: 10pt; color: black; font-family: 宋体">时，主动控制纠正可能的不准确的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">source,opposite</span><span style="font-size: 10pt; color: black; font-family: 宋体">。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; text-align: left" align="left">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Focus Event</span><span style="font-size: 10pt; color: black; font-family: 宋体">支持</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">temporary</span><span style="font-size: 10pt; color: black; font-family: 宋体">应用，尤其体现在当整个</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">window</span><span style="font-size: 10pt; color: black; font-family: 宋体">失去焦点，当再次获取焦点时将恢复此</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">window</span><span style="font-size: 10pt; color: black; font-family: 宋体">的最后聚焦组件。应用程序查询</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">focus event.isTemporary==true</span><span style="font-size: 10pt; color: black; font-family: 宋体">时，则可以确信该组件按既有逻辑很快将恢复焦点。</span><span style="font-family: 宋体">这主要通过</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DefaultKeyboardFocusManager.dispatchEvent</span><span style="font-size: 10pt; color: black; font-family: 宋体">和</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager.retargetEvent</span><span style="font-size: 10pt; color: black; font-family: 宋体">时，对</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">temporary</span><span style="font-size: 10pt; color: black; font-family: 宋体">做了充分的考虑控制。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; text-align: left" align="left">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>KeyEvent<span style="font-family: 宋体">的处理符合规范流程：</span></p>
<p style="margin-left: 36pt; text-indent: -18pt; text-align: left" align="left">a.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">根据</span>request<span style="font-family: 宋体">时间戳缓存。</span></p>
<p style="margin-left: 36pt; text-indent: -18pt; text-align: left" align="left">b.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">解除缓存时首先</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager.<em>isProxyActive</em></span><em><span style="font-size: 10pt; color: black; font-family: 宋体">（</span></em><em><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KEYEVENT</span></em><em><span style="font-size: 10pt; color: black; font-family: 宋体">）</span></em><span style="font-size: 10pt; color: black; font-family: 宋体">，考虑是否交给本地系统代理处理。</span></p>
<p style="margin-left: 36pt; text-indent: -18pt; text-align: left" align="left">c.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: black; font-family: 宋体">否则</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager.</span><span style="font-size: 10pt; color: black; font-family: 宋体">注册</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">keyEventDispatchers</span><span style="font-size: 10pt; color: black; font-family: 宋体">接手处理。</span></p>
<p style="margin-left: 36pt; text-indent: -18pt; text-align: left" align="left">d.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">发布该</span>keyevent<span style="font-family: 宋体">给对应</span>component<span style="font-family: 宋体">进行处理，其中分为如下阶段：</span></p>
<p style="margin-left: 54pt; text-indent: -18pt; text-align: left" align="left">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Allow the Toolkit to pass this to AWTEventListeners.</span><span style="font-size: 10pt; color: black; font-family: 宋体">注册在</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">toolkit</span><span style="font-size: 10pt; color: black; font-family: 宋体">下的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">AWTEventListeners</span><span style="font-size: 10pt; color: black; font-family: 宋体">得到处理。</span></p>
<p style="margin-left: 54pt; text-indent: -18pt; text-align: left" align="left">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager.processKeyEvent</span><span style="font-size: 10pt; color: black; font-family: 宋体">用来处理焦点遍历</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">(TAB</span><span style="font-size: 10pt; color: black; font-family: 宋体">等</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">)</span><span style="font-size: 10pt; color: black; font-family: 宋体">。</span></p>
<p style="margin-left: 54pt; text-indent: -18pt; text-align: left" align="left">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Pre-process any special events before delivery</span><span style="font-size: 10pt; color: black; font-family: 宋体">。对</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KEY_PRESSED</span><span style="font-size: 10pt; color: black; font-family: 宋体">，</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KEY_RELEASED</span><span style="font-size: 10pt; color: black; font-family: 宋体">，组件的容器有机会</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">preProcessKeyEvent</span><span style="font-size: 10pt; color: black; font-family: 宋体">。</span></p>
<p style="margin-left: 54pt; text-indent: -18pt; text-align: left" align="left">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: black; font-family: 宋体">组件的对应</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Key(Press,Typed,~~)Listener</span><span style="font-size: 10pt; color: black; font-family: 宋体">进行处理。</span></p>
<p style="margin-left: 36pt; text-indent: -18pt; text-align: left" align="left">e.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager.</span><span style="font-size: 10pt; color: black; font-family: 宋体">注</span><span style="font-size: 10pt; color: black; font-family: 宋体">册</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">keyEventPostProcessors</span><span style="font-size: 10pt; color: black; font-family: 宋体">接手处理。</span></p>
<p style="margin-left: 36pt; text-indent: -18pt; text-align: left" align="left">f.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: black; font-family: 宋体">组件</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">peer</span><span style="font-size: 10pt; color: black; font-family: 宋体">得到机会处理。</span></p>
<p><span style="font-family: 宋体">在其上</span>1<span style="font-family: 宋体">，</span>2<span style="font-family: 宋体">，</span>3<span style="font-family: 宋体">点的实现中，</span>Jre1.7<span style="font-family: 宋体">版本充分考虑了跨平台性：比如</span>Windows<span style="font-family: 宋体">系统，如果仅仅是拖动滚动条是不会发出</span>FocusEvent<span style="font-family: 宋体">，而其他系统就会发出</span>temporary<span style="font-family: 宋体">的</span>FocusEvent<span style="font-family: 宋体">；有些系统在重量级对等体间切换可以提供准确的</span>opposite<span style="font-family: 宋体">，但是有些系统则不提供。而</span>jre1.7<span style="font-family: 宋体">在实现上融合了各个系统的情况，给出了全面判断并针对性地处理，保证了跨平台的</span>Focus<span style="font-family: 宋体">规范表现。</span></p>
<img src ="http://www.blogjava.net/baixch/aggbug/237408.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-10-29 16:51 <a href="http://www.blogjava.net/baixch/archive/2008/10/29/237408.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Focus实现纪要二</title><link>http://www.blogjava.net/baixch/archive/2008/10/26/236734.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Sun, 26 Oct 2008 09:20:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/10/26/236734.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/236734.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/10/26/236734.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/236734.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/236734.html</trackback:ping><description><![CDATA[&nbsp;
<p style="text-align: center" align="center"><strong>Java Focus</strong><strong><span style="font-family: 宋体">实现纪要二</span></strong></p>
<p style="margin-left: 18pt; text-indent: -18pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">在</span>Jre1.7<span style="font-family: 宋体">版本中，</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager</span><span style="font-size: 10pt; color: black; font-family: 宋体">，</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DefaultKeyboardFocusManager</span><span style="font-size: 10pt; color: black; font-family: 宋体">这两个类</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">,</span><span style="font-size: 10pt; color: black; font-family: 宋体">与</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Component, WComponentPeer</span><span style="font-size: 10pt; color: black; font-family: 宋体">类一起完成了</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">focus</span><span style="font-size: 10pt; color: black; font-family: 宋体">的主要逻辑实现。</span></p>
<p style="margin-left: 20.05pt"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DefaultKeyboardFocusManager</span><span style="font-size: 10pt; color: black; font-family: 宋体">是前者的系统默认实现。其单例注册在</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">appcontext</span><span style="font-size: 10pt; color: black; font-family: 宋体">中</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">,</span><span style="font-size: 10pt; color: black; font-family: 宋体">如果需要，程序员可以替代它，以扩展</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">focus</span><span style="font-size: 10pt; color: black; font-family: 宋体">的逻辑实现。</span></p>
<p style="text-indent: 20pt"><span style="font-size: 8pt; color: black; font-family: 'Courier New'">appcontext.put(KeyboardFocusManager.</span><strong><span style="font-size: 8pt; color: #7f0055; font-family: 'Courier New'">class</span></strong><span style="font-size: 8pt; color: black; font-family: 'Courier New'">, new SelfKeyboardFocusManager());</span></p>
<p style="margin-left: 18pt; text-indent: -18pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Component<span style="font-family: 宋体">中提供了</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 10pt; color: black; font-family: 宋体">方法。而各个组件在初始化时都会安装默认的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Listener</span><span style="font-size: 10pt; color: black; font-family: 宋体">。当这些</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Listener</span><span style="font-size: 10pt; color: black; font-family: 宋体">收到适当的事件通知后（比如</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">mouse_press</span><span style="font-size: 10pt; color: black; font-family: 宋体">）即会调用这个方法。该方法首先判断该组件是否</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">focusable</span><span style="font-size: 10pt; color: black; font-family: 宋体">，组件所依托窗口是否</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">focusable</span><span style="font-size: 10pt; color: black; font-family: 宋体">，当前聚焦组件的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">InputVerifier</span><span style="font-size: 10pt; color: black; font-family: 宋体">是否验收输入等等，判断通过后请求重量级组件容器的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">peer.requestFocus</span><span style="font-size: 10pt; color: black; font-family: 宋体">。</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">WComponentPeer</span><span style="font-size: 10pt; color: black; font-family: 宋体">中提供该</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 10pt; color: black; font-family: 宋体">方法。该方法首先调用</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">native </span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">processSynchronousLightweightTransfer</span><span style="font-size: 10pt; color: black; font-family: 宋体">，其会调用</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManage</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">r .processSynchronousLightweightTransfe</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">r</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">r</span><span style="font-size: 10pt; color: black; font-family: 宋体">，作用是如果当前</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">request</span><span style="font-size: 10pt; color: black; font-family: 宋体">组件的重量级组件容器正对应当前底层系统的聚焦组件，而且当前没有任何切换焦点的</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequests</span><span style="font-size: 10pt; color: black; font-family: 宋体">，这时将直接切换</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">focus</span><span style="font-size: 10pt; color: black; font-family: 宋体">变量</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">.focusOwner</span><span style="font-size: 10pt; color: black; font-family: 宋体">。</span></p>
<p style="margin-left: 17.85pt; text-indent: 0cm; text-align: left" align="left"><span style="font-family: 宋体">如果上述调用没有顺利完成并返回</span>true<span style="font-family: 宋体">，则会调用</span>native _requestFoucs<span style="font-family: 宋体">。该方法会调用</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManage</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">r .</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">shouldNativelyFocusHeavyweight</span><span style="font-size: 10pt; color: black; font-family: 宋体">，其作用就是完成</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">request</span><span style="font-size: 10pt; color: black; font-family: 宋体">登记，并在</span><span style="font-size: 10pt; color: black; font-family: 宋体">登记时间戳以正确缓存处理后续进入</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 10pt; color: black; font-family: 宋体">的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Keyevent</span><span style="font-size: 10pt; color: black; font-family: 宋体">处理。</span></p>
<p style="margin-left: 17.85pt; text-indent: 0cm; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Request</span><span style="font-size: 10pt; color: black; font-family: 宋体">登记的结构为</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">.heavyweightRequests=</span></p>
<p style="margin-left: 17.85pt; text-indent: 0cm; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">LinkedList&lt; HeavyweightFocusRequest &gt; </span></p>
<p style="margin-left: 17.85pt; text-indent: 0cm; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">-- HeavyweightFocusRequest{</span></p>
<p style="margin-left: 17.85pt; text-indent: 0cm; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Component </span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweight</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">;</span></p>
<p style="margin-left: 17.85pt; text-indent: 0cm; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">LinkedList&lt;LightweightFocusRequest&gt; </span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">lightweightRequests</span><span style="font-size: 10pt; color: #0000c0; font-family: 宋体">，</span><span style="font-size: 10pt; color: black; font-family: 宋体">登记方式分为</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">3</span><span style="font-size: 10pt; color: black; font-family: 宋体">种</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">:</span></p>
<p style="margin-left: 43.1pt; text-indent: -18pt; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">a.&nbsp;</span><span style="font-size: 10pt; color: black; font-family: 宋体">如果发出</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 10pt; color: black; font-family: 宋体">的组件的重量级组件容器正对应当前底层系统的聚焦组件，而且当前没有任何切换焦点的</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">,</span><span style="font-size: 10pt; color: black; font-family: 宋体">则增加一个</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 10pt; color: black; font-family: 宋体">并向</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Post-Qqeue post focus-event</span><span style="font-size: 10pt; color: black; font-family: 宋体">。</span></p>
<p style="margin-left: 43.1pt; text-indent: -18pt; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">b.&nbsp;</span><span style="font-size: 10pt; color: black; font-family: 宋体">如果发出</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 10pt; color: black; font-family: 宋体">组件的重量级组件容器不对应当前底层系统的聚焦组件，而且当前没有任何切换焦点的</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 10pt; color: black; font-family: 宋体">；或者</span><span style="font-size: 10pt; color: black; font-family: 宋体">当前存在切换焦点的</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 10pt; color: black; font-family: 宋体">，而最后一个</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">.</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'"> Heavyweight!=</span><span style="font-size: 10pt; color: black; font-family: 宋体">当前</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">request</span><span style="font-size: 10pt; color: black; font-family: 宋体">组件的重量级组件容器，则要</span><span style="font-size: 10pt; color: black; font-family: 宋体">增加一个</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 10pt; color: black; font-family: 宋体">，并同步通知底层系统进行重量级对等组件的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">focus</span><span style="font-size: 10pt; color: black; font-family: 宋体">切换</span><span style="font-size: 10pt; color: #0000c0; font-family: 宋体">。</span></p>
<p style="margin-left: 43.1pt; text-indent: -18pt; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">c.&nbsp;</span><span style="font-size: 10pt; color: black; font-family: 宋体">如果当前存在切换焦点的</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 10pt; color: black; font-family: 宋体">，而且最后一个</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">.</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'"> Heavyweight==</span><span style="font-size: 10pt; color: black; font-family: 宋体">当前</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 10pt; color: black; font-family: 宋体">的组件的重量级组件容器，则直接在</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">request.</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">lightweightRequests</span><span style="font-size: 10pt; color: black; font-family: 宋体">追加一个</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">LightweightFocusRequest</span><span style="font-size: 10pt; color: black; font-family: 宋体">。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; text-align: left" align="left">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: black">EDT</span><span style="color: black; font-family: 宋体">在逐个处理</span><span style="color: black">AWTEvent</span><span style="color: black; font-family: 宋体">时，委托给</span><span style="color: black">EventQueue.</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dispatchEvent</span><span style="font-size: 10pt; color: black; font-family: 宋体">，继而委托给</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Component. dispatchEventImpl,</span><span style="font-size: 10pt; color: black; font-family: 宋体">该方法顺序执行下面的代码片段：</span></p>
<p style="margin-left: 18pt; text-indent: 12pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 宋体">～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～&#183;</span></p>
<p style="margin-left: 45.15pt; text-indent: -4.5pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 9pt; color: #3f7f5f; font-family: 'Courier New'">/*</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'"> focusManagerIsDispatching</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">标志了该</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">event;</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">如果</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">==true</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">意味着该</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">event</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">不会交由</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">KeyboardManager</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">进行</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">retarget</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">及</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">dispatch</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">。而这两个动作主要完成的功能就是刷新</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">java</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">的全局</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">focus</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">变量。因此可以想象</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">focusManagerIsDispatching==true</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">的</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">Focus_event</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">是</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">focus</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">发生切换后的</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">event</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">，而</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">focusManagerIsDispatching==false</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">的是</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">PrepareFocusEvent</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">。</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">*/</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</span><strong><span style="font-size: 6.5pt; color: #7f0055; font-family: 'Courier New'">if</span></strong><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'"> (!e.</span><span style="font-size: 6.5pt; color: #0000c0; font-family: 'Courier New'">focusManagerIsDispatching</span><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">) {//----------</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">PrepareFocusEvent</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 6.5pt; color: #3f7f5f; font-family: 'Courier New'">// Invoke the private focus retargeting method which provides</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 6.5pt; color: #3f7f5f; font-family: 'Courier New'">// lightweight Component supportF</span></p>
<p style="margin-left: 48.75pt; text-indent: -48.75pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 9pt; color: #3f7f5f; font-family: 'Courier New'">/*</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">通过</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">retargetFocus</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">，处理之前注册的</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">request</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">请求，最终激发出合适的</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">CausedFocusEvent</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">，交给下面的</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">dispatch.</span></p>
<p style="text-indent: 36pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">&nbsp;*/</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 6.5pt; color: #7f0055; font-family: 'Courier New'">if</span></strong><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'"> (e.</span><span style="font-size: 6.5pt; color: #0000c0; font-family: 'Courier New'">isPosted</span><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">) {</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e = KeyboardFocusManager.<em>retargetFocusEvent</em>(e);</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.</span><span style="font-size: 6.5pt; color: #0000c0; font-family: 'Courier New'">isPosted</span><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'"> = </span><strong><span style="font-size: 6.5pt; color: #7f0055; font-family: 'Courier New'">true</span></strong><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">;</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 6.5pt; color: #3f7f5f; font-family: 'Courier New'">// Now, with the event properly targeted to a lightweight</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 6.5pt; color: #3f7f5f; font-family: 'Courier New'">// descendant if necessary, invoke the public focus retargeting</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 6.5pt; color: #3f7f5f; font-family: 'Courier New'">// and dispatching function</span></p>
<p style="margin-left: 67.65pt; text-indent: -27pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 9pt; color: #3f7f5f; font-family: 'Courier New'">/*</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">通过</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">dispatch</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">给注册的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DefaultKeyboardFocusManager</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">,</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">最终更新了</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">java</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">的全局</span><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">focus</span><span style="font-size: 9pt; color: #0000c0; font-family: 宋体">变量</span></p>
<p style="text-indent: 36pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 9pt; color: #0000c0; font-family: 'Courier New'">&nbsp;*/</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 6.5pt; color: #7f0055; font-family: 'Courier New'">if</span></strong><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'"> (KeyboardFocusManager.<em>getCurrentKeyboardFocusManager</em>().</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dispatchEvent(e))</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 6.5pt; color: #7f0055; font-family: 'Courier New'">return</span></strong><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">;</span></p>
<p style="line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="margin-left: 18pt; text-indent: 0cm; line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="margin-left: 18pt; text-indent: 12pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 6.5pt; color: black; font-family: 宋体">～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～&#183;</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; line-height: 10pt; text-align: left" align="left">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 9pt; color: black; font-family: 宋体">总之：</span></p>
<p style="margin-left: 33pt; text-indent: -18pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 8pt; color: black; font-family: 'Courier New'">a.&nbsp;</span><span style="font-size: 8pt; color: black; font-family: 宋体">轻量级组件的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">Mouse_Press Listener</span><span style="font-size: 8pt; color: black; font-family: 宋体">会</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 8pt; color: black; font-family: 宋体">。</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">request</span><span style="font-size: 8pt; color: black; font-family: 宋体">通过必要条件检查后会在</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">.heavyweightRequests</span><span style="font-size: 8pt; color: black; font-family: 宋体">缓存列表登记，同时在一个列表中登记一个时间戳</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">marker=</span><span style="font-size: 8pt; color: black; font-family: 宋体">当前系统时间。</span></p>
<p style="margin-left: 33pt; text-indent: -18pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 8pt; color: black; font-family: 'Courier New'">b.&nbsp;</span><span style="font-size: 8pt; color: black; font-family: 宋体">每一个</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">都有一个发生时间</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">when</span><span style="font-size: 8pt; color: black; font-family: 宋体">，这个发生时间认为是</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">AWT-Windows&nbsp;loop</span><span style="font-size: 8pt; color: black; font-family: 宋体">底层</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">event</span><span style="font-size: 8pt; color: black; font-family: 宋体">形成</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">的时间。</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 8pt; color: black; font-family: 宋体">在调用</span><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">KeyboardFocusManager </span><span style="font-size: 6.5pt; color: black; font-family: 宋体">。</span><span style="font-size: 6.5pt; color: black; font-family: 'Courier New'">dispatchEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">处理一个</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">时只要发现</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">when</span><span style="font-size: 8pt; color: black; font-family: 宋体">晚于时间戳缓存列表中登记的第一个时间戳，就充分说明这是在某焦点切换请求发出后发生的键盘事件，则不应该将这个</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent target</span><span style="font-size: 8pt; color: black; font-family: 宋体">到当前全局</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">focus</span><span style="font-size: 8pt; color: black; font-family: 宋体">变量，因而这时暂将此</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">缓存在另一个列表。</span></p>
<p style="margin-left: 33pt; text-indent: -18pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 8pt; color: black; font-family: 'Courier New'">c.&nbsp;</span><span style="font-size: 8pt; color: black; font-family: 宋体">根据前面的分析，在</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 8pt; color: black; font-family: 宋体">时有</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">3</span><span style="font-size: 8pt; color: black; font-family: 宋体">种情况，一种是新增</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 8pt; color: black; font-family: 宋体">，同时</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">post</span><span style="font-size: 8pt; color: black; font-family: 宋体">给</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">post-queue</span><span style="font-size: 8pt; color: black; font-family: 宋体">一个</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">FocusEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">，一种是新增</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 8pt; color: black; font-family: 宋体">，同时因为要求底层系统切换重量级对等体而</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">awt-loop</span><span style="font-size: 8pt; color: black; font-family: 宋体">到一个</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">FocusEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">，这两种情况的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">request</span><span style="font-size: 8pt; color: black; font-family: 宋体">都在列表中期待对应</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">FocusEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">到来再切换焦点。从登记时间戳开始，被</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">awt-loop</span><span style="font-size: 8pt; color: black; font-family: 宋体">到的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">进入</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 8pt; color: black; font-family: 宋体">时都将缓存下来，而一段时间后当期待的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">FocusEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">从</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">post-queue</span><span style="font-size: 8pt; color: black; font-family: 宋体">进入</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">event-queue</span><span style="font-size: 8pt; color: black; font-family: 宋体">并要在</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 8pt; color: black; font-family: 宋体">中处理时，有充分的条件可以判断出此后再进入</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 8pt; color: black; font-family: 宋体">的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">，都至少是</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">request</span><span style="font-size: 8pt; color: black; font-family: 宋体">登记时间戳后发生的，则这时可以完成此</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">request-</span><span style="font-size: 8pt; color: black; font-family: 宋体">删除该</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 8pt; color: black; font-family: 宋体">缓存条目，做</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">focus</span><span style="font-size: 8pt; color: black; font-family: 宋体">实际切换，并将缓存的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent </span><span style="font-size: 8pt; color: black; font-family: 宋体">及时间戳记录处理掉。而第</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">3</span><span style="font-size: 8pt; color: black; font-family: 宋体">种情况是在</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 8pt; color: black; font-family: 宋体">时可以在最末一个</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 8pt; color: black; font-family: 宋体">上直接追加</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">LightWeightReuquest</span><span style="font-size: 8pt; color: black; font-family: 宋体">，那么当该</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">heavyweightRequest</span><span style="font-size: 8pt; color: black; font-family: 宋体">期待的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">FocusEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">到来时，按前面所述处理完该</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">request,</span><span style="font-size: 8pt; color: black; font-family: 宋体">再将后续</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">LightWeightRequest</span><span style="font-size: 8pt; color: black; font-family: 宋体">保存引用到一个全局变量</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">.currentLightweightRequests,</span><span style="font-size: 8pt; color: black; font-family: 宋体">再将此刻为止</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">awt-loop</span><span style="font-size: 8pt; color: black; font-family: 宋体">至的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">post-queue</span><span style="font-size: 8pt; color: black; font-family: 宋体">的所有</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">event</span><span style="font-size: 8pt; color: black; font-family: 宋体">完全</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">flush</span><span style="font-size: 8pt; color: black; font-family: 宋体">到</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">event-queue,</span><span style="font-size: 8pt; color: black; font-family: 宋体">再把一个要求循环处理所有</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">currentLightweightRequests</span><span style="font-size: 8pt; color: black; font-family: 宋体">指向的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">LightWeightRequests</span><span style="font-size: 8pt; color: black; font-family: 宋体">的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">InvocationEvent post </span><span style="font-size: 8pt; color: black; font-family: 宋体">到</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">event-queue</span><span style="font-size: 8pt; color: black; font-family: 宋体">之后。这样当</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 8pt; color: black; font-family: 宋体">开始处理该</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">InvocationEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">时，有充分的条件可以判断出此后再进入</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 8pt; color: black; font-family: 宋体">的</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">，都至少是最后一个后续</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">LightWeightRequest</span><span style="font-size: 8pt; color: black; font-family: 宋体">登记时间戳后发生的，则这时只需按该</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">InvocationEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">执行即可，及逐个清理</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">LightWeightRequest</span><span style="font-size: 8pt; color: black; font-family: 宋体">完成</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">focus</span><span style="font-size: 8pt; color: black; font-family: 宋体">切换及处理时间戳和缓存</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">KeyEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">。如果在循环处理过程中发生对某一个组件</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 8pt; color: black; font-family: 宋体">调用，这时会根据处理之初</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">currentLightweightRequests</span><span style="font-size: 8pt; color: black; font-family: 宋体">中是否只有单独</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">1</span><span style="font-size: 8pt; color: black; font-family: 宋体">个</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">request</span><span style="font-size: 8pt; color: black; font-family: 宋体">来确定能否</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">processSynchronousLightweightTransfe</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">r</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">r</span><span style="font-size: 10pt; color: black; font-family: 宋体">，</span><span style="font-size: 8pt; color: black; font-family: 宋体">即如果有多个，则这时禁止</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">processSynchronousLightweightTransfe</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">r</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">r</span><span style="font-size: 8pt; color: black; font-family: 宋体">以防止破坏了切换焦点的顺序。</span></p>
<p style="margin-left: 33pt; text-indent: -18pt; line-height: 10pt; text-align: left" align="left"><span style="font-size: 8pt; color: black; font-family: 'Courier New'">d.&nbsp;</span><span style="font-size: 8pt; color: black; font-family: 宋体">重量级组件不需要在</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">Mouse_Press Listener request Focus</span><span style="font-size: 8pt; color: black; font-family: 宋体">，当被进行</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">Mouse Press</span><span style="font-size: 8pt; color: black; font-family: 宋体">时，底层系统分发一个</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">Focus Event</span><span style="font-size: 8pt; color: black; font-family: 宋体">，当进入</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 8pt; color: black; font-family: 宋体">处理时，在</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">jre1.7</span><span style="font-size: 8pt; color: black; font-family: 宋体">中通过</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">KeyboardFocusManager</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">.</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">retargetUnexpectedFocusEventretarget</span><span style="font-size: 10pt; color: black; font-family: 宋体">，</span><span style="font-size: 8pt; color: black; font-family: 宋体">首先逐个剔除</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">request</span><span style="font-size: 8pt; color: black; font-family: 宋体">后进行期待匹配</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">(</span><span style="font-size: 8pt; color: black; font-family: 宋体">针对可能的底层分发</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">-post-queue-event-queue</span><span style="font-size: 8pt; color: black; font-family: 宋体">中间环节</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">Event</span><span style="font-size: 8pt; color: black; font-family: 宋体">的遗漏等例外情形</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">)</span><span style="font-size: 8pt; color: black; font-family: 宋体">，如果最后没有一个</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">request</span><span style="font-size: 8pt; color: black; font-family: 宋体">匹配，则直接形成</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">CausedFocusEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">交给后继</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">dispatch</span><span style="font-size: 8pt; color: black; font-family: 宋体">完成焦点切换。更确切地说，对于</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">jre1.7</span><span style="font-size: 8pt; color: black; font-family: 宋体">而言组件聚焦应该都通过</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">requestFocus</span><span style="font-size: 8pt; color: black; font-family: 宋体">完成切换，不通过该方式的聚焦切换在</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">retarget</span><span style="font-size: 8pt; color: black; font-family: 宋体">时将归属到</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">Unexpected</span><span style="font-size: 8pt; color: black; font-family: 宋体">被处理，而重量级组件的这种聚焦正好通过</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">unexpected</span><span style="font-size: 8pt; color: black; font-family: 宋体">完成。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; line-height: 10pt; text-align: left" align="left">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 8pt; color: black; font-family: 宋体">最后，个人认为</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">jre1.7</span><span style="font-size: 8pt; color: black; font-family: 宋体">中存在一个可能的问题：每次</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dispatchEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">时都会在</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">retargetFocusEvent</span><span style="font-size: 8pt; color: black; font-family: 宋体">里</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">processCurrentLightweightRequests</span><span style="font-size: 10pt; color: black; font-family: 宋体">，</span><span style="font-size: 8pt; color: black; font-family: 宋体">这样不久破坏了</span><span style="font-size: 8pt; color: black; font-family: 'Courier New'">4-c</span><span style="font-size: 8pt; color: black; font-family: 宋体">分析的时机逻辑了么？为什么要这样呢？</span></p>
<img src ="http://www.blogjava.net/baixch/aggbug/236734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-10-26 17:20 <a href="http://www.blogjava.net/baixch/archive/2008/10/26/236734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Focus实现纪要一</title><link>http://www.blogjava.net/baixch/archive/2008/10/21/235614.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Tue, 21 Oct 2008 03:08:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/10/21/235614.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/235614.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/10/21/235614.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/235614.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/235614.html</trackback:ping><description><![CDATA[&nbsp;
<p style="text-align: center" align="center"><strong>&nbsp; </p>
<p style="text-align: center" align="center"><strong>Java Focus</strong><strong><span style="font-family: 宋体">实现纪要一</span></strong></p>
<p><span style="font-family: 宋体">窗口系统一般包含一个桌面</span>GUI+<span style="font-family: 宋体">若干应用程序</span>GUI<span style="font-family: 宋体">。每个</span>GUI<span style="font-family: 宋体">都由组件构成，每个组件都可以获得</span>focus<span style="font-family: 宋体">，获得</span>focus<span style="font-family: 宋体">的组件将获得之后的键盘事件，而任意时刻只有一个组件能获得</span>focus<span style="font-family: 宋体">。这个设计适用在当前所有的窗口系统，而跨各种系统的</span>JAVA<span style="font-family: 宋体">应用，其</span>focus<span style="font-family: 宋体">的表现也要遵循这个设计目标。</span></p>
<p>JAVA<span style="font-family: 宋体">的组件分为重量级和轻量级组件，区别在于重量级组件实例的成员</span>peer-<span style="font-family: 宋体">对等体，其行为紧密依托本地系统的</span>GUI<span style="font-family: 宋体">行为函数库来进行实现。比如一个</span>JFRAME<span style="font-family: 宋体">，当</span>setvisible<span style="font-family: 宋体">时，会依托</span>peer.show<span style="font-family: 宋体">进行屏幕绘制行为，该行为会通过本地系统</span>GUI<span style="font-family: 宋体">行为函数库完成；这样一来，当其被点击时，本地系统会依据最初调用本地</span>GUI<span style="font-family: 宋体">函数绘制时留下的信息，从而能够经底层处理后（比如将该鼠标事件附加</span>peer<span style="font-family: 宋体">标记信息，同时可能经底层分析需要构造出一个可能的</span>focus_gain<span style="font-family: 宋体">事件，则在操作系统层面登记当前聚焦</span>GUI<span style="font-family: 宋体">组件等）准确将底层</span>GUI<span style="font-family: 宋体">事件派送给该</span>JVM<span style="font-family: 宋体">进程，该事件因而在</span>jvm<span style="font-family: 宋体">进程中的</span>AWT-Windows<span style="font-family: 宋体">线程</span>loop<span style="font-family: 宋体">获取到，并通过事件提供的</span>peer<span style="font-family: 宋体">标记最终确定目标为重量级组件</span>JFRAME<span style="font-family: 宋体">，因此一个</span>source==JFRAME<span style="font-family: 宋体">的</span>AWTEvent<span style="font-family: 宋体">被构造出来并最终分派给</span>EDT<span style="font-family: 宋体">进行后续处理。</span></p>
<p><span style="font-family: 宋体">事件机制是程序中家喻户晓的设计模式了。但是，看</span>java<span style="font-family: 宋体">的</span>focus<span style="font-family: 宋体">实现中对这个机制似乎多少有些不那么绝对的清晰</span><span style="font-family: Wingdings">J</span><span style="font-family: 宋体">。</span></p>
<p><span style="font-family: 宋体">个人理解，事件的含义就是某种定义的情况发生了。比如点击鼠标这个动作可以说触发了多个事件，如</span>press,release,click<span style="font-family: 宋体">等，分别指发生了鼠标</span>button1<span style="font-family: 宋体">按下，放开，完成点击的情况。</span>button1<span style="font-family: 宋体">按下这个事件比起完成点击就要更基础一些，因为完成点击指的是一个由按下，放开动作序列组合的情况发生了。</span></p>
<p><span style="font-family: 宋体">那么对于</span>focus<span style="font-family: 宋体">，</span>focus_gained,focus_lost<span style="font-family: 宋体">这两个事件应该是指某组件获得焦点或失去焦点的情况发生了，反映在机器里，应该是某种指向当前聚焦组件的全局变量发生了更新。</span></p>
<p><span style="font-family: 宋体">然而在</span>Java awt<span style="font-family: 宋体">实现里，概念混乱出现啦。</span></p>
<p><span style="font-family: 宋体">如果</span>awt_windows loop <span style="font-family: 宋体">到了</span>focus<span style="font-family: 宋体">事件，一，这个事件一定是目标向重量级组件的；二，此时，这个事件对于底层系统的对等组件，</span>focus_gainded<span style="font-family: 宋体">是发生了</span>(<span style="font-family: 宋体">底层系统标记当前聚焦组件的全局变量已经更新；底层操作系统没有</span>mess,<span style="font-family: 宋体">总是在真正</span>focus<span style="font-family: 宋体">改变后才分发</span>focus<span style="font-family: 宋体">事件</span>)<span style="font-family: 宋体">，然而在</span>java<span style="font-family: 宋体">层面，截至到</span>awt_windows loop <span style="font-family: 宋体">到底层</span>focus<span style="font-family: 宋体">事件并包装成</span>FocusEvent<span style="font-family: 宋体">放置到</span>EVENT QUEUE<span style="font-family: 宋体">时，</span>java<span style="font-family: 宋体">层面并没有更新</span>jvm<span style="font-family: 宋体">里的全局变量。所以我个人认为这个时候就不应该包装成</span>FocusEvent<span style="font-family: 宋体">，至少不应该叫这个名字，应该叫</span>PrepareFocusEvent,<span style="font-family: 宋体">嘿嘿。</span></p>
<p><span style="font-family: 宋体">澄清事件机制的概念后，回头看</span>java focus <span style="font-family: 宋体">要实现的目标。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">最简单的设计思路是提供一个</span>setfocus<span style="font-family: 宋体">调用</span>API<span style="font-family: 宋体">，该</span>API<span style="font-family: 宋体">来更新一个全局变量。</span>EDT<span style="font-family: 宋体">每次处理一个</span>keyevent<span style="font-family: 宋体">将根据当前全局变量进行</span>target<span style="font-family: 宋体">。最后给各类组件注册合适的事件监听，比如</span>mouse press listener<span style="font-family: 宋体">，在</span>listen<span style="font-family: 宋体">响应处理中调用</span>setfocus<span style="font-family: 宋体">。</span></p>
<p style="margin-left: 18pt; text-indent: 0cm"><span style="font-family: 宋体">要提供</span>setfocus<span style="font-family: 宋体">指定某组件聚焦。</span>Setfocus<span style="font-family: 宋体">一旦成功返回，该组件将接受后继发生的所有的键盘事件，直到再次失去焦点。</span></p>
<p style="margin-left: 18pt; text-indent: 0cm"><span style="font-family: 宋体">然而问题是轻量级组件的容器是一个重量级组件，而在对轻量级组件调用</span>setfocus<span style="font-family: 宋体">时它的本地对等组件在系统中很可能还没有获得焦点。若实现上只是简单的把</span>java<span style="font-family: 宋体">的全局变量更新了，那系统就会出现两个聚焦组件：一个是底层系统承认的原来的某底层对等组件，一个是</span>java<span style="font-family: 宋体">里认为的现在的</span>jtextfield<span style="font-family: 宋体">。而本地系统始终把键盘事件派发到它认可的聚焦组件上，如果这个聚焦组件属于另外一个</span>C++<span style="font-family: 宋体">进程，那么这些键盘事件就会分发给</span>C++<span style="font-family: 宋体">进程，而不会被</span>JVM<span style="font-family: 宋体">的</span>awt-windows loop<span style="font-family: 宋体">到。也就是说，虽然</span>setfocus<span style="font-family: 宋体">成功返回了，但并不代表随后的键盘事件会</span>target<span style="font-family: 宋体">到这个组件上。所以不能采用这样的设计思路。</span></p>
<p style="margin-left: 18pt; text-indent: 0cm"><span style="font-family: 宋体">尽管如此，实际上我们的组件的监听一般是在</span>mouse_press<span style="font-family: 宋体">上。而这个鼠标按下动作各类底层操作系统处理时一般首先分发</span>mouse_press<span style="font-family: 宋体">底层事件，然后切换焦点，再分发</span>focus<span style="font-family: 宋体">事件。随后的键盘事件会在底层切换焦点后分发出去。假如我们确定下来所有</span>GUI<span style="font-family: 宋体">应用只在</span>EDT<span style="font-family: 宋体">线程在</span>mouse_press<span style="font-family: 宋体">监听处理中</span>setfocus<span style="font-family: 宋体">，实际上不会丢失键盘事件。但是如果我们要在其他情况，比如某</span>worker <span style="font-family: 宋体">线程中</span>setfocus<span style="font-family: 宋体">，那么</span>setfocus<span style="font-family: 宋体">就不再可靠了。</span></p>
<p style="margin-left: 21pt"><span style="font-family: 宋体">那么，根据前面的分析，现在更改设计，在</span>setfocus<span style="font-family: 宋体">处理中调用底层</span>API<span style="font-family: 宋体">要求其重量级容器对应的本地对等组件聚焦并等到它确实聚焦完成了再更新</span>JAVA<span style="font-family: 宋体">的全局变量。但这样也有问题。即使底层系统根据底层调用通知更新了</span>focus,<span style="font-family: 宋体">马上还会继续对可能的焦点切换操作响应（可以认为有一个系统进程在处理外设的响应），很有可能别的</span>C++<span style="font-family: 宋体">应用就在此时再要求</span>focus<span style="font-family: 宋体">，于是接着就更新了底层的</span>focus<span style="font-family: 宋体">登记；而我们的</span>setfocus<span style="font-family: 宋体">调用却是在</span>jvm<span style="font-family: 宋体">进程的某线程中，显然这就是个并发的情景，这样，很有可能我们的对本地对等组件的通知发过去并返回了，那边底层系统就马上切换到了</span>C++<span style="font-family: 宋体">的某个组件</span>focus<span style="font-family: 宋体">，而我们的线程继续更新</span>JAVA<span style="font-family: 宋体">的全局</span>focus<span style="font-family: 宋体">变量，于是虽然</span>setfocus<span style="font-family: 宋体">成功返回了，但并不代表随后的键盘事件会</span>target<span style="font-family: 宋体">到这个组件上。</span></p>
<p style="margin-left: 21pt"><span style="font-family: 宋体">现在看来，除非我们同步这两个进程，让系统进程等待我们的调用</span>setfocus<span style="font-family: 宋体">的线程返回，显然那样是不合理的。</span>(JAVA<span style="font-family: 宋体">只能服从</span>OS<span style="font-family: 宋体">，不能让</span>OS<span style="font-family: 宋体">服从</span>JAVA<span style="font-family: 宋体">。</span>---<span style="font-family: 宋体">出自《英雄乱语》</span><span style="font-family: Wingdings">J</span>)<span style="font-family: 宋体">。</span></p>
<p style="margin-left: 18pt; text-indent: 0cm"><span style="font-family: 宋体">鉴于以上的分析，根本无法实现一个</span>setfocus<span style="font-family: 宋体">来完成一个切换焦点的原子性操作。</span>jre1.7<span style="font-family: 宋体">的实现为不存在</span>setfocus<span style="font-family: 宋体">，而只有</span>requestfocus<span style="font-family: 宋体">，意思是只是将这个切换焦点的请求登记上但并不进行实际切换</span>focus<span style="font-family: 宋体">；随后等收到相应的事件通知后再处理</span>request<span style="font-family: 宋体">并彻底完成一次</span>focus<span style="font-family: 宋体">切换。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">聚焦组件后马上获得随后的键盘事件。</span></p>
<p style="margin-left: 18pt; text-indent: 0cm"><span style="font-family: 宋体">难点是按用户的实际想法，</span>mouse_press<span style="font-family: 宋体">后，马上就要键盘拼写，键盘的输入应该</span>target<span style="font-family: 宋体">到</span>mouse_press<span style="font-family: 宋体">的</span>jtextfield<span style="font-family: 宋体">。根据前面的分析，</span>mouse_press<span style="font-family: 宋体">响应中</span>requestfocus/setfocus<span style="font-family: 宋体">后并没有意味着切换焦点已经完成。若实现上对于后续的键盘事件只是简单地根据</span>JAVA<span style="font-family: 宋体">的那个全局</span>focus<span style="font-family: 宋体">变量</span>target<span style="font-family: 宋体">，则这些键盘事件将不会</span>target<span style="font-family: 宋体">到期待的组件上。</span></p>
<p style="margin-left: 18pt; text-indent: 0cm"><span style="font-family: 宋体">鉴于以上的分析，</span>jre1.7<span style="font-family: 宋体">的实现是</span>requestfocus<span style="font-family: 宋体">时，只要这个请求满足必要条件，那么在其返回前就登记一个时间戳，在这个时间戳之后在下一个</span>requestfocus<span style="font-family: 宋体">时间戳之前，</span>EDT <span style="font-family: 宋体">逐个取的</span>keyevent<span style="font-family: 宋体">都将</span>target<span style="font-family: 宋体">到该组件并登记，直到该组件彻底聚焦完成后，马上把这些</span>keyevent dispatch<span style="font-family: 宋体">。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">需要支持</span>TAB<span style="font-family: 宋体">键等焦点遍历操作。</span></p>
<p style="margin-left: 18pt; text-indent: 0cm"><span style="font-family: 宋体">这一点</span>JAVA<span style="font-family: 宋体">有一个遍历模型，如下：</span></p>
<p style="margin-left: 19.95pt"><span style="font-family: 宋体">具体参照</span><a href="http://java.sun.com/javase/6/docs/api/java/awt/doc-files/FocusSpec.html">http://java.sun.com/javase/6/docs/api/java/awt/doc-files/FocusSpec.html</a></p>
<p style="margin-left: 19.95pt"><span style="font-family: 宋体">该要</span> <span style="font-family: 宋体">求并没有难点。实现上只要对</span>keyevent<span style="font-family: 宋体">监听，并根据规则进行合适处理即可。</span></p>
</strong>
<img src ="http://www.blogjava.net/baixch/aggbug/235614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-10-21 11:08 <a href="http://www.blogjava.net/baixch/archive/2008/10/21/235614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java dnd拖拽实现分析纪要</title><link>http://www.blogjava.net/baixch/archive/2008/10/10/233575.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Fri, 10 Oct 2008 05:37:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/10/10/233575.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/233575.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/10/10/233575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/233575.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/233575.html</trackback:ping><description><![CDATA[<span lang="EN-US" style="font-size: 10.5pt; font-family: 'Calibri','sans-serif'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">&nbsp;
<p style="text-align: center" align="center"><strong>Java dnd</strong><strong><span style="font-family: 宋体">拖拽实现分析纪要</span></strong></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">既有的</span>Swing<span style="font-family: 宋体">组件都内置了拖拽的支持，是怎么样支持呢？</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">首先，在</span>Windows<span style="font-family: 宋体">环境的</span>jvm<span style="font-family: 宋体">进程中，一个</span>gui<span style="font-family: 宋体">程序将启动两个线程：</span>AWT-WINDOWS<span style="font-family: 宋体">（</span>AWT<span style="font-family: 宋体">）和</span>Event-Dispatch-Thread(EDT)<span style="font-family: 宋体">。</span>AWT-WINDOWS<span style="font-family: 宋体">线程不断从</span>windows<span style="font-family: 宋体">操作系统中获取</span>GUI<span style="font-family: 宋体">事件并进行初步的底层处理；其中一些事件会被包装成高级的</span>AWTEvent<span style="font-family: 宋体">置入一个地方，而</span>EDT<span style="font-family: 宋体">线程的处理过程就包括不断在的适当时机从这个地方获取这些</span>AWTEvent<span style="font-family: 宋体">并进行高级处理。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">然后，拖拽的效果就是由以下几个</span>GUI<span style="font-family: 宋体">操作事件及相应程序处理完成的。</span></p>
<p style="margin-left: 39pt; text-indent: -18pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">拖拽开始</span>,<span style="font-family: 宋体">拖拽结束。</span></p>
<p style="margin-left: 39pt; text-indent: -18pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">拖拽进入（源组件</span>/<span style="font-family: 宋体">目的组件），拖拽经过（源组件</span>/<span style="font-family: 宋体">目的组件），拖拽离开（源组件</span>/<span style="font-family: 宋体">目的组件），拖拽中鼠标的移动。</span></p>
<p style="margin-left: 39pt; text-indent: -18pt">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">拖拽操作式样变换。即随键盘操作，可以指示</span>3<span style="font-family: 宋体">种操作式样：剪切式，复制式，链接式。</span></p>
<p style="margin-left: 21pt"><span style="font-family: 宋体">这些事件发生后，</span>AWT<span style="font-family: 宋体">线程即会获取到事件通知并处理，底层处理后会包装交给</span>EDT<span style="font-family: 宋体">继续处理。而处理的程序逻辑一般设计为，对于鼠标图标，会被设计为随拖拽的起始及移动的整个过程中不同事件的发生而发生变化（比如在</span>dragover<span style="font-family: 宋体">事件中可能根据当时情况将图标变为一个叉表示不能拖入）；同时，对于拖拽源组件和目的组件，随不同的事件通知也会被程序设计为产生不同的变化响应（比如，拖拽结束的事件处理中可能指令目的组件复制源组件的文字内容），从而最终实现了拖拽的效果。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">最后，看一些</span>JRE7<span style="font-family: 宋体">中拖拽的实现类。</span></p>
<p>Swing<span style="font-family: 宋体">的</span>JComponent<span style="font-family: 宋体">组件将一些功能委托给其成员</span>ComponentUI<span style="font-family: 宋体">代理。比如</span>JTextField<span style="font-family: 宋体">在构造方法中即会通过</span>UIManager<span style="font-family: 宋体">获得合适的</span>TextUI<span style="font-family: 宋体">实例（</span>UIManager<span style="font-family: 宋体">将根据当前</span>look and feel<span style="font-family: 宋体">设置获取）（此后</span>JTextField<span style="font-family: 宋体">的</span>paint<span style="font-family: 宋体">方法会调用该</span>UI<span style="font-family: 宋体">实例的</span>update<span style="font-family: 宋体">方法从而完成组件绘画），并调用该</span>UI<span style="font-family: 宋体">实例的</span>installUI<span style="font-family: 宋体">方法（在</span>installUI<span style="font-family: 宋体">中则包括给</span>JTextField<span style="font-family: 宋体">对象安装一些监听器，安装</span>TransferHandler<span style="font-family: 宋体">这个支持拖拽的关键成员，它包含</span>DragHandler,DropHandler<span style="font-family: 宋体">两个内部类，而这两个内部类是实现拖拽效果的核心逻辑，安装</span>droptarget<span style="font-family: 宋体">）。</span></p>
<p>Swing<span style="font-family: 宋体">将</span>ui<span style="font-family: 宋体">类划分在几个包中，其中</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">javax.swing.plaf</span><span style="font-size: 10pt; color: black; font-family: 宋体">中存放一些接口；</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">javax.swing.plaf.basic</span><span style="font-size: 10pt; color: black; font-family: 宋体">中存放对接口的基本实现，即多种</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">LAF</span><span style="font-size: 10pt; color: black; font-family: 宋体">的通用实现；</span><em><span style="color: black; font-family: 'Arial','sans-serif'">javax.swing.plaf.metal</span></em><em><span style="color: black; font-family: 宋体">中存放</span></em><em><span style="color: black; font-family: 'Arial','sans-serif'">java</span></em><em><span style="color: black; font-family: 宋体">默认</span></em><em><span style="color: black; font-family: 'Arial','sans-serif'">LAF</span></em><em><span style="color: black; font-family: 宋体">实现；另外还有</span></em><span style="font-size: 10pt; color: black; font-family: 'Courier New'">javax.swing.plaf.multi</span><span style="font-size: 10pt; color: black; font-family: 宋体">用来实现多个</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">LAF</span><span style="font-size: 10pt; color: black; font-family: 宋体">的综合效果实现；</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">javax.swing.plaf.synth</span><span style="font-size: 10pt; color: black; font-family: 宋体">用来实现可通过配置</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">xml</span><span style="font-size: 10pt; color: black; font-family: 宋体">文件更换颜色等皮肤的实现。</span></p>
<p><span style="font-family: 宋体">对于拖拽方面，</span>BasicUI<span style="font-family: 宋体">在</span>installUI<span style="font-family: 宋体">中一般会对组件安装</span>mouseListener<span style="font-family: 宋体">：</span></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">editor</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">.addMouseListener(</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">dragListener</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">);</span></p>
<p><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">editor</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">.addMouseMotionListener(</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">dragListener</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">);</span></p>
<p><span style="font-size: 10pt; color: black; font-family: 宋体">该</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragListener</span><span style="font-size: 10pt; color: black; font-family: 宋体">将监听发生在组件上的鼠标事件，当发现可能是新启动的拖拽鼠标动作并且组件</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragEnable</span><span style="font-size: 10pt; color: black; font-family: 宋体">时，则立刻通知</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DragRecognitionSupport</span><span style="font-size: 10pt; color: black; font-family: 宋体">单例进行组件拖拽识别。该</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">support</span><span style="font-size: 10pt; color: black; font-family: 宋体">单例将辨别鼠标动作本身，确认是组件拖拽开始，再通知组件的</span>TransferHandler<span style="font-family: 宋体">成员对象进行拖拽初始化，即</span><span style="font-size: 10pt; color: black; font-family: 宋体">，</span><span style="font-family: 宋体">经其辨别</span>headless<span style="font-family: 宋体">环境和</span>action<span style="font-family: 宋体">支持后将初始化建立并委托调用</span>TransferHandler.<span style="font-size: 10pt; color: black; font-family: 'Courier New'">SwingDragGestureRecognizer</span><span style="font-size: 10pt; color: black; font-family: 宋体">的全局单例</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">(</span><span style="font-size: 10pt; color: black; font-family: 宋体">成员包括全局单例</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragsource</span><span style="font-size: 10pt; color: black; font-family: 宋体">及</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">draghandler</span><span style="font-size: 10pt; color: black; font-family: 宋体">对象</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">)</span><span style="font-size: 10pt; color: black; font-family: 宋体">，该实例注册拖拽识别</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">listener</span><span style="font-size: 10pt; color: black; font-family: 宋体">及设置</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">sourceAction,</span><span style="font-family: 宋体">最终将通知</span>TransferHandler.DragHandler<span style="font-family: 宋体">对象的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragGestureRecognized</span><span style="font-size: 10pt; color: black; font-family: 宋体">。在该方法中，将创建</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">transferable</span><span style="font-size: 10pt; color: black; font-family: 宋体">及初始化</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">autoscroll</span><span style="font-size: 10pt; color: black; font-family: 宋体">；并通过</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragSource</span><span style="font-size: 10pt; color: black; font-family: 宋体">全局单例完成创建</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DragContext,</span><span style="font-size: 10pt; color: black; font-family: 宋体">并获取及初始化</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DragContextPeer</span><span style="font-size: 10pt; color: black; font-family: 宋体">全局单例（给该单例注册上该</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">component</span><span style="font-size: 10pt; color: black; font-family: 宋体">作为拖拽</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> trigger</span><span style="font-size: 10pt; color: black; font-family: 宋体">，以供</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">native code</span><span style="font-size: 10pt; color: black; font-family: 宋体">可以在处理底层事件时，可以通过</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">x,y</span><span style="font-size: 10pt; color: black; font-family: 宋体">判定是否</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">contains</span><span style="font-size: 10pt; color: black; font-family: 宋体">，从而缩小事件处理范围），并通知</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DragContextPeer</span><span style="font-size: 10pt; color: black; font-family: 宋体">单例拖拽开始，而</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DragContextPeer</span><span style="font-size: 10pt; color: black; font-family: 宋体">单例则会调用底层</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">native code</span><span style="font-size: 10pt; color: black; font-family: 宋体">进行进一步的处理。</span></p>
<p><span style="font-size: 10pt; color: black; font-family: 宋体">此后</span>AWT<span style="font-family: 宋体">线程将通过</span>windows-api<span style="font-family: 宋体">获取到系统底层的各种拖拽事件并进行底层处理，处理过程将会随时引用</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DragContextPeer</span><span style="font-size: 10pt; color: black; font-family: 宋体">单例（处理逻辑包括根据</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">trigger</span><span style="font-size: 10pt; color: black; font-family: 宋体">过滤），并最终通知该单例合适的事件通知。</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Peer</span><span style="font-size: 10pt; color: black; font-family: 宋体">会将这些事件封装成合适的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DragEvent</span><span style="font-size: 10pt; color: black; font-family: 宋体">并提交给</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 10pt; color: black; font-family: 宋体">处理，提交后将促使</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">AWT</span><span style="font-size: 10pt; color: black; font-family: 宋体">线程模拟等待</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 10pt; color: black; font-family: 宋体">处理完该事件。</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 10pt; color: black; font-family: 宋体">的处理逻辑是将事件交给拖拽开始时给组件创建的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DragContext</span><span style="font-size: 10pt; color: black; font-family: 宋体">处理，而该</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">context</span><span style="font-size: 10pt; color: black; font-family: 宋体">对象的处理则会调用其</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragHandler</span><span style="font-size: 10pt; color: black; font-family: 宋体">成员的对应方法进行事件处理，以及给</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragSource</span><span style="font-size: 10pt; color: black; font-family: 宋体">单例相应的监听通知，最后</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">updateCurrentCursor</span><span style="font-size: 10pt; color: black; font-family: 宋体">等，最后</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 10pt; color: black; font-family: 宋体">返回到</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">AWT,peer</span><span style="font-size: 10pt; color: black; font-family: 宋体">处理返回给</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">native code</span><span style="font-size: 10pt; color: black; font-family: 宋体">继续处理。</span></p>
<p><span style="font-size: 10pt; color: black; font-family: 宋体">当拖拽开始后，鼠标图标在一个</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">swing</span><span style="font-size: 10pt; color: black; font-family: 宋体">组件上游晃时，首先</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">windows</span><span style="font-size: 10pt; color: black; font-family: 宋体">会对其顶层容器（如</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">jwindows</span><span style="font-size: 10pt; color: black; font-family: 宋体">）视作拖拽源，经</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">native code</span><span style="font-size: 10pt; color: black; font-family: 宋体">过滤后，如果该</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">swing</span><span style="font-size: 10pt; color: black; font-family: 宋体">组件是此次拖拽</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">trigger</span><span style="font-size: 10pt; color: black; font-family: 宋体">（源），则</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DragContextPeer</span><span style="font-size: 10pt; color: black; font-family: 宋体">能得到</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragover</span><span style="font-size: 10pt; color: black; font-family: 宋体">的通知，进而进行后续处理；同时从另一个方面，这个也被视作一个拖拽目的，即</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">AWT</span><span style="font-size: 10pt; color: black; font-family: 宋体">线程还会对每次拖拽启动建立一个</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DropContextPeer</span><span style="font-size: 10pt; color: black; font-family: 宋体">（为将来支持并发），并调用该</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">peer</span><span style="font-size: 10pt; color: black; font-family: 宋体">的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">handle</span><span style="font-size: 10pt; color: black; font-family: 宋体">事件方法，该方法会将此底层事件包装后提交给</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 10pt; color: black; font-family: 宋体">并促使</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">AWT</span><span style="font-size: 10pt; color: black; font-family: 宋体">等待；</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">EDT</span><span style="font-size: 10pt; color: black; font-family: 宋体">处理该事件时将</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">track</span><span style="font-size: 10pt; color: black; font-family: 宋体">到该事件发生时的顶层组件，以及事件发生的坐标位置，由顶层容器组件的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">LightweightDispatcher</span><span style="font-size: 10pt; color: black; font-family: 宋体">进行初步处理。这个处理将由该事件产生新事件，其</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">event source</span><span style="font-size: 10pt; color: black; font-family: 宋体">将从</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">container</span><span style="font-size: 10pt; color: black; font-family: 宋体">（比如</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">JFRAME</span><span style="font-size: 10pt; color: black; font-family: 宋体">）变为精确的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">jcomponent(</span><span style="font-size: 10pt; color: black; font-family: 宋体">比如</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">JTextField),</span><span style="font-size: 10pt; color: black; font-family: 宋体">同时对于</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">eventId=dragover</span><span style="font-size: 10pt; color: black; font-family: 宋体">的事件，有可能根据具体情况再增加</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragExit</span><span style="font-size: 10pt; color: black; font-family: 宋体">，</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragEnter</span><span style="font-size: 10pt; color: black; font-family: 宋体">两个事件（比如对</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">jframe</span><span style="font-size: 10pt; color: black; font-family: 宋体">窗体是</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dragover</span><span style="font-size: 10pt; color: black; font-family: 宋体">，但鼠标实际是从一个</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">jtextfield</span><span style="font-size: 10pt; color: black; font-family: 宋体">到另外一个</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">jtextfield</span><span style="font-size: 10pt; color: black; font-family: 宋体">），这些精确的事件的处理会再次回到</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DropContextPeer</span><span style="font-size: 10pt; color: black; font-family: 宋体">中得到对应的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">process</span><span style="font-size: 10pt; color: black; font-family: 宋体">。这时的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">process</span><span style="font-size: 10pt; color: black; font-family: 宋体">会处理本身的一些成员数据（当前</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">context,</span><span style="font-size: 10pt; color: black; font-family: 宋体">当前</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">droptarget</span><span style="font-size: 10pt; color: black; font-family: 宋体">等），再将事件委托给</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">source jcomponent</span><span style="font-size: 10pt; color: black; font-family: 宋体">的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">droptarget</span><span style="font-size: 10pt; color: black; font-family: 宋体">进行处理（如果已安装），此时的处理将是传递给对应组件的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">drophandler</span><span style="font-size: 10pt; color: black; font-family: 宋体">进行处理，同时会通知</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">droptarget</span><span style="font-size: 10pt; color: black; font-family: 宋体">的注册监听，最后</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">initializeAutoscrolling</span><span style="font-size: 10pt; color: black; font-family: 宋体">等。</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">drophandler</span><span style="font-size: 10pt; color: black; font-family: 宋体">在处理过程中对</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">event</span><span style="font-size: 10pt; color: black; font-family: 宋体">可以进行</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">accept</span><span style="font-size: 10pt; color: black; font-family: 宋体">或</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">reject</span><span style="font-size: 10pt; color: black; font-family: 宋体">，这两个动作会再去调用</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">dropcontext</span><span style="font-size: 10pt; color: black; font-family: 宋体">进行处理，并最终转到</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">peer</span><span style="font-size: 10pt; color: black; font-family: 宋体">处理成员数据。最后</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">edt</span><span style="font-size: 10pt; color: black; font-family: 宋体">返回到</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">AWT,peer handle</span><span style="font-size: 10pt; color: black; font-family: 宋体">处理结束返回</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">native code</span><span style="font-size: 10pt; color: black; font-family: 宋体">当前</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">drop action</span><span style="font-size: 10pt; color: black; font-family: 宋体">值，</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">native code</span><span style="font-size: 10pt; color: black; font-family: 宋体">继续处理。</span></p>
<p style="text-indent: 15pt"><span style="font-size: 10pt; color: black; font-family: 宋体">通过以上的分析，如果需要定制</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">swing</span><span style="font-size: 10pt; color: black; font-family: 宋体">组件的拖拽逻辑，一个比较基础的入口是</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">transferhandler</span><span style="font-size: 10pt; color: black; font-family: 宋体">；因为所有事件的处理都将经过其两个内部类逻辑处理</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">(DragHandler</span><span style="font-size: 10pt; color: black; font-family: 宋体">和</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">DropHandler)</span><span style="font-size: 10pt; color: black; font-family: 宋体">；而</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">swing</span><span style="font-size: 10pt; color: black; font-family: 宋体">包中的</span>TransferHandler<span style="font-family: 宋体">的具体实现，是这两个内部类的方法都把一些控制划分给了</span>componet<span style="font-family: 宋体">的一些属性设置或</span>TransferHandler<span style="font-family: 宋体">本身的回调方法，所以只需对组件设置合适的属性，或继承并</span>override TransferHandler<span style="font-family: 宋体">合适的方法并给此</span>swing<span style="font-family: 宋体">组件重新</span>setTransferHandler<span style="font-family: 宋体">，即可以定制新的逻辑。如果需要更深层次的定制，则需要细致考虑上述分析，选择合适的定制点。</span></p>
</span>
<img src ="http://www.blogjava.net/baixch/aggbug/233575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-10-10 13:37 <a href="http://www.blogjava.net/baixch/archive/2008/10/10/233575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java乱码?问题</title><link>http://www.blogjava.net/baixch/archive/2008/10/08/233140.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Wed, 08 Oct 2008 07:07:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/10/08/233140.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/233140.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/10/08/233140.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/233140.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/233140.html</trackback:ping><description><![CDATA[真是一个老生常谈的问题啦！<br />
项目上遇到啦，环境是：<br />
1.中间件和数据库都各自在hp-unix机器上。数据库oracle字符集采用ZHS16GBK；中间件（基于jdk1.5）启动时指定字符集是#export lang=zh_CN.hp15CN。<br />
2.客户端采用applet实现。<br />
情况就是有个人名&#8220;李袆&#8221;,通过客户端输入保存后，再查询出来就变成了&#8220;李?&#8221;。<br />
好啦，重新复习一下java乱码问题，google了一大把，有的说得都不对，现在先推荐两篇权威的。<br />
<a href="http://java.sun.com/developer/technicalArticles/Intl/HTTPCharset/">http://java.sun.com/developer/technicalArticles/Intl/HTTPCharset/</a>；<a href="http://java.sun.com/developer/technicalArticles/Intl/Supplementary/">http://java.sun.com/developer/technicalArticles/Intl/Supplementary/</a>；<br />
开始解决问题啦。<br />
1.jvm在内存里存字符串是以utf-16存的，但是class文件和序列化对象文件里的字符串内容以&#8220;modified&#8221;utf-8存；<br />
在jvm1.5里char代表的是编码unit，不是编码point。这样就有可能两个char才代表一个字符。这个&#8220;代表&#8221;的变化是为适应unicode从1.0升到2.0版本，老jdk到新jdk的一个概念改变，很多api和jdk工具因此也发生变化。那时unicode1.0里就是定长16位代表字符，所以老jdk里一个char就代表一个point，当然也是一个unit。但是unicode2.0扩展开来了，因此为了兼容，新jdk就确定一个char只代表一个unit，表示一个point得用int。<br />
&#8220;modified&#8221;utf-8是java对标准utf-8编码的一点更改，可以认为是种特殊编码，为了适应java需要而存在的字符集。<br />
2.客户端接受输入法输入后，在客户端jvm里以utf-16存&#8220;袆&#8221;，而后发送给中间件是通过序列化，以"modifed"utf-8传送，中间件反序列化就又在中间件jvm里以utf-16存&#8220;袆&#8221;啦。这时中间件里的那个java对象要通过 jdbc给oracle发送过去此字符串，oracle的jdbc驱动将以系统默认字符集进行编码传送。可是zh_CN.hp15CN是gb2312标准，没有这个生僻字，只好搞一个&#8220;不存在编码&#8221;编码，这一编码就把信息丢失了；而数据库是以ZHS16GBK认识接受到数据，将这个&#8220;损坏的字&#8221;存到数据文件里啦。这里请问下同行读者,oracle数据库端会不会做zh_CN.hp15CN到ZHS16GBK的转码还是直接认为传过来的一定是ZHS16GBK直接存到数据文件？我个人认为数据库不做这种转码，浪费性能么。但不管怎么说，在中间件哪里，&#8220;袆&#8221;字就被&#8220;损坏&#8221;了，传到数据库怎么样也无法恢复了。<br />
3.这样客户端再去获取时肯定是显示不出来&#8220;袆&#8221;字啦。<br />
于是让客户执行#export lang=zh_CN.gb18030再启动中间件，问题解决。<br />
补充：<br />
1.oracle的jdbc thin驱动就是这样，使用系统默认字符集进行传送编码，不像mysql可以在连接url中指定。不过我个人认为这也不错，因为你即使在url指定正确的编码格式，还要保证操作系统装着这个字符集呢。<br />
2.jsp<a href='mailto:%@page&amp;nbsp;&amp;nbsp; contentType="text/html;charset=gb2312" language="java" pageEncoding="gb2312"%' href_cetemp='mailto:%@page&amp;nbsp;&amp;nbsp; contentType="text/html;charset=gb2312" language="java" pageEncoding="gb2312"%'>%@page&nbsp;&nbsp; contentType="text/html;charset=gb2312" language="java" pageEncoding="gb2312"%</a>这个标记分两部分，pageEncoding是指jsp文本文件本身存在硬盘的编码格式，servlet容器按这个编码格式读取，从而再做转码到合适编码（一般utf-8）的java文件，再编译成含&#8220;modified utf-8字符串&#8221;的class文件，再加载成实例对象；当该对象吐出response时，以contentType里的charset进行编码在网上传送给客户端，并置response头信息编码格式。<br />
3.浏览器客户端接受到response时，会根据头信息获取编码格式，从而解析出正确字符，再根据html规范进行显示。而对于网页提交表单时，也会根据这个信息进行表单内容数据的编码。编码后再进行url编码即发送给服务器。可是表单输入有可能超出这个字符集，则多数浏览器会采用&#（unicode point number）来编码这个字符，继续发送给服务器。同样，如果浏览器在接受response时，得到这种形式的字符串，多数也将进行解码从而显示出来。<br />
4.多数servlet容器在解析request获取参数时统一采用默认配置的iso-8859-1。这个字符集只包含西欧字符，因此解析前统一setCharacterEncoding是必须的。 当然多数都也可以修改默认配置啦。 
<img src ="http://www.blogjava.net/baixch/aggbug/233140.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-10-08 15:07 <a href="http://www.blogjava.net/baixch/archive/2008/10/08/233140.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTTPCLIENT性能调优翻译</title><link>http://www.blogjava.net/baixch/archive/2008/08/12/221483.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Tue, 12 Aug 2008 06:29:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/08/12/221483.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/221483.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/08/12/221483.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/221483.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/221483.html</trackback:ping><description><![CDATA[<div dir="ltr" align="left">httpclient的默认配置提供了最大的可靠性和标准的遵守，而不是性能。（哪个标准？难道是指HTTP协议规范？）有几个配置选项和优化技术，可以显着提高httpclient 的性能表现。 本文档给出了对httpclient如何调优的大纲。<br />
<br />
</div>
<p align="left"><font style="color: red; background-color: #ffff00">1.重用HTTPCLIENT实例。</font></p>
<p dir="ltr" align="left"><font style="color: #000000; background-color: #00ff00">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red"><span style="background-color: #00ff00"><span style="color: red"><span style="color: #000000"><span style="background-color: #00ff00">一般说来，建议一个通讯组件，甚至说一个应用软件就始终维持一个HttpClient对象实例存在。但是如果你的应用很稀罕才用到它，而且还不允许这么一个实例一直存在，那么，这里强烈建议，每次在disposing 它之前，一定要显式地shut down&nbsp;它的 multithreaded connection manager 。这样做是确保连接池里的connection得到释放</span></span><span style="color: #000000">。</span></span> </span></span></font></p>
<p dir="ltr" align="left"><span style="color: red; background-color: #ffff00">2.持续连接不关闭。</span></p>
<p id="result_box" dir="ltr" style="color: red; background-color: #00ff00" align="left"><span style="color: #000000">httpclient总是尽量重用连接。它不要求任何配置，默认情况下就是这样。某些情况下，这可能导致连接泄漏，而耗尽资源。禁用持续连接最简单的方法是提供或扩展一个connection manager，在<a href="http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/HttpConnectionManager.html#releaseConnection(org.apache.commons.httpclient.HttpConnection)">releaseConnection</a>被调用的时候，这个connection manager将把connection真正关闭掉</span><span style="color: #000000">。</span></p>
<span style="color: red; background-color: yellow">3.http method的并发执行。（实际上是在对1.延伸）<br />
</span><span style="color: red; background-color: #00ff00"><span style="color: #000000"><span style="background-color: #00ff00">如果应用程序逻辑允许并发执行多个HTTP请求，（例如对多个服务器的多个并发请求，或对同一个服务器代表不同用户身份的多个请求） ，应用程序可以为每一个HTTP session开启一个专门的线程，这样的设计自然将带来显著的性能提升。 而当使用一个线程安全的连接管理器，如multithreadedhttpconnectionmanager时，HttpClient能保证线程安全。这样，多个线程可以共享这么一个线程安全的HttpClient实例。请注意，应用程序的每个各自执行的线程必须使用各自的httpmethod实例；并且可配置各自的httpstate实例和/或hostconfiguration实例（代表一个特定的会话状态和主机配置）。这个共享的HttpClient和其标配的multithreadedhttpconnectionmanager将为各线程带来最高的性能</span></span><span style="color: #000000">。</span><br />
</span><span style="color: red; background-color: yellow">4.request/response entity 流技术处理</span><br />
<span style="color: #000000; background-color: #00ff00">HttpClient能够有效地流处理request,response。就是说大的entity可以不用在内存（泛滥）缓存就发送或接收。这点在多请求并发时尤其关键。虽然提供了方法可以通过访问字符串或字节组的方式处理数据（而不是通过流），但是不建议这样做。因为除非特别仔细，这样做很容易引起内存溢出，因为这些方法实际上是把整个entity都缓存在了内存中。<br />
response流API：建议使用HttpMethod#getResponseBodyAsStream，将response体作为字节/字符流处理；不建议使用HttpMethod#getResponseBody 和HttpMethod#getResponseBodyAsString 。<br />
request流API：对于request的流处理，技术难题在于如果通讯过程出现问题（认证失败或io失败），那么需要对发送的request entity进行重新获取,重新发送。很明显，(request的数据来源于应用程序的各个方面)，除了可以提供API（NameValuePair 形式）处理可完全缓存在内存的数据（字节组等），不容易提供统一的API。因此（对于大块的entity），程序员可通过自行继承<a href="http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/methods/RequestEntity.html">RequestEntity</a>，在相应回调方法里进行流化处理。</span><br />
<span style="color: red; background-color: yellow">5.Expect-continue handshake</span><br />
<p><span style="background-color: #00ff00">&nbsp;HTTP提供HTTP 100 (Continue) 状态，是指客户端发送一个&#8220;预期HTTP100&#8221;的请求header，如果服务器响应100说明接受该客户端请求，则客户端继续发送body。是啊，如果服务器通过header就能判断是否响应100还是拒绝，那么不通过这条路就直接发送body（尤其是大body）真的太浪费资源了。授权拒绝是最典型的情形了。因此强烈建议对于那些有HTTP认证要求的服务器使用&#8220;预期HTTP100&#8221;这种通讯方式。注意如果通讯要通过代理，程序员要处理可能的警告，因为一些老的HTTP1.0代理服务器不能正确处理&#8220;预期HTTP100&#8221;通讯方式。<br />
</span><span style="color: red; background-color: yellow">6. 钝态连接的检查</span><br />
<span style="background-color: #00ff00">HTTP协议规范允许客户端或服务器端不知会对方，在任意时刻都可以终止一个连接（指底层网络连接），因此这个connection就变成了钝态或者说陈旧了，反正是不能用了。在默认情况下，HttpClient 会在执行HTTP方法前检查要用的连接，看看是否是钝态。这个检查需耗时15-30ms，根据使用的jre不同而不同。关闭这个检查能带来小部分的性能提升，尤其对于小负载response这种通讯。但是关闭后可能面临底层连接已关闭的异常（服务器主动关闭但没通知客户端）。</span><br />
<span style="color: red; background-color: yellow">7.Cookie 处理</span><br />
<span style="background-color: #00ff00">如果一个应用程序，例如web spider，不需要和服务器保持会话状态，则禁用cookie会带来轻微的性能提升。<br />
<br />
</span></p>
 <img src ="http://www.blogjava.net/baixch/aggbug/221483.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-08-12 14:29 <a href="http://www.blogjava.net/baixch/archive/2008/08/12/221483.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MDA 于JAVA</title><link>http://www.blogjava.net/baixch/archive/2008/06/26/210829.html</link><dc:creator>英雄</dc:creator><author>英雄</author><pubDate>Thu, 26 Jun 2008 06:58:00 GMT</pubDate><guid>http://www.blogjava.net/baixch/archive/2008/06/26/210829.html</guid><wfw:comment>http://www.blogjava.net/baixch/comments/210829.html</wfw:comment><comments>http://www.blogjava.net/baixch/archive/2008/06/26/210829.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/baixch/comments/commentRss/210829.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/baixch/services/trackbacks/210829.html</trackback:ping><description><![CDATA[<p><font style="background-color: #c7edcc">现在元数据驱动架构的应用日益广泛了。这种模式的应用一般为公司的架构师根据经验提供一套schema定义，而业务逻辑实现由原来的编码转为按照此schema定义数据。之后有些系统使用代码生成机制来生成代码；而有些系统则采用编写一套框架类，执行时解析定义数据，从而执行数据所表达的逻辑。这两种方式各有利弊。<br />
对于第一种方式，会生成一堆固定模式的代码，如果允许直接修改这些代码，将造成很大的维护量；第二种方式，由于是解析执行，非常值得怀疑是否会造成JVM hotspot机制失灵，从而导致性能问题；最理想的方式我个人认为是生成代码，但限制这些代码为只读代码，同时保证这些生成代码也要建立在框架结构之上，从而可以再灵活动态拦截进代码。这样一方面，提供了MDA外的补充，即可以插写代码；另一方面可以充分利用JVM hotspot编译执行机制。<br />
前面也提到了，由于MDA起源于架构师的经验，因此schema是不太可能保罗万象的。MDA在项目上的应用必须要提供一种补充机制。一般也就是采用AOP切面编程或回调机制来做这件补充。首先保证项目的价值实现，然后再后期将这些代码实现抽象进schema的范围，从而扩大元数据的表达能力。我个人认为元数据扩大的极限就是编程语言，呵呵，想想吧，这个认识不是空话，所以我MDA的系统一定是留着补充机制的。</font></p>
<img src ="http://www.blogjava.net/baixch/aggbug/210829.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/baixch/" target="_blank">英雄</a> 2008-06-26 14:58 <a href="http://www.blogjava.net/baixch/archive/2008/06/26/210829.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>