﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-轻松-随笔分类-JAVA转贴</title><link>http://www.blogjava.net/relax/category/351.html</link><description>记述我学习java的里程</description><language>zh-cn</language><lastBuildDate>Tue, 17 Nov 2009 17:34:31 GMT</lastBuildDate><pubDate>Tue, 17 Nov 2009 17:34:31 GMT</pubDate><ttl>60</ttl><item><title>java 编码转换（转）</title><link>http://www.blogjava.net/relax/archive/2009/11/17/302686.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Tue, 17 Nov 2009 05:57:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2009/11/17/302686.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/302686.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2009/11/17/302686.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/302686.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/302686.html</trackback:ping><description><![CDATA[<p>由于Unicode兼容ASCII（0～255），因此，上面得到的Unicode就是ASCII。 至于转换成二进制或其他进制，Java API提供了方便函数，你可以查Java的API手册。 </p>
<p>以字符a的ASCII为例： int i = 'a'; String iBin = Integer.toBinaryString(i);//二进制 String iHex = Integer.toHexString(i);//十六进制 String iOct = Integer.toOctalString(i);//八进制 String iWoKao = Integer.toString(i,3);//三进制或任何你想要的35进制以下的进制 DEC</p>
<p>[集]java中进行二进制，八进制，十六进制，十进制间进行相互转换&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 十进制转成十六进制： Integer.toHexString(int i) 十进制转成八进制 Integer.toOctalString(int i) 十进制转成二进制 Integer.toBinaryString(int i) 十六进制转成十进制 Integer.valueOf("FFFF",16).toString() 八进制转成十进制 Integer.valueOf("876",8).toString() 二进制转十进制 Integer.valueOf("0101",2).toString()</p>
<p>有什么方法可以直接将2,8,16进制直接转换为10进制的吗? java.lang.Integer类 parseInt(String s, int radix) 使用第二个参数指定的基数，将字符串参数解析为有符号的整数。 examples from jdk: parseInt("0", 10) returns 0 parseInt("473", 10) returns 473 parseInt("-0", 10) returns 0 parseInt("-FF", 16) returns -255 parseInt("1100110", 2) returns 102 parseInt("2147483647", 10) returns 2147483647 parseInt("-2147483648", 10) returns -2147483648 parseInt("2147483648", 10) throws a NumberFormatException parseInt("99", 8) throws a NumberFormatException parseInt("Kona", 10) throws a NumberFormatException parseInt("Kona", 27) returns 411787</p>
<p>进制转换如何写（二，八，十六）不用算法 Integer.toBinaryString Integer.toOctalString Integer.toHexString </p>
<p>例一：</p>
<p>public class Test{&nbsp;&nbsp; public static void main(String args[]){</p>
<p>&nbsp;&nbsp; int i=100;&nbsp;&nbsp;&nbsp; String binStr=Integer.toBinaryString(i);&nbsp;&nbsp;&nbsp; String otcStr=Integer.toOctalString(i);&nbsp;&nbsp;&nbsp; String hexStr=Integer.toHexString(i);&nbsp;&nbsp;&nbsp; System.out.println(binStr);</p>
<p>例二：</p>
<p>public class TestStringFormat {&nbsp;&nbsp; public static void main(String[] args) {&nbsp;&nbsp;&nbsp; if (args.length == 0) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("usage: java TestStringFormat &lt;a number&gt;");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.exit(0);&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp; Integer factor = Integer.valueOf(args[0]);</p>
<p>&nbsp;&nbsp; String s;</p>
<p>&nbsp;&nbsp; s = String.format("%d", factor);&nbsp;&nbsp;&nbsp; System.out.println(s);&nbsp;&nbsp;&nbsp; s = String.format("%x", factor);&nbsp;&nbsp;&nbsp; System.out.println(s);&nbsp;&nbsp;&nbsp; s = String.format("%o", factor);&nbsp;&nbsp;&nbsp; System.out.println(s);&nbsp;&nbsp; } }</p>
<p>各种数字类型转换成字符串型： </p>
<p>String s = String.valueOf( value); // 其中 value 为任意一种数字类型。 </p>
<p>字符串型转换成各种数字类型： </p>
<p>String s = "169"; byte b = Byte.parseByte( s ); short t = Short.parseShort( s ); int i = Integer.parseInt( s ); long l = Long.parseLong( s ); Float f = Float.parseFloat( s ); Double d = Double.parseDouble( s ); </p>
<p>数字类型与数字类对象之间的转换： </p>
<p>byte b = 169; Byte bo = new Byte( b ); b = bo.byteValue(); </p>
<p>short t = 169; Short to = new Short( t ); t = to.shortValue(); </p>
<p>int i = 169; b = bo.byteValue(); </p>
<p>short t = 169; Short to = new Short( t ); t = to.shortValue(); </p>
<p>int i = 169; Integer io = new Integer( i ); i = io.intValue(); </p>
<p>long l = 169; Long lo = new Long( l ); l = lo.longValue(); </p>
<p>float f = 169f; Float fo = new Float( f ); f = fo.floatValue(); </p>
<p>double d = 169f; Double dObj = new Double( d ); d = dObj.doubleValue();</p>
<img src ="http://www.blogjava.net/relax/aggbug/302686.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2009-11-17 13:57 <a href="http://www.blogjava.net/relax/archive/2009/11/17/302686.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK1.5中对XML的简单操作</title><link>http://www.blogjava.net/relax/archive/2008/05/15/200676.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Thu, 15 May 2008 08:44:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2008/05/15/200676.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/200676.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2008/05/15/200676.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/200676.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/200676.html</trackback:ping><description><![CDATA[//TestXML.xml<br />
&lt;?xml version="1.0" encoding="GB2312" ?&gt; <br />
&lt;book&gt; <br />
&lt;title&gt;Java实例一百例&lt;/title&gt; <br />
&lt;page id="1"&gt; <br />
&lt;title&gt;基础知识篇&lt;/title&gt; <br />
&lt;file&gt;base.htm&lt;/file&gt; <br />
&lt;/page&gt; <br />
&lt;page id="3"&gt; <br />
&lt;title&gt;SWING篇&lt;/title&gt; <br />
&lt;file&gt;swing.htm&lt;/file&gt; <br />
&lt;/page&gt; <br />
&lt;page id="28"&gt; <br />
&lt;title&gt;EJB篇&lt;/title&gt; <br />
&lt;file&gt;ejb.htm&lt;/file&gt; <br />
&lt;/page&gt; <br />
&lt;page id="33"&gt; <br />
&lt;title&gt;DOM篇&lt;/title&gt; <br />
&lt;file&gt;xmldom.htm&lt;/file&gt; <br />
&lt;/page&gt; <br />
&lt;/book&gt; <br />
<br />
<br />
//TestXML.java<br />
import javax.xml.parsers.*; <br />
import org.w3c.dom.*; <br />
import java.io.*; <br />
<br />
public class TestXML { <br />
public static void main(String[] args) { <br />
try { <br />
//创建解析工厂 <br />
DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); <br />
//指定DocumentBuilder <br />
DocumentBuilder builder = dbfactory.newDocumentBuilder(); <br />
//从文件构造一个Document，因为XML文件中已经指定了编码，所以这里不必了 <br />
Document doc = builder.parse(new File("TestXML.xml")); <br />
//得到Document的根（节点名：book） <br />
Element root = doc.getDocumentElement(); <br />
System.out.println("根节点标记名：" + root.getTagName()); <br />
<br />
System.out.println("****下面遍历XML元素****"); <br />
//获得page元素 <br />
NodeList list = root.getElementsByTagName("page"); <br />
//遍历page元素 <br />
for (int i=0; i &lt; list.getLength() ; i++) { <br />
//获得page的元素 <br />
Element element = (Element)list.item(i); <br />
//获得ID属性 <br />
String id = element.getAttribute("id"); <br />
//获得title属性 <br />
NodeList titleList = element.getElementsByTagName("title"); <br />
//获得title元素 <br />
Element titleElement = (Element)titleList.item(0); <br />
//获得title元素的第一个值 <br />
String title = titleElement.getFirstChild().getNodeValue(); <br />
//获得file元素名称 <br />
NodeList fileList = element.getElementsByTagName("file"); <br />
//获得file元素 <br />
Element fileElement = (Element)fileList.item(0); <br />
//获得file元素的第一个值 <br />
String file = fileElement.getFirstChild().getNodeValue(); <br />
<br />
System.out.println("ID：" + id + " " + <br />
"标题：" + title + " " + <br />
"文件：" + file); <br />
} <br />
}<br />
catch (Exception e) { <br />
e.printStackTrace(); <br />
} <br />
} <br />
}
<img src ="http://www.blogjava.net/relax/aggbug/200676.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2008-05-15 16:44 <a href="http://www.blogjava.net/relax/archive/2008/05/15/200676.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java.lang.OutOfMemoryError的解決方法集</title><link>http://www.blogjava.net/relax/archive/2008/04/02/190438.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Wed, 02 Apr 2008 11:30:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2008/04/02/190438.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/190438.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2008/04/02/190438.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/190438.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/190438.html</trackback:ping><description><![CDATA[<p><font face="Verdana" color="#000000" size="4">Java虚拟机默认分配64M内存，如果你的应用比较大，超出64M内存，Java虚拟机就会抛出OutOfMemoryError，并停止运行。不管是什么应用（Web应用、Application等），只需要修改你的机器上的运行Java命令，在java&nbsp;xxx命令中添加-Xms(最小使用内存)、-Xmx（最大使用内存）即可解决。当然，这儿的内存容量都是指物理内存，不能超出你的机器的物理内存的总容量。</font></p>
<p><font face="Verdana" color="#000000" size="4">一、Ant使用中的OutOfMemoryError解决：</font></p>
<p><font face="Verdana"><font color="#000000" size="4">到你的Ant的安装目录，在bin子目录中找到ant.bat，使用文字编辑器打开，修改:runAnt处的允许命令，添加如下参数：<br />
<br />
:runAnt<br />
"%_JAVACMD%"&nbsp;-Xms128m&nbsp;-Xmx512m&nbsp;-classpath&nbsp;&#8230;&#8230;<br />
<br />
如果你安装了Jike，使用Jike编译器，则需要修改:runAntWithJikes处的运行命令，同上。</font></font></p>
<p><font face="Verdana"><font color="#000000" size="4">二、tomcat中的内存溢出优化</font></font></p>
<p><font size="4">安装版的：</font></p>
<p>设置的java选项卡有啦。</p>
<p>&nbsp;</p>
<p><font size="4">非安装版的：</font></p>
<p><font size="4">打开编辑catalina.bat，在文件开头处增加如下参数：</font></p>
<p><font face="Verdana"><font color="#000000" size="4">set JAVA_OPTS=-Xms128m -Xmx512m<br />
</font></font></p>
<p><font face="Verdana"><font color="#000000" size="4"><br />
转自:http://blog.csdn.net/zzr173/archive/2006/12/11/1438691.aspx</font></font></p>
<img src ="http://www.blogjava.net/relax/aggbug/190438.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2008-04-02 19:30 <a href="http://www.blogjava.net/relax/archive/2008/04/02/190438.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于提高自己JAVA水平的十大技术讨论</title><link>http://www.blogjava.net/relax/archive/2007/12/21/169224.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Fri, 21 Dec 2007 01:36:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2007/12/21/169224.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/169224.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2007/12/21/169224.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/169224.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/169224.html</trackback:ping><description><![CDATA[　本文列出了当今计算机软件开发和应用领域最重要十种关键
<p><nobr><strong class="kgb" onclick='javascript:window.open("http://pagead2.googlesyndication.com/pagead/iclk?sa=l&ai=BbACgHRZrR4CiIpDE6wORqaVXjL-ZNcCwgIcFwI23AaDRGRABGAEgrYXQDSgUOABQ5-Cz9ARgndnQgZQFqgEKMjAwMDAzNjEyN7IBDW5ld3MuY3Nkbi5uZXTIAQHaAStodHRwOi8vbmV3cy5jc2RuLm5ldC9uLzIwMDcxMjIwLzExMTkyNy5odG1sgAIByAL8iYoDqAMB6AO3AvUDAAQAAA&num=1&adurl=http://www.asus.com.cn/EVENT/2007/1026F8/&client=ca-pub-5186439242807756");GgKwClickStat("技术","www.asus.com.cn","afc","2000036127");' onmouseout='isShowGg = false;InTextAds_GgLayer="_u6280_u672F"' onmouseover='isShowAds = false;isShowAds2 = false;isShowGg = true;InTextAds_GgLayer="_u6280_u672F";KeyGate_ads.ShowGgAds(this,"_u6280_u672F",event)' style="border: 0px none ; margin: 0px; padding: 0px; color: #0000ff; font-weight: normal; text-decoration: underline;">技术</strong></nobr>排名，如果你想保证你现在以及未来的几年不失业，那么你最好跟上这些技术的发展。虽然你不必对这十种技术样样精通，但至少应该对它们非常熟悉。</p>
<p>　<strong>　一、XML</strong></p>
<p>　　在十种技术中，最重要的一种技术我想应该非XML莫属。这里不仅仅指XML规范本身，还包括一系列有关的基于XML的语言：主要有XHTML，
XSLT，XSL，DTDs，XML
Schema(XSD)，XPath，XQuery和SOAP.如果你现在还对XML一无所知，那么赶快狂补吧。XML是包含类似于HTML标签的一个文
本文件，在这个文件中定义了一个树型结构来描述它所保存的<nobr><strong class="kgb" onclick='javascript:window.open("http://s4.17luntan.com/ClickPortal/WebClick.aspx?id=-100850&k=%u6570%u636E&siteid=0098295a-e262-40f7-ae50-7a6fbbdb678b&url=http%3A//news.csdn.net/n/20071220/111927.html&gourl=http%3A//ibm.csdn.net/ISN_J.aspx%3Faction%3DJMP%26pointid%3D2488&parm=78041F5FDC78F73FFC82FDA498786D500E8C3D164E60120E&alliedsiteid=0");' onmouseout="isShowAds = false;isShowAds2 = false" onmouseover='isShowAds = true;isShowAds2 = true;KeyGate_ads.Move(this,"","%u4E00%u4E2A%u771F%u6B63%u7684%u591A%u4EFB%u52A1%u7CFB%u7EDF","-100850","数据","AIX%20V5.3%20%u7CFB%u7EDF%u7BA1%u7406","http%3A//ibm.csdn.net/ISN_J.aspx%3Faction%3DJMP%26pointid%3D2488", event)' style="border: 0px none ; color: #0000ff; font-weight: normal; text-decoration: underline;">数据</strong></nobr>。</p>
<p>　　XML最大的优点是你既可以在这个文本文件中存储结构化数据，也可以在其中存储非结构化数据——也就是说，它能包含和描述"粗糙的"文档数据，就象它描述"规则的"表格数据一样。</p>
<p>　　XHTML是目前编写HTML的首选方法;因为XHTML本身就是格式良好的XML，与通常畸形的HTML文档相比， XHTML格式文档更容易处理。</p>
<p>　　XSLT和XSL是对XML文档进行转换的语言。它们可以将XML文档转换成各种格式，比如另一个文本文件、PDF文件、HTML文件、逗号分割的文件，或者转换成其它的XML文档。</p>
<p>　　DTDs 和XML Schema用来描述XML文件所包含的数据内容的类型，使你不用编写定制的代码就能对XML文档的内容进行"有效性"检查，使内容强行遵守给出的规则。</p>
<p>　　XPath 和 XQuery是查询语言，用它们可以从XML文档中吸取单个的数据项或者数据项列表。XQuery的功能特别强大，因为它对XPath查询进行了扩展。实际上，XQuery和XML的关系就像SQL之于关系数据库一样。</p>
<p>　　SOAP是Web services间进行通讯的标准协议。你不必知道SOAP协议的所有细节，但是你应该熟悉其常用规则及其工作原理，这样你才能使用它。</p>
<p>　<strong>　二、Web Services</strong></p>
<p>　　Web<nobr><strong class="kgb" onclick='javascript:window.open("http://s4.17luntan.com/ClickPortal/WebClick.aspx?id=-100849&k=%u670D%u52A1&siteid=0098295a-e262-40f7-ae50-7a6fbbdb678b&url=http%3A//news.csdn.net/n/20071220/111927.html&gourl=http%3A//ibm.csdn.net/ISN_J.aspx%3Faction%3DJMP%26pointid%3D2473&parm=78041F5FDC78F73FFC82FDA498786D500E8C3D164E60120E&alliedsiteid=0");' onmouseout="isShowAds = false;isShowAds2 = false" onmouseover='isShowAds = true;isShowAds2 = true;KeyGate_ads.Move(this,"","%u4E00%u6B3E%u5F00%u6E90%u7684%u6027%u80FD%u6D4B%u8BD5%u5DE5%u5177","-100849","服务","%u5C06%20Ajax%20%u7528%u4E8E%u591A%u5A92%u4F53","http%3A//ibm.csdn.net/ISN_J.aspx%3Faction%3DJMP%26pointid%3D2473", event)' style="border: 0px none ; color: #0000ff; font-weight: normal; text-decoration: underline;">服务</strong></nobr>是XML
流行后的直接产物。因为XML可以描述数据和对象，XML大纲可以保证XML文档数据的有效性，因为XML的基于文本的规范，因而XML文档极其适合于作
为一种跨平台通讯标准的基本格式。如果你还没有接触过Web服务，那么过不了多久你肯定会碰到它，所以必须熟练掌握Web服务，最好是精通它，因为它是迄
今为止应用程序间跨不同种类机器、语言、平台和位置通讯的最简单的一种方式。不管你需不需要它，Web服务都会是将来互用性的主要趋势。</p>
<p>　　XML工作组的John Bosak曾说过："XML使得Java有事可做"，那么，我们也可以说，Web服务使得所有语言都有事可做。Web服务让运行在大型机上的COBOL应用程序与运行在手持设备上的应用程序相互沟通;让Java小应用与。NET<nobr><strong class="kgb" onclick='javascript:window.open("http://pagead2.googlesyndication.com/pagead/iclk?sa=l&ai=BaKT_HRZrR4CiIpDE6wORqaVXj_qTLZ_H-fYDwI23AfDXHBATGBMgrYXQDSgUOABQ7pejEmCd2dCBlAWqAQoyMDAwMDM2MTI3sgENbmV3cy5jc2RuLm5ldMgBAdoBK2h0dHA6Ly9uZXdzLmNzZG4ubmV0L24vMjAwNzEyMjAvMTExOTI3Lmh0bWypAscbcxfeNoI-yALTg-EBqAMB6AO3AvUDAAQAAA&num=19&adurl=http://www.joysuccess.com/proList.aspx&client=ca-pub-5186439242807756");GgKwClickStat("服务器","www.joysuccess.com","afc","2000036127");' onmouseout='isShowGg = false;InTextAds_GgLayer="_u670D_u52A1_u5668"' onmouseover='isShowAds = false;isShowAds2 = false;isShowGg = true;InTextAds_GgLayer="_u670D_u52A1_u5668";KeyGate_ads.ShowGgAds(this,"_u670D_u52A1_u5668",event)' style="border: 0px none ; margin: 0px; padding: 0px; color: #0000ff; font-weight: normal; text-decoration: underline;">服务器</strong></nobr>相互通讯，让桌面应用与Web服务器进行无缝交互，不但为商业数据处理，同时也为商业功能提供了方便的实现——并且这种实现与语言、平台、和位置无关。</p>
<p>　　<strong>三、面向对象编程</strong></p>
<p>　　许多程序员仍然认为OOP乃技术的象牙之塔，但是细细想一下过去十年里在面向对象领域里占据过统治地位的开发语言之后，你就不会这么认为了，
OOP理念从Smalltalk开始，然后蔓延到C++和Pascal(Delphi)，到Java成为真正的主流，几年之后，VB.NET 和
C#的出现可以说是OOP发展到了登峰造极的地步。虽然使用这些语言不必了解OOP的概念，但如果你缺乏一些OOP的基本知识和方法，我想你很难在逐渐疲
软的就业市场中找到工作。</p>
<p><strong>　四、Java， C++， C#， VB.NET</strong> </p>
<p>　　如果你热衷于技术，并且热爱编程，那么我想你应该轻松玩转这些高级语言，我说的玩转并不一定要你成为超级编程高手。而是能看懂用这些语言编写的
代码即可。如果你还有精力用它们编码那就更好了。其实这种机会甚少。但是看代码的机会很多，学习编程的最有效的一种方式就是看源代码——浩如烟海的源代码
中很多都不是用你所钟爱的开发语言编写的。</p>
<p>　　在过去的几年里，各个语言功能的发展基本上都差不多。现在你完全可以用VB.NET来写Windows服务、Web应用或者命令行程序。即使你
只用其中的一种语言写程序。我认为也完全有必要学习另外一种语言，使自己能阅读和理解它们现有的例子代码，并且能将一种语言编写的代码转换成你首选的编程
语言代码。这里列出的四种语言可谓是一个强大的开发语言工具箱，如果你掌握了它们，毫无疑问你一定是一个众人仰慕的高手。这里我要声明一下：那就是我并没
有要忽略和排除其它的高级语言，如：FORTRAN、COBOL、APL、ADA、Perl和Lisp等等，根据你所从事的领域不同，应该选择适合的语言
和工具。</p>
<p>　　<strong>五、JavaScript</strong></p>
<p>　　Java
和JavaScript两者的名字尽管很类似，但它们之间并没有什么关系。为什么一种脚本语言会如此重要，以至于将它列入十种关键技术之一呢?仔细想一下
就知道了，目前所有主流的浏览器都使用JavaScript.如果你要编写Web应用程序，那么JavaScript不可或缺。此外，
JavaScript还能作为一种<nobr><strong class="kgb" onclick='javascript:window.open("http://pagead2.googlesyndication.com/pagead/iclk?sa=l&ai=BAAJVHRZrR4CiIpDE6wORqaVXpeHNHpne-fQDwI23AcCaDBAEGAQgrYXQDSgUOABQuPTpKGCd2dCBlAWgAaugr_oDqgEKMjAwMDAzNjEyN7IBDW5ld3MuY3Nkbi5uZXTIAQHaAStodHRwOi8vbmV3cy5jc2RuLm5ldC9uLzIwMDcxMjIwLzExMTkyNy5odG1sgAIBqQLHG3MX3jaCPsgC7bnWAagDAegDtwL1AwAEAAA&num=4&adurl=http://www.shenmo.sh.cn/product/product-MAGMA.html&client=ca-pub-5186439242807756");GgKwClickStat("服务器端","www.shenmo.sh.cn","afc","2000036127");' onmouseout='isShowGg = false;InTextAds_GgLayer="_u670D_u52A1_u5668_u7AEF"' onmouseover='isShowAds = false;isShowAds2 = false;isShowGg = true;InTextAds_GgLayer="_u670D_u52A1_u5668_u7AEF";KeyGate_ads.ShowGgAds(this,"_u670D_u52A1_u5668_u7AEF",event)' style="border: 0px none ; margin: 0px; padding: 0px; color: #0000ff; font-weight: normal; text-decoration: underline;">服务器端</strong></nobr>的
脚本语言，如将它嵌入在ASP、ASP.NET中，或者嵌入XSLT来扩展功能。目前JavaScript在Mozilla/Netscape中是激活基
于XUL界面的首选语言，它派生出了ActionScript，成为Flash
MX应用的编程语言。还有就是JavaScript极有可能成为未来新设备的脚本语言以及主流应用的宏语言。</p>
<p>　　相比之下，VBScript虽然在微软的产品中得到很好的支持，但从长远来看，没有迹象表明它会有美好前途。微软自己都趋向于用
JavaScript(或者用由JavaScript派生的JScript)来编写其客户端脚本代码。因此，如果你要选择脚本语言，非
JavaScript莫属。</p>
<p>　<strong>　六、Regular Expressions</strong></p>
<p>　　从所周知，关系数据库的查询使用SQL，搜索XML文档用XPath
和XQuery，而正则表达式则用来搜索纯文本。例如，你可以用一个命令来查找或删除HTML格式文件中的注释内容。大家都用过"IndexOf"、
"InStr"以及"Like"这些内建在JavaScript或VB中的文本搜索函数，这些函数虽然很容易使用，但是它们的功能却无法与正则表达式同日
而语——现在每一种主流的开发语言都提供对正则表达式的存取。尽管有人认为正则表达式本身的读写艰涩难懂，但毕竟它的功能强大，使用它的领域也越来越多。</p>
<p>　　<strong>七、Design Patterns</strong></p>
<p>　　就像OOP通过创建和分类对象来简化编程一样，设计模式将普通的对象交互分类成指定的模型，这是一个从一般到具体的过程。OOP的成分使用得越多，设计模式就显得越有用武之地。所以你必须理解它们，跟上其总体理论的发展。</p>
<p>　<strong>　八、Flash MX</strong></p>
<p>　　当你需要比HTML和CSS所能提供的更多的客户端图形和编程能力时，Flash是最佳选择。在Flash中编程比用Java小应用或者。NET代码来得快得多，也容易得多。</p>
<p>　　在最新版本中(MX)，Flash不仅可以画图和进行动画打包，它还是个高度的可编程应用环境。具备强大的与SOAP
Web服务沟通的能力，可以调用运行在远端服务器上的ColdFusion、Java或。NET代码。可以说Flash几乎无处不在，包括手持设备、置顶
盒、甚至是新的平板电脑，你到处都可以见到它的身影，所以使用它实际上可以扩展和延伸你的应用程序使用领域。</p>
<p><strong>　九、Linux/Windows</strong> </p>
<p>　　这是当今PCs机<nobr><strong class="kgb" onclick='javascript:window.open("http://pagead2.googlesyndication.com/pagead/iclk?sa=l&ai=B9pIRHRZrR4CiIpDE6wORqaVXuarQMI3Ru_8DwI23AdDZERAJGAkgrYXQDSgUOABQrc7vFWCd2dCBlAWqAQoyMDAwMDM2MTI3sgENbmV3cy5jc2RuLm5ldMgBAdoBK2h0dHA6Ly9uZXdzLmNzZG4ubmV0L24vMjAwNzEyMjAvMTExOTI3Lmh0bWypAscbcxfeNoI-yALF6uMDqAMB6AO3AvUDAAQAAA&num=9&adurl=http://www.hunter2006.com/pcmonitor.htm&client=ca-pub-5186439242807756");GgKwClickStat("操作系统","www.hunter2006.com","afc","2000036127");' onmouseout='isShowGg = false;InTextAds_GgLayer="_u64CD_u4F5C_u7CFB_u7EDF"' onmouseover='isShowAds = false;isShowAds2 = false;isShowGg = true;InTextAds_GgLayer="_u64CD_u4F5C_u7CFB_u7EDF";KeyGate_ads.ShowGgAds(this,"_u64CD_u4F5C_u7CFB_u7EDF",event)' style="border: 0px none ; margin: 0px; padding: 0px; color: #0000ff; font-weight: normal; text-decoration: underline;">操作系统</strong></nobr>的
两大阵容，如果你想在计算机行业里混，就一定要熟悉它们。对于Linux，最好能自己安装，配置，下载它的图形用户界面以及一些应用程序。自己安装
Apache并会编写Web应用程序。要清醒地认识到这个世界除了Windows之外，还有Linux的存在。并且这种局面将会长期存在。反过来，如果你
是一个死忠的Linux开发者，不要再继续对Windows的憎恶，要相互学习，取长补短，看看Windows有什么好的东东可以采纳。记住
Windows仍然是桌面之王。</p>
<p>　　谁也说不准你们公司什么时候会决定从Linux转向Windows，或者从Windows转向Linux.谁也说不准什么时候你会跳槽跑到另外
一个使用不同平台的公司上班——或者即便不跳槽，也有可能在不同平台上开始另外一个杀手级项目——所以最好在每个平台上都积累一些经验，而不要在一棵树上
吊死。</p>
<p><strong>　　十、SQL</strong></p>
<p>　　尽管SQL在当今众多的技术中已不是什么新东西，而且在未来的十年里它的作用很有可能被削弱，甚至整个被淘汰，但它仍然是一种基本技能——别看
它是一种基本技能，至今仍有许多开发人员不懂什么是SQL或对它了解不多。不要指望基于图形用户界面的SQL构造器会帮你的忙，还是自己亲手写SQL查询
吧，确定你掌握了SQL的基本语法。现在理解了SQL，不仅对以后学习XQuery有所裨益，而且可以使你很快找到简化或改进当前开发项目的途径。</p>
<p>　　<strong>尾声：培养对技术的好奇心</strong></p>
<p>　　其实，不管技术的发展趋势如何，每个人最重要的一个技能是好奇心。敢于面对挑战，在你目前或未来的工作中，新语言或新技术可能很重要，也可能不
怎么重要，你所学习的东西并不一定非要针对你的工作。不要怕失败，任何新的技术对初学者来说都是困难的。大多数的失败都可以归咎于本身急功近利，希望速
成。俗话说——千里之行，始于足下，应该脚踏实地，一步一个脚印地往前走。不要让时间来左右你行动，而是要利用时间来关注、研究、测试新的开发技术和工
具。<br />
</p>
<p><br />
</p>
<p>注：以上内容来自网络，本人不承担任何连带责任</p>
<p>转自：赛迪网</p>
<img src ="http://www.blogjava.net/relax/aggbug/169224.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2007-12-21 09:36 <a href="http://www.blogjava.net/relax/archive/2007/12/21/169224.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java开发者的十大戒律 </title><link>http://www.blogjava.net/relax/archive/2007/12/21/169217.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Fri, 21 Dec 2007 01:23:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2007/12/21/169217.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/169217.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2007/12/21/169217.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/169217.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/169217.html</trackback:ping><description><![CDATA[<div><dl><dt>
<p>有许多标准和实践准则可适用于Java开发者，但此处要说的，是每个Java开发者需坚守的基本原则。</p>
</dt></dl></div>
<p>　　<strong>一、为<strong style="border: 0px none ; margin: 0px; padding: 0px; font-weight: normal; color: #0000ff; text-decoration: underline;">代码</strong>加注释</strong>。虽然每个人都知道这点，但有时却不自觉忘了履行，今天你&#8220;忘了&#8221;加注释了吗?虽然注释对 程序的功能没什么&#8220;贡献&#8221;，但过一段<strong style="border: 0px none ; margin: 0px; padding: 0px; font-weight: normal; color: #0000ff; text-decoration: underline;">时间</strong>，
比如说两星期之后或者更长，回过头来看看自己的代码，说不定已经记不住它是干什么的了。如果这些代码是你个人的，那还算是走运了，不幸的是，当然了，大多
数时候都是别人的不幸，很多时候大家都是在为公司写代码，写代码的人也许早已经离开了公司，但别忘了一句古话，有来有往嘛，为他人，也为我们自己，请为你
的代码加上注释。 </p>
<p>　　<strong>二、不要让事情复杂化</strong>。<strong style="border: 0px none ; margin: 0px; padding: 0px; font-weight: normal; color: #0000ff; text-decoration: underline;">程序员</strong>有时候总是对<strong style="border: 0px none ; font-weight: normal; color: #0000ff; text-decoration: underline;">简单</strong>问题想出复杂的<strong style="border: 0px none ; font-weight: normal; color: #0000ff; text-decoration: underline;">解决方案</strong>，
比如说，在只有五个用户的程序中引入EJB、对程序实现了并不需要的框架(framework)，之类的还有属性文件、面向对象解决方案、多线程等等。为
什么要这样做呢?也许我们并不知道是否这样会更好，但这样做也许可以学到一些新东西，或者让自己更感兴趣一些。如果是不知道为什么这样做，建议多请教经验
丰富的程序员，如果是为了个人的目的，麻烦让自己更专业一点。 </p>
<p>　　<strong>三、始终牢记</strong>——&#8220;少即是好(Less is more)并不总是对的&#8221;。代码效率虽然很重要，但在许多解决方案中，编写更少的代码并不能改善这些代码的效率，请看下面这个简单的例子： </p>
<p> </p>
<table style="border: 1px dotted #cccccc; table-layout: fixed;" align="center" border="0" cellpadding="6" cellspacing="0" width="95%">
    <tbody>
        <tr>
            <td bgcolor="#f3f3f3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(newStatusCode.equals("SD")&nbsp;&amp;&amp;&nbsp;(sellOffDate&nbsp;==&nbsp;null&nbsp;|| <br />
            todayDate.compareTo(sellOffDate)&lt;0&nbsp;||&nbsp;(lastUsedDate&nbsp;!=&nbsp;null&nbsp;&amp;&amp; <br />
            todayDate.compareTo(lastUsedDate)&gt;0))&nbsp;|| <br />
            (newStatusCode.equals("OBS")&nbsp;&amp;&amp;&nbsp;(OBSDate&nbsp;==&nbsp;null&nbsp;|| <br />
            todayDate.compareTo(OBSDate)&lt;0))){ <br />
            newStatusCode&nbsp;=&nbsp;"NYP"; <br />
            }</td>
        </tr>
    </tbody>
