﻿<?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-jinfeng_wang-随笔分类-view</title><link>http://www.blogjava.net/jinfeng_wang/category/1002.html</link><description>G-G-S,D-D-U!</description><language>zh-cn</language><lastBuildDate>Fri, 16 Apr 2010 12:45:10 GMT</lastBuildDate><pubDate>Fri, 16 Apr 2010 12:45:10 GMT</pubDate><ttl>60</ttl><item><title>网络服务器设计的模型及一些设计方法zz</title><link>http://www.blogjava.net/jinfeng_wang/archive/2010/04/16/318495.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Fri, 16 Apr 2010 03:36:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2010/04/16/318495.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/318495.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2010/04/16/318495.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/318495.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/318495.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="word-spacing: 0px; font: medium 'MS PGothic'; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span class="Apple-style-span" style="font-size: 12px; line-height: 18px; font-family: verdana, sans-serif; text-align: center"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="1" alt="" src="http://cq144.csdn.net/visitlog.php?screen=1280x800&amp;host=blog.csdn.net&amp;browser=Netscape%205%20&amp;os=Windows&amp;url=http://blog.csdn.net/proad/archive/2008/04/16/2296925.aspx&amp;username=J2eeLearner" width="1" border="0" /><iframe id="myframe" border="0" name="myframe" src="http://www.csdn.net/ggmm/dd333.htm" frameborder="no" width="0" scrolling="no" height="0"></iframe></span></span> <a href="http://blog.csdn.net/proad/archive/2008/04/16/2296925.aspx">http://blog.csdn.net/proad/archive/2008/04/16/2296925.aspx</a><br />
<br />
<br />
<span class="Apple-style-span" style="word-spacing: 0px; font: medium 'MS PGothic'; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span class="Apple-style-span" style="font-size: 14px; line-height: 21px; font-family: verdana, sans-serif; text-align: left">
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><strong>1. 常用服务器模型</strong><br />
a.迭代服务器：只有一个进程/线程处理请求。一般为单进程,加上select多路复用,非阻塞socket。<br />
b.迭代/并发混合型服务器：平时迭代处理，对消耗大的请求并发处理。处理请求时设置一个超时，当请求的处理时间超时时，创建一个进程/线程，把处理转给新的进程/线程处理，主进程/线程继续处理其他请求。<br />
c.并发服务器：多个进程/线程并发处理请求。</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><strong>2. 以上三类的服务器比较</strong><br />
迭代服务器：最简单，性能不高。<br />
并发服务器：性能较高，但结构相对比较复杂，开发难度中等。<br />
迭代/并发混合型服务器：性能不错，但结构通常比单纯的并发服务器更复杂。</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><strong>3. 多进程的并发服务器</strong><br />
a. 每个连接fork一个进程：主进程accpet连接，有新连接到来时fork一个进程，然后继续accept，等待新的连接。数据传输由子进程处理，处理完后子进程exit。每个子进程只处理一个连接。<br />
b. Prefork进程：主进程预先fork一些进程，各个子进程竞争accept，然后处理数据传输。一个子进程可以处理一个连接，也可以同时处理多个连接（通过select等）。<br />
c. Prefork进程：由父进程accept请求，通过流管道转发fd到子进程，子进程收到fd后，处理数据传输，处理结束后通知父进程。父进程处理的事情比较简单，容易监控子进程。</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px">以上3种方式性能比较：<br />
a.每个连接fork一个进程：处理smtp等状态较多，数据量比较大时比较简单实用，总体性能不大好。<br />
b.Prefork进程，各个子进程竞争accept：比较简单，性能不错。<br />
c.Prefork进程，由父进程accept请求，通过流管道转发fd到子进程：代码复杂，性能一般不如上一种。</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><strong>4. 多线程的并发服务器</strong><br />
a.每个连接一个线程<br />
b.Prethread多个线程，各个线程互斥accept<br />
c.Prethread多个线程，主线程accept并分发连接给子线程</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><strong>5. 多进程与多线程的比较</strong><br />
使用线程的模型：性能比使用进程要高，但代码比较复杂，对代码质量要求更高，线程出错后可能会影响到所有线程，多进程的模式一个进程出错一般不会影响其他进程。<br />
多线程模型共享数据比较简单有效，多进程模型共享数据比较麻烦，效率也不如线程。</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><strong>6. 一些流行的网络服务器采用的模型</strong></p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><strong>Sendmail:</strong><span class="Apple-converted-space">&nbsp;</span>采用多进程，每个连接fork一个进程.<br />
每个连接fork一个子进程<br />
子进程只处理一个连接<br />
子进程fork一个localmail进程（可以由用户自己编写），通过管道把数据转给localmail处理，把邮件处理业务逻辑独立出来<br />
优点：结构简单，不用维护复杂的状态机</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><strong>Apache1.3:</strong>采用多进程, prefork进程<br />
子进程竞争accept，每次只处理一个连接<br />
主进程不accept，根据负载情况调整子进程数量<br />
子进程运行一段时间后，主进程会让它退出，然后创建一个新的进程，防止内存泄漏等<br />
主进程通过shared memory监控子进程</p>
<p style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px; margin: 1em 0px 0.5em; padding-top: 0px"><strong>移动QQ:</strong><span class="Apple-converted-space">&nbsp;</span>Prefork多个进程，竞争accept,<br />
典型的一问一答TCP服务器，结构简单<br />
每个进程通过select可以同时处理多个连接<br />
采用这种结构的原因有：<br />
每秒请求&lt;1000，可以满足要求<br />
结构简单，容易开发、维护</p>
</span></span>
 <img src ="http://www.blogjava.net/jinfeng_wang/aggbug/318495.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2010-04-16 11:36 <a href="http://www.blogjava.net/jinfeng_wang/archive/2010/04/16/318495.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>劳动法分析</title><link>http://www.blogjava.net/jinfeng_wang/archive/2010/03/19/315853.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Thu, 18 Mar 2010 16:27:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2010/03/19/315853.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/315853.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2010/03/19/315853.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/315853.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/315853.html</trackback:ping><description><![CDATA[&nbsp;
<p>A)<span style="font-family: 'ＭＳ 明朝'">中</span><span style="font-family: SimSun">华</span><span style="font-family: 'ＭＳ 明朝'">人民共和国</span><span style="font-family: SimSun">劳动</span><span style="font-family: 'ＭＳ 明朝'">合同法</span></p>
<p><a href="http://www.molss.gov.cn/gb/news/2007-06/30/content_184630.htm">http://www.molss.gov.cn/gb/news/2007-06/30/content_184630.htm</a></p>
<p>B)<span style="font-family: 'ＭＳ 明朝'">中</span><span style="font-family: SimSun">华</span><span style="font-family: 'ＭＳ 明朝'">人民共和国</span><span style="font-family: SimSun">劳动</span><span style="font-family: 'ＭＳ 明朝'">合同法</span><span style="font-family: SimSun">实</span><span style="font-family: 'ＭＳ 明朝'">施条例</span><span style="font-family: 'ＭＳ 明朝'">(</span><span style="font-family: SimSun">解释劳动法实施</span><span style="font-family: 'ＭＳ 明朝'">)</span></p>
<p><a href="http://www.gov.cn/flfg/2008-09/19/content_1099500.htm">http://www.gov.cn/flfg/2008-09/19/content_1099500.htm</a></p>
<p>C)<span style="font-family: SimSun">关于确立劳动关系有关事项的通知</span></p>
<p><a href="http://www.law-lib.com/law/law_view.asp?id=92395">http://www.law-lib.com/law/law_view.asp?id=92395</a></p>
<p>D)<span style="font-family: SimSun">上海市女职工劳动保护办法</span></p>
<p><a href="http://www.shanghai.gov.cn/shanghai/node2314/node3124/node3125/node3133/userobject6ai655.html">http://www.shanghai.gov.cn/shanghai/node2314/node3124/node3125/node3133/userobject6ai655.html</a></p>
<p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">&#183;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong>C)</strong></span><strong><span style="font-family: SimSun">的相关内容：</strong></span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-family: SimSun">用人单位未与劳动者签订劳动合同，<strong><span style="color: red">认定双方存在劳动关系</strong>时可参照下列凭证：</span></span></p>
<p>(<span style="font-family: SimSun">一</span>)<span style="font-family: SimSun">工资支付凭证或记录</span>(<span style="font-family: SimSun">职工工资发放花名册</span>)<span style="font-family: SimSun">、缴纳各项社会保险费的记录；</span></p>
<p>(<span style="font-family: SimSun">二</span>)<span style="font-family: SimSun">用人单位向劳动者发放的<strong><span style="color: red">&#8220;工作证&#8221;、&#8220;服务证&#8221;等能够证明身份的证件</strong>；</span></span></p>
<p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">&#183;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong>B) </strong></span><strong><span style="font-family: SimSun">的相关内容：</strong></span></p>
<p style="margin-left: 69pt; text-indent: -48pt; tab-stops: list 69.0pt">第六条<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: SimSun">用人单位自用工之日起<span style="color: blue">超过一个月不满一年</span>未与劳动者订立书面劳动合同的，应当依照<span style="color: blue">劳动合同法第八十二条的规定向劳动者每月支付两倍的工资，并与劳动者补订书面劳动合同</span>；劳动者不与用人单位订立书面劳动合同的，用人单位应当书面通知劳动者终止劳动关系，<span style="color: blue">并依照劳动合同法第四十七条的规定支付经济补偿</span>。</span></span><strong><span style="color: red">(1</strong></span><strong><span style="color: red; font-family: SimSun">，相当于给</strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">倍工资，</strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">，补合同，</strong></span><strong><span style="color: red">3</strong></span><strong><span style="color: red; font-family: SimSun">，如果辞退，再按照有合同补偿）</strong></span></p>
<p style="margin-left: 21pt"><span style="font-family: SimSun">第二十七条　劳动合同法第四十七条规定的<strong><span style="color: red">经济补偿的月工资按照劳动者应得工资计算，包括计时工资或者计件工资以及奖金</strong><span style="color: red">。</span></span></span></p>
<p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">&#183;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong>A)</strong></span><strong><span style="font-family: SimSun">的相关内容：</strong></span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: SimSun">第四十二条　劳动者有下列情形之一的，用人单位<strong><span style="color: red">不得依照</strong>本法第四十条、第四十一条的规定解除劳动合同：</span></span></p>
<p><strong><span style="color: red">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</strong></span><strong><span style="color: red; font-family: SimSun">（四）女职工在孕期、产期、哺乳期的</strong></span></p>
<p>&nbsp;<span style="font-family: SimSun">　第四十七条　经济补偿按劳动者在本单位工作的年限，<strong><span style="color: red">每满一年支付一个月工资的标准向劳动者支付。六个月以上不满一年的，按一年计算；</strong>不满六个月的，向劳动者支付半个月工资的经济补偿。</span></span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: SimSun">第八十二条　<strong><span style="color: red">用人单位自用工之日起超过一个月不满一年未与劳动者订立书面劳动合同的，应当向劳动者每月支付二倍的工资。</strong></span></span></p>
<p><strong><span style="color: red">&nbsp;&nbsp;&nbsp; </strong></span><span style="font-family: SimSun">用人单位违反本法规定不与劳动者订立<strong><span style="color: red">无固定期限劳动合同</strong>的，自应当订立无固定期限劳动合同之日起向劳动者每月<strong><span style="color: red">支付二倍的工资</span></strong>。</span></span></p>
<p><strong><span style="color: red">&nbsp;&nbsp;&nbsp;&nbsp; </strong></span><span style="font-family: SimSun">第八十七条　用人<strong><span style="color: red">单位违反本法</strong>规定解除或者终止劳动合同的，应当<strong><span style="color: red">依照本法第四十七条</span></strong>规定的经济补偿<strong><span style="color: red">标准的二倍</span></strong>向劳动者支付赔偿金。</span></span></p>
<p>&nbsp;<span style="font-family: SimSun">第十四条　无固定期限劳动合同，是指用人单位与劳动者约定无确定终止时间的劳动合同。</span></p>
<p>&nbsp;&nbsp;&nbsp; <span style="font-family: SimSun">用人单位与劳动者协商一致，可以订立无固定期限劳动合同。有下列情形之一，劳动者提出或者同意续订、订立劳动合同的，除劳动者提出订立固定期限劳动合同外，应当<strong><span style="color: red">订立无固定期限劳动合同</strong>：</span></span></p>
<p>&nbsp;&nbsp;&nbsp; <span style="font-family: SimSun">（一）劳动者在该用人单位<span style="color: red">连续<strong>工作满十年</strong>的；</span></span></p>
<p>&nbsp;&nbsp;&nbsp; <span style="font-family: SimSun">（二）用人单位初次实行劳动合同制度或者国有企业改制重新订立劳动合同时，劳动者在该用人单位连续工作满十年且距法定退休年龄不足十年的；</span></p>
<p>&nbsp;&nbsp;&nbsp; <span style="font-family: SimSun">（三）<strong><span style="color: red">连续订立二次固定期限劳动合同</strong>，且劳动者没有本法第三十九条和第四十条第一项、第二项规定的情形，续订劳动合同的。</span></span></p>
<p>&nbsp;&nbsp;&nbsp; <span style="font-family: SimSun">用人单位<strong><span style="color: red">自用工之日起满一年不与劳动者订立书面劳动合同的，视为用人单位与劳动者已订立无固定期限劳动合同</strong>。</span></span></p>
<p><strong>&nbsp;</strong></p>
<p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">&#183;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong>D) </strong></span><strong><span style="font-family: SimSun">的相关内容：</strong></span></p>
<p><span style="font-family: SimSun">第十一条</span><span style="font-family: SimSun">对妊娠期的女职工，<strong><span style="color: red">不应延长其劳动时间</strong>；</span></span></p>
<p><span style="font-family: SimSun">第十四条</span><span style="font-family: SimSun">女职工产假分别按下列情况执行：</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: SimSun">（一）单胎顺产者，给予<span style="color: red">产假九十天，其中产前休息十五天，产后休息七十五天。</span></span></p>
<p><span style="font-family: SimSun">第十五条</span><span style="font-family: SimSun">女职工生育后，在其婴儿一周岁内应照顾其在每班劳动时间内<span style="color: red">授乳两次（包括人工喂养）。<span style="color: red">每次</span>单胎纯授乳时间为<span style="color: red">三十分钟</span>，亦可将两次授乳时间合并使用。多胞胎生育者，每多生一胎，每次哺乳时间增加三十分钟。</span></span></p>
<p>&nbsp;<span style="font-family: SimSun">第十八条</span><span style="font-family: SimSun">女职工在<span style="color: red">产假期间的工资照发。按本规定享受的<span style="color: red">产前假和哺乳假的工资</span>按本人原工资的<span style="color: red">百分之八十发给</span>。单位增加工资时，女职工按规定享受的产前假、产假、哺乳假，应作出勤对待。</span></span></p>
<p><strong><span style="color: red">&nbsp;&nbsp;&nbsp; </strong></span></p>
<p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">&#183;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-family: SimSun">结论：</span></strong></span></p>
<p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">1）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><strong><span style="color: red; font-family: SimSun">认定劳动关系：工作证</span></strong></span></p>
<p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">2）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><strong><span style="color: red; font-family: SimSun">是否签合同</span></strong></span></p>
<p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">3）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><strong><span style="color: red; font-family: SimSun">如果没签合同，怎么补偿（</span></strong></span><span style="color: red">1</span><span style="color: red; font-family: SimSun">，<strong>相当于给</strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">倍工资，</strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">，补合同，</strong></span><strong><span style="color: red">3</strong></span><strong><span style="color: red; font-family: SimSun">，如果辞退，再按照有合同补偿）</strong></span></p>
<p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">4）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><strong><span style="color: red; font-family: SimSun">如果是固定合同，怎么补偿（</span></strong></span><strong><span style="color: red">N+1</strong></span><strong><span style="color: red; font-family: SimSun">）</strong></span></p>
<p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">5）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><strong><span style="color: red; font-family: SimSun">如果是无期合同，</span></strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">倍</strong></span></p>
<p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">6）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><strong><span style="color: red; font-family: SimSun">孕妇怎么处理？</span></strong></span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333">1</span><span style="background: silver; color: #333333; font-family: SimSun">、公司辞退孕妇的补偿情况标准是怎样？</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">答：发放工资到哺乳期满；按工作年限计算经济补偿金。</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333">2</span><span style="background: silver; color: #333333; font-family: SimSun">、公司是否可以以我的考核和我是孕产妇不能胜任工作为由对我进行降职降级降薪处理？</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">答：不可以。</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">我们的工资分为基本工资（约占</span><span style="background: silver; color: #333333">1/4)+</span><span style="background: silver; color: #333333; font-family: SimSun">岗位工资</span><span style="background: silver; color: #333333">+</span><span style="background: silver; color: #333333; font-family: SimSun">绩效工资等。是否可能出现只要不降低我的基本工资就是合法的行为？</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">答：不合理。工资是包括了岗位工资和绩效工资。</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333">3</span><span style="background: silver; color: #333333; font-family: SimSun">、如果公司依法破产，我是否有向集团主张赔偿的权利？</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">答：破产也可以主张权利，在破产财产中优先演戏偿。</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333">4</span><span style="background: silver; color: #333333; font-family: SimSun">、如果可能需要诉诸法律，我应该准备哪些方面的举证？</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">答：存在劳动关系的证据最重要，此外，工资条、怀孕的证据、结婚证、准生证</span></p>
<p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">也比较重要。</span><span style="background: silver; color: #333333; font-family: SimSun">（</span><strong><span style="background: silver; color: red; font-family: SimSun">按照劳动法</span></strong><strong><span style="background: silver; color: red">42</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">条，不得解除三期【孕期、产期、哺乳期】妇女。那么如果一定要违反劳动法解除劳动关系，只能按照违反劳动法，按照第八十七条进行二倍赔偿，也就是</span></strong><strong><span style="background: silver; color: red">3</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">倍）</span></strong></p>
<p style="margin-left: 9pt"><strong><span style="font-size: 13.5pt; color: #333333; font-family: 'ＭＳ 明朝'">案例</span></strong><strong><span style="font-size: 13.5pt; color: #333333">:</span></strong></p>
<p style="margin-left: 9pt"><strong><span style="font-size: 13.5pt; color: #333333"><a href="http://www.tianya.cn/publicforum/content/law/1/119373.shtml">http://www.tianya.cn/publicforum/content/law/1/119373.shtml</a> </span></strong></p>
<p style="margin-left: 9pt"><span style="background: silver; font-family: 'ＭＳ 明朝'">案情：</span><span style="background: silver">A</span><span style="background: silver; font-family: 'ＭＳ 明朝'">公司辞退</span><span style="background: silver">B</span><span style="background: silver; font-family: 'ＭＳ 明朝'">孕</span><span style="background: silver; font-family: SimSun">妇</span><span style="background: silver; font-family: 'ＭＳ 明朝'">（不考</span><span style="background: silver; font-family: SimSun">虑</span><span style="background: silver">B</span><span style="background: silver; font-family: 'ＭＳ 明朝'">可能存在的</span><span style="background: silver; font-family: SimSun">过错</span><span style="background: silver; font-family: 'ＭＳ 明朝'">，假</span><span style="background: silver; font-family: SimSun">设</span><span style="background: silver">A</span><span style="background: silver; font-family: 'ＭＳ 明朝'">毫无道理毫无依据的辞退</span><span style="background: silver">B</span><span style="background: silver; font-family: 'ＭＳ 明朝'">孕</span><span style="background: silver; font-family: SimSun">妇</span><span style="background: silver; font-family: 'ＭＳ 明朝'">）。</span></p>
<p style="margin-left: 9pt"><span style="background: silver; font-family: 'ＭＳ 明朝'">　　</span><span style="background: silver; font-family: 'ＭＳ 明朝'">一</span><span style="background: silver; font-family: SimSun">审结</span><span style="background: silver; font-family: 'ＭＳ 明朝'">果：<strong><span style="color: red">判</span></strong></span><strong><span style="background: silver; color: red; font-family: SimSun">赔</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">全</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">额</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">孕期工</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">资</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">、全</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">额产</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">期（</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">晚</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">育</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">还</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">加了</span></strong><strong><span style="background: silver; color: red">15</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">天）工</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">资</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">、</span></strong><strong><span style="background: silver; color: red">75%</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">的哺乳期工</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">资</span></strong><span style="background: silver; font-family: 'ＭＳ 明朝'">，并以入</span><span style="background: silver; font-family: SimSun">职时间</span><span style="background: silver; font-family: 'ＭＳ 明朝'">至三期届</span><span style="background: silver; font-family: SimSun">满为劳动</span><span style="background: silver; font-family: 'ＭＳ 明朝'">合同</span><span style="background: silver; font-family: SimSun">关</span><span style="background: silver; font-family: 'ＭＳ 明朝'">系存</span><span style="background: silver; font-family: SimSun">续</span><span style="background: silver; font-family: 'ＭＳ 明朝'">期</span><span style="background: silver; font-family: SimSun">间计</span><span style="background: silver; font-family: 'ＭＳ 明朝'">算在</span><span style="background: silver; font-family: SimSun">职时间</span><span style="background: silver; font-family: 'ＭＳ 明朝'">，然后以</span><span style="background: silver; font-family: SimSun">该</span><span style="background: silver; font-family: 'ＭＳ 明朝'">在</span><span style="background: silver; font-family: SimSun">职时间</span><span style="background: silver; font-family: 'ＭＳ 明朝'">按照《</span><span style="background: silver; font-family: SimSun">劳动</span><span style="background: silver; font-family: 'ＭＳ 明朝'">合同法》第八十七条判</span><span style="background: silver; font-family: SimSun">赔</span><span style="background: silver; font-family: 'ＭＳ 明朝'">了</span><strong><span style="background: silver; color: red; font-family: SimSun">赔偿</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">金（即合法解除的</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">补偿</span></strong><strong><span style="background: silver; color: red; font-family: 'ＭＳ 明朝'">金的双倍）</span></strong><span style="background: silver; font-family: 'ＭＳ 明朝'">。一</span><span style="background: silver; font-family: SimSun">审</span><span style="background: silver; font-family: 'ＭＳ 明朝'">不是我代理的。</span></p>
<p style="margin-left: 9pt"><span style="background: silver; font-family: 'ＭＳ 明朝'">　　</span><span style="background: silver; font-family: 'ＭＳ 明朝'">二</span><span style="background: silver; font-family: SimSun">审</span><span style="background: silver">A</span><span style="background: silver; font-family: 'ＭＳ 明朝'">公司找到我，我想当然的以</span><span style="background: silver; font-family: SimSun">为</span><span style="background: silver; font-family: 'ＭＳ 明朝'">，按照《</span><span style="background: silver; font-family: SimSun">劳动</span><span style="background: silver; font-family: 'ＭＳ 明朝'">合同法》第八十七条的</span><span style="background: silver; font-family: SimSun">规</span><span style="background: silver; font-family: 'ＭＳ 明朝'">定，</span><span style="background: silver; font-family: SimSun">劳动</span><span style="background: silver; font-family: 'ＭＳ 明朝'">者可以</span><span style="background: silver; font-family: SimSun">选择</span><span style="background: silver; font-family: 'ＭＳ 明朝'">要求</span><span style="background: silver; font-family: SimSun">继续</span><span style="background: silver; font-family: 'ＭＳ 明朝'">履行，不要求</span><span style="background: silver; font-family: SimSun">继续</span><span style="background: silver; font-family: 'ＭＳ 明朝'">履行的，</span><span style="background: silver; font-family: SimSun">应</span><span style="background: silver; font-family: 'ＭＳ 明朝'">当</span><span style="background: silver; font-family: SimSun">仅</span><span style="background: silver; font-family: 'ＭＳ 明朝'">支付双倍</span><span style="background: silver; font-family: SimSun">补偿</span><span style="background: silver; font-family: 'ＭＳ 明朝'">即可，一</span><span style="background: silver; font-family: SimSun">审</span><span style="background: silver; font-family: 'ＭＳ 明朝'">判决属适用法律</span><span style="background: silver; font-family: SimSun">错误</span><span style="background: silver; font-family: 'ＭＳ 明朝'">。</span></p>
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/315853.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2010-03-19 00:27 <a href="http://www.blogjava.net/jinfeng_wang/archive/2010/03/19/315853.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单点登陆(SSO)组件的设计与实现 zz</title><link>http://www.blogjava.net/jinfeng_wang/archive/2008/03/07/184540.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Fri, 07 Mar 2008 08:36:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2008/03/07/184540.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/184540.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2008/03/07/184540.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/184540.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/184540.html</trackback:ping><description><![CDATA[http://www.cnblogs.com/jillzhang/archive/2008/02/01/1061212.html<br />
<br />
<br />
<br />
<br />
<p>&nbsp;
先说几句废话，自我感觉此方案还不错，至少解决了安全性的问题，也实现了统一登出，能跨平台，跨服务期，跨域名，当然需要相应的联盟站点的支持，但从原理上绝对能跨平台。设计和具体实现的描述比较长，今天先介绍一部分
<br />
<br />
<br />
</p>
<h1>1引言 </h1>
<h2>1.1 编写目的 </h2>
<p>详细说明单点登录组件(SSO)的设计思想和实现方法，是日后该组件维护和扩展工作的基本依据文档。预期读者是要实现单点登录(SSO)系统的系统设计人员，系统开发人员，系统维护人员。
</p>
<h2>1.2 背景 </h2>
<p>说明： </p>
<ol style="margin-left: 39pt;">
    <li>
    <div style="text-align: justify;">待开发软件系统的名称；jillzhang的SSO组件 </div>
    </li>
    <li>
    <div style="text-align: justify;">本项目的任务提出者为jillzhang、开发者为jillzhang、用户为有用户整合需求平台的开发和设计人员。
    </div>
    </li>
