﻿<?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-honzeland-随笔分类-Java</title><link>http://www.blogjava.net/honzeland/category/16282.html</link><description>记录点滴。。。</description><language>zh-cn</language><lastBuildDate>Fri, 22 Oct 2010 14:51:44 GMT</lastBuildDate><pubDate>Fri, 22 Oct 2010 14:51:44 GMT</pubDate><ttl>60</ttl><item><title>Servlet Mappings - rules, pattern....</title><link>http://www.blogjava.net/honzeland/archive/2010/10/22/335921.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 22 Oct 2010 14:41:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2010/10/22/335921.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/335921.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2010/10/22/335921.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/335921.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/335921.html</trackback:ping><description><![CDATA[<a href="http://www.rawbw.com/~davidm/tini/TiniHttpServer/docs/ServletMappings.html">http://www.rawbw.com/~davidm/tini/TiniHttpServer/docs/ServletMappings.html</a>
<img src ="http://www.blogjava.net/honzeland/aggbug/335921.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2010-10-22 22:41 <a href="http://www.blogjava.net/honzeland/archive/2010/10/22/335921.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java remote invocation frameworks (RPC)</title><link>http://www.blogjava.net/honzeland/archive/2010/06/09/323153.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Wed, 09 Jun 2010 06:25:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2010/06/09/323153.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/323153.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2010/06/09/323153.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/323153.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/323153.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="color: #000000;"><font size="3">1. Remote
Method Invocation (<span class="relatedlinks-highlight">RMI</span>)</font></p>
<p class="MsoNormal" style="color: #000000;"><font size="3">2. Hessian <o p=""></o></font></p>
<p class="MsoNormal" style="color: #000000;"><font size="3">3. <span class="IL_AD" id="IL_AD4">Burlap</span><o p=""></o></font></p>
<p class="MsoNormal" style="color: #000000;"><font size="3">4. HTTP invoker</font></p>
<p class="MsoNormal" style="color: #000000;"><font size="3">5. <span class="relatedlinks-highlight">EJB</span><o p=""></o><br />
</font></p>
<p class="MsoNormal" style="color: #000000;"><font size="3"></font>6. JAX-RPC<font size="3"><span class="relatedlinks-highlight"><br />
</span></font></p>
<p class="MsoNormal" style="color: #000000;"><font size="3"><span class="relatedlinks-highlight">7. JMX<br />
</span></font></p>
<img src ="http://www.blogjava.net/honzeland/aggbug/323153.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2010-06-09 14:25 <a href="http://www.blogjava.net/honzeland/archive/2010/06/09/323153.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat Architecture Diagram</title><link>http://www.blogjava.net/honzeland/archive/2010/05/10/320458.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Mon, 10 May 2010 02:39:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2010/05/10/320458.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/320458.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2010/05/10/320458.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/320458.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/320458.html</trackback:ping><description><![CDATA[zz from http://marakana.com/forums/tomcat/general/106.html<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/honzeland/Tomcat_Architecture-680x428.png" height="428" width="680" /><br />
Valve and Filter:<br />
"Valve" is Tomcat<a id="KonaLink0" target="undefined" class="kLink" style="text-decoration: underline ! important; position: static;" href="http://www.velocityreviews.com/forums/t147502-anyone-know-the-difference-between-tomcat-valve-and-filter.html#"><font style="color: blue ! important; font-family: sans-serif; font-weight: 400; font-size: 13.3333px; position: static;" color="blue"></font></a> specific notion, and they get applied at a higher level than anything in a specific webapp. Also, they work only in Tomcat.<br />
<br />
"Filter" is a Servlet Specification notion and should work in any compliant servlet container. They get applied at a lower level than all of Tomcat's<br />
Valves.<br />
<br />
However, consider also the division between your application and the application&nbsp;
<a id="KonaLink2" target="undefined" class="kLink" style="text-decoration: underline ! important; position: static;" href="http://www.velocityreviews.com/forums/t147502-anyone-know-the-difference-between-tomcat-valve-and-filter.html#"><font style="color: blue ! important; font-family: sans-serif; font-weight: 400; font-size: 13.3333px; position: static;" color="blue"></font></a>server. Think whether the feature you're planning is part of your application, or is it rather a generic feature of the application server, which could have uses in other applications as well. This would be the correct criteria to decide between Valve and Filter.<br />
<br />
Order for filter: The order in which they are
defined matters. The container will execute the filters in the order
in which they are defined.<br />
<img src ="http://www.blogjava.net/honzeland/aggbug/320458.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2010-05-10 10:39 <a href="http://www.blogjava.net/honzeland/archive/2010/05/10/320458.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Quartz scheduled executions</title><link>http://www.blogjava.net/honzeland/archive/2010/01/21/310422.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Thu, 21 Jan 2010 09:38:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2010/01/21/310422.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/310422.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2010/01/21/310422.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/310422.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/310422.html</trackback:ping><description><![CDATA[这周被Quartz折腾了一番。<br />
我们知道，Quartz采用JobDataMap实现向Job实例传送配置属性，正如Quartz官方文档说的那样：<br />
<br />
How can I provide properties/configuration for a Job instance? The key is the JobDataMap, which is part of the JobDetail object.<br />
The JobDataMap can be used to hold any number of (serializable) objects
which you wish to have made available to the job instance when it
executes.<br />
JobDataMap map ＝ context.getJobDetail().getJobDataMap();<br />
<br />
我们通过map向Job实例传送多个objects，其中有一个是个bean，一个是基本类型。对于scheduled triggers，我们要求bean对于所有的序列都不变，包括其属性，而基本类型可以在Job运行过程中改变，并影响下一个序列。实际情况是，对于下个序列，bean的属性被上次的修改了，而基本类型却维持第一次put到Map里面的值。正好和我们要求的相反。<br />
<br />
受bean的影响，以为map里面包含的都是更新的对象，即每个序列里面的JobDetail是同一个对象，但是基本类型的结果否认了这一点。回头重新翻阅了下Quartz的文档：<br />
<br />
Now, some additional notes about a job's state data (aka JobDataMap): A
Job instance can be defined as "stateful" or "non-stateful".
Non-stateful jobs only have their JobDataMap stored at the time they
are added to the scheduler. This means that any changes made to the
contents of the job data map during execution of the job will be lost,
and will not seen by the job the next time it executes.<br />
<br />
Job有两个子接口：StatefulJob and InterruptableJob，我们继承的是InterruptableJob，或许Quartz应该有个InterruptableStatefulJob。另外StatefulJob不支持并发执行，和我们的需求不匹配，我们有自己的同步控制，Job必须可以并发运行。<br />
<br />
然后查看了Quartz的相关源码：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;RAMJobStore.storeJob</span><span style="color: #008000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;storeJob(SchedulingContext&nbsp;ctxt,&nbsp;JobDetail&nbsp;newJob,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;replaceExisting)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;ObjectAlreadyExistsException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JobWrapper&nbsp;jw&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;JobWrapper((JobDetail)newJob.clone());&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;clone&nbsp;a&nbsp;new&nbsp;one</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" />.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jobsByFQN.put(jw.key,&nbsp;jw);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
}</span></div>
<br />
也就是说，store里面放的是初始JobDetail的克隆，在序列运行完时，只有StatefulJob才会更新store里面的JobDetail：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;RAMJobStore.triggeredJobComplete</span><span style="color: #008000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;triggeredJobComplete(SchedulingContext&nbsp;ctxt,&nbsp;Trigger&nbsp;trigger,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JobDetail&nbsp;jobDetail,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;triggerInstCode)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;JobWrapper&nbsp;jw&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(JobWrapper)&nbsp;jobsByFQN.get(jobKey);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(jw&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JobDetail&nbsp;jd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;jw.jobDetail;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(jd.isStateful())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JobDataMap&nbsp;newData&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;jobDetail.getJobDataMap();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(newData&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newData&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(JobDataMap)newData.clone();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newData.clearDirtyFlag();<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;jd.setJobDataMap(newData);&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;set&nbsp;to&nbsp;new&nbsp;one</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
}</span></div>
<br />
<br />
<br />
然后，每次序列运行时所用的JobDetail，是存放在Store里面的克隆。<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;RAMJobStore.retrieveJob</span><span style="color: #008000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;JobDetail&nbsp;retrieveJob(SchedulingContext&nbsp;ctxt,&nbsp;String&nbsp;jobName,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;groupName)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;JobWrapper&nbsp;jw&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(JobWrapper)&nbsp;jobsByFQN.get(JobWrapper.getJobNameKey(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jobName,&nbsp;groupName));<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(jw&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;(JobDetail)jw.jobDetail.clone()&nbsp;:&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;clone&nbsp;a&nbsp;new</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">}<br />
</span></div>
<br />
<br />
问题很清楚了，存放在Store里面的JobDetail是初始对象的克隆，然后每个序列所用的JobDetail， 是Store里面的克隆，只有Stateful job，Store里面的JobDetail才更新。<br />
最有Quartz里面使用的clone():<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Shallow&nbsp;copy&nbsp;the&nbsp;jobDataMap.&nbsp;&nbsp;Note&nbsp;that&nbsp;this&nbsp;means&nbsp;that&nbsp;if&nbsp;a&nbsp;user<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;modifies&nbsp;a&nbsp;value&nbsp;object&nbsp;in&nbsp;this&nbsp;map&nbsp;from&nbsp;the&nbsp;cloned&nbsp;Trigger<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;they&nbsp;will&nbsp;also&nbsp;be&nbsp;modifying&nbsp;this&nbsp;Trigger.</span><span style="color: #008000;"><br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(jobDataMap&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;copy.jobDataMap&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(JobDataMap)jobDataMap.clone();<br />
}</span></div>
<br />
<br />
所以对于前面所讲的，修改bean的属性，会影响所有clone的对象，因此，我们可以将基本类型封装到一个bean里面，map里面存放的是bean，然后通过修改bean的属性，来达到影响下一个序列的目的。<br />
<br />
<img src ="http://www.blogjava.net/honzeland/aggbug/310422.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2010-01-21 17:38 <a href="http://www.blogjava.net/honzeland/archive/2010/01/21/310422.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Useful Links: ing...</title><link>http://www.blogjava.net/honzeland/archive/2008/06/03/205565.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Tue, 03 Jun 2008 07:09:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2008/06/03/205565.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/205565.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2008/06/03/205565.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/205565.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/205565.html</trackback:ping><description><![CDATA[About Java:<br />
<a title="http://www.theserverside.com" href="http://www.theserverside.com">http://www.theserverside.com</a><br />
<a title="http://www.javablogs.com" href="http://www.javablogs.com">http://www.javablogs.com</a><br />
<a title="http://www.java2s.com" href="http://www.java2s.com">http://www.java2s.com</a><br />
<a title="Java(TM) Platform Performance: Strategies and Tactics" href="http://java.sun.com/docs/books/performance/1st_edition/html/JPTOC.fm.html">Java(TM) Platform Performance: Strategies and Tactics</a><br />
<a title="A Simple Data Access Layer using Hibernate" href="http://www.cnblogs.com/sunsonbaby/archive/2004/12/31/84998.html">A Simple Data Access Layer using Hibernate</a><br />
<a title="Discover the secrets of the Java Serialization API" href="http://java.sun.com/developer/technicalArticles/Programming/serialization/">Discover the secrets of the Java Serialization API</a><br />
<a title="Setting up two-way (mutual) SSL with Tomcat on Java5" href="http://www.vorburger.ch/blog1/2006/08/setting-up-two-way-mutual-ssl-with.html">Setting up two-way (mutual) SSL with Tomcat on Java5</a><br />
<a title="Basic Tomcat Tour and Tomcat Security" href="http://www.unidata.ucar.edu/projects/THREDDS/tech/tutorial/BasicTomcatTourAndSecurity.html">Basic Tomcat Tour and Tomcat Security</a><br />
<a title="When Runtime.exec() won't" href="http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html">When Runtime.exec() won't</a><br />
<a title="Asynchronous processing support in Servlet 3.0" href="http://www.javaworld.com/javaworld/jw-02-2009/jw-02-servlet3.html">Asynchronous processing support in Servlet 3.0</a><br />
About security:<br />
<a title="The Types Of Digital Certificates" href="http://mindprod.com/jgloss/certificate.html">The Types Of Digital Certificates</a><br />
<a title="Cryptography Lecture PPT" href="http://www7.informatik.uni-erlangen.de/%7Edressler/lectures/netzwerksicherheit-ws0708/">Cryptography Lecture PPT</a><br />
<a title="MD5 considered harmful today" href="http://www.win.tue.nl/hashclash/rogue-ca/">MD5 considered harmful today</a><br />
<a title="Cryptography Tutorials - Herong's Tutorial Notes" href="http://www.herongyang.com/crypto/">Cryptography Tutorials - Herong's Tutorial Notes</a><br />
<a title="Defective Sign &amp; Encrypt in S/MIME, PKCS#7, MOSS, PEM, PGP, and XML " href="http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html">Defective Sign &amp; Encrypt in S/MIME, PKCS#7, MOSS, PEM, PGP, and XML</a><br />
<a title="Cryptography resources by Bouncycastle" href="http://www.bouncycastle.org/resources.html">Cryptography resources by Bouncycastle</a><br />
Others:<br />
<a title="Colors for the webColors for the web" href="http://hanuska.blogspot.com/2008/12/colors-for-web.html">Colors for the webColors for the web</a><br />
<a title="Test Framework" href="http://www.opensourcetesting.org/">Test Frameworks</a><br />
<a title="Lightstreamer: a scalable and reliable Server for pushing live data to Rich Internet Applications" href="http://www.lightstreamer.com/">Lightstreamer: a scalable and reliable Server for pushing live data to Rich Internet Applications</a><br />
<a title="工资计算器2009版" href="http://www.makyoo.cn/makyoo/index.html">工资计算器2009版</a><br />
<img src ="http://www.blogjava.net/honzeland/aggbug/205565.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2008-06-03 15:09 <a href="http://www.blogjava.net/honzeland/archive/2008/06/03/205565.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Managing HttpSession Objects</title><link>http://www.blogjava.net/honzeland/archive/2008/05/21/201933.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Wed, 21 May 2008 07:49:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2008/05/21/201933.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/201933.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2008/05/21/201933.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/201933.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/201933.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;"><span style="font-size: 36pt;"><span style="font-size: 24pt;"><span style="font-size: 24pt;"><span style="font-size: 14pt;">zz: java.sys-con.com</span></span></span></span><br />
<p>
<em>Java servlet technology provides developers with functionality,
scalability, and portability that can't be found in other server-side
languages. One feature of the Java servlet specification that's
commonly used, and sometimes misused, is the HttpSession interface.
This simple interface allows you to maintain a session or state for Web
site visitors.</em>
</p>
<p>
In my previous article ("Introduction to Session Management," [<em>JDJ</em>,
Vol. 7, issue 9]), I introduced you to session management and the
HttpSession interface. In that article, we walked through using the
HttpSession API to create, use, and destroy session objects for Web
site visitors. The next step is to better understand how to manage the
sessions and those objects in a session. This article will help you
achieve this by helping you understand the following concepts:
</p>
<ul>
    <li>       Code-based session management through listeners
    </li>
    <li>       Proper design of the session and the objects it contains
    </li>
    <li>       Controlling what is in the session and why it's there
    </li>
    <li>       Session persistence
    </li>
    <li>       Memory management
    </li>