</table>
<p>　　能看明白if条件语句是干什么的吗?能想出来是谁写的这段代码吗?如果把它分成两段独立的if语句，是不是更容易理解呢，下面是修改后的代码： </p>
<p> </p>
<table style="border: 1px dotted #cccccc; table-layout: auto;" align="center" border="0" cellpadding="6" cellspacing="0" width="95%">
    <tbody>
        <tr>
            <td bgcolor="#f3f3f3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(newStatusCode.equals("SD")&nbsp;&amp;&amp;&nbsp;(sellOffDate&nbsp;==&nbsp;null&nbsp;|| <br />
            todayDate.compareTo(sellOffDate)&lt;0&nbsp;||&nbsp;(lastUsedDate&nbsp;!=&nbsp;null&nbsp;&amp;&amp; <br />
            todayDate.compareTo(lastUsedDate)&gt;0))){ <br />
            newStatusCode&nbsp;=&nbsp;"NYP"; <br />
            }else <br />
            if(newStatusCode.equals("OBS")&nbsp;&amp;&amp;&nbsp;(OBSDate&nbsp;==&nbsp;null&nbsp;|| <br />
            todayDate.compareTo(OBSDate)&lt;0)) <br />
            { <br />
            newStatusCode&nbsp;=&nbsp;"NYP"; <br />
            }</td>
        </tr>
    </tbody>
</table>
<p>　　是不是读起来容易多了呢，在此只是多加了一个if和两个花括号，但代码的可读性与可理解性就一下子提高了一大截。 </p>
<p>　　<strong>四、请不要硬编码</strong>。开发者经常有意&#8220;忘记&#8221;或忽略掉这点，因为有些时候开发日程逼得实在太紧。其实，多写一行定义静态变量的代码能花多少时间呢? </p>
<p> </p>
<table style="border: 1px dotted #cccccc; table-layout: auto;" align="center" border="0" cellpadding="6" cellspacing="0" width="95%">
    <tbody>
        <tr>
            <td bgcolor="#f3f3f3"><strong><font color="#990000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></strong>public&nbsp;class&nbsp;A&nbsp;{ <br />
            public&nbsp;static&nbsp;final&nbsp;String&nbsp;S_CONSTANT_ABC&nbsp;=&nbsp;"ABC"; <br />
            public&nbsp;boolean&nbsp;methodA(String&nbsp;sParam1){ <br />
            if&nbsp;(A.S_CONSTANT_ABC.equalsIgnoreCase(sParam1)){ <br />
            return&nbsp;true; <br />
            } <br />
            return&nbsp;false; <br />
            } <br />
            }</td>
        </tr>
    </tbody>
</table>
<p>　　现在，每次需要将&#8220;ABC&#8221;与其他变量进行比较时，不必记住实际代码，直接引用A.S_CONSTANT_ABC就行了，而且在今后需要进行修改时，也可在一处修改，不会翻遍整个源代码逐个修改了。 </p>
<p>　　<strong>五、不要&#8220;创造&#8221;自己的框架(framework)。</strong>确切来说，有数以千计的各种框架存在，而且大多数是开 源的，这些框架都是优秀的解决方案，可用于日常<strong style="border: 0px none ; margin: 0px; padding: 0px; font-weight: normal; color: #0000ff; text-decoration: underline;">程序开发</strong>中，
我们只需使用这些框架的最新版本就行了，至少表面上要跟上形势吧。被大家广为接受的最为明显的一个例子就是Struts了，这个开源web框架非常适合用
在基于web的应用程序中。是不是想开发出自己的Struts呢，还是省点力气吧，回头看看第二条——不要让事情复杂化。另外，如果正在开发的程序只有3
个窗口，就不要使用Struts了，对这种程序来说，不需要那么多的&#8220;控制&#8221;。 </p>
<p>　　<strong>六、不要使用println及字符串连接</strong>。通常为了调试方便，开发者喜欢在可能的所有地方都加上 System.out.println，也许还会提醒自己回过头来再来删除，但有些时候，经常会忘了删除或者不愿意删除它们。既然使用 System.out.println是为了<strong style="border: 0px none ; margin: 0px; padding: 0px; font-weight: normal; color: #0000ff; text-decoration: underline;">测试</strong>，那么测试完之后，为什么还要留着它们呢，因为在删除时，很可能会删除掉真正有用的代码，所以不能低估 System.out.println危害啊，请看下面的代码： </p>
<p> </p>
<table style="border: 1px dotted #cccccc; table-layout: fixed;" align="center" border="0" cellpadding="6" cellspacing="0" width="95%">
    <tbody>
        <tr>
            <td bgcolor="#f3f3f3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;class&nbsp;BadCode&nbsp;{ <br />
            public&nbsp;static&nbsp;void&nbsp;calculationWithPrint(){ <br />
            double&nbsp;someValue&nbsp;=&nbsp;0D; <br />
            for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;10000;&nbsp;i++)&nbsp;{ <br />
            System.out.println(someValue&nbsp;=&nbsp;someValue&nbsp;+&nbsp;i); <br />
            } <br />
            } <br />
            public&nbsp;static&nbsp;void&nbsp;calculationWithOutPrint(){ <br />
            double&nbsp;someValue&nbsp;=&nbsp;0D; <br />
            for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;10000;&nbsp;i++)&nbsp;{ <br />
            someValue&nbsp;=&nbsp;someValue&nbsp;+&nbsp;i; <br />
            } <br />
            } <br />
            public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;[]&nbsp;n)&nbsp;{ <br />
            BadCode.calculationWithPrint(); <br />
            BadCode.calculationWithOutPrint(); <br />
            } <br />
            }</td>
        </tr>
    </tbody>
</table>
<p>　　从测试中可以发现，方法calculationWithOutPrint()执行用了0.001204秒，作为对比，方法calculationWithPrint()执行可是用了10.52秒。 </p>
<p>　　要避免浪费CPU时间，最好的方法是引入像如下的包装方法： </p>
<p> </p>
<table style="border: 1px dotted #cccccc; table-layout: auto;" align="center" border="0" cellpadding="6" cellspacing="0" width="95%">
    <tbody>
        <tr>
            <td bgcolor="#f3f3f3">
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;class&nbsp;BadCode&nbsp;{ <br />
            public&nbsp;static&nbsp;final&nbsp;int&nbsp;DEBUG_MODE&nbsp;=&nbsp;1; <br />
            public&nbsp;static&nbsp;final&nbsp;int&nbsp;PRODUCTION_MODE&nbsp;=&nbsp;2; <br />
            public&nbsp;static&nbsp;void&nbsp;calculationWithPrint(int&nbsp;logMode){ <br />
            double&nbsp;someValue&nbsp;=&nbsp;0D; <br />
            for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;10000;&nbsp;i++)&nbsp;{ <br />
            someValue&nbsp;=&nbsp;someValue&nbsp;+&nbsp;i; <br />
            myPrintMethod(logMode,&nbsp;someValue); <br />
            } <br />
            } <br />
            public&nbsp;static&nbsp;void&nbsp;myPrintMethod(int&nbsp;logMode,&nbsp;double&nbsp;value)&nbsp;{ <br />
            if&nbsp;(logMode&nbsp;&gt;&nbsp;BadCode.DEBUG_MODE)&nbsp;{&nbsp;return;&nbsp;} <br />
            System.out.println(value); <br />
            } <br />
            public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;[]&nbsp;n)&nbsp;{ <br />
            BadCode.calculationWithPrint(BadCode.PRODUCTION_MODE); <br />
            } <br />
            }</p>
            </td>
        </tr>
    </tbody>
</table>
<p>　　另外，字符串连接也是浪费CPU时间的一个大头，请看下面的示例代码： </p>
<p> </p>
<table style="border: 1px dotted #cccccc; table-layout: auto;" align="center" border="0" cellpadding="6" cellspacing="0" width="95%">
    <tbody>
        <tr>
            <td bgcolor="#f3f3f3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;static&nbsp;void&nbsp;concatenateStrings(String&nbsp;startingString)&nbsp;{ <br />
            for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;20;&nbsp;i++)&nbsp;{ <br />
            startingString&nbsp;=&nbsp;startingString&nbsp;+&nbsp;startingString; <br />
            } <br />
            } <br />
            public&nbsp;static&nbsp;void&nbsp;concatenateStringsUsingStringBuffer(String&nbsp;startingString)&nbsp;{ <br />
            StringBuffer&nbsp;sb&nbsp;=&nbsp;new&nbsp;StringBuffer(); <br />
            sb.append(startingString); <br />
            for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;20;&nbsp;i++)&nbsp;{ <br />
            sb.append(sb.toString()); <br />
            } <br />
            }</td>
        </tr>
    </tbody>
</table>
<p>　　在测试中可发现，使用StringBuffer的方法只用了0.01秒执行完毕，而使用连接的方法则用了0.08秒，选择显而易见了。 </p>
<p>　　<strong>七、多关注GUI(用户界面)。</strong>再三强调，GUI对商业客户来说，与程序的功能及效率同等重要，GUI是一 个成功程序的最基本部分，而很多IT经理往往都没注意到GUI的重要性。在现实生活中，许多公司可能为了节省开支，没有雇用那些有着<strong style="border: 0px none ; margin: 0px; padding: 0px; font-weight: normal; color: #0000ff; text-decoration: underline;">设计</strong>&#8220;用户友好&#8221;界面 丰富经验的网页设计者，此时Java开发者只能依赖他们自身的HTML基本功及在此领域有限的知识，结果，很多开发出来的程序都是&#8220;<strong style="border: 0px none ; font-weight: normal; color: #0000ff; text-decoration: underline;">计算机</strong>友好&#8221;甚于&#8220;用 户友好&#8221;。很少有开发者同时精通<strong style="border: 0px none ; font-weight: normal; color: #0000ff; text-decoration: underline;">软件开发</strong>及GUI设计，如果你在公司&#8220;不幸&#8221;被分配负责程序界面，就应该遵守下面三条原则： </p>
<p>　　1、 不要再发明一次轮子，即不做无用功。现有的程序可能会有类似的界面需求。 </p>
<p>　　2、 先创建一个原型。这是非常重要一步，用户一般想看到他们将使用的东西，而且可以先利用这个原型征求用户的意见，再慢慢修改成用户想要的样子。 </p>
<p>　　3、 学会换位思考。换句话来说，就是从用户的角度来审查程序的需求。举例来讲，一个汇总的窗口可以跨页或者不跨页，作为一个软件开发者，可能会倾向于不跨页，因为这样简单一些。但是，从用户的角度来看，可能不希望看到上百行数据都挤在同一页上。 </p>
<p>　　<strong>八、文档需求不放松</strong>。每个商业需求都必须记录在案，这可能听上去像童话，似乎在现实生活中很难实现。而我们要做的是，不管开发时间多紧迫，不管最终期限多临近，对每个商业需求都必须记录在案。 </p>
<p>　　<strong>九、单元测试、单元测试、单元测试</strong>。关于什么是单元测试的最好方法，在此不便细说，只是强调，单元测试一定要完成，这也是<strong style="border: 0px none ; margin: 0px; padding: 0px; font-weight: normal; color: #0000ff; text-decoration: underline;">编程</strong>中最基本的原则。当然了，如果有人帮你做单元测试自然是最好，如果没有，就自己来做吧，当创建一个单元测试计划时，请遵守以下三条最基本的原则： </p>
<p>　　1、 先于编写类代码之前编写单元测试。 </p>
<p>　　2、 记录单元测试中的代码注释。 </p>
<p>　　3、 测试所有执行关键功能的公有方法，这里不是指set和get方法，除非它们是以自己独特方式执行set和get方法。 </p>
<p>　　<strong>十、质量，而不是数量</strong>。有些时候因为产品问题、期限紧迫、或一些预料之外的事情，导致常常不能按时下班，但一般而言，公司不会因为雇员经常加班而对之表扬和奖励，公司只看重高质量的工作。如果遵守了前九条原则，你会发现自己写出的代码bug少且可维护性高，无形中质量提高了一大步。</p>
<p>注：以上内容来自网络，本人不承担任何连带责任</p>
<p>文章转自：<br />
</p>
<br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1956723</p>
<img src ="http://www.blogjava.net/relax/aggbug/169217.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2007-12-21 09:23 <a href="http://www.blogjava.net/relax/archive/2007/12/21/169217.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单元测试利器 JUnit 4</title><link>http://www.blogjava.net/relax/archive/2007/03/05/101945.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Mon, 05 Mar 2007 08:15:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2007/03/05/101945.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/101945.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2007/03/05/101945.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/101945.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/101945.html</trackback:ping><description><![CDATA[
		<p>本文主要介绍了如何使用 JUnit 4 提供的各种功能开展有效的单元测试，并通过一个实例演示了如何使用 Ant 执行自动化的单元测试。本文假设读者对 Eclipse 下进行 Java 开发有一定的经验，并了解 Java 5 中的注解（annotation）特性。</p>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>
				<a name="N10053">
						<span class="atitle">引言</span>
				</a>
		</p>
		<p>毋庸置疑，程序员要对自己编写的代码负责，您不仅要保证它能通过编译，正常地运行，而且要满足需求和设计预期的效果。单元测试正是验证代码行为是否满足预期的有效手段之一。但不可否认，做测试是件很枯燥无趣的事情，而一遍又一遍的测试则更是让人生畏的工作。幸运的是，单元测试工具 JUnit 使这一切变得简单艺术起来。</p>
		<p>JUnit 是 Java 社区中知名度最高的单元测试工具。它诞生于 1997 年，由 Erich Gamma 和 Kent Beck 共同开发完成。其中 Erich Gamma 是经典著作《设计模式：可复用面向对象软件的基础》一书的作者之一，并在 Eclipse 中有很大的贡献；Kent Beck 则是一位极限编程（XP）方面的专家和先驱。</p>
		<p>麻雀虽小，五脏俱全。JUnit 设计的非常小巧，但是功能却非常强大。Martin Fowler 如此评价 JUnit：在软件开发领域，从来就没有如此少的代码起到了如此重要的作用。它大大简化了开发人员执行单元测试的难度，特别是 JUnit 4 使用 Java 5 中的注解（annotation）使测试变得更加简单。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="major2">
						<span class="atitle">JUnit 4 初体验</span>
				</a>
		</p>
		<p>在开始体验 JUnit 4 之前，我们需要以下软件的支持：</p>
		<ul>
				<li>Eclipse：最为流行的 IDE，它全面集成了 JUnit，并从版本 3.2 开始支持 JUnit 4。当然 JUnit 并不依赖于任何 IDE。您可以从 <a href="http://www.eclipse.org/"><font color="#996699">http://www.eclipse.org/</font></a> 上下载最新的 Eclipse 版本。 