</ol>
<h2>1.3 定义 </h2>
<p><strong>SSO</strong>是Single Sign
On的缩写，该技术主要用于用户整合。<br />
<strong>认证中心</strong>：认证中心是用户注册，成员站点管理，用户登录，验证登录信息，保存登录
信息，颁发登录认证的中心站点。&nbsp;<br />
<strong>成员站点:
</strong>成员站点是遵从认证中心规则，享用认证中心统一用户的站点。&nbsp;&nbsp;<br />
<strong>注册站点：</strong>如果想成为成员站点，必须先在认证中心进行站点登记，登记后，认证中心会保存注册站点的配置信息，并将该配置信息发给注册站点。注册站点也需保存这些配置信息，供日后与认证中心交互时候使用。&nbsp;&nbsp;<br />
<strong>联盟用户</strong>：指在认证中心注册的用户，这些用户能被所有的成员站点所共享。<br />
<strong>登录请求</strong>：指成员站点向认证中心发出的带有站点配置的用户登录请求信息。<br />
<strong>登出请求</strong>：只用户向认证中心发出的要求退出登录的请求。&nbsp;&nbsp;<br />
<strong>登录请求验证：</strong>指的是认证中心根据存储的站点信息对成员站点的登录请求信息进行来
源和真实性的验证。<br />
<strong>登出请求验证：</strong>指认证中心在接受来自成员站点的登出请求的时候，对请求的来源和真实性进行的验证<br />
<strong>登录答复：</strong>指认证中心对经过验证的登录请求作出的答复信息。该答复包含用户的登录信息。<br />
<strong>在线联盟用户数</strong>：指的是在成员站点中，在线的联盟用户数量。&nbsp;&nbsp;<br />
<strong>在线联盟用户列表</strong>：指的是在成员站点中，在线的联盟用户的列表信息。&nbsp;<br />
<strong>登录站点清单：</strong>是由认证中心维护的用户的登录站点信息，当用户注销的时候，会遍历此清单，逐个登出。
</p>
<h2>1.4 参考资料 </h2>
<p>本组件的设计和实现参考了下面的系统和书籍 </p>
<ol style="margin-left: 39pt;">
    <li>
    <div style="text-align: justify;"><a href="http://www.cnblogs.com/David-weihw/archive/2007/01/25/630621.html">http://www.cnblogs.com/David-weihw/archive/2007/01/25/630621.html</a>
    </div>
    </li>
    <li>
    <div style="text-align: justify;">《数字签名技术原理及技术》 <br />
    <br />
    </div>
    </li>
</ol>
<h1>2 程序系统的结构 </h1>
<p>本组件包括下面几个应用接口，分别如下： </p>
<ol style="margin-left: 41pt;">
    <li>
    <div style="text-align: justify;">ISite：ISite是用于描述和操作成员站点的接口 </div>
    </li>
    <li>
    <div style="text-align: justify;">IUser : IUser是用于描述和操作联盟用户的接口 </div>
    </li>
    <li>
    <div style="text-align: justify;">IServer:IServer是认证中心处理登录请求和登出请求的接口 </div>
    </li>
    <li>
    <div style="text-align: justify;">IClient: IClient是成员站点发出登录请求和处理登录答复的接口 </div>
    </li>
    <li>
    <div style="text-align: justify;">IUserLoginList：IUserLoginList是描述和操作用户登录站点清单的接口
    </div>
    </li>
    <li>
    <div style="text-align: justify;">ILoginRequest：是记录和操作成员站点发送登录请求的接口。 </div>
    </li>
    <li>
    <div style="text-align: justify;">ILoginRequestContainer：用于保存和维护登录请求列表的接口 </div>
    </li>
    <li>
    <div style="text-align: justify;">IUserStateContainer：是联盟站点中保存用联盟用户登录信息的接口。
    </div>
    </li>
</ol>
<p>它们的定义如下： </p>
<p style="margin-left: 20pt;"><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO1.jpg" />
</p>
<p style="margin-left: 20pt;"><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO2.jpg" />
</p>
<p style="margin-left: 20pt;">组件的工作流程描述如下： </p>
<ol style="margin-left: 41pt;">
    <li>
    <div style="text-align: justify;">第一步，首先注册联盟站点，注册联盟站点用到接口ISite </div>
    </li>
    <li>
    <div style="text-align: justify;">第二步：注册好联盟站点之后，将认证中心产生的站点配置信息（包括站点编号，站点公钥，站点私钥，认证中心的登录地址，认证中心登出地址）存储到联盟站点本地。
    </div>
    </li>
    <li>
    <div style="text-align: justify;">在认证中心上注册一新用户，注册用户需要使用IUser接口 </div>
    </li>
    <li>
    <div style="text-align: justify;">在联盟站点对认证中心发出登录请求 </div>
    </li>
    <li>
    <div style="text-align: justify;">认证中心验证登录请求 </div>
    </li>
    <li>
    <div style="text-align: justify;">在认证中心进行登录 </div>
    </li>
    <li>
    <div style="text-align: justify;">登录成功后，保存登录票据，认证中心对联盟站点发送登录答复，并将此次登录记录到登录站点清单
    </div>
    </li>
    <li>
    <div style="text-align: justify;">联盟站点接收到登录答复后，先进性验证，正确后，根据登录答复中的信息产生用户登录票据，并且更新联盟用户登录数和登录列表
    </div>
    </li>
    <li>
    <div style="text-align: justify;">在联盟站点中发出登出请求 </div>
    </li>
    <li>
    <div style="text-align: justify;">认证中心验证登出请求，正确的话，销毁认证中心用户登录票据，通过用户的登录站点清单，逐个调用联盟站点的登出页面
    </div>
    </li>
    <li>
    <div style="text-align: justify;">在认证中心回调联盟站点的登出页的时候，联盟站点会在登出页中销毁各个的登录票据，并更新在线用户数和用户列表。
    </div>
    </li>
</ol>
<p>&nbsp;</p>
<h1>3 ISite接口设计说明&nbsp;</h1>
<h2>3.1 接口描述 </h2>
<p>ISite接口包括7个属性和2个方法，分别用于在认证中心用于描述和操作站点的配置 </p>
<p>信息。 </p>
<p><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO3.png" align="left" /><br />
</p>
<p><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
其中，各个属性的含义如下</p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 154px;">
    <col style="width: 189px;">
    <col style="width: 189px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">属性名称</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">类型</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">SiteID</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">站点编号，用于表示站点的唯一性。</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">HomePage</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">当登录请求中未提供来源网址项的时候，登录答复发送的地址</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">LogOutUrl</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">在进行统一登出的时候，回调的联盟站点页面地址，这个页面会负责销毁本站的登录票据信息。</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">PublicKey</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">用于数据交换时加密或签名用的公钥</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">PublicAndPrivateKey</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">用于数据交换时加密或签名用的私钥</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">FromUrlKey</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">用于指示联盟站点在发送登录请求和认证站点进行请求验证的时候来源网址存储位置。</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">UidField</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">用于指示联盟站点在发送登录请求和认证站点进行请求验证的时候用户信息的存储位置。</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>还包括两个方法，分别为： </p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 248px;">
    <col style="width: 284px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">方法名</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义和作用</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Add</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">添加新的联盟站点。</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Validate</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">验证联盟对象是否已经存在</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<h2>3.2功能 </h2>
<p>该接口能在认证中心完成新联盟站点添加操作，添加之前可以验证站点是否存在。 </p>
<h2>3.3 默认实现 </h2>
<p style="margin-left: 22pt;">在SSO组件中，已经实现了一个默认的ISite对象。为DefaultServer/
DefaultSite.cs，它将放置在认证中心根目录下的sites.config文件作为存储介质，通过Add方法添加新联盟站点后的效果为：附件中的site.config文件，可自行下载文件后，看其结构。
</p>
<p>&nbsp;</p>
<p style="margin-left: 22pt;">&nbsp;</p>
<h1>4 IUser接口设计说明 </h1>
<h2>4.1接口描述 </h2>
<p>IUser接口包括2个属性和2个方法，用于在认证中心端描和操作述联盟用户。 </p>
<p><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO4.png" />
</p>
<p>其中，各个属性的含义如下 </p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 154px;">
    <col style="width: 189px;">
    <col style="width: 189px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">属性名称</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">类型</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Uid</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">用户编号，是用户的标识</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Pwd</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">用户密码</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>还包括两个方法，分别为： </p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 248px;">
    <col style="width: 284px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">方法名</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义和作用</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Validate</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">验证用户是否存在</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Register</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">添加新用户</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<h2>4.2功能 </h2>
<p>该接口能在认证中心完成新联用户添加操作，添加之前可以验证用户是否存在。 </p>
<h2>4.3 默认实现 </h2>
<p style="margin-left: 22pt;">在SSO组件中，已经实现了一个默认的IUser对象。为DefaultServer/
DefaultUser.cs，它将放置在认证中心根目录下的users.config文件作为存储介质，通过Register方法添加新联盟用户的效果为：附件中的users.config文件，可自行下载文件后，看其结构。
</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1>5 IUserLoginList接口设计说明 </h1>
<h2>5.1接口描述 </h2>
<p style="margin-left: 22pt;">IUserLoginList接口包括3个方法，用于在认证中心描述和操作用户登录的站点清单。 </p>
<p><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO5.png" />
</p>
<p>还包括三个方法，分别为： </p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 248px;">
    <col style="width: 284px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">方法名</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义和作用</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Add</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">验证用户是否存在</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">GetLoginSites</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">获取用户的登录站点清单</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">DeleteUser</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">删除用户的登录站点清单数据</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<h2>5.2功能 </h2>
<p>该接口在认证中心用于用户记录和维护用户登录的站点清单&nbsp;&nbsp;</p>
<h2>5.3 默认实现 </h2>
<p style="margin-left: 22pt;">在SSO组件中，已经实现了一个默认的IUserLoginList对象。为DefaultServer/
UserLoginLog.cs，它通过一个Collection对象来实现用户登录站点清单的维护工作。 </p>
<p style="margin-left: 22pt;">&nbsp;</p>
<p style="margin-left: 22pt;">&nbsp;</p>
<h1>6 IServer接口设计说明 </h1>
<h2>6.1接口描述 </h2>
<p style="margin-left: 22pt;">IServer接口包括2个属性和5个方法，用于接收，验证登录请求，发送登录答复，接搜，验证登出请求，创建本地登录票据，维护用户登录清单。
</p>
<p><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO6.png" />
</p>
<p>两个属性为： </p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 154px;">
    <col style="width: 189px;">
    <col style="width: 189px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">属性名称</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">类型</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Site</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">ISite</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">当前上下文处理请求和答复的站点对象</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Uid</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">当前处理的上下文中的用户编号</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>&nbsp;</p>
<p>还包括三个方法，分别为： </p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 248px;">
    <col style="width: 284px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">方法名</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义和作用</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">CheckUser</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">验证用户对象是否存在</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">CheckExistToken</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">验证登录票据已经存在</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">SaveToken</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">在认证中心本地保存登录票据</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Jump</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">通过url跳转，发送登录答复</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">LogOut</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">统一登出。</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<h2>6.2功能 </h2>
<p style="margin-left: 22pt;">该接口在认证中心，用于接收，验证登录请求，发送登录答复，接搜，验证登出请求，创建本地登录票据，维护用户登录清单
</p>
<h2>6.3 默认实现 </h2>
<p style="margin-left: 22pt;">在SSO组件中，已经实现了一个默认的IServer对象。为DefaultServer/
LoginRequest.cs。 </p>
<p style="margin-left: 22pt;">&nbsp;</p>
<p style="margin-left: 22pt;">&nbsp;</p>
<h1>7 ILoginRequest接口设计说明 </h1>
<h2>7.1接口描述 </h2>
<p style="margin-left: 22pt;">ILoginRequest接口包括2个属性，用于记录和描述联盟站点的登录请求，这些信息在发出登录请求的时候创建，在收到登录答复的时候销毁。用于确保登录答复的不可复用性。
</p>
<p><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO7.png" />
</p>
<p>两个属性为： </p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 154px;">
    <col style="width: 189px;">
    <col style="width: 189px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">属性名称</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">类型</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Identity</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">登录请求标志符，该标志符会发送给服务端，服务端在发送登录答复的时候会回传该标志，联盟站点会根据此标志来验证请求是否是伪造的。</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">TimeStamp</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">DateTime</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">请求的时间戳</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<h2>7.2功能 </h2>
<p style="margin-left: 22pt;">该接口在联盟站点，用于记录和描述联盟站点的登录请求，这些信息在发出登录请求的时候创建，在收到登录答复的时候销毁。用于确保登录答复的不可复用性。7.3
默认实现 </p>
<h2>7.3 默认实现 </h2>
<p style="margin-left: 22pt;">在SSO组件中，已经实现了一个默认的ILoginRequest对象。为DefaultServer/
LoginRequest.cs。 </p>
<p style="margin-left: 22pt;">&nbsp;</p>
<h1>8 ILoginRequestContainer接口设计说明 </h1>
<h2>8.1接口描述 </h2>
<p style="margin-left: 22pt;">ILoginRequestContainer接口包括3个方法，用于在联盟站点中记录和维护登录请求
</p>
<p style="margin-left: 22pt;"><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO8.png" />
</p>
<p>&nbsp;</p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 248px;">
    <col style="width: 284px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">方法名</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义和作用</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Add</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">添加登录请求信息</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Check</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">检查登录请求是否存在</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Remove</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">销毁存在的登录请求</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<h2>8.2功能 </h2>
<p style="margin-left: 22pt;">该接口在联盟站点，用于在联盟站点中记录和维护登录请求 </p>
<h2>8.3 默认实现 </h2>
<p style="margin-left: 22pt;">在SSO组件中，已经实现了一个默认的ILoginRequestContainer对象。为DefaultServer/
LoginRequestContainer.cs。 </p>
<p style="margin-left: 22pt;">&nbsp;</p>
<h1>9 IUserStateContainer接口设计说明 </h1>
<h2>9.1接口描述 </h2>
<p style="margin-left: 22pt;">IUserStateContainer接口包括5个方法，用于在联盟站点中记录和维护在线联盟用户信息
</p>
<p style="margin-left: 22pt;"><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO9.png" />
</p>
<p>&nbsp;</p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 248px;">
    <col style="width: 284px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">方法名</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义和作用</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Add</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">添加登录用户</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">GetList</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">获取在线用户清单</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Check</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">检查某个用户是否已经在线</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Remove</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">移除某个在线用户。</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">GetUserCount</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">获取在线用户个数</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<h2>9.2功能 </h2>
<p style="margin-left: 22pt;">该接口在联盟站点，用于在联盟站点中记录和维护在线联盟用户信息 </p>
<h2>9.3 默认实现 </h2>
<p style="margin-left: 22pt;">在SSO组件中，已经实现了一个默认的IUserStateContainer对象。为DefaultServer/
UserState.cs。 <br />
</p>
<h1>&nbsp;</h1>
<h1>&nbsp;</h1>
<h1>10 IClient接口设计说明 </h1>
<h2>10.1接口描述 </h2>
<p style="margin-left: 22pt;">IClient接口包括6个属性和2个方法，用于发出登录请求和登出请求 </p>
<p style="margin-left: 22pt;"><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/013108_1233_SSO10.png" />
</p>
<p>8个属性为： </p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 154px;">
    <col style="width: 189px;">
    <col style="width: 189px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">属性名称</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">类型</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">SiteID</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">站点编号</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">PrivateKey</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">数据交换时加密或者签名用的公钥</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">LoginAddress</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">认证中心登录地址</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">LogoutAddress</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">认证中心登出地址</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Uid</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">登录的用户编号</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">TimeOut</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">int</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">登录答复的超时时间，单位s</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">UidField</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">登录登出请求中的用户信息的存储位置</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">FromUrlField</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">string</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">登录请求中的来源网址存储位置</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>2个方法为 </p>
<div style="margin-left: 26pt;">
<table style="border-collapse: collapse;" border="0">
    <colgroup>
    <col style="width: 248px;">
    <col style="width: 284px;"></colgroup>
    <tbody valign="top">
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">方法名</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">含义和作用</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">Login</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">发出登录请求，并处理登录答复</span></p>
            </td>
        </tr>
        <tr>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">LogOut</span></p>
            </td>
            <td style="padding-right: 7px; padding-left: 7px;">
            <p><span style="font-size: 10pt;">登出</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<h2>10.2功能 </h2>
