﻿<?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/wuxufeng8080/category/10536.html</link><description>弱水三千，只取一瓢，便能解渴；佛法无边，奉行一法，便能得益。</description><language>zh-cn</language><lastBuildDate>Tue, 20 Mar 2018 20:43:26 GMT</lastBuildDate><pubDate>Tue, 20 Mar 2018 20:43:26 GMT</pubDate><ttl>60</ttl><item><title>redis在Java web项目的简单应用(转载)</title><link>http://www.blogjava.net/wuxufeng8080/articles/433111.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Mon, 19 Mar 2018 11:10:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/433111.html</guid><wfw:comment>http://www.blogjava.net/wuxufeng8080/comments/433111.html</wfw:comment><comments>http://www.blogjava.net/wuxufeng8080/articles/433111.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wuxufeng8080/comments/commentRss/433111.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wuxufeng8080/services/trackbacks/433111.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 看到一篇关于redis和spring集成的文章，实际测试后，可以。转载以备用。谢谢&nbsp;亲昵YY！一.准备要使用的的jar包,我使用了以下jar包，关于json的jar包是方便存储和转换redis用到的值;&nbsp;二.编写加载redis是要用到的实例类&nbsp;[java]&nbsp;view plain&nbsp;copy&nbsp; &nbsp;...&nbsp;&nbsp;<a href='http://www.blogjava.net/wuxufeng8080/articles/433111.html'>阅读全文</a><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/433111.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2018-03-19 19:10 <a href="http://www.blogjava.net/wuxufeng8080/articles/433111.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java防止非法和重复表单提交的分析(ZT)</title><link>http://www.blogjava.net/wuxufeng8080/articles/182979.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Fri, 29 Feb 2008 08:42:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/182979.html</guid><wfw:comment>http://www.blogjava.net/wuxufeng8080/comments/182979.html</wfw:comment><comments>http://www.blogjava.net/wuxufeng8080/articles/182979.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wuxufeng8080/comments/commentRss/182979.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wuxufeng8080/services/trackbacks/182979.html</trackback:ping><description><![CDATA[第一，对于不支持POST的，可以简单的使用如下代码<br />
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img id="_40_52_Open_Image" onclick="this.style.display='none'; document.getElementById('_40_52_Open_Text').style.display='none'; document.getElementById('_40_52_Closed_Image').style.display='inline'; document.getElementById('_40_52_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_40_52_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_40_52_Closed_Text').style.display='none'; document.getElementById('_40_52_Open_Image').style.display='inline'; document.getElementById('_40_52_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">POST</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">.equals(request.getMethod()))&nbsp;</span><span id="_40_52_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_40_52_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;正常进行</span><span style="color: rgb(0,128,0)"><br />
<img id="_57_100_Open_Image" onclick="this.style.display='none'; document.getElementById('_57_100_Open_Text').style.display='none'; document.getElementById('_57_100_Closed_Image').style.display='inline'; document.getElementById('_57_100_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_57_100_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_57_100_Closed_Text').style.display='none'; document.getElementById('_57_100_Open_Image').style.display='inline'; document.getElementById('_57_100_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)">}</span></span><span style="color: rgb(0,0,255)">else</span><span id="_57_100_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_57_100_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;异常请求</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;out.print(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">异常访问</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div>
</div>
<br />
如果是servlet,&nbsp;可以将doGet方法直接返回，不进行处理就行了<br />
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img id="_76_88_Open_Image" onclick="this.style.display='none'; document.getElementById('_76_88_Open_Text').style.display='none'; document.getElementById('_76_88_Closed_Image').style.display='inline'; document.getElementById('_76_88_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_76_88_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_76_88_Closed_Text').style.display='none'; document.getElementById('_76_88_Open_Image').style.display='inline'; document.getElementById('_76_88_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;doGet(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response)&nbsp;</span><span id="_76_88_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_76_88_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: rgb(0,0,0)"><br />
<img id="_167_181_Open_Image" onclick="this.style.display='none'; document.getElementById('_167_181_Open_Text').style.display='none'; document.getElementById('_167_181_Closed_Image').style.display='inline'; document.getElementById('_167_181_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_167_181_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_167_181_Closed_Text').style.display='none'; document.getElementById('_167_181_Open_Image').style.display='inline'; document.getElementById('_167_181_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;doPost(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response)&nbsp;</span><span id="_167_181_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_167_181_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;正常进行操作</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /></span><span style="color: rgb(0,0,0)">}</span></span></div>
</div>
<br />
还可以采用特定的标志来区分，比如 <br />
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">form</span><span style="color: rgb(0,0,255)">&gt;&lt;</span><span style="color: rgb(128,0,0)">input&nbsp;</span><span style="color: rgb(255,0,0)">type</span><span style="color: rgb(0,0,255)">="hidden"</span><span style="color: rgb(255,0,0)">&nbsp;name</span><span style="color: rgb(0,0,255)">="action"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="insert"</span><span style="color: rgb(0,0,255)">/&gt;&lt;/</span><span style="color: rgb(128,0,0)">form</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">&nbsp;</span></div>
</div>
<br />
程序里这样判断<br />
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img id="_93_105_Open_Image" onclick="this.style.display='none'; document.getElementById('_93_105_Open_Text').style.display='none'; document.getElementById('_93_105_Closed_Image').style.display='inline'; document.getElementById('_93_105_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_93_105_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_93_105_Closed_Text').style.display='none'; document.getElementById('_93_105_Open_Image').style.display='inline'; document.getElementById('_93_105_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">POST</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">.equals(request.getMethod())&nbsp;</span><span style="color: rgb(0,0,0)">&amp;&amp;</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">insert</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">.equals(request.getParameter(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">action</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">))))&nbsp;</span><span id="_93_105_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_93_105_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;正常进行</span><span style="color: rgb(0,128,0)"><br />
<img id="_110_153_Open_Image" onclick="this.style.display='none'; document.getElementById('_110_153_Open_Text').style.display='none'; document.getElementById('_110_153_Closed_Image').style.display='inline'; document.getElementById('_110_153_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_110_153_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_110_153_Closed_Text').style.display='none'; document.getElementById('_110_153_Open_Image').style.display='inline'; document.getElementById('_110_153_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)">}</span></span><span style="color: rgb(0,0,255)">else</span><span id="_110_153_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_110_153_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;异常请求</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;out.print(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">异常访问</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div>
</div>
<br />
第二，判断提交的来源referer,代码如下<br />
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img id="_40_212_Open_Image" onclick="this.style.display='none'; document.getElementById('_40_212_Open_Text').style.display='none'; document.getElementById('_40_212_Closed_Image').style.display='inline'; document.getElementById('_40_212_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_40_212_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_40_212_Closed_Text').style.display='none'; document.getElementById('_40_212_Open_Image').style.display='inline'; document.getElementById('_40_212_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">POST</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">.equals(request.getMethod()))&nbsp;</span><span id="_40_212_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_40_212_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;String&nbsp;referer&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;request.getHeader(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">referer</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
<img id="_172_200_Open_Image" onclick="this.style.display='none'; document.getElementById('_172_200_Open_Text').style.display='none'; document.getElementById('_172_200_Closed_Image').style.display='inline'; document.getElementById('_172_200_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_172_200_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_172_200_Closed_Text').style.display='none'; document.getElementById('_172_200_Open_Image').style.display='inline'; document.getElementById('_172_200_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(referer&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">||</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">!</span><span style="color: rgb(0,0,0)">referer.startsWith(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">http://</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">request.getServerName()))&nbsp;</span><span id="_172_200_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_172_200_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;非法来源</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;正常进行</span><span style="color: rgb(0,128,0)"><br />
<img id="_217_260_Open_Image" onclick="this.style.display='none'; document.getElementById('_217_260_Open_Text').style.display='none'; document.getElementById('_217_260_Closed_Image').style.display='inline'; document.getElementById('_217_260_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_217_260_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_217_260_Closed_Text').style.display='none'; document.getElementById('_217_260_Open_Image').style.display='inline'; document.getElementById('_217_260_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)">}</span></span><span style="color: rgb(0,0,255)">else</span><span id="_217_260_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_217_260_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;异常请求</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;out.print(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">异常访问</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div>
</div>
<br />
第三&nbsp;防止重复提交的hashCode <br />
在表单显示页面<br />
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,0,0)">&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">生成一个formhash,算法可以自己定，不随便重复就可以了</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;String&nbsp;formhash&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;MD5.encode(Long.toString(</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;Date().getTime()));<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">读取当前session里面的hashCode集合，此处使用了Set，方便判断。</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;Set</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">String</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">&nbsp;formhashSession&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;(Set</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">String</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">)&nbsp;session.getAttribute(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">formhashSession</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
<img id="_266_315_Open_Image" onclick="this.style.display='none'; document.getElementById('_266_315_Open_Text').style.display='none'; document.getElementById('_266_315_Closed_Image').style.display='inline'; document.getElementById('_266_315_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_266_315_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_266_315_Closed_Text').style.display='none'; document.getElementById('_266_315_Open_Image').style.display='inline'; document.getElementById('_266_315_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(formhashSession&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">)&nbsp;</span><span id="_266_315_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_266_315_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;formhashSession&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;HashSet</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">String</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">();<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;检测重复问题</span><span style="color: rgb(0,128,0)"><br />
<img id="_374_442_Open_Image" onclick="this.style.display='none'; document.getElementById('_374_442_Open_Text').style.display='none'; document.getElementById('_374_442_Closed_Image').style.display='inline'; document.getElementById('_374_442_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_374_442_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_374_442_Closed_Text').style.display='none'; document.getElementById('_374_442_Open_Image').style.display='inline'; document.getElementById('_374_442_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">while</span><span style="color: rgb(0,0,0)">&nbsp;(formhashSession.contains(formhash))&nbsp;</span><span id="_374_442_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_374_442_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;formhash&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;MD5.encode(Long.toString(</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;Date().getTime()));<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;保存到session里面</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;formhashSession.add(formhash);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;保存</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;session.setAttribute(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">formhashSession</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">,&nbsp;formhashSession);</span></div>
</div>
<br />
表单里面增加如下字段<br />
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">input&nbsp;type</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">hidden</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;name</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">formhash</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;id</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">formhash</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;value</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&lt;%=formhash%&gt;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">/&gt;</span><span style="color: rgb(0,0,0)">&nbsp;</span></div>
</div>
<br />
在表单提交页面进行如下处理<br />
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;拿到表单的formhash</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;formhash&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;upload.getParameter(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">formhash</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;拿到session里面的集合</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;Set</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">String</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">&nbsp;formhashSession&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;(Set</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">String</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">)&nbsp;session.getAttribute(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">formhashSession</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;如果没有，则是重复提交，或者非法提交</span><span style="color: rgb(0,128,0)"><br />
<img id="_285_336_Open_Image" onclick="this.style.display='none'; document.getElementById('_285_336_Open_Text').style.display='none'; document.getElementById('_285_336_Closed_Image').style.display='inline'; document.getElementById('_285_336_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_285_336_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_285_336_Closed_Text').style.display='none'; document.getElementById('_285_336_Open_Image').style.display='inline'; document.getElementById('_285_336_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(formhashSession&nbsp;</span><span style="color: rgb(0,0,0)">==</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">||</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">!</span><span style="color: rgb(0,0,0)">formhashSession.contains(formhash))&nbsp;</span><span id="_285_336_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_285_336_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.println(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">请不要重复提交！</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;下面进行其它的操作<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;最后,如果操作成功,从session里面把这个formhash&nbsp;删掉！<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;以免用户少填写了某个字段，造成表单无法再次提交</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;formhashSession.remove(formhash);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;session.setAttribute(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">formhashSession</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">,&nbsp;formhashSession);</span></div>
</div>
<br />
以上内容为本人原创内容，如要转载，请保留完整信息。并注明来源为http://blog.csdn.net/或http://www.Java2000.net,<br />
<br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2119298</p>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/182979.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2008-02-29 16:42 <a href="http://www.blogjava.net/wuxufeng8080/articles/182979.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java文件复制程序(ZT)</title><link>http://www.blogjava.net/wuxufeng8080/articles/182145.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Tue, 26 Feb 2008 01:57:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/182145.html</guid><wfw:comment>http://www.blogjava.net/wuxufeng8080/comments/182145.html</wfw:comment><comments>http://www.blogjava.net/wuxufeng8080/articles/182145.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wuxufeng8080/comments/commentRss/182145.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wuxufeng8080/services/trackbacks/182145.html</trackback:ping><description><![CDATA[转载自 http://www.easyjf.com/blog.ejf?cmd=doc&amp;id=1048581<br />
<br />
<pre style="border-right: #999999 1px dotted; padding-right: 5px; border-top: #999999 1px dotted; padding-left: 5px; font-size: 12px; padding-bottom: 5px; margin-left: 10px; border-left: #999999 1px dotted; margin-right: 10px; padding-top: 5px; border-bottom: #999999 1px dotted; background-color: #eeeeee">import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* &lt;p&gt;
* Title: 文件处理工具类
* &lt;/p&gt;
* &lt;p&gt;
* Description:实现文件的简单处理,复制文件、目录等
* &lt;/p&gt;
* &lt;p&gt;
* Copyright: Copyright (c) 2005
* &lt;/p&gt;
* &lt;p&gt;
* Company: www.easyjf.com
* &lt;/p&gt;
*
* @author 天一
* @version 1.0
*/
public class FileUtil {
/**
* 复制目录下的文件（不包括该目录）到指定目录，会连同子目录一起复制过去。
*
* @param targetFile
* @param path
*/
public static void copyFileFromDir(String targetDir, String path) {
File file = new File(path);
createFile(targetDir, false);
if (file.isDirectory()) {
copyFileToDir(targetDir, listFile(file));
}
}
/**
* 复制目录下的文件（不包含该目录和子目录，只复制目录下的文件）到指定目录。
*
* @param targetDir
* @param path
*/
public static void copyFileOnly(String targetDir, String path) {
File file = new File(path);
File targetFile = new File(targetDir);
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File subFile : files) {
if (subFile.isFile()) {
copyFile(targetFile, subFile);
}
}
}
}
/**
* 复制目录到指定目录。targetDir是目标目录，path是源目录。
* 该方法会将path以及path下的文件和子目录全部复制到目标目录
*
* @param targetDir
* @param path
*/
public static void copyDir(String targetDir, String path) {
File targetFile = new File(targetDir);
createFile(targetFile, false);
File file = new File(path);
if (targetFile.isDirectory() &amp;&amp; file.isDirectory()) {
copyFileToDir(targetFile.getAbsolutePath() + "/" + file.getName(),
listFile(file));
}
}
/**
* 复制一组文件到指定目录。targetDir是目标目录，filePath是需要复制的文件路径
*
* @param targetDir
* @param filePath
*/
public static void copyFileToDir(String targetDir, String... filePath) {
if (targetDir == null || "".equals(targetDir)) {
System.out.println("参数错误，目标路径不能为空");
return;
}
File targetFile = new File(targetDir);
if (!targetFile.exists()) {
targetFile.mkdir();
} else {
if (!targetFile.isDirectory()) {
System.out.println("参数错误，目标路径指向的不是一个目录！");
return;
}
}
for (String path : filePath) {
File file = new File(path);
if (file.isDirectory()) {
copyFileToDir(targetDir + "/" + file.getName(), listFile(file));
} else {
copyFileToDir(targetDir, file, "");
}
}
}
/**
* 复制文件到指定目录。targetDir是目标目录，file是源文件名，newName是重命名的名字。
*
* @param targetFile
* @param file
* @param newName
*/
public static void copyFileToDir(String targetDir, File file, String newName) {
String newFile = "";
if (newName != null &amp;&amp; !"".equals(newName)) {
newFile = targetDir + "/" + newName;
} else {
newFile = targetDir + "/" + file.getName();
}
File tFile = new File(newFile);
copyFile(tFile, file);
}
/**
* 复制文件。targetFile为目标文件，file为源文件
*
* @param targetFile
* @param file
*/
public static void copyFile(File targetFile, File file) {
if (targetFile.exists()) {
System.out.println("文件" + targetFile.getAbsolutePath()
+ "已经存在，跳过该文件！");
return;
} else {
createFile(targetFile, true);
}
System.out.println("复制文件" + file.getAbsolutePath() + "到"
+ targetFile.getAbsolutePath());
try {
InputStream is = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(targetFile);
byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
fos.write(buffer);
}
is.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static String[] listFile(File dir) {
String absolutPath = dir.getAbsolutePath();
String[] paths = dir.list();
String[] files = new String[paths.length];
for (int i = 0; i &lt; paths.length; i++) {
files[i] = absolutPath + "/" + paths[i];
}
return files;
}
public static void createFile(String path, boolean isFile){
createFile(new File(path), isFile);
}
public static void createFile(File file, boolean isFile) {
if (!file.exists()) {
if (!file.getParentFile().exists()) {
createFile(file.getParentFile(), false);
} else {
if (isFile) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
} else {
file.mkdir();
}
}
}
}
}</pre>
<br />
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/182145.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2008-02-26 09:57 <a href="http://www.blogjava.net/wuxufeng8080/articles/182145.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>连接池的基本工作原理</title><link>http://www.blogjava.net/wuxufeng8080/articles/178611.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 31 Jan 2008 00:32:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/178611.html</guid><wfw:comment>http://www.blogjava.net/wuxufeng8080/comments/178611.html</wfw:comment><comments>http://www.blogjava.net/wuxufeng8080/articles/178611.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wuxufeng8080/comments/commentRss/178611.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wuxufeng8080/services/trackbacks/178611.html</trackback:ping><description><![CDATA[连接池的实现&nbsp; <br />
<br />
1、连接池模型&nbsp; <br />
<br />
本文讨论的连接池包括一个连接池类（DBConnectionPool）和一个连接池管理类（DBConnetionPoolManager）。连接池类是对某一数据库所有连接的&#8220;缓冲池&#8221;，主要实现以下功能：①从连接池获取或创建可用连接；②使用完毕之后，把连接返还给连接池；③在系统关闭前，断开所有连接并释放连接占用的系统资源；④还能够处理无效连接（原来登记为可用的连接，由于某种原因不再可用，如超时，通讯问题），并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。&nbsp; <br />
<br />
连接池管理类是连接池类的外覆类（wrapper）,符合单例模式，即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理，具有以下功能：①装载并注册特定数据库的JDBC驱动程序；②根据属性文件给定的信息，创建连接池对象；③为方便管理多个连接池对象，为每一个连接池对象取一个名字，实现连接池名字与其实例之间的映射；④跟踪客户使用连接情况，以便需要是关闭连接释放资源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理，如系统需要连接不同的数据库，或连接相同的数据库但由于安全性问题，需要不同的用户使用不同的名称和密码。&nbsp; <br />
<br />
2、连接池实现&nbsp; <br />
<br />
下面给出连接池类和连接池管理类的主要属性及所要实现的基本接口：&nbsp; <br />
<br />
<br />
public&nbsp;class&nbsp;DBConnectionPool&nbsp;implements&nbsp;TimerListener{&nbsp;&nbsp; <br />
private&nbsp;int&nbsp;checkedOut;//已被分配出去的连接数&nbsp;&nbsp; <br />
private&nbsp;ArrayList&nbsp;freeConnections=new&nbsp;ArrayList(); <br />
//容器，空闲池，根据//创建时间顺序存放已创建但尚未分配出去的连接&nbsp;&nbsp; <br />
private&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;minConn;//连接池里连接的最小数量&nbsp;&nbsp; <br />
private&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;maxConn;//连接池里允许存在的最大连接数&nbsp;&nbsp; <br />
private&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;name;//为这个连接池取个名字，方便管理&nbsp;&nbsp; <br />
private&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;password;//连接数据库时需要的密码&nbsp;&nbsp; <br />
private&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;url;//所要创建连接的数据库的地址&nbsp;&nbsp; <br />
private&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;user;//连接数据库时需要的用户名&nbsp;&nbsp; <br />
public&nbsp;&nbsp;&nbsp;&nbsp;Timer&nbsp;&nbsp;&nbsp;&nbsp;timer;//定时器&nbsp;&nbsp; <br />
public&nbsp;&nbsp;&nbsp;&nbsp;DBConnectionPool(String&nbsp;name,String&nbsp;URL,String&nbsp;user, <br />
String&nbsp;password,int&nbsp;maxConn)//公开的构造函数&nbsp;&nbsp; <br />
public&nbsp;synchronized&nbsp;void&nbsp;freeConnection(Connection&nbsp;con)&nbsp;&nbsp; <br />
//使用完毕之后，把连接返还给空闲池&nbsp;&nbsp; <br />
public&nbsp;synchronized&nbsp;Connection&nbsp;getConnection(long&nbsp;&nbsp;&nbsp;&nbsp;timeout) <br />
//得到一个连接，timeout是等待时间&nbsp;&nbsp; <br />
public&nbsp;synchronized&nbsp;void&nbsp;release() <br />
//断开所有连接，释放占用的系统资源&nbsp;&nbsp; <br />
private&nbsp;Connection&nbsp;newConnection() <br />
//新建一个数据库连接&nbsp;&nbsp; <br />
public&nbsp;synchronized&nbsp;void&nbsp;TimerEvent()&nbsp;&nbsp;&nbsp;&nbsp; <br />
//定时器事件处理函数&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
public&nbsp;class&nbsp;DBConnectionManager&nbsp;{&nbsp;&nbsp; <br />
static&nbsp;private&nbsp;DBConnectionManager&nbsp;instance; <br />
//连接池管理类的唯一实例&nbsp;&nbsp; <br />
static&nbsp;private&nbsp;int&nbsp;clients;//客户数量&nbsp;&nbsp; <br />
private&nbsp;ArrayList&nbsp;drivers=new&nbsp;ArrayList(); <br />
//容器，存放数据库驱动程序&nbsp;&nbsp; <br />
private&nbsp;HashMap&nbsp;pools&nbsp;=&nbsp;new&nbsp;HashMap(); <br />
//以name/value的形式存取连接池对象的名字及连接池对象&nbsp;&nbsp; <br />
static&nbsp;synchronized&nbsp;public&nbsp;DBConnectionManager&nbsp;getInstance() <br />
/**如果唯一的实例instance已经创建，直接返回这个实例;否则，调用私有构造函数， <br />
创建连接池管理类的唯一实例*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
private&nbsp;DBConnectionManager() <br />
//私有构造函数,在其中调用初始化函数init()&nbsp;&nbsp; <br />
public&nbsp;void&nbsp;freeConnection(String&nbsp;name,Connection&nbsp;con) <br />
//释放一个连接，name是一个连接池对象的名字&nbsp;&nbsp; <br />
public&nbsp;Connection&nbsp;getConnection(String&nbsp;name) <br />
//从名字为name的连接池对象中得到一个连接&nbsp;&nbsp; <br />
public&nbsp;Connection&nbsp;getConnection(String&nbsp;name,long&nbsp;time) <br />
//从名字为name的连接池对象中取得一个连接，time是等待时间&nbsp;&nbsp; <br />
public&nbsp;synchronized&nbsp;void&nbsp;release()//释放所有资源&nbsp;&nbsp; <br />
private&nbsp;void&nbsp;createPools(Properties&nbsp;props) <br />
//根据属性文件提供的信息，创建一个或多个连接池&nbsp;&nbsp; <br />
private&nbsp;void&nbsp;init()//初始化连接池管理类的唯一实例，由私有构造函数调用&nbsp;&nbsp; <br />
private&nbsp;void&nbsp;loadDrivers(Properties&nbsp;props)//装载数据库驱动程序&nbsp;&nbsp; <br />
} <br />
&nbsp; <br />
<br />
3、连接池使用&nbsp; <br />
<br />
上面所实现的连接池在程序开发时如何应用到系统中呢？下面以Servlet为例说明连接池的使用。&nbsp; <br />
<br />
Servlet的生命周期是：在开始建立servlet时，调用其初始化（init）方法。之后每个用户请求都导致一个调用前面建立的实例的service方法的线程。最后，当服务器决定卸载一个servlet时，它首先调用该servlet的destroy方法。&nbsp; <br />
<br />
　　根据servlet的特点，我们可以在初始化函数中生成连接池管理类的唯一实例（其中包括创建一个或多个连接池）。如：&nbsp; <br />
<br />
<br />
public&nbsp;void&nbsp;init()&nbsp;throws&nbsp;ServletException&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
　connMgr=DBConnectionManager.getInstance();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
} <br />
&nbsp; <br />
<br />
然后就可以在service方法中通过连接池名称使用连接池，执行数据库操作。最后在destroy方法中释放占用的系统资源，如：&nbsp; <br />
<br />
<br />
public&nbsp;void&nbsp;destroy(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
connMgr.release();&nbsp;&nbsp;&nbsp;&nbsp; <br />
super.destroy();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
} <br />
&nbsp; <br />
<br />
结束语&nbsp; <br />
<br />
在使用JDBC进行与数据库有关的应用开发中，数据库连接的管理是一个难点。很多时候，连接的混乱管理所造成的系统资源开销过大成为制约大型企业级应用效率的瓶颈。对于众多用户访问的Web应用，采用数据库连接技术的系统在效率和稳定性上比采用传统的其他方式的系统要好很多。本文阐述了使用JDBC访问数据库的技术?讨论了基于连接池技术的数据库连接管理的关键问题并给出了一个实现模型。文章所给出的是连接池管理程序的一种基本模式，为提高系统的整体性能，在此基础上还可以进行很多有意义的扩展.</cc> 
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/178611.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2008-01-31 08:32 <a href="http://www.blogjava.net/wuxufeng8080/articles/178611.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用json-lib</title><link>http://www.blogjava.net/wuxufeng8080/articles/169035.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 20 Dec 2007 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/169035.html</guid><wfw:comment>http://www.blogjava.net/wuxufeng8080/comments/169035.html</wfw:comment><comments>http://www.blogjava.net/wuxufeng8080/articles/169035.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wuxufeng8080/comments/commentRss/169035.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wuxufeng8080/services/trackbacks/169035.html</trackback:ping><description><![CDATA[<strong><span style="font-family: 宋体">下载</span></strong>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; </font><span style="font-family: 宋体">到</span><a href="http://json-lib.sourceforge.net/"><font face="Times New Roman">http://json-lib.sourceforge.net</font></a><span style="font-family: 宋体">下载</span><font face="Times New Roman">json-lib-1.1-jdk15.jar</font><span style="font-family: 宋体">，运行</span><font face="Times New Roman">json</font><span style="font-family: 宋体">还需要的包有：</span><font face="Times New Roman">commons-lang.jar</font><span style="font-family: 宋体">、</span><font face="Times New Roman">commons-logging.jar</font><span style="font-family: 宋体">，</span><font face="Times New Roman">commons-beanutils.jar</font><span style="font-family: 宋体">、</span><font face="Times New Roman">xom-1.0-2005-01-05.jar</font><span style="font-family: 宋体">、</span><font face="Times New Roman">ezmorph-1.0.1.jar</font><span style="font-family: 宋体">，可在</span><a href="http://www.docjar.com/"><font face="Times New Roman">http://www.docjar.com</font></a><span style="font-family: 宋体">搜索下载。</span></font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman" size="3">&nbsp;&nbsp;&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; tab-stops: list 42.0pt"><span style="font-family: Wingdings"><font size="3">l</font><span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong><font size="3"><span style="font-family: 宋体">转化数组和集合</span></font></strong></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; boolean[] boolArray = new boolean[]{true,false,true};</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSONArray jsonArray = JSONArray.fromObject(boolArray);</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(jsonArray);</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; </font><span style="font-family: 宋体">输出：</span><font face="Times New Roman">[true,false,true]</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; List list = new ArrayList();</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(&#8220;</font><span style="font-family: 宋体">第一个</span><font face="Times New Roman">&#8221;);</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(&#8220;</font><span style="font-family: 宋体">第二个</span><font face="Times New Roman">&#8221;);</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSONArray jsonArray = JSONArray.fromObject(list);</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; System.out.println(jsonArray);</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; </font><span style="font-family: 宋体">输出：</span><font face="Times New Roman">[&#8220;</font><span style="font-family: 宋体">第一个</span><font face="Times New Roman">&#8221;, &#8220;</font><span style="font-family: 宋体">第二个</span><font face="Times New Roman">&#8221;]</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman" size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSONArray jsonArray3 = JSONArray.fromObject("['json','is','easy']");</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; System.out.println(jsonArray3);</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; </font><span style="font-family: 宋体">输出：</span><font face="Times New Roman">[&#8220;json&#8221;, &#8220;is&#8221;, &#8220;'easy'&#8221;]</font></font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; tab-stops: list 42.0pt"><span style="font-family: Wingdings"><font size="3">l</font><span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong><font size="3"><span style="font-family: 宋体">转化对象</span></font></strong></p>
<p style="margin: 0cm 0cm 0pt 21pt"><strong><font size="3"><span style="font-family: 宋体">转化</span><font face="Times New Roman">Map</font></font></strong></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">Map map = new HashMap();</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">map.put("name","json");</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">map.put("bool",Boolean.TRUE);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">map.put("int",new Integer(1));</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">map.put("arr",new String[]{"a","b"});</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">map.put("func","function(i){return this.arr[i];}");</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">JSONObject json = JSONObject.fromObject(map);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">System.out.println(json);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><span style="font-family: 宋体">输出：</span><font face="Times New Roman">[&#8220;name&#8221;: &#8220;json&#8221;, &#8220;bool&#8221;:true, &#8220;int&#8221;,1, &#8220;arr&#8221;:[ &#8220;a&#8221;, &#8220;b&#8221;], &#8220;func&#8221;:function(i){return this.arr[i];}]</font></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><strong><font size="3"><span style="font-family: 宋体">转化</span><font face="Times New Roman">Bean</font></font></strong></p>
<p style="margin: 0cm 0cm 0pt 21pt"><strong><font size="3"><font face="Times New Roman">MyBean.java</font></font></strong></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">public class MyBean {</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; private String name = "json";</font></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp;private int pojoId = 1;</font></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; private String func1 = "function(i){return this.options[i]}";</font></font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; private JSONFunction func2 = new JSONFunction(new String[]{"i"},"return this.options[i];");</font></font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font face="Times New Roman" size="3">&nbsp;&nbsp;&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font size="3"><font face="Times New Roman">&nbsp;&nbsp;&nbsp; //</font><span style="font-family: 宋体">以下为</span><font face="Times New Roman">get</font><span style="font-family: 宋体">、</span><font face="Times New Roman">set</font><span style="font-family: 宋体">方法</span></font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font face="Times New Roman" size="3">}</font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font face="Times New Roman" size="3">MyBean bean = new MyBean();</font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font face="Times New Roman" size="3">JSONObject jsonObject = JSONObject.fromObject(bean);</font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font face="Times New Roman" size="3">System.out.println(jsonObject);</font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><span style="font-family: 宋体"><font size="3">输出：</font></span></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font face="Times New Roman" size="3">{"func1":function(i){return this.options[i]},"pojoId":1,"name":"json","func2":function(i){ return this.options[i]; }</font></p>
<p style="margin: 0cm 0cm 0pt 84pt; text-indent: -63pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><strong><span style="font-family: 宋体">从</span><font face="Times New Roman">JSON</font></strong><strong><span style="font-family: 宋体">到</span><font face="Times New Roman">Beans</font></strong></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><font face="Times New Roman">//</font><span style="font-family: 宋体">转化为动态</span><font face="Times New Roman">bean</font></font></p>
<p style="margin: 0cm 0cm 0pt 131.25pt; text-indent: -110.25pt"><font face="Times New Roman" size="3">String myjson = "{name=""json"",bool:true,int:1,double:2.2,function:function(a){return a;},array:[1,2]}";</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">JSONObject json1 = JSONObject.fromString(myjson);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">Object bean1 = JSONObject.toBean(json1);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><strong><span style="font-family: 宋体">由</span><font face="Times New Roman">JSON</font></strong><strong><span style="font-family: 宋体">生成</span><font face="Times New Roman">XML</font></strong></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">JSONObject json = new JSONObject(true);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">XMLSerializer xmlSerializer = new XMLSerializer();</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">String xml = xmlSerializer.write(json);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">System.out.println("xml:" + xml);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><span style="font-family: 宋体">输出：</span><font face="Times New Roman">xml:&lt;?xml version="1.0" encoding="UTF-8"?&gt;</font></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&lt;o null="true"/&gt;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">JSONObject json2 = JSONObject.fromObject("{""name"":""json"",""bool"":true,""int"":1}");</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">String xml2 = xmlSerializer.write(json2);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">System.out.println("xml2:" + xml2);</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><span style="font-family: 宋体">输出：</span><font face="Times New Roman">xml2:&lt;?xml version="1.0" encoding="UTF-8"?&gt;</font></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&lt;o&gt;&lt;bool type="boolean"&gt;true&lt;/bool&gt;&lt;int type="number"&gt;1&lt;/int&gt;&lt;name type="string"&gt;json&lt;/name&gt;&lt;/o&gt;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><font face="Times New Roman">&nbsp;JSONArray json3 = JSONArray.fromObject("[1,2,3]");</font></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><font face="Times New Roman">&nbsp;String xml3 = xmlSerializer.write(json3);</font></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><font face="Times New Roman">&nbsp;System.out.println("xml3:" + xml3);</font></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font size="3"><font face="Times New Roman">&nbsp;</font><span style="font-family: 宋体">输出：</span><font face="Times New Roman">xml3:&lt;?xml version="1.0" encoding="UTF-8"?&gt;</font></font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&lt;a&gt;&lt;e type="number"&gt;1&lt;/e&gt;&lt;e type="number"&gt;2&lt;/e&gt;&lt;e type="number"&gt;3&lt;/e&gt;&lt;/a&gt;</font></p>
<p style="margin: 0cm 0cm 0pt 21pt"><font face="Times New Roman" size="3">&nbsp;</font></p>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/169035.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-12-20 14:55 <a href="http://www.blogjava.net/wuxufeng8080/articles/169035.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP分页技术实现</title><link>http://www.blogjava.net/wuxufeng8080/articles/168061.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sun, 16 Dec 2007 05:49:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/168061.html</guid><wfw:comment>http://www.blogjava.net/wuxufeng8080/comments/168061.html</wfw:comment><comments>http://www.blogjava.net/wuxufeng8080/articles/168061.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wuxufeng8080/comments/commentRss/168061.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wuxufeng8080/services/trackbacks/168061.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 目前比较广泛使用的分页方式是将查询结果缓存在HttpSession或有状态bean中，翻页的时候从缓存中取出一页数据显示。这种方法有两个主要的缺点：一是用户可能看到的是过期数据；二是如果数据量非常大时第一次查询遍历结果集会耗费很长时间，并且缓存的数据也会占用大量内存，效率明显下降。                        　　其它常见的方法还有每次翻页都查询一次数据库，从ResultSe...&nbsp;&nbsp;<a href='http://www.blogjava.net/wuxufeng8080/articles/168061.html'>阅读全文</a><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/168061.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-12-16 13:49 <a href="http://www.blogjava.net/wuxufeng8080/articles/168061.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Guice 示例(ZT)</title><link>http://www.blogjava.net/wuxufeng8080/articles/162961.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sun, 25 Nov 2007 05:20:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/162961.html</guid><wfw:comment>http://www.blogjava.net/wuxufeng8080/comments/162961.html</wfw:comment><comments>http://www.blogjava.net/wuxufeng8080/articles/162961.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wuxufeng8080/comments/commentRss/162961.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wuxufeng8080/services/trackbacks/162961.html</trackback:ping><description><![CDATA[<div>
<p>最近在研究Google 的 Guice，感觉用起来挺简单的，入门应该比Spring要容易的多，这也许是因为Guice刚刚出世，很功能还没有完善吧，但据说Google内部已经在用了，我想再过一段时间取Spring而代之也不是没有可能，至少也能跟Spring平分天下吧。</p>
<p>下面是一个简单的小实例</p>
<p>1.业务逻辑接口</p>
<p>package com.hawkunion.guice;</p>
<p>/**<br />
*<br />
* @author 杜庆明<br />
*/<br />
public interface Work {<br />
&nbsp;&nbsp;&nbsp;&nbsp; public void sayHello(String userName);<br />
}</p>
<p>2.实现接口的业务逻辑</p>
<p>package com.hawkunion.guice;</p>
<p>/**<br />
*<br />
* @author 杜庆明<br />
*/<br />
public class WorkImpl implements Work{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; public void sayHello(String userName) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Hello! 欢迎你："+userName);<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}</p>
<p>3.要用到业务逻辑的类</p>
<p>package com.hawkunion.guice;</p>
<p>import com.google.inject.Inject;</p>
<p>/**<br />
*<br />
* @author 杜庆明<br />
*/<br />
public class RunWorkClass {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; private Work work = null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; @Inject<br />
&nbsp;&nbsp;&nbsp;&nbsp; public void setWork(Work workimpl){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.work = workimpl;<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; public void runWork(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; work.sayHello("阿杜");<br />
&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;<br />
}</p>
<p>4.Module</p>
<p>package com.hawkunion.guice;</p>
<p>import com.google.inject.Binder;<br />
import com.google.inject.Module;</p>
<p>/**<br />
*<br />
* @author 杜庆明<br />
*/<br />
public class MyModule implements Module {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; public void configure(Binder binder) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binder.bind(Work.class).to(WorkImpl.class);<br />
&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p>&nbsp;</p>
<p>5.测试</p>
<p>package com.hawkunion.guice;</p>
<p>import com.google.inject.Guice;<br />
import com.google.inject.Injector;<br />
import com.google.inject.Module;</p>
<p>/**<br />
*<br />
* @author 杜庆明<br />
*/<br />
public class TestWork {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String args[]){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RunWorkClass runWorkClass = new RunWorkClass();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Module module = new MyModule();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Injector in = Guice.createInjector(module);//把module给Guice<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in.injectMembers(runWorkClass);//让Guice把需要注入的业务逻辑注入给对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; runWorkClass.runWork();//&nbsp;&nbsp; 运行work<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>Guice和JSF的集成现在还没有搞定，努力中。。。</p>
</div>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/162961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-11-25 13:20 <a href="http://www.blogjava.net/wuxufeng8080/articles/162961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ConcurrentHashMap,一个更快的HashMap</title><link>http://www.blogjava.net/wuxufeng8080/articles/152238.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Fri, 12 Oct 2007 01:59:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/152238.html</guid><wfw:comment>http://www.blogjava.net/wuxufeng8080/comments/152238.html</wfw:comment><comments>http://www.blogjava.net/wuxufeng8080/articles/152238.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wuxufeng8080/comments/commentRss/152238.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wuxufeng8080/services/trackbacks/152238.html</trackback:ping><description><![CDATA[<font face="新宋体">ConcurrentHashMap<code> </code></font>是 Doug Lea 的 <font face="新宋体"><code>util.concurrent</code><code> </code></font>包的一部分，它提供比 Hashtable 或者 synchronizedMap 更高程度的并发性。而且，对于大多数成功的 <code><font face="新宋体">get()</font></code> 操作它会设法避免完全锁定，其结果就是使得并发应用程序有着非常好的吞吐量。这个月，Brian Goetz 仔细分析了<code><font face="新宋体"> ConcurrentHashMap </font></code>的代码，并探讨 Doug Lea 是如何在不损失线程安全的情况下取得这么骄人成绩的。请在 <a href="javascript:void forumWindow()"><u>讨论论坛</u></a> 上与作者及其他读者共享您对本文的一些想法（也可以在文章的顶部或底部点击<strong>讨论</strong>来访问论坛）。
<p>在7月份的那期 <em>Java理论与实践</em>（&#8220;<a href="http://www-900.ibm.com/developerWorks/cn/java/j-jtp07233/"><u>Concurrent collections classes</u></a>&#8221;）中，我们简单地回顾了可伸缩性的瓶颈，并讨论了怎么用共享数据结构的方法获得更高的并发性和吞吐量。有时候学习的最好方法是分析专家的成果，所以这个月我们将分析 Doug Lea 的<font face="新宋体"><code>util.concurrent</code><code> </code></font>包中的 <font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>的实现。JSR 133 将指定 <font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>的一个版本，该版本针对 Java 内存模型（JMM）作了优化，它将包含在 JDK 1.5 的<code><font face="新宋体"> java.util.concurrent </font></code>包中。<font face="新宋体"><code>util.concurrent</code><code> </code></font>中的版本在老的和新的内存模型中都已通过线程安全审核。 </p>
<p><span class="atitle2"><a name="1.0">针对吞吐量进行优化</a></span><br />
<font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>使用了几个技巧来获得高程度的并发以及避免锁定，包括为不同的 hash bucket（桶）使用多个写锁和使用 JMM 的不确定性来最小化锁被保持的时间——或者根本避免获取锁。对于大多数一般用法来说它是经过优化的，这些用法往往会检索一个很可能在 map 中已经存在的值。事实上，多数成功的 get() 操作根本不需要任何锁定就能运行。（警告：不要自己试图这样做！想比 JMM 聪明不像看上去的那么容易。<font face="新宋体"><code>util.concurrent</code><code> </code></font>类是由并发专家编写的，并且在 JMM 安全性方面经过了严格的同行评审。 ）</p>
<p><a name="1.1"><span class="atitle3">多个写锁</span></a><br />
我们可以回想一下，Hashtable（或者替代方案 <code><font face="新宋体">Collections.synchronizedMap</font></code>）的可伸缩性的主要障碍是它使用了一个 map 范围（map-wide）的锁，为了保证插入、删除或者检索操作的完整性必须保持这样一个锁，而且有时候甚至还要为了保证迭代遍历操作的完整性保持这样一个锁。这样一来，只要锁被保持，就从根本上阻止了其他线程访问 Map，即使处理器有空闲也不能访问，这样大大地限制了并发性。 </p>
<p><font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>摒弃了单一的 map 范围的锁，取而代之的是由 32 个锁组成的集合，其中每个锁负责保护 hash bucket 的一个子集。锁主要由变化性操作（<code><font face="新宋体">put() </font></code>和 <code><font face="新宋体">remove()</font></code>）使用。具有 32 个独立的锁意味着最多可以有 32 个线程可以同时修改 map。这并不一定是说在并发地对 map 进行写操作的线程数少于 32 时，另外的写操作不会被阻塞——32 对于写线程来说是理论上的并发限制数目，但是实际上可能达不到这个值。但是，32 依然比 1 要好得多，而且对于运行于目前这一代的计算机系统上的大多数应用程序来说已经足够了。&nbsp; </p>
<p><a name="1.2"><span class="atitle3">map 范围的操作</span></a><br />
有 32 个独立的锁，其中每个锁保护 hash bucket 的一个子集，这样需要独占访问 map 的操作就必须获得所有32个锁。一些 map 范围的操作，比如说<code><font face="新宋体"> size() </font></code>和 <code><font face="新宋体">isEmpty()，</font></code>也许能够不用一次锁整个 map（通过适当地限定这些操作的语义），但是有些操作，比如 map 重排（扩大 hash bucket 的数量，随着 map 的增长重新分布元素），则必须保证独占访问。Java 语言不提供用于获取可变大小的锁集合的简便方法。必须这么做的情况很少见，一旦碰到这种情况，可以用递归方法来实现。 </p>
<p><a name="2.0"><span class="atitle2">JMM概述</span></a><br />
在进入 <code><font face="新宋体">put()</font></code>、<code><font face="新宋体">get()</font></code> 和<code><font face="新宋体"> remove() </font></code>的实现之前，让我们先简单地看一下 JMM。JMM 掌管着一个线程对内存的动作 （读和写）影响其他线程对内存的动作的方式。由于使用处理器寄存器和预处理 cache 来提高内存访问速度带来的性能提升，Java 语言规范（JLS）允许一些内存操作并不对于所有其他线程立即可见。有两种语言机制可用于保证跨线程内存操作的一致性——<font face="新宋体"><code>synchronized</code><code> </code></font>和 <code><font face="新宋体">volatile。</font></code> </p>
<p>按照 JLS 的说法，&#8220;在没有显式同步的情况下，一个实现可以自由地更新主存，更新时所采取的顺序可能是出人意料的。&#8221;其意思是说，如果没有同步的话，在一个给定线程中某种顺序的写操作对于另外一个不同的线程来说可能呈现出不同的顺序， 并且对内存变量的更新从一个线程传播到另外一个线程的时间是不可预测的。 </p>
<p>虽然使用同步最常见的原因是保证对代码关键部分的原子访问，但实际上同步提供三个独立的功能——原子性、可见性和顺序性。原子性非常简单——同步实施一个可重入的（reentrant）互斥，防止多于一个的线程同时执行由一个给定的监视器保护的代码块。不幸的是，多数文章都只关注原子性方面，而忽略了其他方面。但是同步在 JMM 中也扮演着很重要的角色，会引起 JVM 在获得和释放监视器的时候执行内存壁垒（memory barrier）。 </p>
<p>一个线程在获得一个监视器之后，它执行一个<em>读屏障（read barrier）</em>——使得缓存在线程局部内存（比如说处理器缓存或者处理器寄存器）中的所有变量都失效，这样就会导致处理器重新从主存中读取同步代码块使用的变量。与此类似，在释放监视器时，线程会执行一个<em>写屏障（write barrier）</em>——将所有修改过的变量写回主存。互斥独占和内存壁垒结合使用意味着只要您在程序设计的时候遵循正确的同步法则（也就是说，每当写一个后面可能被其他线程访问的变量，或者读取一个可能最后被另一个线程修改的变量时，都要使用同步），每个线程都会得到它所使用的共享变量的正确的值。 </p>
<p>如果在访问共享变量的时候没有同步的话，就会发生一些奇怪的事情。一些变化可能会通过线程立即反映出来，而其他的则需要一些时间（这由关联缓存的本质所致）。结果，如果没有同步您就不能保证内存内容必定一致（相关的变量相互间可能会不一致），或者不能得到当前的内存内容（一些值可能是过时的）。避免这种危险情况的常用方法（也是推荐使用的方法）当然是正确地使用同步。然而在有些情况下，比如说在像 <font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>之类的一些使用非常广泛的库类中，在开发过程当中还需要一些额外的专业技能和努力（可能比一般的开发要多出很多倍）来获得较高的性能。 </p>
<p><a name="3.0"><span class="atitle2">ConcurrentHashMap 实现</span></a><br />
如前所述，<font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>使用的数据结构与 <font face="新宋体"><code>Hashtable</code><code> </code></font>或<font face="新宋体"><code> HashMap</code><code> </code></font>的实现类似，是 hash bucket 的一个可变数组，每个 <font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>都由一个 <font face="新宋体"><code>Map.Entry</code><code> </code></font>元素链构成，如清单1所示。与 <font face="新宋体"><code>Hashtable</code><code> </code></font>和<code><font face="新宋体"> HashMap </font></code>不同的是，<font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>没有使用单一的集合锁（collection lock），而是使用了一个固定的锁池，这个锁池形成了bucket 集合的一个分区。 </p>
<a name="listing1"><strong>清单1. ConcurrentHashMap 使用的 Map.Entry 元素</strong></a><br />
<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1">
    <tbody>
        <tr>
            <td>
            <pre><code>protected static class Entry implements Map.Entry {    protected final Object key;    protected volatile Object value;    protected final int hash;    protected final Entry next;    ...}</code></pre>
            </td>
        </tr>
    </tbody>
</table>
<p><a name="3.1"><span class="atitle3">不用锁定遍历数据结构</span></a><br />
与<code><font face="新宋体"> Hashtable </font></code>或者典型的锁池 <font face="新宋体"><code>Map</code><code> </code></font>实现不同，<font face="新宋体"><code>ConcurrentHashMap.get()</code><code> </code></font>操作不一定需要获取与相关bucket 相关联的锁。如果不使用锁定，那么实现必须有能力处理它用到的所有变量的过时的或者不一致的值，比如说列表头指针和 <font face="新宋体"><code>Map.Entry</code><code> </code></font>元素的域（包括组成每个 hash bucket 条目的链表的链接指针）。 </p>
<p>大多并发类使用同步来保证独占式访问一个数据结构（以及保持数据结构的一致性）。<font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>没有采用独占性和一致性，它使用的链表是经过精心设计的，所以其实现可以<em>检测 </em>到它的列表是否一致或者已经过时。如果它检测到它的列表出现不一致或者过时，或者干脆就找不到它要找的条目，它就会对适当的bucket 锁进行同步并再次搜索整个链。这样做在一般的情况下可以优化查找，所谓的一般情况是指大多数检索操作是成功的并且检索的次数多于插入和删除的次数。 </p>
<p><span class="atitle3"><a name="3.2">使用不变性</a></span><br />
不一致性的一个重要来源是可以避免得，其方法是使 <font face="新宋体"><code>Entry</code><code> </code></font>元素接近不变性——除了值字段（它们是易变的）之外，所有字段都是 final 的。这就意味着不能将元素添加到 hash 链的中间或末尾，或者从 hash 链的中间或末尾删除元素——而只能从 hash 链的开头添加元素，并且删除操作包括克隆整个链或链的一部分并更新列表的头指针。所以说只要有对某个 hash 链的一个引用，即使可能不知道有没有对列表头节点的引用，您也可以知道列表的其余部分的结构不会改变。而且，因为值字段是易变的，所以能够立即看到对值字段的更新，从而大大简化了编写能够处理内存潜在过时的<code><font face="新宋体"> Map </font></code>的实现。 </p>
<p>新的 JMM 为 final 型变量提供初始化安全，而老的 JMM 不提供，这意味着另一个线程看到的可能是 final 字段的默认值，而不是对象的构造方法提供的值。实现必须能够同时检测到这一点，这是通过保证 <font face="新宋体"><code>Entry</code><code> </code></font>中每个字段的默认值不是有效值来实现的。这样构造好列表之后，如果任何一个 <code><font face="新宋体">Entry</font></code> 字段有其默认值（零或空），搜索就会失败，提示同步 <font face="新宋体"><code>get()</code><code> </code></font>并再次遍历链。 </p>
<p><a name="3.3"><span class="atitle3">检索操作</span></a><br />
检索操作首先为目标 bucket 查找头指针（是在不锁定的情况下完成的，所以说可能是过时的），然后在不获取 bucket 锁的情况下遍历 bucket 链。如果它不能发现要查找的值，就会同步并试图再次查找条目，如清单2所示： </p>
<a name="listing2"><strong>清单2. ConcurrentHashMap.get() 实现</strong></a><br />
<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1">
    <tbody>
        <tr>
            <td>
            <pre><code>  public Object get(Object key) {    int hash = hash(key);     // throws null pointer exception if key is null    // Try first without locking...    Entry[] tab = table;    int index = hash &amp; (tab.length - 1);    Entry first = tab[index];    Entry e;    for (e = first; e != null; e = e.next) {      if (e.hash == hash &amp;&amp; eq(key, e.key)) {        Object value = e.value;        // null values means that the element has been removed        if (value != null)           return value;        else          break;      }    }    // Recheck under synch if key apparently not there or interference    Segment seg = segments[hash &amp; SEGMENT_MASK];    synchronized(seg) {       tab = table;      index = hash &amp; (tab.length - 1);      Entry newFirst = tab[index];      if (e != null || first != newFirst) {        for (e = newFirst; e != null; e = e.next) {          if (e.hash == hash &amp;&amp; eq(key, e.key))             return e.value;        }      }      return null;    }  }</code></pre>
            </td>
        </tr>
    </tbody>
</table>
<p><a name="3.4"><span class="atitle3">删除操作</span></a><br />
因为一个线程可能看到 hash 链中链接指针的过时的值，简单地从链中删除一个元素不足以保证其他线程在进行查找的时候不继续看到被删除的值。相反，从清单3我们可以看到，删除操作分两个过程——首先找到适当的 <code><font face="新宋体">Entry </font></code>对象并把其值字段设为 <code><font face="新宋体">null</font></code>，然后对链中从头元素到要删除的元素的部分进行克隆，再连接到要删除的元素之后的部分。因为值字段是易变的，如果另外一个线程正在过时的链中查找那个被删除的元素，它会立即看到一个空值，并知道使用同步重新进行检索。最终，原始 hash 链中被删除的元素将会被垃圾收集。 </p>
<a name="listing3"><strong>清单3. ConcurrentHashMap.remove() 实现</strong></a><br />
<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1">
    <tbody>
        <tr>
            <td>
            <pre><code>  protected Object remove(Object key, Object value) {    /*      Find the entry, then         1. Set value field to null, to force get() to retry        2. Rebuild the list without this entry.           All entries following removed node can stay in list, but           all preceding ones need to be cloned.  Traversals rely           on this strategy to ensure that elements will not be          repeated during iteration.    */    int hash = hash(key);    Segment seg = segments[hash &amp; SEGMENT_MASK];    synchronized(seg) {      Entry[] tab = table;      int index = hash &amp; (tab.length-1);      Entry first = tab[index];      Entry e = first;      for (;;) {        if (e == null)          return null;        if (e.hash == hash &amp;&amp; eq(key, e.key))           break;        e = e.next;      }      Object oldValue = e.value;      if (value != null &amp;&amp; !value.equals(oldValue))        return null;           e.value = null;      Entry head = e.next;      for (Entry p = first; p != e; p = p.next)         head = new Entry(p.hash, p.key, p.value, head);      tab[index] = head;      seg.count--;      return oldValue;    }  }</code></pre>
            </td>
        </tr>
    </tbody>
</table>
<p>图1为删除一个元素之前的 hash 链：</p>
<p><a name="IDANTS1H"><strong>图1. Hash链</strong></a><br />
<img height="80" alt="Figure 1. Hash chain" src="http://www.dingl.com/images/qt/chm-removal-1.jpg" width="481" /></p>
<p>图2为删除元素3之后的链：</p>
<p><a name="IDA1TS1H"><strong>图2. 一个元素的删除过程</strong></a><br />
<img height="167" alt="Figure 2. Removal of an element" src="http://www.dingl.com/images/qt/chm-removal-2.jpg" width="468" /></p>
<p><a name="3.5"><span class="atitle3">插入和更新操作</span></a><br />
<font face="新宋体"><code>put()</code><code> </code></font>的实现很简单。像<code><font face="新宋体"> remove() </font></code>一样，<font face="新宋体"><code>put()</code><code> </code></font>会在执行期间保持 bucket 锁，但是由于 <font face="新宋体"><code>put()</code><code> </code></font>并不是都需要获取锁，所以这并不一定会阻塞其他读线程的执行（也不会阻塞其他写线程访问别的 bucket）。它首先会在适当的 hash 链中搜索需要的键值。如果能够找到，<code><font face="新宋体">value</font></code>字段（易变的）就直接被更新。如果没有找到，新会创建一个用于描述新 map 的新<code><font face="新宋体"> Entry </font></code>对象，然后插入到 bucket 列表的头部。 </p>
<p><a name="3.6"><span class="atitle3">弱一致的迭代器</span></a><br />
由 <font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>返回的迭代器的语义又不同于 <font face="新宋体"><code>ava.util</code><code> </code></font>集合中的迭代器；而且它又是<em>弱一致的（weakly consistent）</em>而非<em> fail-fast</em><em> </em>的（所谓 fail-fast 是指，当正在使用一个迭代器的时候，如何底层的集合被修改，就会抛出一个异常）。当一个用户调用 <font face="新宋体"><code>keySet().iterator()</code><code> </code></font>去迭代器中检索一组 hash 键的时候，实现就简单地使用同步来保证每个链的头指针是当前值。<code><font face="新宋体">next()</font></code>和 <font face="新宋体"><code>hasNext()</code><code> </code></font>操作以一种明显的方式定义，即遍历每个链然后转到下一个链直到所有的链都被遍历。弱一致迭代器可能会也可能不会反映迭代器迭代过程中的插入操作，但是一定会反映迭代器还没有到达的键的更新或删除操作，并且对任何值最多返回一次。<code><font face="新宋体">ConcurrentHashMap</font></code>返回的迭代器不会抛出<font face="新宋体"><code> ConcurrentModificationException</code><code> </code></font>异常。 </p>
<p><a name="3.7"><span class="atitle3">动态调整大小</span></a><br />
随着 map 中元素数目的增长，hash 链将会变长，因此检索时间也会增加。从某种意义上说，增加 bucket 的数目和重排其中的值是非常重要的。在有些像 <font face="新宋体"><code>Hashtable</code><code> </code></font>之类的类中，这很简单，因为保持一个应用到整个 map 的独占锁是可能的。在 <font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>中，每 次一个条目插入的时候，如果链的长度超过了某个阈值，链就被标记为需要调整大小。当有足够多的链被标记为需要调整大小以后，<font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>就使用递归获取每个 bucket 上的锁并重排每个 bucket 中的元素到一个新的 、更大的 hash 表中。多数情况下，这是自动发生的，并且对调用者透明。 </p>
<p><a name="3.8"><span class="atitle3">不锁定？</span></a><br />
要说不用锁定就可以成功地完成 <code><font face="新宋体">get() </font></code>操作似乎有点言过其实，因为<code><font face="新宋体"> Entry </font></code>的<code><font face="新宋体"> value </font></code>字段是易变的，这是用来检测更新和删除的。在机器级，易变的和同步的内容通常在最后会被翻译成相同的缓存一致原语，所以这里会有<em>一些 </em>锁定，虽然只是细粒度的并且没有调度，或者没有获取和释放监视器的 JVM 开销。但是，除语义之外，在很多通用的情况下，检索的次数大于插入和删除的次数，所以说由 <font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>取得的并发性是相当高的。 </p>
<p><a name="4.0"><span class="atitle2">结束语</span></a><br />
<font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>对于很多并发应用程序来说是一个非常有用的类，而且对于理解 JMM 何以取得较高性能的微妙细节是一个很好的例子。<font face="新宋体"><code>ConcurrentHashMap</code><code> </code></font>是编码的经典，需要深刻理解并发和 JMM 才能够写得出。使用它，从中学到东西，享受其中的乐趣——但是除非您是Java 并发方面的专家，否则的话您自己不应该这样试。 </p>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/152238.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-10-12 09:59 <a href="http://www.blogjava.net/wuxufeng8080/articles/152238.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sitemesh</title><link>http://www.blogjava.net/wuxufeng8080/articles/149233.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Fri, 28 Sep 2007 08:44:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/149233.html</guid><wfw:comment>http://www.blogjava.net/wuxufeng8080/comments/149233.html</wfw:comment><comments>http://www.blogjava.net/wuxufeng8080/articles/149233.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wuxufeng8080/comments/commentRss/149233.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wuxufeng8080/services/trackbacks/149233.html</trackback:ping><description><![CDATA[<span class="style7"><font face="宋体" color="#0000ff" size="4"><font size="5">&nbsp;
<p><strong>一、SiteMesh项目简介</strong> </p>
</font><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#000000">OS(OpenSymphony)的SiteMesh是一个用来在JSP中实现页面布局和装饰（layout and decoration）的框架组件，<br />
能够帮助网站开发人员较容易实现页面中动态内容和静态装饰外观的分离。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sitemesh是由一个基于Web页面布局、装饰以及与现存Web应用整合的框架。它能帮助我们在由大量页面构成的项目中创建一致的页面布局和外观，如一致的导航条，一致的banner，一致的版权，等等。它不仅仅能处理动态的内容，如jsp，php，asp等产生的内容，它也能处理静态的内容，如htm的内容，使得它的内容也符合你的页面结构的要求。甚至于它能将HTML文件象include那样将该文件作为一个面板的形式嵌入到别的文件中去。所有的这些，都是GOF的Decorator模式的最生动的实现。尽管它是由java语言来实现的，但它能与其他Web应用很好地集成。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;官方：<a href="http://www.opensymphony.com/sitemesh/">http://www.opensymphony.com/sitemesh/</a><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下载地址：<a href="http://www.opensymphony.com/sitemesh/download.action">http://www.opensymphony.com/sitemesh/download.action</a>&nbsp;目前的最新版本是<font size="3"><span class="releaseName"><strong>Version 2.3</strong></span>；<br />
</font><br />
<font color="#0000ff" size="5"><strong>二、为什么要使用SiteMesh?<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</strong><font size="4"><font color="#000000">我们的团队开发J2EE应用的时候，经常会碰到一个比较头疼的问题：<br />
<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000"><font size="4"><font color="#ff0000">由于Web页面是由不同的人所开发，所以开发出来的界面通常是千奇百怪，通常让项目管理人员苦笑不得。</font><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></font><font color="#000000" size="4">而实际上，任何一个项目都会要求界面的统一风格和美观，既然风格统一，那就说明UI层肯定有很多可以抽出来<br />
共用的静态或动态部分；如何整合这些通用的静态或动态UI呢？Apache Tiles框架站了出来很好的解决了这一问题，<br />
再加上他与struts的完美集成，导致大小项目都把他作为UI层的首选框架，<br />
</font><font color="#0000ff"><br />
</font><font color="#ff0000" size="5"><strong>但是</strong>：<br />
</font><br />
<font size="4">&nbsp;&nbsp;&nbsp;<font color="#000000">Tiles确实有着它很多的不足之处,下文我会介绍,本文想说的是，除了Apache Tiles框架,其实我们还有更好的解决方案，那就是</font></font><strong><font size="5">SiteMesh；<br />
<br />
<font color="#ff0000">本文</font></font><br />
</strong><font size="4">&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;<font color="#000000">介绍了一个基于Web页面的布局、装饰以及应用整合的框架Sitemesh，它能帮助你为你的应用创建一致的外观，很好的取代Apache Tiles;<br />
</font></font><br />
<font color="#0000ff"><strong>三、SiteMesh&nbsp;VS Apache Tiles</strong></font><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#000000"><font size="4">用过struts的朋友应该对Apache Tiles的不会陌生，我曾经有一篇文章介绍过</font><a title="struts中tiles框架的组合与继承" href="http://www.blogjava.net/yjhmily/archive/2006/10/25/77263.html"><font size="4">struts中tiles框架的组合与继承</font></a><font size="4">，现在怎么看怎么觉得复杂;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;从使用角度来看，Tiles似乎是Sitemesh标签&lt;page:applyDecorator&gt;的一个翻版。其实sitemesh最强的一个特性是sitemesh将decorator<br />
模式用在过滤器上。任何需要被装饰的页面都不知道它要被谁装饰，所以它就可以用来装璜来自php、</font><a href="http://www.myfaq.com.cn/Dev/Web/Asp/index.html" target="_blank"><font size="4">asp</font></a><font size="4">、CGI等产生的页面了。你可以定义若干个装饰器，<br />
根据参数动态地选择装饰器，产生动态的外观以满足你的需求。它也有一套功能强大的属性体系，它能帮助你构建功能强大而灵活的装饰器。相比较而言，<br />
在这方面Tiles就逊色许多。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;个人觉得在团队开发里面，Apache Tiles框架会导致所有人不仅仅要了解并且清楚Apache Tiles的存在，并且要特别熟悉每一个Tiles layout模板的<br />
作用，否则就可能出现用错模板的情况；除此之外，每个人涉及到的所有WEB页面都需要去配置文件里面逐个配置，不仅麻烦出错的几率还高；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;而以上所有的不足都是SiteMesh所不存在的；<br />
<br />
<br />
<font color="#0000ff" size="5"><strong>四、SiteMesh的基本原理<br />
</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font size="3">一个请求到服务器后，如果该请求需要sitemesh装饰，服务器先解释被请求的资源，然后根据配置文件获得用于该请求的装饰器，最后用装饰器装饰被<br />
请求资源，将结果一同返回给客户端浏览器。<br />
<br />
</font></font></font><br />
<strong>五、如何使用SiteMesh<br />
<br />
</strong>&nbsp;&nbsp;<font size="4">&nbsp;这里以struts2+spring2+hibernate3构架的系统为例<br />
</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font size="4"><font color="#000000">1、下载SiteMesh</font><font color="#000000">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下载地址：<a href="http://www.opensymphony.com/sitemesh/download.action">http://www.opensymphony.com/sitemesh/download.action</a>&nbsp;目前的最新版本是<font size="3"><span class="releaseName"><strong>Version 2.3</strong></span>；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2、在工程中引入SiteMesh的必要jar包，和struts2-sitemesh-plugin-2.0.8.jar；<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3、修改你的web.xml,在里面加入sitemesh的过滤器，示例代码如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;sitemesh配置&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">sitemesh</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter-class</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;com.opensymphony.module.sitemesh.filter.PageFilter<br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter-class</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter-mapping</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">sitemesh</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">url-pattern</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">/*</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">url-pattern</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter-mapping</span><span style="color: #0000ff">&gt;</span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意过滤器的为止：应该在struts2的org.apache.struts2.dispatcher.FilterDispatcher过滤器之前org.apache.struts2.dispatcher.ActionContextCleanUp过滤器之后，否则会有问题；<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4、在下载的SiteMesh包中找到sitemesh.xml，(\sitemesh-2.3\src\example-webapp\WEB-INF目录下就有)将其拷贝到/WEB-INF目录下；<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5、在sitemesh.xml文件中有一个property结点(如下)，该结点指定了decorators.xml在工程中的位置，让sitemesh.xml能找到他;<br />
按照此路径新建decorators.xml文件，当然这个路径你可以任意改变，只要property结点的value值与其匹配就行；</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 src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">property&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="decorators-file"</span><span style="color: #ff0000">&nbsp;value</span><span style="color: #0000ff">="/WEB-INF/sitemesh/decorators.xml"</span><span style="color: #0000ff">/&gt;</span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6、在WebRoot目录下新建decorators目录，并在该目录下新建一个模板jsp，根据具体项目风格编辑该模板，如下示例：<br />
&nbsp;我的模板：main.jsp</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: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">@&nbsp;page&nbsp;language</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">java</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;pageEncoding</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">UTF-8</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br />
</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">@taglib&nbsp;prefix</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">decorator</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5"><br />
&nbsp;&nbsp;&nbsp;&nbsp;uri</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">http://www.opensymphony.com/sitemesh/decorator</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br />
</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">@taglib&nbsp;prefix</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">page</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;uri</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">http://www.opensymphony.com/sitemesh/page</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;!</span><span style="color: #ff00ff">DOCTYPE&nbsp;html&nbsp;PUBLIC&nbsp;"-//W3C//DTD&nbsp;XHTML&nbsp;1.1&nbsp;Transitional//EN"&nbsp;<br />
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5"><br />
&nbsp;&nbsp;&nbsp;&nbsp;response.setHeader(</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">Pragma</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">,&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">no-cache</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;response.setHeader(</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">Cache-Control</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">,&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">no-cache</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;response.setDateHeader(</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">Expires</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">,&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">0</span><span style="color: #000000; background-color: #f5f5f5">);<br />
</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">html</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">head</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">title</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">decorator:title&nbsp;</span><span style="color: #ff0000">default</span><span style="color: #0000ff">="kangxm&nbsp;test"</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">title</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;页面Head由引用模板的子页面来替换&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">decorator:head&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">head</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">body&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="page-home"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">div&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="page-total"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">div&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="page-header"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">table&nbsp;</span><span style="color: #ff0000">width</span><span style="color: #0000ff">="100%"</span><span style="color: #ff0000">&nbsp;border</span><span style="color: #0000ff">="0"</span><span style="color: #ff0000">&nbsp;cellspacing</span><span style="color: #0000ff">="0"</span><span style="color: #ff0000">&nbsp;cellpadding</span><span style="color: #0000ff">="0"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><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;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><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;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">div&nbsp;</span><span style="color: #ff0000">class</span><span style="color: #0000ff">="topFunc"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><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;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><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;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">table</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;end&nbsp;header&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;&nbsp;Menu&nbsp;Tag&nbsp;begin&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">div&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="page-menu"</span><span style="color: #ff0000">&nbsp;style</span><span style="color: #0000ff">="margin-top:&nbsp;8px;&nbsp;margin-bottom:&nbsp;8px;"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这里放菜单<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;&nbsp;Menu&nbsp;Tag&nbsp;end&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">div&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="page-content"</span><span style="color: #ff0000">&nbsp;class</span><span style="color: #0000ff">="clearfix"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">center</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">table&nbsp;</span><span style="color: #ff0000">width</span><span style="color: #0000ff">="100%"</span><span style="color: #ff0000">&nbsp;border</span><span style="color: #0000ff">="0"</span><span style="color: #ff0000">&nbsp;cellpadding</span><span style="color: #0000ff">="0"</span><span style="color: #ff0000">&nbsp;cellspacing</span><span style="color: #0000ff">="0"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><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;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><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;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">decorator:body&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;这里的内容由引用模板的子页面来替换&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><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;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">table</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">center</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;end&nbsp;content&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">div&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="page-footer"</span><span style="color: #ff0000">&nbsp;class</span><span style="color: #0000ff">="clearfix"</span><span style="color: #0000ff">&gt;<br />
</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这里放页面底部<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;end&nbsp;footer&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;end&nbsp;page&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">body</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">html</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span></div>
<p>这就是个简单的模板，页面的头和脚都由模板里的静态HTML决定了，主页面区域用的是&lt;decorator:body /&gt;标签；<br />
也就是说凡是能进入过滤器的请求生成的页面都会默认加上模板上的头和脚，然后页面自身的内容将自动放到&lt;decorator:body /&gt;标签所在位置；<br />
<br />
&lt;decorator:title&nbsp;default="Welcome&nbsp;to&nbsp;test&nbsp;sitemesh!"&nbsp;/&gt;：读取被装饰页面的标题，并给出了默认标题。<br />
&lt;decorator:head&nbsp;/&gt;：读取被装饰页面的&lt;head&gt;中的内容；<br />
&lt;decorator:body&nbsp;/&gt;：读取被装饰页面的&lt;body&gt;中的内容；<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7、说到这里大家就要想了，那如果某个特殊的需求请求路径在过滤器的范围内，但又不想使用模板怎么办？你总不能这么不讲道理吧！<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;大家放心吧，SiteMesh早就考虑到这一点了，上面第5步说道的decorators.xml这个时候就起到作用了！<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
下面是我的decorators.xml：</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 src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;?</span><span style="color: #ff00ff">xml&nbsp;version="1.0"&nbsp;encoding="ISO-8859-1"</span><span style="color: #0000ff">?&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">decorators&nbsp;</span><span style="color: #ff0000">defaultdir</span><span style="color: #0000ff">="/decorators"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;Any&nbsp;urls&nbsp;that&nbsp;are&nbsp;excluded&nbsp;will&nbsp;never&nbsp;be&nbsp;decorated&nbsp;by&nbsp;Sitemesh&nbsp;</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">excludes</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">pattern</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">/index.jsp*</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">pattern</span><span style="color: #0000ff">&gt;<br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">pattern</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">/login/*</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">pattern</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">excludes</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">decorator&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="main"</span><span style="color: #ff0000">&nbsp;page</span><span style="color: #0000ff">="main.jsp"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">pattern</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">/*</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">pattern</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">decorator</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">decorators</span><span style="color: #0000ff">&gt;</span></div>
<p>decorators.xml有两个主要的结点：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;decorator结点指定了模板的位置和文件名，通过pattern来指定哪些路径引用哪个模板<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;excludes结点则指定了哪些路径的请求不使用任何模板<br />
<br />
如上面代码，/index.jsp和凡是以/login/开头的请求路径一律不使用模板；<br />
<br />
另外还有一点要注意的是：decorators结点的defaultdir属性指定了模板文件存放的目录;<br />
<br />
<font color="#0000ff" size="5"><strong>六、实战感受</strong></font><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;刚刚做完一个用到sitemesh的项目，跟以前用tiles框架相比，最大的感受就是简单，系统设计阶段就把模板文件和sitemesh框架搭好了！<br />
哪些页面使用框架哪些不使用，全部都通过UI Demo很快就定义出来了；在接下来的开发中所有成员几乎感受不到sitemesh的存在，各自仅仅关<br />
心自己的模块功能实现；<br />
<br />
</p>
</font></font><font color="#0000ff" size="5"><strong>七、总结<br />
<br />
</strong><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;<font size="4">使用sitemesh给我们带来的是不仅仅是页面结构问题，它的出现让我们有更多的时间去关注底层业务逻辑，而不是整个页面的风格和结构。它让我们摆脱了大量用include方式复用页面尴尬局面，也避免了tiles框架在团队开发中的复杂度，它还提供了很大的灵活性以及给我们提供了整合异构Web系统页面的一种方案。</font></font></font></font></font></font> </span>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/149233.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-09-28 16:44 <a href="http://www.blogjava.net/wuxufeng8080/articles/149233.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java定时器的使用 </title><link>http://www.blogjava.net/wuxufeng8080/articles/144972.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 13 Sep 2007 13:19:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/144972.html</guid><description><![CDATA[<font size="2">
<div class="bvMsg" id="msgcns!b16fa12ef2f84cb6!121">定时器类Timer在java.util包中。使用时，先实例化，然后使用实例的schedule(TimerTask task, long delay)方法，设定指定的任务task在指定的延迟delay后执行。定时器任务类TimerTask是抽象类，继承并重写其run()方法，可实现具体任务。
<p>schedule(TimerTask task, Date time)设定指定任务task在指定时间time执行。 </p>
<p>cancel()方法结束这个定时器。 </p>
<p>schedule(TimerTask task, long delay, long period)方法设定指定任务task在指定延迟delay后进行固定延迟peroid的执行。 </p>
<p>scheduleAtFixedRate(TimerTask task, long delay, long period)方法设定指定任务task在指定延迟delay后进行固定频率peroid的执行。 </p>
<p>要实现一个定时任务，运用java中的Timer和TimerTask类可以非常容易实现实时调用处理函数。这两个类使用起来非常方便，可以完成我们对定时器的绝大多数需要。<br />
</p>
<p>看个简单的例子:<br />
<br />
import java.io.IOException;<br />
import java.util.Timer;<br />
<br />
public class TimerTest {<br />
<br />
public static void main(String[] args){<br />
Timer timer = new Timer();<br />
timer.schedule(new MyTask(), 1000, 2000);//在1秒后执行此任务,每次间隔2秒,如果传递一个Data参数,就可以在某个固定的时间执行这个任务.<br />
while(true){//这个是用来停止此任务的,否则就一直循环执行此任务了<br />
try {<br />
int ch = System.in.read();<br />
if(ch-'c'==0){<br />
timer.cancel();//使用这个方法退出任务<br />
}<br />
} catch (IOException e) {<br />
// TODO Auto-generated catch block<br />
e.printStackTrace();<br />
}<br />
}<br />
}<br />
<br />
static class MyTask extends java.util.TimerTask{<br />
@Override<br />
public void run() {<br />
// TODO Auto-generated method stub<br />
System.out.println("________");<br />
}<br />
}<br />
}<br />
</p>
</div>
</font>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/144972.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-09-13 21:19 <a href="http://www.blogjava.net/wuxufeng8080/articles/144972.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 内存溢出：java.lang.OutOfMemoryError: Java heap space (ZT)</title><link>http://www.blogjava.net/wuxufeng8080/articles/116365.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 10 May 2007 00:48:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/116365.html</guid><description><![CDATA[<p><font size=3>使用Java程序从数据库中查询大量的数据时出现异常:<br><font color=#ff0000>java.lang.OutOfMemoryError: Java heap space <br></font>在JVM中如果98％的时间是用于GC且可用的 Heap size 不足2％的时候将抛出此异常信息。</font></p>
<p><font size=3>JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值，其初始空间(即-Xms)是物理内存的1/64，最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。<br>例如：<font color=#0000ff>java -jar -Xmn16m -Xms64m -Xmx128m MyApp.jar</font><br>如果Heap Size设置偏小，除了这些异常信息外，还会发现程序的响应速度变慢了。GC占用了更多的时间，而应用分配到的执行时间较少。<br>Heap Size 最大不要超过可用物理内存的80％，一般的要将-Xms和-Xmx选项设置为相同，而-Xmn为1/4的-Xmx值。<br>Heap size的 -Xms -Xmn 设置不要超出物理内存的大小。否则会提示&#8220;Error occurred during initialization of VM Could not reserve enough space for object heap&#8221;。</font></p>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/116365.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-05-10 08:48 <a href="http://www.blogjava.net/wuxufeng8080/articles/116365.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 内存溢出 OutOfMemoryError: PermGen space </title><link>http://www.blogjava.net/wuxufeng8080/articles/116364.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 10 May 2007 00:46:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/116364.html</guid><description><![CDATA[<div class=postcontent>
<div>今天碰到了这个问题:</div>
<div>javax.servlet.ServletException: PermGen space<br>&nbsp;at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:848)<br>&nbsp;at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:781)</div>
<div>&nbsp;</div>
<div>
<p>查了一下, PermGen space的全称是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出，解决方法也一定是加大内存。说说为什么会内存益出：这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域，它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理，所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。</p>
<p>改正方法：-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m</p>
<p>把PermGen space开大点就行了</p>
<p><span>GC(Garbage Collection)应该不会对PermGen space进行清理<br>所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误<br><br>项目是TOMCAT的WEB APP,由于没有在发布的时候对JSP进行pre compile,<br>所以那个错误是在运行是出现的,相信如果把pre compile加上的话,<br>在启动APP的时候就会出错了.</span> </p>
<p><span>这也与我用热部署功能相关, tomcat不重起多次部署, tomcat不会清理前面加载得环境, 仅仅是将context跟改掉为新部署得,所以将越来越多, 导致出现此问题</span> </p>
<p>参考连接：</p>
<p><a href="http://www-128.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/index.html"><font color=#0000ff><u>http://www-128.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/index.html</u></font></a></p>
<p><a href="http://topic.csdn.net/t/20051107/17/4377324.html"><font color=#0000ff><u>http://topic.csdn.net/t/20051107/17/4377324.html</u></font></a></p>
<p><a href="http://blog.chinaunix.net/u/22374/showart.php?id=165291"><u><font color=#0000ff>http://blog.chinaunix.net/u/22374/showart.php?id=165291</font></u></a></p>
</div>
</div>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/116364.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-05-10 08:46 <a href="http://www.blogjava.net/wuxufeng8080/articles/116364.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>POI</title><link>http://www.blogjava.net/wuxufeng8080/articles/POI.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Mon, 12 Feb 2007 00:42:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/POI.html</guid><description><![CDATA[注意：本文针对对<a href="http://struts.apache.org/" target="_blank"><font color="#666600" size="2">Struts</font></a>，Value List有一定使用经验的开发人员，如果你不是在web环境下使用<a href="http://jakarta.apache.org/poi/" target="_blank"><font color="#666600" size="2">POI</font></a>，建议你直接去看<a href="http://jakarta.apache.org/poi/" target="_blank"><font color="#666600" size="2">POI</font></a>的教程。<br />1.问题由来<br />     在此之前，我一直用valuelist来完成查询并显示结果，效果不错。valuelist可以导出excel，csv，但是一用之下，并没有相象的那么好，它导出的excel并不是真正的excel文件，是一个html的文本文件，这样由于某些处理上的不完善，在我这里出现了导出的文件在打开时，表头和下面的内容错开，并且有多余的空列。如果对它的有关源代码进行修改，做到正常显示是没问题的，但是如果客户的需求再变一点点，比如要设置一定的格式，用它来做就不太方便了。所以我只好寻求另一种方案，最后终于找到<a href="http://jakarta.apache.org/poi/" target="_blank"><font color="#666600" size="2">POI</font></a>，看它的介绍很不错，按照它的指南一试之下，也很简单，于是决定就用它了。现在的问题就是怎样取得valuelist的查询结果，并且用<a href="http://jakarta.apache.org/poi/" target="_blank"><font color="#666600" size="2">POI</font></a>导出到Excel中。<br />2.从web页面动作时调用的Action<br />在我们真正用到的查询action里只要设置好三个属性值就可以了.<br />package com.sogoodsoft.test.export.action;<br /><br />import javax.servlet.http.HttpServletRequest;<br />import javax.servlet.http.HttpServletResponse;<br /><br />import org.apache.struts.action.*;<br /><br />import com.sogoodsoft.framework.exporter.ExportBaseAction;<br /><br />/**<br /> * 导出查询的excel表<br /> * <br /> * @author Albert Song <br /> * @version 1.0<br /> */<br />public class ExportQueryAction extends ExportBaseAction {<br /> <br /> public ActionForward execute(ActionMapping mapping, ActionForm form,<br />   HttpServletRequest request, HttpServletResponse response)<br />   throws Exception {<br />  //列名，必须和applicationContext.xml中对应的sql的列名一致。<br />   // 顺序不必一致<br />  <br />  String colNames[]={"stu_no","stu_name"};<br />  //Excel表的表头，列名对应的中文，必须和列名的顺序对应<br />  String titleNames[]={"学号","姓名"};<br />  //applicataionContext.xml中sql对应的id<br />  String valueListName="testList";<br /><br />//  这三项必须设置<br />   setColNames(colNames);<br />   setTitleNames(titleNames);<br />   set<a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>Name(valueListName);<br />   <br />   return super.export(mapping,form,request,response);<br /> }<br />}<br />3.在ExportBaseAction 中取得valuelist的查询结果<br />valuelist可以不用<a href="http://struts.apache.org/" target="_blank"><font color="#666600" size="2">Struts</font></a>单独使用，我这里是在<a href="http://struts.apache.org/" target="_blank"><font color="#666600" size="2">Struts</font></a>中的用法，代码大概像这样<br /><br />package com.sogoodsoft.framework.exporter;<br /><br />import java.util.List;<br />import java.util.ArrayList;<br />import javax.servlet.http.HttpServletRequest;<br />import javax.servlet.http.HttpServletResponse;<br /><br />import org.apache.commons.beanutils.PropertyUtils;<br />import org.apache.struts.action.*;<br /><br />import org.springframework.web.context.WebApplicationContext;<br />import org.springframework.web.context.support.WebApplicationContextUtils;<br /><br />import net.mlw.vlh.*;<br />import net.mlw.vlh.web.<a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>RequestUtil;<br /><br />import com.sogoodsoft.util.BaseAction;<br />/**<br /> * <br /> * <br /> * @author Albert Song <br /> * @version 1.0<br /> */<br />public class ExportBaseAction extends BaseAction {<br /> <br /> /*<br />  *可导出的最大记录数<br />  */<br /> private final static int MAX_NUM_PER_PAGE=10000;<br /> <br /> private <a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>Handler get<a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>Handler() {<br />  WebApplicationContext context = WebApplicationContextUtils<br />    .getWebApplicationContext(getServlet().getServletContext());<br />  return (<a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>Handler) context.getBean("valueListHandler",<br />    <a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>Handler.class);<br /> }<br /><br /> public ActionForward export(ActionMapping mapping, ActionForm form,<br />   HttpServletRequest request, HttpServletResponse response)<br />   throws Exception {<br />  <br />  <a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>Info vli=<a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>RequestUtil.build<a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>Info(request);<br />  vli.setPagingNumberPer(MAX_NUM_PER_PAGE);<br />  <br />  <a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a> valueList = get<a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>Handler().get<a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>(valueListName,<br />    vli);<br />  <br />  List ls=new ArrayList();<br />  ls.add(titleNames);<br />  int colWidths[]=new int[colNames.length];//列宽<br />  for(int i=0;i&lt;colNames.length;i++)<br />  {<br />   colWidths[i]=titleNames[i].length();<br />  }<br />  while(valueList.hasNext())<br />  {<br />   String cols[]=new String[colNames.length];<br />   <br />   Object bean=valueList.next();<br />   <br />   try {<br />    for(int i=0;i&lt;colNames.length;i++)<br />    {<br />     Object value=PropertyUtils.getProperty(bean,colNames[i]);//关键点<br />     if(value==null)<br />      value="-";<br />     cols[i]=(String)value;<br />     if(colWidths[i]&lt;cols[i].length())<br />     {<br />      colWidths[i]=cols[i].length();<br />     }<br />    }<br />    ls.add(cols);<br />   } catch (Exception e) {<br />    <br />     System.out.println("获取valueList的属性值时发生错误");<br />     break;<br />   }<br />  }<br />  <br />  ExcelExporter.export(ls,response,colWidths);<br />  <br />  return null;<br /> }<br /> <br /> /**<br />  * @param colNames返回的记录集的列名.<br />  */<br /> public void setColNames(String[] colNames) {<br />  this.colNames = colNames;<br /> }<br /> /**<br />  * @param titleNames 表头汉字的字符串数组.<br />  */<br /> public void setTitleNames(String[] titleNames) {<br />  this.titleNames = titleNames;<br /> }<br /> /**<br />  * @param valueListName 查询用的value list的sql的entry key .<br />  */<br /> public void set<a href="http://valuelist.sourceforge.net/" target="_blank"><font color="#666600" size="2">ValueList</font></a>Name(String valueListName) {<br />  this.valueListName = valueListName;<br /> }<br />}<br />4.真正导出excel的类<br />这里只是简单的将传入的字符串数组的List导出<br />package com.sogoodsoft.framework.exporter;<br /><br />import java.util.List;<br />import java.io.*;<br /><br />import javax.servlet.http.HttpServletResponse;<br /><br />import org.apache.poi.hssf.usermodel.*;<br /><br />/**<br /> * @author Albert Song<br /> * <br /> * 导出数据到Excel文件中<br /> *  <br /> */<br />public class ExcelExporter {<br /><br /> public static void export(List exportStringArrayList,<br />   HttpServletResponse response) throws Exception {<br /><br />   export(exportStringArrayList,response,null);<br /> }<br /> public static void export(List exportStringArrayList,<br />   HttpServletResponse response,int colWidths[]) throws Exception {<br /><br />   //仅仅为了防止系统抛出空指针异常，这应该算<a href="http://jakarta.apache.org/poi/" target="_blank"><font color="#666600" size="2">POI</font></a>的一个bug吧，这个问题花了我半天时间，现在还没搞明白<br />   //总之设置之后就可以用了：）<br />   System.setProperty("org.apache.poi.util.<a href="http://jakarta.apache.org/poi/" target="_blank"><font color="#666600" size="2">POI</font></a>Logger","org.apache.poi.util.<a href="http://jakarta.apache.org/poi/" target="_blank"><font color="#666600" size="2">POI</font></a>Logger");<br /><br />   List ls=exportStringArrayList;<br />   <br />   HSSFWorkbook wb = new HSSFWorkbook();<br />   HSSFSheet sheet = wb.createSheet("sheet1");<br />   <br />   if(colWidths!=null)<br />   {<br />    for(int i=0;i&lt;colWidths.length;i++)<br />    {<br />     sheet.setColumnWidth((short)i,(short)(colWidths[i]*600));<br />    }<br />   }<br />   <br />   for(int i=0;i&lt;ls.size();i++)<br />     {<br />    HSSFRow row = sheet.createRow(i);<br />      String[] strs=(String[])ls.get(i);<br />      for(int j=0;j&lt;strs.length;j++)<br />      {<br />       HSSFCell cell = row.createCell((short) j);<br />       cell.setEncoding(HSSFCell.ENCODING_UTF_16);<br />       cell.setCellValue(strs[j]);<br />       <br />      }<br />     }<br />   //  Get output stream<br />   response.setContentType("application/x-msdownload");<br />   response.setHeader("content-disposition",<br />     "attachment; filename=dataexport.xls");<br />   OutputStream os = response.getOutputStream();<br />   wb.write(os);<br />   os.close();<br /> }<br /><br />}<br />5.小结<br />这不能算是文章，只能算是一个抛砖引玉的笔记，本人学习<a href="http://jakarta.apache.org/poi/" target="_blank"><font color="#666600" size="2">POI</font></a>也才一天半，贴出来的目的是为了感谢同样贴出文章的同仁们，他们的无私奉献给了我不少启示，节省了我的时间，因此我觉得花一点时间将我的经验和大家分享是值得的。<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/99359.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-02-12 08:42 <a href="http://www.blogjava.net/wuxufeng8080/articles/POI.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>聚集Collection的技巧</title><link>http://www.blogjava.net/wuxufeng8080/articles/96681.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Tue, 30 Jan 2007 02:34:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/96681.html</guid><description><![CDATA[
		<div>1、  MAP<br />特点：同键的新值将覆盖旧值。<br />示例：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">        Map</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> map </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> HashMap</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br />        String str;<br />        str </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">str=null</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        str </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">b</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">str=a</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        str </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">c</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">str=b 新值覆盖旧值，最后map只有(1,c)一个值。返回的b是被覆盖的值<br /></span></div><br />循环遍历：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">        Map</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, Long</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> map </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> HashMap</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, Long</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br />        map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Long(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">));<br />        map.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">b</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Long(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">));<br /><br />        </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000"> (Map.Entry</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String, Long</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> entry : map.entrySet()) {<br />            String key </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> entry.getKey();<br />            Long value </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> entry.getValue();<br />        }<br /></span></div><br />2、Set<br />特点：无序排列，不会存在重复的值，添加重复值也不会报错.Set可以加入null值<br />示例：</div>
		<div>
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<span style="COLOR: #000000">        Set</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000"> set </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">new</span>
						<span style="COLOR: #000000"> HashSet</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000">();<br />        </span>
						<span style="COLOR: #0000ff">boolean</span>
						<span style="COLOR: #000000"> b;<br />        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> set.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">1</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=true</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> set.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">2</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=true</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> set.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">1</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=false</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> set.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">2</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=false 返回值为false，表示没有加入<br /></span>
				</div>
				<br />3、List<br />特点：有序排序，可以加入重复的元素<br />示例：</div>
		<div>
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<span style="COLOR: #000000">        Arrays.asList(</span>
						<span style="COLOR: #0000ff">new</span>
						<span style="COLOR: #000000"> String[] {</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">11</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">, </span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">222</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000"> });</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">返回一个不可改的List</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        List</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000"> l </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> Arrays.asList(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">11</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">, </span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">222</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">, </span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">333</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);<br />        l.subList(</span>
						<span style="COLOR: #000000">1</span>
						<span style="COLOR: #000000">, </span>
						<span style="COLOR: #000000">2</span>
						<span style="COLOR: #000000">); </span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">由第二个和第三个元素生成一个新List</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">
								<br />        ArrayList</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000"> list </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">new</span>
						<span style="COLOR: #000000"> ArrayList</span>
						<span style="COLOR: #000000">&lt;</span>
						<span style="COLOR: #000000">String</span>
						<span style="COLOR: #000000">&gt;</span>
						<span style="COLOR: #000000">(l); </span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">生成一个可改的List</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        </span>
						<span style="COLOR: #0000ff">boolean</span>
						<span style="COLOR: #000000"> b;<br />        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> list.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">11</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=true  List可以加入重复的元素</span>
						<span style="COLOR: #008000">
								<br />
						</span>
						<span style="COLOR: #000000">        b </span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000"> list.add(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">11</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">);</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">b=true<br /></span>
				</div>
				<br />4、Collections<br />特点：Collections.class是集合的工具方法类<br />示例：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">        List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> list1 </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> ArrayList</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br />        List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> list </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> ArrayList</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br /><br />        Collections.sort(list); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">排序</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> pos </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Collections.binarySearch(list, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">key</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">用二叉树算法来查找，首先得排序好</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pos=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> pos);<br /><br />        Collections.copy(list, list1); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">把list1复制到list上，原list元素被覆盖</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.fill(list, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ss</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">用"ss"填充list</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.max(list); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">找最大元素</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.reverse(list); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">把排序</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.shuffle(list);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">混乱排序</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"><br />        Collections.singleton(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ss</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回一个Set集合，不可改，只有ss一个元素</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.unmodifiableList(list);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回一个不可改的新的List，原list不变</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Collections.synchronizedList(list);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回一个同步的新的List，原list不变<br /></span></div></div>
		<br />5、Properties<br />特点：Properties继承自Hashtable，是Map的一个实现。不过它在读取Properties文件方法特别方便<br />示例：<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">        Properties p </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> System.getProperties(); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">得到系统属性</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        p.list(System.out);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">打印所有</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"><br />        </span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000"><br />         * 从user.home=C:\Documents and Settings\chengang<br />         * 读取properties文件填充到Properties<br />         </span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br />        Properties p2 </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> System.getProperties(); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">得到系统属性</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        File file </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> File(p.getProperty(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">user.home</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">), </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">argo.user.properties</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />        p2.load(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> FileInputStream(file));<br />        System.err.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">------------------------------</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />        p2.list(System.out);<br /></span></div><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/96681.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-01-30 10:34 <a href="http://www.blogjava.net/wuxufeng8080/articles/96681.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Annotation 高级应用 (ZT)</title><link>http://www.blogjava.net/wuxufeng8080/articles/93046.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 11 Jan 2007 00:27:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/93046.html</guid><description><![CDATA[
		<span style="COLOR: red">版权声明：本文可以自由转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明</span>
		<br />作者:cleverpig(作者的Blog:<a href="http://blog.matrix.org.cn/page/cleverpig" target="_new"><font color="#002c99">http://blog.matrix.org.cn/page/cleverpig</font></a>)<br />原文:<a href="http://www.matrix.org.cn/resource/article/44/44062_Java+Annotation+Apt.html" target="_new"><font color="#002c99">http://www.matrix.org.cn/resource/article/44/44062_Java+Annotation+Apt.html</font></a><br />关键字:java,annotation,apt<br /><br /><span style="COLOR: blue">前言：</span><br />前不久在matrix上先后发表了<a href="http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html" target="_new"><font color="#002c99">《java annotation 入门》</font></a>、<a href="http://www.matrix.org.cn/resource/article/44/44055_Java+Annotation+Reflect.html" target="_new"><font color="#002c99">《java annotation 手册》</font></a>两篇文章，比较全面的对java annotation的语法、原理、使用三方面进行了阐述。由于《入门》中的简单例程虽然简单明了的说明了annotation用法，但给大家的感觉可能是意犹未见，所以在此行文《java annotation高级应用》，具体实例化解释annotation和annotation processing tool（APT）的使用。望能对各位的有所帮助。<br /><br /><span style="COLOR: blue">一、摘要：</span><br />《java annotation高级应用》具体实例化解释annotation和annotation processing tool（APT）的使用。望能对各位的有所帮助。本文列举了用于演示annotation的BRFW演示框架、演示APT的apt代码实例，并对其进行较为深度的分析，希望大家多多提意见。<br /><br /><span style="COLOR: blue">二、annotation实例分析</span><br /><span style="COLOR: blue">1．BRFW（Beaninfo Runtime FrameWork）定义：</span><br />本人编写的一个annotation功能演示框架。顾名思义，BRFW就是在运行时取得bean信息的框架。<br /><br /><span style="COLOR: blue">2．BRFW的功能：</span><br /><span style="COLOR: green">A．源代码级annotation</span>：在bean的源代码中使用annotation定义bean的信息；<br /><span style="COLOR: green">B．运行时获取bean数据</span>：在运行时分析bean class中的annotation，并将当前bean class中field信息取出，功能类似xdoclet；<br /><span style="COLOR: green">C．运行时bean数据的xml绑定</span>：将获得的bean数据构造为xml文件格式展现。熟悉j2ee的朋友知道，这个功能类似jaxb。<br /><br /><span style="COLOR: blue">3．BRFW框架：</span><br />BRFW主要包含以下几个类：<br /><span style="COLOR: green">A．Persistent类</span>：定义了用于修饰类的固有类型成员变量的annotation。<br /><span style="COLOR: green">B．Exportable类</span>：定义了用于修饰Class的类型的annotation。<br /><span style="COLOR: green">C．ExportToXml类</span>：核心类，用于完成BRFW的主要功能：将具有Exportable Annotation的bean对象转换为xml格式文本。<br /><span style="COLOR: green">D．AddressForTest类</span>：被A和B修饰过的用于测试目的的地址bean类。其中包含了地址定义所必需的信息：国家、省级、城市、街道、门牌等。<br /><span style="COLOR: green">E．AddressListForTest类</span>：被A和B修饰过的友人通讯录bean类。其中包含了通讯录所必备的信息：友人姓名、年龄、电话、住址（成员为AddressForTest类型的ArrayList）、备注。需要说明的是电话这个bean成员变量是由字符串类型组成的ArrayList类型。由于朋友的住址可能不唯一，故这里的住址为由AddressForTest类型组成的ArrayList。<br />从上面的列表中，可以发现A、B用于修饰bean类和其类成员；C主要用于取出bean类的数据并将其作xml绑定，代码中使用了E作为测试类；E中可能包含着多个D。<br />在了解了这个简单框架后，我们来看一下BRFW的代码吧！<br /><br /><span style="COLOR: blue">4．BRFW源代码分析：</span><br /><span style="COLOR: green">A．Persistent类：</span><br /><strong>清单1：</strong><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation.runtimeframework;<br /><br />import java.lang.annotation.*;<br /><br />/**<br /> * 用于修饰类的固有类型成员变量的annotation<br /> * @author cleverpig<br /> *<br /> */<br />@Retention(RetentionPolicy.RUNTIME)<br />@Target(ElementType.FIELD)<br />public @interface Persistent { <br />        String value() default "";<br />}<br /></pre><br /><br /><span style="COLOR: green">B．Exportable类：</span><br /><strong>清单2：</strong><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation.runtimeframework;<br /><br />import java.lang.annotation.*;<br /><br />/**<br /> * 用于修饰类的类型的annotation<br /> * @author cleverpig<br /> *<br /> */<br />@Retention(RetentionPolicy.RUNTIME)<br />@Target(ElementType.TYPE)<br />public @interface Exportable {<br />        //名称<br />        String name() default "";<br />        //描述<br />        String description() default "";<br />        //省略name和description后，用来保存name值<br />        String value() default "";<br />        <br />}<br /></pre><br /><br /><span style="COLOR: green">C．AddressForTest类：</span><br /><strong>清单3：</strong><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation.runtimeframework;<br /><br />/**<br /> * 用于测试的地址类<br /> * @author cleverpig<br /> *<br /> */<br />@Exportable("address")<br />public class AddressForTest {<br />        //国家<br />        @Persistent<br />        private String country=null;<br />        <br />        //省级<br />        @Persistent<br />        private String province=null;<br />        <br />        //城市<br />        @Persistent<br />        private String city=null;<br />        <br />        //街道<br />        @Persistent<br />        private String street=null;<br /><br />        //门牌<br />        @Persistent<br />        private String doorplate=null;<br />        <br />        public AddressForTest(String country,String province,<br />                        String city,String street,String doorplate){<br />                this.country=country;<br />                this.province=province;<br />                this.city=city;<br />                this.street=street;<br />                this.doorplate=doorplate;<br />        }<br />        <br />}<br /></pre><br /><br /><span style="COLOR: green">D．AddressListForTest类：</span><br /><strong>清单4：</strong><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation.runtimeframework;<br /><br />import java.util.*;<br /><br />/**<br /> * 友人通讯录<br /> * 包含：姓名、年龄、电话、住址（多个）、备注<br /> * @author cleverpig<br /> *<br /> */<br />@Exportable(name="addresslist",description="address list")<br />public class AddressListForTest {<br />        //友人姓名<br />        @Persistent<br />        private String friendName=null;<br />        <br />        //友人年龄<br />        @Persistent<br />        private int age=0;<br />        <br />        //友人电话<br />        @Persistent<br />        private ArrayList&lt;String&gt; telephone=null;<br />        <br />        //友人住址：家庭、单位<br />        @Persistent<br />        private ArrayList&lt;AddressForTest&gt; AddressForText=null;<br />        <br />        //备注<br />        @Persistent<br />        private String note=null;<br />        <br />        public AddressListForTest(String name,int age,<br />                        ArrayList&lt;String&gt; telephoneList, <br />                        ArrayList&lt;AddressForTest&gt; addressList,<br />                        String note){<br />                this.friendName=name;<br />                this.age=age;<br />                this.telephone=new ArrayList&lt;String&gt;(telephoneList);<br />                this.AddressForText=new ArrayList&lt;AddressForTest&gt;(addressList);<br />                this.note=note;<br />                <br />        }<br />}<br /></pre><br /><br /><span style="COLOR: green">E．ExportToXml类：</span><br /><strong>清单5：</strong><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation.runtimeframework;<br /><br />import java.lang.reflect.Field;<br />import java.util.Collection;<br />import java.util.Iterator;<br />import java.util.Map;<br />import java.util.ArrayList;<br /><br />/**<br /> * 将具有Exportable Annotation的对象转换为xml格式文本 <br /> * @author cleverpig<br /> *<br /> */<br />public class ExportToXml {<br />        /**<br />         * 返回对象的成员变量的值（字符串类型）<br />         * @param field 对象的成员变量<br />         * @param fieldTypeClass 对象的类型<br />         * @param obj 对象<br />         * @return 对象的成员变量的值（字符串类型）<br />         */<br />        private String getFieldValue(Field field,Class fieldTypeClass,Object obj){<br />                String value=null;<br />                <br />                try{<br />                        if (fieldTypeClass==String.class){<br />                                value=(String)field.get(obj);<br />                        }<br />                        else if (fieldTypeClass==int.class){<br />                                value=Integer.toString(field.getInt(obj));<br />                        }<br />                        else if (fieldTypeClass==long.class){<br />                                value=Long.toString(field.getLong(obj));<br />                        }<br />                        else if (fieldTypeClass==short.class){<br />                                value=Short.toString(field.getShort(obj));<br />                        }<br />                        else if (fieldTypeClass==float.class){<br />                                value=Float.toString(field.getFloat(obj));<br />                        }<br />                        else if (fieldTypeClass==double.class){<br />                                value=Double.toString(field.getDouble(obj));<br />                        }<br />                        else if (fieldTypeClass==byte.class){<br />                                value=Byte.toString(field.getByte(obj));<br />                        }<br />                        else if (fieldTypeClass==char.class){<br />                                value=Character.toString(field.getChar(obj));<br />                        }<br />                        else if (fieldTypeClass==boolean.class){<br />                                value=Boolean.toString(field.getBoolean(obj));<br />                        }<br />                }<br />                catch(Exception ex){<br />                        ex.printStackTrace();<br />                        value=null;<br />                }<br />                return value;<br />        }<br />        <br />        /**<br />         * 输出对象的字段，当对象的字段为Collection或者Map类型时，要调用exportObject方法继续处理<br />         * @param obj 被处理的对象<br />         * @throws Exception<br />         */<br />        public void exportFields(Object obj) throws Exception{<br />                Exportable exportable=obj.getClass().getAnnotation(Exportable.class);        <br />                if (exportable!=null){<br />                        if (exportable.value().length()&gt;0){<br />//                                System.out.println("Class annotation Name:"+exportable.value());<br />                        }<br />                        else{<br />//                                System.out.println("Class annotation Name:"+exportable.name());<br />                        }<br />                }<br />                else{<br />//                        System.out.println(obj.getClass()+"类不是使用Exportable标注过的");<br />                }<br />                <br />                //取出对象的成员变量<br />                Field[] fields=obj.getClass().getDeclaredFields();<br />                <br />                for(Field field:fields){<br />                        //获得成员变量的标注<br />                        Persistent fieldAnnotation=field.getAnnotation(Persistent.class);<br />                        if (fieldAnnotation==null){<br />                                continue;<br />                        }<br />                        //重要:避免java虚拟机检查对私有成员的访问权限<br />                        field.setAccessible(true);<br />                        Class typeClass=field.getType();<br />                        String name=field.getName();<br />                        String value=getFieldValue(field,typeClass,obj);<br />                        <br />                        //如果获得成员变量的值，则输出<br />                        if (value!=null){<br />                                System.out.println(getIndent()+"&lt;"+name+"&gt;\n"<br />                                                +getIndent()+"\t"+value+"\n"+getIndent()+"&lt;/"+name+"&gt;");<br />                        }<br />                        //处理成员变量中类型为Collection或Map<br />                        else if ((field.get(obj) instanceof Collection)||<br />                                        (field.get(obj) instanceof Map)){<br />                                exportObject(field.get(obj));<br />                        }<br />                        else{<br />                                exportObject(field.get(obj));<br />                        }<br />                        <br />                }<br />        }<br />        <br />        //缩进深度<br />        int levelDepth=0;<br />        //防止循环引用的检查者，循环引用现象如：a包含b，而b又包含a<br />        Collection&lt;Object&gt; cyclicChecker=new ArrayList&lt;Object&gt;();<br />        <br />        /**<br />         * 返回缩进字符串<br />         * @return<br />         */<br />        private String getIndent(){<br />                String s="";<br />                for(int i=0;i&lt;levelDepth;i++){<br />                        s+="\t";<br />                }<br />                return s;<br />        }<br />        /**<br />         * 输出对象，如果对象类型为Collection和Map类型，则需要递归调用exportObject进行处理<br />         * @param obj<br />         * @throws Exception<br />         */<br />        public void exportObject(Object obj) throws Exception{<br />                Exportable exportable=null;<br />                String elementName=null;<br />                <br />                //循环引用现象处理<br />                if (cyclicChecker.contains(obj)){<br />                        return;<br />                }<br />                <br />                cyclicChecker.add(obj);<br />                <br />                //首先处理Collection和Map类型<br />                if (obj instanceof Collection){<br />                        for(Iterator i=((Collection)obj).iterator();i.hasNext();){<br />                                exportObject(i.next());<br />                        }<br />                }<br />                else if (obj instanceof Map){<br />                        for(Iterator i=((Map)obj).keySet().iterator();i.hasNext();){<br />                                exportObject(i.next());<br />                        }<br />                }<br />                else{<br /><br />                        exportable=obj.getClass().getAnnotation(Exportable.class);<br />                        //如果obj已经被Exportable Annotation修饰过了（注意annotation是具有继承性的），<br />                        //则使用其name作为输出xml的元素name<br />                        if (exportable!=null){<br />                                if (exportable.value().length()&gt;0){<br />                                        elementName=exportable.value();<br />                                }<br />                                else{<br />                                        elementName=exportable.name();<br />                                }<br />                        }<br />                        //未被修饰或者Exportable Annotation的值为空字符串，<br />                        //则使用类名作为输出xml的元素name<br />                        if (exportable==null||elementName.length()==0){<br />                                elementName=obj.getClass().getSimpleName();<br />                        }<br />                        //输出xml元素头<br />                        System.out.println(getIndent()+"&lt;"+elementName+"&gt;");<br />                        levelDepth++;<br />                        //如果没有被修饰，则直接输出其toString()作为元素值<br />                        if (exportable==null){<br />                                System.out.println(getIndent()+obj.toString());<br />                        }<br />                        //否则将对象的成员变量导出为xml<br />                        else{<br />                                exportFields(obj);<br />                        }<br />                        levelDepth--;<br />                        //输出xml元素结尾<br />                        System.out.println(getIndent()+"&lt;/"+elementName+"&gt;");<br />                        <br />                }<br />                cyclicChecker.remove(obj);<br />        }<br />        <br />        public static void main(String[] argv){<br />                try{<br />                        AddressForTest ad=new AddressForTest("China","Beijing",<br />                                        "Beijing","winnerStreet","10");<br />                        <br />                        ExportToXml test=new ExportToXml();<br />                        <br />                        ArrayList&lt;String&gt; telephoneList=new ArrayList&lt;String&gt;();<br />                        telephoneList.add("66608888");<br />                        telephoneList.add("66608889");<br />                        <br />                        ArrayList&lt;AddressForTest&gt; adList=new ArrayList&lt;AddressForTest&gt;();<br />                        adList.add(ad);<br />                        <br />                        AddressListForTest adl=new AddressListForTest("coolBoy",<br />                                        18,telephoneList,adList,"some words");<br />                        <br />                        test.exportObject(adl);<br />                }<br />                catch(Exception ex){<br />                        ex.printStackTrace();<br />                }<br />        }<br />}<br /></pre><br /><br />在ExportToXml类之前的类比较简单，这里必须说明一下ExportToXml类：此类的核心函数是exportObject和exportFields方法，前者输出对象的xml信息，后者输出对象成员变量的信息。由于对象类型和成员类型的多样性，所以采取了以下的逻辑：<br /><br />在exportObject方法中，当对象类型为Collection和Map类型时，则需要递归调用exportObject进行处理；<br />而如果对象类型不是Collection和Map类型的话，将判断对象类是否被Exportable annotation修饰过：<br />如果没有被修饰，则直接输出&lt;对象类名&gt;对象.toString()&lt;/对象类名&gt;作为xml绑定结果的一部分；<br />如果被修饰过，则需要调用exportFields方法对对象的成员变量进行xml绑定。<br /><br />在exportFields方法中，首先取出对象的所有成员，然后获得被Persisitent annotation修饰的成员。在其后的一句：field.setAccessible(true)是很重要的，因为bean类定义中的成员访问修饰都是private，所以为了避免java虚拟机检查对私有成员的访问权限，加上这一句是必需的。接着后面的语句便是输出&lt;成员名&gt;成员值&lt;/成员名&gt;这样的xml结构。像在exportObject方法中一般，仍然需要判断成员类型是否为Collection和Map类型，如果为上述两种类型之一，则要在exportFields中再次调用exportObject来处理这个成员。<br /><br />在main方法中，本人编写了一段演示代码：建立了一个由单个友人地址类（AddressForTest）组成的ArrayList作为通讯录类（AddressForTest）的成员的通讯录对象，并且输出这个对象的xml绑定，运行结果如下：<br /><br /><strong>清单6：</strong><br /><pre class="overflow"><br />&lt;addresslist&gt;<br />        &lt;friendName&gt;<br />                coolBoy<br />        &lt;/friendName&gt;<br />        &lt;age&gt;<br />                18<br />        &lt;/age&gt;<br />        &lt;String&gt;<br />                66608888<br />        &lt;/String&gt;<br />        &lt;String&gt;<br />                66608889<br />        &lt;/String&gt;<br />        &lt;address&gt;<br />                &lt;country&gt;<br />                        China<br />                &lt;/country&gt;<br />                &lt;province&gt;<br />                        Beijing<br />                &lt;/province&gt;<br />                &lt;city&gt;<br />                        Beijing<br />                &lt;/city&gt;<br />                &lt;street&gt;<br />                        winnerStreet<br />                &lt;/street&gt;<br />                &lt;doorplate&gt;<br />                        10<br />                &lt;/doorplate&gt;<br />        &lt;/address&gt;<br />        &lt;note&gt;<br />                some words<br />        &lt;/note&gt;<br />&lt;/addresslist&gt;<br /></pre><br /><br /><span style="COLOR: blue">三、APT实例分析：</span><br /><span style="COLOR: blue">1．何谓APT？</span><br />根据sun官方的解释，APT（annotation processing tool）是一个命令行工具，它对源代码文件进行检测找出其中的annotation后，使用annotation processors来处理annotation。而annotation processors使用了一套反射API并具备对JSR175规范的支持。<br />annotation processors处理annotation的基本过程如下：首先，APT运行annotation processors根据提供的源文件中的annotation生成源代码文件和其它的文件（文件具体内容由annotation processors的编写者决定），接着APT将生成的源代码文件和提供的源文件进行编译生成类文件。<br />简单的和前面所讲的annotation实例BRFW相比，APT就像一个在编译时处理annotation的javac。而且从sun开发者的blog中看到，java1.6 beta版中已将APT的功能写入到了javac中，这样只要执行带有特定参数的javac就能达到APT的功能。<br /><br /><span style="COLOR: blue">2．为何使用APT？</span><br />使用APT主要目的是简化开发者的工作量，因为APT可以在编译程序源代码的同时，生成一些附属文件（比如源文件、类文件、程序发布描述文字等），这些附属文件的内容也都是与源代码相关的。换句话说，使用APT就是代替了传统的对代码信息和附属文件的维护工作。使用过hibernate或者beehive等软件的朋友可能深有体会。APT可以在编译生成代码类的同时将相关的文件写好，比如在使用beehive时，在代码中使用annotation声明了许多struct要用到的配置信息，而在编译后，这些信息会被APT以struct配置文件的方式存放。<br /><br /><span style="COLOR: blue">3．如何定义processor？</span><br /><span style="COLOR: green">A．APT工作过程：</span><br />从整个过程来讲，首先APT检测在源代码文件中哪些annotation存在。然后APT将查找我们编写的annotation processor factories类，并且要求factories类提供处理源文件中所涉及的annotation的annotation processor。接下来，一个合适的annotation processors将被执行，如果在processors生成源代码文件时，该文件中含有annotation，则APT将重复上面的过程直到没有新文件生成。<br /><br /><span style="COLOR: green">B．编写annotation processors：</span><br />编写一个annotation processors需要使用java1.5 lib目录中的tools.jar提供的以下4个包：<br />com.sun.mirror.apt: 和APT交互的接口；<br />com.sun.mirror.declaration: 用于模式化类成员、类方法、类声明的接口；<br />com.sun.mirror.type: 用于模式化源代码中类型的接口； <br />com.sun.mirror.util: 提供了用于处理类型和声明的一些工具。 <br /><br />每个processor实现了在com.sun.mirror.apt包中的AnnotationProcessor接口，这个接口有一个名为“process”的方法，该方法是在APT调用processor时将被用到的。一个processor可以处理一种或者多种annotation类型。<br />一个processor实例被其相应的工厂返回，此工厂为AnnotationProcessorFactory接口的实现。APT将调用工厂类的getProcessorFor方法来获得processor。在调用过程中，APT将提供给工厂类一个AnnotationProcessorEnvironment 类型的processor环境类对象，在这个环境对象中，processor将找到其执行所需要的每件东西，包括对所操作的程序结构的参考，与APT通讯并合作一同完成新文件的建立和警告/错误信息的传输。<br /><br />提供工厂类有两个方式：通过APT的“-factory”命令行参数提供，或者让工厂类在APT的发现过程中被自动定位（关于发现过程详细介绍请看<a href="http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html" target="_new"><font color="#002c99">http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html</font></a>）。前者对于一个已知的factory来讲是一种主动而又简单的方式；而后者则是需要在jar文件的META-INF/services目录中提供一个特定的发现路径：<br />在包含factory类的jar文件中作以下的操作：在META-INF/services目录中建立一个名为com.sun.mirror.apt.AnnotationProcessorFactory 的UTF-8编码文件，在文件中写入所有要使用到的factory类全名，每个类为一个单独行。<br /><br /><span style="COLOR: blue">4．一个简单的APT实例分析：</span><br /><span style="COLOR: green">A．实例构成：</span><br />Review类：定义Review Annotation；<br />ReviewProcessorFactory类：生成ReviewProcessor的工厂类；<br />ReviewProcessor类：定义处理Review annotation的Processor；<br />ReviewDeclarationVisitor类：定义Review annotation声明访问者，ReviewProcessor将要使用之对Class进行访问。<br />runapt.bat：定义了使用自定义的ReviewProcessor对Review类源代码文件进行处理的APT命令行。<br /><br /><span style="COLOR: green">B．Review类：</span><br /><strong>清单7：</strong><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation.apt;<br /><br />/**<br /> * 定义Review Annotation<br /> * @author cleverpig<br /> *<br /> */<br />public @interface Review {<br />        public static enum TypeEnum{EXCELLENT,NICE,NORMAL,BAD};<br />        TypeEnum type();<br />        String name() default "Review";<br />}<br /></pre><br /><br /><span style="COLOR: green">C．ReviewProcessorFactory类：</span><br /><strong>清单8：</strong><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation.apt;<br /><br />import java.util.Collection;<br />import java.util.Set;<br />import java.util.Arrays;<br />import com.sun.mirror.apt.*;<br />import com.sun.mirror.declaration.AnnotationTypeDeclaration;<br />import com.sun.mirror.apt.AnnotationProcessorEnvironment;<br />//请注意为了方便，使用了静态import<br />import static java.util.Collections.unmodifiableCollection;<br />import static java.util.Collections.emptySet;<br /><br />/**<br /> * 生成ReviewProcessor的工厂类<br /> * @author cleverpig<br /> *<br /> */<br />public class ReviewProcessorFactory implements AnnotationProcessorFactory{<br />        /**<br />         * 获得针对某个（些）类型声明定义的Processor<br />         * @param atds 类型声明集合<br />         * @param env processor环境<br />         */<br />        public AnnotationProcessor getProcessorFor(<br />                        Set&lt;AnnotationTypeDeclaration&gt; atds, <br />                        AnnotationProcessorEnvironment env){<br />                return new ReviewProcessor(env);<br />        }<br />        /**<br />         * 定义processor所支持的annotation类型<br />         * @return processor所支持的annotation类型的集合<br />         */<br />        public Collection&lt;String&gt;         supportedAnnotationTypes(){<br />                //“*”表示支持所有的annotation类型<br />                //当然也可以修改为“foo.bar.*”、“foo.bar.Baz”，来对所支持的类型进行修饰<br />            return unmodifiableCollection(Arrays.asList("*"));<br />    }<br />        <br />        /**<br />         * 定义processor支持的选项<br />         * @return processor支持选项的集合<br />         */<br />        public Collection&lt;String&gt;         supportedOptions(){<br />                //返回空集合<br />            return emptySet();<br />    }<br />        <br />        public static void main(String[] argv){<br />                System.out.println("ok");<br />        }<br />}<br /></pre><br /><br /><span style="COLOR: green">D．ReviewProcessor类：</span><br /><strong>清单9：</strong><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation.apt;<br /><br />import com.sun.mirror.apt.AnnotationProcessor;<br />import com.sun.mirror.apt.AnnotationProcessorEnvironment;<br />import com.sun.mirror.declaration.TypeDeclaration;<br />import com.sun.mirror.util.DeclarationVisitors;<br />import com.sun.mirror.util.DeclarationVisitor;<br /><br />/**<br /> * 定义Review annotation的Processor<br /> * @author cleverpig<br /> *<br /> */<br />public class ReviewProcessor implements AnnotationProcessor{<br />        //Processor所工作的环境<br />        AnnotationProcessorEnvironment env=null;<br />        <br />        /**<br />         * 构造方法<br />         * @param env 传入processor环境<br />         */<br />        public ReviewProcessor(AnnotationProcessorEnvironment env){<br />                this.env=env;<br />        }<br />        <br />        /**<br />         * 处理方法：查询processor环境中的类型声明，<br />         */<br />        public void process(){<br />                //查询processor环境中的类型声明<br />                for(TypeDeclaration type:env.getSpecifiedTypeDeclarations()){<br />                        //返回对类进行扫描、访问其声明时使用的DeclarationVisitor，<br />                        //传入参数：new ReviewDeclarationVisitor()，为扫描开始前进行的对类声明的处理<br />                        //        DeclarationVisitors.NO_OP，表示在扫描完成时进行的对类声明不做任何处理<br />                        DeclarationVisitor visitor=DeclarationVisitors.getDeclarationScanner(<br />                                        new ReviewDeclarationVisitor(),DeclarationVisitors.NO_OP);<br />                        //应用DeclarationVisitor到类型<br />                        type.accept(visitor);<br />                }<br />        }<br />}<br /></pre><br /><br /><span style="COLOR: green">E．ReviewDeclarationVisitor类：</span><br /><strong>清单10：</strong><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation.apt;<br /><br />import com.sun.mirror.util.*;<br />import com.sun.mirror.declaration.*;<br /><br />/**<br /> * 定义Review annotation声明访问者<br /> * @author cleverpig<br /> *<br /> */<br />public class ReviewDeclarationVisitor extends SimpleDeclarationVisitor{<br />        /**<br />         * 定义访问类声明的方法：打印类声明的全名<br />         * @param cd 类声明对象<br />         */<br />        public void visitClassDeclaration(ClassDeclaration cd){<br />                System.out.println("获取Class声明:"+cd.getQualifiedName());<br />        }<br />        <br />        public void visitAnnotationTypeDeclaration(AnnotationTypeDeclaration atd){<br />                System.out.println("获取Annotation类型声明:"+atd.getSimpleName());<br />        }<br />        <br />        public void visitAnnotationTypeElementDeclaration(AnnotationTypeElementDeclaration aed){<br />                System.out.println("获取Annotation类型元素声明:"+aed.getSimpleName());<br />        }<br />}<br /></pre><br /><br /><span style="COLOR: green">F．runapt.bat文件内容如下：</span><br /><strong>清单11：</strong><br /><pre class="overflow"><br />E:<br />rem 项目根目录<br />set PROJECT_ROOT=E:\eclipse3.1RC3\workspace\tigerFeaturePractice<br />rem 包目录路径<br />set PACKAGEPATH=com\bjinfotech\practice\annotation\apt<br />rem 运行根路径<br />set RUN_ROOT=%PROJECT_ROOT%\build<br />rem 源文件所在目录路径<br />set SRC_ROOT=%PROJECT_ROOT%\test<br />rem 设置Classpath<br />set CLASSPATH=.;%JAVA_HOME%;%JAVA_HOME%/lib/tools.jar;%RUN_ROOT%<br /><br />cd %SRC_ROOT%\%PACKAGEPATH%<br />apt -nocompile -factory com.bjinfotech.practice.annotation.apt.ReviewProcessorFactory  ./*.java<br /></pre><br /><br /><span style="COLOR: blue">四、参考资源：</span><br /><a href="http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html" target="_new"><font color="#002c99">http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html</font></a><br />作者的Blog:<a href="http://blog.matrix.org.cn/page/cleverpig" target="_new"><font color="#002c99">http://blog.matrix.org.cn/page/cleverpig</font></a><br /><br /><br /><span style="COLOR: blue">五、源代码下载：</span><br />[<a href="http://www.matrix.org.cn/resource/article/44/resource/upload/forum/2005_12_21_001420_nPNcNUHcHB.rar"><font color="#002c99">下载文件</font></a>]<br /><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/93046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-01-11 08:27 <a href="http://www.blogjava.net/wuxufeng8080/articles/93046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Annotation手册</title><link>http://www.blogjava.net/wuxufeng8080/articles/93045.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 11 Jan 2007 00:26:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/93045.html</guid><description><![CDATA[
		<span style="COLOR: red">版权声明：本文可以自由转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明</span>
		<br />作者:cleverpig(作者的Blog:<a href="http://blog.matrix.org.cn/page/cleverpig" target="_new">http://blog.matrix.org.cn/page/cleverpig</a>)<br />原文:<a href="http://www.matrix.org.cn/resource/article/44/44055_Java+Annotation+Reflect.html" target="_new">http://www.matrix.org.cn/resource/article/44/44055_Java+Annotation+Reflect.html</a><br />关键字:java,annotation,reflect<br /><br /><span style="COLOR: blue">前言：</span><br />在上篇文章<a href="http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html" target="_new">《Java Annotation入门》</a>中概要性的介绍了Annotation的定义、使用，范围涵盖较广，但是深度不够。所以作者在《Java Annotation入门》后，继续整理了Annotation的概念和知识点，与喜欢research的朋友们共享。<br /><br /><span style="COLOR: red">阅读提示：文中提到的程序成员或者程序元素是一个概念，指组成程序代码的单元：如类、方法、成员变量。</span><br /><br /><span style="COLOR: blue">一、Annotation究竟是什么？</span><br /><br />Annotation提供了一条与程序元素关联任何信息或者任何元数据（metadata）的途径。从某些方面看，annotation就像修饰符一样被使用，并应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在annotation的“name=value”结构对中。annotation类型是一种接口，能够通过java反射API的方式提供对其信息的访问。<br /><br />annotation能被用来为某个程序元素（类、方法、成员变量等）关联任何的信息。需要注意的是，这里存在着一个基本的潜规则：annotaion不能影响程序代码的执行，无论增加、删除annotation，代码都始终如一的执行。另外，尽管一些annotation通过java的反射api方法在运行时被访问，而java语言解释器在工作时忽略了这些annotation。正是由于java虚拟机忽略了annotation，导致了annotation类型在代码中是“不起作用”的；只有通过某种配套的工具才会对annotation类型中的信息进行访问和处理。本文中将涵盖标准的annotation和meta-annotation类型，陪伴这些annotation类型的工具是java编译器（当然要以某种特殊的方式处理它们）。<br /><br />由于上述原因，annotation在使用时十分简便。一个本地变量可以被一个以NonNull命名的annotation类型所标注，来作为对这个本地变量不能被赋予null值的断言。而我们可以编写与之配套的一个annotation代码分析工具，使用它来对具有前面变量的代码进行解析，并且尝试验证这个断言。当然这些代码并不必自己编写。在JDK安装后，在JDK/bin目录中可以找到名为“apt”的工具，它提供了处理annotation的框架：它启动后扫描源代码中的annotation，并调用我们定义好的annotation处理器完成我们所要完成的工作（比如验证前面例子中的断言）。说到这里，annotation的强大功能似乎可以替代XDoclet这类的工具了，随着我们的深入，大家会更加坚信这一点。<br />注：详细描述请参看jsr250规范：<br /><a href="http://www.jcp.org/aboutJava/communityprocess/pfd/jsr250/" target="_new">http://www.jcp.org/aboutJava/communityprocess/pfd/jsr250/</a><br /><br /><span style="COLOR: blue">二、Annotation的定义：</span><br /><br />这段文字开始介绍annotation相关技术。在此大家将看到java5.0的标准annotation类型，这种标准类型就是前文中所说的“内建”类型，它们可以直接被javac支持。可喜的是，在java6.0beta版中的javac已经加入了对自定义annotation的支持。<br /><br /><span style="COLOR: blue">1。Annotation的概念和语法：</span><br /><br />首先，关键的概念是理解annotation是与一个程序元素相关联信息或者元数据的标注。它从不影响java程序的执行，但是对例如编译器警告或者像文档生成器等辅助工具产生影响。<br /><br />下面是常用的annotation列表，我们应该注意在annotation和annotation类型之间的不同：<br /><br /><span style="COLOR: green">A.annotation：</span><br />annotation使用了在java5.0所带来的新语法，它的行为十分类似public、final这样的修饰符。每个annotation具有一个名字和成员个数&gt;=0。每个annotation的成员具有被称为name=value对的名字和值（就像javabean一样），name=value装载了annotation的信息。<br /><br /><span style="COLOR: green">B.annotation类型：</span><br />annotation类型定义了annotation的名字、类型、成员默认值。一个annotation类型可以说是一个特殊的java接口，它的成员变量是受限制的，而声明annotation类型时需要使用新语法。当我们通过java反射api访问annotation时，返回值将是一个实现了该annotation类型接口的对象，通过访问这个对象我们能方便的访问到其annotation成员。后面的章节将提到在java5.0的java.lang包里包含的3个标准annotation类型。<br /><br /><span style="COLOR: green">C.annotation成员：</span><br />annotation的成员在annotation类型中以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。在此有一个特定的默认语法：允许声明任何annotation成员的默认值：一个annotation可以将name=value对作为没有定义默认值的annotation成员的值，当然也可以使用name=value对来覆盖其它成员默认值。这一点有些近似类的继承特性，父类的构造函数可以作为子类的默认构造函数，但是也可以被子类覆盖。<br /><br /><span style="COLOR: green">D.marker annotation类型：</span><br />一个没有成员定义的annotation类型被称为marker annotation。这种annotation类型仅使用自身的存在与否来为我们提供信息。如后面要说的Override。<br /><br /><span style="COLOR: green">E.meta-annotation：</span><br />meta-annotation也称为元annotation，它是被用来声明annotation类型的annotation。Java5.0提供了一些标准的元-annotation类型。下面介绍的target、retention就是meta-annotation。<br /><br /><span style="COLOR: green">F.target：</span><br />annotation的target是一个被标注的程序元素。target说明了annotation所修饰的对象范围：annotation可被用于packages、types（类、接口、枚举、annotation类型）、类型成员（方法、构造方法、成员变量、枚举值）、方法参数和本地变量（如循环变量、catch参数）。在annotation类型的声明中使用了target可更加明晰其修饰的目标。<br /><br /><span style="COLOR: green">G.retention：</span><br />annotation的retention定义了该annotation被保留的时间长短：某些annotation仅出现在源代码中，而被编译器丢弃；而另一些却被编译在class文件中；编译在class文件中的annotation可能会被虚拟机忽略，而另一些在class被装载时将被读取（请注意并不影响class的执行，因为annotation与class在使用上是被分离的）。使用这个meta-annotation可以对annotation的“生命周期”限制。<br /><br /><span style="COLOR: green">H.metadata：</span><br />由于metadata被广泛使用于各种计算机开发过程中，所以当我们在这里谈论的metadata即元数据通常指被annotation装载的信息或者annotation本身。<br /><br /><span style="COLOR: blue">2。使用标准Annotation：</span><br />java5.0在java.lang包中定义了3种标准的annotation类型：<br /><br /><span style="COLOR: green">A.Override：</span><br />java.lang.Override是一个marker annotation类型，它被用作标注方法。它说明了被标注的方法重载了父类的方法，起到了断言的作用。如果我们使用了这种annotation在一个没有覆盖父类方法的方法时，java编译器将以一个编译错误来警示。<br />这个annotaton常常在我们试图覆盖父类方法而确又写错了方法名时发挥威力。<br /><br />使用方法极其简单：在使用此annotation时只要在被修饰的方法前面加上@Override。<br />下面的代码是一个使用@Override修饰一个企图重载父类的toString方法，而又存在拼写错误的sample：<br /><b>清单1：</b><br /><pre class="overflow"><br />@Override<br />public String toSting() {   // 注意方法名拼写错了<br />    return "[" + super.toString() + "]";<br />}<br /></pre><br /><br /><span style="COLOR: green">B.Deprecated：</span><br />同样Deprecated也是一个marker annotation。当一个类型或者类型成员使用@Deprecated修饰的话，编译器将不鼓励使用这个被标注的程序元素。而且这种修饰具有一定的“延续性”：如果我们在代码中通过继承或者覆盖的方式使用了这个过时的类型或者成员，虽然继承或者覆盖后的类型或者成员并不是被声明为@Deprecated，但编译器仍然要报警。<br />值得注意，@Deprecated这个annotation类型和javadoc中的@deprecated这个tag是有区别的：前者是java编译器识别的，而后者是被javadoc工具所识别用来生成文档（包含程序成员为什么已经过时、它应当如何被禁止或者替代的描述）。<br />在java5.0，java编译器仍然象其从前版本那样寻找@deprecated这个javadoc tag，并使用它们产生警告信息。但是这种状况将在后续版本中改变，我们应在现在就开始使用@Deprecated来修饰过时的方法而不是@deprecated javadoc tag。<br /><b>清单2：</b><br /><pre class="overflow"><br />下面是一段使用@Deprecated的代码：<br />/**<br /> * 这里是javadoc的@deprecated声明.<br /> * @deprecated No one has players for this format any more.  Use VHS instead.<br /> */<br />@Deprecated public class Betamax { ... }<br /></pre><br /><br /><span style="COLOR: green">C.SuppressWarnings：</span><br />@SuppressWarnings被用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告。在java5.0，sun提供的javac编译器为我们提供了-Xlint选项来使编译器对合法的程序代码提出警告，此种警告从某种程度上代表了程序错误。例如当我们使用一个generic collection类而又没有提供它的类型时，编译器将提示出"unchecked warning"的警告。<br /><br />通常当这种情况发生时，我们就需要查找引起警告的代码。如果它真的表示错误，我们就需要纠正它。例如如果警告信息表明我们代码中的switch语句没有覆盖所有可能的case，那么我们就应增加一个默认的case来避免这种警告。<br />相仿，有时我们无法避免这种警告，例如，我们使用必须和非generic的旧代码交互的generic collection类时，我们不能避免这个unchecked warning。此时@SuppressWarning就要派上用场了，在调用的方法前增加@SuppressWarnings修饰，告诉编译器停止对此方法的警告。<br />SuppressWarning不是一个marker annotation。它有一个类型为String[]的成员，这个成员的值为被禁止的警告名。对于javac编译器来讲，被-Xlint选项有效的警告名也同样对@SuppressWarings有效，同时编译器忽略掉无法识别的警告名。<br /><br />annotation语法允许在annotation名后跟括号，括号中是使用逗号分割的name=value对用于为annotation的成员赋值：<br /><b>清单3：</b><br /><pre class="overflow"><br />@SuppressWarnings(value={"unchecked","fallthrough"})<br />public void lintTrap() { /* sloppy method body omitted */ }<br /></pre><br /><br />在这个例子中SuppressWarnings annotation类型只定义了一个单一的成员，所以只有一个简单的value={...}作为name=value对。又由于成员值是一个数组，故使用大括号来声明数组值。<br /><br />注意：我们可以在下面的情况中缩写annotation：当annotation只有单一成员，并成员命名为"value="。这时可以省去"value="。比如将上面的SuppressWarnings annotation进行缩写：<br /><b>清单4：</b><br /><pre class="overflow"><br />@SuppressWarnings({"unchecked","fallthrough"})<br /></pre><br />如果SuppressWarnings所声明的被禁止警告个数为一个时，可以省去大括号：<br /><pre class="overflow"><br />@SuppressWarnings("unchecked")<br /></pre><br /><br /><span style="COLOR: blue">3。Annotation语法：</span><br /><br />在上一个章节中，我们看到书写marker annotation和单一成员annotation的语法。下面本人来介绍一下完整的语法：<br /><br />annotation由“@+annotation类型名称+(..逗号分割的name-value对...)”组成。其中成员可以按照任何的顺序。如果annotation类型定义了某个成员的默认值，则这个成员可以被省略。成员值必须为编译时常量、内嵌的annotation或者数组。<br /><br />下面我们将定义一个annotation类型名为Reviews，它有一个由@Review annotation数组构成的成员。这个@Review annotation类型有三个成员："reviewer"是一个字符串，"comment" 是一个具有默认值的可选的字符串，"grade"是一个Review.Grade枚举类型值。<br /><b>清单5：</b><br /><pre class="overflow"><br />@Reviews({  // Single-value annotation, so "value=" is omitted here<br />    @Review(grade=Review.Grade.EXCELLENT,<br />            reviewer="df"),<br />    @Review(grade=Review.Grade.UNSATISFACTORY,<br />            reviewer="eg",<br />            comment="This method needs an @Override annotation")<br />})<br /></pre><br />annotation语法的另一个重要规则是没有程序成员可以有多于一个的同一annotation实例。例如在一个类中简单的放置多个@Review annotation。这也是在上面代码中定义@Reviews annotation类型数组的原因。<br /><br /><span style="COLOR: blue">4。Annotation成员类型和值：</span><br /><br />annotation成员必须是非空的编译时常量表达式。可用的成员类型为：primitive类型、, String, Class, enumerated类型, annotation类型, 和前面类型的数组。<br /><br />下面我们定义了一个名为UncheckedExceptions 的annotation类型，它的成员是一个扩展了RuntimeException类的类数组。<br /><b>清单6：</b><br /><pre class="overflow"><br />@UncheckedExceptions({<br />    IllegalArgumentException.class, StringIndexOutOfBoundsException.class<br />})<br /></pre><br /><br /><span style="COLOR: blue">5。Annotation的目标：</span><br /><br />annotation通常被放在类型定义和成员定义的前面。然而它也出现在package、方法参数、本地变量的前面。下面，我们来讨论一下这些不大常用的写法：<br /><br />package annotation出现在package声明的前面。<br />下面的例子package-info.java中不包含任何的公共类型定义，却包含一个可选的javadoc注释。<br /><b>清单7：</b><br /><pre class="overflow"><br />/**<br /> * This package holds my custom annotation types.<br /> */<br />@com.davidflanagan.annotations.Author("David Flanagan")<br />package com.davidflanagan.annotations;<br /></pre><br />当package-info.java文件被编译时，它将产生名为包含annotation（特殊的接口）声明的package-info.class的类。这个接口没有成员，它的名字package-info不是一个合法的java标识，所以它不能用在java源代码中。这个接口的存在只是简单的被看作一个为package annotation准备的占位符。<br /><br />用于修饰方法参数、catch参数、本地变量的annotation只是简单的出现在这些程序成员的修饰符位置。java类文件格式没有为本地变量或者catch参数存储annotation作准备，所以这些annotation总是保留在源代码级别（source retention）；方法参数annotation能够保存在类文件中，也可以在保留到运行时。<br /><br />最后，请注意，枚举类型定义中不允许任何的修饰符修饰其枚举值。<br /><br /><span style="COLOR: blue">6。Annotation和默认值：</span><br />在Annotation中，没有默认值的成员必须有一个成员值。而如何理解默认值是如何被处理就是一个很重要的细节：annotation类型所定义的成员默认值被存储在class文件中，不被编译到annotation里面。如果我们修改一个annotation类型使其成员的默认值发生了改变，这个改变对于所有此类型的annotation中没有明确提供成员值的成员产生影响（即修改了该成员的成员值）。即使在annotation类型使其成员的默认值被改变后annotation从没被重新编译过，该类型的annotation(改变前已经被编译的)也受到影响。<br /><br /><span style="COLOR: blue">三、Annotation工作原理：</span><br /><br /><span style="COLOR: blue">Annotation与反射</span><br />在java5.0中Java.lang.reflect提供的反射API被扩充了读取运行时annotation的能力。让我们回顾一下前面所讲的：一个annotation类型被定义为runtime retention后，它才是在运行时可见，当class文件被装载时被保存在class文件中的annotation才会被虚拟机读取。那么reflect是如何帮助我们访问class中的annotation呢？<br /><br />下文将在java.lang.reflect用于annotation的新特性，其中java.lang.reflect.AnnotatedElement是重要的接口，它代表了提供查询annotation能力的程序成员。这个接口被java.lang.Package、java.lang.Class实现，并间接地被Method类、Constructor类、java.lang.reflect的Field类实现。而annotation中的方法参数可以通过Method类、Constructor类的getParameterAnnotations()方法获得。<br /><br />下面的代码使用了AnnotatedElement类的isAnnotationPresent()方法判断某个方法是否具有@Unstable annotation，从而断言此方法是否稳定：<br /><b>清单8：</b><br /><pre class="overflow"><br />import java.lang.reflect.*;<br /><br />Class c = WhizzBangClass.class;                           <br />Method m = c.getMethod("whizzy", int.class, int.class);  <br />boolean unstable = m.isAnnotationPresent(Unstable.class);<br /></pre><br />isAnnotationPresent()方法对于检查marker annotation是十分有用的，因为marker annotation没有成员变量，所以我们只要知道class的方法是否使用了annotation修饰就可以了。而当处理具有成员的annotation时，我们通过使用getAnnotation()方法来获得annotation的成员信息（成员名称、成员值）。这里我们看到了一套优美的java annotation系统：如果annotation存在，那么实现了相应的annotation类型接口的对象将被getAnnotation()方法返回，接着调用定义在annotation类型中的成员方法可以方便地获得任何成员值。<br /><br />回想一下，前面介绍的@Reviews annotation，如果这个annotation类型被声明为runtime retention的话，我们通过下面的代码来访问@Reviews annotation的成员值：<br /><b>清单9：</b><br /><pre class="overflow"><br />AnnotatedElement target = WhizzBangClass.class; //获得被查询的AnnotatedElement<br />// 查询AnnotatedElement的@Reviews annotation信息<br />Reviews annotation = target.getAnnotation(Reviews.class);<br />// 因为@Reviews annotation类型的成员为@Review annotation类型的数组，<br />// 所以下面声明了Review[] reviews保存@Reviews annotation类型的value成员值。<br />Review[] reviews = annotation.value();<br />// 查询每个@Review annotation的成员信息<br />for(Review r : reviews) {<br />    Review.Grade grade = r.grade();<br />    String reviewer = r.reviewer();<br />    String comment = r.comment();<br />    System.out.printf("%s assigned a grade of %s and comment '%s'%n",<br />                      reviewer, grade, comment);<br />}<br /></pre><br /><br /><span style="COLOR: blue">四、如何自定义Annotation？</span><br /><br /><span style="COLOR: blue">1．详解annotation与接口的异同：</span><br />因为annotation类型是一个非凡的接口，所以两者之间存在着某些差异：<br /><br /><span style="COLOR: green">A.Annotation类型使用关键字@interface而不是interface。</span><br />这个关键字声明隐含了一个信息：它是继承了java.lang.annotation.Annotation接口，并非声明了一个interface。<br /><br /><span style="COLOR: green">B.Annotation类型、方法定义是独特的、受限制的。</span><br />Annotation类型的方法必须声明为无参数、无异常抛出的。这些方法定义了annotation的成员：方法名成为了成员名，而方法返回值成为了成员的类型。而方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用default和一个默认数值来声明成员的默认值，null不能作为成员默认值，这与我们在非annotation类型中定义方法有很大不同。<br />Annotation类型和它的方法不能使用annotation类型的参数、成员不能是generic。只有返回值类型是Class的方法可以在annotation类型中使用generic，因为此方法能够用类转换将各种类型转换为Class。<br /><br /><span style="COLOR: green">C.Annotation类型又与接口有着近似之处。</span><br />它们可以定义常量、静态成员类型（比如枚举类型定义）。Annotation类型也可以如接口一般被实现或者继承。<br /><br /><span style="COLOR: blue">2．实例：</span><br />下面，我们将看到如何定义annotation类型的example。它展示了annotation类型声明以及@interface与interface之间的不同：<br /><b>清单10：</b><br /><pre class="overflow"><br />package com.davidflanagan.annotations;<br />import java.lang.annotation.*;<br /><br />/**<br /> * 使用annotation来描述那些被标注的成员是不稳定的，需要更改<br />*/<br />@Retention(RetentionPolicy.RUNTIME)<br />public @interface Unstable {}<br /></pre><br /><br />下面的另一个example只定义了一个成员。并通过将这个成员命名为value，使我们可以方便的使用这种annotation的快捷声明方式：<br /><b>清单11：</b><br /><pre class="overflow"><br />/**<br /> * 使用Author这个annotation定义在程序中指出代码的作者<br /> */<br />public @interface Author {<br />    /** 返回作者名 */<br />    String value();<br />}<br /></pre><br /><br />以下的example更加复杂。Reviews annotation类型只有一个成员，但是这个成员的类型是复杂的：由Review annotation组成的数组。Review annotation类型有3个成员：枚举类型成员grade、表示Review名称的字符串类型成员Reviewer、具有默认值的字符串类型成员Comment。<br /><b>清单12：</b><br /><pre class="overflow"><br />import java.lang.annotation.*;<br />        <br />/**<br /> * Reviews annotation类型只有一个成员，<br /> * 但是这个成员的类型是复杂的：由Review annotation组成的数组<br /> */<br />@Retention(RetentionPolicy.RUNTIME)<br />public @interface Reviews {<br />    Review[] value();<br />}<br /><br />/**<br />* Review annotation类型有3个成员： <br />* 枚举类型成员grade、<br />  * 表示Review名称的字符串类型成员Reviewer、<br />  * 具有默认值的字符串类型成员Comment。<br /> */<br />public @interface Review {<br />    // 内嵌的枚举类型<br />    public static enum Grade { EXCELLENT, SATISFACTORY, UNSATISFACTORY };<br /><br />    // 下面的方法定义了annotation的成员<br />    Grade grade();                <br />    String reviewer();          <br />    String comment() default "";  <br />}<br /></pre><br /><br />最后，我们来定义一个annotation方法用于罗列出类运行中所有的unchecked异常（上文已经提到这种情况不一定是错误）。这个annotation类型将一个数组作为了唯一的成员。数组中的每个元素都是异常类。为了加强对未检查的异常（此类异常都是在运行时抛出）进行报告，我们可以在代码中对异常的类型进行限制：<br /><b>清单13：</b><br /><pre class="overflow"><br />public @interface UncheckedExceptions {<br />    Class&lt;? extends RuntimeException&gt;[] value();<br />}<br /></pre><br /><br /><span style="COLOR: blue">五、Meta-Annotation</span><br /><br />Annotation类型可以被它们自己所标注。Java5.0定义了4个标准的meta-annotation类型，它们被用来提供对其它annotation类型作说明。这些类型和它们所支持的类在java.lang.annotation包中可以找到。如果需要更详细的信息可以参考jdk5.0手册。<br /><br /><span style="COLOR: blue">1．再谈Target</span><br />作为meta-annotation类型的Target,它描述了annotation所修饰的程序成员的类型。当一个annotation类型没有Target时，它将被作为普通的annotation看待。当将它修饰一个特定的程序成员时，它将发挥其应用的作用，例如：Override用于修饰方法时，增加了@Target这个meta-annotation就使编译器对annotation作检查，从而去掉修饰错误类型的Override。<br /><br />Target meta-annotation类型有唯一的value作为成员。这个成员的类型是java.lang.annotation.ElementType[]类型的，ElementType类型是可以被标注的程序成员的枚举类型。<br /><br /><span style="COLOR: blue">2．Retention的用法</span><br />我们在文章的开头曾经提到过Retention，但是没有详细讲解。Retention描述了annotation是否被编译器丢弃或者保留在class文件；如果保留在class文件中，是否在class文件被装载时被虚拟机读取。默认情况下，annotation被保存在class文件中，但在运行时并不能被反射访问。Retention具有三个取值：source、class、runtime，这些取值来自java.lang.annotation.RetentionPolicy的枚举类型值。<br /><br />Retention meta-annotation类型有唯一的value作为成员，它的取值来自java.lang.annotation.RetentionPolicy的枚举类型值。<br /><br /><span style="COLOR: blue">3．Documented</span><br />Documented是一个meta-annotation类型，用于描述其它类型的annotation应该被作为被标注的程序成员的公共API，因此可以被例如javadoc此类的工具文档化。<br /><br />Documented是一个marker annotation，没有成员。<br /><br /><span style="COLOR: blue">4．Inherited</span><br />@Inherited meta-annotation也是一个marker annotation，它阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class，则这个annotation将被用于该class的子类。<br /><br />注意：@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation，方法并不从它所重载的方法继承annotation。<br /><br />值得思考的是，当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME，则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时，反射代码检查将展开工作：检查class和其父类，直到发现指定的annotation类型被发现，或者到达类继承结构的顶层。<br /><br /><span style="COLOR: blue">六、总结：</span><br /><br />本文几乎覆盖了所有的Annotation的概念和知识点，从annotation的定义、语法到工作原理、如何自定义annotation，直至meta-annotation。其中也具有一些配套的代码片断可参考，虽然不是很多，但是可谓言简意赅、着其重点，本人认为用好annotation的关键还在于使用。希望本手册能够帮助大家用好annotation，这也是本人的最大快乐。<br /><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/93045.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-01-11 08:26 <a href="http://www.blogjava.net/wuxufeng8080/articles/93045.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Annotation入门</title><link>http://www.blogjava.net/wuxufeng8080/articles/93044.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 11 Jan 2007 00:25:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/93044.html</guid><description><![CDATA[
		<span style="COLOR: red">版权声明：本文可以自由转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明</span>
		<br />作者:cleverpig(作者的Blog:<a href="http://blog.matrix.org.cn/page/cleverpig" target="_new">http://blog.matrix.org.cn/page/cleverpig</a>)<br />原文:[http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html]http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html[/url]<br />关键字:Java,annotation,标注<br /><br /><br /><span style="COLOR: blue">摘要：</span><br />本文针对java初学者或者annotation初次使用者全面地说明了annotation的使用方法、定义方式、分类。初学者可以通过以上的说明制作简单的annotation程序，但是对于一些高级的annotation应用（例如使用自定义annotation生成javabean映射xml文件）还需要进一步的研究和探讨。涉及到深入annotation的内容，作者将在后文《Java Annotation高级应用》中谈到。<br /><br />同时，annotation运行存在两种方式：运行时、编译时。上文中讨论的都是在运行时的annotation应用，但在编译时的annotation应用还没有涉及，<br /><br /><span style="COLOR: blue">一、为什么使用Annotation：</span><br /><br />在JAVA应用中，我们常遇到一些需要使用模版代码。例如，为了编写一个JAX-RPC web service，我们必须提供一对接口和实现作为模版代码。如果使用annotation对远程访问的方法代码进行修饰的话，这个模版就能够使用工具自动生成。<br />另外，一些API需要使用与程序代码同时维护的附属文件。例如，JavaBeans需要一个BeanInfo Class与一个Bean同时使用/维护，而EJB则同样需要一个部署描述符。此时在程序中使用annotation来维护这些附属文件的信息将十分便利而且减少了错误。<br /><br /><span style="COLOR: blue">二、Annotation工作方式：</span><br /><br />在5.0版之前的Java平台已经具有了一些ad hoc annotation机制。比如，使用transient修饰符来标识一个成员变量在序列化子系统中应被忽略。而@deprecated这个javadoc tag也是一个ad hoc annotation用来说明一个方法已过时。从Java5.0版发布以来，5.0平台提供了一个正式的annotation功能：允许开发者定义、使用自己的annoatation类型。此功能由一个定义annotation类型的语法和一个描述annotation声明的语法，读取annotaion的API，一个使用annotation修饰的class文件，一个annotation处理工具（apt）组成。<br />annotation并不直接影响代码语义，但是它能够工作的方式被看作类似程序的工具或者类库，它会反过来对正在运行的程序语义有所影响。annotation可以从源文件、class文件或者以在运行时反射的多种方式被读取。<br />当然annotation在某种程度上使javadoc tag更加完整。一般情况下，如果这个标记对java文档产生影响或者用于生成java文档的话，它应该作为一个javadoc tag；否则将作为一个annotation。<br /><br /><span style="COLOR: blue">三、Annotation使用方法：</span><br /><br /><b>1。类型声明方式：</b><br />通常，应用程序并不是必须定义annotation类型，但是定义annotation类型并非难事。Annotation类型声明于一般的接口声明极为类似，区别只在于它在interface关键字前面使用“@”符号。<br />annotation类型的每个方法声明定义了一个annotation类型成员，但方法声明不必有参数或者异常声明；方法返回值的类型被限制在以下的范围：primitives、String、Class、enums、annotation和前面类型的数组；方法可以有默认值。<br /><br />下面是一个简单的annotation类型声明：<br /><b>清单1:</b><br /><pre class="overflow"><br />    /**<br />     * Describes the Request-For-Enhancement(RFE) that led<br />     * to the presence of the annotated API element.<br />     */<br />    public @interface RequestForEnhancement {<br />        int    id();<br />        String synopsis();<br />        String engineer() default "[unassigned]"; <br />        String date();    default "[unimplemented]"; <br />    }<br /></pre><br />代码中只定义了一个annotation类型RequestForEnhancement。<br /><br /><b>2。修饰方法的annotation声明方式：</b><br />annotation是一种修饰符，能够如其它修饰符（如public、static、final）一般使用。习惯用法是annotaions用在其它的修饰符前面。annotations由“@+annotation类型+带有括号的成员-值列表”组成。这些成员的值必须是编译时常量（即在运行时不变）。<br /><br />A：下面是一个使用了RequestForEnhancement annotation的方法声明：<br /><b>清单2:</b><br /><pre class="overflow"><br />    @RequestForEnhancement(<br />        id       = 2868724,<br />        synopsis = "Enable time-travel",<br />        engineer = "Mr. Peabody",<br />        date     = "4/1/3007"<br />    )<br />    public static void travelThroughTime(Date destination) { ... }<br /></pre><br /><br />B：当声明一个没有成员的annotation类型声明时，可使用以下方式：<br /><b>清单3:</b><br /><pre class="overflow"><br />    /**<br />     * Indicates that the specification of the annotated API element<br />     * is preliminary and subject to change.<br />     */<br />    public @interface Preliminary { }<br /></pre><br /><br />作为上面没有成员的annotation类型声明的简写方式：<br /><b>清单4:</b><br /><pre class="overflow"><br />    @Preliminary public class TimeTravel { ... }<br /></pre><br /><br />C：如果在annotations中只有唯一一个成员，则该成员应命名为value：<br /><b>清单5:</b><br /><pre class="overflow"><br />    /**<br />     * Associates a copyright notice with the annotated API element.<br />     */<br />    public @interface Copyright {<br />        String value();<br />    }<br /></pre><br /><br />更为方便的是对于具有唯一成员且成员名为value的annotation（如上文），在其使用时可以忽略掉成员名和赋值号（=）：<br /><b>清单6:</b><br /><pre class="overflow"><br />    @Copyright("2002 Yoyodyne Propulsion Systems")<br />    public class OscillationOverthruster { ... }<br /></pre><br /><br /><b>3。一个使用实例：</b><br />结合上面所讲的，我们在这里建立一个简单的基于annotation测试框架。首先我们需要一个annotation类型来表示某个方法是一个应该被测试工具运行的测试方法。<br /><b>清单7:</b><br /><pre class="overflow"><br />    import java.lang.annotation.*;<br /><br />    /**<br />     * Indicates that the annotated method is a test method.<br />     * This annotation should be used only on parameterless static methods.<br />     */<br />    @Retention(RetentionPolicy.RUNTIME)<br />    @Target(ElementType.METHOD)<br />    public @interface Test { }<br /></pre><br /><br />值得注意的是annotaion类型声明是可以标注自己的，这样的annotation被称为“meta-annotations”。<br /><br />在上面的代码中，@Retention(RetentionPolicy.RUNTIME)这个meta-annotation表示了此类型的annotation将被虚拟机保留使其能够在运行时通过反射被读取。而@Target(ElementType.METHOD)表示此类型的annotation只能用于修饰方法声明。<br /><br />下面是一个简单的程序，其中部分方法被上面的annotation所标注：<br /><b>清单8:</b><br /><pre class="overflow"><br />    public class Foo {<br />        @Test public static void m1() { }<br />        public static void m2() { }<br />        @Test public static void m3() {<br />            throw new RuntimeException("Boom");<br />        }<br />        public static void m4() { }<br />        @Test public static void m5() { }<br />        public static void m6() { }<br />        @Test public static void m7() {<br />            throw new RuntimeException("Crash");<br />        }<br />        public static void m8() { }<br />    }<br /><br />Here is the testing tool:<br /><br />    import java.lang.reflect.*;<br /><br />    public class RunTests {<br />       public static void main(String[] args) throws Exception {<br />          int passed = 0, failed = 0;<br />          for (Method m : Class.forName(args[0]).getMethods()) {<br />             if (m.isAnnotationPresent(Test.class)) {<br />                try {<br />                   m.invoke(null);<br />                   passed++;<br />                } catch (Throwable ex) {<br />                   System.out.printf("Test %s failed: %s %n", m, ex.getCause());<br />                   failed++;<br />                }<br />             }<br />          }<br />          System.out.printf("Passed: %d, Failed %d%n", passed, failed);<br />       }<br />    }<br /></pre><br /><br />这个程序从命令行参数中取出类名，并且遍历此类的所有方法，尝试调用其中被上面的测试annotation类型标注过的方法。在此过程中为了找出哪些方法被annotation类型标注过，需要使用反射的方式执行此查询。如果在调用方法时抛出异常，此方法被认为已经失败，并打印一个失败报告。最后，打印运行通过/失败的方法数量。<br />下面文字表示了如何运行这个基于annotation的测试工具：<br /><br /><b>清单9:</b><br /><pre class="overflow"><br />    $ java RunTests Foo<br />    Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom <br />    Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash <br />    Passed: 2, Failed 2<br /></pre><br /><br /><span style="COLOR: blue">四、Annotation分类：</span><br /><br />根据annotation的使用方法和用途主要分为以下几类：<br /><br /><b>1。内建Annotation——Java5.0版在java语法中经常用到的内建Annotation：</b><br />@Deprecated用于修饰已经过时的方法；<br />@Override用于修饰此方法覆盖了父类的方法（而非重载）；<br />@SuppressWarnings用于通知java编译器禁止特定的编译警告。<br /><br />下面代码展示了内建Annotation类型的用法：<br /><b>清单10:</b><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation;<br /><br />/**<br /> * 演示如何使用java5内建的annotation<br /> * 参考资料：<br /> * http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html<br /> * http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html<br /> * http://mindprod.com/jgloss/annotations.html<br /> * @author cleverpig<br /> *<br /> */<br />import java.util.List;<br /><br />public class UsingBuiltInAnnotation {<br />        //食物类<br />        class Food{}<br />        //干草类<br />        class Hay extends Food{}<br />        //动物类<br />        class Animal{<br />                Food getFood(){<br />                        return null;<br />                }<br />                //使用Annotation声明Deprecated方法<br />                @Deprecated<br />                void deprecatedMethod(){<br />                }<br />        }<br />        //马类-继承动物类<br />        class Horse extends Animal{<br />                //使用Annotation声明覆盖方法<br />                @Override<br />                Hay getFood(){<br />                        return new Hay();<br />                }<br />                //使用Annotation声明禁止警告<br />                @SuppressWarnings({"deprecation","unchecked"})<br />                void callDeprecatedMethod(List horseGroup){<br />                        Animal an=new Animal();<br />                        an.deprecatedMethod();<br />                        horseGroup.add(an);<br />                }<br />        }<br />}<br /></pre><br /><br /><b>2。开发者自定义Annotation：由开发者自定义Annotation类型。</b><br />下面是一个使用annotation进行方法测试的sample：<br /><br />AnnotationDefineForTestFunction类型定义如下：<br /><b>清单11:</b><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation;<br /><br />import java.lang.annotation.*;<br />/**<br /> * 定义annotation<br /> * @author cleverpig<br /> *<br /> */<br />//加载在VM中，在运行时进行映射<br />@Retention(RetentionPolicy.RUNTIME)<br />//限定此annotation只能标示方法<br />@Target(ElementType.METHOD)<br />public @interface AnnotationDefineForTestFunction{}<br /></pre><br /><br />测试annotation的代码如下：<br /><br /><b>清单12:</b><br /><pre class="overflow"><br />package com.bjinfotech.practice.annotation;<br /><br />import java.lang.reflect.*;<br /><br />/**<br /> * 一个实例程序应用前面定义的Annotation：AnnotationDefineForTestFunction<br /> * @author cleverpig<br /> *<br /> */<br />public class UsingAnnotation {<br />        @AnnotationDefineForTestFunction public static void method01(){}<br />        <br />        public static void method02(){}<br />        <br />        @AnnotationDefineForTestFunction public static void method03(){<br />                throw new RuntimeException("method03");<br />        }<br />        <br />        public static void method04(){<br />                throw new RuntimeException("method04");<br />        }<br />        <br />        public static void main(String[] argv) throws Exception{<br />                int passed = 0, failed = 0;<br />                //被检测的类名<br />                String className="com.bjinfotech.practice.annotation.UsingAnnotation";<br />                //逐个检查此类的方法，当其方法使用annotation声明时调用此方法<br />            for (Method m : Class.forName(className).getMethods()) {<br />               if (m.isAnnotationPresent(AnnotationDefineForTestFunction.class)) {<br />                  try {<br />                     m.invoke(null);<br />                     passed++;<br />                  } catch (Throwable ex) {<br />                     System.out.printf("测试 %s 失败: %s %n", m, ex.getCause());<br />                     failed++;<br />                  }<br />               }<br />            }<br />            System.out.printf("测试结果： 通过: %d, 失败： %d%n", passed, failed);<br />        }<br />}<br /></pre><br /><br /><b>3。使用第三方开发的Annotation类型</b><br />这也是开发人员所常常用到的一种方式。比如我们在使用Hibernate3.0时就可以利用Annotation生成数据表映射配置文件，而不必使用Xdoclet。<br /><br /><span style="COLOR: blue">五、总结：</span><br /><br />1。前面的文字说明了annotation的使用方法、定义方式、分类。初学者可以通过以上的说明制作简单的annotation程序，但是对于一些高级的annotation应用（例如使用自定义annotation生成javabean映射xml文件）还需要进一步的研究和探讨。<br /><br />2。同时，annotation运行存在两种方式：运行时、编译时。上文中讨论的都是在运行时的annotation应用，但在编译时的annotation应用还没有涉及，因为编译时的annotation要使用annotation processing tool。<br /><br />涉及以上2方面的深入内容，作者将在后文《Java Annotation高级应用》中谈到。<br /><br /><span style="COLOR: blue">六、参考资源：</span><br />·Matrix-Java开发者社区:<a href="http://www.matrix.org.cn/" target="_new">http://www.matrix.org.cn</a><br />·<a href="http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html" target="_new">http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html</a><br />·<a href="http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html" target="_new">http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html</a><br />·<a href="http://www.javaworld.com/javaworld/jw-03-2005/jw-0321-toolbox.html" target="_new">http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html</a><br />·<a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html" target="_new">http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html</a><br />·作者的Blog:<a href="http://blog.matrix.org.cn/page/cleverpig" target="_new">http://blog.matrix.org.cn/page/cleverpig</a><br /><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/93044.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-01-11 08:25 <a href="http://www.blogjava.net/wuxufeng8080/articles/93044.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java6 WebServices （二）客户端 (ZT)</title><link>http://www.blogjava.net/wuxufeng8080/articles/89492.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Fri, 22 Dec 2006 04:54:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/89492.html</guid><description><![CDATA[
		<div class="postbody">在<a href="http://blog.csdn.net/vip01/archive/2006/12/20/1450269.aspx" _fcksavedurl="http://blog.csdn.net/vip01/archive/2006/12/20/1450269.aspx"><font color="#1d58d1">Java6 WebServices （一）服务端</font></a>这篇文章中和大家分享了Java6 WebServices 服务端的写法，光有服务端还不行，还要有客户端才行啊。看了一些网友的相关文章，都只给出了服务端的写法，没有说客户端怎么说。经过一番研究，终于搞定了客户端，今天偶就和大家分享下。<br />首先启动<a href="http://blog.csdn.net/vip01/archive/2006/12/20/1450269.aspx" _fcksavedurl="http://blog.csdn.net/vip01/archive/2006/12/20/1450269.aspx"><font color="#1d58d1">Java6 WebServices （一）服务端</font></a>一文中写好的服务端。<br />新建个项目。命令行到src目录执行，<br />wsimport -keep  http://localhost:8080/HelloService?wsdl<br />会自动生成一些代码。<br /><br /><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial"><div><span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> org.hermit.study.jdk.client;<br /><br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.jws.WebMethod;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.jws.WebParam;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.jws.WebResult;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.jws.WebService;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.jws.soap.SOAPBinding;<br /><br /><br /></span><span style="COLOR: rgb(0,128,0)">/**</span><span style="COLOR: rgb(0,128,0)"><br /> * This class was generated by the JAXWS SI.<br /> * JAX-WS RI 2.0_02-b08-fcs<br /> * Generated source version: 2.0<br /> * <br /> </span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br />@WebService(name </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">Hello</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">, targetNamespace </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">http://jdk.study.hermit.org/client</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">)<br />@SOAPBinding(style </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> SOAPBinding.Style.RPC)<br /></span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">interface</span><span style="COLOR: rgb(0,0,0)"> Hello {<br /><br /><br />    </span><span style="COLOR: rgb(0,128,0)">/**</span><span style="COLOR: rgb(0,128,0)"><br />     * <br />     * </span><span style="COLOR: rgb(128,128,128)">@param</span><span style="COLOR: rgb(0,128,0)"> arg0<br />     * </span><span style="COLOR: rgb(128,128,128)">@return</span><span style="COLOR: rgb(0,128,0)"><br />     *     returns java.lang.String<br />     </span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br />    @WebMethod<br />    @WebResult(partName </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">return</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">)<br />    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> String sayHello(<br />        @WebParam(name </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">arg0</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">, partName </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">arg0</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">)<br />        String arg0);<br /><br />}<br /></span></div></div><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial"><div><span style="COLOR: rgb(0,0,0)"><br /></span><span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> org.hermit.study.jdk.client;<br /><br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> java.net.MalformedURLException;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> java.net.URL;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.xml.namespace.QName;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.xml.ws.Service;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.xml.ws.WebEndpoint;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.xml.ws.WebServiceClient;<br /><br /><br /></span><span style="COLOR: rgb(0,128,0)">/**</span><span style="COLOR: rgb(0,128,0)"><br /> * This class was generated by the JAXWS SI.<br /> * JAX-WS RI 2.0_02-b08-fcs<br /> * Generated source version: 2.0<br /> * <br /> </span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br />@WebServiceClient(name </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">HelloService</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">, targetNamespace </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">http://jdk.study.hermit.org/client</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">, wsdlLocation </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">http://localhost:8080/HelloService?wsdl</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">)<br /></span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> HelloService<br />    </span><span style="COLOR: rgb(0,0,255)">extends</span><span style="COLOR: rgb(0,0,0)"> Service<br />{<br /><br />    </span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">final</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> URL HELLOSERVICE_WSDL_LOCATION;<br /><br />    </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> {<br />        URL url </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">null</span><span style="COLOR: rgb(0,0,0)">;<br />        </span><span style="COLOR: rgb(0,0,255)">try</span><span style="COLOR: rgb(0,0,0)"> {<br />            url </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> URL(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">http://localhost:8080/HelloService?wsdl</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">);<br />        } </span><span style="COLOR: rgb(0,0,255)">catch</span><span style="COLOR: rgb(0,0,0)"> (MalformedURLException e) {<br />            e.printStackTrace();<br />        }<br />        HELLOSERVICE_WSDL_LOCATION </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> url;<br />    }<br /><br />    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> HelloService(URL wsdlLocation, QName serviceName) {<br />        </span><span style="COLOR: rgb(0,0,255)">super</span><span style="COLOR: rgb(0,0,0)">(wsdlLocation, serviceName);<br />    }<br /><br />    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> HelloService() {<br />        </span><span style="COLOR: rgb(0,0,255)">super</span><span style="COLOR: rgb(0,0,0)">(HELLOSERVICE_WSDL_LOCATION, </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> QName(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">http://jdk.study.hermit.org/client</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">HelloService</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">));<br />    }<br /><br />    </span><span style="COLOR: rgb(0,128,0)">/**</span><span style="COLOR: rgb(0,128,0)"><br />     * <br />     * </span><span style="COLOR: rgb(128,128,128)">@return</span><span style="COLOR: rgb(0,128,0)"><br />     *     returns Hello<br />     </span><span style="COLOR: rgb(0,128,0)">*/</span><span style="COLOR: rgb(0,0,0)"><br />    @WebEndpoint(name </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">HelloPort</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">)<br />    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> Hello getHelloPort() {<br />        </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> (Hello)</span><span style="COLOR: rgb(0,0,255)">super</span><span style="COLOR: rgb(0,0,0)">.getPort(</span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> QName(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">http://jdk.study.hermit.org/client</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">HelloPort</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">), Hello.</span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)">);<br />    }<br /><br />}<br /></span></div></div><br />下面我们再写个测试，看看能不能用：<br /><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial"><div><span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> org.hermit.study.jdk.client.test;<br /><br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> org.hermit.study.jdk.client.Hello;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> org.hermit.study.jdk.client.HelloService;<br /><br /><br /></span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> TestClient {<br />    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)"> main(String[] args) {<br />        HelloService service </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> HelloService();<br />        Hello _hello </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> service.getHelloPort();<br />        System.out.println(_hello.sayHello(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">hermit</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">));<br />    }<br />}</span></div></div>执行。<br />控制台输出：<br />hello:hermit<br /><br />ok！搞定。<br />java6搞定web service就这么简单。。。。。。。。。。。。。。。。。。。。。。。。。。<br /><br />xfire危险了。。。。。。。。。。。。。。。。。。。。。。。。</div>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/89492.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-22 12:54 <a href="http://www.blogjava.net/wuxufeng8080/articles/89492.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java6 WebServices （一）服务端 (ZT)</title><link>http://www.blogjava.net/wuxufeng8080/articles/89491.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Fri, 22 Dec 2006 04:53:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/89491.html</guid><description><![CDATA[Java6发布了，其中一个吸引我的新特性就是原生支持WebServices。在这和大家分享下学习心得。<br />下面就开始写个最简单的WebServices：<br /><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial"><div><span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> org.hermit.study.jdk;<br /><br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.jws.WebMethod;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.jws.WebService;<br /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.jws.soap.SOAPBinding;<br /><br />@WebService(targetNamespace </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">http://jdk.study.hermit.org/client</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">)<br />@SOAPBinding(style </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> SOAPBinding.Style.RPC)<br /></span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> Hello {<br />    @WebMethod<br />    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> String sayHello(String name) {<br />        </span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">hello:</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)"> name;<br />    }<br />}<br /></span></div></div>怎么样简洁吧，很多朋友的写法还要在命令行中执行“<span style="FONT-FAMILY: 'Courier New',Courier,monospace"><span style="COLOR: rgb(0,0,0)">wsgen –cp . &lt;path&gt;</span></span>”<br />用偶这种方法写的service可以省去上面这步。<br /><br />targetNamespace = "http://jdk.study.hermit.org/client"这句是指定客户端获取服务端服务后存放的类路径。注意是反着的，http: //jdk.study.hermit.org/client在客户端生成的类会放在org.hermit.study.jdk.client包下。<br />下面是发布服务：<br /><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial"><div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" /><span style="COLOR: rgb(0,0,255)">package</span><span style="COLOR: rgb(0,0,0)"> org.hermit.study.jdk;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" /><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" /></span><span style="COLOR: rgb(0,0,255)">import</span><span style="COLOR: rgb(0,0,0)"> javax.xml.ws.Endpoint;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" /><br /><img id="_88_206_Open_Image" onclick="this.style.display='none'; document.getElementById('_88_206_Open_Text').style.display='none'; document.getElementById('_88_206_Closed_Image').style.display='inline'; document.getElementById('_88_206_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" /><img id="_88_206_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_88_206_Closed_Text').style.display='none'; document.getElementById('_88_206_Open_Image').style.display='inline'; document.getElementById('_88_206_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" /></span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> StartService </span><span id="_88_206_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_88_206_Open_Text"><span style="COLOR: rgb(0,0,0)">{<br /><img id="_130_204_Open_Image" onclick="this.style.display='none'; document.getElementById('_130_204_Open_Text').style.display='none'; document.getElementById('_130_204_Closed_Image').style.display='inline'; document.getElementById('_130_204_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" /><img id="_130_204_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_130_204_Closed_Text').style.display='none'; document.getElementById('_130_204_Open_Image').style.display='inline'; document.getElementById('_130_204_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" />    </span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)"> main(String[] args) </span><span id="_130_204_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_130_204_Open_Text"><span style="COLOR: rgb(0,0,0)">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" />        Endpoint.publish(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">http://localhost:8080/HelloService</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">, </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> Hello());<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" />    }</span></span><span style="COLOR: rgb(0,0,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" _fcksavedurl="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span></div></div>呵呵，更简洁。一句话而已。<br /><span id="_88_206_Open_Text"><span id="_130_204_Open_Text"><span style="COLOR: rgb(0,0,0)">http://localhost:8080/HelloService是指发布的地址<br /><br />运行</span></span></span><span style="COLOR: rgb(0,0,0)">StartService </span><span id="_88_206_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_88_206_Open_Text"><span style="COLOR: rgb(0,0,0)">，开发浏览器输入：http://localhost:8080/HelloService?wsdl<br /><br /></span></span><br /><br />如果能看到以下内容，就可以<br /><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial"><div><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">&lt;?</span><span style="COLOR: rgb(255,0,255)">xml version="1.0" encoding="UTF-8" </span><span style="COLOR: rgb(0,0,255)">?&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">definitions </span><span style="COLOR: rgb(255,0,0)">xmlns</span><span style="COLOR: rgb(0,0,255)">="http://schemas.xmlsoap.org/wsdl/"</span><span style="COLOR: rgb(255,0,0)"> xmlns:tns</span><span style="COLOR: rgb(0,0,255)">="http://jdk.study.hermit.org/client"</span><span style="COLOR: rgb(255,0,0)"> xmlns:xsd</span><span style="COLOR: rgb(0,0,255)">="http://www.w3.org/2001/XMLSchema"</span><span style="COLOR: rgb(255,0,0)"> xmlns:soap</span><span style="COLOR: rgb(0,0,255)">="http://schemas.xmlsoap.org/wsdl/soap/"</span><span style="COLOR: rgb(255,0,0)"> targetNamespace</span><span style="COLOR: rgb(0,0,255)">="http://jdk.study.hermit.org/client"</span><span style="COLOR: rgb(255,0,0)"> name</span><span style="COLOR: rgb(0,0,255)">="HelloService"</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">types </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">message </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="sayHello"</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">part </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="arg0"</span><span style="COLOR: rgb(255,0,0)"> type</span><span style="COLOR: rgb(0,0,255)">="xsd:string"</span><span style="COLOR: rgb(255,0,0)"> </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">message</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">message </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="sayHelloResponse"</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">part </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="return"</span><span style="COLOR: rgb(255,0,0)"> type</span><span style="COLOR: rgb(0,0,255)">="xsd:string"</span><span style="COLOR: rgb(255,0,0)"> </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">message</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">portType </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="Hello"</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">operation </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="sayHello"</span><span style="COLOR: rgb(255,0,0)"> parameterOrder</span><span style="COLOR: rgb(0,0,255)">="arg0"</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">input </span><span style="COLOR: rgb(255,0,0)">message</span><span style="COLOR: rgb(0,0,255)">="tns:sayHello"</span><span style="COLOR: rgb(255,0,0)"> </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">output </span><span style="COLOR: rgb(255,0,0)">message</span><span style="COLOR: rgb(0,0,255)">="tns:sayHelloResponse"</span><span style="COLOR: rgb(255,0,0)"> </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">operation</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">portType</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">binding </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="HelloPortBinding"</span><span style="COLOR: rgb(255,0,0)"> type</span><span style="COLOR: rgb(0,0,255)">="tns:Hello"</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">soap:binding </span><span style="COLOR: rgb(255,0,0)">style</span><span style="COLOR: rgb(0,0,255)">="rpc"</span><span style="COLOR: rgb(255,0,0)"> transport</span><span style="COLOR: rgb(0,0,255)">="http://schemas.xmlsoap.org/soap/http"</span><span style="COLOR: rgb(255,0,0)"> </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">operation </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="sayHello"</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">soap:operation </span><span style="COLOR: rgb(255,0,0)">soapAction</span><span style="COLOR: rgb(0,0,255)">=""</span><span style="COLOR: rgb(255,0,0)"> </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">input</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">soap:body </span><span style="COLOR: rgb(255,0,0)">use</span><span style="COLOR: rgb(0,0,255)">="literal"</span><span style="COLOR: rgb(255,0,0)"> namespace</span><span style="COLOR: rgb(0,0,255)">="http://jdk.study.hermit.org/client"</span><span style="COLOR: rgb(255,0,0)"> </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">input</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">output</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">soap:body </span><span style="COLOR: rgb(255,0,0)">use</span><span style="COLOR: rgb(0,0,255)">="literal"</span><span style="COLOR: rgb(255,0,0)"> namespace</span><span style="COLOR: rgb(0,0,255)">="http://jdk.study.hermit.org/client"</span><span style="COLOR: rgb(255,0,0)"> </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">output</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">operation</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">binding</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">service </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="HelloService"</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />- </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">port </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="HelloPort"</span><span style="COLOR: rgb(255,0,0)"> binding</span><span style="COLOR: rgb(0,0,255)">="tns:HelloPortBinding"</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;</span><span style="COLOR: rgb(128,0,0)">soap:address </span><span style="COLOR: rgb(255,0,0)">location</span><span style="COLOR: rgb(0,0,255)">="http://localhost:8080/HelloService"</span><span style="COLOR: rgb(255,0,0)"> </span><span style="COLOR: rgb(0,0,255)">/&gt;</span><span style="COLOR: rgb(0,0,0)"> <br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">port</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">service</span><span style="COLOR: rgb(0,0,255)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br />  </span><span style="COLOR: rgb(0,0,255)">&lt;/</span><span style="COLOR: rgb(128,0,0)">definitions</span><span style="COLOR: rgb(0,0,255)">&gt;</span></div></div><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/89491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-22 12:53 <a href="http://www.blogjava.net/wuxufeng8080/articles/89491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jdk1.5 for-each(enhanced for loop )</title><link>http://www.blogjava.net/wuxufeng8080/articles/88197.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88197.html</guid><description><![CDATA[for-each(enhanced for loop )<br />接下来向你介绍的Tiger新特性,应该是大家比较期待的一个，在前面的例子里已经数次出现。<br />对了，就是 for-each(enhanced for loop )特性了。<br /><br />for-each(enhanced for loop ),说得全一点应该是 for each element in the aggregation 。顾名思义，就是在for循环中逐个取出集合中的元素。<br />它的语法是<br />for(Type i : 集合){<br />i ...<br />}<br /><br />这里的集合包括两种：<br />第一种是实现java.lang.Iterable接口的类，第二种就是array(数组)。<br />java.lang.Iterable是一个Tiger新引入的接口.在Tiger中，java.util.Colletcion 接口直接继承了 Iterable 接口。所以，所有Colletcion的子类都可以用于for-each语法里。同时，由于java.util.Map 接口里有 Collection&lt;V&gt;; values(),Set&lt;Map.Entry&lt;K,V&gt;;&gt;; entrySet() 和 Set&lt;K&gt;; keySet()三个方法返回Collention的子类。所以所有Map的子类也是可以间接的使用在for-each语句里的。<br />还是先来看一个例子吧.<br /><br />[code]<br />//TestForEach.java<br />import java.util.*;<br />public class TestForEach{<br />public static void main(String arg[]){<br />ArrayList list = new  ArrayList();<br />list.add("asdf");<br />list.add("fdaf");<br />list.add("dfafds");<br />list.add("dsafdsaf");<br />int i=1;<br />for(Object s : list){<br />list.remove(s);<br />System.out.println("element "+i+"  is:"+s);<br />i++;<br />}<br />i=1;<br />Object o[] = list.toArray();<br />for(Object s : o){<br />System.out.println("element "+i+"  is:"+s);<br />i++;<br />}<br /><br />}<br />}<br />[/code]<br /><br />for-each使我们更方便对集合里的元素进行遍历。实际上，编译器在处理Iterable和array时,分别采用如下的方法进行转换<br />[code]<br />Iterable:<br />  for ( Iterator&lt;E&gt;; #i = Expression.iterator(); #i.hasNext(); ) {<br />  FormalParameter = #i.next();<br />  Statement<br />    }<br /><br /><br />array:<br />Type[] #a = Expression;<br />L1: L2: ... Lm://The possibly empty sequence of labels preceding the enhanced for loop is represented by L1: L2: ... Lm. This sequence is moved beyond the assignment to #a so that continue and break statements with labels will work properly. <br />    for (int #i = 0; #i &lt; #a.length; #i++) {<br />        FormalParameter = #a[ #i ] ;<br />        Statement<br />    }<br /><br />[/code]<br /><br /><br />不过，值得注意的是，在Iterable中，for-each遍历是concurrent的，也就是说，在对Iterable进行遍历时，Iterable对象是不能改变的。这意味着我们不可以通过for-each进行移除以及修改的动作.<br />[code]<br />//TestForEach2.java<br />import java.util.*;<br />public class TestForEach2{<br />public static void main(String arg[]){<br />ArrayList list = new  ArrayList();<br />list.add("asdf");<br />list.add("fdaf");<br />list.add("dfafds");<br />list.add("dsafdsaf");<br />int i=1;<br />for(Object s : list){<br />System.out.println("removing element "+i+" :"+s);<br />list.remove(s);//java.util.ConcurrentModificationException<br />i++;<br />}<br /><br />}<br />}<br /><br />//运行<br />removing element 1 :asdf<br />java.util.ConcurrentModificationException<br />        at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)<br />        at java.util.AbstractList$Itr.next(AbstractList.java:420)<br />        at TestForEach.main(TestForEach.java:11)<br />Exception in thread "main" Normal Termination<br />[/code]<br /><br /><br />创建我们的可以直接用于for-each的类<br /><br />通常，我们都通过数组或者是Collection/Map的子类来使用for-each语句，当然我们也可以创建自己的for-each类（Iterable）<br />java.lang.Iterable是一个Tiger新引入的接口，它要求实现的方法只有一个，就是 Iterator&lt;T&gt;; iterator().这就要求我们需要去构造一个Iterator.Iterator接口有三个方法：boolean hasNext(),Type next()和remove()，其中remove为optional opreration，可以不必实现。<br /><br />下面的例子使用了一个Iterator的内部类,就其意义来说，是实现一组的平方数的一个迭代。（现实中也许永远不需这种用法 :） ）<br />[code]<br />//MyForEach.java<br />import java.util.*;<br />public class MyForEach implements Iterable{<br />int start,end;<br />int step=1;<br />public MyForEach(){<br />start=5;<br />end=10;<br />}<br />public MyForEach(int start){<br />this.start=start;<br />end=start+5;<br />}<br />public MyForEach(int start,int end){<br />this.start=start;<br />this.end=end;<br />if(start&lt;end)<br />        step=-1;<br />}<br />public Iterator iterator(){<br />return new Iterator(){//inner class of Iterator<br />        int currentPos=start;<br />        public void remove(){<br />                //do nothing<br />                                throw new UnsupportedOperationException();<br />        }<br />        public boolean hasNext(){//check if exceed the end  <br />                return (step&gt;;0)^(currentPos&gt;;end);<br />        }<br />        public Object next(){<br />                if(!hasNext())<br />                        throw new NoSuchElementException();<br />                int ret=currentPos*currentPos;//平方数<br />                currentPos+=step;<br />                return ret;<br />                }<br />        };<br />}<br />public static void main(String args[]){<br />MyForEach m1 = new MyForEach();<br />for(Object o:m1)<br />        System.out.println(o);<br /><br />}<br /><br />}<br /><br />[/code]<br /><br />还是那句老话，自己好好体会一下吧。<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88197.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 16:02 <a href="http://www.blogjava.net/wuxufeng8080/articles/88197.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jdk1.5 Variable-Arity Methods(Varargs) </title><link>http://www.blogjava.net/wuxufeng8080/articles/88194.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 07:55:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88194.html</guid><description><![CDATA[Variable-Arity Methods(Varargs) <br />可匹配不同长度的自变量的函数，意思就是说，定义好的同一个Method,可以接收个数不一样的变量，看起来有点类似于过载。<br />我们还是先来看一个例子吧。<br /><br />[code]<br />//TestVarargs.java<br />public class TestVarargs{<br /><br /><br />//这个方法展示了varargs的基本语法<br />// 类型（Type）,加3个点，再加变量名,中间可以有或无空格<br />// 而使用该变量时，是以一个Type[]的形式的,等于是一个Array<br />//public static void out(int...   i){//这种可以<br />//public static void out(int  ...i){//这种也可以<br />//public static void out(int  ...  i){//这种也可以<br />public static void out(int...i){//这种也可以<br />        System.out.println("method:out(int... i),vararg.length:"+i.length);<br />        if(i.length==0)<br />                return;<br />        //for-each  featrue<br />        for(Object ii:i)<br />                System.out.print("\t "+ii);<br />        System.out.println();<br />        }<br /><br />//和 out(Object... i) 存在二义性 <br />//public static void out(int i1,int... i){...}<br /><br /><br />//varargs 只能出现在parameter的最后<br />//public static void out(int... i,String s){...}<br /><br />//当然，其他变量可以出现在前面。<br />public static void out(String s,int... i){<br />        System.out.println("method:out(String s,int... i),vararg.length:"+i.length);<br />        if(i.length==0)<br />                return;<br />        //for-each  future<br />        for(int ii:i)<br />                System.out.print("\t "+ii);<br />        System.out.println();<br />        }<br /><br />public static void main(String args[]){<br />        out(123,1343,4542,677675);<br />        out(12323,43243,00);<br />        out("",12);<br />        out("");<br />        out();<br />        }<br />}<br />[/code]<br />该说明的基本上都在源码的注释里头了。<br />值得一提的是，根据JSR201的说法，对它的支持主要是在complier上，在VM的层面上是不需要支持的。在某种意义上，我们可以把它看作<br />[code]<br />        out(int...i){};<br />        out(123,1343,4542,677675); <br />        ==<br />        out(int[] i){};<br />        out(new Int[]{123,1343,4542,677675});<br />[/code]<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88194.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 15:55 <a href="http://www.blogjava.net/wuxufeng8080/articles/88194.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jdk1.5 static import</title><link>http://www.blogjava.net/wuxufeng8080/articles/88191.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 07:52:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88191.html</guid><description><![CDATA[static import<br />static import就是允许在代码中直接引用别的类的static变量和方法（当然，在权限许可范围内），我们可以简单的把它当成import的延续。<br />它的语法如下：<br />import static CLASS_NAME.MEMBER_NAME;<br />或者 import static CLASS_NAME.×;<br /><br /><br />事实上，Tiger引入static import最主要考虑到两个需要，第一个就是对一些工具性的，常用的静态方法进行直接引用。<br />比如,java.lang.Math里的一大堆数学方法abs,exp等。<br />第二个就是对常数变量进行直接引用，其中也包扩对enum的直接引用（参考上一篇文章Season的例子）<br />[code]<br />//StaticImportTest.java<br />import static java.lang.Math.*;<br /><br />public class StaticImportTest{<br /><br />public static void main(String arsg[]){<br />System.out.println("1 ＋ 1 ="+(1+1));<br />System.out.println("abs(-1)="+abs(-1));<br />System.out.println("exp(1.5)="+exp(1.5));<br />System.out.println("Pi = "+PI);<br />System.out.println("E = "+E);<br /><br />}<br /><br />}<br />[/code]<br />这样的代码不仅省却了Programmer的劳动，在可读性上也是有所增强。<br /><br />static import的限制和import也基本一样，就是不能出现二义性。<br />另外，static import不支持先import类，然后import static 类.*(不加package)的形式<br />如<br />[code]<br />import  java.util.*;<br />import static Calendar.*;<br />......<br />[/code]<br />就算在同一个包也是如此。<br /><br />值得注意的是，过多的static import也许可能影响程序的可读性，如：<br />[code]<br />//StaticImportTest2.java<br />import static java.lang.Integer.parseInt;<br />import static java.lang.Double.*;<br /><br />public class StaticImportTest{<br /><br />public static void main(String arsg[]){<br />String iv = "1239";<br />String dv = "123.3456";<br />System.out.println(iv+":"+parseInt(iv));<br />System.out.println(dv+":"+parseDouble(dv));<br />System.out.println("Double's MaxValue is:"+MAX_VALUE );<br /><br />}<br />[/code]<br />虽然能编译通过，但是却很容易混绕读者视线。<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88191.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 15:52 <a href="http://www.blogjava.net/wuxufeng8080/articles/88191.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jdk1.5 Type Safe Enum </title><link>http://www.blogjava.net/wuxufeng8080/articles/88190.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88190.html</guid><description><![CDATA[Type Safe Enum <br /><br />Tiger的改进其实真的称得上是顺应民意,里面的好多特性都可以在两本Java巨著&lt;&lt;Think In Java&gt;;&gt;;和&lt;&lt;Effective Java&gt;;&gt;;发现一些端倪.<br />(不得不承认,&lt;&lt;Think In Java&gt;;&gt;;和&lt;&lt;Effective Java&gt;;&gt;;是Java历史上最经典的两本书,多读多受益)<br />比如,之前提到过的Genric,在&lt;&lt;Think In Java&gt;;&gt;; 第九章介绍Colletion时就对Genric作出了预期,同时也实现某种形式的Genric(TIJ 2ND,P449-P455).<br />另外,Think In Java里也提及了利用interface来定义一组常量的方法(P358-P360),不少标准的Java库类也使用了这种方法(如java.util.zip.ZipConsts.不过,你将会发现,在Tiger里它已经不复存在了)<br />这种做法叫做Const Interface,大家也许或多或少都使用过.但是,Const Interface的方式在&lt;&lt;Effective Java&gt;;&gt;;受到了极大的否定(Item 17).书里提出了使用Type Safe Enum的方法(Item 21)来取代Const Interface.让我们对比一下以下两段代码<br /><br />Const Interface<br />[code]<br />//SeasonConst.java<br />// Constant interface pattern - do not use! <br />public interface SeasonConst { <br />public static final int SPRING = 1;<br />public static final int SUMMER = 2;<br />public static final int AUTUMN = 3;<br />public static final int WINTER = 4;<br />}<br /><br />//TestConst.java<br />//using of Constant interface<br />public class TestConst implements SeasonConst{<br />public void seasonLiving(int season){<br />if(season==SPRING){<br />System.out.println("we BBQ at SPRING");<br />}<br />else if(season==SUMMER){<br />System.out.println("we swim at SUMMER");<br />}<br />else if(season==AUTUMN){<br />System.out.println("we kite at AUTUMN");<br />}<br />else if(season==WINTER){<br />System.out.println("we skate at WINTER");<br />}<br />else{<br />System.out.println("What ?");<br /><br />}<br />}<br />public static void main(String args[]){<br />TestConst t = new TestConst();<br />t.seasonLiving(SPRING);<br />t.seasonLiving(WINTER);<br />t.seasonLiving(WINTER+1);<br />//t.sersonLiving(WEEK_DAY.MONDAY);//程序无法和其他常数完整的区分<br />}<br />}<br />[/code]<br /><br />Type Safe Enum<br />[code]<br />//SeasonEnum.java<br />// The typesafe enum (j2sdk1.4)pattern <br />public class SeasonEnum { <br />private final String name;<br />private SeasonEnum(String name) {<br />this.name = name; <br />}<br />public String toString() { return name; }<br />public static final SeasonEnum SPRING = new SeasonEnum("SPRING"); <br />public static final SeasonEnum SUMMER = new SeasonEnum("SUMMER"); <br />public static final SeasonEnum AUTUMN = new SeasonEnum("AUTUMN"); <br />public static final SeasonEnum WINTER = new SeasonEnum("WINTER"); <br />}<br /><br />//TestEnum.java<br />//using of typesafe enum (j2sdk1.4)<br />public class TestEnum{<br />public void seasonLiving(SeasonEnum season){<br />if(season==SeasonEnum.SPRING){<br />System.out.println("we BBQ at "+season);<br />}<br />else if(season==SeasonEnum.SUMMER){<br />System.out.println("we swim at "+season);<br />}<br />else if(season==SeasonEnum.AUTUMN){<br />System.out.println("we kite at "+season);<br />}<br />else if(season==SeasonEnum.WINTER){<br />System.out.println("we skate at "+season);<br />}<br />else{<br />System.out.println("What ?");<br />}<br />}<br />public static void main(String args[]){<br />TestEnum t = new TestEnum();<br />t.seasonLiving(SeasonEnum.SPRING);<br />t.seasonLiving(SeasonEnum.WINTER);<br />//t.seasonLiving(WINTER+1);no way to put a season not in the SeasonEnum<br /><br />}<br />}<br />[/code]<br /><br />可以看出,Type Safe Enum在以下几个方面优于Const Interface<br />1.不会违背OO继承的意义.<br />2.类型安全,不会有无意义的常数混进正常常数中<br />3.保持自己的独立性,不像Const interface再编译后就失去了意义<br />4.可直接用于print<br />5.作为一个Object,可以拥有自己的方法,变量,可以继承,implement interface<br /><br />但是,相对的,Type Safe Enum在使用中也有几点不利的地方<br /><br />1.不能直接用于switch<br />2.必须跟上类名,增加复杂性<br />3.繁琐<br /><br />于是,Tiger中引入了 typesafe Enum和static import ,同时启用了一个新的关键字enum(这也是Tiger中引入的唯一一个关键字).再配合上Genric,使得整个结构变得严谨而易用.<br /><br />让我们还是使用方才的例子来说明吧,先来一个最简单的例子.<br />[code]<br />public class TestEnumTiger1{<br />public enum SeasonSimpliest {        SPRING,        SUMMER,        AUTUMN,        WINTER}<br /><br /><br />public void seasonLiving(SeasonSimpliest season){<br /><br />if(season==SeasonSimpliest.SPRING){<br />System.out.println("we BBQ at "+season);<br />}<br />else if(season==SeasonSimpliest.SUMMER){<br />System.out.println("we swim at "+season);<br />}<br />else if(season==SeasonSimpliest.AUTUMN){<br />System.out.println("we kite at "+season);<br />}<br />else if(season==SeasonSimpliest.WINTER){<br />System.out.println("we skate at "+season);<br />}<br />else{<br />System.out.println("What ?");<br />}<br />}<br />public static void main(String args[]){<br />TestEnumTiger1 t = new TestEnumTiger1();<br />t.seasonLiving(SeasonSimpliest.SPRING);<br />t.seasonLiving(SeasonSimpliest.WINTER);<br />System.out.println("the seasong is :"+SeasonSimpliest.SPRING);<br />//t.seasonLiving(WINTER+1);no way to put a season not in the SeasonEnum<br />//t.seasonLiving(new SeasonSimpliest("Five Season"));no way to put a season not in the SeasonEnum<br /><br />}<br />}[/code]<br /><br />这里面的常量直接用enum修饰,再加上一个名字和所需常量就可以了.<br />enum SeasonSimpliest {        SPRING,        SUMMER,        AUTUMN,        WINTER}<br />不过,不要被这种形式所迷惑,以为enum是一个primtive type,与int,boolean一样,那就错了.<br />让我们编译一下这个文件,再看看编译后的目录<br />里面除了有TestEnumTiger1.java,TestEnumTiger1.class之外,还有一个TestEnumTiger1$SeasonSimpliest.class,这就暴露了enum的某些行为方式,它在某种意义上是一个class.<br />在上面的源码中,它成了一个inner-class.<br /><br />OK.让我们改改代码,把enum作为一个独立个体来处理<br />[code]<br />//SeasonSimpliest.java<br />package test;<br />public enum SeasonSimpliest {SPRING,SUMMER,AUTUMN,WINTER}<br />[/code]<br /><br />[code]<br />//enum &amp; static import<br />package test;<br />import static test.SeasonSimpliest.*;<br /><br />public class TestEnumTiger2{<br /><br />public void seasonLiving(SeasonSimpliest season){<br />switch(season){<br />case SPRING:<br />System.out.println("we BBQ at "+season);<br />break;<br />case SUMMER:<br />System.out.println("we swim at "+season);<br />break;<br />case AUTUMN:<br />System.out.println("we kite at "+season);<br />break;<br />case WINTER:<br />System.out.println("we skate at "+season);<br />break;<br />default:throw new AssertionError("something must be wrong,no such a season");<br />}<br />}<br />public static void main(String args[]){<br />TestEnumTiger2 t = new TestEnumTiger2();<br />t.seasonLiving(SPRING);<br />t.seasonLiving(WINTER);<br />System.out.println("the season is :"+SUMMER);<br />//t.seasonLiving(WINTER+1);no way to put a season not in the SeasonEnum<br />//t.seasonLiving(new SeasonSimpliest("Five Season"));no way to put a season not in the SeasonEnum<br /><br />}<br />}<br /><br />[/code]<br /><br />为了使整个代码显得更加简洁,我引入import static ,稍后再作更详细介绍,现在先来看看enum的好处.<br />1.避免了使用Const interface<br />2.很简单的定义方式<br />3.Type Safe,类型安全的,不会和其他的常量混绕.<br />4.可以使用switch<br />5.作为一个Class,它可以有自己Method,Field,也可以implements interface.<br /><br />为了更好的说明第5点,我给大家展示一个复杂的enum type.<br /><br />[code]<br />//SeasonComplex.java<br />//implements interface,owner method &amp; field<br />public  enum SeasonComplex implements Comparable&lt;SeasonComplex&gt;; {<br />        SPRING(1),<br />        SUMMER(2),<br />        AUTUMN(3),<br />        WINTER(4);<br />private final int seasonNumber;<br />Season(int value){<br />        seasonNumber=value;<br />        }<br />public int seasonNumber(){<br />        return seasonNumber;<br />}<br />public int compare(Season c){<br />return seasonNumber - c.seasonNumber;<br />}<br />public String description(){<br />return this+":第"+ seasonNumber +"季";<br />}<br />};<br /><br />[/code]<br /><br />具体的我就不一一写清楚,大家好好体会吧.<br /><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 15:50 <a href="http://www.blogjava.net/wuxufeng8080/articles/88190.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jdk1.5 generic</title><link>http://www.blogjava.net/wuxufeng8080/articles/88185.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 07:45:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88185.html</guid><description><![CDATA[老虎来了,你准备好了吗?<br /><br />也不知什么时候,Sun推出了Tiger的Beta版(J2SE 1.5.0 Beta 1).<br />早在Sun公布Tiger草案时,就对它是又爱又恨,一下子加了那么多得编程特性( http://www.chinaunix.net/forum/viewtopic.php?t=104044 ),真不知道会不会适应不过来.不过,所谓"兵来将挡",不入虎穴,焉得虎子,请大家与我一起进入"Tiger"的世界.<br /><br />1.下载及安装<br />第一步当然就是把老虎请到我们的家中来咯.<br />先到http://java.sun.com, 或者 http://java.sun.com/j2se/1.5.0/index.jsp ,就可以发现在右侧Popular Downloads里的赫然就是我们要找的"Tiger",点击进入 http://java.sun.com/j2se/1.5.0/download.jsp ,点击SDK 下面的download,同意协议,再选择相应的平台,windowns 48M,Sparc64只需要9M,点击下载,或者可以直接右键使用Flashget/Netant下载.<br />呵呵,记得回到 http://java.sun.com/j2se/1.5.0/download.jsp 同时把Docment也给download下来.<br /><br />下载完毕就可以开始安装了,当然,安装前先看看Installation Notes,Window下的没什么特别,solaris64好像还需要打patch.<br />我用的是windows,运行下载的文件(用flashget下载的好像需要改扩展名为.exe),跟着wizard往下走,默认安装路径是 C:\Program Files\Java\j2sdk1.5.0\,如果你和我一样讨厌空格,可以把它放在C:\j2sdk1.5.0,中间的安装步骤就不用说了,十几二十分钟,安装就完成了.把下载来的docment也顺便给解开,放在C:\j2sdk1.5.0\doc下.<br /><br />2.环境配置<br />安装完毕之后,就需要配置一下环境,改动一下两个环境变量<br />JAVA_HOME=c:\j2sdk1.5.0<br />PATH=c:\j2sdk1.5.0\bin;......(原来的PATH)<br /><br />3.Hello World<br />好了,现在Tiger已经在电脑里安了身了.下面,我们就开始我们的骑虎之旅吧.<br /><br />正如 http://www.chinaunix.net/forum/viewtopic.php?t=104044 里提到的,java语言规范(JSR)201有不少变化.其中,在集合的Frame里有几个重要的变化,让我们以这几个变化中的 [color=blue]generic [/color]开始展开骑虎之旅.<br /><br /><br />generic指的就是对特定的集合,只能容纳特定的类的对象,而在取出来时不需做Cast.他的语法类似<br />[code]<br />Vector&lt;String&gt;; v = new Vector&lt;String&gt;;();<br />c.add("test");<br />String s = c.get("test");<br />[/code]<br />我们就以上面的代码为例<br />[code]<br />//GenricTest.java<br />import java.util.*;<br />public class GenricTest{<br />public static void main(String args[]){<br />Vector&lt;String&gt;; v = new Vector&lt;String&gt;;();<br />v.add("Hello World");<br />String s = v.get(0);<br />System.out.println(s);<br />}<br />}<br />[/code]<br />保存,javac之......<br />却出现了这个<br />[code]<br />GenricTest.java:4: '(' or '[' expected<br />Vector&lt;String&gt;; v = new Vector&lt;String&gt;;();<br />                             ^<br />1 error<br />[/code]<br /><br />怎么回事?呵呵明天回来告诉你.<br />:)<br /><br /><br />昨天说到javac竟然不能编译新语法的java文件,难道是环境每设对,先来试验一下java<br />[code]<br />java -version<br />java version "1.5.0-beta"<br />Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-bet<br />Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)<br />[/code]<br />java没问题,也就是说路径设置正确了<br />那试试javac<br />[code]<br />Usage: javac &lt;options&gt;; &lt;source files&gt;;<br />where possible options include:<br />  -g                        Generate all debugging info<br />  -g:none                   Generate no debugging info<br />  -g:{lines,vars,source}    Generate only some debugging info<br />  -nowarn                   Generate no warnings<br />  -verbose                  Output messages about what the compiler is doing<br />  -deprecation              Output source locations where deprecated APIs are used<br />  -classpath &lt;path&gt;;         Specify where to find user class files<br />  -sourcepath &lt;path&gt;;        Specify where to find input source files<br />  -bootclasspath &lt;path&gt;;     Override location of bootstrap class files<br />  -extdirs &lt;dirs&gt;;           Override location of installed extensions<br />  -d &lt;directory&gt;;            Specify where to place generated class files<br />  -encoding &lt;encoding&gt;;      Specify character encoding used by source files<br />  -source &lt;release&gt;;         Provide source compatibility with specified release<br />  -target &lt;release&gt;;         Generate class files for specific VM version<br />  -help                     Print a synopsis of standard options<br />[/code]<br />呵呵,看出来了吗,原来有一个-source &lt;release&gt;; 的选项,是指定source compatibility (源代码兼容)一直都没怎么注意,想必是这里出错了.<br />OK,让我们再来javac一把<br />[code]<br />javac -source 1.5  GenricTest.java<br /><br />[/code]<br />什么都没提示,那就继续运行 java<br />[code]<br />java GenricTest<br /><br />Hello World<br />[/code]<br />好了,梦寐以求的Hello World终于展现在我们面前了.我们已经成功的爬上了虎背.<br />4,猫和狗<br />Genric 当然没那么简单,它的重点在于只容纳特定类的对象.如果你读过关于集合是如何不管放进去的对象的,你也许会记得有着么一个例子(或者类似的)<br /><br />[quote]<br />....<br />我们往Vector里放进去了几只猫,虽然我们很清楚,这个Vector应该只有猫,但是,编译器并不提供任何的保障,一个疏忽,可能会使我们不小心就往里面扔进去一条狗<br />.....<br />[/quote]<br />那么,让我们看看,Genric是如何防止往一个给猫设计的List扔进去一条狗的,下面的例子有点复杂.<br /><br />[code]<br />//GenricTestCatAndDog.java<br /><br />import java.util.*;<br />class Cat {<br />String name;<br />public Cat(){}<br />public Cat(String name){<br />this.name=name;<br />}<br />public void catchMouse(){<br />//...<br />}<br />}<br />class Dog{<br />String name;<br />public Dog(){}<br />public Dog(String name){<br />this.name=name;<br />}<br />public void bark(){<br />//...<br />}<br />}<br />public class GenricTestCatAndDog{<br />public static void main(String args[]){<br />Vector&lt;Cat&gt;; v = new Vector&lt;Cat&gt;;();<br />Cat cat = new Cat("Jacky");<br />Dog dog = new Dog("Mike");<br />v.add(cat);<br />v.add(dog);<br />System.out.println(v.get(0));<br />System.out.println(v.get(1));<br />}<br />}[/code]<br />保存,再javac之<br />[code]<br />javac -source 1.5 GenricTestCatAndDog.java<br /><br />GenricTestCatAndDog.java:30: cannot find symbol<br />symbol  : method add(Dog)<br />location: class java.util.Vector&lt;Cat&gt;;<br />v.add(dog);<br />^<br />1 error<br />[/code]<br /><br />正如我们所看到的,dog不能被放到Vector&lt;Cat&gt;;里面.<br />我们试着把放进去Dog的代码注释掉,再编译,通过了.<br />现在猫可以高高兴兴的在自己的窝里睡觉,不用担心狗跑来骚扰了.而我们从猫窝里抓出来得动物,也不用再去检查一下是否是猫,直接就可以命令他去抓老鼠(catchMouse)了<br />[code]<br />//GenricTestCatAndDog2.java<br /><br />import java.util.*;<br />class Cat {<br />String name;<br />public Cat(){}<br />public Cat(String name){<br />this.name=name;<br />}<br />public void catchMouse(){<br />System.out.println((name==null?"I am ":name+" is ")+" catching mouse.... ");<br />//...<br />}<br />}<br />class Dog{<br />String name;<br />public Dog(){}<br />public Dog(String name){<br />this.name=name;<br />}<br />public void bark(){<br />//...<br />}<br />}<br />public class GenricTestCatAndDog2{<br />public static void main(String args[]){<br />Vector&lt;Cat&gt;; v = new Vector&lt;Cat&gt;;();<br />Cat cat = new Cat("Jacky");<br />Dog dog = new Dog("Mike");<br />v.add(cat);<br />//v.add(dog);<br />v.get(0).catchMouse();<br />}<br />}<br />[/code]<br />编译并运行<br />[code]<br />javac -source 1.5 GenricTestCatAndDog2.java<br /><br />java  GenricTestCatAndDog2<br />Jacky is  catching mouse....<br />[/code]<br /><br />让我们先休息一下,好好看看我们的猫捉会老鼠,明天回来,继续骑虎之旅.....<br /><br />Genric兼容性<br /><br />我们已经见识了Genric带来的好处,特定Collection/Map只能容纳特定类型的对象,取出来时不需要Cast.<br />但是,我们毕竟需要使用以前的某些程序.那么,新语法对以前的代码有没有影响呢.让我们用新的javac编译一下以前的这一段代码:<br />[code]<br />//GenricTest2.java<br />import java.util.*;<br />public class GenricTest2{<br />public static void main(String args[]){<br />Vector v = new Vector();<br />v.add("Helo World");<br />String s = (String)v.get(0);<br />System.out.println(s);<br />}<br />}<br />[/code]<br /><br />[code]<br />javac -source 1.5 GenricTest2.java<br /><br />Note: GenricTest2.java uses unchecked or unsafe operations.<br />Note: Recompile with -Xlint:unchecked for details.<br /><br />[/code]<br />ok,javac的内部参数都出来了,继续编译<br />[code]<br />javac -source 1.5 -Xlint:unchecked GenricTest2.java<br /><br />GenricTest2.java:5: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.Vector<br />v.add("Helo World");<br />^<br />1 warning<br />[/code]<br />看出来了,这就象以前的 -deprecation 参数,给你一些提示.当然,原来的代码还是能继续使用的.  <br /><br />创建自己的Genric类<br /><br />根据前面的介绍,对于Genric,大家应该已经有所了解.那么,我们能不能创建自己的包含Genric特性的类呢?<br />让我们去看看Vector.java的源代码,看看它是如何做到的.然后,我们就可以依样画葫芦了;<br />大家都知道,jsdk发布时,通常都附带源代码.打开C:\j2sdk1.5.0,src.zip就放在那里,解开,打开java\util\Vector.java.<br /><br />源码挺长,我就只列出它的重要部分(类定义,默认构造函数,add方法)<br />[quote]<br />....<br />public class Vector&lt;E&gt;;<br />    extends AbstractList&lt;E&gt;;<br />    implements List&lt;E&gt;;, RandomAccess, Cloneable, java.io.Serializable<br />.....<br />public Vector() {<br />        this(10);<br />    }<br />    public Vector(int initialCapacity) {<br />        this(initialCapacity, 0);<br />    }<br />   public Vector(int initialCapacity, int capacityIncrement) {<br />   super();<br />   ...<br />        public void add(E o) {<br />            checkForComodification();<br /><br />            try {<br />                AbstractList.this.add(cursor++, o);<br />                lastRet = -1;<br />                expectedModCount = modCount;<br />            } catch(IndexOutOfBoundsException e) {<br />                throw new ConcurrentModificationException();<br />            }<br />        }<br />    }<br />....<br />)<br />[/quote]<br />当然,还得看看它的父类(AbstractList)以及祖父类(AbstractCollection),它们的默认构造函数都是空白.<br />同时,可以看到,add方法出现了"&lt;E&gt;;"里的E.<br /><br />ok,画一个葫芦先<br /><br />[code]<br />//MyGenricGun.java<br />//子弹<br />class Bulltin<br />{<br />        int damage;<br />        public Bulltin(){};<br />};<br />//普通子弹<br />class SmallBulltin extends Bulltin<br />{<br />        <br />        public SmallBulltin(){damage=10;};<br />};<br />//火箭炮<br />class Rocket extends Bulltin<br />{<br />        public Rocket(){damage=2000;};<br />};<br /><br />//可以指定放子弹类型的Gun<br />public class MyGenricGun&lt;MyType extends Bulltin&gt;;{<br /><br />//上子弹<br />public void addBulltin(MyType bulletin){<br />        System.out.println("add a bulletin,damage is " + bulletin.damage);<br />//....<br />}<br /><br />public static void main(String args[]){<br />//放小子弹的枪<br />MyGenricGun&lt;SmallBulltin&gt;; gun1 = new   MyGenricGun&lt;SmallBulltin&gt;;();<br />//放火箭炮的枪<br />MyGenricGun&lt;Rocket&gt;; gun2 = new   MyGenricGun&lt;Rocket&gt;;();<br />//什么子弹都能放的枪<br />MyGenricGun&lt;Bulltin&gt;; gun3 = new   MyGenricGun&lt;Bulltin&gt;;();<br />//什么都能放的枪<br />MyGenricGun gun4 = new   MyGenricGun();<br />//什么都能放的枪<br />//MyGenricGun&lt;Object&gt;; gun5 = new   MyGenricGun&lt;Object&gt;;();//不成功<br />gun1.addBulltin(new SmallBulltin());<br />//gun1.addBulltin(new Rocket());//不成功<br />//gun2.addBulltin(new SmallBulltin());//不成功<br />gun2.addBulltin(new Rocket());<br />gun3.addBulltin(new Bulltin());<br />gun3.addBulltin(new Rocket());<br />gun3.addBulltin(new SmallBulltin());<br />gun4.addBulltin(new SmallBulltin());<br />gun4.addBulltin(new Rocket());<br />gun4.addBulltin(new Bulltin());<br />//gun4.addBulltin(new Integer(1));//不成功<br />}<br /><br />}<br />[/code]<br /><br />大家可以把标有"//不成功"的地方的注释去掉/加上,对比一下编译结果,就可以大概知道Genric的运行逻辑了.<br /><br />自己再琢磨琢磨,看看java.util里的Colletion及Map FrameWork里的包,Genric暂时就说到这里.<br /><br />下周,将为大家继续带来 Tiger的其他新特性(Auto Boxing unBoxing,Enhanced for loop,Enumerated types等)<br /><br /><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88185.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 15:45 <a href="http://www.blogjava.net/wuxufeng8080/articles/88185.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2SE 5.0的三种内置注释类型</title><link>http://www.blogjava.net/wuxufeng8080/articles/88182.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 07:33:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88182.html</guid><description><![CDATA[
		<h2>
				<a id="_2ba92b7c852b_HomePageDays_DaysList_ctl06_DayItem_DayList_ctl00_TitleUrl" href="/robin/archive/2006/01/01/26283.html">J2SE 5.0的三种内置注释类型</a>
		</h2>
		<div class="comText">注解(annotation)是J2SE 5.0的新内容，它给我们提供了很好的编程支持，下面介绍一下其内置的三种注解类型：<br /><br /><strong>1. @Override</strong><br /><br /><font face="Courier New" size="2">@Override用在多态情况下，比如：<br /><br /></font><div class="xoopsCode"><code><pre><font size="2">public abstract class Animal{
   public void say(){
      System.out.println("annimal is saying");
   }
}

public class Cat extends Animal{
    @Override
    public void say(){
        System.out.println("miao, miao");
    }
}
</font></pre></code></div><br /><font face="Courier New" size="2">通过@Override来告诉java编译器，say方法是重载的父类的方法，这样，当父类的say方法签名改名的话，比如增加了一些参数，那么子类的Cat中的say方法编译时就会报错，说没有正确的重载父类方法，所以，@Override可以帮我们验证程序的正确性，这一点，很有用。<br /></font><br /><strong>2. @Deprecated <br /></strong><br /><font face="Courier New" size="2">@Deprecated的意思和JavaDoc中的@deprecated注释在本质上是一样的，使用如下：<br /><br /></font><code><p class="xoopsCode"><font size="2">public class DeprecatedExample { <br />   @Deprecated <br />   public static void badMethod() { }<br />}<br /><br />public class DeprecatedUser { <br />   public static void main(String[] args){<br />      DeprecatedExample.badMethod(); <br />   } <br />}<br /></font></p></code><br /><font face="Courier New" size="1"><font size="2">上面的代码如果用javac进行编译的话，会打印出如下信息:<br />Note: DeprecatedUser.java uses or overrides a deprecated API.<br />Note: Recompile with -Xlint:deprecation for details.<br />1 error<br />如果你按提示重新加-Xlint进行编译，你就可以得到错误的详细信息：<br />% javac -Xlint:deprecation<br />DeprecatedUser.java:3: warning: [deprecation] badMethod() in DeprecatedExample<br />has been deprecated<br />DeprecatedExample.badMethod();<br /><br />需要注意的是：和javadoc中的@deprecated相比，@Deprecated并没有强大多少，因为它不支持参数，而@deprecated后面还可以跟字符串来给一些相关的信息，但@Deprecated做不到，但它提供了运行时自省的功能，来提示错误，所以建议@Deprecated和@deprecated同时使用。</font><br /></font><br /><font face="宋体, MS Song"> <strong>3. @SuppressWarnings</strong><br /><br /></font><font face="Courier New" size="2">顾名思义，就是抑制警告信息的出现，使用如下：<br /></font><font size="2"><code>public class DeprecatedExample2{ <br />   @Deprecated <br />   public static void foo() { }<br />}<br /><br />public class DeprecatedUser2 { <br />   @SuppressWarnings(value={"deprecation"}) <br />   public static void main(String[] args) { <br />      DeprecatedExample2.foo(); <br />   } <br />}<br /></code><br /></font><font face="Courier New" size="2">上述@SuppressWarnings(value={"deprecation"})的作用就是抑制编译器报deprecation的错。<br />@SuppressWarnings(value={"deprecation"})只支持一个参数，是数组类型，所以你可以不用加value, 写成：@SuppressWarnings({"deprecation"})；当想抑制多个类型的警告信息时，可写：@SuppressWarnings({"unchecked","fallthrough",deprecation"}).<br /><br />注意：在JDK1.5.0 release中，@SuppressWarnings还没有得到完全支持，会在以后支持，但Sun并没有给出具体的时间。</font></div>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88182.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 15:33 <a href="http://www.blogjava.net/wuxufeng8080/articles/88182.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SpringSide中使用的JDK5.0特性</title><link>http://www.blogjava.net/wuxufeng8080/articles/88181.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 07:28:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88181.html</guid><description><![CDATA[
		<h1>
				<a name="JDK5-SpringSide%E4%B8%AD%E4%BD%BF%E7%94%A8%E7%9A%84JDK5.0%E7%89%B9%E6%80%A7">
				</a>SpringSide中使用的JDK5.0特性</h1>
		<p>      随着光阴推移，Annotation 慢慢在开源框架中推广，泛型渐渐被程序员们用熟，加上AutoBoxing的小糖，SpringSide终于离不开JDK5.0。</p>
		<h2>
				<a name="JDK5-1.AutoBoxing%E4%B8%8EForEach%E5%BE%AA%E7%8E%AF">
				</a>1.AutoBoxing 与 For Each 循环</h2>
		<p>    本来int的非Object性就很无聊，在JDK5.0终于提供了autoboxing功能。这个语法简化糖，被用在了每一个地方。</p>
		<p>    for each 循环也改善了原本总要愣一下的collection遍历。不过对于非JDK基本类型，collection必须用泛型声明，如List&lt;Book&gt;。</p>
		<h2>
				<a name="JDK5-2.%E6%B3%9B%E5%9E%8B">
				</a>2. 泛型</h2>
		<p>    泛型大量用于SpringSide Core中的基类，使子类更简洁，基类更强大。当然，基类是难读了，所以才需要社区花上这么长的时间来把&lt;T&gt;看到顺眼。</p>
		<p>    泛型使用的有两个定式：</p>
		<h3>
				<a name="JDK5-2.1%E9%81%BF%E5%85%8D%E5%BC%BA%E5%88%B6%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2">
				</a>2.1 避免强制类型转换</h3>
		<p>   如果函数输入参数里含Class类型，而返回值又是该Class的实体，应该将该函数设为泛型函数。最典型的例子是<span class="nobr"><a title="Visit page outside Confluence" href="http://www.springside.org.cn/docs/api/org/springside/core/dao/HibernateGenericDao.html" rel="nofollow">HibernateGenericDao<sup><img class="rendericon" height="7" alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" width="7" align="absMiddle" border="0" /></sup></a></span>的get() 函数</p>
		<div class="code">
				<div class="codeContent">
						<pre class="code-java">
								<span class="code-keyword">public</span> &lt;T&gt; T get(<span class="code-object">Class</span>&lt;T&gt; entityClass, Serializable id) {
   <span class="code-keyword">return</span> (T) getHibernateTemplate().get(entityClass, id);
}</pre>
				</div>
		</div>
		<p>  其中眼花缭乱的第一个&lt;T&gt;声明这是一个泛型函数，第2个T声明返回值为T，第三个Class&lt;T&gt;代表 T.class。基类写的辛苦，但子类用得爽快 </p>
		<p>   Book book = (Book)manager.get(Book.class,1) 简化成了 Book book = manager.get(Book.class,1);</p>
		<h3>
				<a name="JDK5-2.2%E6%B3%9B%E5%9E%8B%E9%85%8D%E5%90%88%E5%8F%8D%E5%B0%84API%E4%BB%8ET%E8%8E%B7%E5%BE%97T.class%E3%80%82">
				</a>2. 2 泛型配合反射API从T获得 T.class。</h3>
		<p>   最典型的例子<span class="nobr"><a title="Visit page outside Confluence" href="http://www.springside.org.cn/docs/api/org/springside/core/dao/HibernateEntityDao.html" rel="nofollow">HibernateEntityDao<sup><img class="rendericon" height="7" alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" width="7" align="absMiddle" border="0" /></sup></a></span>，子类只需以下定义，即获得要管理的Entity的Class。</p>
		<div class="code">
				<div class="codeContent">
						<pre class="code-java">BookManager <span class="code-keyword">extends</span> HibernateEntityDao&lt;Book&gt;</pre>
				</div>
		</div>
		<p>    此时子类只要声明一次T，上面的Book book = (Book)manager(Book.class,1) 就能简化成Book = manager.get(1);</p>
		<p>    一举两得地既避免了强制类型转换，又声明了T.class 供框架使用，无须再在Manager的构造函数或getEntityClass()函数定义entityClass，。</p>
		<p>    反射的API 详见<span class="nobr"><a title="Visit page outside Confluence" href="http://www.springside.org.cn/docs/api/org/springside/core/utils/GenericsUtils.html" rel="nofollow">GenricsUtils<sup><img class="rendericon" height="7" alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" width="7" align="absMiddle" border="0" /></sup></a></span> ，精简的对上面BookManager的定义反射代码如下:</p>
		<div class="code">
				<div class="codeContent">
						<pre class="code-java">Type genType = clazz.getGenericSuperclass();
Type [] params = ((ParameterizedType) genType).getActualTypeArguments();
<span class="code-keyword">return</span> (<span class="code-object">Class</span>) params[0];</pre>
				</div>
		</div>
		<p>   泛型反射的关键是获取ParameterizedType，再调用它的getActualTypeArguments()方法获得实际绑定的类型。但注意public class BookManager&lt;Book&gt;是不能被反射的，因为擦拭法的缘故。只有在Superclass 或者成员变量(Field.getGenericType())等有函数返回ParameterizedType的时候才能成功反射，，</p>
		<p>比如 </p>
		<div class="code">
				<div class="codeContent">
						<pre class="code-java">
								<span class="code-keyword">public</span> class BookManager <span class="code-keyword">extends</span> Manager&lt;Book&gt;{} <span class="code-keyword">public</span> class BookAction {    <span class="code-keyword">private</span> BookManager&lt;Book&gt; manager;}</pre>
				</div>
		</div>
		<h3>
				<a name="JDK5-%26nbsp%3B2.3%E5%85%B6%E4%BB%96%E5%BA%94%E7%94%A8">
				</a> 2.3 其他应用</h3>
		<p>   1. 在XFire中，List getBooksByCategory()函数返回的结果，需要用aegis.xml 文件声明List中的元素为Book.</p>
		<p>   而如果定义函数为 List&lt;Book&gt; getBooksByCategory()，就不再需要声明，省掉XMl配置文件。</p>
		<h2>
				<a name="JDK5-3.Annotation">
				</a>3.Annotation</h2>
		<p>     Annotation 大幅提升了Java的编程模式，SpringSide 目前运用的Annotation 有以下三个地方，幸运的是前两者同时也提供JDK1.4的JAVADoc式配置，只是麻烦一点点而已</p>
		<h3>
				<a name="JDK5-%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B3.1.HibernateAnnotation">
				</a>     3.1. Hibernate Annotation</h3>
		<p>         使用Hibernate Annotation 代替hbm文件，因为annotation高度的默认性，典型的POJO基本上不需要定义什么，代码的简约性和可管理性大幅提高，直追ROR。</p>
		<p>         另外，经过测试，annotation 完全能胜任一些比较复杂的Mapping定义，如Product-Book的父子继承关系，Order-OrderItem-Product的经典三角关系。</p>
		<h3>
				<a name="JDK5-%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B2.XFireJSR181Annotation">
				</a>     2. XFire JSR181 Annotation</h3>
		<p>         JSR181声明的Web Service，比原本用xml定义的模式节约了XML文件和配置代码的数量。</p>
		<h3>
				<a name="JDK5-%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B3.%26nbsp%3B%E5%A3%B0%E6%98%8EEntity%E7%B1%BB%E5%9E%8B%E7%9A%84Annotation">
				</a>     3. 声明Entity类型的Annotation</h3>
		<p>         使用Annotation 声明Entity的类型，比如Udeletable，Auditable 等，比用接口声明的方式有更少的侵入性，详见 <a title="InterfaceAnnotation" href="http://wiki.springside.org.cn/display/springside/InterfaceAnnotation">侵入，非侵入？Interface vs Annotation</a>。</p>
		<h2>
				<a name="JDK5-4.%E4%B8%89%E7%A7%8D%E5%86%85%E7%BD%AEAnnotation">
				</a>4. 三种内置Annotation</h2>
		<p>JDK5.0 有SuppressWarnings，Deprecated和Override 三种内置的annotation：</p>
		<h3>
				<a name="JDK5-%26nbsp%3B@Override">
				</a>  <b>@Override</b></h3>
		<p>   此标签一方面提醒用户这是个重载函数，另一方面保证了父类函数的参数或者名字改变时，子类如果没有跟着变化，就会编译不过。</p>
		<p>   虽然有点占地方，但用处的确很大，不会哪天子类被人卖了都不知道。</p>
		<p>  所以我设置了让IDEA6检查所有重载函数必须加上@Override标识。</p>
		<h3>
				<a name="JDK5-%26nbsp%3B@SuppressWarnings%28%22unchecked%22%29">
				</a>  <b>@SuppressWarnings("unchecked")</b></h3>
		<p>    此标签可以让编译器忽略某种warning信息，比如减少JDK5.0的集合操作引入范型后无处不在的warning。</p>
		<p>    因为有些非JDK5.0的开源库如hibernate, 函数返回的一定是List，而不会是List&lt;User&gt;，这时候IDE就会爆出很多warning。用SuppressWarning("unchecked")可以让IDE安静一些。</p>
		<p>    其他常用warning还包括 @SuppressWarnings("unused") 和 SuppressWarnings("serial")</p>
		<h3>
				<a name="JDK5-%26nbsp%3B@Deprecated">
				</a>  <b>@Deprecated</b></h3>
		<p>   此标签以前写在JavaDoc里，现在提到annotation，注释已废弃的函数。用户使用该函数的话，编译时会得到"你用了废弃"的提示。</p>
		<h2>
				<a name="JDK5-5.%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0">
				</a>5.可变参数</h2>
		<p>用于<span class="nobr"><a title="Visit page outside Confluence" href="http://www.springside.org.cn/docs/api/org/springside/core/commons/dao/HibernateGenericDao.html" rel="nofollow">HibernateGenericDao<sup><img class="rendericon" height="7" alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" width="7" align="absMiddle" border="0" /></sup></a></span>中，简化函数接口。</p>
		<p>比如 一个public List find(String hql, Object... values)，就支持了如下四种调用，避免了以前的煞费苦心的定义多种接口，然后把参数转成统一模式的大量重复定义。</p>
		<div class="preformatted">
				<div class="preformattedContent">
						<pre>dao.find(hql);
dao.find(hql,arg0);
dao.find(hql,arg0,arg1);
dao.find(hql,new Object[arg0,arg1])
</pre>
				</div>
		</div>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88181.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 15:28 <a href="http://www.blogjava.net/wuxufeng8080/articles/88181.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程编程的设计模式 临界区模式</title><link>http://www.blogjava.net/wuxufeng8080/articles/88160.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 06:18:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88160.html</guid><description><![CDATA[
		<p>
				<strong>
						<font color="#ff0000">多线程编程的设计模式 临界区模式(一)</font>
				</strong>
		</p>
		<p>临界区模式 Critical Section Pattern 是指在一个共享范围中只让一个线程执行的模式.<br />它是所有其它多线程设计模式的基础,所以我首先来介绍它.<br />把着眼点放在范围上,这个模式叫临界区模式,如果把作眼点放在执行的线程上,这个模式就叫<br />单线程执行模式.</p>
		<p>首先我们来玩一个钻山洞的游戏,我 Axman,朋友 Sager,同事 Pentium4.三个人在八角游乐场<br />循环钻山洞(KAO,减肥训练啊),每个人手里有一个牌子,每钻一次洞口的老头会把当前的次序,<br />姓名,牌号显示出来,并检查名字与牌号是否一致.</p>
		<p>OK,这个游戏的参与者有游乐场老头Geezer,Player,就是我们,还有山洞 corrie.</p>
		<p>public class Geezer {<br />    public static void main(String[] args){<br />        <br />        System.out.println("预备,开始!");<br />        Corrie c = new Corrie();//只有一个山洞,所以生存一个实例后传给多个Player.<br />        new Player("Axman","001",c).start();<br />        new Player("Sager","002",c).start();<br />        new Player("Pentium4","003",c).start();<br />    }<br />}</p>
		<p>这个类暂时没有什么多说的,它是一个Main的角色.</p>
		<p>public class Player extends Thread{<br />    private final String name;<br />    private final String number;<br />    private final Corrie corrie;<br />    public Player(String name,String number,Corrie corrie) {<br />        this.name = name;<br />        this.number = number;<br />        this.corrie = corrie;<br />    }<br />    <br />    public void run(){<br />        while(true){<br />            this.corrie.into(this.name,this.number);<br />        }<br />    }<br />}<br />在这里,我们把成员字段都设成final的,为了说明一个Player一旦构造,他的名字和牌号就不能改<br />变,简单说在游戏中,我,Sager,Pentium4三个人不会自己偷偷把自己的牌号换了,也不会偷偷地去<br />钻别的山洞,如果这个游戏一旦发生错误,那么错误不在我们玩家.</p>
		<p>import java.util.*;<br />public class Corrie {<br />    private int count = 0;<br />    private String name;<br />    private String number;<br />    private HashMap lib = new HashMap();//保存姓名与牌号的库<br />    <br />    public Corrie(){<br />        <br />        lib.put("Axman","001");<br />        lib.put("Sager","002");<br />        lib.put("Pentium4","003");<br /> <br />    }<br />    <br />    public void into(String name,String number){<br />        this.count ++;<br />        this.name = name;<br />        this.number = number;<br />        if(this.lib.get(name).equals(number))<br /> test():<br />    }<br />    <br />    public String display(){<br />        return this.count+": " + this.name + "(" + this.number + ")";<br />    }</p>
		<p>    private void test(){<br />        if(this.lib.get(name).equals(number))<br />            ;<br />            //System.out.println("OK:" + display());<br />        else<br />            System.out.println("ERR:" + display());<br />    }<br />}<br />这个类中增加了一个lib的HashMap,相当于一个玩家姓名与牌号的库,因为明知道Corrie只有一个实例,<br />所以我用了成员对象而不是静态实例,只是为了能在构造方法中初始化库中的内容,从真正意义中说应<br />该在一个辅助类中实现这样的数据结构封装的功能.如果不提供这个lib,那么在check的时候就要用<br />if(name.equasl("Axman")){<br /> if(!number.equals("001")) //出错<br />}<br />else if .......<br />这样复杂的语句,如果player大多可能会写到手抽筋,所以用一个lib来chcek就非常容象.</p>
		<p>
				<br />运行这个程序需要有一些耐心,因为即使你的程序写得再差在很多单线程测试环境下也能可是正确的.<br />而且多线程程序在不同的机器上表现不同,要发现这个例子的错识,可能要运行很长一段时间,如果你的<br />机器是多CPU的,那么出现错误的机会就大好多.</p>
		<p>在我的笔记本上最终出现错误是在11分钟以后,出现的错误有几钟情况:<br />1: ERR:Axman(003)<br />2: ERR:Sager(002)<br />第一种情况是检查到了错误,我的牌号明明是001,却打印出来003,而第二种明明没有错误,却打印了错误.</p>
		<p>事实上根据以前介绍的多线程知识,不难理解这个例子的错误出现,因为into不是线程安全的,所以在其中<br />一个线程执行this.name = "Axman";后,本来应该执行this.numner="001",却被切换到另一个线程中执行<br />this.number="003",然后又经过不可预知的切换执行其中一个的if(this.lib.get(name).equals(number))<br />而出现1的错误,而在打印这个错误时因为display也不是线程安全的,正要打印一个错误的结果时,由于<br />this.name或this.number其中一个字段被修改却成了正确的匹配而出现错误2.</p>
		<p>另外还有可能会出现序号颠倒或不对应,但这个错误我们无法直观地观察,因为你根本不知道哪个序号"应该"<br />给哪个Player,而序号颠倒则有可能被滚动的屏幕所掩盖.</p>
		<p>
				<br />[正确的Critical Section模式的例子]<br />我们知道出现这些错误是因为Corrie类的方法不是线程安全的,那么只要修改Corrie类为线程安全的类就行<br />了.其它类则不需要修改,上面说过,如果出现错误那一定不是我们玩家的事:</p>
		<p> </p>
		<p>import java.util.*;<br />public class Corrie {<br />    private int count = 0;<br />    private String name;<br />    private String number;<br />    private HashMap lib = new HashMap();//保存姓名与牌号的库<br />    <br />    public Corrie(){<br />        <br />        lib.put("Axman","001");<br />        lib.put("Sager","002");<br />        lib.put("Pentium4","003");<br /> <br />    }<br />    <br />    public synchronized void into(String name,String number){<br />        this.count ++;<br />        this.name = name;<br />        this.number = number;<br /> test();<br />    }<br />    <br />    public synchronized String display(){<br />        return this.count+": " + this.name + "(" + this.number + ")";<br />    }</p>
		<p>    private void test(){<br />        if(this.lib.get(name).equals(number))<br />            ;<br />            //System.out.println("OK:" + display());<br />        else<br />            System.out.println("ERR:" + display());<br />    }<br />}</p>
		<p>运行这个例子,如果你的耐心,开着你的机器运行三天吧.虽然测试100天并不能说明第101天没有出错,<br />at least,现在的正确性比原来那个没有synchronized 保护的例子要可靠多了!</p>
		<p>到这里我们对Critical Section模式的例程有了直观的了解,在详细解说这个模式之前,请想一下,test<br />方法安全吗?为什么?<br /><br /></p>
		<p>所谓模式就是脱离特定的例子使用更一般化的,通用化的表达方式来察看,描述,总结相同的问题.现在<br />我们来研究这个模式:<br /><br />共享资源(sharedResource)参与者:<br />在临界区模式中,一定有一个或一个以上的共享资源角色的参与.在上面这个例子中就是山洞(Corrie).<br /><br />共享资源参与者会被多个线程访问,这个角色的访问方法有两种类型,一种是多个线程访问也不会发生问<br />题的方法,称为线程安全的方法,另一种就是在多个线程同时访问时会发生问题需要保护的方法,称为不安<br />全的方法.<br /><br /><br />这里所说的线程安全和不安全的方法,不用多说大家都知道是指公开的方法.对上节最后我留下的问题而<br />言,test方法是安全的,因为它是private的,只会被into方法调用,而into方法是同步的,简单说test中的<br />代码一定会在同步块中执行,而display方法是public的,有可能被任何线程调用,所以它需要同步.<br /><br />对于线程安全的方法,不需要多说.而对于不安全的方法,只要定义为synchronized的就可以达到保护的<br />目的.也就是多个线程同时执行该段代码时,只有一个线程有机会执行,具体机制我们在多线程中同步对象<br />锁中已经说明过.我们把这种只有一个线程能进入的程序范围,称为[临界区]<br /><br /><br />尽管JDK5以后提供了很多功能更强,语义更准确的并发控制的接口供程序员调用,但我还是极力推荐在大<br />多数情况下(除非需要有效的控制)还是使用synchronized来保护临界区,因为synchronized块的开始和结<br />束是自动控制的,在离开同步块时会自动释放同步对象锁.而使用java的lock对象时,你不得不每时每刻小<br />心地在finally从句中调用lock对象的unlock方法,这比在finally从句中释放数据库连结更重要!<br /><br />[适用环境]<br /><br />1.单线程环境:单线程环境中肯定只有一个线程执行,无论是否在临界区中反正只有一个线程执行,所以没<br />有必要用synchronized保护,当然如果你非想用synchronized保护没有问题,只是会引起性能的降低,但不<br />会降低太大.这就象一个人在家里已经关上了大门,还关着卧室的小门,除了会给你带来一些不便之处,没有<br />什么太大的损失.<br /><br />2.多线程环境:如果这些多线程环境中各自完全独立地运行,当然没有问题.但如果多个线程可能访问同一<br />SharedResource对象时,就需要使用临界区模式来保护.有时管理线程的环境会提供一种SafeThread环境来<br />确保线程的独立,这种情况就不需要使用临界区模式.<br /><br />3.SharedResource的状态会发生改变的情况才需要使用这个模式,如果SharedResource对象一经生成就不<br />会改变,当然不需要保护.(只读模式)<br /><br />4.在必要的确保安全性的时候使用这个模式.比如java数据结构类大多数都不是线程安全的.因为很多情况<br />下发生多个线程共享冲突对程序本身并无大碍,比如用一个ArrayList或HashMap存放在线人数,对于在线<br />人数这种数据本来就不可能精确地计算,只是相对时间内的一个概数,所以多个线程访问对产生冲突对其几<br />乎没有影响.<br />但是对于需要确保线程安全的时候,java仍然提供了大量的线程安全的数据结构的封装,由Collections类<br />提供的synchronizedXXX()方法可以将传入的数据结构封装为线程安全的.<br /><br /><br />[性能因素]<br />在程序设计中,大多数情况下,各种优点无法共存,事实上如果使用一个模式能给其它方面的优点也带来提<br />升那简单就没有理由不使用该模式了.对于安全性的提升往往要以牺牲性能为代价,所以临界区模式会带来<br />一些性能方面的损失.如何权衡这它们之间的比例,要看程序运行的环境,目的等各方面的因素.<br /><br />1.获取对象锁的操作本身是要花时间的.一个线程在获取同步对象锁时,其实就是一个全局对象的自旋锁,这<br />个全局对象是要注册到线程管理系统中的.这个过程本身需要一定的时间.但这个过程性能影响并不大.<br /><br />2.同步对象锁被其它线程占用时需要等待.当一个线程进入同步块时,获取该同步对象的锁,如果该锁被其它<br />线程拥有测当前线程必须等待,从而降低性能,这方面性能的降低较大.<br /></p>
		<p>提高性能的方法一是尽量减少共享资源的数量.二是尽量减小临界区的范围.双检锁模式就是减小临界区范</p>
		<p>围的一种手段.</p>
		<p>
				<br />
				<br />[死锁问题]<br />临界区模式中非常重要的一点是多线程程序的生命指数.再安全的程序如果运行一定时间就结束自己的生命<br />而不能继续运行,那就根本不能达到设计的目的.除去系统突发因素,影响生命指数的最大原因就是死锁.<br />对于大家都熟悉的五个哲学家(好象是故意调侃哲学家)吃面条的例子,我们用最简单的模型简单为两个哲学<br />家.然后从中抽象出死锁的最一般的条件:<br /><br />1.有多个共享资源被多线程共享.对于两个吃面的哲学家而言就是刀和叉两上以上的共享资源.<br /><br />2.对一个共享资源的占用还没有释放锁又获取另一个共享资源.占用了刀的时候又要获取叉.<br /><br />3.对共享资源的占用顺序是不固定的.如果哲学家按一定顺序使用刀和叉,一个用完了思考时再让给另一个<br />用那就能很好地完成目标而不会发生死锁,正时因为对共享资源占用的顺序是无法确定的.当一个结程占用<br />一个共享资源时,要获取另一个线程占用的共享资源,而另一个线程释放这个共享资源的条件是以获取被原<br />先被占用的共享资源时,才会发生死锁.<br /><br />所以如果我们破坏上面其中之一的条件就不会发生死锁问题,也就是在设计时要考虑不要同时发生上面的<br />三程情况.<br /><br />[嵌套锁定]<br />对于同一对象的嵌套锁定,例子如下:<br />synchronized(this){//1<br />    System.out.println("outter");<br />    synchronized(this){//2<br />        System.out.println("inner");<br />    }<br />}<br />这个例子能运行吗?答案是可以很好地运行.<br />一般以为线程运行到1时,获取了当前对象锁,打印outter后,运行到2,又要获取当前对象锁,而此时当前对象<br />锁还没有释放,所以线程一直等在这儿发生死锁.<br />其实java是一种smart language,在编译的时候,它就会检查对同一对象的嵌套锁定.因为不可能发生在层同<br />步块中有多个线程进入而其中一个线程要进入内层同步块的情况,也就是外层同步块本身就可以保证只有一<br />个线程获取同步对象的锁,所以内层同一对象的同步块在编译的时候已经失去它的作用.<br /><br />[继承和扩展]<br />对于临界区模式而言,即使我们已经使用synchronized方法对共享资源进行保护,但是子类在扩展接口时很可<br />能将共享资源以不安全方式暴露出去.这是非常值得注意的问题.设计时应该尽时将对共享资源的访问方法加<br />以保护,可以使用private和final等限制,另外在子类设计时也要充分考虑对父类共享资源的访问.<br /></p>
		<p>[高级主题:关于synchronized]</p>
		<p>其实在多线程编程基础部分,我已经谈过synchronized相关的内容.但临界区模式是其它多线程编程模式的基<br />础,所以在这里继续深入一下谈谈synchronized相关的一些内容.</p>
		<p>只要见到synchronized关键字,第一要想到的问题就是,synchronized在保护谁?</p>
		<p>在上面的例子中,synchronized保护的是Corrie对象的counter,name,number三个字段不被"交差赋值",也就是<br />这三个字段同时只能被一个线程访问.<br />其次我们要考虑的问题是:这些对象都被妥善地保护了吗?</p>
		<p>这是非常重要的问题.无论你花巨资打造一把高安全性锁,把自己的家门牢牢地锁住,可是你却把门旁边的窗子<br />敞开着,那么你花巨资打造的锁又要什么意义呢?所以要确保从任何一个通道访问被保护的对象都被加锁控制<br />的,比如字段是否都private或protected的,对于protected的子类中的扩展方法是否能保护被保护对象.</p>
		<p>对于上面的例子因为display有可能被外面的方法单独调用,所以它也必须是同步的.而test方法只会在into中<br />调用,简单说它只是所有通道被加了锁的大房子中的一个小单元,所以不必担心有人会从外部访问它.</p>
		<p>要注意保护的范围是三个同时需要保护的字段,如果它们被分别放在synchronized方法中保护,并不能保证它们<br />本个字段同时只有一个线程访问.</p>
		<p>那么我们就有一个问题,获取谁的锁呢?</p>
		<p>要保护一个对象,当然直接获取这个对象的锁,我们上面的例子可以理解为要同时保护三个对象,那么其实就是<br />要保护这个本个对象的容器.也就是它们所在的实例.如果不相关的三个对象要同时保护,一定要放在同时容纳<br />它们的容器中,否则无法同时保护它们的状态.对于上面的例子我们同样可以理解为要保护的是Corrie的实例,<br />因为这个实例是这三个字段的容器.所以我们用synchronized方法就是等同于synchronized(this){.......}<br />如果这个游戏中有多个山洞,而只有一块显示牌,那以我们就需要保护多个实例的三个字段同时只被一个线程<br />访问,我们就需要synchronized(Corrie.class)来保证多个实例被多个线程访问时只有一个对程能同时对三个<br />字段访问.<br />所以获取谁的锁定也是一个很重要的问题,如果你选择了错误的对象,就象你花巨资打了一把锁却锁了别人的<br />门.</p>
		<p>synchronized就是原子操作,简单说在一个线程进行同步块中的代码时不能进入,这是很明显的.但同时,多个<br />同步方法或多个获取同一对象的同步块在同一时候也只能一个线程能访问其中之一,因为控制谁能访问的是要<br />获得那个同步对象的锁.如:<br />class C{<br /> synchronized  a(){}<br /> synchronized  b(){}<br />}</p>
		<p>当一个线程进入同步方法a后那么其它线程当然不能进入a,同时也不能进入b,因为能进入的条件是获取this对<br />象的锁.一个结程进入a后this对象的锁被这个线程获取,其它线程进入b也同样要获取这个锁,而不仅仅是进入<br />a要获取这个锁.这一点一定要理解.</p>
		<p>理解上面的知识我们再回过头来看原子操作.</p>
		<p>JLS规定对于基本类型(除long和double)以外的赋值和引用都是原子操作,并且对于引用类型的赋值和引用也是<br />原子操作.</p>
		<p>注意这里有两个方面的知识点:</p>
		<p>1.对于long和double的操作非原子性的.需要说明这只是JLS的规定,但大多数JVM的实现其实已经保证了long和<br />double的赋值和引用也是原子性的,只是允许某种实现可以不是原子性的操作.</p>
		<p>对于其它基本类型如int,如果一个线程执行x = 1;另一个线程执行x = 2;<br />由于可见性的问题(多线程编程系统中已经介绍),x要么就是1,要么就是2,看谁先同步到主存储区.</p>
		<p>但对于long,l = 1;l = 2;分别由两个线程执行的结果有可能不是你想象的,它们有可能是0,或1,或2,或一个其<br />它的随机数,简单说两上线程中l的值的部分bit位可能被另一个线程改写.所以最可靠的是放在synchronized中<br />或用volatile 保护.当然这里说的是"有非常可靠的需要",一般而言现在的JVM已经能保证long和double也是原<br />子操作的.</p>
		<p>2.我们看到,对于引用对象的赋值和引用也是原子的.</p>
		<p>我们还是看javaworld上dcl的例子.</p>
		<p> 那个错误的例子误了好多人,(JAVA与模式的作者就是受害人),我们先不说JAVA内存模型的原因(前面我已经从<br />JAVA内存模型上说明了那个例子是错误的,我是说对那个例子的分析是错误的).单从对于"引用对象的赋值和引<br />用也是原子的"这句话,就知道对于引用字段的赋值,绝对不可能出现先分配空间,然后再还没有被始化或还没有<br />调构造方法之前又被别的线程引用.因为当一个线程在执行赋值的时候是原子性的操作,其它线程的引用操作也是原子性的操作 的,在赋值操作没有完成之前其它线程根本不可能见到"分配了空间却没有<br />初始化或没有调用构造方法"的这个对象.<br /><br />不知道什么原因,这样的一个例子从它诞生开始竟然是所有人都相信了,也许有人责疑过但我不知道.如果你有足<br />够的基础知识,就不必跟着别人的感觉走!<br /></p>
		<p>因为这是一个最最基础的模式,暂时不介绍它与其它模式的关系.在以后介绍其它模式时反过来再和它进行比较.</p>
		<p>而一些复杂的模式都是在这个简单的模式的基础上延伸的.</p>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 14:18 <a href="http://www.blogjava.net/wuxufeng8080/articles/88160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程编程的设计模式 不变模式(zt)</title><link>http://www.blogjava.net/wuxufeng8080/articles/88158.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 06:16:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88158.html</guid><description><![CDATA[
		<div>
				<a href="http://blog.csdn.net/axman/category/231455.aspx">http://blog.csdn.net/axman/category/231455.aspx</a>
				<br />多线程编程的设计模式 不变模式(一)</div>
		<div>虽然这个模式的名称已经有人介绍过,但我仍然要以我的方式来介绍它,因为我对这个模式要说的</div>
		<div>东西比现有的我所能看到的介绍更全面更深入.</div>
		<div> </div>
		<div>一.不变模式需要的基础.</div>
		<div>模式虽然显得高深,但学习它的难度很低,即使你只是一个中级水平的程度员,也可以在很短的时候</div>
		<div>学会一个模式(当然要能正确地运用那需要丰富的经验积累).对于基础知识的深入才是一个优秀的</div>
		<div>程序员所具备有必要条件.</div>
		<div> </div>
		<div>我下面要说的话不是说国内没有基础深厚的java技术人员,而是说没有基础深厚却又能说清楚让别</div>
		<div>人也深厚起来的人.简单说高手随处可见,但可以做师父的高手我没有见到.那么就让我这个不是高</div>
		<div>手的人来补一堂Java最最基础的知识吧.</div>
		<div> </div>
		<div>基础类型和引用类型的内存布局:</div>
		<div>int x = 1;</div>
		<div>int y = x;</div>
		<div>x ++;</div>
		<div>System.out.println(y);</div>
		<div>有99.99%的Java程序员都知道y为1.当把类型为int的变量x作为类型为y的变量的值时,堆栈中会产生一个与x同样大小的值,但无法改变它们是两个不同的副本事实.它们互不相关,仅仅是在”创建” y的依据,完成后它们之间没有任何关系,既然没有任何关系,当然修改其中一个就不会影响另一个.这时它们有内存布局为:</div>
		<div>
				<span>       <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/axman/1.jpg" /></span>
		</div>
		<div>为了简化说明引用类型我们用Integer来作为例子.它的值作为它最重要的属性被表示出来:</div>
		<div> </div>
		<div>Integer x  =  new Integer(100);</div>
		<div>Integer y  =  x;</div>
		<div>这时正确的表述为产生了两个指向同一对象的变量(或引用).只要看它们的内存而局就知道它们的意义了:</div>
		<div> </div>
		<div>
				<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/axman/2.JPG" />
		</div>
		<div> </div>
		<div>对于引用类型,改变引用本身并不影响其它指向同一对象的引用,改变引用本身就是把引用指点向另一个对象,简单说就是重新赋值.假如 x = new Integer(101);那么它并不影响y指向原来的100.</div>
		<div>但改变对象的内容则同时影响其它指向同一引用的变量,因为Integer被设计为不变模式,所以我们目前不能修改它的内容,也就是不能个性100为101.下面的内容中会介绍修改对象内容.</div>
		<div>
		</div>
		<div>对于引用参数传递,方法外的引用和方法内的引用虽然变量名在语法相同,但实际变量本身因为作用范围原因是不</div>
		<div>同的,但它们都指向同一对象.</div>
		<div>StringBuffer sb = new StringBuffer("xxxx");</div>
		<div>amethod(sb){</div>
		<div>  </div>
		<div>}</div>
		<div>这是发生的内存而局如下:</div>
		<div>
				<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/axman/3.JPG" />
		</div>
		<div> </div>
		<div>在没有以不变模式来介绍String的时候,我们先来看String类的其它几个属性,其实String类要说的东西太多,这里只说几个必要的知识:</div>
		<div>
				<span>       String s1 = “1111”;</span>
		</div>
		<div style="TEXT-INDENT: 21pt">String s2 = “1111”;</div>
		<div style="TEXT-INDENT: 21pt">String 是唯一可以直接赋常量值的类(这只是对于程序员而言,也就从语法而言),对于这样的字面值赋值,其底层就是调用String s1 = new String(“1111”). .intern();</div>
		<div style="TEXT-INDENT: 21pt">即先在字符串缓存池中查找是否有字符常量”1111”,如果有测将s1指向这个对象.没有则先创建对象放入字符串缓存池,然后将s1指向它,并销毁堆中的对象,当String s2 = “1111”;时仍然是调用</div>
		<div style="TEXT-INDENT: 21pt">String s2 = new String(“1111”). .intern();这时已经找到字符常量”1111”,所以s2也指向了字符串缓存池中那个对象,并销毁了堆中的”1111”,这样做的结果就是直接赋字面值的语句如果字面值相同它们就都指向同一对象.</div>
		<div style="TEXT-INDENT: 21pt"> </div>
		<div style="TEXT-INDENT: 21pt">因为字符串类是不变模式最典型的代表,所以其它的知识将在下面继续介绍.<br /><br />多线程编程的设计模式 不变模式(二)
<p> 不变模式(Immutable Pattern)顾名思义,它的状态在它的生命周期内是永恒的(晕,<strong>永恒的日月星晨,对象如人,<br />太渺小,谈不上永恒!</strong>),不会改变的.对于其中的不变类(Immutable Class),它的实例可以在运行期间保持状态永远不会被<br />改变,所以不需要采取共享互斥机制来保护,如果运用得当可以节省大量的时间成本.</p><p> 请注意上面这段话,不变模式其中的不变类,说明不变类只是不变模式中一个组成部分,不变类和与之相辅的可变<br />类,以及它们之间的关系才共同构成不变模式!所以在涉及不变模式的时候一定要研究一个类是不变的还是可变的(Mutable).<br />在jdk中的String类和StringBuffer类就组成了一个不变模式.</p><p>还是先看具体的例子:</p><p>final class Dog{<br />    private final String name;<br />    private final int age;<br />    public Dog(String name,int age){<br />        this.name = name;<br />        this.age = age;<br />    }<br />    <br />    public String getName(){return this.name;}<br />    public int getAge(){return this.age;}<br />    <br />    public String toString(){<br />        return "Dog's name = " + this.name + ",age = " + this.age;<br />    }<br />}</p><p>1.Dog类本身被声明为final,可以保证它本身的状态不会被子类扩展方法所改变.<br />2.Dog类的所有成员变量都是final的,保证它在构造后不会被重新赋值.而且Dog类所有属性是private的,只提供getter访问.<br />3.Dog类的能传入的参数本身是Immutable的.这一点非常重要将在下面具体说明.<br />以上条件都是必要条件,而不是充要条件.</p><p>class DisplayDog extends Thread{<br />    private Dog dog;<br />    public DisplayDog(Dog dog){<br />        this.dog = dog;<br />    }<br />    <br />    public void run(){<br />        while(true){<br />            System.out.println(this.getName() + " display: " + dog);<br />        }<br />    }<br />}</p><p>DisplayDog类是把一个Dog对象传入后,不断显示这个dog的属性.我们会同时用多个线程来显示同一dog对象,看看它们在共享<br />同一对象时对象的状态:<br />public class Test {<br />    public static void main(String[] args) throws Exception {<br />        Dog dog = new Dog("Sager",100);<br />        new DisplayDog(dog).start();<br />        new DisplayDog(dog).start();<br />        new DisplayDog(dog).start();<br />    }<br />}<br />运行这个例子你可以等上一个月,虽然运行一年都正常并不能说明第366天不出现异常,但我们可以把这样的结果认为是一种<br />说明.多个线程共享一个不变类的实例时,这个实例的状态不会发生改变.事实上它没有地方让你去改变.<br />在临界区模式中有些操作必须只允许有一个线程操作,而这个类本身以及对它的访问类中并不需要进行临界区保护,这就让多<br />个线程不必等待从而提高了性能.</p><p>既然有这么好的优势,那我们在需要临界区保护的对象为什么不都设计成不变类呢?</p><p>1.不变类设计起来有一定难度.对于上面这个用来示例的Dog,由于其本身的属性,方法都很简单,我们还可以充分地考虑到可<br />以改变它状态的各种情况.但对于复杂的类,要保证它的不变性,是一个非常吃力的工作.<br /> <br />不变类中,任何一个必要都件都不是充要条件,虽然连老骨灰都没有这么说过,但我还是要真诚地目光深邃语气凝重地告诉你.<br />没有任何条件是充要条件的意思就是如果任何一个必要条件你没考虑到,那它就会无法保证类的不可变性.没有规范,没有模<br />板,完全看一人设计人员的经验和水平.也许你自以为考虑很全面的一个"不变类"在其他高手面前轻而易举地就"可变"了.</p><p>2.不变类的种种必要条件限制了类设计的全面性,灵活性.这点不用多说,简单说因为是不变类,所以你不能A,因为是不变类,你<br />不能B.</p><p>当然,如果你是一人很有经验的设计者,你能成功地设计一个不变类,但因为它的限制而失去一些功能,你就要以使用与之相辅<br />的可变类.并且它们之间可以相互转换,在需要不变性操作的时候以不变类提供给用户,在需要可变性操作的时候以可变类提供<br />给用户.</p><p>在jdk中String被设计为不可变类,一旦生成一个String对象,它的所有属性就不会被变,任何方法要么返回这个对象本身的原<br />始状态,要么抛弃原来的字符串返回一个新字符串,而绝对不会返回被修改了的字符串对象.<br />但是很多时候返回新字符串抛弃原来的字符串对象这样的操作太浪费资源了.特别是在循环地操作的时候:</p><p> String s = "Axman";<br /> for(int i=0;i&lt;1000*1000;i++) s += "x";这样的操作是致命的.<br />那么这种时候需要将原始的不变的s包装成可变的StringBuffer来操作,性能的改变可能是成千上万倍:</p><p>        StringBuffer sb = new StringBuffer(s); //将不变的String包装成可变的String;<br />        for(int i=0;i&lt;1000*1000;i++)<br />            sb.append("x");<br />        s = new String(sb); //将可变类封装成不变类.虽然可以调用toString(),但那不是可变到不变的转换.</p><p>在将可变类封装到不变类的时候要特别小心.因为你传入的引用在外面是可以被修改的.所以即使你不变类本身不能去改变属<br />性但属性有一个外部引用.可以在外面修改:</p><p>final class MutableDog{<br />    private String name;<br />    private int age;<br />    public MutableDog(String name,int age){<br />        this.name = name;<br />        this.age = age;<br />    }<br />    public synchronized void setDog(String name,int age){<br />        this.name = name;<br />        this.age = age;<br />    }<br />    public String getName(){return this.name;}<br />    public int getAge(){return this.age;}</p><p>    public synchronized String toString(){<br />        return "Dog's name = " + this.name + ",age = " + this.age;<br />    }<br />    <br />     public synchronized ImmatableDog getImmatableDog(){<br />         return new ImmatableDog(this);<br />     }<br />}</p><p>final class ImmatableDog{<br />    private final String name;<br />    private final int age;<br />    public ImmatableDog(String name,int age){<br />        this.name = name;<br />        this.age = age;<br />    }<br />    <br />    public ImmatableDog(MutableDog dog){<br />        this.name = dog.getName();<br />        this.age = dog.getAge();<br />    }    <br />    <br />    public String getName(){return this.name;}<br />    public int getAge(){return this.age;}<br />    <br />    public String toString(){<br />        return "Dog's name = " + this.name + ",age = " + this.age;<br />    }<br />}</p><p><br />MutableDog类是可变的,可以满足我们利用对象的缓冲来让对象成为表示另一个实体的功能.但它们之间<br />随时可以根据需要相互转换,但是我们发现:<br />    public ImmatableDog(MutableDog dog){<br />        this.name = dog.getName();<br />        this.age = dog.getAge();<br />    }<br />这个方法是不安全的.当一个属性为"Sager",100的dog被传进来后,执行this.name = dog.getName();后,<br />如果线程切换到其它线程执行,那么dog的属性就可能是"p4",80,这时再执行this.age = dog.getAge();<br />我们就会得到一个属性为"Sager",80的这样一个错误的不可变对象.这是一个非常危险的陷井.在这里我们<br />可以通过同上来解决:<br />    public ImmatableDog(MutableDog dog){<br />        synchronized(dog){<br />            this.name = dog.getName();<br />            this.age = dog.getAge();<br />        }<br />    }<br />注意这里同步的MutableDog,它将会和MutableDog的setDog产生互斥.它们都需要获取同一MutableDog对象的<br />锁,如果MutableDog的setDog不是方法同步(synchronized(this)),即使ImmatableDog(MutableDog dog)中同步<br />了dog,也不能保证安全,它们需要在同一对象上互斥.</p><p>但同步也并不一定能保证传入的参数不可变:</p><p>我曾以下面这个例子来作为对一个Java程序员的终极测试,终极测试的意思是说,如果你不懂并不说明你水平<br />差,但如何你懂这个问题那就没有必要测试其它问题了.</p><p>    public static void test(Object[] objs){<br />        java.security.BasicPermission bp  =  xxxxx;</p><p>        for(Object o: objs){<br />            bp.checkGuard(o);<br />        }<br />        for(Object o: abjs){<br />            o.xxx;<br />        }<br />    }<br />当一个数据被传入后我们需要对其中的每个元素做安全性检查,如果通不过bp.checkGuard(o);自己会抛出<br />异常的.但如果objs[0]被bp.checkGuard(o);过后,外面的线程通过objs去修改objs[0],这时就会把一个没有<br />经过安全检查的对象绕过bp.checkGuard(o);而直接被调用.假如Runtime.exec(String[] args)就是这样实<br />现我们可以想象会出现什么问题.</p><p>所以对于这样的传入参数,我们可以将其在方法类复制为本地变量(数组).或使用它的深度clone,打断与方法<br />外的联系:</p><p>    public static void test(Object[] objs){<br /> Object tmp = new Object[objs.lenth];<br /> System.arrayCopy(objs,tmp,0,0,objs.lenth);<br /> java.security.BasicPermission bp  =  xxxxx;</p><p>        for(Object o: tmp){<br />            bp.checkGuard(o);<br />        }<br />        for(Object o: tmp){<br />            o.xxx;<br />        }<br />    }</p><p><br />先说到这里吧.休息一下. </p></div>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88158.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 14:16 <a href="http://www.blogjava.net/wuxufeng8080/articles/88158.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JFreeChart介绍及经典入门资料(ZT)</title><link>http://www.blogjava.net/wuxufeng8080/articles/62635.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Wed, 09 Aug 2006 12:10:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/62635.html</guid><description><![CDATA[
		<font color="#993300">一、JFreeChart获取。<br />        JFreeChart是JFreeChart公司在开源网站SourceForge.net上的一个项目，该公司的主要产品有如下：<br />        1、JFreeReport：报表解决工具<br />        2、JFreeChart：Java图形解决方案（Application/Applet/Servlet/Jsp）<br />        3、JCommon：JFreeReport和JFreeChart的公共类库<br />        4、JFreeDesigner：JFreeReport的报表设计工具<br /><br />    我们可以从jfree官方网站上获取最新版本和相关资料（但是jfree的document需要40美金才能获取），<br />    获取地址：</font>
		<a href="http://www.jfree.org/jfreechart/index.html">
				<font color="#993300" size="3">http://www.jfree.org/jfreechart/index.html</font>
		</a>
		<font color="#993300" size="3">（同时可以获得简明介绍）<br />    我们以当前最新版本：jfreechart_0.9.21.zip为例子进行说明。<br /><br />二、JFreeChart配置安装<br />    1、解压jfreechart_0.9.21.zip到指定位置，其中source是jfreechart的源码，jfreechart-0.9.21-demo.jar<br />       是例子程序（该部分留给大家自己去研究）<br />    2、为了配置成功，我们需要关注的文件有如下三个：jfreechart-0.9.21.jar、lib\jcommon-0.9.6.jar、<br />       lib\gnujaxp.jar<br />    3、如果是Application开发，把上述三个文件拷贝到%JAVA_HOME%\LIB中，同时在环境变量CLASSPATH中加入<br />       如果是WEB开发，以TOMCAT中的一个WEB项目TEST为例子说明：<br />       把上述三个文件拷贝到TEST\WEB-INF\LIB中，然后修改TEST\WEB-INF\web.xml文件，在其中加入如下代码：<br />                &lt;servlet&gt;<br />                    &lt;servlet-name&gt;DisplayChart&lt;/servlet-name&gt;<br />                    &lt;servlet-class&gt;org.jfree.chart.servlet.DisplayChart&lt;/servlet-class&gt;<br />                &lt;/servlet&gt;<br />                &lt;servlet-mapping&gt;<br />                    &lt;servlet-name&gt;DisplayChart&lt;/servlet-name&gt;<br />                    &lt;url-pattern&gt;/servlet/DisplayChart&lt;/url-pattern&gt;<br />                &lt;/servlet-mapping&gt;<br />               至此jfreechart的配置就完成了，下面就可以进行jfreechart的开发了。这里值得提出的是jfreechart的类<br />       结构设计前后兼容性不是很好，不同版本的jfreechart中类库结构可能不一样，有时候可能需要查源码。如果<br />       是中文显示的时候可能依据观感需要改变源码的字体，不过我个人觉得这个版本比以前版本要好一些。<br /><br />三、JFreeChart功能介绍<br />    JFreeChart目前是最好的java图形解决方案，基本能够解决目前的图形方面的需求，主要包括如下几个方面：<br />    pie charts (2D and 3D)：饼图（平面和立体）<br />    bar charts (regular and stacked, with an optional 3D effect)：柱状图<br />    line and area charts：曲线图<br />    scatter plots and bubble charts<br />    time series, high/low/open/close charts and candle stick charts：时序图<br />    combination charts：复合图<br />    Pareto charts<br />    Gantt charts：甘特图<br />    wind plots, meter charts and symbol charts<br />    wafer map charts<br />    (态图表,饼图(二维和三维) , 柱状图 (水平,垂直),线图,点图,时间变化图,甘特图, 股票行情图,混和图, 温度计图, 刻度图等常用商用图表)<br />    图形可以导出成PNG和JPEG格式，同时还可以与PDF和EXCEL关联<br />    <br />    JFreeChart核心类库介绍：<br />            研究jfreechart源码发现源码的主要由两个大的包组成：org.jfree.chart,org.jfree.data。其中前者主要与图形<br />    本身有关，后者与图形显示的数据有关。具体研究如果大家有兴趣的话可以自己研究，以后有时间我会告诉大家怎么去<br />    研究源码。<br />         核心类主要有：<br />           org.jfree.chart.JFreeChart：图表对象，任何类型的图表的最终表现形式都是在该对象进行一些属性的定制。JFreeChart引擎本身提供了一个工厂类用于创建不同类型的图表对象<br />           org.jfree.data.category.XXXDataSet:数据集对象，用于提供显示图表所用的数据。根据不同类型的图表对应着很多类型的数据集对象类<br />           org.jfree.chart.plot.XXXPlot：图表区域对象，基本上这个对象决定着什么样式的图表，创建该对象的时候需要Axis、Renderer以及数据集对象的支持<br />           org.jfree.chart.axis.XXXAxis：用于处理图表的两个轴：纵轴和横轴<br />           org.jfree.chart.render.XXXRender：负责如何显示一个图表对象<br />           org.jfree.chart.urls.XXXURLGenerator:用于生成Web图表中每个项目的鼠标点击链接<br />           XXXXXToolTipGenerator:用于生成图象的帮助提示，不同类型图表对应不同类型的工具提示类<br />    <br />四、JFreeChart开发（Application/Applet）<br />1、pie charts，代码如下<br />/**<br /> * Description:This application is the first jfreechart<br /> * Datetime:20058-02-11<br /> */<br />package demo;<br /><br />import org.jfree.chart.JFreeChart;<br />import org.jfree.chart.ChartFactory;<br />import org.jfree.chart.ChartFrame;<br />import org.jfree.data.general.DefaultPieDataset;<br /><br />public class FirstJFreeChart {<br />  public FirstJFreeChart() {<br />  }<br />  <br />  public static void main(String[] args){<br />    DefaultPieDataset dpd = new DefaultPieDataset();<br />    dpd.setValue("管理人员",25);<br />    dpd.setValue("市场人员",25);<br />    dpd.setValue("开发人员",45);<br />    dpd.setValue("其他人员",5);<br />    <br />    //Create JFreeChart object<br />    //参数可以查看源码<br />    JFreeChart pieChart = ChartFactory.createPieChart("CityInfoPort公司组织架构图",dpd,true,true,false);<br />    ChartFrame pieFrame = new ChartFrame("CityInfoPort公司组织架构图",pieChart);<br />    pieFrame.pack();<br />    pieFrame.setVisible(true);<br />  }<br />}<br /><br />上面例子可以进一步改进，如下：<br />/**<br /> * Description:This application is the first jfreechart<br /> * Datetime:20058-02-11<br /> */<br />package com.cityinforport.demo;<br /><br />import org.jfree.chart.JFreeChart;<br />import org.jfree.chart.ChartPanel;<br />import org.jfree.chart.ChartFactory;<br />import org.jfree.chart.ChartFrame;<br />import org.jfree.data.general.DefaultPieDataset;<br />import org.jfree.chart.plot.PiePlot;<br />import org.jfree.data.general.PieDataset;<br />import org.jfree.ui.ApplicationFrame;<br />import org.jfree.ui.RefineryUtilities;<br />import java.awt.Font;<br />import javax.swing.*;<br /><br /><br />public class FirstJFreeChart extends ApplicationFrame {<br />  //构造函数<br />  public FirstJFreeChart(String s){<br />    super(s);<br />    setContentPane(createDemoPanel());<br />  }<br />  <br />  public static void main(String[] args){<br />    FirstJFreeChart fjc = new FirstJFreeChart("CityInfoPort公司组织架构图");<br />    fjc.pack();<br />    RefineryUtilities.centerFrameOnScreen(fjc);<br />    fjc.setVisible(true);<br />  }<br />  <br />  //生成饼图数据集对象<br />  public static PieDataset createDataset(){<br />    DefaultPieDataset defaultpiedataset = new DefaultPieDataset();<br />    defaultpiedataset.setValue("管理人员",10.02D);<br />    defaultpiedataset.setValue("市场人员",20.23D);<br />    defaultpiedataset.setValue("开发人员",60.02D);<br />    defaultpiedataset.setValue("OEM人员",10.02D);<br />    defaultpiedataset.setValue("其他人员",5.11D);<br />    <br />    return defaultpiedataset;<br />  }<br />  <br />  //生成图表主对象JFreeChart<br />  public static JFreeChart createChart(PieDataset piedataset){<br />    //定义图表对象<br />    JFreeChart jfreechart = ChartFactory.createPieChart("CityInfoPort公司组织架构图",piedataset,true,true,false);<br />    //获得图表显示对象<br />    PiePlot pieplot = (PiePlot)jfreechart.getPlot();<br />    //设置图表标签字体<br />    pieplot.setLabelFont(new Font("SansSerif",Font.BOLD,12));<br />    pieplot.setNoDataMessage("No data available");<br />    pieplot.setCircular(true);<br />    pieplot.setLabelGap(0.01D);//间距<br />    <br />    return jfreechart;<br />  }<br />  <br />  //生成显示图表的面板<br />  public static JPanel createDemoPanel(){<br />    JFreeChart jfreechart = createChart(createDataset());<br />    return new ChartPanel(jfreechart);<br />  }<br />  <br />}<br /></font>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/62635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-08-09 20:10 <a href="http://www.blogjava.net/wuxufeng8080/articles/62635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Quartz应用（ZT）</title><link>http://www.blogjava.net/wuxufeng8080/articles/58708.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Tue, 18 Jul 2006 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/58708.html</guid><description><![CDATA[
		<div class="postTitle"> </div>
		<p>　　Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个，百个，甚至是好几万个Jobs这样复杂的日程序表。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本为Quartz 1.5.2。</p>
		<p>实例：</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 src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #0000ff">package</span>
				<span style="COLOR: #000000"> example.quartz;<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> org.quartz.CronTrigger;<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> org.quartz.Job;<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> org.quartz.JobDetail;<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> org.quartz.JobExecutionContext;<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> org.quartz.JobExecutionException;<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> org.quartz.Scheduler;<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> org.quartz.SchedulerFactory;<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> java.util.Date;<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_278_303_Open_Image" onclick="this.style.display='none'; Codehighlighter1_278_303_Open_Text.style.display='none'; Codehighlighter1_278_303_Closed_Image.style.display='inline'; Codehighlighter1_278_303_Closed_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_278_303_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_278_303_Closed_Text.style.display='none'; Codehighlighter1_278_303_Open_Image.style.display='inline'; Codehighlighter1_278_303_Open_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span id="Codehighlighter1_278_303_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">/** */</span>
				<span id="Codehighlighter1_278_303_Open_Text">
						<span style="COLOR: #008000">/**</span>
						<span style="COLOR: #008000">
								<br />
								<img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" /> * </span>
						<span style="COLOR: #808080">@author</span>
						<span style="COLOR: #008000"> kestrel<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /> </span>
						<span style="COLOR: #008000">*/</span>
				</span>
				<span style="COLOR: #000000">
						<br />
						<img id="Codehighlighter1_305_315_Open_Image" onclick="this.style.display='none'; Codehighlighter1_305_315_Open_Text.style.display='none'; Codehighlighter1_305_315_Closed_Image.style.display='inline'; Codehighlighter1_305_315_Closed_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
						<img id="Codehighlighter1_305_315_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_305_315_Closed_Text.style.display='none'; Codehighlighter1_305_315_Open_Image.style.display='inline'; Codehighlighter1_305_315_Open_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" />
				</span>
				<span id="Codehighlighter1_305_315_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">/**/</span>
				<span id="Codehighlighter1_305_315_Open_Text">
						<span style="COLOR: #008000">/*</span>
						<span style="COLOR: #008000"> 实现Job </span>
						<span style="COLOR: #008000">*/</span>
				</span>
				<span style="COLOR: #000000">
						<br />
						<img id="Codehighlighter1_358_1171_Open_Image" onclick="this.style.display='none'; Codehighlighter1_358_1171_Open_Text.style.display='none'; Codehighlighter1_358_1171_Closed_Image.style.display='inline'; Codehighlighter1_358_1171_Closed_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
						<img id="Codehighlighter1_358_1171_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_358_1171_Closed_Text.style.display='none'; Codehighlighter1_358_1171_Open_Image.style.display='inline'; Codehighlighter1_358_1171_Open_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" />
				</span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> QuartzReport </span>
				<span style="COLOR: #0000ff">implements</span>
				<span style="COLOR: #000000"> Job </span>
				<span id="Codehighlighter1_358_1171_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.cnweblog.com/Images/dot.gif" />
				</span>
				<span id="Codehighlighter1_358_1171_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" /><br /><img id="Codehighlighter1_362_372_Open_Image" onclick="this.style.display='none'; Codehighlighter1_362_372_Open_Text.style.display='none'; Codehighlighter1_362_372_Closed_Image.style.display='inline'; Codehighlighter1_362_372_Closed_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_362_372_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_362_372_Closed_Text.style.display='none'; Codehighlighter1_362_372_Open_Image.style.display='inline'; Codehighlighter1_362_372_Open_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
						<span id="Codehighlighter1_362_372_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">/**/</span>
						<span id="Codehighlighter1_362_372_Open_Text">
								<span style="COLOR: #008000">/*</span>
								<span style="COLOR: #008000"> 重载该函数 </span>
								<span style="COLOR: #008000">*/</span>
						</span>
						<span style="COLOR: #000000">
								<br />
								<img id="Codehighlighter1_451_576_Open_Image" onclick="this.style.display='none'; Codehighlighter1_451_576_Open_Text.style.display='none'; Codehighlighter1_451_576_Closed_Image.style.display='inline'; Codehighlighter1_451_576_Closed_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
								<img id="Codehighlighter1_451_576_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_451_576_Closed_Text.style.display='none'; Codehighlighter1_451_576_Open_Image.style.display='inline'; Codehighlighter1_451_576_Open_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">void</span>
						<span style="COLOR: #000000"> execute(JobExecutionContext cntxt) </span>
						<span style="COLOR: #0000ff">throws</span>
						<span style="COLOR: #000000"> JobExecutionException </span>
						<span id="Codehighlighter1_451_576_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.cnweblog.com/Images/dot.gif" />
						</span>
						<span id="Codehighlighter1_451_576_Open_Text">
								<span style="COLOR: #000000">{<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(</span>
								<span style="COLOR: #000000">"</span>
								<span style="COLOR: #000000">Generating report - </span>
								<span style="COLOR: #000000">"</span>
								<span style="COLOR: #000000">
										<br />
										<img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />                        </span>
								<span style="COLOR: #000000">+</span>
								<span style="COLOR: #000000"> cntxt.getJobDetail().getJobDataMap().get(</span>
								<span style="COLOR: #000000">"</span>
								<span style="COLOR: #000000">type</span>
								<span style="COLOR: #000000">"</span>
								<span style="COLOR: #000000">)<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />                        </span>
								<span style="COLOR: #000000">+</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">new</span>
								<span style="COLOR: #000000"> Date());<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
						</span>
						<span style="COLOR: #000000">
								<br />
								<img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />
								<br />
								<img id="Codehighlighter1_619_1169_Open_Image" onclick="this.style.display='none'; Codehighlighter1_619_1169_Open_Text.style.display='none'; Codehighlighter1_619_1169_Closed_Image.style.display='inline'; Codehighlighter1_619_1169_Closed_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
								<img id="Codehighlighter1_619_1169_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_619_1169_Closed_Text.style.display='none'; Codehighlighter1_619_1169_Open_Image.style.display='inline'; Codehighlighter1_619_1169_Open_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">static</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">void</span>
						<span style="COLOR: #000000"> main(String[] args) </span>
						<span id="Codehighlighter1_619_1169_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.cnweblog.com/Images/dot.gif" />
						</span>
						<span id="Codehighlighter1_619_1169_Open_Text">
								<span style="COLOR: #000000">{<br /><img id="Codehighlighter1_627_1116_Open_Image" onclick="this.style.display='none'; Codehighlighter1_627_1116_Open_Text.style.display='none'; Codehighlighter1_627_1116_Closed_Image.style.display='inline'; Codehighlighter1_627_1116_Closed_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_627_1116_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_627_1116_Closed_Text.style.display='none'; Codehighlighter1_627_1116_Open_Image.style.display='inline'; Codehighlighter1_627_1116_Open_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        </span>
								<span style="COLOR: #0000ff">try</span>
								<span style="COLOR: #000000"> </span>
								<span id="Codehighlighter1_627_1116_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.cnweblog.com/Images/dot.gif" />
								</span>
								<span id="Codehighlighter1_627_1116_Open_Text">
										<span style="COLOR: #000000">{<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />            SchedulerFactory schedFact </span>
										<span style="COLOR: #000000">=</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">new</span>
										<span style="COLOR: #000000"> org.quartz.impl.StdSchedulerFactory();<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />            Scheduler sched </span>
										<span style="COLOR: #000000">=</span>
										<span style="COLOR: #000000"> schedFact.getScheduler();<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />            sched.start();<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />            JobDetail jobDetail </span>
										<span style="COLOR: #000000">=</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">new</span>
										<span style="COLOR: #000000"> JobDetail(</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">Income Report</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">,<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />                    </span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">Report Generation</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">, QuartzReport.</span>
										<span style="COLOR: #0000ff">class</span>
										<span style="COLOR: #000000">);<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />            jobDetail.getJobDataMap().put(</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">type</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">, </span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">FULL</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">);<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />            CronTrigger trigger </span>
										<span style="COLOR: #000000">=</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">new</span>
										<span style="COLOR: #000000"> CronTrigger(</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">Income Report</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">,<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />                    </span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">Report Generation</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">);<br /><img id="Codehighlighter1_1010_1023_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1010_1023_Open_Text.style.display='none'; Codehighlighter1_1010_1023_Closed_Image.style.display='inline'; Codehighlighter1_1010_1023_Closed_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1010_1023_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1010_1023_Closed_Text.style.display='none'; Codehighlighter1_1010_1023_Open_Image.style.display='inline'; Codehighlighter1_1010_1023_Open_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />            </span>
										<span id="Codehighlighter1_1010_1023_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">/**/</span>
										<span id="Codehighlighter1_1010_1023_Open_Text">
												<span style="COLOR: #008000">/*</span>
												<span style="COLOR: #008000"> 每1分钟执行一次 </span>
												<span style="COLOR: #008000">*/</span>
										</span>
										<span style="COLOR: #000000">
												<br />
												<img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />            trigger.setCronExpression(</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">0 0/1 * * * ?</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">);<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />            sched.scheduleJob(jobDetail, trigger);<br /><img id="Codehighlighter1_1138_1166_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1138_1166_Open_Text.style.display='none'; Codehighlighter1_1138_1166_Closed_Image.style.display='inline'; Codehighlighter1_1138_1166_Closed_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1138_1166_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1138_1166_Closed_Text.style.display='none'; Codehighlighter1_1138_1166_Open_Image.style.display='inline'; Codehighlighter1_1138_1166_Open_Text.style.display='inline';" src="http://www.cnweblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        }</span>
								</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">catch</span>
								<span style="COLOR: #000000"> (Exception e) </span>
								<span id="Codehighlighter1_1138_1166_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.cnweblog.com/Images/dot.gif" />
								</span>
								<span id="Codehighlighter1_1138_1166_Open_Text">
										<span style="COLOR: #000000">{<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/InBlock.gif" align="top" />            e.printStackTrace();<br /><img src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span>
								</span>
								<span style="COLOR: #000000">
										<br />
										<img src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
						</span>
						<span style="COLOR: #000000">
								<br />
								<img src="http://www.cnweblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
		</div>
		<p>
				<br />Quartz的配置文件：quartz.properties<br /># Configure Main Scheduler Properties <br />org.quartz.scheduler.instanceName = TestScheduler<br />org.quartz.scheduler.instanceId = one</p>
		<p># Configure ThreadPool <br />org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool<br />org.quartz.threadPool.threadCount =  5<br />org.quartz.threadPool.threadPriority = 4</p>
		<p># Configure JobStore <br />org.quartz.jobStore.misfireThreshold = 5000<br />org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore<br /><br />附：cronExpression配置说明<br /></p>
		<table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellspacing="0" cellpadding="0" border="1">
				<tbody>
						<tr style="mso-yfti-irow: 0">
								<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; mso-border-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">字段<span lang="EN-US"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<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: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">允许值<span lang="EN-US"><o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<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: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">允许的特殊字符<span lang="EN-US"><o:p></o:p></span></span>
												</font>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 1">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; 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; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">秒<span lang="EN-US"><o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">0-59<o:p></o:p></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">, - * /<o:p></o:p></span>
												</font>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 2">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; 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; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">分<span lang="EN-US"><o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">0-59<o:p></o:p></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">, - * /<o:p></o:p></span>
												</font>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 3">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; 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; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">小时<span lang="EN-US"><o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">0-23<o:p></o:p></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">, - * /<o:p></o:p></span>
												</font>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 4">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; 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; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">日期<span lang="EN-US"><o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">1-31<o:p></o:p></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">, - * ? / L W C<o:p></o:p></span>
												</font>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 5">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; 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; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">月份<span lang="EN-US"><o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">1-12 或者 JAN-DEC<o:p></o:p></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">, - * /<o:p></o:p></span>
												</font>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 6">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; 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; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">星期<span lang="EN-US"><o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">1-7 或者 SUN-SAT<o:p></o:p></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">, - * ? / L C #<o:p></o:p></span>
												</font>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 7; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; 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; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">年（可选）<span lang="EN-US"><o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span style="FONT-FAMILY: Georgia">留空<span lang="EN-US">, 1970-2099<o:p></o:p></span></span>
												</font>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 142.05pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="189">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<font face="Georgia">
														<span lang="EN-US" style="FONT-FAMILY: Georgia">, - * /<o:p></o:p></span>
												</font>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/58708.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-07-18 11:00 <a href="http://www.blogjava.net/wuxufeng8080/articles/58708.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>