</li>
				<li>Ant：基于 Java 的开源构建工具，您可以在 <a href="http://ant.apache.org/"><font color="#5c81a7">http://ant.apache.org/</font></a> 上得到最新的版本和丰富的文档。Eclipse 中已经集成了 Ant，但是在撰写本文时，Eclipse 使用的 Ant 版本较低（必需 1.7 或者以上版本），不能很好的支持 JUnit 4。 
</li>
				<li>JUnit：它的官方网站是 <a href="http://www.junit.org/"><font color="#5c81a7">http://www.junit.org/</font></a>。您可以从上面获取关于 JUnit 的最新消息。如果您和本文一样在 Eclipse 中使用 JUnit，就不必再下载了。 </li>
		</ul>
		<p>首先为我们的体验新建一个 Java 工程 —— coolJUnit。现在需要做的是，打开项目 coolJUnit 的属性页 -&gt; 选择“Java Build Path”子选项 -&gt; 点选“Add Library…”按钮 -&gt; 在弹出的“Add Library”对话框中选择 JUnit（<a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#figure001"><font color="#5c81a7">图1</font></a>），并在下一页中选择版本 4.1 后点击“Finish”按钮。这样便把 JUnit 引入到当前项目库中了。</p>
		<br />
		<a name="figure001">
				<b>图1 为项目添加 JUnit 库</b>
		</a>
		<br />
		<img alt="图1 为项目添加 JUnit 库" src="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/figure001.jpg" />
		<br />
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N1009A">
																				<b>请注意 JDK 的版本</b>
																		</a>
																		<br />
																		<p>JUnit 4.1 是基于 Java 5 的升级版本，它使用了 Tiger 中的很多新特性来简化原有的使用方式。正因为如此，它并不能直接运行在 JDK1.4.x 版本上。如果您需要在 JDK1.4.x 版本使用 JUnit 的话，请使用 3.8.1 版本。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>可以开始编写单元测试了吗？等等……，您打算把单元测试代码放在什么地方呢？把它和被测试代码混在一起，这显然会照成混乱，因为单元测试代码是不会出现在最终产品中的。建议您分别为单元测试代码与被测试代码创建单独的目录，并保证测试代码和被测试代码使用相同的包名。这样既保证了代码的分离，同时还保证了查找的方便。遵照这条原则，我们在项目 coolJUnit 根目录下添加一个新目录 testsrc，并把它加入到项目源代码目录中（加入方式见 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#figure002"><font color="#5c81a7">图2</font></a>）。</p>
		<br />
		<a name="figure002">
				<b>图2 修改项目源代码目录</b>
		</a>
		<br />
		<img alt="图2 修改项目源代码目录" src="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/figure002.jpg" />
		<br />
		<p>现在我们得到了一条 JUnit 的最佳实践：单元测试代码和被测试代码使用一样的包，不同的目录。</p>
		<p>一切准备就绪，一起开始体验如何使用 JUnit 进行单元测试吧。下面的例子来自笔者的开发实践：工具类 WordDealUtil 中的静态方法 wordFormat4DB 是专用于处理 Java 对象名称向数据库表名转换的方法（您可以在代码注释中可以得到更多详细的内容）。下面是第一次编码完成后大致情形：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">package com.ai92.cooljunit;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 对名称、地址等字符串格式的内容进行格式检查
 * 或者格式化的工具类
 * 
 * @author Ai92
 */
public class WordDealUtil {