<p style="margin-left: 22pt;">该接口在联盟站点，用于发出登录请求和登出请求 </p>
<h2>10.3 默认实现 </h2>
<p style="margin-left: 22pt;">在SSO组件中，已经实现了一个默认的IClient对象。为DefaultServer/
DefaultClient.cs </p>
<p style="margin-left: 22pt;">&nbsp;</p>
<h1>11 本系统的安全性 </h1>
<h2>11.1 登录请求的格式 </h2>
<p>联盟站点向认证中心发送的登录请求格式如下： </p>
<p>站点信息+登录请求编号+时间戳+空用户信息+对站点信息和登录清秋号的签名信息。<br />
除了签名信息之外的全部信息均为明文传送，但因为重要的数据均经过数字签名，结果是站点信息和登录请求编号是不能被篡改的，保证了认证中心收到的登录请求的真实性。
</p>
<h2>11.2 登录答复的格式 </h2>
<p>认证中心发给联盟站点的登录答复格式如下 </p>
<p>登录用户信息+登录请求编号+时间戳+对用户信息和登录请求号和时间戳的签名信息<br />
其中登录用户信息是经过非对称加密的。请求号和时间戳因为经过签名，故也不能篡改，这样就可以保证联盟站点收到的登录答复的真实性和完整性。并且非正常联盟站点无法解密用户信息，也无法从中获取好处。&nbsp;&nbsp;</p>
<p><strong>篇幅太大，下面还有很长的内容要说，先发布以下，感兴趣的朋友可以先下载程序尝试使用。以后，我会逐渐添加Sql 和
Oracle的实现。您也可以根据接口规范，开发符合自己系统需求的SSO系统，今天先到这吧<br />
<br />
程序文件：<a href="/Files/jillzhang/SSO.rar">/Files/jillzhang/SSO.rar</a><br />
</strong></p>
<p><br />
<span style="color: red;"><strong style="font-size: 18pt; font-family: 微软雅黑;">更新：新增登录流程图：<br />
<br />
</strong></span><a class="postTitle2" id="AjaxHolder_ctl01_TitleUrl" href="http://www.cnblogs.com/jillzhang/archive/2008/02/01/1061212.html">[原创]单点登陆(SSO)组件的设计与实现二-登录流程图</a>&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/images/cnblogs_com/jillzhang/sso_login2.jpg" border="0" height="150" width="160" /></p>
<br />
<p><br />
</p>
<br />
<p><br />
</p>
<br />
<p><br />
</p>
<p><br />
<span style="color: red;">新增登出流程图 2008-02-02</span><br />
<br />
<img alt="" src="http://www.blogjava.net/images/cnblogs_com/jillzhang/sso_login2.jpg" border="0" height="796" width="781" /><br />
<br />
上面是整体流程图，这个SSO组件在安全上有了很充分的考虑，可以说是非常安全，那么下面看看登录请求数据的格式，和为何它能保证真实性和完整性<br />
<br />
<img alt="" src="http://www.blogjava.net/images/cnblogs_com/jillzhang/sso_loginrequest4.jpg" border="0" height="812" width="730" /><br />
<br />
这样，当数据在传输过程中，如果站点编号，用户编号，请求号任意一项做任何的修改，当认证中心接收到数据之后，均无法与签名信息进行匹配。凡是认证中心能验证通过的请求均为合法的，真实的，完整的请求信息。<br />
<br />
登录答复的格式如下图所示<br />
<img alt="" src="http://www.blogjava.net/images/cnblogs_com/jillzhang/sso_loginresponse3.jpg" border="0" height="861" width="726" /><br />
因为登录号，时间戳，用户信息均加入数字签名信息，所以这些数据在传输中不能被伪造和篡改，而用户信息经过非对称性加密，也防止非真正请求发送者能解析出用户信息，这样在接受和发送请求和响应的时候，就实现了绝对的安全。<br />
当然不是没有破绽，破绽在于当请求答复未到达联盟站点之前，有人截获并先于正常用户登录了联盟站点，此时我们可以将用户的ip信息作为答复数据的一部分，加入签名，以此实现很高的安全保证<br />
<br />
登出流程图<br />
<img alt="" src="http://www.blogjava.net/images/cnblogs_com/jillzhang/sso_logout.jpg" border="0" height="820" width="720" /> <br />
</p>
<br />
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/184540.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2008-03-07 16:36 <a href="http://www.blogjava.net/jinfeng_wang/archive/2008/03/07/184540.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>大嘴日语的破解</title><link>http://www.blogjava.net/jinfeng_wang/archive/2007/04/10/109767.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Tue, 10 Apr 2007 14:58:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2007/04/10/109767.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/109767.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2007/04/10/109767.html#Feedback</comments><slash:comments>44</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/109767.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/109767.html</trackback:ping><description><![CDATA[<p>&nbsp;<br>最近想要一个背单词的软件<br><br>自己做一个容易，词库比较麻烦。<br><br>在网上找啊找，都没啥特别好用的<br><br>后来就盯上了《大嘴日语》<br><br>从大嘴2.0开始，就没有破解版可以下载<br>（自己也是做软件的，还想破解别人的免费用，sigh）<br><br>下了个最新的6.0 和可以破解的2.0<br><br>来回把词库拷贝，居然发现大嘴用的的DBISAM文件数据库<br><br>不厚道的找东西，破解<br><br>不厚道的来回倒腾数据，现在词库已经在我的Access中了。<br><br>对于我来说，数据才是重要的。<br>TTS，其他功能，都是可以做出来的。<br><br>软件的漏洞到底在哪儿？<br><br>怎么确保软件没有漏洞？<br><br>大嘴从2.0到7.0，做足了加密功夫，一直没有破解版流出，<br><br>竟然还有这么大的一个后门。<br><br>不得不值得好好的思量一番周边软件的质量。<br><br>参见：<a href="http://www.blogjava.net/jinfeng_wang/archive/2007/02/14/99819.html">http://www.blogjava.net/jinfeng_wang/archive/2007/02/14/99819.html</a><br><br>btw: 个人研究，不算盗版吧 ^_^<br></p>
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/109767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2007-04-10 22:58 <a href="http://www.blogjava.net/jinfeng_wang/archive/2007/04/10/109767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>人员、资源、操作及这三者构成的权限控制</title><link>http://www.blogjava.net/jinfeng_wang/archive/2007/02/14/99819.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Wed, 14 Feb 2007 06:53:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2007/02/14/99819.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/99819.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2007/02/14/99819.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/99819.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/99819.html</trackback:ping><description><![CDATA[Web系统因为是面向Internet/Intranet的，所以其安全性比常规的应用程序系统更难以保证。<br /><br />在谈到其安全性的时候，很多的都是从“网络安全”的角度去看待问题，殊不知，堡垒<br />的内部是最最不安全的。对付“黑客攻击”是系统管理员所要面对的问题，而如何更好的<br />加强堡垒内部自身的安全，是在Web程序的设计中就需要考虑的问题。<br /><br />系统管理员所要面对的网络攻击、操作系统 安全不是我所考虑的问题，如何加强Web系统<br />自身的健康是我所最最关心的事情。 <br /><br />从“构造URL”攻击到“注入SQL文”攻击，都是属于过分信任用户输入，而造成的安全问题。<br />这恰恰应该是由应用程序自身加以重视、解决的问题。<br /><br />基于角色的安全控制已经逐渐的被大家逐渐的接受，每个用户被分配为不同的角色，不同的角色<br />具有不同的操作权限。 但是如何划分角色、用户、操作权限，则是需要认真对待的问题。<br /><br />举例：<br />一个MIS系统中，员工有查询工资的权限，但是某个员工是否具有查询其他员工的权限呢？<br /><br />不能深入的追问问题，详细的分辨清楚系统中到底有多少角色、每个用户所在的角色，是不能完成安全控制的。<br /><br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000"><br /><font color="#0000ff" size="5"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />btw: 以上的问题，大家不妨在自己的类似系统中自己去检查一下，有此问题的占绝大多数吧。<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />看过此文的，愿意回答“是”“否”的，可以留言， 也当作一个调查吧。</font><br /></span></div><br /><br />上面的这个例子，就是一个很成熟的办公系统中存在的问题。使用客户端script脚本，控制了用户的界面操作，殊不知maxthon就可以解除这个限制。此系统中，用户的请求都被整理为URL（get方式提交），虽然URL中的键值含义并不是很明显，但是还是可以尝试着去攻击，获取秘密。<br /><br />认真的核查用户的输入，利用AOP部署，细密的对用户的输入进行核查，是很有必要的事情。<br /><br />某个人、某个资源、某个操作，这三个要素组织在一起则是：某个人对某个资源进行某项操作<br />实际情况下，许多人、许多资源、对每个资源冰存在着多个操作。<br /><br />将人、资源、操作进行划分，可以得到：<br />具体的某一类人，可以对某些资源，进行某些的操作＝》 这就是具体的某项权限限制。<br />    某一类人，则可以归纳为角色。<br />    对某些资源的某些操作，则可以归纳为工作任务。<br />也就是说，整个系统是“某个角色去完成某些工作任务，而具体的一个帐户属于某个角色，某项工作则具体的是指对某个资源进行某个操作”。<br /><br />相对来说，系统中的人员是最容易辨认的，系统中的资源也是可以在系统的功能调查时分清楚的，系统中的操作则是最复杂、最难分清晰，甚至在系统完成时都会变化的。<br /><br />只有分辨清楚了系统中的人、资源、操作，才能辨别清楚系统中的具体的权限限制。<br /><br />“基于角色的安全控制”这样的提法，只提及了人，未能强调将资源、操作进行规类，这是很不充分的一种提法。<br /><br />在Web系统中，系统在设计的过程中，就分清楚资源，分清楚操作，极大缩小每个页面的功能、提高页面功能的原子性，这也是权限控制对系统设计提出的一项要求。<br /><br />前面提及使用AOP进行权限控制，现在简述一下各部件的功能：<br />   业务模块－－完成具体的对某个资源的操作；<br />   前台页面模块－－ 完成整体页面的整合；<br />   安全控制模块－－实现安全控制功能，完成人员、角色、工作的逻辑判断；<br />   AOP配置整合模块－－粘合安全控制模块和业务模块；<br /><br /><br />在于如何去解决，而是如何去发现。隐藏起来的问题更是危险。<br /><br />而如何发现问题，则完全是一个素质、能力的事情，也许这是下一个话题。<br /><img src ="http://www.blogjava.net/jinfeng_wang/aggbug/99819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2007-02-14 14:53 <a href="http://www.blogjava.net/jinfeng_wang/archive/2007/02/14/99819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>buying  notbook</title><link>http://www.blogjava.net/jinfeng_wang/archive/2007/02/02/97420.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Fri, 02 Feb 2007 01:21:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2007/02/02/97420.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/97420.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2007/02/02/97420.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/97420.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/97420.html</trackback:ping><description><![CDATA[标  题: 中海购T40手记<br />发信站: 水木社区 (Fri Feb  2 00:30:29 2007), 站内<br /><br />本来看中的是nc6000,觉得性价比不错，但是昨天mm转了一圈之后，就定在了T40上<br /><br />中午11点半从东门出发，骑车<br />先去北大南门吃饭，不表<br />到太平洋买了一块三星银盘+盘盒：470 + 50 = 520<br />将近1点了，：）<br /><br />中海小传一圈，回到580柜台，T40摆了好几台，分两种<br />一种就是迅驰1.5G/512M/40G/DVD/ATI 7500 32M/   3800<br />另外一种多了蓝牙、无线，光驱是DVD-CDRW  4000<br />同时问了nc6000的价格，高分才3500<br /><br />蓝牙没用，CDRW也没用，就是奇怪为什么迅驰还不带无线网卡<br />加网卡还要另收50，讲价未果，于是不要网卡了，反正暂时用不到<br /><br />开始挑机器，只摆了4台第一种机器<br />让老板再拿出几台，被告知只有这几台，感觉必然说谎阿<br />没办法，埋头挑<br /><br />先看屏幕，把亮度都调到最高，开始对比<br />有一台的屏幕很亮，但是用手按水波纹很严重<br />还有一台屏幕发黄，直接淘汰<br />最后选了一台水波纹不是很明显的，但是显示的颜色不是很鲜艳，没有第一台的颜色正，显得有点灰灰的<br /><br />键盘都不错，不油<br /><br />继续，因为赶时间回实验室有事，很多没很仔细测<br />ntest看屏，没看出什么问题，也许是自己太菜吧<br />erest看配置，符合<br />cpu-z看cpu和内存，发现两条内存牌子不一样，一个英飞铃，一个金士顿，让老板给换成一样的，于是老板把另外一个机器拆开，找到一条英飞铃，给我按上。在另外一台机器上看内存，发现竟然还有现代的。<br />super-pi计算100万，用了1分04秒，另外一台用了1分39秒。测了3200位的，初始化用了39秒，没继续，回来也没全测完，明天测一下<br />mentest测内存，测了200%多<br />hdtune测硬盘，没问题<br /><br />试了一下光驱，发现读CD的时候还很安静，但是读DVD（找了一个划的比较厉害的）的时候风扇就响的利害了，没办法，说风扇没法换，我也不懂，忍了<br /><br />看电池，只有两台机器有电池，于是到带蓝牙的机器上拿了一块用过25次的，可是健康状况显示差。不懂。那掉电源显示还能用1小时，另外一个用过118次，将看情况显示良好，但是显示只能用44分钟。拿了第一块<br /><br />这里发现一个问题，拔掉电源屏幕会闪，而且每个机器都是这样，不知道会有什么隐患。不爽的是我挑的这台屏幕黑的时间比别的长，大牛给分析一下。<br /><br />又看了看bios，对比了一下序列号，没啥问题。别的也不知道看啥了<br /><br />关机，换上80G的硬盘，把40G的换到移动硬盘盒里<br />看了一下机器外观，发现上盖上有条划痕，我忍<br />让老板给擦了擦机器<br />送一个包，好烂<br />一个IBM小鼠<br /><br />说声谢谢，然后走人，被叫回来，忘了给钱了，：）<br /><br />回来测了3DMARK，4004分<br />大牛说说，我还需要做些什么测试？机器可能有些什么问题？<br />争取3天内解决出现的问题。<br /><br />over<br />菜鸟第一次在中海买东西，多谢一勺等大牛的帖子指导<br />欢迎点评<br /><br /><br />＝＝＝＝＝＝＝＝＝＝<br />sp2004使劲跑一晚上<br /><br /><img src ="http://www.blogjava.net/jinfeng_wang/aggbug/97420.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2007-02-02 09:21 <a href="http://www.blogjava.net/jinfeng_wang/archive/2007/02/02/97420.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MindManager6使用体会</title><link>http://www.blogjava.net/jinfeng_wang/archive/2007/01/27/96267.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Sat, 27 Jan 2007 05:45:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2007/01/27/96267.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/96267.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2007/01/27/96267.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/96267.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/96267.html</trackback:ping><description><![CDATA[过年放假的一个好处就是，终于可以比较悠闲的靠在床上，随便想想该写些什么。
<p>　　在这篇<a href="http://herock.net/archives/000161.html">MindManager的免费阅读器</a>后面，<a href="http://blog.94smart.com/">94smart</a>等朋友热情怂恿我写一篇教程，今天准备试着写一点儿，不过不能算是教程，只是浮光掠影，介绍一下在使用中曾给我带来惊喜的几个亮点而已。</p><p>　　一直希望有一个电子化的工具能够方便、形象的整理头脑中漫无边际的杂乱想法，就像铅笔和白纸能够做到的那样，但是又能避免写满东西的白纸不易传播和保存的缺点。</p><p>　　最初通过一些<a href="http://www.outgo.cn/blogview.asp?logid=16">介绍文章</a>，看到了<a href="http://freemind.sourceforge.net/wiki/index.php/Main_Page">FreeMind</a>，著名的开源free思维管理工具，优势是明显的，比如： 
</p><ol><li>跨平台。除了Windows之外，也提供了Mac OS X、Linux等版本，实际上，它支持所有的操作系统。<br /></li><li>免费使用。不需要任何破解和注册码之类，可以心安理得的不花钱永远使用它。<br /></li><li>功能比较强大，基本的思维导图应该具备的功能都有，也可以发布到web上。<br /></li><li>轻便小巧，但是可定制程度依然很好，当然这是针对那些动手能力较高的用户而言，对我这样不会写代码的人，这个方面的特性并不在考虑之列。</li></ol><p></p><p>　　使用的时候需要先安装java的运行库，有点麻烦，而且关键是有一些操作方式，个人感觉不太顺手，导致思路频频被打断，被迫开始摸索使用的方法，这样对于一个普通的使用者来说，学习的时间成本便上升了，后来不得不尝试了商业软件－<a href="http://www.mindjet.com/">MindManager</a>，这款软件并不开源，也不能跨平台，只支持Windows这一家系统，但是由于很好的迎合了windows软件的操作方式，大大降低了熟稔windows软件用户的学习成本，更和office系列软件做到了紧密整合，数据在其中流动非常顺畅。</p><p>　　第一个令我激动的MindManager应用就是Web2.0周刊的制作，我当时的需要就是每天用最简单的方法收集相关信息，包含链接、笔记或评论、分类等信息，在周末的时候统一整理一下，直接输出相应的html页面，可以上传到服务器上供访问，MindManager刚好可以近乎完美的实现，（<a href="http://web2week.com/magazine/4-sep4-10/">这里</a>可以看到实际效果）我只需要自己写一下css，用来保证最终的html页面以我想要的样式呈现，其它的html代码，就无需我操心，全部由MindManager代劳了。想尝试一下这个功能的话，可以在"File"--"Export"--"Save as Webpages..."中找到。</p><p><img src="http://www.mindjet.com/images/eng/homepage_header.gif" /></p><p>　　实际上无需什么教程，安装完MindManager之后，“help”和"Learning Center"都是非常棒的使用教程，而且后者还是直观的视频模式，快速浏览一下，就可以对MindManager这款软件有大致的了解了。</p><p>　　在“Learn More”中的“提示和技巧”使用了MindManager的格式来展示，很有意思，在这里可以学到“生成图片格式”、“格式编排”、“浏览导图”、“编辑技巧”等方面的知识。</p><p>　　MindManager6分为基础版和专业版，两个版本共有的一些新特性包括： 
</p><ol><li>大纲编辑模式。"view"--"outline"<br /></li><li>制表制图。"topic"--"Spreadsheet"<br /></li><li>组织结构图布局，可用来展示团队和公司的组织结构。"format"--"topic..."之后选择"Subtopics Layout"的标签，然后选择"Org-Chart"<br /></li><li>输出到powerpoint。"format"--之后选择"Microsoft PowerPoint Slides..."<br /></li><li>从IE导入。如果使用IE的话，可以通过点击工具栏的按钮添加某个网页的标题和链接到MindManager中自动生成一个topic。<br /></li><li>支持掌上电脑手写笔记及大纲。"topic"--"notes"以及"view"--"outline"<br /></li><li>分类线，可以把同类的topics用一条线划到一起，以示区别。<br /></li><li>自动编号。"Format"--"Numberling..."<br /></li><li>自动平衡,可以重新摆放topic的位置，使其看起来更协调。"view"--"balance map"<br /></li><li>note中的拼写检查。"topic"--"notes"<br /></li><li>特别的粘贴。可以选择需要以何种格式粘贴剪贴板中的内容。"edit"--"paste special"</li></ol><p></p><p>　　而只在MindManager6专业版中才有的特性如下： 
</p><ol><li>导出到visio。"format"--"Microsoft Visio Stencils...","File"--"export"--"Microsoft Visio Export"<br /></li><li>链接到excel表格。"insert"--"Microsoft Excel Range..."<br /></li><li>插入附件。"file"--"Add Attachment..."<br /></li><li>超强过滤器。"edit"--"filter"-"power filter"<br /></li><li>超强选择。"edit"--"select"--"power edit"<br /></li><li>自定义属性。"topic"--"Custom Properties..."<br /></li><li>加入书签。"topic"--"bookmark"<br /></li><li>评论模式，可以区分别人所作的评论，并方便的拒绝或者接受。"tools"--"start review"<br /></li><li>闹钟提示。"topic"--"alert..."<br /></li><li>文本记号。希望和你进行对话的使用者可以在你制作到导图上使用文本记号（text marker），标记出他们的意见。"topic"--"test marker"<br /></li><li>记时器。"tools"--"timer"<br /></li><li>标签。"topic"--"label..."</li></ol><p></p><p>　　如果你主要使用Windows系统工作，而且office也始终在你的电脑中占有一席之地，最后，你也不在乎花一些美刀或者勇于想办法不花这些美刀，来得到一个真正强大、全能的思维导图工具的话，选择MindManager pro 6吧，应该不会后悔。</p><img src ="http://www.blogjava.net/jinfeng_wang/aggbug/96267.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2007-01-27 13:45 <a href="http://www.blogjava.net/jinfeng_wang/archive/2007/01/27/96267.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>测试的全路经覆盖</title><link>http://www.blogjava.net/jinfeng_wang/archive/2007/01/05/91877.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Thu, 04 Jan 2007 17:20:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2007/01/05/91877.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/91877.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2007/01/05/91877.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/91877.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/91877.html</trackback:ping><description><![CDATA[
		<p>
				<br />在Junit/Nunit测试出现之后，出现了一个工具Jcover/Ncover,此工具代码覆盖率分析工具，可以分析测试代码的测试范围的覆盖率。<br /><br />第一次知道此工具的时候，相当的兴奋，因为这样可以轻松的把握项目中的测试代码情况。在看到自己的每行代码都被测试之后，相当的幸福啊，再加上Maven等工具可以自动连跑，那是足够保证了单元测试的覆盖率了啊。<br /><br />正是因为不假思索的信任，导致了问题的出现：Cover工具的覆盖，是代码行的覆盖，而不是代码Step的覆盖。所谓的代码行，是指代码中可以被执行到的具体某物理行，但是Step则是指每一步逻辑。对于if (a==b||c==d||e==f)这样的判断，应该是有三个step在其中的。正是由于信任了Cover工具，导致代码覆盖率不够，未能测试到e==f的判断，导致了一个bug在最后才被发现。问题发现的越迟，付出的代价越大。</p>
		<p>上面已经说明了全路径覆盖的含义（目前Cover工具无法达到的功能），那么全路径覆盖是不是很有必要且一定要的呢？答案是“YES”.做到全路径覆盖的测试是很痛苦的一件事情，但是，当你从全路径覆盖中找到重大问题时，才会回头来看“如果我做了全副该测试，这段路径的错误逻辑就不会出现的”。</p>
		<p>就拿上篇"CheckedException VS UncheckedException"中的例子，当代码结构逐渐演化为多出入口调用C模块时，“C处不能决定具体的出错信息”。但是在代码中，如果恰恰就是在"C处误认为可以决定错误消息"时，对于这个“误操作”，就可以通过全路径覆盖发现这个问题。if(a==b||c==d||e==f) {throw new MyException("error msg.")}，这样的一行代码，需要面对三种问题去报出错信息，其负担太重，情况复杂（然后有了错误代码）。</p>
		<p>如果做了全路径覆盖，可以走到（e==f）的判断，此时即可发现错误消息不正确的问题。</p>
		<p>如何才能保证完成全路径覆盖呢？<br />1）手工debug跟踪，保证每一步都走到，对于最后的(e==f)，跟踪的好辛苦阿，创造这样的条件（走到e==f）就好累的。<br />2）利用Ncover的功能，对于这样的复杂逻辑，手工进行debug跟踪。<br />3)拆开代码，为三行（每个step为单独的一行），利用NCover自动分析。 哈，老师教过的"，不允许出现过于复杂的代码"这个原则被发挥到极致了。</p>
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/91877.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2007-01-05 01:20 <a href="http://www.blogjava.net/jinfeng_wang/archive/2007/01/05/91877.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>错误处理的恢复</title><link>http://www.blogjava.net/jinfeng_wang/archive/2006/07/10/57571.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Mon, 10 Jul 2006 14:52:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2006/07/10/57571.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/57571.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2006/07/10/57571.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/57571.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/57571.html</trackback:ping><description><![CDATA[错误处理的恢复一直是容易被恢复的问题，<br />一个状态机中，出现错误的时候，一定要及时地修正状态机的状态。<br />上面的一句话可能是很容易理解的一句话，<br />但是在实际运用中，如何去真的体会到状态机的存在，及时进行错误恢复<br />却不是一件很容易能够做到的事情。<br /><br />之所以在“.NET C#中使用Unchecked Exception”，很大的一个原因--“很多时候是用户是没法去做错误修复的”，这真的是很奇怪的一个理由，而且这个理由竟然被很多人相信了。<br /><br />今天才意识到错误处理的恢复是自己没有遇到的一个重要的问题，胆战心惊！<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/57571.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2006-07-10 22:52 <a href="http://www.blogjava.net/jinfeng_wang/archive/2006/07/10/57571.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ADO.NET Connection Status Map</title><link>http://www.blogjava.net/jinfeng_wang/archive/2006/06/03/50173.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Sat, 03 Jun 2006 13:35:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2006/06/03/50173.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/50173.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2006/06/03/50173.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/50173.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/50173.html</trackback:ping><description><![CDATA[
		<img src="http://www.blogjava.net/images/blogjava_net/jinfeng_wang/6626/r_ConnectionStatus.JPG" />
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/50173.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2006-06-03 21:35 <a href="http://www.blogjava.net/jinfeng_wang/archive/2006/06/03/50173.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Checked Exception VS UnChecked Excetion (续2)</title><link>http://www.blogjava.net/jinfeng_wang/archive/2006/06/03/50170.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Sat, 03 Jun 2006 13:22:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2006/06/03/50170.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/50170.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2006/06/03/50170.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/50170.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/50170.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal">
				<span style="font-family: &quot;ＭＳ 明朝&quot;;" lang="ZH-CN">　　</span>
				<span style="font-family: SimSun;" lang="ZH-CN">假设我的团队正在开发一个库程序，由于某种原因，现在希望能够得到所有最外层</span>
				<span style="" lang="EN-US">API</span>
				<span style="font-family: SimSun;" lang="ZH-CN">所抛出的所有异常的类型、各自的信息、并且能够附上各种异常所出现的原因和解决办法。如果开发过程中内部使用的是</span>
				<span style="" lang="EN-US">Unchecked
