﻿<?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-Sung in Blog-文章分类-Ｅｃｌｉｐｓｅ</title><link>http://www.blogjava.net/qq13367612/category/4377.html</link><description>&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font class="subhead" size=3&gt;&lt;b&gt;一些技术文章 &amp; 一些生活杂碎&lt;/b&gt;&lt;/font&gt;</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 03:57:13 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 03:57:13 GMT</pubDate><ttl>60</ttl><item><title>Eclipse中自动重构实现探索 </title><link>http://www.blogjava.net/qq13367612/articles/17837.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:42:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17837.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17837.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17837.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17837.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17837.html</trackback:ping><description><![CDATA[<P>
<TABLE cellSpacing=0 cellPadding=0 width=680 border=0>
<TBODY>
<TR>
<TD vAlign=top>
<TABLE class=zhi14 height=38 cellSpacing=0 cellPadding=0 width=648 align=center border=0>
<TBODY>
<TR>
<TD style="WORD-BREAK: break-all" vAlign=top width=648 height=18>本文用eclipse的自动重构功能对一个程序实例进行重构，目的是探索Eclipse自动重构可以在多大程度上辅助重构这个过程。程序实例使用《Refactoring：Improving the Design of Existing Code》一书中的例子。<BR>　　<BR>　　Eclipse的自动重构功能能够很好地支持各种程序元素的重命名，并自动更新相关的引用。Eclipse能够支持方法、字段在类之间移动，并自动更新引用。Eclipse较好地支持内联字段、函数的更新替换。Eclipse较好地支持抽取方法、变量等程序元素。<BR>　　<BR>　　重构的过程是一个不断尝试和探索的过程。Eclipse的重构支持撤销和重做，并且能够预览重构结果，这些是很实用的功能。<BR>　　<BR>　　Eclipse的重命名、抽取方法、移动、内联功能、更改方法特征符等代码结构级别的重构方法，是比较成熟同时也值得使用的功能。至于设计结构上的重构，eclipse还不能很好地支持。但是作者相信，自动重构的理念应该是"工具辅助下的重构工作"，人仍然承担大部分重构工作。<BR>　　<BR>　　<B>一、预备工作</B><BR>　　<BR>　　本文使用《Refactoring：Improving the Design of Existing Code》一书第一章的例子。重构前的代码及每一步重构后的代码见附件。读者最好配合《Refactoring：Improving the Design of Existing Code》一书阅读本文。<BR>　　<BR>　　Eclipse使用如下版本：<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.10.10.59.43.1.jpg"><BR>　　同时安装了中文语言包。<BR>　　<BR>　　<B>二、重构第一步：分解并重组statement()</B><BR>　　<BR>　　目的：<BR>　　<BR>　　1、 把statement()函数中的swich语句提炼到独立的函数amountFor()中。<BR>　　<BR>　　2、 修改amountFor()参数命名<BR>　　<BR>　　重构方法：<BR>　　<BR>　　Extract Method<BR>　　Rename Method<BR>　　<BR>　　方法：<BR>　　<BR>　　1、选中swich语句的代码块，在右键菜单中选择"重构/抽取方法"，出现参数对话框。Eclipse自动分析代码块中的局部变量，找到了两个局部变量：each和thisAmount。其中，each只是在代码块中被读取，但thisAmount会在代码块中被修改。按照重构Extract Method总结出来的规则，应该把each当作抽取函数的参数、thisAmount当作抽取函数的返回值。然而Eclipse并不做区分，直接把这两个变量当作抽取新方法的参数，如图。<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.10.10.59.52.2.jpg"><BR>　　我们的目的是把在抽取函数中不会被修改的each作为参数；会被修改的thisAmount作为返回值。解决的办法是，把 double thisAmount = 0; 这行代码移到switch语句的上面，变成这样：<BR>　　<BR>　　double thisAmount = 0;<BR>　　switch(each.getMovie().getPriceCode()){<BR>　　case Movie.REGULAR:<BR>　　thisAmount += 2;<BR>　　if(each.getDaysRented()&gt;2)<BR>　　thisAmount += (each.getDaysRented()-2)*1.5;<BR>　　break;<BR>　　<BR>　　case Movie.NEW_RELEASE:<BR>　　thisAmount += each.getDaysRented()*3;<BR>　　break;<BR>　　<BR>　　case Movie.CHILDRENS:<BR>　　thisAmount += 1.5;<BR>　　if(each.getDaysRented()&gt;3)<BR>　　thisAmount += (each.getDaysRented()-3)*1.5;<BR>　　break;<BR>　　}<BR>　　<BR>　　选中这段代码，在右键菜单中选择"重构/抽取方法"，eclipse这次变得聪明点了，如图。<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.10.11.0.0.3.jpg"><BR>　　选择"预览"按钮预先查看重构后的结果，符合我们最初的目的。<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.10.11.0.10.4.jpg"><BR>　　选择"确定"按钮，重构后的代码片断如下：<BR>　　<BR>　　public String statement() {<BR>　　double totalAmount = 0;<BR>　　int frequentRenterPoints = 0;<BR>　　Enumeration rentals = _rentals.elements();<BR>　　String result = "Rental Record for " + getName() + "\n";<BR>　　<BR>　　while(rentals.hasMoreElements()){<BR>　　Rental each = (Rental)rentals.nextElement();<BR>　　<BR>　　double thisAmount = amountFor(each);<BR>　　<BR>　　frequentRenterPoints ++;<BR>　　if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE &amp;&amp;each.getDaysRented()&gt;1)<BR>　　frequentRenterPoints ++;<BR>　　<BR>　　result += "\t" + each.getMovie().getTitle() + "\t" +String.valueOf(thisAmount) + "\n";<BR>　　totalAmount += thisAmount;<BR>　　}<BR>　　<BR>　　result += "Amount owed is " + String.valueOf(totalAmount) + "\n";<BR>　　result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";<BR>　　<BR>　　return result;<BR>　　}<BR>　　<BR>　　/**<BR>　　* @param each<BR>　　* @return<BR>　　*/<BR>　　private double amountFor(Rental each) {<BR>　　double thisAmount = 0;<BR>　　switch(each.getMovie().getPriceCode()){<BR>　　case Movie.REGULAR:<BR>　　thisAmount += 2;<BR>　　if(each.getDaysRented()&gt;2)<BR>　　thisAmount += (each.getDaysRented()-2)*1.5;<BR>　　break;<BR>　　<BR>　　case Movie.NEW_RELEASE:<BR>　　thisAmount += each.getDaysRented()*3;<BR>　　break;<BR>　　<BR>　　case Movie.CHILDRENS:<BR>　　thisAmount += 1.5;<BR>　　if(each.getDaysRented()&gt;3)<BR>　　thisAmount += (each.getDaysRented()-3)*1.5;<BR>　　break;<BR>　　}<BR>　　return thisAmount;<BR>　　}<BR>　　<BR>　　2、选中amountFor()的参数each，在右键菜单中选择"重构/重命名"，在对话框中输入新的名称：aRental，选择确定，amountFor()中所有each的引用全部被替换成新的名称。用同样的办法修改amountFor()中的局部变量thisAmount为result。重构后的amountFor()代码如下：<BR>　　<BR>　　/**<BR>　　* @param aRental<BR>　　* @return<BR>　　*/<BR>　　private double amountFor(Rental aRental) {<BR>　　double result = 0;<BR>　　switch(aRental.getMovie().getPriceCode()){<BR>　　case Movie.REGULAR:<BR>　　result += 2;<BR>　　if(aRental.getDaysRented()&gt;2)<BR>　　result += (aRental.getDaysRented()-2)*1.5;<BR>　　break;<BR>　　<BR>　　case Movie.NEW_RELEASE:<BR>　　result += aRental.getDaysRented()*3;<BR>　　break;<BR>　　<BR>　　case Movie.CHILDRENS:<BR>　　result += 1.5;<BR>　　if(aRental.getDaysRented()&gt;3)<BR>　　result += (aRental.getDaysRented()-3)*1.5;<BR>　　break;<BR>　　}<BR>　　return result;<BR>　　}<BR>　　<BR>　　<B>三、重构第二步：搬移"金额计算"代码</B><BR>　　<BR>　　目的：<BR>　　<BR>　　1、 将函数amountFor()转移到Rental类中，并更名为getCharge()。<BR>　　<BR>　　2、 更新并替换所有对amountFor()的引用。<BR>　　<BR>　　重构方法：<BR>　　<BR>　　Move Method<BR>　　Change Method signatrue<BR>　　Inline Method<BR>　　Inline Temp<BR>　　<BR>　　方法：<BR>　　<BR>　　1、选中函数amountFor()的定义，在右键菜单中选择"重构/移动"，显示参数设置对话框。把新方法名改成getCharge。按下"确定"按钮，Customer Class中的amountFor()函数被移动到Rental Class中，并更名为：getCharge()。<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.10.11.0.19.5.jpg"><BR>　　同时eclipse自动在Customer的amountFor()函数中添加一行对新函数的"委托"代码：<BR>　　<BR>　　private double amountFor(Rental aRental) {<BR>　　return aRental.getCharge();<BR>　　}<BR>　　<BR>　　这行代码会产生编译错误，原因是amountFor()的private型被传递到了新的方法中：<BR>　　<BR>　　/**<BR>　　* @param this<BR>　　* @return<BR>　　*/<BR>　　private double getCharge() {<BR>　　……<BR>　　}<BR>　　<BR>　　2、继续重构！选中getCharge()方法，在右键菜单中选择"重构/更改方法特征符"，弹出参数选择对话框，把访问修饰符从private改成public。Eclipse的编译错误提示自动消失。<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.10.11.0.28.6.jpg"><BR>　　3、回到Customer类，把所有对amountFor()引用的地方替换成直接对getCharge()的引用。选中Customer类的函数amountFor(Rental aRental)，在右键菜单中选择"重构/内联"，出现参数选择对话框。<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.10.11.0.36.7.jpg"><BR>　　选择"确认"按钮，引用amountFor()的地方被替换成对getCharge()的引用。<BR>　　<BR>　　public String statement() {<BR>　　……<BR>　　double thisAmount = each.getCharge();<BR>　　……<BR>　　}<BR>　　<BR>　　4、除去临时变量thisAmount。<BR>　　<BR>　　选中变量thisAmount，在右键菜单中选择"重构/内联"，重构预览窗口如下，可见达到了重构的目的。按下"确认"按钮重构代码。<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.10.11.0.45.8.jpg"><BR>　　statement()代码：<BR>　　<BR>　　public String statement() {<BR>　　double totalAmount = 0; // 总消费金额<BR>　　int frequentRenterPoints = 0; // 常客积点<BR>　　Enumeration rentals = _rentals.elements();<BR>　　String result = "Rental Record for " + getName() + "\n";<BR>　　<BR>　　while(rentals.hasMoreElements()){<BR>　　Rental each = (Rental)rentals.nextElement(); //取得一笔租借记录<BR>　　<BR>　　// add frequent renter points(累加 常客积点)<BR>　　frequentRenterPoints ++;<BR>　　// add bouns for a two day new release rental<BR>　　if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE &amp;&amp; each.getDaysRented()&gt;1)<BR>　　frequentRenterPoints ++;<BR>　　<BR>　　// show figures for this rental(显示此笔租借数据)<BR>　　result += "\t" + each.getMovie().getTitle() + "\t" +<BR>　　String.valueOf(each.getCharge()) + "\n";<BR>　　totalAmount += each.getCharge();<BR>　　}<BR>　　<BR>　　// add footer lines（结尾打印）<BR>　　result += "Amount owed is " + String.valueOf(totalAmount) + "\n";<BR>　　result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";<BR>　　<BR>　　return result;<BR>　　}<BR>　　<BR>　　<B>四、重构第三步：提炼"常客积点计算"代码</B><BR>　　<BR>　　目的：提取"常客积点计算"代码并放在Rental类中，"常客积点计算"代码如下。<BR>　　<BR>　　public String statement() {<BR>　　……<BR>　　// add frequent renter points<BR>　　frequentRenterPoints ++;<BR>　　// add bouns for a two day new release rental<BR>　　if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE &amp;&amp; each.getDaysRented()&gt;1)<BR>　　frequentRenterPoints ++;<BR>　　……<BR>　　}<BR>　　<BR>　　重构后的代码如下：<BR>　　<BR>　　frequentRenterPoints += each.getFrequentRenterPoints();<BR>　　<BR>　　重构方法：<BR>　　<BR>　　Extract Method<BR>　　Move Method<BR>　　Change Method signatrue<BR>　　Inline Method<BR>　　<BR>　　方法：<BR>　　<BR>　　1、 首先，抽取代码到独立的函数中。<BR>　　<BR>　　用"抽取方法"重构代码，函数名：getFrequentRenterPoints。很遗憾，eclipse的不能生成诸如：frequentRenterPoints += getFrequentRenterPoints(Rental aRental); 的代码。原因是执行自增操作的局部变量frequentRenterPoints要出现在等式右边，因此抽取函数getFrequentRenterPoints()一定要把frequentRenterPoints作为参数。手工修改函数和对函数的引用，重构后的代码如下：<BR>　　<BR>　　public String statement() {<BR>　　……<BR>　　while(rentals.hasMoreElements()){<BR>　　……<BR>　　frequentRenterPoints += getFrequentRenterPoints(each);<BR>　　……<BR>　　}<BR>　　……<BR>　　}<BR>　　<BR>　　/**<BR>　　* @param each<BR>　　* @return<BR>　　*/<BR>　　private int getFrequentRenterPoints(Rental each) {<BR>　　if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE &amp;&amp; each.getDaysRented()&gt;1)<BR>　　return 2;<BR>　　else<BR>　　return 1;<BR>　　}<BR>　　<BR>　　2、 把getFrequentRenterPoints（）移动到Rental类中。<BR>　　<BR>　　3、 对getFrequentRenterPoints（）"更改方法特征符"为public。<BR>　　<BR>　　4、 对Customer的函数getFrequentRenterPoints()执行内联操作，重构目标完成。<BR>　　<BR>　　<B>五、重构第四步：去除临时变量（totalAmount和frequentRenterPoints）</B><BR>　　<BR>　　目的：去除临时变量（totalAmount和frequentRenterPoints）<BR>　　<BR>　　方法：<BR>　　<BR>　　1、 分析totalAmount和frequentRenterPoints的定义和引用结构如下：<BR>　　<BR>　　// 声明和定义<BR>　　double totalAmount = 0;<BR>　　int frequentRenterPoints = 0;<BR>　　……<BR>　　// 在循环中修改<BR>　　while(rentals.hasMoreElements()){<BR>　　……<BR>　　frequentRenterPoints += each.getFrequentRenterPoints();<BR>　　……<BR>　　totalAmount += each.getCharge();<BR>　　……<BR>　　}<BR>　　……<BR>　　// 在循环外使用<BR>　　result += "Amount owed is " + String.valueOf(totalAmount) + "\n";<BR>　　result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";<BR>　　……<BR>　　<BR>　　上述两个变量在循环体外面定义和使用，在循环中被修改，运用Replace Temp with Query方法去除这两个临时变量是一项稍微复杂的重构。很遗憾，eclipse目前不支持这样的重构。<BR>　　<BR>　　2、手工修改代码。<BR>　　<BR>　　<B>六、重构第五步：运用多态取代与价格相关的条件逻辑</B><BR>　　<BR>　　目的：<BR>　　<BR>　　1、 把Rental类中的函数getCharge()移动到Movie类中。<BR>　　<BR>　　2、 把Rental类中的函数getFrequentRenterPoints()移动到Movie类中。<BR>　　<BR>　　重构方法：<BR>　　<BR>　　Move Method<BR>　　Inline Method<BR>　　<BR>　　方法：<BR>　　<BR>　　1、 选中Rental类中的函数getCharge()，右键菜单选中"重构/移动"，eclipse提示找不到接收者，不能移动。原因在于这行语句：<BR>　　<BR>　　switch(getMovie().getPriceCode()){//取得影片出租价格<BR>　　<BR>　　选中getMovie()，右键菜单选中"重构/内联"，确定后代码成为：<BR>　　<BR>　　switch(_movie.getPriceCode()){ //取得影片出租价格<BR>　　<BR>　　选中getCharge()，执行"重构/移动"后，函数被移动到Movie类中。然而这只是部分达成了重构目的，我们发现，移动后的代码把Rental作为参数传给了getCharge()，手工修改一下，代码变成：<BR>　　<BR>　　class Movie ……<BR>　　/**<BR>　　* @param this<BR>　　* @return<BR>　　*/<BR>　　public double getCharge(int _daysRented) {<BR>　　double result = 0;<BR>　　switch(getPriceCode()){ //取得影片出租价格<BR>　　case Movie.REGULAR: // 普通片<BR>　　result += 2;<BR>　　if(_daysRented&gt;2)<BR>　　result += (_daysRented-2)*1.5;<BR>　　break;<BR>　　<BR>　　case Movie.NEW_RELEASE: // 新片<BR>　　result += _daysRented*3;<BR>　　break;<BR>　　<BR>　　case Movie.CHILDRENS: // 儿童片<BR>　　result += 1.5;<BR>　　if(_daysRented&gt;3)<BR>　　result += (_daysRented-3)*1.5;<BR>　　break;<BR>　　}<BR>　　return result;<BR>　　}<BR>　　<BR>　　class Rental……<BR>　　/**<BR>　　* @param this<BR>　　* @return<BR>　　*/<BR>　　public double getCharge() {<BR>　　return _movie.getCharge(_daysRented);<BR>　　}<BR>　　<BR>　　2、用同样的步骤处理getFrequentRenterPoints()，重构后的代码：<BR>　　<BR>　　class Movie ……<BR>　　/**<BR>　　* @param frequentRenterPoints<BR>　　* @param this<BR>　　* @return<BR>　　*/<BR>　　public int getFrequentRenterPoints(int daysRented) {<BR>　　if((getPriceCode())==Movie.NEW_RELEASE &amp;&amp; daysRented&gt;1)<BR>　　return 2;<BR>　　else<BR>　　return 1;<BR>　　}<BR>　　class Rental……<BR>　　/**<BR>　　* @param frequentRenterPoints<BR>　　* @param this<BR>　　* @return<BR>　　*/<BR>　　public int getFrequentRenterPoints(int daysRented) {<BR>　　if((getPriceCode())==Movie.NEW_RELEASE &amp;&amp; daysRented&gt;1)<BR>　　return 2;<BR>　　else<BR>　　return 1;<BR>　　}<BR>　　<BR>　　<B>七、重构第六步：终于……我们来到继承</B><BR>　　<BR>　　目的：对switch语句引入state模式。<BR>　　<BR>　　方法：<BR>　　<BR>　　很遗憾，不得不在这里提前结束eclipse的自动重构之旅。Eclipse几乎不能做结构上的重构。也许Martin Fowler在书中呼唤的自动重构工具止于"工具辅助下的重构工作"这一理念。艺术是人类的专利，编程艺术的梦想将持续下去。<BR>　　<BR>　　感兴趣的读者可以查看手工重构的最后一步代码。将重构进行到底！<BR>　　<BR>　　附录：eclipse支持的重构方法（摘自eclipse中文帮助）<BR>　　 <IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.10.11.1.0.9.jpg"> </TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD vAlign=top height=225>
<TABLE cellSpacing=0 cellPadding=0 width=679 align=center border=0>
<TBODY>
<TR>
<TD width=687>&nbsp;</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></P><img src ="http://www.blogjava.net/qq13367612/aggbug/17837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:42 <a href="http://www.blogjava.net/qq13367612/articles/17837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Eclipse编辑中文资源文件 </title><link>http://www.blogjava.net/qq13367612/articles/17836.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:41:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17836.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17836.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17836.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17836.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17836.html</trackback:ping><description><![CDATA[既然生为中国人，就没有什么好抱怨的了，遇到编码的问题，那只有解决它了。<BR>　　<BR>　　如果经常使用Struts，并做过国际化操作的人来说，对于中文资源文件的处理应该不会感到陌生的。比如下面两个文件，一个是英文的，一个是中文的。对于英文的，一切照常；对于中文的，一般需要用JDK的native2ascii工具进行转换。<BR>　　<BR>　　application_en.properties<BR>　　# Resources for the Hello sample application<BR>　　hello.title=A first Struts program<BR>　　hello.prompt.user=Please enter a UserName<BR>　　hello.page.hello=Hello<BR>　　hello.page.wellocome=Wellcome to Blog of Javamxj<BR>　　<BR>　　application_zh_CN.properties<BR>　　# Hello实例使用的资源文件<BR>　　<BR>　　hello.title=第一个Struts应用<BR>　　hello.prompt.user=请输入用户名<BR>　　hello.page.hello=你好<BR>　　hello.page.wellocome=欢迎来到Javamxj的Blog<BR>　　<BR>　　我当前使用的Eclipse版本是3.1M6，如果使用Eclipse编辑application_zh_CN.properties文件，保存后，关闭这个文件，然后再次打开它，会发现这个文件中的中文字符都变成了？？？？。<BR>　　<BR>　　为什么会发生这种情况呢？在中文操作系统下，Eclipse中的Java类型文件的编码的默认设置是GBK，但是对Properties资源文件的编码的默认设置是ISO-8859-1。所以编辑Java文件中的中文不会出现问题，但编辑Properties资源文件中的中文会出现问题。<BR>　　<BR>　　在3.1M6版本下，我们可以直接修改Properties资源文件的默认编码了（Eclipse3.0版本好像不支持）。在Eclipse主界面下，打开 Window -&gt;Perferences -&gt;General -&gt;Editors -&gt;Context Types:<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.6.11.10.52.25.1.jpg"><BR>　　修改为GBK后，再次打开application_zh_CN.properties文件，编辑后保存，再打开时，文件中的中文字符可以正常显示了。<BR>　　<BR>　　这还不行，还必须利用native2ascii来转换一下。<BR>　　<BR>　　native2ascii-本地码-至-ASCII 码转换器<BR>　　<BR>　　将含有本地编码字符（既非 Latin1 又非 Unicode 字符）的文件转换为 Unicode 编码字符的文件。<BR>　　<BR>　　结构<BR>　　<BR>　　native2ascii [options] [inputfile [outputfile]]<BR>　　<BR>　　说明<BR>　　<BR>　　Java 编译器和其它 Java 工具只能处理含有 Latin-1 和/或 Unicode 编码（\udddd 记号）字符的文件。native2ascii 将含有其它字符编码的文件转换成含 Latin-1 和/或 Unicode 编码字符的文件。<BR>　　<BR>　　若省略 outputfile，则使用标准输出设备输出。此外，如果也省略 inputfile，则使用标准输入设备输入。<BR>　　<BR>　　选项<BR>　　<BR>　　-reverse<BR>　　<BR>　　执行相反的操作：将含 Latin-1 和/或 Unicode 编码字符的文件转换成含本地编码字符的文件：<BR>　　<BR>　　-encoding encoding_name<BR>　　<BR>　　指定转换过程使用的编码名称。缺省的编码从系统属性 file.encoding 中得到。encoding_name 字符串必须是符合要求的字符串。<BR>　　<BR>　　比如可以这样利用native2ascii：<BR>　　<BR>　　native2ascii -encoding gbk application_zh_CN.properties temp.properties<BR>　　<BR>　　这里将根据application_zh_CN.properties输出了一个临时文件temp.properties，然后把application_zh_CN.properties中的文件内容替换为这个临时文件的内容就可以了。<BR>　　<BR>　　转换后的application_zh_CN.properties<BR>　　<BR>　　# Hello\u5b9e\u4f8b\u4f7f\u7528\u7684\u8d44\u6e90\u6587\u4ef6<BR>　　<BR>　　hello.title=\u7b2c\u4e00\u4e2aStruts\u5e94\u7528<BR>　　hello.prompt.user=\u8bf7\u8f93\u5165\u7528\u6237\u540d<BR>　　hello.page.hello=\u4f60\u597d<BR>　　hello.page.wellocome=\u6b22\u8fce\u6765\u5230Javamxj\u7684Blog<BR>　　<BR>　　这样的操作对于一个或两个资源文件还行，如果多个资源文件，这样未免有些太麻烦了。你可以建立一个批处理文件（.bat）；或者建立一个Ant文件，利用其包含的native2ascii任务，也可以进行批处理。<BR>　　<BR>　　但是自从使用Eclipse后，好处多多，在Eclipse下，有这么两个插件，可以用来处理资源文件，它们使用起来各有千秋。<BR>　　<BR>　　JInto 0.8.0<BR>　　<BR>　　主页 http://www.guh-software.de/jinto.html<BR>　　<BR>　　下载 http://www.guh-software.de/jinto/de.guhsoft.jinto_0.8.0.zip<BR>　　<BR>　　文档 http://www.guh-software.de/jinto/JIntoGettingStarted.pdf （英文）<BR>　　<BR>　　仔细看看文档，它提供的功能还是很不错的。<BR>　　<BR>　　Properties Editor<BR>　　<BR>　　主页 http://propedit.sourceforge.jp/index_en.html<BR>　　<BR>　　它提供了三个版本，单独运行的版本、Eclipse版本、JBuilder版本，这里只看看Eclipse3下的版本。<BR>　　<BR>　　PropertiesEditor_EclipsePlugin_for_3.0 V4.4.0<BR>　　<BR>　　分别以links方式安装这两个插件，启动Eclipse，切换到Perferences，如图：<BR>　　<BR>　　· JInto插件<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.6.11.10.52.37.2.jpg"><BR>　　· Properties Editor插件<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.6.11.10.52.48.3.jpg"><BR>　　· 先利用Properties Editor插件编辑资源文件，选中application_zh_CN.properties，右击，选择对应的插件，如图操作：<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.6.11.10.52.59.4.jpg"><BR>　　· Properties Editor插件编辑的效果<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.6.11.10.53.12.5.jpg"><BR>　　· 然后利用JInto插件编辑资源文件：<BR>　　 <IMG src="http://www.chinaitlab.com/www/imgfiles/2005.6.11.10.53.26.6.jpg"><BR>　　对应XML文件类型，默认的编码是UTF-8,但如果在xml声明中可以指定其编码，如“&lt;?xml version="1.0" encoding="GBK"?&gt;”就指定其编码为GBK。这样，Eclipse在读取xml文件时，会首先根据其声明来设置这个文件的编码，如果在声明中没有指定其编码，那么会采用UTF-8编码来读取这个文件。所以对于xml文件，就不需要强制设置其默认的编码类型了。 <img src ="http://www.blogjava.net/qq13367612/aggbug/17836.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:41 <a href="http://www.blogjava.net/qq13367612/articles/17836.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse插件开发之添加简单的GUI元素</title><link>http://www.blogjava.net/qq13367612/articles/17835.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:35:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17835.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17835.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17835.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17835.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17835.html</trackback:ping><description><![CDATA[编写Eclipse插件的方法很简单，你只需要编写一个应用程序，并把它"添加"到Eclipse上。但是与编写音乐类似，在能够创作一部著作之前，首先必须学习大量的相关知识。<BR>　　<BR>　　本文将讨论少许几个简单的GUI元素：<BR>　　<BR>　　· 工具条按钮<BR>　　<BR>　　· 菜单项<BR>　　<BR>　　· 对话框<BR>　　<BR>　　为了使用这些元素，我们将稍微修改已有的插件，顺便编写一个可供使用的工具类。<BR>　　<BR>　　<B>扩展点（Extension Points）</B><BR>　　<BR>　　我们不能随意地向Eclipse用户界面的任何地方添加窗口小部件，只能在特殊的、指定的、有记载的位置添加。这些位置被称为扩展点（extension points）。在基本的Eclipse安装中存在数以百计可供使用的扩展点。插件自身也可以发布新的扩展点。<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.21.11.10.35.1.gif"></CENTER><BR>　　 
<CENTER>图1：扩展页</CENTER><BR>　　<BR>　　现在请点击"添加"（ADD）按钮，出现了图2所示的列表。<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.21.11.10.45.2.gif"></CENTER><BR>　　 
<CENTER>图2：新增扩展向导，扩展列表</CENTER><BR>　　<BR>　　上下滚动这个列表可以看到很多可供使用的扩展点。你可能注意到了有两种类型的扩展点：带有扩展模板的（用加号标识）和不带扩展模板的。大多数经常用到的扩展点都带有用于辅助开发扩展的模板。图2中选择的扩展点Action Set，带有一个叫做"Hello World"操作集的模板。当你选择某个模板的时候，会出现简短的描述。"下一个"页面将询问模板使用的参数。<BR>　　<BR>　　现在请关闭向导并返回到"扩展"属性页。选择"Invokatron编辑器"。在这个属性页中，你可能注意到了我们在向导中为Invokatron编辑器输入的信息。正常的扩展需要一个唯一的标识符（ID字段）、一个供显示的名称（Name字段）和它所属的扩展点（Point字段）。从模板中建立的扩展（例如Invokatron编辑器）需要更多的参数。没有模板的扩展点也需要更多的信息，但是这些信息只能在文本编辑器中输入。<BR>　　<BR>　　<B>添加工具条按钮</B><BR>　　<BR>　　现在我们已经了解了扩展点是什么，让我们来添加一个扩展吧。我们首先添加的是一个工具条按钮。这个按钮将调用我们前面建立的新的Invokatron向导。<BR>　　<BR>　　添加工具条按钮有三个步骤：<BR>　　<BR>　　1.声明一个新扩展。<BR>　　<BR>　　2.用特定的标记来扩充该声明。<BR>　　<BR>　　3.编写操作委托类<BR>　　<BR>　　1.声明一个新扩展<BR>　　<BR>　　我们已经知道怎样实现这个步骤了。简单地返回到扩展点下的plugin.xml编辑器。点击"添加"。工具条按钮在org.eclipse.ui.actionSets扩展点下面。不要使用模板，直接点击"完成"。输入下面一些内容：<BR>　　<BR>　　· Id: NewInvokatronAction<BR>　　<BR>　　· Name: New Invokatron Document Action<BR>　　<BR>　　· Point: (使用默认值：org.eclipse.ui.actionSets)<BR>　　<BR>　　返回plugin.xml属性页，Eclipse给这个文件添加了新的代码片断。<BR>　　<BR>　　2.用特定的标记来扩充该声明<BR>　　<BR>　　这个新扩展几乎毫无内容。我们在下面添加一些标记（tag）。你知道可以使用哪些标记吗？你可以右键点击"所有扩展"树中的元素，选择"新增"菜单，会得到一个列表。你也可以查看Eclipse文档。<BR>　　<BR>　　现在我们看到自己可以在＜extension＞标记内部添加一个＜actionSet＞标记。它可以包含零个或多个＜menu＞标记，后面跟着零个或多个＜action＞标记，还可以选择使用＜description＞标记。但是其中最重要的标记是＜action＞。它可以同时描述工具条按钮和菜单项。&gt;BR&gt;下面是我们将添加的工具条按钮的XML代码片断。其中的新代码是黑体的。我们在后面会剖析这段代码。<BR>　　<BR>　　＜extension id="NewInvokatronAction"<BR>　　name="New Invokatron Document Action"<BR>　　point="org.eclipse.ui.actionSets"＞<BR>　　＜actionSet id="invokatron.actionSet"<BR>　　label="Invokatron Actions"<BR>　　visible="true"＞<BR>　　＜action id="invokatron.wizard.RunWizardAction"<BR>　　toolbarPath="org.eclipse.ui.workbench.file/new.ext"<BR>　　icon="icons/InvokatronIcon16.gif"<BR>　　tooltip="Starts the New Invokatron Document Wizard."<BR>　　class="invokatron.wizard.RunWizardAction"＞<BR>　　＜/action＞<BR>　　＜/actionSet＞<BR>　　＜/extension＞<BR>　　<BR>　　所有这些操作都可以在plugin.xml编辑器中用图形化的方式来完成，但是我们查看XML以明确字段的完整文本内容。此处的＜actionSet＞标记只含有一个操作（action）。操作表现为菜单中的项或工具条中的按钮的对象。操作的属性实在太多了，你可以在在线文档中查阅。其中最有趣的一些属性是：<BR>　　<BR>　　· id：操作的唯一标识符。可以用于在运行时引用操作。<BR>　　<BR>　　· toolbarPath：放置工具条按钮的位置。<BR>　　<BR>　　· icon：工具条按钮或菜单项左侧显示的图标。它是一个与开发目录关联的16×16的GIF文件。请把 图片存放到Invokatron\icons文件夹中。这个文件夹已经被包含到二进制建立路径中，因此该图标将放入插件的文档目录中。<BR>　　<BR>　　· tooltip：当鼠标停留在工具条按钮上的时候出现的文本内容。<BR>　　<BR>　　· class：这些操作的完整的合格的类名称。<BR>　　<BR>　　<B>关于工具条路径</B><BR>　　<BR>　　工具条路径（toolbar path）指出了添加工具条按钮的位置。由于任何人都可以建立工具条，而且有时候一个按钮可以包含子选项，因此我们用分层的标识符列表来访问这个位置。下面是经常用到的工具条列表和它们的路径：<BR>　　<BR>　　· 文件： org.eclipse.ui.workbench.file 带有一些公共的分组标志（你可以添加按钮的更多的位置）：<BR>　　<BR>　　o "新建"区：new.ext<BR>　　o "保存"区：save.ext<BR>　　o "打印"区：print.ext<BR>　　o "建立"区：build.ext<BR>　　<BR>　　· 导航： org.eclipse.ui.workbench.navigate<BR>　　<BR>　　· 载入： org.eclipse.debug.ui.launchActionSet<BR>　　<BR>　　· 编辑器表示：org.eclipse.ui.edit.text.actionSet.presentation<BR>　　<BR>　　· 搜索： org.eclipse.search.searchActionSet<BR>　　<BR>　　· Java元素建立：org.eclipse.jdt.ui.JavaElementCreationActionSet<BR>　　<BR>　　· 组： Team<BR>　　<BR>　　· CVS： CVS<BR>　　<BR>　　如果你提供的工具条ID不带有标志ID，你的按钮就会被添加到紧挨着这个工具条的一个新工具条之上。接着这个新工具条就可以被添加到Eclipse GUI上了。有时候你会看到使用工具条路径"正常的（Normal）"的插件。这是旧的名称转换。在Eclipse 3中这样使用的时候会建立一个叫作"Normal"的新工具条。如果你建立一个新工具条ID，你的工具条会被添加到"文件"工具条后面。<BR>　　<BR>　　请注意"文件"工具条的"新建"组标志。这是我们添加自己的按钮的地方。由于标志ID是new.ext，完整的路径就是：<BR>　　<BR>　　org.eclipse.ui.workbench.file/new.ext<BR>　　<BR>　　3.编写操作委托类<BR>　　<BR>　　最后一步是编写少量的用于实现操作的Java。这个类称为操作委托。<BR>　　<BR>　　package invokatron.wizard;<BR>　　<BR>　　public class RunWizardAction extends Action<BR>　　implements IWorkbenchWindowActionDelegate {<BR>　　/** 操作被建立的时候调用*/<BR>　　public void init(IWorkbenchWindow window) {}<BR>　　<BR>　　/** 操作被删除的时候调用*/<BR>　　public void dispose() {}<BR>　　<BR>　　/** 操作被执行的时候调用 */<BR>　　public void run(IAction action) {<BR>　　InvokatronWizard wizard= new InvokatronWizard();<BR>　　Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();<BR>　　WizardDialog dialog= new WizardDialog(shell, wizard);<BR>　　dialog.create();<BR>　　dialog.open();<BR>　　}<BR>　　<BR>　　/** 编辑器中的对象被选中或取消选择的时候调用*/<BR>　　public void selectionChanged(IAction action, ISelection selection) {}<BR>　　}<BR>　　<BR>　　<B>添加菜单项</B><BR>　　<BR>　　你也许猜到了添加菜单项与添加工具条按钮的过程几乎相同。你也必须声明一个扩展（同种类型的）、用特定的标记（相同的标记）来扩充它，并编写操作类（相同的类）。其主要的不同点是扩展的声明。下面是菜单项的扩展XML代码（没有相应的工具条按钮）：<BR>　　<BR>　　＜extension id="NewInvokatronAction"<BR>　　name="New Invokatron Document Action"<BR>　　point="org.eclipse.ui.actionSets"＞<BR>　　＜actionSet id="invokatron.actionSet"<BR>　　label="Invokatron Actions"<BR>　　visible="true"＞<BR>　　＜action id="invokatron.wizard.RunWizardAction"<BR>　　label="New Invokatron"<BR>　　menubarPath="file/new.ext"<BR>　　icon="icons/InvokatronIcon16.gif"<BR>　　tooltip="Starts the New Invokatron Document Wizard."<BR>　　class="invokatron.wizard.RunWizardAction"＞<BR>　　＜/action＞<BR>　　＜/actionSet＞<BR>　　＜/extension＞<BR>　　<BR>　　标签（label）属性包含了显示在菜单项上的文本内容。键盘快捷键用"&amp;"符号表示，在XML中是&amp;。下面是一个组合了菜单项和工具条按钮的例子：<BR>　　<BR>　　＜extension id="NewInvokatronAction"<BR>　　name="New Invokatron Document Action"<BR>　　point="org.eclipse.ui.actionSets"＞<BR>　　＜actionSet id="invokatron.actionSet"<BR>　　label="Invokatron Actions"<BR>　　visible="true"＞<BR>　　＜action id="invokatron.wizard.RunWizardAction"<BR>　　label="New Invokatron"<BR>　　menubarPath="file/new.ext"<BR>　　toolbarPath="org.eclipse.ui.workbench.file/new.ext"<BR>　　icon="icons/invokatronPicture.gif"<BR>　　tooltip="Starts the New Invokatron Document Wizard."<BR>　　class="invokatron.wizard.RunWizardAction"＞<BR>　　＜/action＞<BR>　　＜/actionSet＞<BR>　　＜/extension＞<BR>　　<BR>　　菜单与工具条只有稍微的不同。工具条只有一个"层次"，而菜单有完整的层次。这也是用操作来声明菜单这种方法可行的原因。菜单都列举在＜actionSet＞标记之中，在＜action＞标记之上。它们的语法如下：<BR>　　<BR>　　＜menu id="unique.ID"<BR>　　＜!-- New menu at the top-level. The menubarPath<BR>　　for actions inside this menu is: Special --＞<BR>　　path="Special"<BR>　　label="This is a parent menu item."＞<BR>　　＜!-- Optional, the menubarPath for actions after<BR>　　this separator is: Special/BelowBar --＞<BR>　　＜separator name="BelowBar"＞<BR>　　＜/menu＞<BR>　　<BR>　　<B>关于菜单条路径</B><BR>　　<BR>　　菜单条路径（menubar path）指出了添加菜单项的位置。我们使用分层的标识符列表来访问这个位置。下面是经常使用的菜单条列表以及它们的路径和公共组标志：<BR>　　<BR>　　· 文件：file<BR>　　<BR>　　o "开始" 区：fileStart<BR>　　<BR>　　o "新建"菜单内部的"附加"组标志： new/additions<BR>　　<BR>　　o "新建"区，在"新建"菜单下面：new.ext<BR>　　<BR>　　o "关闭" 区：close.ext<BR>　　<BR>　　o "保存" 区：save.ext<BR>　　<BR>　　o "打印" 区：print.ext<BR>　　<BR>　　o "打开" 区：open.ext<BR>　　<BR>　　o "导入" 区：import.ext<BR>　　<BR>　　o "附加" 区：additions<BR>　　<BR>　　o "最近的文档" 区：mru<BR>　　<BR>　　o "结束" 区：fileEnd<BR>　　<BR>　　· 编辑： edit<BR>　　<BR>　　o "开始" 区：editStart<BR>　　<BR>　　o "撤销" 区：undo.ext<BR>　　<BR>　　o "剪切" 区：cut.ext<BR>　　<BR>　　o "查找" 区：find.ext<BR>　　<BR>　　o "添加" 区：add.ext<BR>　　<BR>　　o "结束" 区（有时不是结束）：fileEnd<BR>　　<BR>　　o "附加" 区：additions<BR>　　<BR>　　· 源： org.eclipse.jdt.ui.source.menu<BR>　　<BR>　　· 重构： org.eclipse.jdt.ui.refactoring.menu<BR>　　<BR>　　· 导航： navigate<BR>　　<BR>　　o "开始"区：navStart<BR>　　<BR>　　o "Go To"菜单中的"附加"组标志： goTo/additions<BR>　　<BR>　　o "打开"区（有四个）：open.ext, open.ext2, open.ext3, and open.ext4<BR>　　<BR>　　o "显示"区（有四个）：show.ext, show.ext2, show.ext3, and show.ext4<BR>　　<BR>　　o "附加"区：additions<BR>　　<BR>　　o "结束"区：navEnd<BR>　　<BR>　　· 搜索： org.eclipse.search.menu<BR>　　<BR>　　· 项目： project<BR>　　<BR>　　o "开始"区：projStart<BR>　　<BR>　　o "打开"区：open.ext<BR>　　<BR>　　o "建立"区：build.ext<BR>　　<BR>　　o "附加"区：additions<BR>　　<BR>　　o "结束"区：projEnd<BR>　　<BR>　　· 载入： launch<BR>　　<BR>　　· 运行： org.eclipse.ui.run<BR>　　<BR>　　· "附加"组标志：additions<BR>　　<BR>　　· 窗口： window<BR>　　<BR>　　o "附加"区：additions<BR>　　<BR>　　o "结束"区：additionsend<BR>　　<BR>　　· 帮助： help<BR>　　<BR>　　o "开始"区：helpStart<BR>　　<BR>　　o "主要组"区：group.main.ext<BR>　　<BR>　　o "教程组"区：group.tutorials<BR>　　<BR>　　o "工具组"区：group.tools<BR>　　<BR>　　o "更新组"区：group.updates<BR>　　<BR>　　o "结束"区（有时候不是结束）： helpEnd<BR>　　<BR>　　o "附加"区：additions<BR>　　<BR>　　o "关于组"区：group.about.ext<BR>　　<BR>　　如果你提供的菜单条ID不带有标志ID，那么你的菜单项将出现在这个菜单条的后面。如果你建立了一个新菜单条ID，你的菜单条就被添加到"项目"和"运行"菜单之间。<BR>　　<BR>　　Eclipse开发者提示：请让工具条和菜单条ID、标志位置保持一致性。<BR>　　<BR>　　请注意"文件"菜单的"新建"组标志。这是我们添加自己的菜单的位置。由于它的标志ID是new.ext，所以完整的路径是：file/new.ext<BR>　　<BR>　　<B>结果</B><BR>　　<BR>　　操作集合中还有其它一些特性可供使用，包括快捷键、状态按钮、浮动图标、帮助内容和窗体工具条等等。操作集合只是记载的数十个扩展点中的一种类型的扩展。因此我们看到的只是冰山一角。但是至少它使我们理解了扩展点是如何工作的。我们看到的这些过程都是很好的。<BR>　　<BR>　　在讲解向导自定义之前，我们看一下图3所显示的新工具条按钮和菜单项：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.21.11.10.55.3.gif"></CENTER><BR>　　 
<CENTER>图3：新的菜单项和工具条按钮</CENTER><BR>　　<BR>　　<B>标准对话框</B><BR>　　<BR>　　Eclipse提供了所有的标准对话框和建立自定义对话框的简单途径。大多数标准对话框都是由org.eclipse.jface.dialogs.MessageDialog类提供的。这个类含有很多用于建立标准对话框的静态方法。下面表格列举了我们可以使用的标准对话框。<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.21.11.11.4.4.gif"></CENTER><BR>　　有人可能认为使用标准对话框的时候，JOptionPane类比MessageDialog提供了更大的灵活性。但是归根结底，在MessageDialog的构造函数和自定义对话框的帮助下，你几乎可以实现所有的事务。MessageDialog中缺少而JOptionPane拥有的唯一的特性是在HTML中直接进行消息格式化。但是使用自定义对话框的时候是可以实现这种功能的。<BR>　　<BR>　　<B>对话框辅助类</B><BR>　　<BR>　　现在我们知道了可供选择的类型了，让我们来建立Invokatron需要的对话框吧。有两个地方需要对话框：<BR>　　<BR>　　· 代码生成过程的确认信息，是否覆盖前面的代码。<BR>　　<BR>　　· 输入一个值的对话框（与JOptionPane.showInputDialog()类似）。<BR>　　<BR>　　这个类中的第一个方法是用于确认代码覆盖的：<BR>　　<BR>　　public static boolean openOverwriteDialog(Shell parent) {<BR>　　return MessageDialog.openConfirm(parent,<BR>　　"Confirmation",<BR>　　"You are about to overwrite your class. " +<BR>　　"Are you sure you want to continue?");<BR>　　}<BR>　　<BR>　　上面的代码非常简单，我们仅仅建立了一个常规的确认对话框。输入对话框有点麻烦：MessageDialog没有输入字段。我们只能建立一个新对话框类，可以是Dialog的子类。我们也可以建立MessageDialog的子类并重载它的createCustomArea()方法，添加输入字段。但是我们还有更简单的方法。<BR>　　<BR>　　我们将使用InputDialog类：<BR>　　<BR>　　public static String openInputDialog(<BR>　　Shell parent,<BR>　　String title,<BR>　　String question,<BR>　　String initialValue) {<BR>　　<BR>　　InputDialog dlg = new InputDialog(<BR>　　parent,<BR>　　title,<BR>　　question,<BR>　　initialValue,<BR>　　null); //这是一个可供选择的有效的类<BR>　　dlg.open();<BR>　　<BR>　　if(dlg.getReturnCode()!=Window.OK) //点击"确认"了吗？<BR>　　return null;<BR>　　<BR>　　return dlg.getValue();<BR>　　}<BR>　　<BR>　　我们的对话框辅助类完成了。你可以在图4中看到这些对话框。<BR>　　 
<CENTER><IMG src="http://www.chinaitlab.com/www/imgfiles/2005.5.21.11.11.13.5.gif"></CENTER><BR>　　 
<CENTER>图4：对话框</CENTER><BR>　　<BR>　　<B>Eclipse交响乐</B><BR>　　<BR>　　Eclipse与音乐类似；一旦你学会了如何使用那些可供使用的乐器，你就能编写自己的交响乐了。在本文中我们简短地了解了两类工具：扩展点和对话框。 <img src ="http://www.blogjava.net/qq13367612/aggbug/17835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:35 <a href="http://www.blogjava.net/qq13367612/articles/17835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse快速上手指南之使用ANT</title><link>http://www.blogjava.net/qq13367612/articles/17821.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:32:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17821.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17821.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17821.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17821.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17821.html</trackback:ping><description><![CDATA[Ant是Java平台下非常棒的批处理命令执行程序，能非常方便地自动完成编译，测试，打包，部署等等一系列任务，大大提高开发效率。如果你现在还没有开始使用Ant，那就要赶快开始学习使用，使自己的开发水平上一个新台阶。<BR>　　<BR>　　Eclipse中已经集成了Ant，我们可以直接在Eclipse中运行Ant。<BR>　　<BR>　　以前面建立的Hello工程为例，创建以下目录结构：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2004.12.8.10.47.38.1.gif"></CENTER><BR>　　新建一个build.xml，放在工程根目录下。build.xml定义了Ant要执行的批处理命令。虽然Ant也可以使用其它文件名，但是遵循标准能更使开发更规范，同时易于与别人交流。<BR>　　<BR>　　通常，src存放Java源文件，classes存放编译后的class文件，lib存放编译和运行用到的所有jar文件，web存放JSP等web文件，dist存放打包后的jar文件，doc存放API文档。<BR>　　<BR>　　然后在根目录下创建build.xml文件，输入以下内容：<BR>　　<BR>　　＜?xml version="1.0"?＞<BR>　　＜project name="Hello world" default="doc"＞<BR>　　<BR>　　＜!-- properies --＞<BR>　　＜property name="src.dir" value="src" /＞<BR>　　＜property name="report.dir" value="report" /＞<BR>　　＜property name="classes.dir" value="classes" /＞<BR>　　＜property name="lib.dir" value="lib" /＞<BR>　　＜property name="dist.dir" value="dist" /＞<BR>　　＜property name="doc.dir" value="doc"/＞<BR>　　<BR>　　＜!-- 定义classpath --＞<BR>　　＜path id="master-classpath"＞<BR>　　＜fileset file="${lib.dir}/*.jar" /＞<BR>　　＜pathelement path="${classes.dir}"/＞<BR>　　＜/path＞<BR>　　<BR>　　＜!-- 初始化任务 --＞<BR>　　＜target name="init"＞<BR>　　＜/target＞<BR>　　<BR>　　＜!-- 编译 --＞<BR>　　＜target name="compile" depends="init" description="compile the source files"＞<BR>　　＜mkdir dir="${classes.dir}"/＞<BR>　　＜javac srcdir="${src.dir}" destdir="${classes.dir}" target="1.4"＞<BR>　　＜classpath refid="master-classpath"/＞<BR>　　＜/javac＞<BR>　　＜/target＞<BR>　　<BR>　　＜!-- 测试 --＞<BR>　　＜target name="test" depends="compile" description="run junit test"＞<BR>　　＜mkdir dir="${report.dir}"/＞<BR>　　＜junit printsummary="on"<BR>　　haltonfailure="false"<BR>　　failureproperty="tests.failed"<BR>　　showoutput="true"＞<BR>　　＜classpath refid="master-classpath" /＞<BR>　　＜formatter type="plain"/＞<BR>　　＜batchtest todir="${report.dir}"＞<BR>　　＜fileset dir="${classes.dir}"＞<BR>　　＜include name="**/*Test.*"/＞<BR>　　＜/fileset＞<BR>　　＜/batchtest＞<BR>　　＜/junit＞<BR>　　＜fail if="tests.failed"＞<BR>　　***********************************************************<BR>　　**** One or more tests failed! Check the output ... ****<BR>　　***********************************************************<BR>　　＜/fail＞<BR>　　＜/target＞<BR>　　<BR>　　＜!-- 打包成jar --＞<BR>　　＜target name="pack" depends="test" description="make .jar file"＞<BR>　　＜mkdir dir="${dist.dir}" /＞<BR>　　＜jar destfile="${dist.dir}/hello.jar" basedir="${classes.dir}"＞<BR>　　＜exclude name="**/*Test.*" /＞<BR>　　＜exclude name="**/Test*.*" /＞<BR>　　＜/jar＞<BR>　　＜/target＞<BR>　　<BR>　　＜!-- 输出api文档 --＞<BR>　　＜target name="doc" depends="pack" description="create api doc"＞<BR>　　＜mkdir dir="${doc.dir}" /＞<BR>　　＜javadoc destdir="${doc.dir}"<BR>　　author="true"<BR>　　version="true"<BR>　　use="true"<BR>　　windowtitle="Test API"＞<BR>　　＜packageset dir="${src.dir}" defaultexcludes="yes"＞<BR>　　＜include name="example/**" /＞<BR>　　＜/packageset＞<BR>　　＜doctitle＞＜![CDATA[＜h1＞Hello, test＜/h1＞]]＞＜/doctitle＞<BR>　　＜bottom＞＜![CDATA[＜i＞All Rights Reserved.＜/i＞]]＞＜/bottom＞<BR>　　＜tag name="todo" scope="all" description="To do:" /＞<BR>　　＜/javadoc＞<BR>　　＜/target＞<BR>　　＜/project＞<BR>　　<BR>　　以上xml依次定义了init（初始化），compile（编译），test（测试），doc（生成文档），pack（打包）任务，可以作为模板。<BR>　　<BR>　　选中Hello工程，然后选择“Project”，“Properties”，“Builders”，“New…”，选择“Ant Build”：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2004.12.8.10.48.21.2.gif"></CENTER><BR>　　填入Name：Ant_Builder；Buildfile：build.xml；Base Directory：${workspace_loc:/Hello}（按“Browse Workspace”选择工程根目录），由于用到了junit.jar包，搜索Eclipse目录，找到junit.jar，把它复制到Hello/lib目录下，并添加到Ant的Classpath中：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2004.12.8.10.48.49.3.gif"></CENTER><BR>　　然后在Builder面板中钩上Ant_Build，去掉Java Builder：<BR>　　 
<CENTER><IMG src="http://www.chinaitlab.com/www/imgfiles/2004.12.8.10.49.31.4.gif"></CENTER><BR>　　再次编译，即可在控制台看到Ant的输出：<BR>　　<BR>　　Buildfile: F:\eclipse-projects\Hello\build.xml<BR>　　<BR>　　init:<BR>　　<BR>　　compile:<BR>　　[mkdir] Created dir: F:\eclipse-projects\Hello\classes<BR>　　[javac] Compiling 2 source files to F:\eclipse-projects\Hello\classes<BR>　　<BR>　　test:<BR>　　[mkdir] Created dir: F:\eclipse-projects\Hello\report<BR>　　[junit] Running example.HelloTest<BR>　　[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.02 sec<BR>　　<BR>　　pack:<BR>　　[mkdir] Created dir: F:\eclipse-projects\Hello\dist<BR>　　[jar] Building jar: F:\eclipse-projects\Hello\dist\hello.jar<BR>　　<BR>　　doc:<BR>　　[mkdir] Created dir: F:\eclipse-projects\Hello\doc<BR>　　[javadoc] Generating Javadoc<BR>　　[javadoc] Javadoc execution<BR>　　[javadoc] Loading source files for package example...<BR>　　[javadoc] Constructing Javadoc information...<BR>　　[javadoc] Standard Doclet version 1.4.2_04<BR>　　[javadoc] Building tree for all the packages and classes...<BR>　　[javadoc] Building index for all the packages and classes...<BR>　　[javadoc] Building index for all classes...<BR>　　[javadoc] Generating F:\eclipse-projects\Hello\doc\stylesheet.css...<BR>　　[javadoc] Note: Custom tags that could override future standard tags: @todo. To avoid potential overrides, use at least one period character (.) in custom tag names.<BR>　　[javadoc] Note: Custom tags that were not seen: @todo<BR>　　BUILD SUCCESSFUL<BR>　　Total time: 11 seconds<BR>　　<BR>　　Ant依次执行初始化，编译，测试，打包，生成API文档一系列任务，极大地提高了开发效率。将来开发J2EE项目时，还可加入部署等任务。并且，即使脱离了Eclipse环境，只要正确安装了Ant，配置好环境变量ANT_HOME=＜Ant解压目录＞，Path=…;%ANT_HOME%\bin，在命令行提示符下切换到Hello目录，简单地键入ant即可。 <img src ="http://www.blogjava.net/qq13367612/aggbug/17821.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:32 <a href="http://www.blogjava.net/qq13367612/articles/17821.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Eclipse中如何利用Maven </title><link>http://www.blogjava.net/qq13367612/articles/17819.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:20:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17819.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17819.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17819.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17819.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17819.html</trackback:ping><description><![CDATA[Maven 将作为一个普通的构建系统，被人们重新认识，并且它将超越 Java技术。本文不打算成为一篇 Maven 教程，而是将 Maven 与其他技术进行比较，让您洞察 Maven 与 Eclipse 相适应的地方，以及如何使这些工具相互协作。<BR>　　<BR>　　在过去几年中，Maven 已经不仅仅是 Java 世界的一个时髦话题。自 2001 年起，Maven 已经成为构建工具领域的先驱。最近几年，人们常拿它与 Ant 比较。因为 Maven 与 Ant 有一些显而易见的相似之处，所以拿它们俩作比较似乎是很自然的事。<BR>　　<BR>　　比如说，在两种情况下，XML 脚本都是可用的；两种工具都可以生产工件；它们还可以共享相同的分类法和概念，比如 项目（project）、目标（target）与 目标（goal），以及 依赖关系（depends） 和 先决条件（prereqs）。但它们实质上有很大的差别。<BR>　　<BR>　　Ant 只是一个 XML 脚本工具，而 Maven 是一个普通的构建工具，它关注的重点是一个叫做项目对象模型（POM）的概念。POM 暴露的是粗粒度的、面向构建的任务，这些任务被称为目标，它们提供了一些准则，帮助您开发构建方法和实现最佳实践。<BR>　　<BR>　　在某些方面，Maven 属于软件工厂尽管目前它仍在外围。更确切地说，诸如 Maven 之类的构建工具是软件工厂领域中必不可少的。<BR>　　<BR>　　<B>软件工厂</B><BR>　　<BR>　　通过显著提高自动开发的级别，软件工厂提供了一个花费更少、更灵活的应用程序开发方法。根据 Software Factories Web 站点的说法，“软件工厂是一个软件产品线，它根据构建特殊种类的应用程序的方法，配置一些可扩展的开发工具……提供打包的内容……以及指导”。<BR>　　<BR>　　<B>软件工厂涉及三个主要概念：</B><BR>　　<BR>　　模式，提供了一些元数据，描述组成应用程序的不同工件的结构，以及它们是如何交互的。 一个或多个模板，提供了启动程序工具箱，以及构建应用程序所需的其他任何东西。 可扩展的开发环境，用于配置、定制和装配组件。<BR>　　<BR>　　如今，这类工具已经逐渐引起了认识到它们的价值的那些工具制造人员、工具开发人员和软件编辑的注意。这些工具促进了软件开发过程的工业化，降低了投入市场的成本和时间，同时还提高了生产率，加快了对进化需求的反应。<BR>　　<BR>　　仔细查看一下 Maven 的主要特性，您就会认识到 Maven 与软件工厂之间的相似之处：Maven 使用 POM 作为元数据来描述项目结构，并通过通用应用程序插件来获得可扩展的项目模板。<BR>　　<BR>　　因为 Maven 非常灵活并且是开放源码的，所以很容易推断和设想 Maven 是软件工厂平台中的一个核心组件。但是，还有另一种说法。上述类比并不完全，因为目前的 Maven 缺乏专用的开发环境，而这类环境有助于创建特定于域或特定于企业的插件和模板，并允许您轻松地配置项目或定制行为。<BR>　　<BR>　　不过，Maven 的主要目标是标准化构建过程，并保证代码构建-测试-部署（CBTD）循环中的质量和易再现性（easy reproducibility）。它还可以制定度量标准，帮助您了解开发状态。<BR>　　<BR>　　CBTD 本体论在软件工程领域已经不再新鲜，但 Maven 可以使您标准化这种本体论，并通过抽象这种理论，将它想像成一个完整的实体。考虑到不断增长的项目的复杂性，标准化成为一种迫切需要。<BR>　　<BR>　　扩建的概念，我们称之为元构建，因为其无可估量的价值以及保证下一级质量的特性，正逐渐被人们认识。持续集成（continuous integration）就是建立在这个概念的基础之上，但它也应用了在 IDE 上下文之外的地方进行构建的能力。<BR>　　<BR>　　<B>模糊的界限</B><BR>　　<BR>　　使用过 Java 技术的人应该都听说过 Eclipse。2001 年年中的时候，Eclipse 推出了它的第一个版本，标志其成熟的是它为集成开发环境（IDE）提供了一个机会，特别是为 Java 开发人员（不严谨地说）提供了一个机会。<BR>　　<BR>　　Eclipse 是一种开放的、以语言为中心的平台，也可以将它用作教育性项目和研究项目的基础平台，其中一些平台捐赠给了 Eclipse 团体。<BR>　　<BR>　　就像 Microsoft已经采用软件工厂方法一样，Eclipse 也开始转向模型驱动开发（MDD）方向，并且最近已经公布了一个新的项目提议 —— 模型驱动的开发集成（MDDi）。<BR>　　<BR>　　根据该提议，“Eclipse MDDi 项目专用于平台的实现……其设计目标是支持各种建模语言（统一建模语言或特定于域的语言）和模型驱动的技术。”<BR>　　<BR>　　渐渐地，一些工具开始假定某些特性可以完全并且顺利地集成在一起，Maven 和 Eclipse（即使作为一个简单的 IDE）也不例外。因此，从构建的角度来看，二者似乎出现了重叠，如图 1 所示。<BR>　　 
<CENTER><IMG src="http://www.chinaitlab.com/www/imgfiles/2005.8.13.11.50.32.42.1.gif"></CENTER><BR>　　 
<CENTER>图 1. 扩建的概念</CENTER><BR>　　<BR>　　图1描述的实际上是以前讨论的扩建概念。正如以前定义的那样，整个扩建过程包括几个任务，同时还表示了一个元构建实例。任务可以是以下两种类型之一：原子任务是细粒度的，并且是上下文不明确的，这种任务的两个实例几乎是相同的；宏观任务是复合任务，它充当微观任务的容器。<BR>　　<BR>　　构建，从扩展的意义上说，只处理宏观任务；原子任务的触发取决于配置。这意味着用户对系统有着较高层次的看法，这使得系统更易于维护和发展。<BR>　　<BR>　　此外，Maven 和 Eclipse 都是开放的，并且很容易通过插件扩展它们，使其满足您的需要。但是，因为它们针对的受众不同，所以它们之间的相似性也到此为止：多数 Eclipse 最终用户是一些开发人员；而 Maven 主要针对的是一些构建管理人员。<BR>　　<BR>　　尽管如此，Maven 仍然是一个命令行工具。虽然图形用户界面（GUI）是按照 Jason Van Zyl（Maven 的制造者和架构师）指示的方向开发的，但 Maven 目前仍然没有帮助用户执行特殊任务的特定 GUI，比如创建或更新配置，或者只用一个鼠标单击发起构建。<BR>　　<BR>　　上面描述的典型构建顺序在 Eclipse 中不像在 Maven 中那么顺利。Eclipse 的特性之一是开发 环境造成构建过程不连续，这要归因于一些人为因素：并不是每次成功编译之后都进行测试、所有测试没必要一次运行、可以跳过一些微观任务，等等。<BR>　　<BR>　　各种因素都会导致产生差异，这就是为什么开发人员每天至少必须运行一次完整的构建过程，以确信他们没有破坏什么的原因。<BR>　　<BR>　　不过，因为 Eclipse 是一个可扩展平台，所以它受到许多用户社区的支持，这使它成为驻留 Maven 驱动的开发、允许开发人员和构建管理人员以某种简单的方式进行协作的理想之地。<BR>　　<BR>　　将 Maven 集成到 Eclipse 中 Mevenide 是 Codehaus 主办的一个项目，旨在通过将 Maven 集成到 IDE 中，简化 Maven 的使用。<BR>　　<BR>　　现在，Borland Software 的 JBuilder、NetBeans 和 Eclipse 都受到支持。其他一些项目也部分地将 Maven 集成到 Eclipse 中，这样，就可以与 Mevenide（如 Maven Workshop）共享一些特性。除了增加 Maven 的易用性之外，为什么需要这种插件？<BR>　　<BR>　　通过提供一些工具和视图，让您了解 Maven 隐藏的复杂性并改进团队环境中的协作，Mevenide for Eclipse 提高了生产率。<BR>　　<BR>　　从协作的角度来看，假如构建已经被 Maven 化了，那么最有用的特性就是 Eclipse 项目元数据与 Maven 元数据之间的双向同步。如果开发人员忘记在向 Eclipse 中添加一个依赖关系之后更新 POM，那么该怎么办？<BR>　　<BR>　　如果重构无法传播到 Maven，该怎么办？构建可能会中断，或者一些单元测试可能被拒绝，因此，真的需要使 Eclipse 元数据和 Maven 元数据保持同步。Mevenide 监听元数据的变化，并使您能够很容易地确定元数据不匹配的地方，这可以防止进行被严重破坏的构建。<BR>　　<BR>　　但 POM 并不只是关于依赖关系和项目布局的。它还包含一些不用于结构上的项目管理信息，比如版本号、名称、ID 和源储存库的位置。Eclipse 元数据并不总是反映所有这些信息。<BR>　　<BR>　　因此，需要另一个编辑这些信息的方法。为此，Mevenide 提供了一个图形编辑器，该编辑器使 POM 的维护变得更容易，并允许您避开一些烦琐的、容易出错的原始 XML 手工编辑。每个 POM 语义部分都被表示为一个编辑器页，这增强了模型的整体可靠性。<BR>　　<BR>　　此外，为了最大限度地减少创建 POM 的无聊过程，Mevenide 提供了一个相当简单的、可扩展的 POM 模板机制。<BR>　　<BR>　　阻止 Maven 在 Eclipse 之外的地方运行的能力是从类似 Mevenide 的插件中最容易获得的一项功能。您可以选择某些执行任务（用 Maven 的术语来讲是 目标），这些任务可以是通过 Maven 插件全局定义的任务，也可以是依赖于项目的任务，或者，您可以通过定义构建敏感的变量来定制构建。<BR>　　<BR>　　Eclipse 控制台上只显示了一些相关的选项（即在 IDE 的上下文中相关），对于其他任何插件，控制台上只输出构建日志。这一特性非常重要，因为它避免了在控制台与 Eclipse 之间不停地来回奔波。<BR>　　<BR>　　Mevenide 还集成了其他许多帮助方法特性，但它们不是很重要。例如，您可以定义给定目标与文件模式之间的关系，这样，就可以根据工作空间增加的增量来激活那些任务。<BR>　　<BR>　　您还可以浏览工件储存库，或者根据名称搜索某个给定的工件（一个工件 就是一个构建结果，它可以是 JAR 文件、可执行文件或者是一个完整的 Web 站点）。然后，可以重定向到 Mevenide 站点，获得完整的特性列表。<BR>　　<BR>　　不过，仍然还有一个问题：即使 Mevenide 增强了生产率和易用性，但您仍然必须认识到哪些工具可以在特殊环境中满足您的需要。通过 Maven Console 运行 Maven 会话可能非常耗时，所以，为了获得较高的生产率，在对会话进行编码期间，应该改为使用 JUnit 集成的 Eclipse 支持来运行测试，并依赖于 Eclipse 的内部编译器来生成可执行的文件。<BR>　　<BR>　　但在向源代码储存库提交任何东西之前，应该确保 POM 是同步的，并回滚所有不需要的 .classpath 或 .project 修改 —— 也就是说，假设这些文件都是在源代码控制之下，这可能是有争议的。这个话题在 Martin Van den Bemt 的 blog 中讨论过。<BR>　　<BR>　　<B>结束语</B><BR>　　<BR>　　尽管 Maven 和 Eclipse 具有不同的特性，但从构建的角度看，它们在某些地方可能出现重叠。它们之间存在的对立似乎也相当多，但我们很容易克服这些，通过努力最终使它们相互协作，共创一片沃土。<BR>　　<BR>　　诸如 Mevenide 之类的工具可以使 Maven 和 Eclipse 顺利合作，并使它们保持同步，但您必须认识到，在某一个给定的开发阶段，哪种工具最能满足您的需要。<BR>　　<BR>　　尽管 Maven 作为质量保证过程中的一个重要因素，正逐渐被人们所认可，但在将它集成到开发环境（尤其是 Eclipse）中，使 Maven 成为一等 IDE 公民这一点上，还有待提高。<BR>　　<BR>　　到那时，我们就可以考虑其他的 Maven 用例，比如说，更进一步地将它集成到全局开发过程中，以及像 Eclipse 这样的可扩展环境如何帮助实现这些集成。 <img src ="http://www.blogjava.net/qq13367612/aggbug/17819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:20 <a href="http://www.blogjava.net/qq13367612/articles/17819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>测试实践：Eclipse 之 JUnit</title><link>http://www.blogjava.net/qq13367612/articles/17818.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17818.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17818.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17818.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17818.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17818.html</trackback:ping><description><![CDATA[这篇文章将给你介绍JUnit——一个工程测试调式的工具。 在介绍了了 测试驱动开发理论之后，我们继续介绍“怎样用Eclipse创建你的、JUnit Test”。 我们会用象"hello word"一样简单例子来向你揭露JUnit Case。<BR>　　<BR>　　自动化测试（automated testing）在好多书籍中被介绍了，但很少注意讲怎样去组织这些测试。 当测试写的越多时，很难知道把这些测试放到哪或者用什么去调用它们。 在极限编程---Extreme Programming(xp)，测试驱动开发 Test-Driven Development (TDD)盛行的时代，这成了一个很大的问题。 你可以把 测试驱动开发（TDD）认为是"Development through testing" 开发由经测试。<BR>　　<BR>　　TDD的主要条款：<BR>　　<BR>　　在任何代码片段之前，必须先写好自动检测这段代码功能的程序。既然代码不存在，那么测试在一开始就失败。<BR>　　<BR>　　在 测试通过之后，复制的代码必须删掉。<BR>　　<BR>　　象这样的方式每个程序员都可以应用，并不需要特定的方法论。但在我们开始写test之前， 值得我们注意的是，先考虑一下如何组织自动化测试。<BR>　　<BR>　　这里有几种我们需要考虑的测试<BR>　　<BR>　　单元测试(Unit test) :这些是为检查个别模块（比如classes类）服务的。 如果对象需要访问外部的数据源，比如Database，就需要通过一些模拟的对象（MOCK object）来模拟Database， （但这也只有在真实环境的数据与测试环境不同的时候。<BR>　　比如测试环境里面没有真实Datebase,就需要MOCK Object）<BR>　　<BR>　　用户测试 （Customer's test）:这里是功能的，系统的并且认可的测试。系统中所有的行为检查都做为一个整体。 在XP理论中，这些测试，是由用户编写的，给出测试案例提纲。<BR>　　<BR>　　集成测试 （Itegration tests）: 这些测试象是在用户测试和单元测试之间的十字路口。 集成测试帮助程序测试几个级别中交互。 ，Mock Object不会出现在集承测试中，他会增加测试时间。同样，集成测试也经常需要存在的特定的测试环境，比如从数据库中放一些测试数据。集成测试也许使用外部的lib。 Cactus就是这样一个J2EE集成的lib。 解释这些测试已经超出了本篇文章的范围，并且也需要详细的理论叙述，所以，你仅需要知道这种测试存在就可以了。<BR>　　<BR>　　开发测试（Developer's test） : 这种测试就是那些开发者校验 整段代码，新加的代码，新加的函数函数。 对于每个开发而言， 随时生成新的的测试去检查代码是很重要的。 组织这些测试和组织这些代码有着同样的重要性。<BR>　　<BR>　　至于本文其他地方，只要说到"测试"，就是专指开发测试（Developer's test）。<BR>　　<BR>　　在开发期间， 一个程序员有时可能问自己：系统中这个行为有test么，这个test存在么，哪里可以找到这个test？每次发现错误，都是靠最基础修改bug而不是通过自动测试，这是一个典型的例子。 在这种情形下事情进展可能是：<BR>　　<BR>　　去找到这个函数的测试（可能测试已经写了，但里面还有一些小错误）<BR>　　如果这样的测试还没有，或者测试不能盖住这种错误，我们就写一个新的测试来盖住这种错误。<BR>　　现在 我们深信，程序在新的测试中不会通过。<BR>　　修复程序中的bug。<BR>　　再运行测试<BR>　　确定程序在测试中通过了。<BR>　　<BR>　　当然，可能出现各种各样的处理， 但思想必须很明确：你只需纠正那些被测试找出那些错误。<BR>　　<BR>　　现在，让我们告诉你一个开发人员怎样解决这种情形。 通过存在的功能性的测试<BR>　　<BR>　　我利用一些集成的开发环境（IDE）来查找 被修正那些类和方法的放在什么地方。<BR>　　<BR>　　制造一个已知的错误环境，来查找那些代码判断存在错误。<BR>　　<BR>　　最后但不是最不重要的，写好测试并且放到一个现有的测试类中去。 如果你不小心出了错误， 期望你和你的同事能注意到副本，并且纠正它<BR>　　<BR>　　都准就绪，开始建立测试了， 所以现在需要给测试取一个名称。 你可能说，“这不是问题: 在每个类面前加个Test就是了！” 但并不是那么简单的， 让我告诉你这样如果可能造成的问题：<BR>　　<BR>　　当时候我们在使用TDD的方式开发时， 需要测试的class或者method可能都不存在。<BR>　　<BR>　　也可能一个test 含盖了好几个方法，甚至好几个classes。<BR>　　<BR>　　这些仅仅是最普通的问题， 下面还有更多。<BR>　　<BR>　　给个在test命名上的建议: test 类的取名首先应该表达出这个类是一个test类，并且能确切的表示出他要检查哪些，留有这个原class名的味道。 其实这很容易，请别担心这个名称会变的很长或者很丑陋，自己随便怎样取都可以。<BR>　　<BR>　　下面我们将使用Eclipse中的JUnit工具建立我们的第一个测试，假定你已经下载了这个产品的当前版本， 如果没有，你随时可以从它的官方网站(www.eclipse.org)下载。我们需要JUnit,你也可以从它的官方网站（www.junit.org）上下载，下载并解压缩到你硬盘中存放java libaries的地方。<BR>　　<BR>　　打开Eclipse.我们将建立一个新的工程的工作空间（workplace project） 点 File -&gt; New -&gt;Project,选择Java一路Next。 输入工程名称（project name），比如ProjectWithJUnit. 点击完成。 这样就建立了一个新工程，让我们配置一下我们的Eclipse,于是，我们把JUnit library 添加到build path. 点击 Project--&gt;Properties, 选择Java Build Path Libraries, 点Add Exteranal JARs 选中JUnit.jar。 你将会看到JUnit将会出现在的屏幕上 libraries列表中。 点Okay,Eclipse将强制rebuild所有的build paths.<BR>　　<BR>　　我们已经准备好，开始写我们的"Hello World"了 . 让我们遵照TDD规范：在编码之前就建立测试。为了， 我们将假顶我们将要写的类名是HelloWorld 有一个返回字符串的方法 say().<BR>　　<BR>　　要建立这样一个test, 在ProjectWithJUnit标题上右键， 选择New -&gt; Other,展开"Java"， 选择JUnit. 在对话框的右边一拦里选择TestCase,接着点Next. 参见图1。<BR>　　<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2004.9.24.11.24.19.01.gif"> </CENTER><BR>　　图1。 在Eclipse 中建立JUnit test<BR>　　在Test class:一拦里输入我们需要测试的class--HelloWorld。并且给Test case取个名称--- 比如，TestThatWeGetHelloWorldPrompt(是的，这看上去太长了，但是它能很清楚表达出它的意思) 点Finish完成。<BR>　　<BR>　　下面是 TestThatWeGetHelloWorldPrompt.java的代码：<BR>　　<BR>　　public class TestThatWeGetHelloWorldPrompt<BR>　　<BR>　　extends TestCase {<BR>　　<BR>　　public TestThatWeGetHelloWorldPrompt(<BR>　　<BR>　　String name) {<BR>　　<BR>　　super(name);<BR>　　<BR>　　}<BR>　　<BR>　　public void testSay() {<BR>　　<BR>　　HelloWorld hi = new HelloWorld();<BR>　　<BR>　　assertEquals("Hello World!", hi.say());<BR>　　<BR>　　}<BR>　　<BR>　　public static void main(String[] args) {<BR>　　<BR>　　junit.textui.TestRunner.run(<BR>　　<BR>　　TestThatWeGetHelloWorldPrompt.class);<BR>　　<BR>　　}<BR>　　<BR>　　}<BR>　　<BR>　　这个代码一点都不复杂，仅仅有一点点特别。 不管怎样，让我们详细的检查它。 我们继承了JUnit的TestCase. (TestCase 在JUnit的javadoc里定义是"用来运行多个Test的固定装置")。 JUnit也定义了TestSuite 由于一组关联的TestCase组成..<BR>　　<BR>　　通过以下两步来建立我们简单的Test Case;<BR>　　<BR>　　建立Junit.framework.TestCase的实例.<BR>　　定义一些 以"test"开头的测试函数, 并且返回一空值.(比如 testWasTranscationSuccessful(),testShow()等等).<BR>　　<BR>　　TestThatWeGetHelloWorldPrompt.java 同时遵循这些标准: 这些TestCase的子类含有一个testSay()的方法. 这个方法由assertEquals()方法调用, 用于检验say()的返回值（按照这里的做法返回应该是不一致，因为一开始建立的HelloWorld 我们让say()返回的值是null）.<BR>　　<BR>　　main()主函数是用来运行test并且显示输出的结果. JUnit的TestRunnery以（swing.u）图形和本文（text.ui）的的方式来执行我们的test并反馈信息。我们就使用文本(text.ui),这个Eclipse肯定支持. （译注：这里可能翻译的不怎么好，所谓文本和图形，是指你在建立TestCase的时候，有一个选项，Which method stubs would you like to create,选择text.ui|| swing.ui||awt.ui，一般是选择text.ui因为Eclipse肯定支持这个）, 依照这些文本的信息,Eclipse同时会生成图形显示。（在Package Exploer的下面Tab条上会多个JUnit,点它就看到了:）。<BR>　　<BR>　　又一个所以,按照现在这样测试驱动的开发的做法, 一旦我们跑起了我们的test,我们应该看到返回一些错误的信息。 点Run-&gt; Run as -&gt; JUnit Test（注意啊， 这个TestThatWeGetHelloWorldPrompt.java应该在Package Explorer被点中，在左边那个window中）,你点到的因该是JUnit window（就是下面的那个Tab条，注意不是Package Exploer)，这样你就看到了JUnit window， 他会显示一个红色条，表示是一个失败的Test。 (如果你按了运行它没有自动转到这个窗口，你可以点做下Tab条 上的JUnit标签。)<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2004.9.24.11.24.31.02.gif"> </CENTER><BR>　　一按运行, 太好了，果然出错了。好，现在正式开始建立用于工作的HelloWorld代码，---点New-&gt;Class，可能和原来的的重复，那就把原来的删掉。代码如下：<BR>　　<BR>　　HelloWolrd.java<BR>　　<BR>　　public class HelloWorld {<BR>　　<BR>　　public String say() {<BR>　　<BR>　　return("Hello World!");<BR>　　<BR>　　}<BR>　　<BR>　　}<BR>　　<BR>　　这及为简单的，都用不着注释。现在再来测试一下看看结果。就用上面的方法，点Run-&gt; Run As Jnit. 在左边的JUnit窗口中出现了一个绿条。 看图三。 出现绿色的条表示测试通过了。<BR>　　<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2004.9.24.11.24.42.03.gif"> </CENTER><BR>　　现在，再变个条件,让测试不通过。 这将帮助我们理解JUnit test怎样覆盖并且报出不同的错误。 编辑 assertEquals()方法，把它的返回值从"Hello World!"变成另外一个值 比如"Hello ME!". 这样，当你再运行这个JUnit test，那个显示条又变成红的了，并且在Failuer Trace里看到是不是什么导致了错误。 如图:<BR>　　<BR>　　 
<CENTER><IMG src="http://www.chinaitlab.com/www/imgfiles/2004.9.24.11.24.53.04.gif"> </CENTER><BR>　　总结。我想说一些自己的想法(这里还是原文不是翻译过来的)。 我过去并不认为测试代码是开发过程中很重要的一部分。 但在最近几年发展的很快,多亏了那些方法论(比如基于异常开发"exceptions-based development"等),他们促进了测试以及测试工具的发展。<BR><img src ="http://www.blogjava.net/qq13367612/aggbug/17818.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:19 <a href="http://www.blogjava.net/qq13367612/articles/17818.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Eclipse开发Hibernate应用程序</title><link>http://www.blogjava.net/qq13367612/articles/17817.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:18:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17817.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17817.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17817.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17817.html</trackback:ping><description><![CDATA[Eclipse是目前非常流行的开发平台，开放扩展的架构让很多程序员找到了自己个性化的工作环境，Hibernate也是目前牛叉得不得了的框架，至少在EJB 3大行其道之前，它是我们在考虑OR映射时非常好的选择。本文主要介绍如何利用Hibernate Syn插件在Eclipse 3.0.1中快速的开发Hibernate应用程序，提高我们的工作效率。关于Hibernate框架的细节，本文不做过多的讨论，请参考相关资料，推荐《Hibernate in action》一书。<BR>　　<BR>　　首先需要安装这个插件，Eclipse 3.0.1为我们提供了更加方便的插件管理方式，选择菜单“帮助?软件更新?查找并安装”（本人的Eclipse使用了语言抱汉化，请英文界面用户自行对照），选择“搜索要安装的新功能部件”，操作界面如下：<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.3.18.10.53.37.1.jpg"><BR>　　选择“新建远程站点”，填写名称“Hibernate plugin”，下面的URL中填入：http://www.binamics.com/hibernatesync<BR>　　如下图：<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.3.18.10.53.55.2.jpg"><BR>　　然后在“安装”界面中选中我们刚添加的“Hibernate plugin”，一路Next，Eclipse就可以自己下载完成安装，然后Eclipse自动重启动一次就完成了。<BR>　　<BR>　　下面演示一个最简单的单表操作，可以让我们很快熟悉开发过程。我们选择Mysql数据库来做这个应用，首先建立一个数据表，名为user_info，包含id、name、password三个字段，建表语句如下：<BR>　　<BR>　　# Host: localhost<BR>　　# Database: test<BR>　　# Table: 'user_info'<BR>　　#<BR>　　CREATE TABLE `user_info` (<BR>　　`id` int(11) NOT NULL auto_increment,<BR>　　`name` varchar(100) NOT NULL default '',<BR>　　`password` varchar(100) NOT NULL default '',<BR>　　PRIMARY KEY (`id`)<BR>　　);<BR>　　<BR>　　然后新建一个普通的Java项目：“新建?项目?Java项目”，注意加入Hibernate的所有lib文件，以及mysql的jdbc驱动文件。下面我们需要在项目中加入一个Hibernate的配置文件，在src目录下选择“新建?其他?hibernate?hibernate configuration file”，如下图：<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.3.18.10.54.6.3.jpg"><BR>　　在弹出的界面中，你需要指定要使用的数据库，以及连接数据库所需要的信息，我们对应的选择了数据库为mysql，并配置了数据库的URL和管理员帐号，如下：<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.3.18.10.54.17.4.jpg"><BR>　　在上图中，我们还可以指定从JNDI数据源中获得连接，可以点击“Datasource“标签进行配置。<BR>　　<BR>　　“完成”之后系统会自己生成一个名为“hibernate.cfg.xml”的文件，里面包含了基本的配置信息，如果需要高级配置，可以手动添加。<BR>　　<BR>　　下面我们要生成映射文件，首先新建一个包“org.bromon.zizz.pojo”，在这个包下选择“新建?其他?hibernate?hibernate mapping file”，在弹出的界面中点击“刷新”，讲会列出库中所有的数据表，选中我们要使用的“user_info”表，以及我们要生成的pojo文件所在的包：org.bromon.zizz.pojo。如下图：<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.3.18.10.54.27.5.jpg"><BR>　　在上述界面的“Properties”标签中可以配置hbm的其他选项，包括文件扩展名，聚合列名，ID生成规则等。完成后，系统会自动生成一个名为“UserInfo.hbm”的文件，我们可以通过这个文件生成相关的存根类。在UserInfo.hbm文件上选择“Hibernate Synchronizer?Synchronize files”：<BR>　　　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.3.18.10.54.40.6.jpg"><BR>　　该操作将生成三个包八个类文件，里面封装了Hibernate的操作细节，让我们可以专心面对业务逻辑的开发，仔细阅读这些文件可以提高你对Hibernate的认识，增长应用技巧。<BR>　　<BR>　　然后我们需要在Hibernate的配置文件中添加对UserInfo的相关信息，在UserInfo.hbm上选择“Synchronizer?Add Mapping Reference”。现在我们可以开始编写自己的程序逻辑了，代码可以写在org.bromon.zizz.pojo.dao. UserInfoDAO中，这个类的代码不会被插件修改。我们首先创建一条新的记录，在该类中加入一个main方法：<BR>　　<BR>　　public static void main(String args[])<BR>　　{<BR>　　try<BR>　　{<BR>　　_RootDAO.initialize();<BR>　　UserInfoDAO uid=new UserInfoDAO();<BR>　　<BR>　　org.bromon.zizz.pojo.UserInfo ui=new org.bromon.zizz.pojo.UserInfo();<BR>　　ui.setName("bromon");<BR>　　ui.setPassword("123");<BR>　　<BR>　　uid.save(ui);<BR>　　<BR>　　}catch(Exception e)<BR>　　{<BR>　　e.printStackTrace();<BR>　　}<BR>　　}<BR>　　<BR>　　可以看出，插件已经把session操作和事务操作都封装起来了，我们的代码工作得到了极大的简化。而且我们可以利用插件自带的Hibernate editor来编辑hbm文件，非常方便，我们需要把ID的生成方式改为“identity”：<BR>　　 <IMG src="http://www.chinaitlab.com/www/imgfiles/2005.3.18.10.54.51.7.jpg"><BR>　　要让这个程序正常运行，还需要对配置文件hibernate.cfg.xml作一些修改。值得注意的是，请不要在该插件以外的环境中修改配置文件（比如使用DreamWeaver之类的工具编辑文件），否则会造成系统与资源不同步的错误，这可能是插件的一个bug。使用Eclipse的“文本编辑器”打开该文件，其中有如下的内容：<BR>　　<BR>　　＜property name="hibernate.transaction.factory_class"＞<BR>　　net.sf.hibernate.transaction.JTATransactionFactory<BR>　　＜/property＞<BR>　　＜property name="jta.UserTransaction"＞<BR>　　java:compUserTransaction<BR>　　＜/property＞<BR>　　<BR>　　由于在我们的例子中，并没有使用JTA来控制事务，所以需要将上面的内容注释掉，程序才能正常运行。<BR>　　<BR>　　OK，Run一下，可以看到数据已经被保存到数据库。<BR>　　<BR>　　如果在实际开发工作中，需要重新设计数据表结构，那么只需要在.hbm文件中做相应的修改，然后执行“Synchronize and Overwrite”的操作，插件会重新生成存根文件，我们只需要修改程序逻辑就可以了，非常方便。有了这样的功能插件，我们可以极大的从配置文件的编写、查错中解脱出来，从而提高我们的工作效率。 <img src ="http://www.blogjava.net/qq13367612/aggbug/17817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:18 <a href="http://www.blogjava.net/qq13367612/articles/17817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Myeclipse快速开发struts应用程序 </title><link>http://www.blogjava.net/qq13367612/articles/17816.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:14:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17816.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17816.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17816.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17816.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17816.html</trackback:ping><description><![CDATA[开发环境：<BR>　　jdk5.0<BR>　　eclipse3.1M7 <BR>　　myeclipse3.84<BR>　　tomcat5.0.28<BR>　　<BR>　　简介：<BR>　　文本主要介绍用myeclipse的struts designer（图形化开发环境）开发一个简单的用户登录程序片段。<BR>　　主要包括2个jsp文件、一个ActionForm、一个Action等其它<BR>　　userLogin.jsp(用户登录及错误提示页面) userLoginSuccess.jsp(提示登录成功页面)<BR>　　UserLoginForm.java(ActionForm,存放用户提交信息)<BR>　　UserLoginAction.java(Action,简单的处理用户登录事件)<BR>　　<BR>　　开始吧<BR>　　首先我们先建立一个j2ee的web project.如图1:<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.35.42.1.gif"></CENTER><BR>　　点击next,Project name输入LoginDemo,其余保持默认,点击finish.<BR>　　在package explorer下,就可以看到我们的项目了,然后给这个项目添加Struts框架必要的文件.在我们项目名上点击右键,选择MyEclipes --&gt; Add Struts Capabilities...弹出对话框图2：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.35.58.2.gif"></CENTER><BR>　　其中Struts config path就是我们的struts配置文件，URL pattern我们选择*.do，Default application resource为我们默认的资源文件地方，你可以选择它的存储位置，我们在这里保持默认。点击Finish后，项目结构类似于图3：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.36.15.3.jpg"></CENTER><BR>　　现在就来开始我们的例子吧。首先修改/WEB-INF/web.xml文件,为其添加标签库(在使用中发现，不添加也能成功。但为了保持书上一致，还是添加安全些。hoho~~)将下面代码添加至 </WEBAPP>上面：<BR>　　<BR>　　<TAGLIB><BR>　　<TAGLIB-URI>/tags/struts-html</TAGLIB-URI><BR>　　<TAGLIB-LOCATION>/WEB-INF/struts-html.tld</TAGLIB-LOCATION><BR>　　</TAGLIB><BR>　　<BR>　　<TAGLIB><BR>　　<TAGLIB-URI>/tags/struts-bean</TAGLIB-URI><BR>　　<TAGLIB-LOCATION>/WEB-INF/struts-bean.tld</TAGLIB-LOCATION><BR>　　</TAGLIB><BR>　　<BR>　　<TAGLIB><BR>　　<TAGLIB-URI>/tags/struts-logic</TAGLIB-URI><BR>　　<TAGLIB-LOCATION>/WEB-INF/struts-logic.tld</TAGLIB-LOCATION><BR>　　</TAGLIB><BR>　　完成后，打开struts-config.xml文件，点击这个界面左下角的Design进入可视化设计界面。有没有注意右边的Palette :) 点击它，让我们来开始我们的jsp页面设计。我们先建立userLoginSuccess.jsp文件，为啥先建这一个呢？等下就知道了，在myeclipse中可以一次性把我们的Action,ActionForm,Jsp文件一次建好（将三个有关联的文件等下创建）。<BR>　　点击Palette面版上的创建JSP文件图标,弹出创建JSP文件面板。图4：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.36.29.4.gif"></CENTER><BR>　　在File Name里输入userLoginSuccess.jsp，Template to use选择2] Standard JSP using Struts 1.1,点击Finish完成。<BR>　　完成后，struts-config.xml文件自动被更新，可视化界在上也出现了刚新建的JSP模块。新建的jsp文件也被打开了。<BR>　　覆盖所有的<%@ taglib ...... 为我们开始在/WEB-INF/web.xml中定义的：<BR>　　<BR>　　<%@ taglib uri="/tags/struts-html" prefix="html"%><BR>　　<%@ taglib uri="/tags/struts-bean" prefix="bean"%><BR>　　<%@ taglib uri="/tags/struts-logic" prefix="logic"%><BR>　　<BR>　　然后在中添加:<BR>　　Hello <?xml:namespace prefix = bean /><bean:write scope="request" name="userName"></bean:write>.<BR>　　这里将request中的属性userName输出在页面上，所以等下我们在UserLoginAction中，登录成功后要设置一个相关属性。<BR>　　<BR>　　OK,下面来开始我们最后三个文件的设计吧。在Struts-config.xml的Design模式中，在画版的空白区域点右键，选择New --&gt; New Form, Action and JSP 弹出ActionForm的选项面板，我们按图上输入相关值，图5：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.36.45.5.gif"></CENTER><BR>　　在Optional Details的Form Properties选项卡，点add为这个ActionForm添加相关值，在这个登录示例中，将添加两个属性userName和password，图6：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.37.1.6.jpg"></CENTER><BR>　　在添加password时，注意将JSP input type 下拉框选择password.<BR>　　完成这步后，我们就将ActionForm设计完成。<BR>　　接下来选择 Optional Details的JSP选项卡,我们选中Create JSP form? 这一步myeclipse将为我们创建一个简单的与用户交互的登录页面。保持内容和图7一样。图7：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.37.14.7.gif"></CENTER><BR>　　因为我们这只是简单的演示一个登录片段，所以不用验证用户信息是否合法，所以将 Option Details的method选项卡的新建方法去掉，如图8：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.37.31.8.gif"></CENTER><BR>　　点Next，进入Action选项面板.将Option Details的Form选项卡中Validate Form取消选择，如图9：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.37.50.9.gif"></CENTER><BR>　　然后在Forwards选项卡中点add添加成功和失败返回的页面.如图10：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.38.4.10.jpg"></CENTER><BR>　　点击Finish完成。在Struts-config.xml的Design中，可以看到图11所示：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.38.18.11.gif"></CENTER><BR>　　最后，简单的修改一下userLogin.jsp,将所有<%@ taglib ...%>替换为：<BR>　　<%@ taglib uri="/tags/struts-html" prefix="html"%><BR>　　<%@ taglib uri="/tags/struts-bean" prefix="bean"%><BR>　　修改UserLoginAction中的execute片段为如下所示，图12：<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.38.32.12.gif"></CENTER><BR>　　OK，完成。。。下面就部暑项目，测试。。。<BR>　　<BR>　　像为项目添加Struts框架一样，在项目名上右击，选择MyEclipse --&gt; Add and Remove Project development.<BR>　　在弹出对话框上，单击add ，在弹出的 New Deployment 对话框上，Server选Tomcat5，点击Finish完成部署，如图13:<BR>　　 
<CENTER>　<IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.38.48.13.gif"></CENTER><BR>　　在用浏览器上打开：http://127.0.0.1:8080/LoginDemo/userLogin.jsp<BR>　　输入密码123456,用户名EricHe。显示成功：<BR>　　 
<CENTER><IMG src="http://www.chinaitlab.com/www/imgfiles/2005.7.12.11.39.1.14.jpg"></CENTER><BR>　　如果输错，或不输入，则无反映又回到当前登录页面（因为我们没有设置错误信息）。<BR><img src ="http://www.blogjava.net/qq13367612/aggbug/17816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:14 <a href="http://www.blogjava.net/qq13367612/articles/17816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse 3.0 简介和插件开发示例 </title><link>http://www.blogjava.net/qq13367612/articles/17814.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:06:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17814.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17814.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17814.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17814.html</trackback:ping><description><![CDATA[<IMG height=1 src="http://www.pcbookcn.com/images/ads_200.gif" width=1 align=left> <SPAN class=main>Eclipse 是一个很让人着迷的开发环境，它提供的核心框架和可扩展的插件机制给广大的程序员提供了无限的想象和创造空间。目前网上流传相当丰富且全面的开发工具方面的插件，但是Eclipse已经超越了开发环境的概念，可以想象Eclipse将成为未来的集成的桌面环境。目前的Eclipse本身就具备资源管理和外部程序的功能，加上无所不能的插件，将构成一个丰富多彩的工作环境而不仅仅是一个IDE。<BR><BR>　　<B>1.Eclipse简介和插件开发</B><BR><BR>　　Eclipse 是一个很让人着迷的开发环境，它提供的核心框架和可扩展的插件机制给广大的程序员提供了无限的想象和创造空间。目前网上流传相当丰富且全面的开发工具方面的插件，但是Eclipse已经超越了开发环境的概念，可以想象Eclipse将成为未来的集成的桌面环境。目前的Eclipse本身就具备资源管理和外部程序的功能，加上无所不能的插件，将构成一个丰富多彩的工作环境而不仅仅是一个IDE。对于程序员来说，没有什么比可以随心所欲的定制的工作环境更重要，你的决心，勇气和创造力在与别人分享成果的过程中一览无余。好了，你是不是心动了，如果你已经对Eclipse有一定的认识，那么，和我一起打造自己的个性化工作环境吧，首先我们一起开发一个天气预报的插件，然后我们打造属于自己的邮件快速监控功能。 <BR><BR>　　以下的工作基于一定的前提，那就是你是一名Java程序员，你很欣赏并正开始使用Eclipse这个超酷的工作环境，别忘了下载最新版的Eclipse3.0，本文基于Eclipse3.0开发。<BR><BR>　　<B>2.天气预报插件</B><BR><BR>　　如果你已经厌倦了总是要登录某些网站从相关网页上获取信息，这里有一个让你通过Eclipse快速获取信息的新方法。让我们从头开始，做一个属于自己的天气预报插件吧，你的Eclipse将具有天气预报功能，是不是很酷呢？<BR><BR>　　在这一部分，我们将要实现一个Eclipse插件，他可以在任何我们想知道的时候通过简单的点击鼠标告诉我们本地区的天气预报，这当然很刺激。对于一个程序员而言，事情就应该如此。让我们开始吧，我们首先要定义一个插件，把他加到菜单和工具栏中。对于没有插件开发经验的你，可以参考《开发 Eclipse 插件》，树立基本的插件开发意识，当然，本文将详细的辅助你完成这一创造性的工作。<BR><BR>　　2.1最基础的插件<BR><BR>　　打开菜单 File -＞ New-＞ Other -＞Plug-in Project，输入项目名称，next出现对话框，只要在插件名处输入"muplugin",next 以后选择 "Hello,World"的插件模板你可以直接新建一个名为myplugin的最简单的插件，但其实我们的天气预报并不比它复杂多少，建完改插件以后的效果如下图。<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=center><IMG onerror="this.src='/img_article/200512814610734.png';" hspace=3 src="http://www.pcbookcn.com/img_article/200512814611580.png" align=center vspace=1 border=1></DIV></TD></TR></TBODY></TABLE><BR>　　现在，将项目作为运行时工作台运行（run － run as runtime workbench），在一个全新的Eclipse窗口中，通过点击菜单 sample menu 的sample Action或者工具栏中的圆形Eclipse 图标，你将看到如下效果的对话框。<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=center><IMG onerror="this.src='/img_article/200512814611621.png';" hspace=3 src="http://www.pcbookcn.com/img_article/200512814611360.png" align=center vspace=1 border=1></DIV></TD></TR></TBODY></TABLE><BR>　　到此为止，天气预报插件的原始版做成了，通过修改plugin.xml，我们将菜单改成中文形式，需要修改的地方就2处，详见表格。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>＜actionSet label="Sample Action Set" visible="true" id="myplugin.actionSet"＞<BR>＜menu label="我的空间" id="sampleMenu"＞<BR>＜separator name="sampleGroup"＞<BR>＜/separator＞<BR>＜/menu＞<BR>＜action label="天气预报" icon="icons/sample.gif" class="myplugin.actions.SampleAction"<BR>tooltip="Hello, Eclipse world" menubarPath="sampleMenu/sampleGroup"<BR>toolbarPath="sampleGroup" id="myplugin.actions.SampleAction"＞<BR>＜/action＞<BR></TD></TR></TBODY></TABLE><BR>　　此时在运行时工作台，我们的菜单已经改变。<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=center><IMG onerror="this.src='/img_article/200512814612371.png';" hspace=3 src="http://www.pcbookcn.com/img_article/200512814612797.png" align=center vspace=1 border=1></DIV></TD></TR></TBODY></TABLE><BR>　　2.2用VisualEditer制作天气预报对话框<BR><BR>　　虽然菜单是天气预报，但是我们需要的不是hello Eclispe对话框，我们需要的是告诉我们天气的对话框，当然需要我们从头开始，于是我们需要重新构建一个对话框，这个就需要 Visual Editor来帮助进行界面的开发。我们将使用Visual Editor实现一个Swing对话框，当然只用VE做一个对话框是有点大材小用，但是作为起点，已经合适了。<BR><BR>　　首先构建Visual Editer开发环境(读者可参考相关资料)，当一切准备齐全，鼠标右键点击PackgeExpoler中的 "muplugin.actions"java文件，从弹出式菜单中选择 new-＞other-＞VisualClass，新建一个可视化的类，弹出界面如下图：<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=center><IMG style="WIDTH: 596px; HEIGHT: 514px" height=565 onerror="this.src='/img_article/200512814612112.png';" hspace=3 src="http://www.pcbookcn.com/img_article/200512814613784.png" width=488 align=center vspace=1 border=1></DIV></TD></TR></TBODY></TABLE><BR>　　选择next，然后在name中输入WeatherDialog，这个就是我们用来显示天气预报的dialog<BR><BR>　　选择该对话框的超类为javax.swing.JDiaog,点击Finish按钮。等待一段时间后，我们的对话框就基本生成了，鼠标点击左上角图标，直接输入天气预报就是对话框的标题，同时 我们可以看到左侧的VisualEditor面板。<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=center><IMG style="WIDTH: 614px; HEIGHT: 378px" height=395 onerror="this.src='/img_article/200512814613833.png';" hspace=3 src="http://www.pcbookcn.com/img_article/200512814613738.png" width=612 align=center vspace=1 border=1></DIV></TD></TR></TBODY></TABLE><BR>　　 然后我们将该对话框于与刚才的天气预报菜单连接找到SampleAction的run函数，如下所示：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>public void run(IAction action) {<BR>　MessageDialog.openInformation(<BR>　　window.getShell(),"Myplugin Plug-in", "Hello, Eclipse world");<BR>}</TD></TR></TBODY></TABLE><BR>　　替换成如下代码<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>public void run(IAction action) <BR>{<BR>WeatherDialog wd=new WeatherDialog();<BR>wd.setSize(400, 335);<BR>wd.show(); <BR>}</TD></TR></TBODY></TABLE><BR>　　此时，点击菜单运行，我们的对话框看起来象这个样子，在此基础上我们还要在上面增加天气预报信息。<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=center><IMG onerror="this.src='/img_article/200512814614140.png';" hspace=3 src="http://www.pcbookcn.com/img_article/200512814614472.png" align=center vspace=1 border=1></DIV></TD></TR></TBODY></TABLE><BR>　　2.3增加天气预报功能<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=center><IMG onerror="this.src='/img_article/200512814614876.png';" hspace=3 src="http://www.pcbookcn.com/img_article/200512814614811.png" align=center vspace=1 border=1></DIV></TD></TR></TBODY></TABLE><BR>　　下面的部分是重点，我们将使用具有解析Html功能的Swing组件JEditPane，来获取网络上的现成的天气预报信息，根据上图，从 VisualEditor的面板中Swing Components组点击JEditPane，加入到对话框中。并修改对话框代码使得最终的代码如下：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>/*<BR>* Created on 2004-9-23<BR>* */<BR>package myplugin;<BR><BR><BR>import java.io.BufferedReader;<BR>import java.io.InputStreamReader;<BR>import java.net.URL;<BR><BR>import javax.swing.JDialog;<BR>import javax.swing.JEditorPane;<BR><BR>/**<BR>* ＜p＞Title: WatherDialog＜/p＞<BR>* ＜p＞Description: 这个是对话框类，用于显示指定城市的当天的天气预报＜/p＞<BR>* ＜p＞Copyright: Copyright (c) 2004＜/p＞<BR>* ＜p＞Company:UF SOFT＜/p＞<BR>* @author 赵勇<BR>* @version 1.0<BR>*/<BR>public class WatherDialog extends JDialog<BR>{<BR>String city="北京";<BR><BR>private JEditorPane jEditorPane = null;<BR>/**<BR>* This method initializes <BR>* /<BR>public WatherDialog(String city) <BR>{<BR>super();<BR>this.city=city;<BR>initialize();<BR>}<BR>/**<BR>* This method initializes this<BR>* @return void<BR>*/<BR>private void initialize() <BR>{<BR>this.setContentPane(getJEditorPane());<BR>try<BR>{<BR>//构建URL对象<BR>URL url =new URL("http://weather.news.sina.com.cn//cgi-bin/figureWeather/simpleSearch.cgi?city="+city);<BR>String temp="";<BR>BufferedReader in <BR>= new BufferedReader(new InputStreamReader(url.openStream()));<BR>//使用openStream得到一输入流并由此构造一个BufferedReader对象<BR>String inputLine;<BR>//从输入流不断的读数据，直到读完为止<BR>while ((inputLine = in.readLine()) != null)<BR>temp=temp+inputLine+"\n";<BR>//关闭输入流<BR>in.close(); <BR>String weather <BR>=temp.substring ( temp.indexOf( "＜body"),<BR>temp.lastIndexOf( "body＞")+5);<BR><BR>this.jEditorPane .setText(weather);<BR>} <BR>catch (Exception e)<BR>{<BR>e.printStackTrace();<BR>} <BR>this.setTitle("天气预报");<BR>this.setSize(400, 166);<BR><BR>}<BR>/**<BR>* This method initializes jEditorPane <BR>* <BR>* @return javax.swing.JEditorPane <BR>*/ <BR>private JEditorPane getJEditorPane() <BR>{<BR>if (jEditorPane == null) <BR>{<BR>jEditorPane = new JEditorPane();<BR>jEditorPane.setContentType( "text/html");<BR>}<BR>return jEditorPane;<BR>}<BR>} // @jve:decl-index=0:visual-constraint="70,19"</TD></TR></TBODY></TABLE><BR>　　以上代码中最关键的部分就是对话框中的JEditorPane对象，在初始化时，从一个URL 获取天气预报信息，表现为Html标记片段，不用解析，直接调用JEditorPane的setText 方法，就可以将Html格式的信息直接按解析过的方式显示，也就是天气预报信息了，<BR><BR>　　此时Action中的调用需要做修改<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>public void run(IAction action) <BR>{<BR>WeatherDialog wd=new WeatherDialog("北京");<BR>wd.setSize(400, 335);<BR>wd.show(); <BR>}</TD></TR></TBODY></TABLE><BR>　　现在以运行时工作台的方式运行，点击天气预报菜单，可以看到下图：<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=center><IMG onerror="this.src='/img_article/200512814615436.png';" hspace=3 src="http://www.pcbookcn.com/img_article/200512814616965.png" align=center vspace=1 border=1></DIV></TD></TR></TBODY></TABLE>
<P><BR>　　如果你在上海或者其他城市，试着修改city参数为"上海"，再次运行，你将发现，你仍然能够得到该城市的天气预报（这里我们从网站上提取的信息，有点投机取巧了）。值得注意的是，Xmethod网站提供了一个天气预报的WebService，可惜只有美国的城市，不然我们可以使用Web Service调用获取天气预报，将会更酷。<BR><BR>　　现在运行是工作台已经具备了天气预报的功能，还需要更进一步，将改插件导出发布，拷贝到Eclipse根目录的plugins目录中，重新启动（具体参见Eclipse帮助）。现在你自己的Eclipse，就具备了天气预报的功能，只要你点击鼠标，就可以在编程之余轻松的获取天气信息。 除非你的老板认为你在工作时间随时了解天气情况不是一个好主意，我认为你完全可以将这个插件纳入个人收藏的插件之列。你也可以在此基础上扩展，增加一些配置文件和属性设置，定制出满足自己要求的插件。如果能够增加信息的自动过滤和筛选，那将是一次很愉快的体验，如果你有时间和兴趣，不妨一试。</P>
<P>　<B>3.邮件快速监控插件</B><BR><BR>　　现在你的工作因为Eclipse而更加惬意，更具创造力，那么你还有什么不满？你是否厌倦了各种邮件客户端随时随地的骚扰你呢？你希望你在高兴的时候适时的了解一下邮件的概况？好了，既然想到了为什么犹豫呢，因为你是程序员，你就是要用Eclipse享受完全DIY的乐趣。<BR><BR>　　3.1生成插件<BR><BR>　　本部分我们将在以上myplugin插件的基础上增加一个邮件过滤显示的对话框，类似的我们通过VisualEditer创建一个名为MailDialog的对话框，并增加一个JEditPane用来显示邮箱中我们关注的信息。<BR><BR>　　修改plugin.xml，增加一个"我的邮件"菜单<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>＜action<BR>label="邮件信息"<BR>icon="icons/sample.gif"<BR>class="myplugin.actions.MailAction"<BR>tooltip="邮件信息"<BR>menubarPath="sampleMenu/sampleGroup"<BR>toolbarPath="sampleGroup"<BR>id="myplugin.actions.MailAction"＞<BR>＜/action＞</TD></TR></TBODY></TABLE><BR>　　现在，你知道要创建一个MailAction的Action类，并在在Run中增加如下代码<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>MailConfig mail=new MailConfig();<BR><BR>String popServer="server";<BR>String popUser="zhaoyong";<BR>String popPassword="1234";<BR><BR>//设置需要过滤的关键字：发件人和邮件主题<BR>String [] strFrom=new String[] {"zhaoyong"};<BR>String [] strSubject=new String[] {"测试"};<BR><BR>MailConfig[] mc =new MailConfig [] { mail };<BR>MailDialog md=new MailDialog(mc);<BR>System.err.println("run run run ") ;<BR>md.setSize(400, 335);<BR>md.show();</TD></TR></TBODY></TABLE><BR>　　以上的代码编译不会通过，但是别着急，慢慢来，很快了。<BR><BR>　　3.2构建邮件监控对话框 <BR><BR>　　当然你需要建立一个MailConfig类用来表示一个邮箱的具体设置已及相关信息，这里就不在累述说明，详情参见参考资料中的代码。需要说明的式MailConfig除了要记录一个邮箱的地址，用户名和密码外，还提供2个关键字数组，如果为空，不加过滤，如果关键字有值，系统会根据发件人和邮件标题中是否包含关键字来进行显示邮件信息，已保证你的绝对自由。<BR><BR>　　首先我们需要实现一个MailConfig类，表示邮件配置，每个MailConfig的对象代表一个邮件帐户，我们的系统将能显示多个邮箱的配置，每个MailConfig中使用一个数组来保存需要过滤的收件人和邮件地址。<BR><BR>　　MailConfig类的中的变量如下： <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>String popServer;<BR>String popUser;<BR>String popPassword;<BR><BR>//设置需要过滤的关键字：发件人和邮件主题<BR><BR>String [] strFrom;<BR>String [] strSubject; <BR><BR>//是否显示邮件内容 <BR>boolean isViewContent=false;</TD></TR></TBODY></TABLE><BR>　　同样，我们将使用一个对话框来显示邮件信息，MailDialog需要引用javaMail.jar,和activation.jar这两个类包，确保已经有这两个类包并加入到项目的类路径中。最后的MailDialog代码如下：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>package myplugin;<BR><BR><BR>import java.io.IOException;<BR>import java.util.Properties;<BR><BR>import javax.mail.Folder;<BR>import javax.mail.Message;<BR>import javax.mail.MessagingException;<BR>import javax.mail.Session;<BR>import javax.mail.Store;<BR>import javax.mail.internet.InternetAddress;<BR>import javax.swing.JDialog;<BR>import javax.swing.JEditorPane;<BR>import javax.swing.JTextPane;<BR>/**<BR>* @author zhaoyong<BR>*<BR>* TODO To change the template for this generated type comment go to<BR>* Window - Preferences - Java - Code Style - Code Templates<BR>*/<BR>public class MailDialog extends JDialog<BR>{<BR><BR>private JEditorPane jEditorPane = null;<BR>private JTextPane jTextPane = null;<BR><BR>//可以显示多个邮件配置<BR>MailConfig[] mc= null; <BR><BR><BR>/**<BR>* This method initializes <BR>* 构造函数<BR>* @param mc : 需要显示的多个邮箱配置对象。<BR>*/<BR>public MailDialog(MailConfig[] mc) <BR>{<BR><BR>super();<BR><BR>if(mc!=null)<BR>this.mc = mc;<BR>else<BR>System.err.println("邮件配置错误！") ;<BR><BR>initialize();<BR>}<BR>/**<BR>* This method initializes this<BR>* 初始化<BR>* @return void<BR>*/<BR>private void initialize() <BR>{<BR>try<BR>{<BR>//设定显示内容的面板<BR>this.setContentPane(getJTextPane());<BR>//取得所有的新邮件信息<BR>String s= getAllMailInfo(); <BR>//将信息显示在对话框中<BR>this.jTextPane .setText(s);<BR><BR>this.setTitle("邮件信息");<BR>this.setSize(251, 100);<BR>} <BR>catch (Exception e)<BR>{ <BR>//发生错误显示错误信息<BR>this.jTextPane .setText(e.toString());<BR>e.printStackTrace();<BR>}<BR><BR>}<BR>/**取得所有的邮箱的需要监控的邮件信息<BR>* <BR>* @return String <BR>*/<BR>private String getAllMailInfo()<BR>{<BR>String allMailInfo="";<BR><BR>if (mc.length ＜1)<BR>allMailInfo="没有配置邮箱！";<BR>else<BR>{<BR>for(int i=0;i＜mc.length;i++)<BR>{<BR>//循环获取每个邮箱的邮件信息 <BR>allMailInfo=allMailInfo+getMailInfo(mc[i]);<BR>}<BR>}<BR>//还没有收到相关的邮件<BR>if (allMailInfo.trim().length() ==0)<BR>allMailInfo="未检测到相关新邮件！";<BR>return allMailInfo;<BR><BR>}<BR>/*<BR>*得到一个邮箱中满足条件的所有新邮件的字符串形式<BR>**/<BR>private String getMailInfo(MailConfig mc)<BR>{<BR>//最终输出的邮件信息<BR>String mailInfo="";<BR><BR>//每个邮箱服务器上的Store和Folder对象<BR>Store store=null;<BR>Folder folder=null;<BR><BR>try<BR>{<BR><BR>Properties props = System.getProperties();<BR>//与邮件服务器生成一个Session<BR>Session session = Session.getDefaultInstance( props,null);<BR><BR>//给出服务器，用户名，密码连接服务器<BR>store = session.getStore("pop3");<BR>store.connect(mc.getPopServer(), mc.getPopUser(),mc.getPopPassword());<BR><BR>//取得默认的邮件Folder<BR>folder = store.getDefaultFolder();<BR>if (folder == null) <BR>throw new Exception("No default folder");<BR><BR>//取得收件箱<BR>folder = folder.getFolder("INBOX");<BR>if (folder == null) <BR>throw new Exception("No POP3 INBOX");<BR><BR>//以只读方式打开收件箱<BR>folder.open(Folder.READ_ONLY);<BR><BR>//获取所有新邮件并处理<BR>Message[] msgs = folder.getMessages(); <BR><BR>for (int i = 0; i ＜ msgs.length; i++)<BR>{<BR>Message message= msgs[i];<BR>//取得每封邮件的信息，需要引用MailConfig对象进行关键字过滤<BR>mailInfo = mailInfo+ getMessageInfo( message,mc); <BR>}<BR><BR>}<BR>catch (Exception ex)<BR>{<BR>ex.printStackTrace();<BR>}<BR>finally<BR>{<BR>//安全的关闭邮件服务器资源<BR>try<BR>{<BR>if (folder!=null) folder.close(true);<BR>if (store!=null) store.close();<BR>}<BR>catch (Exception ex2) {ex2.printStackTrace();}<BR>}<BR>return mailInfo;<BR>}<BR><BR>/**<BR>* 得到一封邮件的信息，需要根据MailConfig过滤<BR>* @param mailInfo<BR>* @param message<BR>* @return 邮件信息<BR>* @throws MessagingException<BR>* @throws IOException<BR>*/<BR>private String getMessageInfo( final Message message ,final MailConfig mc) <BR>throws MessagingException, IOException <BR>{<BR>//返回的改邮件信息<BR>String mailInfo="";<BR><BR>String from=((InternetAddress)message.getFrom()[0]).getPersonal();<BR><BR>if (from==null) <BR>from=((InternetAddress)message.getFrom()[0]).getAddress();<BR><BR>String subject=message.getSubject();<BR><BR>//如果满足过滤信息则显示，否则返回空<BR>if(isElementinString(from,mc.getStrFrom())<BR>||isElementinString(subject,mc.getStrSubject()) ) <BR>{ <BR>mailInfo=mailInfo+"发件人 : "+from+"\n"; <BR>mailInfo=mailInfo+"邮件主题 : "+subject+"\n";<BR>mailInfo=mailInfo+"发送时间 : "+message.getSentDate() +"\n";<BR><BR>//如果显示内容，则打印内容<BR>if(mc.isViewContent)<BR>mailInfo=mailInfo+message.getContent() +"\n";<BR><BR>mailInfo=mailInfo+"------------------------------------\n";<BR>}<BR>return mailInfo;<BR>}<BR><BR>private JTextPane getJTextPane() <BR>{<BR>if (jTextPane == null) <BR>{<BR>jTextPane = new JTextPane();<BR>}<BR><BR>return jTextPane;<BR>}<BR><BR>/**<BR>* 判断目标关键字数组中是否有指定的字符串,进行过滤<BR>* @param targetStr ：<BR>* @param keys ：<BR>* @return 如果有，返回true， 否则返回false<BR>*/<BR><BR>private boolean isElementinString(String targetStr,String [] keys)<BR>{<BR>//没指定过滤条件，显示所有<BR>if (keys==null)<BR>return true;<BR>//指定字符串为空，直接返回false<BR>if (targetStr==null)<BR>return false;<BR>for(int i=0;i＜keys.length ;i++)<BR>{<BR>if (targetStr.indexOf(keys[i])＞-1)<BR>return true;<BR>}<BR>return false;<BR>}<BR><BR>} <BR>// @jve:decl-index=0:visual-constraint="10,10"－－说明，这是Visual Editor添加的控制信息</TD></TR></TBODY></TABLE><BR>　　以上代码的注释已经保证你能够看清楚，这里就不加累述，有兴趣的可以自己试试，体验一切尽在掌握的快感。当然这个例子做的实在简单，因此也为你的进一步开发留有足够的余地。<BR><BR>　　3.3 打包和发布<BR><BR>　　到此，在mypulgin中增加了邮件信息菜单和对话框，系统的plugin.xml如下：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#d8d8d1 border=1>
<TBODY>
<TR>
<TD>＜?xml version="1.0" encoding="UTF-8"?＞<BR>＜?eclipse version="3.0"?＞<BR>＜plugin<BR>id="myplugin"<BR>name="Myplugin Plug-in"<BR>version="1.0.0"<BR>provider-name=""<BR>class="myplugin.MypluginPlugin"＞<BR><BR>＜runtime＞<BR>＜library name="myplugin.jar"＞<BR>＜export name="*"/＞<BR>＜/library＞<BR>＜library name="lib/javaMail.jar"＞<BR>＜export name="*"/＞<BR>＜/library＞<BR>＜library name="lib/activation.jar"＞<BR>＜export name="*"/＞<BR>＜/library＞<BR>＜/runtime＞<BR><BR>＜requires＞<BR>＜import plugin="org.eclipse.ui"/＞<BR>＜import plugin="org.eclipse.core.runtime"/＞<BR>＜/requires＞<BR><BR>＜extension<BR>point="org.eclipse.ui.actionSets"＞<BR>＜actionSet<BR>label="Sample Action Set"<BR>visible="true"<BR>id="myplugin.actionSet"＞<BR>＜menu<BR>label="我的空间"<BR>id="sampleMenu"＞<BR>＜separator<BR>name="sampleGroup"＞<BR>＜/separator＞<BR>＜/menu＞<BR>＜action<BR>label="天气预报"<BR>icon="icons/sample.gif"<BR>class="myplugin.actions.SampleAction"<BR>tooltip="Hello, Eclipse world"<BR>menubarPath="sampleMenu/sampleGroup"<BR>toolbarPath="sampleGroup"<BR>id="myplugin.actions.SampleAction"＞<BR>＜/action＞<BR>＜action<BR>label="邮件信息"<BR>icon="icons/sample.gif"<BR>class="myplugin.actions.MailAction"<BR>tooltip="邮件信息"<BR>menubarPath="sampleMenu/sampleGroup"<BR>toolbarPath="sampleGroup"<BR>id="myplugin.actions.MailAction"＞<BR>＜/action＞<BR>＜/actionSet＞<BR>＜/extension＞<BR>＜/plugin＞</TD></TR></TBODY></TABLE><BR>　　实际上，我们在一个插件中加入了2个功能，因此就实现了我们的开发环境的自我扩展和定制。同样，参考Eclipse的帮助，你可以轻松的再次将插件打包导出，并将其加入自己的Eclipse 的plugins目录（可能需要解压缩），或通过help菜单的Update选项进行安装，注意导出时需要选定相关的类包。重新启动，你将发现自己的IDE已经多了自己的菜单，开发环境已经随着自己的意愿在改变了，程序员天生的满足感油然而生。 <BR><BR>　　现在，你可以在需要的时候点击菜单，了解你希望监控的邮件情况或者最近的天气情况，一切轻松的尽在掌握，Eclipse的插件，就是这样全能。<BR><BR>　　<B>4.总结</B> <BR><BR>　　那么，聪明的你有没有发现什么问题，对，上面的东西太粗糙，太简单了，你可以做进一步的优化设计和功能加强，比如，自己增加邮件配置文件而不是写在代码里面，动态监控弹出邮件预警（通过事先设定的紧急状态），你也许还会想起来很多的新的主意，比如我为什么不能有个能看电影的插件？或是Eclipse中飘出动听的音乐？别急，这些不一定需要你亲手去做，http://sourceforge.net/projects/rocexwang/ 有一个播放器插件，但是现在仅能播放音乐，国外已经有人用Eclipse开发游戏，也有人用Eclipse来做MIS系统的。http://www.matrix.org.cn/forum_view.asp?forum_id=25&amp;view_id=10510 有一个国人开发的俄罗斯方块游戏，虽然简单了一点。当然，通过网址http://eclipse-plugins.2y.net/eclipse/index.jsp和http://www.eclipseplugincentral.com/你可以找到很多的插件，如果你知道什么更好的插件，请告诉我。<BR><BR>　　Eclipse提供了一个纯的框架和插件结构，使得开发任何功能的插件都能成为现实。本文介绍了2个有趣的Eclipse插件的开发，可以使我们的工作环境增加了两个可爱的小功能，同时也使得你具备了基础的插件开发能力，借助Eclipse的强大功能，从此你可以把你的任何想法变为现实。同时请保持与别人的交流，我会很乐意了解你的新奇的插件，并收藏和学习任何好的插件，打造一个完全属于自己的个性化的开发环境。Eclipse将在不久的将来成为一个全能的Platform，这一点在全世界数以万计的开发人员的手中，正一点一点变为现实。</P></SPAN><img src ="http://www.blogjava.net/qq13367612/aggbug/17814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:06 <a href="http://www.blogjava.net/qq13367612/articles/17814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse的使用简介及插件开发</title><link>http://www.blogjava.net/qq13367612/articles/17813.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:04:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17813.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17813.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17813.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17813.html</trackback:ping><description><![CDATA[<P>Eclipse 是替代IBM Visual Age for Java（以下简称IVJ）的下一代IDE开发环境，但它未来的目标不仅仅是成为专门开发Java程序的IDE环境，根据Eclipse的体系结构，通过开发插件，它能扩展到任何语言的开发，甚至能成为图片绘制的工具。目前，Eclipse已经开始提供C语言开发的功能插件。更难能可贵的是，Eclipse是一个开放源代码的项目，任何人都可以下载Eclipse的源代码，并且在此基础上开发自己的功能插件。也就是说未来只要有人需要，就会有建立在Eclipse之上的COBOL，Perl，Python等语言的开发插件出现。同时可以通过开发新的插件扩展现有插件的功能，比如在现有的Java开发环境中加入Tomcat服务器插件。可以无限扩展，而且有着统一的外观，操作和系统资源管理，这也正是Eclipse的潜力所在。</P>
<P>虽然目前Eclipse项目还没有最后完成，但从已有的版本中已经能领略到Eclipse设计主导思想和主要功能特点。现在就了解Eclipse不但能使广大程序员对这款业界期望很高的IDE能一睹为快，更为重要的是如果能参加到Eclipse项目的开发中或是阅读它的开放源代码，这对广大程序员来说无疑是一个千载难逢的提高编程水平的好机会。Eclipse计划提供多个平台的版本，象Windows，Linux，Solaris，HP-UX和AIX，以下只介绍Windows版本。本文第一部分先介绍Eclipse的基本使用方法。第二部分介绍如何进行Eclipse的插件开发。</P>
<P><A name=1><SPAN class=atitle2>一．Eclipse简介</SPAN></A><BR></P>
<P>Eclipse是开放源代码的项目，你可以到 <A href="http://www.eclipse.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">www.eclipse.org</A>去免费下载Eclipse的最新版本，一般Eclipse提供几个下载版本：Release，Stable Build，Integration Build和Nightly Build，建议下载Release或Stable版本，笔者用的是Build20020125（Stable版本）。Eclipse本身是用Java语言编写，但下载的压缩包中并不包含Java运行环境，需要用户自己另行安装JRE，并且要在操作系统的环境变量中指明JRE中bin的路径。安装Eclipse的步骤非常简单：只需将下载的压缩包按原路径直接解压既可。需注意如果有了更新的版本，要先删除老的版本重新安装，不能直接解压到原来的路径覆盖老版本。在解压缩之后可以到相应的安装路径去找Eclipse.exe运行。如果下载的是Release或Stable版本，并且JRE环境安装正确无误，一般来说不会有什么问题，在闪现一个很酷的月蚀图片后，Eclipse会显示它的缺省界面： </P>
<P><A name=N10052><B></B></A><BR><IMG height=427 alt=图一 src="http://www-128.ibm.com/developerworks/cn/java/l-eclipse/1.gif" width=554 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>图一 </P>
<P>乍一看起来，Eclipse的界面有点象JBilder，但实际操作进程中会发现它更象IVJ，毕竟开发Eclipse的主导用量是开发IVJ的原班人马（可参考www.oti.com）。另外还值得一提的是Eclipse项目的参预者除了IBM以外，还有象Borland，Rational Software，RedHat，Merant等一大批业界的姣姣者，这也为Eclipse的未来奠定了良好的基础。</P>
<P>下面将分别对Eclipse的各种特性作简单介绍，包括：文件存放，开发环境，编译与运行，版本管理，使用插件。</P>
<P><A name=2><SPAN class=atitle3>1． 文件存放</SPAN></A><BR></P>
<P>大多IVJ的初学者都对找不到Java源代码感到非常不适应，因为IVJ把所有的源代码都存储到一个reponsitory库文件中，想要得到文本格式的源代码必须用Export功能从reponsitory中导出源代码。使用了reponsitory的IVJ对源代码的管理功能几乎达到极致，正是这一点使得许多程序员对IVJ钟爱有加。而Eclipse将源代码以文本方式保存，却实现了IVJ对源代码管理的几乎全部功能，并且还增加了一些新的功能，能达到这一点，不能不惊叹于Eclipse开发者的高超技巧。</P>
<P>安装Eclipse之后，在安装路径的下一层路径中会有一个workspace文件夹。每当在Eclipse中新生成一个项目，缺省情况下都会在workspace中产生和项目同名的文件夹以存放该项目所用到的全部文件。你可以用Windows资源管理器直接访问或维护这些文件。</P>
<P>将已有的文件加入到一个项目中目前有三种方式：第一种是象在IVJ中的一样，用IDE的"File"菜单中的"Import"功能将文件导入到项目中。这也是推荐的方式。第二种是从Windows的资源管理器中直接拖动文件到项目中。第三种就是直接将文件拷贝到项目文件夹中，然后在Eclipse的资源浏览窗口中选择项目或文件夹并执行从本地刷新功能（Refresh from locate）。需要说明的一点是，项目文件夹可以放在计算机的任何位置，并且可以在Eclipse中用新建项目的方法将项目路径指定到已经存在的项目文件夹，然后在Eclipse中刷新即可。但要注意的是，任何项目文件夹建立或指定，目前都只能在Eclipse中用新建项目的方法来实现，即使是在缺省存储项目文件夹的workspace路径下新建立一个文件夹，在Eclipse环境中也是无法将它变成一个项目，也就是说，这个文件夹对Eclipse是不可视的。</P>
<P><A name=3><SPAN class=atitle3>2． Eclipse开发环境</SPAN></A><BR></P>
<P>和IVJ一样，Eclipse开发环境被称为Workbench，它主要由三个部分组成：视图（Perspective），编辑窗口（Editor）和观察窗口（View）。在下面的介绍中，希望读者能知道Java视图，Java包浏览窗口，资源视图，资源浏览窗口等区别（其实最主要的也就是要区别视图和窗口），以免在进一步的阅读中产生混淆。图二是它们之间的关系结构略图：</P>
<P><A name=N10082><B></B></A><BR><IMG height=361 alt=图二 src="http://www-128.ibm.com/developerworks/cn/java/l-eclipse/2.gif" width=553 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>图二 </P>
<P>在图二中，可以看出Workbench包含多个视图，而每个视图又包含不同的窗口。由于每个编辑窗口有很大的共性，而且缺省情况它们都在同一区域中显示，因此我们只在每个视图中标出一个编辑窗口，以绿色表示。观察窗口则各不相同，这里以红色表示。</P>
<P>下面首先介绍编辑窗口。所有文件的显示和编辑都包含在编辑窗口里。缺省情况下打开的多个文件是以标签（TagTable）方式在同一个窗口中排列，可以用拖动方式将这些文件排列成各种布局。方法是拖动某一个文件的标签（tag）到编辑窗口的边框，当光标有相应的变化时再释放。</P>
<P>当文件被加入到项目中后，在资源浏览或Java包浏览窗口双击文件，Eclipse会试图打开这个文件：其中Eclipse内嵌的编辑器能缺省打开一些文件，如*.java，*.txt，*.class等等。如果是其它类型的文件，Eclipse会调用操作系统相应的缺省编辑器打开，如word文档，PDF文件等。同时Eclipse也可以象IVJ一样用指定的编辑器打开相应的文件。例如在Eclipse项目中双击HTML文件时，可能希望是用Notepad打开，而不是用系统缺省的IE浏览器打开。实现的方法是打开菜单栏中的WorkBenchàPreferences对话框，之后在对话框中选择WorkBenchàFile Editors，然后添加文件类型，如*.html，再为其指定编辑器即可。</P>
<P>在编辑窗口，还值得注意的是，习惯了IVJ的程序员在编辑Java程序的时候，更愿意以方法为独立的编辑单位（即在编辑窗口中只显示单个的方法，而不是程序全部的源代码），这种方式也的确是非常合理的开发方式，不仅代码的显示更加简捷，还能辅助程序员编出封装性更好的类。在Eclipse在工具栏上提供了一个切换按钮，可以在"显示全部代码"和"只显示所选单元"（这里的单元指的是单个方法、变量、导入的包等）之间切换（可参考下面的图三）。建议没有使用过IVJ的程序员也尝试一下在"只显示所选单元"状态下进行代码开发。</P>
<P>其次要介绍的是观察窗口，它配合编辑窗口并提供了多种的相关信息和浏览方式。常用的观察窗口有资源浏览窗口（Navigator），Java包浏览窗口(Packages)，控制台（Console），任务栏（Task）等等。</P>
<P>浏览窗口和Java浏览窗口是观察窗口核心部分。前者和Windows的浏览器差不多，能浏览项目文件夹中的所有文件，后者用来浏览项目中的Java包，包中的类，类中的变量和方法等信息。在Java浏览窗口中可以通过用鼠标右键的菜单中的Open Type Hierarchy打开层次浏览窗口（Hierarchy），这个窗口非常实用，它能非常清晰的查看类的层次结构。类中的编译出错信息可以在任务窗口中查到，同时它也可以成为名符其实的任务窗口：向其中添加新的任务描述信息，来跟踪项目的进度。控制台则主要用来显示程序的输出信息。在调试程序的时候，会有更丰富的观察窗口来帮助程序员进行调试，如变量值察看窗口，断点窗口等等。</P>
<P>观察窗口是任何IDE开发环境的核心，用好观察窗口是也就是用好IDE开发环境。Eclipse提供了丰富的观察窗口，能真正用好这些窗口恐怕要得经过一段时间的磨练。</P>
<P>最后介绍视图。一个视图包括一个或多个编辑窗口和观察窗口。在开发环境的最左侧的快捷栏中的上部分显示的就是当前所打开的视图图标。视图是Eclipse的最灵活的部分，可以自定义每个视图中包含的观察窗口种类，也可以自定义一个新视图。这些功能都被包括在"Perspective" 菜单中。在Eclipse的Java开发环境中提供了几种缺省视图，如资源视图（Resource Perspective，它也是第一次启动Eclipse时的缺省视图），Java视图（Java Perspective），调试视图（Debug Perspective），团队视图(Team Perspective)等等。每一种视图都对应不同种类的观察窗口。可以从菜单栏中的PerspectiveàShow View看到该视图对应的观察窗口。当然，每个视图的观察窗口都是可配置的，可以在菜单栏中的PerspectiveàCustomize进行配置。多样化的视图不但可以帮助程序员以不同角度观察代码，也可以满足不同的编程习惯。</P>
<P><A name=4><SPAN class=atitle3>3． 编译与运行</SPAN></A><BR></P>
<P>在IVJ中调试功能非常强大，多种跟踪方式，断点设置，变量值察看窗口等等。这些在Eclipse中都也有提供。在本文下面介绍插件的时候，会结合例子更加详细的介绍如何使用配置项目环境，如何运行和调试程序。</P>
<P>在Java视图中，工具栏中有两个按钮，分别用来进行调试和运行。并且可能由于安装的插件不同Eclipse会存在多种运行/调试程序的方式，为了确定当前项目用那一种方式运行，需要在项目的属性选项中的设置LauncheràRun/Debug选项。通常我们需要用的是"Java　Applicantion"方式。在这种方式下，如果当前位置是包含main()方法的Java程序，点击调试/运行按钮就会立即开始执行调试/运行功能。如果当前位置是在包或项目上，Eclipse会搜索出当前位置所包含的所有可执行程序，然后由程序员自己选择运行那一个。</P>
<P>在目前的Eclipse的Release和Stable版本中缺省安装了插件开发环境（Plug-in Development Environment，即PDE，它本身也是一个插件），此时系统除了"Java Applicantion" 运行方式，可能还有另外两种方式："Run-time WorkBench"和"Run-time WorkBench with Tracing"，当用PDE开发插件的时候会用到这两种运行方式，在下面我们也有提到。</P>
<P><A name=5><SPAN class=atitle3>4． 版本管理</SPAN></A><BR></P>
<P>可以把Eclipse的版本管理分为个人（或称为本地）和团队两种。</P>
<P>Eclipse提供了强大的个人版本管理机制，每一次被保存的更改都可以得到恢复。而且可以精确到每一个方法的版本恢复。操作也十分方便，在任何一个能看到所要操作文件的观察窗口中，例如资源浏览窗口，选中该文件，点击右鼠标键，选择Compare with或Replace with，如果是恢复已经被删除的方法则可以选择Add from local history，之后相应的本地历史记录就会显示出来，按照你的需求找到相应的版本就可以了。强大的个人版本管理功能为程序员提供了更多的信心：只管编下去，任何不小心的错误都可以恢复，在Eclipse下开发，是有"后悔药"的！</P>
<P>Eclipse缺省为版本管理工具CVS提供了接口，可以非常方便的连接到CVS服务器上。通过CVS版本管理，Eclipse为团队开发提供良好的环境。要连接CVS服务器需要先打开团队视图（Team Perspective），然后在Reponsitories观察窗口中点击鼠标右键并选择新建（New），在打开的对话框中可以填入要连接的CVS库所需要的信息，如CVS服务器类型，目前Eclipse支持三种方式：pserver、extssh和ext，还要填入用户名，主机名，密码，reponsitory地址等信息。</P>
<P>在Eclipse中使用CVS需要注意的是一些术语和功能的变化，CVS中的Branch这里被称为Stream，取消了CVS中check out、import和commit等功能，统统用鼠标右键菜单中的Team-&gt;Synchronized with Stream来替代。这些功能都通过图形界面完成，在每次操作中都会有当前文件和以前各个版本的比较窗口，操作非常直观，易于掌握，因此这里也就不再做进一步介绍了。</P>
<P><A name=6><SPAN class=atitle3>5． 使用插件</SPAN></A><BR></P>
<P>使用插件可以丰富Eclipse的功能。下面将介绍如何应用插件来嵌入Tomcat服务器。这个插件并不是Eclipse项目组开发的，而是一家叫sysdeo的公司开发，非常小巧，只有27.8K。你可以到 <A href="http://www.sysdeo.com/eclipse/tomcatPlugin.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">http://www.sysdeo.com/eclipse/tomcatPlugin.html</A>去免费下载。另外，这个插件只支持Tomat4.0以上的版本，可以在 <A href="http://www.apache.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">www.apache.org</A>得到Tomcat的最新版本。 </P>
<P>要安装插件只需将下载的zip文件按原路径解压到"你的Eclipse的安装路径\plugins"下面，然后重新启动Eclipse。启动后在菜单栏上选择PerspectiveàCustomize，在打开的对话框中选中OtheràTomcat。之后马上会发现Eclipse有了两处变化：菜单栏中多了一个Tomcat选项，工具栏中多了两个按钮，上面是大家可能非常熟悉的Tomcat小猫，如下图三。除此之外，在菜单栏中选择：WorkbenchàPreferences，打开对话框后会发现这也多了一个Tomcat选项，在这里要求指定你的Tomcat安装根路径。之后还要检查一下在Preferences对话框中的JavaàInstalled JRE所指定的JRE和启动Tomcat的JRE是否为同一个JRE，如果不是，可能会导致Tomat不能正常启动。如果以上检查没有问题，就可以用工具栏上的"小猫"直接起动Tomcat了。要注意的是，启动过程很慢，要耐心等到以下信息出现：</P>
<P>Starting service Tomcat-Standalone <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Apache Tomcat/4.0.1 <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Starting service Tomcat-Apache <BR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Apache Tomcat/4.0.1 </P>
<P>之后就可以在外部浏览器（如IE）中输入 <A href="http://localhost:8080/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">http://localhost:8080</A>来测试Tomcat是否正常。 </P>
<P><A name=N100F3><B></B></A><BR><IMG height=96 alt=图三 src="http://www-128.ibm.com/developerworks/cn/java/l-eclipse/3.gif" width=554 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>图三 </P>
<P>如果启动正常，可以进一步尝试在Eclipse中调试Servlet或JSP程序。下面我们将用Tomcat自带的Servlet例程HelloWorldExample.java来示范一下如何在Eclipse中调试Sevlet程序。</P>
<P>首先要在Java视图中新建一个Java项目，为了方便，可以直接将项目路径指定到HelloWorldExmaple程序所在路径，如图四：</P>
<P><A name=N10107><B></B></A><BR><IMG height=184 alt=图四 src="http://www-128.ibm.com/developerworks/cn/java/l-eclipse/4.gif" width=496 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>图四 </P>
<P>之后按"Next"，进入Java Settings对话框，选择Libraries标签，并用Add External JARs按钮来指定Servlet.jar包的位置。这里直接用了Tomcat中的Servlet.jar包。如图五：</P>
<P><A name=N10118><B></B></A><BR><IMG height=246 alt=图五 src="http://www-128.ibm.com/developerworks/cn/java/l-eclipse/5.gif" width=493 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>图五 </P>
<P>最后，点击"Finish"完成项目的生成。在新生成项目中的default package可以找到HelloWorldExample.java，双击打开文件，并可尝试给HelloWorldExample加上一个断点（双击编辑窗口左侧边界）。之后在外部浏览器中输入 <A href="http://localhost:8080/examples/servlet/HelloWorldExample" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">http://localhost:8080/examples/servlet/HelloWorldExample</A>，再回过来看Eclipse发生了什么变化，是一个调试窗口呀！在Eclipse中进行的调试操作和绝大多数的IDE大同小异，如设置断点，单步跟踪，变量值察看等等，在这里也就不用再详述了。 </P>
<P><A name=7><SPAN class=atitle2>二．开发Eclipse插件（Plug-ins）</SPAN></A><BR></P>
<P>Eclipse最有魅力的地方就是它的插件体系结构。在这个体系中重要的概念是扩展点（extension points），也就是为插件提供的接口。每一个插件都是在现有的扩展点上开发，并可能还留有自己的扩展点，以便在这个插件上继续开发。</P>
<P>由于有了插件，Eclipse系统的核心部分在启动的时候要完成的工作十分简单：启动平台的基础部分和查找系统的插件。在Eclipse中实现的绝大部分功能是由相应的插件完成的，比如WrokBench UI插件完成界面的外观显示，Resource Management插件完成维护或生成项目或文件等资源管理工作（在下面的第二个例子就会用到这个插件），而Version and Configuration Management (VCM)插件则负责完成版本控制功能，等等。虽然以上提到的每一个功能都是绝大多数IDE环境所必备的功能，Eclipse却也把它们都做成了插件模式，甚至用来开发Java程序的开发环境（Java development tooling，JDT）也只不过是Eclipse系统中的一个普通插件而已。整个Eclipse体系结构就象一个大拼图，可以不断的向上加插件，同时，现有插件上还可以再加插件。下面的插件开发示例就是在WorkBench UI插件中的观察窗口扩展点上开发的。</P>
<P>本文第一部分介绍过Eclipse的开发界面其中之一就是观察窗口，它通常配合编辑窗口显示一些有用的信息，在这里我们只简单生成一个显示欢迎信息的观察窗口，假设新插件的名子叫Welcome。</P>
<P>第一步，先用向导新建一个Java项目。我们可以在菜单栏选择FileàNew，或用工具栏的向导按键，或是在资源窗口用鼠标右键菜单中的New，打开向导对话框，然后用缺省方式创建项目。并在项目中建立一个Welcome.java文件，代码如下：</P>
<P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
package com.nidapeng.eclipse.plugin;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.SWT;
import org.eclipse.ui.part.ViewPart;
public class Welcome extends ViewPart {
	Label label;
	public Welcome() {
	}
	public void createPartControl(Composite parent) {
		label = new Label(parent, SWT.WRAP);
		label.setText("Welcome to Eclipse");
	}
	public void setFocus() {
	}
}
</CODE></PRE></TD></TR></TBODY></TABLE></P>
<P>为使这个程序能正常编译，要配置它的编译环境，即指定所需的CLASSPATH。在Eclipse中可以用几种方法，常用的是两种：第一是在资源窗口或Java包窗口选中该项目，点击鼠标右键，在打开的菜单中选择属性（Properties），之后在属性对话框中选择Java Build PathàLibraries，用Add External JARs功能添加三个包，它们都是Eclipse的现有插件的类包，可以在"你的Eclipse安装路径\plugins"下面的相应路径中找到。分别是org.eclipse.core.runtime插件中的runtime.jar，org.eclipse.swt中的swt.jar和org.eclipse.ui中的workbench.jar。第二种指定CLASSPATH的方法是先将以上提到的三个包直接导入到Eclipse中的某下一个项目中。如果导入到和Welcome.java相同的项目中，则无需进一步指定CLASSPATH，否则需要在项目的属性菜单中选择Java Build PathàProjects，然后选中这三个包所在的项目。</P>
<P>在我们的项目中还要生成一个XML文件，它的名字必须plugin.xml。代码如下：</P>
<P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;plugin
   id="com.nidapeng.eclipse.plugin"
   name="Welcome to Eclipse"
   version="1.0"
   provider-name="Ni Dapeng"&gt;
&lt;requires&gt;
   &lt;import plugin="org.eclipse.ui"/&gt;
&lt;/requires&gt;
&lt;runtime&gt;
   &lt;library name="welcome.jar"/&gt;
&lt;/runtime&gt;
&lt;extension
      point="org.eclipse.ui.views"&gt;
   &lt;category
         name="Welcome"
         id="com.nidapeng.eclipse.plugin.category1"&gt;
  &lt;/category&gt;
   &lt;view
         name="Welcome to Eclipse"
         category="com.nidapeng.eclipse.plugin.category1"
         class="com.nidapeng.eclipse.plugin.Welcome"
         id="com.nidapeng.eclipse.plugin.view1"&gt;
  &lt;/view&gt;
&lt;/extension&gt;
&lt;/plugin&gt;
</CODE></PRE></TD></TR></TBODY></TABLE></P>
<P>在plugin.xml中一共有四个主要的标签：plugin，requires，runtime，extension。其中plugin标签的属性提供的是我们要开发的Welcome插件的基本信息，除了name，version，provider-name等，最重要的是id，它要求不能和现有的Eclipse插件id有冲突，因此我们用包名作为插件的id。requires标签中所列出的是需要的插件，这里我们要用到Eclipse Workbench和SWT API，因此导入了org.eclipse.ui插件。runtime标签指明的是我们开发的插件所在JAR包的文件名。extension标签是插件扩展点的信息。org.eclipse.ui.views是Eclipse系统提供的观察窗口扩展点，我们的例子是一个观察窗口（View），这表明我们是要在 org.eclipse.ui.views扩展点上进一步开发。extension中还包括category和view两个标签，在后续的启动Welcome插件步骤中，我们就会知道这两个标签的含义。要注意的是category和view标签的id的唯一性，并且在view的属性中声明了Welcome插件的类名。</P>
<P>在Eclipse中为plugin.xml提供了缺省可视化的编辑器，在编写plugin.xml过程中可以借助这个编辑器完成一些工作。如果你直接录入了plugin.xml文件源代码，还可以用这个编辑器校验你的代码：如果编辑器不能正确读入，就表明你的plugin.xml有一些问题。</P>
<P>在确认Weclome.java和plugin.xml都正确无误之后，可以用Eclipse菜单栏中的Export命令将Weclome.java导出为JAR文件，它的名子应该和plugin.xml中runtime声明的JAR相一致。同时导出plugin.xml。安装Welcome插件的方法和本文第一部分介绍的安装Tomcat插件方法是一样的：首先在"Eclipse的安装路径\plugins"路径下面建立一个com.nidapeng.eclipse.plugin路径，然后将Weclome.jar和plugin.xml拷到这个路径下。之后必需重新启动Eclipse，在Eclipse启动的时候，它会搜索所有在插件路径下的插件并注册它们（仅仅是注册，只有在需要某个插件的时候，Eclipse才会启动它）。在重新启动的Eclipse的菜单栏中选择PerspectiveàShow ViewàOthers，在打开的对话框中我们会找到在plugin.xml中extension的category标签中声明的name属性：Welcome。在Welcome的支结点中包含了view标签name属性：Welcome to Eclipse。选中它并确认，Welcome窗口就会显示在Eclipse Workbench上的某个位置 。如果在执行了以上操作，但没有显示新窗口，可以再次打开Show View菜单，此时在菜单中应该有新一顶选择：Welcome to Eclipse，然后选中它。</P>
<P>上面我们完成了一个观察窗口的插件，但这个操作过程对开发稍微复杂一些的插件就显得不太方便了：每次测试都要将代码打包，发布，再重新启动Eclipse系统！为此Eclipse提供了一个专门为开发插件而做插件（有点绕嘴）：Plug-in Development Environment（PDE）。本文前面曾提到，目前Eclipse的Release或Stable版本缺省提供了这个插件，因此如果安装的Eclipse是这两个版本中的一个就可以直接进行下面的步骤。下面我们再用PDE环境开发一个稍微复杂一些的插件。</P>
<P>第一步仍然要新建一个项目，只是在向导中不是用Java项目，而是Plug-in Development中的Plug-in Project。在应用向导生成新项目的时候，要注意两点：第一是PDE的项目名称就是plugin的id，因此要保证它的唯一性，这里我们的项目名是com.nidapeng.eclipse.plugin.pde。其次为了进一步说明Eclipse插件的结构，在Plug-in Code Generators中，选择用向导模板生成一个缺省的插件，如图六：</P>
<P><A name=N1015E><B></B></A><BR><IMG height=194 alt=图六 src="http://www-128.ibm.com/developerworks/cn/java/l-eclipse/6.gif" width=484 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>图六 </P>
<P>这个用缺省方式生成的插件类对于我们将要的代码并不是必需的，也可以用生成空插件的方式建立我们的项目，这样做只是为进一步说明Eclipse的插件结构。</P>
<P>项目生成之后，在我们的项目中会包含一个PdePlugin.java文件，它就是以缺省方式生成的插件类。注意到它继承了AbstractUIPlugin类，而AbstractUIPlugin类实现了org.eclipse.ui.plugin接口。事实上，所有的Eclipse插件都会有一个相应的实现plugin接口的类，这个类将是新插件的主类（类似于有main()函数的Java类），它负责管理插件的生存期。在我们的AbstractUIPlugin继承子类中，可以用singleton模式来保存在Eclipse中的生成的该插件的第一个也是唯一实例，一般来说，在该继承子类中也要实现一个getDefault()方法以返回当前插件的实例。而且，当Eclipse首次使用该插件的时候，这个主类将是第一个被调用的类，因此我们也可以在它的代码中执行一些初始化的工作。而且如果插件需要使用Preferences，Dialogs或Images资源，也可以通过这个类中的相应方法来得到它们的实例，如用其中的getDialogSettings()，getPreferenceStore()，getImageRegistry()方法。</P>
<P>但是象前面提到的，PdePlugin.java对下面的例子并不是必需的，我们不用对它进行任何修改。在我们第一个例子中的Weclome插件，根本就没有生成AbstractUIPlugin的继承子类，此时系统会自动为Weclome插件生成一个缺省的主类（类似于Java类构造函数，如果没有声明，系统会指定一个默认的构造函数）。</P>
<P>下面的代码是才真正实现了我们新插件的功能，假设这个插件名子是NoticeView：</P>
<P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
package com.nidapeng.eclipse.plugin.pde;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.runtime.CoreException;
import java.util.ResourceBundle;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
public class NoticeView extends ViewPart implements　
Runnable,IResourceChangeListener ,IResourceDeltaVisitor{
	private ResourceBundle resourceBundle;
	private Label label;
	private Display disp; 
	private String dispTxt;
	public NoticeView() {
    ResourcesPlugin.getWorkspace().addResourceChangeListener(this,
      IResourceChangeEvent.PRE_CLOSE
      | IResourceChangeEvent.PRE_DELETE
      | IResourceChangeEvent.PRE_AUTO_BUILD
      | IResourceChangeEvent.POST_AUTO_BUILD
      | IResourceChangeEvent.POST_CHANGE);
	}
	public static IWorkspace getWorkspace() {
		//ResourcesPlugin插件的主类！
 		return ResourcesPlugin.getWorkspace();
 	}
	public void createPartControl(Composite parent) {
   		label = new Label(parent, SWT.WRAP);
		label.setText("change your project status...");
         disp = Display.getDefault();
 	}
	public void setFocus() {
 	}
	// 实现IResourceChangeListener接口中的resourceChanged方法
	public void resourceChanged(IResourceChangeEvent event) {
  		IResource res = event.getResource();
  		switch (event.getType()) {
   			case IResourceChangeEvent.PRE_CLOSE :
    				dispTxt = res.getFullPath() + " is about to closed!";
    				break;
   			case IResourceChangeEvent.PRE_DELETE :
    				dispTxt = res.getFullPath() + " is about to be deleted!";
   				break;
   			case IResourceChangeEvent.POST_CHANGE :
    				try {
     				event.getDelta().accept(this);
    				} catch (CoreException e) {
    					 e.printStackTrace();
    				}
    				break;
   			case IResourceChangeEvent.PRE_AUTO_BUILD :
    				try {
     				event.getDelta().accept(this);
    				} catch (CoreException e) {	
     				e.printStackTrace();
    				}
    				break;
   			case IResourceChangeEvent.POST_AUTO_BUILD :
    				try {
     				event.getDelta().accept(this);
    				} catch (CoreException e) {
     					e.printStackTrace();
    				}
    				break;
  		}
  		disp.syncExec(this);
 	}
 	// 实现IResourceDeltaVisitor接口中的visit方法
 	public boolean visit(IResourceDelta delta) {
  		IResource res = delta.getResource();
  		switch (delta.getKind()) {
   		case IResourceDelta.ADDED :
    			dispTxt = "Resource "+res.getFullPath()+" was added.";
    			break;
   		case IResourceDelta.REMOVED:
    			dispTxt = "Resource "+res.getFullPath()+" was removed.";
   			break;
   		case IResourceDelta.CHANGED :
    			dispTxt = "Resource "+res.getFullPath()+" has changed.";
   			break;
  		}
  		return true; // visit the children
 	}
	// 实现Runnable接口中的run方法
 	public void run() {
  		try {
   			label.setText(dispTxt); 
  		} catch (Exception e) {
   			e.printStackTrace();
  		}
	}
}
</CODE></PRE></TD></TR></TBODY></TABLE></P>
<P>象上面的第一个Welcome插件，这个新插件同样继承了ViewPart，不同的是实现了三个接口：Runnable,IResourceChangeListener ,IResourceDeltaVisitor。其中的Runnable大家应该很熟悉：多线程的接口。而IResourceChangeListener和IResourceDeltaVisitor是Eclipse系统中的资源接口，这里的资源是指Eclipse中的项目或文件等。在下面运行NoticeView插件的过程中你可以通过添加、打开、删除项目或文件来触发这两个接口中的事件，并在我们的观察窗口中显示相关信息。</P>
<P>在程序中比较奇怪部分的是在resourceChanged()函数里面，并没有象大家想象的那样直接调用label.setText()方法来显示信息，而是调用了disp.syncExec(this)，其中的disp是Display类型的对象。这是因为resourceChanged()方法运行的线程和lable所在插件运行的Eclipse主线程并不是同一个线程，如果直接调用label.setText()方法，会抛出一个异常。</P>
<P>下面还需要对项目中的plugin.xml进行一些改动，主要就是加上扩展点声明：</P>
<P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;plugin
   id="com.nidapeng.eclipse.plugin.pde"
   name="Pde Plugin"
   version="1.0.0"
   provider-name="NIDAPENG"
   class="com.nidapeng.eclipse.plugin.pde.PdePlugin"&gt;
&lt;requires&gt;
   &lt;import plugin="org.eclipse.core.runtime"/&gt;
   &lt;import plugin="org.eclipse.core.resources"/&gt;
   &lt;import plugin="org.eclipse.ui"/&gt;
&lt;/requires&gt;
&lt;runtime&gt;
   &lt;library name="pde.jar"/&gt;
&lt;/runtime&gt;
&lt;extension
      id="NoticeView"
      name="Notice View"
      point="org.eclipse.ui.views"&gt;
   &lt;category
         name="Notice"
         id="com.nidapeng.eclipse.plugin.pde.category1"&gt;
   &lt;/category&gt;
   &lt;view
         name="Notice Resource View"
         category="com.nidapeng.eclipse.plugin.pde.category1"
         class="com.nidapeng.eclipse.plugin.pde.NoticeView"
         id="com.nidapeng.eclipse.plugin.pde.view1"&gt;
  &lt;/view&gt;
&lt;/extension&gt;
&lt;/plugin&gt;
</CODE></PRE></TD></TR></TBODY></TABLE></P>
<P>这个xml文件和Welcome插件的plugin.xml非常接近，这里就不做过多的说明了。</P>
<P>要运行这个插件，可以直接用Eclipse中的运行按钮，因为这个项目是一个Plug-in Project，此时项目会自动以Run-time Workbench方式运行。运行后，会生成一个和当前Eclipse完全一致的平台，在这个平台上可以直接运行NoticeView插件，查看这个插件到底会执行什么功能，也可以用直接Run-time Workbench方式调试插件。这里省去了安装插件，重启动Eclipse等过程，可以看到用PDE开发插件的过程比直接用Java开发环境简洁了很多！</P>
<P>Eclipse的开发不仅仅限于插件的开发，它还可以取代Java中的标准Swing，进行基于Java的独立应用程序GUI开发。它带来的好处是显而易见的：高速，资源占用低，跨平台，代码开放，有大公司的支持等等。</P>
<P>由于Eclipse目前还在开发阶段，笔者在用它调试程序时发现有些性能还不是十分的稳定，一些地方会遇到奇怪的问题，要求使用者能想一些办法解决。不过，以现在Eclipse的开发速度，相信过不了多久，它的各种功能会逐步完善。目前Eclipse虽然有种种不足，但瑕不掩玉，笔者对Eclipse的总体印象还是非常不错的，运行速度，资源占用都要好于IVJ，操作起来也大多顺手，而且即使在现阶段也很少有意外退出等重大的Bug发生，希望未来的Eclipse能真正达到IVJ的功能，VisualCafe的速度，成为广大程序员开发软件的一大利器！</P><img src ="http://www.blogjava.net/qq13367612/aggbug/17813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:04 <a href="http://www.blogjava.net/qq13367612/articles/17813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse插件开发 之 初步探索</title><link>http://www.blogjava.net/qq13367612/articles/17812.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 07:01:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17812.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17812.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17812.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17812.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17812.html</trackback:ping><description><![CDATA[随着Eclipse作为一个集成开发环境和富客户端(Rich Client)平台而广泛流行起来，更多的公司和个人进入到开发Eclipse插件的队伍中。你想过写一个你自己的Eclipse插件么？这篇文章中我将带领你开发一个简单的可视化插件。这里你可以学习Eclipse插件的体系结构，并且学着熟悉Plug-in Development Environment（PDE）。 <BR><BR>　　<B>简介</B><BR><BR>　　许多年以前，当我第一次仔细考察Eclipse时（我记得当时好像是2.0版本），我对它的完全免费印象非常深。它提供了很多非常不错的Java开发能力，但是当时并没有比那些商业版本好上多少。然而，真正吸引我的是我发现可以用我自己的代码随意扩展它的特性。事实上，并不需要特别的工具--Eclipse提供了所有可以用于自身开发的工具和框架。<BR><BR>　　从那以后，Eclipse开始在各方面成熟起来--它的设计更加改进了，它的结构变得更加强健且不失灵活，它的各种工具也变得更加强大和高效。它已经从一个工具集成框架变成了一个开发胖客户端(rich-client)程序的平台。这也证明了我心目中对它本身的基本设计理念的质量的评价。<BR><BR>　　扩展Eclipse需要你对可用的结构和工具的基本熟悉和了解。因为学习如何去做一件事情的最好方式就是去试着自己做做看，本篇文章将会帮助你使用插件开发环境PDE开发一个简单的Eclipse插件。当你学习一点Eclipse体系结构的背景信息之后，你将会使用PDE向导来创建一个新的插件，完成一个简单的工作台视图，并且测试你的工作看最后的结果。实现的具体细节不能一一说明了。为了完成这个工作，你需要获得最新的Eclipse SDK(3.1版本)，可以从 http://www.eclipse.org/downloads 获得一份免费的拷贝。<BR><BR>　　<B>所有的东西都是插件</B><BR><BR>　　从一个开发者的角度来说，Eclipse是一个开发各种客户端程序的平台。本身其是作为一个开发工具而产生的，现在它的范围已经扩展到包括各种胖客户端应用程序，以及非桌面环境，比如手持设备和嵌入式系统。为了支持如此大范围的应用，高度的可扩展性是非常必要的。每个基于Eclipse的程序都包含了多个组件，它们被称作为插件(plugins)，相互间通过预先定义的接口集合进行交互。插件通过一个很小的运行时层来进行管理，负责它们的发现和启动。从3.0版本开始，原来的运行时层实现被新的基于开放服务网关初始化(Open Services Gateway initiative, OSGi)所替代，从而提高了Eclipse向多个硬件和操作系统的移植能力，并且提供了对管理的执行环境的兼容性。因此，目前的Eclipse插件是作为OSGi的组件来开发的。<BR><BR>　　和其他的组件管理环境类似，每个Eclipse插件的运行时特性是在它的描述符中被指定的，运行时层使用描述符来配置插件的执行环境。在3.0版本以前，描述符是一个XML格式的文件，名为plugin.xml，在每个插件目录的根目录中保存。为了和OSGi运行时整合，插件一般被打包成JAR文件，并且它们的属性比如单一的标识符，版本号，运行时classpath和导出的包，被包含在它们的JAR manifest中（即META-INF/MANIFEST.MF）。然而，对于一般记录Eclipse插件的特性的描述符--插件扩展和扩展点--仍然留在plugin.xml文件中描述。<BR><BR>　　一个插件的扩展点基本上是它的组件配置点，使用XML Schema子集描述。一个完成某种抽象功能的插件，比如在工作台显示独立视图等，将会公布一个扩展点，指定每个实现必须完成什么才能被这个插件使用。这些一般需要包含简单的属性，比如窗口标题和图标路径，同时也包含实现具体接口的类名称。在这里的例子中，每个要提供一个视图实现的插件必须声明一个插件描述符属性的ID是org.eclipse.ui.views扩展点的扩展。这个扩展必须指定类实现接口的名为org.eclipse.ui.IViewPart。在运行时，工作台插件查找插件记录中所有的org.eclipse.ui.views的扩展并且将它们提供给用户作为可显示的视图。当用户选择打开某个视图时，工作台插件初始化指定在插件描述符中视图的实现类，并且通过接口org.eclipse.ui.IViewPart来和它交互。这个机制是Eclipse扩展性的基石。插件给其他的插件提供具体的实现，很多都是实现了自身高度抽象，并且将它们作为扩展点提供给其他的插件来完成。<BR><BR>　　P 1: plugin.xml的内容:<BR><BR>
<TABLE borderColor=#cccccc width="75%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD>＜?xml version="1.0" encoding="UTF-8"?＞<BR>＜?eclipse version="3.0"?＞<BR>　＜plugin＞<BR>　　＜extension point="org.eclipse.ui.views"＞<BR>　　　＜category id="com.developer.superview.category1" name="Developer.com"/＞<BR>　　　＜view category="com.developer.superview.category1" class="com.developer.superview.Superview" id="com.developer.superview.view1" name="Superview"/＞<BR>　　＜/extension＞<BR>　＜/plugin＞</TD></TR></TBODY></TABLE><BR>　　<B>插件开发环境</B><BR><BR>　　就像你所看到的一样，开发Eclipse程序的核心任务主要包含创建实现一个或者多个扩展的插件。理论上来说，没有东西会阻止你使用记事本，或者vi或者命令行中的javac来开发Eclipse插件（我想听听尝试过的人怎么说得！）。幸运的是，Eclipse拥有一个强大的工具集来使这一任务变得简单。插件开发环境PDE是作为Eclipse SDK的一个部分自由分发的，并且作为一个基于Eclipse的IDE工具的好范例而存在--它只是一些插件和它们的扩展的集合（事实上他们也留下了一些扩展点，你可以用这些扩展点来开发自己的PDE扩展）。<BR><BR>　　在PDE中，每个正在开发的插件都是被单个的Java工程所代表。插件工程具有一些独一无二的特性来标示自己。比如说它们每一个都有一个插件描述符（一个manifest和/或一个plugin.xml文件），一个基于描述符指定的依赖关系的动态classpath，特殊的编译器，和其他配置属性。PDE提供了一个插件创建向导，可以选择各种需要的部分创建插件工程。<BR><BR>　　PDE带有一个特别的多页编辑器来使得插件开发更加简单。插件Manifest编辑器用到3个文件--包含的manifest（META-INF/MANIFEST.MF），plugin.xml和build.properties.它允许你编辑所有必要的属性来描述一个插件--它的基本运行时要求，依赖，扩展，扩展点等等。当开发插件的时候你需要做更详细的了解。<BR><BR>　　因为Eclipse插件都是Java的工程，它们缺省都是逐步构建的，不需要特别的人工编译步骤。PDE也允许使用Ant来创建非自动编译的插件；你可以为你的插件创建一个Ant的build脚本（在Package Explorer中，右键点击你的plugin.xml并且选择PDE Tools -＞ Create Ant Build File），它提供了创建多个目标输出的方式（比如插件JAR包，源代码包等等）。<BR><BR>　　为了测试你的工作，PDE提供了一个特别的启动配置类型，允许你使用它的配置中包含的工作区插件来启动另外一个工作台实例（被称为运行时工作台）（也被称作为self－hosting--你不比将你的插件安装进一个外部的工作台来测试它们，你可以使用自己的开发工作台动态安装）。你的Eclipse启动配置将允许你指定你想包含的哪个插件，特殊的命令行参数，环境属性等等。<BR><BR>　　PDE也有一个强大的用户文档和扩展参考信息（Javadoc和扩展点文档）。因为它是和Eclipse在一个规则下分发的，所以它的代码也是完全开放的，并且缺省包含的SDK中。<BR><STRONG>创建简单的插件</STRONG> <BR><BR>　　为了对使用PDE开发插件有个更好的理解，你可以开发一个简单的工作台视图。它的功能是列出运行时工作台中所有的可用视图（你可以称它为超级视图）。当你这样做的时候，你可以使用这个身边的例子，检查插件Manifest编辑器的各个部分。<BR><BR>　　首先，启动你的Eclipse SDK，选择一个空工作区。当你关掉欢迎页面时，你应该缺省进入Java开发模式。第一步，使用新建插件向导来创建插件。然后，使用插件Manifest编辑器编辑其描述符，并且使用JDT来实现一个Java类。最后，在一个运行时工作台启动插件来看效果。好，开始：<BR><BR>　　1. 在main menu中，点击File-＞New-＞Project，然后选择Plug-in Project并且点击Next；<BR><BR>　　2. 在下一个向导页中，输入com.developer.superview作为工程名。点击Next；<BR><BR>　　3. 在此页中，保持所有的域为缺省值，点击Finish。当被问到是否转换到插件开发模式时，选择yes。这时，插件已经被创建了，并且你可以在插件Manifest编辑器中看到总览。<BR><BR>　　总览页面包含了一些一般属性，如插件的ID，版本，名称，提供者，插件类和平台过滤器。它还提供了到其他页面的链接，这些页面指定了插件内容，编译配置，和测试运行的链接以及导出插件（所有的和简单描述）。ID是必须的且必须为独一无二的。版本一般为3到4个部分组成，使用点号隔开的版本标识符(major.minor.service{.qualifier})。插件版本在你的平台插件开发向导中有详细记述。在这个练习里，你可以指定为缺省的1.0.0。姓名和提供者是可选的，只是被用来在产品配置里显示的标记。类属性也是可选的，目前它可以被用来代表一个单独的运行时插件实例，可以用来作为一个单独的对多个插件特定数据的访问点。在这个例子里，向导闯将了一个缺省的类实现，你可以在例子的任何代码里提到它。平台过滤器可以用来限制插件的平台可用性（这个例子里没有用到）。<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=left><IMG src="http://www.blogjava.net/images/blogjava_net/qq13367612/4168/o_001.gif" border=0></DIV></TD></TR></TBODY></TABLE><BR>　　依赖页面允许你指定其他一些你所依赖的插件，无论是编译的还是运行时的。增加一个插件依赖意味着被选择插件的所有Java包的导出，包含任何的扩展点，对你自己的代码都是可用的。你可以选择在你的SDK安装时增加任何可用插件，包括你的工作台（也就是说，其他你当前正在使用的插件）。<BR><BR>　　在我们这里例子里，你将把org.eclipse.core.runtime和org.eclipse.ui作为你的依赖。任何依赖都是可选的（确认你的代码需要它），你可以选择重新导入一个依赖（选择列表中的一个插件，并且点击属性…）。你可以请求某个Java包对你的类启动器可用，无论它是从何而来。这是一个高级开发主题在你的平台文档中有详细叙述。这个页面里，你可以做一些各种类型的依赖关系的分析，可以给你一个更加好的插件依赖的认识。 运行时页面允许你指定想导出的Java包(也就是说，在你的插件列表中使你的插件可见)。在这个列表中，你无须导出任何东西，因为你不提供任何的功能作为公共API可用。如果你要这么作，那你必须使得它们针对其衍生的插件可用（这是更加高级的开发主题了）。Classpath节是用来指定哪个类文件夹或者JAR文件应该作为你的运行时classpath，如果有多个的话（缺省只有你的插件的根目录是被包含在它的classpath里）。<BR><BR>　　扩展页面是你指定你所有的插件扩展的地方。它包含了一个通过你插件实现的扩展的树（你可以从列在你的依赖的插件中选择公布的扩展点），和一个详细的包含反映你的当前树选择的域的表单。要创建新的扩展元素，右键点击树中的元素，选择New子菜单。对元素的选择以及每个元素的属性集合，依赖于关联的扩展点。你可以通过右键点击树中的扩展的方式来获得你的扩展点文档，然后选择Show Description。事实上，为了继续我们的例子，我们将为超级视图实现增加一个新的扩展：<BR><BR>　　4. 点击Add。在New Extension对话框中，选择扩展点org.eclipse.ui.views。点击Finish。<BR><BR>　　5. 右键点击列表中的扩展；选择New-＞category。输入Developer.com作为名称（类型ID为com.developer.superview.category1 保持不变）。<BR><BR>　　6. 右键点击扩展，选择New-＞view，输入SuperView作为名称，com.developer.superview.category1作为分类（和在第５步中创建的类型ID匹配）。<BR><BR>　　7. 点击class链接。输入Superview作为类名，点击Finish。这将会创建一个新的实现所需接口的类，并且在Java编辑器中打开它。<BR><BR>　　你可以马上回到视图的开发中来。现在，激活插件Manifest编辑器，点击扩展点的yemi。如果可用，将会列出所有你的插件公布的扩展点。每个扩展点的细节都是可以使用扩展点方案编辑器来编辑的（这里不再详细叙述了）。<BR><BR>　　生成页面允许你对插件的生成配置进行指定（或者选择自定义生成来生成一个完整的自定义的生成过程，这个你需要自己实现）。这些信息将会被增量生成器（你的工程的生成路径也会相应的更新，这也是你不能直接更改而让PDE来为你做的原因）和一个Ant生成脚本所使用，你只能选择两者中的一个。在这个联系里，你无须特别的生成要求。若你要这样作，比如为你的视图使用一个自定制的图标，你必须保证它的目录是在二进制生成段中被检查过的，以使得它对你的代码在运行时可用。<BR><BR>　　MANIFEST.MF，plugin.xml，和build.properties允许你编辑相应文件的源代码。这个只对高级熟练的Eclipse开发者推荐使用。<BR><BR>　　现在你对插件Manifest编辑器比较熟悉了，我们可以继续我们的例子：<BR>8. 激活Superview.java编辑器。你可以看到，为了完成视图的实现，你必须实现最少两个方法：createPartControl(Composite)和setFocus()。这里，我就不详细讨论底层的API了。现在，你应该知道你要创建一个表式的可视化组件——表格查看器——来显示你的视图内容。你将配置它为一个内容提供者来给它操纵你的组件的能力（具体的说就是提取出你的模型结构元素来适应表格的包含），和一个标志提供者，来给予它使用适当的标志和可选图片来转化你的模型元素到表格项的能力。你也可以给它配置一个排序器来按照字母表顺序显示表项。最后，你给它一个输入--你的模型对象，即运行时可用的一组所有可用视图的描述符。完整实现如下：<BR><BR>　　List 2: SuperView.java(继承ViewPart类):<BR><BR>
<TABLE borderColor=#cccccc width="75%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD>
<P>package com.developer.superview;</P>
<P>import org.eclipse.jface.viewers.ArrayContentProvider;<BR>import org.eclipse.jface.viewers.LabelProvider;<BR>import org.eclipse.jface.viewers.TableViewer;<BR>import org.eclipse.jface.viewers.ViewerSorter;<BR>import org.eclipse.swt.widgets.Composite;<BR>import org.eclipse.ui.PlatformUI;<BR>import org.eclipse.ui.part.ViewPart;</P>
<P>public class SuperView extends ViewPart {<BR> private TableViewer viewer;<BR> <BR> <BR> public SuperView() {<BR>  super();<BR> }</P>
<P> public void createPartControl(Composite parent) {<BR>  viewer = new TableViewer(parent);<BR>  viewer.setContentProvider(new ArrayContentProvider()); <BR>  viewer.setLabelProvider(new LabelProvider());<BR>  viewer.setSorter(new ViewerSorter());<BR>  viewer.setInput(PlatformUI.getWorkbench().getViewRegistry().getViews());<BR> }</P>
<P> public void setFocus() {<BR>  viewer.getTable().setFocus(); <BR> }</P>
<P>}</P></TD></TR></TBODY></TABLE><BR>　　这已经足够运行这个例子了，保存，然后：<BR><BR>　　9. 在你的Package Explore里右键点击，选择Run As -＞ Eclipse Application。这将创建一个新的Eclipse使用缺省值的启动配置，启动它。<BR><BR>　　10. 当运行时工作台出现的时候，你应该看到欢迎视图。点击Window-＞Show View-＞Other…选择Developer.com-＞Superview。点击OK。<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=left><IMG src="http://www.blogjava.net/images/blogjava_net/qq13367612/4168/o_002.gif" border=0></DIV></TD></TR></TBODY></TABLE><BR>　　你应该看到的是Superview显示的形式是：视图＜视图号＞。这作为一个例子来演示PDE使用已经足够了。然而，如果你想更深一步进入JFace的学习，你可以学着看能否把这个界面做的更加人性化一点。<BR><BR>　　在这里，表格里每条记录代表一个工作台视图；你提供的模型对象作为该查看器的输入为一组视图的描述符（IViewDescriptor），你使用的内容提供者将任何数组对象转化为一个它的元素列表（父子关系）。但是，标志提供者只是简单的使用了每个元素的toString（）方法来作为其标记。接口IViewDescriptor提供方法来获得视图标号（getLabel（）），甚至可以获得视图的图标图像（getImageDescriptor（））。你所要做的是重载两个标记提供者的方法：<BR>11. 关闭运行时工作台。在Superview.java编辑器中，子类new LabelProvider()如列表3所示：<BR><BR>　　P 3: SuperView.java(重写LabelProvider类部分方法):<BR><BR>
<TABLE borderColor=#cccccc width="75%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD>
<P>package com.developer.superview;</P>
<P>import org.eclipse.swt.graphics.Image;<BR>import java.util.HashMap;<BR>import java.util.Iterator;<BR>import java.util.Map;</P>
<P>import org.eclipse.jface.resource.ImageDescriptor;<BR>import org.eclipse.jface.viewers.ArrayContentProvider;<BR>import org.eclipse.jface.viewers.LabelProvider;<BR>import org.eclipse.jface.viewers.TableViewer;<BR>import org.eclipse.jface.viewers.ViewerSorter;<BR>import org.eclipse.swt.widgets.Composite;<BR>import org.eclipse.ui.PlatformUI;<BR>import org.eclipse.ui.part.ViewPart;<BR>import org.eclipse.ui.views.IViewDescriptor;</P>
<P>public class SuperView extends ViewPart {<BR> private TableViewer viewer;<BR>  <BR> public SuperView() {<BR>  super();<BR> }</P>
<P> public void createPartControl(Composite parent) {<BR>  viewer = new TableViewer(parent);<BR>  viewer.setContentProvider(new ArrayContentProvider()); <BR>  viewer.setLabelProvider(new MoreLabelProvider());<BR>  viewer.setSorter(new ViewerSorter());<BR>  viewer.setInput(PlatformUI.getWorkbench().getViewRegistry().getViews());<BR> }</P>
<P> public void setFocus() {<BR>  viewer.getTable().setFocus(); <BR> }<BR> <BR>class MoreLabelProvider extends LabelProvider{<BR> private final Map images = new HashMap();<BR> public String getText(Object element)<BR> {<BR>  return ((IViewDescriptor) element).getLabel();<BR> }<BR> public Image getImage(Object element) <BR> {<BR>  Image image = (Image) images.get(element);<BR>  if (image == null) <BR>  {<BR>   IViewDescriptor view = (IViewDescriptor) element;<BR>   ImageDescriptor desc = view.getImageDescriptor();<BR>   image = desc.createImage();<BR>   images.put(element, image); <BR>  }<BR>  return image; <BR> }<BR> public void dispose() <BR> {  <BR>  for (Iterator i = images.values().iterator(); i.hasNext();) <BR>    ((Image) i.next()).dispose();    <BR> }<BR>}<BR> <BR>}<BR></P></TD></TR></TBODY></TABLE><BR>　　这里，你已经重载了getText(Object)方法来返回元素（一个IViewDescriptor的实例）的标号。为了使得看起来更加好看，你可以重载getImage(Object)方法来返回每个视图的文字标号的关联图标。这里比较复杂一点了，你必须学习JFace和SWT，你将会发现图像(org.eclipse.swt.graphics.Image)是操作系统的资源，必须被程序来管理。然而，IViewDescriptor只是返回了一个ImageDescriptor而不是图像本身。一个图像标识符可能被用来创建一个Image实例，但是必须能够在不需要的时候释放。由于这个原因，你必须跟踪创建的所有的Image实例并在不需要的时候释放掉它。<BR><BR>　　要看最后的输入，重新启动运行时工作台。（Ctrl + F11）<BR><BR>
<TABLE width="90%" align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=left><IMG src="http://www.blogjava.net/images/blogjava_net/qq13367612/4168/o_003.gif" border=0></DIV></TD></TR></TBODY></TABLE><BR>　　<B>打包并且分发插件</B><BR><BR>　　即使你可能完成了插件的开发和测试，你也需要将其从开发环境里导出分发到用户手中。幸运的是，Eclipse没有把这个交给你自己完成。你可以使用导出向导，它出现在你的插件编辑器的总览页面里。它将创建一个分发包文件，包含你的插件代码和资源。用户只要将其解压在他们的Eclipse安装里，如果它们的环境的所有依赖关系都满足，那么Eclipse将会在需要时自动发现和激活你的插件。<BR><BR>　　这种形式的分发和安装被成为未管理的--如果你将来进行更新的话，你将发现和安装你的插件的更新的任务交给了用户。一个更加有组织的方法时将你的插件组织成feature。feature是一组同时安装和管理的插件。在集合插件之外，feature包含了一些信息，这些信息允许Eclipse更新管理器来定位公布的更新，并且发现新的关联的feature。这样的发布在某个web目录下的更新叫做更新站点。PDE提供了向导和编辑器来支持feature和更新站点的开发。<BR><BR>　　如果你开发整个应用程序而不只是插件和feature，需要已有的基于Eclipse的产品的安装，你需要使用产品配置编辑器（Product Configuration editor）和产品导出向导（Eclipse Product export wizard），把你的应用作为一个独立的Eclipse产品。这个高级主题可以独立成为一篇文章了。<BR><BR>　　<B>结论</B><BR><BR>　　Eclipse是一个伟大的工具和胖客户端应用平台，不单提供了它的免费开放组件，页提供了它自身的开放实现。在Eclipse中，所有功能都封装成插件，它们一个个使用良定义的扩展点结合在一起。它的PDE提供了功能强大的工具和向导来帮助你开发你自己的插件。更重要的是，它提供了整个环节的开发支持，包括分发和后期产品维护。<img src ="http://www.blogjava.net/qq13367612/aggbug/17812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:01 <a href="http://www.blogjava.net/qq13367612/articles/17812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Eclipse 插件开发</title><link>http://www.blogjava.net/qq13367612/articles/17811.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 02 Nov 2005 06:56:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17811.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17811.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17811.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17811.html</trackback:ping><description><![CDATA[<SPAN class=atitle2>如何创建、调试和安装插件</SPAN>
<P><A name=1><SPAN class=atitle2>基于插件的体系结构</SPAN></A><BR>Eclipse 平台是 IBM 向开发源码社区捐赠的开发框架，它之所以出名并不是因为 IBM 宣称投入开发的资金总数 ― 4 千万美元 ― 而是因为如此巨大的投入所带来的成果：一个成熟的、精心设计的以及可扩展的体系结构。Eclipse 的价值是它为创建可扩展的集成开发环境提供了一个开放源码平台。这个平台允许任何人构建与环境和其它工具无缝集成的工具。</P>
<P>工具与 Eclipse 无缝集成的关键是 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">插件</I>。除了小型的运行时内核之外，Eclipse 中的所有东西都是插件。从这个角度来讲，所有功能部件都是以同等的方式创建的。从这个角度来讲，所有功能部件都是以同等的方式创建的。 </P>
<P>但是，某些插件比其它插件更重要些。Workbench 和 Workspace 是 Eclipse 平台的两个必备的插件 ― 它们提供了大多数插件使用的扩展点，如图 1 所示。插件需要扩展点才可以插入，这样它才能运行。</P>
<P><A name=figure1><B>图 1. Eclipse Workbench 和 Workspace：必备的插件支持 </B></A><BR><IMG height=260 alt="Eclipse Workbench" src="http://www-128.ibm.com/developerworks/cn/java/os-ecplug/figure1.gif" width=369 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>Workbench 组件包含了一些扩展点，例如，允许您的插件扩展 Eclipse 用户界面，使这些用户界面带有菜单选择和工具栏按钮；请求不同类型事件的通知；以及创建新视图。Workspace 组件包含了可以让您与资源（包括项目和文件）交互的扩展点。</P>
<P>当然，其它插件可以扩展的 Eclipse 组件并非只有 Workbench 和 Workspace。此外，还有一个 Debug 组件可以让您的插件启动程序、与正在运行的程序交互，以及处理错误 ― 这是构建调试器所必需的。虽然 Debug 组件对于某些类型的应用程序是必需的，但大多数应用程序并不需要它。</P>
<P>还有一个 Team 组件允许 Eclipse 资源与版本控制系统（VCS）交互，但除非您正在构建 VCS 的 Eclipse 客户机，否则 Team 组件，就象 Debug 组件一样，不会扩展或增强它的功能。</P>
<P>最后，还有一个 Help 组件可以让您提供应用程序的联机文档和与上下文敏感的帮助。没有人会否认帮助文档是专业应用程序必备的部分，但它并不是插件功能的必要部分。</P>
<P>上述每个组件提供的扩展点都记录在 Eclipse Platform Help 中，该帮助在 Platform Plug-in Developer 指南的参考部分中。乍一看，尤其是 API 参考大全的 Workbench 部分，一开始会令人望而却步。我们不会深入了解众多可用扩展点的详细信息，而只是粗略地看一个简单插件及其组件。</P>
<P><A name=2><SPAN class=atitle2>插件简介</SPAN></A><BR>创建插件最简单的方法是使用 Plug-in Development Environment（PDE）。PDE 和 Java Development Tooling（JDT）IDE 是 Eclipse 的标准扩展。PDE 提供了一些向导以帮助创建插件，包括我们将在这里研究的“Hello, world”示例。</P>
<P>从 Eclipse 菜单，选择 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">File=>New=>Other</B>（或按 Ctrl-N），然后选择 Select 对话框左边的 Plug-in Development 向导。在 Select 对话框的右边，选择 Plug-in Project。按 Next。在下一屏上，输入项目名称；我使用了 <CODE>com.example.hello</CODE> 。再次按 Next。在下一屏上，请注意，插件标识就与项目名称相同。使用项目名称作为插件标识可以将该插件与另一个插件的名称发生冲突的机会减到最小。再按一次 Next。下一屏让您选择是手工创建初始插件代码，还是运行代码生成向导。保留代码生成向导的缺省选项，选择“Hello, World”，然后按 Next，如图 2 所示。 </P>
<P><A name=figure2><B>图 2. 选择“Hello, World”代码生成向导 </B></A><BR><IMG height=500 alt=新插件 src="http://www-128.ibm.com/developerworks/cn/java/os-ecplug/figure2.gif" width=525 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>下一屏要求一些附加信息。请注意这一屏上的信息：它包含了插件名称、版本号、提供者名称和类名。这些是关于插件的重要信息，我们将在稍后研究。可以接受向导提供的缺省值。按 Next。在下一屏幕上，接受包名、类名和消息文本的缺省值。选择“Add the action set to the resource perspective”复选框。按 Finish。</P>
<P>如果接到通知：向导需要启用某些其它插件才能完成，那么按 OK。</P>
<P>过一会儿，向导将完成，而在您的工作区中将会有一个新的项目，名为 <CODE>com.example.hello</CODE> ，如图 3 所示。 </P>
<P><A name=figure3><B>图 3. PDE 透视图：Welcome to Hello Plug-in </B></A><BR><IMG height=450 alt="PDE 透视图" src="http://www-128.ibm.com/developerworks/cn/java/os-ecplug/figure3.gif" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>在 Package Explorer 中，工作台的左边是向导创建的一些东西的概述。大多数项都不引人关注：包括项目类路径中的许多 <CODE>.jar</CODE> 文件（这些包括插件和 Java 运行时所需的 Eclipse 类）、一个图标文件夹（包含了工具栏按钮的图形），以及 <CODE>build.properties</CODE> 文件（包含自动构建脚本所使用的变量）。 </P>
<P>这里最有意思的东西是 src 文件夹，它包含了插件和 plugin.xml 文件的源代码 ― plug-in.xml 是插件的清单文件。我们将先查看 plugin.xml。</P>
<P><A name=3><SPAN class=atitle2>插件清单文件</SPAN></A><BR>插件清单文件 plugin.xml 包含了 Eclipse 将插件集成到框架所使用的描述信息。缺省情况下，当第一次创建插件时，会在清单编辑器区域中打开 plugin.xml。编辑器底部的选项卡让您可以选择关于插件的不同信息集合。Welcome 选项卡显示了消息“Welcome to Hello Plug-In”，并且简要讨论了所使用的模板和关于使用 Eclipse 实现插件的提示。选择“Source”选项卡可以让您查看 plugin.xml 文件的完整源代码。</P>
<P>让我们看看插件清单文件的各个部分。首先是关于插件的常规信息，包括它的名称、版本号、实现它的类文件的名称和 <CODE>.jar</CODE> 文件名。 </P><A name=code1><B>清单 1. 插件清单文件 ― 常规信息</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
<?xmlversion="1.0" encoding="UTF-8"?>
<plugin
   id="com.example.hello"
   name="Hello Plug-in"
   version="1.0.0"
   provider-name="EXAMPLE"
   class="com.example.hello.HelloPlugin">

   <runtime>
      <library name="hello.jar"/>
   </runtime>
  </CODE></PRE></TD></TR></TBODY></TABLE>
<P>接着，列出了我们的插件所需的插件：</P><A name=code2><B>清单 2. 插件清单文件 ― 必需的插件</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
   <requires>
      <import plugin="org.eclipse.core.resources"/>
      <import plugin="org.eclipse.ui"/>
   </requires>
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>列出的第一个插件 <CODE>org.eclipse.core.resources</CODE> 是工作区插件，但实际上我们的插件并不需要它。第二个插件 <CODE>org.eclipse.ui</CODE> 是工作台。我们需要工作台插件，因为我们将扩展它的两个扩展点，正如后面的 extension 标记所指出的。 </P>
<P>第一个 extension 标记拥有点属性 <CODE>org.eclipse.ui.actionSets</CODE> 。操作集合是插件添加到工作台用户界面的一组 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">基值</I>― 即，菜单、菜单项和工具栏。操作集合分组了基值，这样用户可以更方便地管理它们。例如，我们的 Hello 插件的菜单和工具栏项将出现在 Resource 透视图中，因为当在运行代码生成向导时，我们做了这样的选择。如果用户要更改它，可以使用 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Window=>Customize Perspective</B>菜单选项从要在 Resource 透视图中显示的项中除去“Sample Action Set”。 </P>
<P><A name=figure4><B>图 4. 定制 Resource 透视图 </B></A><BR><IMG height=453 alt="Resource 透视图" src="http://www-128.ibm.com/developerworks/cn/java/os-ecplug/figure4.gif" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>操作集合包含了两个标记： <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">menu 标记</I>（描述菜单项应该出现在工作台菜单的什么位置，以及如何出现）和 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">action 标记</I>（描述它应该做什么）― 尤其是 action 标记标识了执行操作的类。注：这个类不是上面列出的插件类。 </P><A name=code3><B>清单 3. 操作集合</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
   <extension
         point="org.eclipse.ui.actionSets">
      <actionSet
            label="Sample Action Set"
            visible="true"
            id="com.example.hello.actionSet">
         <menu
               label="Sample &Menu"
               id="sampleMenu">
            <separator
                  name="sampleGroup">
            </separator>
         </menu>
         <action
               label="&Sample Action"
               icon="icons/sample.gif"
               class="com.example.hello.actions.SampleAction"
               tooltip="Hello, Eclipse world"
               menubarPath="sampleMenu/sampleGroup"
               toolbarPath="sampleGroup"
               id="com.example.hello.actions.SampleAction">
         </action>
      </actionSet>
   </extension>
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>许多菜单和操作属性的目的相当明显 ― 例如，提供工具提示文本和标识工具栏项的图形。但还要注意 action 标记中的 <CODE>menubarPath</CODE> ：这个属性标识了 menu 标记中定义的哪个菜单项调用 action 标记中定义的操作。有关这个和其它工作台扩展点的详细信息，请参考 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Platform Plug-in Developer Guide</I>，尤其是“Plugging into the workbench”章节（可以从 Eclipse 的帮助菜单中获取该指南）。 </P>
<P>由于我们选择了将插件添加到 Resource 透视图，于是生成了第二个 extension 标记。这个标记会导致当 Eclipse 第一次启动并装入我们的插件时，将插件添加到 Resource 透视图。</P><A name=code4><B>清单 4. extension 标记</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
   <extension
         point="org.eclipse.ui.perspectiveExtensions">
      <perspectiveExtension
            targetID="org.eclipse.ui.resourcePerspective">
         <actionSet
               id="com.example.hello.actionSet">
         </actionSet>
      </perspectiveExtension>
   </extension>
</plugin>
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>如果忽略这最后一个 extension，用户就需要使用 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Window=>Customize Perspective</B>将插件添加到 Resource（或其它）透视图。 </P>
<P><A name=4><SPAN class=atitle2>插件源代码</SPAN></A><BR>代码生成向导生成了两个 Java 源文件，打开 PDE Package Explorer 中的 src 文件夹就可以看到它们。第一个文件 <CODE>HelloPlugin.java</CODE> 是插件类，它继承了 <CODE>AbstractUIPlugin</CODE> 抽象类。 <CODE>HelloPlugin</CODE> 负责管理插件的生命周期，在更为扩展的应用程序中，它负责维护诸如对话框设置和用户首选项等内容。 <CODE>HelloPlugin</CODE> 要做的事就这么多： </P><A name=code5><B>清单 5. HelloPlugin</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
packagecom.example.hello.actions;

import org.eclipse.ui.plugin.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.resources.*;
import java.util.*;

/**
 * The main plugin class to be used in the desktop.
 */
public class HelloPlugin extends AbstractUIPlugin {
      //The shared instance.
      private static HelloPlugin plugin;
      //Resource bundle.
      private ResourceBundle resourceBundle;

      /**
       * The constructor.
       */
      public HelloPlugin(IPluginDescriptor descriptor) {
            super(descriptor);
            plugin = this;
            try {
                  resourceBundle= ResourceBundle.getBundle(
                       "com.example.hello.HelloPluginResources");
            } catch (MissingResourceException x) {
                  resourceBundle = null;
            }
      }

      /**
       * Returns the shared instance.
       */
      public static HelloPlugin getDefault() {
            return plugin;
      }

      /**
       * Returns the workspace instance.
       */
      public static IWorkspace getWorkspace() {
            return ResourcesPlugin.getWorkspace();
      }

      /**
       * Returns the string from the plugin's resource bundle,
       * or 'key' if not found.
       */
      public static String getResourceString(String key) {
            ResourceBundle bundle= HelloPlugin.getDefault().getResourceBundle();
            try {
                  return bundle.getString(key);
            } catch (MissingResourceException e) {
                  return key;
            }
      }

      /**
      * Returns the plugin's resource bundle,
      */
      public ResourceBundle getResourceBundle() {
          return resourceBundle;
      }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>第二个源文件 <CODE>SampleAction.java</CODE> 包含的类将执行在清单文件的操作集合中指定的操作。 <CODE>SampleAction</CODE> 实现了 <CODE>IWorkbenchWindowActionDelegate</CODE> 接口，它允许 Eclipse 使用插件的代理，这样不是在万不得已的情况下，Eclipse 就无需装入插件（这项优化工作使在装入插件时发生内存和性能方面的问题降到最低）。 <CODE>IWorkbenchWindowActionDelegate</CODE> 接口方法使插件可以与代理进行交互： </P><A name=code6><B>清单 6. IWorkbenchWindowActionDelegate 接口方法</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
package com.example.hello.actions;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.jface.dialogs.MessageDialog;

/**
 * Our sample action implements workbench action delegate.
 * The action proxy will be created by the workbench and
 * shown in the UI. When the user tries to use the action,
 * this delegate will be created and execution will be
 * delegated to it.
 * @see IWorkbenchWindowActionDelegate
 */
public class SampleAction implements IWorkbenchWindowActionDelegate {
      private IWorkbenchWindow window;
      /**
       * The constructor.
       */
      public SampleAction() {
      }

      /**
       * The action has been activated. The argument of the
       * method represents the 'real' action sitting
       * in the workbench UI.
       * @see IWorkbenchWindowActionDelegate#run
       */
      public void run(IAction action) {
            MessageDialog.openInformation(
                  window.getShell(),
                  "Hello Plug-in",
                  "Hello, Eclipse world");
      }

      /**
       * Selection in the workbench has been changed. We
       * can change the state of the 'real' action here
       * if we want, but this can only happen after
       * the delegate has been created.
       * @see IWorkbenchWindowActionDelegate#selectionChanged
       */
      public void selectionChanged(IAction action, ISelection selection) {
      }

      /**
       * We can use this method to dispose of any system
       * resources we previously allocated.
       * @see IWorkbenchWindowActionDelegate#dispose
       */
      public void dispose() {
      }

      /**
       * We will cache window object in order to
       * be able to provide parent shell for the message dialog.
       * @see IWorkbenchWindowActionDelegate#init
       */
      public void init(IWorkbenchWindow window) {
            this.window = window;
      }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=5><SPAN class=atitle2>运行和调试插件</SPAN></A><BR>当开发 Eclipse 的插件时，必须停止 Eclipse 并用新的插件重新启动它以便进行测试和调试，这很笨拙。幸好，Eclipse PDE 提供了一个自托管（self-hosted）的开发环境，它让您无需将插件安装在工作台的单独实例中即可运行。</P>
<P>要运行 Hello 插件，选择 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Run=>Run As=>Run-time Workbench</B>来启动另一个 Workbench 实例，而该实例添加了插件的菜单选项和工具栏，如图 5 所示。 </P>
<P><A name=figure5><B>图 5. 在运行时工作台中运行的 Hello 插件 </B></A><BR><IMG height=448 alt="Hello 插件" src="http://www-128.ibm.com/developerworks/cn/java/os-ecplug/figure5.gif" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml"> </P>
<P>我们可以通过单击工具栏按钮或从“Sample Menu”菜单激活插件。任何一种方法都会生成一个框，其标题是“Hello Plug-in”，内容是“Hello, Eclipse world”，以及一个 OK 按钮，按该按钮可以关闭这个框。</P>
<P>通过选择 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Run=>Debug As=>Run-time Workbench</B>，按类似的方法调试插件。这次，当插件在第二个工作台实例中运行时，我们可以在最初的工作台中单步执行源代码，以及检查变量等。 </P>
<P>一旦插件经过测试并准备发布，我们就需要将它适当打包，以便在 Eclipse 中安装。</P>
<P><A name=6><SPAN class=atitle2>打包插件</SPAN></A><BR>Eclipse 在启动时会查看其插件目录来确定要装入哪些插件。要安装插件，我们需要在插件目录中创建一个子目录，并将程序文件和清单文件复制到那里。建议目录名称能表示插件的标识，并且后面跟下划线和版本号，但是这种做法不是必需的。假设 Eclipse 安装在 C:\eclipse 中；我们要创建一个目录：</P>
<P><CODE>C:\eclipse\plugins\com.example.hello_1.0.0. </CODE></P>
<P>按照 Java 程序的标准，我们的程序文件需要归档到 <CODE>.jar</CODE> 文件中 — 我们的插件清单文件，您也许记得它包含这个项： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
   <runtime>
      <library name="hello.jar"/>
   </runtime>
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>要创建 <CODE>hello.jar</CODE> 文件，我们可以通过突出显示项目名称，并从 Eclipse 菜单选择 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">File=>Export</B>，以导出插件文件。选择 JAR 文件作为导出方式，按 Next，然后浏览到我们为它创建的目录。下一步，我们还需要将 plugin.xml 文件复制到这个目录。也可以使用 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">File=>Export</B>菜单选项（但请要记住选择 File System 作为导出目的地）。 </P>
<P>这就是安装插件所需的全部操作，但您将需要停止并重新启动 Eclipse，以便能识别这个新的插件。从帮助菜单中选择“About Eclipse Platform”，可以找到关于已安装插件的信息，包括版本号。在出现的屏幕上有一个按钮是 Plug-in Details；向下滚动列表来寻找 Hello 插件及其版本号。</P>
<P><A name=7><SPAN class=atitle2>更新插件版本</SPAN></A><BR>在目录名称中包含版本号的目的是允许在同一台机器上共存某个插件的多个版本（每次只装入一个版本）。我们可以通过创建一个 Hello 插件的已更新版本来看看这是如何工作的：例如，将 plugin.xml 文件中的版本号更改成“1.0.1”，然后将 <CODE>SampleAction.java</CODE> 中的文本更改成“New and improved Hello, Eclipse world”。从 Eclipse 菜单中选择 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Project=> Rebuild All</B>。下一步，将项目文件以 JAR 形式导出到新的插件目录，例如， <CODE>com.example.hello_1.0.1</CODE> 。将修订过的 plugin.xml 文件复制到同一个目录中。当停止并重新启动 Eclipse 时，只会装入已更新的插件。 </P>
<P><A name=8><SPAN class=atitle2>插件片段和功能部件</SPAN></A><BR>Eclipse 由插件组成，但在开发 Eclipse 的插件时，还要慎重考虑另外两个级别的组件 ― 插件片段和功能部件。</P>
<P>插件 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">片段</I>（如名称所暗示的）是完整插件的组成部分 ― <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">目标</I>插件。片段提供的功能与目标插件的功能合并。片段可以用于将插件本地化成各种语言；在无需形成一个全新发行版的情况下，以增量形式将功能部件添加到现有插件，或者提供特定于平台的功能。在许多方面，片段与插件一样。主要的区别就是片段没有插件类 ― 片段的生命周期由其目标插件管理。此外，片段的清单文件叫作 fragment.xml，它列出了目标插件的标识和版本号，以及片段的标识和版本号。 </P>
<P>另一方面，插件 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">功能部件</I>根本不包含编码。在 Eclipse 体系结构术语中，功能部件是将一组相关插件打包到完整的产品中。例如，JDT 是包含了象 Java 编辑器、调试器和控制台这样的插件的功能部件。名为 feature.xml 的清单文件描述了一个功能部件归档文件。在其中，该清单文件包含了对该功能部件所包含的插件和其它资源的引用、关于如何更新该功能部件的信息、版权信息和许可证信息。 </P>
<P>在 Eclipse 中， <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">主功能部件</I>设置了 Eclipse 平台的外观。主功能部件旨在确定诸如给予 Eclipse 其身份的闪屏和其它特征之类的东西。Eclipse 只允许一个主功能部件。用这种方式，通过创建一组插件，将它们打包到功能部件中，并且使这个功能部件成为主功能部件，就可以重新创建 Eclipse 的品牌，并将它用于创建全新且不同的产品。如果从 Eclipse.org 下载，缺省主功能部件是 <CODE>eclipse.org.platform</CODE> 。 </P>
<P><A name=9><SPAN class=atitle2>后续步骤</SPAN></A><BR>在插件的介绍里我们只是稍微了解一些插件的必要用法。学习插件的更多知识的最佳参考资料是 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Plug-in Developer's Guide</I>，可以从 Eclipse 中的帮助菜单中获得该指南。该文档包含了编程指南、Eclipse API 和插件扩展点的参考大全、Eclipse.org 上可用的编程示例的指南，以及常见问题列表。另一个优秀参考资料是 Eclipse 本身的源代码。根据您的兴趣，您也许想要查找一些示例，以了解不同工作台功能部件（如视图和编辑器）是如何扩展的，或者如何使用 SWT（Eclipse 图形 API）。此外，下面的 <A href="http://www-128.ibm.com/developerworks/cn/java/os-ecplug/index.html#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">参考资料</A>可以帮助您学到更多知识。 </P>
<P><A name=resources><SPAN class=atitle2>参考资料 </SPAN></A>
<UL>
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www.ibm.com/developerworks/library/os-ecplug/index.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">英文原文</A>. <BR><BR>
<LI>可以从 <A href="http://www.eclipse.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Eclipse 项目网站</A>获得 Eclipse 的文档、文章以及下载 Eclipse。 <BR><BR>
<LI>浏览完整的 <A href="http://eclipse-plugins.2y.net/eclipse/index.jsp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Eclipse 插件列表</A>。 <BR><BR>
<LI>还可以获得更多的 <A href="http://www.improve-technologies.com/pages/Java/IDE/Eclipse/Plug-ins/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">插件信息（法语）</A>。 <BR><BR>
<LI>可以从以下 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">developerWorks</I>文章中学到更多 Eclipse 知识： 
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">
<LI>David Gallardo 的另一篇文章“ <A href="http://www.ibm.com/developerworks/opensource/library/os-ecov/">Getting started with the Eclipse Platform</A>”（ <I>developerWorks</I>，2002 年 11 月） 
<LI>“ <A href="http://www.ibm.com/developerworks/opensource/library/os-swing/">Plug a Swing-based development tool into Eclipse</A>”（ <I>developerWorks</I>，2002 年 10 月） 
<LI>“ <A href="http://www.ibm.com/developerworks/opensource/library/os-i18n/">Internationalizing your Eclipse plug-in</A>”（ <I>developerWorks</I>，2002 年 6 月） 
<LI>“ <A href="http://www.ibm.com/developerworks/opensource/library/os-i18n2/">Testing your internationalized Eclipse plug-in</A>”（ <I>developerWorks</I>，2002 年 7 月） 
<LI>“ <A href="http://www.ibm.com/developerworks/library/x-wxxm13/">Working XML: Use Eclipse to build a user interface for XM</A>”（ <I>developerWorks</I>，2002 年 10 月） 
<LI>“ <A href="http://www.ibm.com/developerworks/linux/library/l-erick.html">采访 Marc Erikson：Eclipse 代码捐赠</A>”（ <I>developerWorks</I>，2001 年 11 月） 
<LI>“ <A href="http://www.ibm.com/developerworks/opensource/library/os-plat/">Working the Eclipse Platform</A>”（ <I>developerWorks</I>，2001 年 11 月） 
<LI>“ <A href="http://www.ibm.com/developerworks/library/i-wsad/">Getting to know WebSphere Studio Application Developer</A>”（ <I>developerWorks</I>，2001 年 11 月） 
<LI>“ <A href="http://www.ibm.com/developerworks/library/i-oopsla/">Help for reusing your assets</A>”（ <I>developerWorks</I>，2001 年 11 月） 
<LI>“ <A href="http://www.ibm.com/developerworks/library/j-nativegui/">Create native, cross-platform GUI applications</A>”（ <I>developerWorks</I>，2002 年 4 月） </LI></UL><BR>
<LI>有关插件开发的更多详细信息，请参阅 <A href="http://www.eclipse.org/articles" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Eclipse.org 站点上的文章</A>。 <BR><BR>
<LI>请在 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">developerWorks</I>上的 <A href="http://www-124.ibm.com/developerworks/oss/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">开放源码项目专区</A>和 <A href="http://www.ibm.com/developerworks/java" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">Java 技术专区</A>中查找您需要的参考资料。 <BR></LI></UL><img src ="http://www.blogjava.net/qq13367612/aggbug/17811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-02 14:56 <a href="http://www.blogjava.net/qq13367612/articles/17811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse及其插件介绍和下载</title><link>http://www.blogjava.net/qq13367612/articles/17167.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Fri, 28 Oct 2005 06:21:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17167.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17167.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17167.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17167.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17167.html</trackback:ping><description><![CDATA[0.Eclipse下载<BR>EMF,GEF - Graphical Editor Framework,UML2,VE - Visual Editor都在这里下载<BR><A href="http://www.eclipse.org/downloads/index.php">http://www.eclipse.org/downloads/index.php</A><BR> <BR>0.5.lomboz J2EE插件,开发JSP,EJB<BR><A href="http://forge.objectweb.org/projects/lomboz">http://forge.objectweb.org/projects/lomboz</A><BR>1.MyEclipse J2EE开发插件，支持SERVLET/JSP/EJB/数据库操纵等 <BR><A href="http://www.myeclipseide.com/">http://www.myeclipseide.com</A><BR> <BR>2.Properties Editor  编辑java的属性文件，并可以自动存盘为Unicode格式 <BR><A href="http://propedit.sourceforge.jp/index_en.html">http://propedit.sourceforge.jp/index_en.html</A> <BR>  <BR>3.Colorer Take  为上百种类型的文件按语法着色 <BR><A href="http://colorer.sourceforge.net/">http://colorer.sourceforge.net/</A> <BR>  <BR>4.XMLBuddy 编辑xml文件<BR><A href="http://www.xmlbuddy.com/">http://www.xmlbuddy.com</A> <BR>  <BR>5.Code Folding  加入多种代码折叠功能（比eclipse自带的更多） <BR><A href="http://www.coffee-bytes.com/servlet/PlatformSupport">http://www.coffee-bytes.com/servlet/PlatformSupport</A> <BR>  <BR>6.Easy Explorer  从eclipse中访问选定文件、目录所在的文件夹 <BR><A href="http://easystruts.sourceforge.net/">http://easystruts.sourceforge.net/</A> <BR>  <BR>7.Fat Jar 打包插件，可以方便的完成各种打包任务，可以包含外部的包等 <BR><A href="http://fjep.sourceforge.net/">http://fjep.sourceforge.net/</A> <BR>  <BR>8.RegEx Test 测试正则表达式 <BR><A href="http://brosinski.com/stephan/archives/000028.php">http://brosinski.com/stephan/archives/000028.php</A> <BR>  <BR>9.JasperAssistant 报表插件（强，要钱的） <BR><A href="http://www.jasperassistant.com/">http://www.jasperassistant.com/</A> <BR>  <BR>10.Jigloo GUI Builder ＪＡＶＡ的ＧＵＩ编辑插件 <BR><A href="http://cloudgarden.com/jigloo/">http://cloudgarden.com/jigloo/</A> <BR>  <BR>11.Profiler 性能跟踪、测量工具，能跟踪、测量ＢＳ程序 <BR><A href="http://sourceforge.net/projects/eclipsecolorer/">http://sourceforge.net/projects/eclipsecolorer/</A> <BR>  <BR>12.AdvanQas 提供对if/else等条件语句的提示和快捷帮助（自动更改结构等） <BR><A href="http://eclipsecolorer.sourceforge.net/advanqas/index.html">http://eclipsecolorer.sourceforge.net/advanqas/index.html</A> <BR>  <BR>13.Log4E Log4j插件，提供各种和Log4j相关的任务，如为方法、类添加一个logger等 <BR><A href="http://log4e.jayefem.de/index.php/Main_Page">http://log4e.jayefem.de/index.php/Main_Page</A> <BR>  <BR>14.VSSPlugin VSS插件 <BR><A href="http://sourceforge.net/projects/vssplugin">http://sourceforge.net/projects/vssplugin</A> <BR>  <BR>15.Implementors 提供跳转到一个方法的实现类，而不是接中的功能（实用!） <BR><A href="http://eclipse-tools.sourceforge.net/implementors/">http://eclipse-tools.sourceforge.net/implementors/</A> <BR>  <BR>16.Call Hierarchy 显示一个方法的调用层次（被哪些方法调，调了哪些方法） <BR><A href="http://eclipse-tools.sourceforge.net/call-hierarchy/index.html">http://eclipse-tools.sourceforge.net/call-hierarchy/index.html</A> <BR>  <BR>17.EclipseTidy 检查和格式化HTML/XML文件 <BR><A href="http://eclipsetidy.sourceforge.net/">http://eclipsetidy.sourceforge.net/</A> <BR>  <BR>18.Checkclipse 检查代码的风格、写法是否符合规范 <BR><A href="http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm">http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm</A> <BR>  <BR>19.Hibernate Synchronizer Hibernate插件，自动映射等 <BR><A href="http://www.binamics.com/hibernatesync/">http://www.binamics.com/hibernatesync/</A> <BR>  <BR>20.VeloEclipse  Velocity插件 <BR><A href="http://propsorter.sourceforge.net/">http://propsorter.sourceforge.net/</A> <BR>  <BR>21.EditorList 方便的列出所有打开的Editor <BR><A href="http://editorlist.sourceforge.net/">http://editorlist.sourceforge.net/</A> <BR>  <BR>22.MemoryManager 内存占用率的监视 <BR><A href="http://cloudgarden.com/memorymanager/">http://cloudgarden.com/memorymanager/</A> <BR> <BR>23.swt-designer java的GUI插件<BR><A href="http://www.swt-designer.com/">http://www.swt-designer.com/</A><BR> <BR>24.TomcatPlugin 支持Tomcat插件 <BR><A href="http://www.sysdeo.com/eclipse/tomcatPlugin.html">http://www.sysdeo.com/eclipse/tomcatPlugin.html</A><BR> <BR>25.XML Viewer <BR><A href="http://tabaquismo.freehosting.net/ignacio/eclipse/xmlview/index.html">http://tabaquismo.freehosting.net/ignacio/eclipse/xmlview/index.html</A><BR> <BR>26.quantum 数据库插件<BR><A href="http://quantum.sourceforge.net/">http://quantum.sourceforge.net/</A><BR> <BR>27.Dbedit 数据库插件<BR><A href="http://sourceforge.net/projects/dbedit">http://sourceforge.net/projects/dbedit</A><BR> <BR>28.clay.core 可视化的数据库插件 <BR><A href="http://www.azzurri.jp/en/software/index.jsp">http://www.azzurri.jp/en/software/index.jsp</A> <BR><A href="http://www.azzurri.jp/eclipse/plugins">http://www.azzurri.jp/eclipse/plugins</A><BR> <BR>29.hiberclipse hibernate插件 <BR><A href="http://hiberclipse.sourceforge.net/">http://hiberclipse.sourceforge.net</A><BR><A href="http://www.binamics.com/hibernatesync">http://www.binamics.com/hibernatesync</A><BR> <BR>30.struts-console Struts插件<BR><A href="http://www.jamesholmes.com/struts/console/">http://www.jamesholmes.com/struts/console/</A><BR> <BR>31.easystruts Struts插件<BR><A href="http://easystruts.sourceforge.net/">http://easystruts.sourceforge.net</A> <BR> <BR>32.veloedit Velocity插件<BR><A href="http://veloedit.sourceforge.net/">http://veloedit.sourceforge.net/</A><BR> <BR>33.jalopy 代码整理插件<BR><A href="http://jalopy.sourceforge.net/">http://jalopy.sourceforge.net/</A><BR> <BR>34.JDepend 包关系分析<BR><A href="http://andrei.gmxhome.de/jdepend4eclipse/links.html">http://andrei.gmxhome.de/jdepend4eclipse/links.html</A><BR> <BR>35.Spring IDE Spring插件<BR><A href="http://springide-eclip.sourceforge.net/updatesite/">http://springide-eclip.sourceforge.net/updatesite/</A><BR> <BR>36.doclipse 可以产生xdoclet 的代码提示<BR><A href="http://beust.com/doclipse/">http://beust.com/doclipse/</A><BR><img src ="http://www.blogjava.net/qq13367612/aggbug/17167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-28 14:21 <a href="http://www.blogjava.net/qq13367612/articles/17167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse插件内幕-插件开发:如何定制一个向导</title><link>http://www.blogjava.net/qq13367612/articles/15978.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Sun, 16 Oct 2005 05:00:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/15978.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/15978.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/15978.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/15978.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/15978.html</trackback:ping><description><![CDATA[前段时间，我买了个很小的、口袋式的电子通讯簿。我一直随身带着它，直到有一天，它坏了。我联系了卖家，对方告诉我，他们没有办法维修，但是可以给我换个新的，就在这个时候，我意识到了数据的重要性。和存储的信息相比，这个小发明简直一文不值。<BR><BR>在这个文章系列中，第一部分向读者介绍了Eclipse的插件开发环境，并开发了一个简单的插件；第二部分添加了工具栏按钮、一个菜单项和对话框。一个小发明并不能为我们做什么事情，它仅仅将样本信息按照某个字体格式显示给我们，那么我们要做的是教会它去处理实际的数据。我们要通知那些插件，让它们按照我们的需要来工作。本文讨论了如何来定制一个编辑文件的向导。<BR><BR><B><SPAN style="FONT-SIZE: 16px">一 Invokatron的故事</SPAN></B><BR><BR>首先，我们来了解一下Invokatron，在前面的文章中，我们也提到了Invokatron是一个产生Java代码的图形化工具，用这个工具，你可以方便的采用拖放方式来创建一个Java Class。这个“dragged-in”方法被编辑好的方法调用（invoked），这就是它名字的由来。我们将采用数据驱动的方式来设计我们的系统。<BR><BR>在下面的章节中，我们将开发这个图形应用接口程序。从现在开始我们需要列出插件输入和存储的重要数据。这就是我们常说的应用程序的模型。在接下来的文章中，我们将制作这个图形化界面。目前我们需要考虑的仅仅是提取出哪些信息是我们的插件需要存放的重要数据。这部分通常被称作是应用的模型<BR>（Model）部分。以下是设计系统时需要考虑的东西：<BR>●        哪部分数据是需要保存的？<BR>●        这些数据用什么样的存储结构来表示他们？POJO，JavaBean，还是EJB？<BR>●        这些数据如何进行持久化？用数据库中的表，XML文件，属性文件还是一个序列化的二进制流文件？<BR>●        数据的读取采用哪些途径？使用新建文件向导，其他类型的向导，一个弹出式的对话框，一个图形化的编辑器，文本编辑器还是使用文件属性页？<BR>在我们继续前行之前，这些问题必须解决。没有一种答案是适用于所有项目的，这些答案是基于项目需求。我为我们的项目做了以下的定义：<BR>●        一个Java类包含类名，一个包，一个父类，并实现某些接口。我们先定义这些，在后面的文章中将添加一些其他的数据信息。<BR>●        这些数据将由一个继承自Properties类的子类来表示。这些构成了编辑器的“文档类”。<BR>●        我们将采用一类属性文件来实现转换。利用Properties类，这样的操作很容易实现。<BR>●        采用一个新建文件向导来初始化数据，接着，我们让用户在属性窗口或者文本编辑器中修改数据。这步操作将在下面的文档中进行说明。<BR><BR><B><SPAN style="FONT-SIZE: 16px">二 文档类</SPAN></B><BR><BR>接下来要做的是写文档类。创建一个名为invokatron.model的包，然后创建一个名为InvokatronDocument的类。这是我们最初的文档类：<BR><BR><PRE class=overflow title="pre code">public class InvokatronDocument<BR>        extends Properties<BR>{<BR>    public static final String PACKAGE = "package";<BR>    public static final String SUPERCLASS = "superclass";<BR>    public static final String INTERFACES = "interfaces";<BR>}</PRE><BR><BR>使用Properties类可以简单的实现数据的转换和保存操作。其中，getter和setter方法并不是必须的，如果你想添加这些方法的话，你可以添加它们。这个类并没有写完，在后面，我们将给它加上Eclipse需要使用的接口。对这个类而言，要取得一个属性，只需要这样的操作：<BR><BR><PRE class=overflow title="pre code">String package =<BR>    document.getProperty(InvokatronDocument.PACKAGE);</PRE><BR><BR><B><SPAN style="FONT-SIZE: 16px">三 定制一个向导</SPAN></B><BR><BR><BR>看一下我们在之前的文章中使用到的向导（如果你现在还没有源代码，请在<A href="http://www.matrix.org.cn/resource/upload/content/2005_09_03_002742_aKuWiCMHUP.zip" target=_new>这里下载</A>）。记住，你可以通过我们添加的工具栏按钮或者菜单项来打开这个向导。请看图1：<BR><IMG onmouseover=javascript:ImgShowTip(this); style="DISPLAY: inline" onclick=javascript:ImgClick(this); height=300 alt=image src="http://www.matrix.org.cn/resource/upload/content/2005_09_03_002445_oxjvsfCfdB.gif" width=321 onload=javascript:ImgLoad(this); border=0 resized="1"><BR>图1 以前的向导<BR><BR>这个向导只有一页，在右上角也没有图片。我们想添加更多的信息并且有个漂亮的图片。换句话说，我们想定制这个向导。<BR><BR>首先让我们来剖析一下向导。打开InvokatronWizard.java文件，注意这个类继承了Wizard并且实现了InewWizard接口。这里有很多你必须知道的方法。定制我们的向导，只需要简单的调用或者重写这些方法。这里有一些重要介绍：<BR><BR><BR><B><SPAN style="FONT-SIZE: 12px">3.1 关于生命期的方法</SPAN></B><BR>我们需要重写这些方法来加入关于那些初始化和销毁定制的向导代码。<BR>●        构造器。这个方法将在向导进行实例化的时候、并且Eclispe向它传送信息之前调用。是向导的常规信息初始化的实现。通常情况下你会调用“美化方法”（见下面）来给对话框做默认设置。<BR>●        init(IWorkbench workbench, IStructuredSelection editorSelection)：这个方法由Eclipse调用，它给向导提供一些工作取信息。重写这个方法来处理Iworkbench和之后将使用的对象。如果这是个编辑向导而不是新建向导，我们需要将当前编辑器的选择项也作为一个参数。<BR>●        dispose()：由Eclipse调用来处理回收。重写这个方法来回收向导所占用的资源。<BR>●        finalize()：对于回收处理，建议采用dispose()方法调用。<BR><BR><B><SPAN style="FONT-SIZE: 12px">3.2 美化方法</SPAN></B><BR>以下的方法将装饰这个向导窗口：<BR>●        setWindowTitle(String title)：调用这个方法来取得标题栏字符。<BR>●        setDefaultPageImageDescriptor(ImageDescriptor image)：调用这个方法来取得显示在所有向导页右上角的图片。<BR>●        setTitleBarColor(RGB color)：调用这个方法来来定义标题栏的颜色。<BR><BR><B><SPAN style="FONT-SIZE: 12px">3.3 按钮的常用方法</SPAN></B><BR>下面的方法控制向导中的按钮的可用性和它的操作。<BR>●        boolean canFinish()：重写这个方法，根据向导的状态来指明Finish按钮是否可用。<BR>●        boolean performFinish()：重写这个方法，实现这个向导最根本的业务逻辑。如果向导不能完成（产生错误）则返回false。<BR>●        boolean performCancel()：重写这个方法，当用户单击Cancel按钮的时候做清除操作。如果这个向导不能取消，返回false。<BR>●        boolean isHelpAvailable()：重写这个方法，定义Help按钮是否可见。<BR>●        boolean needsPreviousAndNextButtons()：重写这个方法，定义Previous和Next按钮是否可见。<BR>●        boolean needsProgressMonitor()：重写这个方法，指明过程监听器控件是否可见。它将在单击“Finish”按钮后调用performFinish()方法的时候出现。<BR><BR><B><SPAN style="FONT-SIZE: 12px">3.4 页面的常用方法</SPAN></B><BR>下面的方法将控制页面的出现：<BR>●        addPages()：当向导框出现的时候调用。重写这个方法给向导添加新页面。<BR>●        createPageControls(Composite pageContainer)：Eclipse调用这个方法将向导中的所有页面（由上面的addPages()方法添加的）实例化。重写这个方法，添加向导中一直可见的控件（不仅仅是页面）。<BR>●        IWizardPage getStartingPage()：重写这个方法来定义向导的第一个页面。<BR>●        IWizardPage getNextPage(IWizardPage nextPage)：在默认情况下，单击Next按钮将得到addPages()方法提供的页面数组中的下一页。你可能需要根据用户的选择而转向不同的页面。重写这个方法来得到下个页面。<BR>●        IWizardPage getPreviousPage(IWizardPage previousPage)：与getNextPage()方法类似，用来计算得到前一个页面。<BR>●        int getPageCount()：返回使用addPages()方法添加的页面个数。你不需要重写这个方法，除非你想显示和页面实际数量不一致的数量。<BR><BR><B><SPAN style="FONT-SIZE: 12px">3.5 其他有用的方法</SPAN></B><BR>这里有很多有用的辅助性方法：<BR>●        setDialogSettings(IDialogSettings settings)：你可以加载对话框的设置并调用init()方法来发布其中的数据。典型的，向导中的问题设置是默认的，在这里（DialogSettings）察看更多的信息。<BR>●        IDialogSettings getDialogSettings()：使用这个方法可以找回需要的数据。在performFinish()方法的最后，你可以将数据再次存入文件。<BR>●        IWizardContainer getContainer()：可以得到Shell对象，运行后台线程，刷新窗口，等等。<BR><BR><B><SPAN style="FONT-SIZE: 12px">3.6 向导页方法</SPAN></B><BR>我们已经看到，一个向导是一个或者多个页面的组合。这些页面扩展了WizardPage类并实现了IwizardPage接口。为了定制一个个性化的向导，还有很多方法是必须掌握的。这里介绍一些比较重要的方法：<BR>●        构造器：初始化页面<BR>●        dispose()：重写这个方法，实现清除代码。<BR>●        createControl(Composite parent)：重写这个方法，为这个页面添加控制器。<BR>●        IWizard getWizard()：用来得到向导对象。在调用getDialogSettings()方法的时候有用。<BR>●        setTitle(String title)：为向导的标题区提供显示的文字。<BR>●        setDescription(String description)：提供显在在标题文字下的信息。<BR>●        setImageDescriptor(ImageDescriptor image)：得到一个图片，用来取代西安在在向导右上角的默认图片。<BR>●        setMessage(String message)：在描述信息的下方显示的文本信息，一般用来提示或者警告用户。<BR>●        setErrorMessage(String error)：在描述信息的下面高亮度显示一个字符串。它表示向导在处理完错误信息之前不能做下一步的操作。<BR>●        setPageComplete(boolean complete)：如果输入参数是true，那么Next按钮可以使用。<BR>●        performHelp()：重写这个方法，提供内容敏感的帮助。这个将在Help按钮被按下的时候被向导调用。<BR><BR><BR><B><SPAN style="FONT-SIZE: 16px">四 为向导编码</SPAN></B><BR><BR>这些方法使得我们开发一个可扩展的向导成为可能。我们现在来修改这个在前面文章中创建的Invokatron向导，给他添加一个页面来请求原始的文档数据，并添加一个图片。下面的代码中粗体部分是新增加的：<BR><BR><PRE class=overflow title="pre code">public class InvokatronWizard extends Wizard<BR>        implements INewWizard {<BR>    private InvokatronWizardPage page;<BR>    private InvokatronWizardPage2 page2;<BR>    private ISelection selection;<BR><BR>    public InvokatronWizard() {<BR>        super();<BR>        setNeedsProgressMonitor(true);<BR>        ImageDescriptor image =<BR>            AbstractUIPlugin.<BR>                imageDescriptorFromPlugin("Invokatron",<BR>                   "icons/InvokatronIcon32.GIF");<BR>        setDefaultPageImageDescriptor(image);<BR>    }<BR><BR>    public void init(IWorkbench workbench,<BR>            IStructuredSelection selection) {<BR>        this.selection = selection;<BR>    }</PRE><BR><BR>在构造函数中，我们打开了过程监听器并为向导设置了图片。你可以通过右键下载这个新图标：<BR><BR><IMG onmouseover=javascript:ImgShowTip(this); style="DISPLAY: inline" onclick=javascript:ImgClick(this); alt=image src="http://www.matrix.org.cn/resource/upload/content/2005_09_03_003521_sCEpZekBTW.gif" onload=javascript:ImgLoad(this); border=0 resized="0"><BR><BR>将这个图标保存在Invokatron/icons文件夹下。为了促进图片的加载，我们使用了AbstractUIPlugin.imageDescriptorFromPlugin()方法。<BR><BR>注意：你必须知道，尽管这个向导是InewWizard类型的向导，但并不是所有的向导是用来产生新文档的。要想知道怎么去显示一个“独立”的向导，请参看文章最后的资源部分。<BR>接下来是addPages()方法：<BR><BR><PRE class=overflow title="pre code">    public void addPages() {<BR>        page=new InvokatronWizardPage(selection);<BR>        addPage(page);<BR>        page2 = new InvokatronWizardPage2(<BR>            selection);<BR>        addPage(page2);<BR>    }</PRE><BR><BR>在这个方法中，我们添加了一个名为InvokatronWizardPage2的新页面，我们待会就会写这个页面。接下来是用户按下向导中的Finish按钮后会调用的方法：<BR><BR>    <PRE class=overflow title="pre code">public boolean performFinish() {<BR>        //First save all the page data as variables.<BR>        final String containerName =<BR>            page.getContainerName();<BR>        final String fileName =<BR>            page.getFileName();<BR>        final InvokatronDocument properties =<BR>            new InvokatronDocument();<BR>        properties.setProperty(<BR>            InvokatronDocument.PACKAGE,<BR>            page2.getPackage());<BR>        properties.setProperty(<BR>            InvokatronDocument.SUPERCLASS,<BR>            page2.getSuperclass());<BR>        properties.setProperty(<BR>            InvokatronDocument.INTERFACES,<BR>            page2.getInterfaces());<BR><BR>        //Now invoke the finish method.<BR>        IRunnableWithProgress op =<BR>            new IRunnableWithProgress() {<BR>            public void run(<BR>                    IProgressMonitor monitor)<BR>                    throws InvocationTargetException {<BR>                try {<BR>                    doFinish(<BR>                        containerName,<BR>                        fileName,<BR>                        properties,<BR>                        monitor);<BR>                } catch (CoreException e) {<BR>                    throw new InvocationTargetException(e);<BR>                } finally {<BR>                    monitor.done();<BR>                }<BR>            }<BR>        };<BR>        try {<BR>            getContainer().run(true, false, op);<BR>        } catch (InterruptedException e) {<BR>            return false;<BR>        } catch (InvocationTargetException e) {<BR>            Throwable realException =<BR>                e.getTargetException();<BR>            MessageDialog.openError(<BR>                getShell(),<BR>                "Error",<BR>                realException.getMessage());<BR>            return false;<BR>        }<BR>        return true;<BR>    }</PRE><BR><BR>现在我们需要作一些数据保存的工作。这个工作将被向导的容器（Eclipse工作区）执行，所以必须实现IrunnableWithProgress接口，这个接口只包含一个run()方法。IprogressMonitor允许输出任务的过程信息。这是我们接下来将会看到的。真正的数据保存操作在辅助性方法中，doFinish()：<BR><BR>    <PRE class=overflow title="pre code">private void doFinish(<BR>        String containerName,<BR>        String fileName,<BR>        Properties properties,<BR>        IProgressMonitor monitor)<BR>        throws CoreException {<BR>        // create a sample file<BR>        monitor.beginTask("Creating " + fileName, 2);<BR>        IWorkspaceRoot root = ResourcesPlugin.<BR>            getWorkspace().getRoot();<BR>        IResource resource = root.findMember(<BR>            new Path(containerName));<BR>        if (!resource.exists() ||<BR>            !(resource instanceof IContainer)) {<BR>            throwCoreException("Container \"" +<BR>                containerName +<BR>                "\" does not exist.");<BR>        }<BR>        IContainer container =<BR>            (IContainer)resource;<BR>        final IFile iFile = container.getFile(<BR>            new Path(fileName));<BR>        final File file =<BR>            iFile.getLocation().toFile();<BR>        try {<BR>            OutputStream os =<BR>                new FileOutputStream(file, false);<BR>            properties.store(os, null);<BR>            os.close();<BR>        } catch (IOException e) {<BR>            e.printStackTrace();<BR>            throwCoreException(<BR>                "Error writing to file " +<BR>                file.toString());<BR>        }<BR><BR>        //Make sure the project is refreshed<BR>        //as the file was created outside the<BR>        //Eclipse API.<BR>        container.refreshLocal(<BR>            IResource.DEPTH_INFINITE, monitor);<BR><BR>        monitor.worked(1);<BR><BR>        monitor.setTaskName(<BR>            "Opening file for editing...");<BR>        getShell().getDisplay().asyncExec(<BR>            new Runnable() {<BR>            public void run() {<BR>                IWorkbenchPage page =<BR>                    PlatformUI.getWorkbench().<BR>                        getActiveWorkbenchWindow().<BR>                        getActivePage();<BR>                try {<BR>                    IDE.openEditor(<BR>                        page,<BR>                        iFile,<BR>                        true);<BR>                } catch (PartInitException e) {<BR>                }<BR>            }<BR>        });<BR>        monitor.worked(1);<BR>    }</PRE><BR><BR>这里，我们做了很多工作：<BR>●        我们得到了想保存的这个文件的路径（作为Eclipse的IFile类）<BR>●        我们也得到了与之等价的File<BR>●        我们将属性保存到了相应的路径下<BR>●        接着，我们请求Eclipse工作台刷新项目，这样，这个新的文件就显示出来了。<BR>●        最后，我们制定为将来制定了一个工作计划。这些工作包括在编辑器中打开一个新的文件。<BR>●        我们传递一个参数，调用IprogressMonitor对象的方法，使用户能接收到整个工作过程的信息。<BR><BR>最后一个方法是当保存文件失败的情况下，在向导中显示错误信息的辅助性方法：<BR><BR>    <PRE class=overflow title="pre code">private void throwCoreException(<BR>            String message) throws CoreException {<BR>        IStatus status =<BR>            new Status(<BR>                IStatus.ERROR,<BR>                "Invokatron",<BR>                IStatus.OK,<BR>                message,<BR>                null);<BR>        throw new CoreException(status);<BR>    }<BR>}</PRE><BR><BR>一个CoreException被向导捕获，接着，它所包含的Status对象将信息呈现给用户。这时，向导并没有关闭。<BR><BR><BR><B><SPAN style="FONT-SIZE: 16px">五 为新建向导页编程</SPAN></B><BR><BR>接着，我们来写InvokatronWizardPage2。这个类是一个新添加的文件：<BR><BR><PRE class=overflow title="pre code">public class InvokatronWizardPage2 extends WizardPage {<BR>    private Text packageText;<BR>    private Text superclassText;<BR>    private Text interfacesText;<BR>    private ISelection selection;<BR><BR>    public InvokatronWizardPage2(ISelection selection) {<BR>        super("wizardPage2");<BR>        setTitle("Invokatron Wizard");<BR>        setDescription("This wizard creates a new"+<BR>            " file with *.invokatron extension.");<BR>        this.selection = selection;<BR>    }<BR><BR>    private void updateStatus(String message) {<BR>        setErrorMessage(message);<BR>        setPageComplete(message == null);<BR>    }<BR><BR>    public String getPackage() {<BR>        return packageText.getText();<BR>    }<BR>    public String getSuperclass() {<BR>        return superclassText.getText();<BR>    }<BR>    public String getInterfaces() {<BR>        return interfacesText.getText();<BR>    }</PRE><BR><BR>上面的构造函数设置了页面的标题（它将高亮显示在标题栏下）。我们也有一些辅助性方法。updateStatus将管理显示出的这个特定页面的错误信息。如果没有错误信息，，那就说明页面完成了；这时，Next按钮将变成可用的状态。这里对数据属性内容设置了getter方法。接下来是createControl()方法，它将创建页面上所有可见的组建。<BR><BR>    <PRE class=overflow title="pre code">public void createControl(Composite parent) {<BR>        Composite controls =<BR>            new Composite(parent, SWT.NULL);<BR>        GridLayout layout = new GridLayout();<BR>        controls.setLayout(layout);<BR>        layout.numColumns = 3;<BR>        layout.verticalSpacing = 9;<BR><BR>        Label label =<BR>            new Label(controls, SWT.NULL);<BR>        label.setText("&Package:");<BR><BR>        packageText = new Text(<BR>            controls,<BR>            SWT.BORDER | SWT.SINGLE);<BR>        GridData gd = new GridData(<BR>            GridData.FILL_HORIZONTAL);<BR>        packageText.setLayoutData(gd);<BR>        packageText.addModifyListener(<BR>            new ModifyListener() {<BR>                public void modifyText(<BR>                        ModifyEvent e) {<BR>                    dialogChanged();<BR>                }<BR>        });<BR><BR>        label = new Label(controls, SWT.NULL);<BR>        label.setText("Blank = default package");<BR><BR>        label = new Label(controls, SWT.NULL);<BR>        label.setText("&Superclass:");<BR><BR>        superclassText = new Text(<BR>            controls,<BR>            SWT.BORDER | SWT.SINGLE);<BR>        gd = new GridData(<BR>            GridData.FILL_HORIZONTAL);<BR>        superclassText.setLayoutData(gd);<BR>        superclassText.addModifyListener(<BR>            new ModifyListener() {<BR>                public void modifyText(<BR>                        ModifyEvent e) {<BR>                    dialogChanged();<BR>            }<BR>        });<BR><BR>        label = new Label(controls, SWT.NULL);<BR>        label.setText("Blank = Object");<BR><BR>        label = new Label(controls, SWT.NULL);<BR>        label.setText("&Interfaces:");<BR><BR>        interfacesText = new Text(<BR>            controls,<BR>            SWT.BORDER | SWT.SINGLE);<BR>        gd = new GridData(<BR>            GridData.FILL_HORIZONTAL);<BR>        interfacesText.setLayoutData(gd);<BR>        interfacesText.addModifyListener(<BR>            new ModifyListener() {<BR>                public void modifyText(<BR>                        ModifyEvent e) {<BR>                    dialogChanged();<BR>            }<BR>        });<BR><BR>        label = new Label(controls, SWT.NULL);<BR>        label.setText("Separated by ','");<BR><BR>        dialogChanged();<BR>        setControl(controls);<BR>    }</PRE><BR><BR>你需要了解SWT来书写这些代码。如果你对SWT不了解，在文章的最后有一些链接，这些链接可以告诉你学习SWT的地方。基本上这个方法创建了标签、输入框并对他们进行了布局。每次输入框的改变，它的数据也通过dialogChanged()方法来进行修改：<BR><BR>    <PRE class=overflow title="pre code">private void dialogChanged() {<BR>        String aPackage = getPackage();<BR>        String aSuperclass = getSuperclass();<BR>        String interfaces = getInterfaces();<BR><BR>        String status = new PackageValidator().isValid(aPackage);<BR>        if(status != null) {<BR>            updateStatus(status);<BR>            return;<BR>        }<BR><BR>        status = new SuperclassValidator().isValid(aSuperclass);<BR>        if(status != null) {<BR>            updateStatus(status);<BR>            return;<BR>        }<BR><BR>        status = new InterfacesValidator().isValid(interfaces);<BR>        if(status != null) {<BR>            updateStatus(status);<BR>            return;<BR>        }<BR><BR>        updateStatus(null);<BR>    }<BR><BR>}</PRE><BR><BR>这些工作利用了3个工具类来完成：PackageValidator，SuperclassValidator和InterfacesValidator。我们将在后面来完成这三个类。<BR><BR><B><SPAN style="FONT-SIZE: 12px">5.1 验证类</SPAN></B><BR><BR>在用户输入数据后，验证工作可以在插件的任何部分完成。所以，将验证代码放在一个可重用的类中是有意义的，这样比将验证代码四处拷贝要好得多。下面是一个验证类的例子：<BR><BR><PRE class=overflow title="pre code">public class InterfacesValidator implements ICellEditorValidator<BR>{<BR>    public String isValid(Object value)<BR>    {<BR>        if( !( value instanceof String) )<BR>            return null;<BR><BR>        String interfaces = ((String)value).trim();<BR>        if( interfaces.equals(""))<BR>            return null;<BR><BR>        String[] interfaceArray = interfaces.split(",");<BR>        for (int i = 0; i < interfaceArray.length; i++)<BR>        {<BR>            IStatus status = JavaConventions<BR>                    .validateJavaTypeName(interfaceArray[i]);<BR>            if (status.getCode() != IStatus.OK)<BR>                return "Validation of interface " + interfaceArray[i]<BR>                        + ": " + status.getMessage();<BR>        }<BR>        return null;<BR>    }<BR>}</PRE><BR><BR>其他的验证类跟这个十分相似——参见文档最后的源代码。<BR>另一个Eclipse工厂中的漂亮的类是JavaConventions，它将为我们验证数据。它包含了很多验证方法，例如：<BR>●        validateJavaTypeName()用来检查类和接口的名称<BR>●        validatePackageName()用来检查包名<BR>●        validateFieldName()用来检查数据成员的名称<BR>●        validateMethodName()用来检查方法名称<BR>●        validateIdentifierName()用来检查变量名称<BR>我们目前不需要使用ICellEditorValidator接口，但是在下一篇文章中，我们将使用到它。<BR><BR><B><SPAN style="FONT-SIZE: 16px">六 结果</SPAN></B><BR>到这里，我们已经完成了一个有图片并由第二页的向导，它将初始化Invokatron文档。图2就是结果：<BR><BR><IMG onmouseover=javascript:ImgShowTip(this); style="DISPLAY: inline" onclick=javascript:ImgClick(this); height=300 alt=image src="http://www.matrix.org.cn/resource/upload/content/2005_09_03_004120_loKLfazgNz.gif" width=331 onload=javascript:ImgLoad(this); border=0 resized="1"><BR>图2 自定义的向导<BR><BR><B><SPAN style="FONT-SIZE: 16px">七 耀眼的小发明</SPAN></B><BR><BR>正如我们所看到的，很多应用都是数据驱动的。表现方式也很重要。一个糟糕的小发明是卖不出去的，但是一个耀眼的小发明却可以卖出去。但是数据，才是我们这些程序员的根源。<BR>在这篇文章中，我们首先决定了那些数据是需要处理的。接着，我们通过定制的向导可视化地捕获了这些数据。下篇文章将在表现方式上进行进一步阐述，这将包括一个定制的编辑器和一个属性页。<BR><BR><B><SPAN style="FONT-SIZE: 16px">八 资源</SPAN></B><BR>●        PluginTest3.zip 示例代码:[<A href="http://www.matrix.org.cn/resource/upload/content/2005_09_03_004247_MtAmrLULed.zip">下载文件</A>]<BR>●        <A href="http://help.eclipse.org/help30/topic/org.eclipse.platform.doc.isv/guide/dialogs_wizards.htm" target=_new>“Eclipse Platform Online Help: Wizards”</A><BR>●        <A href="http://www.eclipse.org/articles/Article-JFace%20Wizards/wizardArticle.html" target=_new>“Creating JFace Wizards”</A>阐述了如何创建独立的向导<BR>●        读<A href="http://www.eclipse.org/articles/main.html#SWT" target=_new>这些文档</A>来学习SWT。一定要阅读“SWT: The Standard Widget Toolkit”的第一和第二部分，还有“Understanding Layouts in SWT”。<BR><BR><BR><B><SPAN style="FONT-SIZE: 16px">九 作者和译者简介</SPAN></B><BR>作者：Emmanuel Proulx 是一位J2EE和EJB方面的资深专家，也是一位WebLogic Server 7.0鉴定工程师。他主攻电信和网络开发领域。<BR>译者：<A href="http://www.matrix.org.cn/user.shtml?username=hopeshared" target=_new>hopeshared</A> 是一位在读MSE，目前从事Eclipse插件研究与开发工作。<BR><BR><B><SPAN style="FONT-SIZE: 16px">十 相关文档</SPAN></B><BR><A href="http://www.onjava.com/pub/a/onjava/2005/03/30/eclipse.html" target=_new>Eclipse Plugins Exposed, Part 2: Simple GUI Elements</A><BR>Eclipse由大量的插件组成，但是你不能随意的编写代码然后简单的与之合并起来。在Emmanuel Proulx这个关于Eclipse的文章系列的第二部分中，他通过创建一个工具栏按钮、菜单项、对话框等介绍了Eclipse的“扩展点”……<BR><BR><A href="http://www.onjava.com/pub/a/onjava/2005/02/09/eclipse.html" target=_new>Eclipse Plugins Exposed, Part 1: A First Glimpse</A><BR>很多开发者仅仅将Eclipse作为一个集成开发环境来使用，从来不去它强大的可扩展性。就像Emmanuel Proulx在这个系列文章的开始所展示的，Eclipse的插件系统提供给你一个可定制的工作平台，这样，你可以定制Eclipse来适应开发的需求……<BR><img src ="http://www.blogjava.net/qq13367612/aggbug/15978.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-16 13:00 <a href="http://www.blogjava.net/qq13367612/articles/15978.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>