</ul>
The Java APIs discussed in this article are from Sun's Java Servlet 2.3 specification.
<p><font face="Arial" size="+1">
<strong>Listeners</strong></font><br />
A listener is an object that's
called when a specified event occurs. There are four listener
interfaces that allow you to monitor changes to sessions and the
objects that are in those sessions:
</p>
<ul>
    <li>       HttpSessionListener
    </li>
    <li>       HttpSessionBindingListener
    </li>
    <li>       HttpSessionAttributeListener
    </li>
    <li>       HttpSessionActivationListener
    </li>
</ul>
Figure 1 provides a method summary for each of the listener
interfaces. The implementing class that you write will override these
methods to provide the functionality you need.
<p>
<strong>HttpSessionListener</strong><br />
The HttpSessionListener
interface is used to monitor when sessions are created and destroyed on
the application server. Its best practical use would be to track
session use statistics for a server.
</p>
<p> The use of HttpSessionListener requires a configuration entry
in the deployment descriptor, or web.xml file, of the application
server. This entry points the server to a class that will be called
when a session is created or destroyed. The entry required is simple.
All you need is a listener and listener-class element in the following
format. The listener-class element must be a fully qualified class
name.
</p>
<p><font color="#800000">
&lt;listener&gt;<br />
&lt;listener-class&gt;package.Class&lt;/listener-class&gt;<br />
&lt;/listener&gt;
</font>
</p>
<p> As you can see in Figure 1, the class that implements this
listener can override two methods: sessionCreated() and
sessionDestroyed(). These methods will be notified when the server
creates or destroys a session.
</p>
<p> These methods take an HttpSessionEvent object as a parameter.
HttpSessionEvent is simply a class that represents notifications of
changes to the Web application's sessions. HttpSessionEvent has one
method, getSession(), that returns the HttpSession object that's been
modified.
</p>
<p>
<strong>HttpSessionBindingListener</strong><br />
The
HttpSessionBindingListener interface is implemented when an object
needs to be notified if it's being bound to a session or unbound from a
session.
</p>
<p> This interface has two methods, valueBound() and
valueUnbound(), that are notified when the status of the object has
changed (see Figure 1).
</p>
<p> These methods have an HttpSessionBindingEvent parameter that
can be used to retrieve the session that the object was bound to and
the name it was given in the session. In Figure 2, you can see the
methods of this object that are used to get the name that's assigned to
the object, the session it's bound to, and the actual object.
</p>
<p>
<strong>HttpSessionAttributeListener</strong><br />
The
HttpSessionAttributeListener interface is used to monitor changes to
attributes in any session on the server. This can be useful when you
know the name assigned to a specific object that gets put into the
session and you want to track how often it's being used.
</p>
<p> As with HttpSessionListener, HttpSessionAttributeListener also
requires an entry in the deployment descriptor for the server. This
entry tells the server which class to call when an attribute in a
session has changed.
</p>
<p> The HttpSessionAttributeListener interface has three methods -
attributeAdded(), attributeRemoved(), and attributeReplaced(). These
methods, shown in Figure 1, are called by the server when attributes of
a session are changed.
</p>
<p>
<strong>HttpSessionActivationListener</strong><br />
The final listener,
HttpSessionActivationListener, is implemented when an object needs to
know if the session that it's bound to is being activated or passivated
(moved). You would come across this scenario if your session is being
shared across JVMs or your server is persisting the session in a
database or file system.
</p>
<p> This interface, displayed in Figure 1, has two methods that
are overridden by the implementing class: sessionDidActivate() and
sessionWillPassivate(). These methods are called when the status of the
session in a JVM is changed.
</p>
<p><font face="Arial" size="+1">
<strong>Session Persistence</strong></font><br />
Today's J2EE-compliant
servers allow for fault-tolerance and failover to provide support in
the event that a server suddenly becomes unavailable because of
hardware, software, or network failure. This support is usually
provided by allowing two or more application servers, often called a
cluster, to run together and provide backup support for each other. If
one server fails, the others pick up the requests and continue on as if
nothing happened. This allows your Web site visitors to keep going
without interruption.
</p>
<p> A proxy server is usually used in front of the application
servers. This server is responsible for directing each HTTP request to
the appropriate server. The proxy server can be set up to ensure that
the server receiving the first request from a user will continue to
receive all subsequent requests from that user. This means that a
session created for the user on the application server will continue to
be available for that user. If the server suddenly fails, there has to
be a system in place to allow the session to continue on without it.
</p>
<p> Session persistence allows the session contents to be saved
outside the application server so that other servers can access it.
Figure 3 shows the relationship between the persisted session data and
the application servers that access it. In this figure, you see a
client accessing a Web site's HTTP server. The HTTP server is
forwarding requests for application resources to one of the application
servers through the use of a proxy server. The application servers are
persisting the session data in an external form.
</p>
<p>
There are four types of session persistence:
</p>
<ol>
    <li>Memory persistence (one server or a cluster of two or more)
    </li>
    <li>File system persistence
    </li>
    <li>Database persistence
    </li>
    <li>Cookie persistence
    </li>
</ol>
Every application server will handle session persistence
differently and all servers may not support all types of persistence.
Objects that are placed in the session must be serializable for
persistence to work.
<p>
<strong>Memory Persistence</strong><br />
In most cases, a single
standalone server will store sessions in memory. This allows for fast
retrieval and update of the information. It also means that the session
information will be lost when the server is shut down. This is usually
the default configuration on most application servers. Memory
persistence can be used when two or more servers need to share the
session information. The application servers can be configured to share
any changes made to the session so that the information is available on
multiple servers. This redundancy of the session information helps the
cluster preserve the session during a failure.
</p>
<p>
<strong>File System Persistence</strong><br />
File system persistence
can be used to serialize any objects that are in the session. The
object contents are placed in a file on the server. The location of the
files created is configurable; however, the files must be accessible by
all the servers in the cluster. The speed at which the file system is
accessed can be a factor in the performance of your Web site. A slow
disk drive, for example, would result in a delay as data is read from
or written to the file.
</p>
<p>
<strong>Database Persistence</strong><br />
Database persistence can be
used to provide a central data store for the session contents. Each
application server in the cluster must be able to access the database.
When sessions are modified, the changes are immediately persisted in
the database. A data source is usually set up for JDBC persistence and
the connections are pooled. This provides a quicker response. There's
also the issue of database failover, which would be addressed at the
database level of the system.
</p>
<p>
<strong>Cookie Persistence</strong><br />
The fourth type of session
persistence, cookie persistence, is so ineffective and insecure that it
doesn't deserve consideration when designing a fail-safe system. Cookie
persistence, as the name implies, persists session data by storing the
session information in browser cookie(s). There's a limitation on data
handling because cookies store only text, not objects, and the amount
of data that can be transmitted in a cookie is limited. There's also
the fact that cookies transmit data back and forth between the client
and the server. This prevents you (at least it should) from saving
sensitive information, like a social security number. This type of
persistence should be used in only the smallest of Web sites, and only
if there's a good reason not to store the session in memory.
</p>
<p> The most common type of persistence is database persistence.
It provides an efficient way of saving session data and it's usually
fairly easy to set up on the application server. Memory persistence in
a cluster is also easy to use, if your application server supports it.
The only drawback is that sessions can sometimes hold large amounts of
data. Storing the session in memory reduces the amount of memory
available to the other processes on the server. File system persistence
can be slow at times and the file system may not always be accessible
to multiple servers.
</p>
<p><font face="Arial" size="+1">
<strong>Watching the Session Size</strong></font><br />
As you and your
fellow employees work on a Web application, you may notice that more
and more objects are being thrown into the session, often "for
convenience" or "just temporarily." The session becomes a quick
catch-all for any information you need to get from your servlets to
your JSPs. The HttpSession interface makes sessions easy to use, which
can lead to the session being overused. This is a concern because the
session takes up space. In most cases that would be memory space. In
other cases, it could be database or file system space. In all cases,
it means more work for the server and more work for the programmers to
manage what is there.
</p>
<p> Although the session is convenient because it's accessible
from every servlet or JSP, it's not always the best place to put
information. Most of the data that's retrieved for display in a Web
application will only be used on one page. Instead of putting the
information into the session scope, use the request scope and then
forward the request from the servlet to the JSP. This causes the
objects to be destroyed after the request has ended, which is after the
data is displayed by the JSP. If you put the objects into the session,
you would either have to remove them in your code or leave them there.
Leaving objects in the session is not a good idea because you're using
up valuable resources for no reason. This becomes even more of an issue
when your Web site has hundreds or thousands of visitors, all of whom
have a session that's loaded with objects.
</p>
<p> Some objects should be stored in the session. Objects that may
be needed over and over again as a user moves through a Web site are
those that should be put into the session. Anything that needs to exist
longer than one request can be stored in the session, as long as these
objects are removed as soon as they're no longer needed.
</p>
<p><font face="Arial" size="+1">
<strong>Considerations for Managing Sessions</strong></font><br />
When working with sessions, there are a few things to consider before designing or redesigning a Web application:
</p>
<ul>
    <li>       Are sessions needed in the application?
    </li>
    <li>       How long should the session be inactive before timing out?
    </li>
    <li>       Are all the objects in the session serializable?
    </li>
    <li>       Are the objects being bound to the session too large?
    </li>
    <li>       Do the objects that are in the session really need to be there?
    </li>