Exception</span>
				<span style="font-family: SimSun;" lang="ZH-CN">，那么对于这个任务简直就麻烦了。没办法，开发人员一个个的自我进行检查然后统计吧，但是往往这样的统计总会有漏网之鱼。现在的</span>
				<span style="" lang="EN-US">MSDN</span>
				<span style="font-family: SimSun;" lang="ZH-CN">中的异常信息糟糕的很，最底层的公有库的异常信息内容可能完整一点，但是上层的库的异常信息糟糕的不行，根本不能完整的报全所有出错的可能性。</span>
				<span style="" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="text-indent: 21pt;">
				<span style="font-family: SimSun;" lang="ZH-CN">你可以想象的出，一个库函数的异常信息不完整，对于他的用户来说，是多么不友好的事情。假设</span>
				<span style="" lang="EN-US">MSDN</span>
				<span style="font-family: SimSun;" lang="ZH-CN">中</span>
				<span style="" lang="EN-US">File.Open()</span>
				<span style="font-family: SimSun;" lang="ZH-CN">会抛出</span>
				<span style="" lang="EN-US">IOException</span>
				<span style="font-family: SimSun;" lang="ZH-CN">，你的程序就很难想到很规矩的对</span>
				<span style="" lang="EN-US">IOException</span>
				<span style="font-family: SimSun;" lang="ZH-CN">做了</span>
				<span style="" lang="EN-US">catch</span>
				<span style="font-family: SimSun;" lang="ZH-CN">，然后提示用户检查相应位置的文件是否存在</span>
				<span style="" lang="EN-US">/</span>
				<span style="font-family: SimSun;" lang="ZH-CN">被打开等。别指望</span>
				<span style="" lang="EN-US">MSDN</span>
				<span style="font-family: SimSun;" lang="ZH-CN">的那些信息能够对终端用户有多大的帮助，太多不懂计算机的人在傻呆呆的握着鼠标了。再加上</span>
				<span style="" lang="EN-US">MicroSoft</span>
				<span style="font-family: SimSun;" lang="ZH-CN">的提示信息本身就存在着“答非所问”，“莫名其妙”的事情，用户看到这些情况就更不知道怎么解决问题了。再加上自己的应用程序中会弹出一个个“蹩脚”的运行时错误的错误框，真的不是一个很如意的创作。</span>
				<span style="" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="" lang="EN-US">
						<span style=""> </span>
						<span style=""> </span>
						<span style=""> </span>
						<span style=""> </span>
				</span>
				<span style="font-family: SimSun;" lang="ZH-CN">但是，如果使用的是</span>
				<span style="" lang="EN-US">Checked Exception</span>
				<span style="font-family: SimSun;" lang="ZH-CN">，这时候编译器会强迫你的外部接口的异常相当的完整，最起码可以做到比</span>
				<span style="" lang="EN-US">MSDN</span>
				<span style="font-family: SimSun;" lang="ZH-CN">的异常类型齐整。</span>
				<span style="" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="" lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="" lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="" lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="" lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/50170.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2006-06-03 21:22 <a href="http://www.blogjava.net/jinfeng_wang/archive/2006/06/03/50170.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库驱动程序的测试需要注意的问题</title><link>http://www.blogjava.net/jinfeng_wang/archive/2006/05/28/48597.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Sun, 28 May 2006 07:52:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2006/05/28/48597.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/48597.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2006/05/28/48597.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/48597.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/48597.html</trackback:ping><description><![CDATA[
		<div>
				<font face="MS UI Gothic" size="2">
						<font color="#ff0000">1. 不要用TestCase的构造函数初始化Fixture，而要用<br />setUp()和tearDown()方法。</font>
				</font>
		</div>
		<div>
				<font face="MS UI Gothic" size="2">
						<font color="#ff0000">
								<br />
						</font>2. 不要依赖或假定测试运行的顺序，因为JUnit利用<br />Vector保存测试方法。所以不同的平台会按不同的<br />顺序从Vector中取出测试方法。 <br /><br /><font color="#ff0000"></font></font>
		</div>
		<div>
				<font face="MS UI Gothic" size="2">
						<font color="#ff0000">3. 避免编写有副作用的TestCase。例如：如果随后的<br />测试依赖于某些特定的交易数据，就不要提交交易数<br />据。简单的会滚就可以了。</font>
						<br />
				</font>
		</div>
		<div>
				<font face="MS UI Gothic" size="2">
						<font color="#ff0000">
								<br />  对于我们来说，有时是必须要提交，以至于有副作用的。</font>
				</font>
		</div>
		<div>
				<font face="MS UI Gothic" color="#ff0000" size="2">  例如：在执行“插入“后，数据库显然会多出一条数<br />据来。那么必须在随后每个测试自己消除自己的副<br />作用。</font>
		</div>
		<div>
				<font face="MS UI Gothic" color="#ff0000" size="2">  在这里，就是自己“再删除刚插入的数据”。（这时候<br />需要考虑到这个善后的工作不能自己就不能有副作用，</font>
		</div>
		<div>
				<font face="MS UI Gothic" color="#ff0000" size="2">  删除多了其他的数据）。</font>
		</div>
		<div>
				<font face="MS UI Gothic" color="#ff0000" size="2">
				</font> </div>
		<div>
				<font face="MS UI Gothic" color="#ff0000" size="2">  这里的副作用还指“影响到周围环境”，因为我们现<br />在工作的人比较多，所以最好大家的测试服务器能够<br />分开来，</font>
		</div>
		<div>
				<font face="MS UI Gothic" color="#ff0000" size="2"> 例如一个人一个Database实例（可以建得稍微小一<br />点）或者一个人一个数据库，</font>
				<font face="MS UI Gothic" color="#ff0000" size="2">  注意将这些个人之间<br />有区别的内容用常量在每个人自己的所有程序中公<br />用。而不是分布在各个位置。</font>
				<font face="MS UI Gothic" color="#ff0000" size="2">  否则以后要改换测试<br />服务器，所有的程序都需要改动。</font>
		</div>
		<div>
				<font face="MS UI Gothic" color="#ff0000" size="2">
				</font> </div>
		<div>
				<font face="MS UI Gothic" color="#ff0000" size="2">  为了保证测试程序能够很容易的到处执行，请保证<br />大家的数据库服务器的测试数据全部一致。</font>
				<font face="MS UI Gothic" color="#ff0000" size="2"> 否则，<br />就不能做到很容易得拿到FJ也可以很容易的运行，<br />所以需要准备“测试数据集“。</font>
				<font face="MS UI Gothic" color="#ff0000" size="2">包括：Schema ,table ，<br />stored procedure等数据库对象的结构一致，</font>
				<font face="MS UI Gothic" color="#ff0000" size="2"> 还包<br />括数据库的数据内容保持一致。</font>
		</div>
		<font face="MS UI Gothic" size="2">
				<div>
						<br />4. 当继承一个测试类时，记得调用父类的setUp()和<br />tearDown()方法。 </div>
				<div>
						<br />5. 将测试代码和工作代码放在一起，一边同步编译<br />和更新。（使用Ant中有支持junit的task.） </div>
				<div>
						<br />6. 测试类和测试方法应该有一致的命名方案。如在<br />工作类名前加上test从而形成测试类名。 </div>
				<div>
						<font color="#ff0000">可能这里我们需要改动，将函数名和我们的测试用<br />例的编号一致起来。</font>
				</div>
				<div>
						<br />7. 确保测试与时间无关，不要依赖使用过期的数据<br />进行测试。导致在随后的维护过程中很难重现测试。 </div>
				<div>
						<br />8. 如果你编写的软件面向国际市场，编写测试时要<br />考虑国际化的因素。不要仅用母语的Locale进行测试。 </div>
				<div>
						<br />9. 尽可能地利用JUnit提供地assert/fail方法以及<br />异常处理的方法，可以使代码更为简洁。 </div>
				<div> </div>
				<div>
						<font color="#ff0000">这个内容有其关键，assert语句的好坏直接影响<br />到测试的正确性。</font>
						<font color="#ff0000">因为assert就是用于当前测试<br />项的正确性的。</font>
				</div>
				<div>
						<br />10.测试要尽可能地小，执行速度快。 <br /><br /><br />==========<br />1）将所有的数据库的测试数据用ODBC程序自动<br />生成的。 <font face="MS UI Gothic" size="2">用户可以简单的</font><font face="MS UI Gothic" size="2">修改ConnectionString，<br />然后运行程序，就可以创建生成数</font><font face="MS UI Gothic" size="2">据库/数据库<br />表/存储结构</font><font face="MS UI Gothic" size="2">，并且自动插入数据。<br /></font><div><font face="MS UI Gothic" size="2"></font> </div><div><font face="MS UI Gothic" size="2">   2）为了保证多个测试人员的不干扰，建议分别<br />各自单独使用自己的数据</font><font face="MS UI Gothic" size="2">库。否则会因为一个自<br />己的错误，影响别人的工作。</font></div><div><font face="MS UI Gothic" size="2"></font> </div><div><font face="MS UI Gothic" size="2">   3）在自己的程序中，所有涉及环境的内容都用<br />单独放到一个类中，用static</font><font face="MS UI Gothic" size="2">常量共享使用（这样<br />就便于很容易的更换环境再进行测试，做到很容<br />易的移植</font><font face="MS UI Gothic" size="2">测试环境）。</font></div><div><font face="MS UI Gothic" size="2"></font> </div><div><font face="MS UI Gothic" size="2">   4）关于数据库表结构，我建议测试表中含有一<br />个主键，我们在插入数据的时</font><font face="MS UI Gothic" size="2">候，保证测试用例，<br />测试用例程序，测试用例程序中的数据，这三者<br />的编号一</font><font face="MS UI Gothic" size="2">致起来。便于出现问题时，可以排除数据。</font></div></div>
		</font>
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/48597.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2006-05-28 15:52 <a href="http://www.blogjava.net/jinfeng_wang/archive/2006/05/28/48597.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Checked Exception VS UnChecked Excetion (续)</title><link>http://www.blogjava.net/jinfeng_wang/archive/2006/05/12/45911.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Fri, 12 May 2006 12:21:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2006/05/12/45911.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/45911.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2006/05/12/45911.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/45911.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/45911.html</trackback:ping><description><![CDATA[
		<p>上篇：<a href="/jinfeng_wang/archive/2006/05/11/45726.html">http://www.blogjava.net/jinfeng_wang/archive/2006/05/11/45726.html</a><br /><br />先来回复两个回帖：<br />"你可以把IO等异常转化成你类库中中定义的异常。当然你定义的异常是Checked Exception 还是 UnChecked Excetion 那你自己定了。 "<br /><br />假设我按照这条建议去做了，那么我可以抛出XXXLibException。假设我的异常采用的是CheckedException，那么客户程序员可以捕捉它。但是对于不同的出错原因（例如不同的原因，包括无权限、硬盘满、U盘被拔了等等，导致无法正常写日志文件），程序都是捕捉XXXLibException，那么客户程序员就无法根据不同的异常去做相应的处理（例如提示用户修改权限、直接启用备用目录，直接退出程序）。总之，如果异常类型不同，客户程序可以根据“异常类型”做不同的工作（编译器＋工具可以实现自动代码生成）；但是如果全部合并为一个异常，那么客户程序只能根据“ExceptionMessage”尝试着做不同的工作（恰恰目前没有办法完成自动编码）。<br /><br /><br /><br />"要知道 JDK 的 FileWriter 是可以抛出 IOException 的子类的，只要文档足够详细，Java代码中也可以只去捕捉更明细的异常， 也可以就捕捉并重新抛出包装过的异常（甚至是RuntimException），除非呆板地去捕获每个异常，不然代码怎么会丑陋呢？"<br /><br />RuntiomeException，也就是UncheckedException（类于.NET的Exception），它不会要求客户代码强行捕捉异常，据此我写了下面的一个程序：<br />private void button1_Click(object sender, System.EventArgs e)<br />  {<br />   throw new Exception("s");<br />  }<br />     我只试了.NET的程序，出现的界面大家自己试 。因为UncheckedException没有要求客户程序去捕捉（客户程序员不能自觉的发现库中抛出的各种异常），让最终用户直接面对这样的异常，是一个道德的事情么？<br /></p>
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/45911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2006-05-12 20:21 <a href="http://www.blogjava.net/jinfeng_wang/archive/2006/05/12/45911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Checked Exception  VS UnChecked  Excetion</title><link>http://www.blogjava.net/jinfeng_wang/archive/2006/05/11/45726.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Thu, 11 May 2006 13:18:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2006/05/11/45726.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/45726.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2006/05/11/45726.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/45726.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/45726.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US">1</span>
				</b>
				<b>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
						<span lang="EN-US">.NET Framework IO Interface<span style="mso-spacerun: yes">  </span>and<span style="mso-spacerun: yes">  </span>JDK IO Interface<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US">1.1</span>
				</b>
				<b>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．</span>
						<span lang="EN-US">.NET Framework 1.1<o:p></o:p></span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<span style="mso-spacerun: yes">   </span>public StreamWriter(<span style="mso-spacerun: yes">    </span>string path<span style="mso-spacerun: yes">  </span>);</span>
		</p>
		<h4 style="MARGIN: 12pt 0cm 4.8pt -13.5pt">
				<span style="FONT-SIZE: 8pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">异常</span>
				<span lang="EN-US" style="FONT-SIZE: 8pt">
						<o:p>
						</o:p>
				</span>
		</h4>
		<p>
		</p>
		<table style="BORDER-RIGHT: #999999 0.75pt solid; BORDER-TOP: #999999 0.75pt solid; BACKGROUND: #999999; BORDER-LEFT: #999999 0.25pt solid; WIDTH: 105.8%; BORDER-BOTTOM: #999999 0.25pt solid; mso-cellspacing: 0cm" cellspacing="0" cellpadding="0" width="105%" bgcolor="#999999" border="1">
				<tbody>
						<tr style="HEIGHT: 19.3pt">
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 38.9%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; HEIGHT: 19.3pt; BACKGROUND-COLOR: transparent" valign="top" width="38%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt; TEXT-ALIGN: center" align="center">
												<b>
														<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">异常类型</span>
												</b>
												<b>
														<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
																<o:p>
																</o:p>
														</span>
												</b>
										</p>
								</td>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 61.1%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; HEIGHT: 19.3pt; BACKGROUND-COLOR: transparent" valign="top" width="61%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt; TEXT-ALIGN: center" align="center">
												<b>
														<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">条件</span>
												</b>
												<b>
														<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
																<o:p>
																</o:p>
														</span>
												</b>
										</p>
								</td>
						</tr>
						<tr style="HEIGHT: 13.35pt">
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 38.9%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; HEIGHT: 13.35pt; BACKGROUND-COLOR: transparent" valign="top" width="38%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
														<a href="http://msdn.microsoft.com/library/CHS/cpref/html/frlrfsystemunauthorizedaccessexceptionclasstopic.asp">UnauthorizedAccessException</a>
												</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 61.1%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; HEIGHT: 13.35pt; BACKGROUND-COLOR: transparent" valign="top" width="61%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">访问被拒绝。</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr style="HEIGHT: 15.15pt">
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 38.9%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; HEIGHT: 15.15pt; BACKGROUND-COLOR: transparent" valign="top" width="38%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
														<a href="http://msdn.microsoft.com/library/CHS/cpref/html/frlrfsystemargumentexceptionclasstopic.asp">ArgumentException</a>
												</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 61.1%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; HEIGHT: 15.15pt; BACKGROUND-COLOR: transparent" valign="top" width="61%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<i>
														<span lang="EN-US" style="FONT-FAMILY: Verdana">path</span>
												</i>
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
												</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">为空字符串</span>
												<span lang="EN-US" style="FONT-FAMILY: Verdana">("")</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">。</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 38.9%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="38%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
														<a href="http://msdn.microsoft.com/library/CHS/cpref/html/frlrfsystemargumentnullexceptionclasstopic.asp">ArgumentNullException</a>
												</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 61.1%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="61%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<i>
														<span lang="EN-US" style="FONT-FAMILY: Verdana">path</span>
												</i>
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
												</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">为空引用（</span>
												<span lang="EN-US" style="FONT-FAMILY: Verdana">Visual Basic </span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">中为</span>
												<span style="FONT-FAMILY: Verdana">
														<b>
																<span lang="EN-US">Nothing</span>
														</b>
												</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">）。</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 38.9%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="38%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
														<a href="http://msdn.microsoft.com/library/CHS/cpref/html/frlrfsystemiodirectorynotfoundexceptionclasstopic.asp">DirectoryNotFoundException</a>
												</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 61.1%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="61%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">指定的路径无效，比如在未映射的驱动器上。</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 38.9%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="38%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
														<a href="http://msdn.microsoft.com/library/CHS/cpref/html/frlrfsystemiopathtoolongexceptionclasstopic.asp">PathTooLongException</a>
												</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 61.1%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="61%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">指定的路径、文件名或者两者都超出了系统定义的最大长度。例如，在基于</span>
												<span lang="EN-US" style="FONT-FAMILY: Verdana">Windows </span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">的平台上，路径必须小于</span>
												<span lang="EN-US" style="FONT-FAMILY: Verdana">248 </span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">个字符，文件名必须小于</span>
												<span lang="EN-US" style="FONT-FAMILY: Verdana">260 </span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">个字符。</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 38.9%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="38%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
														<a href="http://msdn.microsoft.com/library/CHS/cpref/html/frlrfsystemioioexceptionclasstopic.asp">IOException</a>
												</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 61.1%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="61%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<i>
														<span lang="EN-US" style="FONT-FAMILY: Verdana">path</span>
												</i>
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
												</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">包含不正确或无效的文件名、目录名或卷标的语法。</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 38.9%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="38%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span lang="EN-US" style="FONT-FAMILY: Verdana">
														<a href="http://msdn.microsoft.com/library/CHS/cpref/html/frlrfsystemsecuritysecurityexceptionclasstopic.asp">SecurityException</a>
												</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: #999999; PADDING-RIGHT: 0.75pt; BORDER-TOP: #999999; PADDING-LEFT: 0.75pt; PADDING-BOTTOM: 0.75pt; BORDER-LEFT: #999999; WIDTH: 61.1%; PADDING-TOP: 0.75pt; BORDER-BOTTOM: #999999; BACKGROUND-COLOR: transparent" valign="top" width="61%">
										<p class="MsoNormal" style="MARGIN: 7.2pt 0cm 3.6pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">调用方没有所要求的权限。</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: black; FONT-FAMILY: Verdana">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US">1.2 JDK 1.4.2 :<o:p></o:p></span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">public FileWriter(String fileName)<span style="mso-spacerun: yes">  </span>throws IOException</span>
		</p>
		<pre>
				<span lang="EN-US">Constructs a FileWriter object given a file name. </span>
		</pre>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US">Parameters:</span>
				</b>
				<span lang="EN-US">
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 36pt">
				<code>
						<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体">fileName</span>
				</code>
				<span lang="EN-US">- String The system-dependent filename. </span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US">Throws:</span>
				</b>
				<span lang="EN-US">
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 36pt">
				<code>
						<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体">
								<a title="class in java.io" href="file:///D:JDK_DOC%25201.4docsapijavaioIOException.html">IOException</a>
						</span>
				</code>
				<span lang="EN-US">- if the named file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US">2</span>
				</b>
				<b>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、解析</span>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">.NET</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span>
				<span lang="EN-US">Excetpion</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</span>
				<span lang="EN-US">Unchecked</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">异常，客户端不要求去</span>
				<span lang="EN-US">Check</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码，但是</span>
				<span lang="EN-US">JAVA</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的绝大部分</span>
				<span lang="EN-US">Checked</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">异常，它要求客户端的代码检测异常。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt; mso-char-indent-count: 2.07; mso-char-indent-size: 10.5pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">假设一个这样的场景，方法</span>
				<span lang="EN-US">OutMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">调用</span>
				<span lang="EN-US">InnerMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，而内部方法</span>
				<span lang="EN-US">InnerMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">抛出的异常</span>
				<span lang="EN-US">InnerException</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt; mso-char-indent-count: 2.07; mso-char-indent-size: 10.5pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于</span>
				<span lang="EN-US">Java</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span>
				<span lang="EN-US">CheckedException</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，或者</span>
				<span lang="EN-US">OutMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">去抛出</span>
				<span lang="EN-US">InnerException</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，或者</span>
				<span lang="EN-US">OutMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">捕捉</span>
				<span lang="EN-US">InnerException</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（然后做处理）。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">再来观察一下</span>
				<span lang="EN-US">JDK</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span>
				<span lang="EN-US">FileWriter</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的异常声明，我没有详细测试其在各种可能出错情况下抛出的</span>
				<span lang="EN-US">IOException</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的消息，但是其分类远远不如</span>
				<span lang="EN-US">.NET</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span>
				<span lang="EN-US">StreamWriter</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。假设</span>
				<span lang="EN-US">Java</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">想照抄</span>
				<span lang="EN-US">.NET</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span>
				<span lang="EN-US">StreamWriter</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，对于</span>
				<span lang="EN-US">Java</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的使用者来说，无异于恶梦。外部的代码需要捕获如此多的异常消息（不捕捉就会在</span>
				<span lang="EN-US">OutMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">抛出一大堆的异常，问题继续传播下去，这是</span>
				<span lang="EN-US">CheckException</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的一个弱点）。也许正是出于这样的问题，所以此处</span>
				<span lang="EN-US">Java</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口的异常声明比较简单。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">那么假设我是一个库设计者，正在用到了</span>
				<span lang="EN-US">IO</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。如果我使用</span>
				<span lang="EN-US">.NET</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进行开发，对于</span>
				<span lang="EN-US">IOException</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来说，我是否有必要捕捉呢？捕捉的目的是为了“处理”，那么对于库设计者，显然这时候需要通知其“客户程序员”出错的原因，所以这里的库设计者的行为最好就是“不处理”。如果处理，那只能是“</span>
				<span lang="EN-US">catch</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、再</span>
				<span lang="EN-US">throw</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”。那么这样的处理显然是无意义的，因为原始异常已经足以提醒客户程序员出错的原因了。如果捕捉，那代码会特别的丑陋（直接</span>
				<span lang="EN-US">catch Exception</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的行为是不可取的）。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">CheckedException</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的另外一个缺点就是“将</span>
				<span lang="EN-US">Exceotion</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">加入了</span>
				<span lang="EN-US">Interface</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的规格声明“。假设</span>
				<span lang="EN-US">OutMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">调用了</span>
				<span lang="EN-US">InnerMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，此时</span>
				<span lang="EN-US">InnerMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的设计者需要增加一个异常，那么会直接影响到</span>
				<span lang="EN-US">OutMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。当然这里的</span>
				<span lang="EN-US">InnerMethod</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的设计者此时已经做了“修改接口声明“的行为。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"> </span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"> </p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<br />   随后待续...... <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US"> <o:p></o:p></span>
		</p>
		<p> </p>
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/45726.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2006-05-11 21:18 <a href="http://www.blogjava.net/jinfeng_wang/archive/2006/05/11/45726.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>测试、构建和重构(zz)</title><link>http://www.blogjava.net/jinfeng_wang/archive/2006/04/26/43358.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Wed, 26 Apr 2006 08:52:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2006/04/26/43358.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/43358.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2006/04/26/43358.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/43358.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/43358.html</trackback:ping><description><![CDATA[
		<div class="entrylistTitle">测试、构建和重构</div>
		<div class="entrylistDescription">
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl00_TitleUrl" href="http://www.cnblogs.com/confach/archive/2005/06/20/177817.html" target="_blank">NUnit2.0详细使用方法</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl01_TitleUrl" href="http://www.cnblogs.com/excel/archive/2005/06/17/176100.html" target="_blank">重构啊重构</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl02_TitleUrl" href="http://www.cnblogs.com/snowwolf/archive/2004/06/18/16644.html" target="_blank">.Net Code Cover</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl03_TitleUrl" href="http://www.cnblogs.com/william_fire/archive/2004/11/15/63867.html" target="_blank">让代码更具有可测试性</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl04_TitleUrl" href="http://www.cnblogs.com/anf/archive/2005/03/20/122342.html" target="_blank">NMock --- 从零开始</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl05_TitleUrl" href="http://www.cnblogs.com/jiezhi/archive/2005/04/28/146779.html" target="_blank">Unit Test : rules,design and strategy</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl06_TitleUrl" href="http://blog.joycode.com/musicland/archive/2005/04/16/48690.aspx" target="_blank">Concurrent connection limit</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl07_TitleUrl" href="http://www.cnblogs.com/iaxes/articles/121158.html" target="_blank">Log4Net Appender 之 ADONetAppender</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl08_TitleUrl" href="http://www.cnblogs.com/dahuzizyd/archive/2005/03/04/112566.html" target="_blank">Bug管理的流程和几个重点</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl09_TitleUrl" href="http://blog.joycode.com/ghj/articles/44720.aspx" target="_blank">把单元测试代码跟项目代码放在一个工程中</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl10_TitleUrl" href="http://www.cnblogs.com/java_aix/archive/2005/02/10/103717.html" target="_blank">Subversion配置安装教程（三） </a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl11_TitleUrl" href="http://www.cnblogs.com/java_aix/archive/2005/02/09/103500.html" target="_blank">Subversion配置安装教程（二） </a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl12_TitleUrl" href="http://www.cnblogs.com/java_aix/archive/2005/02/08/103399.html" target="_blank">Subversion配置安装教程（一）</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl13_TitleUrl" href="http://www.cnblogs.com/william_fire/articles/102245.html" target="_blank">敏捷（AM）：TDD(Test Driven Development）实践与变化--&gt;TAD（Test Assist Development)</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl14_TitleUrl" href="http://blog.joycode.com/uestc95/archive/2005/01/14/43057.aspx" target="_blank">如何在*.CS文件中加入版本跟踪信息？</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl15_TitleUrl" href="http://www.cnblogs.com/xchunyu/archive/2005/01/12/90425.html" target="_blank">推荐一个关于"架构"的演示文稿(PPT)</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl16_TitleUrl" href="http://blog.joycode.com/oldsidney/archive/2005/01/06/42468.aspx" target="_blank">什麼是 LoadRunner？ </a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl17_TitleUrl" href="http://www.cnblogs.com/dudu/archive/2004/12/18/78838.html" target="_blank">推荐一个不错的VS.NET集成单元测试工具TestDriven.NET</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl18_TitleUrl" href="http://www.cnblogs.com/bigtall/archive/2004/11/24/68126.html" target="_blank">实战dailybuild-cc.net的配置</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl19_TitleUrl" href="http://www.cnblogs.com/netcobra/archive/2004/11/24/68204.html" target="_blank">[翻译] NMock 两分钟教程</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl20_TitleUrl" href="http://www.cnblogs.com/netcobra/archive/2004/11/24/68199.html" target="_blank">[翻译] NMock 简介</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl21_TitleUrl" href="http://www.cnblogs.com/william_fire/archive/2004/11/15/64111.html" target="_blank">测试驱动开的的实例</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl22_TitleUrl" href="http://www.cnblogs.com/William_Fire/archive/2004/11/15/63867.html" target="_blank">让代码更具有可测试性</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl23_TitleUrl" href="http://www.cnblogs.com/rickie/archive/2004/11/08/61311.html" target="_blank">重构（Refactoring）技巧读书笔记 之三 </a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl24_TitleUrl" href="http://pfzhou.cnblogs.com/pvistely/archive/2004/11/11/62600.html" target="_blank">第一次用CVS后的流程小结（其实VSS也一样）</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl25_TitleUrl" href="http://pfzhou.cnblogs.com/airforce1st/archive/2004/10/22/55303.html" target="_blank">我也再补充一个NANT使用注意事项</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl26_TitleUrl" href="http://pfzhou.cnblogs.com/rickie/archive/2004/10/04/48859.aspx" target="_blank">重构（Refactoring）技巧读书笔记 之二</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl27_TitleUrl" href="http://pfzhou.cnblogs.com/rickie/archive/2004/09/25/46577.aspx" target="_blank">重构（Refactoring）技巧读书笔记 之一</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl28_TitleUrl" href="http://blog.csdn.net/ycw/archive/2004/09/05/95076.aspx" target="_blank">Bugzilla简明使用手则</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl29_TitleUrl" href="http://pfzhou.cnblogs.com/ccBoy/archive/2004/08/31/38140.aspx" target="_blank">Daily Build 的链接</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl30_TitleUrl" href="http://pfzhou.cnblogs.com/muddle/archive/2004/04/20/6673.aspx" target="_self">Test-Driven Development In .NET 部分译文</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl31_TitleUrl" href="http://pfzhou.cnblogs.com/feidao/archive/2004/06/19/17050.aspx" target="_blank">有关于Refactor(重构)与Source(源)的比较</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl32_TitleUrl" href="http://pfzhou.cnblogs.com/coolbug/archive/2004/07/26/27367.aspx" target="_blank">终于完成了DailyBuild</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl33_TitleUrl" href="http://pfzhou.cnblogs.com/ccBoy/archive/2004/07/26/27363.aspx" target="_blank">用MSBuild.... DailyBuild和软件开发流程的东东</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl34_TitleUrl" href="http://pfzhou.cnblogs.com/coolbug/archive/2004/07/27/27735.aspx" target="_blank">DailyBuild全攻略</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl35_TitleUrl" href="http://pfzhou.cnblogs.com/unruledboy/archive/2004/08/13/33227.aspx" target="_blank">关于Peer Review、代码评审和测试驱动等</a>
				</h5>
		</div>
		<div class="post">
				<h5>
						<a id="FavoriteList1_Favorites_ctl36_TitleUrl" href="http://pfzhou.cnblogs.com/jobs/archive/2004/08/13/33065.aspx" target="_blank">测试开发驱动实践</a>
				</h5>
		</div>
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/43358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2006-04-26 16:52 <a href="http://www.blogjava.net/jinfeng_wang/archive/2006/04/26/43358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>追求代码质量: 不要被覆盖报告所迷惑(zz)</title><link>http://www.blogjava.net/jinfeng_wang/archive/2006/04/26/43340.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Wed, 26 Apr 2006 08:24:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2006/04/26/43340.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/43340.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2006/04/26/43340.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/43340.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/43340.html</trackback:ping><description><![CDATA[
		<blockquote>测试覆盖工具对单元测试具有重要的意义，但是经常被误用。这个月，Andrew Glover 会在他的新系列 —— <i>追求代码质量</i> 中向您介绍值得参考的专家意见。第一部分深入地介绍覆盖报告中数字的真实含义。然后他会提出您可以尽早并经常地利用覆盖来确保代码质量的三个方法。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>您还记得以前大多数开发人员是如何追求代码质量的吗。在那时，有技巧地放置 <code>main()</code> 方法被视为灵活且适当的测试方法。经历了漫长的道路以后，现在自动测试已经成为高质量代码开发的基本保证，对此我很感谢。但是这还不是我所要感谢的全部。Java™ 开发人员现在拥有很多通过代码度量、静态分析等方法来度量代码质量的工具。我们甚至已经设法将重构分类成一系列便利的模式！</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">要获得有关代码质量问题的答案，您可以访问由 Andrew Glover 主持的 <a href="http://www.ibm.com/developerworks/forums/dw_forum.jsp?forum=812&amp;cat=10"><font color="#5c81a7">Code Quality</font></a> 论坛。 </td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>所有的这些新的工具使得确保代码质量比以前简单得多，不过您还需要知道如何使用它们。在这个系列中，我将重点阐述有关保证代码质量的一些有时看上去有点神秘的东西。除了带您一起熟悉有关代码质量保证的众多工具和技术之外，我还将为您说明：</p>
		<ul>
				<li>定义并有效度量最影响质量的代码方面。 
</li>
				<li>设定质量保证目标并照此规划您的开发过程。 
</li>
				<li>确定哪个代码质量工具和技术可以满足您的需要。 