	/**
	 * 将Java对象名称（每个单词的头字母大写）按照
	 * 数据库命名的习惯进行格式化
	 * 格式化后的数据为小写字母，并且使用下划线分割命名单词
	 * 
	 * 例如：employeeInfo 经过格式化之后变为 employee_info
	 * 
	 * @param name	Java对象名称
	 */
	public static String wordFormat4DB(String name){
		Pattern p = Pattern.compile("[A-Z]");
		Matcher m = p.matcher(name);
		StringBuffer sb = new StringBuffer();
		
		while(m.find()){
			m.appendReplacement(sb, "_"+m.group());
		}
		return m.appendTail(sb).toString().toLowerCase();
	}
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>它是否能按照预期的效果执行呢？尝试为它编写 JUnit 单元测试代码如下：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">package com.ai92.cooljunit;

import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class TestWordDealUtil {
	//测试wordFormat4DB正常运行的情况
	@Test public void wordFormat4DBNormal(){
		String target = "employeeInfo";
		String result = WordDealUtil.wordFormat4DB(target);
		
		assertEquals("employee_info", result);
	}
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>很普通的一个类嘛！测试类 TestWordDealUtil 之所以使用“Test”开头，完全是为了更好的区分测试类与被测试类。测试方法 wordFormat4DBNormal 调用执行被测试方法 WordDealUtil.wordFormat4DB，以判断运行结果是否达到设计预期的效果。需要注意的是，测试方法 wordFormat4DBNormal 需要按照一定的规范书写：</p>
		<ol>
				<li>测试方法必须使用注解 org.junit.Test 修饰。 
</li>
				<li>测试方法必须使用 public void 修饰，而且不能带有任何参数。 </li>
		</ol>
		<p>测试方法中要处理的字符串为“employeeInfo”，按照设计目的，处理后的结果应该为“employee_info”。assertEquals 是由 JUnit 提供的一系列判断测试结果是否正确的静态断言方法（位于类 org.junit.Assert 中）之一，我们使用它将执行结果 result 和预期值“employee_info”进行比较，来判断测试是否成功。</p>
		<p>看看运行结果如何。在测试类上点击右键，在弹出菜单中选择 Run As JUnit Test。运行结果如<a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#figure003"><font color="#5c81a7">下图</font></a>所示：</p>
		<br />
		<a name="figure003">
				<b>图3 JUnit 运行成功界面</b>
		</a>
		<br />
		<img alt="图3 JUnit 运行成功界面" src="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/figure003.jpg" />
		<br />
		<p>绿色的进度条提示我们，测试运行通过了。但现在就宣布代码通过了单元测试还为时过早。记住：您的单元测试代码不是用来证明您是对的，而是为了证明您没有错。因此单元测试的范围要全面，比如对边界值、正常值、错误值得测试；对代码可能出现的问题要全面预测，而这也正是需求分析、详细设计环节中要考虑的。显然，我们的测试才刚刚开始，继续补充一些对特殊情况的测试：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public class TestWordDealUtil {
	……
	//测试 null 时的处理情况
	@Test public void wordFormat4DBNull(){
		String target = null;
		String result = WordDealUtil.wordFormat4DB(target);
		
		assertNull(result);
	}
	
	//测试空字符串的处理情况
	@Test public void wordFormat4DBEmpty(){
		String target = "";
		String result = WordDealUtil.wordFormat4DB(target);
		
		assertEquals("", result);
	}

	//测试当首字母大写时的情况
	@Test public void wordFormat4DBegin(){
		String target = "EmployeeInfo";
		String result = WordDealUtil.wordFormat4DB(target);
		
		assertEquals("employee_info", result);
	}
	
	//测试当尾字母为大写时的情况
	@Test public void wordFormat4DBEnd(){
		String target = "employeeInfoA";
		String result = WordDealUtil.wordFormat4DB(target);
		
		assertEquals("employee_info_a", result);
	}
	
	//测试多个相连字母大写时的情况
	@Test public void wordFormat4DBTogether(){
		String target = "employeeAInfo";
		String result = WordDealUtil.wordFormat4DB(target);
		
		assertEquals("employee_a_info", result);
	}
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>再次运行测试。很遗憾，JUnit 运行界面提示我们有两个测试情况未通过测试（<a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#figure004"><font color="#5c81a7">图4</font></a>）——当首字母大写时得到的处理结果与预期的有偏差，造成测试失败（failure）；而当测试对 null 的处理结果时，则直接抛出了异常——测试错误（error）。显然，被测试代码中并没有对首字母大写和 null 这两种特殊情况进行处理，修改如下：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">//修改后的方法wordFormat4DB
/**
	 * 将Java对象名称（每个单词的头字母大写）按照
	 * 数据库命名的习惯进行格式化
	 * 格式化后的数据为小写字母，并且使用下划线分割命名单词
	 * 如果参数name为null，则返回null
	 * 
	 * 例如：employeeInfo 经过格式化之后变为 employee_info
	 * 
	 * @param name Java对象名称
	 */
	public static String wordFormat4DB(String name){
		
		if(name == null){
			return null;
		}
		
		Pattern p = Pattern.compile("[A-Z]");
		Matcher m = p.matcher(name);
		StringBuffer sb = new StringBuffer();
		
		while(m.find()){
			if(m.start() != 0)
				m.appendReplacement(sb, ("_"+m.group()).toLowerCase());
		}
		return m.appendTail(sb).toString().toLowerCase();
	}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<a name="figure004">
				<b>图4 JUnit 运行失败界面</b>
		</a>
		<br />
		<img alt="图4 JUnit 运行失败界面" src="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/figure004.jpg" />
		<br />
		<p>JUnit 将测试失败的情况分为两种：failure 和 error。Failure 一般由单元测试使用的断言方法判断失败引起，它表示在测试点发现了问题；而 error 则是由代码异常引起，这是测试目的之外的发现，它可能产生于测试代码本身的错误（测试代码也是代码，同样无法保证完全没有缺陷），也可能是被测试代码中的一个隐藏的bug。</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N1010C">
																				<b>请牢记！</b>
																		</a>
																		<br />
																		<p>请牢记这一条 JUnit 最佳实践：测试任何可能的错误。单元测试不是用来证明您是对的，而是为了证明您没有错。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>啊哈，再次运行测试，绿条又重现眼前。通过对 WordDealUtil.wordFormat4DB 比较全面的单元测试，现在的代码已经比较稳定，可以作为 API 的一部分提供给其它模块使用了。</p>
		<p>不知不觉中我们已经使用 JUnit 漂亮的完成了一次单元测试。可以体会到 JUnit 是多么轻量级，多么简单，根本不需要花心思去研究，这就可以把更多的注意力放在更有意义的事情上——编写完整全面的单元测试。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N1011B">
						<span class="atitle">JUnit 深入</span>
				</a>
		</p>
		<p>当然，JUnit 提供的功能决不仅仅如此简单，在接下来的内容中，我们会看到 JUnit 中很多有用的特性，掌握它们对您灵活的编写单元测试代码非常有帮助。</p>
		<p>
				<a name="N10125">
						<span class="smalltitle">
								<strong>
										<font face="Arial">Fixture</font>
								</strong>
						</span>
				</a>
		</p>
		<p>何谓 Fixture？它是指在执行一个或者多个测试方法时需要的一系列公共资源或者数据，例如测试环境，测试数据等等。在编写单元测试的过程中，您会发现在大部分的测试方法在进行真正的测试之前都需要做大量的铺垫——为设计准备 Fixture 而忙碌。这些铺垫过程占据的代码往往比真正测试的代码多得多，而且这个比率随着测试的复杂程度的增加而递增。当多个测试方法都需要做同样的铺垫时，重复代码的“坏味道”便在测试代码中弥漫开来。这股“坏味道”会弄脏您的代码，还会因为疏忽造成错误，应该使用一些手段来根除它。</p>
		<p>JUnit 专门提供了设置公共 Fixture 的方法，同一测试类中的所有测试方法都可以共用它来初始化 Fixture 和注销 Fixture。和编写 JUnit 测试方法一样，公共 Fixture 的设置也很简单，您只需要：</p>
		<ol>
				<li>使用注解 org,junit.Before 修饰用于初始化 Fixture 的方法。 
</li>
				<li>使用注解 org.junit.After 修饰用于注销 Fixture 的方法。 
</li>
				<li>保证这两种方法都使用 public void 修饰，而且不能带有任何参数。 </li>
		</ol>
		<p>遵循上面的三条原则，编写出的代码大体是这个样子：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">//初始化Fixture方法
@Before public void init(){……}

//注销Fixture方法
@After public void destroy(){……}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这样，在每一个测试方法执行之前，JUnit 会保证 init 方法已经提前初始化测试环境，而当此测试方法执行完毕之后，JUnit 又会调用 destroy 方法注销测试环境。注意是每一个测试方法的执行都会触发对公共 Fixture 的设置，也就是说使用注解 Before 或者 After 修饰的公共 Fixture 设置方法是方法级别的（<a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#figure005"><font color="#5c81a7">图5</font></a>）。这样便可以保证各个独立的测试之间互不干扰，以免其它测试代码修改测试环境或者测试数据影响到其它测试代码的准确性。</p>
		<br />
		<a name="figure005">
				<b>图5 方法级别 Fixture 执行示意图</b>
		</a>
		<br />
		<img alt="图5 方法级别 Fixture 执行示意图" src="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/figure005.gif" />
		<br />
		<p>可是，这种 Fixture 设置方式还是引来了批评，因为它效率低下，特别是在设置 Fixture 非常耗时的情况下（例如设置数据库链接）。而且对于不会发生变化的测试环境或者测试数据来说，是不会影响到测试方法的执行结果的，也就没有必要针对每一个测试方法重新设置一次 Fixture。因此在 JUnit 4 中引入了类级别的 Fixture 设置方法，编写规范如下：</p>
		<ol>
				<li>使用注解 org,junit.BeforeClass 修饰用于初始化 Fixture 的方法。 
</li>
				<li>使用注解 org.junit.AfterClass 修饰用于注销 Fixture 的方法。 
</li>
				<li>保证这两种方法都使用 public static void 修饰，而且不能带有任何参数。 </li>
		</ol>
		<p>类级别的 Fixture 仅会在测试类中所有测试方法执行之前执行初始化，并在全部测试方法测试完毕之后执行注销方法（<a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#figure006"><font color="#5c81a7">图6</font></a>）。代码范本如下：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">//类级别Fixture初始化方法
@BeforeClass public static void dbInit(){……}
	
//类级别Fixture注销方法
	@AfterClass public static void dbClose(){……}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<a name="figure006">
				<b>图6 类级别 Fixture 执行示意图</b>
		</a>
		<br />
		<img alt="图6 类级别 Fixture 执行示意图" src="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/figure006.gif" />
		<br />
		<p>
				<a name="N1017E">
						<span class="smalltitle">
								<strong>
										<font face="Arial">异常以及时间测试</font>
								</strong>
						</span>
				</a>
		</p>
		<p>注解 org.junit.Test 中有两个非常有用的参数：expected 和 timeout。参数 expected 代表测试方法期望抛出指定的异常，如果运行测试并没有抛出这个异常，则 JUnit 会认为这个测试没有通过。这为验证被测试方法在错误的情况下是否会抛出预定的异常提供了便利。举例来说，方法 supportDBChecker 用于检查用户使用的数据库版本是否在系统的支持的范围之内，如果用户使用了不被支持的数据库版本，则会抛出运行时异常 UnsupportedDBVersionException。测试方法 supportDBChecker 在数据库版本不支持时是否会抛出指定异常的单元测试方法大体如下：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@Test(expected=UnsupportedDBVersionException.class)
	public void unsupportedDBCheck(){
		……
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>注解 org.junit.Test 的另一个参数 timeout，指定被测试方法被允许运行的最长时间应该是多少，如果测试方法运行时间超过了指定的毫秒数，则JUnit认为测试失败。这个参数对于性能测试有一定的帮助。例如，如果解析一份自定义的 XML 文档花费了多于 1 秒的时间，就需要重新考虑 XML 结构的设计，那单元测试方法可以这样来写：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@Test(timeout=1000)
	public void selfXMLReader(){
		……
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="N10193">
						<span class="smalltitle">
								<strong>
										<font face="Arial">忽略测试方法</font>
								</strong>
						</span>
				</a>
		</p>
		<p>JUnit 提供注解 org.junit.Ignore 用于暂时忽略某个测试方法，因为有时候由于测试环境受限，并不能保证每一个测试方法都能正确运行。例如下面的代码便表示由于没有了数据库链接，提示 JUnit 忽略测试方法 unsupportedDBCheck：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@ Ignore(“db is down”)
@Test(expected=UnsupportedDBVersionException.class)
	public void unsupportedDBCheck(){
		……
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>但是一定要小心。注解 org.junit.Ignore 只能用于暂时的忽略测试，如果需要永远忽略这些测试，一定要确认被测试代码不再需要这些测试方法，以免忽略必要的测试点。</p>
		<p>
				<a name="N101A4">
						<span class="smalltitle">
								<strong>
										<font face="Arial">测试运行器</font>
								</strong>
						</span>
				</a>
		</p>
		<p>又一个新概念出现了——测试运行器，JUnit 中所有的测试方法都是由它负责执行的。JUnit 为单元测试提供了默认的测试运行器，但 JUnit 并没有限制您必须使用默认的运行器。相反，您不仅可以定制自己的运行器（所有的运行器都继承自 org.junit.runner.Runner），而且还可以为每一个测试类指定使用某个具体的运行器。指定方法也很简单，使用注解 org.junit.runner.RunWith 在测试类上显式的声明要使用的运行器即可：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@RunWith(CustomTestRunner.class)
public class TestWordDealUtil {
……
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>显而易见，如果测试类没有显式的声明使用哪一个测试运行器，JUnit 会启动默认的测试运行器执行测试类（比如上面提及的单元测试代码）。一般情况下，默认测试运行器可以应对绝大多数的单元测试要求；当使用 JUnit 提供的一些高级特性（例如即将介绍的两个特性）或者针对特殊需求定制 JUnit 测试方式时，显式的声明测试运行器就必不可少了。</p>
		<p>
				<a name="N101B5">
						<span class="smalltitle">
								<strong>
										<font face="Arial">测试套件</font>
								</strong>
						</span>
				</a>
		</p>
		<p>在实际项目中，随着项目进度的开展，单元测试类会越来越多，可是直到现在我们还只会一个一个的单独运行测试类，这在实际项目实践中肯定是不可行的。为了解决这个问题，JUnit 提供了一种批量运行测试类的方法，叫做测试套件。这样，每次需要验证系统功能正确性时，只执行一个或几个测试套件便可以了。测试套件的写法非常简单，您只需要遵循以下规则：</p>
		<ol>
				<li>创建一个空类作为测试套件的入口。 
</li>
				<li>使用注解 org.junit.runner.RunWith 和 org.junit.runners.Suite.SuiteClasses 修饰这个空类。 
</li>
				<li>将 org.junit.runners.Suite 作为参数传入注解 RunWith，以提示 JUnit 为此类使用套件运行器执行。 
</li>
				<li>将需要放入此测试套件的测试类组成数组作为注解 SuiteClasses 的参数。 
</li>
				<li>保证这个空类使用 public 修饰，而且存在公开的不带有任何参数的构造函数。 </li>
		</ol>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">package com.ai92.cooljunit;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
……

/**
 * 批量测试 工具包 中测试类
 * @author Ai92
 */
@RunWith(Suite.class)
@Suite.SuiteClasses({TestWordDealUtil.class})
public class RunAllUtilTestsSuite {
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>上例代码中，我们将前文提到的测试类 TestWordDealUtil 放入了测试套件 RunAllUtilTestsSuite 中，在 Eclipse 中运行测试套件，可以看到测试类 TestWordDealUtil 被调用执行了。测试套件中不仅可以包含基本的测试类，而且可以包含其它的测试套件，这样可以很方便的分层管理不同模块的单元测试代码。但是，您一定要保证测试套件之间没有循环包含关系，否则无尽的循环就会出现在您的面前……。</p>
		<p>
				<a name="N101D8">
						<span class="smalltitle">
								<strong>
										<font face="Arial">参数化测试</font>
								</strong>
						</span>
				</a>
		</p>
		<p>回顾一下我们在小节“<a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#major2"><font color="#5c81a7">JUnit 初体验</font></a>”中举的实例。为了保证单元测试的严谨性，我们模拟了不同类型的字符串来测试方法的处理能力，为此我们编写大量的单元测试方法。可是这些测试方法都是大同小异：代码结构都是相同的，不同的仅仅是测试数据和期望值。有没有更好的方法将测试方法中相同的代码结构提取出来，提高代码的重用度，减少复制粘贴代码的烦恼？在以前的 JUnit 版本上，并没有好的解决方法，而现在您可以使用 JUnit 提供的参数化测试方式应对这个问题。</p>
		<p>参数化测试的编写稍微有点麻烦（当然这是相对于 JUnit 中其它特性而言）：</p>
		<ol>
				<li>为准备使用参数化测试的测试类指定特殊的运行器 org.junit.runners.Parameterized。 
</li>
				<li>为测试类声明几个变量，分别用于存放期望值和测试所用数据。 
</li>
				<li>为测试类声明一个使用注解 org.junit.runners.Parameterized.Parameters 修饰的，返回值为 java.util.Collection 的公共静态方法，并在此方法中初始化所有需要测试的参数对。 
</li>
				<li>为测试类声明一个带有参数的公共构造函数，并在其中为第二个环节中声明的几个变量赋值。 
</li>
				<li>编写测试方法，使用定义的变量作为参数进行测试。 </li>
		</ol>
		<p>我们按照这个标准，重新改造一番我们的单元测试代码：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">package com.ai92.cooljunit;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class TestWordDealUtilWithParam {

		private String expected;
	
		private String target;
	
		@Parameters
		public static Collection words(){
	    		return Arrays.asList(new Object[][]{
	          	{"employee_info", "employeeInfo"},		//测试一般的处理情况
	          	{null, null},							//测试 null 时的处理情况
	          	{"", ""},								//测试空字符串时的处理情况
	          	{"employee_info", "EmployeeInfo"},		//测试当首字母大写时的情况
	          	{"employee_info_a", "employeeInfoA"},	//测试当尾字母为大写时的情况
	          	{"employee_a_info", "employeeAInfo"}	//测试多个相连字母大写时的情况
	    		});
		}
	
	 	/**
	 	* 参数化测试必须的构造函数
	 	* @param expected	期望的测试结果，对应参数集中的第一个参数
	 	* @param target	测试数据，对应参数集中的第二个参数
	 	*/
		public TestWordDealUtilWithParam(String expected , String target){
			this.expected = expected;
			this.target = target;
		}
	
	 	/**
	 	* 测试将 Java 对象名称到数据库名称的转换
	 	*/
		@Test public void wordFormat4DB(){
			assertEquals(expected, WordDealUtil.wordFormat4DB(target));
		}
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>很明显，代码瘦身了。在静态方法 words 中，我们使用二维数组来构建测试所需要的参数列表，其中每个数组中的元素的放置顺序并没有什么要求，只要和构造函数中的顺序保持一致就可以了。现在如果再增加一种测试情况，只需要在静态方法 words 中添加相应的数组即可，不再需要复制粘贴出一个新的方法出来了。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10205">
						<span class="atitle">JUnit 和 Ant</span>
				</a>
		</p>
		<p>随着项目的进展，项目的规模在不断的膨胀，为了保证项目的质量，有计划的执行全面的单元测试是非常有必要的。但单靠JUnit提供的测试套件很难胜任这项工作，因为项目中单元测试类的个数在不停的增加，测试套件却无法动态的识别新加入的单元测试类，需要手动修改测试套件，这是一个很容易遗忘得步骤，稍有疏忽就会影响全面单元测试的覆盖率。</p>
		<p>当然解决的方法有多种多样，其中将 JUnit 与构建利器 Ant 结合使用可以很简单的解决这个问题。Ant —— 备受赞誉的 Java 构建工具。它凭借出色的易用性、平台无关性以及对项目自动测试和自动部署的支持，成为众多项目构建过程中不可或缺的独立工具，并已经成为事实上的标准。Ant 内置了对 JUnit 的支持，它提供了两个 Task：junit 和 junitreport，分别用于执行 JUnit 单元测试和生成测试结果报告。使用这两个 Task 编写构建脚本，可以很简单的完成每次全面单元测试的任务。 </p>
		<p>不过，在使用 Ant 运行 JUnit 之前，您需要稍作一些配置。打开 Eclipse 首选项界面，选择 Ant -&gt; Runtime 首选项（见<a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#figure007"><font color="#5c81a7">图7</font></a>），将 JUnit 4.1 的 JAR 文件添加到 Classpath Tab 页中的 Global Entries 设置项里。记得检查一下 Ant Home Entries 设置项中的 Ant 版本是否在 1.7.0 之上，如果不是请替换为最新版本的 Ant JAR 文件。</p>
		<br />
		<a name="figure007">
				<b>图7 Ant Runtime 首选项</b>
		</a>
		<br />
		<img alt="图7 Ant Runtime 首选项" src="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/figure007.jpg" />
		<br />
		<p>剩下的工作就是要编写 Ant 构建脚本 build.xml。虽然这个过程稍嫌繁琐，但这是一件一劳永逸的事情。现在我们就把前面编写的测试用例都放置到 Ant 构建脚本中执行，为项目 coolJUnit 的构建脚本添加一下内容：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&lt;?xml version="1.0"?&gt;
&lt;!-- ============================================= 
     auto unittest task    
     ai92                                                                
     ========================================== --&gt;
&lt;project name="auto unittest task" default="junit and report" basedir="."&gt;

		&lt;property name="output folder" value="bin"/&gt;

		&lt;property name="src folder" value="src"/&gt;
	
		&lt;property name="test folder" value="testsrc"/&gt;
	
		&lt;property name="report folder" value="report" /&gt;

		&lt;!-- - - - - - - - - - - - - - - - - - 
          target: test report folder init                      
         - - - - - - - - - - - - - - - - - --&gt;
		&lt;target name="test init"&gt;
			&lt;mkdir dir="${report folder}"/&gt;
		&lt;/target&gt;
	
		&lt;!-- - - - - - - - - - - - - - - - - - 
          target: compile                      
         - - - - - - - - - - - - - - - - - --&gt;
		&lt;target name="compile"&gt;
			&lt;javac srcdir="${src folder}" destdir="${output folder}" /&gt;
			&lt;echo&gt;compilation complete!&lt;/echo&gt;
		&lt;/target&gt;

		&lt;!-- - - - - - - - - - - - - - - - - - 
          target: compile test cases                      
         - - - - - - - - - - - - - - - - - --&gt;
		&lt;target name="test compile" depends="test init"&gt;
			&lt;javac srcdir="${test folder}" destdir="${output folder}" /&gt;
			&lt;echo&gt;test compilation complete!&lt;/echo&gt;
		&lt;/target&gt;
	
		&lt;target name="all compile" depends="compile, test compile"&gt;
		&lt;/target&gt;
	
		&lt;!-- ======================================== 
          target: auto test all test case and output report file                      
      	===================================== --&gt;
		&lt;target name="junit and report" depends="all compile"&gt;
			&lt;junit printsummary="on" fork="true" showoutput="true"&gt;
				&lt;classpath&gt;
					&lt;fileset dir="lib" includes="**/*.jar"/&gt;
					&lt;pathelement path="${output folder}"/&gt;
				&lt;/classpath&gt;
				&lt;formatter type="xml" /&gt;
				&lt;batchtest todir="${report folder}"&gt;
					&lt;fileset dir="${output folder}"&gt;
						&lt;include name="**/Test*.*" /&gt;
					&lt;/fileset&gt;
				&lt;/batchtest&gt;
			&lt;/junit&gt;
			&lt;junitreport todir="${report folder}"&gt;
				&lt;fileset dir="${report folder}"&gt;
					&lt;include name="TEST-*.xml" /&gt;
				&lt;/fileset&gt;
				&lt;report format="frames" todir="${report folder}" /&gt;
			&lt;/junitreport&gt;
		&lt;/target&gt;
&lt;/project&gt;
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>Target junit report 是 Ant 构建脚本中的核心内容，其它 target 都是为它的执行提供前期服务。Task junit 会寻找输出目录下所有命名以“Test”开头的 class 文件，并执行它们。紧接着 Task junitreport 会将执行结果生成 HTML 格式的测试报告（<a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#figure008"><font color="#5c81a7">图8</font></a>）放置在“report folder”下。</p>
		<p>为整个项目的单元测试类确定一种命名风格。不仅是出于区分类别的考虑，这为 Ant 批量执行单元测试也非常有帮助，比如前面例子中的测试类都已“Test”打头，而测试套件则以“Suite”结尾等等。</p>
		<br />
		<a name="figure008">
				<b>图8 junitreport 生成的测试报告</b>
		</a>
		<br />
		<img alt="图8 junitreport 生成的测试报告" src="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/figure008.jpg" />
		<br />
		<p>现在执行一次全面的单元测试变得非常简单了，只需要运行一下 Ant 构建脚本，就可以走完所有流程，并能得到一份详尽的测试报告。您可以在 <a href="http://ant.apache.org/manual/index.html"><font color="#5c81a7">Ant 在线手册</font></a> 中获得上面提及的每一个 Ant 内置 task 的使用细节。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10249">
						<span class="atitle">总结</span>
				</a>
		</p>
		<p>随着越来越多的开发人员开始认同并接受极限编程（XP）的思想，单元测试的作用在软件工程中变得越来越重要。本文旨在将最新的单元测试工具 JUnit 4 介绍给您，以及如何结合 IDE Eclipse 和构建工具 Ant 创建自动化单元测试方案。并且还期望您能够通过本文“感染”一些好的单元测试意识，因为 JUnit 本身仅仅是一份工具而已，它的真正优势来自于它的思想和技术。</p>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/index.html?S_TACT=105AGX52&amp;S_CMP=techcsdn#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<span class="atitle">
						<a name="download">下载</a>
				</span>
		</p>
		<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<th scope="col">描述</th>
								<th scope="col">名字</th>
								<th scope="col" align="right">大小</th>
								<th scope="col">下载方法</th>
						</tr>
						<tr>
								<th class="tb-row" scope="row">本文示例代码</th>
								<td nowrap="">coolJUnit.zip</td>
								<td nowrap="" align="right">24 KB</td>
								<td nowrap="">
										<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-lo-junit4/coolJUnit.zip">
												<b>
														<font color="#5c81a7">HTTP</font>
												</b>
										</a>
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr valign="top">
								<td colspan="5">
										<font color="#5c81a7">
												<img height="12" alt="" src="http://www.ibm.com/i/c.gif" width="12" border="0" />
										</font>
								</td>
						</tr>
						<tr>
								<td>
										<font color="#5c81a7">
												<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/fw.gif" width="16" />
										</font>
								</td>
								<td>
										<a class="fbox" href="http://www.ibm.com/developerworks/cn/whichmethod.html">
												<font color="#5c81a7">关于下载方法的信息</font>
										</a>
								</td>
								<td>
										<font color="#5c81a7">
												<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="50" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="resources">
						<span class="atitle">参考资料 </span>
				</a>
		</p>
		<b>学习</b>
		<br />
		<ul>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html">
								<font color="#5c81a7">JUnit 4 抢先看</font>
						</a>（Elliotte Rusty Harold, developerWorks, 2005 年 10 月）：Elliotte Rusty Harold 为大家揭开了 JUnit 4 新框架的面纱。<br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/j-cq08296/">
								<font color="#5c81a7">追求代码质量: JUnit 4 与 TestNG 的对比</font>
						</a>（Andrew Glover, developerWorks, 2006 年 9 月）：Andrew Glover 探讨了这两种框架各自的独特之处，并阐述了 TestNG 独有的三种高级测试特性。<br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/j-testng/">
								<font color="#5c81a7">TestNG 使 Java 单元测试轻而易举</font>
						</a>（Filippo Diotalevi, developerWorks, 2005 年 1 月）：TestNG 不仅确实强大、创新、可扩展、灵活，它还展示了 Java Annotations（JDK 5.0 中的重大新特性）的有趣应用。<br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/j-annotate1/">
								<font color="#5c81a7">Tiger 中的注释，第 1 部分: 向 Java 代码中添加元数据</font>
						</a>（Brett McLaughlin, developerWorks, 2004 年 9 月）：本文解释了元数据如此有用的原因，向您介绍了 Java 语言中的注释，并研究了 Tiger 的内置注释。 <br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/j-ant/index.html">
								<font color="#5c81a7">利用 Ant 和 JUnit 进行增量开发</font>
						</a>（Malcolm Davis, developerWorks, 2000 年 11 月）：本文通过使用代码样本说明了单元测试的种种好处，特别是使用 Ant 和 JUnit 带来的各种方便。 <br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/j-cq/">
								<i>
										<font color="#5c81a7">追求代码质量系列</font>
								</i>
						</a>（Andrew Glover, developerWorks）：在这个系列中，Andrew Glover 将重点阐述有关保证代码质量的一些有时看上去有点神秘的东西。 <br /><br /></li>
		</ul>
		<br />
		<b>获得产品和技术</b>
		<br />
		<ul>
				<li>
						<a href="http://www.junit.org/">
								<font color="#5c81a7">获得 JUnit 软件和相关信息</font>
						</a>。<br /><br /></li>
				<li>
						<a href="http://ant.apache.org/">
								<font color="#5c81a7">获得 Ant 软件和相关信息</font>
						</a>。<br /><br /></li>
				<li>
						<a href="http://www.eclipse.org/">
								<font color="#996699">获得 Eclipse 软件和相关信息</font>
						</a>。</li>
		</ul>
		<br />
<img src ="http://www.blogjava.net/relax/aggbug/101945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2007-03-05 16:15 <a href="http://www.blogjava.net/relax/archive/2007/03/05/101945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>weblogic中文显示乱码解决办法</title><link>http://www.blogjava.net/relax/archive/2007/03/05/101935.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Mon, 05 Mar 2007 07:53:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2007/03/05/101935.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/101935.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2007/03/05/101935.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/101935.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/101935.html</trackback:ping><description><![CDATA[
		<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
				<font face="Times New Roman">
				</font>中文显示乱码解决办法：</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>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: -18pt; TEXT-ALIGN: left; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">1．</span>
				</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">web.xml</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 17.95pt; TEXT-INDENT: 12pt; TEXT-ALIGN: left; mso-para-margin-left: 1.71gd; mso-char-indent-count: 1.0" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">&lt;context-param&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-spacerun: yes">        </span>&lt;param-name&gt;weblogic.httpd.inputCharset./*&lt;/param-name&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 17.95pt; TEXT-INDENT: 36pt; TEXT-ALIGN: left; mso-para-margin-left: 1.71gd; mso-char-indent-count: 3.0" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-tab-count: 1">   </span>&lt;param-value&gt;GB2312&lt;/param-value&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-spacerun: yes">  </span>&lt;/context-param&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: -18pt; TEXT-ALIGN: left; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">2．</span>
				</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">weblogic.xml</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 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<span style="mso-spacerun: yes"> </span>
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">&lt;jsp-descriptor&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-spacerun: yes"> </span>
						<span style="mso-spacerun: yes"> </span>&lt;jsp-param&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-tab-count: 1">
						</span>
						<span style="mso-spacerun: yes">    </span>&lt;param-name&gt;compileCommand&lt;/param-name&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 17.95pt; TEXT-INDENT: 24pt; TEXT-ALIGN: left; mso-para-margin-left: 1.71gd; mso-char-indent-count: 2.0" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-tab-count: 1">       </span>&lt;param-value&gt;javac&lt;/param-value&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-spacerun: yes">  </span>&lt;/jsp-param&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-spacerun: yes">  </span>&lt;jsp-param&gt; <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-tab-count: 1">
						</span>
						<span style="mso-spacerun: yes">    </span>&lt;param-name&gt;compilerSupportsEncoding&lt;/param-name&gt; <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 17.95pt; TEXT-INDENT: 24pt; TEXT-ALIGN: left; mso-para-margin-left: 1.71gd; mso-char-indent-count: 2.0" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-tab-count: 1">       </span>&lt;param-value&gt;true&lt;/param-value&gt; <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-spacerun: yes">  </span>&lt;/jsp-param&gt; <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-spacerun: yes">  </span>&lt;jsp-param&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-tab-count: 1">
						</span>
						<span style="mso-spacerun: yes">    </span>&lt;param-name&gt;encoding&lt;/param-name&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-tab-count: 1">
						</span>
						<span style="mso-spacerun: yes">    </span>&lt;param-value&gt;GB2312&lt;/param-value&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-spacerun: yes">    </span>&lt;/jsp-param&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<span style="mso-spacerun: yes">  </span>&lt;/jsp-descriptor&gt;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: lime">
						<o:p> </o:p>
				</span>
		</p>
<img src ="http://www.blogjava.net/relax/aggbug/101935.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2007-03-05 15:53 <a href="http://www.blogjava.net/relax/archive/2007/03/05/101935.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>澄清Java语言接口与继承的本质     选择自 psyl 的 Blog </title><link>http://www.blogjava.net/relax/archive/2006/03/07/34046.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Tue, 07 Mar 2006 05:34:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2006/03/07/34046.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/34046.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2006/03/07/34046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/34046.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/34046.html</trackback:ping><description><![CDATA[<SPAN id=ArticleContent1_ArticleContent1_lblContent>大多数人认为，接口的意义在于顶替多重继承。众所周知Java没有c++那样多重继承的机制，但是却能够实作多个接口。其实这样做是很牵强的，接口和继承是完全不同的东西，接口没有能力代替多重继承，也没有这个义务。接口的作用，一言以蔽之，就是标志类的类别（type&nbsp;of&nbsp;class）。把不同类型的类归于不同的接口，可以更好的管理他们。OO的精髓，我以为，是对对象的抽象，最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言（比如c++、java、c#等），就是因为设计模式所研究的，实际上就是如何合理的去抽象。（cowboy的名言是“抽象就是抽去像的部分”，看似调侃，实乃至理）。<BR><BR>　　设计模式中最基础的是工厂模式（Factory），在我最近的一个很简单的应用中，我想尽量的让我的程序能够在多个数据库间移植，当然，这涉及很多问题，单是如何兼容不同DBMS的SQL就让人头痛。我们不妨先把问题简单化，只考虑如何连接不同的数据库。<BR><BR>　　假设我有很多个类，分别是Mysql.java、SQLServer.java、Oracle.java、DB2.java，他们分别连接不同的数据库，统一返回一个Connection对象，并且都有一个close方法，用于关闭连接。只需要针对你的DBMS，选择不同的类，就可以用了，但是我的用户他会使用什么数据库？我不知道，我希望的是尽量少的修改代码，就能满足他的需要。我可以抽象如下接口：<BR><BR>package&nbsp;org.bromon.test;<BR>public&nbsp;interface&nbsp;DB<BR>{<BR>　　java.sql.Connection&nbsp;openDB(String&nbsp;url,String&nbsp;user,String&nbsp;password);<BR>　　void&nbsp;close();<BR>}&nbsp;<BR><BR>　　这个接口只定义两个方法，没有任何有实际意义的代码，具体的代码由实作这个接口的类来给出，比如Mysql.java：<BR><BR>Package&nbsp;org.bromon.test;<BR>import&nbsp;java.sql.*;<BR>public&nbsp;class&nbsp;Mysql&nbsp;implements&nbsp;DB<BR>{<BR>　　private&nbsp;String&nbsp;url=”jdbc:mysql:localhost:3306/test”;<BR>　　private&nbsp;String&nbsp;user=”root”;<BR>　　private&nbsp;String&nbsp;password=””;<BR>　　private&nbsp;Connection&nbsp;conn;<BR>　　public&nbsp;Connection&nbsp;openDB(url,user,password)<BR>　　{<BR>　　　　//连接数据库的代码<BR>　　}<BR><BR>　　public&nbsp;void&nbsp;close()<BR>　　{<BR>　　　　//关闭数据库<BR>　　}<BR>}&nbsp;<BR><BR>　　类似的当然还有Oracle.java等等，接口DB给这些类归了个类，在应用程序中我们这样定义对象：<BR><BR>　　org.bromon.test.DB&nbsp;myDB;<BR><BR>　　使用myDB来操作数据库，就可以不用管实际上我所使用的是哪个类，这就是所谓的“开-闭”原则。但是问题在于接口是不能实例化的，myDB=new&nbsp;DB()，这样的代码是绝对错误的，我们只能myDB=new&nbsp;Mysql()或者myDB=new&nbsp;Oracle()。麻烦了，我还是需要指定具体实例化的是哪个类，用了接口跟没用一样。所以我们需要一个工厂：<BR><BR>package&nbsp;org.bromon.test;<BR>public&nbsp;class&nbsp;DBFactory<BR>{<BR>　　public&nbsp;static&nbsp;DB&nbsp;Connection&nbsp;getConn()<BR>　　{<BR>　　　　Return(new&nbsp;Mysql());<BR>　　}<BR>}&nbsp;<BR><BR>　　所以实例化的代码变成：myDB=DBFactory.getConn()；<BR><BR>　　这就是23种模式中最基础的普通工厂(Factory)，工厂类负责具体实例化哪个类，而其他的程序逻辑都是针对DB这个接口进行操作，这就是“针对接口编程”。责任都被推卸给工厂类了，当然你也可以继续定义工厂接口，继续把责任上抛，这就演变成抽象工厂(Abstract&nbsp;Factory)。<BR><BR>　　整个过程中接口不负责任何具体操作，其他的程序要连接数据库的话，只需要构造一个DB对象就OK，而不管工厂类如何变化。这就是接口的意义----抽象。<BR><BR>　　继承的概念不用多说，很好理解。为什么要继承呢？因为你想重用代码？这绝对不是理由，继承的意义也在于抽象，而不是代码重用。如果对象A有一个run()方法，对象B也想有这个方法，所以有人就Class&nbsp;B&nbsp;extends&nbsp;A。这是不经大脑的做法。如果在B中实例化一个A，调用A的Run()方法，是不是可以达到同样的目的？如下：<BR><BR>Class&nbsp;B<BR>{<BR>　　A&nbsp;a=new&nbsp;A();<BR>　　a.run();<BR>}&nbsp;<BR><BR>　　这就是利用类的聚合来重用代码，是委派模式的雏形，是GoF一贯倡导的做法。<BR><BR>　　那么继承的意义何在？其实这是历史原因造成的，最开始的OO语言只有继承，没有接口，所以只能以继承来实现抽象，请一定注意，继承的本意在于抽象，而非代码重用（虽然继承也有这个作用），这是很多Java烂书最严重的错误之一，它们所造成的阴影，我至今还没有完全摆脱，坏书害人啊，尤其是入门类的，流毒太大。什么时候应该使用继承？只在抽象类中使用，其他情况下尽量不使用。抽象类也是不能实例化的，它仅仅提供一个模版而已，这就很能说明问题。<BR><BR>　　软件开发的万恶之源，一是重复代码而不是重用代码，二是烂用继承，尤以c++程序员为甚。Java中取缔多重继承，目的就是制止烂用继承，实是非常明智的做法，不过很多人都不理解。Java能够更好的体现设计，这是让我入迷的原因之一. <BR></SPAN><BR><img src ="http://www.blogjava.net/relax/aggbug/34046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2006-03-07 13:34 <a href="http://www.blogjava.net/relax/archive/2006/03/07/34046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>weblogic和mq的集成</title><link>http://www.blogjava.net/relax/archive/2006/03/07/34026.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Tue, 07 Mar 2006 03:51:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2006/03/07/34026.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/34026.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2006/03/07/34026.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/34026.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/34026.html</trackback:ping><description><![CDATA[<SPAN class=postdetails><FONT size=2>weblogic:8.1 sp2 <BR>MQ:5.3 <BR><BR>摘要：把weblogic 和MQ集成起来是非常有价值的应用。本文讨论使用weblogic的Foreign JMS Server 配置JNDI,MDB配置，使用MQ提供的 <BR>JMSADMIN配置MQ的jndi。也没有那么详细啦，还是需要读者自己作一番小小的努力的。 <BR><BR>关键词：jms,Weblogic foreign JMS Server,JNDI,JMSAdmin <BR><BR>开始： <BR>1、安装Weblogic 和MQ（废话）。 <BR>2、配置JMSAdmin（就是在 mq安装目录下的 java/bin/目录里没有扩展名的的文件） <BR>uncomment下面两行，同时在你的机器上建相应的目录C:/JNDI-Directory <BR><BR><BR></FONT></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>java代码:&nbsp;</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR><BR>INITIAL_CONTEXT_FACTORY=com.<SPAN style="COLOR: #000000">sun</SPAN>.<SPAN style="COLOR: #000000">jndi</SPAN>.<SPAN style="COLOR: #000000">fscontext</SPAN>.<SPAN style="COLOR: #000000">RefFSContextFactory</SPAN> <BR><BR>PROVIDER_URL=file:/C:/JNDI-Directory&nbsp; &nbsp; <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR><BR><FONT size=2>以上配置适用于使用文件jndi。 <BR>3、配置mq的jndi <BR>下面使用jmsadmin配置mq的jndi。 <BR>下面是使用jmsadmin的一些命令的例子。 <BR>其实你可以去ibm的网站上面下载图形界面的东东，就不用记这些命令啦。 <BR>这个东东叫：JMSADMINGUI <BR><BR><BR></FONT></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>java代码:&nbsp;</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR><BR>def qcf<SPAN style="COLOR: #000000">(</SPAN>ivtQCF<SPAN style="COLOR: #000000">)</SPAN> <BR>def q<SPAN style="COLOR: #000000">(</SPAN>ivtQ<SPAN style="COLOR: #000000">)</SPAN> qu<SPAN style="COLOR: #000000">(</SPAN>SYSTEM.<SPAN style="COLOR: #000000">DEFAULT</SPAN>.<SPAN style="COLOR: #000000">LOCAL</SPAN>.<SPAN style="COLOR: #000000">QUEUE</SPAN><SPAN style="COLOR: #000000">)</SPAN> <BR>def tcf<SPAN style="COLOR: #000000">(</SPAN>ivtTCF<SPAN style="COLOR: #000000">)</SPAN> <BR>def t<SPAN style="COLOR: #000000">(</SPAN>ivtT<SPAN style="COLOR: #000000">)</SPAN> topic<SPAN style="COLOR: #000000">(</SPAN>MQJMS/PSIVT/Information<SPAN style="COLOR: #000000">)</SPAN> <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR><BR><BR><FONT size=2>或者你可以执行IVTSETUP脚本来完成一个可以使用的JNDI配置。 <BR><BR>4、配置Weblogic的Foreign JMSServer以下属性进行配置： <BR></FONT></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>java代码:&nbsp;</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR>JNDI Initial <SPAN style="COLOR: #aaaadd" ?>Context</SPAN> Factory-&gt;com.<SPAN style="COLOR: #000000">sun</SPAN>.<SPAN style="COLOR: #000000">jndi</SPAN>.<SPAN style="COLOR: #000000">fscontext</SPAN>.<SPAN style="COLOR: #000000">RefFSContextFactory</SPAN> <BR>JNDI <SPAN style="COLOR: #aaaadd" ?>Connection</SPAN> URL-&gt;file:/C:/JNDI-Directory&nbsp; &nbsp; &nbsp; <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR><FONT size=2>5、配置Foreign JMS Connection Factories <BR><BR>代码: <BR></FONT></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>java代码:&nbsp;</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR>Local JNDI <SPAN style="COLOR: #aaaadd" ?>Name</SPAN>:mqqcf<SPAN style="COLOR: #000000">(</SPAN>在weblogic 中使用的QueueConnectionFactory的JNDI的名字<SPAN style="COLOR: #000000">)</SPAN> <BR><SPAN style="COLOR: #aaaadd" ?>Remote</SPAN> JNDI <SPAN style="COLOR: #aaaadd" ?>Name</SPAN>:ivtQCF<SPAN style="COLOR: #000000">(</SPAN>已经在通过jmsadmin配置º玫Äjndi的名字<SPAN style="COLOR: #000000">)</SPAN> <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR><FONT size=2>6、配置foreign JMS destination <BR><BR></FONT></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>java代码:&nbsp;</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR><BR>Local JNDI <SPAN style="COLOR: #aaaadd" ?>Name</SPAN>: MQQUEUE <BR><SPAN style="COLOR: #aaaadd" ?>Remote</SPAN> JNDI <SPAN style="COLOR: #aaaadd" ?>Name</SPAN>: ivtQ <BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR><FONT size=2>同上。 <BR>7、MDB配置 <BR><BR><BR><BR></FONT></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>java代码:&nbsp;</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR><BR>&lt;?xml version="<SPAN style="COLOR: #000000" ?>1</SPAN>.<SPAN style="COLOR: #000000" ?>0</SPAN>"?&gt; <BR>&lt;!DOCTYPE ejb-jar <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>PUBLIC</SPAN> "-<SPAN style="COLOR: #6666ff">//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"&gt; </SPAN><BR>&lt;!-- This ejb-jar.<SPAN style="COLOR: #000000">xml</SPAN> file defines a message-driven bean called "SimpleMDB". <SPAN style="COLOR: #000000">It</SPAN> uses container-managed transactions, because "transaction-type" is "<SPAN style="COLOR: #aaaadd" ?>Container</SPAN>" and "trans-attribute" is "Required". --&gt; <BR>&lt;ejb-jar&gt; <BR>&nbsp; &nbsp;&lt;enterprise-beans&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;message-driven&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;ejb-name&gt;ReceiveMessageMDB&lt;/ejb-name&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;ejb-<SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>class</SPAN>&gt;com.<SPAN style="COLOR: #000000">rm</SPAN>.<SPAN style="COLOR: #000000">mdb</SPAN>.<SPAN style="COLOR: #000000">ReceiveMessageBean</SPAN>&lt;/ejb-<SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>class</SPAN>&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;transaction-type&gt;<SPAN style="COLOR: #aaaadd" ?>Container</SPAN>&lt;/transaction-type&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;message-driven-destination&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;!-- In WebLogic Server <SPAN style="COLOR: #000000" ?>6</SPAN>.<SPAN style="COLOR: #000000" ?>0</SPAN>, this next parameter is named "jms-destination-type" --&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;destination-type&gt;javax.<SPAN style="COLOR: #000000">jms</SPAN>.<SPAN style="COLOR: #000000">Queue</SPAN>&lt;/destination-type&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/message-driven-destination&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;/message-driven&gt; <BR>&nbsp; &nbsp;&lt;/enterprise-beans&gt; <BR>&nbsp; &nbsp;&lt;assembly-descriptor&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;container-transaction&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;method&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;ejb-name&gt;ReceiveMessageMDB&lt;/ejb-name&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;method-name&gt;*&lt;/method-name&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/method&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;trans-attribute&gt;NotSupported&lt;/trans-attribute&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;/container-transaction&gt; <BR>&nbsp; &nbsp;&lt;/assembly-descriptor&gt; <BR>&lt;/ejb-jar&gt;&nbsp; &nbsp; &nbsp; &nbsp; <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>java代码:&nbsp;</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR>&lt;?xml version="<SPAN style="COLOR: #000000" ?>1</SPAN>.<SPAN style="COLOR: #000000" ?>0</SPAN>" encoding="UTF-<SPAN style="COLOR: #000000" ?>8</SPAN>"?&gt; <BR>&lt;!DOCTYPE weblogic-ejb-jar <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>PUBLIC</SPAN> <SPAN style="COLOR: #0000ff">'-//BEA Systems, Inc.//DTD WebLogic 8.1.0 EJB//EN'</SPAN> <SPAN style="COLOR: #0000ff">'http://www.bea.com/servers/wls810/dtd/weblogic-ejb-jar.dtd'</SPAN>&gt; <BR>&lt;weblogic-ejb-jar&gt; <BR>&lt;weblogic-enterprise-bean&gt; <BR>&lt;ejb-name&gt;ReceiveMessageMDB&lt;/ejb-name&gt; <BR>&lt;message-driven-descriptor&gt; <BR>&lt;pool&gt; <BR>&lt;max-beans-in-free-pool&gt;<SPAN style="COLOR: #000000" ?>8</SPAN>&lt;/max-beans-in-free-pool&gt; <BR>&lt;initial-beans-in-free-pool&gt;<SPAN style="COLOR: #000000" ?>1</SPAN>&lt;/initial-beans-in-free-pool&gt; <BR>&lt;/pool&gt; <BR>&lt;destination-jndi-name&gt;MQQUEUE&lt;/destination-jndi-name&gt; <BR>&lt;initial-context-factory&gt; weblogic.<SPAN style="COLOR: #000000">jndi</SPAN>.<SPAN style="COLOR: #000000">WLInitialContextFactory</SPAN> &lt;/initial-context-factory&gt; <BR>&lt;provider-url&gt;t3:<SPAN style="COLOR: #6666ff">//localhost:7001&lt;/provider-url&gt; </SPAN><BR>&lt;connection-factory-jndi-name&gt;MQQCF&lt;/connection-factory-jndi-name&gt; <BR>&lt;/message-driven-descriptor&gt; <BR>&lt;/weblogic-enterprise-bean&gt; <BR>&lt;/weblogic-ejb-jar&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR><FONT size=2>注意： <BR>如果 ejb-jar.xml中的&lt;trans-attribute&gt;NotSupported&lt;/trans-attribute&gt; <BR>为required则需要使用XAQueueConnectionFactory.</FONT></SPAN> <img src ="http://www.blogjava.net/relax/aggbug/34026.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2006-03-07 11:51 <a href="http://www.blogjava.net/relax/archive/2006/03/07/34026.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 2.0：“本地”接口和“远程”接口</title><link>http://www.blogjava.net/relax/archive/2005/12/02/22267.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Fri, 02 Dec 2005 09:03:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/12/02/22267.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/22267.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/12/02/22267.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/22267.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/22267.html</trackback:ping><description><![CDATA[<STRONG>个新的接口可以使你更有效地访问EJB。学习如何运用它们，以及何时运用它们。 <BR xmlns:fo="http://www.w3.org/1999/XSL/Format"></STRONG><SPAN class=AboutAuthor xmlns:fo="http://www.w3.org/1999/XSL/Format">by Rudy Dahbura</SPAN> 
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>当前的EJB 2.0规范有新的接口功能，这在原先的EJB 1.1中是没有的。学习运用这些新的功能，它们可以使你更容易地、更有效地访问EJB。</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>缺点是什么呢？你将牺牲位置的独立性，但有时侯，这种代价是值得的。了解何时、如何运用新的功能对编写设计良好的EJB应用程序是至关重要的。</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>EJB 1.1规范给EJB客户端提供了一个remote interface和一个remote home interface与EJB实例交互，得到位置的透明度。以类似的形式，EJB 2.0规范现在给EJB客户端提供了一个local interface和一个local home interface来与共享同一个JVM的EJB实例交互。</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>EJB remote interface（javax.ejb.EJBObject）和remote home interface（javax.ejb.EJBHome）在本质上是Java RMI接口。远程客户端运用接口和与Java RMI-IIOP兼容的参数与EJBs通讯。参数和方法的结果值在同一个容器中传递，或者跨网络传递到远程容器。</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>这种编程模式给EJB客户端提供了一种访问EJB组件的方法，就好像这些组件是本地的一样。然后，容器就可以透明地处理网络通讯和执行其它功能。这种方法很适合粗粒度的（coarse-grained）方法调用，其中客户端和EJBs之间的客户端通讯保持到最小限度。</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>相反，EJB local interface（javax.ejb.EJBLocalObject）和local home interface（javax.ejb.EJBLocalHome）不是Java RMI接口，它们是EJB 2.0的新功能。本地客户端——如其它EJBs，运用相同JVM中传递的参数直接与EJBs通讯。这种技术消除了网络潜在的问题、参数复制的问题以及需要与Java RMI-IIOP兼容的问题。也意味着，EJB客户端可以运用一个更轻量级的编程模式来访问服务。该方法很适合细粒度的（fine-grained）方法调用，因为作为EJB实例的位于同一个JVM中的EJB客户端可以用本地接口来避免不必要的费用。</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>引进本地客户端产生的另一个显著的变化就是类型的转换。所有的EJB实例在运用前必须转换到它们恰当的接口类型，所以，有时侯，在运用远程客户端时，要保证Java RMI-IIOP的兼容性，你必须在转换EJB实例前运用java.rmi.PortableRemoteObject.narrow()来缩小（narrow）它。</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>但本地客户端可以直接把EJB实例转换成local home interface类型，如下面的代码片段： 
<TABLE bgColor=#ffffaa>
<TBODY>
<TR>
<TD><FONT color=#0000cc><PRE>InitialContext initCtx = new 
InitialContext();
   ExampleLocalHome exampleLocalHome = 
(ExampleLocalHome)initCtx.lookup("java:comp/
env/ejb/Example");</PRE></FONT></TD></TR></TBODY></TABLE></FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>从local home创建了EJB实例： 
<TABLE bgColor=#ffffaa>
<TBODY>
<TR>
<TD><FONT color=#0000cc><PRE>ExampleLocal exampleLocal = 
exampleLocalHome.create();</PRE></FONT></TD></TR></TBODY></TABLE></FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>也许EJB 2.0的最有趣、最容易被忽视的一个方面就是session和entity beans可以同时运用远程和本地接口，这就给了你很大的灵活性。运用两种接口给了潜在的bean客户端最大程度的自由，不管它们是不是在一起的。</FONT></P><BR xmlns:fo="http://www.w3.org/1999/XSL/Format"><?xml version="1.0" encoding="utf-16"?><BR xmlns:fo="http://www.w3.org/1999/XSL/Format"><SPAN class=AboutAuthor xmlns:fo="http://www.w3.org/1999/XSL/Format"></SPAN>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>&lt;session&gt;和&lt;entity&gt;元素描述了session和entity bean的部署属性。EJB 1.1和EJB 2.0规范定义了两个元素，&lt;home&gt;和&lt;remote&gt;。（以前的规范需要两个元素，但它们在2.0版中是可选的）。它们分别包含EJB remote home interface和remote interface的完全资格类名。 </FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>类似地，EJB 2.0规范定义了两个附加的元素，&lt;local-home&gt;和&lt;local&gt;。正如你预料的，它们包含EJB local home interface和local interface的完全资格类名。下面的代码显示了如何运用这些新元素： 
<TABLE bgColor=#ffffaa>
<TBODY>
<TR>
<TD><FONT color=#0000cc><PRE>&lt;ejb-jar&gt;
   &lt;enterprise-beans&gt;
      &lt;session&gt;
         &lt;ejb-name&gt;...&lt;/ejb-name&gt;
         &lt;local-home&gt;...&lt;/local-home&gt;
         &lt;local&gt;...&lt;/local&gt;
         &lt;ejb-link&gt;...&lt;/ejb-link&gt;
         ...
      &lt;/session&gt;
   &lt;/enterprise-beans&gt;
   &lt;assembly-descriptor&gt;
...
   &lt;/assembly-descriptor&gt;
&lt;/ejb-jar&gt;
</PRE></FONT></TD></TR></TBODY></TABLE></FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black><B><FONT color=#333399>聪明地访问本地客户端的一个实例</FONT></B><BR>本地EJB客户端的概念在如<A href="">列表1</A>所示的例子中得到了很好地阐明，其中显示了一个无状态session bean，它的local interface和它的local home interface。注意，接口不扩展java.rmi.Remote。 </FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>无状态session bean的XML部署描述如下面的代码所示，它也重点强调了&lt;local&gt;和&lt;local-home&gt;元素的运用： 
<TABLE bgColor=#ffffaa>
<TBODY>
<TR>
<TD><FONT color=#0000cc><PRE>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE ejb-jar PUBLIC
   '-//Sun Microsystems, Inc.//DTD Enterprise 
JavaBeans 2.0//EN'
   'http://java.sun.com/dtd/ejb-jar_2_0.dtd'&gt;
&lt;ejb-jar&gt;
   &lt;enterprise-beans&gt;
      &lt;session&gt;
         &lt;ejb-name&gt;Example&lt;/ejb-name&gt;
         &lt;local-
home&gt;com.acmecorp.ejb.ExampleLocalHome&lt;/
local-home&gt;
         &lt;local&gt;com.acmecorp.ejb.ExampleLocal&lt;/local&gt;
         &lt;ejb-
class&gt;com.acmecorp.ejb.ExampleBean&lt;/
ejb-class&gt;
         &lt;session-
type&gt;Stateless&lt;/session-type&gt;
         &lt;transaction-
type&gt;Container&lt;/transaction-type&gt;
      &lt;/session&gt;
   &lt;/enterprise-beans&gt;
   &lt;assembly-descriptor&gt;
      &lt;method-permission&gt;
         &lt;unchecked/&gt;
         &lt;method&gt;
            &lt;ejb-name&gt;Example&lt;/ejb-name&gt;
            &lt;method-name&gt;*&lt;/method-name&gt;
         &lt;/method&gt;
      &lt;/method-permission&gt;
      &lt;container-transaction&gt;
         &lt;method&gt;
            &lt;ejb-name&gt;Example&lt;/ejb-name&gt;
            &lt;method-name&gt;*&lt;/method-name&gt;
         &lt;/method&gt;
         &lt;trans-
attribute&gt;NotSupported&lt;/trans-attribute&gt;
      &lt;/container-transaction&gt;
   &lt;/assembly-descriptor&gt;
&lt;/ejb-jar&gt;
</PRE></FONT></TD></TR></TBODY></TABLE></FONT></P><BR xmlns:fo="http://www.w3.org/1999/XSL/Format"><?xml version="1.0" encoding="utf-16"?><BR xmlns:fo="http://www.w3.org/1999/XSL/Format"><SPAN class=AboutAuthor xmlns:fo="http://www.w3.org/1999/XSL/Format"></SPAN>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>然后，一个本地的客户端创建并访问一个已经创建的enterprise bean的实例。下面的代码也显示了如何转换一个bean的实例，而不用先缩小它： 
<TABLE bgColor=#ffffaa>
<TBODY>
<TR>
<TD><FONT color=#0000cc><PRE>&lt;%@ page errorPage="/error.jsp" 
import="javax.naming.*, 
com.acmecorp.ejb.*" 
%&gt;
&lt;%

   InitialContext initCtx = new InitialContext();
   ExampleLocalHome exampleLocalHome = 
(ExampleLocalHome)initCtx.lookup("java:comp/env/
ejb/Example");
   ExampleLocal exampleLocal = 
exampleLocalHome.create();

%&gt;
&lt;html&gt;
&lt;head&gt;
   &lt;title&gt;Default&lt;/title&gt;
   &lt;link rel="STYLESHEET" type="text/css" 
href="styles/default.css"&gt;
&lt;/head&gt;
&lt;body&gt;
   &lt;pre class="code"&gt;&lt;%= 
exampleLocal.getMessage() %&gt;&lt;/pre&gt;
&lt;/body&gt;
&lt;/html&gt;
</PRE></FONT></TD></TR></TBODY></TABLE></FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>在这个例子中，本地客户端是一个JSP页面，因此是一个Web组件。（在有些情况中，当Web组件位于相同的JVM中时，它们访问EJB 2.0本地组件接口。）</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>最后是Web组件的部署描述： 
<TABLE bgColor=#ffffaa>
<TBODY>
<TR>
<TD><FONT color=#0000cc><PRE>&lt;web-app&gt;
   &lt;!-- EJB Reference information --&gt;
   &lt;ejb-local-ref&gt;
      &lt;ejb-ref-name&gt;ejb/Example&lt;
/ejb-ref-name&gt;
      &lt;ejb-ref-type&gt;Session&lt;
/ejb-ref-type&gt;
      &lt;local-home&gt;com.acmecorp.ejb.ExampleLocalHome&lt;
/local-home&gt;
      &lt;local&gt;com.acmecorp.ejb.ExampleLocal&lt;
/local&gt;
      &lt;ejb-link&gt;Example&lt;/ejb-link&gt;
   &lt;/ejb-local-ref&gt;
&lt;/web-app&gt;
</PRE></FONT></TD></TR></TBODY></TABLE></FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>注意用&lt;ejb-local-ref&gt;元素来声明本地EJB引用。通过&lt;ejb-link&gt;元素得到一个明显的与EJB的链接。它的值必须等于EJB XML描述符中的&lt;ejb-name&gt;元素。</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black><B><FONT color=#333399>未来会有更大的灵活性？</FONT></B><BR>目前还是公开草案的EJB 2.1规范为访问无状态session beans定义了一个Web services客户端。远程客户端将以一种位置独立的方式与无状态session beans通讯，这种通讯主要运用SOAP 1.1通过HTTP进行基于XML的调用。因为XML、SOAP和HTTP是独立于语言的，所以客户端不需要是Java对象，可以是运行在不同平台上的其它类型的对象。</FONT></P>
<P xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=black>到那时，EJB 2.0的新功能就会更受Java开发人员的欢迎了，使他们能够创建代码，更有效地运用本地和远程接口。通过运用这些功能，并对你的设计能力进行正确的评估，你就可以创建应用程序，使它们最大限度地运用EJBs。</FONT></P><BR xmlns:fo="http://www.w3.org/1999/XSL/Format"><FONT color=#666666 xmlns:fo="http://www.w3.org/1999/XSL/Format"><I>关于作者:</I></FONT><BR xmlns:fo="http://www.w3.org/1999/XSL/Format">Rudy Dahbura是位住在洛杉矶的软件顾问。他在洛杉矶的Sierra Systems Group工作，他运用分布式对象技术已经有五年了。他的联系方式是<A href="" target=_blank xmlns:fo="http://www.w3.org/1999/XSL/Format">rdahbura@sierrasystems.com</A>。<BR xmlns:fo="http://www.w3.org/1999/XSL/Format"><img src ="http://www.blogjava.net/relax/aggbug/22267.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-12-02 17:03 <a href="http://www.blogjava.net/relax/archive/2005/12/02/22267.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一段利用管道的多线程程序</title><link>http://www.blogjava.net/relax/archive/2005/12/02/22184.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Fri, 02 Dec 2005 01:05:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/12/02/22184.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/22184.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/12/02/22184.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/22184.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/22184.html</trackback:ping><description><![CDATA[<P>import java.io.*;</P>
<P>public class PipeIODemo1{<BR>&nbsp;public static void main(String[] args) throws IOException{<BR>&nbsp;&nbsp;//创建一个管道输出流对象<BR>&nbsp;&nbsp;PipedWriter out=new PipedWriter();<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//创建一个管道输入流对象<BR>&nbsp;&nbsp;PipedReader in=new PipedReader();<BR>&nbsp;&nbsp;//把管道输入流对象和管道输出流对象联接起来<BR>&nbsp;&nbsp;in.connect(out);<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//以上2个语句等效于<BR>&nbsp;&nbsp;//PipedReader in=new PipedReader(out);<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OutThread objOut=new OutThread(out);<BR>&nbsp;&nbsp;InThread objIn=new InThread(in);<BR>&nbsp;&nbsp;objOut.start();<BR>&nbsp;&nbsp;objIn.start();</P>
<P>&nbsp;&nbsp;try{<BR>&nbsp;&nbsp;&nbsp;objOut.join();<BR>&nbsp;&nbsp;&nbsp;objIn.join();<BR>&nbsp;&nbsp;}catch (InterruptedException e){}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println();<BR>&nbsp;&nbsp;System.out.println("Run Completed!!");<BR>&nbsp;}<BR>}</P>
<P><BR>//定义一个写线程类<BR>class OutThread extends Thread{<BR>&nbsp;private Writer out;<BR>&nbsp;<BR>&nbsp;public OutThread(Writer out){<BR>&nbsp;&nbsp;this.out=out;<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public void run(){<BR>&nbsp;&nbsp;try{<BR>&nbsp;&nbsp;&nbsp;try{<BR>&nbsp;&nbsp;&nbsp;&nbsp;for(char c='A'; c&lt;='Z'; c++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(c);<BR>&nbsp;&nbsp;&nbsp;}finally{<BR>&nbsp;&nbsp;&nbsp;&nbsp;out.close();<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}catch(IOException e){<BR>&nbsp;&nbsp;&nbsp;getThreadGroup().uncaughtException(this, e);<BR>&nbsp;&nbsp;}<BR>&nbsp;}<BR>}</P>
<P>class InThread extends Thread{<BR>&nbsp;private Reader in;</P>
<P>&nbsp;public InThread(Reader in){<BR>&nbsp;&nbsp;this.in=in;<BR>&nbsp;}</P>
<P>&nbsp;public void run(){<BR>&nbsp;&nbsp;int ch;<BR>&nbsp;&nbsp;try{<BR>&nbsp;&nbsp;&nbsp;try{<BR>&nbsp;&nbsp;&nbsp;&nbsp;while ((ch=in.read())!=-1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print((char)ch);<BR>&nbsp;&nbsp;&nbsp;}finally{<BR>&nbsp;&nbsp;&nbsp;&nbsp;in.close();<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}catch(IOException e){<BR>&nbsp;&nbsp;&nbsp;getThreadGroup().uncaughtException(this, e);<BR>&nbsp;&nbsp;}<BR>&nbsp;}<BR>}</P><img src ="http://www.blogjava.net/relax/aggbug/22184.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-12-02 09:05 <a href="http://www.blogjava.net/relax/archive/2005/12/02/22184.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hashtable和HashMap的区别</title><link>http://www.blogjava.net/relax/archive/2005/12/01/22126.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Thu, 01 Dec 2005 08:42:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/12/01/22126.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/22126.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/12/01/22126.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/22126.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/22126.html</trackback:ping><description><![CDATA[1.Hashtable是Dictionary的子类，HashMap是Map接口的一个实现类；<BR><BR>2.Hashtable中的方法是同步的，而HashMap中的方法在缺省情况下是非同步的。即是说，在多线程应用程序中，不用专门的操作就安全地可以使用Hashtable了；而对于HashMap，则需要额外的同步机制。但HashMap的同步问题可通过Collections的一个静态方法得到解决：<BR><B>Map Collections.synchronizedMap(Map m)</B><BR>这个方法返回一个同步的Map，这个Map封装了底层的HashMap的所有方法，使得底层的HashMap即使是在多线程的环境中也是安全的。<BR><BR>3.在HashMap中，null可以作为键，这样的键只有一个；可以有一个或多个键所对应的值为null。当get()方法返回null值时，即可以表示HashMap中没有该键，也可以表示该键所对应的值为null。因此，在HashMap中不能由get()方法来判断HashMap中是否存在某个键，而应该用containsKey()方法来判断。 <BR><BR>4.其底层的实现机制不同，hashmap的访问速度要快于hashtable，因为它不需要进行同步检验，建议在非多线程环境中使用hashmap代替hashtable .<BR><!-- the post be hidden --><img src ="http://www.blogjava.net/relax/aggbug/22126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-12-01 16:42 <a href="http://www.blogjava.net/relax/archive/2005/12/01/22126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java正则表达式详解</title><link>http://www.blogjava.net/relax/archive/2005/11/29/21807.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Tue, 29 Nov 2005 04:30:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/11/29/21807.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/21807.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/11/29/21807.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/21807.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/21807.html</trackback:ping><description><![CDATA[<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>如果你曾经用过Perl或任何其他内建正则表达式支持的语言，你一定知道用正则表达式处理文本和匹配模式是多么简单。如果你不熟悉这个术语，那么“正则表达式”（Regular Expression）就是一个字符构成的串，它定义了一个用来搜索匹配字符串的模式。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>许多语言，包括Perl、PHP、Python、JavaScript和JScript，都支持用正则表达式处理文本，一些文本编辑器用正则表达式实现高级“搜索-替换”功能。那么Java又怎样呢？本文写作时，一个包含了用正则表达式进行文本处理的Java规范需求（Specification Request）已经得到认可，你可以期待在JDK的下一版本中看到它。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>然而，如果现在就需要使用正则表达式，又该怎么办呢？你可以从Apache.org下载源代码开放的Jakarta-ORO库。本文接下来的内容先简要地介绍正则表达式的入门知识，然后以Jakarta-ORO API为例介绍如何使用正则表达式。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B><FONT size=4>一、正则表达式基础知识</FONT></B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串，搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感，单词“catalog”、“Catherine”、“sophisticated”都可以匹配。也就是说： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_a[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>1.1 句点符号</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>假设你在玩英文拼字游戏，想要找出三个字母的单词，而且这些单词必须以“t”字母开头，以“n”字母结束。另外，假设有一本英文字典，你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式，你可以使用一个通配符——句点符号“.”。这样，完整的表达式就是“t.n”，它匹配“tan”、“ten”、“tin”和“ton”，还匹配“t#n”、“tpn”甚至“t n”，还有其他许多无意义的组合。这是因为句点符号匹配所有字符，包括空格、Tab字符甚至换行符： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_b[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>1.2 方括号符号</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>为了解决句点符号匹配范围过于广泛这一问题，你可以在方括号（“[]”）里面指定看来有意义的字符。此时，只有方括号里面指定的字符才参与匹配。也就是说，正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配，因为在方括号之内你只能匹配单个字符： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_c[1].jpg" border=0></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>1.3 “或”符号</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>如果除了上面匹配的所有单词之外，你还想要匹配“toon”，那么，你可以使用“|”操作符。“|”操作符的基本意义就是“或”运算。要匹配“toon”，使用“t(a|e|i|o|oo)n”正则表达式。这里不能使用方扩号，因为方括号只允许匹配单个字符；这里必须使用圆括号“()”。圆括号还可以用来分组，具体请参见后面介绍。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_d[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>1.4 表示匹配次数的符号</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>表一显示了表示匹配次数的符号，这些符号用来确定紧靠该符号左边的符号出现的次数： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4n[1].jpg" border=0></P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式如图一所示。在正则表达式中，连字符（“-”）有着特殊的意义，它表示一个范围，比如从0到9。因此，匹配社会安全号码中的连字符号时，它的前面要加上一个转义字符“\”。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4a[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图一：匹配所有123-12-1234形式的社会安全号码</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>假设进行搜索的时候，你希望连字符号可以出现，也可以不出现——即，999-99-9999和999999999都属于正确的格式。这时，你可以在连字符号后面加上“？”数量限定符号，如图二所示： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4b[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图二：匹配所有123-12-1234和123121234形式的社会安全号码</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>下面我们再来看另外一个例子。美国汽车牌照的一种格式是四个数字加上二个字母。它的正则表达式前面是数字部分“[0-9]{4}”，再加上字母部分“[A-Z]{2}”。图三显示了完整的正则表达式。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4c[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图三：匹配典型的美国汽车牌照号码，如8836KV</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>1.5 “否”符号 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>“^”符号称为“否”符号。如果用在方括号内，“^”表示不想要匹配的字符。例如，图四的正则表达式匹配所有单词，但以“X”字母开头的单词除外。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4d[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图四：匹配所有单词，但“X”开头的除外</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>1.6 圆括号和空白符号 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>假设要从格式为“June 26, 1951”的生日日期中提取出月份部分，用来匹配该日期的正则表达式可以如图五所示： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4e[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图五：匹配所有Moth DD,YYYY格式的日期</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>新出现的“\s”符号是空白符号，匹配所有的空白字符，包括Tab字符。如果字符串正确匹配，接下来如何提取出月份部分呢？只需在月份周围加上一个圆括号创建一个组，然后用ORO API（本文后面详细讨论）提取出它的值。修改后的正则表达式如图六所示： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4f[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图六：匹配所有Month DD,YYYY格式的日期，定义月份值为第一个组</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>1.7 其它符号</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>为简便起见，你可以使用一些为常见正则表达式创建的快捷符号。如表二所示： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>表二：常用符号 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4o[1].jpg" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>例如，在前面社会安全号码的例子中，所有出现“[0-9]”的地方我们都可以使用“\d”。修改后的正则表达式如图七所示： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4g[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图七：匹配所有123-12-1234格式的社会安全号码</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B><FONT size=4>二、Jakarta-ORO库</FONT></B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>有许多源代码开放的正则表达式库可供Java程序员使用，而且它们中的许多支持Perl 5兼容的正则表达式语法。我在这里选用的是Jakarta-ORO正则表达式库，它是最全面的正则表达式API之一，而且它与Perl 5正则表达式完全兼容。另外，它也是优化得最好的API之一。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>Jakarta-ORO库以前叫做OROMatcher，Daniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下载它。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>我首先将简要介绍使用Jakarta-ORO库时你必须创建和访问的对象，然后介绍如何使用Jakarta-ORO API。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>▲ PatternCompiler对象</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>首先，创建一个Perl5Compiler类的实例，并把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实现，允许你把正则表达式编译成用来匹配的Pattern对象。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_e[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>▲ Pattern对象</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>要把正则表达式编译成Pattern对象，调用compiler对象的compile()方法，并在调用参数中指定正则表达式。例如，你可以按照下面这种方式编译正则表达式“t[aeio]n”： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_f[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>默认情况下，编译器创建一个大小写敏感的模式（pattern）。因此，上面代码编译得到的模式只匹配“tin”、“tan”、 “ten”和“ton”，但不匹配“Tin”和“taN”。要创建一个大小写不敏感的模式，你应该在调用编译器的时候指定一个额外的参数： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_g[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>创建好Pattern对象之后，你就可以通过PatternMatcher类用该Pattern对象进行模式匹配。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>▲ PatternMatcher对象</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>PatternMatcher对象根据Pattern对象和字符串进行匹配检查。你要实例化一个Perl5Matcher类并把结果赋值给PatternMatcher接口。Perl5Matcher类是PatternMatcher接口的一个实现，它根据Perl 5正则表达式语法进行模式匹配： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_h[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>使用PatternMatcher对象，你可以用多个方法进行匹配操作，这些方法的第一个参数都是需要根据正则表达式进行匹配的字符串： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>· boolean matches(String input, Pattern pattern)：当输入字符串和正则表达式要精确匹配时使用。换句话说，正则表达式必须完整地描述输入字符串。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>· boolean matchesPrefix(String input, Pattern pattern)：当正则表达式匹配输入字符串起始部分时使用。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>· boolean contains(String input, Pattern pattern)：当正则表达式要匹配输入字符串的一部分时使用（即，它必须是一个子串）。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>另外，在上面三个方法调用中，你还可以用PatternMatcherInput对象作为参数替代String对象；这时，你可以从字符串中最后一次匹配的位置开始继续进行匹配。当字符串可能有多个子串匹配给定的正则表达式时，用PatternMatcherInput对象作为参数就很有用了。用PatternMatcherInput对象作为参数替代String时，上述三个方法的语法如下： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>· boolean matches(PatternMatcherInput input, Pattern pattern) </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>· boolean matchesPrefix(PatternMatcherInput input, Pattern pattern) </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>· boolean contains(PatternMatcherInput input, Pattern pattern) </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B><FONT size=4>三、应用实例</FONT></B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>下面我们来看看Jakarta-ORO库的一些应用实例。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>3.1 日志文件处理</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>任务：分析一个Web服务器日志文件，确定每一个用户花在网站上的时间。在典型的BEA WebLogic日志文件中，日志记录的格式如下： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_i[1].jpg" border=0></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>分析这个日志记录，可以发现，要从这个日志文件提取的内容有两项：IP地址和页面访问时间。你可以用分组符号（圆括号）从日志记录提取出IP地址和时间标记。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>首先我们来看看IP地址。IP地址有4个字节构成，每一个字节的值在0到255之间，各个字节通过一个句点分隔。因此，IP地址中的每一个字节有至少一个、最多三个数字。图八显示了为IP地址编写的正则表达式： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4h[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图八：匹配IP地址</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>IP地址中的句点字符必须进行转义处理（前面加上“\”），因为IP地址中的句点具有它本来的含义，而不是采用正则表达式语法中的特殊含义。句点在正则表达式中的特殊含义本文前面已经介绍。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>日志记录的时间部分由一对方括号包围。你可以按照如下思路提取出方括号里面的所有内容：首先搜索起始方括号字符（“[”），提取出所有不超过结束方括号字符（“]”）的内容，向前寻找直至找到结束方括号字符。图九显示了这部分的正则表达式。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4i[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图九：匹配至少一个字符，直至找到“]”</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>现在，把上述两个正则表达式加上分组符号（圆括号）后合并成单个表达式，这样就可以从日志记录提取出IP地址和时间。注意，为了匹配“- -”（但不提取它），正则表达式中间加入了“\s-\s-\s”。完整的正则表达式如图十所示。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4j[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图十：匹配IP地址和时间标记</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>现在正则表达式已经编写完毕，接下来可以编写使用正则表达式库的Java代码了。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>为使用Jakarta-ORO库，首先创建正则表达式字符串和待分析的日志记录字符串： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_j[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>这里使用的正则表达式与图十的正则表达式差不多完全相同，但有一点例外：在Java中，你必须对每一个向前的斜杠（“\”）进行转义处理。图十不是Java的表示形式，所以我们要在每个“\”前面加上一个“\”以免出现编译错误。遗憾的是，转义处理过程很容易出现错误，所以应该小心谨慎。你可以首先输入未经转义处理的正则表达式，然后从左到右依次把每一个“\”替换成“\\”。如果要复检，你可以试着把它输出到屏幕上。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>初始化字符串之后，实例化PatternCompiler对象，用PatternCompiler编译正则表达式创建一个Pattern对象： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_k[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>现在，创建PatternMatcher对象，调用PatternMatcher接口的contain()方法检查匹配情况： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_l[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>接下来，利用PatternMatcher接口返回的MatchResult对象，输出匹配的组。由于logEntry字符串包含匹配的内容，你可以看到类如下面的输出： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_m[1].jpg" border=0></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>3.2 HTML处理实例一</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>下面一个任务是分析HTML页面内FONT标记的所有属性。HTML页面内典型的FONT标记如下所示： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><FONT face="Arial, Serif" color=red size=+2></FONT><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_n[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>程序将按照如下形式，输出每一个FONT标记的属性： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_o[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>在这种情况下，我建议你使用两个正则表达式。第一个如图十一所示，它从字体标记提取出“"face="Arial, Serif" size="+2" color="red"”。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4k[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图十一：匹配FONT标记的所有属性</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>第二个正则表达式如图十二所示，它把各个属性分割成名字-值对。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4l[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图十二：匹配单个属性，并把它分割成名字-值对</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>分割结果为： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_p[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>现在我们来看看完成这个任务的Java代码。首先创建两个正则表达式字符串，用Perl5Compiler把它们编译成Pattern对象。编译正则表达式的时候，指定Perl5Compiler.CASE_INSENSITIVE_MASK选项，使得匹配操作不区分大小写。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>接下来，创建一个执行匹配操作的Perl5Matcher对象。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_q[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>假设有一个String类型的变量html，它代表了HTML文件中的一行内容。如果html字符串包含FONT标记，匹配器将返回true。此时，你可以用匹配器对象返回的MatchResult对象获得第一个组，它包含了FONT的所有属性： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_r[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>接下来创建一个PatternMatcherInput对象。这个对象允许你从最后一次匹配的位置开始继续进行匹配操作，因此，它很适合于提取FONT标记内属性的名字-值对。创建PatternMatcherInput对象，以参数形式传入待匹配的字符串。然后，用匹配器实例提取出每一个FONT的属性。这通过指定PatternMatcherInput对象（而不是字符串对象）为参数，反复地调用PatternMatcher对象的contains()方法完成。PatternMatcherInput对象之中的每一次迭代将把它内部的指针向前移动，下一次检测将从前一次匹配位置的后面开始。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>本例的输出结果如下： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_s[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><B>3.3 HTML处理实例二</B> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>下面我们来看看另一个处理HTML的例子。这一次，我们假定Web服务器从widgets.acme.com移到了newserver.acme.com。现在你要修改一些页面中的链接： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_t[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>执行这个搜索的正则表达式如图十三所示： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4m[1].gif" border=0> </P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>
<P align=center>图十三：匹配修改前的链接</P></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>如果能够匹配这个正则表达式，你可以用下面的内容替换图十三的链接： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><A href="http://newserver.acme.com/interface.html#$1"></A><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_u[1].jpg" border=0></TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>注意#字符的后面加上了$1。Perl正则表达式语法用$1、$2等表示已经匹配且提取出来的组。图十三的表达式把所有作为一个组匹配和提取出来的内容附加到链接的后面。 </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>现在，返回Java。就象前面我们所做的那样，你必须创建测试字符串，创建把正则表达式编译到Pattern对象所必需的对象，以及创建一个PatternMatcher对象：<IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_v[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>接下来，用com.oroinc.text.regex包Util类的substitute()静态方法进行替换，输出结果字符串： </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_w[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>Util.substitute()方法的语法如下： </TD></TR></TBODY></TABLE>
<TABLE height=17 width=620 align=center>
<TBODY>
<TR>
<TD class=a14 height=13><IMG src="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/CyberArticle/120_files/01_7_31_4_x[1].jpg" border=0> </TD></TR></TBODY></TABLE>
<TABLE width=620 align=center>
<TBODY>
<TR>
<TD class=a14>这个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象，它决定了替换操作如何进行。本例使用的是Perl5Substitution对象，它能够进行Perl5风格的替换。第四个参数是想要进行替换操作的字符串，最后一个参数允许指定是否替换模式的所有匹配子串（Util.SUBSTITUTE_ALL），或只替换指定的次数。 <BR><BR></TD></TR></TBODY></TABLE>补充:现在java里已经正则表达式加进了 java.util.regex包里用起来很简单和上面的介绍也差不多.举个匹配的例子:&nbsp;Pattern&nbsp;p=null;&nbsp;//正则表达式 <BR><BR>&nbsp;Matcher&nbsp;m=null;&nbsp;//操作的字符串 <BR><BR>&nbsp;boolean&nbsp;b; <BR><BR>&nbsp;String&nbsp;s=null; <BR><BR>&nbsp;StringBuffer&nbsp;sb=null; <BR><BR>&nbsp;int&nbsp;i=0; <BR><BR>&nbsp;//字符串匹配，这是不符合的 <BR><BR>&nbsp;&nbsp;p&nbsp;=&nbsp;Pattern.compile("a*b"); <BR><BR>&nbsp;&nbsp;m&nbsp;=&nbsp;p.matcher("baaaaab"); <BR><BR>&nbsp;&nbsp;b&nbsp;=&nbsp;m.matches();&nbsp;<BR>&nbsp;out.println(b); <BR><BR>其实就是这么简单.不过经过我的实验发现java里的正则表达式在做字符替换的时候效率并不是很高,看过还是主要用在字符串匹配方面应用比较多.<img src ="http://www.blogjava.net/relax/aggbug/21807.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-11-29 12:30 <a href="http://www.blogjava.net/relax/archive/2005/11/29/21807.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Commons 阅读笔记 之 Log4J 篇</title><link>http://www.blogjava.net/relax/archive/2005/04/14/3282.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Thu, 14 Apr 2005 07:12:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/04/14/3282.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/3282.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/04/14/3282.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/3282.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/3282.html</trackback:ping><description><![CDATA[<FONT face=宋体><STRONG>•配置Log4J<BR></STRONG>问题：<BR>Log4J支持Properties和XML两种格式的配置文件。<BR>解决方案：<BR>定义log4j.properties配置文件<BR></FONT>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>#&nbsp;所有Log信息输出到标准输出(System.out)和在下面指定的一个文件<BR>#&nbsp;WARN是默认的logging级别<BR>log4j.rootCategory&nbsp;=&nbsp;WARN,&nbsp;STDOUT,&nbsp;FILE<BR><BR>#&nbsp;应用程序的logging级别是DEBUG<BR>log4j.logger.com.discursive&nbsp;=&nbsp;DEBUG<BR><BR>#&nbsp;配置标准输出Appender<BR>log4j.appender.STDOUT&nbsp;=&nbsp;org.apache.log4j.ConsoleAppender<BR>log4j.appender.STDOUT.layout&nbsp;=&nbsp;org.apache.log4j.PatternLayout<BR>log4j.appender.STDOUT.layout.ConversionPattern&nbsp;=&nbsp;%5p&nbsp;(%F:%L)&nbsp;%m%n<BR><BR>#&nbsp;配置输出文件Appender<BR>log4j.appender.FILE&nbsp;=&nbsp;org.apache.log4j.RollingFileAppender<BR>log4j.appender.FILE.File&nbsp;=&nbsp;output.log<BR>log4j.appender.FILE.MaxFileSize&nbsp;=&nbsp;2000KB<BR>log4j.appender.FILE.MaxBackupIndex&nbsp;=&nbsp;5<BR>log4j.appender.FILE.layout&nbsp;=&nbsp;org.apache.log4j.PatternLayout<BR>log4j.appender.FILE.layout.ConversionPattern&nbsp;=&nbsp;%d&nbsp;%-5p&nbsp;%c&nbsp;-&nbsp;%m%n<BR></TD></TR></TBODY></TABLE><BR><BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>PropertyConfigurator.configure(getClass()<BR>&nbsp;&nbsp;.getResource("/resources/log4j.properties"));<BR><BR>Logger&nbsp;logger&nbsp;=&nbsp;Logger.getLogger("com.discursive.SomeApp");<BR>logger.info("This&nbsp;is&nbsp;a&nbsp;info&nbsp;message");<BR>logger.error("This&nbsp;is&nbsp;a&nbsp;error&nbsp;message");<BR></TD></TR></TBODY></TABLE><BR><BR>使用BasicConfigurator类来加载log4j.properties配置。使用Logger.getLogger获得一个logger实例。<BR>配置文件中的rootCategory指定将log输出到控制台和output.log文件。文件Appender使用了RollingFileAppender，当文件大小达到最大文件大小(MaxFileSize)2000KB时，RollingFileAppender会备份原log文件，并再创建一个新的log文件。<BR>配置文件指定默认的logging级别是DEBUG(log4j.logger.com.discursive&nbsp;=&nbsp;DEBUG)。所以，所有级别低于DEBUG的log信息都不会被输出。Log4J按重要度定义了五个log级别，分别是：DEBUG,&nbsp;INFO,&nbsp;WARN,&nbsp;ERROR,&nbsp;和FATAL。<BR>其他：<BR>Log4J还可以使用XML格式的配置文件，使用DOMConfigurator读取。<BR>Log4J使用Appender和Layout来定制log输出。Appender指定输出到何处，Layout指定如何输出(输出的格式)。<BR>Log4J内置的Appender有：<BR>•SMTPAppender<BR>•RollingFileAppender<BR>•SocketAppender<BR>•SyslogAppender<BR>•NTEventLogAppender<BR>Log4J支持的Layout有<BR>•XMLLayout<BR>•PatternLayout<BR>•HTMLLayout<BR>•DateLayout.<img src ="http://www.blogjava.net/relax/aggbug/3282.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-04-14 15:12 <a href="http://www.blogjava.net/relax/archive/2005/04/14/3282.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Commons 阅读笔记 之 Configuration 篇</title><link>http://www.blogjava.net/relax/archive/2005/04/14/3280.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Thu, 14 Apr 2005 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/04/14/3280.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/3280.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/04/14/3280.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/3280.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/3280.html</trackback:ping><description><![CDATA[<FONT face=宋体><STRONG>•访问Properties格式的配置文件<BR></STRONG>问题：<BR>希望能以精确类型的方式访问到配置信息，而不仅仅是String类型。&nbsp;<BR>解决方案：<BR>使用PropertiesConfiguration类可以加载并访问properties格式的配置文件，并提供对数值型、数组型和List列表型配置信息的支持。<BR>比如，有如下的配置信息：<BR></FONT>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>speed=23.332<BR>names=Bob,Gautam,Jarret,Stefan<BR>correct=false<BR></TD></TR></TBODY></TABLE><BR><BR>可以像这样来访问他们：<BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>Configuration&nbsp;config&nbsp;=&nbsp;new&nbsp;PropertiesConfiguration(getClass()<BR>&nbsp;&nbsp;&nbsp;&nbsp;.getResource("/resources/config.properties"));<BR><BR>float&nbsp;speed&nbsp;=&nbsp;config.getFloat("speed");<BR>List&nbsp;names&nbsp;=&nbsp;config.getList("names");<BR>boolean&nbsp;correct&nbsp;=&nbsp;config.getBoolean("correct");<BR></TD></TR></TBODY></TABLE><BR><BR>传递给PropertiesConfiguration构建函数的参数可以是文件名、可以访问到文件的URL、以及文件本身(File对象)。当然，Properties类也可以完成同样的事情，但只支持返回String类型的值。<BR><BR><B>•访问XML格式的配置文件</B><BR>问题：<BR>希望使用XML格式的配置文件来配置应用程序。<BR>解决方案：<BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>Configuration&nbsp;config&nbsp;=&nbsp;new&nbsp;XMLConfiguration("resources/config.xml");<BR>List&nbsp;criterias&nbsp;=&nbsp;config.getList("start-criteria.criteria");<BR>String&nbsp;criteria&nbsp;=&nbsp;config.getString("start-criteria.criteria(0)");<BR>String&nbsp;type&nbsp;=&nbsp;config.getString("start-criteria.criteria(0)［@type］");//自己替换［］<BR>int&nbsp;horsepower&nbsp;=&nbsp;config.getInt("horsepower");<BR></TD></TR></TBODY></TABLE><BR><BR>使用XMLConfiguration类可以加载并访问XML格式的配置文件，访问配置信息使用的是XPath格式&nbsp;(XPath请参数相应的XML文档)。<BR>传递给XMLConfiguration构建函数的参数可以是文件名、可以访问到文件的URL、以及文件本身(File对象)。<BR><BR><B>•访问组合配置</B><BR>问题：<BR>有时候应用程序使用一种多层结构的配置方式，即上一层的配置可以被下一层选择性地覆盖。<BR>解决方案：<BR>configuration.xml<BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="ISO-8859-1"&nbsp;?&gt;<BR>&lt;configuration&gt;<BR>&nbsp;&lt;properties&nbsp;fileName="user.properties"&nbsp;/&gt;<BR>&nbsp;&lt;properties&nbsp;fileName="local.properties"&nbsp;/&gt;<BR>&nbsp;&lt;properties&nbsp;fileName="global.properties"&nbsp;/&gt;<BR>&lt;/configuration&gt;<BR></TD></TR></TBODY></TABLE><BR><BR>global.properties<BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>threads.max=50<BR>threads.min=2<BR>timeout=15.52<BR>interactive=true<BR>color=red<BR>speed=50<BR>name=Default&nbsp;User<BR></TD></TR></TBODY></TABLE><BR><BR>local.properties<BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>#&nbsp;Overrides&nbsp;Global&nbsp;Props<BR>threads.max=30<BR>speed=55<BR></TD></TR></TBODY></TABLE><BR><BR>user.properties<BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>#&nbsp;Overrides&nbsp;Local&nbsp;Props<BR>threads.min=1<BR>color=black<BR>speed=5000<BR>name=Sean<BR></TD></TR></TBODY></TABLE><BR><BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>ConfigurationFactory&nbsp;factory&nbsp;=&nbsp;new&nbsp;ConfigurationFactory();<BR>factory.setConfigurationURL(CfgTest3.class.getResource("/resources/configuration.xml"));<BR>Configuration&nbsp;config&nbsp;=&nbsp;factory.getConfiguration();<BR><BR>//&nbsp;print&nbsp;out&nbsp;properties<BR>System.out.println("Timeout:&nbsp;"&nbsp;+&nbsp;config.getFloat("timeout"));<BR>System.out.println("Max&nbsp;Threads:&nbsp;"&nbsp;+&nbsp;config.getString("threads.max"));<BR>System.out.println("Name:&nbsp;"&nbsp;+&nbsp;config.getString("name"));<BR>System.out.println("Speed:&nbsp;"&nbsp;+&nbsp;config.getInt("speed"));<BR></TD></TR></TBODY></TABLE><BR><BR>创建一个声明多个properties配置的configuration.xml文件，并传递给ConfigurationFactory，ConfigurationFactory解析这些properties配置，生成一个包含最终配置信息的Configuration实例，通过这个实例访问到的配置信息，就是被覆盖过的最终版本。<BR>上面实例中的configuration.xml文件由多个&lt;properties/&gt;元素组成，覆盖的顺序由上往下，也就是说user.properties会覆盖local.properties，local.properties会覆盖global.properties。<BR>其他：<BR>configuration.xml文件可以使用如下的元素来声明配置文件：<BR>•&lt;properties/&gt;&nbsp;用于声明properties格式的配置文件<BR>•&lt;xml/&gt;用于声明xml格式的配置文件<BR>除了可以访问properties格式和xml格式的配置文件以外，Commons&nbsp;Configuration包还定义了JNDIConfiguration类来访问JNDI树格式的配置信息，具体的方法请参考其他相关文档。<img src ="http://www.blogjava.net/relax/aggbug/3280.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-04-14 14:52 <a href="http://www.blogjava.net/relax/archive/2005/04/14/3280.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Spring AOP 缓存方法结果集 </title><link>http://www.blogjava.net/relax/archive/2005/04/11/3141.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Mon, 11 Apr 2005 07:17:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/04/11/3141.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/3141.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/04/11/3141.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/3141.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/3141.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 我们都知道Hibernate可以用ehcache来作为Second Level Cache.主要是针对POJO的缓存,而且缓存的读取在Hibernate中是写死.实际运用中感觉很不灵活.今天看到一篇介绍利用Spring Interceptor 来缓存指定方法结果的例子,感觉很不错,充分体会到AOP的强大力量 :)首先配置ehcache.xml&nbsp;&lt;...&nbsp;&nbsp;<a href='http://www.blogjava.net/relax/archive/2005/04/11/3141.html'>阅读全文</a><img src ="http://www.blogjava.net/relax/aggbug/3141.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-04-11 15:17 <a href="http://www.blogjava.net/relax/archive/2005/04/11/3141.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转帖]ant入门：我喜欢简单：ant - java 构建工具</title><link>http://www.blogjava.net/relax/archive/2005/02/21/1387.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Mon, 21 Feb 2005 04:16:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/02/21/1387.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/1387.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/02/21/1387.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/1387.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/1387.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;管理你的代码，doc文件,编译,配置等开发工作你是怎末做的：自己管理源目录，编译文件，copy,实施...<BR>在window写bat,在unix写shell？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可惜我不怎末会写。所以我制作一个ejb的过程是这样的：<BR>写代码-&gt;写个bat编译代码-&gt;组织文件(ejb-jar.xml,jboss.xml...)-&gt;压缩文件生成jar文档-&gt;<BR>实施......(还有同样的测试过程)(为甚末不用jbuild?)<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;这中间每次修改都要经过重复的无数次手工copy,paste...过程，好累，好花时间。可我确实不想去<BR>学脚本编写，unix,linux下我还得重学，太累。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;如果你和我一样希望自动执行预定义的动作却又不想太累，那末，我觉得ANT工具不错：<BR>它可以以相同的用法用在不同平台(跨平台)。它是JAVA做的，免费的，开源的，据说网上已经成了事实的JAVA<BR>构建标准，还听说高手都用它......&nbsp;^_^<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;我花了2天时间才掌握了它的基本用法，我希望你能通过我的文章和试验花半天时间就掌握它。<BR><BR>内容：<BR>&nbsp;&nbsp;&nbsp;下载，安装&nbsp;<BR>&nbsp;&nbsp;&nbsp;hello&nbsp;ant&nbsp;<BR>&nbsp;&nbsp;&nbsp;hello&nbsp;ant&nbsp;进级&nbsp;<BR>&nbsp;&nbsp;&nbsp;参考及下载&nbsp;<BR><BR>下载，安装<BR>&nbsp;&nbsp;&nbsp;又下载?又是一大堆参数变量?&nbsp;&nbsp;:(<BR>&nbsp;&nbsp;&nbsp;&nbsp;<IMG src="http://www.matrix.org.cn/images/small/url.gif" align=absMiddle><A href="http://jakarta.apache.org/ant/index.html&nbsp;" target=_blank>http://jakarta.apache.org/ant/index.html&nbsp;</A>;它是apache的java子项目"jakarta"的子项目.你可以选择<BR>当前的版本，目前我是1.5版,window版，以下就用它讲。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;解压后ant_home用来方便访问。并确保你也设置了java_home&nbsp;。<BR>&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;ant_home=D:\java\kit\ant\jakarta-ant-1.5.1&nbsp;&nbsp;&nbsp;&nbsp;这是我的目录&nbsp;&nbsp;&nbsp;&nbsp;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;就这些，简单吧。<BR><BR>hello&nbsp;ant<BR><BR>我们要开发一个java类：其内容只有一句，输出"hello&nbsp;ant"字符串。并使用ant完成编译和运行工作，这个例子只是为了跑通ant，不附加多余的东西。<BR><BR>下图为文件组织，请建立相应的目录，并编写HelloAnt.java<BR><A href="http://www.matrix.org.cn/upload/forum/2005221103950.gif" target=_blank><IMG height=375 alt="" src="http://www.matrix.org.cn/upload/forum/2005221103950.gif" width=500 onload="javascript:if(this.width>screen.width-215)this.width=screen.width-215" align=center border=0 dypop="按此在新窗口浏览图片"></A><BR>按照人家老外的文件组织规则咱也照搬。<BR><BR>hello.ant.HelloAnt.java:<BR>[code]<BR>package&nbsp;hello.ant;<BR><BR>public&nbsp;class&nbsp;HelloAnt{<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("hello&nbsp;ant,ant&nbsp;的第一次接触，好棒！");<BR>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<BR>}<BR>[/code]<BR><BR>在项目根目录(hello-ant\)写1个文件：ant执行配置文件build.xml:<BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>&lt;?xml&nbsp;version="1.0"&nbsp;&nbsp;encoding="GB2312"&nbsp;?&gt;<BR><BR>&lt;!--&nbsp;一个项目,可包含很多任务组(target)&nbsp;--&gt;<BR>&lt;project&nbsp;default="main"&nbsp;basedir="."&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;项目中的一个任务组,可包含很多任务(task:javac,java...)&nbsp;--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;target&nbsp;name="main"&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--编译--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;javac&nbsp;srcdir="src\main\hello\ant"&nbsp;destdir="build\classes"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--运行--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;java&nbsp;classname="hello.ant.HelloAnt"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;classpath&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement&nbsp;path="build\classes"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/classpath&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/java&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<BR>&lt;/project&gt;<BR></TD></TR></TBODY></TABLE><BR><BR><BR>ok,一切大功告成，哦，不，还没有运行它。<BR><BR>dos下进入hello-ant的目录，即build.xml所在的目录，我们要用ant工具执行它&nbsp;，&nbsp;<BR><BR>执行:&nbsp;%ant_home%/bin/ant&nbsp;-file&nbsp;build.xml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用ant工具执行当前目录下的配置文件build.xml&nbsp;<BR><BR>或&nbsp;&nbsp;：ant&nbsp;-file&nbsp;build.xml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;你如果设置%ant_home%/bin到path中<BR><BR>这次ok了，这是答案：<BR><BR>命令提示符窗口&nbsp;<BR>D:\temp\hello-ant&gt;ant&nbsp;-file&nbsp;build.xml<BR>Buildfile&amp;:&nbsp;build.xml<BR><BR>main:<BR>[javac]&nbsp;Compiling&nbsp;1&nbsp;source&nbsp;file&nbsp;to&nbsp;D:\temp\hello-ant\build\classes<BR>[java]&nbsp;hello&nbsp;ant,ant&nbsp;的第一次接触，好棒！<BR><BR>BUILD&nbsp;SUCCESSFUL<BR>Total&nbsp;time:&nbsp;2&nbsp;seconds<BR>D:\temp\hello-ant&gt;&nbsp;&nbsp;<BR><BR>检查一下build/classes目录，哦，看到编译过的文件就在这里:<BR>build/classes/hello/ant/HelloAnt.class.<BR><BR><BR>hello&nbsp;ant&nbsp;进级<BR><BR>(此段比较废话，可以略过)<BR>你也许会说：这末简单的工作写个批处理不就得了，又xml又ant的，把我的时间都浪费完了，我用jbuild或<BR>webShpere不就得了，怎末说你才明白呢？反正网上开源项目大多数都用ant,你总不能给人家个*.jpx吧，<BR>而且这样的工具太贵，受不了(当然用D的兄弟不怕^_^&nbsp;)，而且ant可以让你明确的管理和自动化所有的东西:<BR>编译-实施-测试...,哎，稍微麻烦一点点，但节约你以前花在零碎的copy,paste上的时间.而且我发现管理<BR>代码的质量有所提高.<BR><BR>我们要改进build.xml，让它做更多的事情：<BR><BR>定义全局变量&nbsp;<BR>初始化,主要是建立目录&nbsp;<BR>编译&nbsp;&nbsp;(已有)&nbsp;<BR>打包为jar&nbsp;<BR>建立API&nbsp;document．tion&nbsp;<BR>生成distribution产品&nbsp;<BR>凡事都讲究平衡，你要ant给你做更多事，当然要累一点点，不过只用累一次，以后的代码修改后的构建都是"一键式"完成,我们制作一个hello的简单例子，你可以自己做j2ee的练习。<BR><BR>我们要扩充目录结构，使它更像回事：<BR><BR>ant处理编译之前的目录：<BR><A href="http://www.matrix.org.cn/upload/forum/2005221104418.gif" target=_blank><IMG height=375 alt=按此在新窗口浏览图片 src="http://www.matrix.org.cn/upload/forum/2005221104418.gif" width=500 onload="javascript:if(this.width>screen.width-215)this.width=screen.width-215" align=center border=0></A><BR><BR>ant处理之后的目录：<BR><A href="http://www.matrix.org.cn/upload/forum/2005221104435.gif" target=_blank><IMG height=375 alt=按此在新窗口浏览图片 src="http://www.matrix.org.cn/upload/forum/2005221104435.gif" width=500 onload="javascript:if(this.width>screen.width-215)this.width=screen.width-215" align=center border=0></A><BR><BR>图中：\src,\docs,\lib是自己组织的文件结构，\build,\dist是ant动态生成的成品。<BR><BR>\src&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;源文件：java源，script源，jsp源，xml配置.....<BR>\src\main&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java源<BR>\src\script&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window,unix,liunx的执行script，我们的简单只有一个：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;run.bat:&nbsp;&nbsp;java&nbsp;hello.ant.HelloAnt<BR><BR>\docs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;手写说明文档<BR>\lib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;程序所需类库的jar,比如j2ee.jar,mail,jar...<BR><BR>\build&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用ant动态生成的构建目录<BR>\build\classes&nbsp;&nbsp;编译的类文件<BR>\build\docs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;copy&nbsp;"\docs"的手写说明文档，和ant生成的api文档<BR>\build\lib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;放置我们自己的HelloAnt.class打包成品hello-ant.jar<BR><BR>\dist\bin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;copy&nbsp;"\src\script"&nbsp;得执行文件<BR>\dist\docs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;copy&nbsp;"\build\docs"&nbsp;的文档<BR>\dist\lib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;除了copy&nbsp;"\build\lib"下的hello-ant.jar外，<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;还应copy&nbsp;"\lib"的程序所需jar，这里我们没有。<BR><BR>以上是我学老外的文件组织，大家可以按照自己的爱好组织<BR><BR>我们编写必要的文件：&nbsp;<BR>hello.ant.&nbsp;HelloAnt.java:已有<BR>\src\script.bat:<BR>
<TABLE style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>
<TBODY>
<TR>
<TD style="WORD-WRAP: break-word"><BR>@echo&nbsp;off<BR>echo&nbsp;========================================================<BR>echo&nbsp;&nbsp;&nbsp;请先设置&nbsp;Environment<BR>echo&nbsp;.<BR>echo&nbsp;&nbsp;&nbsp;JAVA_HOME:&nbsp;%JAVA_HOME%<BR>echo&nbsp;======================================================<BR><BR>%java_home%\bin\java&nbsp;-classpath&nbsp;..\lib\hello-ant.jar&nbsp;&nbsp;hello.ant.HelloAnt<BR><BR>pause&nbsp;<BR></TD></TR></TBODY></TABLE><BR><BR>\docs\index.html&nbsp;随便写一个手写的文档&nbsp;:<BR>\build.xml&nbsp;配置文件:<BR>[code]<BR>&lt;?xml&nbsp;version="1.0"&nbsp;&nbsp;encoding="GB2312"&nbsp;?&gt;<BR>&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;=======================================================================<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hello-ant&nbsp;项目&nbsp;,学习ant工具的第2个build&nbsp;file.<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;参照ant的jakarta-ant-1.6alpha的build.xml<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Copyright&nbsp;(c)&nbsp;2002&nbsp;The&nbsp;Neusoft&nbsp;Software&nbsp;Foundation.&nbsp;&nbsp;All&nbsp;rights<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reserved.<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;=======================================================================<BR>--&gt;<BR><BR>&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;文档结构为:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;project&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;全局变量的定义<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property/&gt;...<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;target&nbsp;name="1"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;任务组(tasks)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;javac&gt;&lt;/javac&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一项javac任务<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;&lt;oneTask&gt;&lt;/ontTask&gt;&nbsp;&nbsp;&nbsp;一项其它任务<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;target&nbsp;name="2"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;javac&gt;&lt;/javac&gt;<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;&lt;oneTask&gt;&lt;/ontTask&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/project&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;project代表一个项目，<BR>&nbsp;&nbsp;&nbsp;&nbsp;default:运行到名称为"dist"的target(任务组)<BR>&nbsp;&nbsp;&nbsp;&nbsp;basedir:基准路径。<BR>--&gt;<BR>&lt;project&nbsp;default="dist"&nbsp;basedir="."&gt;<BR><BR>&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;定义属性（property&nbsp;tasks）<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;最好把用到的路径呀，名称呀都在这里定义成全局变量<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;例：定义<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="a"&nbsp;value="hello"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以后就可以这样用它：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="b"&nbsp;value="${a}/b"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;现在:b=="hello/b"<BR>&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>--&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--主要的系统环境属性--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;environment="env"/&gt;&lt;!--取window,unix...的环境变量--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="java.home"&nbsp;value="${env.JAVA_HOME}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="ant.home"&nbsp;&nbsp;value="${env.ANT_HOME}"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--主要的app环境属性--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="app.name"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="hello-ant"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="app.jar"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="${app.name}.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="app.copyright"&nbsp;value="&nbsp;Copyright&nbsp;(c)&nbsp;2002&nbsp;The&nbsp;Neusoft&nbsp;Software&nbsp;Foundation.&nbsp;&nbsp;All&nbsp;rights&nbsp;reserved."/&gt;<BR><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--app中src的属性--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="src.dir"&nbsp;&nbsp;&nbsp;&nbsp;value="src"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="src.main"&nbsp;&nbsp;&nbsp;value="${src.dir}/main"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="src.script"&nbsp;value="${src.dir}/script"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--app用到的lib--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="lib.dir"&nbsp;value="lib"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--app的build目录中--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="build.dir"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="build"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="build.classes"&nbsp;&nbsp;value="${build.dir}/classes"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="build.docs"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="${build.dir}/docs"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="build.docs.api"&nbsp;value="${build.docs}/api"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="build.lib"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="${build.dir}/lib"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--app的dist&nbsp;(distribution)&nbsp;目录中--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="dist.dir"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="dist"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="dist.bin"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="${dist.dir}/bin"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="dist.docs"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="${dist.dir}/docs"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="dist.lib"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="${dist.dir}/lib"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--app的docs目录中--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="docs.dir"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="docs"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;定义一组路径以后可以通过id重用这组路径&nbsp;，例：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;javac&nbsp;srcdir="src/main"&nbsp;destdir="build/classes"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;classpath&nbsp;refid="classpath"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/javac&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;path&nbsp;id="classpath"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--本项目只有一个java，用不上classpath，这里只是做个例子--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement&nbsp;location="${build.classes}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement&nbsp;path="${java.home}/lib/tools.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/path&gt;<BR><BR>&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init&nbsp;准备目录(File&nbsp;Tasks)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;主要的目录结构通常是不会变的，一起生成他们<BR>&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;target&nbsp;name="init"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--清除以前目录--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;delete&nbsp;dir="${build.dir}"&nbsp;failonerror="false"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;delete&nbsp;dir="${dist.dir}"&nbsp;&nbsp;failonerror="false"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--准备目录--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mkdir&nbsp;dir="${build.dir}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mkdir&nbsp;dir="${build.classes}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mkdir&nbsp;dir="${build.docs}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mkdir&nbsp;dir="${build.docs.api}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mkdir&nbsp;dir="${build.lib}"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mkdir&nbsp;dir="${dist.dir}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mkdir&nbsp;dir="${dist.bin}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mkdir&nbsp;dir="${dist.lib}"/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<BR><BR>&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Build&nbsp;the&nbsp;code&nbsp;(Compile&nbsp;Tasks,File&nbsp;Tasks)<BR>&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;target&nbsp;name="build"&nbsp;depends="init"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--编译--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;javac&nbsp;srcdir="${src.main}"&nbsp;destdir="${build.classes}"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;classpath&nbsp;refid="classpath"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/javac&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<BR><BR>&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;打包文档(Archive&nbsp;Tasks)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create&nbsp;the&nbsp;project&nbsp;jars:&nbsp;xxx1.jar&nbsp;and&nbsp;xxx2.jar<BR>&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>--&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;target&nbsp;name="jars"&nbsp;depends="build"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;jar&nbsp;basedir="${build.classes}"&nbsp;jarfile="${build.lib}/${app.jar}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<BR><BR>&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Creates&nbsp;the&nbsp;API&nbsp;document．tion<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;target&nbsp;name="javadocs"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;depends="jars"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description="--&gt;&nbsp;creates&nbsp;the&nbsp;API&nbsp;document．tion"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--copy&nbsp;docs&nbsp;手册...&nbsp;--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;copy&nbsp;todir="${build.docs}"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;fileset&nbsp;dir="${docs.dir}"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/copy&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;javadoc&nbsp;packagenames="hello.ant.*"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sourcepath="${src.main}"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultexcludes="yes"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;destdir="${build.docs.api}"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;author="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;use="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;windowtitle="Docs&nbsp;API"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;doctitle&gt;&lt;![CDATA[&lt;h1&gt;hello&nbsp;ant&nbsp;Docs&nbsp;API&lt;/h1&gt;]]&gt;&lt;/doctitle&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;bottom&gt;&lt;![CDATA[&lt;i&gt;${app.copyright}&lt;/i&gt;]]&gt;&lt;/bottom&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tag&nbsp;name="todo"&nbsp;scope="all"&nbsp;description="To&nbsp;do:"&nbsp;/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/javadoc&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<BR><BR>&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create&nbsp;the&nbsp;distribution&nbsp;that&nbsp;can&nbsp;run&nbsp;(Archive&nbsp;Tasks)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;主要是从各目录中把该copy的copy上<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>--&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;target&nbsp;name="dist"&nbsp;depends="javadocs"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--copy&nbsp;bin&nbsp;执行文件&nbsp;--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;copy&nbsp;todir="${dist.bin}"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;fileset&nbsp;dir="${src.script}/"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/copy&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;copy&nbsp;todir="${dist.docs}"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;fileset&nbsp;dir="${build.docs}/"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/copy&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;copy&nbsp;lib&nbsp;文件&nbsp;--&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;copy&nbsp;todir="${dist.lib}"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;fileset&nbsp;dir="${build.lib}/"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/copy&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<BR>&lt;!--<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cleans&nbsp;everything(File&nbsp;Tasks)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;例如可以删除build中的文件，留给你发挥吧<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;===================================================================<BR>--&gt;<BR><BR>&lt;/project&gt;<BR>[/code]<BR><BR>build.xml多了些，但其实很简单：(注释比较详细可以参照，这里再简单说一下)<BR><BR>一个build.xml包含一个工程的自动化处理的完整xml说明，并且基本由3种东东组成：<BR><BR>&lt;project&nbsp;&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;1.全局变量的定义<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property/&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;2.任务组<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;target&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.许多单项任务...&nbsp;像copy,delete,javac,jar...<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;task1/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;task2/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;task3/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<BR><BR>&lt;/project&gt;<BR><BR><BR>参考及下载：<BR><BR>本文程序:第1个hello-ant<BR><BR>本文程序:第2个进阶的hello-ant<BR><BR>ant最新下载：<BR><IMG src="http://www.matrix.org.cn/images/small/url.gif" align=absMiddle><A href="http://jakarta.apache.org/ant/index.html&nbsp;" target=_blank>http://jakarta.apache.org/ant/index.html&nbsp;</A>;<BR><BR>ant具体的编写方法参考ant手册以下2部分就形，<BR><IMG src="http://www.matrix.org.cn/images/small/url.gif" align=absMiddle><A href="http://jakarta.apache.org/ant/manual/using&nbsp;" target=_blank>http://jakarta.apache.org/ant/manual/using&nbsp;</A>;使用说明<BR><IMG src="http://www.matrix.org.cn/images/small/url.gif" align=absMiddle><A href="http://jakarta.apache.org/ant/manual/coretasklist.html&nbsp;" target=_blank>http://jakarta.apache.org/ant/manual/coretasklist.html&nbsp;</A>;核心tasks<BR>其他一大堆东西你要看也行。不过我觉得比较浪费时间。<BR><IMG src="http://www.matrix.org.cn/images/small/url.gif" align=absMiddle><A href="http://jakarta.apache.org/ant/manual/index.html&nbsp;" target=_blank>http://jakarta.apache.org/ant/manual/index.html&nbsp;</A>;&nbsp;手册index<BR><BR>huihoo.com翻译改编的ant/manual/using<BR><IMG src="http://www.matrix.org.cn/images/small/url.gif" align=absMiddle><A href="http://www.huihoo.com/java/ant.html&nbsp;" target=_blank>http://www.huihoo.com/java/ant.html&nbsp;</A>;<BR><BR>用ANT构造Application作者：余斌斌&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG src="http://www.matrix.org.cn/images/small/url.gif" align=absMiddle><A href="http://developer.ccidnet.com/pub/disp/Article?columnID=295&amp;articleID=27619&amp;pageNO=1" target=_blank>http://developer.ccidnet.com/pub/disp/Article?columnID=295&amp;articleID=27619&amp;pageNO=1</A><BR><BR>ibm&nbsp;利用&nbsp;Ant&nbsp;和&nbsp;JUnit&nbsp;进行增量开发——使用单元测试来逐步改进代码<BR><IMG src="http://www.matrix.org.cn/images/small/url.gif" align=absMiddle><A href="http://www-900.ibm.com/developerWorks/cn/java/j-ant/index.shtml" target=_blank>http://www-900.ibm.com/developerWorks/cn/java/j-ant/index.shtml</A><BR><BR>关于作者：<BR><BR>陈鹏，东软西安公司。作为一名狂热的程序员希望每一天都能成长进步，并希望与大家分享快乐和知识。<BR>请用以下方式和他联系：email&nbsp;chen56@msn.com&nbsp;&nbsp;<BR><img src ="http://www.blogjava.net/relax/aggbug/1387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-02-21 12:16 <a href="http://www.blogjava.net/relax/archive/2005/02/21/1387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA 的MD5加密算法源代码</title><link>http://www.blogjava.net/relax/archive/2005/02/02/923.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Wed, 02 Feb 2005 08:11:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/02/02/923.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/923.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/02/02/923.html#Feedback</comments><slash:comments>15</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/923.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/923.html</trackback:ping><description><![CDATA[<P><SPAN id=ArticleContent1_ArticleContent1_lblContent><SPAN id=ArticleContent1_ArticleContent1_lblContent>import java.security.*;<BR>import java.security.spec.*; </P>
<P>class MD5_Test{</P>
<P>&nbsp;&nbsp; public final static String MD5(String s){<BR>&nbsp;&nbsp;&nbsp;&nbsp; char hexDigits[] = {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'e', 'f'};<BR>&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] strTemp = s.getBytes();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageDigest mdTemp = MessageDigest.getInstance("MD5");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mdTemp.update(strTemp);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] md = mdTemp.digest();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int j = md.length;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char str[] = new char[j * 2];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int k = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; j; i++) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte byte0 = md[i];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str[k++] = hexDigits[byte0 &gt;&gt;&gt; 4 &amp; 0xf];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str[k++] = hexDigits[byte0 &amp; 0xf];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new String(str);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (Exception e){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>}<BR>&nbsp;public static void main(String[] args){<BR>&nbsp;//MD5_Test aa = new MD5_Test();</P>
<P>&nbsp;System.out.print(MD5_Test.MD5("XX"));<BR>&nbsp;}<FONT color=#800080><U><BR></FONT></U></P></SPAN></SPAN><img src ="http://www.blogjava.net/relax/aggbug/923.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-02-02 16:11 <a href="http://www.blogjava.net/relax/archive/2005/02/02/923.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> jsp template之我见 </title><link>http://www.blogjava.net/relax/archive/2005/02/02/922.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Wed, 02 Feb 2005 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/02/02/922.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/922.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/02/02/922.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/922.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/922.html</trackback:ping><description><![CDATA[<SPAN id=ArticleContent1_ArticleContent1_lblContent>我们在做程序的过程中，常常会遇到这样一种情况，就是在一个项目中，会发现有很多页面的框架基本相同的，只是具体显示的内容不同，而按常规的做法，我们可能会用include语句来提出框架内容，然后在每个页面中引用这些框架，但这样就会产生一个问题，如果我的框架发生变化了，那应该怎么办呢？举个例子，一个index.jsp可能包含有head.jsp和foot.jsp。而其它页面也同样包含这两个JSP。但如果我在index.jsp里有一段导航条的代码，我现在想在每个页面里引用，而不想加到head.jsp中，难道我们要在每个页面里都增加这个导航条的代码吗？我想我是不会这样做的。因为有一种更好的办法来解决这种问题。那就是采用模板页面。<BR><BR>template页面的原理，其实就是写一个servlet来实现页面的跳转，然后在web.xml里面配置这个servlet，使要使用模板的这一类JSP文件，都通过这个servlet来处理，使它们都转到模板页面即可。然后在模板页面中include这些页面的内容页即可。<BR><BR>具体的做法，只要写一个template.jsp做为模板页面、一个TemplateDispatch.java做为跳转的类就可以了。然后在调用时，直接指向这个SERVLET，加一个参数，说明要用到哪个内容页就行了。写个简单的例子如下：<BR>template.jsp<BR>=====================================<BR>&lt;% page contentType="text/html; charset=gb2312"%&gt;<BR>&lt;%@ include file=“head.jsp“%&gt;<BR>&lt;%=(String)request.getAttribute(“body“)%&gt;<BR>&lt;%@ include file=“foot.jsp“%&gt;<BR><BR>TemplateDispatch<BR>=====================================<BR>public class TemplateDispatchextends HttpServlet{<BR>&nbsp;&nbsp;&nbsp;&nbsp;public void doGet(HttpServletRequest request,HttpServletResponse response){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doPost(request,response);&nbsp;&nbsp; <BR>&nbsp;}<BR>&nbsp;&nbsp;&nbsp; public void doPost(HttpServletRequest request,HttpServletResponse response){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpSession session = request.getSession(true);<BR>session.setAttribute(“body“,“index.jsp“);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RequestDispatcher rd = session.getServletContext().getRequestDispatcher("template.jsp");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rd.forward(request,response);<BR>}<BR>}<BR><BR>web.xml<BR>=====================================<BR>&nbsp; &lt;servlet&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;dispatch&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;TemplateDispatchextends &lt;/servlet-class&gt;<BR>&nbsp; &lt;/servlet&gt;<BR>&nbsp; &lt;servlet-mapping&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;dispatch&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/*&lt;/url-pattern&gt;<BR>&nbsp; &lt;/servlet-mapping&gt;<BR><BR>代码是即兴写的，没有做过测试，只是表达一下意思。<BR>===========================================<BR><BR>如果觉得简单的话，还可以扩展一下。通过配置文件配置内容页，以及taglib来定义两个标签insert用来增加内容页、value用来在模板里直接显示内容。<BR><BR>现在在回头想想前面提到的问题，是不是会比较容易解决了呢？如果页面有什么变动的话，只要修改一下模板页就可以了。这样还不会犯漏掉哪个页面的错误。<BR></SPAN><img src ="http://www.blogjava.net/relax/aggbug/922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-02-02 16:00 <a href="http://www.blogjava.net/relax/archive/2005/02/02/922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts学习资源 </title><link>http://www.blogjava.net/relax/archive/2005/02/02/921.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Wed, 02 Feb 2005 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/02/02/921.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/921.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/02/02/921.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/921.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/921.html</trackback:ping><description><![CDATA[<SPAN id=ArticleContent1_ArticleContent1_lblContent>深入了解Servlet<FONT color=#000000> 最新技术:<BR>http://java.sun.com/products/servlet/index.html<BR>http://www.servlets.com<BR><BR>最新的JSP开发技术:<BR>http://java.sun.com/products/jsp<BR>http://java.sun.com/products/jsp/docs.html<BR><BR>深入了解JavaBean:<BR>http://java.sun.com/products/javabeans/<BR><BR>JSP标签技术:<BR>http://java.sun.com/products/jsp/tutorial/TagLibrariesTOC.html<BR>http://jsptags.com<BR><BR>EJB组件开发技术:<BR>http://java.sun.com/products/ejb/index.html<BR><BR>深入了解XML:<BR>http://www.w3.org/TR/2000/REC-xml-20001006<BR>http://www.w3schools.com/xml/default.asp<BR><BR>Struts控制面板工具:<BR>http://www.jamesholmes.com/struts/console/<BR><BR>Struts邮件列表:<BR>&nbsp; 1.STRUTS-USER:面向Struts应用开发者<BR>&nbsp;&nbsp;&nbsp;&nbsp; FAQs:http://jakarta.apache.org/struts/faqs/<BR>&nbsp; 2.STRUTS-DEV:面向Struts框架开发者<BR>&nbsp;&nbsp;<BR>&nbsp; 订阅：http://jakarta.apache.org/struts/using.html#lists<BR>&nbsp; 搜索：http://jakarta.apache.org/site/mail2.html<BR>&nbsp; <BR>Struts资源：<BR>&nbsp; 主页：http://jakarta.apache.org/struts<BR>&nbsp; 资源：http://jakarta.apache.org/struts/resources/index.html</FONT></SPAN><img src ="http://www.blogjava.net/relax/aggbug/921.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-02-02 15:50 <a href="http://www.blogjava.net/relax/archive/2005/02/02/921.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDBC连接数据库经验技巧集萃 </title><link>http://www.blogjava.net/relax/archive/2005/02/01/891.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Tue, 01 Feb 2005 04:26:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/02/01/891.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/891.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/02/01/891.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/891.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/891.html</trackback:ping><description><![CDATA[Java数据库连接（JDBC）由一组用 Java 编程语言编写的类和接口组成。JDBC 为工具/数据库开发人员提供了一个标准的 API，使他们能够用纯Java API 来编写数据库应用程序。然而各个开发商的接口并不完全相同，所以开发环境的变化会带来一定的配置变化。本文主要集合了不同数据库的连接方式。<BR><BR>　　<B>一、连接各种数据库方式速查表</B><BR><BR>　　下面罗列了各种数据库使用JDBC连接的方式，可以作为一个手册使用。 <BR><BR>　　1、Oracle8/8i/9i数据库（thin模式） <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); <BR>String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID <BR>String user="test"; <BR>String password="test"; <BR>Connection conn= DriverManager.getConnection(url,user,password); </TD></TR></TBODY></TABLE><BR>　　2、DB2数据库 <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance(); <BR>String url="jdbc:db2://localhost:5000/sample"; //sample为你的数据库名 <BR>String user="admin"; <BR>String password=""; <BR>Connection conn= DriverManager.getConnection(url,user,password); </TD></TR></TBODY></TABLE><BR>　　3、Sql Server7.0/2000数据库 <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); <BR>String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb"; <BR>//mydb为数据库 <BR>String user="sa"; <BR>String password=""; <BR>Connection conn= DriverManager.getConnection(url,user,password); </TD></TR></TBODY></TABLE><BR>　　4、Sybase数据库 <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>Class.forName("com.sybase.jdbc.SybDriver").newInstance(); <BR>String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB为你的数据库名 <BR>Properties sysProps = System.getProperties(); <BR>SysProps.put("user","userid"); <BR>SysProps.put("password","user_password"); <BR>Connection conn= DriverManager.getConnection(url, SysProps); </TD></TR></TBODY></TABLE><BR>　　5、Informix数据库 <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>Class.forName("com.informix.jdbc.IfxDriver").newInstance(); <BR>String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver; <BR>user=testuser;password=testpassword"; //myDB为数据库名 <BR>Connection conn= DriverManager.getConnection(url); </TD></TR></TBODY></TABLE><BR>　　6、MySQL数据库 <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>Class.forName("org.gjt.mm.mysql.Driver").newInstance(); <BR>String url ="jdbc:mysql://localhost/myDB?user=soft&amp;password=soft1234&amp;useUnicode=true&amp;characterEncoding=8859_1" <BR>//myDB为数据库名 <BR>Connection conn= DriverManager.getConnection(url); </TD></TR></TBODY></TABLE><BR>　　7、PostgreSQL数据库 <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>Class.forName("org.postgresql.Driver").newInstance(); <BR>String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库名 <BR>String user="myuser"; <BR>String password="mypassword"; <BR>Connection conn= DriverManager.getConnection(url,user,password); </TD></TR></TBODY></TABLE><BR>　　8、access数据库直连用ODBC的<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;<BR>String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");<BR>Connection conn = DriverManager.getConnection(url,"","");<BR>Statement stmtNew=conn.createStatement() ;</TD></TR></TBODY></TABLE><BR>　　<B>二、JDBC连接MySql方式</B><BR><BR>　　下面是使用JDBC连接MySql的一个小的教程 <BR><BR>　　1、查找驱动程序<BR><BR>　　MySQL目前提供的java驱动程序为Connection/J，可以从MySQL官方网站下载，并找到mysql-connector-java-3.0.15-ga-bin.jar文件，此驱动程序为纯java驱动程序，不需做其他配置。<BR><BR>　　2、动态指定classpath<BR><BR>　　如果需要执行时动态指定classpath，就在执行时采用－cp方式。否则将上面的.jar文件加入到classpath环境变量中。<BR><BR>　　3、加载驱动程序<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>try{<BR>　Class.forName(com.mysql.jdbc.Driver);<BR>　System.out.println(Success loading Mysql Driver!);<BR>}catch(Exception e)<BR>{<BR>　System.out.println(Error loading Mysql Driver!);<BR>　e.printStackTrace();<BR>}</TD></TR></TBODY></TABLE><BR>　　4、设置连接的url<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>jdbc：mysql：//localhost/databasename[?pa=va][＆pa=va]</TD></TR></TBODY></TABLE><BR><SPAN class=f14>　　<B>三、以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧</B><BR><BR>　　1、在客户端软件开发中使用Thin驱动程序<BR><BR>　　在开发Java软件方面，Oracle的数据库提供了四种类型的驱动程序，二种用于应用软件、applets、servlets等客户端软件，另外二种用于数据库中的Java存储过程等服务器端软件。在客户机端软件的开发中，我们可以选择OCI驱动程序或Thin驱动程序。OCI驱动程序利用Java本地化接口（JNI），通过Oracle客户端软件与数据库进行通讯。Thin驱动程序是纯Java驱动程序，它直接与数据库进行通讯。为了获得最高的性能，Oracle建议在客户端软件的开发中使用OCI驱动程序，这似乎是正确的。但我建议使用Thin驱动程序，因为通过多次测试发现，在通常情况下，Thin驱动程序的性能都超过了OCI驱动程序。<BR><BR>　　2、关闭自动提交功能，提高系统性能<BR><BR>　　在第一次建立与数据库的连接时，在缺省情况下，连接是在自动提交模式下的。为了获得更好的性能，可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能，如下所示：<BR><BR>　　conn.setAutoCommit(false);<BR><BR>　　值得注意的是，一旦关闭了自动提交功能，我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理。<BR><BR>　　3、在动态SQL或有时间限制的命令中使用Statement对象<BR><BR>　　在执行SQL命令时，我们有二种选择：可以使用PreparedStatement对象，也可以使用Statement对象。无论多少次地使用同一个SQL命令，PreparedStatement都只对它解析和编译一次。当使用Statement对象时，每次执行一个SQL命令时，都会对它进行解析和编译。这可能会使你认为，使用PreparedStatement对象比使用Statement对象的速度更快。然而，我进行的测试表明，在客户端软件中，情况并非如此。因此，在有时间限制的SQL操作中，除非成批地处理SQL命令，我们应当考虑使用Statement对象。<BR><BR>　　此外，使用Statement对象也使得编写动态SQL命令更加简单，因为我们可以将字符串连接在一起，建立一个有效的SQL命令。因此，我认为，Statement对象可以使动态SQL命令的创建和执行变得更加简单。<BR><BR>　　4、利用helper函数对动态SQL命令进行格式化<BR><BR>　　在创建使用Statement对象执行的动态SQL命令时，我们需要处理一些格式化方面的问题。例如，如果我们想创建一个将名字O'Reilly插入表中的SQL命令，则必须使用二个相连的“''”号替换O'Reilly中的“'”号。完成这些工作的最好的方法是创建一个完成替换操作的helper方法，然后在连接字符串心服用公式表达一个SQL命令时，使用创建的helper方法。与此类似的是，我们可以让helper方法接受一个Date型的值，然后让它输出基于Oracle的to_date()函数的字符串表达式。<BR><BR>　　5、利用PreparedStatement对象提高数据库的总体效率<BR><BR>　　在使用PreparedStatement对象执行SQL命令时，命令被数据库进行解析和编译，然后被放到命令缓冲区。然后，每当执行同一个PreparedStatement对象时，它就会被再解析一次，但不会被再次编译。在缓冲区中可以发现预编译的命令，并且可以重新使用。在有大量用户的企业级应用软件中，经常会重复执行相同的SQL命令，使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务，我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。<BR><BR>　　6、在成批处理重复的插入或更新操作中使用PreparedStatement对象<BR><BR>　　如果成批地处理插入和更新操作，就能够显著地减少它们所需要的时间。Oracle提供的Statement和 CallableStatement并不真正地支持批处理，只有PreparedStatement对象才真正地支持批处理。我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理，或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制，可以以如下所示的方式调用setExecuteBatch()：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>PreparedStatement pstmt3D null;<BR>try {<BR>　((OraclePreparedStatement)pstmt).setExecuteBatch(30);<BR>　...<BR>　pstmt.executeUpdate();<BR>} </TD></TR></TBODY></TABLE><BR>　　调用setExecuteBatch()时指定的值是一个上限，当达到该值时，就会自动地引发SQL命令执行，标准的executeUpdate()方法就会被作为批处理送到数据库中。我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务。<BR><BR>　　7、使用Oracle locator方法插入、更新大对象（LOB）<BR><BR>　　Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理，尤其是Thin驱动程序不支持利用PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值，也不支持利用setCharacterStream()方法设置CLOB的值。只有locator本身中的方法才能够从数据库中获取LOB类型的值。可以使用PreparedStatement对象插入或更新LOB，但需要使用locator才能获取LOB的值。由于存在这二个问题，因此，我建议使用locator的方法来插入、更新或获取LOB的值。<BR><BR>　　8、使用SQL92语法调用存储过程<BR><BR>　　在调用存储过程时，我们可以使用SQL92或Oracle PL/SQL，由于使用Oracle PL/SQL并没有什么实际的好处，而且会给以后维护你的应用程序的开发人员带来麻烦，因此，我建议在调用存储过程时使用SQL92。<BR><BR>　　9、使用Object SQL将对象模式转移到数据库中<BR><BR>　　既然可以将Oracle的数据库作为一种面向对象的数据库来使用，就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象，将它们的属性映射到关系表中，然后在这些bean中添加方法。尽管这样作在Java中没有什么问题，但由于操作都是在数据库之外进行的，因此其他访问数据库的应用软件无法利用对象模式。如果利用Oracle的面向对象的技术，可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作，然后使用JPublisher等工具生成自己的Java bean类。如果使用这种方式，不但Java应用程序可以使用应用软件的对象模式，其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式。<BR><BR>　　10、利用SQL完成数据库内的操作<BR><BR>　　我要向大家介绍的最重要的经验是充分利用SQL的面向集合的方法来解决数据库处理需求，而不是使用Java等过程化的编程语言。<BR><BR>　　如果编程人员要在一个表中查找许多行，结果中的每个行都会查找其他表中的数据，最后，编程人员创建了独立的UPDATE命令来成批地更新第一个表中的数据。与此类似的任务可以通过在set子句中使用多列子查询而在一个UPDATE命令中完成。当能够在单一的SQL命令中完成任务，何必要让数据在网上流来流去的？我建议用户认真学习如何最大限度地发挥SQL的功能。 <BR></SPAN><img src ="http://www.blogjava.net/relax/aggbug/891.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-02-01 12:26 <a href="http://www.blogjava.net/relax/archive/2005/02/01/891.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java的破解和反破解之道 </title><link>http://www.blogjava.net/relax/archive/2005/02/01/889.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Tue, 01 Feb 2005 03:25:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/02/01/889.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/889.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/02/01/889.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/889.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/889.html</trackback:ping><description><![CDATA[摘自<A href="http://www.99college.com/">久久学院</A><BR><SPAN class=f14>　　java字节码能够很容易被反编译大家都晓得啦，今天下午我为了得到一个心仪已久的jbuilder opentools（昨天1.0 Released，新鲜出炉！但只能用14天，这怎么行，于是我不惜放下其他工作，研究了一把该软件加密方法的破解和反破解，结合以前的一些经验，作文一篇与大家共飨，并不是鼓励大家...... <BR><BR>　　<STRONG>破解之道：</STRONG> <BR><BR><IMG height=328 src="http://www.yesky.com/image20010518/239500.gif" width=604 useMap=#Map border=0> <MAP name=Map><AREA shape=RECT target=_blank coords=253,237,541,264 href="http://dev.yesky.com/SoftChannel/72342371961929728/index.shtml"></MAP><BR><BR>　　对一些提供license.key（包含授权信息的加密文件）的软件，一般这种文件会采用DES,RAS和CRC校验而且一般是二进制的（即使有时输出成BASE64编码），直接修改文件是浪费时间的，你可以先反编译通过阅读源程序来探究解密过程，如果过程是可逆的，那么你自己实现一个加密过程，可以很容易的生成你自己想要的license key；如果过程不可逆也不是就搞不定了，有些强度不大的加密算法还是可以用暴力破解法来搞定，还有一种情况是对数字加密（一般指过期时间）如果你能修改这个过期时间那么你就可以多用一会儿了，用数学方法描述一下： <BR><BR>　　假设集合 X 是明文包含的元素集合，Y是X经过算法后的映射，包含密文元素，，如果有存在两个算法A和B，能使得{ Y －A-&gt; X } = { Y -B-&gt; X }，A算法可逆，但B算法是不可逆的，生产方用A的逆算法加密授权信息（X:String) 到(Y:byte[])，并在软件中用B算法解密，这样你就搞不定了，但如果集合X的元素是有限的，假设只有0-9 （new Date().getTime()格式），那么算法B就称为不可逆但不可靠的，因为你通过一个样本（一般都会给你评价版的license啦！），是可以得到某些Y集合中元素在X集合中的逆映射的，这样你可以直接用这张映射表来修改license了... <BR><BR>　　<STRONG>反破解之道</STRONG>： <BR><BR>　　如果是做产品或提供演示程序，加密还是有好处的，加密的软件可以用上面提到的JODE，一般都是对编译好的class文件进行扰乱，因为并不是所有的符号都需要扰乱，如果你开发的是一个类库，或者某些类需要动态装载，那些公共API就必须保留符号不变，这样别人才能使用你的类库。先编写脚本对那些需要保留的符号名称进行配置，某些扰乱器能够调整字节码的顺序，使反编译更加困难。如果你用的代码扰乱器能保证别人不能通过反编译来修改或代替你的class，那么你还得注意不要用不可靠的加密算法。</SPAN><B><BR></B><img src ="http://www.blogjava.net/relax/aggbug/889.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-02-01 11:25 <a href="http://www.blogjava.net/relax/archive/2005/02/01/889.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>