</ul>
<font face="Arial" size="+1">
<strong>A Need for Sessions</strong></font><br />
If you have unique
users on a Web site and need to know who they are or need to get
specific information to them, such as search results, then you should
be using sessions. If you follow the guidelines set here, there's no
reason not to use the HttpSession interface that Java provides. It's
easy to use, flexible, secure, and it helps you to build a better Web
site.
<p> There's another architecture that deals with maintaining state for
a client. Instead of relying on the HttpSession interface, state for
clients can be maintained within Enterprise JavaBeans (EJBs). The EJB
architecture takes the business logic for an application and places it
in components or beans. A session bean is a type of EJB that exists for
a given client/server session and provides database access or other
business logic, such as calculations. Session beans can be stateless or
they can maintain the state for a client, very much like an HttpSession
object.
</p>
<p> There is still some debate over where the state for a Web site
visitor should be maintained. The best design for the application at
this time is to continue using the HttpSession object for maintaining
the state of the presentation layer of the Web application and to use
stateful EJBs to maintain the state of the business logic and data
layer. There are many other factors that should be considered with
EJBs, one being the better performance of stateless beans over those
that maintain state. These issues, which are outside the scope of this
article, should be considered carefully when architecting an
application.
</p>
<p><font face="Arial" size="+1">
<strong>Session Timeout</strong></font><br />
By default, on most servers
the session is set to expire after 30 minutes of inactivity. The amount
of time can be configured in the deployment descriptor of the Web
application. The HttpSession API also provides a
setMaxInactiveInterval() method that you can use to specify the timeout
period for a session. The getMaxInactiveInterval() method will return
this timeout value. The value given is in seconds.
</p>
<p> The length of time will vary depending on what your visitors
are doing on your site. If they're logging in to check their account
balance, a shorter session timeout period can be used because it
doesn't take long for a person to read a couple of numbers. If, on the
other hand, the user is logging in to read large amounts of data, you
need to be sure that you provide enough time for the user to do what he
or she wants without being logged out. If the user is constantly
navigating through your site, the session will last indefinitely.
</p>
<p><font face="Arial" size="+1">
<strong>Implement Serializable</strong></font><br />
It's important to
make sure that all objects placed in the session can be serialized.
This may not be an issue if you know that your Web application will not
run in a cluster, but it should still be done anyway. What happens if
your Web site grows too big for one server and you suddenly have to
move to two? If you implement Serializable in your code now, you won't
have to go back and do it later.
</p>
<p><font face="Arial" size="+1">
<strong>Keep It Simple</strong></font><br />
You should design objects
that are going to be placed into a session so that they're not too big
and don't contain unnecessary information. A JavaBean that contains a
customer's name, address, phone number, e-mail address, credit card
numbers, and order history should not be placed into the session if
you're only going to use the object to get the customer's name.
</p>
<p><font face="Arial" size="+1">
<strong>Session Contents</strong></font><br />
When you're working on a
Web site, it's important to know which objects are in the session and
why they're needed. The size of the session should be kept as small as
possible. If you're building a new Web site, work out ahead of time
what goes in the session, why it's there, and where it gets removed. If
you're redesigning an existing site, this may be a little tougher,
especially when you have hundreds of servlets and JSPs to deal with. In
this case, try implementing an HttpSessionAttributeListener to get an
idea of what is going into the session. With this information, you may
be able to better manage your sessions.
</p>
<p><font face="Arial" size="+1">
<strong>Conclusion</strong></font><br />
Hopefully this article helped
you to better understand the design issues involved in using the
HttpSession interface. Java provides a more robust session
implementation than other languages. It's because of this power and
flexibility that you must take the time to properly lay out the use of
the session. A well-designed session will help make a Web application
better for the programmers and the users.
</p>
<p><font face="Arial" size="+1">
<strong>References</strong></font><br />
</p>
<div class="storybody">
<li>       Hall, M. (2002). <em>More Servlets and JavaServer Pages</em>. Prentice Hall PTR.
</li>
<li>       <em>Java Servlet Technology:</em>
<a href="http://java.sun.com/products/servlet" target="new">http://java.sun.com/products/servlet</a>
</li>
<li>       <em>Enterprise JavaBeans Technology:</em>
<a href="http://java.sun.com/products/ejb" target="new">http://java.sun.com/products/ejb</a>
</li>
<li>       <em>Java BluePrints (J2EE):</em>
<a href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications" target="new">http://java.sun.com/blueprints/guidelines/
designing_enterprise_applications</a></li>
</div>
<br />
<br />
另外，还有一些收集的材料<br />
关于HttpSession的误解实在是太多了，本来是一个很简单的问题，怎会搞的如此的复杂呢？下面说说我的理解吧：<br />
1、HTTP协议本身是&#8220;连接-请求-应答-关闭连接&#8221;模式的，是一种无状态协议（HTTP只是一个传输协议）；<br />
2、Cookie规范是为了给HTTP增加状态跟踪用的（如果要精确把握，建议仔细阅读一下相关的RFC），但不是唯一的手段；<br />
3、所谓Session，指的是客户端和服务端之间的一段交互过程的状态信息（数据）；这个状态如何界定，生命期有多长，这是应用本身的事情；<br />
4、由于B/S计算模型中计算是在服务器端完成的，客户端只有简单的显示逻辑，所以，Session数据对客户端应该是透明的不可理解的并且应该受控于服务端；Session数据要么保存到服务端（HttpSession），要么在客户端和服务端之间传递（Cookie或url rewritting或Hidden input）；<br />
5、由于HTTP本身的无状态性，服务端无法知道客户端相继发来的请求是来自一个客户的，所以，当使用服务端HttpSession存储会话数据的时候客户端的每个请求都应该包含一个session的标识(sid, jsessionid 等等)来告诉服务端；<br />
6、会话数据保存在服务端（如HttpSession）的好处是减少了HTTP请求的长度，提高了网络传输效率；客户端session信息存储则相反；<br />
7、客户端Session存储只有一个办法：cookie(url rewritting和hidden input因为无法做到持久化，不算，只能作为交换session id的方式，即a method of session tracking)，而服务端做法大致也是一个道理：容器有个session管理器（如tomcat的 org.apache.catalina.session包里面的类），提供session的生命周期和持久化管理并提供访问session数据的 api；<br />
8、使用服务端还是客户端session存储要看应用的实际情况的。一般来说不要求用户注册登录的公共服务系统（如google）采用 cookie做客户端session存储（如google的用户偏好设置），而有用户管理的系统则使用服务端存储。原因很显然：无需用户登录的系统唯一能够标识用户的就是用户的电脑，换一台机器就不知道谁是谁了，服务端session存储根本不管用；而有用户管理的系统则可以通过用户id来管理用户个人数据，从而提供任意复杂的个性化服务；<br />
9、客户端和服务端的session存储在性能、安全性、跨站能力、编程方便性等方面都有一定的区别，而且优劣并非绝对（譬如TheServerSide号称不使用HttpSession，所以性能好，这很显然：一个具有上亿的访问用户的系统，要在服务端数据库中检索出用户的偏好信息显然是低效的，Session管理器不管用什么数据结构和算法都要耗费大量内存和CPU时间；而用cookie，则根本不用检索和维护session数据，服务器可以做成无状态的，当然高效）；<br />
reply1: <br />
不过我们也不能在session里面放入过多的东西<br />
一般来说不能超过4K<br />
太多了<br />
对系统资源是一个很严重的浪费<br />
reply2: <br />
4K已是很大的一个数字了。<br />
我一般喜欢写一个类。封装用户登陆后的一些信息。<br />
然后把这个类放在session中，取得直接用类的方法取相关信息，<br />
<br />
</span>
<img src ="http://www.blogjava.net/honzeland/aggbug/201933.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2008-05-21 15:49 <a href="http://www.blogjava.net/honzeland/archive/2008/05/21/201933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Svn revision retrieve and logging to database</title><link>http://www.blogjava.net/honzeland/archive/2008/04/28/196772.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Mon, 28 Apr 2008 07:43:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2008/04/28/196772.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/196772.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2008/04/28/196772.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/196772.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/196772.html</trackback:ping><description><![CDATA[最近接到两个很小的tickets，两个都是为了项目开发时的方便：一是将logs写入到数据库中，以方便日志的查询；一是在build时，在war包加入svn revision info。<br />
1） logging to database<br />
经过调查，决定采用log4j的org.apache.log4j.jdbc.JDBCAppender，于是采用：<br />
# logging to db<br />
log4j.logger.com.example=DEBUG, DATABASE<br />
log4j.additivity.com.example=false<br />
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender<br />
log4j.appender.DATABASE.url=jdbc:postgresql://localhost:5432/test<br />
log4j.appender.DATABASE.driver=org.postgresql.Driver<br />
log4j.appender.DATABASE.user=pguser<br />
log4j.appender.DATABASE.password=post<br />
log4j.appender.DATABASE.sql=INSERT INTO debug_log(created, logger, priority, message) VALUES (to_timestamp('%d{ISO8601}','YYYY-MM-DD HH:MI:SS.MS'),'%c.%M:%L','%p','%m')<br />
log4j.appender.DB.layout=org.apache.log4j.PatternLayout<br />
log4j.appender.DATABASE.layout.ConversionPattern=%d{ISO8601} %p %c.%M:%L %m<br />
很直观，用起来还很方便，但是不久就出现了问题，tomcat抛出了exception。只好把之前fixed ticket reopen，提交新的comments：Unfortunately, org.apache.log4j.jdbc.JDBCAppender that ships with the Log4j distribution is not able to process logging messages that have characters like ' (single quote) and , (comma) in it. When logging messages contains characters like single quote or comma, the program will throw an exception.<br />
重新google了，找到了一个plusjdbc，Looking further, I found an alternative JDBCAppender package (org.apache.log4j.jdbcplus.JDBCAppender) from http://www.dankomannhaupt.de/projects/index.html. It can solve this problem. 长叹了一下。<br />
<br />
最后采用：<br />
log4j.appender.DATABASE=org.apache.log4j.jdbcplus.JDBCAppender<br />
log4j.appender.DATABASE.url=jdbc:postgresql://localhost:5432/test<br />
log4j.appender.DATABASE.dbclass=org.postgresql.Driver<br />
log4j.appender.DATABASE.username=pguser<br />
log4j.appender.DATABASE.password=post<br />
log4j.appender.DATABASE.sql=INSERT INTO debug_log(created, logger, priority, message) VALUES (to_timestamp('@LAYOUT:1@', 'YYYY-MM-DD HH:MI:SS.MS'),'@LAYOUT:3@','@LAYOUT:2@','@LAYOUT:4@')<br />
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout<br />
log4j.appender.DATABASE.layout.ConversionPattern=%d{ISO8601}#%p#%c.%M:%L#%m<br />
log4j.appender.DATABASE.layoutPartsDelimiter=#<br />
log4j.appender.DATABASE.buffer=1<br />
log4j.appender.DATABASE.commit=true<br />
log4j.appender.DATABASE.quoteReplace=true<br />
问题解决，但是中间有点小波折，在我的项目中，log4j.jar（&gt;1.2.9）重复了，在$CATALINA_HOME/lib下有一份，在web工程下的WEB-INF/lib下也有一份，而plus-jdbc.jar放置在$CATALINA_HOME/lib下，结果启动Tomcat，出现<br />
log4j:ERROR A "org.apache.log4j.jdbcplus.JDBCAppender" object is not assignable to a "org.apache.log4j.Appender" variable.<br />
log4j:ERROR The class "org.apache.log4j.Appender" was loaded by<br />
log4j:ERROR [WebappClassLoader^M<br />
&nbsp; delegate: false^M<br />
&nbsp; repositories:^M<br />
----------&gt; Parent Classloader:^M<br />
org.apache.catalina.loader.StandardClassLoader@1ccb029^M<br />
] whereas object of type<br />
log4j:ERROR "org.apache.log4j.jdbcplus.JDBCAppender" was loaded by [org.apache.catalina.loader.StandardClassLoader@1ccb029].<br />
log4j:ERROR Could not instantiate appender named "DATABASE".<br />
原来是两个JDBCAppender实例不在同一个classlaoder里面，将WEB-INF/lib下的log4j.jar删除掉，重启就没问题了，按理，将$CATALINA_HOME/lib下的plus-jdbc.jar移到WEB-INF/lib下，应该也没问题，没有测试。<br />
<br />
2）Add build revision info in war file and read it on tomcat startup<br />
这个经历比较惨痛，两个问题，如何获取revision？ And how to read it when tomcat startup? 第二个问题倒是没什么，采用javax.servlet.ServletContextListener就可以实现，很简单，走弯路的是第一个问题，google后发现有两种常见的实现：<br />
As I have learned, there are totally two solutions to get svn revision info.<br />
<br />
First, retrieve the svn revision from local file($BASE_HOME/.svn/entries). Just parsing the xml file, get the revision property and write it to a properties file.（就是该死的xml，远在乌克兰的同事，该文件却不是xml的，也只怪自己调研不充分，还得折腾了半天，后来发现，最新版的svn为了performance的考虑，采用meta data来实现entries）<br />
<br />
Second, retrieve the svn revision from the remote repository. The solution always use a svn client to perform a demand with remote server to retrieve the revision info. Installing a snv client and using SvnAnt? are most commonly used at present. SvnAnt? is an ant task that provides an interface to Subversion revision control system and encapsulates the svn client. It uses javahl - a native (JNI) java interface for the subversion api if it can find the corresponding library. javahl is platform-dependent.<br />
<br />
Because of needing interaction with the server(服务器在国外，更新很慢), now I employ the first solution. But I found a flaw of this method when i was going off duty. Generally, we may update our project with svn before committing. This may make a mismatch with svn revision between remote server and local file. Svn revision in local file is usually updated when we update our project. But when we take a commit after update, the svn revision in the remote server will change to a new one.<br />
<br />
So, the case is that if we update, commit, and then build, we may get a mismatch with the newest svn revision, and build the error revision into our ROOT.war. If we update , then build ,without commit, we can get right revision info.<br />
<br />
下面是第一版实现：<br />
&nbsp;&nbsp;&nbsp; &lt;!--&nbsp; retrieve the svn revision from the remote repository<br />
&nbsp;&nbsp;&nbsp; &lt;path id="svnant.lib" &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;fileset dir="${lib.dir}"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;include name="svnant.jar"/&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;include name="svnClientAdapter.jar"/&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;include name="svnjavahl.jar"/&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/fileset&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/path&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;taskdef name="svn" classpathref="svnant.lib" classname="org.tigris.subversion.svnant.SvnTask" /&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;target name="get-svn-revision"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;svn username="*******" password="******" javahl="true"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;status urlProperty="https://example.com" path="." revisionProperty="svn.revision" /&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/svn&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;echo&gt;svn revision: ${svn.revision}&lt;/echo&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/target&gt;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;!--&nbsp; retrieve the svn revision from local file(.svn/entries). The file may contain several&nbsp; 'wc-entries.entry.revision' elements. <br />
&nbsp;&nbsp;&nbsp; The property will get several values seperated by ',' when using xmlproperty task.&nbsp; Then the svn revison expected will be the<br />
&nbsp;&nbsp;&nbsp; max one of these property values. <br />
&nbsp;&nbsp;&nbsp; &nbsp;--&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="svn.revision.file" value=".svn/entries" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;!-- This property is used to run xmlproperty task successfully with a low version of svn client (under 1.3.1). Don't&nbsp; sure whether it really makes sense --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="build.id" value="foo" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;target name="get-svn-revision"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;xmlproperty file="${svn.revision.file}" collapseAttributes="true"/&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;echo&gt;svn revision: ${wc-entries.entry.revision}&lt;/echo&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/target&gt;<br />
<br />
&nbsp;&nbsp;&nbsp; &lt;!-- <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; If the file doesn't contain any 'wc-entries.entry.revision' element, the content of the property file will be: revision = ${wc-entries.entry.revision};<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; If contain a 'wc-entries.entry.revision' element, mark this value as $revision_value, then&nbsp; the content will be: revision = $revision_value;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; If contain several 'wc-entries.entry.revision' elements, mark these values as $value1, $value2, ..., respectively, then the content will be: revision = $value1,$value2,..., seperated by a ',';<br />
&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="svn.revision.propertyfile" value="${build.dir}/revision.properties" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;target name="write-svn-revision-to-file" depends="get-svn-revision"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;delete file="${svn.revision.propertyfile}"/&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;propertyfile file="${svn.revision.propertyfile}" comment="record svn revision"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;entry&nbsp; key="revision" value="${wc-entries.entry.revision}"/&gt; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/propertyfile&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/target&gt; <br />
<br />
结果write-svn-revision-to-file这个在我这倒是可以获取本地的svn revision，但是远方的同事可急了，build老失败，只好把这部分build注释了，还好，到周末了，可以在家好好研究一下，很快找了一个新的工具：<br />
It's my fault. In my version of svn, the entries file is xml formatted. So i parse it using ant task - 'xmlproperty'. Now i have fix this problem by using 'svnkit' tools, a pure java svn toolkit. Now there are two ways to retrieve svn revision. One is from remote repository server. For this one, before building, you should set your own username and password for the remote repository server('remote.repository.username' and 'remote.repository.password' properties in build.xml,respectively). Another one is retrieving revision from local working copy. If using this one, you should set 'local.repository' property in build.xml to your own directory.<br />
利用svnkit，从服务器上获取revision大概是：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded(urlStr)); <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; repository.setAuthenticationManager(authManager);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; headRevision = repository.getLatestRevision();<br />
从本地working copy获取revision：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SVNClientManager clientManager = SVNClientManager.newInstance(); <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SVNWCClient wcClient = clientManager.getWCClient();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SVNInfo info = wcClient.doInfo(new File(fileUrl), SVNRevision.WORKING);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; headRevision = info.getRevision().getNumber();&nbsp; <br />
<br />
利用ant task将获取的revision写入到一个配置文件中（如revision.properties）,在tomcat启动的时候加载进来，就可以了。&nbsp;&nbsp;&nbsp; <br />
<img src ="http://www.blogjava.net/honzeland/aggbug/196772.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2008-04-28 15:43 <a href="http://www.blogjava.net/honzeland/archive/2008/04/28/196772.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat ClassLoader and load resources</title><link>http://www.blogjava.net/honzeland/archive/2008/04/24/195605.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Thu, 24 Apr 2008 07:46:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2008/04/24/195605.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/195605.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2008/04/24/195605.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/195605.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/195605.html</trackback:ping><description><![CDATA[zz: http://rosonsandy.blogdriver.com/rosonsandy/871539.html<br />
<br />
1 - Tomcat的类载入器的结构<br />
Tomcat Server在启动的时候将构造一个ClassLoader树，以保证模块的类库是私有的<br />
Tomcat Server的ClassLoader结构如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-----------------------------+ <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bootstrap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
<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;&nbsp; | <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
<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;&nbsp; | <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Common&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
<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; | <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; Catalina&nbsp; Shared&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />
<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; | <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebApp1&nbsp; WebApp2&nbsp;&nbsp; | <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-----------------------------+<br />
<br />
其中：<br />
- Bootstrap - 载入JVM自带的类和$JAVA_HOME/jre/lib/ext/*.jar<br />
- System - 载入$CLASSPATH/*.class<br />
- Common - 载入$CATALINA_HOME/common/...，它们对TOMCAT和所有的WEB APP都可见<br />
- Catalina - 载入$CATALINA_HOME/server/...，它们仅对TOMCAT可见，对所有的WEB APP都不可见<br />
- Shared - 载入$CATALINA_HOME/shared/...，它们仅对所有WEB APP可见，对TOMCAT不可见（也不必见）<br />
- WebApp - 载入ContextBase?/WEB-INF/...，它们仅对该WEB APP可见<br />
<br />
2 - ClassLoader的工作原理<br />
<br />
每个运行中的线程都有一个成员contextClassLoader，用来在运行时动态地载入其它类<br />
系统默认的contextClassLoader是systemClassLoader，所以一般而言java程序在执行时可以使用JVM自带的类、$JAVA_HOME/jre/lib/ext/中的类和$CLASSPATH/中的类<br />
可以使用Thread.currentThread().setContextClassLoader(...);更改当前线程的contextClassLoader，来改变其载入类的行为<br />
<br />
ClassLoader被组织成树形，一般的工作原理是：<br />
1) 线程需要用到某个类，于是contextClassLoader被请求来载入该类<br />
2) contextClassLoader请求它的父ClassLoader来完成该载入请求<br />
3) 如果父ClassLoader无法载入类，则contextClassLoader试图自己来载入<br />
<br />
注意：WebApp?ClassLoader的工作原理和上述有少许不同：<br />
它先试图自己载入类（在ContextBase?/WEB-INF/...中载入类），如果无法载入，再请求父ClassLoader完成<br />
<br />
由此可得：<br />
- 对于WEB APP线程，它的contextClassLoader是WebApp?ClassLoader<br />
- 对于Tomcat Server线程，它的contextClassLoader是CatalinaClassLoader<br />
<br />
3 类的查找<br />
<br />
ClassLoader类中loadClass方法为缺省实现，用下面的顺序查找类：<br />
1、调用findLoadedClass方法来检查是否已经被加载。如果没有则继续下面的步骤。<br />
2、如果当前类装载器有一个指定的委托父装载器，则用委托父装载器的loadClass方法加载类，也就是委托给父装载器加载相应的类。<br />
3、如果这个类装载器的委托层级体系没有一个类装载器加载该类，则使用类装载器定位类的特定实现机制，调用findClass方法来查找类。<br />
<br />
4 - 部分原代码分析<br />
4.1 - org/apache/catalina/startup/Bootstrap.java<br />
Bootstrap中定义了三个classloader:commonLoader,catalinaLoader,sharedLoader.三者关系如下：<br />
//注意三个自己定置的ClassLoader的层次关系： <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // systemClassLoader (root) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; +--- commonLoader <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +--- catalinaLoader <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +--- sharedLoader<br />
<br />
Tomcat Server线程的起点<br />
构造ClassLoader树，通过Thread.currentThread().setContextClassLoader(catalinaLoader)设置当前的classloader为catalinaLoader。<br />
载入若干类，然后转入org.apache.catalina.startup.Catalina类中<br />
<br />
4.2 org.apache.catalina.loader.StandardClassLoader.java<br />
<br />
通过看loadClass这个方法来看tomcat是如何加载类的，顺序如下：<br />
<br />
(0) Check our previously loaded class cache查找已经装载的class<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clazz = findLoadedClass(name);<br />
<br />
(1) If a system class, use system class loader通过系统classloader来装载class<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ClassLoader loader = system;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clazz = loader.loadClass(name);<br />
<br />
(2) Delegate to our parent if requested如果有代理则使用父类classloader<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ClassLoader loader = parent;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (loader == null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loader = system;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clazz = loader.loadClass(name);<br />
<br />
(3) Search local repositories 查找本地类池，比如$CATALINA_HOME/server<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clazz = findClass(name);<br />
<br />
(4) Delegate to parent unconditionally 默认使用代理装载器<br />
<br />
[查看代码]<br />
<br />
4.3 - org/apache/catalina/startup/ClassLoaderFactory.java<br />
<br />
根据设置创建并返回StandardClassLoader的实例<br />
<br />
[查看代码]<br />
<br />
4.4 - org/apache/catalina/loader/StandardClassLoader.java<br />
<br />
类载入器<br />
<br />
4.5 - org/apache/catalina/startup/SecurityClassLoad.java<br />
<br />
该类仅包含一个静态方法，用来为catalinaLoader载入一些类<br />
<br />
[查看代码]<br />
<br />
Appendix - 参考<br />
<br />
[1] http://jakarta.apache.org/tomcat/中的Tomcat 4.1.x文档Class Loader HOW-TO<br />
<br />
在一个JVM中可能存在多个ClassLoader，每个ClassLoader拥有自己的NameSpace。一个ClassLoader只能拥有一个class对象类型的实例，但是不同的ClassLoader可能拥有相同的class对象实例，这时可能产生致命的问题。如ClassLoaderA，装载了类A的类型实例A1，而ClassLoaderB，也装载了类A的对象实例A2。逻辑上讲A1=A2，但是由于A1和A2来自于不同的ClassLoader，它们实际上是完全不同的，如果A中定义了一个静态变量c，则c在不同的ClassLoader中的值是不同的。<br />
<br />
[2] 深入Java2平台安全<br />
<br />
zz: http://mail-archives.apache.org/mod_mbox/tomcat-users/200212.mbox/raw/%3c20021204192034.P86616-100000@icarus.apache.org%3e<br />
try {<br />
&nbsp;&nbsp; &nbsp;Properties props = new Properties();<br />
&nbsp;&nbsp; &nbsp;InputStream in = getClass().getResourceAsStream("/conf/db.properties");<br />
&nbsp;&nbsp; &nbsp;props.load(in);<br />
&nbsp;&nbsp; &nbsp;...... <br />
&nbsp;&nbsp; &nbsp;propertie1 = props.getProperty("propertie1");<br />
<br />
The examples already given will find properties files for you just fine whether the file is in a directory structure or inside an archive.&nbsp; How do you think Java loads classes?&nbsp; It works out of archives, no? here are some various was to access a properties file ( or any resource, for that matter) in whether the app is deployed as a directory or as a .war file (even inside a .jar file in WEB-INF/lib)....<br />
<br />
1. This will load a file in WEB-INF/classes/conf or any jar file in the classpath with a package of "conf"... <br />
&nbsp;&nbsp; &nbsp;getClass().getResourceAsStream("/conf/db.properties"); <br />
2. This will load a file relative to the current class.&nbsp; For instance, if the class is "org.mypackage.MyClass", then the file would be loaded at "org.mypackage.conf.dbproperties".&nbsp; Note that this is because we didn't prepend "/" to the path.&nbsp; When that is done, the file is loaded from the root of the current classloader where this loads it relative to the current class... <br />
&nbsp;&nbsp; &nbsp;getClass().getResourceAsStream("conf/db.properties"); <br />
3. This will find db.properties anywhere in the current classloader as long as it exists in a "conf" package... <br />
&nbsp;&nbsp; &nbsp;getClass().getClassLoader().getResourceAsStream("conf/db.properties"); <br />
4. This will find the file in a "conf" directory inside the webapp (starting from the root).&nbsp; This starts looking in the same directory as contains WEB-INF.&nbsp; When I say "directory", I don't mean "filesystem".&nbsp; This could be in a .war file as well as in an actual directory on the filesystem... <br />
&nbsp;&nbsp; &nbsp;getServletContext().getResourceAsStream("/conf/db.properties"); <br />
5. Of course you would probably not want just anyone seeing your db.properties file, so you'd probably want to put in inside WEB-INF of your webapp, so....<br />
&nbsp;&nbsp; &nbsp;getServletContext().getResourceAsStream("/WEB-INF/conf/db.properties");<br />
6. If your db.properties exists in another classloader which your app has access to, you can reach it by using:<br />
&nbsp;&nbsp; &nbsp;Thread.currentThread().getContextClassLoader().getResourceAsStream("conf/db.properties");<br />
that will act similar to getClass().getClassLoader(), but it can see across all available classloaders where the latter can only see within the classloader that loaded the current class.
<img src ="http://www.blogjava.net/honzeland/aggbug/195605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2008-04-24 15:46 <a href="http://www.blogjava.net/honzeland/archive/2008/04/24/195605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Double Checked Locking 模式</title><link>http://www.blogjava.net/honzeland/archive/2008/02/19/180666.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Tue, 19 Feb 2008 06:21:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2008/02/19/180666.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/180666.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2008/02/19/180666.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/180666.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/180666.html</trackback:ping><description><![CDATA[经典文章：<br />
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;"><a title="Double-checked locking: Clever, but broken" href="http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html">Double-checked locking: Clever, but broken</a><br />
<a title="Warning! Threading in a multiprocessor world" href="http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-toolbox.html">Warning! Threading in a multiprocessor world</a><br />
<a title="The &quot;Double-Checked Locking is Broken&quot; Declaration" href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">The "Double-Checked Locking is Broken" Declaration</a><br />
<a title="When is a singleton not a singleton?" href="http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton.html"><a title="When is a singleton not a singleton?" href="http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton.html">When is a singleton not a singleton?</a></a><br />
</span><span style="color: #000000;"><a title="http://docs.huihoo.com/ace_tao/double_checked_locking.html" href="http://docs.huihoo.com/ace_tao/double_checked_locking.html"></a></span>
<img src ="http://www.blogjava.net/honzeland/aggbug/180666.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2008-02-19 14:21 <a href="http://www.blogjava.net/honzeland/archive/2008/02/19/180666.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现java UDP Server －－2008农历新年第一贴（原创）</title><link>http://www.blogjava.net/honzeland/archive/2008/02/15/180097.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 15 Feb 2008 08:19:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2008/02/15/180097.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/180097.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2008/02/15/180097.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/180097.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/180097.html</trackback:ping><description><![CDATA[一、UDP Server<br />
项目的需要，需要利用java实现一个udp server，主要的功能是侦听来自客户端的udp请求，客户请求可能是大并发量的，对于每个请求Server端的处理很简单，处理每个请求的时间大约在1ms左右，但是Server端需要维护一个对立于请求的全局变量Cache，项目本身已经采用Mina架构（http://mina.apache.org/），我要开发的Server作为整个项目的一个模块，由于之前没有开发UDP Server，受TCP Server的影响，很自然的想利用多线程来实现，对于每个客户请求，新建一个线程来处理相应的逻辑，在实现的过程中，利用Mina的Thread Model，实现了一个多线程的UDP Server，但是由于要维护一个全局Cache，需要在各线程之间同步，加之处理请求的时间很短，很快就发现在此利用多线程，并不能提高性能，于是决定采用单线程来实现，在动手之前，还是发现有两种方案来实现单线程UDP Server：<br />
1） 采用JDK的DatagramSocket和DatagramPacket来实现<br />
public class UDPServerUseJDK extends Thread{ <br />
&nbsp;&nbsp; &nbsp;/**<br />
&nbsp;&nbsp; &nbsp; * Constructor<br />
&nbsp;&nbsp; &nbsp; * @param port port used to listen incoming connection<br />
&nbsp;&nbsp; &nbsp; * @throws SocketException error to consturct a DatagramSocket with this port<br />
&nbsp;&nbsp; &nbsp; */<br />
&nbsp;&nbsp; &nbsp;public MediatorServerUseJDK(int port) throws SocketException{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this("MediatorServerThread", port);<br />
&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;/**<br />
&nbsp;&nbsp; &nbsp; * Constructor<br />
&nbsp;&nbsp; &nbsp; * @param name the thread name<br />
&nbsp;&nbsp; &nbsp; * @param port port used to listen incoming connection<br />
&nbsp;&nbsp; &nbsp; * @throws SocketException error to consturct a DatagramSocket with this port<br />
&nbsp;&nbsp; &nbsp; */<br />
&nbsp;&nbsp; &nbsp;public MediatorServerUseJDK(String name, int port) throws SocketException{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;super(name);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;socket = new DatagramSocket(port); <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Mediator server started on JDK model...");<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Socket buffer size: " + socket.getReceiveBufferSize());<br />
&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;public void run(){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;long startTime = 0;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while(true){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;buf = new byte[1024];<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// receive request<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;packet = new DatagramPacket(buf, buf.length);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; socket.receive(packet); <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;.........<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }catch (IOException e) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;.........<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;}<br />
｝<br />
2） 采用Mina的DatagramAcceptor来实现，在创建Exector的时候，只传递单个线程<br />
public class MediatorServerUseMina {<br />
&nbsp;&nbsp; &nbsp;private DatagramAcceptor acceptor;<br />
<br />
&nbsp;&nbsp; &nbsp;public MediatorServerUseMina() {<br />
<br />
&nbsp;&nbsp; &nbsp;}<br />
<br />
&nbsp;&nbsp; &nbsp;public void startListener(InetSocketAddress address, IoHandler handler) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// create an acceptor with a single thread<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.acceptor = new DatagramAcceptor(Executors.newSingleThreadExecutor());<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// configure the thread models<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;DatagramAcceptorConfig acceptorConfig = acceptor.getDefaultConfig();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;acceptorConfig.setThreadModel(ThreadModel.MANUAL);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// set the acceptor to reuse the address<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;acceptorConfig.getSessionConfig().setReuseAddress(true);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// add io filters<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;DefaultIoFilterChainBuilder filterChainBuilder = acceptor.getFilterChain();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// add CPU-bound job first,<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;filterChainBuilder.addLast("codec", new ProtocolCodecFilter(new StringCodecFactory())); <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// bind<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;acceptor.bind(address, handler);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Mediator Server started on mina model...");<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Socket buffer size: " + acceptorConfig.getSessionConfig().getReceiveBufferSize());<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.err.println("Error starting component listener on port(UDP) " + address.getPort() + ": "<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;+ e.getMessage());<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;} <br />
}<br />
二、Performance Test<br />
为了测试两个Server的性能，写了个简单的测试客户端<br />
import java.io.IOException;<br />
import java.net.DatagramPacket;<br />
import java.net.DatagramSocket;<br />
import java.net.InetAddress;<br />
import java.net.SocketException;<br />
import java.net.UnknownHostException;<br />
<br />
/**<br />
&nbsp;* @author Herry Hong<br />
&nbsp;* <br />
&nbsp;*/<br />
<br />
public class PerformanceTest {<br />
&nbsp;&nbsp; &nbsp;/** Number of threads to be created */<br />
&nbsp;&nbsp; &nbsp;static final int THREADS = 100;<br />
&nbsp;&nbsp; &nbsp;/** Packets to be sent per thread */<br />
&nbsp;&nbsp; &nbsp;static final int PACKETS = 500;<br />
&nbsp;&nbsp; &nbsp;/** The interval of two packets been sent for each thread */<br />
&nbsp;&nbsp; &nbsp;private static final int INTERVAL = 80;<br />
&nbsp;&nbsp; &nbsp;private static final String DATA = "5a76d93cb435fc54eba0b97156fe38f432a4e1da3a87cce8a222644466ed1317";<br />
<br />
&nbsp;&nbsp; &nbsp;private class Sender implements Runnable {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;private InetAddress address = null;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;private DatagramSocket socket = null;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;private String msg = null;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;private String name = null;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;private int packet_sent = 0;<br />
<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;public Sender(String addr, String msg, String name) throws SocketException,<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;UnknownHostException {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.address = InetAddress.getByName(addr);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.socket = new DatagramSocket();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.msg = msg;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.name = name;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;@Override<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;public void run() {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// send request<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;byte[] buf = msg.getBytes();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;DatagramPacket packet = new DatagramPacket(buf, buf.length,<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;address, 8000);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;for (int i = 0; i &lt; PerformanceTest.PACKETS; i++) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;socket.send(packet);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;packet_sent++;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Thread.sleep(INTERVAL);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;e.printStackTrace();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (InterruptedException e) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;e.printStackTrace();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//System.out.println("Thread " + name + " sends " + packet_sent + " packets.");<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//System.out.println("Thread " + name + " end!");<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;}<br />
<br />
&nbsp;&nbsp; &nbsp;/**<br />
&nbsp;&nbsp; &nbsp; * @param args<br />
&nbsp;&nbsp; &nbsp; */<br />
&nbsp;&nbsp; &nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (args.length != 1) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Usage: java PerformanceTest &lt;hostname&gt;");<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;String msg; <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;for (int i = 0; i &lt; THREADS; i++) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(i % 2 == 0){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;msg = i + "_" + (i+1) + ""r"n" + (i+1) + "_" + i + ""r"n" + DATA;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}else{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;msg = i + "_" + (i-1) + ""r"n" + (i-1) + "_" + i + ""r"n" + DATA;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;new Thread(new PerformanceTest().new Sender(args[0], msg, "" + i)).start();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (SocketException e) { <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;e.printStackTrace();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (UnknownHostException e) { <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;e.printStackTrace();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} <br />
&nbsp;&nbsp; &nbsp;}<br />
}<br />
三、测试结果<br />
测试环境：<br />
Server：AMD Athlon(tm) 64 X2 Dual Core Processor 4000+，1G memory<br />
Client：AMD Athlon(tm) 64 X2 Dual Core Processor 4000+，1G memory<br />
在测试的过程中，当INTERVAL设置的太小时，服务器端会出现丢包现象，INTERVAL越小，丢包越严重，为了提高Server的性能，特将Socket的ReceiveBufferSize设置成默认大小的两倍，<br />
对于JDK实现：<br />
&nbsp;&nbsp; &nbsp;public MediatorServerUseJDK(String name, int port) throws SocketException{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;super(name);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;socket = new DatagramSocket(port);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// set the receive buffer size to double default size<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socket.setReceiveBufferSize(socket.getReceiveBufferSize() * 2); <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Mediator server started on JDK model...");<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Socket buffer size: " + socket.getReceiveBufferSize());<br />
&nbsp;&nbsp; &nbsp;}<br />
对于Mina实现：<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;DatagramAcceptorConfig acceptorConfig = acceptor.getDefaultConfig();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;acceptorConfig.setThreadModel(ThreadModel.MANUAL);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// set the acceptor to reuse the address<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;acceptorConfig.getSessionConfig().setReuseAddress(true);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// set the receive buffer size to double default size<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;int recBufferSize = acceptorConfig.getSessionConfig().getReceiveBufferSize();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;acceptorConfig.getSessionConfig().setReceiveBufferSize(recBufferSize * 2);<br />
此时，相同的INTERVAL，丢包现象明显减少。<br />
接下来，再测试不同实现的性能差异：<br />
UDP server started on JDK model...<br />
Socket buffer size: 110592<br />
INTERVAL ＝ 100ms，没有出现丢包，<br />
Process time: 49988<br />
Process time: 49982<br />
Process time: 49984<br />
Process time: 49986<br />
Process time: 49984<br />
INTERVAL ＝ 80ms，仍然没有丢包，不管Server是不是初次启动<br />
Process time: 40006<br />
Process time: 40004<br />
Process time: 40003<br />
Process time: 40005<br />
Process time: 40013<br />
UDP Server started on mina model...<br />
Socket buffer size: 110592<br />
INTERVAL ＝ 80ms，Server初次启动时，经常会出现丢包，当第一次（指服务器初次启动时）没有丢包时，随后基本不丢包，<br />
Process time: 39973<br />
Process time: 40006<br />
Process time: 40007<br />
Process time: 40008<br />
Process time: 40008<br />
INTERVAL ＝ 100ms，没有出现丢包<br />
Process time: 49958<br />
Process time: 49985<br />
Process time: 49983<br />
Process time: 49988<br />
四、结论<br />
在该要求下，采用JDK和Mina实现性能相当，但是在Server初次启动时JDK实现基本不会出现丢包，而Mina实现则在Server初次启动时经常出现丢包现象，在经历第一次测试后，两种实现处理时间相近，请求并发量大概为每ms一个请求时，服务器不会出现丢包。<br />
<br />
<img src ="http://www.blogjava.net/honzeland/aggbug/180097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2008-02-15 16:19 <a href="http://www.blogjava.net/honzeland/archive/2008/02/15/180097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>将Openfire导入到Eclipse中</title><link>http://www.blogjava.net/honzeland/archive/2008/01/25/177812.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 25 Jan 2008 09:36:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2008/01/25/177812.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/177812.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2008/01/25/177812.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/177812.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/177812.html</trackback:ping><description><![CDATA[1、 从Openfire SVN Server中dump出源码；<br />
2、 Build: ant&nbsp; &amp; ant plugins<br />
3、 将build后的target/openfire作为openfire_home<br />
4、 在target/openfire下建立两个目录：src和classes，将dump下来的源码copy到src路径下，将classes设置为eclipse编译后的输出路径<br />
5、 将$openfire_home/lib下的openfire.jar中src中存在的部分删除，剩下的部分作为新的openfire.jar，注意，在ubuntu下之间打开openfire.jar时，直接将/org/jivesoftware/admin, /org/jivesoftware/openfire, /org/jivesoftware/util三个目录删除，而对于/org/jivesoftware/database目录，只将源码中有的那部分删除，/org/jivesoftware下面还有一个隐藏目录/org/jivesoftware/stringprep，不能删除，接下来，将$openfire_home/lib下的jar包作为工程的Referenced Libraries.<br />
6、 将取出来的工程下src/web/WEB-INF/classes/openfire_init.xml导入到eclipse的查询路径里，如将src/web/WEB-INF/classes目录作为eclipse的源目录，这样openfire_init.xml自动copy到$openfire_home/classses下面，将openfire_init.xml中的openfireHome设置为$openfire_home<br />
7、 修改org.jivesoftware.openfire.starter.ServerStarter中的如下两个field，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String DEFAULT_LIB_DIR = "../lib";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String DEFAULT_ADMIN_LIB_DIR = "../plugins/admin/webapp/WEB-INF/lib";<br />
改成：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String DIR_PREFIX = "$openfire_home";&nbsp;&nbsp;&nbsp;&nbsp; // to be your own openfire_home<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String DEFAULT_LIB_DIR = DIR_PREFIX + "lib";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String DEFAULT_ADMIN_LIB_DIR = DIR_PREFIX + "plugins/admin/webapp/WEB-INF/lib";<br />
<img src ="http://www.blogjava.net/honzeland/aggbug/177812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2008-01-25 17:36 <a href="http://www.blogjava.net/honzeland/archive/2008/01/25/177812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DWR 调用返回值方法</title><link>http://www.blogjava.net/honzeland/archive/2008/01/15/175465.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Tue, 15 Jan 2008 06:45:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2008/01/15/175465.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/175465.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2008/01/15/175465.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/175465.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/175465.html</trackback:ping><description><![CDATA[zz: http://daoger.javaeye.com/blog/47801<br />
<br />
2.调用有简单返回值的java方法
<br />
2.1、<span class="hilite1">dwr</span>.xml的配置
<br />
配置同1.1
<br />
&lt;<span class="hilite1">dwr</span>&gt;
<br />
&lt;allow&gt;
<br />
&lt;create creator="new" javascript="testClass" &gt;
<br />
&lt;param name="class" value="com.<span class="hilite1">dwr</span>.TestClass" /&gt;
<br />
&lt;include method="testMethod2"/&gt;
<br />
&lt;/create&gt;
<br />
&lt;/allow&gt;
<br />
&lt;/<span class="hilite1">dwr</span>&gt;
<br />
2.2、javascript中调用
<br />
首先，引入javascript脚本
<br />
其次，编写调用java方法的javascript函数和接收返回值的回调函数
<br />
Function callTestMethod2(){
<br />
testClass.testMethod2(callBackFortestMethod2);
<br />
}
<br />
Function callBackFortestMethod2(data){
<br />
//其中date接收方法的返回值
<br />
//可以在这里对返回值进行处理和显示等等
<br />
alert("the return value is " + data);
<br />
}
<br />
其中callBackFortestMethod2是接收返回值的回调函数
<br />
<br />
<br />
3、调用有简单参数的java方法
<br />
3.1、<span class="hilite1">dwr</span>.xml的配置
<br />
配置同1.1
<br />
&lt;<span class="hilite1">dwr</span>&gt;
<br />
&lt;allow&gt;
<br />
&lt;create creator="new" javascript="testClass" &gt;
<br />
&lt;param name="class" value="com.<span class="hilite1">dwr</span>.TestClass" /&gt;
<br />
&lt;include method="testMethod3"/&gt;
<br />
&lt;/create&gt;
<br />
&lt;/allow&gt;
<br />
&lt;/<span class="hilite1">dwr</span>&gt;
<br />
3.2、javascript中调用
<br />
首先，引入javascript脚本
<br />
其次，编写调用java方法的javascript函数
<br />
Function callTestMethod3(){
<br />
//定义要传到java方法中的参数
<br />
var data;
<br />
//构造参数
<br />
data = &#8220;test String&#8221;;
<br />
testClass.testMethod3(data);
<br />
}
<br />
<br />
<br />
4、调用返回JavaBean的java方法
<br />
4.1、<span class="hilite1">dwr</span>.xml的配置
<br />
&lt;<span class="hilite1">dwr</span>&gt;
<br />
&lt;allow&gt;
<br />
&lt;create creator="new" javascript="testClass" &gt;
<br />
&lt;param name="class" value="com.<span class="hilite1">dwr</span>.TestClass" /&gt;
<br />
&lt;include method="testMethod4"/&gt;
<br />
&lt;/create&gt;
<br />
&lt;convert converter="bean" match=""com.<span class="hilite1">dwr</span>.TestBean"&gt;
<br />
&lt;param name="include" value="username,password" /&gt;
<br />
&lt;/convert&gt;
<br />
&lt;/allow&gt;
<br />
&lt;/<span class="hilite1">dwr</span>&gt;
<br />
&lt;creator&gt;标签负责公开用于Web远程的类和类的方法，&lt;convertor&gt;标签则负责这些方法的参数和返回类型。convert元素的作用是告诉<span class="hilite1">DWR</span>在服务器端Java 对象表示和序列化的JavaScript之间如何转换数据类型。<span class="hilite1">DWR</span>自动地在Java和JavaScript表示之间调整简单数据类型。这些类型包括Java原生类型和它们各自的封装类表示，还有String、Date、数组和集合类型。<span class="hilite1">DWR</span>也能把JavaBean转换成JavaScript 表示，但是出于安全性的原因，要求显式的配置，&lt;convertor&gt;标签就是完成此功能的。converter="bean"属性指定转换的方式采用JavaBean命名规范，match=""com.<span class="hilite1">dwr</span>.TestBean"属性指定要转换的javabean名称，&lt;param&gt;标签指定要转换的JavaBean属性。
<br />
4.2、javascript中调用
<br />
首先，引入javascript脚本
<br />
其次，编写调用java方法的javascript函数和接收返回值的回调函数
<br />
Function callTestMethod4(){
<br />
testClass.testMethod4(callBackFortestMethod4);
<br />
}
<br />
Function callBackFortestMethod4(data){
<br />
//其中date接收方法的返回值
<br />
//对于JavaBean返回值，有两种方式处理
<br />
//不知道属性名称时，使用如下方法
<br />
for(var property in data){
<br />
alert("property:"+property);
<br />
alert(property+":"+data[property]);
<br />
}
<br />
//知道属性名称时，使用如下方法
<br />
alert(data.username);
<br />
alert(data.password);
<br />
}
<br />
其中callBackFortestMethod4是接收返回值的回调函数
<br />
<br />
5、调用有JavaBean参数的java方法
<br />
5.1、<span class="hilite1">dwr</span>.xml的配置
<br />
配置同4.1
<br />
&lt;<span class="hilite1">dwr</span>&gt;
<br />
&lt;allow&gt;
<br />
&lt;create creator="new" javascript="testClass" &gt;
<br />
&lt;param name="class" value="com.<span class="hilite1">dwr</span>.TestClass" /&gt;
<br />
&lt;include method="testMethod5"/&gt;
<br />
&lt;/create&gt;
<br />
&lt;convert converter="bean" match="com.<span class="hilite1">dwr</span>.TestBean"&gt;
<br />
&lt;param name="include" value="username,password" /&gt;
<br />
&lt;/convert&gt;
<br />
&lt;/allow&gt;
<br />
&lt;/<span class="hilite1">dwr</span>&gt;
<br />
5.2、javascript中调用
<br />
首先，引入javascript脚本
<br />
其次，编写调用java方法的javascript函数
<br />
Function callTestMethod5(){
<br />
//定义要传到java方法中的参数
<br />
var data;
<br />
//构造参数，date实际上是一个object
<br />
data = { username:"user", password:"password" }
<br />
testClass.testMethod5(data);
<br />
}
<br />
<br />
<br />
6、调用返回List、Set或者Map的java方法
<br />
6.1、<span class="hilite1">dwr</span>.xml的配置
<br />
配置同4.1
<br />
&lt;<span class="hilite1">dwr</span>&gt;
<br />
&lt;allow&gt;
<br />
&lt;create creator="new" javascript="testClass" &gt;
<br />
&lt;param name="class" value="com.<span class="hilite1">dwr</span>.TestClass" /&gt;
<br />
&lt;include method="testMethod6"/&gt;
<br />
&lt;/create&gt;
<br />
&lt;convert converter="bean" match="com.<span class="hilite1">dwr</span>.TestBean"&gt;
<br />
&lt;param name="include" value="username,password" /&gt;
<br />
&lt;/convert&gt;
<br />
&lt;/allow&gt;
<br />
&lt;/<span class="hilite1">dwr</span>&gt;
<br />
注意：如果List、Set或者Map中的元素均为简单类型（包括其封装类）或String、Date、数组和集合类型，则不需要&lt;convert&gt;标签。
<br />
6.2、javascript中调用(以返回List为例，List的元素为TestBean)
<br />
首先，引入javascript脚本
<br />
其次，编写调用java方法的javascript函数和接收返回值的回调函数
<br />
Function callTestMethod6(){
<br />
testClass.testMethod6(callBackFortestMethod6);
<br />
}
<br />
Function callBackFortestMethod6(data){
<br />
//其中date接收方法的返回值
<br />
//对于JavaBean返回值，有两种方式处理
<br />
//不知道属性名称时，使用如下方法
<br />
for(var i=0;i&lt;data.length;i++){
<br />
for(var property in data){
<br />
alert("property:"+property);
<br />
alert(property+":"+data[property]);
<br />
}
<br />
}
<br />
//知道属性名称时，使用如下方法
<br />
for(var i=0;i&lt;data.length;i++){
<br />
alert(data[i].username);
<br />
alert(data[i].password);
<br />
}
<br />
}
<br />
<br />
<br />
7、调用有List、Set或者Map参数的java方法
<br />
7.1、<span class="hilite1">dwr</span>.xml的配置
<br />
&lt;<span class="hilite1">dwr</span>&gt;
<br />
&lt;allow&gt;
<br />
&lt;create creator="new" javascript="testClass" &gt;
<br />
&lt;param name="class" value="com.<span class="hilite1">dwr</span>.TestClass" /&gt;
<br />
&lt;include method="testMethod7"/&gt;
<br />
&lt;/create&gt;
<br />
&lt;convert converter="bean" match="com.<span class="hilite1">dwr</span>.TestBean"&gt;
<br />
&lt;param name="include" value="username,password" /&gt;
<br />
&lt;/convert&gt;
<br />
&lt;/allow&gt;
<br />
&lt;<span class="hilite2">signatures</span>&gt;
<br />
&lt;![CDATA[
<br />
import java.util.List;
<br />
import com.<span class="hilite1">dwr</span>.TestClass;
<br />
import com.<span class="hilite1">dwr</span>.TestBean;
<br />
TestClass.testMethod7(List&lt;TestBean&gt;);
<br />
]]&gt;
<br />
&lt;/<span class="hilite2">signatures</span>&gt;
<br />
&lt;/<span class="hilite1">dwr</span>&gt;
<br />
&lt;<span class="hilite2">signatures</span>&gt;标签是用来声明java方法中List、Set或者Map参数所包含的确切类，以便java代码作出判断。
<br />
7.2、javascript中调用(以返回List为例，List的元素为TestBean)
<br />
首先，引入javascript脚本
<br />
其次，编写调用java方法的javascript函数
<br />
Function callTestMethod7(){
<br />
//定义要传到java方法中的参数
<br />
var data;
<br />
//构造参数，date实际上是一个object数组，即数组的每个元素均为object
<br />
data = [
<br />
{
<br />
username:"user1",
<br />
password:"password2"
<br />
},
<br />
{
<br />
username:"user2",
<br />
password:" password2"
<br />
}
<br />
];
<br />
testClass.testMethod7(data);
<br />
}
<br />
<br />
注意：
<br />
1、对于第6种情况，如果java方法的返回值为Map，则在接收该返回值的javascript回调函数中如下处理：
<br />
function callBackFortestMethod(data){
<br />
//其中date接收方法的返回值
<br />
for(var property in data){
<br />
var bean = data[property];
<br />
alert(bean.username);
<br />
alert(bean.password);
<br />
}
<br />
}
<br />
2、对于第7种情况，如果java的方法的参数为Map（假设其key为String，value为TestBean），则在调用该方法的javascript函数中用如下方法构造要传递的参数：
<br />
function callTestMethod (){
<br />
//定义要传到java方法中的参数
<br />
var data;
<br />
//构造参数，date实际上是一个object，其属性名为Map的key，属性值为Map的value
<br />
data = {
<br />
"key1":{
<br />
username:"user1",
<br />
password:"password2"
<br />
},
<br />
"key2":{
<br />
username:"user2",
<br />
password:" password2"
<br />
}
<br />
};
<br />
testClass.testMethod(data);
<br />
}
<br />
并且在<span class="hilite1">dwr</span>.xml中增加如下的配置段
<br />
&lt;<span class="hilite2">signatures</span>&gt;
<br />
&lt;![CDATA[
<br />
import java.util.List;
<br />
import com.<span class="hilite1">dwr</span>.TestClass;
<br />
import com.<span class="hilite1">dwr</span>.TestBean;
<br />
TestClass.testMethod7(Map&lt;String,TestBean&gt;);
<br />
]]&gt;
<br />
&lt;/<span class="hilite2">signatures</span>&gt;
<br />
3、由以上可以发现，对于java方法的返回值为List(Set)的情况，<span class="hilite1">DWR</span>将其转化为Object数组，传递个javascript；对于java方法的返回值为Map的情况，<span class="hilite1">DWR</span>将其转化为一个Object，其中Object的属性为原Map的key值，属性值为原Map相应的value值。
<br />
4、如果java方法的参数为List(Set)和Map的情况，javascript中也要根据3种所说，构造相应的javascript数据来传递到java中。<br />
<img src ="http://www.blogjava.net/honzeland/aggbug/175465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2008-01-15 14:45 <a href="http://www.blogjava.net/honzeland/archive/2008/01/15/175465.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>glassfish java.net.UnknownHostException: xxx: xxx</title><link>http://www.blogjava.net/honzeland/archive/2008/01/09/174021.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Wed, 09 Jan 2008 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2008/01/09/174021.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/174021.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2008/01/09/174021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/174021.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/174021.html</trackback:ping><description><![CDATA[启动glassfish时，发生如下异常：<br />
xxx@xxx:/opt$ asadmin start-domain domain1<br />
Jan 9, 2008 2:49:18 PM com.sun.enterprise.util.ASenvPropertyReader setSystemProperties<br />
SEVERE: property_reader.unknownHost<br />
java.net.UnknownHostException: xxx: xxx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.InetAddress.getLocalHost(InetAddress.java:1353)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.enterprise.util.net.NetUtils.getCanonicalHostName(NetUtils.java:102)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.enterprise.util.ASenvPropertyReader.setSystemProperties(ASenvPropertyReader.java:201)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.enterprise.cli.commands.S1ASCommand.&lt;init&gt;(S1ASCommand.java:164)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.enterprise.cli.commands.BaseLifeCycleCommand.&lt;init&gt;(BaseLifeCycleCommand.java:101)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.enterprise.cli.commands.StartDomainCommand.&lt;init&gt;(StartDomainCommand.java:78)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.reflect.Constructor.newInstance(Constructor.java:513)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Class.newInstance0(Class.java:355)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Class.newInstance(Class.java:308)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.enterprise.cli.framework.CommandFactory.createCommand(CommandFactory.java:91)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.enterprise.cli.framework.CLIMain.invokeCommand(CLIMain.java:160)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.enterprise.cli.framework.CLIMain.main(CLIMain.java:79)<br />
Starting Domain domain1, please wait.<br />
Log redirected to /opt/glassfish/domains/domain1/logs/server.log.<br />
Redirecting output to /opt/glassfish/domains/domain1/logs/server.log<br />
Domain domain1 is ready to receive client requests. Additional services are being started in background. <br />
java.net.UnknownHostException: hongzeguo: hongzeguo<br />
CLI156 Could not start the domain domain1.<br />
<br />
Solution：<br />
xxx@xxx:/opt$ nslookup xxx<br />
Server:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 202.106.46.151<br />
Address:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 202.106.46.151#53<br />
<br />
** server can't find xxx: NXDOMAIN<br />
<br />
Check your /etc/hosts file. Does it have an entry with actual name and ip address of your box? <br />
For example: append follows&nbsp; to /etc/hosts<br />
127.0.0.1 xxx<br />
<br />
<br />
<img src ="http://www.blogjava.net/honzeland/aggbug/174021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2008-01-09 15:19 <a href="http://www.blogjava.net/honzeland/archive/2008/01/09/174021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JMock Examples</title><link>http://www.blogjava.net/honzeland/archive/2007/12/13/167464.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Thu, 13 Dec 2007 04:45:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2007/12/13/167464.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/167464.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2007/12/13/167464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/167464.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/167464.html</trackback:ping><description><![CDATA[The following is a simple example of a servlet we will write unit tests for:<br />
<br />
The servlet:<br />
import javax.servlet.http.HttpServlet;<br />
import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpServletResponse;<br />
import javax.servlet.ServletException;<br />
import java.io.IOException;<br />
import java.util.Map;<br />
<br />
public class MyServlet extends HttpServlet {<br />
&nbsp;&nbsp; &nbsp;private MyService myService;<br />
&nbsp;&nbsp; &nbsp;public void setMyService(MyService myService) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.myService = myService;<br />
&nbsp;&nbsp; &nbsp;}<br />
<br />
&nbsp;&nbsp; &nbsp;public void process(HttpServletRequest request, HttpServletResponse response) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;String action = request.getParameter("action");<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if ("update".equals(action)) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Map parameters = request.getParameterMap();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;myService.updateModel(parameters);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (MyException e) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;request.setAttribute("error", e.getMessage());<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;request.setAttribute("model", myService.getModel());<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;getServletContext().getRequestDispatcher("myView.jsp").forward(request, response);<br />
&nbsp;&nbsp; &nbsp;}<br />
<br />
&nbsp;&nbsp; &nbsp;protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;process(request, response);<br />
&nbsp;&nbsp; &nbsp;}<br />
}<br />
<br />
The unit test: <br />
&nbsp;&nbsp;&nbsp; * if the action is update, does it call myService.updateModel (example is below)<br />
&nbsp;&nbsp;&nbsp; * if myService.updateModel throws an exception does the response contain the exceptions message (not implemented below)<br />
import org.jmock.Mock;<br />
import org.jmock.MockObjectTestCase;<br />
public class MyServletTest extends MockObjectTestCase {<br />
&nbsp;&nbsp; &nbsp;private Mock mockMyService;<br />
&nbsp;&nbsp; &nbsp;private Mock mockRequest;<br />
&nbsp;&nbsp; &nbsp;private Mock mockResponse;<br />
&nbsp;&nbsp; &nbsp;private MyService myService;<br />
&nbsp;&nbsp; &nbsp;private HttpServletRequest request;<br />
&nbsp;&nbsp; &nbsp;private HttpServletResponse response;<br />
&nbsp;&nbsp; &nbsp;private MyServlet myServlet;<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;protected void setUp() throws java.lang.Exception {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;mockMyService = mock(MyService.class);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;mockRequest = mock(HttpServletRequest.class);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;mockResponse = mock(HttpServletResponse.class);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;myService = (MyService) mockMyService.proxy();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;request = (HttpServletRequest) mockRequest.proxy();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;response = (HttpServletResponse) mockResponse.proxy();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;myServlet = new MyServlet();<br />
&nbsp;&nbsp; &nbsp;}<br />
<br />
&nbsp;&nbsp; &nbsp;public void testUpdate() {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// SETUP ANY OBJECTS USED ONLY IN THIS TESTCASE<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Map parameters = new Hashtable();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// SETUP THE EXPECTED CALLS TO THE MOCK OBJECTS<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// setup the mock request object to have the getParameter <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// method called once with argument being equal to the <br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// string action and have it return the string update<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;mockRequest.expects(once()).method("getParameter").<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;with(eq("action")).will(returnValue("update"));<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// setup the mock request object to have the getParameterMap<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// method called once with no arguments and have it<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// return an empty map<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;mockRequest.expects(once()).method("getParameterMap")<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;.will(returnValue(parameters));<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// setup the mock myService object to have the updateModel<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// method called once with the parameters map as the<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// argument<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;mockMyService.expects(once()).method("updateModel").with(same(parameters));<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// setup the mock myService object to have the getModel<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// method called once with no arguments and have it<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// return an empty map<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;mockMyService.expects(once()).method("getModel")<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;.will(returnValue(parameters));<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// setup the mock myService object to have the updateModel<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// method called once with the parameters map as the<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// argument<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;mockRequest.expects(once()).method("setAttribute").with(eq("model"), same(parameters));<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// RUN THE TEST<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// add the myService mock object to the servlet so<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// that it can handle calls later<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;myServlet.setMyService(myService);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;myServlet.process(request, response);<br />
&nbsp;&nbsp; &nbsp;}<br />
}<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/honzeland/aggbug/167464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2007-12-13 12:45 <a href="http://www.blogjava.net/honzeland/archive/2007/12/13/167464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse 启动设置，避免Out of Memory</title><link>http://www.blogjava.net/honzeland/archive/2007/12/13/167463.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Thu, 13 Dec 2007 04:40:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2007/12/13/167463.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/167463.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2007/12/13/167463.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/167463.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/167463.html</trackback:ping><description><![CDATA[-vmargs<br />
-Xmx512M<br />
-XX:PermSize=64M<br />
-XX:MaxPermSize=128M<br />
<br />
<img src ="http://www.blogjava.net/honzeland/aggbug/167463.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2007-12-13 12:40 <a href="http://www.blogjava.net/honzeland/archive/2007/12/13/167463.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>国外著名java技术资料网站</title><link>http://www.blogjava.net/honzeland/archive/2007/05/18/118366.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 18 May 2007 06:59:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2007/05/18/118366.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/118366.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2007/05/18/118366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/118366.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/118366.html</trackback:ping><description><![CDATA[<p style="color: red;"><a href="http://www.onjava.com/" target="_blank">http://www.onjava.com</a></p>
<p>&nbsp;&nbsp;&nbsp; <span style="color: red;">O'Reilly的Java网站. 每周都有新文章</span></p>
<p><a href="http://java.sun.com/" target="_blank">http://java.sun.com</a></p>
<p>&nbsp;&nbsp;&nbsp; 官方的Java开发者网站 - 每周都有新文章发表</p>
<p><a href="http://www.developer.com/java" target="_blank">http://www.developer.com/java</a></p>
<p>&nbsp;&nbsp;&nbsp; <span style="color: red;">由Gamelan.com 维护的Java技术文章网站</span></p>
<p><a href="http://www.java.net/" target="_blank">http://www.java.net</a></p>
<p>&nbsp;&nbsp;&nbsp; Sun公司维护的一个Java社区网站</p>
<p><a href="http://www.ibm.com/developerworks/java" target="_blank">http://www.ibm.com/developerworks/java</a>
</p>
<p>&nbsp;&nbsp;&nbsp; IBM的Developerworks技术网站; 这是其中的Java技术主页</p>
<p><a href="http://www.javaworld.com/" target="_blank">http://www.javaworld.com</a></p>
<p>&nbsp;&nbsp;&nbsp; <span style="color: red;">最早的一个Java站点. 每周更新Java技术文章</span></p>
<a href="http://www.javadesktop.org/" target="_blank">http://www.javadesktop.org</a>
<p>&nbsp;&nbsp;&nbsp; 位于Java.net的一个Java桌面技术社区网站. </p>
<p><a href="http://www.theserverside.com/" target="_blank">http://www.theserverside.com</a>
</p>
<p>&nbsp;&nbsp;&nbsp; 这是一个讨论所有Java服务器端技术的网站. </p>
<p><a href="http://www.jars.com/" target="_blank">http://www.jars.com</a>
</p>
<p>&nbsp;&nbsp;&nbsp; 提供Java评论服务. 包括各种framework和应用程序</p>
<p><a href="http://www.ibiblio.org/javafaq/javafaq.html" target="_blank">http://www.ibiblio.org/javafaq/javafaq.html</a>
</p>
<p>&nbsp;&nbsp;&nbsp; comp.lang.java的FAQ站点 - 收集了来自comp.lang.java新闻组的问题和答案的分类目录. </p>
<p><a href="http://java.sun.com/docs/books/tutorial/" target="_blank">http://java.sun.com/docs/books/tutorial/</a>
</p>
<p>&nbsp;&nbsp;&nbsp; 来自SUN公司的官方Java指南 - 对于了解几乎所有的java技术特性非常有帮助. </p>
<p><a href="http://www.javablogs.com/" target="_blank">http://www.javablogs.com</a>
</p>
&nbsp;&nbsp;&nbsp; 互联网上最活跃的一个Java Blog网站.
<p style="color: red;"><a href="http://www.java2s.com/" target="_blank">http://www.java2s.com</a></p>
&nbsp;&nbsp;<span style="color: red;">&nbsp; Java Codes</span><br>  <img src ="http://www.blogjava.net/honzeland/aggbug/118366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2007-05-18 14:59 <a href="http://www.blogjava.net/honzeland/archive/2007/05/18/118366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于ServerSocket.accept()</title><link>http://www.blogjava.net/honzeland/archive/2006/11/30/84607.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Thu, 30 Nov 2006 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2006/11/30/84607.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/84607.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2006/11/30/84607.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/84607.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/84607.html</trackback:ping><description><![CDATA[
		<p style="TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<span style="FONT-SIZE: 10.5pt">
						<font face="宋体">对于<span lang="EN-US">TCP</span>套接字，在服务器端通常采用下面的语句来实现：</font>
						<span lang="EN-US">
								<br />
								<font face="宋体">    ServerSocket welcomeSocket = new ServerSocket(6789);  (1)<br />    Socket connectionSocket = welcomeSocket.accept();     (2) <br /></font>
						</span>
						<font face="宋体">第（<span lang="EN-US">1</span>）句创建了一个能监听某些客户机<span lang="EN-US">“</span>敲门<span lang="EN-US">”</span>声的门，<span lang="EN-US">welcomeSocket</span>在<span lang="EN-US">6789</span>端口上监听；当某些客户机与<span lang="EN-US">welcomeSocket</span>连接时，第（<span lang="EN-US">2</span>）句创建了一个新的套接字，称为<span lang="EN-US">connectionSocket</span>，这个套接字<span style="COLOR: red">也使用<span lang="EN-US">6789</span>端口</span>，这时，两个套接字使用了相同的端口号，因为<span lang="EN-US">TCP</span><span style="COLOR: red">连接套接字</span>由一个四元组（源<span lang="EN-US">IP</span>地址，源端口号，目的<span lang="EN-US">IP</span>地址，目的端口号）来标识，<span lang="EN-US">UDP</span>套接字（面向无连接的）由一个包含目的<span lang="EN-US">IP</span>地址和目的端口号组成的二元组来标识。之后，<span lang="EN-US">TCP</span>在客户端的<span lang="EN-US">clientSocket</span>和服务器端的<span lang="EN-US">connectionSocket</span>之间建立了一条直接的虚礼管道，该客户机与服务器可以通过该管道彼此发送字节，并且发送的所有字节将按顺序到达对方。随着<span lang="EN-US">connectionSocket</span>的建立，该服务器能继续使用<span lang="EN-US">welcomeSocket</span>监听其它客户机的连接请求。<span lang="EN-US"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
<img src ="http://www.blogjava.net/honzeland/aggbug/84607.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2006-11-30 16:46 <a href="http://www.blogjava.net/honzeland/archive/2006/11/30/84607.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Override and Overload</title><link>http://www.blogjava.net/honzeland/archive/2006/11/10/80325.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 10 Nov 2006 02:37:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2006/11/10/80325.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/80325.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2006/11/10/80325.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/80325.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/80325.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<strong>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Override:</span>
				</strong>
				<strong>
						<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（覆盖）</span>
				</strong>
				<b>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">
								<br />
						</span>
				</b>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">1</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Override</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">发生在继承中，使得一个子类</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Override</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其父类的一个</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">method</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">
						<br />2</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Override Rules</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Keeping the contract</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。子类</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">override</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">父类的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">method</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时，必须要保证</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">overriding method</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和父类中的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">overridden method</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">具有相同的对外协议</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">contract</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，即<span style="COLOR: red">相同的参数列表和兼容的返回类型</span>。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">
						<br />3</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Arguments must be the same, and return types must be compatible.<br />4</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">The method can't be less accessible. </span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">考虑如下情况：如果访问权限变小了，如由父类</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Parent</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">public void test()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">变成子类</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Son</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">private void test()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，如果编译器允许权限变小，在某一类中有如下语句：</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Parent p = new Son()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">p.test()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；则这些语句能够通过编译，当该类加载运行时，将会出现错误，因为父类</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">reference p</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">指向的是一子类</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Son</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的对象，而</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Son</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">test()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">private</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，不能在其他类中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">invoke</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">
						<br />      </span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">另外，上面的语句在编译器允许权限变小情况下之所以能够通过编译，是因为在</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">“Parent p = new Son()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">”</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，声明了一个父类</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">Parent</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">reference p</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，由于</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">p</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是父类的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">reference</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，由于父类中的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">test()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">public</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，故</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">“p.test()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">”</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">能够通过编译；而在运行时，</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">p</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">指向的是一个子类的对象，</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">p.test()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在运行时调用的是子类对象中的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">test()</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">
						<br />
						<br />
						<strong>Overload</strong>
				</span>
				<strong>
						<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：（重载）</span>
				</strong>
				<b>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">
								<br />
						</span>
				</b>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">1</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、重载：两个或多个</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">methods</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">具有<span style="COLOR: red">相同的</span></span>
				<span lang="EN-US" style="COLOR: red; mso-bidi-font-size: 10.5pt">name</span>
				<span style="COLOR: red; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
				<span style="COLOR: red; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不同的</span>
				<span lang="EN-US" style="COLOR: red; mso-bidi-font-size: 10.5pt">argument lists</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">
						<br />2</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">The return types can be different.<br />3</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">You can't change <span style="COLOR: red">ONLY</span> the return type</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：不能仅仅改变返回类型，</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">To overload a method, you <span style="COLOR: red">MUST</span> change the argument list, although you can change the return type to anything.<br />4</span>
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">You can vary the access levels in any direction.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span>
		</p>
<img src ="http://www.blogjava.net/honzeland/aggbug/80325.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2006-11-10 10:37 <a href="http://www.blogjava.net/honzeland/archive/2006/11/10/80325.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>全面解析Java中的String数据类型</title><link>http://www.blogjava.net/honzeland/archive/2006/11/05/79190.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Sun, 05 Nov 2006 06:32:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2006/11/05/79190.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/79190.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2006/11/05/79190.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/79190.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/79190.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b style="mso-bidi-font-weight: normal">
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">1. </span>
				</b>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">首先</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">不属于</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">8</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">种基本数据类型，</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">是一个对象。</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />
						</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　因为对象的默认值是</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">null</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">，所以</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的默认值也是</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">null</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">；但它又是一种特殊的对象，有其它对象没有的一些特性。</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />
								<b style="mso-bidi-font-weight: normal">2.</b> new String()</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">和</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">new String(“”)</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">都是申明一个新的空字符串，是空串不是</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">null</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">；</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />
								<b style="mso-bidi-font-weight: normal">3.</b> String str=”kvill”</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">；</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String str=new String (“kvill”);</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的区别：在这里，我们不谈堆，也不谈栈，只先简单引入常量池这个简单的概念。</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />
						</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　<span style="COLOR: red">常量池</span></span>
				<span lang="EN-US" style="COLOR: red; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">(constant pool)</span>
				<span style="COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">指的是在编译期被确定，并被保存在已编译的</span>
				<span lang="EN-US" style="COLOR: red; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">.class</span>
				<span style="COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">文件中的一些数据。它包括了关于类、方法、接口等中的常量，也包括字符串常量。</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />
						</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　看例</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">1</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">：</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />String s0=”kvill”; <br />String s1=”kvill”; <br />String s2=”kv” + “ill”; <br />System.out.println( s0==s1 ); <br />System.out.println( s0==s2 ); <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　结果为：</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />true <br />true <br /></span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　首先，我们要知结果为道</span>
				<span lang="EN-US" style="COLOR: red; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">Java</span>
				<span style="COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">会确保一个字符串常量只有一个拷贝</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　因为例子中的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s0</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">和</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s1</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">中的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">都是字符串常量，它们<span style="COLOR: red">在编译期就被确定了</span>，所以</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s0==s1</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">为</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">true</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">；而</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kv”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">和</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”ill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">也都是字符串常量，当一个字符串由多个字符串常量连接而成时，它自己肯定也是字符串常量，所以</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s2</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">也同样在编译期就被解析为一个字符串常量，所以</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s2</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">也是常量池中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的一个引用。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　所以我们得出</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s0==s1==s2; </span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">用</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">new String() </span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">创建的字符串不是常量，不能在编译期就确定，所以</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">new String() </span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">创建的字符串不放入常量池中，它们有自己的地址空间。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　看例</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">2</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">：</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />String s0=”kvill”; <br />String s1=new String(”kvill”); <br />String s2=”kv” + new String(“ill”); <br />System.out.println( s0==s1 ); <br />System.out.println( s0==s2 ); <br />System.out.println( s1==s2 ); <br /></span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　结果为：</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />false <br />false <br />false<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　例</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">2</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s0</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">还是常量池中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的应用，</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s1</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">因为无法在编译期确定，所以是运行时创建的新对象</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的引用，</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s2</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">因为有后半部分</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">new String(“ill”)</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">所以也无法在编译期确定，所以也是一个新创建对象</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的应用</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">;</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">明白了这些也就知道为何得出此结果了。</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />
								<b style="mso-bidi-font-weight: normal">4. </b>String.intern()</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">：</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />
						</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　再补充介绍一点：存在于</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">.class</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">文件中的常量池，在运行期被</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">JVM</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">装载，并且可以扩充。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">intern()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">方法就是扩充常量池的一个方法；当一个</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">实例</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">str</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">调用</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">intern()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">方法时，</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">Java</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">查找常量池中是否有相同</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">Unicode</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的字符串常量，如果有，则返回其的引用，如果没有，则在常量池中增加一个</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">Unicode</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">等于</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">str</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的字符串并返回它的引用；看例</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">3</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">就清楚了</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />
						</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　例</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">3</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">：</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />String s0= “kvill”; <br />String s1=new String(”kvill”); <br />String s2=new String(“kvill”); <br />System.out.println( s0==s1 ); <br />System.out.println( “**********” ); <br />s1.intern(); <br />s2=s2.intern(); //</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">把常量池中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">“kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的引用赋给</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s2 <br />System.out.println( s0==s1); <br />System.out.println( s0==s1.intern() ); <br />System.out.println( s0==s2 ); <br /></span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　结果为：</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />false <br />********** <br />false //</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">虽然执行了</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s1.intern(),</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">但它的返回值没有赋给</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s1 <br />true //</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">说明</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s1.intern()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">返回的是常量池中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的引用</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />true<br /></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　最后我再破除一个错误的理解：有人说，</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">“</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">使用</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String.intern()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">方法则可以将一个</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">类的保存到一个全局</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">表中，如果具有相同值的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">Unicode</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">字符串已经在这个表中，那么该方法返回表中已有字符串的地址，如果在表中没有相同值的字符串，则将自己的地址注册到表中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">“</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">如果我把他说的这个全局的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">表理解为常量池的话，他的最后一句话，</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">“</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">如果在表中没有相同值的字符串，则将自己的地址注册到表中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">是错的：</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />
						</span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　看例</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">4</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">：</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<br />String s1=new String("kvill"); <br />String s2=s1.intern(); <br />System.out.println( s1==s1.intern() ); <br />System.out.println( s1+" "+s2 ); <br />System.out.println( s2==s1.intern() ); <br /></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　结果：</span>
				<span style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">false <br />kvill kvill <br />true <br /></span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　在这个类中我们没有声名一个</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">常量，所以常量池中一开始是没有</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的，当我们调用</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s1.intern()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">后就在常量池中新添加了一个</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">常量，原来的不在常量池中的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">仍然存在，也就不是</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">“</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">将自己的地址注册到常量池中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">了。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s1==s1.intern()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">为</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">false</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">说明原来的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">“kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">仍然存在；</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s2</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">现在为常量池中</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">“kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的地址，所以有</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">s2==s1.intern()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">为</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">true</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />
						<b style="mso-bidi-font-weight: normal">5.</b>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">关于</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">equals()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">和</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">==<br /></span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　这个对于</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">简单来说就是比较两字符串的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">Unicode</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">序列是否相当，如果相等返回</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">true;</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">而</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">==</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">是比较两字符串的地址是否相同，也就是是否是同一个字符串的引用。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />
						<b style="mso-bidi-font-weight: normal">6.</b>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">关于</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">是不可变的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<br />
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　这一说又要说很多，大家只要知道</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的实例一旦生成就不会再改变了，比如说：</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String str=”kv”+”ill”+” “+”ans”; <br /></span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">　　就是有</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">4</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">个字符串常量，首先</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kv”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">和</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”ill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">生成了</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">存在内存中，然后</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">又和</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">” “ </span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">生成</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt"> ”kvill “</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">存在内存中，最后又和生成了</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”kvill ans”;</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">并把这个字符串的地址赋给了</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">str,</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">就是因为</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">“</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">不可变</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">产生了很多临时变量，这也就是为什么建议用</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">StringBuffer</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">的原因了，因为</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">StringBuffer</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">是可改变的。</span>
				<span lang="EN-US" style="mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">
						<o:p>
						</o:p>
				</span>
		</p>
<img src ="http://www.blogjava.net/honzeland/aggbug/79190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2006-11-05 14:32 <a href="http://www.blogjava.net/honzeland/archive/2006/11/05/79190.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Abstract class and interface</title><link>http://www.blogjava.net/honzeland/archive/2006/10/26/77439.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Thu, 26 Oct 2006 09:27:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2006/10/26/77439.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/77439.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2006/10/26/77439.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/77439.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/77439.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">1</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、抽象类和接口都不能被实例化；</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">2</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、抽象类：抽象类中可以不包含抽象方法，即类中的方法都是非抽象的，但是在类的声明中加上</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">abstract</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，以使得该类是抽象的，目的是防止客户端程序员创建该类的对象；</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">3</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、接口中的方法总是</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">abstract and public</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，不管是否被显示的声明；</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">4</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、接口中的</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">field</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">只能是</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">public static final</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">5</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、接口本身可以是</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">public or protected</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">6</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">extended class</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">必须实现抽象类中的所有抽象方法，</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">implemented class</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">必须实现接口中的所有方法，因为接口中的所有方法都是</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">abstract</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
<img src ="http://www.blogjava.net/honzeland/aggbug/77439.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2006-10-26 17:27 <a href="http://www.blogjava.net/honzeland/archive/2006/10/26/77439.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2EE学习笔记：</title><link>http://www.blogjava.net/honzeland/archive/2006/10/13/75013.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 13 Oct 2006 07:53:00 GMT</pubDate><guid>http://www.blogjava.net/honzeland/archive/2006/10/13/75013.html</guid><wfw:comment>http://www.blogjava.net/honzeland/comments/75013.html</wfw:comment><comments>http://www.blogjava.net/honzeland/archive/2006/10/13/75013.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/honzeland/comments/commentRss/75013.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/honzeland/services/trackbacks/75013.html</trackback:ping><description><![CDATA[
		<p>
				<font color="#ff0000" size="5">
						<strong>Part One: The Web Tier</strong>
				</font>
		</p>
		<p>
				<font size="5">
						<strong>
								<font size="4">Section One: Configuring Web Applications</font>
						</strong>
				</font>
		</p>
		<p>
				<font size="4">
						<strong>
								<font size="3">Mapping URLs to Web Components</font>
						</strong>
				</font>
		</p>
		<p class="pBody">When a request is received by the web container it must determine which web component should handle the request. It does so by mapping the URL path contained in the request to a web application and a web component. A URL path contains the context root and an alias: </p>
		<p class="pPreformattedRelative">http://<code class="cVariable">host</code>:<code class="cVariable">port</code>/<code class="cVariable">context_root</code>/<code class="cVariable">alias</code><a name="wp219218"></a></p>
		<p>A context root identifies a web application in a Java EE server. You specify the context root when you deploy a web module. A context root must start with a forward slash (/) and end with a string.<br /> <br />The alias identifies the web component that should handle a request. The alias path must start with a forward slash (/) and end with a string or a wildcard expression with an extension (for example, *.jsp). Since web containers automatically map an alias that ends with *.jsp, you do not have to specify an alias for a JSP page unless you wish to refer to the page by a name other than its file name. </p>
		<p class="pHeading2">
				<font size="4">
						<strong>
								<font size="3">Declaring Welcome Files</font>
						</strong>
				</font>
		</p>
		<a name="wp85893">
		</a>
		<p class="pBody">For example, suppose you define a welcome file welcome.html. When a client requests a URL such as host:port/webapp/directory, where directory is not mapped to a servlet or JSP page, the file host:port/webapp/directory/welcome.html is returned to the client.<br /></p>
		<p class="pBody">If no welcome file is specified, the Application Server will use a file named <code class="cCode">index.</code><code class="cVariable">XXX</code>, where <code class="cVariable">XXX</code> can be <code class="cCode">html</code> or <code class="cCode">jsp</code>, as the default welcome file. If there is no welcome file and no file named <code class="cCode">index.</code><code class="cVariable">XXX</code>, the Application Server returns a directory listing. </p>
		<a name="wp222536">
		</a>
		<p class="pBody">To specify a welcome file in the web application deployment descriptor, you need to nest a <code class="cCode">welcome-file</code> element inside a <code class="cCode">welcome-file-list</code> element. The <code class="cCode">welcome-file</code> element defines the JSP page to be used as the welcome page. Make sure this JSP page is actually included in your WAR file. <br /><br /></p>
		<p class="pHeading2">
				<font size="4">
						<strong>
								<font size="3">Setting Initialization Parameters</font>
						</strong>
				</font>
		</p>
		<a name="wp222559">
		</a>
		<p class="pBody">The web components in a web module share an object that represents their application context. You can pass initialization parameters to the context or to a web component. </p>
		<a name="wp226898">
		</a>
		<p class="pBody">To add a context parameter you need the following in the example's web.xml file: </p>
		<div class="pSmartList1">
				<ul class="pSmartList1">
						<a name="wp226899">
						</a>
						<div class="pSmartList1">
								<li>A <code class="cCode">param-name</code> element that specifies the context object </li>
						</div>
						<a name="wp229279">
						</a>
						<div class="pSmartList1">
								<li>A <code class="cCode">param-value</code> element that specifies the parameter to pass to the context object. </li>
						</div>
						<a name="wp229280">
						</a>
						<div class="pSmartList1">
								<li>A <code class="cCode">context-param</code> element that encloses the previous two elements. </li>
						</div>
				</ul>
		</div>
		<a name="wp229284">
		</a>
		<p class="pBody">To add a web component initialization parameter you need the following in the example's web.xml file: </p>
		<div class="pSmartList1">
				<ul class="pSmartList1">
						<a name="wp229291">
						</a>
						<div class="pSmartList1">
								<li>A <code class="cCode">param-name</code> element that specifies the name of the initialization parameter </li>
						</div>
						<a name="wp229292">
						</a>
						<div class="pSmartList1">
								<li>A <code class="cCode">param-value</code> element that specifies the value of the initialization parameter </li>
						</div>
						<a name="wp229293">
						</a>
						<div class="pSmartList1">
								<li>An <code class="cCode">init-param</code> element that encloses the previous two elements </li>
						</div>
				</ul>
		</div>
		<a name="wp83548">
		</a>
		<p class="pHeading2">
				<strong>Mapping Errors to Error Screens </strong>
		</p>
		<p class="pHeading2">
				<strong>Declaring Resource References </strong>
		</p>
		<p class="pBody">
				<br />
		</p>
<img src ="http://www.blogjava.net/honzeland/aggbug/75013.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/honzeland/" target="_blank">honzeland</a> 2006-10-13 15:53 <a href="http://www.blogjava.net/honzeland/archive/2006/10/13/75013.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>