</li>
				<li>实现最佳实践（清除不好的），使确保代码质量<i>及早并经常地</i> 成为开发实践中轻松且有效的方面。 </li>
		</ul>
		<p>在这个月，我将首先看看 Java 开发人员中最流行也是最容易的质量保证工具包：测试覆盖度量。</p>
		<p>
				<a name="N1008B">
						<span class="atitle">
								<font face="Arial" size="4">谨防上当</font>
						</span>
				</a>
		</p>
		<p>这是一个晚上鏖战后的早晨，大家都站在饮水机边上。开发人员和管理人员们了解到一些经过良好测试的类可以达到超过 90% 的覆盖率，正在高兴地互换着 NFL 风格的点心。团队的集体信心空前高涨。从远处可以听到 “放任地重构吧” 的声音，似乎缺陷已成为遥远的记忆，响应性也已微不足道。但是一个很小的反对声在说：</p>
		<p>
				<i>女士们，先生们，不要被覆盖报告所愚弄</i>。</p>
		<p>现在，不要误解我的意思：并不是说使用测试覆盖工具是愚蠢的。对单元测试范例，它是很重要的。不过更重要的是您如何理解所得到的信息。许多开发团队会在这儿犯第一个错。</p>
		<p>高覆盖率只是表示执行了很多的代码，并不意味着这些代码被<i>很好地</i> 执行。如果您关注的是代码的质量，就必须精确地理解测试覆盖工具能做什么，不能做什么。然后您才能知道如何使用这些工具去获取有用的信息。而不是像许多开发人员那样，只是满足于高覆盖率。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N100A2">
						<span class="atitle">
								<font face="Arial" size="4">测试覆盖度量</font>
						</span>
				</a>
		</p>
		<p>测试覆盖工具通常可以很容易地添加到确定的单元测试过程中，而且结果可靠。下载一个可用的工具，对您的 Ant 和 Maven 构建脚本作一些小的改动，您和您的同事就有了在饮水机边上谈论的一种新报告：<i>测试覆盖报告</i>。当 <code>foo</code> 和 <code>bar</code> 这样的程序包令人惊奇地显示<i>高</i> 覆盖率时，您可以得到不小的安慰。如果您相信至少您的部分代码可以保证是 “没有 BUG” 的，您会觉得很安心。但是这样做是一个错误。</p>
		<p>存在不同类型的覆盖度量，但是绝大多数的工具会关注<i>行覆盖</i>，也叫做<i>语句覆盖</i>。此外，有些工具会报告<i>分支覆盖</i>。通过用一个测试工具执行代码库并捕获整个测试过程中与被 “触及” 的代码对应的数据，就可以获得测试覆盖度量。然后这些数据被合成为覆盖报告。在 Java 世界中，这个测试工具通常是 JUnit 以及名为 Cobertura、Emma 或 Clover 等的覆盖工具。</p>
		<p>
				<i>行覆盖</i>只是指出代码的哪些行被执行。如果一个方法有 10 行代码，其中的 8 行在测试中被执行，那么这个方法的行覆盖率是 80%。这个过程在总体层次上也工作得很好：如果一个类有 100 行代码，其中的 45 行被触及，那么这个类的行覆盖率就是 45%。同样，如果一个代码库包含 10000 个非注释性的代码行，在特定的测试运行中有 3500 行被执行，那么这段代码的行覆盖率就是 35%。</p>
		<p>报告<i>分支覆盖</i> 的工具试图度量决策点（比如包含逻辑 <code>AND</code> 或 <code>OR</code> 的条件块）的覆盖率。与行覆盖一样，如果在特定方法中有两个分支，并且两个分支在测试中都被覆盖，那么您可以说这个方法有 100% 的分支覆盖率。</p>
		<p>问题是，这些度量有什么用？很明显，很容易获得所有这些信息，不过您需要知道如何使用它们。一些例子可以阐明我的观点。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N100DB">
						<span class="atitle">
								<font face="Arial" size="4">代码覆盖在活动</font>
						</span>
				</a>
		</p>
		<p>我在清单 1 中创建了一个简单的类以具体表述类层次的概念。一个给定的类可以有一连串的父类，例如 <code>Vector</code>，它的父类是 <code>AbstractList</code>，<code>AbstractList</code> 的父类又是 <code>AbstractCollection</code>，<code>AbstractCollection</code> 的父类又是 <code>Object</code>：</p>
		<br />
		<a name="code1">
				<b>清单 1. 表现类层次的类</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package com.vanward.adana.hierarchy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Hierarchy {
  private Collection classes;
  private Class baseClass;

  public Hierarchy() {
    super();
    this.classes = new ArrayList();
  }

  public void addClass(final Class clzz){
    this.classes.add(clzz);
  }
  /**
   * @return an array of class names as Strings
   */
  public String[] getHierarchyClassNames(){
    final String[] names = new String[this.classes.size()];        
    int x = 0;
    for(Iterator iter = this.classes.iterator(); iter.hasNext();){
       Class clzz = (Class)iter.next();
       names[x++] = clzz.getName();
    }        
    return names;
  }

  public Class getBaseClass() {
    return baseClass;
  }

  public void setBaseClass(final Class baseClass) {
    this.baseClass = baseClass;
  }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>正如您看到的，清单 1 中的 <code>Hierarchy</code> 类具有一个 <code>baseClass</code> 实例以及它的父类的集合。清单 2 中的 <code>HierarchyBuilder</code> 通过两个复制 <code>buildHierarchy</code> 的重载的 <code>static</code> 方法创建了 <code>Hierarchy</code> 类。</p>
		<br />
		<a name="code2">
				<b>清单 2. 类层次生成器</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package com.vanward.adana.hierarchy;

public class HierarchyBuilder {  

  private HierarchyBuilder() {
    super();		
  }

  public static Hierarchy buildHierarchy(final String clzzName) 
    throws ClassNotFoundException{
      final Class clzz = Class.forName(clzzName, false, 
          HierarchyBuilder.class.getClassLoader());        
      return buildHierarchy(clzz);
  }

  public static Hierarchy buildHierarchy(Class clzz){
    if(clzz == null){
      throw new RuntimeException("Class parameter can not be null");
    }

    final Hierarchy hier = new Hierarchy();
    hier.setBaseClass(clzz);

    final Class superclass = clzz.getSuperclass();

    if(superclass != 
      null &amp;&amp; superclass.getName().equals("java.lang.Object")){
       return hier; 
    }else{      
       while((clzz.getSuperclass() != null) &amp;&amp; 
          (!clzz.getSuperclass().getName().equals("java.lang.Object"))){
             clzz = clzz.getSuperclass();
             hier.addClass(clzz);
       }	        
       return hier;
    }
  }      
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Lucida Console">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Lucida Console">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Lucida Console">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N1012B">
						<span class="atitle">
								<font face="Arial" size="4">现在是测试时间！</font>
						</span>
				</a>
		</p>
		<p>有关测试覆盖的文章怎么能缺少测试案例呢？在清单 3 中，我定义了一个简单的有三个测试案例的 JUnit 测试类，它将试图执行 <code>Hierarchy</code> 类和 <code>HierarchyBuilder</code> 类：</p>
		<br />
		<a name="code3">
				<b>清单 3. 测试 HierarchyBuilder！</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package test.com.vanward.adana.hierarchy;

import com.vanward.adana.hierarchy.Hierarchy;
import com.vanward.adana.hierarchy.HierarchyBuilder;
import junit.framework.TestCase;

public class HierarchyBuilderTest extends TestCase {
  
  public void testBuildHierarchyValueNotNull() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertNotNull("object was null", hier);
  }

  public void testBuildHierarchyName() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be junit.framework.Assert", 
       "junit.framework.Assert", 
         hier.getHierarchyClassNames()[1]);      
  }

  public void testBuildHierarchyNameAgain() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be junit.framework.TestCase", 
       "junit.framework.TestCase", 
         hier.getHierarchyClassNames()[0]);      
  }
 
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>因为我是一个狂热的测试人员，我自然希望运行一些覆盖测试。对于 Java 开发人员可用的代码覆盖工具中，我比较喜欢用 Cobertura，因为它的报告很友好。而且，Corbertura 是开放源码项目，它派生出了 JCoverage 项目的前身。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10149">
						<span class="atitle">
								<font face="Arial" size="4">Cobertura 的报告</font>
						</span>
				</a>
		</p>
		<p>运行 Cobertura 这样的工具和运行您的 JUnit 测试一样简单，只是有一个用专门逻辑在测试时检查代码以报告覆盖率的中间步骤（这都是通过工具的 Ant 任务或 Maven 的目标完成的）。</p>
		<p>正如您在图 1 中看到的，<code>HierarchyBuilder</code> 的覆盖报告说明部分代码<i>没有</i> 被执行。事实上，Cobertura 认为 <code>HierarchyBuilder</code> 的行覆盖率为 59%，分支覆盖率为 75%。</p>
		<br />
		<a name="N10162">
				<b>图 1. Cobertura 的报告</b>
		</a>
		<br />
		<img height="718" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/coverage-01-1.gif" width="572" border="0" />
		<br />
		<p>这样看来，我的第一次覆盖测试是失败的。首先，带有 <code>String</code> 参数的 <code>buildHierarchy()</code> 方法根本没有被测试。其次，另一个 <code>buildHierarchy()</code> 方法中的两个条件都没有被执行。有趣的是，所要关注的正是第二个没有被执行的 <code>if</code> 块。</p>
		<p>因为我所需要做的只是增加一些测试案例，所以我并不担心这一点。一旦我到达了所关注的区域，我就可以很好地完成工作。注意我这儿的逻辑：我使用测试报告来了解什么<i>没有</i> 被测试。现在我已经可以选择使用这些数据来增强测试或者继续工作。在本例中，我准备增强我的测试，因为我还有一些重要的区域未覆盖。</p>
		<p>
				<a name="N1018A">
						<span class="smalltitle">
								<strong>
										<font face="Arial">Cobertura：第二轮</font>
								</strong>
						</span>
				</a>
		</p>
		<p>清单 4 是一个更新过的 JUnit 测试案例，增加了一些附加测试案例，以试图完全执行 <code>HierarchyBuilder</code>： </p>
		<br />
		<a name="code4">
				<b>清单 4. 更新过的 JUnit 测试案例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package test.com.vanward.adana.hierarchy;

import com.vanward.adana.hierarchy.Hierarchy;
import com.vanward.adana.hierarchy.HierarchyBuilder;
import junit.framework.TestCase;

public class HierarchyBuilderTest extends TestCase {
  
  public void testBuildHierarchyValueNotNull() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertNotNull("object was null", hier);
  }

  public void testBuildHierarchyName() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be junit.framework.Assert", 
       "junit.framework.Assert", 
         hier.getHierarchyClassNames()[1]);      
  }

  public void testBuildHierarchyNameAgain() { zo       
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be junit.framework.TestCase", 
       "junit.framework.TestCase", 
         hier.getHierarchyClassNames()[0]);      
  }

  public void testBuildHierarchySize() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be 2", 2, hier.getHierarchyClassNames().length);
  }

  public void testBuildHierarchyStrNotNull() throws Exception{
    Hierarchy hier = 
       HierarchyBuilder.
       buildHierarchy("test.com.vanward.adana.hierarchy.HierarchyBuilderTest");
    assertNotNull("object was null", hier);
  }

  public void testBuildHierarchyStrName() throws Exception{        
    Hierarchy hier = 
       HierarchyBuilder.
       buildHierarchy("test.com.vanward.adana.hierarchy.HierarchyBuilderTest");
    assertEquals("should be junit.framework.Assert", 
      "junit.framework.Assert",
        hier.getHierarchyClassNames()[1]);
  }

  public void testBuildHierarchyStrNameAgain() throws Exception{
    Hierarchy hier = 
       HierarchyBuilder.
       buildHierarchy("test.com.vanward.adana.hierarchy.HierarchyBuilderTest");
    assertEquals("should be junit.framework.TestCase", 
      "junit.framework.TestCase",
        hier.getHierarchyClassNames()[0]);      
  }

  public void testBuildHierarchyStrSize() throws Exception{        
     Hierarchy hier = 
        HierarchyBuilder.
        buildHierarchy("test.com.vanward.adana.hierarchy.HierarchyBuilderTest");
     assertEquals("should be 2", 2, hier.getHierarchyClassNames().length);        
  }

  public void testBuildHierarchyWithNull() {
     try{
       Class clzz = null;
       HierarchyBuilder.buildHierarchy(clzz);
       fail("RuntimeException not thrown");
     }catch(RuntimeException e){}
  }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>当我使用新的测试案例再次执行测试覆盖过程时，我得到了如图 2 所示的更加完整的报告。现在，我覆盖了未测试的 <code>buildHierarchy()</code> 方法，也处理了另一个 <code>buildHierarchy()</code> 方法中的两个 <code>if</code> 块。然而，因为 <code>HierarchyBuilder</code> 的构造器是 <code>private</code> 类型的，所以我不能通过我的测试类测试它（我也不关心）。因此，我的行覆盖率仍然只有 88%。</p>
		<br />
		<a name="N101BA">
				<b>图 2. 谁说没有第二次机会</b>
		</a>
		<br />
		<img height="709" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/coverage-01.gif" width="569" border="0" />
		<br />
		<p>正如您看到的，使用一个代码覆盖工具<i>可以</i> 揭露重要的没有相应测试案例的代码。重要的事情是，在阅读报告（<i>特别</i> 是覆盖率高的）时需要小心，它们也许隐含危险的信息。让我们看看两个例子，看看在高覆盖率后面隐藏着什么。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N101D2">
						<span class="atitle">
								<font face="Arial" size="4">条件带来的麻烦</font>
						</span>
				</a>
		</p>
		<p>正如您已经知道的，代码中的许多变量可能有多种状态；此外，条件的存在使得执行有多条路径。在留意这些问题之后，我将在清单 5 中定义一个极其简单只有一个方法的类：</p>
		<br />
		<a name="code5">
				<b>清单 5.您能看出下面的缺陷吗？ </b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package com.vanward.coverage.example01;

public class PathCoverage {

  public String pathExample(boolean condition){
    String value = null;
    if(condition){
      value = " " + condition + " ";
    }
    return value.trim();
  }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>您是否发现了清单 5 中有一个隐藏的缺陷呢？如果没有，不要担心，我会在清单 6 中写一个测试案例来执行 <code>pathExample()</code> 方法并确保它正确地工作： </p>
		<br />
		<a name="code1">
				<b>清单 6. JUnit 来救援！ </b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package test.com.vanward.coverage.example01;

import junit.framework.TestCase;
import com.vanward.coverage.example01.PathCoverage;

public class PathCoverageTest extends TestCase {

  public final void testPathExample() {
    PathCoverage clzzUnderTst = new PathCoverage();
    String value = clzzUnderTst.pathExample(true);
    assertEquals("should be true", "true", value);
  }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>我的测试案例正确运行，我的神奇的代码覆盖报告（如下面图 3 所示）使我看上去像个超级明星，测试覆盖率达到了 100%！</p>
		<br />
		<a name="#figure3">
				<b>图 3. 覆盖率明星 </b>
		</a>
		<br />
		<img height="399" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/coverage-ex01.gif" width="515" border="0" />
		<br />
		<p>我想现在应该到饮水机边上去说了，但是等等，我不是怀疑代码中有什么缺陷呢？认真检查清单 5 会发现，如果 <code>condition</code> 为 <code>false</code>，那么第 13 行确实会抛出 <code>NullPointerException</code>。<i>Yeesh</i>，这儿发生了什么？</p>
		<p>这表明行覆盖的确不能很好地指示测试的有效性。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N1021F">
						<span class="atitle">
								<font face="Arial" size="4">路径的恐怖</font>
						</span>
				</a>
		</p>
		<p>在清单 7 中，我定义了另一个包含 <i>indirect</i> 的简单例子，它仍然有不能容忍的缺陷。请注意 <code>branchIt()</code> 方法中 <code>if</code> 条件的后半部分。（<code>HiddenObject</code> 类将在清单 8 中定义。）</p>
		<br />
		<a name="code1">
				<b>清单 7. 这个代码足够简单</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package com.vanward.coverage.example02;

import com.acme.someotherpackage.HiddenObject;

public class AnotherBranchCoverage {
   
  public void branchIt(int value){
    if((value &gt; 100) || (HiddenObject.doWork() == 0)){
      this.dontDoIt();
    }else{
      this.doIt();
    }
  }                             

  private void dontDoIt(){
    //don't do something...
  }

  private void doIt(){
    //do something!
  }   
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>呀！清单 8 中的 <code>HiddenObject</code> 是<i>有害的</i>。与清单 7 中一样，调用 <code>doWork()</code> 方法会导致 <code>RuntimeException</code>：</p>
		<br />
		<a name="code1">
				<b>清单 8. 上半部分！ </b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package com.acme.someotherpackage.HiddenObject;

public class HiddenObject {

  public static int doWork(){
    //return 1;
    throw new RuntimeException("surprise!");
  }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>但是我的确可以通过一个良好的测试捕获这个异常！在清单 9 中，我编写了另一个好的测试，以图挽回我的超级明星光环：</p>
		<br />
		<a name="code1">
				<b>清单 9. 使用 JUnit 规避风险</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package test.com.vanward.coverage.example02;

import junit.framework.TestCase;
import com.vanward.coverage.example02.AnotherBranchCoverage;

public class AnotherBranchCoverageTest extends TestCase {
    
