﻿<?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-与心灵对话-随笔分类-Java</title><link>http://www.blogjava.net/dongwq/category/24878.html</link><description>过去理解的，现在未必理解。
过去懂得的，重温必有新意。
整理过去，整理现在。成就现在，成就未来。</description><language>zh-cn</language><lastBuildDate>Thu, 25 Nov 2010 10:48:42 GMT</lastBuildDate><pubDate>Thu, 25 Nov 2010 10:48:42 GMT</pubDate><ttl>60</ttl><item><title>div的visibility和display属性的区别</title><link>http://www.blogjava.net/dongwq/archive/2010/09/14/331970.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Tue, 14 Sep 2010 05:47:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2010/09/14/331970.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/331970.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2010/09/14/331970.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/331970.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/331970.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&#8226;&nbsp;&nbsp;前者：看见与不看见，但是位置保留。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8226;&nbsp;&nbsp;后者处理与位置有关：block,&nbsp;inline,&nbsp;none&nbsp;分别是有前后换行，不换行，不显示功能但是不保留位置。<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&#8226;&nbsp;&nbsp;二者功能差异：保留位置，和位置形式<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">script&nbsp;language</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">javascript</span><span style="color: #000000;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;toggleVisibility(me)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(me.style.visibility</span><span style="color: #000000;">==</span><span style="color: #000000;">"</span><span style="color: #000000;">hidden</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;me.style.visibility</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">visible</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;me.style.visibility</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">hidden</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">script</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">DIV&nbsp;&nbsp;onclick</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">toggleVisibility(this)</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;style</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">position:relative</span><span style="color: #000000;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;第一行文本将会触发</span><span style="color: #000000;">"</span><span style="color: #000000;">hidden</span><span style="color: #000000;">"</span><span style="color: #000000;">和</span><span style="color: #000000;">"</span><span style="color: #000000;">visible</span><span style="color: #000000;">"</span><span style="color: #000000;">属性，注意第二行的变化。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">DIV</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">DIV</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">因为visibility会保留元素的位置，所以第二行不会移动.</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">DIV</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">script&nbsp;language</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">javascript</span><span style="color: #000000;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;toggleDisplay(me){<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(me.style.display</span><span style="color: #000000;">==</span><span style="color: #000000;">"</span><span style="color: #000000;">block</span><span style="color: #000000;">"</span><span style="color: #000000;">){<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;me.style.display</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">inline</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000;">"</span><span style="color: #000000;">文本现在是：'inline'.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(me.style.display</span><span style="color: #000000;">==</span><span style="color: #000000;">"</span><span style="color: #000000;">inline</span><span style="color: #000000;">"</span><span style="color: #000000;">){<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;me.style.display</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">none</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000;">"</span><span style="color: #000000;">文本现在是:'none'.3秒钟后自动重新显示。</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;window.setTimeout(</span><span style="color: #000000;">"</span><span style="color: #000000;">blueText.style.display='block';</span><span style="color: #000000;">"</span><span style="color: #000000;">,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">3000</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="color: #000000;">javascript</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;me.style.display</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">block</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000;">"</span><span style="color: #000000;">文本现在是:'block'.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">script</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">DIV</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">在</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">span&nbsp;id</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">blueText</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;onclick</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">toggleDisplay(this)</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;style</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">color:blue;position:relative;cursor:hand;</span><span style="color: #000000;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;蓝色</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">span</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">文字上点击来查看效果.</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">DIV</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
</span></div><img src ="http://www.blogjava.net/dongwq/aggbug/331970.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2010-09-14 13:47 <a href="http://www.blogjava.net/dongwq/archive/2010/09/14/331970.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>项目经理之修炼(8)——别忘了告诉别人你是谁 </title><link>http://www.blogjava.net/dongwq/archive/2010/09/08/331412.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Wed, 08 Sep 2010 09:02:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2010/09/08/331412.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/331412.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2010/09/08/331412.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/331412.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/331412.html</trackback:ping><description><![CDATA[<h3><a href="http://laosunisme.javaeye.com/blog/756250">项目经理之修炼(8)——别忘了告诉别人你是谁 </a></h3>
<strong>文章分类:<a style="padding-right: 10px; text-decoration: none" href="http://www.javaeye.com/blogs/category/develop">软件开发管理</a></strong>
<div class="blog_content">副标题——名不正言不顺，项目管理难度加倍 <br />
<br />
你能想象美国总统上任，却没有总统就职仪式吗？ <br />
你能想象北京奥林匹克运动会，没有开幕式表演吗？？ <br />
OK。相信你一定见过这样的场景： <br />
某老板匆匆忙忙地进了屋，忽地来了一嗓子：&#8220;大家静静，通知大家一下：以后，某项目就由小张负责了！&#8221; <br />
<br />
************************************************** <br />
<br />
话说楚汉相争。刘邦在萧何的再三举荐下，决定让韩信为大将。 <br />
<br />
&#8220;来人，叫韩信过来，我要封他为大将。&#8221;刘邦道。 <br />
<br />
萧何表示异议：&#8220;汉王你一向傲慢没有礼貌，现在拜大将就和喊一个小孩子那么随便，所以韩信才会离开的。汉王要想用人家，必须选一个吉日，吃素，设祭坛，用非常郑重地礼节来拜将才行。&#8221;刘邦同意萧何的意见。 <br />
<br />
结果，尽管韩信是个无名小卒，却顺利的接过了军权，而没有碰到那些元老们的抵抗，成功地导演了一幕幕战争奇迹。 <br />
<br />
************************************************** <br />
<br />
登台拜将，是一件具有深刻管理内涵的故事。它告诉我们这样一个道理： <br />
——内容是重要的，但形式却是不容忽视。 <br />
<br />
我们不求老板非要在某个公开场合悠扬地宣告：&#8220;某项目成立了!!小张从此站起来了！！！&#8221;什么吉日，什么斋戒，什么礼仪。。。也就罢了。 <br />
<br />
但是，不给正式任命书；不在正式场合公布；甚至连一个头衔都舍不得。这绝对是没天理的。 <br />
<br />
************************************************** <br />
<br />
&#8220;看，老板不重视这个项目。。。&#8221;（相关人员） <br />
&#8220;瞧，老板不重视这个家伙。估计这个家伙没有什么后台&#8221; （相关人员） <br />
&#8220;你负责某项目？我怎么不知道有这么个项目呢？你是哪位啊？&#8221; （相关人员） <br />
&#8220;老板似乎并不重视/信任我啊&#8221; （项目经理） <br />
<br />
*************************************************** <br />
<br />
以上种种，对项目的推动极为不利的。尤其是手下有资深员工、或者项目经理候补者等挑战者的时候，问题将会加倍严重。 <br />
<br />
大家可能会怀疑：&#8220;没有那么严重吧？&#8221; <br />
没有不严重，只有更严重！！ <br />
这其中蕴含着一个深刻的道理——名不正则言不顺！！ <br />
<br />
言不顺是什么意思呢？ <br />
<br />
-你的意见可能被忽视； <br />
-你的命令可能被当作建议； <br />
-你的计划可能被别人忘记； <br />
试想，你如果是项目经理，你的项目将会怎样。。。。。。 <br />
<br />
********************************************************* <br />
<br />
Question: 我没有办法叫老板改变。那么，我该怎么办？ <br />
Answer：要写一封邮件！！告诉别人你是谁。 <br />
<br />
********************************************************* <br />
<br />
你的老板犯了错误，可是你不能将错就错！你的老板忽视了&#8220;名&#8221;的问题（形式问题），你一定要扳回来！！ <br />
试想，你的老板不重视，你也不重视，你能指望别人重视吗？？ <br />
当然，答案就是别人会更不重视！！ <br />
<br />
那么，这封邮件该怎么写呢？？ <br />
<br />
<br />
************************************************** <br />
<br />
MailTo: 所有下属 <br />
CC:&nbsp;&nbsp;&nbsp;&nbsp; 所有相关领导，所有相关人员，自己 <br />
Title:&nbsp; 【A项目】A项目的新项目经理小张向大家问好 <br />
Content: <br />
<br />
1 开门见山地告诉别人自己的位置（正名） <br />
2 向相关人员致敬，并自然地点出自己的优势（自我介绍） <br />
3 向领导致敬致谢（拉近和领导关系） <br />
4 暗示自己的权利范围（宣布自己的领地） <br />
5 喊两句口号（合作和积极的姿态是必要的） <br />
6 不要忘了签名（进一步加深印象） <br />
<br />
//其中，1、2、4是必须要表现出来的 <br />
<br />
************************************************** <br />
<br />
上面这封邮件，基本上完成了告诉别人你是谁的问题，而且完成了你的位置身份暗示。 <br />
如果说老板不负责任的任命形式带给你身份位置认同危机，沉重打击了你的威信的话， <br />
通过这份邮件，你已经用身份暗示这个武器，夺回了主动权！！ <br />
<br />
从这封信以后，由于你的身份位置的明确， <br />
相关人员在潜意识中会认同你的领地所有权， <br />
会对在你的领地上和你发生冲突产生不自然，不合法甚至负罪感， <br />
从而下意识中就会避免和你发生冲突。 <br />
<br />
反过来讲，你的位置身份的明确，将成为你自信的源泉， <br />
而这种位置感产生的自信将使你的发言充满了正义感， <br />
加上项目经理这个位置所带来的小小的势能。。。 <br />
权力这个东西，真好！！ <br />
<br />
嗯，一个好的开端，不是吗? <br />
</div><img src ="http://www.blogjava.net/dongwq/aggbug/331412.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2010-09-08 17:02 <a href="http://www.blogjava.net/dongwq/archive/2010/09/08/331412.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JS 函数的使用</title><link>http://www.blogjava.net/dongwq/archive/2010/07/25/327078.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Sun, 25 Jul 2010 07:38:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2010/07/25/327078.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/327078.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2010/07/25/327078.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/327078.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/327078.html</trackback:ping><description><![CDATA[<br />
<br />
1、函数定义和使用<br />
<p><font style="background-color: #c7edcc"></font>&nbsp;</p>
<p><font style="background-color: #c7edcc">&lt;script&gt;</font></p>
<p><font style="background-color: #c7edcc">function sqrt(x) {<br />
&nbsp;&nbsp;&nbsp; return x * x;<br />
}<br />
function other(f) {<br />
&nbsp;&nbsp;&nbsp; var y = f(10);<br />
&nbsp;&nbsp;&nbsp; return y;<br />
}</font></p>
<p><font style="background-color: #c7edcc">var farr = new Array();<br />
farr[0] = function(arg) { return arg + arg;};<br />
farr[1] = function(arg) { return arg * arg;};</font></p>
<p><font style="background-color: #c7edcc">document.write(farr[0](10) + '&lt;br/&gt;');<br />
document.write(farr[1](10));</font></p>
<p><font style="background-color: #c7edcc"></font>&nbsp;</p>
<p><font style="background-color: #c7edcc">document.write(other(sqrt));</font></p>
<p><font style="background-color: #c7edcc">&lt;/script&gt;</font></p>
<p><font style="background-color: #c7edcc">sqrt.count = 0; <br />
sqrt.getcount = function() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.count;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }; // 附加函式</font></p>
<p><font style="background-color: #c7edcc">//sqrt();<br />
document.write(sqrt.count, '&lt;br/&gt;');<br />
document.write(sqrt.getcount());<br />
</font></p><img src ="http://www.blogjava.net/dongwq/aggbug/327078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2010-07-25 15:38 <a href="http://www.blogjava.net/dongwq/archive/2010/07/25/327078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zz＜设计模式：java语言中的应用＞摘要、总结 收藏 </title><link>http://www.blogjava.net/dongwq/archive/2010/05/28/322156.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Fri, 28 May 2010 08:24:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2010/05/28/322156.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/322156.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2010/05/28/322156.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/322156.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/322156.html</trackback:ping><description><![CDATA[<p>＜设计模式：java语言中的应用＞摘要、总结 收藏 <br />
＜设计模式：java语言中的应用＞一书已经学完，现做个摘要、总结。</p>
<p>创建模式(Creational Patterns)<br />
Abstract Factory Builder<br />
Factory Method&nbsp; Prototype<br />
Singleton</p>
<p>结构模式(Structural Patterns)<br />
Adapter&nbsp; Bridge<br />
Composite Decorator<br />
Facade&nbsp; Flyweight<br />
Proxy</p>
<p>行为模式(Behavioral Pattern)<br />
Chain of Responsibility&nbsp; Command<br />
Interpreter&nbsp;&nbsp; Iterator<br />
Mediator&nbsp;&nbsp; Memento<br />
Observer&nbsp;&nbsp; State<br />
Strategy&nbsp;&nbsp; Template Method<br />
Visitor</p>
<p>一、创建模式(Creational Patterns)</p>
<p>1.Abstract Factory(抽象工厂)—把相关零件组合成产品<br />
&nbsp;Abstract Factory Pattern 是把各种抽象零件组合成抽象产品。换句话说，处理的重点是在接口(API)而不是零件的具体实现。只利用接口(API)就能把零件组合成产品.<br />
&nbsp;程序示例:<br />
&nbsp;--Main.java 测试用的类<br />
&nbsp;|-factory<br />
&nbsp;|&nbsp;&nbsp;&nbsp; |-------Factory.java 表示抽象工厂的类(产生Link,Tray,Page)<br />
&nbsp;|&nbsp;&nbsp;&nbsp; |-------Itme.java 用来统一处理Link和Tray的类<br />
&nbsp;|&nbsp;&nbsp;&nbsp; |-------Link.java 抽象零件:表示HTML连接的类<br />
&nbsp;|&nbsp;&nbsp;&nbsp; |-------Tray.java 抽象零件:抽取Link和Tray的类<br />
&nbsp;|&nbsp;&nbsp;&nbsp; |-------Page.java 抽象零件:表示HTML网页的类<br />
&nbsp;|<br />
&nbsp;|-listfactory<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------listFactory.java 表示具体工厂的类(产生ListLink,ListTray,ListPage)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------listLink.java 具体零件:表示HTML连接的类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------listTray.java 具体零件:抽取Link和Tray的类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------listPage.java 具体零件:表示HTML网页的类<br />
&nbsp;步骤:定义抽象零件-&gt;用抽象零件定义抽象工厂-&gt;定义具体零件(继承实现抽象零件)-&gt;定义具体工厂(继承实现抽象工厂,制造实际产品)</p>
<p>2.Factory Method<br />
&nbsp;Factory Method Pattern 在父类规定对象的创建方法,但并没有深入到较具体的类名.所有具体的完整内容都放在子类.根据这个原则,我们可以大致分成产生对象实例的大纲(框架)和实际产生对象实例的类两方面.<br />
&nbsp;程序示例:<br />
&nbsp;--Main.java 测试用的类<br />
&nbsp;|-framework<br />
&nbsp;|&nbsp;&nbsp;&nbsp; |-------Product.java 仅定义抽象方法use的抽象类<br />
&nbsp;|&nbsp;&nbsp;&nbsp; |-------Factory.java 规定createProduct,registerProduct,实现create的抽象类(类似模板方法)<br />
&nbsp;|<br />
&nbsp;|-idcard<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------IDCard.java 实现方法use的具体类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------IDCardFactory.java 实现方法createProduct,registerProduct的类<br />
&nbsp;步骤:定义抽象产品-&gt;根据抽象产品定义抽象工厂-&gt;定义具体产品(继承实现抽象产品)-&gt;定义具体工厂(继承实现抽象工厂,制造实际产品)</p>
<p>3.Singleton(单件)－唯一的对象实例<br />
&nbsp;Singleton Pattern 是针对一个类而言. Singleton类只会产生１个对象实例．Singleton类把singleton定义为static字段(类变量),再以Singleton类的对象实例进行初始化．这个初始化的操作仅在加载Singleton类时进行一次．<br />
&nbsp;Singleton类的构造函数是private的，主要是为了禁止从非Singleton类调用构造函数．即使下面这个表达式不在此类之内，编译时仍然会出现错误．<br />
&nbsp; 程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Singleton.java 只有１个对象实例的类<br />
&nbsp;步骤:定义一个该类类型的static字段，同时实例化-&gt;该类的构造方法设为private-&gt;定义一个static的getInstance()方法，返回已经实例化的static字段．</p>
<p>4.Builder(生成器)－组合复杂的对象实例<br />
&nbsp;Builder Pattern 是采用循序渐进的方式组合较复杂对象实例的．<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Builder.java 规定建立文件时的方法的抽象类<br />
&nbsp;|--Director.java 产生１个文件的类<br />
&nbsp;|--TextBuilder.java 产生plaintext格式(一般文本格式)的类<br />
&nbsp;|--HTMLBuilder.java 产生HTML格式的类<br />
&nbsp;步骤:定义建立文件时的通用方法(Builder.java)-&gt;根据通用方法组织建立文件(Director.java)-&gt;根据不同需求实现建立文件的通用方法(TextBuilder.java,HTMLBuilder.java)</p>
<p>5.Prototype(原型)－复制建立对象<br />
&nbsp;Prototype Pattern 不是利用类产生对象实例，而是从一个对象实例产生出另一个新对象实例．<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--MessageBox.java 把字符串框起来use的类．实现use和createClone<br />
&nbsp;|--UnderlinePen.java 把字符串加上下划线的类．实现use和createCone<br />
&nbsp;|--framework<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------Product.java 已声明抽象方法use和createClone的接口<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------Manager.java 利用createClone复制对象实例的类<br />
&nbsp;步骤:规定可复制产品的接口(Product.java,继承Cloneable接口)-&gt;保存可复制的产品(以Product类型存以哈西表中)，并提供复制产品的方法create(调用产品的复制方法，复制工作在具体产品类中执行)(Manager.java)-&gt;定义可复制的具体产品(UnderlinePen.java,MessageBox.java,实现复制产品方法)</p>
<p><br />
二、结构模式(Structural Patterns)</p>
<p>1.Adapter(适配器)－换个包装再度利用<br />
&nbsp;Adapter Pattern 把既有的无法直接利用的内容转换成必要的类型后再使用．具有填平＂既有内容＂和＂需要结果＂两者间＂落差＂的功能．<br />
&nbsp;Adapter Pattern 有继承和委托两种形式．<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Banner.java 具有原始功能showWithParen,showWithAster的类<br />
&nbsp;|--Print.java 所需新功能printWeak,printStrong的接口或抽象类<br />
&nbsp;|--PrintBanner.java 把原始功能转换成新功能的类<br />
&nbsp;步骤:<br />
&nbsp;(继承)构造具有原始功能的类(Banner.java)-&gt;定义具有新功能的接口(Print.java)-&gt;转换(PrintBanner.java,继承Banner实现Print接口,即继承旧方法实现新功能)<br />
&nbsp;(委托)构造具有原始功能的类(Banner.java)-&gt;定义具有新功能的抽象类(Print.java)-&gt;转换(PrintBanner.java,继承具有新功能的Print类.定义委托对象,即原始功能类.构造时传入原始功能实例对象，新功能的实现利用委托对象的原始功能．)</p>
<p>2.Bridge(桥接)－分成功能层次和实现层次<br />
&nbsp;Bridge Pattern 沟通着＂功能的类层次＂和＂实现的类层次＂<br />
&nbsp;功能的类层次：给父类增加不同的功能<br />
&nbsp;实现的类层次：给父类以不同的实现<br />
&nbsp;Bridge Pattern 本质上是通过功能类(最上层的功能类)中的一个实现类(最上层的实现类，一般是抽象类)字段来桥接两个类层次的．<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Display.java 功能类层次的最上层类<br />
&nbsp;|--CountDisplay.java 功能类层次的新增功能类<br />
&nbsp;|--DisplayImpl.java 实现类层次的最上层类<br />
&nbsp;|--StringDisplayImpl.java 实现类层次的实现类<br />
&nbsp;步骤:定义实现类层次的最上层类(DisplayImpl.java)-&gt;定义功能类层次的最上层类(Display.java,使用Adapter Pattern的委托方式把DisplayImpl.java的原始功能转换成Display.java的新功能)-&gt;定义功能类层次的新增功能类(CountDisplay.java)-&gt;定义实现类层次的实现类(StringDisplayImpl.java)</p>
<p>3.Composite(组成)-对容器和内容一视同仁<br />
&nbsp;有时候把容器和内容当作是同类来处理会比较好下手。容器里面可以是内容，也可以是更小一号的容器；而这个小一号的容器里还可以再放更小一号的容器，可以建立出像这样大套小的结构和递归结构的Pattern就是Composite Pattern<br />
&nbsp;使用Composite Pattern,容器和内容必须有一定的共性.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--File.java 表示文件的类<br />
&nbsp;|--Directory.java 表示目录的类<br />
&nbsp;|--Entry.java 对File和Directory一视同仁的抽象类<br />
&nbsp;|--FileTreatmentException.java 欲在文件内新增Entry时所发生的异常类<br />
&nbsp;步骤:定义异常类(FileTreatmentException.java)-&gt;定义进入点类,即将容器和内容一视同仁的抽象类(Entry.java,容器和内容都含有共同的方法)-&gt;定义容器类和内容类(File.java,Directory.java,继承Entry,实现通用方法)</p>
<p>4.Decorator(装饰)-对装饰和内容一视同仁<br />
&nbsp;先建立一个核心对象,再一层层加上装饰用的功能,就可以完成符合所需的对象.可以看成是多个通用的适配器.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Display.java 打印字符串用的抽象类<br />
&nbsp;|--StringDisplay.java 只有1行的打印字符串用的类<br />
&nbsp;|--Border.java 表示"装饰外框"的抽象类<br />
&nbsp;|--SideBorder.java 只在左右加上装饰外框的类<br />
&nbsp;|--FullBorder.java 在上下左右加上装饰外框的类<br />
&nbsp;步骤:定义核心对象的抽象类(Display.java)-&gt;定义核心对象类(StringDisplay.java)-&gt;定义装饰类的抽象类(Border.java,继承核心对象的抽象类Display.java,以便装饰和内容一视同仁.装饰类中继承自核心对象抽象类的方法委托给传入的核心对象)-&gt;定义其它装饰类(SideBorder.java,FullBorder.java,继承Border.java)</p>
<p>5.Facade(外观)-单一窗口<br />
&nbsp;Facade Pattern 能整理错综复杂的来龙去脉,提供较高级的接口(API).Facade参与者让系统外部看到较简单的接口(API).而且Facade参与者还会兼顾系统内部各类功能和互动关系,以最正确的顺序利用类.<br />
&nbsp;Facade Pattern 把业务逻辑封装起来,只提供一个简单的接口给外部调用.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--maildata.txt 邮件列表文件<br />
&nbsp;|--pagemaker<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------Database.java 从邮件信箱取得用户名称的类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------HtmlWriter.java 产生HTML文件的类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------PageMaker.java 根据邮件信箱产生用户网页的类<br />
&nbsp;步骤:定义业务逻辑需要的相关类(Database.java,HtmlWriter.java)-&gt;定义外部接口类(PageMaker.java)</p>
<p>6.Flyweight(享元)-有相同的部分就共享,采用精简政策<br />
&nbsp;"尽量共享对象实例,不做无谓的new".不是一需要对象实例就马上new,如果可以利用其他现有的对象实例,就让它们共享.这就是Flyweigth Pattern的核心概念.<br />
&nbsp;Flyweight Pattern 实质是把创建的占用内存量大的对象存储起来(一般用hashtable存储),后续使用时,再从hashtable取出.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--BigChar.java 表示"大型字符"的类<br />
&nbsp;|--BigCharFactory.java 共享并产生BigChar的对象实例的类<br />
&nbsp;|--BigString.java 表示多个BigChar所产生的"大型文本"的类<br />
&nbsp;步骤:定义占用内存量大,需要共享的类(Display.java)-&gt;定义共享实例的类(BigCharFactory.java,共享处理在此进行,将产生的共享对象存储在哈希表中,第二次使用时从表中取出即可,不需要new)-&gt;定义共享对象组合使用类(BigString.java)</p>
<p>7.Proxy(代理)-需要再建立<br />
&nbsp;代理就是那个代替本来应该自己动手做事的本人的人.<br />
&nbsp;由于代理纯粹只是代理工作而已,因此能力范围也有限.如果遇到超出代理能力所及的范围,代理就应该去找本人商量才对.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Printer.java 表示命名的打印机的类(本人)<br />
&nbsp;|--Printable.java Printer和PrinterProxy共享的接口<br />
&nbsp;|--PrinterProxy.java 表示命名的打印机的类(代理)<br />
&nbsp;步骤:定义本人和代理都能处理的问题的接口(Printable.java)-&gt;建立本人类(Printer.java,实现Printable.java接口)-&gt;建立代理类(PrinterProxy.java,定义本人字段,把代理无法处理的问题交给本人)</p>
<p><br />
三、行为模式(Behavioral Pattern)</p>
<p>1.Chain of Responsibility(职责链)-责任转送<br />
&nbsp;先对人产生一个要求,如果这个人有处理的能力就处理掉;如果不能处理的话,就把要求转送给"第二个人".同样的,如果第二个人有处理的能力时就处理掉,不能处理的话,就继续转送给"第三个人",依此类推.这就是Chain of Responsiblility Pattern.<br />
&nbsp;Chain of Responsibility Pattern 的关键在于定义转送字段(next)和定义职责链.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 建立Support的连锁,产生问题的测试用类<br />
&nbsp;|--Trouble.java 表示发生问题的类.内有问题编号.<br />
&nbsp;|--Support.java 解决问题的抽象类.内有转送字段和处理方法.<br />
&nbsp;|--NoSupport.java 解决问题的具体类(永远"不处理")<br />
&nbsp;|--LimitSupport.java 解决问题的具体类(解决小于指定号码的问题)<br />
&nbsp;|--OddSupport.java 解决问题的具体类(解决奇数号码的问题)<br />
&nbsp;|--SpecialSupport.java 解决问题的具体类(解决特殊号码的问题)<br />
&nbsp;步骤:建立问题类(Trouble.java)-&gt;建立解决问题的抽象类(Support.java,定义了转送字段next,设置转送字段的方法setNext和处理问题的方法support)-&gt;建立解决问题的具体类(NoSupport.java,LimitSupport.java,OddSupport.java,SpecialSupport.java,继承Support.java)-&gt;产生处理问题的对象,建立职责链</p>
<p>2.Command(命令)-将命令写成类<br />
&nbsp;用一个"表示命令的类的对象实例"来代表欲执行的操作,而不需采用"调用方法"的类的动态处理.如欲管理相关纪录,只需管理该对象实例的集合即可.而若预先将命令的集合存储起来,还可再执行同一命令;或者是把多个命令结合成一个新命令供再利用.<br />
&nbsp;Command Pattern 重点在于存储/使用命令<br />
&nbsp;程序示例:<br />
&nbsp;--Main.java 测试用的类<br />
&nbsp;|-command<br />
&nbsp;|&nbsp;&nbsp;&nbsp; |-------Command.java 表示"命令"的接口<br />
&nbsp;|&nbsp;&nbsp;&nbsp; |-------MacroCommand.java 表示"结合多个命名的命令"的类<br />
&nbsp;|<br />
&nbsp;|-drawer<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------DrawCommand.java 表示"点的绘制命令"的类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------Drawable.java 表示"绘制对象"的接口<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------DrawCanvas.java 表示"绘制对象"的类<br />
&nbsp;步骤:建立命令接口(Command.java)-&gt;建立命令结合类(MacroCommand.java,将各个命令存储到一个Stack类型的字段)-&gt;建立绘制命令类(DrawCommand.java,定义绘制对象字段drawable,实现命令接口)-&gt;建立绘制对象接口(Drawable.java)-&gt;建立绘制对象类(DrawCanvas.java,实现绘制对象接口,定义命令集合字段history)-&gt;测试</p>
<p>3.Interpreter(解释器)-以类来表达语法规则<br />
&nbsp;Interpreter Pattern 是用简单的"迷你语言"来表现程序要解决的问题,以迷你语言写成"迷你程序"而表现具体的问题.迷你程序本身无法独自启动,必须先用java语言另外写一个负责"解释(interpreter)"的程序.解释程序能分析迷你语言,并解释\执行迷你程序.这个解释程序也称为解释器.当应解决的问题发生变化时,要修改迷你程序来对应处理.而不是修改用java语言写成的程序.<br />
&nbsp;迷你语言语法:<br />
&nbsp;&lt;program&gt;::=program&lt;command list&gt;<br />
&nbsp;&lt;command list&gt;::=&lt;command&gt;* end<br />
&nbsp;&lt;command&gt;::=&lt;repeat command&gt;|&lt;primitive command&gt;<br />
&nbsp;&lt;repeat command&gt;::=repeat&lt;number&gt;&lt;command list&gt;<br />
&nbsp;&lt;primitive command&gt;::=go|right|left<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Node.java 树状剖析中"节点"的类<br />
&nbsp;|--ProgramNode.java 对应&lt;program&gt;的类<br />
&nbsp;|--CommandListNode.java 对应&lt;command list&gt;的类<br />
&nbsp;|--CommandNode.java 对应&lt;command&gt;的类<br />
&nbsp;|--RepeatCommandNode.java 对应&lt;repeat command&gt;的类<br />
&nbsp;|--PrimitiveCommandNode.java 对应&lt;primitive command&gt;的类<br />
&nbsp;|--Context.java 表示语法解析之前后关系的类<br />
&nbsp;|--ParseException.java 语法解析中的例外类<br />
&nbsp;步骤:确定迷你语言的语法-&gt;建立语法解析类(Context.java,使用java.util.StringTokenizer类)-&gt;建立解析异常类(ParseException.java)-&gt;建立语法节点抽象类(Node.java,定义parse解析方法)-&gt;建立各语法节点对应的语法类(ProgramNode.java,CommandListNode.java,CommandNode.java,RepeatCommandNode.java,PrimitiveCommand.java,继承语法节点Node.java类)</p>
<p>4.Iterator-迭代器<br />
&nbsp;Iterator Pattern 是指依序遍历并处理多个数字或变量.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Aggregate.java 表示已聚合的类<br />
&nbsp;|--Iterator.java 执行递增\遍历的接口<br />
&nbsp;|--Book.java 表示书籍的类<br />
&nbsp;|--BookShelf.java 表示书架的类<br />
&nbsp;|--BookShelfIterator.java 扫描书架的类<br />
&nbsp;步骤:定义聚合接口(Aggregate.java)-&gt;定义遍历接口(Iterator.java)-&gt;建立具体的遍历对象类(Book.java)-&gt;建立具体的聚合类(BookShelf.java,实现聚合接口)-&gt;建立具体的遍历类(BookShelfIterator.java,实现遍历接口)</p>
<p>5.Mediator(中介者)-只要面对一个顾问<br />
&nbsp;每个成员都只对顾问提出报告,也只有顾问会发出指示给各个成员;成员们彼此也不会去探问目前状况如何,或乱发指示给其他成员.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Mediator.java 决定"顾问"接口(API)的接口<br />
&nbsp;|--Colleague.java 决定"成员"接口(API)的接口<br />
&nbsp;|--ColleagueButton.java 实现Colleagues接口.表示按键的类<br />
&nbsp;|--ColleagueTextField.java 实现Colleagues接口.输入文本的类<br />
&nbsp;|--ColleagueCheckbox.java 实现Colleagues接口.表示选择项目(在此为选择按钮)的类<br />
&nbsp;|--LoginFrame.java 实现Mediator接口.表示登录对话框的类<br />
&nbsp;步骤:定义顾问接口(Mediator.java)-&gt;定义成员接口(Colleague.java)-&gt;建立具体的成员类(ColleagueButton.java,ColleagueTextField.java,ColleagueCheckbox.java,实现成员接口)-&gt;建立具体的顾问类(LoginFrame.java,实现顾问接口)</p>
<p>6.Memento(备忘录)-存储状态<br />
&nbsp;Memento Pattern 会把某个时间点的对象实例状态记录存储起来,等到以后再让对象实例复原到当时的状态.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 进行游戏的类.先把Memento的对象实例存储起来,如有必要时再复原Gamer的状态<br />
&nbsp;|--game<br />
&nbsp;&nbsp;&nbsp;&nbsp; |-------Gamer.java 玩游戏的主人翁的类<br />
&nbsp;&nbsp;&nbsp;&nbsp; |-------Memento.java 表示Gamer状态的类.产生Memento的对象实例<br />
&nbsp;步骤:建立需要存储状态的类(Gamer.java)-&gt;建立状态类(Memento.java,状态类与需要存储状态的类Gamer.java应具有相同的必要字段)</p>
<p>7.Observer(观察者)-通知状态变化<br />
&nbsp;当被Observer Pattern 列入观察名单的状态发生变化,就会通知观察者.在写一些跟状态变化有关的处理时,Observer Pattern是很好用的工具.<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Observer.java 表示观察者的接口<br />
&nbsp;|--NumberGenerator.java 表示产生数值对象的抽象类<br />
&nbsp;|--RandomNumberGenerator.java 产生随机数的类<br />
&nbsp;|--DigitObserver.java 以数字表示数值的类<br />
&nbsp;|--GraphObserver.java 以简易长条图表示数值的类<br />
&nbsp;步骤:定义观察者接口(Observer.java)-&gt;建立被观察的类(NumberGenerator.java,RandomNumberGenerator.java,定义观察者结合字段将观察者存储起来)-&gt;建立具体的观察者类(DigitObserver.java,GraphObserver.java,实现观察者接口)</p>
<p>8.State(状态)-以类表示状态<br />
&nbsp;以类来表示状态之后，只要切换类就能表现&#8220;状态变化&#8221;，而且在必须新增其他状态时，也很清楚该编写哪个部分。<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--State.java 表示金库状态的接口<br />
&nbsp;|--DayState.java 实现State的类。表示白天的状态<br />
&nbsp;|--NightState.java 实现State的类。表示夜间的状态<br />
&nbsp;|--Context.java 管理金库的状态变化，跟保安中心联络的接口<br />
&nbsp;|--SafeFrame.java 实现Context的类。含有按钮、画面显示等的用户接口<br />
&nbsp;步骤:定义状态接口(State.java,将使用State Pattern之前各种行为方法抽象出来)-&gt;建立具体的状态类(DayState.java,NightState.java,实现状态接口,状态变化的具体动作在这里执行)-&gt;定义管理状态变化的接口(Context.java,规定状态变化及相关的调用方法)-&gt;建立状态管理类(SafeFrame.java,实现状态管理接口)</p>
<p>9.Strategy(策略)-把算法整个换掉<br />
&nbsp;在Strategy Pattern之下，可以更换实现算法的部分而且不留痕迹。切换整个算法，简化改为采用其他方法来解决同样的问题。<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Hand.java 表示猜拳&#8220;手势&#8221;的类<br />
&nbsp;|--Strategy.java 表示猜拳&#8220;战略&#8221;的接口<br />
&nbsp;|--WinningStrategy.java 表示猜赢之后继续出同样招式的战略的类<br />
&nbsp;|--ProbStrategy.java 表示从上一次出的招式，以概率分配方式求出下一个招式机率的类<br />
&nbsp;|--Player.java 表示玩猜拳的游戏者的类<br />
&nbsp;步骤:定义策略接口(Strategy.java)-&gt;建立具体的策略类(WinningStrategy.java,ProbStrategy.java,实现策略接口)-&gt;建立使用策略的类(Player.java,定义策略字段，以便使用切换策略)-&gt;建立其它类(Main.java,Hand.java)</p>
<p>10.Template Method(模板方法)-实际处理交给子类<br />
&nbsp;在父类指定处理大纲、在子类规定具体内容的Design Pattern就称为Template Method Pattern<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--AbstractDisplay.java 只实现方法display的抽象类<br />
&nbsp;|--CharDisplay.java 实现方法open,print,close的类<br />
&nbsp;|--StringDisplay.java 实现方法open,print,close的类<br />
&nbsp;步骤:定义模板类(AbstractDisplay.java,实现dispaly方法，即制作了模板)-&gt;建立具体内容类(CharDisplay.java,StringDisplay.java,继承模板类，实现模板类没有实现的方法)</p>
<p>11.Visitor(访问者)-在结构中穿梭还同时做事<br />
&nbsp;Visitor Pattern 把数据结构和处理两者分开，另外写一个表示在数据结构内穿梭来去的主体&#8220;访客&#8221;的类，然后把处理交给这个类来进行。如此一来，如果想追加新的处理行为时，只要再建立一个新的&#8220;访客&#8221;即可。而在数据结构这边，也只要能接受来敲门的&#8220;访客&#8221;就能完成动作。<br />
&nbsp;在父类指定处理大纲、在子类规定具体内容的Design Pattern就称为Template Method Pattern<br />
&nbsp;程序示例:<br />
&nbsp;|--Main.java 测试用的类<br />
&nbsp;|--Visitor.java 表示访问文件或目录的访客的抽象类<br />
&nbsp;|--Acceptor.java 表示接受Visitor类的对象实例的数据结构的接口<br />
&nbsp;|--ListVisitor.java Visitor类的子类，打印文件和目录信息的类<br />
&nbsp;|--Entry.java File和Directory的父类的抽象类(实现Acceptor接口)<br />
&nbsp;|--File.java 表示文件的类<br />
&nbsp;|--Directory.java 表示目录的类<br />
&nbsp;|--FileTreatmentException.java 发生在对File进行add时的例外类<br />
&nbsp;步骤:定义访问者的抽象类(Visitor.java,定义访问方法)-&gt;定义受访者接口(Acceptor.java,定义接受访问的方法)-&gt;建立具体的访问者类(ListVisitor.java,继承访问者抽象类，实现访问方法)-&gt;建立具体的受访者类(Entry.java,File.java,Directory.java,实现受访者接口)-&gt;编写异常类(FileTreatmentException.java)</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/pian_yun/archive/2007/09/14/1784981.aspx</p><img src ="http://www.blogjava.net/dongwq/aggbug/322156.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2010-05-28 16:24 <a href="http://www.blogjava.net/dongwq/archive/2010/05/28/322156.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java语言中容易被人忽视的细节</title><link>http://www.blogjava.net/dongwq/archive/2009/12/03/304710.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Thu, 03 Dec 2009 14:46:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/12/03/304710.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/304710.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/12/03/304710.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/304710.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/304710.html</trackback:ping><description><![CDATA[<br />
<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>作为一门优秀的面向对象的程序设计语言,正在被越来越多的人使用。本文试图列出作者在实际开发中碰到的一些<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>语言的容易被人忽视的细节,希望能给正在学习Java语言的人有所帮助。
<p>　　1，位移运算越界怎么处理</p>
<p>　　考察下面的代码输出结果是多少?</p>
<p>　　int a=5;</p>
<p>　　System.out.println(a &lt; &lt;33);</p>
<p>　　按照常理推测,把a左移33位应该将a的所有有效位都移出去了，那剩下的都是零啊，所以输出结果应该是0才对啊，可是执行后发现输出结果是10，为什么呢？因为Java语言对位移运算作了优化处理，Java语言对a &lt; &lt;b转化为a &lt; &lt;(b%32)来处理，所以当要移位的位数b超过32时，实际上移位的位数是b%32的值，那么上面的代码中a &lt; &lt;33相当于a &lt; &lt;1，所以输出结果是10。</p>
<p>　　2，可以让i!=i吗？</p>
<p>　　当你看到这个命题的时候一定会以为我疯了，或者Java语言疯了。这看起来是绝对不可能的，一个数怎么可能不等于它自己呢？或许就真的是Java语言疯了，不信看下面的代码输出什么？</p>
<p>　　double i=0.0/0.0;</p>
<p>　　if(i==i){</p>
<p>　　System.out.println("Yes i==i");</p>
<p>　　}else{</p>
<p>　　System.out.println("No i!=i");</p>
<p>　　}</p>
<p>　　上面的代码输出"No i!=i"，为什么会这样呢？关键在0.0/0.0这个值，在IEEE 754浮点算术规则里保留了一个特殊的值用来表示一个不是数字的数量。这个值就是NaN("Not a Number"的缩写)，对于所有没有良好定义的浮点计算都将得到这个值，比如：0.0/0.0；其实我们还可以直接使用Double.NaN来得到这个值。在IEEE 754规范里面规定NaN不等于任何值，包括它自己。所以就有了i！=i的代码。</p>
<p>　　3，怎样的equals才<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>？</p>
<p>　　我们都知道在Java规范里定义了equals方法覆盖的5大原则：reflexive（反身性），symmetric（对称性），transitive（传递性），consistent（一致性），non-null（非空性）。那么考察下面的代码：</p>
<p>　　public class Student{</p>
<p>　　private String name;</p>
<p>　　private int age;</p>
<p>　　public Student(String name,int age){</p>
<p>　　this.name=name;</p>
<p>　　this.age=age;</p>
<p>　　}</p>
<p>　　public boolean equals(Object obj){</p>
<p>　　if(obj instanceof Student){</p>
<p>　　Student s=(Student)obj;</p>
<p>　　if(s.name.equals(this.name) &amp;&amp; s.age==this.age){</p>
<p>　　return true;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　return super.equals(obj);</p>
<p>　　}</p>
<p>　　}</p>
<p>　　你认为上面的代码equals方法的覆盖<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>吗？表面看起来好像没什么问题，这样写也确实满足了以上的五大原则。但其实这样的覆盖并不很安全，假如Student类还有一个子类CollegeStudent,如果我拿一个Student对象和一个CollegeStudent对象equals,只要这两个对象有相同的name和age，它们就会被认为相等，但实际上它们是两个不同类型的对象啊。问题就出在instanceof这个运算符上，因为这个运算符是向下兼容的，也就是说一个CollegeStudent对象也被认为是一个Student的实例。怎样去解决这个问题呢？那就只有不用instanceof运算符，而使用对象的getClass()方法来判断两个对象是否属于同一种类型，例如，将上面的equals()方法修改为：</p>
<p>　　public boolean equals(Object obj){</p>
<p>　　if(obj.getClass()==Student.class){</p>
<p>　　Student s=(Student)obj;</p>
<p>　　if(s.name.equals(this.name) &amp;&amp; s.age==this.age){</p>
<p>　　return true;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　return super.equals(obj);</p>
<p>　　}</p>
<p>　　这样才能保证obj对象一定是Student的实例，而不会是Student的任何子类的实例。</p>
4，浅复制与深复制
<p>　　1）浅复制与深复制概念</p>
<p>　　⑴浅复制（浅克隆）</p>
<p>　　被复制对象的所有变量都含有与原来的对象相同的值，而所有的对其他对象的引用仍然指向原来的对象。换言之，浅复制仅仅复制所考虑的对象，而不复制它所引用的对象。</p>
<p>　　⑵深复制（深克隆）</p>
<p>　　被复制对象的所有变量都含有与原来的对象相同的值，除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象，而不再是原有的那些被引用的对象。换言之，深复制把要复制的对象所引用的对象都复制了一遍。</p>
<p>　　2）Java的clone（）方法</p>
<p>　　⑴clone方法将对象复制了一份并返回给调用者。一般而言，clone（）方法满足：</p>
<p>　　①对任何的对象x，都有x.clone() !=x//克隆对象与原对象不是同一个对象</p>
<p>　　②对任何的对象x，都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样</p>
<p>　　③如果对象x的equals()方法定义恰当，那么x.clone().equals(x)应该成立。</p>
<p>　　⑵Java中对象的克隆</p>
<p>　　①为了获取对象的一份拷贝，我们可以利用Object类的clone()方法。</p>
<p>　　②在派生类中覆盖基类的clone()方法，并声明为public。</p>
<p>　　③在派生类的clone()方法中，调用super.clone()。</p>
<p>　　④在派生类中实现Cloneable接口。</p>
<p>　　请看如下代码：</p>
<p>　　class Student implements Cloneable{</p>
<p>　　String name;</p>
<p>　　int age;</p>
<p>　　Student(String name,int age){</p>
<p>　　this.name=name;</p>
<p>　　this.age=age;</p>
<p>　　}</p>
<p>　　public Object clone(){</p>
<p>　　Object obj=null;</p>
<p>　　try{</p>
<p>　　obj=(Student)super.clone();</p>
<p>　　//Object中的clone()识别出你要复制的是哪一个对象。</p>
<p>　　}</p>
<p>　　catch(CloneNotSupportedException e){</p>
<p>　　e.printStackTrace();</p>
<p>　　}</p>
<p>　　return obj;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　public static void main(String[] args){</p>
<p>　　Student s1=new Student("zhangsan",18);</p>
<p>　　Student s2=(Student)s1.clone();</p>
<p>　　s2.name="lisi";</p>
<p>　　s2.age=20;</p>
<p>　　System.out.println("name="+s1.name+","+"age="+s1.age);//修改学生2</p>
<p>　　//后，不影响学生1的值。</p>
<p>　　}</p>
<p>　　说明：</p>
<p>　　①为什么我们在派生类中覆盖Object的clone()方法时，一定要调用super.clone()呢？在运行时刻，Object中的clone()识别出你要复制的是哪一个对象，然后为此对象分配空间，并进行对象的复制，将原始对象的内容一一复制到新对象的<a class="channel_keylink" href="http://www.storworld.com/" target="_blank">存储</a>空间中。</p>
<p>　　②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。</p>
<p>　　class Teacher{</p>
<p>　　String name;</p>
<p>　　int age;</p>
<p>　　Teacher(String name,int age){</p>
<p>　　this.name=name;</p>
<p>　　this.age=age;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　class Student implements Cloneable{</p>
<p>　　String name;</p>
<p>　　int age;</p>
<p>　　Teacher t;//学生1和学生2的引用值都是一样的。</p>
<p>　　Student(String name,int age,Teacher t){</p>
<p>　　this.name=name;</p>
<p>　　this.age=age;</p>
<p>　　this.t=t;</p>
<p>　　}</p>
public Object clone(){
<p>　　Student stu=null;</p>
<p>　　try{</p>
<p>　　stu=(Student)super.clone();</p>
<p>　　}catch(CloneNotSupportedException e){</p>
<p>　　e.printStackTrace();</p>
<p>　　}</p>
<p>　　stu.t=(Teacher)t.clone();</p>
<p>　　return stu;</p>
<p>　　}</p>
<p>　　public static void main(String[] args){</p>
<p>　　Teacher t=new Teacher("tangliang",30);</p>
<p>　　Student s1=new Student("zhangsan",18,t);</p>
<p>　　Student s2=(Student)s1.clone();</p>
<p>　　s2.t.name="tony";</p>
<p>　　s2.t.age=40;</p>
<p>　　System.out.println("name="+s1.t.name+","+"age="+s1.t.age);</p>
<p>　　//学生1的老师成为tony,age为40。</p>
<p>　　}</p>
<p>　　}</p>
<p>　　那应该如何实现深层次的克隆，即修改s2的老师不会影响s1的老师？代码改进如下。</p>
<p>　　class Teacher implements Cloneable{</p>
<p>　　String name;</p>
<p>　　int age;</p>
<p>　　Teacher(String name,int age){</p>
<p>　　this.name=name;</p>
<p>　　this.age=age;</p>
<p>　　}</p>
<p>　　public Object clone(){</p>
<p>　　Object obj=null;</p>
<p>　　try{</p>
<p>　　obj=super.clone();</p>
<p>　　}catch(CloneNotSupportedException e){</p>
<p>　　e.printStackTrace();</p>
<p>　　}</p>
<p>　　return obj;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　class Student implements Cloneable{</p>
<p>　　String name;</p>
<p>　　int age;</p>
<p>　　Teacher t;</p>
<p>　　Student(String name,int age,Teacher t){</p>
<p>　　this.name=name;</p>
<p>　　this.age=age;</p>
<p>　　this.t=t;</p>
<p>　　}</p>
<p>　　public Object clone(){</p>
<p>　　Student stu=null;</p>
<p>　　try{</p>
<p>　　stu=(Student)super.clone();</p>
<p>　　}catch(CloneNotSupportedException e){</p>
<p>　　e.printStackTrace();</p>
<p>　　}</p>
<p>　　stu.t=(Teacher)t.clone();</p>
<p>　　return stu;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　public static void main(String[] args){</p>
<p>　　Teacher t=new Teacher("tangliang",30);</p>
<p>　　Student s1=new Student("zhangsan",18,t);</p>
<p>　　Student s2=(Student)s1.clone();</p>
<p>　　s2.t.name="tony";</p>
<p>　　s2.t.age=40;</p>
<p>　　System.out.println("name="+s1.t.name+","+"age="+s1.t.age);</p>
<p>　　//学生1的老师不改变。</p>
<p>　　}</p>
3）利用串行化来做深复制
<p>　　把对象写到流里的过程是串行化（Serilization）过程，Java程序员又非常形象地称为&#8220;冷冻&#8221;或者&#8220;腌咸菜（picking）&#8221;过程；而把对象从流中读出来的并行化（Deserialization）过程则叫做&#8220;解冻&#8221;或者&#8220;回鲜(depicking)&#8221;过程。应当指出的是，写在流里的是对象的一个拷贝，而原对象仍然存在于JVM里面，因此&#8220;腌成咸菜&#8221;的只是对象的一个拷贝，Java咸菜还可以回鲜。</p>
<p>　　在Java语言里深复制一个对象，常常可以先使对象实现Serializable接口，然后把对象（实际上只是对象的一个拷贝）写到一个流里（腌成咸菜），再从流里读出来（把咸菜回鲜），便可以重建对象。</p>
<p>　　如下为深复制源代码。</p>
<p>　　public Object deepClone(){</p>
<p>　　//将对象写到流里</p>
<p>　　ByteArrayOutoutStream bo=new ByteArrayOutputStream();</p>
<p>　　ObjectOutputStream oo=new ObjectOutputStream(bo);</p>
<p>　　oo.writeObject(this);</p>
<p>　　//从流里读出来</p>
<p>　　ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());</p>
<p>　　ObjectInputStream oi=new ObjectInputStream(bi);</p>
<p>　　return(oi.readObject());</p>
<p>　　}</p>
<p>　　这样做的前提是对象以及对象内部所有引用到的对象都是可串行化的，否则，就需要仔细考察那些不可串行化的对象可否设成transient，从而将之排除在复制过程之外。上例代码改进如下。</p>
<p>　　class Teacher implements Serializable{</p>
<p>　　String name;</p>
<p>　　int age;</p>
<p>　　Teacher(String name,int age){</p>
<p>　　this.name=name;</p>
<p>　　this.age=age;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　class Student implements Serializable</p>
<p>　　{</p>
<p>　　String name;//常量对象。</p>
<p>　　int age;</p>
<p>　　Teacher t;//学生1和学生2的引用值都是一样的。</p>
<p>　　Student(String name,int age,Teacher t){</p>
<p>　　this.name=name;</p>
<p>　　this.age=age;</p>
<p>　　this.p=p;</p>
<p>　　}</p>
<p>　　public Object deepClone() throws IOException,</p>
<p>　　OptionalDataException,ClassNotFoundException</p>
<p>　　{</p>
<p>　　//将对象写到流里</p>
<p>　　ByteArrayOutoutStream bo=new ByteArrayOutputStream();</p>
<p>　　ObjectOutputStream oo=new ObjectOutputStream(bo);</p>
<p>　　oo.writeObject(this);</p>
<p>　　//从流里读出来</p>
<p>　　ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());</p>
<p>　　ObjectInputStream oi=new ObjectInputStream(bi);</p>
<p>　　return(oi.readObject());</p>
<p>　　}</p>
<p>　　}</p>
<p>　　public static void main(String[] args){</p>
<p>　　Teacher t=new Teacher("tangliang",30);</p>
<p>　　Student s1=new Student("zhangsan",18,t);</p>
<p>　　Student s2=(Student)s1.deepClone();</p>
<p>　　s2.t.name="tony";</p>
<p>　　s2.t.age=40;</p>
<p>　　System.out.println("name="+s1.t.name+","+"age="+s1.t.age);</p>
<p>　　//学生1的老师不改变。</p>
<p>　　}</p><img src ="http://www.blogjava.net/dongwq/aggbug/304710.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-12-03 22:46 <a href="http://www.blogjava.net/dongwq/archive/2009/12/03/304710.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>xml特殊字符zz</title><link>http://www.blogjava.net/dongwq/archive/2009/11/16/302456.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Sun, 15 Nov 2009 16:32:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/11/16/302456.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/302456.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/11/16/302456.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/302456.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/302456.html</trackback:ping><description><![CDATA[<div class="tit">xml特殊字符</div>
<div class="date">2008-07-03 14:31</div>
<table style="table-layout: fixed; width: 100%">
    <tbody>
        <tr>
            <td>
            <div class="cnt" id="blog_text">转义字符 <br />
            不合法的XML字符必须被替换为相应的实体。 <br />
            <br />
            如果在XML文档中使用类似"&lt;" 的字符, 那么解析器将会出现错误，因为解析器会认为这是一个新元素的开始。所以不应该象下面那样书写代码: <br />
            <br />
            &lt;message&gt;if salary &lt; 1000 then&lt;/message&gt; <br />
            为了避免出现这种情况，必须将字符"&lt;" 转换成实体，象下面这样: <br />
            &lt;message&gt;if salary &amp;lt; 1000 then&lt;/message&gt; <br />
            下面是五个在XML文档中预定义好的实体: <br />
            <br />
            &amp;lt; &lt; 小于号 <br />
            &amp;gt; &gt; 大于号 <br />
            &amp;amp; &amp; 和 <br />
            &amp;apos; ' 单引号 <br />
            &amp;quot; " 双引号 <br />
            实体必须以符号"&amp;"开头，以符号";"结尾。 <br />
            注意: 只有"&lt;" 字符和"&amp;"字符对于XML来说是严格禁止使用的。剩下的都是合法的，为了减少出错，使用实体是一个好习惯。 <br />
            <br />
            CDATA部件 <br />
            在CDATA内部的所有内容都会被解析器忽略。 <br />
            <br />
            如果文本包含了很多的"&lt;"字符和"&amp;"字符——就象程序代码一样，那么最好把他们都放到CDATA部件中。 <br />
            <br />
            一个 CDATA 部件以"&lt;![CDATA[" 标记开始，以"]]&gt;"标记结束: <br />
            <br />
            &lt;script&gt; <br />
            &lt;![CDATA[ <br />
            function matchwo(a,b) <br />
            { <br />
            if (a &lt; b &amp;&amp; a &lt; 0) then <br />
            { <br />
            return 1 <br />
            } <br />
            else <br />
            { <br />
            return 0 <br />
            } <br />
            } <br />
            ]]&gt; <br />
            &lt;/script&gt; <br />
            在前面的例子中，所有在CDATA部件之间的文本都会被解析器忽略。 <br />
            <br />
            CDATA注意事项: <br />
            CDATA部件之间不能再包含CDATA部件（不能嵌套）。如果CDATA部件包含了字符"]]&gt;" 或者"&lt;![CDATA[" ，将很有可能出错哦。 <br />
            <br />
            同样要注意在字符串"]]&gt;"之间没有空格或者换行符。 </div>
            </td>
        </tr>
    </tbody>
</table><img src ="http://www.blogjava.net/dongwq/aggbug/302456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-11-16 00:32 <a href="http://www.blogjava.net/dongwq/archive/2009/11/16/302456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDBC优化策略总结zz</title><link>http://www.blogjava.net/dongwq/archive/2009/11/14/302366.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Sat, 14 Nov 2009 11:18:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/11/14/302366.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/302366.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/11/14/302366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/302366.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/302366.html</trackback:ping><description><![CDATA[JDBC优化策略总结<br />
相比Hibernate、iBatis、DBUtils等，理论上JDBC的性能都超过它们。JDBC提供更底层更精细的数据访问策略，这是Hibernate等框架所不具备的。
<p>　　在一些高性能的数据操作中，越高级的框架越不适合使用。这里是我在开发中对JDBC使用过程中一些优化经验总结。</p>
<p>　　1、选择纯<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>的JDBC驱动。</p>
<p>　　2、使用连接池--使用一个&#8220;池&#8221;来管理JDBC连接，并精心调试池配置的参数，目前可用的数据库连接池很多很多。</p>
<p>　　如何配置合适的参数呢，需要的是<a class="channel_keylink" href="http://softtest.chinaitlab.com/" target="_blank">测试</a>，而不是感觉。</p>
<p>　　3、重用Connection--最大限度使用每个数据库连接，得到了就不要轻易&#8220;丢弃&#8221;。</p>
<p>　　有时候在一个过程中，会多次操作数据库，而仅仅需要一个连接就够了，没必用一次就获取一个连接，用完后关闭或者入池。这样会增加&#8220;池&#8221;管理的成本，千万别以为你用了&#8220;池&#8221;就可以随便申请和归还连接，都是有代价的。如果是一个庞大循环块中操作数据库，更应该注意此问题！</p>
<p>　　4、重用Statement--对于一些预定义SQL，设置为静态常量，并尽可能重用预定义SQL产生的PreparedStatement对象。对于多次使用一种模式的SQL，使用预定义SQL可以获取更好的性能。</p>
<p>　　5、使用批处理SQL。</p>
<p>　　6、优化结果集ResultSet--查询时候，返回的结果集有不同的类型，优先选择只读结果集、不可滚动的属性。</p>
<p>　　这里是很容易出现问题的地方：</p>
<div align="center">
<div style="border-right: #cccccc 1px solid; padding-right: 4px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 10pt; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; color: #000000; word-break: break-all; line-height: 16px; padding-top: 4px; border-bottom: #cccccc 1px solid; font-family: verdana,宋体; background-color: #eeeeee">
<div align="left">java.sql.ResultSet <br />
<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> CLOSE_CURSORS_AT_COMMIT&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示调用 Connection.commit 方法时应该关闭 ResultSet 对象。&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> CONCUR_READ_ONLY&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示不可以更新的 ResultSet 对象的并发模式。&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> CONCUR_UPDATABLE&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示可以更新的 ResultSet 对象的并发模式。&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> FETCH_FORWARD&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示将按正向（即从第一个到最后一个）处理结果集中的行。&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> FETCH_REVERSE&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示将按反向（即从最后一个到第一个）处理结果集中的行处理。&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> FETCH_UNKNOWN&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示结果集中的行的处理顺序未知。&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> HOLD_CURSORS_OVER_COMMIT&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示调用 Connection.commit 方法时不应关闭 ResultSet 对象。&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> TYPE_FORWARD_ONLY&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示指针只能向前移动的 ResultSet 对象的类型。&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> TYPE_SCROLL_INSENSITIVE&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示可滚动但通常不受其他的更改影响的 ResultSet 对象的类型。&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">static</font> <font color="#0000ff">int</font> TYPE_SCROLL_SENSITIVE&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该常量指示可滚动并且通常受其他的更改影响的 ResultSet 对象的类型。 </div>
</div>
</div>
<div>&nbsp;</div>
<div>　　说明下：</div>
<p>　　结果集分两种类型：只读和可更改，只读的话，更省内存，查询的结果集不能更改。如果结果集在查询后，更改了值又要保存，则使用可更改结果集。</p>
<p>　　结果集的游标也有两种类型：如果没必要让游标自由滚动，则选择单方向移动的游标类型。</p>
<p>　　对于是否并发操作：如果不需要考虑线程<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>，则选择忽略并发的结果集类型，否则选择并发<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>的类型。</p>
<p>　　另外，还要控制结果的大小，几乎所有的数据库都有查询记录条数控制的策略，可以海量数据进行分批处理，一次一批，这样不至于把系统搞死。</p>
<p>　　7、事物优化--如果数据库不支持事物，就不要写回滚代码，如果不考虑事物，就不要做事务的控制。</p>
<p>　　8、安全优化--管理好你的Connection对象，在异常时候能&#8220;入池&#8221;或者关闭。因此应该将Connection释放的代码写在异常处理的finally块中。</p>
<p>　　9、异常处理优化--不要轻易吞噬SQLException，对于DAO、Service层次的数据访问，一般在DAO中跑出异常，在Service中处理异常。但DAO中也可以处理异常，并做转义抛出，不要随便抛出RuntimeExeption，因为这是JVM抛出的，不需要你可以去抛出，因为RuntimeException往往会导致系统挂起。</p>
<p>　　10、代码高层优化--在以上的基础上，优化封装你的数据访问方式，尽可能让代码简洁好维护，如果你还觉得性能不行，那就该从整个系统角度考虑优化了，比如加上缓存<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>，集群、负载均衡、优化数据库<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>等等，以获取更好的系能。</p>
<p>　　本文出自 &#8220;熔 岩&#8221; 博客，请务必保留此出处<a href="http://lavasoft.blog.51cto.com/62575/225828">http://lavasoft.blog.51cto.com/62575/225828</a></p><img src ="http://www.blogjava.net/dongwq/aggbug/302366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-11-14 19:18 <a href="http://www.blogjava.net/dongwq/archive/2009/11/14/302366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java代码优化编程(2) </title><link>http://www.blogjava.net/dongwq/archive/2009/11/14/302365.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Sat, 14 Nov 2009 11:15:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/11/14/302365.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/302365.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/11/14/302365.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/302365.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/302365.html</trackback:ping><description><![CDATA[<h1 class="Article_tle">java代码优化编程(2) </h1>
<div class="Article_content">
<p>　　17、不用new关键词创建类的实例</p>
<p>　　用new关键词创建类的实例时，构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口，我们可以调用它的clone()方法。clone()方法不会调用任何类构造函数。</p>
<p>　　在使用设计模式（Design Pattern）的场合，如果用Factory模式创建对象，则改用clone()方法创建新的对象实例非常简单。例如，下面是Factory模式的一个典型实现：</p>
<p>　　public static Credit getNewCredit() {</p>
<p>　　return new Credit();</p>
<p>　　}</p>
<p>　　改进后的代码使用clone()方法，如下所示：</p>
<p>　　private static Credit BaseCredit = new Credit();</p>
<p>　　public static Credit getNewCredit() {</p>
<p>　　return (Credit) BaseCredit.clone();</p>
<p>　　}</p>
<p>　　上面的思路对于数组处理同样很有用。</p>
<p>　　18、乘法和除法</p>
<p>　　考虑下面的代码：</p>
<p>　　for (val = 0; val &lt; 100000; val +=5) {</p>
<p>　　alterX = val * 8; myResult = val * 2;</p>
<p>　　}</p>
<p>　　用移位操作替代乘法操作可以极大地提高性能。下面是修改后的代码：</p>
<p>　　for (val = 0; val &lt; 100000; val += 5) {</p>
<p>　　alterX = val &lt;&lt; 3; myResult = val &lt;&lt; 1;</p>
<p>　　}</p>
<p>　　修改后的代码不再做乘以8的操作，而是改用等价的左移3位操作，每左移1位相当于乘以2。相应地，右移1位操作相当于除以2。值得一提的是，虽然移位操作速度快，但可能使代码比较难于理解，所以最好加上一些注释。</p>
<p>　　19、在JSP页面中关闭无用的会话。</p>
<p>　　一个常见的误解是以为session在有客户端访问时就被创建，然而事实是直到某server端程序调用 HttpServletRequest.getSession(true)这样的语句时才被创建，注意如果JSP没有显示的使用 &lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#112;&#97;&#103;&#101;">%@page</a> session="false"%&gt; 关闭session，则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的 session对象的来历。由于session会消耗内存资源，因此，如果不打算使用session，应该在所有的JSP中关闭它。</p>
<p>　　对于那些无需跟踪会话状态的页面，关闭自动创建的会话可以节省一些资源。使用如下page指令：&lt;%@ page session="false"%&gt;</p>
<p>　　20、JDBC与I/O</p>
<p>　　如果应用程序需要访问一个规模很大的数据集，则应当考虑使用块提取方式。默认情况下，JDBC每次提取32行数据。举例来说，假设我们要遍历一个5000行的记录集，JDBC必须调用数据库157次才能提取到全部数据。如果把块大小改成512，则调用数据库的次数将减少到10次。</p>
<p>　　[p][/p]21、Servlet与内存使用</p>
<p>　　许多开发者随意地把大量信息保存到用户会话之中。一些时候，保存在会话中的对象没有及时地被垃圾回收机制回收。从性能上看，典型的症状是用户感到系统周期性地变慢，却又不能把原因归于任何一个具体的组件。如果监视JVM的堆空间，它的表现是内存占用不正常地大起大落。</p>
<p>　　解决这类内存问题主要有二种办法。第一种办法是，在所有作用范围为会话的Bean中实现HttpSessionBindingListener接口。这样，只要实现valueUnbound()方法，就可以显式地释放Bean使用的资源。 另外一种办法就是尽快地把会话作废。大多数应用<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>都有设置会话作废间隔时间的选项。另外，也可以用编程的方式调用会话的setMaxInactiveInterval()方法，该方法用来设定在作废会话之前，Servlet容器允许的客户请求的最大间隔时间，以秒计。</p>
<p>　　22、使用缓冲标记</p>
<p>　　一些应用<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>加入了面向JSP的缓冲标记功能。例如，BEA的WebLogic Server从6.0版本开始支持这个功能，Open Symphony工程也同样支持这个功能。JSP缓冲标记既能够缓冲页面片断，也能够缓冲整个页面。当JSP页面执行时，如果目标片断已经在缓冲之中，则生成该片断的代码就不用再执行。页面级缓冲捕获对指定 URL的请求，并缓冲整个结果页面。对于购物篮、目录以及门户网站的主页来说，这个功能极其有用。对于这类应用，页面级缓冲能够保存页面执行的结果，供后继请求使用。</p>
<p>　　23、选择合适的引用机制</p>
<p>　　在典型的JSP应用系统中，页头、页脚部分往往被抽取出来，然后根据需要引入页头、页脚。当前，在JSP页面中引入外部资源的方法主要有两种：include指令，以及include动作。</p>
<p>　　include 指令：例如&lt;%@ include file="copyright.html" %&gt;。该指令在编译时引入指定的资源。在编译之前，带有 include指令的页面和指定的资源被合并成一个文件。被引用的外部资源在编译时就确定，比运行时才确定资源更高效。</p>
<p>　　include动作：例如&lt;jsp:include page="copyright.jsp" /&gt;。该动作引入指定页面执行后生成的结果。由于它在运行时完成，因此对输出结果的控制更加灵活。但时，只有当被引用的内容频繁地改变时，或者在对主页面的请求没有出现之前，被引用的页面无法确定时，使用include 动作才合算。</p>
24、及时清除不再需要的会话
<p>　　为了清除不再活动的会话，许多应用服务器都有默认的会话超时时间，一般为30分钟。当应用服务器需要保存更多会话时，如果内存容量不足，操作系统会把部分内存数据转移到磁盘，应用服务器也可能根据&#8220;最近最频繁使用 &#8221;（Most Recently Used）算法把部分不活跃的会话转储到磁盘，甚至可能抛出&#8220;内存不足&#8221;异常。在大规模系统中，串行化会话的代价是很昂贵的。当会话不再需要时，应当及时调用HttpSession.invalidate()方法清除会话。 HttpSession.invalidate()方法通常可以在应用的退出页面调用。</p>
<p>　　25、不要将数组声明为：public static final 。</p>
<p>　　26、HashMap的遍历效率讨论</p>
<p>　　经常遇到对HashMap中的key和value值对的遍历操作，有如下两种方法：Map&lt;String, String[]&gt; paraMap = new HashMap&lt;String, String[]&gt;();</p>
<p>　　................//第一个循环</p>
<p>　　Set&lt;String&gt; appFieldDefIds = paraMap.keySet();</p>
<p>　　for (String appFieldDefId : appFieldDefIds) {</p>
<p>　　String[] values = paraMap.get(appFieldDefId);</p>
<p>　　......</p>
<p>　　}</p>
<p>　　//第二个循环</p>
<p>　　for(Entry&lt;String, String[]&gt; entry : paraMap.entrySet()){</p>
<p>　　String appFieldDefId = entry.getKey();</p>
<p>　　String[] values = entry.getValue();</p>
<p>　　.......</p>
<p>　　}</p>
<p>　　第一种实现明显的效率不如第二种实现。</p>
<p>　　分析如下 Set&lt;String&gt; appFieldDefIds = paraMap.keySet(); 是先从HashMap中取得keySet</p>
<p>　　代码如下：</p>
<p>　　public Set&lt;K&gt; keySet() {</p>
<p>　　Set&lt;K&gt; ks = keySet;</p>
<p>　　return (ks != null ? ks : (keySet = new KeySet()));</p>
<p>　　}</p>
<p>　　private class KeySet extends AbstractSet&lt;K&gt; {</p>
<p>　　public Iterator&lt;K&gt; iterator() {</p>
<p>　　return newKeyIterator();</p>
<p>　　}</p>
<p>　　public int size() {</p>
<p>　　return size;</p>
<p>　　}</p>
<p>　　public boolean contains(Object o) {</p>
<p>　　return containsKey(o);</p>
<p>　　}</p>
<p>　　public boolean remove(Object o) {</p>
<p>　　return HashMap.this.removeEntryForKey(o) != null;</p>
<p>　　}</p>
<p>　　public void clear() {</p>
<p>　　HashMap.this.clear();</p>
<p>　　}</p>
<p>　　}</p>
<p>　　其实就是返回一个私有类KeySet, 它是从AbstractSet继承而来，实现了Set接口。</p>
<p>　　再来看看for/in循环的语法</p>
<p>　　for(declaration : expression)</p>
<p>　　statement</p>
<p>　　在执行阶段被翻译成如下各式</p>
<p>　　for(Iterator&lt;E&gt; #i = (expression).iterator(); #i.hashNext();){</p>
<p>　　declaration = #i.next();</p>
<p>　　statement</p>
<p>　　}</p>
因此在第一个for语句for (String appFieldDefId : appFieldDefIds) 中调用了HashMap.keySet().iterator() 而这个方法调用了newKeyIterator()
<p>　　Iterator&lt;K&gt; newKeyIterator() {</p>
<p>　　return new KeyIterator();</p>
<p>　　}</p>
<p>　　private class KeyIterator extends HashIterator&lt;K&gt; {</p>
<p>　　public K next() {</p>
<p>　　return nextEntry().getKey();</p>
<p>　　}</p>
<p>　　}</p>
<p>　　所以在for中还是调用了</p>
<p>　　在第二个循环for(Entry&lt;String, String[]&gt; entry : paraMap.entrySet())中使用的Iterator是如下的一个内部类</p>
<p>　　private class EntryIterator extends HashIterator&lt;Map.Entry&lt;K,V&gt;&gt; {</p>
<p>　　public Map.Entry&lt;K,V&gt; next() {</p>
<p>　　return nextEntry();</p>
<p>　　}</p>
<p>　　}</p>
<p>　　此时第一个循环得到key，第二个循环得到HashMap的Entry</p>
<p>　　效率就是从循环里面体现出来的第二个循环此致可以直接取key和value值</p>
<p>　　而第一个循环还是得再利用HashMap的get(Object key)来取value值</p>
<p>　　现在看看HashMap的get(Object key)方法</p>
<p>　　public V get(Object key) {</p>
<p>　　Object k = maskNull(key);</p>
<p>　　int hash = hash(k);</p>
<p>　　int i = indexFor(hash, table.length); //Entry[] table</p>
<p>　　Entry&lt;K,V&gt; e = table;</p>
<p>　　while (true) {</p>
<p>　　if (e == null)</p>
<p>　　return null;</p>
<p>　　if (e.hash == hash &amp;&amp; eq(k, e.key))</p>
<p>　　return e.value;</p>
<p>　　e = e.next;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　其实就是再次利用Hash值取出相应的Entry做比较得到结果，所以使用第一中循环相当于两次进入HashMap的Entry中</p>
<p>　　而第二个循环取得Entry的值之后直接取key和value，效率比第一个循环高。其实按照Map的概念来看也应该是用第二个循环好一点，它本来就是key和value的值对，将key和value分开操作在这里不是个好选择。</p>
<p>　　27、array(数组) 和 ArryList的使用</p>
<p>　　array（[]）：最高效；但是其容量固定且无法动态改变；</p>
<p>　　ArrayList：容量可动态增长；但牺牲效率；</p>
<p>　　基于效率和类型检验，应尽可能使用array，无法确定数组大小时才使用ArrayList！</p>
<p>　　ArrayList是Array的复杂版本</p>
<p>　　ArrayList内部封装了一个Object类型的数组，从一般的意义来说，它和数组没有本质的差别，甚至于ArrayList的许多方法，如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。</p>
<p>　　ArrayList存入对象时，抛弃类型信息，所有对象屏蔽为Object，编译时不检查类型，但是运行时会报错。</p>
<p>　　注：jdk5中加入了对泛型的支持，已经可以在使用ArrayList时进行类型检查。</p>
<p>　　从这一点上看来，ArrayList与数组的区别主要就是由于动态增容的效率问题了</p>
<p>　　28、尽量使用HashMap 和ArrayList ,除非必要，否则不推荐使用HashTable和Vector ，后者由于使用同步机制，而导致了性能的开销。</p>
<p>　　29、StringBuffer 和StringBuilder的区别：</p>
<p>　　java.lang.StringBuffer 线程<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>的可变字符序列。一个类似于 String 的字符串缓冲区，但不能修改。StringBuilder。与该类相比，通常应该优先使用 java.lang.StringBuilder类，因为它支持所有相同的操作，但由于它不执行同步，所以速度更快。为了获得更好的性能，在构造 StirngBuffer 或 StirngBuilder 时应尽可能指定它的容量。当然，如果你操作的字符串长度不超过 16 个字符就不用了。 相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%-15% 左右的性能提升，但却要冒多线程不<a class="channel_keylink" href="http://security.chinaitlab.com/" target="_blank">安全</a>的风险。而在现实的模块化编程中，负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行，因此：除非你能确定你的系统的瓶颈是在 StringBuffer 上，并且确定你的模块不会运行在多线程模式下，否则还是用 StringBuffer 吧。</p>
</div><img src ="http://www.blogjava.net/dongwq/aggbug/302365.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-11-14 19:15 <a href="http://www.blogjava.net/dongwq/archive/2009/11/14/302365.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java代码优化编程(1) </title><link>http://www.blogjava.net/dongwq/archive/2009/11/14/302364.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Sat, 14 Nov 2009 11:12:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/11/14/302364.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/302364.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/11/14/302364.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/302364.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/302364.html</trackback:ping><description><![CDATA[<h1 class="Article_tle">&nbsp;</h1>
<div class="Article_content">
<p>　　可供程序利用的资源（内存、CPU时间、网络带宽等）是有限的，优化的目的就是让程序用尽可能少的资源完成预定的任务。优化通常包含两方面的内容：减小代码的体积，提高代码的运行效率。本文讨论的主要是如何提高代码的效率。</p>
<p>　　在 <a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>程序中，性能问题的大部分原因并不在于<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>语言，而是在于程序本身。养成好的代码编写习惯非常重要，比如正确地、巧妙地运用 java.lang.String类和java.util.Vector类，它能够显着地提高程序的性能。下面我们就来具体地分析一下这方面的问题。</p>
<p>　　1、&nbsp;&nbsp;&nbsp; 尽量指定类的final修饰符 带有final修饰符的类是不可派生的。在Java核心API中，有许多应用final的例子，例如 java.lang.String。为String类指定final防止了人们覆盖length()方法。另外，如果指定一个类为final，则该类所有的方法都是final。Java编译器会寻找机会内联（inline）所有的final方法（这和具体的编译器实现有关）。此举能够使性能平均提高 50% 。</p>
<p>　　2、&nbsp;&nbsp;&nbsp; 尽量重用对象。特别是String 对象的使用中，出现字符串连接情况时应用StringBuffer 代替。由于系统不仅要花时间生成对象，以后可能还需花时间对这些对象进行垃圾回收和处理。因此，生成过多的对象将会给程序的性能带来很大的影响。</p>
<p>　　3、&nbsp;&nbsp;&nbsp; 尽量使用局部变量，调用方法时传递的参数以及在调用中创建的临时变量都保存在栈（Stack）中，速度较快。其他变量，如静态变量、实例变量等，都在堆（Heap）中创建，速度较慢。另外，依赖于具体的编译器/JVM，局部变量还可能得到进一步优化。请参见《尽可能使用堆栈变量》。</p>
<p>　　4、&nbsp;&nbsp;&nbsp; 不要重复初始化变量&nbsp; 默认情况下，调用类的构造函数时， Java会把变量初始化成确定的值：所有的对象被设置成null，整数变量（byte、 short、int、long）设置成0，float和double变量设置成0.0，逻辑值设置成false。当一个类从另一个类派生时，这一点尤其应该注意，因为用new关键词创建一个对象时，构造函数链中的所有构造函数都会被自动调用。</p>
<p>　　5、&nbsp;&nbsp;&nbsp; 在JAVA + ORACLE 的应用系统开发中，java中内嵌的SQL语句尽量使用大写的形式，以减轻ORACLE解析器的解析负担。</p>
<p>　　6、&nbsp;&nbsp;&nbsp; Java 编程过程中，进行数据库连接、I/O流操作时务必小心，在使用完毕后，即使关闭以释放资源。因为对这些大对象的操作会造成系统大的开销，稍有不慎，会导致严重的后果。</p>
<p>　　7、&nbsp;&nbsp;&nbsp; 由于JVM的有其自身的GC机制，不需要程序开发者的过多考虑，从一定程度上减轻了开发者负担，但同时也遗漏了隐患，过分的创建对象会消耗系统的大量内存，严重时会导致内存泄露，因此，保证过期对象的及时回收具有重要意义。JVM回收垃圾的条件是：对象不在被引用；然而，JVM的GC并非十分的机智，即使对象满足了垃圾回收的条件也不一定会被立即回收。所以，建议我们在对象使用完毕，应手动置成null。</p>
<p>　　8、&nbsp;&nbsp;&nbsp; 在使用同步机制时，应尽量使用方法同步代替代码块同步。</p>
<p>　　9、&nbsp;&nbsp;&nbsp; 尽量减少对变量的重复计算</p>
<p>　　例如：for(int i = 0;i &lt; list.size; i ++) {</p>
<p>　　&#8230;</p>
<p>　　}</p>
<p>　　应替换为：</p>
<p>　　for(int i = 0,int len = list.size();i &lt; len; i ++) {</p>
<p>　　&#8230;</p>
<p>　　}</p>
<p>　　10、尽量采用lazy loading 的策略，即在需要的时候才开始创建。</p>
<p>　　例如：&nbsp;&nbsp;&nbsp; String str = &#8220;aaa&#8221;;</p>
<p>　　if(i == 1) {</p>
<p>　　list.add(str);</p>
<p>　　}</p>
<p>　　应替换为：</p>
<p>　　if(i == 1) {</p>
<p>　　String str = &#8220;aaa&#8221;;</p>
<p>　　list.add(str);</p>
<p>　　}</p>
<p>　　11、慎用异常</p>
<p>　　异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地（Native）方法，fillInStackTrace()方法检查堆栈，收集调用跟踪信息。只要有异常被抛出，VM就必须调整调用堆栈，因为在处理过程中创建了一个新的对象。 异常只能用于错误处理，不应该用来控制程序流程。</p>
12、不要在循环中使用：
<p>　　Try {</p>
<p>　　} catch() {</p>
<p>　　}</p>
<p>　　应把其放置在最外层。</p>
<p>　　13、StringBuffer 的使用：</p>
<p>　　StringBuffer表示了可变的、可写的字符串。</p>
<p>　　有三个构造方法 :</p>
<p>　　StringBuffer ();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //默认分配16个字符的空间</p>
<p>　　StringBuffer (int size);&nbsp; //分配size个字符的空间</p>
<p>　　StringBuffer (String str);&nbsp; //分配16个字符+str.length()个字符空间</p>
<p>　　你可以通过StringBuffer的构造函数来设定它的初始化容量，这样可以明显地提升性能。这里提到的构造函数是 StringBuffer(int length)，length参数表示当前的StringBuffer能保持的字符数量。你也可以使用 ensureCapacity(int minimumcapacity)方法在StringBuffer对象创建之后设置它的容量。首先我们看看 StringBuffer的缺省行为，然后再找出一条更好的提升性能的途径。</p>
<p>　　StringBuffer在内部维护一个字符数组，当你使用缺省的构造函数来创建StringBuffer对象的时候，因为没有设置初始化字符长度，StringBuffer的容量被初始化为16个字符，也就是说缺省容量就是16个字符。当StringBuffer达到最大容量的时候，它会将自身容量增加到当前的2倍再加2，也就是（2*旧值+2）。如果你使用缺省值，初始化之后接着往里面追加字符，在你追加到第16个字符的时候它会将容量增加到34（2*16+2），当追加到34个字符的时候就会将容量增加到 70（2*34+2）。无论何事只要StringBuffer到达它的最大容量它就不得不创建一个新的字符数组然后重新将旧字符和新字符都拷贝一遍――这也太昂贵了点。所以总是给StringBuffer设置一个合理的初始化容量值是错不了的，这样会带来立竿见影的性能增益。</p>
<p>　　StringBuffer初始化过程的调整的作用由此可见一斑。所以，使用一个合适的容量值来初始化StringBuffer永远都是一个最佳的建议。</p>
<p>　　14、合理的使用Java类 java.util.Vector。</p>
<p>　　简单地说，一个Vector就是一个java.lang.Object实例的数组。Vector与数组相似，它的元素可以通过整数形式的索引访问。但是，Vector类型的对象在创建之后，对象的大小能够根据元素的增加或者删除而扩展、缩小。请考虑下面这个向Vector加入元素的例子：</p>
<p>　　Object obj = new Object();</p>
<p>　　Vector v = new Vector(100000);</p>
<p>　　for(int I=0;</p>
<p>　　I&lt;100000; I++) { v.add(0,obj); }</p>
<p>　　除非有绝对充足的理由要求每次都把新元素插入到Vector的前面，否则上面的代码对性能不利。在默认构造函数中，Vector的初始<a class="channel_keylink" href="http://www.storworld.com/" target="_blank">存储</a>能力是10个元素，如果新元素加入时<a class="channel_keylink" href="http://www.storworld.com/" target="_blank">存储</a>能力不足，则以后存储能力每次加倍。Vector类就象StringBuffer类一样，每次扩展存储能力时，所有现有的元素都要复制到新的存储空间之中。下面的代码片段要比前面的例子快几个数量级：</p>
<p>　　Object obj = new Object();</p>
<p>　　Vector v = new Vector(100000);</p>
<p>　　for(int I=0; I&lt;100000; I++) { v.add(obj); }</p>
<p>　　同样的规则也适用于Vector类的remove()方法。由于Vector中各个元素之间不能含有&#8220;空隙&#8221;，删除除最后一个元素之外的任意其他元素都导致被删除元素之后的元素向前移动。也就是说，从Vector删除最后一个元素要比删除第一个元素&#8220;开销&#8221;低好几倍。</p>
<p>　　假设要从前面的Vector删除所有元素，我们可以使用这种代码：</p>
<p>　　for(int I=0; I&lt;100000; I++)</p>
<p>　　{</p>
<p>　　v.remove(0);</p>
<p>　　}</p>
<p>　　但是，与下面的代码相比，前面的代码要慢几个数量级：</p>
<p>　　for(int I=0; I&lt;100000; I++)</p>
<p>　　{</p>
<p>　　v.remove(v.size()-1);</p>
<p>　　}</p>
<p>　　从Vector类型的对象v删除所有元素的最好方法是：</p>
<p>　　v.removeAllElements();<br />
<br />
<br />
假设Vector类型的对象v包含字符串&#8220;Hello&#8221;。考虑下面的代码，它要从这个Vector中删除&#8220;Hello&#8221;字符串： </p>
<p>　　String s = "Hello";</p>
<p>　　int i = v.indexOf(s);</p>
<p>　　if(I != -1) v.remove(s);</p>
<p>　　这些代码看起来没什么错误，但它同样对性能不利。在这段代码中，indexOf()方法对v进行顺序搜索寻找字符串&#8220;Hello&#8221;，remove(s)方法也要进行同样的顺序搜索。改进之后的版本是：</p>
<p>　　String s = "Hello";</p>
<p>　　int i = v.indexOf(s);</p>
<p>　　if(I != -1) v.remove(i);</p>
<p>　　这个版本中我们直接在remove()方法中给出待删除元素的精确索引位置，从而避免了第二次搜索。一个更好的版本是：</p>
<p>　　String s = "Hello"; v.remove(s);</p>
<p>　　最后，我们再来看一个有关Vector类的代码片段：</p>
<p>　　for(int I=0; I++;I &lt; v.length)</p>
<p>　　如果v包含100,000个元素，这个代码片段将调用v.size()方法100,000次。虽然size方法是一个简单的方法，但它仍旧需要一次方法调用的开销，至少JVM需要为它配置以及清除堆栈环境。在这里，for循环内部的代码不会以任何方式修改Vector类型对象v的大小，因此上面的代码最好改写成下面这种形式：</p>
<p>　　int size = v.size(); for(int I=0; I++;I&lt;size)</p>
<p>　　虽然这是一个简单的改动，但它仍旧赢得了性能。毕竟，每一个CPU周期都是宝贵的。</p>
<p>　　15、当复制大量数据时，使用System.arraycopy()命令。</p>
<p>　　16、代码重构：增强代码的可读性。</p>
<p>　　例如：</p>
<p>　　public class ShopCart {</p>
<p>　　private List carts ;</p>
<p>　　&#8230;</p>
<p>　　public void add (Object item) {</p>
<p>　　if(carts == null) {</p>
<p>　　carts = new ArrayList();</p>
<p>　　}</p>
<p>　　crts.add(item);</p>
<p>　　}</p>
<p>　　public void remove(Object item) {</p>
<p>　　if(carts. contains(item)) {</p>
<p>　　carts.remove(item);</p>
<p>　　}</p>
<p>　　}</p>
<p>　　public List getCarts() {</p>
<p>　　//返回只读列表</p>
<p>　　return Collections.unmodifiableList(carts);</p>
<p>　　}</p>
<p>　　//不推荐这种方式</p>
<p>　　//this.getCarts().add(item);</p>
<p>　　}</p>
</div><img src ="http://www.blogjava.net/dongwq/aggbug/302364.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-11-14 19:12 <a href="http://www.blogjava.net/dongwq/archive/2009/11/14/302364.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA虚拟机内存分配与回收机制 </title><link>http://www.blogjava.net/dongwq/archive/2009/10/12/297976.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Mon, 12 Oct 2009 13:22:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/10/12/297976.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/297976.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/10/12/297976.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/297976.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/297976.html</trackback:ping><description><![CDATA[&nbsp;<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>把内存划分成两种：一种是栈内存，一种是堆内存。
<p>&nbsp;&nbsp;&nbsp; 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。</p>
<p>&nbsp;&nbsp;&nbsp; 当在一段代码块定义一个变量时，<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>就在栈中为这个变量分配内存空间，当超过变量的作用域后，Java会自动释放掉为该变量所分配的内存空间，该内存空间可以立即被另作他用。</p>
<p>&nbsp;&nbsp;&nbsp; 堆内存用来存放由new创建的对象和数组。</p>
<p>&nbsp;&nbsp;&nbsp; 在堆中分配的内存，由Java虚拟机的自动垃圾回收器来管理。</p>
<p>&nbsp;&nbsp;&nbsp; 在堆中产生了一个数组或对象后，还可以在栈中定义一个特殊的变量，让栈中这个变量的取值等于数组或对象在堆内存中的首地址，栈中的这个变量就成了数组或对象的引用变量。</p>
<p>&nbsp;&nbsp;&nbsp; 引用变量就相当于是为数组或对象起的一个名称，以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。</p>
<p>&nbsp;&nbsp;&nbsp; 具体的说：</p>
<p>&nbsp;&nbsp;&nbsp; 栈与堆都是Java用来在Ram中存放数据的地方。与<a class="channel_keylink" href="http://c.chinaitlab.com/" target="_blank">C++</a>不同，Java自动管理栈和堆，程序员不能直接地设置栈或堆。</p>
<p>&nbsp;&nbsp;&nbsp; Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等 指令建立，它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的，堆的优势是可以动态地分配内存大小，生存期也不必事先告诉编译器，因为它是在运行时 动态分配内存的，Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是，由于要在运行时动态分配内存，存取速度较慢。</p>
<p>&nbsp;&nbsp;&nbsp; 栈的优势是，存取速度比堆要快，仅次于寄存器，栈数据可以共享。但缺点是，存在栈中的数据大小与生存期必须是确定的，缺乏灵活性。栈中主要存放一些基本 类型的变量（,int, short, long, byte, float, double, boolean, char）和对象句柄。</p>
<p>&nbsp;&nbsp;&nbsp; 栈有一个很重要的特殊性，就是存在栈中的数据可以共享。假设我们同时定义：</p>
<p>&nbsp;&nbsp;&nbsp; int a = 3;</p>
<p>&nbsp;&nbsp;&nbsp; int b = 3；</p>
<p>&nbsp;&nbsp;&nbsp; 编译器先处理int a = 3；首先它会在栈中创建一个变量为a的引用，然后查找栈中是否有3这个值，如果没找到，就将3存放进来，然后将a指向3。接着处理int b = 3；在创建完b的引用变量后，因为在栈中已经有3这个值，便将b直接指向3。这样，就出现了a与b同时均指向3的情况。这时，如果再令a=4；那么编译器 会重新搜索栈中是否有4值，如果没有，则将4存放进来，并令a指向4；如果已经有了，则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这 种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的，因为这种情况a的修改并不会影响到b, 它是由编译器完成的，它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态，会影响到另一个对象引用变量。</p>
<p>&nbsp;&nbsp;&nbsp; String是一个特殊的包装类数据。可以用：</p>
<p>&nbsp;&nbsp;&nbsp; String str = new String("abc");</p>
<p>&nbsp;&nbsp;&nbsp; String str = "abc";</p>
<p>&nbsp;&nbsp;&nbsp; 两种的形式来创建，第一种是用new()来新建对象的，它会在存放于堆中。每调用一次就会创建一个新的对象。</p>
<p>&nbsp;&nbsp;&nbsp; 而第二种是先在栈中创建一个对String类的对象引用变量str，然后查找栈中有没有存放"abc"，如果没有，则将"abc"存放进栈，并令str指向&#8220;abc&#8221;，如果已经有&#8220;abc&#8221; 则直接令str指向&#8220;abc&#8221;。</p>
<p>&nbsp;&nbsp;&nbsp; 比较类里面的数值是否相等时，用equals()方法；当<a class="channel_keylink" href="http://softtest.chinaitlab.com/" target="_blank">测试</a>两个包装类的引用是否指向同一个对象时，用==，下面用例子说明上面的理论。</p>
<p>&nbsp;&nbsp;&nbsp; String str1 = "abc";</p>
<p>&nbsp;&nbsp;&nbsp; String str2 = "abc";</p>
<p>&nbsp;&nbsp;&nbsp; System.out.println(str1==str2); //true可以看出str1和str2是指向同一个对象的。</p>
<p>&nbsp;&nbsp;&nbsp; String str1 =new String ("abc");</p>
<p>&nbsp;&nbsp;&nbsp; String str2 =new String ("abc");</p>
<p>&nbsp;&nbsp;&nbsp; System.out.println(str1==str2); // false用new的方式是生成不同的对象。每一次生成一个。</p>
<p>&nbsp;&nbsp;&nbsp; 因此用第二种方式创建多个&#8220;abc&#8221;字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度，因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc")；的代码，则一概在堆中创建新对象，而不管其字符串值是否相等，是否有必要创建新对象，从而加重了程序的负担。</p>
<p>&nbsp;&nbsp;&nbsp; 另一方面, 要注意: 我们在使用诸如String str = "abc"；的格式定义类时，总是想当然地认为，创建了String类的对象str。担心陷阱！对象可能并没有被创建！而可能只是指向一个先前已经创建的 对象。只有通过new()方法才能保证每次都创建一个新的对象。 由于String类的immutable性质，当String变量需要经常变换其值时，应该考虑使用StringBuffer类，以提高程序效率。</p>
<p>&nbsp;&nbsp;&nbsp; java中内存分配策略及堆和栈的比较</p>
<p>&nbsp;&nbsp;&nbsp; 2.1 内存分配策略按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.静态<a class="channel_keylink" href="http://www.storworld.com/" target="_blank">存储</a>分配是指在编译时就能确定每个数据目标在运行时刻的<a class="channel_keylink" href="http://www.storworld.com/" target="_blank">存储</a>空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允 许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知 的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存.和我们在数据结构所熟知 的栈一样,栈式存储分配按照先进后出的原则进行分配。</p>
<p>&nbsp;&nbsp;&nbsp; 静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时 模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释 放.</p>
<p>&nbsp;&nbsp;&nbsp; 2.2 堆和栈的比较</p>
<p>&nbsp;&nbsp;&nbsp; 上面的定义从编译原理的教材中总结而来,除静态存储分配之外,都显得很呆板和难以理解,下面撇开静态存储分配,集中比较堆和栈:从堆和栈的功能和作用来通俗的比较,堆主要用来存放对象的，栈主要是用来执行程序的.而这种不同又主要是由于堆和栈的特点决定的:在编程中，例如C/<a class="channel_keylink" href="http://c.chinaitlab.com/" target="_blank">C++</a>中，所有的方法调用都是通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶 向上用就行,就好像工厂中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候，修改栈指针就可以把栈中的内容销毁.这样的模式速度最快, 当然要用来运行程序了.需要注意的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程 序运行时进行的,但是分配的大小多少是确定的,不变的,而这个"大小多少"是在编译时确定的,不是在运行时.堆是应用程序在运行的时候请求操作系统分配给自己内存，由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间，因此用堆的效率非常低.但是堆的 优点在于,编译器不必知道要从堆里分配多少存储空间，也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性。事实上,面 向对象的多态性,堆内存分配是必不可少的,因为多态变量所需的存储空间只有在运行时创建了对象之后才能确定.在C++中，要求创建一个对象时，只需用 new命令编制相关的代码即可。执行这些代码时，会在堆里自动进行数据的保存.当然，为达到这种灵活性，必然会付出一定的代价:在堆里分配存储空间时会花 掉更长的时间！这也正是导致我们刚才所说的效率低的原因,看来列宁同志说的好,人的优点往往也是人的缺点,人的缺点往往也是人的优点.</p>
<p>&nbsp;&nbsp;&nbsp; 2.3 JVM中的堆和栈JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说，它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。</p>
<p>&nbsp;&nbsp;&nbsp; 我们知道,某个线程正在执行的方法称为此线程的当前方法.我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的 Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据.这个帧在这里和编译 原理中的活动纪录的概念是差不多的.从Java的这种分配机制来看,堆栈又可以这样理解:堆栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域，该区域具有先进后出的特性。</p>
<p>&nbsp;&nbsp;&nbsp; 每一个Java应用都唯一对应一个JVM实例，每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程 共享.跟C/C++不同，Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的，但是这个对象的引用却是在堆栈中分配,也 就是说在建立一个对象时从两个地方都分配内存，在堆中分配的内存实际建立这个对象，而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。</p><img src ="http://www.blogjava.net/dongwq/aggbug/297976.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-10-12 21:22 <a href="http://www.blogjava.net/dongwq/archive/2009/10/12/297976.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zz:Java AIO初探(异步网络IO) </title><link>http://www.blogjava.net/dongwq/archive/2009/09/21/295914.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Mon, 21 Sep 2009 14:22:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/09/21/295914.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/295914.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/09/21/295914.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/295914.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/295914.html</trackback:ping><description><![CDATA[Java&nbsp;AIO初探(异步网络IO)&nbsp;<br />
<br />
&nbsp; 按照《Unix网络编程》的划分，IO模型可以分为：阻塞IO、非阻塞IO、IO复用、信号驱动IO和异步IO，按照POSIX标准来划分只分为两类：同步IO和异步IO.如何区分呢？首先一个IO操作其实分成了两个步骤：发起IO请求和实际的IO操作，同步IO和异步IO的区别就在于第二个步骤是否阻塞，如果实际的IO读写阻塞请求进程，那么就是同步IO，因此阻塞IO、非阻塞IO、IO服用、信号驱动IO都是同步IO，如果不阻塞，而是操作系统帮你做完IO操作再将结果返回给你，那么就是异步IO.阻塞IO和非阻塞IO的区别在于第一步，发起IO请求是否会被阻塞，如果阻塞直到完成那么就是传统的阻塞IO，如果不阻塞，那么就是非阻塞IO.
<p>&nbsp;&nbsp;&nbsp; <a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a> nio 2.0的主要改进就是引入了异步IO（包括文件和网络），这里主要介绍下异步网络IO API的使用以及框架的设计，以TCP服务端为例。首先看下为了支持AIO引入的新的类和接口：</p>
<p>&nbsp;&nbsp;&nbsp; java.nio.channels.AsynchronousChannel标记一个channel支持异步IO操作。</p>
<p>&nbsp;&nbsp;&nbsp; java.nio.channels.AsynchronousServerSocketChannel ServerSocket的aio版本，创建TCP服务端，绑定地址，监听端口等。</p>
<p>&nbsp;&nbsp;&nbsp; java.nio.channels.AsynchronousSocketChannel面向流的异步socket channel，表示一个连接。</p>
<p>&nbsp;&nbsp;&nbsp; java.nio.channels.AsynchronousChannelGroup异步channel的分组管理，目的是为了资源共享。一个AsynchronousChannelGroup绑定一个线程池，这个线程池执行两个任务：处理IO事件和派发CompletionHandler.AsynchronousServerSocketChannel创建的时候可以传入一个AsynchronousChannelGroup，那么通过AsynchronousServerSocketChannel创建的AsynchronousSocketChannel将同属于一个组，共享资源。</p>
<p>&nbsp;&nbsp;&nbsp; java.nio.channels.CompletionHandler异步IO操作结果的回调接口，用于定义在IO操作完成后所作的回调工作。AIO的API允许两种方式来处理异步操作的结果：返回的Future模式或者注册CompletionHandler，我更推荐用CompletionHandler的方式，这些handler的调用是由AsynchronousChannelGroup的线程池派发的。显然，线程池的大小是性能的关键因素。AsynchronousChannelGroup允许绑定不同的线程池，通过三个静态方法来创建：public static AsynchronousChannelGroup withFixedThreadPool（int nThreads，</p>
<p>&nbsp;&nbsp;&nbsp; ThreadFactory threadFactory）</p>
<p>&nbsp;&nbsp;&nbsp; throws IOException</p>
<p>&nbsp;&nbsp;&nbsp; public static AsynchronousChannelGroup withCachedThreadPool（ExecutorService executor，</p>
<p>&nbsp;&nbsp;&nbsp; int initialSize）</p>
<p>&nbsp;&nbsp;&nbsp; public static AsynchronousChannelGroup withThreadPool（ExecutorService executor）</p>
<p>&nbsp;&nbsp;&nbsp; throws IOException</p>
<p>&nbsp;&nbsp;&nbsp; 需要根据具体应用相应调整，从框架角度出发，需要暴露这样的配置选项给用户。</p>
<p>&nbsp;&nbsp;&nbsp; 在介绍完了aio引入的TCP的主要接口和类之后，我们来设想下一个aio框架应该怎么设计。参考非阻塞nio框架的设计，一般都是采用Reactor模式，Reacot负责事件的注册、select、事件的派发；相应地，异步IO有个Proactor模式，Proactor负责CompletionHandler的派发，查看一个典型的IO写操作的流程来看两者的区别：</p>
<p>&nbsp;&nbsp;&nbsp; Reactor：&nbsp; send（msg） -&gt; 消息队列是否为空，如果为空&nbsp; -&gt; 向Reactor注册OP_WRITE，然后返回 -&gt; Reactor select -&gt; 触发Writable，通知用户线程去处理 -&gt;先注销Writable（很多人遇到的cpu 100%的问题就在于没有注销），处理Writeable，如果没有完全写入，继续注册OP_WRITE.注意到，写入的工作还是用户线程在处理。</p>
<p>&nbsp;&nbsp;&nbsp; Proactor： send（msg） -&gt; 消息队列是否为空，如果为空，发起read异步调用，并注册CompletionHandler，然后返回。 -&gt; 操作系统负责将你的消息写入，并返回结果（写入的字节数）给Proactor -&gt; Proactor派发CompletionHandler.可见，写入的工作是操作系统在处理，无需用户线程参与。事实上在aio的API中，AsynchronousChannelGroup就扮演了Proactor的角色。</p>
<p>&nbsp;&nbsp;&nbsp; CompletionHandler有三个方法，分别对应于处理成功、失败、被取消（通过返回的Future）情况下的回调处理：</p>
<p>&nbsp;&nbsp;&nbsp; public interface CompletionHandler {</p>
<p>&nbsp;&nbsp;&nbsp; void completed（V result， A attachment）；</p>
<p>&nbsp;&nbsp;&nbsp; void failed（Throwable exc， A attachment）；</p>
<p>&nbsp;&nbsp;&nbsp; void cancelled（A attachment）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; 其中的泛型参数V表示IO调用的结果，而A是发起调用时传入的attchment.</p>
<p>&nbsp;&nbsp;&nbsp; 在初步介绍完aio引入的类和接口后，我们看看一个典型的tcp服务端是怎么启动的，怎么接受连接并处理读和写，这里引用的代码都是yanf4j 的aio分支中的代码，可以从svn checkout，svn地址： <a href="http://yanf4j.googlecode.com/svn/branches/yanf4j-aio">http://yanf4j.googlecode.com/svn/branches/yanf4j-aio</a></p>
<p>&nbsp;&nbsp;&nbsp; 第一步，创建一个AsynchronousServerSocketChannel，创建之前先创建一个AsynchronousChannelGroup，上文提到AsynchronousServerSocketChannel可以绑定一个AsynchronousChannelGroup，那么通过这个AsynchronousServerSocketChannel建立的连接都将同属于一个AsynchronousChannelGroup并共享资源：this.asynchronousChannelGroup = AsynchronousChannelGroup。withCachedThreadPool（Executors.newCachedThreadPool（），this.threadPoolSize）；然后初始化一个AsynchronousServerSocketChannel，通过open方法：this.serverSocketChannel = AsynchronousServerSocketChannel。open（this.asynchronousChannelGroup）；通过nio 2.0引入的SocketOption类设置一些TCP选项：this.serverSocketChannel。setOption（StandardSocketOption.SO_REUSEADDR，true）；this.serverSocketChannel。setOption（StandardSocketOption.SO_RCVBUF，16*1024）；</p>
<p>&nbsp;&nbsp;&nbsp; 绑定本地地址：</p>
<p>&nbsp;&nbsp;&nbsp; this.serverSocketChannel。bind（new InetSocketAddress（"localhost"，8080）， 100）；其中的100用于指定等待连接的队列大小（backlog）。完了吗？还没有，最重要的监听工作还没开始，监听端口是为了等待连接上来以便accept产生一个AsynchronousSocketChannel来表示一个新建立的连接，因此需要发起一个accept调用，调用是异步的，操作系统将在连接建立后，将最后的结果——AsynchronousSocketChannel返回给你：</p>
<p>&nbsp;&nbsp;&nbsp; public void pendingAccept（）{</p>
<p>&nbsp;&nbsp;&nbsp; if （this.started&nbsp; this.serverSocketChannel.isOpen（）） { this.acceptFuture = this.serverSocketChannel.accept（null，</p>
<p>&nbsp;&nbsp;&nbsp; new AcceptCompletionHandler（））；</p>
<p>&nbsp;&nbsp;&nbsp; } else {</p>
<p>&nbsp;&nbsp;&nbsp; throw new IllegalStateException（"Controller has been closed"）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; 注意，重复的accept调用将会抛出PendingAcceptException，后文提到的read和write也是如此。accept方法的第一个参数是你想传给CompletionHandler的attchment，第二个参数就是注册的用于回调的CompletionHandler，最后返回结果Future.你可以对future做处理，这里采用更推荐的方式就是注册一个CompletionHandler.那么accept的CompletionHandler中做些什么工作呢？显然一个赤裸裸的AsynchronousSocketChannel是不够的，我们需要将它封装成session，一个session表示一个连接（mina里就叫IoSession了），里面带了一个缓冲的消息队列以及一些其他资源等。在连接建立后，除非你的<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>只准备接受一个连接，不然你需要在后面继续调用pendingAccept来发起另一个accept请求：</p>
<p>&nbsp;&nbsp;&nbsp; private final class AcceptCompletionHandler implements</p>
<p>&nbsp;&nbsp;&nbsp; CompletionHandler {</p>
<p>&nbsp;&nbsp;&nbsp; @Override</p>
<p>&nbsp;&nbsp;&nbsp; public void cancelled（Object attachment）{</p>
<p>&nbsp;&nbsp;&nbsp; logger.warn（"Accept operation was canceled"）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
&nbsp; @Override
<p>&nbsp;&nbsp;&nbsp; public void completed（AsynchronousSocketChannel socketChannel，</p>
<p>&nbsp;&nbsp;&nbsp; Object attachment）{</p>
<p>&nbsp;&nbsp;&nbsp; try {</p>
<p>&nbsp;&nbsp;&nbsp; logger.debug（"Accept connection from " + socketChannel.getRemoteAddress（））；</p>
<p>&nbsp;&nbsp;&nbsp; configureChannel（socketChannel）；</p>
<p>&nbsp;&nbsp;&nbsp; AioSessionConfig sessionConfig = buildSessionConfig（socketChannel）；</p>
<p>&nbsp;&nbsp;&nbsp; Session session = new AioTCPSession（sessionConfig，AioTCPController.this.configuration。getSessionReadBufferSize（），AioTCPController.this.sessionTimeout）；session.start（）；</p>
<p>&nbsp;&nbsp;&nbsp; registerSession（session）；</p>
<p>&nbsp;&nbsp;&nbsp; } catch（Exception e）{</p>
<p>&nbsp;&nbsp;&nbsp; e.printStackTrace（）；logger.error（"Accept error"， e）；</p>
<p>&nbsp;&nbsp;&nbsp; notifyException（e）；</p>
<p>&nbsp;&nbsp;&nbsp; } finally {</p>
<p>&nbsp;&nbsp;&nbsp; pendingAccept（）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; @Override</p>
<p>&nbsp;&nbsp;&nbsp; public void failed（Throwable exc， Object attachment） { logger.error（"Accept error"， exc）；</p>
<p>&nbsp;&nbsp;&nbsp; try {</p>
<p>&nbsp;&nbsp;&nbsp; notifyException（exc）；</p>
<p>&nbsp;&nbsp;&nbsp; } finally {</p>
<p>&nbsp;&nbsp;&nbsp; pendingAccept（）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; 注意到了吧，我们在failed和completed方法中在最后都调用了pendingAccept来继续发起accept调用，等待新的连接上来。有的同学可能要说了，这样搞是不是递归调用，会不会堆栈溢出？实际上不会，因为发起accept调用的线程与CompletionHandler回调的线程并非同一个，不是一个上下文中，两者之间没有耦合关系。要注意到，CompletionHandler的回调共用的是AsynchronousChannelGroup绑定的线程池，因此千万别在回调方法中调用阻塞或者长时间的操作，例如sleep，回调方法最好能支持超时，防止线程池耗尽。</p>
<p>&nbsp;&nbsp;&nbsp; 连接建立后，怎么读和写呢？回忆下在nonblocking nio框架中，连接建立后的第一件事是干什么？注册OP_READ事件等待socket可读。异步IO也同样如此，连接建立后马上发起一个异步read调用，等待socket可读，这个是Session.start方法中所做的事情：</p>
<p>&nbsp;&nbsp;&nbsp; public class AioTCPSession {</p>
<p>&nbsp;&nbsp;&nbsp; protected void start0（）{</p>
<p>&nbsp;&nbsp;&nbsp; pendingRead（）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; protected final void pendingRead（）{</p>
<p>&nbsp;&nbsp;&nbsp; if （！isClosed（）&nbsp; this.asynchronousSocketChannel.isOpen（）） { if （！this.readBuffer.hasRemaining（）） { this.readBuffer = ByteBufferUtils。increaseBufferCapatity（this.readBuffer）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; this.readFuture = this.asynchronousSocketChannel.read（this.readBuffer， this， this.readCompletionHandler）；</p>
<p>&nbsp;&nbsp;&nbsp; } else {</p>
<p>&nbsp;&nbsp;&nbsp; throw new IllegalStateException（</p>
<p>&nbsp;&nbsp;&nbsp; "Session Or Channel has been closed"）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; AsynchronousSocketChannel的read调用与AsynchronousServerSocketChannel的accept调用类似，同样是非阻塞的，返回结果也是一个Future，但是写的结果是整数，表示写入了多少字节，因此read调用返回的是Future，方法的第一个参数是读的缓冲区，操作系统将IO读到数据拷贝到这个缓冲区，第二个参数是传递给CompletionHandler的attchment，第三个参数就是注册的用于回调的CompletionHandler.这里保存了read的结果Future，这是为了在关闭连接的时候能够主动取消调用，accept也是如此。现在可以看看read的CompletionHandler的实现：</p>
<p>&nbsp;&nbsp;&nbsp; public final class ReadCompletionHandler implements</p>
<p>&nbsp;&nbsp;&nbsp; CompletionHandler {</p>
<p>&nbsp;&nbsp;&nbsp; private static final Logger log = LoggerFactory</p>
<p>&nbsp;&nbsp;&nbsp; 。getLogger（ReadCompletionHandler.class）；</p>
<p>&nbsp;&nbsp;&nbsp; protected final AioTCPController controller；</p>
<p>&nbsp;&nbsp;&nbsp; public ReadCompletionHandler（AioTCPController controller）{</p>
<p>&nbsp;&nbsp;&nbsp; this.controller = controller；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; @Override</p>
<p>&nbsp;&nbsp;&nbsp; public void cancelled（AbstractAioSession session）{</p>
<p>&nbsp;&nbsp;&nbsp; log.warn（"Session（" + session.getRemoteSocketAddress（）</p>
<p>&nbsp;&nbsp;&nbsp; + "）read operation was canceled"）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; @Override</p>
<p>&nbsp;&nbsp;&nbsp; public void completed（Integer result， AbstractAioSession session） { if （log.isDebugEnabled（））</p>
<p>&nbsp;&nbsp;&nbsp; log.debug（"Session（" + session.getRemoteSocketAddress（）</p>
<p>&nbsp;&nbsp;&nbsp; + "）read +" + result + " bytes"）；</p>
<p>&nbsp;&nbsp;&nbsp; if（result 0）{</p>
<p>&nbsp;&nbsp;&nbsp; session.updateTimeStamp（）；session.getReadBuffer（）。flip（）；session.decode（）；session.getReadBuffer（）。compact（）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; } finally {</p>
<p>&nbsp;&nbsp;&nbsp; try {</p>
<p>&nbsp;&nbsp;&nbsp; session.pendingRead（）；</p>
<p>&nbsp;&nbsp;&nbsp; } catch（IOException e）{</p>
<p>&nbsp;&nbsp;&nbsp; session.onException（e）；session.close（）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; controller.checkSessionTimeout（）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; @Override</p>
<p>&nbsp;&nbsp;&nbsp; public void failed（Throwable exc， AbstractAioSession session） { log.error（"Session read error"， exc）；session.onException（exc）；session.close（）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
&nbsp;如果IO读失败，会返回失败产生的异常，这种情况下我们就主动关闭连接，通过session.close（）方法，这个方法干了两件事情：关闭channel和取消read调用：if （null ！= this.readFuture） { this.readFuture.cancel（true）；
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; this.asynchronousSocketChannel.close（）；&nbsp;&nbsp; 在读成功的情况下，我们还需要判断结果result是否小于0，如果小于0就表示对端关闭了，这种情况下我们也主动关闭连接并返回。如果读到一定字节，也就是result大于0的情况下，我们就尝试从读缓冲区中decode出消息，并派发给业务处理器的回调方法，最终通过pendingRead继续发起read调用等待socket的下一次可读。可见，我们并不需要自己去调用channel来进行IO读，而是操作系统帮你直接读到了缓冲区，然后给你一个结果表示读入了多少字节，你处理这个结果即可。而nonblocking IO框架中，是reactor通知用户线程socket可读了，然后用户线程自己去调用read进行实际读操作。这里还有个需要注意的地方，就是decode出来的消息的派发给业务处理器工作最好交给一个线程池来处理，避免阻塞group绑定的线程池。</p>
<p>&nbsp;&nbsp;&nbsp; IO写的操作与此类似，不过通常写的话我们会在session中关联一个缓冲队列来处理，没有完全写入或者等待写入的消息都存放在队列中，队列为空的情况下发起write调用：</p>
<p>&nbsp;&nbsp;&nbsp; protected void write0（WriteMessage message）{</p>
<p>&nbsp;&nbsp;&nbsp; boolean needWrite = false；</p>
<p>&nbsp;&nbsp;&nbsp; synchronized （this.writeQueue） { needWrite = this.writeQueue.isEmpty（）；this.writeQueue.offer（message）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; if（needWrite）{</p>
<p>&nbsp;&nbsp;&nbsp; pendingWrite（message）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; protected final void pendingWrite（WriteMessage message）{</p>
<p>&nbsp;&nbsp;&nbsp; message = preprocessWriteMessage（message）；</p>
<p>&nbsp;&nbsp;&nbsp; if （！isClosed（）&nbsp; this.asynchronousSocketChannel.isOpen（）） { this.asynchronousSocketChannel.write（message.getWriteBuffer（），this， this.writeCompletionHandler）；</p>
<p>&nbsp;&nbsp;&nbsp; } else {</p>
<p>&nbsp;&nbsp;&nbsp; throw new IllegalStateException（</p>
<p>&nbsp;&nbsp;&nbsp; "Session Or Channel has been closed"）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; write调用返回的结果与read一样是一个Future，而write的CompletionHandler处理的核心逻辑大概是这样：</p>
<p>&nbsp;&nbsp;&nbsp; @Override</p>
<p>&nbsp;&nbsp;&nbsp; public void completed（Integer result， AbstractAioSession session） { if （log.isDebugEnabled（））</p>
<p>&nbsp;&nbsp;&nbsp; log.debug（"Session（" + session.getRemoteSocketAddress（）</p>
<p>&nbsp;&nbsp;&nbsp; + "）writen " + result + " bytes"）；</p>
<p>&nbsp;&nbsp;&nbsp; WriteMessage writeMessage；</p>
<p>&nbsp;&nbsp;&nbsp; Queue writeQueue = session.getWriteQueue（）；</p>
<p>&nbsp;&nbsp;&nbsp; synchronized（writeQueue）{</p>
<p>&nbsp;&nbsp;&nbsp; writeMessage = writeQueue.peek（）；if （writeMessage.getWriteBuffer（） == null || ！writeMessage.getWriteBuffer（）。hasRemaining（）） { writeQueue.remove（）；if （writeMessage.getWriteFuture（） ！= null） { writeMessage.getWriteFuture（）。setResult（Boolean.TRUE）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; try {</p>
<p>&nbsp;&nbsp;&nbsp; session.getHandler（）。onMessageSent（session，writeMessage.getMessage（））；</p>
<p>&nbsp;&nbsp;&nbsp; } catch（Exception e）{</p>
<p>&nbsp;&nbsp;&nbsp; session.onException（e）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; writeMessage = writeQueue.peek（）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; if （writeMessage ！= null） {</p>
<p>&nbsp;&nbsp;&nbsp; try {</p>
<p>&nbsp;&nbsp;&nbsp; session.pendingWrite（writeMessage）；</p>
<p>&nbsp;&nbsp;&nbsp; } catch（IOException e）{</p>
<p>&nbsp;&nbsp;&nbsp; session.onException（e）；session.close（）；</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; compete方法中的result就是实际写入的字节数，然后我们判断消息的缓冲区是否还有剩余，如果没有就将消息从队列中移除，如果队列中还有消息，那么继续发起write调用。</p>
<p>&nbsp;&nbsp;&nbsp; 重复一下，这里引用的代码都是yanf4j aio分支中的源码，感兴趣的朋友可以直接check out出来看看： <a href="http://yanf4j.googlecode.com/svn/branches/yanf4j-aio">http://yanf4j.googlecode.com/svn/branches/yanf4j-aio</a>.在引入了aio之后，java对于网络层的支持已经非常完善，该有的都有了，java也已经成为<a class="channel_keylink" href="http://server.chinaitlab.com/" target="_blank">服务器</a>开发的首选语言之一。java的弱项在于对内存的管理上，由于这一切都交给了GC，因此在高性能的网络服务器上还是Cpp的天下。java这种单一堆模型比之erlang的进程内堆模型还是有差距，很难做到高效的垃圾回收和细粒度的内存管理。</p>
<p>&nbsp;&nbsp;&nbsp; 这里仅仅是介绍了aio开发的核心流程，对于一个网络框架来说，还需要考虑超时的处理、缓冲buffer的处理、业务层和网络层的切分、可扩展性、性能的可调性以及一定的通用性要求。</p><img src ="http://www.blogjava.net/dongwq/aggbug/295914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-09-21 22:22 <a href="http://www.blogjava.net/dongwq/archive/2009/09/21/295914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java泛型学习笔记</title><link>http://www.blogjava.net/dongwq/archive/2009/08/15/291268.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Sat, 15 Aug 2009 08:15:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/08/15/291268.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/291268.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/08/15/291268.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/291268.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/291268.html</trackback:ping><description><![CDATA[<p><br />
generic points to List&lt;String&gt; , List is called raw type here, and &lt;String&gt; is the parametered type.</p>
<p>Generic's functions are :<br />
1. remove type cast;<br />
2. typesafe programming;</p>
<p>The key question of Generic:<br />
1. the inheritance attribute of OO is not support: List&lt;String&gt; is not a type of List&lt;Object&gt;。<br />
<br />
2. Collection&lt;?&gt; c: the parametered type is unknown. so you cant add elem into c.but you may get the elem in c and we know they are of type Object. <br />
<br />
</p>
<p>3、类型推断</p>
<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"><img id="Codehighlighter1_77_148_Open_Image" onclick="this.style.display='none'; Codehighlighter1_77_148_Open_Text.style.display='none'; Codehighlighter1_77_148_Closed_Image.style.display='inline'; Codehighlighter1_77_148_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_77_148_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_77_148_Closed_Text.style.display='none'; Codehighlighter1_77_148_Open_Image.style.display='inline'; Codehighlighter1_77_148_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;T&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;&nbsp;fromArrayToCollection(T[]&nbsp;a,&nbsp;Collection&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;&nbsp;T&nbsp;&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;c)&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_77_148_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_77_148_Open_Text"><span style="color: #000000">{&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br />
<img id="Codehighlighter1_101_144_Open_Image" onclick="this.style.display='none'; Codehighlighter1_101_144_Open_Text.style.display='none'; Codehighlighter1_101_144_Closed_Image.style.display='inline'; Codehighlighter1_101_144_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_101_144_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_101_144_Closed_Text.style.display='none'; Codehighlighter1_101_144_Open_Image.style.display='inline'; Codehighlighter1_101_144_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;&nbsp;(T&nbsp;o&nbsp;:&nbsp;a)&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_101_144_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_101_144_Open_Text"><span style="color: #000000">{&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c.add(o);&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;&nbsp;correct&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div>
<p>&nbsp; 对这个方法参数化类型T，由定义数据a和Collection时传入的共同决定，它们可以使用相同类型，也可以使用不同类型，当类型不同时，它们必须有继承关系，类型推断时使用较高的那个。<br />
4， when to use &lt;?&gt; or &lt;T&gt; :他们主要用在泛型方法，T相比?，它有名称，可多次使用来表达依赖关系。所以在不表达依赖关系的地方就应该使用?。它简单、灵活。</p>
<p class="Arial10" style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">而且有趣的是，它们并非水火不容，反而可以精妙配合，如下：</span>&nbsp;<span style="font-family: 宋体">&nbsp;</p>
<p>&nbsp;</p>
<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: #008080">1</span><img id="Codehighlighter1_20_106_Open_Image" onclick="this.style.display='none'; Codehighlighter1_20_106_Open_Text.style.display='none'; Codehighlighter1_20_106_Closed_Image.style.display='inline'; Codehighlighter1_20_106_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_20_106_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_20_106_Closed_Text.style.display='none'; Codehighlighter1_20_106_Open_Image.style.display='inline'; Codehighlighter1_20_106_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Collections&nbsp;</span><span id="Codehighlighter1_20_106_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_20_106_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">3</span><span style="color: #000000"><img id="Codehighlighter1_99_102_Open_Image" onclick="this.style.display='none'; Codehighlighter1_99_102_Open_Text.style.display='none'; Codehighlighter1_99_102_Closed_Image.style.display='inline'; Codehighlighter1_99_102_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_99_102_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_99_102_Closed_Text.style.display='none'; Codehighlighter1_99_102_Open_Image.style.display='inline'; Codehighlighter1_99_102_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;T&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;copy(List&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;T&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;dest,&nbsp;List&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">?</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;T&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;src)&nbsp;</span><span id="Codehighlighter1_99_102_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_99_102_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;</span></div>
<p>&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left" align="left">这个合作使得</span><font face="宋体"><span lang="EN-US">dest</span> <span style="font-family: 宋体">与</span> <span lang="EN-US">src</span> <span style="font-family: 宋体">的依赖关系得以表达，同时让</span> <span lang="EN-US">src</span> <span style="font-family: 宋体">的接纳范畴扩大了。假如我们只用泛型方法来实现：</span>&nbsp;</font><span style="font-family: 宋体">&nbsp;</p>
<p>&nbsp;</p>
<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: #008080">1</span><img id="Codehighlighter1_20_110_Open_Image" onclick="this.style.display='none'; Codehighlighter1_20_110_Open_Text.style.display='none'; Codehighlighter1_20_110_Closed_Image.style.display='inline'; Codehighlighter1_20_110_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_20_110_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_20_110_Closed_Text.style.display='none'; Codehighlighter1_20_110_Open_Image.style.display='inline'; Codehighlighter1_20_110_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Collections&nbsp;</span><span id="Codehighlighter1_20_110_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_20_110_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">3</span><span style="color: #000000"><img id="Codehighlighter1_103_106_Open_Image" onclick="this.style.display='none'; Codehighlighter1_103_106_Open_Text.style.display='none'; Codehighlighter1_103_106_Closed_Image.style.display='inline'; Codehighlighter1_103_106_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_103_106_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_103_106_Closed_Text.style.display='none'; Codehighlighter1_103_106_Open_Image.style.display='inline'; Codehighlighter1_103_106_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;T,&nbsp;S&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;T&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;copy(List&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;T&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;dest,&nbsp;List&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;S&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;src)&nbsp;</span><span id="Codehighlighter1_103_106_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_103_106_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;</span></div>
<p>&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left" align="left">那么</span><font face="宋体"><span lang="EN-US">S</span> <span style="font-family: 宋体">的存在就显得有些不必要，有些不优雅。总的来说，通配符更简洁清晰，只要情况允许就应该首选。</span> <br />
</font><br />
5、由于普通数组是协变的，而GenricType由于List&lt;String&gt;不是List&lt;Object&gt;的子类型，所以它不能协变。可以使用?来new 一个数组。但是通常new完就要加元素，而？类型未知不可以产生对象的。所以最后使用Class&lt;T&gt; 类型做形参，实参用T.class就可以。这就是为什么Hibernate.load和get中会使用的.class的用法。比较新知识点是String.class就是Class&lt;String&gt;(String.class称字面类常量)。当传入Class&lt;T&gt; c 对象后，可以利用reflect来构造对象，并作状态设置。<br />
<br />
<br />
</p><img src ="http://www.blogjava.net/dongwq/aggbug/291268.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-08-15 16:15 <a href="http://www.blogjava.net/dongwq/archive/2009/08/15/291268.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse下的重构整理</title><link>http://www.blogjava.net/dongwq/archive/2009/08/13/291098.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Thu, 13 Aug 2009 15:32:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/08/13/291098.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/291098.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/08/13/291098.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/291098.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/291098.html</trackback:ping><description><![CDATA[<p>Eclipse下的重构：</p>
<p>什么是重构<br />
重构是指在保持程序的全部功能的基础上改变程序结构的过程。重构的类型有很多，如更改类名，改变方法名，或者提取代码到方法中。每一次重构，都要执行一系列的步骤，这些步骤要保证代码和原代码相一致。</p>
<p><br />
重构的理由：为整理，为扩展，为优雅。</p>
<p>在Eclipse下的重构：</p>
<p>重构会关联多个文件，在一次重构时，不可再修改并保存文件，重构无法撤销或重做。</p>
<p>Eclipse中的重构类型<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你看一下Eclipse的重构菜单，可以看到四部分。第一部分是撤销和重做。其他的三部分包含Eclipse提供的三种类型的重构。<br />
第一种类型的重构改变代码的物理结构，像Rename和Move。第二种是在类层次上改变代码结构，例如Pull Up和Push Down。第三种是改变类内部的代码，像Extract Method和Encapsulate Field。这三部分的重构列表如下。<br />
&nbsp;<br />
类型1 物理结构<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rename<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Move<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Change Method signature<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Convert Anonymous Class to Nested<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Convert Member Type to New File：内部类提出一个单独类。<br />
&nbsp;<br />
类型2 类层次结构<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Push Down：将父类中方法或成员移到子类。<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Push Up<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Extract Interface<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Generalize Type (Eclipse 3)<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User Supertype Where Possible<br />
类型3 类内部结构<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Inline<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Extract Method<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Extract Local Variable<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Extract Constant<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Introduce Parameter：引进参数替换local var<br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Introduce Factory <br />
l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Encapsulate Field<br />
<br />
<br />
表从Eclipse帮助中提取，列出了各种重构支持的Java资源类型，对应的快捷键。 </p>
<div>&nbsp;</div>
<p>&nbsp;</p>
<p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>名字</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>可应用的Java元素</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>快捷键</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>Undo</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>在一次重构后可执行</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Alt + Shift + Z</span> </div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>Redo</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>在一次撤销重构后可执行</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Alt + Shift + Y</span> </div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>Rename</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对方法，成员变量，局部变量，方法参数，对象，类，包，源代码目录，工程可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Alt + Shift + R</span> </div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>Move</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对方法，成员变量，局部变量，方法参数，对象，类，包，源代码目录，工程可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Alt + Shift + V</span> </div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Change Method Signature</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对方法可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div><span style="font-size: 10pt">Alt + Shift + C</span> </div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Convert Anonymous Class to Nested</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对匿名内部类可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Move Member Type to New File</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对嵌套类可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Push Down</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对同一个类中成员变量和方法可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Pull Up</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对同一个类中成员变量和方法，嵌套类可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Extract Interface</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对类可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Generalize Type</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对对象的声明可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Use Supertype Where Possible</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对类可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>Inline</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对方法，静态final类，局部变量可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Alt + Shift + I</span> </div>
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Extract Method</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对方法中的一段代码可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Alt + Shift + M</span> </div>
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Extract Local Variable</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对选中的与局部变量相关的代码可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Alt + Shift + L</span> </div>
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Extract Constant</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对静态final类变量，选中的与静态final类变量相关的代码可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Introduce Parameter</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对方法中对成员变量和局部变量的引用可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Introduce Factory</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对构造方法可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 142pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div align="left"><span style="font-size: 10pt">Convert Local Variable to Field</span> </div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div>对局部变量可用。</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: rgb(236,233,216); padding-bottom: 0cm; width: 142.05pt; border-top-color: rgb(236,233,216); padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="189">
            <div><span style="font-size: 10pt">Alt + Shift +</span></div>
            </td>
        </tr>
    </tbody>
</table>
</p><img src ="http://www.blogjava.net/dongwq/aggbug/291098.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-08-13 23:32 <a href="http://www.blogjava.net/dongwq/archive/2009/08/13/291098.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse中常用的快捷键(最经典的快捷键,就不用多说了)</title><link>http://www.blogjava.net/dongwq/archive/2009/07/30/289184.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Thu, 30 Jul 2009 14:45:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/07/30/289184.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/289184.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/07/30/289184.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/289184.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/289184.html</trackback:ping><description><![CDATA[<p>Eclipse中常用的快捷键(最经典的快捷键,就不用多说了)</p>
<p>Ctrl+D: 删除当前行&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>Ctrl+Alt+&#8595; 复制当前行到下一行(复制增加)</p>
<p>Ctrl+Alt+&#8593; 复制当前行到上一行(复制增加)</p>
<p>Alt+&#8595; 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)</p>
<p>Alt+&#8593;&nbsp;&nbsp;&nbsp; 当前行和上面一行交互位置(同上)</p>
<p>Alt+&#8592; 前一个编辑的页面</p>
<p>Alt+&#8594; 下一个编辑的页面(当然是针对上面那条来说了)</p>
<p>Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性</p>
<p>Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)</p>
<p>Shift+Ctrl+Enter 在当前行插入空行(原理同上条)</p>
<p>Ctrl+Q&nbsp;&nbsp;&nbsp; 定位到最后编辑的地方</p>
<p>Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)</p>
<p>Ctrl+M 最大化当前的Edit或View (再按则反之)</p>
<p>Ctrl+/&nbsp;&nbsp;&nbsp; 注释当前行,再按则取消注释</p>
<p>Ctrl+O&nbsp;&nbsp;&nbsp; 快速显示 OutLine</p>
<p>Ctrl+T&nbsp;&nbsp;&nbsp; 快速显示当前类的继承结构</p>
<p>Ctrl+W 关闭当前Editer</p>
<p>Ctrl+K&nbsp;&nbsp;&nbsp; 参照选中的Word快速定位到下一个</p>
<p>Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)</p>
<p>Ctrl+/(小键盘) 折叠当前类中的所有代码</p>
<p>Ctrl+&#215;(小键盘) 展开当前类中的所有代码</p>
<p>Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用Alt+/来代替)</p>
<p>Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)</p>
<p>Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有,则在stutes line中显示没有找到了,查一个单词时,特别实用,这个功能Idea两年前就有了)</p>
<p>Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)</p>
<p>Ctrl+Shift+F4 关闭所有打开的Editer</p>
<p>Ctrl+Shift+X&nbsp;&nbsp;&nbsp; 把当前选中的文本全部变为大写</p>
<p>Ctrl+Shift+Y&nbsp;&nbsp;&nbsp; 把当前选中的文本全部变为小写</p>
<p>Ctrl+Shift+F 格式化当前代码</p>
<p>Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反之)</p>
<p>下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift开头的了)</p>
<p>Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力)</p>
<p>Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)</p>
<p>Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)</p>
<p>Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)</p>
<p>Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)</p>
<p>Alt+Shift+I 合并变量(可能这样说有点不妥Inline) </p>
<p>Alt+Shift+V 移动函数和变量(不怎么常用)</p>
<p>Alt+Shift+Z 重构的后悔药(Undo)</p>
<p>Ctrl+Shift+U 选择选中的文字后非常类似于UE的列表查询</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/f128690011/archive/2007/06/24/1664354.aspx</p><img src ="http://www.blogjava.net/dongwq/aggbug/289184.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-07-30 22:45 <a href="http://www.blogjava.net/dongwq/archive/2009/07/30/289184.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zz:Mysql中文乱码的几个解决方法</title><link>http://www.blogjava.net/dongwq/archive/2009/07/26/288485.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Sun, 26 Jul 2009 15:08:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/07/26/288485.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/288485.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/07/26/288485.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/288485.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/288485.html</trackback:ping><description><![CDATA[<div class="blog_title">
<h3 class="" title="随笔"><a href="http://deepsea0001.javaeye.com/blog/344961">Mysql中文乱码的几个解决方法</a></h3>
</div>
<div class="blog_content">1:改变数据库的默认编码配置，在MYSQL的安装目录中，找到my.ini，修改默认编码为：default-character-set=utf8 <br />
<br />
2:建立数据库时，CREATE DATABASE ms_db CHARACTER SET utf8 COLLATE utf8_general_ci; <br />
<br />
3:执行脚本：指定编码格式set names utf8(注意，不是UTF-8 <br />
<br />
4:如果你采用的是外部接入的方式，在连接中确定请求的编码格式如：jdbc:mysql://localhost:3306 /ms_db?useUnicode=true&amp;characterEncoding=UTF-8(不要出现任何空格，否则出错) <br />
<br />
5:set character_set_results=gbk;(解决命令行乱码问题)； <br />
<br />
-------------------------------------------------------------------------------- <br />
<br />
问题的关键在于数据导出、导入时要做到所使用的字符集相一致： <br />
1、mysqldump 的 default-character-set变量; <br />
2、mysql 的--default-character-set变量; <br />
3、mysqld的 Db characterset变量。 <br />
例如：备份使用latin1字符集则恢复时也要使用该字符集并且数据库的缺省字符集也要是该字符集，即latin1. 换成gbk也应该一样. <br />
<br />
乱码的根源在于字符集的不一致：操作系统（Windows为gbk，Linux是UTF－8），数据库（CREATE DATABASE db_name DEFAULT CHARACTER SET gbk 或者CREATE DATABASE db_name DEFAULT CHARACTER SET latin1）使用图形界面是就更要注意其缺省配置。 <br />
<br />
-------------------------------------------------------------------------------- <br />
<br />
在这里我把自己知道的东东贴出来，还望大家多多提意见，补充，谢谢~~ <br />
<br />
show variables like 'character%';查看字符编码 <br />
<br />
--更改字符集 <br />
SET character_set_client = utf-8 ; <br />
SET character_set_connection = utf-8 ; <br />
SET character_set_database = utf-8 ; <br />
SET character_set_results = utf-8 ; <br />
SET character_set_server = utf-8 ; <br />
<br />
<br />
SET collation_connection = utf8 ; <br />
SET collation_database = utf8 ; <br />
SET collation_server = utf8 ; <br />
<br />
<br />
MySQL的字符集支持(Character Set Support)有两个方面：字符集(Character set)和排序方式(Collation)。对于字符集的支持细化到四个层次: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 服务器(server)，数据库(database)，数据表(table)和连接(connection)。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.MySQL默认字符集:MySQL对于字符集的指定可以细化到一个数据库，一张表，一列.传统的程序在创建数据库和数据表时并没有使用那么复杂的配置，它们用的是默认的配置.&nbsp;&nbsp;&nbsp; (1)编译MySQL 时，指定了一个默认的字符集，这个字符集是 latin1；(2)安装MySQL 时，可以在配置文件 (my.ini) 中指定一个默认的的字符集，如果没指定，这个值继承自编译时指定的；(3)启动mysqld 时，可以在命令行参数中指定一个默认的的字符集，如果没指定，这个值继承自配置文件中的配置,此时 character_set_server 被设定为这个默认的字符集；(4)当创建一个新的数据库时，除非明确指定，这个数据库的字符集被缺省设定为character_set_server； (5)当选定了一个数据库时，character_set_database 被设定为这个数据库默认的字符集；(6)在这个数据库里创建一张表时，表默认的字符集被设定为 character_set_database，也就是这个数据库默认的字符集；(7)当在表内设置一栏时，除非明确指定，否则此栏缺省的字符集就是表默认的字符集；如果什么地方都不修改，那么所有的数据库的所有表的所有栏位的都用 latin1 存储，不过我们如果安装 MySQL，一般都会选择多语言支持，也就是说，安装程序会自动在配置文件中把 default_character_set 设置为 UTF-8，这保证了缺省情况下，所有的数据库的所有表的所有栏位的都用 UTF-8 存储。 <br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.查看默认字符集(默认情况下，mysql的字符集是latin1(ISO_8859_1)通常，查看系统的字符集和排序方式的设定可以通过下面的两条命令： <br />
&nbsp;&nbsp;&nbsp;&nbsp; mysql&gt; SHOW VARIABLES LIKE 'character%'; <br />
+--------------------------+---------------------------------+ <br />
| Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
+--------------------------+---------------------------------+ <br />
| character_set_client&nbsp;&nbsp;&nbsp;&nbsp; | latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_connection | latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_database&nbsp;&nbsp; | latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_filesystem | binary&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_results&nbsp;&nbsp;&nbsp; | latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_server&nbsp;&nbsp;&nbsp;&nbsp; | latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_system&nbsp;&nbsp;&nbsp;&nbsp; | utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_sets_dir&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | D:"mysql-5.0.37"share"charsets" | <br />
+--------------------------+---------------------------------+ <br />
<br />
mysql&gt; SHOW VARIABLES LIKE 'collation_%'; <br />
+----------------------+-----------------+ <br />
| Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
+----------------------+-----------------+ <br />
| collation_connection | utf8_general_ci | <br />
| collation_database&nbsp;&nbsp; | utf8_general_ci | <br />
| collation_server&nbsp;&nbsp;&nbsp;&nbsp; | utf8_general_ci | <br />
+----------------------+-----------------+ <br />
<br />
3.修改默认字符集 <br />
(1) 最简单的修改方法，就是修改mysql的my.ini文件中的字符集键值， <br />
如&nbsp;&nbsp;&nbsp; default-character-set = utf8 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; character_set_server = utf8 <br />
&nbsp;&nbsp; 修改完后，重启mysql的服务，service mysql restart <br />
&nbsp;&nbsp; 使用 mysql&gt; SHOW VARIABLES LIKE 'character%';查看，发现数据库编码均已改成utf8 <br />
+--------------------------+---------------------------------+ <br />
| Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
+--------------------------+---------------------------------+ <br />
| character_set_client&nbsp;&nbsp;&nbsp;&nbsp; | utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_connection | utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_database&nbsp;&nbsp; | utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_filesystem | binary&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_results&nbsp;&nbsp;&nbsp; | utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_server&nbsp;&nbsp;&nbsp;&nbsp; | utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_set_system&nbsp;&nbsp;&nbsp;&nbsp; | utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
| character_sets_dir&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | D:"mysql-5.0.37"share"charsets" | <br />
+--------------------------+---------------------------------+ <br />
<br />
&nbsp;&nbsp; (2) 还有一种修改字符集的方法，就是使用mysql的命令 <br />
&nbsp;&nbsp;&nbsp;&nbsp; SET character_set_client = utf8 ; <br />
&nbsp;&nbsp;&nbsp;&nbsp; SET character_set_connection = utf8 ; <br />
&nbsp;&nbsp;&nbsp;&nbsp; SET character_set_database = utf8 ; <br />
&nbsp;&nbsp;&nbsp;&nbsp; SET character_set_results = utf8 ; <br />
&nbsp;&nbsp;&nbsp;&nbsp; SET character_set_server = utf8 ; <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; mysql&gt; SET collation_connection = utf8 ; <br />
&nbsp;&nbsp;&nbsp;&nbsp; mysql&gt; SET collation_database = utf8 ; <br />
&nbsp;&nbsp;&nbsp;&nbsp; mysql&gt; SET collation_server = utf8 ; <br />
<br />
一般就算设置了表的默认字符集为utf8并且通过UTF-8编码发送查询，你会发现存入数据库的仍然是乱码。问题就出在这个connection连接层上。解决方法是在发送查询前执行一下下面这句： <br />
SET NAMES 'utf8'; <br />
<br />
它相当于下面的三句指令： <br />
SET character_set_client = utf8; <br />
SET character_set_results = utf8; <br />
SET character_set_connection = utf8; <br />
<br />
不知道什么原因,我在自己机器上把上述三个字符集都设置成utf8后,查询中文结果还是乱码,只有把character_set_results设置成GBK之后才能从命令行正常显示中文. <br />
set character_set_results=GBK; <br />
<br />
--------------------------------------------------------------- <br />
<br />
如果用eclipse ： <br />
&nbsp;&nbsp; 点击Window--&gt;Preferences，展开General--&gt;WorkSpace，看到左边的Text file encoding没有，默认的设定是简体中文编码（gbk，gb2312这样），而linux下面呢，是UTF-8。 <br />
<br />
当你新建一个项目，希望使用和WorkSpace不同编码，请右击你的项目，选择Properties，点击Resource，看到Text file encoding了吧，点击Other，选择UTF-8 <br />
<br />
<br />
最后,将my.ini中的两处default 的字符集改为gbk不要使用utf8 <br />
</div><img src ="http://www.blogjava.net/dongwq/aggbug/288485.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-07-26 23:08 <a href="http://www.blogjava.net/dongwq/archive/2009/07/26/288485.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zz:提升JSP页面响应速度的七大秘籍绝招</title><link>http://www.blogjava.net/dongwq/archive/2009/06/17/282921.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Wed, 17 Jun 2009 13:53:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/06/17/282921.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/282921.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/06/17/282921.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/282921.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/282921.html</trackback:ping><description><![CDATA[<font style="font-size: 14pt" color="#02368d"><strong>方法一：在servlet的init()方法中缓存数据
<p>　　当应用服务器初始化servlet实例之后，为客户端请求提供服务之前，它会调用这个servlet的init()方法。在一个servlet 的生命周期中，init()方法只会被调用一次。通过在init()方法中缓存一些静态的数据或完成一些只需要执行一次的、耗时的操作，就可大大地提高系统性能。</p>
<p>　　例如，通过在init()方法中建立一个JDBC连接池是一个最佳例子，假设我们是用jdbc2.0的DataSource接口来取得<a class="ReplaceKeyword" href="http://www.knowsky.com/sql.asp" target="_blank">数据库</a>连接，在通常的情况下，我们需要通过JNDI来取得具体的数据源。我们可以想象在一个具体的应用中，如果每次SQL请求都要执行一次JNDI查询的话，那系统性能将会急剧下降。解决方法是如下代码，它通过缓存DataSource，使得下一次SQL调用时仍然可以继续利用它：</p>
<p>以下是引用片段：<br />
public class ControllerServlet extends HttpServlet{ <br />
private javax.sql.DataSource testDS = null; 　 <br />
public void init(ServletConfig config) throws ServletException　{ <br />
super.init(config); 　　 <br />
Context ctx = null;　　 <br />
try{ 　　　 <br />
ctx = new InitialContext();　　　 <br />
testDS = (javax.sql.DataSource)ctx.lookup("jdbc/testDS"); <br />
}catch(NamingException ne){ne.printStackTrace();} <br />
}catch(Exception e){e.printStackTrace();} <br />
}　 <br />
public javax.sql.DataSource getTestDS(){　 <br />
　return testDS;　 <br />
}　 <br />
... <br />
...&nbsp; <br />
} </p>
<p><br />
　<span style="font-weight: bold">　方法 2:禁止servlet和</span><a class="ReplaceKeyword" style="font-weight: bold" href="http://www.knowsky.com/jsp.asp" target="_blank">JSP</a><span style="font-weight: bold"> 自动重载(auto-reloading)</span></p>
<p>　　Servlet/JSP提供了一个实用的技术，即自动重载技术，它为开发人员提供了一个好的开发环境，当你改变servlet和JSP页面后而不必重启应用服务器。然而，这种技术在产品运行阶段对系统的资源是一个极大的损耗，因为它会给JSP引擎的类装载器(classloader)带来极大的负担。因此关闭自动重载功能对系统性能的提升是一个极大的帮助。</p>
<p>　<span style="font-weight: bold">　方法 3: 不要滥用HttpSession</span></p>
<p>　　在很多应用中，我们的程序需要保持客户端的状态，以便页面之间可以相互联系。但不幸的是由于HTTP具有天生无状态性，从而无法保存客户端的状态。因此一般的应用服务器都提供了session来保存客户的状态。在JSP应用服务器中，是通过HttpSession对像来实现session的功能的，但在方便的同时，它也给系统带来了不小的负担。因为每当你获得或更新session时，系统者要对它进行费时的序列化操作。你可以通过对 HttpSession的以下几种处理方式来提升系统的性能。</p>
<p>　　如果没有必要，就应该关闭JSP页面中对HttpSession的缺省设置。 如果你没有明确指定的话，每个JSP页面都会缺省地创建一个HttpSession。如果你的JSP中不需要使用session的话，那可以通过如下的JSP页面指示符来禁止它：</p>
<p>以下是引用片段：<br />
＜%@ page session="false"%＞ </p>
<p><br />
　　不要在HttpSession中存放大的数据对像：如果你在HttpSession中存放大的数据对像的话，每当对它进行读写时，应用服务器都将对其进行序列化，从而增加了系统的额外负担。你在HttpSession中存放的数据对像越大，那系统的性能就下降得越快。</p>
<p>　　当你不需要HttpSession时，尽快地释放它：当你不再需要session时，你可以通过调用 HttpSession.invalidate()方法来释放它。尽量将session的超时时间设得短一点：在JSP应用服务器中，有一个缺省的 session的超时时间。当客户在这个时间之后没有进行任何操作的话，系统会将相关的session自动从内存中释放。超时时间设得越大，系统的性能就会越低，因此最好的方法就是尽量使得它的值保持在一个较低的水平。</p>
<p>　<span style="font-weight: bold">　方法 4: 将页面输出进行压缩</span></p>
<p>　　压缩是解决数据冗余的一个好的方法，特别是在网络带宽不够发达的今天。有的浏览器支持gzip(GNU zip)进行来对HTML文件进行压缩，这种方法可以戏剧性地减少HTML文件的下载时间。因此，如果你将servlet或JSP页面生成的HTML页面进行压缩的话，那用户就会觉得页面浏览速度会非常快。但不幸的是，不是所有的浏览器都支持gzip压缩，但你可以通过在你的程序中检查客户的浏览器是否支持它。下面就是关于这种方法实现的一个代码片段：</p>
<p>以下是引用片段：<br />
public void doGet(HttpServletRequest request, HttpServletResponse response) <br />
throws IOException, ServletException { <br />
OutputStream out = null; <br />
String encoding = request.getHeader("Accept-Encoding"); 　 <br />
if (encoding != null &amp;&amp; encoding.indexOf("gzip") != -1){ <br />
request.setHeader("Content-Encoding" , "gzip");　　 <br />
out = new GZIPOutputStream(request.getOutputStream()); <br />
}　 <br />
else if (encoding != null &amp;&amp; encoding.indexOf("comdivss") != -1){ <br />
request.setHeader("Content-Encoding" , "comdivss");　　 <br />
out = new ZIPOutputStream(request.getOutputStream()); <br />
}else{　　 <br />
out = request.getOutputStream(); <br />
}　 <br />
...　 <br />
...&nbsp; <br />
} </p>
<p style="font-weight: bold">　　方法 5: 使用线程池</p>
<p>　　应用服务器缺省地为每个不同的客户端请求创建一个线程进行处理，并为它们分派service()方法，当service()方法调用完成后，与之相应的线程也随之撤消。由于创建和撤消线程会耗费一定的系统资源，这种缺省模式降低了系统的性能。但所幸的是我们可以通过创建一个线程池来改变这种状况。</p>
<p>　　另外，我们还要为这个线程池设置一个最小线程数和一个最大线程数。在应用服务器启动时，它会创建数量等于最小线程数的一个线程池，当客户有请求时，相应地从池从取出一个线程来进行处理，当处理完成后，再将线程重新放入到池中。如果池中的线程不够地话，系统会自动地增加池中线程的数量，但总量不能超过最大线程数。通过使用线程池，当客户端请求急剧增加时，系统的负载就会呈现的平滑的上升曲线，从而提高的系统的可伸缩性。</p>
<p>　<span style="font-weight: bold">　方法 6: 选择正确的页面包含机制</span></p>
<p>　　在JSP中有两种方法可以用来包含另一个页面：</p>
<p>　　1、使用include指示符</p>
<p>以下是引用片段：<br />
＜%@ includee file=&#8221;test.jsp&#8221; %＞ </p>
<p><br />
　　2、使用jsp指示符</p>
<p>以下是引用片段：<br />
＜jsp:includee page=&#8221;test.jsp&#8221; flush=&#8221;true&#8221;/＞ </p>
<p><br />
　　在实际中发现，如果使用第一种方法的话，可以使得系统性能更高。</p>
<p style="font-weight: bold">　　方法 7:正确地确定javabean的生命周期</p>
<p>　　JSP的一个强大的地方就是对javabean的支持。通过在JSP页面中使用jsp:useBean标签，可以将javabean直接插入到一个JSP页面中。它的使用方法如下：</p>
<p>以下是引用片段：<br />
＜jsp:useBean id="name" scope="page|request|session|application"&nbsp; <br />
class="package.className" type="typeName"＞ <br />
＜/jsp:useBean＞ </p>
<p><br />
　　其中scope属性指出了这个bean的生命周期。缺省的生命周期为page。如果你没有正确地选择bean的生命周期的话，它将影响系统的性能。</p>
<p>　　举例来说，如果你只想在一次请求中使用某个bean，但你却将这个bean的生命周期设置成了session，那当这次请求结束后，这个 bean将仍然保留在内存中，除非session超时或用户关闭浏览器。这样会耗费一定的内存，并无谓的增加了JVM垃圾收集器的工作量。因此为bean 设置正确的生命周期，并在bean的使命结束后尽快地清理它们，会使用系统性能有一个提高。</p>
<p>　　其它一些有用的方法</p>
<p>　　1、在字符串连接操作中尽量不使用&#8220;+&#8221;操作符：在java编程中，我们常常使用&#8220;+&#8221;操作符来将几个字符串连接起来，但你或许从来没有想到过它居然会对系统性能造成影响吧?由于字符串是常量，因此JVM会产生一些临时的对像。你使用的&#8220;+&#8221;越多，生成的临时对像就越多，这样也会给系统性能带来一些影响。解决的方法是用StringBuffer对像来代替&#8220;+&#8221;操作符。</p>
<p>　　2、避免使用System.out.println()方法：由于System.out.println()是一种同步调用，即在调用它时，磁盘I/O操作必须等待它的完成，因此我们要尽量避免对它的调用。但我们在调试程序时它又是一个必不可少的方便工具，为了解决这个矛盾，我建议你最好使用 Log4j工具(<a href="http://jakarta.apache.org/">http://Jakarta.apache.org</a> )，它既可以方便调试，而不会产生System.out.println()这样的方法。</p>
<p>　　3、ServletOutputStream 与 PrintWriter的权衡：使用PrintWriter可能会带来一些小的开销，因为它将所有的原始输出都转换为字符流来输出，因此如果使用它来作为页面输出的话，系统要负担一个转换过程。而使用ServletOutputStream作为页面输出的话就不存在一个问题，但它是以二进制进行输出的。因此在实际应用中要权衡两者的利弊。</p>
<p>　　总结</p>
<p>　　本文的目的是通过对servlet和JSP的一些调优技术来极大地提高你的应用程序的性能，并因此提升整个J2EE应用的性能。通过这些调优技术，你可以发现其实并不是某种技术平台(比如J2EE和.NET之争)决定了你的应用程序的性能，重要是你要对这种平台有一个较为深入的了解，这样你才能从根本上对自己的应用程序做一个优化。</p>
</strong></font><img src ="http://www.blogjava.net/dongwq/aggbug/282921.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-06-17 21:53 <a href="http://www.blogjava.net/dongwq/archive/2009/06/17/282921.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再见regex</title><link>http://www.blogjava.net/dongwq/archive/2009/06/17/282911.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Wed, 17 Jun 2009 12:44:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/06/17/282911.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/282911.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/06/17/282911.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/282911.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/282911.html</trackback:ping><description><![CDATA[<p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td align="center" height="25"><font style="font-size: 14pt" color="#02368d"><strong>正则表达式规则</strong></font><br />
            </td>
        </tr>
        <tr>
            <td bgcolor="#d2dee2" height="1"><br />
            </td>
        </tr>
        <tr>
            <td bgcolor="#ffffff" height="1"><br />
            </td>
        </tr>
        <tr>
            <td align="center">
            <table style="border-collapse: collapse" cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td width="100%">
                        <div id="art" style="margin: 15px" width="100%">
                        <div class="cnt">
                        <p>String.matches() 这个方法主要是返回是否匹配指定的字符串，如果匹配则为true,否则为false;</p>
                        <p>如：/**<br />
                        &nbsp;&nbsp;&nbsp; * 判断字符创是否是一个有效的日期<br />
                        &nbsp;&nbsp;&nbsp; * <br />
                        &nbsp;&nbsp;&nbsp; * @param theStr<br />
                        &nbsp;&nbsp;&nbsp; * @return true 是，false否<br />
                        &nbsp;&nbsp;&nbsp; */<br />
                        public static boolean isDate(String theStr) {<br />
                        &nbsp;&nbsp;&nbsp; return theStr.matches("<a href="file://%20%20d%7b4%7d%20%20-%20%20d%7b1,2%7d%20%20-%20%20d%7b1,2/">\\d{4}\\-\\d{1,2}\\-\\d{1,2</a>}");<br />
                        }</p>
                        <p>这个方法的参数为正则表达式，关于正则表达式的用法如下：</p>
                        <p>&nbsp;&nbsp;&nbsp; 正则表达式（regular expression）描述了一种字符串匹配的模式，可以用来：（1）检查一个串中是否含有符合某个规则的子串，并且可以得到这个子串；（2）根据匹配规则对字符串进行灵活的替换操作。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正则表达式学习起来其实是很简单的，不多的几个较为抽象的概念也很容易理解。之所以很多人感觉正则表达式比较复杂，一方面是因为大多数的文档没有做到由浅入深地讲解，概念上没有注意先后顺序，给读者的理解带来困难；另一方面，各种引擎自带的文档一般都要介绍它特有的功能，然而这部分特有的功能并不是我们首先要理解的。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文章中的每一个举例，都可以点击进入到测试页面进行测试。闲话少说，开始。&nbsp;&nbsp;</p>
                        <h4>1. 正则表达式规则</h4>
                        <h5><a name="common"></a>1.1 普通字符</h5>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号，都是"普通字符"。表达式中的普通字符，在匹配一个字符串的时候，匹配与之相同的一个字符。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=c&amp;txt=abcde"><font color="#000080">举例1：表达式 "c"，在匹配字符串 "abcde" 时</font></a>，匹配结果是：成功；匹配到的内容是："c"；匹配到的位置是：开始于2，结束于3。（注：下标从0开始还是从1开始，因当前编程语言的不同而可能不同）<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=bcd&amp;txt=abcde"><font color="#000080">举例2：表达式 "bcd"，在匹配字符串 "abcde" 时</font></a>，匹配结果是：成功；匹配到的内容是："bcd"；匹配到的位置是：开始于1，结束于4。</p>
                        <hr color="#fea089" size="1" />
                        <h5><a name="escaped"></a>1.2 简单的转义字符</h5>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一些不便书写的字符，采用在前面加 "\" 的方法。这些字符其实我们都已经熟知了。</p>
                        <p>&nbsp;</p>
                        <table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
                            <tbody>
                                <tr bgcolor="#f0f0f0">
                                    <td width="70">
                                    <p>表达式</p>
                                    </td>
                                    <td>
                                    <p>可匹配</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p>\r, \n</p>
                                    </td>
                                    <td>
                                    <p>代表回车和换行符</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p>\t</p>
                                    </td>
                                    <td>
                                    <p>制表符</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p>\\</p>
                                    </td>
                                    <td>
                                    <p>代表 "\" 本身</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 还有其他一些在后边章节中有特殊用处的标点符号，在前面加 "\" 后，就代表该符号本身。比如：^, $ 都有特殊意义，如果要想匹配字符串中 "^" 和 "$" 字符，则表达式就需要写成 "\^" 和 "\$"。</p>
                        <p>&nbsp;</p>
                        <table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
                            <tbody>
                                <tr bgcolor="#f0f0f0">
                                    <td width="66">
                                    <p>表达式</p>
                                    </td>
                                    <td>
                                    <p>可匹配</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p>\^</p>
                                    </td>
                                    <td>
                                    <p>匹配 ^ 符号本身</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p>\$</p>
                                    </td>
                                    <td>
                                    <p>匹配 $ 符号本身</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p>\.</p>
                                    </td>
                                    <td>
                                    <p>匹配小数点（.）本身</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这些转义字符的匹配方法与 "普通字符" 是类似的。也是匹配与之相同的一个字符。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5C$d&amp;txt=abc$de"><font color="#000080">举例1：表达式 "\$d"，在匹配字符串 "abc$de" 时</font></a>，匹配结果是：成功；匹配到的内容是："$d"；匹配到的位置是：开始于3，结束于5。</p>
                        <hr color="#fea089" size="1" />
                        <h5><a name="multi"></a>1.3 能够与 '多种字符' 匹配的表达式</h5>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正则表达式中的一些表示方法，可以匹配 '多种字符' 其中的任意一个字符。比如，表达式 "\d" 可以匹配任意一个数字。虽然可以匹配其中任意字符，但是只能是一个，不是多个。这就好比玩扑克牌时候，大小王可以代替任意一张牌，但是只能代替一张牌。</p>
                        <p>&nbsp;</p>
                        <table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
                            <tbody>
                                <tr bgcolor="#f0f0f0">
                                    <td width="66">
                                    <p>表达式</p>
                                    </td>
                                    <td>
                                    <p>可匹配</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#900050">\d</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>任意一个数字，0~9 中的任意一个</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#900050">\w</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>任意一个字母或数字或下划线，也就是 A~Z,a~z,0~9,_ 中任意一个</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#900050">\s</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>包括空格、制表符、换页符等空白字符的其中任意一个</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#900050">.</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>小数点可以匹配除了换行符（\n）以外的任意一个字符</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cd%5Cd&amp;txt=abc123"><font color="#000080">举例1：表达式 "</font><span name="pattern"><font color="#000000"><font color="#900050">\d</font><font color="#900050">\d</font></font></span><font color="#000080">"，在匹配 "abc123" 时</font></a>，匹配的结果是：成功；匹配到的内容是："12"；匹配到的位置是：开始于3，结束于5。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=a.%5Cd&amp;txt=aaa100"><font color="#000080">举例2：表达式 "</font><span name="pattern"><font color="#000000">a<font color="#900050">.</font><font color="#900050">\d</font></font></span><font color="#000080">"，在匹配 "aaa100" 时</font></a>，匹配的结果是：成功；匹配到的内容是："aa1"；匹配到的位置是：开始于1，结束于4。</p>
                        <hr color="#fea089" size="1" />
                        <h5><a name="custom"></a>1.4 自定义能够匹配 '多种字符' 的表达式</h5>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用方括号 [ ] 包含一系列字符，能够匹配其中任意一个字符。用 [^ ] 包含一系列字符，则能够匹配其中字符之外的任意一个字符。同样的道理，虽然可以匹配其中任意一个，但是只能是一个，不是多个。</p>
                        <p>&nbsp;</p>
                        <table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
                            <tbody>
                                <tr bgcolor="#f0f0f0">
                                    <td width="80">
                                    <p>表达式</p>
                                    </td>
                                    <td>
                                    <p>可匹配</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#900050">[ab5@]</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>匹配 "a" 或 "b" 或 "5" 或 "@"</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#900050">[^abc]</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>匹配 "a","b","c" 之外的任意一个字符</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#900050">[f-k]</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>匹配 "f"~"k" 之间的任意一个字母</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#900050">[^A-F0-3]</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>匹配 "A"~"F","0"~"3" 之外的任意一个字符</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Bbcd%5D%5Bbcd%5D&amp;txt=abc123"><font color="#000080">举例1：表达式 "</font><span name="pattern"><font color="#000000"><font color="#900050">[bcd]</font><font color="#900050">[bcd]</font></font></span><font color="#000080">" 匹配 "abc123" 时</font></a>，匹配的结果是：成功；匹配到的内容是："bc"；匹配到的位置是：开始于1，结束于3。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5B%5Eabc%5D&amp;txt=abc123"><font color="#000080">举例2：表达式 "</font><span name="pattern"><font color="#000000"><font color="#900050">[^abc]</font></font></span><font color="#000080">" 匹配 "abc123" 时</font></a>，匹配的结果是：成功；匹配到的内容是："1"；匹配到的位置是：开始于3，结束于4。</p>
                        <hr color="#fea089" size="1" />
                        <h5><a name="times"></a>1.5 修饰匹配次数的特殊符号</h5>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前面章节中讲到的表达式，无论是只能匹配一种字符的表达式，还是可以匹配多种字符其中任意一个的表达式，都只能匹配一次。如果使用表达式再加上修饰匹配次数的特殊符号，那么不用重复书写表达式就可以重复匹配。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用方法是："次数修饰"放在"被修饰的表达式"后边。比如："[bcd][bcd]" 可以写成 "[bcd]{2}"。</p>
                        <p>&nbsp;</p>
                        <table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
                            <tbody>
                                <tr bgcolor="#f0f0f0">
                                    <td width="67">
                                    <p>表达式</p>
                                    </td>
                                    <td>
                                    <p>作用</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#e07000">{n}</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>表达式重复n次，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=%20w%7B2%7D&amp;txt=ab+c6"><font color="#000080">"\w{2}" 相当于 "\w\w"</font></a>；<a href="http://www.regexlab.com/zh/workshop.asp?pat=a%7B5%7D&amp;txt=bbaaaaaddee"><font color="#000080">"a{5}" 相当于 "aaaaa"</font></a></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#e07000">{m,n}</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>表达式至少重复m次，最多重复n次，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=ba%7B1,3%7D&amp;txt=a,baaa,baa,b,ba"><font color="#000080">"ba{1,3}"可以匹配 "ba"或"baa"或"baaa"</font></a></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#e07000">{m,}</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>表达式至少重复m次，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=%20w%20d%7B2,%7D&amp;txt=b1,a12,_456,_4AA,M12344,12346546547446534543543"><font color="#000080">"\w\d{2,}"可以匹配 "a12","_456","M12344"...</font></a></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#e07000">?</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>匹配表达式0次或者1次，相当于 {0,1}，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=a%5Bcd%5D%3F&amp;txt=a,c,d,ac,ad"><font color="#000080">"a[cd]?"可以匹配 "a","ac","ad"</font></a></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#e07000">+</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>表达式至少出现1次，相当于 {1,}，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=a%2Bb&amp;txt=a%2Cb%2Cab%2Caab%2Caaab"><font color="#000080">"a+b"可以匹配 "ab","aab","aaab"...</font></a></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#e07000">*</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>表达式不出现或出现任意次，相当于 {0,}，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5C%5E*b&amp;txt=%5E%2Cb%2C%5E%5E%5Eb%2C%5E%5E%5E%5E%5E%5E%5Eb"><font color="#000080">"\^*b"可以匹配 "b","^^^b"...</font></a></p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cd%2B%5C.%3F%5Cd*&amp;txt=It%20costs%20%2412.5"><font color="#000080">举例1：表达式 "</font><span name="pattern"><font color="#000000"><font color="#900050">\d</font><font color="#e07000">+</font>\.<font color="#e07000">?</font><font color="#900050">\d</font><font color="#e07000">*</font></font></span><font color="#000080">" 在匹配 "It costs $12.5" 时</font></a>，匹配的结果是：成功；匹配到的内容是："12.5"；匹配到的位置是：开始于10，结束于14。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=go%7B2,8%7Dgle&amp;txt=Ads%20by%20goooooogle%2C%20or%20gooogle"><font color="#000080">举例2：表达式 "</font><span name="pattern"><font color="#000000">go<font color="#e07000">{2,8}</font>gle</font></span><font color="#000080">" 在匹配 "Ads by goooooogle" 时</font></a>，匹配的结果是：成功；匹配到的内容是："goooooogle"；匹配到的位置是：开始于7，结束于17。</p>
                        <hr color="#fea089" size="1" />
                        <h5><a name="special"></a>1.6 其他一些代表抽象意义的特殊符号</h5>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一些符号在表达式中代表抽象的特殊意义：</p>
                        <p>&nbsp;</p>
                        <table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
                            <tbody>
                                <tr bgcolor="#f0f0f0">
                                    <td width="67">
                                    <p>表达式</p>
                                    </td>
                                    <td>
                                    <p>作用</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#ff00ff">^</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>与字符串开始的地方匹配，不匹配任何字符</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#ff00ff">$</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>与字符串结束的地方匹配，不匹配任何字符</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><span name="pattern"><font color="#000000"><font color="#ff00ff">\b</font></font></span></p>
                                    </td>
                                    <td>
                                    <p>匹配一个单词边界，也就是单词和空格之间的位置，不匹配任何字符</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 进一步的文字说明仍然比较抽象，因此，举例帮助大家理解。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Eaaa&amp;txt=xxx+aaa+xxx"><font color="#000080">举例1：表达式 "</font><span name="pattern"><font color="#000000"><font color="#ff00ff">^</font>aaa</font></span><font color="#000080">" 在匹配 "xxx aaa xxx" 时</font></a>，匹配结果是：失败。因为 "^" 要求与字符串开始的地方匹配，因此，只有当 "aaa" 位于字符串的开头的时候，"^aaa" 才能匹配，<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Eaaa&amp;txt=aaa+xxx+xxx"><font color="#000080">比如："aaa xxx xxx"</font></a>。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=aaa$&amp;txt=xxx+aaa+xxx"><font color="#000080">举例2：表达式 "</font><span name="pattern"><font color="#000000">aaa<font color="#ff00ff">$</font></font></span><font color="#000080">" 在匹配 "xxx aaa xxx" 时</font></a>，匹配结果是：失败。因为 "$" 要求与字符串结束的地方匹配，因此，只有当 "aaa" 位于字符串的结尾的时候，"aaa$" 才能匹配，<a href="http://www.regexlab.com/zh/workshop.asp?pat=aaa$&amp;txt=xxx+xxx+aaa"><font color="#000080">比如："xxx xxx aaa"</font></a>。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=.%5Cb.&amp;txt=@@@abc"><font color="#000080">举例3：表达式 "</font><span name="pattern"><font color="#000000"><font color="#900050">.</font><font color="#ff00ff">\b</font><font color="#900050">.</font></font></span><font color="#000080">" 在匹配 "@@@abc" 时</font></a>，匹配结果是：成功；匹配到的内容是："@a"；匹配到的位置是：开始于2，结束于4。<br />
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 进一步说明："\b" 与 "^" 和 "$" 类似，本身不匹配任何字符，但是它要求它在匹配结果中所处位置的左右两边，其中一边是 "\w" 范围，另一边是 非"\w" 的范围。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cbend%5Cb&amp;txt=weekend,endfor,end"><font color="#000080">举例4：表达式 "</font><span name="pattern"><font color="#000000"><font color="#ff00ff">\b</font>end<font color="#ff00ff">\b</font></font></span><font color="#000080">" 在匹配 "weekend,endfor,end" 时</font></a>，匹配结果是：成功；匹配到的内容是："end"；匹配到的位置是：开始于15，结束于18。</p>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一些符号可以影响表达式内部的子表达式之间的关系：</p>
                        <p>&nbsp;</p>
                        <table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
                            <tbody>
                                <tr bgcolor="#f0f0f0">
                                    <td width="65">
                                    <p>表达式</p>
                                    </td>
                                    <td>
                                    <p>作用</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p>|</p>
                                    </td>
                                    <td>
                                    <p>左右两边表达式之间 "或" 关系，匹配左边或者右边</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p>( )</p>
                                    </td>
                                    <td>
                                    <p>(1). 在被修饰匹配次数的时候，括号中的表达式可以作为整体被修饰<br />
                                    (2). 取匹配结果的时候，括号中的表达式匹配到的内容可以被单独得到</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=Tom%7CJack&amp;txt=I%27m+Tom%2C+he+is+Jack"><font color="#000080">举例5：表达式 "</font><span name="pattern"><font color="#000000">Tom<font color="#5050ff">|</font>Jack</font></span><font color="#000080">" 在匹配字符串 "I'm Tom, he is Jack" 时</font></a>，匹配结果是：成功；匹配到的内容是："Tom"；匹配到的位置是：开始于4，结束于7。匹配下一个时，匹配结果是：成功；匹配到的内容是："Jack"；匹配到的位置时：开始于15，结束于19。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%28go%5Cs*%29%2B&amp;txt=Let%27s%20go%20go%20go%21"><font color="#000080">举例6：表达式 "</font><span name="pattern"><font color="#000000"><font color="#5050ff">(</font>go<font color="#900050">\s</font><font color="#e07000">*</font><font color="#5050ff">)</font><font color="#e07000">+</font></font></span><font color="#000080">" 在匹配 "Let's go go go!" 时</font></a>，匹配结果是：成功；匹配到内容是："go go go"；匹配到的位置是：开始于6，结束于14。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%uFFE5%28%5Cd%2B%5C.%3F%5Cd*%29&amp;txt=%uFF0410.9%2C%uFFE520.5"><font color="#000080">举例7：表达式 "</font><span name="pattern"><font color="#000000">￥<font color="#5050ff">(</font><font color="#900050">\d</font><font color="#e07000">+</font>\.<font color="#e07000">?</font><font color="#900050">\d</font><font color="#e07000">*</font><font color="#5050ff">)</font></font></span><font color="#000080">" 在匹配 "＄10.9,￥20.5" 时</font></a>，匹配的结果是：成功；匹配到的内容是："￥20.5"；匹配到的位置是：开始于6，结束于10。单独获取括号范围匹配到的内容是："20.5"。</p>
                        <hr color="#fea089" size="1" />
                        <h4>2. 正则表达式中的一些高级规则</h4>
                        <h5><a name="reluctant"></a>2.1 匹配次数中的贪婪与非贪婪</h5>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在使用修饰匹配次数的特殊符号时，有几种表示方法可以使同一个表达式能够匹配不同的次数，比如："{m,n}", "{m,}", "?", "*", "+"，具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中，总是尽可能多的匹配。比如，针对文本 "dxxxdxxxd"，举例如下：</p>
                        <p>&nbsp;</p>
                        <table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
                            <tbody>
                                <tr bgcolor="#f0f0f0">
                                    <td width="93">
                                    <p>表达式</p>
                                    </td>
                                    <td>
                                    <p>匹配结果</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><a href="http://www.regexlab.com/zh/workshop.asp?pat=%28d%29%28%5Cw%2B%29&amp;txt=dxxxdxxxd"><span name="pattern"><font color="#000000"><font color="#5050ff">(</font>d<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#5050ff">)</font></font></span></a></p>
                                    </td>
                                    <td>
                                    <p>"\w+" 将匹配第一个 "d" 之后的所有字符 "xxxdxxxd"</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><a href="http://www.regexlab.com/zh/workshop.asp?pat=%28d%29%28%5Cw%2B%29%28d%29&amp;txt=dxxxdxxxd"><span name="pattern"><font color="#000000"><font color="#5050ff">(</font>d<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#5050ff">)</font><font color="#5050ff">(</font>d<font color="#5050ff">)</font></font></span></a></p>
                                    </td>
                                    <td>
                                    <p>"\w+" 将匹配第一个 "d" 和最后一个 "d" 之间的所有字符 "xxxdxxx"。虽然 "\w+" 也能够匹配上最后一个 "d"，但是为了使整个表达式匹配成功，"\w+" 可以 "让出" 它本来能够匹配的最后一个 "d"</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由此可见，"\w+" 在匹配的时候，总是尽可能多的匹配符合它规则的字符。虽然第二个举例中，它没有匹配最后一个 "d"，但那也是为了让整个表达式能够匹配成功。同理，带 "*" 和 "{m,n}" 的表达式都是尽可能地多匹配，带 "?" 的表达式在可匹配可不匹配的时候，也是尽可能的 "要匹配"。这 种匹配原则就叫作 "贪婪" 模式 。</p>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 非贪婪模式：<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在修饰匹配次数的特殊符号后再加上一个 "?" 号，则可以使匹配次数不定的表达式尽可能少的匹配，使可匹配可不匹配的表达式，尽可能的 "不匹配"。这种匹配原则叫作 "非贪婪" 模式，也叫作 "勉强" 模式。如果少匹配就会导致整个表达式匹配失败的时候，与贪婪模式类似，非贪婪模式会最小限度的再匹配一些，以使整个表达式匹配成功。举例如下，针对文本 "dxxxdxxxd" 举例：</p>
                        <p>&nbsp;</p>
                        <table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
                            <tbody>
                                <tr bgcolor="#f0f0f0">
                                    <td width="93">
                                    <p>表达式</p>
                                    </td>
                                    <td>
                                    <p>匹配结果</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><a href="http://www.regexlab.com/zh/workshop.asp?pat=%28d%29%28%5Cw%2B%3F%29&amp;txt=dxxxdxxxd"><span name="pattern"><font color="#000000"><font color="#5050ff">(</font>d<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#e07000">?</font><font color="#5050ff">)</font></font></span></a></p>
                                    </td>
                                    <td>
                                    <p>"\w+?" 将尽可能少的匹配第一个 "d" 之后的字符，结果是："\w+?" 只匹配了一个 "x"</p>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    <p><a href="http://www.regexlab.com/zh/workshop.asp?pat=%28d%29%28%5Cw%2B%3F%29%28d%29&amp;txt=dxxxdxxxd"><span name="pattern"><font color="#000000"><font color="#5050ff">(</font>d<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#e07000">?</font><font color="#5050ff">)</font><font color="#5050ff">(</font>d<font color="#5050ff">)</font></font></span></a></p>
                                    </td>
                                    <td>
                                    <p>为了让整个表达式匹配成功，"\w+?" 不得不匹配 "xxx" 才可以让后边的 "d" 匹配，从而使整个表达式匹配成功。因此，结果是："\w+?" 匹配 "xxx"</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 更多的情况，举例如下：<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%3Ctd%3E%28%2E%2A%29%3C%2Ftd%3E&amp;txt=%3Ctd%3E%3Cp%3Eaa%3C%2Fp%3E%3C%2Ftd%3E%3Ctd%3E%3Cp%3Ebb%3C%2Fp%3E%3C%2Ftd%3E"><font color="#000080">举例1：表达式 "</font><span name="pattern"><font color="#000000">&lt;td&gt;<font color="#5050ff">(</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#5050ff">)</font>&lt;/td&gt;</font></span><font color="#000080">" 与字符串 "&lt;td&gt;&lt;p&gt;aa&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;bb&lt;/p&gt;&lt;/td&gt;" 匹配时</font></a>，匹配的结果是：成功；匹配到的内容是 "&lt;td&gt;&lt;p&gt;aa&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;bb&lt;/p&gt;&lt;/td&gt;" 整个字符串， 表达式中的 "&lt;/td&gt;" 将与字符串中最后一个 "&lt;/td&gt;" 匹配。 <br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%3Ctd%3E%28%2E%2A%3F%29%3C%2Ftd%3E&amp;txt=%3Ctd%3E%3Cp%3Eaa%3C%2Fp%3E%3C%2Ftd%3E%3Ctd%3E%3Cp%3Ebb%3C%2Fp%3E%3C%2Ftd%3E"><font color="#000080">举例2：相比之下，表达式 "</font><span name="pattern"><font color="#000000">&lt;td&gt;<font color="#5050ff">(</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font><font color="#5050ff">)</font>&lt;/td&gt;</font></span><font color="#000080">" 匹配举例1中同样的字符串时</font></a>，将只得到 "&lt;td&gt;&lt;p&gt;aa&lt;/p&gt;&lt;/td&gt;"， 再次匹配下一个时，可以得到第二个 "&lt;td&gt;&lt;p&gt;bb&lt;/p&gt;&lt;/td&gt;"。</p>
                        <hr color="#fea089" size="1" />
                        <h5><a name="backref"></a>2.2 反向引用 \1, \2...</h5>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 表达式在匹配时，表达式引擎会将小括号 "( )" 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候，小括号包含的表达式所匹配到的字符串可以单独获取。这一点，在前面的举例中，已经多次展示了。在实际应用场合中，当用某种边界来查找，而所要获取的内容又不包含边界时，必须使用小括号来指定所要的范围。比如前面的 "<span name="pattern"><font color="#000000">&lt;td&gt;<font color="#5050ff">(</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font><font color="#5050ff">)</font>&lt;/td&gt;</font></span>"。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实，"小括号包含的表达式所匹配到的字符串" 不仅是在匹配结束后才可以使用，在匹配过程中也可以使用。表达式后边的部分，可以引用前面 "括号内的子匹配已经匹配到的字符串"。引用方法是 "\" 加上一个数字。"\1" 引用第1对括号内匹配到的字符串，"\2" 引用第2对括号内匹配到的字符串&#8230;&#8230;以此类推，如果一对括号内包含另一对括号，则外层的括号先排序号。换句话说，哪一对的左括号 "(" 在前，那这一对就先排序号。</p>
                        <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 举例如下：<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%28%27%7C%22%29%28%2E%2A%3F%29%28%5C1%29&amp;txt=%27Hello%27%2C+%22World%22"><font color="#000080">举例1：表达式 "</font><span name="pattern"><font color="#000000"><font color="#5050ff">(</font>'<font color="#5050ff">|</font>"<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font><font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#ff00ff">\1</font><font color="#5050ff">)</font></font></span><font color="#000080">" 在匹配 " 'Hello', "World" " 时</font></a>，匹配结果是：成功；匹配到的内容是：" 'Hello' "。再次匹配下一个时，可以匹配到 " "World" "。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%28%5Cw%29%5C1%7B4%2C%7D&amp;txt=aa%20bbbb%20abcdefg%20ccccc%20111121111%20999999999"><font color="#000080">举例2：表达式 "</font><span name="pattern"><font color="#000000"><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#5050ff">)</font><font color="#ff00ff">\1</font><font color="#e07000">{4,}</font></font></span><font color="#000080">" 在匹配 "aa bbbb abcdefg ccccc 111121111 999999999" 时</font></a>，匹配结果是：成功；匹配到的内容是 "ccccc"。再次匹配下一个时，将得到 999999999。这个表达式要求 "\w" 范围的字符至少重复5次，<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cw%7B5%2C%7D&amp;txt=aa%20bbbb%20abcdefg%20ccccc%20111121111%20999999999"><font color="#000080">注意与 "\w{5,}" 之间的区别</font></a>。<br />
                        <br />
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.regexlab.com/zh/workshop.asp?pat=%3C%28%5Cw%2B%29%5Cs%2A%28%5Cw%2B%28%3D%28%27%7C%22%29%2E%2A%3F%5C4%29%3F%5Cs%2A%29%2A%3E%2E%2A%3F%3C%2F%5C1%3E&amp;txt=%3Ctd+id%3D%27td1%27+style%3D%22bgcolor%3Awhite%22%3E%3C%2Ftd%3E%0D%0A%3Cbody+onload%3D%22doit%28%29%22%3E%3C%2Fbody%3E"><font color="#000080">举例3：表达式 "</font><span name="pattern"><font color="#000000">&lt;<font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#5050ff">)</font><font color="#900050">\s</font><font color="#e07000">*</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#5050ff">(</font>=<font color="#5050ff">(</font>'<font color="#5050ff">|</font>"<font color="#5050ff">)</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font><font color="#ff00ff">\4</font><font color="#5050ff">)</font><font color="#e07000">?</font><font color="#900050">\s</font><font color="#e07000">*</font><font color="#5050ff">)</font><font color="#e07000">*</font>&gt;<font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font>&lt;/<font color="#ff00ff">\1</font>&gt;</font></span><font color="#000080">" 在匹配 "&lt;td id='td1' style="bgcolor:white"&gt;&lt;/td&gt;" 时</font></a>，匹配结果是成功。如果 "&lt;td&gt;" 与 "&lt;/td&gt;" 不配对，则会匹配失败；如果改成其他配对，也可以匹配成功。</p>
                        </div>
                        </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td align="center" height="25"><font style="font-size: 14pt" color="#02368d"><strong>在java语言中使用正则表达式</strong></font><br />
            </td>
        </tr>
        <tr>
            <td bgcolor="#d2dee2" height="1"><br />
            </td>
        </tr>
        <tr>
            <td bgcolor="#ffffff" height="1"></td>
        </tr>
        <tr>
            <td align="center">
            <table style="border-collapse: collapse" cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td width="100%">
                        <div id="art" style="margin: 15px" width="100%">
                        <div>&nbsp; 首先让我们构成一个正则表达式。为简单起见，先构成一个正则表达式来识别下面格式的电话号码数字：(nnn)nnn-nnnn。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 第一步，创建一个pattern对象来匹配上面的子字符串。一旦程序运行后，如果需要的话，可以让这个对象一般化。匹配上面格式的正则表达可以这样构成： (\d{3})\s\d{3}-\d{4}，其中\d单字符类型用来匹配从0到9的任何数字，另外{3}重复符号，是个简便的记号，用来表示有3个连续的数字位，也等效于(\d\d\d)。\s也另外一个比较有用的单字符类型，用来匹配空格，比如Space键，tab键和换行符。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 是不是很简单？但是，如果把这个正则表达式的模式用在java程序中，还要做两件事。对java的解释器来说，在反斜线字符(\)前的字符有特殊的含义。在java中，与regex有关的包，并不都能理解和识别反斜线字符(\)，尽管可以试试看。但为避免这一点，即为了让反斜线字符(\)在模式对象中被完全地传递，应该用双反斜线字符(\)。此外圆括号在正则表达中两层含义，如果想让它解释为字面上意思（即圆括号），也需要在它前面用双反斜线字符(\)。也就是像下面的一样： &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; \\(\\d{3}\\)\\s\\d{3}-\\d{4} &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 现在介绍怎样在java代码中实现刚才所讲的正则表达式。要记住的事，在用正则表达式的包时，在你所定义的类前需要包含该包，也就是这样的一行： &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; import &nbsp; java.util.regex.*; &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 下面的一段代码实现的功能是，从一个文本文件逐行读入，并逐行搜索电话号码数字，一旦找到所匹配的，然后输出在控制台。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; BufferedReader &nbsp; in; &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; Pattern &nbsp; pattern &nbsp; = &nbsp; Pattern.compile("\\(\\d{3}\\)\\s\\d{3}-\\d{4}"); &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; in &nbsp; = &nbsp; new &nbsp; BufferedReader(new &nbsp; FileReader("phone")); &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; String &nbsp; s; &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; while &nbsp; ((s &nbsp; = &nbsp; in.readLine()) &nbsp; != &nbsp; null) &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; { &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; Matcher &nbsp; matcher &nbsp; = &nbsp; pattern.matcher(s); &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; if &nbsp; (matcher.find()) &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; { &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; System.out.println(matcher.group()); &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; } &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; } &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; in.close(); &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 对那些熟悉用Python或Javascript来实现正则表达式的人来说，这段代码很平常。在Python和Javascript这些语言中，或者其他的语言，这些正则表达式一旦明确地编译过后，你想用到哪里都可以。与Perl的单步匹配相比，看起来多多做了些工作，但这并不很费事。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; find()方法，就像你所想象的，用来搜索与正则表达式相匹配的任何目标字符串，group()方法，用来返回包含了所匹配文本的字符串。应注意的是，上面的代码，仅用在每行只能含有一个匹配的电话号码数字字符串时。可以肯定的说，java的正则表达式包能用在一行含有多个匹配目标时的搜索。本文的原意在于举一些简单的例子来激起读者进一步去学习java自带的正则表达式包，所以对此就没有进行深入的探讨。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 这相当漂亮吧! &nbsp; 但是很遗憾的是，这仅是个电话号码匹配器。很明显，还有两点可以改进。如果在电话号码的开头，即区位号和本地号码之间可能会有空格。我们也可匹配这些情况，则通过在正则表达式中加入\s?来实现，其中?元字符表示在模式可能有0或1个空格符。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 第二点是，在本地号码位的前三位和后四位数字间有可能是空格符，而不是连字号，更有胜者，或根本就没有分隔符，就是7位数字连在一起。对这几种情况，我们可以用(-|)?来解决。这个结构的正则表达式就是转换器，它能匹配上面所说的几种情况。在()能含有管道符|时，它能匹配是否含有空格符或连字符，而尾部的?元字符表示是否根本没有分隔符的情况。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 最后，区位号也可能没有包含在圆括号内，对此可以简单地在圆括号后附上?元字符，但这不是一个很好的解决方法。因为它也包含了不配对的圆括号，比如" (555" &nbsp; 或 &nbsp; "555)"。相反，我们可以通过另一种转换器来强迫让电话号码是否带有有圆括号：(\(\d{3}\)|\d{3})。如果我们把上面代码中的正则表达式用这些改进后的来替换的话，上面的代码就成了一个非常有用的电话号码数字匹配器： &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; Pattern &nbsp; pattern &nbsp; = &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; Pattern.compile("(\\(\\d{3}\\)|\\d{3})\\s?\\d{3}(-|)?\\d{4}"); &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 可以确定的是，你可以自己试着进一步改进上面的代码。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 现在看看第二个例子，它是从Friedl的中改编过来的。其功能是用来检查文本文件中是否有重复的单词，这在印刷排版中会经常遇到，同样也是个语法检查器的问题。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 匹配单词，像其他的一样，也可以通过好几种的正则表达式来完成。可能最直接的是\b\w+\b，其优点在于只需用少量的regex元字符。其中\w元字符用来匹配从字母a到u的任何字符。+元字符表示匹配匹配一次或多次字符，\b元字符是用来说明匹配单词的边界，它可以是空格或任何一种不同的标点符号（包括逗号，句号等）。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 现在，我们怎样来检查一个给定的单词是否被重复了三次？为完成这个任务，需充分利用正则表达式中的所熟知的向后扫描。如前面提到的，圆括号在正则表达式中有几种不同的用法，一个就是能提供组合类型，组合类型用来保存所匹配的结果或部分匹配的结果（以便后面能用到），即使遇到有相同的模式。在同样的正则表达中，可能（也通常期望）不止有一个组合类型。在第n个组合类型中匹配结果可以通过向后扫描来获取到。向后扫描使得搜索重复的单词非常简单：\b(\w+) \s+\1\b。 &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 圆括号形成了一个组合类型，在这个正则表示中它是第一组合类型（也是仅有的一个）。向后扫描\1，指的是任何被\w+所匹配的单词。我们的正则表达式因此能匹配这样的单词，它有一个或多个空格符，后面还跟有一个与此相同的单词。注意的是，尾部的定位类型(\b)必不可少，它可以防止发生错误。如果我们想匹配"Paris &nbsp; in &nbsp; the &nbsp; the &nbsp; spring"，而不是匹配"Java's &nbsp; regex &nbsp; package &nbsp; is &nbsp; the &nbsp; theme &nbsp; of &nbsp; this &nbsp; article"。根据java现在的格式，则上面的正则表达式就是：Pattern &nbsp; pattern &nbsp; =Pattern.compile("\\b(\\w+)\\s+\\1\\b"); &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 最后进一步的修改是让我们的匹配器对大小写敏感。比如，下面的情况："The &nbsp; the &nbsp; theme &nbsp; of &nbsp; this &nbsp; article &nbsp; is &nbsp; the &nbsp; Java's &nbsp; regex &nbsp; package."，这一点在regex中能非常简单地实现，即通过使用在Pattern类中预定义的静态标志CASE_INSENSITIVE &nbsp; ： &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; Pattern &nbsp; pattern &nbsp; =Pattern.compile("\\b(\\w+)\\s+\\1\\b", &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; Pattern.CASE_INSENSITIVE); &nbsp; <br />
                        &nbsp; &nbsp; <br />
                        &nbsp; 有关正则表达式的话题是非常丰富，而且复杂的，用Java来实现也非常广泛，则需要对regex包进行的彻底研究，我们在这里所讲的只是冰山一角。即使你对正则表达式比较陌生，使用regex包后会很快发现它强大功能和可伸缩性。如果你是个来自Perl或其他语言王国的老练的正则表达式的黑客，使用过 regex包后，你将会安心地投入到java的世界，而放弃其他的工具，并把java的regex包看成是手边必备的利器。</div>
                        </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table><img src ="http://www.blogjava.net/dongwq/aggbug/282911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-06-17 20:44 <a href="http://www.blogjava.net/dongwq/archive/2009/06/17/282911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jndi全局注册表和enc的基本概念  zz</title><link>http://www.blogjava.net/dongwq/archive/2009/03/24/261647.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Tue, 24 Mar 2009 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/03/24/261647.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/261647.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/03/24/261647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/261647.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/261647.html</trackback:ping><description><![CDATA[<table style="border-collapse: collapse" cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
    <tbody>
        <tr>
            <td align="center" bgcolor="#bbf0ff"><font style="font-size: 14pt" color="#000066"><strong>jndi全局注册表和enc的基本概念</strong></font> </td>
            <tr>
                <td>
                <table style="border-collapse: collapse" bordercolor="#bbf0ff" cellspacing="1" cellpadding="0" width="100%" border="1">
                    <tbody>
                        <tr>
                            <td align="center">
                            <table style="border-collapse: collapse; word-wrap: break-word" cellspacing="0" cellpadding="0" width="650" border="0">
                                <tbody>
                                    <tr>
                                        <td align="center">
                                        <table style="border-collapse: collapse; word-wrap: break-word" cellspacing="0" cellpadding="0" width="100%" border="0">
                                            <tbody>
                                                <tr>
                                                    <td width="650">
                                                    <div id="art" style="margin: 15px">&nbsp;&nbsp; 通俗的将jndi就是对ejb容器中所有的资源和组件进行管理的花名册，通过该服务，可以很方便的找到希望使用的资源。当组件被部署到服务器上后，该组件就会被自动注册到花名册上，以便用户使用，如果组件被卸载，花名册上的记录就会自动消失。<br />
                                                    &nbsp;&nbsp;&nbsp; jndi中注册的所有的资源和组件可以被服务器内外的各种程序请求或者访问，是一种全局性的资源！但是ejb中不同的组件通过全局性的jndi服务器形成依赖关系，则会给系统造成不稳定的因素！因此就引入了enc（ejb组件的企业名称上下文）的概念！通过她来实现不同组件之间的引用关系！！！！<br />
                                                    在上一篇文章中写到了通过标注的方式实现方向依赖注入！还以上篇为例：<br />
                                                    有接口：HelloWordRemote&nbsp; HelloWordLocal ICal(Remote)<br />
                                                    而HelloWordBean实现了分别实现了他们<br />
                                                    另外又有了个远程接口：<br />
                                                    @Remote<br />
                                                    public Interface MyService{<br />
                                                    public String helloWord();<br />
                                                    public int add(int a,int b);<br />
                                                    }<br />
                                                    一个类想实现这个接口并且在这个类中引用了...如下：<br />
                                                    @Stateless<br />
                                                    public class FacedServcie implements MyService{<br />
                                                    private HelloWordLocal myserv1;<br />
                                                    private ICal ical;<br />
                                                    .....<br />
                                                    ....<br />
                                                    }<br />
                                                    可以通过配置文件实现反向依赖注入：<br />
                                                    &lt;ejb-jar<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns="http://java.sun.com/xml/ns/javaee"<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xsi:schemaLocation="http://java.sun.com/xml/ns/javaee<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; version="3.0"&gt;<br />
                                                    &nbsp;&nbsp; &lt;enterprise-beans&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;session&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;FacedServcie&lt;/ejb-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-ref&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-ref-name&gt;abc1&lt;/ejb-ref-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-ref-type&gt;Session&lt;/ejb-ref-type&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;remote&gt;com.ICal&lt;/remote&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;mapped-name&gt;HelloWordBean1/remote&lt;/mapped-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;injection-target&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;injection-target-class&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xiaoxiao.FacedService<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/injection-target-class&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;injection-target-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ical<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/injection-target-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/injection-target&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/ejb-ref&gt; <br />
                                                    .........(对于另一个组件的配置)<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/session&gt;<br />
                                                    &nbsp;&nbsp; &lt;/enterprise-beans&gt;<br />
                                                    &lt;/ejb-jar&gt;<br />
                                                    <span style="color: rgb(255,1,2)">还可以通过检索的方式来实现：<br />
                                                    @Stateless</span><br style="color: rgb(255,1,2)" />
                                                    <span style="color: rgb(255,1,2)">public class FacedServcie implements MyService{</span><br style="color: rgb(255,1,2)" />
                                                    <span style="color: rgb(255,1,2)">private HelloWordLocal myserv1;</span><br style="color: rgb(255,1,2)" />
                                                    <span style="color: rgb(255,1,2)">private ICal ical;</span><br style="color: rgb(255,1,2)" />
                                                    <span style="color: rgb(255,1,2)">public String helloWord(){<br />
                                                    try{<br />
                                                    InitialContext ctx=new InitalContext();<br />
                                                    ical=(ICal)ctx.lookup("java:comp/env/abc1");<br />
                                                    //其中java:comp/env是组件局部enc所有记录的根路径而abc1是在配置文件中注册的名字！<br />
                                                    }catch(NamingException e){}<br />
                                                    if(ical!=null){<br />
                                                    return ical.helloWord();<br />
                                                    }else{<br />
                                                    return "error!";<br />
                                                    }<br />
                                                    }<br />
                                                    ....<br style="color: rgb(255,1,2)" />
                                                    </span><span style="color: rgb(255,1,2)">}</span><br />
                                                    配置文件如下：<br />
                                                    &lt;ejb-jar<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns="http://java.sun.com/xml/ns/javaee"<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xsi:schemaLocation="http://java.sun.com/xml/ns/javaee<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; version="3.0"&gt;<br />
                                                    &nbsp;&nbsp; &lt;enterprise-beans&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;session&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;FacedServcie&lt;/ejb-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-ref&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-ref-name&gt;abc1&lt;/ejb-ref-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-ref-type&gt;Session&lt;/ejb-ref-type&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;remote&gt;com.ICal&lt;/remote&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;mapped-name&gt;HelloWordBean1/remote&lt;/mapped-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/ejb-ref&gt; <br />
                                                    .........(对于另一个组件的配置)<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/session&gt;<br />
                                                    &nbsp;&nbsp; &lt;/enterprise-beans&gt;<br />
                                                    &lt;/ejb-jar&gt;<br />
                                                    本人建议使用第一种反向依赖注入的方式！<br />
                                                    还有其他的一些注入：如持久化单元注入，资源型注入 数据源类型的注入。。。<br />
                                                    </div>
                                                    </td>
                                                </tr>
                                            </tbody>
                                        </table>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                            </td>
                        </tr>
                    </tbody>
                </table>
                </td>
            </tr>
        </tbody>
    </table><img src ="http://www.blogjava.net/dongwq/aggbug/261647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-03-24 10:26 <a href="http://www.blogjava.net/dongwq/archive/2009/03/24/261647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB事务ZZ</title><link>http://www.blogjava.net/dongwq/archive/2009/03/24/261646.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Tue, 24 Mar 2009 02:25:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/03/24/261646.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/261646.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/03/24/261646.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/261646.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/261646.html</trackback:ping><description><![CDATA[<table style="border-collapse: collapse" cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
    <tbody>
        <tr>
            <td align="center" bgcolor="#bbf0ff"><font style="font-size: 14pt" color="#000066"><strong>EJB事务</strong></font> </td>
            <tr>
                <td>
                <table style="border-collapse: collapse" bordercolor="#bbf0ff" cellspacing="1" cellpadding="0" width="100%" border="1">
                    <tbody>
                        <tr>
                            <td align="center">
                            <table style="border-collapse: collapse; word-wrap: break-word" cellspacing="0" cellpadding="0" width="650" border="0">
                                <tbody>
                                    <tr>
                                        <td align="center">
                                        <table style="border-collapse: collapse; word-wrap: break-word" cellspacing="0" cellpadding="0" width="100%" border="0">
                                            <tbody>
                                                <tr>
                                                    <td width="650">
                                                    <div id="art" style="margin: 15px">在ejb组件设计中,组件行为有时需要具备事务特征,即使用事务保证组件行为的完整性,使组件要么执行成功,要么回到起点.等价没有执行!<br />
                                                    讨论事务时要明确两个概念:<br />
                                                    事务范围<br />
                                                    算法的可恢复性与事务性:如果事务中的算法动作结果受事务提交或者回滚影响,则该算法具有事务可恢复性,否则就不具备事务可恢复性.<br />
                                                    事务在本质上就是一个管理系列算法动作一致性的对象!ejb提供了两种事务类型:声明性和程序性事务<br />
                                                    声明性事务:由ejb容器负责事务对象的 生成,管理,销毁;具体算法在事务上的注册,事务的提交和回滚等<br />
                                                    主要介绍声明性的事务:<br />
                                                    &nbsp;&nbsp; ejb容器为其中的<span style="color: rgb(255,1,2)">所有的ejb组件</span>提供了一种默认的事务模式:Requires<br />
                                                    在该模式下面,组件中的方法如果在事务环境下被调用(即客户端调用了该组件的方法),则方法中的逻辑会被添加到客户端的事务环境中,和客户端的程序使用相同的事务控制对象.如果不在事务环境中调用(在客户端没有调用该组件中的方法),ejb容器就创建新的事务对象,管理该方法中的所有逻辑.<br />
                                                    例如:<br />
                                                    ejb组件:<br />
                                                    &nbsp;&nbsp; @Statefull<br />
                                                    public class personmanager inplements IPersonAdmin{<br />
                                                    @PersistenceContext(unitName="mydb")<br />
                                                    private EntityManager manager;<br />
                                                    @EJB(mappedName="MySession/remote")<br />
                                                    private IPersonAdmin mytools;<br />
                                                    public List&lt;person&gt; QueryAll(){<br />
                                                    ....<br />
                                                    }<br />
                                                    public void createPerson(Person p){<br />
                                                    Person pobj=new Person();<br />
                                                    pobj.setName("ziaoxioa");<br />
                                                    #1 manager.persist(pobj);<br />
                                                    #2 mytools.createPerson(p);<br />
                                                    #3 manager.persist(null);<br />
                                                    }<br />
                                                    客户代码:<br />
                                                    ...<br />
                                                    myinf.createPerson(p);<br />
                                                    ...<br />
                                                    默认情况下,ejb读物起会为ejb组件中的所有方法配置一中requires型的事务服务.在这种事务模式下面,如果方法被在事务环境下调用,方法就使用客户端事务对象和事务环境ruguo不在事务环境中被调用,则ejb容器就会创建新的事务对象和环境来负责管理该方法的逻辑完整性!由于上面的#3错误,所以数据库中不会添加任何记录!<br />
                                                    ejb容器为ejb组件添加的默认的事务策略能够满足多数情况下的算法要求，特殊情况下，可以通过@TransactionAttribute和&lt;container-transaction&gt;标记修改组件的默认事务策略！如下：<br />
                                                    &lt;ejb-jar<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns="http://java.sun.com/xml/ns/javaee"<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xsi:schemaLocation="http://java.sun.com/xml/ns/javaee<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; version="3.0"&gt;<br />
                                                    &lt;assembly-descriptor&gt;<br />
                                                    &nbsp;&nbsp; &lt;container-transaction&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;MySession&lt;/ejb-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method-name&gt;createPerson&lt;/method-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/method&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;trans-attribute&gt;RequiresNew&lt;/trans-attribute&gt;<br />
                                                    &nbsp;&nbsp; &lt;/container-transaction&gt;<br />
                                                    &lt;/assembly-descriptor&gt;<br />
                                                    &lt;/ejb-jar&gt;<br />
                                                    @TransactionAttribute(REQUIRES_NEW)<br />
                                                    public void createPerson(Person p){<br />
                                                    manager.persist(p);<br />
                                                    }<br />
                                                    这样MySession中的createPerson方法事务修改成了RequiesNew模式，在这种模式下，ejb容器不论客户端是否具有事务特征，为createPerson创建一个新的事务对象，此时两个createPerson在完全不同的事务对象控制下，所以#2可以提交到数据库中，#1，#3则回滚<br />
                                                    声明性事务模式：<br />
                                                    <table style="width: 519px; height: 129px" cellspacing="1" cellpadding="1" border="1">
                                                        <tbody>
                                                            <tr>
                                                                <td>&nbsp;Required</td>
                                                                <td>&nbsp;ejb容器为ejb组件方法提供的默认事务模式，在这种模式下，如果调用程序具备自身的事务对象，则组件方法就和客户程序使用相同的事务对象，否则ejb容器就会创建新的事务对象来管理组件方法逻辑</td>
                                                            </tr>
                                                            <tr>
                                                                <td>&nbsp;Supports</td>
                                                                <td>&nbsp;在这种模式下，如果调用程序具备事务特征，则组件方法就会调用调用程序事务对象管理自身逻辑，如果调用程序不包含任何的事务对象，则组件方法也处于无事务管理状态</td>
                                                            </tr>
                                                            <tr>
                                                                <td>&nbsp;NotSupported</td>
                                                                <td>&nbsp;这种模式下，组件方法不支持事务，同时也会忽略掉调用程序中的事务对象，组件方法中的逻辑不受客户程序事务的提交或回滚的影响</td>
                                                            </tr>
                                                            <tr>
                                                                <td>&nbsp;RequiresNew</td>
                                                                <td>&nbsp;在这种模式下，忽略调用程序具备的事务特征，ejb容器会新创建一个新的事务对象管理组件方法逻辑</td>
                                                            </tr>
                                                            <tr>
                                                                <td>&nbsp;Mandatory</td>
                                                                <td>&nbsp;ejb容器不会为该方法创建新的事务管理对象。该组件方法的调用程序必须提供事务对象，处于事务环境中，否则程序将产生异常javax.ejb.EJBTransactionRequiredException<br />
                                                                </td>
                                                            </tr>
                                                            <tr>
                                                                <td>&nbsp;Never</td>
                                                                <td>&nbsp;这种模式下，该方法不会被ejb容器提供事务对象服务，并且调用程序也不能处于事务环境中，否则将产生EJBException异常<br />
                                                                </td>
                                                            </tr>
                                                        </tbody>
                                                    </table>
                                                    <br />
                                                    下面的程序首先清楚组件上的默认事务模式，然后在为方法设定具体事务属性：<br />
                                                    &lt;assembly-descriptor&gt;<br />
                                                    &nbsp;&nbsp; &lt;container-transaction&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;MySession&lt;/ejb-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method-name&gt;*&lt;/method-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/method&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;trans-attribute&gt;NotSupported&lt;/trans-attribute&gt;<br />
                                                    &nbsp;&nbsp; &lt;/container-transaction&gt;<br />
                                                    &nbsp;&nbsp; &lt;container-transaction&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;MySession&lt;/ejb-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;method-name&gt;createPerson&lt;/method-name&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/method&gt;<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;trans-attribute&gt;Required&lt;/trans-attribute&gt;<br />
                                                    &nbsp;&nbsp; &lt;/container-transaction&gt;<br />
                                                    &lt;/assembly-descriptor&gt;<br />
                                                    声明性事务的控制：<br />
                                                    @Stateless<br />
                                                    /*10*/public class PersonManager implements IPersonAdmin<br />
                                                    /*11*/{<br />
                                                    /*12*/&nbsp;&nbsp;&nbsp; &nbsp;@Resource <br />
                                                    /*13*/&nbsp;&nbsp;&nbsp; &nbsp;private EJBContext ctx;<br />
                                                    /*14*/&nbsp;&nbsp;&nbsp; &nbsp;@PersistenceContext(unitName="mydb")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
                                                    /*15*/&nbsp;&nbsp; private EntityManager manager;<br />
                                                    /*16*/&nbsp;&nbsp; @EJB(mappedName="MySession/remote")<br />
                                                    /*17*/&nbsp;&nbsp; private IPersonAdmin mytools;<br />
                                                    /*18*/&nbsp;&nbsp; public List&lt;Person&gt; QueryAll()<br />
                                                    /*19*/&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
                                                    /*20*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Query q=manager.createQuery("from Person c");<br />
                                                    /*21*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List results=q.getResultList();<br />
                                                    /*22*/&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;List&lt;Person&gt; result=(List&lt;Person&gt;)results;<br />
                                                    /*23*/&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return result;<br />
                                                    /*24*/&nbsp;&nbsp; }<br />
                                                    /*25*/&nbsp;&nbsp; public void createPerson(Person p) <br />
                                                    /*26*/&nbsp;&nbsp; {<br />
                                                    /*27*/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; Person pobj=new Person();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
                                                    /*28*/ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pobj.setName("zhanghao");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
                                                    /*29*/ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pobj.setAge(new Integer(32));&nbsp; <br />
                                                    /*30*/ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pobj.setSex("male");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
                                                    /*31*/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; manager.persist(pobj);<br />
                                                    /*32*/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; boolean result=ctx.getRollbackOnly();<br />
                                                    /*33*/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; if(!result)<br />
                                                    /*34*/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; {<br />
                                                    /*35*/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; ctx.setRollbackOnly();&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
                                                    /*36*/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; }<br />
                                                    /*37*/&nbsp;&nbsp; }<br />
                                                    /*38*/}<br />
                                                    该方法使用gejb容器提供的默认的事务模式，事务会在方法结束时自动提交。<br />
                                                    getRollbackOnly()返回房前事务的状态，true表示已经回滚，false表示没有回滚。<br />
                                                    </div>
                                                    </td>
                                                </tr>
                                            </tbody>
                                        </table>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                            </td>
                        </tr>
                    </tbody>
                </table>
                </td>
            </tr>
        </tbody>
    </table><img src ="http://www.blogjava.net/dongwq/aggbug/261646.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-03-24 10:25 <a href="http://www.blogjava.net/dongwq/archive/2009/03/24/261646.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zz视频总结-jndi  </title><link>http://www.blogjava.net/dongwq/archive/2009/03/24/261645.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Tue, 24 Mar 2009 02:22:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/03/24/261645.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/261645.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/03/24/261645.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/261645.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/261645.html</trackback:ping><description><![CDATA[<table style="border-collapse: collapse" cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
    <tbody>
        <tr>
            <td align="center" bgcolor="#bbf0ff"><font style="font-size: 14pt" color="#000066"><strong>视频总结-jndi</strong></font> </td>
            <tr>
                <td>
                <table style="border-collapse: collapse" bordercolor="#bbf0ff" cellspacing="1" cellpadding="0" width="100%" border="1">
                    <tbody>
                        <tr>
                            <td align="center">
                            <table style="border-collapse: collapse; word-wrap: break-word" cellspacing="0" cellpadding="0" width="650" border="0">
                                <tbody>
                                    <tr>
                                        <td align="center">
                                        <table style="border-collapse: collapse; word-wrap: break-word" cellspacing="0" cellpadding="0" width="100%" border="0">
                                            <tbody>
                                                <tr>
                                                    <td width="650">
                                                    <div id="art" style="margin: 15px">
                                                    <div>jndi：java命名和目录接口<br />
                                                    &nbsp;&nbsp;&nbsp;&nbsp; jndi把object和context(还可以有subcontext)组织成一个jndi树<br />
                                                    这样object就可一被绑定到不同的context上面</div>
                                                    <div>jndi是一种查找服务，用于查找：<br />
                                                    &nbsp;&nbsp;&nbsp; web应用环境变量<br />
                                                    &nbsp;&nbsp;&nbsp; EJB和他们的环境变量<br />
                                                    &nbsp;&nbsp;&nbsp; 通过DataSource的数据库连接池<br />
                                                    &nbsp;&nbsp;&nbsp; JMS没有表和连接工厂<br />
                                                    &nbsp;&nbsp;&nbsp; 其他服务<br />
                                                    不要将jndi当做数据库使用<br />
                                                    &nbsp;&nbsp;&nbsp; jndi对象存储在内存中<br />
                                                    &nbsp;&nbsp;&nbsp; 访问jndi对象与网络性能有关</div>
                                                    <div>jndi树：<br />
                                                    InitialContext是JNDI树所有搜索的起点<br />
                                                    对象绑定到jndi树上，java对象是树叶，context是节点<br />
                                                    一个绑定把对象与一个逻辑名和一个context关联起来</div>
                                                    <div>创建Initial Context<br />
                                                    从服务器端对象连接到jndi<br />
                                                    //创建一个InitialContext<br />
                                                    context ctx=new InitialContext();//链接到当前的jndi树上<br />
                                                    从任何一个地方连接到jndi<br />
                                                    &nbsp; .创建Environment对象<br />
                                                    &nbsp;&nbsp; weblogic.jndi.Enviroment env=new Weblogix.jndi.Enviroment();<br />
                                                    &nbsp;&nbsp; 填写Enviroment<br />
                                                    &nbsp;&nbsp; env.setProviderurl("t3://127.0.0.1:7001");//weblogic server的位置<br />
                                                    &nbsp;&nbsp; env.setSecurityPrincipal("system");//安全信息<br />
                                                    &nbsp;&nbsp; env.setSecurityCredentiais("password");<br />
                                                    &nbsp;&nbsp; //使用Environment对象创建InitialContext<br />
                                                    &nbsp;&nbsp; context ctx=env.getInitialContext();<br />
                                                    &nbsp; .hashtable的用法....<br />
                                                    创建subcontext<br />
                                                    &nbsp; 创建一个用于绑定对象的subcontext<br />
                                                    &nbsp; 创建Environment对象<br />
                                                    &nbsp; context ctx=env.getInitialContext();//首先获得已经存在的subcontext或者initialcontext<br />
                                                    &nbsp; 填写Environment<br />
                                                    &nbsp; context subcontext=ctx.createSubcontext("newSubcontext");<br />
                                                    &nbsp; subcontext.rebind("boundobject",object);<br />
                                                    &nbsp; subcontext.close();<br />
                                                    &nbsp; ctx.close();<br />
                                                    其他链接到jndi的方法：<br />
                                                    &nbsp; <br />
                                                    使用ConstantProperties名和hashtable类：<br />
                                                    &nbsp;HashTable env=new HashTable();<br />
                                                    &nbsp;env.put(Context.initial_context_factory,"weblogic.jndi.WLInitialContextFactory");<br />
                                                    &nbsp;env.put(Context.procider_url,"t3://localhost:7001");<br />
                                                    &nbsp;env.put(Context.security_principal,"system");<br />
                                                    &nbsp;env.put(Context.crrdentials,"password");<br />
                                                    &nbsp;Context ctx=new InitialContext(env);<br />
                                                    另一个例子：使用hardcoded名和properties类<br />
                                                    &nbsp;Properties env=new Properties();<br />
                                                    &nbsp;env.setProperties("java.naming.factory.initial","weblogic.jndi.WLInitialContextFactory");<br />
                                                    &nbsp;env.setProperties("java.naming.provider.url","t3://localhost:7001")<br />
                                                    &nbsp;env.setProperties("java.naming.security.principal","system");<br />
                                                    &nbsp;env.setProperties("java.naming.security.credentials","password");<br />
                                                    &nbsp;Context ctx=new InitialContext(env);</div>
                                                    <div>jndi.properties<br />
                                                    .jndi.properties文件为所有的Initial Contexts设置默认的属性<br />
                                                    .jndi.properties文件的搜索顺序<br />
                                                    &nbsp;&nbsp;&nbsp; .classpath<br />
                                                    &nbsp;&nbsp;&nbsp; .$JAVA_HOME/lib<br />
                                                    实例：<br />
                                                    &nbsp;java.naming.factoyr.initial=weblogic.jndi.WLInitialContextFactory<br />
                                                    &nbsp;java.naming.security.url=t3://localhost:7001<br />
                                                    &nbsp;java.naming.security.pricipal=system<br />
                                                    &nbsp;java.naming.security.credentials=password<br />
                                                    &nbsp;使用默认值：<br />
                                                    &nbsp;Context ctx=new InitialContext();</div>
                                                    <div>从jndi查找：<br />
                                                    .lookup()从jndi树获得对象<br />
                                                    .通过lookup()返回的对象必须映射到他们合适的类型<br />
                                                    try{<br />
                                                    //先获得InitialContext<br />
                                                    //Context ic=new Context();<br />
                                                    Object obj;<br />
                                                    obj=ic.lookup("javax.transation.UserTransaction");<br />
                                                    UserTransaction ut=(UserTransaction)obj;<br />
                                                    ut.begin();<br />
                                                    .....<br />
                                                    ic.close();<br />
                                                    }catch(NamingEcxeption e){....}</div>
                                                    <div>远程绑定对象：<br />
                                                    .远程绑定到远程命名服务的对象必须是序列化的<br />
                                                    .访问命名服务时，对象是采用复制机制<br />
                                                    查找的对象是序列化到客户端的</div>
                                                    <div>一个binding实例：</div>
                                                    <div>public static Context getInitialContext()throws NamingException{<br />
                                                    &nbsp;&nbsp; 创建Environment对象<br />
                                                    &nbsp;&nbsp; weblogic.jndi.Environment env=new Weblogix.jndi.Environment();<br />
                                                    &nbsp;&nbsp; 填写Enviroment<br />
                                                    &nbsp;&nbsp; env.setProviderurl("t3://127.0.0.1:7001");//weblogic server的位置<br />
                                                    &nbsp;&nbsp; env.setSecurityPrincipal("system");//安全信息<br />
                                                    &nbsp;&nbsp; env.setSecurityCredentiais("password");<br />
                                                    &nbsp;&nbsp; //使用Environment对象创建InitialContext<br />
                                                    &nbsp;&nbsp; context ctx=env.getInitialContext();<br />
                                                    &nbsp;&nbsp; return ctx;<br />
                                                    }<br />
                                                    //获得Initial Context<br />
                                                    Context ctx=getInitialContext();<br />
                                                    //创建名为band的对象<br />
                                                    Bank myBank=new Bank();<br />
                                                    //把对象绑定到jndi树<br />
                                                    ctx.rebind("theBank",myBank);<br />
                                                    ctx.close();</div>
                                                    <div><br />
                                                    </div>
                                                    </div>
                                                    </td>
                                                </tr>
                                            </tbody>
                                        </table>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                            </td>
                        </tr>
                    </tbody>
                </table>
                </td>
            </tr>
        </tbody>
    </table><img src ="http://www.blogjava.net/dongwq/aggbug/261645.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-03-24 10:22 <a href="http://www.blogjava.net/dongwq/archive/2009/03/24/261645.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0中的依赖注入，截获器及其在WebLogic Server 10中的扩展</title><link>http://www.blogjava.net/dongwq/archive/2009/03/23/261563.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Mon, 23 Mar 2009 10:49:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2009/03/23/261563.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/261563.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2009/03/23/261563.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/261563.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/261563.html</trackback:ping><description><![CDATA[<h1>EJB3.0中的依赖注入，截获器及其在WebLogic Server 10中的扩展<span>2007-09-05 来自：lizhe1985&nbsp;<wbr>&nbsp;<wbr>[<a href="http://middleware.csdn.net/page/157591a8-2101-4b41-b544-58f9981a6f03#">收藏到我的网摘</a>]</span></h1>
<h2><br />
<br />
1 前言<br />
<br />
　　与EJB2.1相比，EJB3.0规范引入了两个重要概念：依赖注入（DI：Dependency Injection）和截获器（Interceptor），本文首先介绍了这两个概念并给出相关示例，然后分析了EJB3.0规范在这两方面的不足之处，最终深入探讨了WebLogic Server 10对它们的支持和扩展。<br />
<br />
2 依赖注入<br />
<br />
　　2.1 基本概念<br />
<br />
　　依赖注入是从开源社区的一些著名轻量级容器（如Spring、Pico container）中所发展出来的概念，其主要思想就是由容器而不是对象本身来负责处理对象之间的依赖关系。与传统的服务定位器相比，依赖注入具有易测试、弱侵入性等优点，这也就是为什么在最新的Java EE 5规范中引入它的原因。<br />
<br />
　　对于EJB3.0来说，依赖注入就是由容器负责查找被依赖的对象并注入到依赖bean中，而bean本身不再需要进行JNDI或者context查询。此外，依赖注入发生在任何业务方法被调用之前，而且支持setter方法注入和域注入两种方式。<br />
<br />
　　通过与标注结合使用，在bean类中声明依赖注入是非常简单的（当然，也可以在部署描述符文件中声明依赖注入）：<br />
<br />
　　　　@EJB用于注入EJB业务对象<br />
　　　　@PersistenceUnit 用于注入EntityManagerFactory<br />
　　　　@PersistenceContext 用于注入EntityManager<br />
　　　　@Resource 用于注入其它资源对象，如连接工厂、消息目标等<br />
<br />
　　2.2 示例<br />
<br />
@Stateless<br />
public class ServiceBean implements Service {<br />
private javax.sql.DataSource myDS;<br />
@Resource(mappedName=&#8220;LocalDataSource")<br />
public void setMyDS(javax.sql.DataSource ds) {this.myDS = ds; }<br />
@EJB(beanName=&#8220;AccountBean")<br />
private Account account;<br />
}<br />
<br />
　　在无状态会话bean ServiceBean中，声明了两个依赖：一个是数据源，一个是业务接口。在运行期间，EJB3.0容器一旦创建了ServiceBean的实例，就会分别通过方法注入和域注入将数据源对象和业务对象注入到ServiceBean中。<br />
<br />
3 截获器<br />
<br />
　　3.1 基本概念<br />
<br />
　　作为EJB3.0中提出的新概念，截获器是可以对bean的业务方法和生命周期事件进行拦截的组件。截获器需要由@Interceptors 或发布描述符文件中相关的标签指定。截获器可以带有状态而且可以进行依赖注入，其生命周期与其所绑定的EJB bean实例的生命周期一致。<br />
<br />
　　定义在截获器中用于拦截目的的方法被称为截获器方法，其中，针对业务方法的截获器方法通过@AroundInvoke标注或发布描述符文件中相关的标签指定；针对生命周期回调的截获器方法通过@PostConstruct, @PreDestroy等标注或发布描述符文件中对应的标签指定。<br />
<br />
　　截获器分为四类：<br />
<br />
　　　　缺省截获器：可作用于ejb-jar中定义的所有EJB bean。缺省截获器只能定义在DD中，不存在相应的标注<br />
　　　　类级截获器：只能作用于所指定的EJB bean<br />
　　　　方法级截获器：只能作用于所指定的某个EJB bean业务方法，方法级截获器不能用于拦截bean的生命周期事件<br />
　　　　bean 级截获器：又被称为自我截获器，因为截获器同时就是EJB bean本身，此时相关的截获器方法只能作用于该EJB<br />
<br />
　　3.2 截获器链的调用顺序<br />
<br />
　　因为可以为EJB定义多个截获器，所以存在截获器链的调用顺序问题，缺省情况下，以下原则被遵循：<br />
<br />
　　　　调用顺序依次是缺省截获器、类级截获器、方法级截获器以及bean级截获器<br />
　　　　对于同类别的截获器，按照声明的顺序调用<br />
　　　　总是优先调用父类的截获器方法。<br />
<br />
　　此外，EJB3.0规范还提供了更灵活的选项，详细信息请参考EJB3.0规范中&#8220;截获器&#8221;一节：<br />
<br />
　　　　在发布描述符文件中设置&#8220;exclude-default-interceptors&#8221; 可以取消对缺省截获器的调用，而应用&#8220;exclude-class-interceptors&#8221;则取消对类级截获器的调用<br />
　　　　为了替换缺省的截获器链调用顺序，可以设置发布描述符文件的&#8220;interceptor-order&#8221;。<br />
<br />
　　3.3 示例<br />
<br />
@Stateless(name="Trader")<br />
@Interceptors(ClassInterceptor.class)<br />
public class TraderBean implements Trader {<br />
@Interceptors(MethodInterceptor.class)<br />
public String sell(String stockSymbol) {<br />
&#8230;<br />
}<br />
@AroundInvoke<br />
public Object selfInterceptor(InvocationContext) throws Exception {<br />
&#8230;<br />
}<br />
}<br />
<br />
　　在无状态会话bean TraderBean中，声明了两个截获器：一个类级截获器，一个方法级截获器，此外，通过使用@AroundInvoke标注，TraderBean的方法selfInterceptor被声明为截获器方法，所以TraderBean就是bean级截获器。<br />
<br />
4 EJB3.0规范在依赖注入和截获器方面的不足<br />
<br />
　　从依赖注入方面来说，EJB3.0目前支持的注入类型是非常有限的，诸如List、Map之类的集合类型都不能被注入。<br />
<br />
　　另一方面，EJB3.0的截获器可被看作是一种AOP模型，截获器类相当于方面（Aspect），而截获器方法相当于通知（Advice），但这种AOP是非常简单的：<br />
<br />
　　　　不支持引入（Introduction）；<br />
　　　　不支持切入点（Pointcut）模式<br />
　　　　通过标注告诉容器某个EJB需要使用截获器，从而使得这种AOP模型具有一定的侵入性<br />
<br />
5 WebLogic Server 10 EJB3.0容器简介<br />
<br />
　　 5.1 Pitchfork 简介<br />
<br />
　　Pitchfork是由Interface21与BEA合作开发的一个具有Apache License的开源项目，作为Spring的&#8220;增值&#8221;项目，开发Pitchfork有两个目的：<br />
<br />
　　　　当前应用服务器可使用Pitchfork实现Java EE 5中的依赖注入，标注处理以及EJB3.0中的截获器。<br />
　　　　在Spring容器中支持Java EE 5的标注<br />
<br />
　　5.2 WebLogic Server 10 EJB3.0容器的架构<br />
<br />
　　WebLogic Server 10完全支持Java EE 5和EJB3.0，其EJB3.0 容器是基于Pitchfork来实现依赖注入与截获器的，而Pitchfork又利用了Spring的依赖注入和AOP。此时，WebLogic Server 10的用户有两种选择：<br />
<br />
　　　　使用EJB3.0标准模型： EJB bean实例由EJB容器创建，然后由Pitchfork实施Java EE 5 的依赖注入和截获器，这是WebLogic Server 10的缺省配置。<br />
　　　　使用Spring扩展模型：EJB bean实例由Spring容器创建并实施Spring的依赖注入，然后由Pitchfork实施Java EE 5的依赖注入，EJB3.0截获器和Spring AOP。<br />
<br />
6 Spring扩展模型<br />
<br />
　　6.1 使用Spring扩展模型的主要开发步骤<br />
<br />
　　　　下载某个版本的Spring类库（最好是由BEA指定的版本），至少需要包括以下jar文件：spring.jar, aspectjweaver.jar, commons-logging.jar, log4j-1.2.14.jar，如果需要，还可以增加其它jar文件。<br />
　　　　将这些jar文件加入到WebLogic Server 10的类路径中。<br />
　　　　创建文本文件Weblogic.application.ComponentFacotry以标识当前应用将使用Spring扩展模型，其内容只有一行：　　　　Weblogic.application.SpringComponentFactory。<br />
　　　　创建/META-INF/services子目录，然后放入前面创建的文件Weblogic.application.ComponentFacotry<br />
　　　　建立Spring 配置文件，并放入到/META-INF目录下，如果是EJB应用程序，Spring配置文件的名字应该是spring-ejb-jar.xml，如果是Web应用程序，Spring配置文件的名字则是spring-web.xml.<br />
　　　　为了使EJB bean能利用Spring的依赖注入与AOP，需要同时将其定义在spring-ejb-jar.xml（或spring-web.xml）中，从Spring角度来看，这就是一个普通的Spring bean，只不过它的id或name必须与对应的EJB　name相同。<br />
　　　　将上述目录文件、相关的Java类、部署描述符等打包成标准的jar文件、war文件或ear文件。<br />
<br />
　　需要注意的是，在Spring配置文件中定义的bean，如果它也是一个EJB bean，则该Spring bean的class属性会被忽略以避免潜在的冲突。<br />
<br />
　　6.2 示例<br />
<br />
　　示例一：利用Spring的依赖注入。本例将演示两点，(1) 注入一个集合类型，(2) 注入一个Spring POJO对象<br />
<br />
　　(1) 开发一个bean类<br />
<br />
@Stateless(name="AccountManagementBean")<br />
@Remote({examples.AccountManagement.class})<br />
public class AccountManagementBean<br />
{<br />
private List accountList;<br />
private BusinessObject businessObject;<br />
public boolean doBusiness(String account) {<br />
if (accountList.contains(account)) {<br />
businessObject.doBusiness();<br />
return true;<br />
}<br />
return false;<br />
}<br />
public BusinessObject getBusinessObject() {<br />
return businessObject;<br />
}<br />
public void setBusinessObject(BusinessObject businessObject) {<br />
this.businessObject = businessObject;<br />
}<br />
<br />
public List getAccountList() {<br />
return accountList;<br />
}<br />
public void setAccountList(List accountList) {<br />
this.accountList = accountList;<br />
}<br />
}<br />
　　(2) 一个POJO<br />
<br />
public class BusinessObjectImpl implements BusinessObject<br />
{<br />
private String result;<br />
<br />
public void doBusiness() {<br />
System.out.println("I am doing business, the result is: " + result);<br />
}<br />
<br />
public String getResult() {<br />
return result;<br />
}<br />
<br />
public void setResult(String result) {<br />
this.result = result;<br />
}<br />
}<br />
　　(3) Spring-ejb-jar.xml<br />
<br />
&#8230;<br />
＜beans＞<br />
＜bean name="BusinessObject" class="examples.BusinessObjectImpl"＞<br />
＜property name="result" value="success" /＞<br />
＜/bean＞<br />
＜bean id="AccountManagementBean"＞<br />
＜property name="businessObject" ref="BusinessObject" /＞<br />
＜property name="accountList"＞<br />
＜list＞<br />
＜value＞Safin＜/value＞<br />
＜value＞Amy＜/value＞<br />
＜value＞Albert＜/value＞<br />
＜value＞Yang＜/value＞<br />
＜/list＞<br />
＜/property＞<br />
＜/bean＞<br />
＜/beans＞<br />
<br />
　　示例二：利用Spring 的AOP。本例演示了混合使用JEE interceptor、基于代理的Spring AOP以及AspectJ的Aspect<br />
<br />
　　(1) 开发一个bean类<br />
<br />
@Stateless(name="AccountManagementBean")<br />
@Remote({examples.AccountManagement.class})<br />
public class AccountManagementBean<br />
{<br />
public AccountManagementBean() {}<br />
@Interceptors({examples.JEEInterceptor.class})<br />
public boolean doBusiness(String account) {<br />
System.out.println("I am doing business " + account);<br />
return true;<br />
}<br />
}<br />
<br />
　　(2) 开发一个JEE interceptor<br />
<br />
public class JEEInterceptor {<br />
@AroundInvoke<br />
private Object intercept(InvocationContext inv) throws Exception{<br />
System.out.println("I am in JEEInterceptor.intercept()");<br />
return inv.proceed();<br />
}<br />
}<br />
<br />
　　(3) 开发一个Advice<br />
<br />
public class SimpleAdvice implements MethodInterceptor{<br />
public Object invoke(MethodInvocation invocation) throws Throwable {<br />
System.out.println("I am in Spring AOP interceptor");<br />
return invocation.proceed();<br />
}<br />
}<br />
<br />
　　(4) 开发一个Pointcut<br />
<br />
public class SimpleStaticPointcut extends StaticMethodMatcherPoint<wbr>cut {<br />
public boolean matches(Method method, Class cls) {<br />
return "doBusiness".equals(method.getName());<br />
}<br />
public ClassFilter getClassFilter() {<br />
return new ClassFilter() {<br />
public boolean matches(Class cls) {<br />
return AccountManagementBean.class.isAssignableFrom(cls);<br />
}<br />
};<br />
}<br />
}<br />
<br />
　　(5) 开发一个AspectJ Aspect<br />
<br />
@Aspect<br />
public class Aspects {<br />
@Around("execution(* examples.AccountManagementBean.doBusiness(..))")<br />
public Object around(ProceedingJoinPoint pjp) {<br />
System.out.println(&#8220;I am in AspectJ aspect);<br />
Object retVal = null;<br />
try {<br />
retVal = pjp.proceed();<br />
} catch (Throwable e) {<br />
e.printStackTrace();<br />
}<br />
return retVal;<br />
}<br />
}<br />
<br />
　　(5) Spring-ejb-jar.xml<br />
<br />
＜?xml version="1.0" encoding="UTF-8"?＞<br />
＜beans xmlns="http://www.springframework.org/schema/beans"<br />
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />
xmlns:aop="http://www.springframework.org/schema/aop"<br />
xsi:schemaLocation="http://www.springframework.org/schema/beans<br />
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd<br />
http://www.springframework.org/schema/aop<br />
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"＞<br />
＜bean id="AccountManagementBean" /＞<br />
＜bean id="myAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"＞<br />
＜property name="advice"＞<br />
＜bean class=&#8221;examples.SimpleAdvice&#8221; /＞<br />
＜/property＞<br />
＜property name="pointcut"＞<br />
＜bean class="examples.SimpleStaticPointcut" /＞<br />
＜/property＞<br />
＜/bean＞<br />
＜bean id="MyAspect" class="examples.Aspects" /＞<br />
＜/beans＞<br />
<br />
　　6.3 优点<br />
<br />
　　提供Spring扩展模型具有如下好处：<br />
<br />
　　　　可以在同一个发布单元中混合使用EJB bean和Spring POJO，而且一个EJB bean可以同时是一个Spring POJO，因此被EJB容器和Spring容器同时管理<br />
　　　　有效地克服了EJB3.0 规范在依赖注入和截获器方面的一些缺陷<br />
　　　　为用户提供更灵活的选择：<br />
　　　　　　如果标准的EJB 依赖注入以及截获器可以满足应用需求，或者可移植性是优先考虑的因素，则选用标准模型<br />
　　　　　　如果标准的EJB依赖注入以及截获器不能满足应用需求，或者不用考虑可移植性，或者需要集成一些Spring应用，则应选用Spring扩展模型<br />
<br />
7 Spring AOP在WebLogic Server 10 Spring扩展模型中的使用限制及说明<br />
<br />
　　7.1 代理生成方式<br />
<br />
　　Spring AOP采用的是一种基于代理的框架，目前有两种生成代理的方式：JDK动态代理和CGLIB。在WebLogic Server 10的Spring扩展模型中，目前不支持CGLIB方式，这主要是因为生成的EJB类都是final的<br />
<br />
　　7.2 代理创建<br />
<br />
　　在Spring中，代理或者是通过诸如ProxyFactoryBean之类的工厂bean明确创建，或者是通过&#8220;自动代理&#8221;创建器隐含创建。<br />
<br />
　　在WebLogic Server 10中，Pitchfork已经隐含提供了类似的&#8220;自动代理&#8221;机制，所以原有的Spring代理创建方式是无效的，换句话说，用户只需要在Spring配置文件中定义目标bean以及对应的Spring Advisor和AspectJ Aspect, 不需要再定义ProxyFactoryBean和&#8220;自动代理&#8221;创建器，Pitchfork会自动为我们创建AOP代理<br />
<br />
　　7.3 截获的顺序问题<br />
<br />
　　在Spring扩展模型中，可以混合使用JEE截获器、Spring Advisor以及AspectJ Aspect，此时的调用顺序为JEE截获器、Spring Advisor以及AspectJ Aspect。<br />
<br />
　　7.4 bean的实例化模式<br />
<br />
　　缺省方式下，Spring bean是Singleton的，即Spring容器总是返回同一个bean实例，在Spring扩展模型中，这意味着同一个Spring Advisor或AspectJ Aspect实例将被应用到不同的EJB bean实例上，如果Advisor或Aspect实例是有状态的，这可能会产生问题，为此我们推荐如下的使用方式：<br />
<br />
　　　SLSB &amp; MDB<br />
　　　　带有状态的Advisor或Aspect<br />
　　　　　不推荐用带有状态的Advisor或Aspect，除非用户意识到相关的后果并认为这种后果是可以接收的，此时的实例化模式取决于具体应用<br />
　　　　没有状态的Advisor或Aspect<br />
　　　　　采用Singleton实例化模式<br />
　　　SFSB<br />
　　　　带有状态的Advisor或Aspect<br />
　　　　　正常情况下应该采用的实例化模式是Prototype，除非用户意识到采用Singletong的后果并认为这种后果是可以接收的<br />
　　　　没有状态的Advisor或Aspect<br />
　　　　　采用Singleton实例化模式<br />
<br />
8 结束语<br />
<br />
　　依赖注入和截获器的引入，使得EJB3.0克服了很多EJB2.1的缺点，但与开源社区中流行的轻量级容器相比，EJB3.0无论是在依赖注入的范围还是在AOP的易用性方面都还存在一定的不足。而最近BEA所推出的WebLogic Server 10不但完全支持EJB3.0，而且对其进行了有效扩展，这使得一方面可以充分利用在开源社区中出于领导地位的Spring在依赖注入和AOP方面的强大能力，另一方面又紧密依托WebLogic Server 10在事务、安全、集群方面领先的技术，从而为EJB3.0用户开发出易维护、可扩展、高效率的企业应用程序打下坚实的基础。<br />
<br />
作者简介<br />
<br />
　　李钢 dev2devid: cc_masterli ，BEA研发中心WebLogic Server 研发团队成员，西安交通大学计算机专业博士，一直从事java中间件领域的研发，2005年加入BEA，现为EJB3 中国研发小组的负责人。</h2><img src ="http://www.blogjava.net/dongwq/aggbug/261563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2009-03-23 18:49 <a href="http://www.blogjava.net/dongwq/archive/2009/03/23/261563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zz利用静态内部类为您的代码添加辅助功能</title><link>http://www.blogjava.net/dongwq/archive/2007/10/13/152656.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Sat, 13 Oct 2007 15:43:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2007/10/13/152656.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/152656.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2007/10/13/152656.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/152656.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/152656.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 学会了这个技巧，您便可以把静态内部类的使用加入到您的 Java 使用技巧集锦当中。静态内部类是在另一个类的定义中进行定义，并且标记为静态的类。我将向您展示一个实例，它利用静态内部类向另一个类中添加测试代码。&nbsp;&nbsp;<a href='http://www.blogjava.net/dongwq/archive/2007/10/13/152656.html'>阅读全文</a><img src ="http://www.blogjava.net/dongwq/aggbug/152656.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2007-10-13 23:43 <a href="http://www.blogjava.net/dongwq/archive/2007/10/13/152656.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zz:Java正则表达式4种常用功能 增加常用示例</title><link>http://www.blogjava.net/dongwq/archive/2007/08/24/139195.html</link><dc:creator>小强摩羯座</dc:creator><author>小强摩羯座</author><pubDate>Fri, 24 Aug 2007 15:02:00 GMT</pubDate><guid>http://www.blogjava.net/dongwq/archive/2007/08/24/139195.html</guid><wfw:comment>http://www.blogjava.net/dongwq/comments/139195.html</wfw:comment><comments>http://www.blogjava.net/dongwq/archive/2007/08/24/139195.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongwq/comments/commentRss/139195.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongwq/services/trackbacks/139195.html</trackback:ping><description><![CDATA[<span class="bold">Java正则表达式4种常用功能</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;四种功能可以总结成：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1、查询用find()判断是否查询到。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2、匹配必须先用find()方法判断查询到,再用group()得匹配串。没有使用find()不能直接取出匹配串。<br />
&nbsp;&nbsp;&nbsp;这样设计可能是为了一般的处理逻辑上的合理性，因为不能没有判断是否查询到，就去取匹配串，那是不安全的。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3、分解串用split()。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4、替换方法有replaceAll(),replaceFirst()。<br />
<div class="t_msgfont" id="message10174477">正则表达式在字符串处理上有着强大的功能，sun在jdk1.4加入了对它的支持 <br />
<br />
下面简单的说下它的4种常用功能： <br />
<br />
查询： <br />
<br />
String str="abc efg ABC"; <br />
<br />
String regEx="a|f"; //表示a或f <br />
<br />
Pattern p=Pattern.compile(regEx); <br />
<br />
Matcher m=p.matcher(str); <br />
<br />
boolean rs=m.find(); <br />
<br />
如果str中有regEx，那么rs为true，否则为flase。如果想在查找时忽略大小写，则可以写成Pattern p=Pattern.compile(regEx,Pattern.CASE_INSENSITIVE); <br />
<br />
提取： <br />
String regEx=".+\\\\(.+)$"; <br />
<br />
String str="c:\\dir1\\dir2\\name.txt"; <br />
<br />
Pattern p=Pattern.compile(regEx); <br />
<br />
Matcher m=p.matcher(str); <br />
<br />
boolean rs=m.find(); <br />
<br />
for(int i=1;i&lt;=m.groupCount();i++){ <br />
<br />
System.out.println(m.group(i)); <br />
<br />
} <br />
<br />
以上的执行结果为name.txt，提取的字符串储存在m.group(i)中，其中i最大值为m.groupCount(); <br />
<br />
分割： <br />
<br />
String regEx="::"; <br />
<br />
Pattern p=Pattern.compile(regEx); <br />
<br />
String[] r=p.split("xd::abc::cde"); <br />
<br />
执行后，r就是{"xd","abc","cde"}，其实分割时还有跟简单的方法： <br />
<br />
String str="xd::abc::cde"; <br />
<br />
String[] r=str.split("::"); <br />
<br />
替换（删除）： <br />
<br />
String regEx="a+"; //表示一个或多个a <br />
<br />
Pattern p=Pattern.compile(regEx); <br />
<br />
Matcher m=p.matcher("aaabbced a ccdeaa"); <br />
<br />
String s=m.replaceAll("A"); <br />
<br />
结果为"Abbced A ccdeA" <br />
<br />
如果写成空串，既可达到删除的功能，比如： <br />
<br />
String s=m.replaceAll(""); <br />
<br />
结果为"bbced ccde" <br />
<br />
附： <br />
<br />
\d 等於 [0-9] 数字 <br />
\D 等於 [^0-9] 非数字 <br />
\s 等於 [ \t\n\x0B\f\r] 空白字元 <br />
\S 等於 [^ \t\n\x0B\f\r] 非空白字元 <br />
\w 等於 [a-zA-Z_0-9] 数字或是英文字 <br />
\W 等於 [^a-zA-Z_0-9] 非数字与英文字 <br />
<br />
^ 表示每行的开头 <br />
$ 表示每行的结尾<br />
<br />
<br />
<br />
<div>
<div>"^\\d+$"　　//非负整数（正整数 + 0）<br />
"^[0-9]*[1-9][0-9]*$"　　//正整数<br />
"^((-\\d+)|(0+))$"　　//非正整数（负整数 + 0）<br />
"^-[0-9]*[1-9][0-9]*$"　　//负整数<br />
"^-?\\d+$"　　　　//整数<br />
"^\\d+(<a><font color="#fc8044">\\.\\d+)?$</font></a>"　　//非负浮点数（正浮点数 + 0）<br />
"^(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*))$"　　//正浮点数<br />
"^((-\\d+(<a><font color="#fc8044">\\.\\d+)?)|(0+(\\.0+)?))$</font></a>"　　//非正浮点数（负浮点数 + 0）<br />
"^(-(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*)))$"　　//负浮点数<br />
"^(-?\\d+)(<a><font color="#fc8044">\\.\\d+)?$</font></a>"　　//浮点数<br />
"^[A-Za-z]+$"　　//由26个英文字母组成的字符串<br />
"^[A-Z]+$"　　//由26个英文字母的大写组成的字符串<br />
"^[a-z]+$"　　//由26个英文字母的小写组成的字符串<br />
"^[A-Za-z0-9]+$"　　//由数字和26个英文字母组成的字符串<br />
"^\\w+$"　　//由数字、26个英文字母或者下划线组成的字符串<br />
"^[\\w-]+(<a><font color="#fc8044">\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$</font></a>"　　　　//email地址<br />
"^[a-zA-z]+://(<a><font color="#fc8044">\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\S*)?$</font></a>"　　//url<br />
&lt;input onkeyup="value=value.replace(/[^\u4E00-\u9FA5\w]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5\w]/g,''))" value="允许下划线,数字字母和汉字"&gt;</div>
<div>只能输入数字："^[0-9]*$"。<br />
只能输入n位的数字："^\d{n}$"。<br />
只能输入至少n位的数字："^\d{n,}$"。<br />
只能输入m~n位的数字：。"^\d{m,n}$"<br />
只能输入零和非零开头的数字："^(0|[1-9][0-9]*)$"。<br />
只能输入有两位小数的正实数："^[0-9]+(.[0-9]{2})?$"。<br />
只能输入有1~3位小数的正实数："^[0-9]+(.[0-9]{1,3})?$"。<br />
只能输入非零的正整数："^\+?[1-9][0-9]*$"。<br />
只能输入非零的负整数："^\-[1-9][]0-9"*$。<br />
只能输入长度为3的字符："^.{3}$"。<br />
只能输入由26个英文字母组成的字符串："^[A-Za-z]+$"。<br />
只能输入由26个大写英文字母组成的字符串："^[A-Z]+$"。<br />
只能输入由26个小写英文字母组成的字符串："^[a-z]+$"。<br />
只能输入由数字和26个英文字母组成的字符串："^[A-Za-z0-9]+$"。<br />
只能输入由数字、26个英文字母或者下划线组成的字符串："^\w+$"。<br />
验证用户密码："^[a-zA-Z]\w{5,17}$"正确格式为：以字母开头，长度在6~18之间，只能包含字符、数字和下划线。<br />
验证是否含有^%&amp;',;=?$\"等字符："[^%&amp;',;=?$\x22]+"。<br />
只能输入汉字："^[\u4e00-\u9fa5]{0,}$"<br />
验证Email地址："^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。<br />
验证InternetURL："^http://([\w-]+\.)+[\w-]+(/[\w-./?%&amp;=]*)?$"。<br />
验证电话号码："^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$"正确格式为："XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。<br />
验证身份证号（15位或18位数字）："^\d{15}|\d{18}$"。<br />
验证一年的12个月："^(0?[1-9]|1[0-2])$"正确格式为："01"～"09"和"1"～"12"。<br />
验证一个月的31天："^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为；"01"～"09</div>
</div>
</div><img src ="http://www.blogjava.net/dongwq/aggbug/139195.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongwq/" target="_blank">小强摩羯座</a> 2007-08-24 23:02 <a href="http://www.blogjava.net/dongwq/archive/2007/08/24/139195.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>