  public final void testBranchIt() {
    AnotherBranchCoverage clzzUnderTst = new AnotherBranchCoverage();
    clzzUnderTst.branchIt(101);
  }    
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>您对这个测试案例有什么想法？您也许会写出更多的测试案例，但是请设想一下清单 7 中不确定的条件有不止一个的缩短操作会如何。设想如果前半部分中的逻辑比简单的 <code>int</code> 比较更复杂，那么<i>您</i> 需要写多少测试案例才能满意？</p>
		<p>
				<a name="N10274">
						<span class="smalltitle">
								<strong>
										<font face="Arial">仅仅给我数字</font>
								</strong>
						</span>
				</a>
		</p>
		<p>现在，对清单 7、8、9 的测试覆盖率的分析结果不再会使您感到惊讶。在图 4 的报告中显示我达到了 75% 的行覆盖率和 100% 的分支覆盖率。最重要的是，我执行了第 10 行！</p>
		<br />
		<a name="N1027F">
				<b>图 4.愚弄的报酬</b>
		</a>
		<br />
		<img height="497" alt="" src="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/coverage-ex02.gif" width="528" border="0" />
		<br />
		<p>从第一印象看，这让我骄傲。但是这个报告有什么误导吗？只是粗略地看一看报告中的数字，会导致您相信代码是经过<i>良好测试的</i>。基于这一点，您也许会认为出现缺陷的风险很低。这个报告并不能帮助您确定 <code>or</code> 缩短操作的后半部分是一个定时炸弹！</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10298">
						<span class="atitle">
								<font face="Arial" size="4">质量测试</font>
						</span>
				</a>
		</p>
		<p>我不止一次地说：您可以（而且应该）使用测试覆盖工具作为您的测试过程的一部分。但是<i>不要被覆盖报告所愚弄</i>。关于覆盖报告您需要了解的主要事情是，覆盖报告最好用来检查哪些代码<i>没有经过</i> 充分的测试。当您检查覆盖报告时，找出较低的值，并了解为什么特定的代码没有经过充分的测试。知道这些以后，开发人员、管理人员以及 QA 专业人员就可以在真正需要的地方使用测试覆盖工具。通常有下列三种情况：</p>
		<ul>
				<li>估计修改已有代码所需的时间 
</li>
				<li>评估代码质量 
</li>
				<li>评定功能测试 </li>
		</ul>
		<p>现在我可以断定对测试覆盖报告的一些使用方法会将您引入歧途，下面这些最佳实践可以使得测试覆盖报告可以真正为您所用。</p>
		<p>
				<a name="N102B6">
						<span class="smalltitle">
								<strong>
										<font face="Arial">1. 估计修改已有代码所需的时间</font>
								</strong>
						</span>
				</a>
		</p>
		<p>对一个开发团队而言，针对代码编写测试案例自然可以增加集体的信心。与没有相应测试案例的代码相比，经过测试的代码更容易重构、维护和增强。测试案例因为暗示了代码在测试工作中是<i>如何</i> 工作的，所以还可以充当内行的文档。此外，如果被测试的代码发生改变，测试案例通常也会作相应的改变，这与诸如注释和 Javadoc 这样的静态代码文档不同。</p>
		<p>在另一方面，没有经过相应测试的代码更难于理解和<i>安全地</i> 修改。因此，知道代码有没有被测试，并看看实际的测试覆盖数值，可以让开发人员和管理人员更准确地预知修改已有代码所需的时间。</p>
		<p>再次回到饮水机边上，可以更好地阐明我的观点。</p>
		<blockquote>市场部的 Linda：“我们想让系统在用户完成一笔交易时做 <i>x</i> 工作。这需要多长时间。我们的用户需要尽快实现这一功能。” <br /><br />管理人员 Jeff：“让我看看，这个代码是 Joe 在几个月前编写的，需要对业务层和 UI 做一些变动。Mary 也许可以在两天内完成这项工作。” <br /><br />Linda：“Joe？他是谁？” <br /><br />Jeff：“哦，Joe，因为他不知道自己在干什么，所以被我解雇了。” </blockquote>
		<p>情况似乎有点不妙，不是吗？尽管如此，Jeff 还是将任务分配给了 Mary，Mary 也认为能够在两天内完成工作 —— 确切地说，在看到代码之前她是这么认为的。</p>
		<blockquote>Mary：“Joe 写这些代码时是不是<i>睡着了</i>？这是我所见过的最差的代码。我甚至不能确认这是 Java 代码。除非推倒重来，要不我根本没法修改。” </blockquote>
		<p>情况对 “饮水机” 团队不妙，不是吗？但是我们假设，如果在这个不幸的事件的当初，Jeff 和 Mary 就拥有一份测试报告，那么情况会如何呢？当 Linda 要求实现新功能时，Jeff 做的第一件事就是检查以前生成的覆盖报告。注意到需要改动的软件包几乎没有被覆盖，然后他就会与 Mary 商量。</p>
		<blockquote>Jeff：“Joe 编写的这个代码很差，绝大多数没经过测试。您认为要支持 Linda 所说的功能需要多长时间？” <br /><br />Mary：“这个代码很混乱。我甚至都不想看到它。为什么不让 Mark 来做呢？” <br /><br />Jeff：“因为 Mark 不编写测试，刚被我解雇了。我需要您测试这个代码并作一些改动。告诉我您需要多长时间。” <br /><br />Mary：“我至少需要两天编写测试，然后我会重构这个代码，增加新的功能。我想总共需要四天吧。” </blockquote>
		<p>正如他们所说的，知识的力量是强大的。开发人员可以在试图修改代码<i>之前</i> 使用覆盖报告来检查代码质量。同样，管理人员可以使用覆盖数据更好地估计开发人员实际所需的时间。</p>
		<p>
				<a name="N102F8">
						<span class="smalltitle">
								<strong>
										<font face="Arial">2. 评估代码质量</font>
								</strong>
						</span>
				</a>
		</p>
		<p>开发人员的测试可以降低代码中存在缺陷的风险，因此现在很多开发团队在新开发和更改代码的同时需要编写单元测试。然而正如前面所提到的 Mark 一样，并不总是在编码的同时进行单元测试，因而会导致低质量代码的出现。</p>
		<p>监控覆盖报告可以帮助开发团队迅速找出不断增长的<i>没有</i> 相应测试的代码。例如，在一周开始时运行覆盖报告，显示项目中一个关键的软件包的覆盖率是 70%。如果几天后，覆盖率下降到了 60%，那么您可以推断：</p>
		<ul>
				<li>软件包的代码行增加了，但是没有为新代码编写相应的测试（或者是新增加的测试不能有效地覆盖新代码）。<br /><br /></li>
				<li>删除了测试案例。<br /><br /></li>
				<li>上述两种情况都发生了。 </li>
		</ul>
		<p>能够监控事情的发展，无疑是件好事。定期地查阅报告使得设定目标（例如获得覆盖率、维护代码行的测试案例的比例等）并监控事情的发展变得更为容易。如果您发现测试没有如期编写，您可以提前采取一些行动，例如对开发人员进行培训、指导或帮助。与其让用户 “在使用中” 发现程序缺陷（这些缺陷本应该在几个月前通过简单的测试暴露出来），或者等到管理人员发现没有编写单元测试时再感到惊讶（和愤怒），还不如采取一些预防性的措施。</p>
		<p>使用覆盖报告来确保正确的测试是一项伟大的实践。关键是要训练有素地完成这项工作。例如，使每晚生成并查阅覆盖报告成为<i>连续累计</i> 过程的一部分。</p>
		<p>
				<a name="N10320">
						<span class="smalltitle">
								<strong>
										<font face="Arial">3. 评定功能测试</font>
								</strong>
						</span>
				</a>
		</p>
		<p>假设覆盖报告在指出<i>没有经过</i> 足够测试的代码部分方面非常有效，那么质量保证人员可以使用这些数据来评定与功能测试有关的关注区域。让我们回到 “饮水机” 团队来看看 QA 的负责人 Drew 是如何评价 Joe 的代码的：</p>
		<blockquote>Drew 对 Jeff 说：“我们为下一个版本编写了测试案例，我们注意到很多代码没有被覆盖。那好像是与股票交易有关的代码。” <br /><br />Jeff：“哦，我们在这个领域有好些问题。如果我是一个赌徒的话，我会对这个功能区域给予特别的关注。Mary 正在对这个应用程序做一些其他的修改 —— 她在编写单元测试方面做得很好，但是这个代码也太差了点。” <br /><br />Drew：“是的，我正在确定工作的资源和级别，看上去我没必要那么担心了，我估计我们的团队会对股票交易模块引起足够的关注。” </blockquote>
		<p>知识再次显示了其强大的力量。与其他软件生命周期中的风险承担者（例如 QA）配合，您可以利用覆盖报告所提供的信息来降低风险。在上面的场景中，也许 Jeff 可以为 Drew 的团队提供一个早期的不包含 Mary 的所有修改的版本。不过无论如何，Drew 的团队都应该关注应用程序的股票交易方面，与其他具有相应单元测试的代码相比，这个地方似乎存在更大的缺陷风险。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-cq01316/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10338">
						<span class="atitle">
								<font face="Arial" size="4">测试有什么好处</font>
						</span>
				</a>
		</p>
		<p>对单元测试范例而言，测试覆盖度量工具是一个有点奇怪的组成部分。对于一个已存在的有益的过程，覆盖度量可以增加其深度和精度。然而，您应该仔细地阅读代码覆盖报告。单独的高覆盖率并不能确保代码的质量。对于减少缺陷，代码的高覆盖并不是必要条件，尽管高覆盖的代码的确<i>更少</i> 有缺陷。</p>
		<p>测试覆盖度量的窍门是使用覆盖报告找出<i>未经</i> 测试的代码，分别在微观和宏观两个级别。通过从顶层开始分析您的代码库，以及分析单个类的覆盖，可以促进深入的覆盖测试。一旦您能够综合这些原则，您和您的组织就可以在真正需要的地方使用覆盖度量工具，例如估计一个项目所需的时间，持续监控代码质量以及促进与 QA 的协作。</p>
		<br />
<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/43340.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2006-04-26 16:24 <a href="http://www.blogjava.net/jinfeng_wang/archive/2006/04/26/43340.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 或许对YM很不公平,但他会勇敢的去面对不可能的任务 zz from hc</title><link>http://www.blogjava.net/jinfeng_wang/archive/2006/03/14/35197.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Tue, 14 Mar 2006 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2006/03/14/35197.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/35197.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2006/03/14/35197.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/35197.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/35197.html</trackback:ping><description><![CDATA[&nbsp;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;这个世界上有很多奇怪的不公平,比如说你永远没办法理解为什么中国的要黑会这么多,一个像YM这样对中国体育做出如此多贡献而且公众形象完美无缺的年轻人到底哪里得罪了他们,会让他们如此不遗余力的去黑他.<BR>&nbsp;&nbsp; &nbsp;<BR>&nbsp;&nbsp; &nbsp; 你同样没办法理解,在这个如今充满了高薪低能和满篇大话的NBA联盟里面,像YM这样一个勤勤恳恳,谦虚谨慎的人居然会排在被高估球员榜的第二位,唯一排在他前面的那个人目前球队成绩联盟倒第一而他却自称自己为天下第一PG,而那个拿着上千万年薪,自称自己是联盟第二中锋如今却只能给一个塞内加尔无名小子打替补的丹皮尔却可以在被高估傍上名落孙山.<BR><BR>&nbsp;&nbsp; &nbsp; 今天的比赛如果以一个要迷的角度看或许并不糟糕,YM继续不错的发挥,拿下全场最漂亮的数据,25分10板3帽3助而且只有一个失误,火箭在TMAC和威思利两大主力同时受伤的情况下(TMAC是火箭第一得分手,威思利是火箭最准的外线投手和最好的外线防守队员),仍然跟卫冕冠军,主场成绩高达26胜4负的马刺硬拼到了最后.是的,这个结果很另人欣慰了.但如果你看了赛后美国媒体的报道,你的心情恐怕就没有这么欣慰了.<BR><BR>&nbsp;&nbsp; &nbsp; YAHOO的赛后报道用了一半以上的文字去描述基诺比例和芬利在YM面前的那两个扣篮,同时还不忘附上这两个人在赛后采访中对这两个扣篮感想,YAHOO对这两个扣篮的描述相当的生动,绝对能让你有身临其境的感觉,而如果你想象力不够的话也不要紧,要黑电台ESPN今天晚上肯定会把这两个扣篮放上500次的.接下来他们又不忘夸奖TD在第四节的表.,当然最后也提了一下YM25分的全场最高分,可他们同时强调了17分是上半场得到的.NBA.COM的报道也大同小异,重点描述了那两个扣篮后,特别说明了YM在马刺反超比赛的第三节里只得到了2分.没错,这就是美国媒体对这场比赛的赛后分析,无视YM在马刺多人包夹防守下死拼42分钟是多么的不易,无视火箭的人员不整以及角色球员跟马刺队员的差距,他们只是一股脑地把火箭输球的责任全推给了YM,把他描述成一个关键时刻没法得分并且被小个子暴头的软蛋.<BR><BR>&nbsp;&nbsp; &nbsp; 这确实是很不公平,但现实就是这么的残忍,成王败寇是竞技场上永远不变的真理.作为领袖人物,只要球队输球,不论你个人的表现如何,你都要去承担责任,像今天湖人输给了超音速,KB也没在媒体的赛后分析里得到什么好话.美国媒体的宠儿KB尚且如此待遇,YM就更不用说了.美国的媒体从来就对他十分的苛刻和缺乏耐心.像巴克利这样伟大的球员当年居然只看了5场比赛就给YM判了死刑,说他永远得不到19分,神投米勒更甚,他在当了评论员后,只要提到YM就不停的强调YM的极限也就是当年的荷兰人史密次.这些NBA的老一代对外籍球员(特别YM还是亚洲球员)的藐视与不屑是根深蒂固的.所以在YM拿到总冠军之前,永远不要指望这些专家们会给YM什么公正的评价.<BR><BR>&nbsp;&nbsp; &nbsp; 在竞技体育里面,还有一条真理跟成王败寇同样不可颠覆,那就是ONE PERSON DOSENT MAKE A TEAM,没有人可以靠一己之力去赢得比赛,这已经被证明了无数次了.<BR><BR>&nbsp;&nbsp; &nbsp;狼王KG是一个非常好的例子,作为联盟的效率王,KG这些年的表现一直惊人的稳定,单看个人数据他几乎年年都是MVP的水准,但角色球员的不同却决定了他球队的成绩.当他身边有好的帮手的时候,KG可以带队打进西部决赛,拿下MVP.可当角色球员的实力不济的时候,虽然他个人表现依旧神勇无比,但球队只能常年止步季后赛第一轮,甚至在最近两年连续无缘PLAYOFF.<BR><BR>&nbsp;&nbsp; &nbsp;KB的情况也是如此,今年他个人的表现已经接近半神,平均得分上35,单场81分都是近乎神奇的表演,可即便他个人能力如此出色,再加上菲尔这样的大师指教,湖人如今仍然只有33胜31负的季后赛边缘成绩.在球队2哥奥多姆受伤的三场比赛里,KB倾尽全力仍不能避免湖人三连败,不仅被步行者横扫26分,甚至被联盟垫底的山猫拿下.而在不堪回首的去年,由于伤病和角色球员能力不足,KB在最后20场比赛里孤掌难鸣,湖人不得不最终吞下2胜18负的苦果.<BR><BR>&nbsp;&nbsp; &nbsp;火箭的一哥TMAC当年也有跟KB类似的经历,02-03赛季,打出职业生涯最佳表现的他在拿下得分王的同时入选联盟第一阵容,而且当时魔术的阵容虽然受到HILL合同的影响算不上豪华,但起码还有最佳第六人阿姆思特朗和最佳新人米勒这样相当不错的选手.尽管如此,球队的最终成绩也只有42胜40负,连西部第九的火箭成绩都比他强.而且这个成绩还是在当时整体实力薄弱的东部取得的.03-04赛季,失去了阿姆思特朗和米勒这两位帮手,TAMC虽然还可拿下得分王,但球队开季20场比赛里只有1胜19负.最终联盟垫底.<BR><BR>&nbsp;&nbsp; &nbsp;现在的YM获得的评价远没有KG,KB,TMAC那么高,可摆在他面前的20场比赛却比当年的KB,TMAC的20场还要恐怖,在主力受伤,龙套实力不济的情况下,YM要率领球对面对一个真正魔鬼的赛程.先是连续8场面对胜率5成的对手,包括与西部霸主小牛马刺的4场,外加客场挑战对火箭势在必得的黄蜂和复仇心切的快船.而在四月份,还有一个6连客在等待着他们.火箭要想进入PLAYOFF的话,在这魔鬼般的20场比赛里起码要拿下14场也就是70%的胜率,在TMAC和威思利都受伤的情况下,这已经不能说是严峻的考验,而完全算是一个不可能完成的任务.如果从纸面上的实力分析,如果对手完全正常发挥而火箭其他球员不超常,那么就算YM在这20场比赛里场场拿下30/10,火箭胜利的场次也不会超过5场.<BR>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<BR>&nbsp;&nbsp; &nbsp;事实上除了发生奇迹外,火箭成绩不佳而YM数据出色是最后20场里可能出现的最乐观的情况了.但如果真的出现这种情况,不要天真的指望美国媒体会因为YM数据出色就把他说成孤胆英雄,他们才不会把火箭成绩不佳的责任归结给赛程,角色球员的实力和病榻上的TMAC.无视YM的努力,把他说成一个无法领导球队的软蛋和废物才是他们的方式.不要怀疑,整整四年以来,他们一直在不遗余力的这么做.绝对不要去奢望他们会给YM一个公平的评价.<BR><BR>&nbsp;&nbsp; &nbsp;很奇怪,当YM面对不可能的任务和很可能随之而来的不公正的评价的时候,我这个要迷居然一点也不为他担心,估计这也是看YM打球多年锻炼出来的吧.因为从YM出道那天开始,挑战不可能的任务对他来说就像家常便饭一样.我已经记不清这些年来他搞定了多少所谓的"不可能"了.<BR><BR>&nbsp;&nbsp; &nbsp;还记得十年前吗?如果有人跟我说,那个在卢家湾体育场上一场比赛要摔20个跟头的大竹杆有一天会超过WZZ,会颠覆八一王朝,我肯定会对他蔑视的一笑,连"不可能"这三个字都懒得说,而如果谁当时说YM会进NBA,而且会成为状元秀,他身旁的朋友说不定会立刻煽他一耳光,告诉他:你Y快醒醒,别TMD大白天说梦话.<BR><BR>&nbsp;&nbsp; &nbsp;还记得四年前吗?NBA的名宿查尔斯爵士曾级毫不犹豫的宣布,单场19分是YM不可能完成的任务,他甚至为此打赌在几亿电视观众面前去亲驴屁股.<BR><BR>&nbsp;&nbsp; &nbsp;还记得两年前的夏天吗?全世界的人都认为中国队不可能战胜塞黑进入奥运会8强,连被许多人说成BT要迷的CCTV5都放弃对YM的期望了,CCTV5先是在下午的奥运会报道里调侃YM的胡子,接下来更是在塞黑和中国的生死大战前一个小时就宣布八强对阵是欧洲冠军立陶宛对世界冠军塞黑,<BR><BR>&nbsp;&nbsp; &nbsp;就算上面那些往事你都记不清了,那你总不会忘记就在仅仅三个月以前,还有9成的球迷不相信今年的YM可以打出20/10的平均数据,认为这绝对是不可能的任务吧.<BR><BR>&nbsp;&nbsp; &nbsp;当然这次YM面对的挑战比上面那些更加可怕,以火箭现在的情况和赛程来看,想要进PLAYOFF,就算是状态最佳时的飞人乔丹来了,没有逆天的好运气也是完全没有希望的.理性的来看,火箭胜少负多是肯定的,甚至很有可能像去年的KB和前年的MD那样20场比赛里1胜N败.<BR><BR>&nbsp;&nbsp; 但我相信YM不会被失败击垮,就算在接下来的20场比赛里全负,就算NBA.COM的首页大标题变成"YM是个废物."我仍然相信他不会垮.因为如果他是一个这么容易就趴下的人,早在十几年前,姚妈妈领着还是孩子的YM满怀希望的去看国内的篮球名宿,却得到了一句:"没有天赋,难成大气,远不及WZZ."的评语的时候,他就会放弃NBA的梦想了如果YM是那么容易放弃的人,那么早在02年先是国家队兵败世界锦标赛和釜山亚运会,然后他作为NBA状元却在第一场比赛一分为得的时候就垮了.正因为过去这些种种的压力和不公正的评价他都抗了过去,所以我相信不管接下来的火箭队成绩如何,不管美国的专家媒体在赛季结束会给YM一个什么样的评价,他都会精神饱满的出现在今年夏天的世界锦标赛上,穿上国家队的战袍,像全世界展现他FIBA比赛里第一中锋的威力.而在接下来的06-07赛季,他也一定会再次生龙活虎的去继续搏杀,毫不迟疑的面对挑战.<BR><BR>&nbsp;&nbsp; &nbsp;我最早看YM打球的时候也不喜欢他,直到他去了NBA才出于同胞的原因开是支持他.如今看YM打球看了这么多年,虽然谈不上对真正的YM有多么了解,但也多少可以看到他某些真实的一面.YM作为一个来自篮球第三世界的外籍球员,能够在身体素质BT如云的NBA走到今天这步,绝对不是靠他那除了身高外一无是处的身体素质.扒掉这个男人所谓天才的外衣,真正支持他成功的是他惊人的勤奋和面对挫折时超乎寻常的坚强意志.正像YM的主教练范甘迪说的那样,任何一个人如果能像YM那么努力的话,他都会取得自己所能取得的最大成功.在NBA里,凭借父母给的好身板而在生理上比YM"硬汉"的人多得数不过来,但这些人中能在心理上比YM坚强的"硬汉"却只是屈指可数.而这才是是我现在喜欢,相信YM的最大原因.<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/35197.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2006-03-14 11:16 <a href="http://www.blogjava.net/jinfeng_wang/archive/2006/03/14/35197.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Comparing Web Frameworks (zz)</title><link>http://www.blogjava.net/jinfeng_wang/archive/2005/04/30/3959.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Sat, 30 Apr 2005 03:01:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2005/04/30/3959.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/3959.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2005/04/30/3959.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/3959.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/3959.html</trackback:ping><description><![CDATA[<P>download URL : <A href="https://equinox.dev.java.net/framework-comparison/WebFrameworks.pdf">https://equinox.dev.java.net/framework-comparison/WebFrameworks.pdf</A><BR><BR>Comparing Web Frameworks: <BR>Struts, Spring MVC, WebWork, Tapestry &amp; <BR>JSF <BR>Matt Raible <BR><A href="http://www.raibledesigns.com/">www.raibledesigns.com</A> <BR>!ww.raibledesigns.co"</P>
<P>Who is Matt Raible? <BR>. Developing websites since 1994 (before Netscape 1.0) <BR>- Developing in J2EE webapps since 1999 <BR>. Committer on several open source projects:Roller <BR>Weblogger, XDoclet, Struts Menu, Display Tag, AppFuse <BR>. J2EE 5.0 Expert Group Member <BR>. Author: Spring Live (SourceBeat) and contributor to <BR>Pro JSP (Apress) <BR>!ww.raibledesigns.co" !ww.springlive.co"</P>
<P>Framework Experience <BR>. Struts: used since June 2001 - same time 1.0 was <BR>released. <BR>. Spring MVC: used since January 2004 - before 1.0 <BR>was released. <BR>. WebWork: used since July 2004. <BR>. Tapestry: used since July 2004. <BR>. JSF: used since July 2004 - both Sun’s RI and <BR>MyFaces. <BR>!ww.raibledesigns.co"</P>
<P>Meet the Candidates <BR>!ww.raibledesigns.co"</P>
<P>Struts <BR>. Pros: <BR>. The “Standard” - lots of Struts jobs <BR>. Lots of information and examples <BR>. HTML tag library is one of the best <BR>. Cons: <BR>. ActionForms - they’re a pain <BR>. Can’t unit test - StrutsTestCase only does integration <BR>. Mailing list volume is overwhelming <BR>!ww.raibledesigns.co"</P>
<P>Spring MVC <BR>!ww.raibledesigns.co" <BR>. Pros: <BR>. Lifecyle for overriding binding, validation, etc. <BR>. Integrates with many view options seamlessly: JSP/JSTL, <BR>Tiles, Velocity, FreeMarker, Excel, XSL, PDF <BR>. Inversion of Control makes it easy to test <BR>. Cons: <BR>. Not many using it <BR>. Requires writing lots of code in JSPs <BR>. Almost too flexible - no common parent Controller</P>
<P>WebWork <BR>!ww.raibledesigns.co" <BR>. Pros: <BR>. Simple architecture - easy to extend <BR>. Tag Library is easy to customize - backed by Velocity <BR>. Interceptors are pretty slick <BR>. Cons: <BR>. Documentation only recently written, few examples <BR>. Client-side validation immature</P>
<P>Tapestry <BR>!ww.raibledesigns.co" <BR>. Pros: <BR>. Very productive once you learn it <BR>. Templates are HTML - great for designers <BR>. Healthy and smart user community <BR>. Cons: <BR>. Documentation very conceptual, rather than pragmatic <BR>. Steep learning curve - very few examples <BR>. Impossible to test - page classes are abstract</P>
<P>JSF <BR>!ww.raibledesigns.co" <BR>. Pros: <BR>. J2EE Standard - lots of demand and jobs <BR>. Fast and easy to develop with <BR>. Rich Navigation framework <BR>. Cons: <BR>. Tag soup for JSPs <BR>. Immature technology - doesn’t come with everything <BR>. No single source for implementation</P>
<P>Controllers and Views <BR>. Struts: UserAction extends DispatchAction <BR>. Spring MVC: UserFormController extends <BR>SimpleFormController <BR>. WebWork: UserAction extends ActionSupport <BR>. Tapestry: UserForm extends BasePage <BR>. JSF: UserForm <BR>!ww.raibledesigns.co"</P>
<P>List Screens <BR>. How easy is it to integrate a sortable/ <BR>pageable list of data? <BR>. Struts, Spring MVC and WebWork can all <BR>use Tag Libraries like the Display Tag <BR>. Tapestry has a contrib:Table component <BR>. JSF has a dataTable with no sorting - have <BR>to write your own logic if you want it <BR>!ww.raibledesigns.co"</P>
<P>Bookmarking and URLs <BR>. Using container-managed authentication (or other filterbased <BR>security systems) allow users to bookmark pages. <BR>They can click the bookmark, login and go directly to the <BR>page. <BR>. WebWork has namespaces - makes it easy <BR>. Struts and Spring allow full URL control <BR>. Tapestry has ugly URLs - difficult to segment the app for <BR>different roles <BR>. JSF does a POST for everything <BR>!ww.raibledesigns.co"</P>
<P>Validation <BR>. Validation should be easy to configure, be robust on the <BR>client side and either provide good out of the box messages <BR>or allow you to easily customize them. <BR>. Struts and Spring MVC use Commons Validator - a <BR>mature solution <BR>. WebWork uses OGNL for powerful expressions - <BR>client-side support very new <BR>. Tapestry has very robust validation - good messages <BR>without need to customize <BR>. JSF - ugly default messages, but easiest to configure <BR>!ww.raibledesigns.co"</P>
<P>Testability <BR>. Struts - can use StrutsTestCase <BR>. Spring and WebWork allow easy testing with <BR>mocks (i.e. EasyMock, jMock, Spring Mocks) <BR>. Tapestry is impossible to test because page classes <BR>are abstract <BR>. JSF page classes can be easily tested and actually <BR>look a lot like WebWork actions <BR>!ww.raibledesigns.co"</P>
<P>Success Messages <BR>. The duplicate-post problem, what is it? <BR>. Easiest way to solve: redirect after POST <BR>. Struts is the only framework that allows success <BR>messages to live through a redirect <BR>. Spring and WebWork require custom solutions <BR>. Tapestry requires you to throw an Exception to redirect <BR>. JSF requires a custom solution, i18n messages difficult to <BR>get in page beans <BR>!ww.raibledesigns.co"</P>
<P>Spring Integration <BR>. All frameworks have integration with Spring <BR>. Struts: ContextLoaderPlugin and Base classes <BR>. WebWork: SpringObjectFactory <BR>. Tapestry: override base engine, grab from servlet <BR>context, put into global map <BR>. JSF: DelegateVariableResolver or JSF-Spring Library <BR>!ww.raibledesigns.co"</P>
<P>Internationalization <BR>. JSTL’s &lt;fmt:message&gt; tag makes it easy <BR>. No standard for getting i18n messages in <BR>controller classes <BR>. Struts, Spring and JSF encourage one <BR>ResourceBundle per locale <BR>. WebWork and Tapestry advocate separate <BR>files for each page/action <BR>!ww.raibledesigns.co"</P>
<P>Page Decoration <BR>. Used Tiles since it first came out in 2001 <BR>. SiteMesh is much easier to setup and use <BR>. Tiles can be used in Struts, Spring and JSF <BR>. Requires configuration for each page <BR>. SiteMesh can be used with all frameworks <BR>. Requires very little maintenance after <BR>setup <BR>!ww.raibledesigns.co"</P>
<P>Tools <BR>. Struts has a lot of IDE support and even has <BR>frameworks built on top of it (i.e. Beehive’s <BR>PageFlow) <BR>. Spring has Spring IDE - only does XML validation, <BR>not a UI/web tool <BR>. WebWork has none <BR>. Tapestry has Spindle - great for coders <BR>. JSF has many, all cost money and hook into <BR>proprietary app servers <BR>!ww.raibledesigns.co"</P>
<P>Business/Marketing <BR>. Struts is still in high-demand and widely-used <BR>. Spring is getting more press, but mostly due to the <BR>framework’s other features <BR>. WebWork is gaining ground, but pretty scarce on <BR>job boards <BR>. Tapestry is even more scarce - needs more <BR>marketing <BR>. JSF is quickly becoming popular <BR>!ww.raibledesigns.co"</P>
<P>Dice Job Count <BR>October 15, 2004 <BR>0 <BR>375 <BR>750 <BR>1,125 <BR>1,500 <BR>Struts <BR>Spring Framework <BR>WebWork <BR>Tapestry <BR>JSF <BR>!ww.raibledesigns.co"</P>
<P>My Opinion <BR>. Struts is fast to develop with because most problems have <BR>been solved. HTML tag library the best of the bunch. <BR>. Spring is nice, but lack of form tags drops it down a notch <BR>or two. JSP 2.0 tag files exist in issue tracker. <BR>. I like WebWork a lot, but lack of of good client-side <BR>validation support is a killer. <BR>. Tapestry - I haven’t finished the learning curve. <BR>. JSF - needs to listen to developers to see what they want <BR>instead of tools vendors. <BR>!ww.raibledesigns.co"</P>
<P>Which would I choose? <BR>. Quick and dirty project? <BR>. Struts because I know it best <BR>. Massive enterprise project? <BR>. Tapestry for its reusable components <BR>. If I got a job as an open source developer? <BR>. WebWork because using it requires you <BR>to dig into the frameworks <BR>!ww.raibledesigns.co"</P>
<P>Resources <BR>. Download sample apps for this presentation <BR>. <A href="http://equinox.dev.java.net/framework-comparison">http://equinox.dev.java.net/framework-comparison</A> <BR>. Struts - <A href="http://struts.apache.org/">http://struts.apache.org</A> <BR>. StrutsTestCase: <A href="http://strutstestcase.sf.net/">http://strutstestcase.sf.net</A> <BR>. Spring MVC - <A href="http://www.springframework.org/">http://www.springframework.org</A> <BR>. Spring IDE: <A href="http://www.springframework.org/spring-ide/eclipse">http://www.springframework.org/spring-ide/eclipse</A> <BR>. WebWork - <A href="http://opensymphony.org/webwork">http://opensymphony.org/webwork</A> <BR>. Eclipse Plugin: <A href="http://sf.net/projects/eclipsework">http://sf.net/projects/eclipsework</A> <BR>. IDEA Plugin: <A href="http://wiki.opensymphony.com/display/WW/IDEA+Plugin">http://wiki.opensymphony.com/display/WW/IDEA+Plugin</A> <BR>!ww.raibledesigns.co"</P>
<P>Resources, cont. <BR>. Tapestry - <A href="http://jakarta.apache.org/tapestry">http://jakarta.apache.org/tapestry</A> <BR>. Spindle: <A href="http://spindle.sourceforge.net/">http://spindle.sourceforge.net</A> <BR>. JSF - <A href="http://java.sun.com/j2ee/javaserverfaces">http://java.sun.com/j2ee/javaserverfaces</A> and http:// <BR>myfaces.org <BR>. Java Studio Creator: <A href="http://sun.com/software/products/jscreator">http://sun.com/software/products/jscreator</A> <BR>. MyEclipse: <A href="http://myeclipseide.com/">http://myeclipseide.com</A> <BR>. IDEA: <A href="http://www.jetbrains.com/idea">http://www.jetbrains.com/idea</A> <BR>. SiteMesh: <A href="http://opensymphony.com/sitemesh">http://opensymphony.com/sitemesh</A> <BR>!ww.raibledesigns.co"</P>
<P>Resources, cont. <BR>. Testing Frameworks <BR>. JUnit: <A href="http://junit.org/">http://junit.org</A> <BR>. EasyMock: <A href="http://easymock.org/">http://easymock.org</A> <BR>. jMock: <A href="http://jmock.org/">http://jmock.org</A> <BR>. jWebUnit: <A href="http://jwebunit.sourceforge.net/">http://jwebunit.sourceforge.net</A> <BR>. Canoo WebTest: <A href="http://webtest.canoo.com/">http://webtest.canoo.com</A> <BR>. XDoclet - <A href="http://xdoclet.sourceforge.net/">http://xdoclet.sourceforge.net</A> <BR>. AppFuse - <A href="http://appfuse.dev.java.net/">http://appfuse.dev.java.net</A> <BR>!ww.raibledesigns.co"</P>
<P>Books <BR>. Struts in Action, Ted Husted and Team <BR>. Struts Live, Rick Hightower and Jonathan Lehr <BR>. Spring Live, Matt Raible <BR>. Spring in Action, Craig Walls and Ryan Breidenbach <BR>. Professional Java Development with Spring, Rod <BR>Johnson, Juergen Hoeller and Team</P>
<P>Books, cont. <BR>. WebWork in Action, Patrick Lightbody and Team <BR>. Tapestry in Action, Howard Lewis Ship <BR>. Core JSF, David Geary and Cay Horstmann <BR>. JSF in Action, Kito Mann</P>
<P>The End <BR>...or is it just the beginning... <BR>!ww.raibledesigns.co"</P>
<P>&nbsp;</P><img src ="http://www.blogjava.net/jinfeng_wang/aggbug/3959.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2005-04-30 11:01 <a href="http://www.blogjava.net/jinfeng_wang/archive/2005/04/30/3959.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习的一个过程(zz)</title><link>http://www.blogjava.net/jinfeng_wang/archive/2005/04/30/3958.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Sat, 30 Apr 2005 02:59:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2005/04/30/3958.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/3958.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2005/04/30/3958.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/3958.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/3958.html</trackback:ping><description><![CDATA[<FONT face=Arial size=2>学习的一个过程<BR><BR>头一天听到XX事物，啊，真是个好东东....一定要学好它<BR>第二天，学习了一下，啊太难了，太麻烦了....鬼知道人们为什么说他好<BR>第三天，仔细用了一下，原来这么简单，简直是太简单了，这么简单的东东，居然这么多人说好<BR>第三天，看起来，自己对它的了解还不够啊<BR>第四天，不是不够而是非常不够，看起来还得认真学习<BR>第五天，再也不敢说对它有了解了，简直是高深莫测啊<BR>第六天，感觉这个东东比较有意思，原来还可以这个样子的啊<BR>第七天，好象这么做，就可以完成以前不敢想的事情了<BR>第八天，现在用得很好了，你个呆瓜，怎么说这个东东不好？o原来你是菜鸟啊<BR>第九天，这个东东，如果能这样一些就更好了。</FONT><BR><BR><BR>对照一下自己，学的好多东西都还是停留在3、4、5啊！ 叹～<img src ="http://www.blogjava.net/jinfeng_wang/aggbug/3958.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2005-04-30 10:59 <a href="http://www.blogjava.net/jinfeng_wang/archive/2005/04/30/3958.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SiteMesh  resources(zz)</title><link>http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3192.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Tue, 12 Apr 2005 13:42:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3192.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/3192.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3192.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/3192.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/3192.html</trackback:ping><description><![CDATA[<P class=paragraph>SiteMesh is a web-page layout and decoration framework and web- application integration framework to aid in creating large sites consisting of many pages for which a consistent look/feel, navigation and layout scheme is required.</P>
<H3 class=heading3><A name=Index-ExternalDocumentation>External Documentation </A></H3>
<UL class=star>
<LI><SPAN class=nobr><A title="Visit page outside Confluence" href="http://www.opensymphony.com/sitemesh/">Documentation<SUP><IMG class=rendericon height=7 alt="" src="http://wiki.opensymphony.com/images/icons/linkext7.gif" width=7 align=absMiddle border=0></SUP></A></SPAN> - documentation and a description of SiteMesh 
<LI><SPAN class=nobr><A title="Visit page outside Confluence" href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html"><FONT color=#ff0000>Will Iverson's Introduction to SiteMesh<SUP><IMG class=rendericon height=7 alt="" src="http://wiki.opensymphony.com/images/icons/linkext7.gif" width=7 align=absMiddle border=0></SUP></FONT></A></SPAN> 
<LI><SPAN class=nobr><A title="Visit page outside Confluence" href="http://www.opensymphony.com/sitemesh/api/">API JavaDocs<SUP><IMG class=rendericon height=7 alt="" src="http://wiki.opensymphony.com/images/icons/linkext7.gif" width=7 align=absMiddle border=0></SUP></A></SPAN> 
<LI><SPAN class=nobr><A title="Visit page outside Confluence" href="http://www.opensymphony.com/sitemesh/tags.html">JSP Tag Reference<SUP><IMG class=rendericon height=7 alt="" src="http://wiki.opensymphony.com/images/icons/linkext7.gif" width=7 align=absMiddle border=0></SUP></A></SPAN> 
<LI><SPAN class=nobr><A title="TSS - SiteMesh.ppt attached to Index" href="http://wiki.opensymphony.com/download/attachments/144/TSS+-+SiteMesh.ppt?version=1"><FONT color=#ff0000>SiteMesh Presentation</FONT><SUP><IMG class=rendericon height=7 alt="" src="http://wiki.opensymphony.com/images/icons/link_attachment_7.gif" width=7 align=absMiddle border=0></SUP></A></SPAN> - SiteMesh presentation <SPAN class=nobr><A title="View profile for Mike Cannon-Brookes" href="http://wiki.opensymphony.com/display/~mike"><SUP><IMG class=rendericon height=12 alt="" src="http://wiki.opensymphony.com/images/icons/user_12.gif" width=12 align=absMiddle border=0></SUP>Mike Cannon-Brookes</A></SPAN> gave at <SPAN class=nobr><A title="Visit page outside Confluence" href="http://www.theserverside.com/symposium">TSSS<SUP><IMG class=rendericon height=7 alt="" src="http://wiki.opensymphony.com/images/icons/linkext7.gif" width=7 align=absMiddle border=0></SUP></A></SPAN> in Vegas. 
<LI><SPAN class=nobr><A title="Visit page outside Confluence" href="http://jroller.com/page/timosinko/20050124#using_velocity_as_sitemesh_decorator"><FONT color=#ff0000>Using Velocity as SiteMesh decorator with Spring framework</FONT> <SUP><IMG class=rendericon height=7 alt="" src="http://wiki.opensymphony.com/images/icons/linkext7.gif" width=7 align=absMiddle border=0></SUP></A></SPAN> 
<LI><SPAN class=nobr><A title="Visit page outside Confluence" href="http://bellsouthpwp.net/t/o/tooger/ajug/ajug_sitemesh.pdf"><FONT color=#ff0000>Jason Chambers' SiteMesh presentation to Atlanta Java Users Group</FONT><SUP><IMG class=rendericon height=7 alt="" src="http://wiki.opensymphony.com/images/icons/linkext7.gif" width=7 align=absMiddle border=0></SUP></A></SPAN> </LI></UL>
<H3 class=heading3><A name=Index-UserContributeddocs>User Contributed docs</A></H3>
<UL class=star>
<LI><A title=Explorations href="http://wiki.opensymphony.com/display/SM/Explorations">Explorations</A> 
<LI><A title="SiteMesh on Tomcat vs Weblogic" href="http://wiki.opensymphony.com/display/SM/SiteMesh+on+Tomcat+vs+Weblogic">SiteMesh on Tomcat vs Weblogic</A> 
<LI><A title="Compare Sitemesh - Tiles" href="http://wiki.opensymphony.com/pages/viewpage.action?pageId=244">Compare Sitemesh - Tiles</A> 
<LI><A title="Server Compatibility" href="http://wiki.opensymphony.com/display/SM/Server+Compatibility">Server Compatibility</A> </LI></UL>
<H3 class=heading3><A name=Index-ReleaseNotes>Release Notes</A></H3>
<UL class=star>
<LI><A title="Release Notes 2.2" href="http://wiki.opensymphony.com/display/SM/Release+Notes+2.2">Release Notes 2.2</A> 
<LI><A title="Release Notes 2.1" href="http://wiki.opensymphony.com/display/SM/Release+Notes+2.1">Release Notes 2.1</A> </LI></UL>
<H3 class=heading3><A name=Index-DeveloperNotes>Developer Notes</A></H3>
<UL class=star>
<LI><A title="SiteMesh 3 Roadmap" href="http://wiki.opensymphony.com/display/SM/SiteMesh+3+Roadmap">SiteMesh 3 Roadmap</A> </LI></UL><img src ="http://www.blogjava.net/jinfeng_wang/aggbug/3192.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2005-04-12 21:42 <a href="http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3192.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用sitemesh建立复合视图(ZZ)</title><link>http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3191.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Tue, 12 Apr 2005 13:31:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3191.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/3191.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3191.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/3191.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/3191.html</trackback:ping><description><![CDATA[(作者:chen-neu ,提供给<FONT color=green><EM> </EM>huihoo.com</FONT> 发布) <BR><BR>
<P><FONT size=2><B>sitemesh是opensymphony团队开发的j2ee应用框架之一，旨在提高页面的可维护性和复用性。opensymphony的另一个广为人知的框架为webwork是用作web层的表示框架。他们都是开源的，可以在www.sf.net下找到。</B></FONT></P>
<P><FONT size=2><B>应用于以下大项目的例子：http://opensource.thoughtworks.com/projects/sitemesh.html</B></FONT></P>
<UL>
<LI><A href="http://www.jboss.org/">www.jboss.org</A> 
<LI><A href="http://www.theserverside.com/">www.theserverside.com</A> 
<LI><A href="http://www.opensymphony.com/">www.opensymphony.com</A> 
<LI><A href="http://www.atlassian.com/">www.atlassian.com</A> </LI></UL>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD width="100%" bgColor=#000080 height=19><FONT color=#ffffff size=2>简介：</FONT> </TD></TR>
<TR>
<TD width="100%" height=63><FONT size=2>sitemesh应用Decorator模式，用filter截取request和response,把页面组件head,content,banner结合为一个完整的视图。通常我们都是用include标签在每个jsp页面中来不断的包含各种header, stylesheet, scripts and footer，现在，在sitemesh的帮助下，我们可以开心的删掉他们了。如下图，你想轻松的达到复合视图模式，那末看完本文吧。</FONT> 
<P><IMG height=495 src="http://www.huihoo.com/java/sitemesh/index_example-diagram.gif" width=704></P>
<P>　</P></TD></TR>
<TR>
<TD width="100%" bgColor=#000080 height=19><FONT color=#ffffff size=2>hello sitemesh：</FONT> </TD></TR>
<TR>
<TD width="100%" height=15>
<OL>
<LI><FONT size=2>在WEB-INF/web.xml中copy以下filter的定义:</FONT> 
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="80%" border=1>
<TBODY>
<TR>
<TD width="100%" bgColor=#efefef><PRE class=codeblock>&lt;filter&gt;
  &lt;filter-name&gt;sitemesh&lt;/filter-name&gt;
  &lt;filter-class&gt;com.opensymphony.module.sitemesh.filter.PageFilter&lt;/filter-class&gt;
&lt;/filter&gt;

&lt;filter-mapping&gt;
  &lt;filter-name&gt;sitemesh&lt;/filter-name&gt;
  &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;

&lt;taglib&gt;
  &lt;taglib-uri&gt;sitemesh-decorator&lt;/taglib-uri&gt;
  &lt;taglib-location&gt;/WEB-INF/sitemesh-decorator.tld&lt;/taglib-location&gt;
&lt;/taglib&gt;

&lt;taglib&gt;
  &lt;taglib-uri&gt;sitemesh-page&lt;/taglib-uri&gt;
  &lt;taglib-location&gt;/WEB-INF/sitemesh-page.tld&lt;/taglib-location&gt;
&lt;/taglib&gt;
</PRE></TD></TR></TBODY></TABLE><FONT size=2><BR></FONT>
<LI><FONT size=2>copy所需jar和dtd文件至相应目录，访问<A href="http://opensymphony.sourceforge.net/">opensymphony.sourceforge.net</A>的cvs以获取sitemesh最新版本。</FONT> 
<TABLE width="80%" border=0>
<TBODY>
<TR>
<TD width="35%"><FONT size=2>sitemesh.jar</FONT></TD>
<TD width="65%"><FONT size=2>WEB-INF/lib</FONT> </TD></TR>
<TR>
<TD width="35%"><FONT size=2>sitemesh-decorator.tld</FONT></TD>
<TD width="65%"><FONT size=2>WEB-INF</FONT> </TD></TR>
<TR>
<TD width="35%"><FONT size=2>sitemesh-page.tld</FONT></TD>
<TD width="65%"><FONT size=2>WEB-INF</FONT> </TD></TR></TBODY></TABLE><FONT size=2><BR></FONT>
<LI><FONT size=2>建立</FONT><FONT size=2>WEB-INF/</FONT><FONT size=2>decorators.xml描述各装饰器页面(可仿照sitemesh例子)。</FONT> 
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="80%" bgColor=#efefef border=1>
<TBODY>
<TR>
<TD width="100%"><PRE><FONT size=2>&lt;decorators defaultdir="/_decorators"&gt;
    &lt;decorator name="main" page="main.jsp"&gt;
        &lt;pattern&gt;*&lt;/pattern&gt;
    &lt;/decorator&gt;
&lt;/decorators&gt;</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2><BR><BR></FONT></P>
<LI><FONT size=2>建立装饰器页面 /_decorators/main.jsp<BR></FONT>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="80%" bgColor=#efefef border=1>
<TBODY>
<TR>
<TD width="100%"><PRE><FONT size=2>&lt;%@ page contentType="text/html; charset=GBK"%&gt;
&lt;%@ taglib uri="sitemesh-decorator" prefix="decorator" %&gt;

&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;&lt;decorator:title default="装饰器页面..." /&gt;&lt;/title&gt;
    &lt;decorator:head /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    sitemesh的例子&lt;hr&gt;
    &lt;decorator:body /&gt;
    &lt;hr&gt;chen56@msn.com
  &lt;/body&gt;
&lt;/html&gt;
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2><BR></FONT></P>
<LI><FONT size=2>建立一个的被装饰页面 /index.jsp(内容页面)</FONT> 
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="80%" bgColor=#efefef border=1>
<TBODY>
<TR>
<TD width="100%"><PRE><FONT size=2>&lt;%@ page contentType="text/html; charset=GBK"%&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Agent Test&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p&gt;本页只有一句，就是本句.&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</FONT></PRE></TD></TR></TBODY></TABLE></LI></OL>
<P><FONT size=2>最后访问index.jsp，将生成如下页面：</FONT> 
<P><FONT size=2><IMG height=363 src="http://www.huihoo.com/java/sitemesh/index_sitemesh.jpg" width=411 border=0></FONT> 
<P><FONT size=2>而且，所有的页面也会如同index.jsp一样，被sitemesh的filter使用装饰模式修改成如上图般模样，却不用再使用include标签。<BR><BR><BR>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD width="100%" bgColor=#000080 height=19><B><FONT color=#ffffff size=2>装饰器&nbsp; decorator概念</FONT></B> </TD></TR>
<TR>
<TD width="100%" height=63><FONT size=2>建立可复用的web应用程序,一个通用的方法是建立一个分层系统，如同下面一个普通的web应用：</FONT> 
<UL>
<LI><FONT size=2>前端，front-end:JSP和Servlets，或jakarta的velocity</FONT> 
<LI><FONT size=2>控制层框架 Controller ： (Struts/Webwork)</FONT> 
<LI><FONT size=2>业务逻辑 Business ：主要业务逻辑</FONT> 
<LI>
<P><FONT size=2>持久化框架 ：hibernate/jdo</FONT></P></LI></UL>
<P><FONT size=2>可糟糕的是前端的页面逻辑很难被复用，当你在每一个页面中用数之不尽的include来复用公共的header, stylesheet, scripts，footer时，一个问题出现了-重复的代码，每个页面必须用copy来复用页面结构，而当你需要创意性的改变页面结构时，灾难就爱上了你。</FONT></P>
<P><FONT size=2>sitemesh通过filter截取request和response，并给原始的页面加入一定的装饰(可能为header,footer...)，然后把结果返回给客户端，并且被装饰的原始页面并不知道sitemesh的装饰，这也就达到了脱耦的目的。</FONT></P>
<P><FONT size=2>据说即将新出台的Portlet规范会帮助我们标准的实现比这些更多更cool的想法，但可怜的我还不懂它到底是一个什末东东，有兴趣的人可以研究<BR><A href="http://jakarta.apache.org/jetspeed">jetspeed</A>，或<A href="http://www.jcp.org/en/jsr/detail?id=168">JSR (Java Specification Request) 168</A>,但我想sitemesh如此简单，我们不妨先用着。</FONT></P>
<P>　</P></TD></TR>
<TR>
<TD width="100%" bgColor=#000080 height=19><B><FONT color=#ffffff size=2>让我们看看怎样配置环境</FONT> </B></TD></TR>
<TR>
<TD width="100%" height=15><FONT size=2>除了要copy到WEB-INF/lib中的sitemesh.jar, </FONT><FONT size=2>copy到WEB-INF中的sitemesh-decorator.tld,sitemesh-page.tld文件外，还有2个文件要建立到WEB-INF/：</FONT> 
<UL>
<LI><FONT size=2>sitemesh.xml (可选)&nbsp;&nbsp;</FONT> 
<LI><FONT size=2>decorators.xml&nbsp;</FONT> </LI></UL>
<H2><FONT size=2>sitemesh.xml&nbsp;可以设置2种信息:</FONT></H2>
<P><FONT size=2><B>Page Parsers</B> ：负责读取stream的数据到一个Page对象中以被SiteMesh解析和操作。(不太常用，默认即可)</FONT></P>
<P><FONT size=2><B>Decorator Mappers</B>&nbsp;: 不同的装饰器种类，我发现2种比较有用都列在下面。一种通用的mapper,可以指定装饰器的配置文件名，另一种可打印的装饰器，可以允许你当用http://localhost/aaa/a.html?printable=true方式访问时给出原始页面以供打印(免得把header,footer等的花哨的图片也搭上)<BR><BR><I>(但一般不用建立它，默认设置足够了：com/opensymphony/module/sitemesh/factory/sitemesh-default.xml）：</I></FONT> </P>
<P><FONT size=2><B>范例：</B></FONT> </P>
<TABLE style="BORDER-COLLAPSE: collapse" height=1 cellSpacing=0 cellPadding=0 width="100%" bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD width="100%"><CODE><FONT size=2>&lt;sitemesh&gt;<BR>&nbsp;&nbsp;&lt;page-parsers&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;parser default="true" class="com.opensymphony.module.sitemesh.parser.DefaultPageParser" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.FastPageParser" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;parser content-type="text/html;charset=ISO-8859-1" class="com.opensymphony.module.sitemesh.parser.FastPageParser" /&gt;<BR>&nbsp;&nbsp;&lt;/page-parsers&gt;<BR><BR>&nbsp;&nbsp;&lt;decorator-mappers&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param name="config" value="/WEB-INF/decorators.xml" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/mapper&gt;<BR></FONT></CODE><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;mapper class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="decorator" value="printable" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="parameter.name" value="printable" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="parameter.value" value="true" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/mapper&gt;<CODE><BR>&nbsp;&nbsp;</CODE></FONT><CODE><FONT size=2>&lt;/decorator-mappers&gt;<BR>&lt;/sitemesh&gt; </FONT></CODE></TD></TR></TBODY></TABLE>
<P><FONT size=2><B>decorators.xml</B>&nbsp;：定义构成复合视图的所有页面构件的描述(主要结构页面，header,footer...)，如下例：</FONT></P>
<TABLE style="BORDER-COLLAPSE: collapse" height=1 cellSpacing=0 cellPadding=0 width="100%" bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD width="100%"><FONT size=2>&lt;decorators defaultdir="/_decorators"&gt;<BR>&nbsp; &lt;decorator name="main" page="main.jsp"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;pattern&gt;*&lt;/pattern&gt;<BR>&nbsp; &lt;/decorator&gt;<BR>&nbsp; &lt;decorator name="printable" page="printable.jsp" role="customer" webapp="aaa" /&gt;<BR>&lt;/decorators&gt;</FONT></TD></TR></TBODY></TABLE>
<P><FONT size=2></FONT>&nbsp;</P>
<UL>
<LI><FONT size=2>defaultdir: 包含装饰器页面的目录</FONT> 
<LI><FONT size=2>page : 页面文件名</FONT> 
<LI><FONT size=2>name : 别名</FONT> 
<LI><FONT size=2>role : 角色，用于安全</FONT> 
<LI><FONT size=2>webapp : 可以另外指定此文件存放目录</FONT> 
<LI><FONT size=2>Patterns : 匹配的路径，可以用*,那些被访问的页面需要被装饰。</FONT> </LI></UL>
<P><FONT size=2>　</FONT> </P></TD></TR>
<TR>
<TD width="100%" bgColor=#000080 height=13><B><FONT color=#ffffff size=2>最重要的是写出装饰器本身(也就是那些要复用页面，和结构页面)。</FONT></B> </TD></TR>
<TR>
<TD width="100%" height=15><FONT size=2>其实，重要的工作就是制作装饰器页面本身(也就是包含结构和规则的页面)，然后把他们描述到decorators.xml中。</FONT> 
<P><FONT size=2>让我们来先看一看最简单的用法：其实最常用也最简单的用法就是我们的hello例子，面对如此众多的技术，我想只要达到功能点到为止即可，没必要去研究太深(除非您有更深的需求)。</FONT></P>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="80%" bgColor=#efefef border=1>
<TBODY>
<TR>
<TD width="100%"><PRE><FONT size=2>&lt;%@ page contentType="text/html; charset=GBK"%&gt;
&lt;%@ taglib uri="sitemesh-decorator" prefix="decorator" %&gt;

&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;&lt;decorator:title default="装饰器页面..." /&gt;&lt;/title&gt;
    &lt;decorator:head /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    sitemesh的例子&lt;hr&gt;
    &lt;decorator:body /&gt;
    &lt;hr&gt;chen56@msn.com
  &lt;/body&gt;
&lt;/html&gt;
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>我们在装饰器页面只用了2个标签：</FONT></P>
<P><FONT size=2>&lt;decorator:title default="装饰器页面..." /&gt;&nbsp;&nbsp;&nbsp; ： 把请求的原始页面的title内容插入到&lt;title&gt;&lt;/title&gt;中间。</FONT></P>
<P><FONT size=2>&lt;decorator:body /&gt; ： 把请求的原始页面的body内的全部内容插入到相应位置。</FONT></P>
<P><FONT size=2>然后我们在decorator.xml中加入以下描述即可： </FONT></P>
<P><FONT size=2>&lt;decorator name="main" page="main.jsp"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;pattern&gt;*&lt;/pattern&gt;<BR>&lt;/decorator&gt;<BR></FONT></P>
<P><FONT size=2>这样，请求的所有页面都会被重新处理，并按照main.jsp的格式重新展现在你面前。</FONT></P>
<P>　 </P></TD></TR>
<TR>
<TD width="100%" bgColor=#000080 height=19><B><FONT color=#ffffff size=2>让我们看看更多的用法。(抄袭sitemesh文档)</FONT></B> </TD></TR>
<TR>
<TD width="100%" height=15><FONT size=2>以下列着全部标签：</FONT> 
<TABLE width="80%" align=center>
<TBODY>
<TR>
<TD vAlign=top><STRONG><FONT size=2>Decorator Tags</FONT></STRONG></TD>
<TD vAlign=top><STRONG><FONT size=2>Page Tags</FONT></STRONG></TD></TR>
<TR>
<TD vAlign=top><FONT size=2>被用于建立装饰器页面.</FONT></TD>
<TD vAlign=top><FONT size=2>被用于从原始内容页面访问装饰器.</FONT></TD></TR>
<TR>
<TD vAlign=top><FONT size=3><A href="http://www.huihoo.com/java/sitemesh/2.html#decorator:head"><CODE>&lt;decorator:head /&gt;</CODE></A><BR><A href="http://www.huihoo.com/java/sitemesh/2.html#decorator:body"><CODE>&lt;decorator:body /&gt;</CODE></A><BR><A href="http://www.huihoo.com/java/sitemesh/2.html#decorator:title"><CODE>&lt;decorator:title /&gt;</CODE></A><BR><A href="http://www.huihoo.com/java/sitemesh/2.html#decorator:getProperty"><CODE>&lt;decorator:getProperty /&gt;</CODE></A><BR><A href="http://www.huihoo.com/java/sitemesh/2.html#decorator:usePage"><CODE>&lt;decorator:usePage /&gt;</CODE></A><BR></FONT></TD>
<TD vAlign=top><FONT size=3><A href="http://www.huihoo.com/java/sitemesh/2.html#page:applyDecorator"><CODE>&lt;page:applyDecorator /&gt;</CODE></A><BR><A href="http://www.huihoo.com/java/sitemesh/2.html#page:param"><CODE>&lt;page:param</CODE></A></FONT></TD></TR></TBODY></TABLE>　 
<P><STRONG><A name=decorator:head><FONT size=2>&lt;decorator:head /&gt;</FONT></A></STRONG></P>
<P><FONT size=2>插入原始页面(被包装页面)的head标签中的内容(不包括head标签本身)。</FONT></P><STRONG><A name=decorator:body><FONT size=2>&lt;decorator:body /&gt;</FONT></A></STRONG> 
<P><FONT size=2>插入原始页面(被包装页面)的body标签中的内容。</FONT></P>
<P><STRONG><A name=decorator:title><FONT size=2>&lt;decorator:title [ default="..." ] /&gt;</FONT></A></STRONG></P>
<P><FONT size=2>插入原始页面(被包装页面)的<A name=decorator:title>title</A>标签中的内容，还可以添加一个缺省值。</FONT></P>
<P><FONT size=2>例：</FONT></P>
<P><FONT size=2>/_decorator/main.jsp中 （装饰器页面）: &lt;title&gt;</FONT><A name=decorator:title><FONT size=2>&lt;decorator:title default="却省title-hello"&nbsp; /&gt;</FONT></A><FONT size=2><A name=decorator:title> - 附加标题</A>&lt;/title&gt;</FONT></P>
<P><FONT size=2>/aaa.jsp中 (原始页面)：&lt;title&gt;<A name=decorator:title>aaa页面</A>&lt;/title&gt;</FONT></P>
<P><FONT size=2>访问/aaa.jsp的结果：&lt;title&gt;<A name=decorator:title>aaa页面</A> <A name=decorator:title>- 附加标题</A>&lt;/title&gt;</FONT></P>
<P><STRONG><A name=decorator:getProperty><FONT size=2>&lt;decorator:getProperty property="..." [ default="..." ] [ writeEntireProperty="..." ]/&gt;</FONT></A></STRONG></P>
<P><FONT size=2>在标签处插入原始页面(被包装页面)的原有的<A name=decorator:title>标签的属性</A>中的内容，还可以添加一个缺省值。</FONT></P>
<P><FONT size=2>sitemesh文档中的例子很好理解：</FONT><BR><FONT size=2>The decorator: </FONT><FONT size=3><CODE>&lt;body bgcolor="white"&lt;decorator:getProperty property="body.onload" writeEntireProperty="true" /&gt;&gt;</CODE><BR></FONT><FONT size=2>The undecorated page: </FONT><FONT size=3><CODE>&lt;body onload="document.someform.somefield.focus();"&gt;</CODE><BR></FONT><FONT size=2>The decorated page: </FONT><FONT size=3><CODE>&lt;body bgcolor="white" onload="document.someform.somefield.focus();"&gt;</CODE></FONT></P>
<P><FONT size=2><STRONG>注意，</STRONG></FONT><CODE><FONT size=2>writeEntireProperty="true"会在插入内容前加入一个空格。</FONT></CODE></P>
<P><FONT size=2><STRONG><A name=decorator:usePage>&lt;decorator:usePage id="..." /&gt;</A></STRONG><BR>象jsp页面中的&lt;jsp:useBean&gt;标签一样，可以使用被包装为一个Page对象的页面。 (懒的用)</FONT></P>
<P><FONT size=2>例：可用<A name=decorator:usePage>&lt;decorator:usePage id="page" /&gt;<STRONG> ：</STRONG></A></FONT><A name=decorator:usePage><FONT size=3>&lt;%=</FONT></A><FONT size=3><CODE><NOBR>page.getTitle()%&gt;达到</NOBR>&lt;decorator:title/&gt;的访问结果。</CODE></FONT></P>
<P>　</P>
<P><FONT size=2><A name=page:applyDecorator><STRONG>&lt;page:applyDecorator name="..." [ page="..." title="..." ] &gt;<BR></STRONG></A><STRONG><A name=page:param>&lt;page:param name="..."&gt; ... &lt;/page:param&gt;</A></STRONG><BR><STRONG><A name=page:param>&lt;page:param name="..."&gt; ... &lt;/page:param&gt;</A><BR>&lt;/page:applyDecorator&gt;</STRONG></FONT></P>
<P><FONT size=2>应用包装器到指定的页面上，一般用于被包装页面中主动应用包装器。这个标签有点不好理解，我们来看一个例子：</FONT></P>
<P><FONT size=2>包装器页面 /_decorators/panel.jsp：&lt;p&gt;&lt;decorator:title /&gt;&lt;/p&gt;&nbsp; ... &lt;p&gt;&lt;decorator:body /&gt;&lt;/p&gt;<BR>&nbsp; 并且在decorators.xml中有&lt;decorator name="panel" page="panel.jsp"/&gt;<BR><BR>一个公共页面，即将被panel包装：/_public/date.jsp:&nbsp;&nbsp;<BR>&nbsp; ... &lt;%=new java.util.Date()%&gt;&nbsp; ...&lt;decorator:getProperty property="myEmail" /&gt;<BR><BR>被包装页面 /page.jsp ：&nbsp;<BR>&nbsp; &lt;title&gt;page的应用&lt;/title&gt;&nbsp;<BR>&nbsp; .....&nbsp;&nbsp;</FONT><A name=page:applyDecorator><FONT size=2><BR>&nbsp; &lt;page:applyDecorator name="panel" page="/_public/date.jsp" &gt;<BR>&nbsp;&nbsp;&nbsp; &lt;page:param name="myEmail"&gt; chen_p@neusoft.com &lt;/page:param&gt;<BR>&nbsp; &lt;/page:applyDecorator&gt;<STRONG><BR></STRONG></FONT></A></P>
<P><FONT size=2>最后会是什末结果呢？除了/page.jsp会被默认的包装页面包装上header,footer外，page.jsp页面中还内嵌了date.jsp页面，并且此date.jsp页面还会被panel.jsp包装为一个title加body的有2段的页面，第1段是date.jsp的title，第2段是date.jsp的body内容。</FONT></P>
<P><FONT size=2>另外，<A name=page:applyDecorator>page:applyDecorator</A>中包含的page:param标签所声明的属性值还可以在包装页面中用</FONT><A name=decorator:getProperty><FONT size=2>decorator:getProperty</FONT></A><FONT size=2>标签访问到。<BR><BR></P>
<P><FONT size=2><B>前面的文章已经足以应用sitemesh来改善您的应用，但我发现还有一些其他的东东可能也会对大家有所帮助</B></FONT></P>
<P>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD width="100%" bgColor=#000080 height=19><FONT color=#ffffff size=2>可打印的界面装饰</FONT> </TD></TR>
<TR>
<TD width="100%" height=63><FONT size=2>前面说过有1种可打印的装饰器，可以允许你当用http://localhost/aaa/a.html?printable=true方式访问时，应用其他的装饰器(自己指定)，给出原始页面以供打印(免得把header,footer等的花哨的图片也搭上)。</FONT> 
<P><FONT size=2>让我们来看一看怎样实现他：</FONT></P>
<P><FONT size=2>1.首先在WEB-INFO/sitemesh.xml中设置：<BR>&nbsp; &lt;mapper class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;param name="decorator" value="printable" /&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;param name="parameter.name" value="printable" /&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;param name="parameter.value" value="true" /&gt;<BR>&nbsp; &lt;/mapper&gt;<BR>这样就可以通过?printable=true来使用名为printable的装饰器，而不是用原来的装饰器。</FONT></P>
<P><FONT size=2>2.在WEB-INFO/decorators.xml中定义相应的printable装饰器<BR>&nbsp; &lt;decorator name="printable" page="printable.jsp"/&gt;</FONT></P>
<P><FONT size=2>3.最后编写printable装饰器/decorators/printable.jsp </FONT></P>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="80%" bgColor=#efefef border=1>
<TBODY>
<TR>
<TD width="100%" bgColor=#efefef><FONT size=2>&lt;%@ taglib uri="sitemesh-decorator" prefix="decorator" %&gt;<BR>&lt;html&gt;<BR>&lt;head&gt;<BR>&nbsp; &lt;title&gt;&lt;decorator:title /&gt;&lt;/title&gt;<BR>&nbsp; &lt;decorator:head /&gt;<BR>&lt;/head&gt;<BR>&lt;body&gt;<BR><BR>&nbsp; &lt;h1&gt;&lt;decorator:title /&gt;&lt;/h1&gt;<BR>&nbsp; &lt;p align="right"&gt;&lt;i&gt;(printable version)&lt;/i&gt;&lt;/p&gt;<BR><BR>&nbsp; &lt;decorator:body /&gt;<BR><BR>&lt;/body&gt;<BR>&lt;/html&gt;</FONT></TD></TR></TBODY></TABLE>
<P><FONT size=2>这样就可以让一个原始页面通过?printable=true开关来切换不同的装饰器页面。</FONT></P>
<P>　 </P></TD></TR></TBODY></TABLE>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD width="100%" bgColor=#000080 height=19><FONT color=#ffffff size=2>中文问题</FONT></TD></TR>
<TR>
<TD width="100%" height=63><FONT size=2>由于sitemesh内部所使用的缺省字符集为iso-8859-1，直接使用会产生乱码，我们可以通过以下方法纠正之：</FONT> 
<UL>
<LI><FONT size=2>方法1：可以在您所用的application server的配置文件中找一找，有没有设置encoding或<CODE></CODE></FONT><CODE><FONT size=2>charset的项目，然后设成gbk或gb2312即可</FONT></CODE> 
<LI><CODE><FONT size=2>方法2：这也是我们一直使用的方法。<BR>1.在每一个jsp页里设置: &lt;%@ page contentType="text/html; charset=gbk"%&gt; 来告诉server你所要求的字符集。<BR>2.在每个jsp页的head中定义：&lt;META HTTP-EQUIV="content-type" CONTENT="text/html; charset=gbk"&gt; 来告诉浏览器你所用的字符集。</FONT></CODE> </LI></UL></TD></TR></TBODY></TABLE>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 height=1 cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD width="100%" bgColor=#000080 height=19><FONT color=#ffffff size=2>总结：使用sitemesh最通常的途径：</FONT></TD></TR>
<TR>
<TD width="100%" height=15>
<P><FONT size=2>1.配置好环境，</FONT> 
<P><FONT size=2>2.在WEB-INFO/decroators.xml中描述你将建立的包装器。</FONT> 
<P><FONT size=2>3.开发在decroators.xml中描述的包装器，最好存放在/_decorators目录下</FONT></P>
<P><FONT size=2>4.ok ，可以看看辛勤的成果了 :)</FONT></P></TD></TR></TBODY></TABLE></P>
<HR color=#ff0000 SIZE=1>

<P><FONT color=#ff0000 size=2><B>资源：</B></FONT></P>
<UL>
<LI><FONT size=2><A href="http://www.huihoo.com/java/sitemesh/@test/sitemesh-cvs-2003-08-13_test-2003-08-21.zip">下载我提供的ant build的例子&nbsp;</A>&nbsp;<BR>我在j2sdk-1_4_0,tomcat4.0.3和tomcat5下测试通过，请先运行/build.bat,以生成/dist/web.war文件，然后实施到你的服务器即可。<BR></FONT>
<LI><FONT size=2>opensymphony团队的项目集合：<BR><A href="http://sourceforge.net/projects/opensymphony">http://sourceforge.net/projects/opensymphony</A> <BR></FONT>
<LI><SPAN class=nav><A href="http://wiki.opensymphony.com/"><FONT size=2>Wiki ：http://wiki.opensymphony.com/<BR></FONT></A></SPAN>
<LI><SPAN class=nav><A href="http://sourceforge.net/cvs/?group_id=9890"><FONT size=2>在sf的cvs上下载最新版本CVS</FONT></A></SPAN> </LI></UL>
<P class=MsoNormal><B><FONT color=#ff0000 size=2>关于作者：</FONT></B></P>
<P class=MsoNormal><FONT size=2>陈鹏，西安东软公司。作为一名狂热的程序员希望每一天都能成长进步，并希望与大家分享快乐和知识。<BR>请用以下方式和他联系：email <A href="mailto:chen56@msn.com">chen56@msn.com</A> &nbsp;</FONT></P></FONT></TD></TR></TBODY></TABLE></FONT></P></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/jinfeng_wang/aggbug/3191.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2005-04-12 21:31 <a href="http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3191.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Introduction to SiteMesh(zz)</title><link>http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3190.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Tue, 12 Apr 2005 13:27:00 GMT</pubDate><guid>http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3190.html</guid><wfw:comment>http://www.blogjava.net/jinfeng_wang/comments/3190.html</wfw:comment><comments>http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3190.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jinfeng_wang/comments/commentRss/3190.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jinfeng_wang/services/trackbacks/3190.html</trackback:ping><description><![CDATA[<!--  content here  --><!-- CS_PAGE_BREAK -->
<H2><IMG height=91 alt="Introduction to SiteMesh" hspace=10 src="http://today.java.net/images/tiles/111-sitemesh.gif" width=111 align=left border=0> Introduction to SiteMesh</H2>by <A href="http://today.java.net/pub/au/13">Will Iverson</A><BR>03/11/2004<BR clear=all><BR><!--  sidebar begins  --><!--  don't move sidebars  --><!--  sidebar ends  --><!--  sidebar begins  --><!--  TOC  -->
<TABLE cellSpacing=0 cellPadding=0 align=right border=0>
<TBODY>
<TR>
<TD bgColor=#000000><IMG height=1 src="http://today.java.net/im/a.gif" width=10></TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=6 align=right border=0>
<TBODY>
<TR>
<TD><IMG height=1 src="http://today.java.net/im/a.gif" width=10><BR><B>Contents</B></TD></TR>
<TR>
<TD><A href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html#How_Does_It_Work">How Does It Work?</A></TD></TR>
<TR>
<TD><A href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html#Installing_SiteMesh">Installing SiteMesh</A></TD></TR>
<TR>
<TD>&nbsp;&nbsp;&nbsp;<A href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html#web_xml"><I>web.xml</I></A></TD></TR>
<TR>
<TD>&nbsp;&nbsp;&nbsp;<A href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html#decorators_xml"><I>decorators.xml</I></A></TD></TR>
<TR>
<TD>&nbsp;&nbsp;&nbsp;<A href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html#decorators_jsp"></I>decorators/*.jsp</I></A></TD></TR>
<TR>
<TD>&nbsp;&nbsp;&nbsp;<A href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html#sitemesh_jar"><I>sitemesh-2.0.1.jar</I></A></TD></TR>
<TR>
<TD>&nbsp;&nbsp;&nbsp;<A href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html#tld"><I>*.tld</I></A></TD></TR>
<TR>
<TD><A href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html#Advanced_SiteMesh">Advanced SiteMesh</A></TD></TR>
<TR>
<TD><A href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html#Summary">Summary</A></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD bgColor=#000000><IMG height=1 src="http://today.java.net/im/a.gif" width=10></TD></TR></TBODY></TABLE><!--  sidebar ends  -->
<P>In the past, I used to build my web applications the old-fashioned way: handcrafting assembly, carefully building my raw byte handlers to work with Unicode, counting instructions, and using make files to target different CPUs.</P>
<P>OK, maybe not.</P>
<P>Although I've never actually felt the need to build my web application with assembly (CISC or RISC), I sometimes think my fellow developers are on a quest to make their development processes as painful as possible. In particular, I've seen many developers agonize over the best way to handle basic web application building blocks: things like headers, footers, navigation bars, support for printable pages, light-weight pages for handheld devices, and more. In the end, things like includes and brute-force copy-and-paste win out surprisingly often.</P>
<P>In my experience, I've been able to easily solve these problems cleanly, easily, and elegantly using the open source servlet filter <A href="http://www.opensymphony.com/sitemesh/">SiteMesh</A>, which is <A href="http://sitemesh.dev.java.net/">hosted on java.net</A>. Instead of requiring a new templating language, XSLT, or "porting" your pages to a new system, using SiteMesh often allows you to dramatically simplify your pages while still using ordinary HTML, JSP, servlets (including Struts), and other familiar technologies.</P>
<H2 id=How_Does_It_Work>How Does It Work?</H2>
<P>SiteMesh implements a page filter, taking advantage of one of the lesser-known features of the servlet specification. Let's imagine you have a simple JSP that returns the current date and time. Ordinarily, the request for the page comes in to the application server, the page is rendered, and then the results are returned to the web browser. SiteMesh, as a page filter, takes the page after it is rendered and performs additional processing before returning the document to the web browser. This change is most simply described as the additional step shown between Figure 1 and Figure 2. </P>
<P><IMG height=202 alt="Figure 1" src="http://today.java.net/images/2004/03/sitemesh_fig1.gif" width=532><BR><EM>Figure 1. Normal Page Rendering</EM></P>
<P><IMG height=202 alt="Figure 2" src="http://today.java.net/images/2004/03/sitemesh_fig2.gif" width=532><BR><EM>Figure 2. SiteMesh Page Rendering</EM></P>
<P>Let's look at a simple example of this. Consider the following simple JSP:</P><PRE><CODE>&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Simple Document&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        Hello World! &lt;br /&gt;
        &lt;%= 1+1 %&gt;
        &lt;/body&gt;
&lt;/html&gt;</CODE></PRE>
<P>You'll notice that the page has a title and a body (like any ordinary HTML page). You'll notice a tiny bit of JSP code -- this will be rendered just as you would expect. Indeed, you can use any and all features that you would expect, and you link between the various JSP and other resources just as you might expect. </P>
<P>Now, let's look at a simple SiteMesh "decorator" page. Listing 2 shows a JSP page, called by SiteMesh.</P><PRE><CODE>&lt;%@ taglib uri="sitemesh-decorator"
prefix="decorator" %&gt;
&lt;html&gt;
 &lt;head&gt;
 &lt;title&gt;
 My Site - &lt;decorator:title default="Welcome!" /&gt;
 &lt;/title&gt;
 &lt;decorator:head /&gt;
 &lt;/head&gt;
 &lt;body&gt;
 &lt;h1&gt;&lt;decorator:title default="Welcome!" /&gt;&lt;/h1&gt;
 &lt;p&gt;&lt;decorator:body /&gt;&lt;/p&gt; 
 &lt;p&gt;&lt;small&gt;
 (&lt;a 
    href="?printable=true"&gt;printable version&lt;/a&gt;)
    &lt;/small&gt;&lt;/p&gt;
 &lt;/body&gt;
&lt;/html&gt;</CODE></PRE>
<P>Looking at the decorator, we can see a few interesting things. First, a SiteMesh taglib is introduced in the first line. This taglib includes everything required to work with the original page. You can see that we use two of the SiteMesh declared tags, <CODE>&lt;decorator:title&gt;</CODE> and <CODE>&lt;decorator:body&gt;</CODE>. Not surprisingly, the <CODE>&lt;decorator:title&gt;</CODE> returns the contents of the <CODE>&lt;title&gt;</CODE> tag in the original page, and <CODE>&lt;decorator:body&gt;</CODE> the content. We're making a few fairly radical changes to the page, including repeating the title both in the <CODE>HEAD</CODE> element as well as the <CODE>BODY</CODE>. We're also adding a link to a printable version of the page.</P>
<P>For comparison, Figure 3 shows the rendered original page and Figure 4 the rendered decorated page. Notice the appearance of the title text both in the browser window title bar and in the HTML of the page in the decorated page. You'll also notice that we added a printable page link, as well -- we'll come back to this later. </P>
<P><IMG height=186 alt="Figure 3" src="http://today.java.net/images/2004/03/sitemesh_fig3.gif" width=309><BR><EM>Figure 3. Original Undecorated Page</EM></P>
<P><IMG height=299 alt="Figure 4" src="http://today.java.net/images/2004/03/sitemesh_fig4.gif" width=309><BR><EM>Figure 4. Decorated Page</EM></P>
<P>Obviously, this is a much cleaner system for applying traditional header and footer content than using include directives (such as <CODE>&lt;jsp:include page="foo.jsp" flush="true" /&gt;</CODE>). It's much more flexible and natural, and encourages JSP pages with no navigation or other presentation data. I have found that a combination of decorators and CSS overrides of standard HTML tags allows me to virtually eliminate formatting information from my JSP pages.</P>
<H2 id=Installing_SiteMesh>Installing SiteMesh</H2>
<P>Note that the screenshots, etc. are based on Windows XP Professional, <A href="http://jakarta.apache.org/tomcat/index.html">Tomcat 5.0.19</A>, and Java 2 SDK 1.4.2_03. I'm going to assume that you have installed and are able to get Tomcat working. You might have to tweak things slightly, but I've gotten all of this to work fine on Tomcat 4.1 and WebLogic as well, and SiteMesh lists many other supported web application servers. </P>
<P>SiteMesh 2.0.1, the version described in this article, can be downloaded <A href="https://sitemesh.dev.java.net/servlets/ProjectDocumentList?folderID=542">here</A>. There are four files available for download from SiteMesh's java.net project repository. The <I>sitemesh-2.0.1.jar</I> file is just the core JAR file, <I>sitemesh-2.0.1-sources.zip</I> is self-describing, and <I>sitemesh-example.war</I> provides a complex example showing some of SiteMesh's more advanced features.</P>
<P>To keep things simple, we'll start with the <A href="https://sitemesh.dev.java.net/files/documents/887/2097/sitemesh-example.war"><I>sitemesh-blank.war</I></A> file, building and modifying as we go along. Instead of just dropping the WAR file into our Tomcat <I>webapps</I> directory, we'll crack open the WAR open and drop it in uncompressed, as shown in Figure 5.</P>
<P><IMG height=255 alt="Figure 5" src="http://today.java.net/images/2004/03/sitemesh_fig5.gif" width=201><BR><EM>Figure 5. SiteMesh Blank WAR Contents</EM></P>
<P>There are a number of files here, so let's take a moment to describe what they do.</P>
<H5 id=web_xml><I>web.xml</I></H5>
<P>First, the <I>WEB-INF/web.xml</I> file, shown in Listing 3, contains directives to install the SiteMesh filter and the taglib libraries. If you're adding SiteMesh to an existing web application, you'll need to add these directives to your <I>WEB-INF/web.xml</I> file. </P><PRE><CODE>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
 &lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;    
&lt;web-app&gt;    
 &lt;!-- Start of SiteMesh stuff --&gt;    
 &lt;filter&gt;
 &lt;filter-name&gt;sitemesh&lt;/filter-name&gt;
     &lt;filter-class&gt;com.opensymphony.module.sitemesh.filter.PageFilter&lt;/filter-class&gt;
 &lt;/filter&gt;    
 &lt;filter-mapping&gt;
    &lt;filter-name&gt;sitemesh&lt;/filter-name&gt;
 &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;
 &lt;/filter-mapping&gt;    
 &lt;taglib&gt;
    &lt;taglib-uri&gt;sitemesh-page&lt;/taglib-uri&gt;
    &lt;taglib-location&gt;/WEB-INF/sitemesh-page.tld&lt;/taglib-location&gt;
 &lt;/taglib&gt;    
 &lt;taglib&gt;
    &lt;taglib-uri&gt;sitemesh-decorator&lt;/taglib-uri&gt;
     &lt;taglib-location&gt;/WEB-INF/sitemesh-decorator.tld&lt;/taglib-location&gt;
 &lt;/taglib&gt;    
 &lt;!-- End of SiteMesh stuff --&gt;    
&lt;/web-app&gt;</CODE></PRE>
<P>Note: you'll notice that I've flagged the <CODE>url-pattern</CODE> line -- if you are using Tomcat 5 (instead of Tomcat 4) you'll need to change the pattern from the default <CODE>*</CODE> to something like <CODE>*.jsp</CODE>. The <CODE>*</CODE> pattern is not allowed under the latest servlet specification.</P>
<H5 id=decorators_xml><I>decorators.xml</I></H5>
<P>The <I>WEB-INF/decorators.xml</I> file is used to bind a decorator name to a specific JSP decorator file. So, for example, we might bind a decorator named <CODE>handheld</CODE> to the JSP page decorator <CODE>minimal.jsp</CODE>.</P><PRE><CODE>&lt;decorators defaultdir="/decorators"&gt;
 &lt;decorator name="main" page="main.jsp"&gt;
 &lt;pattern&gt;*&lt;/pattern&gt;
 &lt;/decorator&gt;
 
 &lt;decorator name="panel" page="panel.jsp"/&gt;
 &lt;decorator name="printable" page="printable.jsp"/&gt;
&lt;/decorators&gt;</CODE></PRE>
<P>As we can see in this code listing, we define three decorators, and then bind them to three similarly named JSP pages. We also see that the default decorator, <CODE>main.jsp</CODE>, will be applied for files by default.</P>
<P>By default, SiteMesh will use the following logic to determine what decorator to apply:</P><!--  sidebar begins  -->
<TABLE cellSpacing=12 cellPadding=6 width=200 align=right border=0>
<TBODY>
<TR>
<TD vAlign=top bgColor=#efefef>
<P>This logic is expressed in described in the <EM>sitemesh-2.0.1.jar</EM> file at <EM>\com\opensymphony\module\sitemesh\factor\sitemesh-default.xml</EM>. You can override this behavior with a wide variety of <A href="http://www.opensymphony.com/sitemesh/api/com/opensymphony/module/sitemesh/mapper/package-summary.html">built-in mappers </A>for things like language, client operating system, web browser/user agent, etc. by creating a <EM>WEB-INF\sitemesh.xml</EM> file. You'll find an example of this included in the <EM>sitemesh-example.war</EM> file.</P></TD></TR></TBODY></TABLE><!--  sidebar ends  -->
<OL>
<LI>Does the page specifically request a decorator using a meta decorator tag? 
<LI>Is the page a frame set (if so, don't apply a decorator)? 
<LI>Does the page have a <CODE>printable=true</CODE> parameter&gt; (If so, use the printable decorator.) 
<LI>Does the page specifically request a decorator by the decorator file name? 
<LI>Does the page match a pattern in the <I>decorators.xml</I> file? </LI></OL>
<P>Conceptually, the first rule that evaluates to true determines the decorator that is used. In the example above, when the <CODE>printable=true</CODE> parameter is present, the <CODE>printable.jsp</CODE> decorator (rule #3) is used instead of the <CODE>main.jsp</CODE> (matched in rule #5). In SiteMesh, these rules are described as <I>mappers</I>. </P>
<H5 id=decorators_jsp><I>decorators/*.jsp</I></H5>
<P>The three files in the decorators directory are the various decorator JSP files, as described by <I>decorators.xml</I>. We saw an example of a simple decorator above, and we'll look at a more sophisticated example later in this article.</P>
<H5 id=sitemesh_jar><I>sitemesh-2.0.1.jar</I></H5>
<P>This is the main SiteMesh binary, typically installed in the <I>WEB-INF/lib</I> directory. You can find the Javadoc for this library at <A href="http://www.opensymphony.com/sitemesh/api/">www.opensymphony.com/sitemesh/api</A>.</P>
<H5 id=tld><I>*.tld</I></H5>
<P>SiteMesh uses two tag libraries, but most users will only need the decorator tags (<I>sitemesh-decorator.tld</I>). You can find documentation on these at <A href="http://www.opensymphony.com/sitemesh/tags.html">www.opensymphony.com/sitemesh/tags.html</A>. We've already touched on the main tags, used to retrieve the head, title, and body. We'll look at the remaining tag, <CODE>getProperty</CODE>, in the next section. </P>
<H2 id=Advanced_SiteMesh>Advanced SiteMesh</H2>
<P>One of the more powerful abilities of SiteMesh is to use the ordinary HTML <CODE>meta</CODE> tag (for example, <CODE>&lt;meta name="foo" content="bar"&gt;</CODE>) to pass information from the base page to the decorator. For example, let's say that we would like to define the author of an HTML page using a <CODE>meta</CODE> tag, as shown below. </P><PRE><CODE>&lt;html&gt;
    &lt;meta name="author" content="test@example.com"&gt;
    &lt;head&gt;
        &lt;title&gt;Simple Document&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        Hello World! &lt;br /&gt;
        &lt;%= 1+1 %&gt;
        &lt;/body&gt;
&lt;/html&gt;</CODE></PRE>
<P>We can make a decorator "smart" enough to know to look for this <CODE>meta</CODE> tag, and if present, generate the appropriate HTML:</P><PRE><CODE>&lt;%@ taglib uri="sitemesh-decorator" prefix="decorator" %&gt;
 &lt;decorator:usePage id="myPage" /&gt;
 &lt;html&gt;
 &lt;head&gt;
 &lt;title&gt;My Site -
    &lt;decorator:title default="Welcome!" /&gt;
 &lt;/title&gt;
 &lt;decorator:head /&gt;
 &lt;/head&gt;

 &lt;body&gt;
 &lt;h1&gt;&lt;decorator:title default="Welcome!" /&gt;&lt;/h1&gt;
 &lt;h3&gt;
 &lt;a href="mailto:&lt;decorator:getProperty property="meta.author" 
            default="staff@example.com" /&gt;"&gt;
 &lt;decorator:getProperty property="meta.author"
              default="staff@example.com" /&gt;
 &lt;/a&gt;&lt;/h3&gt;&lt;hr /&gt;
 &lt;decorator:body /&gt;
 &lt;p&gt;&lt;small&gt;
    (&lt;a href="?printable=true"&gt;printable version&lt;/a&gt;)
    &lt;/small&gt;
 &lt;/p&gt;
 &lt;/body&gt;
 &lt;/html&gt;</CODE></PRE>
<P>You'll notice that we use a default attribute in the <CODE>getProperty</CODE> tag -- if no author is specified, we'll just assume that it was written by the staff. If you decide to use this model for storing page metadata, you'll want to work with your content developers and other team members to determine what tags you want to use and how you'll be using them. At the simple end, you may want to use <CODE>meta</CODE> tags to describe things like the author and page timestamp. At the complex end, you may do things like standardize on an XML file to manage your site navigation and use a <CODE>meta</CODE> tag to pass the page's node to the decorator. </P>
<P>The page that results from applying this decorator to the JSP page above is shown in Figure 6.</P>
<P><IMG height=359 alt="Figure 6" src="http://today.java.net/images/2004/03/sitemesh_fig6.gif" width=392><BR><EM>Figure 6. <CODE>meta</CODE> Tag Displayed</EM></P>
<P>These page attributes are powerful, and you can retrieve many different properties, not just the <CODE>meta</CODE> tags (here's <A href="http://www.opensymphony.com/sitemesh/api/com/opensymphony/module/sitemesh/HTMLPage.html">a list of generated page properties</A>). After using SiteMesh for a while, you'll start thinking about HTML and JSP as a mechanism for generating simple markup -- closer to the original intent of HTML -- without having to make a full switch to an XML/XSL or other template engine.</P>
<H2 id=Summary>Summary</H2>
<P>As we've seen, SiteMesh provides for a powerful, easy-to-use, non-intrusive mechanism for applying page templates. It's easy to envision a wide range of possible uses. For example, you might define a decorator that emits extra debugging information about the page, as determined by the browser (this is especially powerful when combined with a web browser that lets you set an arbitrary user-agent). You might define a decorator with a stripped-down XML output, allowing for easier automated testing. You can even use the decorator to grab content from other pages, for example, to simple portal-like capability.</P>
<P>Once you've gotten comfortable with <I>sitemesh-blank.war</I>, I'd suggest looking at <I>sitemesh-example.war</I> for more features and ideas.</P>
<P>Regardless of how you use SiteMesh, I've found that it lets me centralize a tremendous amount of code, moving it out of my presentation layer and into my decorators, without having to learn a new programming language or templating system. </P>
<P>Oh, and as a final note for those of you still interested in building web pages in assembly, check out <A href="http://home.worldonline.dk/viksoe/asmil.htm">home.worldonline.dk/viksoe/asmil.htm</A>.</P>
<P>Good luck and happy coding!</P>
<P><EM><A href="http://today.java.net/pub/au/13">Will Iverson</A> served as Developer Relations Manager for the VisualCafé group at Symantec, as the Java &amp; Runtimes Product Manager at Apple Computer and has led Cascade Technology Group, a private consulting firm, since 1999.</EM></P><img src ="http://www.blogjava.net/jinfeng_wang/aggbug/3190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2005-04-12 21:27 <a href="http://www.blogjava.net/jinfeng_wang/archive/2005/04/12/3190.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>