??xml version="1.0" encoding="utf-8" standalone="yes"?>中文字幕亚洲免费无线观看日本,亚洲AV无码乱码麻豆精品国产,久久久久亚洲AV成人网http://m.tkk7.com/qq13367612/articles/17837.htmlSungSungWed, 02 Nov 2005 07:42:00 GMThttp://m.tkk7.com/qq13367612/articles/17837.htmlhttp://m.tkk7.com/qq13367612/comments/17837.htmlhttp://m.tkk7.com/qq13367612/articles/17837.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17837.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17837.html
本文用eclipse的自动重构功能对一个程序实例进行重构,目的是探索Eclipse自动重构可以在多大程度上辅助重构q个q程。程序实例用《RefactoringQImproving the Design of Existing Code》一书中的例子?BR>  
  Eclipse的自动重构功能能够很好地支持各种E序元素的重命名Qƈ自动更新相关的引用。Eclipse能够支持Ҏ(gu)、字D在cM间移动,q自动更新引用。Eclipse较好地支持内联字Dc(din)函数的更新替换。Eclipse较好地支持抽取方法、变量等E序元素?BR>  
  重构的过E是一个不断尝试和探烦(ch)的过E。Eclipse的重构支持撤销和重做,q且能够预览重构l果Q这些是很实用的功能?BR>  
  Eclipse的重命名、抽取方法、移动、内联功能、更Ҏ(gu)法特征符{代码结构别的重构Ҏ(gu)Q是比较成熟同时也值得使用的功能。至于设计结构上的重构,eclipseq(sh)能很好地支持。但是作者相信,自动重构的理念应该是"工具辅助下的重构工作"Qh仍然承担大部分重构工作?BR>  
  一、预备工?/B>
  
  本文使用《RefactoringQImproving the Design of Existing Code》一书第一章的例子。重构前的代码及(qing)每一步重构后的代码见附g。读者最好配合《RefactoringQImproving the Design of Existing Code》一书阅L文?BR>  
  Eclipse使用如下版本Q?BR>   
  同时安装?jin)中文语a包?BR>  
  二、重构第一步:(x)分解qlstatement()
  
  目的Q?BR>  
  1?把statement()函数中的swich语句提炼到独立的函数amountFor()中?BR>  
  2?修改amountFor()参数命名
  
  重构Ҏ(gu)Q?BR>  
  Extract Method
  Rename Method
  
  Ҏ(gu)Q?BR>  
  1、选中swich语句的代码块Q在右键菜单中选择"重构/抽取Ҏ(gu)"Q出现参数对话框。Eclipse自动分析代码块中的局部变量,扑ֈ?jin)两个局部变量:(x)each和thisAmount。其中,each只是在代码块中被dQ但thisAmount?x)在代码块中被修攏V按照重构Extract Methodȝ出来的规则,应该把each当作抽取函数的参数、thisAmount当作抽取函数的返回倹{然而Eclipseq不做区分,直接把这两个变量当作抽取新方法的参数Q如图?BR>   
  我们的目的是把在抽取函数中不?x)被修改的each作ؓ(f)参数Q会(x)被修改的thisAmount作ؓ(f)q回倹{解决的办法是,?double thisAmount = 0; q行代码Udswitch语句的上面,变成q样Q?BR>  
  double thisAmount = 0;
  switch(each.getMovie().getPriceCode()){
  case Movie.REGULAR:
  thisAmount += 2;
  if(each.getDaysRented()>2)
  thisAmount += (each.getDaysRented()-2)*1.5;
  break;
  
  case Movie.NEW_RELEASE:
  thisAmount += each.getDaysRented()*3;
  break;
  
  case Movie.CHILDRENS:
  thisAmount += 1.5;
  if(each.getDaysRented()>3)
  thisAmount += (each.getDaysRented()-3)*1.5;
  break;
  }
  
  选中q段代码Q在右键菜单中选择"重构/抽取Ҏ(gu)"Qeclipseq次变得聪明点了(jin)Q如图?BR>   
  选择"预览"按钮预先查看重构后的l果Q符合我们最初的目的?BR>   
  选择"定"按钮Q重构后的代码片断如下:(x)
  
  public String statement() {
  double totalAmount = 0;
  int frequentRenterPoints = 0;
  Enumeration rentals = _rentals.elements();
  String result = "Rental Record for " + getName() + "\n";
  
  while(rentals.hasMoreElements()){
  Rental each = (Rental)rentals.nextElement();
  
  double thisAmount = amountFor(each);
  
  frequentRenterPoints ++;
  if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE &&each.getDaysRented()>1)
  frequentRenterPoints ++;
  
  result += "\t" + each.getMovie().getTitle() + "\t" +String.valueOf(thisAmount) + "\n";
  totalAmount += thisAmount;
  }
  
  result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
  result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";
  
  return result;
  }
  
  /**
  * @param each
  * @return
  */
  private double amountFor(Rental each) {
  double thisAmount = 0;
  switch(each.getMovie().getPriceCode()){
  case Movie.REGULAR:
  thisAmount += 2;
  if(each.getDaysRented()>2)
  thisAmount += (each.getDaysRented()-2)*1.5;
  break;
  
  case Movie.NEW_RELEASE:
  thisAmount += each.getDaysRented()*3;
  break;
  
  case Movie.CHILDRENS:
  thisAmount += 1.5;
  if(each.getDaysRented()>3)
  thisAmount += (each.getDaysRented()-3)*1.5;
  break;
  }
  return thisAmount;
  }
  
  2、选中amountFor()的参数eachQ在右键菜单中选择"重构/重命?Q在对话框中输入新的名称QaRentalQ选择定QamountFor()中所有each的引用全部被替换成新的名U。用同样的办法修改amountFor()中的局部变量thisAmount为result。重构后的amountFor()代码如下Q?BR>  
  /**
  * @param aRental
  * @return
  */
  private double amountFor(Rental aRental) {
  double result = 0;
  switch(aRental.getMovie().getPriceCode()){
  case Movie.REGULAR:
  result += 2;
  if(aRental.getDaysRented()>2)
  result += (aRental.getDaysRented()-2)*1.5;
  break;
  
  case Movie.NEW_RELEASE:
  result += aRental.getDaysRented()*3;
  break;
  
  case Movie.CHILDRENS:
  result += 1.5;
  if(aRental.getDaysRented()>3)
  result += (aRental.getDaysRented()-3)*1.5;
  break;
  }
  return result;
  }
  
  三、重构第二步Q搬U?金额计算"代码
  
  目的Q?BR>  
  1?函数amountFor()转移到RentalcMQƈ更名为getCharge()?BR>  
  2?更新q替换所有对amountFor()的引用?BR>  
  重构Ҏ(gu)Q?BR>  
  Move Method
  Change Method signatrue
  Inline Method
  Inline Temp
  
  Ҏ(gu)Q?BR>  
  1、选中函数amountFor()的定义,在右键菜单中选择"重构/Ud"Q显C参数设|对话框。把新方法名Ҏ(gu)getCharge。按?定"按钮QCustomer Class中的amountFor()函数被移动到Rental Class中,q更名ؓ(f)QgetCharge()?BR>   
  同时eclipse自动在Customer的amountFor()函数中添加一行对新函数的"委托"代码Q?BR>  
  private double amountFor(Rental aRental) {
  return aRental.getCharge();
  }
  
  q行代码?x)生编译错误,原因是amountFor()的private型被传递到?jin)新的方法中Q?BR>  
  /**
  * @param this
  * @return
  */
  private double getCharge() {
  …?BR>  }
  
  2、l重构!选中getCharge()Ҏ(gu)Q在右键菜单中选择"重构/更改Ҏ(gu)特征W?Q弹出参数选择对话框,把访问修饰符从privateҎ(gu)public。Eclipse的编译错误提C动消失?BR>   
  3、回到Customerc,把所有对amountFor()引用的地Ҏ(gu)换成直接对getCharge()的引用。选中Customercȝ函数amountFor(Rental aRental)Q在右键菜单中选择"重构/内联"Q出现参数选择对话框?BR>   
  选择"认"按钮Q引用amountFor()的地方被替换成对getCharge()的引用?BR>  
  public String statement() {
  …?BR>  double thisAmount = each.getCharge();
  …?BR>  }
  
  4、除M(f)时变量thisAmount?BR>  
  选中变量thisAmountQ在右键菜单中选择"重构/内联"Q重构预览窗口如下,可见辑ֈ?jin)重构的目的。按?认"按钮重构代码?BR>   
  statement()代码Q?BR>  
  public String statement() {
  double totalAmount = 0; // L贚w?BR>  int frequentRenterPoints = 0; // 常客U点
  Enumeration rentals = _rentals.elements();
  String result = "Rental Record for " + getName() + "\n";
  
  while(rentals.hasMoreElements()){
  Rental each = (Rental)rentals.nextElement(); //取得一W租借记?BR>  
  // add frequent renter points(累加 常客U点)
  frequentRenterPoints ++;
  // add bouns for a two day new release rental
  if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE && each.getDaysRented()>1)
  frequentRenterPoints ++;
  
  // show figures for this rental(昄此笔U借数?
  result += "\t" + each.getMovie().getTitle() + "\t" +
  String.valueOf(each.getCharge()) + "\n";
  totalAmount += each.getCharge();
  }
  
  // add footer linesQ结打华ͼ(j)
  result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
  result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";
  
  return result;
  }
  
  四、重构第三步Q提?常客U点计算"代码
  
  目的Q提?常客U点计算"代码q放在RentalcMQ?常客U点计算"代码如下?BR>  
  public String statement() {
  …?BR>  // add frequent renter points
  frequentRenterPoints ++;
  // add bouns for a two day new release rental
  if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE && each.getDaysRented()>1)
  frequentRenterPoints ++;
  …?BR>  }
  
  重构后的代码如下Q?BR>  
  frequentRenterPoints += each.getFrequentRenterPoints();
  
  重构Ҏ(gu)Q?BR>  
  Extract Method
  Move Method
  Change Method signatrue
  Inline Method
  
  Ҏ(gu)Q?BR>  
  1?首先Q抽取代码到独立的函C?BR>  
  ?抽取Ҏ(gu)"重构代码Q函数名QgetFrequentRenterPoints。很遗憾Qeclipse的不能生成诸如:(x)frequentRenterPoints += getFrequentRenterPoints(Rental aRental); 的代码。原因是执行自增操作的局部变量frequentRenterPoints要出现在{式双Q因此抽取函数getFrequentRenterPoints()一定要把frequentRenterPoints作ؓ(f)参数。手工修改函数和对函数的引用Q重构后的代码如下:(x)
  
  public String statement() {
  …?BR>  while(rentals.hasMoreElements()){
  …?BR>  frequentRenterPoints += getFrequentRenterPoints(each);
  …?BR>  }
  …?BR>  }
  
  /**
  * @param each
  * @return
  */
  private int getFrequentRenterPoints(Rental each) {
  if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE && each.getDaysRented()>1)
  return 2;
  else
  return 1;
  }
  
  2?把getFrequentRenterPointsQ)(j)Ud到RentalcM?BR>  
  3?对getFrequentRenterPointsQ)(j)"更改Ҏ(gu)特征W?为public?BR>  
  4?对Customer的函数getFrequentRenterPoints()执行内联操作Q重构目标完成?BR>  
  五、重构第四步Q去除(f)时变量(totalAmount和frequentRenterPointsQ?/B>
  
  目的Q去除(f)时变量(totalAmount和frequentRenterPointsQ?BR>  
  Ҏ(gu)Q?BR>  
  1?分析totalAmount和frequentRenterPoints的定义和引用l构如下Q?BR>  
  // 声明和定?BR>  double totalAmount = 0;
  int frequentRenterPoints = 0;
  …?BR>  // 在@环中修改
  while(rentals.hasMoreElements()){
  …?BR>  frequentRenterPoints += each.getFrequentRenterPoints();
  …?BR>  totalAmount += each.getCharge();
  …?BR>  }
  …?BR>  // 在@环外使用
  result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
  result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";
  …?BR>  
  上述两个变量在@环体外面定义和用,在@环中被修改,q用Replace Temp with QueryҎ(gu)去除q两个(f)时变量是一稍微复杂的重构。很遗憾Qeclipse目前不支持这L(fng)重构?BR>  
  2、手工修改代码?BR>  
  六、重构第五步Q运用多态取代与h相关的条仉辑
  
  目的Q?BR>  
  1?把RentalcM的函数getCharge()Ud到MoviecM?BR>  
  2?把RentalcM的函数getFrequentRenterPoints()Ud到MoviecM?BR>  
  重构Ҏ(gu)Q?BR>  
  Move Method
  Inline Method
  
  Ҏ(gu)Q?BR>  
  1?选中RentalcM的函数getCharge()Q右键菜单选中"重构/Ud"Qeclipse提示找不到接收者,不能Ud。原因在于这行语句:(x)
  
  switch(getMovie().getPriceCode()){//取得q出租h
  
  选中getMovie()Q右键菜单选中"重构/内联"Q确定后代码成ؓ(f)Q?BR>  
  switch(_movie.getPriceCode()){ //取得q出租h
  
  选中getCharge()Q执?重构/Ud"后,函数被移动到MoviecM。然而这只是部分达成?jin)重构目的,我们发现Q移动后的代码把Rental作ؓ(f)参数传给?jin)getCharge()Q手工修改一下,代码变成Q?BR>  
  class Movie …?BR>  /**
  * @param this
  * @return
  */
  public double getCharge(int _daysRented) {
  double result = 0;
  switch(getPriceCode()){ //取得q出租h
  case Movie.REGULAR: // 普通片
  result += 2;
  if(_daysRented>2)
  result += (_daysRented-2)*1.5;
  break;
  
  case Movie.NEW_RELEASE: // 新片
  result += _daysRented*3;
  break;
  
  case Movie.CHILDRENS: // 儿童?BR>  result += 1.5;
  if(_daysRented>3)
  result += (_daysRented-3)*1.5;
  break;
  }
  return result;
  }
  
  class Rental…?BR>  /**
  * @param this
  * @return
  */
  public double getCharge() {
  return _movie.getCharge(_daysRented);
  }
  
  2、用同样的步骤处理getFrequentRenterPoints()Q重构后的代码:(x)
  
  class Movie …?BR>  /**
  * @param frequentRenterPoints
  * @param this
  * @return
  */
  public int getFrequentRenterPoints(int daysRented) {
  if((getPriceCode())==Movie.NEW_RELEASE && daysRented>1)
  return 2;
  else
  return 1;
  }
  class Rental…?BR>  /**
  * @param frequentRenterPoints
  * @param this
  * @return
  */
  public int getFrequentRenterPoints(int daysRented) {
  if((getPriceCode())==Movie.NEW_RELEASE && daysRented>1)
  return 2;
  else
  return 1;
  }
  
  七、重构第六步Q终于……我们来到?/B>
  
  目的Q对switch语句引入state模式?BR>  
  Ҏ(gu)Q?BR>  
  很遗憾,不得不在q里提前l束eclipse的自动重构之旅。Eclipse几乎不能做结构上的重构。也许Martin Fowler在书中呼唤的自动重构工具止于"工具辅助下的重构工作"q一理念。艺术是人类的专利,~程艺术的梦惛_持箋(hu)下去?BR>  
  感兴的读者可以查看手工重构的最后一步代码。将重构q行到底Q?BR>  
  附录Qeclipse支持的重构方法(摘自eclipse中文帮助Q?BR>  
 



Sung 2005-11-02 15:42 发表评论
]]>
利用Eclipse~辑中文资源文g http://m.tkk7.com/qq13367612/articles/17836.htmlSungSungWed, 02 Nov 2005 07:41:00 GMThttp://m.tkk7.com/qq13367612/articles/17836.htmlhttp://m.tkk7.com/qq13367612/comments/17836.htmlhttp://m.tkk7.com/qq13367612/articles/17836.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17836.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17836.html  
  如果l常使用StrutsQƈ做过国际化操作的人来_(d)对于中文资源文g的处理应该不?x)感到陌生的。比如下面两个文Ӟ一个是英文的,一个是中文的。对于英文的Q一切照常;对于中文的,一般需要用JDK的native2ascii工具q行转换?BR>  
  application_en.properties
  # Resources for the Hello sample application
  hello.title=A first Struts program
  hello.prompt.user=Please enter a UserName
  hello.page.hello=Hello
  hello.page.wellocome=Wellcome to Blog of Javamxj
  
  application_zh_CN.properties
  # Hello实例使用的资源文?BR>  
  hello.title=W一个Struts应用
  hello.prompt.user=误入用户名
  hello.page.hello=你好
  hello.page.wellocome=Ƣ迎来到Javamxj的Blog
  
  我当前用的Eclipse版本?.1M6Q如果用Eclipse~辑application_zh_CN.properties文gQ保存后Q关闭这个文Ӟ然后再次打开它,?x)发现这个文件中的中文字W都变成?jin)?Q?Q?BR>  
  Z么会(x)发生q种情况呢?在中文操作系l下QEclipse中的Javacd文g的编码的默认讄是GBKQ但是对Properties资源文g的编码的默认讄是ISO-8859-1。所以编辑Java文g中的中文不会(x)出现问题Q但~辑Properties资源文g中的中文?x)出现问题?BR>  
  ?.1M6版本下,我们可以直接修改Properties资源文g的默认编码了(jin)QEclipse3.0版本好像不支持)(j)。在Eclipseȝ面下Q打开 Window ->Perferences ->General ->Editors ->Context Types:
   
  修改为GBK后,再次打开application_zh_CN.properties文gQ编辑后保存Q再打开Ӟ文g中的中文字符可以正常昄?jin)?BR>  
  q还?sh)行Q还必须利用native2ascii来{换一下?BR>  
  native2ascii-本地??ASCII 码{换器
  
  含有本地编码字W(既非 Latin1 又非 Unicode 字符Q的文g转换?Unicode ~码字符的文件?BR>  
  l构
  
  native2ascii [options] [inputfile [outputfile]]
  
  说明
  
  Java ~译器和其它 Java 工具只能处理含有 Latin-1 ??Unicode ~码Q\udddd 记号Q字W的文g。native2ascii 含有其它字W编码的文g转换成含 Latin-1 ??Unicode ~码字符的文件?BR>  
  若省?outputfileQ则使用标准输出讑֤输出。此外,如果也省?inputfileQ则使用标准输入讑֤输入?BR>  
  选项
  
  -reverse
  
  执行相反的操作:(x)含 Latin-1 ??Unicode ~码字符的文件{换成含本地编码字W的文gQ?BR>  
  -encoding encoding_name
  
  指定转换q程使用的编码名U。缺省的~码从系l属?file.encoding 中得到。encoding_name 字符串必LW合要求的字W串?BR>  
  比如可以q样利用native2asciiQ?BR>  
  native2ascii -encoding gbk application_zh_CN.properties temp.properties
  
  q里根据a(chn)pplication_zh_CN.properties输出?jin)一个(f)时文件temp.propertiesQ然后把application_zh_CN.properties中的文g内容替换个(f)时文件的内容可以了(jin)?BR>  
  转换后的application_zh_CN.properties
  
  # Hello\u5b9e\u4f8b\u4f7f\u7528\u7684\u8d44\u6e90\u6587\u4ef6
  
  hello.title=\u7b2c\u4e00\u4e2aStruts\u5e94\u7528
  hello.prompt.user=\u8bf7\u8f93\u5165\u7528\u6237\u540d
  hello.page.hello=\u4f60\u597d
  hello.page.wellocome=\u6b22\u8fce\u6765\u5230Javamxj\u7684Blog
  
  q样的操作对于一个或两个资源文gq行Q如果多个资源文Ӟq样未免有些太麻?ch)?jin)。你可以建立一个批处理文gQ?batQ;或者徏立一个Ant文gQ利用其包含的native2asciidQ也可以q行批处理?BR>  
  但是自从使用Eclipse后,好处多多Q在Eclipse下,有这么两个插Ӟ可以用来处理资源文gQ它们用v来各有千U?BR>  
  JInto 0.8.0
  
  主页 http://www.guh-software.de/jinto.html
  
  下蝲 http://www.guh-software.de/jinto/de.guhsoft.jinto_0.8.0.zip
  
  文档 http://www.guh-software.de/jinto/JIntoGettingStarted.pdf Q英文)(j)
  
  仔细看看文档Q它提供的功能还是很不错的?BR>  
  Properties Editor
  
  主页 http://propedit.sourceforge.jp/index_en.html
  
  它提供了(jin)三个版本Q单独运行的版本、Eclipse版本、JBuilder版本Q这里只看看Eclipse3下的版本?BR>  
  PropertiesEditor_EclipsePlugin_for_3.0 V4.4.0
  
  分别以links方式安装q两个插Ӟ启动EclipseQ切换到PerferencesQ如图:(x)
  
  · JInto插g
   
  · Properties Editor插g
   
  · 先利用Properties Editor插g~辑资源文gQ选中application_zh_CN.propertiesQ右击,选择对应的插Ӟ如图操作Q?BR>   
  · Properties Editor插g~辑的效?BR>   
  · 然后利用JInto插g~辑资源文gQ?BR>  
  对应XML文gcdQ默认的~码是UTF-8,但如果在xml声明中可以指定其~码Q如?lt;?xml version="1.0" encoding="GBK"?>”就指定其编码ؓ(f)GBK。这PEclipse在读取xml文gӞ?x)首先根据其声明来设|这个文件的~码Q如果在声明中没有指定其~码Q那么会(x)采用UTF-8~码来读取这个文件。所以对于xml文gQ就不需要强制设|其默认的编码类型了(jin)?

Sung 2005-11-02 15:41 发表评论
]]>
Eclipse插g开发之d单的GUI元素http://m.tkk7.com/qq13367612/articles/17835.htmlSungSungWed, 02 Nov 2005 07:35:00 GMThttp://m.tkk7.com/qq13367612/articles/17835.htmlhttp://m.tkk7.com/qq13367612/comments/17835.htmlhttp://m.tkk7.com/qq13367612/articles/17835.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17835.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17835.html  
  本文讨论少许几个简单的GUI元素Q?BR>  
  · 工具条按?BR>  
  · 菜单?BR>  
  · 对话?BR>  
  Z(jin)使用q些元素Q我们将E微修改已有的插ӞZ~写一个可供用的工具cR?BR>  
  扩展点(Extension PointsQ?/B>
  
  我们不能随意地向Eclipse用户界面的Q何地Ҏ(gu)加窗口小部gQ只能在Ҏ(gu)的、指定的、有记蝲的位|添加。这些位|被UCؓ(f)扩展点(extension pointsQ。在基本的Eclipse安装中存在数以百计可供用的扩展炏V插件自w也可以发布新的扩展炏V?BR>  
 

  
?Q扩展页

  
  现在L(fng)?d"QADDQ按钮,出现?jin)?所C的列表?BR>  
 

  
?Q新增扩展向|扩展列表

  
  上下滚动q个列表可以看到很多可供使用的扩展点。你可能注意C(jin)有两U类型的扩展点:(x)带有扩展模板的(用加h识)(j)和不带扩展模板的。大多数l常用到的扩展点都带有用于辅助开发扩展的模板。图2中选择的扩展点Action SetQ带有一个叫?Hello World"操作集的模板。当你选择某个模板的时候,?x)出现简短的描述?下一?面询问模板用的参数?BR>  
  现在请关闭向导ƈq回?扩展"属性页。选择"Invokatron~辑?。在q个属性页中,你可能注意到?jin)我们在向导中?f)Invokatron~辑器输入的信息。正常的扩展需要一个唯一的标识符QID字段Q、一个供昄的名UͼName字段Q和它所属的扩展点(Point字段Q。从模板中徏立的扩展Q例如Invokatron~辑器)(j)需要更多的参数。没有模板的扩展点也需要更多的信息Q但是这些信息只能在文本~辑器中输入?BR>  
  d工具条按?/B>
  
  现在我们已经?jin)解了(jin)扩展点是什么,让我们来d一个扩展吧。我们首先添加的是一个工h按钮。这个按钮将调用我们前面建立的新的Invokatron向导?BR>  
  d工具条按钮有三个步骤Q?BR>  
  1.声明一个新扩展?BR>  
  2.用特定的标记来扩充该声明?BR>  
  3.~写操作委托c?BR>  
  1.声明一个新扩展
  
  我们已经知道怎样实现q个步骤?jin)。简单地q回到扩展点下的plugin.xml~辑器。点?d"。工h按钮在org.eclipse.ui.actionSets扩展点下面。不要用模板,直接点击"完成"。输入下面一些内容:(x)
  
  · Id: NewInvokatronAction
  
  · Name: New Invokatron Document Action
  
  · Point: (使用默认|(x)org.eclipse.ui.actionSets)
  
  q回plugin.xml属性页QEclipsel这个文件添加了(jin)新的代码片断?BR>  
  2.用特定的标记来扩充该声明
  
  q个新扩展几乎毫无内宏V我们在下面d一些标讎ͼtagQ。你知道可以使用哪些标记吗?你可以右键点?所有扩??wi)中的元素,选择"新增"菜单Q会(x)得到一个列表。你也可以查看Eclipse文档?BR>  
  现在我们看到自己可以在<extensionQ标记内部添加一个<actionSetQ标记。它可以包含零个或多个<menuQ标讎ͼ后面跟着零个或多个<actionQ标讎ͼq可以选择使用QdescriptionQ标记。但是其中最重要的标记是QactionQ。它可以同时描述工具条按钮和菜单V?gt;BR>下面是我们将d的工h按钮的XML代码片断。其中的C码是黑体的。我们在后面?x)剖析这D代码?BR>  
  Qextension id="NewInvokatronAction"
  name="New Invokatron Document Action"
  point="org.eclipse.ui.actionSets"Q?BR>  QactionSet id="invokatron.actionSet"
  label="Invokatron Actions"
  visible="true"Q?BR>  Qaction id="invokatron.wizard.RunWizardAction"
  toolbarPath="org.eclipse.ui.workbench.file/new.ext"
  icon="icons/InvokatronIcon16.gif"
  tooltip="Starts the New Invokatron Document Wizard."
  class="invokatron.wizard.RunWizardAction"Q?BR>  Q?actionQ?BR>  Q?actionSetQ?BR>  Q?extensionQ?BR>  
  所有这些操作都可以在plugin.xml~辑器中用图形化的方式来完成Q但是我们查看XML以明字D늚完整文本内容。此处的QactionSetQ标记只含有一个操作(actionQ。操作表Cؓ(f)菜单中的Ҏ(gu)工具条中的按钮的对象。操作的属性实在太多了(jin)Q你可以在在U文档中查阅。其中最有趣的一些属性是Q?BR>  
  · idQ操作的唯一标识W。可以用于在q行时引用操作?BR>  
  · toolbarPathQ放|工h按钮的位|?BR>  
  · iconQ工h按钮或菜单项左侧昄的图标。它是一个与开发目录关联的16×16的GIF文g。请?囄存放到Invokatron\icons文g夹中。这个文件夹已经被包含到二进制徏立\径中Q因此该图标放入插件的文档目录中?BR>  
  · tooltipQ当鼠标停留在工h按钮上的时候出现的文本内容?BR>  
  · classQ这些操作的完整的合格的cdU?BR>  
  关于工具条\?/B>
  
  工具条\径(toolbar pathQ指Z(jin)d工具条按钮的位置。由于Q何h都可以徏立工hQ而且有时候一个按钮可以包含子选项Q因此我们用分层的标识符列表来访问这个位|。下面是l常用到的工h列表和它们的路径Q?BR>  
  · 文gQ?org.eclipse.ui.workbench.file 带有一些公q分组标志Q你可以d按钮的更多的位置Q:(x)
  
  o "新徏"区:(x)new.ext
  o "保存"区:(x)save.ext
  o "打印"区:(x)print.ext
  o "建立"区:(x)build.ext
  
  · DQ?org.eclipse.ui.workbench.navigate
  
  · 载入Q?org.eclipse.debug.ui.launchActionSet
  
  · ~辑器表C:(x)org.eclipse.ui.edit.text.actionSet.presentation
  
  · 搜烦(ch)Q?org.eclipse.search.searchActionSet
  
  · Java元素建立Qorg.eclipse.jdt.ui.JavaElementCreationActionSet
  
  · l:(x) Team
  
  · CVSQ?CVS
  
  如果你提供的工具条ID不带有标志IDQ你的按钮就?x)被d到紧挨着q个工具条的一个新工具条之上。接着q个新工h可以被d到Eclipse GUI上了(jin)。有时候你?x)看C用工h路径"正常的(NormalQ?的插件。这是旧的名U{换。在Eclipse 3中这样用的时候会(x)建立一个叫?Normal"的新工具条。如果你建立一个新工具条IDQ你的工h?x)被d?文g"工具条后面?BR>  
  h?文g"工具条的"新徏"l标志。这是我们添加自q按钮的地斏V由于标志ID是new.extQ完整的路径是Q?BR>  
  org.eclipse.ui.workbench.file/new.ext
  
  3.~写操作委托c?BR>  
  最后一步是~写量的用于实现操作的Java。这个类UCؓ(f)操作委托?BR>  
  package invokatron.wizard;
  
  public class RunWizardAction extends Action
  implements IWorkbenchWindowActionDelegate {
  /** 操作被徏立的时候调?/
  public void init(IWorkbenchWindow window) {}
  
  /** 操作被删除的时候调?/
  public void dispose() {}
  
  /** 操作被执行的时候调?*/
  public void run(IAction action) {
  InvokatronWizard wizard= new InvokatronWizard();
  Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
  WizardDialog dialog= new WizardDialog(shell, wizard);
  dialog.create();
  dialog.open();
  }
  
  /** ~辑器中的对象被选中或取消选择的时候调?/
  public void selectionChanged(IAction action, ISelection selection) {}
  }
  
  d菜单?/B>
  
  你也许猜C(jin)d菜单与d工具条按钮的q程几乎相同。你也必d明一个扩展(同种cd的)(j)、用特定的标讎ͼ相同的标讎ͼ(j)来扩充它Qƈ~写操作c(相同的类Q。其主要的不同点是扩展的声明。下面是菜单的扩展XML代码Q没有相应的工具条按钮)(j)Q?BR>  
  Qextension id="NewInvokatronAction"
  name="New Invokatron Document Action"
  point="org.eclipse.ui.actionSets"Q?BR>  QactionSet id="invokatron.actionSet"
  label="Invokatron Actions"
  visible="true"Q?BR>  Qaction id="invokatron.wizard.RunWizardAction"
  label="New Invokatron"
  menubarPath="file/new.ext"
  icon="icons/InvokatronIcon16.gif"
  tooltip="Starts the New Invokatron Document Wizard."
  class="invokatron.wizard.RunWizardAction"Q?BR>  Q?actionQ?BR>  Q?actionSetQ?BR>  Q?extensionQ?BR>  
  标签QlabelQ属性包含了(jin)昄在菜单项上的文本内容。键盘快捷键?&"W号表示Q在XML中是&。下面是一个组合了(jin)菜单和工具条按钮的例子Q?BR>  
  Qextension id="NewInvokatronAction"
  name="New Invokatron Document Action"
  point="org.eclipse.ui.actionSets"Q?BR>  QactionSet id="invokatron.actionSet"
  label="Invokatron Actions"
  visible="true"Q?BR>  Qaction id="invokatron.wizard.RunWizardAction"
  label="New Invokatron"
  menubarPath="file/new.ext"
  toolbarPath="org.eclipse.ui.workbench.file/new.ext"
  icon="icons/invokatronPicture.gif"
  tooltip="Starts the New Invokatron Document Wizard."
  class="invokatron.wizard.RunWizardAction"Q?BR>  Q?actionQ?BR>  Q?actionSetQ?BR>  Q?extensionQ?BR>  
  菜单与工h只有E微的不同。工h只有一?层次"Q而菜单有完整的层ơ。这也是用操作来声明菜单q种Ҏ(gu)可行的原因。菜单都列D在<actionSetQ标C中,在<actionQ标C上。它们的语法如下Q?BR>  
  Qmenu id="unique.ID"
  Q?-- New menu at the top-level. The menubarPath
  for actions inside this menu is: Special --Q?BR>  path="Special"
  label="This is a parent menu item."Q?BR>  Q?-- Optional, the menubarPath for actions after
  this separator is: Special/BelowBar --Q?BR>  Qseparator name="BelowBar"Q?BR>  Q?menuQ?BR>  
  关于菜单条\?/B>
  
  菜单条\径(menubar pathQ指Z(jin)d菜单的位置。我们用分层的标识W列表来讉Kq个位置。下面是l常使用的菜单条列表以及(qing)它们的\径和公共l标志:(x)
  
  · 文gQfile
  
  o "开? 区:(x)fileStart
  
  o "新徏"菜单内部?附加"l标志:(x) new/additions
  
  o "新徏"区,?新徏"菜单下面Qnew.ext
  
  o "关闭" 区:(x)close.ext
  
  o "保存" 区:(x)save.ext
  
  o "打印" 区:(x)print.ext
  
  o "打开" 区:(x)open.ext
  
  o "导入" 区:(x)import.ext
  
  o "附加" 区:(x)additions
  
  o "最q的文档" 区:(x)mru
  
  o "l束" 区:(x)fileEnd
  
  · ~辑Q?edit
  
  o "开? 区:(x)editStart
  
  o "撤销" 区:(x)undo.ext
  
  o "剪切" 区:(x)cut.ext
  
  o "查找" 区:(x)find.ext
  
  o "d" 区:(x)add.ext
  
  o "l束" 区(有时不是l束Q:(x)fileEnd
  
  o "附加" 区:(x)additions
  
  · 源:(x) org.eclipse.jdt.ui.source.menu
  
  · 重构Q?org.eclipse.jdt.ui.refactoring.menu
  
  · DQ?navigate
  
  o "开?区:(x)navStart
  
  o "Go To"菜单中的"附加"l标志:(x) goTo/additions
  
  o "打开"区(有四个)(j)Qopen.ext, open.ext2, open.ext3, and open.ext4
  
  o "昄"区(有四个)(j)Qshow.ext, show.ext2, show.ext3, and show.ext4
  
  o "附加"区:(x)additions
  
  o "l束"区:(x)navEnd
  
  · 搜烦(ch)Q?org.eclipse.search.menu
  
  · 目Q?project
  
  o "开?区:(x)projStart
  
  o "打开"区:(x)open.ext
  
  o "建立"区:(x)build.ext
  
  o "附加"区:(x)additions
  
  o "l束"区:(x)projEnd
  
  · 载入Q?launch
  
  · q行Q?org.eclipse.ui.run
  
  · "附加"l标志:(x)additions
  
  · H口Q?window
  
  o "附加"区:(x)additions
  
  o "l束"区:(x)additionsend
  
  · 帮助Q?help
  
  o "开?区:(x)helpStart
  
  o "主要l?区:(x)group.main.ext
  
  o "教程l?区:(x)group.tutorials
  
  o "工具l?区:(x)group.tools
  
  o "更新l?区:(x)group.updates
  
  o "l束"区(有时候不是结束)(j)Q?helpEnd
  
  o "附加"区:(x)additions
  
  o "关于l?区:(x)group.about.ext
  
  如果你提供的菜单条ID不带有标志IDQ那么你的菜单项出现在q个菜单条的后面。如果你建立?jin)一个新菜单条IDQ你的菜单条pd?目"?q行"菜单之间?BR>  
  Eclipse开发者提C:(x)误工具条和菜单条ID、标志位|保持一致性?BR>  
  h?文g"菜单?新徏"l标志。这是我们添加自q菜单的位|。由于它的标志ID是new.extQ所以完整的路径是:(x)file/new.ext
  
  l果
  
  操作集合中还有其它一些特性可供用,包括快捷键、状态按钮、Q动图标、帮助内容和H体工具条等{。操作集合只是记载的数十个扩展点中的一U类型的扩展。因此我们看到的只是冰山一角。但是至它使我们理解了(jin)扩展Ҏ(gu)如何工作的。我们看到的q些q程都是很好的?BR>  
  在讲解向D定义之前Q我们看一下图3所昄的新工具条按钮和菜单:(x)
  
 

  
?Q新的菜单项和工h按钮

  
  标准对话?/B>
  
  Eclipse提供?jin)所有的标准对话框和建立自定义对话框的简单途径。大多数标准对话框都是由org.eclipse.jface.dialogs.MessageDialogcL供的。这个类含有很多用于建立标准对话框的?rn)态方法。下面表格列举了(jin)我们可以使用的标准对话框?BR>  
 

  有h可能认ؓ(f)使用标准对话框的时候,JOptionPanecLMessageDialog提供?jin)更大的灉|性。但是归根结底,在MessageDialog的构造函数和自定义对话框的帮助下Q你几乎可以实现所有的事务。MessageDialog中缺而JOptionPane拥有的唯一的特性是在HTML中直接进行消息格式化。但是用自定义对话框的时候是可以实现q种功能的?BR>  
  对话框辅助类
  
  现在我们知道?jin)可供选择的类型了(jin)Q让我们来徏立Invokatron需要的对话框吧。有两个地方需要对话框Q?BR>  
  · 代码生成q程的确认信息,是否覆盖前面的代码?BR>  
  · 输入一个值的对话框(与JOptionPane.showInputDialog()cMQ?BR>  
  q个cM的第一个方法是用于认代码覆盖的:(x)
  
  public static boolean openOverwriteDialog(Shell parent) {
  return MessageDialog.openConfirm(parent,
  "Confirmation",
  "You are about to overwrite your class. " +
  "Are you sure you want to continue?");
  }
  
  上面的代码非常简单,我们仅仅建立?jin)一个常规的认对话框。输入对话框有点ȝ(ch)QMessageDialog没有输入字段。我们只能徏立一个新对话框类Q可以是Dialog的子cR我们也可以建立MessageDialog的子cdƈ重蝲它的createCustomArea()Ҏ(gu)Q添加输入字Dc(din)但是我们还有更单的Ҏ(gu)?BR>  
  我们用InputDialogc:(x)
  
  public static String openInputDialog(
  Shell parent,
  String title,
  String question,
  String initialValue) {
  
  InputDialog dlg = new InputDialog(
  parent,
  title,
  question,
  initialValue,
  null); //q是一个可供选择的有效的c?BR>  dlg.open();
  
  if(dlg.getReturnCode()!=Window.OK) //点击"认"?jin)吗Q?BR>  return null;
  
  return dlg.getValue();
  }
  
  我们的对话框辅助cd成了(jin)。你可以在图4中看到这些对话框?BR>  

  
?Q对话框

  
  Eclipse交响?/B>
  
  Eclipse与音乐类|一旦你学会(x)?jin)如何用那些可供用的乐器Q你p~写自己的交响乐?jin)。在本文中我们简短地?jin)解了(jin)两cdP(x)扩展点和对话框?

Sung 2005-11-02 15:35 发表评论
]]>
Eclipse快速上手指南之使用ANThttp://m.tkk7.com/qq13367612/articles/17821.htmlSungSungWed, 02 Nov 2005 07:32:00 GMThttp://m.tkk7.com/qq13367612/articles/17821.htmlhttp://m.tkk7.com/qq13367612/comments/17821.htmlhttp://m.tkk7.com/qq13367612/articles/17821.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17821.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17821.html  
  Eclipse中已l集成了(jin)AntQ我们可以直接在Eclipse中运行Ant?BR>  
  以前面徏立的Hello工程ZQ创Z下目录结构:(x)
  
 

  新徏一个build.xmlQ放在工E根目录下。build.xml定义?jin)Ant要执行的批处理命令。虽然Ant也可以用其它文件名Q但是遵循标准能更开发更规范Q同时易于与别h交流?BR>  
  通常Qsrc存放Java源文Ӟclasses存放~译后的class文gQlib存放~译和运行用到的所有jar文gQweb存放JSP{web文gQdist存放打包后的jar文gQdoc存放API文档?BR>  
  然后在根目录下创建build.xml文gQ输入以下内容:(x)
  
  Q?xml version="1.0"?Q?BR>  Qproject name="Hello world" default="doc"Q?BR>  
  Q?-- properies --Q?BR>  Qproperty name="src.dir" value="src" /Q?BR>  Qproperty name="report.dir" value="report" /Q?BR>  Qproperty name="classes.dir" value="classes" /Q?BR>  Qproperty name="lib.dir" value="lib" /Q?BR>  Qproperty name="dist.dir" value="dist" /Q?BR>  Qproperty name="doc.dir" value="doc"/Q?BR>  
  Q?-- 定义classpath --Q?BR>  Qpath id="master-classpath"Q?BR>  Qfileset file="${lib.dir}/*.jar" /Q?BR>  Qpathelement path="${classes.dir}"/Q?BR>  Q?pathQ?BR>  
  Q?-- 初始化Q?--Q?BR>  Qtarget name="init"Q?BR>  Q?targetQ?BR>  
  Q?-- ~译 --Q?BR>  Qtarget name="compile" depends="init" description="compile the source files"Q?BR>  Qmkdir dir="${classes.dir}"/Q?BR>  Qjavac srcdir="${src.dir}" destdir="${classes.dir}" target="1.4"Q?BR>  Qclasspath refid="master-classpath"/Q?BR>  Q?javacQ?BR>  Q?targetQ?BR>  
  Q?-- 试 --Q?BR>  Qtarget name="test" depends="compile" description="run junit test"Q?BR>  Qmkdir dir="${report.dir}"/Q?BR>  Qjunit printsummary="on"
  haltonfailure="false"
  failureproperty="tests.failed"
  showoutput="true"Q?BR>  Qclasspath refid="master-classpath" /Q?BR>  Qformatter type="plain"/Q?BR>  Qbatchtest todir="${report.dir}"Q?BR>  Qfileset dir="${classes.dir}"Q?BR>  Qinclude name="**/*Test.*"/Q?BR>  Q?filesetQ?BR>  Q?batchtestQ?BR>  Q?junitQ?BR>  Qfail if="tests.failed"Q?BR>  ***********************************************************
  **** One or more tests failed! Check the output ... ****
  ***********************************************************
  Q?failQ?BR>  Q?targetQ?BR>  
  Q?-- 打包成jar --Q?BR>  Qtarget name="pack" depends="test" description="make .jar file"Q?BR>  Qmkdir dir="${dist.dir}" /Q?BR>  Qjar destfile="${dist.dir}/hello.jar" basedir="${classes.dir}"Q?BR>  Qexclude name="**/*Test.*" /Q?BR>  Qexclude name="**/Test*.*" /Q?BR>  Q?jarQ?BR>  Q?targetQ?BR>  
  Q?-- 输出api文档 --Q?BR>  Qtarget name="doc" depends="pack" description="create api doc"Q?BR>  Qmkdir dir="${doc.dir}" /Q?BR>  Qjavadoc destdir="${doc.dir}"
  author="true"
  version="true"
  use="true"
  windowtitle="Test API"Q?BR>  Qpackageset dir="${src.dir}" defaultexcludes="yes"Q?BR>  Qinclude name="example/**" /Q?BR>  Q?packagesetQ?BR>  QdoctitleQ<![CDATA[Qh1QHello, testQ?h1Q]]Q</doctitleQ?BR>  QbottomQ<![CDATA[QiQAll Rights Reserved.Q?iQ]]Q</bottomQ?BR>  Qtag name="todo" scope="all" description="To do:" /Q?BR>  Q?javadocQ?BR>  Q?targetQ?BR>  Q?projectQ?BR>  
  以上xml依次定义?jin)initQ初始化Q,compileQ编译)(j)QtestQ测试)(j)QdocQ生成文档)(j)QpackQ打包)(j)dQ可以作为模ѝ?BR>  
  选中Hello工程Q然后选择“Project”,“Properties”,“Builders”,“New…”,选择“Ant Build”:(x)
  
 

  填入NameQAnt_BuilderQBuildfileQbuild.xmlQBase DirectoryQ?{workspace_loc:/Hello}Q按“Browse Workspace”选择工程根目录)(j)Q由于用C(jin)junit.jar包,搜烦(ch)Eclipse目录Q找到junit.jarQ把它复制到Hello/lib目录下,q添加到Ant的Classpath中:(x)
  
 

  然后在Builder面板中钩上Ant_BuildQ去掉Java BuilderQ?BR>  

  再次~译Q即可在控制台看到Ant的输出:(x)
  
  Buildfile: F:\eclipse-projects\Hello\build.xml
  
  init:
  
  compile:
  [mkdir] Created dir: F:\eclipse-projects\Hello\classes
  [javac] Compiling 2 source files to F:\eclipse-projects\Hello\classes
  
  test:
  [mkdir] Created dir: F:\eclipse-projects\Hello\report
  [junit] Running example.HelloTest
  [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.02 sec
  
  pack:
  [mkdir] Created dir: F:\eclipse-projects\Hello\dist
  [jar] Building jar: F:\eclipse-projects\Hello\dist\hello.jar
  
  doc:
  [mkdir] Created dir: F:\eclipse-projects\Hello\doc
  [javadoc] Generating Javadoc
  [javadoc] Javadoc execution
  [javadoc] Loading source files for package example...
  [javadoc] Constructing Javadoc information...
  [javadoc] Standard Doclet version 1.4.2_04
  [javadoc] Building tree for all the packages and classes...
  [javadoc] Building index for all the packages and classes...
  [javadoc] Building index for all classes...
  [javadoc] Generating F:\eclipse-projects\Hello\doc\stylesheet.css...
  [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.
  [javadoc] Note: Custom tags that were not seen: @todo
  BUILD SUCCESSFUL
  Total time: 11 seconds
  
  Ant依次执行初始化,~译Q测试,打包Q生成API文档一pddQ极大地提高?sh)(jin)开发效率。将来开发J2EE目Ӟq可加入部v{Q务。ƈ且,即q?jin)Eclipse环境Q只要正安装了(jin)AntQ配|好环境变量ANT_HOME=QAnt解压目录Q,Path=?%ANT_HOME%\binQ在命o(h)行提C符下切换到Hello目录Q简单地键入ant卛_?

Sung 2005-11-02 15:32 发表评论
]]>
在Eclipse中如何利用Maven http://m.tkk7.com/qq13367612/articles/17819.htmlSungSungWed, 02 Nov 2005 07:20:00 GMThttp://m.tkk7.com/qq13367612/articles/17819.htmlhttp://m.tkk7.com/qq13367612/comments/17819.htmlhttp://m.tkk7.com/qq13367612/articles/17819.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17819.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17819.html  
  在过dq中QMaven 已经不仅仅是 Java 世界的一个时髦话题。自 2001 qvQMaven 已经成ؓ(f)构徏工具领域的先驱。最q几q_(d)Z常拿它与 Ant 比较。因?Maven ?Ant 有一些显而易见的怼之处Q所以拿它们俩作比较g是很自然的事?BR>  
  比如_(d)在两U情况下QXML 脚本都是可用的;两种工具都可以生产工Ӟ它们q可以共享相同的分类法和概念Q比?目QprojectQ、目标(targetQ与 目标QgoalQ,以及(qing) 依赖关系QdependsQ??先决条gQprereqsQ。但它们实质上有很大的差别?BR>  
  Ant 只是一?XML 脚本工具Q?Maven 是一个普通的构徏工具Q它x(chng)的重Ҏ(gu)一个叫做项目对象模型(POMQ的概念。POM 暴露的是_粒度的、面向构建的dQ这些Q务被UCؓ(f)目标Q它们提供了(jin)一些准则,帮助(zhn)开发构建方法和实现最?jng)_c(din)?BR>  
  在某些方面,Maven 属于软g工厂管目前它仍在外围。更切地说Q诸?Maven 之类的构建工h软g工厂领域中必不可的?BR>  
  软g工厂
  
  通过显著提高自动开发的U别QY件工厂提供了(jin)一个花Ҏ(gu)、更灉|的应用程序开发方法。根?Software Factories Web 站点的说法,“Y件工厂是一个Y件品线Q它Ҏ(gu)构徏Ҏ(gu)U类的应用程序的Ҏ(gu)Q配|一些可扩展的开发工具……提供打包的内容……以?qing)指导”?BR>  
  软g工厂涉及(qing)三个主要概念Q?/B>
  
  模式Q提供了(jin)一些元数据Q描q组成应用程序的不同工g的结构,以及(qing)它们是如何交互的?一个或多个模板Q提供了(jin)启动E序工具,以及(qing)构徏应用E序所需的其他Q何东ѝ?可扩展的开发环境,用于配置、定制和装配lg?BR>  
  如今Q这cd具已l逐渐引v?jin)认识到它们的h(hun)值的那些工具刉h员、工具开发h员和软g~辑的注意。这些工具促(j)q了(jin)软g开发过E的工业化,降低?jin)投入?jng)场的成本和时_(d)同时q提高(sh)(jin)生率,加快?jin)对q化需求的反应?BR>  
  仔细查看一?Maven 的主要特性,(zhn)就?x)认识?Maven 与Y件工厂之间的怼之处QMaven 使用 POM 作ؓ(f)元数据来描述目l构Qƈ通过通用应用E序插g来获得可扩展的项目模ѝ?BR>  
  因ؓ(f) Maven 非常灉|q且是开放源码的Q所以很Ҏ(gu)推断和设?Maven 是Y件工厂^C的一个核?j)组件。但是,q有另一U说法。上q类比ƈ不完全,因ؓ(f)目前?Maven ~Z专用的开发环境,而这cȝ境有助于创徏特定于域或特定于企业的插件和模板Qƈ允许(zhn)轻村֜配置目或定制行为?BR>  
  不过QMaven 的主要目标是标准化构E,q保证代码构?试-部vQCBTDQ@环中的质量和易再现性(easy reproducibilityQ。它q可以制定度量标准,帮助(zhn)了(jin)解开发状态?BR>  
  CBTD 本体论在软g工程领域已经不再新鲜Q但 Maven 可以使?zhn)标准化这U本体论Qƈ通过抽象q种理论Q将它想像成一个完整的实体。考虑C断增长的目的复杂性,标准化成ZU迫切需要?BR>  
  扩徏的概念,我们UC为元构徏Q因为其无可估量的h(hun)g?qing)保证下一U质量的Ҏ(gu),正逐渐被h们认识。持l集成(continuous integrationQ就是徏立在q个概念的基之上Q但它也应用?jin)?IDE 上下文之外的地方q行构徏的能力?BR>  
  模糊的界?/B>
  
  使用q?Java 技术的人应该都听说q?Eclipse?001 q年中的时候,Eclipse 推出?jin)它的第一个版本,标志其成熟的是它为集成开发环境(IDEQ提供了(jin)一个机?x),特别是?f) Java 开发h员(不严谨地_(d)(j)提供?jin)一个机?x)?BR>  
  Eclipse 是一U开攄、以语言Z?j)的q_Q也可以它用作教育性项目和研究目的基q_Q其中一些^台捐赠给?Eclipse 团体?BR>  
  像 Microsoft已经采用软g工厂Ҏ(gu)一PEclipse 也开始{向模型驱动开发(MDDQ方向,q且最q已l公布了(jin)一个新的项目提?—?模型驱动的开发集成(MDDiQ?BR>  
  Ҏ(gu)该提议,“Eclipse MDDi 目专用于^台的实现……其设计目标是支持各U徏模语aQ统一建模语言或特定于域的语言Q和模型驱动的技术。?BR>  
  渐渐圎ͼ一些工具开始假定某些特性可以完全ƈ且顺利地集成在一PMaven ?EclipseQ即使作Z个简单的 IDEQ也不例外。因此,从构建的角度来看Q二者似乎出C(jin)重叠Q如?1 所C?BR>  

  
?1. 扩徏的概?/CENTER>
  
  ?描述的实际上是以前讨论的扩徏概念。正如以前定义的那样Q整个扩E包括几个Q务,同时q表CZ(jin)一个元构徏实例。Q务可以是以下两种cd之一Q原子Q务是l粒度的Qƈ且是上下文不明确的,q种d的两个实例几乎是相同的;宏观d是复合Q务,它充当微观Q务的容器?BR>  
  构徏Q从扩展的意义上_(d)只处理宏观Q务;原子d的触发取决于配置。这意味着用户对系l有着较高层次的看法,q得系l更易于l护和发展?BR>  
  此外QMaven ?Eclipse 都是开攄Qƈ且很Ҏ(gu)通过插g扩展它们Q其满x(chng)的需要。但是,因ؓ(f)它们针对的受众不同,所以它们之间的怼性也到此为止Q多?Eclipse 最l用h一些开发h员;?Maven 主要针对的是一些构建管理h员?BR>  
  管如此QMaven 仍然是一个命令行工具。虽然图形用L(fng)面(GUIQ是按照 Jason Van ZylQMaven 的制造者和架构师)(j)指示的方向开发的Q但 Maven 目前仍然没有帮助用户执行Ҏ(gu)d的特?GUIQ比如创建或更新配置Q或者只用一个鼠标单dh建?BR>  
  上面描述的典型构建顺序在 Eclipse 中不像在 Maven 中那么顺利。Eclipse 的特性之一是开?环境造成构徏q程不连l,q要归因于一些h为因素:(x)q不是每ơ成功编译之后都q行试、所有测试没必要一ơ运行、可以蟩q一些微观Q务,{等?BR>  
  各种因素都会(x)D产生差异Q这是Z么开发h员每天至必运行一ơ完整的构徏q程Q以信他们没有破坏什么的原因?BR>  
  不过Q因?Eclipse 是一个可扩展q_Q所以它受到许多用户C֌的支持,q它成为驻?Maven 驱动的开发、允许开发h员和构徏理人员?sh)某U简单的方式q行协作的理想之地?BR>  
  ?Maven 集成?Eclipse ?Mevenide ?Codehaus d的一个项目,旨在通过?Maven 集成?IDE 中,?Maven 的用?BR>  
  现在QBorland Software ?JBuilder、NetBeans ?Eclipse 都受到支持。其他一些项目也部分地将 Maven 集成?Eclipse 中,q样Q就可以?MevenideQ如 Maven WorkshopQ共享一些特性。除?jin)增?Maven 的易用性之外,Z么需要这U插Ӟ
  
  通过提供一些工具和视图Q让(zhn)了(jin)?Maven 隐藏的复杂性ƈ改进团队环境中的协作QMevenide for Eclipse 提高?sh)(jin)生产率?BR>  
  从协作的角度来看Q假如构建已l被 Maven 化了(jin)Q那么最有用的特性就?Eclipse 目元数据与 Maven 元数据之间的双向同步。如果开发h员忘记在?Eclipse 中添加一个依赖关pM后更?POMQ那么该怎么办?
  
  如果重构无法传播?MavenQ该怎么办?构徏可能?x)中断,或者一些单元测试可能被拒绝Q因此,真的需要 Eclipse 元数据和 Maven 元数据保持同步。Mevenide 监听元数据的变化Qƈ使?zhn)能够很容易地定元数据不匚w的地方,q可以防止进行被严重破坏的构建?BR>  
  ?POM q不只是关于依赖关系和项目布局的。它q包含一些不用于l构上的目理信息Q比如版本号、名U、ID 和源储存库的位置。Eclipse 元数据ƈ不L反映所有这些信息?BR>  
  因此Q需要另一个编辑这些信息的Ҏ(gu)。ؓ(f)此,Mevenide 提供?jin)一个图形编辑器Q该~辑器 POM 的维护变得更Ҏ(gu)Qƈ允许(zhn)避开一些烦(ch)琐的、容易出错的原始 XML 手工~辑。每?POM 语义部分都被表示Z个编辑器,q增Z(jin)模型的整体可靠性?BR>  
  此外Qؓ(f)?jin)最大限度地减少创徏 POM 的无聊过E,Mevenide 提供?jin)一个相当简单的、可扩展?POM 模板机制?BR>  
  L Maven ?Eclipse 之外的地方运行的能力是从cM Mevenide 的插件中最Ҏ(gu)获得的一功能。?zhn)可以选择某些执行dQ用 Maven 的术语来讲是 目标Q,q些d可以是通过 Maven 插g全局定义的Q务,也可以是依赖于项目的dQ或者,(zhn)可以通过定义构徏敏感的变量来定制构徏?BR>  
  Eclipse 控制C只显CZ(jin)一些相关的选项Q即?IDE 的上下文中相养I(j)Q对于其他Q何插Ӟ控制C只输出构建日志。这一Ҏ(gu)非帔R要,因ؓ(f)它避免了(jin)在控制台?Eclipse 之间不停地来回奔波?BR>  
  Mevenide q集成了(jin)其他许多帮助Ҏ(gu)Ҏ(gu),但它们不是很重要。例如,(zhn)可以定义给定目标与文g模式之间的关p,q样Q就可以Ҏ(gu)工作I间增加的增量来Ȁz那些Q务?BR>  
  (zhn)还可以览工g储存库,或者根据名U搜索某个给定的工gQ一个工?是一个构建结果,它可以是 JAR 文g、可执行文g或者是一个完整的 Web 站点Q。然后,可以重定向到 Mevenide 站点Q获得完整的Ҏ(gu)列表?BR>  
  不过Q仍然还有一个问题:(x)即 Mevenide 增强?jin)生产率和易用性,但?zhn)仍然必须认识到哪些工具可以在?gu)环境中满x(chng)的需要。通过 Maven Console q行 Maven ?x)话可能非常耗时Q所以,Z(jin)获得较高的生产率Q在对会(x)话进行编码期_(d)应该改ؓ(f)使用 JUnit 集成?Eclipse 支持来运行测试,q依赖于 Eclipse 的内部编译器来生成可执行的文件?BR>  
  但在向源代码储存库提交Q何东西之前,应该保 POM 是同步的Qƈ回滚所有不需要的 .classpath ?.project 修改 —?也就是说Q假设这些文仉是在源代码控制之下,q可能是有争议的。这个话题在 Martin Van den Bemt ?blog 中讨?BR>  
  l束?/B>
  
  管 Maven ?Eclipse h不同的特性,但从构徏的角度看Q它们在某些地方可能出现重叠。它们之间存在的对立g也相当多Q但我们很容易克服这些,通过努力最l它们怺协作Q共创一片沃土?BR>  
  诸如 Mevenide 之类的工具可以 Maven ?Eclipse 利合作Qƈ使它们保持同步,但?zhn)必须认识刎ͼ在某一个给定的开发阶D,哪种工具最能满x(chng)的需要?BR>  
  管 Maven 作ؓ(f)质量保证q程中的一个重要因素,正逐渐被h们所认可Q但在将它集成到开发环境(其?EclipseQ中Q Maven 成ؓ(f)一{?IDE 公民q一点上Q还有待提高?BR>  
  到那Ӟ我们可以考虑其他?Maven 用例Q比如说Q更q一步地它集成到全局开发过E中Q以?qing)?Eclipse q样的可扩展环境如何帮助实现q些集成?

Sung 2005-11-02 15:20 发表评论
]]>试实践QEclipse ?JUnithttp://m.tkk7.com/qq13367612/articles/17818.htmlSungSungWed, 02 Nov 2005 07:19:00 GMThttp://m.tkk7.com/qq13367612/articles/17818.htmlhttp://m.tkk7.com/qq13367612/comments/17818.htmlhttp://m.tkk7.com/qq13367612/articles/17818.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17818.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17818.html  
  自动化测试(automated testingQ在好多书籍中被介绍?jin),但很注意讲怎样ȝl这些测试?当测试写的越多时Q很隄道把q些试攑ֈ哪或者用什么去调用它们?在极限编E?--Extreme Programming(xp)Q测试驱动开?Test-Driven Development (TDD)盛行的时代,q成?jin)一个很大的问题?你可以把 试驱动开发(TDDQ认为是"Development through testing" 开发由l测试?BR>  
  TDD的主要条ƾ:(x)
  
  在Q何代码片D之前,必须先写好自动检这D代码功能的E序。既然代码不存在Q那么测试在一开始就p|?BR>  
  ?试通过之后Q复制的代码必须删掉?BR>  
  象这L(fng)方式每个E序员都可以应用Qƈ不需要特定的Ҏ(gu)论。但在我们开始写test之前Q?值得我们注意的是Q先考虑一下如何组l自动化试?BR>  
  q里有几U我们需要考虑的测?BR>  
  单元试(Unit test) :q些是ؓ(f)(g)查个别模块(比如classesc)(j)服务的?如果对象需要访问外部的数据源,比如DatabaseQ就需要通过一些模拟的对象QMOCK objectQ来模拟DatabaseQ?Q但q也只有在真实环境的数据与测试环境不同的时候?BR>  比如试环境里面没有真实Datebase,需要MOCK ObjectQ?BR>  
  用户试 QCustomer's testQ?q里是功能的Q系l的q且认可的测试。系l中所有的行ؓ(f)(g)查都做ؓ(f)一个整体?在XP理论中,q些试Q是qL(fng)写的Q给出测试案例提UӀ?BR>  
  集成试 QItegration testsQ? q些试象是在用h试和单元试之间的十字\口?集成试帮助E序试几个U别中交互?QMock Object不会(x)出现在集承测试中Q他?x)增加测试时间。同P集成试也经帔R要存在的特定的测试环境,比如从数据库中放一些测试数据。集成测试也怋用外部的lib?Cactus是q样一个J2EE集成的lib?解释q些试已经出?jin)本文章的范围Qƈ且也需要详l的理论叙述Q所以,你仅需要知道这U测试存在就可以?jin)?BR>  
  开发测试(Developer's testQ?: q种试是那些开发者校?整段代码Q新加的代码Q新加的函数函数?对于每个开发而言Q?随时生成新的的测试去(g)查代码是很重要的?l织q些试和组l这些代码有着同样的重要性?BR>  
  至于本文其他地方Q只要说?试"Q就是专指开发测试(Developer's testQ?BR>  
  在开发期_(d) 一个程序员有时可能问自己:(x)pȝ中这个行为有test么,q个test存在么,哪里可以扑ֈq个testQ每ơ发现错误,都是靠最基础修改bug而不是通过自动试Q这是一个典型的例子?在这U情形下事情q展可能是:(x)
  
  L到这个函数的试Q可能测试已l写?jin),但里面还有一些小错误Q?BR>  如果q样的测试还没有Q或者测试不能盖住这U错误,我们写一个新的测试来盖住q种错误?BR>  现在 我们׃Q程序在新的试中不?x)通过?BR>  修复E序中的bug?BR>  再运行测?BR>  定E序在测试中通过?jin)?BR>  
  当然Q可能出现各U各L(fng)处理Q?但思想必须很明:(x)你只需U正那些被测试找出那些错误?BR>  
  现在Q让我们告诉你一个开发h员怎样解决q种情Ş?通过存在的功能性的试
  
  我利用一些集成的开发环境(IDEQ来查找 被修正那些类和方法的攑֜什么地斏V?BR>  
  刉一个已知的错误环境Q来查找那些代码判断存在错误?BR>  
  最后但不是最不重要的Q写好测试ƈ且放C个现有的试cM厅R?如果你不心(j)Z(jin)错误Q?期望你和你的同事能注意到副本Qƈ且纠正它
  
  都准qAQ开始徏立测试了(jin)Q?所以现在需要给试取一个名U?你可能说Q“这不是问题: 在每个类面前加个Test是?jin)!?但ƈ不是那么单的Q?让我告诉你这样如果可能造成的问题:(x)
  
  当时候我们在使用TDD的方式开发时Q?需要测试的class或者method可能都不存在?BR>  
  也可能一个test 含盖?jin)好几个?gu)Q甚臛_几个classes?BR>  
  q些仅仅是最普通的问题Q?下面q有更多?BR>  
  l个在test命名上的: test cȝ取名首先应该表达?gu)个类是一个testc,q且能确切的表示Z要检查哪些,留有q个原class名的味道?其实q很Ҏ(gu)Q请别担?j)这个名UC(x)变的很长或者很丑陋Q自己随便怎样取都可以?BR>  
  下面我们用Eclipse中的JUnit工具建立我们的第一个测试,假定你已l下载了(jin)q个产品的当前版本, 如果没有Q你随时可以从它的官方网?www.eclipse.org)下蝲。我们需要JUnit,你也可以从它的官方网站(www.junit.orgQ上下蝲Q下载ƈ解压~到你硬盘(sh)存放java libaries的地斏V?BR>  
  打开Eclipse.我们徏立一个新的工E的工作I间Qworkplace projectQ??File -> New ->Project,选择Java一路Next?输入工程名称Qproject nameQ,比如ProjectWithJUnit. 点击完成?q样徏立了(jin)一个新工程Q让我们配置一下我们的Eclipse,于是Q我们把JUnit library d到build path. 点击 Project-->Properties, 选择Java Build Path Libraries, 点Add Exteranal JARs 选中JUnit.jar?你将?x)看到JUnit会(x)出现在的屏幕?libraries列表中?点Okay,Eclipse强制rebuild所有的build paths.
  
  我们已经准备好,开始写我们?Hello World"?. 让我们遵照TDD规范Q在~码之前徏立测试。ؓ(f)?jin)?我们假我们将要写的类名是HelloWorld 有一个返回字W串的方?say().
  
  要徏立这样一个test, 在ProjectWithJUnit标题?sh)右键?选择New -> Other,展开"Java"Q?选择JUnit. 在对话框的右边一拦里选择TestCase,接着点Next. 参见??BR>  
  
 

  ??在Eclipse 中徏立JUnit test
  在Test class:一拦里输入我们需要测试的class--HelloWorld。ƈ且给Test case取个名称--- 比如QTestThatWeGetHelloWorldPrompt(是的Q这看上d长了(jin)Q但是它能很清楚表达出它的意? 点Finish完成?BR>  
  下面?TestThatWeGetHelloWorldPrompt.java的代码:(x)
  
  public class TestThatWeGetHelloWorldPrompt
  
  extends TestCase {
  
  public TestThatWeGetHelloWorldPrompt(
  
  String name) {
  
  super(name);
  
  }
  
  public void testSay() {
  
  HelloWorld hi = new HelloWorld();
  
  assertEquals("Hello World!", hi.say());
  
  }
  
  public static void main(String[] args) {
  
  junit.textui.TestRunner.run(
  
  TestThatWeGetHelloWorldPrompt.class);
  
  }
  
  }
  
  q个代码一炚w不复杂,仅仅有一点点特别?不管怎样Q让我们详细的检查它?我们l承?jin)JUnit的TestCase. (TestCase 在JUnit的javadoc里定义是"用来q行多个Test的固定装|?)?JUnit也定义了(jin)TestSuite ׃一l关联的TestCasel成..
  
  通过以下两步来徏立我们简单的Test Case;
  
  建立Junit.framework.TestCase的实?
  定义一??test"开头的试函数, q且q回一I?(比如 testWasTranscationSuccessful(),testShow(){等).
  
  TestThatWeGetHelloWorldPrompt.java 同时遵@q些标准: q些TestCase的子cd有一个testSay()的方? q个Ҏ(gu)由assertEquals()Ҏ(gu)调用, 用于(g)验say()的返回|按照q里的做法返回应该是不一_(d)因ؓ(f)一开始徏立的HelloWorld 我们让say()q回的值是nullQ?
  
  main()d数是用来q行testq且昄输出的结? JUnit的TestRunnery以(swing.uQ图形和本文Qtext.uiQ的的方式来执行我们的testq反馈信息。我们就使用文本(text.ui),q个Eclipse肯定支持. Q译注:(x)q里可能译的不怎么好,所谓文本和囑ŞQ是指你在徏立TestCase的时候,有一个选项QW(xu)hich method stubs would you like to create,选择text.ui|| swing.ui||awt.uiQ一般是选择text.ui因ؓ(f)Eclipse肯定支持q个Q? 依照q些文本的信?Eclipse同时?x)生成图形显C。(在Package Exploer的下面Tab条上?x)多个JUnit,点它?yu)qC(jin):Q?BR>  
  又一个所?按照现在q样试驱动的开发的做法, 一旦我们跑起了(jin)我们的test,我们应该看到q回一些错误的信息?点Run-> Run as -> JUnit TestQ注意啊Q?q个TestThatWeGetHelloWorldPrompt.java应该在Package Explorer被点中,在左辚w个window中)(j),你点到的因该是JUnit windowQ就是下面的那个Tab条,注意不是Package Exploer)Q这样你qC(jin)JUnit windowQ?他会(x)昄一个红色条Q表C是一个失败的Test?(如果你按?jin)运行它没有自动转到q个H口Q你可以点做下Tab?上的JUnit标签?
  
 

  一按运? 太好?jin),果然出错了(jin)。好Q现在正式开始徏立用于工作的HelloWorld代码Q?--点New->ClassQ可能和原来的的重复Q那把原来的删掉。代码如下:(x)
  
  HelloWolrd.java
  
  public class HelloWorld {
  
  public String say() {
  
  return("Hello World!");
  
  }
  
  }
  
  q及(qing)为简单的Q都用不着注释。现在再来测试一下看看结果。就用上面的Ҏ(gu)Q点Run-> Run As Jnit. 在左边的JUnitH口中出C(jin)一个绿条?看图三?出现l色的条表示试通过?jin)?BR>  
  
 

  现在Q再变(sh)条g,让测试不通过?q将帮助我们理解JUnit test怎样覆盖q且报出不同的错误?~辑 assertEquals()Ҏ(gu)Q把它的q回g"Hello World!"变成另外一个?比如"Hello ME!". q样Q当你再q行q个JUnit testQ那个显C条又变成红的了(jin)Qƈ且在Failuer Trace里看到是不是什么导致了(jin)错误?如图:
  
  

  ȝ。我惌一些自qx(chng)(q里q是原文不是译q来??我过dƈ不认为测试代码是开发过E中很重要的一部分?但在最q几q发展的很快,多亏?jin)那些方法?比如Z异常开?exceptions-based development"{?,他们?j)进了(jin)测试以及(qing)测试工L(fng)发展?BR>

Sung 2005-11-02 15:19 发表评论
]]>
利用Eclipse开发Hibernate应用E序http://m.tkk7.com/qq13367612/articles/17817.htmlSungSungWed, 02 Nov 2005 07:18:00 GMThttp://m.tkk7.com/qq13367612/articles/17817.htmlhttp://m.tkk7.com/qq13367612/comments/17817.htmlhttp://m.tkk7.com/qq13367612/articles/17817.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17817.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17817.html  
  首先需要安装这个插ӞEclipse 3.0.1为我们提供了(jin)更加方便的插件管理方式,选择菜单“帮?软g更新?查找q安装”(本h的Eclipse使用?jin)语a抱汉化,误文界面用戯行对照)(j)Q选择“搜索要安装的新功能部g”,操作界面如下Q?BR>   
  选择“新E站点”,填写名称“Hibernate plugin”,下面的URL中填入:(x)http://www.binamics.com/hibernatesync
  如下图:(x)
   
  然后在“安装”界面中选中我们刚添加的“Hibernate plugin”,一路NextQEclipse可以自׃载完成安装,然后Eclipse自动重启动一ơ就完成?jin)?BR>  
  下面演示一个最单的单表操作Q可以让我们很快熟?zhn)开发过E。我们选择Mysql数据库来做这个应用,首先建立一个数据表Q名为user_infoQ包含id、name、password三个字段Q徏表语句如下:(x)
  
  # Host: localhost
  # Database: test
  # Table: 'user_info'
  #
  CREATE TABLE `user_info` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL default '',
  `password` varchar(100) NOT NULL default '',
  PRIMARY KEY (`id`)
  );
  
  然后新徏一个普通的Java目Q“新?目?Java目”,注意加入Hibernate的所有lib文gQ以?qing)mysql的jdbc驱动文g。下面我们需要在目中加入一个Hibernate的配|文Ӟ在src目录下选择“新?其他?hibernate?hibernate configuration file”,如下图:(x)
   
  在弹出的界面中,你需要指定要使用的数据库Q以?qing)连接数据库所需要的信息Q我们对应的选择?jin)数据库为mysqlQƈ配置?jin)数据库的URL和管理员帐号Q如下:(x)
   
  在上图中Q我们还可以指定从JNDI数据源中获得q接Q可以点几ZDatasource“标{进行配|?BR>  
  “完成”之后系l会(x)自己生成一个名为“hibernate.cfg.xml”的文gQ里面包含了(jin)基本的配|信息,如果需要高U配|,可以手动d?BR>  
  下面我们要生成映文Ӟ首先新徏一个包“org.bromon.zizz.pojo”,在这个包下选择“新?其他?hibernate?hibernate mapping file”,在弹出的界面中点几Z刷新”,讲会(x)列出库中所有的数据表,选中我们要用的“user_info”表Q以?qing)我们要生成的pojo文g所在的包:(x)org.bromon.zizz.pojo。如下图Q?BR>   
  在上q界面的“Properties”标{中可以配置hbm的其他选项Q包括文件扩展名Q聚合列名,ID生成规则{。完成后Q系l会(x)自动生成一个名为“UserInfo.hbm”的文gQ我们可以通过q个文g生成相关的存根类。在UserInfo.hbm文g上选择“Hibernate Synchronizer?Synchronize files”:(x)
   
  该操作将生成三个包八个类文gQ里面封装了(jin)Hibernate的操作细节,让我们可以专?j)面对业务逻辑的开发,仔细阅读q些文g可以提高?sh)对Hibernate的认识,增长应用技巧?BR>  
  然后我们需要在Hibernate的配|文件中d对UserInfo的相关信息,在UserInfo.hbm上选择“Synchronizer?Add Mapping Reference”。现在我们可以开始编写自qE序逻辑?jin),代码可以写在org.bromon.zizz.pojo.dao. UserInfoDAO中,q个cȝ代码不会(x)被插件修攏V我们首先创Z条新的记录,在该cM加入一个mainҎ(gu)Q?BR>  
  public static void main(String args[])
  {
  try
  {
  _RootDAO.initialize();
  UserInfoDAO uid=new UserInfoDAO();
  
  org.bromon.zizz.pojo.UserInfo ui=new org.bromon.zizz.pojo.UserInfo();
  ui.setName("bromon");
  ui.setPassword("123");
  
  uid.save(ui);
  
  }catch(Exception e)
  {
  e.printStackTrace();
  }
  }
  
  可以看出Q插件已l把session操作和事务操作都装h?jin),我们的代码工作得C(jin)极大的简化。而且我们可以利用插g自带的Hibernate editor来编辑hbm文gQ非常方便,我们需要把ID的生成方式改为“identity”:(x)
  
  要让q个E序正常q行Q还需要对配置文ghibernate.cfg.xml作一些修攏V值得注意的是Q请不要在该插g以外的环境中修改配置文gQ比如用DreamWeaver之类的工L(fng)辑文Ӟ(j)Q否则会(x)造成pȝ与资源不同步的错误,q可能是插g的一个bug。用Eclipse的“文本编辑器”打开该文Ӟ其中有如下的内容Q?BR>  
  Qproperty name="hibernate.transaction.factory_class"Q?BR>  net.sf.hibernate.transaction.JTATransactionFactory
  Q?propertyQ?BR>  Qproperty name="jta.UserTransaction"Q?BR>  java:compUserTransaction
  Q?propertyQ?BR>  
  ׃在我们的例子中,q没有用JTA来控制事务,所以需要将上面的内Ҏ(gu)释掉Q程序才能正常运行?BR>  
  OKQRun一下,可以看到数据已经被保存到数据库?BR>  
  如果在实际开发工作中Q需要重新设计数据表l构Q那么只需要在.hbm文g中做相应的修改,然后执行“Synchronize and Overwrite”的操作Q插件会(x)重新生成存根文gQ我们只需要修改程序逻辑可以了(jin)Q非常方ѝ有?jin)这L(fng)功能插gQ我们可以极大的从配|文件的~写、查错中解脱出来Q从而提高我们的工作效率?

Sung 2005-11-02 15:18 发表评论
]]>
利用Myeclipse快速开发struts应用E序 http://m.tkk7.com/qq13367612/articles/17816.htmlSungSungWed, 02 Nov 2005 07:14:00 GMThttp://m.tkk7.com/qq13367612/articles/17816.htmlhttp://m.tkk7.com/qq13367612/comments/17816.htmlhttp://m.tkk7.com/qq13367612/articles/17816.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17816.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17816.html  jdk5.0
  eclipse3.1M7
  myeclipse3.84
  tomcat5.0.28
  
  介:(x)
  文本主要介绍用myeclipse的struts designerQ图形化开发环境)(j)开发一个简单的用户dE序片段?BR>  主要包括2个jsp文g、一个ActionForm、一个Action{其?BR>  userLogin.jsp(用户d?qing)错误提C页? userLoginSuccess.jsp(提示d成功面)
  UserLoginForm.java(ActionForm,存放用户提交信息)
  UserLoginAction.java(Action,单的处理用户d事g)
  
  开始吧
  首先我们先徏立一个j2ee的web project.如图1:
  
 

  点击next,Project name输入LoginDemo,其余保持默认,点击finish.
  在package explorer?可以看到我们的目?然后l这个项目添加Struts框架必要的文?在我们项目名上点d?选择MyEclipes --> Add Struts Capabilities...弹出对话框图2Q?BR>  
 

  其中Struts config path是我们的struts配置文gQURL pattern我们选择*.doQDefault application resource为我们默认的资源文g地方Q你可以选择它的存储位置Q我们在q里保持默认。点击Finish后,目l构cM于图3Q?BR>  
 

  现在来开始我们的例子吧。首先修?WEB-INF/web.xml文g,为其d标签?在用中发现Q不d也能成功。但Z(jin)保持书上一_(d)q是d安全些。hoho~~)下面代码添加至 上面Q?BR>  
  
  /tags/struts-html
  /WEB-INF/struts-html.tld
  

  
  
  /tags/struts-bean
  /WEB-INF/struts-bean.tld
  

  
  
  /tags/struts-logic
  /WEB-INF/struts-logic.tld
  

  完成后,打开struts-config.xml文gQ点击这个界面左下角的Designq入可视化设计界面。有没有注意双的Palette :) 点击它,让我们来开始我们的jsp面设计。我们先建立userLoginSuccess.jsp文gQؓ(f)啥先一个呢Q等下就知道?jin),在myeclipse中可以一ơ性把我们的Action,ActionForm,Jsp文g一ơ徏好(三个有兌的文件等下创建)(j)?BR>  点击Palette面版上的创徏JSP文g图标,弹出创徏JSP文g面板。图4Q?BR>  
 

  在File Name里输入userLoginSuccess.jspQTemplate to use选择2] Standard JSP using Struts 1.1,点击Finish完成?BR>  完成后,struts-config.xml文g自动被更斎ͼ可视化界在上也出C(jin)刚新建的JSP模块。新建的jsp文g也被打开?jin)?BR>  覆盖所有的<%@ taglib ...... 为我们开始在/WEB-INF/web.xml中定义的Q?BR>  
  <%@ taglib uri="/tags/struts-html" prefix="html"%>
  <%@ taglib uri="/tags/struts-bean" prefix="bean"%>
  <%@ taglib uri="/tags/struts-logic" prefix="logic"%>
  
  然后在中d:
  Hello .
  q里request中的属性userName输出在页面上Q所以等下我们在UserLoginAction中,d成功后要讄一个相兛_性?BR>  
  OK,下面来开始我们最后三个文件的设计吧。在Struts-config.xml的Design模式中,在画版的I白区域点右键,选择New --> New Form, Action and JSP 弹出ActionForm的选项面板Q我们按图上输入相关|?Q?BR>  
 

  在Optional Details的Form Properties选项卡,点add个ActionFormd相关|在这个登录示例中Q将d两个属性userName和passwordQ图6Q?BR>  
 

  在添加passwordӞ注意JSP input type 下拉框选择password.
  完成q步后,我们将ActionForm设计完成?BR>  接下来选择 Optional Details的JSP选项?我们选中Create JSP form? q一步myeclipseؓ(f)我们创徏一个简单的与用户交互的d面。保持内容和?一栗图7Q?BR>  
 

  因ؓ(f)我们q只是简单的演示一个登录片D,所以不用验证用户信息是否合法,所以将 Option Details的method选项卡的新徏Ҏ(gu)LQ如?Q?BR>  
 

  点NextQ进入Action选项面板.Option Details的Form选项卡中Validate Form取消选择Q如?Q?BR>  
 

  然后在Forwards选项卡中点addd成功和失败返回的面.如图10Q?BR>  
 

  点击Finish完成。在Struts-config.xml的Design中,可以看到?1所C:(x)
  
 

  最后,单的修改一下userLogin.jsp,所?%@ taglib ...%>替换为:(x)
  <%@ taglib uri="/tags/struts-html" prefix="html"%>
  <%@ taglib uri="/tags/struts-bean" prefix="bean"%>
  修改UserLoginAction中的execute片段为如下所C,?2Q?BR>  
 

  OKQ完成。。。下面就部暑目Q测试。。?BR>  
  像ؓ(f)目dStruts框架一P在项目名上右击,选择MyEclipse --> Add and Remove Project development.
  在弹出对话框上,单击add Q在弹出?New Deployment 对话框上QServer选Tomcat5Q点击Finish完成部vQ如?3:
  
 

  在用览器上打开Qhttp://127.0.0.1:8080/LoginDemo/userLogin.jsp
  输入密码123456,用户名EricHe。显C成功:(x)
  

  如果输错Q或不输入,则无反映又回到当前登录页面(因ؓ(f)我们没有讄错误信息Q?BR>

Sung 2005-11-02 15:14 发表评论
]]>
Eclipse 3.0 介和插g开发示?http://m.tkk7.com/qq13367612/articles/17814.htmlSungSungWed, 02 Nov 2005 07:06:00 GMThttp://m.tkk7.com/qq13367612/articles/17814.htmlhttp://m.tkk7.com/qq13367612/comments/17814.htmlhttp://m.tkk7.com/qq13367612/articles/17814.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17814.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17814.html Eclipse 是一个很让h着qL(fng)开发环境,它提供的核心(j)框架和可扩展的插件机制给q大的程序员提供?jin)无限的惌和创造空间。目前网上流传相当丰富且全面的开发工h面的插gQ但是Eclipse已经越?jin)开发环境的概念Q可以想象Eclipse成为未来的集成的桌面环境。目前的Eclipse本n具备资源管理和外部E序的功能,加上无所不能的插Ӟ构成一个丰富多彩的工作环境而不仅仅是一个IDE?BR>
  1.Eclipse介和插g开?/B>

  Eclipse 是一个很让h着qL(fng)开发环境,它提供的核心(j)框架和可扩展的插件机制给q大的程序员提供?jin)无限的惌和创造空间。目前网上流传相当丰富且全面的开发工h面的插gQ但是Eclipse已经越?jin)开发环境的概念Q可以想象Eclipse成为未来的集成的桌面环境。目前的Eclipse本n具备资源管理和外部E序的功能,加上无所不能的插Ӟ构成一个丰富多彩的工作环境而不仅仅是一个IDE。对于程序员来说Q没有什么比可以随心(j)所Ʋ的定制的工作环境更重要Q你的决?j),勇气和创造力在与别h分n成果的过E中一览无余。好?jin),你是不是心(j)动了(jin),如果你已l对Eclipse有一定的认识Q那么,和我一h造自q个性化工作环境吧,首先我们一起开发一个天气预报的插gQ然后我们打造属于自q邮g快速监控功能?

  以下的工作基于一定的前提Q那是你是一名JavaE序员,你很ƣ赏q正开始用Eclipseq个酷的工作环境,别忘?sh)(jin)下载最新版的Eclipse3.0Q本文基于Eclipse3.0开发?BR>
  2.天气预报插g

  如果你已l厌倦了(jin)L要登录某些网站从相关|页上获取信息,q里有一个让你通过Eclipse快速获取信息的新方法。让我们从头开始,做一个属于自q天气预报插g吧,你的Eclipse具有天气预报功能,是不是很酷呢Q?BR>
  在这一部分Q我们将要实C个Eclipse插gQ他可以在Q何我们想知道的时候通过单的点击鼠标告诉我们本地区的天气预报Q这当然很刺Ȁ。对于一个程序员而言Q事情就应该如此。让我们开始吧Q我们首先要定义一个插Ӟ把他加到菜单和工h中。对于没有插件开发经验的你,可以参考《开?Eclipse 插g》,?wi)立基本的插件开发意识,当然Q本文将详细的辅助你完成q一创造性的工作?BR>
  2.1最基础的插?BR>
  打开菜单 File -Q?New-Q?Other -QPlug-in ProjectQ输入项目名Uͼnext出现对话框,只要在插件名处输?muplugin",next 以后选择 "Hello,World"的插件模板你可以直接新徏一个名为myplugin的最单的插gQ但其实我们的天气预报ƈ不比它复杂多,建完Ҏ(gu)件以后的效果如下图?BR>

  现在Q将目作ؓ(f)q行时工作台q行Qrun Q?run as runtime workbenchQ,在一个全新的EclipseH口中,通过点击菜单 sample menu 的sample Action或者工h中的圆ŞEclipse 图标Q你看到如下效果的对话框?BR>

  到此为止Q天气预报插件的原始版做成了(jin)Q通过修改plugin.xmlQ我们将菜单Ҏ(gu)中文形式Q需要修改的地方?处,详见表格?BR>
QactionSet label="Sample Action Set" visible="true" id="myplugin.actionSet"Q?BR>Qmenu label="我的I间" id="sampleMenu"Q?BR>Qseparator name="sampleGroup"Q?BR>Q?separatorQ?BR>Q?menuQ?BR>Qaction label="天气预报" icon="icons/sample.gif" class="myplugin.actions.SampleAction"
tooltip="Hello, Eclipse world" menubarPath="sampleMenu/sampleGroup"
toolbarPath="sampleGroup" id="myplugin.actions.SampleAction"Q?BR>Q?actionQ?BR>

  此时在运行时工作収ͼ我们的菜单已l改变?BR>

  2.2用VisualEditer制作天气预报对话?BR>
  虽然菜单是天气预报,但是我们需要的不是hello Eclispe对话框,我们需要的是告诉我们天气的对话框,当然需要我们从头开始,于是我们需要重新构Z个对话框Q这个就需?Visual Editor来帮助进行界面的开发。我们将使用Visual Editor实现一个Swing对话框,当然只用VE做一个对话框是有点大材小用,但是作ؓ(f)L(fng)Q已l合适了(jin)?BR>
  首先构徏Visual Editer开发环?读者可参考相兌?Q当一切准备齐全,鼠标右键点击PackgeExpoler中的 "muplugin.actions"java文gQ从弹出式菜单中选择 new-Qother-QVisualClassQ新Z个可视化的类Q弹出界面如下图Q?BR>

  选择nextQ然后在name中输入WeatherDialogQ这个就是我们用来显C天气预报的dialog

  选择该对话框的超cMؓ(f)javax.swing.JDiaog,点击Finish按钮。等待一D|间后Q我们的对话框就基本生成?jin),鼠标点击左上角图标,直接输入天气预报是对话框的标题Q同?我们可以看到左侧的VisualEditor面板?BR>

   然后我们该对话框于与刚才的天气预报菜单q接扑ֈSampleAction的run函数Q如下所C:(x)

public void run(IAction action) {
 MessageDialog.openInformation(
  window.getShell(),"Myplugin Plug-in", "Hello, Eclipse world");
}

  替换成如下代?BR>
public void run(IAction action)
{
WeatherDialog wd=new WeatherDialog();
wd.setSize(400, 335);
wd.show();
}

  此时Q点击菜单运行,我们的对话框看v来象q个样子Q在此基上我们还要在上面增加天气预报信息?BR>

  2.3增加天气预报功能


  下面的部分是重点Q我们将使用h解析Html功能的SwinglgJEditPaneQ来获取|络上的现成的天气预报信息,Ҏ(gu)上图Q从 VisualEditor的面板中Swing Componentsl点击JEditPaneQ加入到对话框中。ƈ修改对话框代码得最l的代码如下Q?BR>
/*
* Created on 2004-9-23
* */
package myplugin;


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

import javax.swing.JDialog;
import javax.swing.JEditorPane;

/**
* QpQTitle: WatherDialogQ?pQ?BR>* QpQDescription: q个是对话框c,用于昄指定城市(jng)的当天的天气预报Q?pQ?BR>* QpQCopyright: Copyright (c) 2004Q?pQ?BR>* QpQCompany:UF SOFTQ?pQ?BR>* @author 赵勇
* @version 1.0
*/
public class WatherDialog extends JDialog
{
String city="北京";

private JEditorPane jEditorPane = null;
/**
* This method initializes
* /
public WatherDialog(String city)
{
super();
this.city=city;
initialize();
}
/**
* This method initializes this
* @return void
*/
private void initialize()
{
this.setContentPane(getJEditorPane());
try
{
//构徏URL对象
URL url =new URL("http://weather.news.sina.com.cn//cgi-bin/figureWeather/simpleSearch.cgi?city="+city);
String temp="";
BufferedReader in
= new BufferedReader(new InputStreamReader(url.openStream()));
//使用openStream得到一输入ƈ由此构造一个BufferedReader对象
String inputLine;
//从输入流不断的读数据Q直到读完ؓ(f)?BR>while ((inputLine = in.readLine()) != null)
temp=temp+inputLine+"\n";
//关闭输入?BR>in.close();
String weather
=temp.substring ( temp.indexOf( "Qbody"),
temp.lastIndexOf( "bodyQ?)+5);

this.jEditorPane .setText(weather);
}
catch (Exception e)
{
e.printStackTrace();
}
this.setTitle("天气预报");
this.setSize(400, 166);

}
/**
* This method initializes jEditorPane
*
* @return javax.swing.JEditorPane
*/
private JEditorPane getJEditorPane()
{
if (jEditorPane == null)
{
jEditorPane = new JEditorPane();
jEditorPane.setContentType( "text/html");
}
return jEditorPane;
}
} // @jve:decl-index=0:visual-constraint="70,19"

  以上代码中最关键的部分就是对话框中的JEditorPane对象Q在初始化时Q从一个URL 获取天气预报信息Q表Cؓ(f)Html标记片段Q不用解析,直接调用JEditorPane的setText Ҏ(gu)Q就可以Html格式的信息直接按解析q的方式昄Q也是天气预报信息?jin)?BR>
  此时Action中的调用需要做修改

public void run(IAction action)
{
WeatherDialog wd=new WeatherDialog("北京");
wd.setSize(400, 335);
wd.show();
}

  现在以运行时工作台的方式q行Q点d气预报菜单,可以看到下图Q?BR>


  如果你在上v或者其他城?jng),试着修改city参数?上v"Q再ơ运行,你将发现Q你仍然能够得到该城?jng)的天气预报Q这里我们从|站上提取的信息Q有Ҏ(gu)机取巧了(jin)Q。值得注意的是QXmethod|站提供?jin)一个天气预报的WebServiceQ可惜只有美国的城市(jng)Q不然我们可以用Web Service调用获取天气预报Q将?x)更酗?BR>
  现在q行是工作台已经具备?jin)天气预报的功能Q还需要更q一步,改插g导出发布Q拷贝到Eclipse根目录的plugins目录中,重新启动Q具体参见Eclipse帮助Q。现在你自己的EclipseQ就具备?jin)天气预报的功能Q只要你点击鼠标Q就可以在编E之余轻杄获取天气信息?除非你的老板认ؓ(f)你在工作旉随时?jin)解天气情况不是一个好LQ我认ؓ(f)你完全可以将q个插gU_个h收藏的插件之列。你也可以在此基上扩展,增加一些配|文件和属性设|,定制出满p求的插g。如果能够增加信息的自动qo(h)和筛选,那将是一ơ很愉快的体验,如果你有旉和兴,不妨一试?/P>

 3.邮g快速监控插?/B>

  现在你的工作因ؓ(f)Eclipse而更加惬意,更具创造力Q那么你q有什么不满?你是否厌倦了(jin)各种邮g客户端随旉地的?d)扰你呢Q你希望你在高兴的时候适时的了(jin)解一下邮件的概况Q好?jin),既然惛_?jin)?f)什么犹豫呢Q因Z是程序员Q你是要用Eclipse享受完全DIY的乐?BR>
  3.1生成插g

  本部分我们将在以上myplugin插g的基上增加一个邮件过滤显C的对话框,cM的我们通过VisualEditer创徏一个名为MailDialog的对话框Qƈ增加一个JEditPane用来昄邮箱中我们关注的信息?BR>
  修改plugin.xmlQ增加一?我的邮g"菜单

Qaction
label="邮g信息"
icon="icons/sample.gif"
class="myplugin.actions.MailAction"
tooltip="邮g信息"
menubarPath="sampleMenu/sampleGroup"
toolbarPath="sampleGroup"
id="myplugin.actions.MailAction"Q?BR>Q?actionQ?/TD>

  现在Q你知道要创Z个MailAction的Actionc,q在在Run中增加如下代?BR>
MailConfig mail=new MailConfig();

String popServer="server";
String popUser="zhaoyong";
String popPassword="1234";

//讄需要过滤的关键字:(x)发g人和邮g主题
String [] strFrom=new String[] {"zhaoyong"};
String [] strSubject=new String[] {"试"};

MailConfig[] mc =new MailConfig [] { mail };
MailDialog md=new MailDialog(mc);
System.err.println("run run run ") ;
md.setSize(400, 335);
md.show();

  以上的代码编译不?x)通过Q但是别着急,慢慢来,很快?jin)?BR>
  3.2构徏邮g监控对话?

  当然你需要徏立一个MailConfigcȝ来表CZ个邮q具体讄已及(qing)相关信息Q这里就不在累述说明Q详情参见参考资料中的代码。需要说明的式MailConfig除了(jin)要记录一个邮q地址Q用户名和密码外Q还提供2个关键字数组Q如果ؓ(f)I,不加qo(h)Q如果关键字有|pȝ?x)根据发件h和邮件标题(sh)是否包含关键字来q行昄邮g信息Q已保证你的l对自由?BR>
  首先我们需要实C个MailConfigc,表示邮g配置Q每个MailConfig的对象代表一个邮件帐P我们的系l将能显C多个邮q配置Q每个MailConfig中用一个数l来保存需要过滤的收g人和邮g地址?BR>
  MailConfigcȝ中的变量如下Q?

String popServer;
String popUser;
String popPassword;

//讄需要过滤的关键字:(x)发g人和邮g主题

String [] strFrom;
String [] strSubject;

//是否昄邮g内容
boolean isViewContent=false;

  同样Q我们将使用一个对话框来显C邮件信息,MailDialog需要引用javaMail.jar,和activation.jarq两个类包,保已经有这两个cdq加入到目的类路径中。最后的MailDialog代码如下Q?BR>
package myplugin;


import java.io.IOException;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JTextPane;
/**
* @author zhaoyong
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class MailDialog extends JDialog
{

private JEditorPane jEditorPane = null;
private JTextPane jTextPane = null;

//可以昄多个邮g配置
MailConfig[] mc= null;


/**
* This method initializes
* 构造函?BR>* @param mc : 需要显C的多个邮箱配置对象?BR>*/
public MailDialog(MailConfig[] mc)
{

super();

if(mc!=null)
this.mc = mc;
else
System.err.println("邮g配置错误Q?) ;

initialize();
}
/**
* This method initializes this
* 初始?BR>* @return void
*/
private void initialize()
{
try
{
//讑֮昄内容的面?BR>this.setContentPane(getJTextPane());
//取得所有的新邮件信?BR>String s= getAllMailInfo();
//信息显C在对话框中
this.jTextPane .setText(s);

this.setTitle("邮g信息");
this.setSize(251, 100);
}
catch (Exception e)
{
//发生错误昄错误信息
this.jTextPane .setText(e.toString());
e.printStackTrace();
}

}
/**取得所有的邮箱的需要监控的邮g信息
*
* @return String
*/
private String getAllMailInfo()
{
String allMailInfo="";

if (mc.length Q?)
allMailInfo="没有配置邮箱Q?;
else
{
for(int i=0;iQmc.length;i++)
{
//循环获取每个邮箱的邮件信?
allMailInfo=allMailInfo+getMailInfo(mc[i]);
}
}
//q没有收到相关的邮g
if (allMailInfo.trim().length() ==0)
allMailInfo="未检到相关新邮Ӟ";
return allMailInfo;

}
/*
*得到一个邮׃满条g的所有新邮g的字W串形式
**/
private String getMailInfo(MailConfig mc)
{
//最l输出的邮g信息
String mailInfo="";

//每个邮箱服务器上的Store和Folder对象
Store store=null;
Folder folder=null;

try
{

Properties props = System.getProperties();
//与邮件服务器生成一个Session
Session session = Session.getDefaultInstance( props,null);

//l出服务器,用户名,密码q接服务?BR>store = session.getStore("pop3");
store.connect(mc.getPopServer(), mc.getPopUser(),mc.getPopPassword());

//取得默认的邮件Folder
folder = store.getDefaultFolder();
if (folder == null)
throw new Exception("No default folder");

//取得收g?BR>folder = folder.getFolder("INBOX");
if (folder == null)
throw new Exception("No POP3 INBOX");

//以只L式打开收g?BR>folder.open(Folder.READ_ONLY);

//获取所有新邮gq处?BR>Message[] msgs = folder.getMessages();

for (int i = 0; i Q?msgs.length; i++)
{
Message message= msgs[i];
//取得每封邮g的信息,需要引用MailConfig对象q行关键字过?BR>mailInfo = mailInfo+ getMessageInfo( message,mc);
}

}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
//安全的关闭邮件服务器资源
try
{
if (folder!=null) folder.close(true);
if (store!=null) store.close();
}
catch (Exception ex2) {ex2.printStackTrace();}
}
return mailInfo;
}

/**
* 得到一邮件的信息Q需要根据MailConfigqo(h)
* @param mailInfo
* @param message
* @return 邮g信息
* @throws MessagingException
* @throws IOException
*/
private String getMessageInfo( final Message message ,final MailConfig mc)
throws MessagingException, IOException
{
//q回的改邮g信息
String mailInfo="";

String from=((InternetAddress)message.getFrom()[0]).getPersonal();

if (from==null)
from=((InternetAddress)message.getFrom()[0]).getAddress();

String subject=message.getSubject();

//如果满qo(h)信息则显C,否则q回I?BR>if(isElementinString(from,mc.getStrFrom())
||isElementinString(subject,mc.getStrSubject()) )
{
mailInfo=mailInfo+"发g?: "+from+"\n";
mailInfo=mailInfo+"邮g主题 : "+subject+"\n";
mailInfo=mailInfo+"发送时?: "+message.getSentDate() +"\n";

//如果昄内容Q则打印内容
if(mc.isViewContent)
mailInfo=mailInfo+message.getContent() +"\n";

mailInfo=mailInfo+"------------------------------------\n";
}
return mailInfo;
}

private JTextPane getJTextPane()
{
if (jTextPane == null)
{
jTextPane = new JTextPane();
}

return jTextPane;
}

/**
* 判断目标关键字数l中是否有指定的字符?q行qo(h)
* @param targetStr Q?BR>* @param keys Q?BR>* @return 如果有,q回trueQ?否则q回false
*/

private boolean isElementinString(String targetStr,String [] keys)
{
//没指定过滤条Ӟ昄所?BR>if (keys==null)
return true;
//指定字符串ؓ(f)I,直接q回false
if (targetStr==null)
return false;
for(int i=0;iQkeys.length ;i++)
{
if (targetStr.indexOf(keys[i])Q?1)
return true;
}
return false;
}

}
// @jve:decl-index=0:visual-constraint="10,10"Q-说明Q这是Visual Editord的控制信?/TD>

  以上代码的注释已l保证你能够看清楚,q里׃加篏qͼ有兴的可以自己试试Q体验一切尽在掌握的快感。当然这个例子做的实在简单,因此也ؓ(f)你的q一步开发留有够的余地?BR>
  3.3 打包和发?BR>
  到此Q在mypulgin中增加了(jin)邮g信息菜单和对话框Q系l的plugin.xml如下Q?BR>
Q?xml version="1.0" encoding="UTF-8"?Q?BR>Q?eclipse version="3.0"?Q?BR>Qplugin
id="myplugin"
name="Myplugin Plug-in"
version="1.0.0"
provider-name=""
class="myplugin.MypluginPlugin"Q?BR>
QruntimeQ?BR>Qlibrary name="myplugin.jar"Q?BR>Qexport name="*"/Q?BR>Q?libraryQ?BR>Qlibrary name="lib/javaMail.jar"Q?BR>Qexport name="*"/Q?BR>Q?libraryQ?BR>Qlibrary name="lib/activation.jar"Q?BR>Qexport name="*"/Q?BR>Q?libraryQ?BR>Q?runtimeQ?BR>
QrequiresQ?BR>Qimport plugin="org.eclipse.ui"/Q?BR>Qimport plugin="org.eclipse.core.runtime"/Q?BR>Q?requiresQ?BR>
Qextension
point="org.eclipse.ui.actionSets"Q?BR>QactionSet
label="Sample Action Set"
visible="true"
id="myplugin.actionSet"Q?BR>Qmenu
label="我的I间"
id="sampleMenu"Q?BR>Qseparator
name="sampleGroup"Q?BR>Q?separatorQ?BR>Q?menuQ?BR>Qaction
label="天气预报"
icon="icons/sample.gif"
class="myplugin.actions.SampleAction"
tooltip="Hello, Eclipse world"
menubarPath="sampleMenu/sampleGroup"
toolbarPath="sampleGroup"
id="myplugin.actions.SampleAction"Q?BR>Q?actionQ?BR>Qaction
label="邮g信息"
icon="icons/sample.gif"
class="myplugin.actions.MailAction"
tooltip="邮g信息"
menubarPath="sampleMenu/sampleGroup"
toolbarPath="sampleGroup"
id="myplugin.actions.MailAction"Q?BR>Q?actionQ?BR>Q?actionSetQ?BR>Q?extensionQ?BR>Q?pluginQ?/TD>

  实际上,我们在一个插件中加入?个功能,因此实C(jin)我们的开发环境的自我扩展和定制。同P参考Eclipse的帮助,你可以轻杄再次插件打包导出,q将其加入自qEclipse 的plugins目录Q可能需要解压羃Q,或通过help菜单的Update选项q行安装Q注意导出时需要选定相关的类包。重新启动,你将发现自己的IDE已经多了(jin)自己的菜单,开发环境已l随着自己的意愿在改变?sh)(jin),E序员天生的满感a(b)然而生?

  现在Q你可以在需要的时候点击菜单,?jin)解你希望监控的邮g情况或者最q的天气情况Q一切轻杄在掌握QEclipse的插Ӟ是q样全能?BR>
  4.ȝ

  那么Q聪明的你有没有发现什么问题,对,上面的东西太_糙Q太单了(jin)Q你可以做进一步的优化设计和功能加强,比如Q自己增加邮仉|文件而不是写在代码里面,动态监控弹出邮仉警(通过事先讑֮的紧急状态)(j)Q你也许q(sh)(x)惌v来很多的新的LQ比如我Z么不能有个能看电(sh)q插gQ或是Eclipse中飘出动听的音乐Q别急,q些不一定需要你亲手dQhttp://sourceforge.net/projects/rocexwang/ 有一个播攑֙插gQ但是现在仅能播N乐,国外已经有h用Eclipse开发游戏,也有人用Eclipse来做MISpȝ的。http://www.matrix.org.cn/forum_view.asp?forum_id=25&view_id=10510 有一个国人开发的俄罗斯方块游戏,虽然单了(jin)一炏V当?dng)通过|址http://eclipse-plugins.2y.net/eclipse/index.jsp和http://www.eclipseplugincentral.com/你可以找到很多的插gQ如果你知道什么更好的插gQ请告诉我?BR>
  Eclipse提供?jin)一个纯的框架和插gl构Q得开发Q何功能的插g都能成ؓ(f)现实。本文介l了(jin)2个有的Eclipse插g的开发,可以使我们的工作环境增加?jin)两个可q功能,同时也得你具备?jin)基的插件开发能力,借助Eclipse的强大功能,从此你可以把你的Mx(chng)变(sh)ؓ(f)现实。同时请保持与别人的交流Q我?x)很乐意了(jin)解你的新奇的插Ӟq收藏和学习(fn)M好的插gQ打造一个完全属于自q个性化的开发环境。Eclipse在不久的将来成Z个全能的PlatformQ这一点在全世界数以万计的开发h员的手中Q正一点一点变?sh)现实?/P>

Sung 2005-11-02 15:06 发表评论
]]>
Eclipse的用简介及(qing)插g开?/title><link>http://m.tkk7.com/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://m.tkk7.com/qq13367612/articles/17813.html</guid><wfw:comment>http://m.tkk7.com/qq13367612/comments/17813.html</wfw:comment><comments>http://m.tkk7.com/qq13367612/articles/17813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/qq13367612/comments/commentRss/17813.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/qq13367612/services/trackbacks/17813.html</trackback:ping><description><![CDATA[<P>Eclipse 是替代IBM Visual Age for JavaQ以下简UIVJQ的下一代IDE开发环境,但它未来的目标不仅仅是成Z门开发JavaE序的IDE环境Q根据Eclipse的体pȝ构,通过开发插Ӟ它能扩展CQ何语a的开发,甚至能成为图片绘制的工具。目前,Eclipse已经开始提供C语言开发的功能插g。更难能可贵的是QEclipse是一个开放源代码的项目,M人都可以下蝲Eclipse的源代码Qƈ且在此基上开发自q功能插g。也是说未来只要有人需要,׃(x)有徏立在Eclipse之上的COBOLQPerlQPython{语a的开发插件出现。同时可以通过开发新的插件扩展现有插件的功能Q比如在现有的Java开发环境中加入Tomcat服务器插件。可以无限扩展,而且有着l一的外观,操作和系l资源管理,q也正是Eclipse的潜力所在?/P> <P>虽然目前Eclipse目q没有最后完成,但从已有的版本中已经能领略到Eclipse设计d思想和主要功能特炏V现在就?jin)解Eclipse不但能q大E序员对q款业界期望很高的IDE能一睹ؓ(f)快,更ؓ(f)重要的是如果能参加到Eclipse目的开发中或是阅读它的开放源代码Q这对广大程序员来说无疑是一个千载难逢的提高~程水^的好Z(x)。Eclipse计划提供多个q_的版本,象WindowsQLinuxQSolarisQHP-UX和AIXQ以下只介绍Windows版本。本文第一部分先介lEclipse的基本用方法。第二部分介l如何进行Eclipse的插件开发?/P> <P><A name=1><span id="eqwka2i" class=atitle2>一QEclipse?/SPAN></A><BR></P> <P>Eclipse是开放源代码的项目,你可以到 <A 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>d费下载Eclipse的最新版本,一般Eclipse提供几个下蝲版本QReleaseQStable BuildQIntegration Build和Nightly BuildQ徏议下载Release或Stable版本Q笔者用的是Build20020125QStable版本Q。Eclipse本n是用Java语言~写Q但下蝲的压~包中ƈ不包含Javaq行环境Q需要用戯己另行安装JREQƈ且要在操作系l的环境变量中指明JRE中bin的\径。安装Eclipse的步骤非常简单:(x)只需下载的压羃包按原\径直接解压既可。需注意如果有了(jin)更新的版本,要先删除老的版本重新安装Q不能直接解压到原来的\径覆盖老版本。在解压~之后可以到相应的安装\径去找Eclipse.exeq行。如果下载的是Release或Stable版本Qƈ且JRE环境安装正确无误Q一般来说不?x)有什么问题,在闪C个很L(fng)月蚀囄后,Eclipse?x)显C它的缺省界面:(x) </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>乍一看v来,Eclipse的界面有点象JBilderQ但实际操作q程中会(x)发现它更象IVJQ毕竟开发Eclipse的主导用量是开发IVJ的原班h马(可参考www.oti.comQ。另外还值得一提的是Eclipse目的参预者除?jin)IBM以外Q还有象BorlandQRational SoftwareQRedHatQMerant{一大批业界的姣姣者,q也为Eclipse的未来奠定了(jin)良好的基?/P> <P>下面分别对Eclipse的各U特性作单介l,包括Q文件存放,开发环境,~译与运行,版本理Q用插件?/P> <P><A name=2><span id="socsscq" class=atitle3>1Q?文g存放</SPAN></A><BR></P> <P>大多IVJ的初学者都Ҏ(gu)不到Java源代码感到非怸适应Q因为IVJ把所有的源代码都存储C个reponsitory库文件中Q想要得到文本格式的源代码必ȝExport功能从reponsitory中导出源代码。用了(jin)reponsitory的IVJҎ(gu)代码的管理功能几乎达到极_(d)正是q一点得许多程序员对IVJ钟爱有加。而Eclipse源代码以文本方式保存,却实C(jin)IVJҎ(gu)代码理的几乎全部功能,q且q增加了(jin)一些新的功能,能达到这一点,不能不惊叹于Eclipse开发者的高超技巧?/P> <P>安装Eclipse之后Q在安装路径的下一层\径中?x)有一个workspace文g夏V每当在Eclipse中新生成一个项目,~省情况下都?x)在workspace中生和目同名的文件夹以存放该目所用到的全部文件。你可以用Windows资源理器直接访问或l护q些文g?/P> <P>已有的文g加入C个项目中目前有三U方式:(x)W一U是象在IVJ中的一P用IDE?File"菜单中的"Import"功能文件导入到目中。这也是推荐的方式。第二种是从Windows的资源管理器中直接拖动文件到目中。第三种是直接文件拷贝到目文g夹中Q然后在Eclipse的资源浏览窗口中选择目或文件夹q执行从本地h功能QRefresh from locateQ。需要说明的一Ҏ(gu)Q项目文件夹可以攑֜计算机的M位置Qƈ且可以在Eclipse中用新徏目的方法将目路径指定到已l存在的目文g夹,然后在Eclipse中刷新即可。但要注意的是,M目文g夹徏立或指定Q目前都只能在Eclipse中用新徏目的方法来实现Q即使是在缺省存储项目文件夹的workspace路径下新建立一个文件夹Q在Eclipse环境中也是无法将它变成一个项目,也就是说Q这个文件夹对Eclipse是不可视的?/P> <P><A name=3><span id="s2a0kuc" class=atitle3>2Q?Eclipse开发环?/SPAN></A><BR></P> <P>和IVJ一PEclipse开发环境被UCؓ(f)WorkbenchQ它主要׃个部分组成:(x)视图QPerspectiveQ,~辑H口QEditorQ和观察H口QViewQ。在下面的介l中Q希望读者能知道Java视图QJava包浏览窗口,资源视图Q资源浏览窗口等区别Q其实最主要的也是要区别视囑֒H口Q,以免在进一步的阅读中生؜淆。图二是它们之间的关pȝ构略图:(x)</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>在图二中Q可以看出Workbench包含多个视图Q而每个视囑֏包含不同的窗口。由于每个编辑窗口有很大的共性,而且~省情况它们都在同一区域中显C,因此我们只在每个视图中标Z个编辑窗口,以绿色表C。观察窗口则各不相同Q这里以U色表示?/P> <P>下面首先介绍~辑H口。所有文件的昄和编辑都包含在编辑窗口里。缺省情况下打开的多个文件是以标{(TagTableQ方式在同一个窗口中排列Q可以用拖动方式这些文件排列成各种布局。方法是拖动某一个文件的标签QtagQ到~辑H口的边框,当光标有相应的变化时再释放?/P> <P>当文件被加入到项目中后,在资源浏览或Java包浏览窗口双?yn)LӞEclipse?x)试图打开q个文gQ其中Eclipse内嵌的编辑器能缺省打开一些文Ӟ?.javaQ?.txtQ?.class{等。如果是其它cd的文ӞEclipse?x)调用操作系l相应的~省~辑器打开Q如word文档QPDF文g{。同时Eclipse也可以象IVJ一L(fng)指定的编辑器打开相应的文件。例如在Eclipse目中双击HTML文gӞ可能希望是用Notepad打开Q而不是用pȝ~省的IE览器打开。实现的Ҏ(gu)是打开菜单栏中的WorkBenchàPreferences对话框,之后在对话框中选择WorkBenchàFile EditorsQ然后添加文件类型,?.htmlQ再为其指定~辑器即可?/P> <P>在编辑窗口,q值得注意的是Q习(fn)惯了(jin)IVJ的程序员在编辑JavaE序的时候,更愿意以Ҏ(gu)为独立的~辑单位Q即在编辑窗口中只显C单个的Ҏ(gu)Q而不是程序全部的源代码)(j)Q这U方式也的确是非常合理的开发方式,不仅代码的显C更加简Pq能辅助E序员编出封装性更好的cR在Eclipse在工h上提供了(jin)一个切换按钮,可以?昄全部代码"?只显C所选单?Q这里的单元指的是单个方法、变量、导入的包等Q之间切换(可参考下面的图三Q。徏议没有用过IVJ的程序员?sh)尝试一下在"只显C所选单?状态下q行代码开发?/P> <P>其次要介l的是观察窗口,它配合编辑窗口ƈ提供?jin)多U的相关信息和浏览方式。常用的观察H口有资源浏览窗口(NavigatorQ,Java包浏览窗?Packages)Q控制台QConsoleQ,d栏(TaskQ等{?/P> <P>览H口和Java览H口是观察窗口核?j)部分。前者和W(xu)indows的浏览器差不多,能浏览项目文件夹中的所有文Ӟ后者用来浏览项目中的Java包,包中的类Q类中的变量和方法等信息。在Java览H口中可以通过用鼠标右键的菜单中的Open Type Hierarchy打开层次览H口QHierarchyQ,q个H口非常实用Q它能非常清晰的查看cȝ层次l构。类中的~译出错信息可以在Q务窗口中查到Q同时它也可以成为名W其实的dH口Q向其中d新的d描述信息Q来跟踪目的进度。控制台则主要用来显C程序的输出信息。在调试E序的时候,?x)有更丰富的观察H口来帮助程序员q行调试Q如变量值察看窗口,断点H口{等?/P> <P>观察H口是Q何IDE开发环境的核心(j)Q用好观察窗口是也就是用好IDE开发环境。Eclipse提供?jin)丰富的观察H口Q能真正用好q些H口恐怕要得经q一D|间的练?/P> <P>最后介l视图。一个视囑֌括一个或多个~辑H口和观察窗口。在开发环境的最左侧的快h中的上部分显C的是当前所打开的视囑֛标。视图是Eclipse的最灉|的部分,可以自定义每个视图中包含的观察窗口种c,也可以自定义一个新视图。这些功能都被包括在"Perspective" 菜单中。在Eclipse的Java开发环境中提供?jin)几U缺省视图,如资源视图(Resource PerspectiveQ它也是W一ơ启动Eclipse时的~省视图Q,Java视图QJava PerspectiveQ,调试视图QDebug PerspectiveQ,团队视图(Team Perspective){等。每一U视N对应不同U类的观察窗口。可以从菜单栏中的PerspectiveàShow View看到该视囑֯应的观察H口。当?dng)每个视图的观察窗口都是可配置的,可以在菜单栏中的PerspectiveàCustomizeq行配置。多样化的视图不但可以帮助程序员?sh)不同角度观察代码,也可以满不同的~程?fn)惯?/P> <P><A name=4><span id="g2qqwqm" class=atitle3>3Q?~译与运?/SPAN></A><BR></P> <P>在IVJ中调试功能非常强大,多种跟踪方式Q断点设|,变量值察看窗口等{。这些在Eclipse中都也有提供。在本文下面介绍插g的时候,?x)结合例子更加详l的介绍如何使用配置目环境Q如何运行和调试E序?/P> <P>在Java视图中,工具栏中有两个按钮,分别用来q行调试和运行。ƈ且可能由于安装的插g不同Eclipse?x)存在多U运?调试E序的方式,Z(jin)定当前目用那一U方式运行,需要在目的属性选项中的讄LauncheràRun/Debug选项。通常我们需要用的是"Java Applicantion"方式。在q种方式下,如果当前位置是包含main()Ҏ(gu)的JavaE序Q点击调?q行按钮׃(x)立即开始执行调?q行功能。如果当前位|是在包或项目上QEclipse?x)搜索出当前位置所包含的所有可执行E序Q然后由E序员自己选择q行那一个?/P> <P>在目前的Eclipse的Release和Stable版本中缺省安装了(jin)插g开发环境(Plug-in Development EnvironmentQ即PDEQ它本n也是一个插Ӟ(j)Q此时系l除?Java Applicantion" q行方式Q可能还有另外两U方式:(x)"Run-time WorkBench"?Run-time WorkBench with Tracing"Q当用PDE开发插件的时候会(x)用到q两U运行方式,在下面我们也有提到?/P> <P><A name=5><span id="sqeuo2y" class=atitle3>4Q?版本理</SPAN></A><BR></P> <P>可以把Eclipse的版本管理分Z人(或称为本圎ͼ(j)和团队两U?/P> <P>Eclipse提供?jin)强大的个h版本理机制Q每一ơ被保存的更攚w可以得到恢复。而且可以_到每一个方法的版本恢复。操作也十分方便Q在M一个能看到所要操作文件的观察H口中,例如资源览H口Q选中该文Ӟ点击右鼠标键Q选择Compare with或Replace withQ如果是恢复已经被删除的Ҏ(gu)则可以选择Add from local historyQ之后相应的本地历史记录׃(x)昄出来Q按照你的需求找到相应的版本可以了(jin)。强大的个h版本理功能为程序员提供?jin)更多的信?j)Q只编下去QQ何不心(j)的错误都可以恢复Q在Eclipse下开发,是有"后?zhn)?的!</P> <P>Eclipse~省为版本管理工具CVS提供?jin)接口,可以非常方便的连接到CVS服务器上。通过CVS版本理QEclipse为团队开发提供良好的环境。要q接CVS服务器需要先打开团队视图QTeam PerspectiveQ,然后在Reponsitories观察H口中点击鼠标右键ƈ选择新徏QNewQ,在打开的对话框中可以填入要q接的CVS库所需要的信息Q如CVS服务器类型,目前Eclipse支持三种方式Qpserver、extssh和extQ还要填入用户名Q主机名Q密码,reponsitory地址{信息?/P> <P>在Eclipse中用CVS需要注意的是一些术语和功能的变化,CVS中的Branchq里被称为StreamQ取消了(jin)CVS中check out、import和commit{功能,l统用鼠标右键菜单中的Team->Synchronized with Stream来替代。这些功能都通过囑Ş界面完成Q在每次操作中都?x)有当前文g和以前各个版本的比较H口Q操作非常直观,易于掌握Q因此这里也׃再做q一步介l了(jin)?/P> <P><A name=6><span id="ae00wu0" class=atitle3>5Q?使用插g</SPAN></A><BR></P> <P>使用插g可以丰富Eclipse的功能。下面将介绍如何应用插g来嵌入Tomcat服务器。这个插件ƈ不是Eclipse目l开发的Q而是一家叫sysdeo的公司开发,非常yQ只?7.8K。你可以?<A 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>d费下载。另外,q个插g只支持Tomat4.0以上的版本,可以?<A 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文g按原路径解压?你的Eclipse的安装\径\plugins"下面Q然后重新启动Eclipse。启动后在菜单栏上选择PerspectiveàCustomizeQ在打开的对话框中选中OtheràTomcat。之后马上会(x)发现Eclipse有了(jin)两处变化Q菜单栏中多?jin)一个Tomcat选项Q工h中多?jin)两个按钮,上面是大家可能非常熟?zhn)的Tomcat猫Q如下图三。除此之外,在菜单栏中选择QWorkbenchàPreferencesQ打开对话框后?x)发现这也多了(jin)一个Tomcat选项Q在q里要求指定你的Tomcat安装根\径。之后还要检查一下在Preferences对话框中的JavaàI(yng)nstalled JRE所指定的JRE和启动Tomcat的JRE是否为同一个JREQ如果不是,可能?x)导致Tomat不能正常启动。如果以上检查没有问题,可以用工具栏上?猫"直接起动Tomcat?jin)。要注意的是Q启动过E很慢,要耐心(j){到以下信息出现Q?/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>之后可以在外部览器(如IEQ中输入 <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>如果启动正常Q可以进一步尝试在Eclipse中调试Servlet或JSPE序。下面我们将用Tomcat自带的Servlet例程HelloWorldExample.java来示范一下如何在Eclipse中调试SevletE序?/P> <P>首先要在Java视图中新Z个Java目Qؓ(f)?jin)方便,可以直接项目\径指定到HelloWorldExmapleE序所在\径,如图四:(x)</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"Q进入Java Settings对话框,选择Libraries标签Qƈ用Add External JARs按钮来指定Servlet.jar包的位置。这里直接用?jin)Tomcat中的Servlet.jar包。如图五Q?/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.javaQ双?yn)L开文gQƈ可尝试给HelloWorldExample加上一个断点(双击~辑H口左侧边界Q。之后在外部览器中输入 <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>Q再回过来看Eclipse发生?jin)什么变化,是一个调试窗口呀Q在Eclipse中进行的调试操作和绝大多数的IDE大同异Q如讄断点Q单步跟t,变量值察看等{,在这里也׃用再详述?jin)?</P> <P><A name=7><span id="eeg20c0" class=atitle2>二.开发Eclipse插gQPlug-insQ?/SPAN></A><BR></P> <P>Eclipse最有魅力的地方是它的插g体系l构。在q个体系中重要的概念是扩展点Qextension pointsQ,也就是ؓ(f)插g提供的接口。每一个插仉是在现有的扩展点上开发,q可能还留有自己的扩展点Q以便在q个插g上l开发?/P> <P>׃有了(jin)插gQEclipsepȝ的核?j)部分在启动的时候要完成的工作十分简单:(x)启动q_的基部分和查扄l的插g。在Eclipse中实现的l大部分功能是由相应的插件完成的Q比如WrokBench UI插g完成界面的外观显C,Resource Management插g完成l护或生成项目或文g{资源管理工作(在下面的W二个例子就?x)用到这个插Ӟ?j)Q而Version and Configuration Management (VCM)插g则负责完成版本控制功能,{等。虽然以上提到的每一个功能都是绝大多数IDE环境所必备的功能,Eclipse却也把它们都做成?jin)插件模式,甚至用来开发JavaE序的开发环境(Java development toolingQJDTQ也只不q是Eclipsepȝ中的一个普通插件而已。整个Eclipse体系l构p一个大拼图Q可以不断的向上加插Ӟ同时Q现有插件上q可以再加插件。下面的插g开发示例就是在WorkBench UI插g中的观察H口扩展点上开发的?/P> <P>本文W一部分介绍qEclipse的开发界面其中之一是观察H口Q它通常配合~辑H口昄一些有用的信息Q在q里我们只简单生成一个显C欢q信息的观察H口Q假设新插g的名子叫Welcome?/P> <P>W一步,先用向导新徏一个Java目。我们可以在菜单栏选择FileàNewQ或用工h的向导按键,或是在资源窗口用鼠标右键菜单中的NewQ打开向导对话框,然后用缺省方式创建项目。ƈ在项目中建立一个Welcome.java文gQ代码如下:(x)</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>Zɘq个E序能正常编译,要配|它的编译环境,x(chng)定所需的CLASSPATH。在Eclipse中可以用几种Ҏ(gu)Q常用的是两U:(x)W一是在资源H口或Java包窗口选中该项目,点击鼠标右键Q在打开的菜单中选择属性(PropertiesQ,之后在属性对话框中选择Java Build PathàLibrariesQ用Add External JARs功能d三个包,它们都是Eclipse的现有插件的cdQ可以在"你的Eclipse安装路径\plugins"下面的相应\径中扑ֈ。分别是org.eclipse.core.runtime插g中的runtime.jarQorg.eclipse.swt中的swt.jar和org.eclipse.ui中的workbench.jar。第二种指定CLASSPATH的方法是先将以上提到的三个包直接导入到Eclipse中的某下一个项目中。如果导入到和W(xu)elcome.java相同的项目中Q则无需q一步指定CLASSPATHQ否则需要在目的属性菜单中选择Java Build PathàProjectsQ然后选中q三个包所在的目?/P> <P>在我们的目中还要生成一个XML文gQ它的名字必plugin.xml。代码如下:(x)</P> <P> <TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1> <TBODY> <TR> <TD><PRE><CODE> <?xml version="1.0" encoding="UTF-8"?> <plugin id="com.nidapeng.eclipse.plugin" name="Welcome to Eclipse" version="1.0" provider-name="Ni Dapeng"> <requires> <import plugin="org.eclipse.ui"/> </requires> <runtime> <library name="welcome.jar"/> </runtime> <extension point="org.eclipse.ui.views"> <category name="Welcome" id="com.nidapeng.eclipse.plugin.category1"> </category> <view name="Welcome to Eclipse" category="com.nidapeng.eclipse.plugin.category1" class="com.nidapeng.eclipse.plugin.Welcome" id="com.nidapeng.eclipse.plugin.view1"> </view> </extension> </plugin> </CODE></PRE></TD></TR></TBODY></TABLE></P> <P>在plugin.xml中一共有四个主要的标{:(x)pluginQrequiresQruntimeQextension。其中plugin标签的属性提供的是我们要开发的Welcome插g的基本信息,除了(jin)nameQversionQprovider-name{,最重要的是idQ它要求不能和现有的Eclipse插gid有冲H,因此我们用包名作为插件的id。requires标签中所列出的是需要的插gQ这里我们要用到Eclipse Workbench和SWT APIQ因此导入了(jin)org.eclipse.ui插g。runtime标签指明的是我们开发的插g所在JAR包的文g名。extension标签是插件扩展点的信息。org.eclipse.ui.views是Eclipsepȝ提供的观察窗口扩展点Q我们的例子是一个观察窗口(ViewQ,q表明我们是要在 org.eclipse.ui.views扩展点上q一步开发。extension中还包括category和view两个标签Q在后箋(hu)的启动Welcome插g步骤中,我们׃(x)知道q两个标{含义。要注意的是category和view标签的id的唯一性,q且在view的属性中声明?jin)Welcome插g的类名?/P> <P>在Eclipse中ؓ(f)plugin.xml提供?jin)缺省可视化的编辑器Q在~写plugin.xmlq程中可以借助q个~辑器完成一些工作。如果你直接录入?jin)plugin.xml文g源代码,q可以用q个~辑器校验你的代码:(x)如果~辑器不能正读入,p明你的plugin.xml有一些问题?/P> <P>在确认Weclome.java和plugin.xml都正无误之后,可以用Eclipse菜单栏中的Export命o(h)Weclome.java导出为JAR文gQ它的名子应该和plugin.xml中runtime声明的JAR怸致。同时导出plugin.xml。安装Welcome插g的方法和本文W一部分介绍的安装Tomcat插gҎ(gu)是一L(fng)Q首先在"Eclipse的安装\径\plugins"路径下面建立一个com.nidapeng.eclipse.plugin路径Q然后将Weclome.jar和plugin.xml拷到q个路径下。之后必需重新启动EclipseQ在Eclipse启动的时候,它会(x)搜烦(ch)所有在插g路径下的插gq注册它们(仅仅是注册,只有在需要某个插件的时候,Eclipse才会(x)启动它)(j)。在重新启动的Eclipse的菜单栏中选择PerspectiveàShow ViewàOthersQ在打开的对话框中我们会(x)扑ֈ在plugin.xml中extension的category标签中声明的name属性:(x)Welcome。在Welcome的支l点中包含了(jin)view标签name属性:(x)Welcome to Eclipse。选中它ƈ认QW(xu)elcomeH口׃(x)昄在Eclipse Workbench上的某个位置 。如果在执行?jin)以上操作,但没有显C新H口Q可以再ơ打开Show View菜单Q此时在菜单中应该有C剙择QWelcome to EclipseQ然后选中它?/P> <P>上面我们完成?jin)一个观察窗口的插gQ但q个操作q程对开发稍微复杂一些的插g显得不太方便了(jin)Q每ơ测试都要将代码打包Q发布,再重新启动EclipsepȝQؓ(f)此Eclipse提供?jin)一个专门ؓ(f)开发插件而做插gQ有点绕_(d)(j)QPlug-in Development EnvironmentQPDEQ。本文前面曾提到Q目前Eclipse的Release或Stable版本~省提供?jin)这个插Ӟ因此如果安装的Eclipse是这两个版本中的一个就可以直接q行下面的步骤。下面我们再用PDE环境开发一个稍微复杂一些的插g?/P> <P>W一步仍然要新徏一个项目,只是在向g不是用Java目Q而是Plug-in Development中的Plug-in Project。在应用向导生成新项目的时候,要注意两点:(x)W一是PDE的项目名U就是plugin的idQ因此要保证它的唯一性,q里我们的项目名是com.nidapeng.eclipse.plugin.pde。其ơؓ(f)?jin)进一步说明Eclipse插g的结构,在Plug-in Code Generators中,选择用向导模板生成一个缺省的插gQ如囑օQ?/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>q个用缺省方式生成的插gcd于我们将要的代码q不是必需的,也可以用生成I插件的方式建立我们的项目,q样做只是ؓ(f)q一步说明Eclipse的插件结构?/P> <P>目生成之后Q在我们的项目中?x)包含一个PdePlugin.java文gQ它?yu)是以缺省方式生成的插gcR注意到它承了(jin)AbstractUIPluginc,而AbstractUIPlugincdC(jin)org.eclipse.ui.plugin接口。事实上Q所有的Eclipse插g都会(x)有一个相应的实现plugin接口的类Q这个类是新插件的ȝQ类g有main()函数的Javac)(j)Q它负责理插g的生存期。在我们的AbstractUIPluginl承子类中,可以用singleton模式来保存在Eclipse中的生成的该插g的第一个也是唯一实例Q一般来_(d)在该l承子类中也要实C个getDefault()Ҏ(gu)以返回当前插件的实例。而且Q当Eclipse首次使用该插件的时候,q个ȝ是W一个被调用的类Q因此我们也可以在它的代码中执行一些初始化的工作。而且如果插g需要用PreferencesQDialogs或Images资源Q也可以通过q个cM的相应方法来得到它们的实例,如用其中的getDialogSettings()QgetPreferenceStore()QgetImageRegistry()Ҏ(gu)?/P> <P>但是象前面提到的QPdePlugin.java对下面的例子q不是必需的,我们不用对它q行M修改。在我们W一个例子中的Weclome插gQ根本就没有生成AbstractUIPlugin的承子c,此时pȝ?x)自动?f)Weclome插g生成一个缺省的ȝQ类gJavacL造函敎ͼ如果没有声明Q系l会(x)指定一个默认的构造函敎ͼ(j)?/P> <P>下面的代码是才真正实C(jin)我们新插件的功能Q假设这个插件名子是NoticeViewQ?/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插g的主c! 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Ҏ(gu) 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Ҏ(gu) 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Ҏ(gu) public void run() { try { label.setText(dispTxt); } catch (Exception e) { e.printStackTrace(); } } } </CODE></PRE></TD></TR></TBODY></TABLE></P> <P>象上面的W一个Welcome插gQ这个新插g同样l承?jin)ViewPartQ不同的是实C(jin)三个接口QRunnable,IResourceChangeListener ,IResourceDeltaVisitor。其中的Runnable大家应该很熟(zhn):(x)多线E的接口。而IResourceChangeListener和IResourceDeltaVisitor是Eclipsepȝ中的资源接口Q这里的资源是指Eclipse中的目或文件等。在下面q行NoticeView插g的过E中你可以通过d、打开、删除项目或文g来触发这两个接口中的事gQƈ在我们的观察H口中显C相关信息?/P> <P>在程序中比较奇怪部分的是在resourceChanged()函数里面Qƈ没有象大家想象的那样直接调用label.setText()Ҏ(gu)来显CZ息,而是调用?jin)disp.syncExec(this)Q其中的disp是Displaycd的对象。这是因为resourceChanged()Ҏ(gu)q行的线E和lable所在插件运行的EclipseȝEƈ不是同一个线E,如果直接调用label.setText()Ҏ(gu)Q会(x)抛出一个异常?/P> <P>下面q需要对目中的plugin.xmlq行一些改动,主要是加上扩展点声明:(x)</P> <P> <TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1> <TBODY> <TR> <TD><PRE><CODE> <?xml version="1.0" encoding="UTF-8"?> <plugin id="com.nidapeng.eclipse.plugin.pde" name="Pde Plugin" version="1.0.0" provider-name="NIDAPENG" class="com.nidapeng.eclipse.plugin.pde.PdePlugin"> <requires> <import plugin="org.eclipse.core.runtime"/> <import plugin="org.eclipse.core.resources"/> <import plugin="org.eclipse.ui"/> </requires> <runtime> <library name="pde.jar"/> </runtime> <extension id="NoticeView" name="Notice View" point="org.eclipse.ui.views"> <category name="Notice" id="com.nidapeng.eclipse.plugin.pde.category1"> </category> <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"> </view> </extension> </plugin> </CODE></PRE></TD></TR></TBODY></TABLE></P> <P>q个xml文g和W(xu)elcome插g的plugin.xml非常接近Q这里就不做q多的说明了(jin)?/P> <P>要运行这个插Ӟ可以直接用Eclipse中的q行按钮Q因个项目是一个Plug-in ProjectQ此旉目会(x)自动以Run-time Workbench方式q行。运行后Q会(x)生成一个和当前Eclipse完全一致的q_Q在q个q_上可以直接运行NoticeView插gQ查看这个插件到底会(x)执行什么功能,也可以用直接Run-time Workbench方式调试插g。这里省M(jin)安装插gQ重启动Eclipse{过E,可以看到用PDE开发插件的q程比直接用Java开发环境简z了(jin)很多Q?/P> <P>Eclipse的开发不仅仅限于插g的开发,它还可以取代Java中的标准SwingQ进行基于Java的独立应用程序GUI开发。它带来的好处是显而易见的Q高速,资源占用低,跨^収ͼ代码开放,有大公司的支持等{?/P> <P>׃Eclipse目前q在开发阶D,W者在用它调试E序时发现有些性能q(sh)是十分的E_Q一些地方会(x)遇到奇怪的问题Q要求用者能想一些办法解冟뀂不q,以现在Eclipse的开发速度Q相信过不了(jin)多久Q它的各U功能会(x)逐步完善。目前Eclipse虽然有种U不I但瑕不掩玉,W者对Eclipse的M印象q是非常不错的,q行速度Q资源占用都要好于IVJQ操作v来也大多手Q而且即在现阶段也很有意外退出等重大的Bug发生Q希望未来的Eclipse能真正达到IVJ的功能,VisualCafe的速度Q成为广大程序员开发Y件的一大利器!</P><img src ="http://m.tkk7.com/qq13367612/aggbug/17813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/qq13367612/" target="_blank">Sung</a> 2005-11-02 15:04 <a href="http://m.tkk7.com/qq13367612/articles/17813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse插g开??初步探烦(ch)http://m.tkk7.com/qq13367612/articles/17812.htmlSungSungWed, 02 Nov 2005 07:01:00 GMThttp://m.tkk7.com/qq13367612/articles/17812.htmlhttp://m.tkk7.com/qq13367612/comments/17812.htmlhttp://m.tkk7.com/qq13367612/articles/17812.html#Feedback0http://m.tkk7.com/qq13367612/comments/commentRss/17812.htmlhttp://m.tkk7.com/qq13367612/services/trackbacks/17812.html
  ?/B>

  许多q以前,当我W一ơ仔l考察EclipseӞ我记得当时好像是2.0版本Q,我对它的完全免费印象非常深。它提供?jin)很多非怸错的Java开发能力,但是当时q没有比那些商业版本好上多少。然而,真正吸引我的是我发现可以用我自己的代码随意扩展它的特性。事实上Qƈ不需要特别的工具--Eclipse提供?jin)所有可以用于自w开发的工具和框架?BR>
  从那以后QEclipse开始在各方面成熟v?-它的设计更加改进?jin),它的l构变得更加强健且不qz,它的各种工具也变得更加强大和高效。它已经从一个工具集成框架变成了(jin)一个开发胖客户?rich-client)E序的^台。这也证明了(jin)我心(j)目中对它本n的基本设计理늚质量的评仗?BR>
  扩展Eclipse需要你对可用的l构和工L(fng)基本熟?zhn)和?jin)解。因为学?fn)如何去做一件事情的最好方式就是去试着自己做做看,本篇文章会(x)帮助你用插件开发环境PDE开发一个简单的Eclipse插g。当你学?fn)一点Eclipse体系l构的背景信息之后,你将?x)用PDE向导来创Z个新的插Ӟ完成一个简单的工作台视图,q且试你的工作看最后的l果。实现的具体l节不能一一说明?jin)。ؓ(f)?jin)完成这个工作,你需要获得最新的Eclipse SDK(3.1版本)Q可以从 http://www.eclipse.org/downloads 获得一份免费的拯?BR>
  所有的东西都是插g

  从一个开发者的角度来说QEclipse是一个开发各U客L(fng)E序的^台。本w其是作Z个开发工兯(g)生的Q现在它的范围已l扩展到包括各种胖客L(fng)应用E序Q以?qing)非桌面环境Q比如手持设备和嵌入式系l。ؓ(f)?jin)支持如此大范围的应用,高度的可扩展性是非常必要的。每个基于Eclipse的程序都包含?jin)多个组Ӟ它们被称作?f)插g(plugins)Q相互间通过预先定义的接口集合进行交互。插仉过一个很的q行时层来进行管理,负责它们的发现和启动。从3.0版本开始,原来的运行时层实现被新的Z开放服务网兛_始化(Open Services Gateway initiative, OSGi)所替代Q从而提高(sh)(jin)Eclipse向多个硬件和操作pȝ的移植能力,q且提供?jin)对理的执行环境的兼容性。因此,目前的Eclipse插g是作为OSGi的组件来开发的?BR>
  和其他的lg理环境cMQ每个Eclipse插g的运行时Ҏ(gu)是在它的描q符中被指定的,q行时层使用描述W来配置插g的执行环境。在3.0版本以前Q描q符是一个XML格式的文Ӟ名ؓ(f)plugin.xmlQ在每个插g目录的根目录中保存。ؓ(f)?jin)和OSGiq行时整合,插g一般被打包成JAR文gQƈ且它们的属性比如单一的标识符Q版本号Q运行时classpath和导出的包,被包含在它们的JAR manifest中(即META-INF/MANIFEST.MFQ。然而,对于一般记录Eclipse插g的特性的描述W?-插g扩展和扩展点--仍然留在plugin.xml文g中描q?BR>
  一个插件的扩展点基本上是它的组仉|点Q用XML Schema子集描述。一个完成某U抽象功能的插gQ比如在工作台显C独立视囄Q将?x)公布一个扩展点Q指定每个实现必d成什么才能被q个插g使用。这些一般需要包含简单的属性,比如H口标题和图标\径,同时也包含实现具体接口的cdU。在q里的例子中Q每个要提供一个视囑֮现的插g必须声明一个插件描q符属性的ID是org.eclipse.ui.views扩展点的扩展。这个扩展必L定类实现接口的名为org.eclipse.ui.IViewPart。在q行Ӟ工作台插件查找插件记录中所有的org.eclipse.ui.views的扩展ƈ且将它们提供l用户作为可昄的视图。当用户选择打开某个视图Ӟ工作台插件初始化指定在插件描q符中视囄实现c,q且通过接口org.eclipse.ui.IViewPart来和它交互。这个机制是Eclipse扩展性的基石。插件给其他的插件提供具体的实现Q很多都是实C(jin)自n高度抽象Qƈ且将它们作ؓ(f)扩展Ҏ(gu)供给其他的插件来完成?BR>
  P 1: plugin.xml的内?

Q?xml version="1.0" encoding="UTF-8"?Q?BR>Q?eclipse version="3.0"?Q?BR> QpluginQ?BR>  Qextension point="org.eclipse.ui.views"Q?BR>   Qcategory id="com.developer.superview.category1" name="Developer.com"/Q?BR>   Qview category="com.developer.superview.category1" class="com.developer.superview.Superview" id="com.developer.superview.view1" name="Superview"/Q?BR>  Q?extensionQ?BR> Q?pluginQ?/TD>

  插g开发环?/B>

  像你所看到的一P开发EclipseE序的核?j)Q务主要包含创建实C个或者多个扩展的插g。理Z来说Q没有东西会(x)L你用记事本Q或者vi或者命令行中的javac来开发Eclipse插gQ我惛_听尝试过的h怎么说得Q)(j)。幸q的是,Eclipse拥有一个强大的工具集来使这一d变得单。插件开发环境PDE是作为Eclipse SDK的一个部分自由分发的Qƈ且作Z个基于Eclipse的IDE工具的好范例而存?-它只是一些插件和它们的扩展的集合Q事实上他们也留下了(jin)一些扩展点Q你可以用这些扩展点来开发自qPDE扩展Q?BR>
  在PDE中,每个正在开发的插g都是被单个的Java工程所代表。插件工E具有一些独一无二的特性来标示自己。比如说它们每一个都有一个插件描q符Q一个manifest?或一个plugin.xml文gQ,一个基于描q符指定的依赖关pȝ动态classpathQ特D的~译器,和其他配|属性。PDE提供?jin)一个插件创建向|可以选择各种需要的部分创徏插g工程?BR>
  PDE带有一个特别的多页~辑器来使得插g开发更加简单。插件Manifest~辑器用?个文?-包含的manifestQMETA-INF/MANIFEST.MFQ,plugin.xml和build.properties.它允怽~辑所有必要的属性来描述一个插?-它的基本q行时要求,依赖Q扩展,扩展点等{。当开发插件的时候你需要做更详l的?jin)解?BR>
  因ؓ(f)Eclipse插g都是Java的工E,它们~省都是逐步构徏的,不需要特别的人工~译步骤。PDE也允怋用Ant来创建非自动~译的插Ӟ你可以ؓ(f)你的插g创徏一个Ant的build脚本Q在Package Explorer中,右键点击你的plugin.xmlq且选择PDE Tools -Q?Create Ant Build FileQ,它提供了(jin)创徏多个目标输出的方式(比如插gJAR包,源代码包{等Q?BR>
  Z(jin)试你的工作QPDE提供?jin)一个特别的启动配置cdQ允怽使用它的配置中包含的工作区插件来启动另外一个工作台实例Q被UCؓ(f)q行时工作台Q(也被UC为selfQhosting--你不比将你的插g安装q一个外部的工作台来试它们Q你可以使用自己的开发工作台动态安装)(j)。你的Eclipse启动配置允怽指定你想包含的哪个插ӞҎ(gu)的命令行参数Q环境属性等{?BR>
  PDE也有一个强大的用户文档和扩展参考信息(Javadoc和扩展点文档Q。因为它是和Eclipse在一个规则下分发的,所以它的代码也是完全开攄Qƈ且缺省包含的SDK中?BR>创徏单的插g

  Z(jin)对用PDE开发插件有个更好的理解Q你可以开发一个简单的工作台视图。它的功能是列出q行时工作台中所有的可用视图Q你可以U它U视图)(j)。当你这样做的时候,你可以用这个n边的例子Q检查插件Manifest~辑器的各个部分?BR>
  首先Q启动你的Eclipse SDKQ选择一个空工作区。当你关掉欢q页面时Q你应该~省q入Java开发模式。第一步,使用新徏插g向导来创建插件。然后,使用插gManifest~辑器编辑其描述W,q且使用JDT来实C个JavacR最后,在一个运行时工作台启动插件来看效果。好Q开始:(x)

  1. 在main menu中,点击File-QNew-QProjectQ然后选择Plug-in Projectq且点击NextQ?BR>
  2. 在下一个向导页中,输入com.developer.superview作ؓ(f)工程名。点击NextQ?BR>
  3. 在此中Q保持所有的域ؓ(f)~省|点击Finish。当被问到是否{换到插g开发模式时Q选择yes。这Ӟ插g已经被创Z(jin)Qƈ且你可以在插件Manifest~辑器中看到总览?BR>
  总览面包含?jin)一些一般属性,如插件的IDQ版本,名称Q提供者,插gcdq_qo(h)器。它q提供了(jin)到其他页面的链接Q这些页面指定了(jin)插g内容Q编译配|,和测试运行的链接以及(qing)导出插gQ所有的和简单描qͼ(j)。ID是必ȝ且必Mؓ(f)独一无二的。版本一般ؓ(f)3?个部分组成,使用点号隔开的版本标识符(major.minor.service{.qualifier})。插件版本在你的q_插g开发向g有详l记q。在q个l习(fn)里,你可以指定ؓ(f)~省?.0.0。姓名和提供者是可选的Q只是被用来在品配|里昄的标记。类属性也是可选的Q目前它可以被用来代表一个单独的q行时插件实例,可以用来作ؓ(f)一个单独的对多个插件特定数据的讉K炏V在q个例子里,向导闯将?jin)一个缺省的cd玎ͼ你可以在例子的Q何代码里提到它。^台过滤器可以用来限制插g的^台可用性(q个例子里没有用刎ͼ(j)?BR>

  依赖面允许你指定其他一些你所依赖的插Ӟ无论是编译的q是q行时的。增加一个插件依赖意味着被选择插g的所有Java包的导出Q包含Q何的扩展点,对你自己的代码都是可用的。你可以选择在你的SDK安装时增加Q何可用插Ӟ包括你的工作収ͼ也就是说Q其他你当前正在使用的插Ӟ(j)?BR>
  在我们这里例子里Q你把org.eclipse.core.runtime和org.eclipse.ui作ؓ(f)你的依赖。Q何依赖都是可选的Q确认你的代码需要它Q,你可以选择重新导入一个依赖(选择列表中的一个插Ӟq且点击属性…)(j)。你可以h某个Java包对你的cd动器可用Q无论它是从何而来。这是一个高U开发主题在你的q_文档中有详细叙述。这个页面里Q你可以做一些各U类型的依赖关系的分析,可以l你一个更加好的插件依赖的认识?q行旉面允怽指定惛_出的Java?也就是说Q在你的插g列表中你的插g可见)。在q个列表中,你无dZQ何东西,因ؓ(f)你不提供M的功能作为公共API可用。如果你要这么作Q那你必M得它们针对其衍生的插件可用(q是更加高的开发主题(sh)(jin)Q。Classpath节是用来指定哪个cL件夹或者JAR文g应该作ؓ(f)你的q行时classpathQ如果有多个的话Q缺省只有你的插件的根目录是被包含在它的classpath里)(j)?BR>
  扩展面是你指定你所有的插g扩展的地斏V它包含?jin)一个通过你插件实现的扩展的树(wi)Q你可以从列在你的依赖的插g中选择公布的扩展点Q,和一个详l的包含反映你的当前?wi)选择的域的表单。要创徏新的扩展元素Q右键点?yn)L(wi)中的元素Q选择New子菜单。对元素的选择以及(qing)每个元素的属性集合,依赖于关联的扩展炏V你可以通过右键点击?wi)中的扩展的方式来获得你的扩展点文档Q然后选择Show Description。事实上Qؓ(f)?jin)l我们的例子Q我们将U视囑֮现增加一个新的扩展:(x)

  4. 点击Add。在New Extension对话框中Q选择扩展点org.eclipse.ui.views。点击Finish?BR>
  5. 右键点击列表中的扩展Q选择New-Qcategory。输入Developer.com作ؓ(f)名称Q类型ID为com.developer.superview.category1 保持不变Q?BR>
  6. 右键点击扩展Q选择New-QviewQ输入SuperView作ؓ(f)名称Qcom.developer.superview.category1作ؓ(f)分类Q和在第Q步中创建的cdID匚wQ?BR>
  7. 点击class链接。输入Superview作ؓ(f)cdQ点击Finish。这会(x)创徏一个新的实现所需接口的类Qƈ且在Java~辑器中打开它?BR>
  你可以马上回到视囄开发中来。现在,ȀzL件Manifest~辑器,点击扩展点的yemi。如果可用,会(x)列出所有你的插件公布的扩展炏V每个扩展点的细节都是可以用扩展点Ҏ(gu)~辑器来~辑的(q里不再详细叙述?jin)?j)?BR>
  生成面允许你对插g的生成配|进行指定(或者选择自定义生成来生成一个完整的自定义的生成q程Q这个你需要自己实玎ͼ(j)。这些信息将?x)被增量生成器(你的工程的生成\径也?x)相应的更新Q这也是你不能直接更改而让PDE来ؓ(f)你做的原因)(j)和一个Ant生成脚本所使用Q你只能选择两者中的一个。在q个联系里,你无ȝ别的生成要求。若你要q样作,比如Z的视图用一个自定制的图标,你必M证它的目录是在二q制生成D中被检查过的,以得它对你的代码在q行时可用?BR>
  MANIFEST.MFQplugin.xmlQ和build.properties允许你编辑相应文件的源代码。这个只寚wU熟l的Eclipse开发者推荐用?BR>
  现在你对插gManifest~辑器比较熟(zhn)了(jin)Q我们可以l我们的例子Q?BR>8. ȀzSuperview.java~辑器。你可以看到Qؓ(f)?jin)完成视囄实现Q你必须实现最两个方法:(x)createPartControl(Composite)和setFocus()。这里,我就不详l讨论底层的API?jin)。现在,你应该知道你要创Z个表式的可视化组件——表格查看器——来昄你的视图内容。你配|它Z个内Ҏ(gu)供者来l它操纵你的lg的能力(具体的说是提取Z的模型结构元素来适应表格的包含)(j)Q和一个标志提供者,来给予它使用适当的标志和可选图片来转化你的模型元素到表格项的能力。你也可以给它配|一个排序器来按照字母表序昄表项。最后,你给它一个输?-你的模型对象Q即q行时可用的一l所有可用视囄描述W。完整实现如下:(x)

  List 2: SuperView.java(l承ViewPartc?:

package com.developer.superview;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

public class SuperView extends ViewPart {
 (tng)private TableViewer viewer;
 (tng)
 (tng)
 (tng)public SuperView() {
 (tng) (tng)super();
 (tng)}

 (tng)public void createPartControl(Composite parent) {
 (tng) (tng)viewer = new TableViewer(parent);
 (tng) (tng)viewer.setContentProvider(new ArrayContentProvider());
 (tng) (tng)viewer.setLabelProvider(new LabelProvider());
 (tng) (tng)viewer.setSorter(new ViewerSorter());
 (tng) (tng)viewer.setInput(PlatformUI.getWorkbench().getViewRegistry().getViews());
 (tng)}

 (tng)public void setFocus() {
 (tng) (tng)viewer.getTable().setFocus();
 (tng)}

}


  q已l够运行这个例子了(jin)Q保存,然后Q?BR>
  9. 在你的Package Explore里右键点击,选择Run As -Q?Eclipse Application。这创Z个新的Eclipse使用~省值的启动配置Q启动它?BR>
  10. 当运行时工作台出现的时候,你应该看到欢q视图。点击Window-QShow View-QOther…选择Developer.com-QSuperview。点击OK?BR>

  你应该看到的是Superview昄的Ş式是Q视图<视图P。这作ؓ(f)一个例子来演示PDE使用已经_?jin)。然而,如果你想更深一步进入JFace的学?fn),你可以学着看能否把q个界面做的更加人性化一炏V?BR>
  在这里,表格里每条记录代表一个工作台视图Q你提供的模型对象作查看器的输入Zl视囄描述W(IViewDescriptorQ,你用的内容提供者将M数组对象转化Z个它的元素列表(父子关系Q。但是,标志提供者只是简单的使用?jin)每个元素的toStringQ)(j)Ҏ(gu)来作为其标记。接口IViewDescriptor提供Ҏ(gu)来获得视图标PgetLabelQ)(j)Q,甚至可以获得视图的图标图像(getImageDescriptorQ)(j)Q。你所要做的是重蝲两个标记提供者的Ҏ(gu)Q?BR>11. 关闭q行时工作台。在Superview.java~辑器中Q子cnew LabelProvider()如列?所C:(x)

  P 3: SuperView.java(重写LabelProviderc部分方?:

package com.developer.superview;

import org.eclipse.swt.graphics.Image;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.views.IViewDescriptor;

public class SuperView extends ViewPart {
 (tng)private TableViewer viewer;
 (tng) (tng)
 (tng)public SuperView() {
 (tng) (tng)super();
 (tng)}

 (tng)public void createPartControl(Composite parent) {
 (tng) (tng)viewer = new TableViewer(parent);
 (tng) (tng)viewer.setContentProvider(new ArrayContentProvider());
 (tng) (tng)viewer.setLabelProvider(new MoreLabelProvider());
 (tng) (tng)viewer.setSorter(new ViewerSorter());
 (tng) (tng)viewer.setInput(PlatformUI.getWorkbench().getViewRegistry().getViews());
 (tng)}

 (tng)public void setFocus() {
 (tng) (tng)viewer.getTable().setFocus();
 (tng)}
 (tng)
class MoreLabelProvider extends LabelProvider{
 (tng)private final Map images = new HashMap();
 (tng)public String getText(Object element)
 (tng){
 (tng) (tng)return ((IViewDescriptor) element).getLabel();
 (tng)}
 (tng)public Image getImage(Object element)
 (tng){
 (tng) (tng)I(yng)mage image = (Image) images.get(element);
 (tng) (tng)if (image == null)
 (tng) (tng){
 (tng) (tng) (tng)I(yng)ViewDescriptor view = (IViewDescriptor) element;
 (tng) (tng) (tng)I(yng)mageDescriptor desc = view.getImageDescriptor();
 (tng) (tng) (tng)image = desc.createImage();
 (tng) (tng) (tng)images.put(element, image);
 (tng) (tng)}
 (tng) (tng)return image;
 (tng)}
 (tng)public void dispose()
 (tng){ (tng) (tng)
 (tng) (tng)for (Iterator i = images.values().iterator(); i.hasNext();)
 (tng) (tng) (tng) (tng)((Image) i.next()).dispose();  (tng) (tng)
 (tng)}
}
 (tng)
}


  q里Q你已经重蝲?jin)getText(Object)Ҏ(gu)来返回元素(一个IViewDescriptor的实例)(j)的标受ؓ(f)?jin)得看h更加好看Q你可以重蝲getImage(Object)Ҏ(gu)来返回每个视囄文字标号的关联图标。这里比较复杂一点了(jin)Q你必须学习(fn)JFace和SWTQ你会(x)发现囑փ(org.eclipse.swt.graphics.Image)是操作系l的资源Q必被E序来管理。然而,IViewDescriptor只是q回?jin)一个ImageDescriptor而不是图像本w。一个图像标识符可能被用来创Z个Image实例Q但是必能够在不需要的时候释放。由于这个原因,你必跟t创建的所有的Image实例q在不需要的时候释放掉它?BR>
  要看最后的输入Q重新启动运行时工作台。(Ctrl + F11Q?BR>

  打包q且分发插g

  即你可能完成了(jin)插g的开发和试Q你也需要将其从开发环境里导出分发到用h中。幸q的是,Eclipse没有把这个交l你自己完成。你可以使用导出向导Q它出现在你的插件编辑器的总览面里。它?yu)创Z个分发包文gQ包含你的插件代码和资源。用户只要将其解压在他们的Eclipse安装里,如果它们的环境的所有依赖关p都满Q那么Eclipse会(x)在需要时自动发现和激zM的插件?BR>
  q种形式的分发和安装被成为未理?-如果你将来进行更新的话,你将发现和安装你的插件的更新的Q务交l了(jin)用户。一个更加有l织的方法时你的插件组l成feature。feature是一l同时安装和理的插件。在集合插g之外Qfeature包含?jin)一些信息,q些信息允许Eclipse更新理器来定位公布的更斎ͼq且发现新的兌的feature。这L(fng)发布在某个web目录下的更新叫做更新站点。PDE提供?jin)向导和~辑器来支持feature和更新站点的开发?BR>
  如果你开发整个应用程序而不只是插g和featureQ需要已有的ZEclipse的品的安装Q你需要用品配|编辑器QProduct Configuration editorQ和产品导出向导QEclipse Product export wizardQ,把你的应用作Z个独立的Eclipse产品。这个高U主题可以独立成Z文章了(jin)?BR>
  l论

  Eclipse是一个伟大的工具和胖客户端应用^収ͼ不单提供?jin)它的免费开攄Ӟ|供了(jin)它自w的开攑֮现。在Eclipse中,所有功能都装成插Ӟ它们一个个使用良定义的扩展点结合在一赗它的PDE提供?jin)功能强大的工具和向导来帮助你开发你自己的插件。更重要的是Q它提供?jin)整个环节的开发支持,包括分发和后期品维护?img src ="http://m.tkk7.com/qq13367612/aggbug/17812.html" width = "1" height = "1" />

Sung 2005-11-02 15:01 发表评论
]]>
Eclipse 插g开?/title><link>http://m.tkk7.com/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://m.tkk7.com/qq13367612/articles/17811.html</guid><wfw:comment>http://m.tkk7.com/qq13367612/comments/17811.html</wfw:comment><comments>http://m.tkk7.com/qq13367612/articles/17811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/qq13367612/comments/commentRss/17811.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/qq13367612/services/trackbacks/17811.html</trackback:ping><description><![CDATA[<span id="mggui2c" class=atitle2>如何创徏、调试和安装插g</SPAN> <P><A name=1><span id="geaqguq" class=atitle2>Z插g的体pȝ?/SPAN></A><BR>Eclipse q_?IBM 向开发源码社区捐赠的开发框Ӟ它之所以出名ƈ不是因ؓ(f) IBM 宣称投入开发的资金L ?4 千万元 ?而是因ؓ(f)如此巨大的投入所带来的成果:(x)一个成熟的、精?j)设计的以?qing)可扩展的体系l构。Eclipse 的h(hun)值是它ؓ(f)创徏可扩展的集成开发环境提供了(jin)一个开放源码^台。这个^台允怓Q何h构徏与环境和其它工具无缝集成的工兗?/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">插g</I>。除?jin)小型的q行时内怹外,Eclipse 中的所有东襉K是插件。从q个角度来讲Q所有功能部仉是以同等的方式创建的。从q个角度来讲Q所有功能部仉是以同等的方式创建的?</P> <P>但是Q某些插件比其它插g更重要些。Workbench ?Workspace ?Eclipse q_的两个必备的插g ?它们提供?jin)大多数插g使用的扩展点Q如?1 所C。插仉要扩展点才可以插入,q样它才能运行?/P> <P><A name=figure1><B>?1. Eclipse Workbench ?WorkspaceQ必备的插g支持 </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 lg包含?jin)一些扩展点Q例如,允许(zhn)的插g扩展 Eclipse 用户界面Qɘq些用户界面带有菜单选择和工h按钮Q请求不同类型事件的通知Q以?qing)创建新视图。Workspace lg包含?jin)可以让?zhn)与资源Q包括项目和文gQ交互的扩展炏V?/P> <P>当然Q其它插件可以扩展的 Eclipse lgq只有 Workbench ?Workspace。此外,q有一?Debug lg可以让?zhn)的插件启动程序、与正在q行的程序交互,以及(qing)处理错误 ?q是构徏调试器所必需的。虽?Debug lg对于某些cd的应用程序是必需的,但大多数应用E序q不需要它?/P> <P>q有一?Team lg允许 Eclipse 资源与版本控制系l(VCSQ交互,但除非?zhn)正在构?VCS ?Eclipse 客户机,否则 Team lgQ就?Debug lg一P不会(x)扩展或增强它的功能?/P> <P>最后,q有一?Help lg可以让?zhn)提供应用E序的联机文档和与上下文敏感的帮助。没有h?x)否认帮助文档是专业应用E序必备的部分,但它q不是插件功能的必要部分?/P> <P>上述每个lg提供的扩展点都记录在 Eclipse Platform Help 中,该帮助在 Platform Plug-in Developer 指南的参考部分中。乍一看,其?API 参考大全的 Workbench 部分Q一开始会(x)令h望而却步。我们不?x)深入?jin)解众多可用扩展点的详l信息,而只是粗略地看一个简单插件及(qing)其组件?/P> <P><A name=2><span id="smammus" class=atitle2>插g?/SPAN></A><BR>创徏插g最单的Ҏ(gu)是?Plug-in Development EnvironmentQPDEQ。PDE ?Java Development ToolingQJDTQIDE ?Eclipse 的标准扩展。PDE 提供?jin)一些向g帮助创徏插gQ包括我们将在这里研I的“Hello, world”示例?/P> <P>?Eclipse 菜单Q选择 <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>Q或?Ctrl-NQ,然后选择 Select 对话框左边的 Plug-in Development 向导。在 Select 对话框的双Q选择 Plug-in Project。按 Next。在下一屏上Q输入项目名Uͼ我用了(jin) <CODE>com.example.hello</CODE> 。再ơ按 Next。在下一屏上Q请注意Q插件标识就与项目名U相同。用项目名UC为插件标识可以将该插件与另一个插件的名称发生冲突的机?x)减到最。再按一?Next。下一屏让(zhn)选择是手工创建初始插件代码,q是q行代码生成向导。保留代码生成向导的~省选项Q选择“Hello, World”,然后?NextQ如?2 所C?</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>下一屏要求一些附加信息。请注意q一屏上的信息:(x)它包含了(jin)插g名称、版本号、提供者名U和cd。这些是关于插g的重要信息,我们在E后研究。可以接受向导提供的~省倹{按 Next。在下一屏幕上,接受包名、类名和消息文本的缺省倹{选择“Add the action set to the resource perspective”复选框。按 Finish?/P> <P>如果接到通知Q向导需要启用某些其它插件才能完成,那么?OK?/P> <P>q一?x)儿Q向导将完成Q而在(zhn)的工作Z会(x)有一个新的项目,名ؓ(f) <CODE>com.example.hello</CODE> Q如?3 所C?</P> <P><A name=figure3><B>?3. PDE 透视图:(x)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 中,工作台的左边是向导创建的一些东西的概述。大多数w不引人关注:(x)包括目c\径中的许?<CODE>.jar</CODE> 文gQ这些包括插件和 Java q行时所需?Eclipse c)(j)、一个图标文件夹Q包含了(jin)工具栏按钮的囑ŞQ,以及(qing) <CODE>build.properties</CODE> 文gQ包含自动构本所使用的变量)(j)?</P> <P>q里最有意思的东西?src 文g夹,它包含了(jin)插g?plugin.xml 文g的源代码 ?plug-in.xml 是插件的清单文g。我们将先查?plugin.xml?/P> <P><A name=3><span id="cc0mcma" class=atitle2>插g清单文g</SPAN></A><BR>插g清单文g plugin.xml 包含?Eclipse 插仉成到框架所使用的描qC息。缺省情况下Q当W一ơ创建插件时Q会(x)在清单编辑器区域中打开 plugin.xml。编辑器底部的选项卡让(zhn)可以选择关于插g的不同信息集合。Welcome 选项卡显CZ(jin)消息“Welcome to Hello Plug-In”,q且要讨Z(jin)所使用的模板和关于使用 Eclipse 实现插g的提C。选择“Source”选项卡可以让(zhn)查?plugin.xml 文g的完整源代码?/P> <P>让我们看看插件清单文件的各个部分。首先是关于插g的常规信息,包括它的名称、版本号、实现它的类文g的名U和 <CODE>.jar</CODE> 文g名?</P><A name=code1><B>清单 1. 插g清单文g ?常规信息</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>接着Q列Z(jin)我们的插件所需的插Ӟ(x)</P><A name=code2><B>清单 2. 插g清单文g ?必需的插?/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> 是工作区插gQ但实际上我们的插gq不需要它。第二个插g <CODE>org.eclipse.ui</CODE> 是工作台。我们需要工作台插gQ因为我们将扩展它的两个扩展点,正如后面?extension 标记所指出的?</P> <P>W一?extension 标记拥有点属?<CODE>org.eclipse.ui.actionSets</CODE> 。操作集合是插gd到工作台用户界面的一l?<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菜单、菜单项和工h。操作集合分l了(jin)基|q样用户可以更方便地理它们。例如,我们?Hello 插g的菜单和工具栏项出现在 Resource 透视图中Q因为当在运行代码生成向导时Q我们做?jin)这L(fng)选择。如果用戯更改它,可以使用 <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 透视图中昄的项中除厠ZSample 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>操作集合包含?jin)两个标讎ͼ?x) <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>Q描q菜单项应该出现在工作台菜单的什么位|,以及(qing)如何出现Q和 <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>Q描q它应该做什么)(j)?其?action 标记标识?jin)执行操作的cR注Q这个类不是上面列出的插件类?</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>许多菜单和操作属性的目的相当明显 ?例如Q提供工hC文本和标识工具栏项的图形。但q要注意 action 标记中的 <CODE>menubarPath</CODE> Q这个属性标识了(jin) menu 标记中定义的哪个菜单调?action 标记中定义的操作。有兌个和其它工作台扩展点的详l信息,请参?<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>Q尤其是“Plugging into the workbench”章节(可以?Eclipse 的帮助菜单中获取该指南)(j)?</P> <P>׃我们选择?jin)将插gd?Resource 透视图,于是生成?jin)第二?extension 标记。这个标C(x)D?Eclipse W一ơ启动ƈ装入我们的插件时Q将插gd?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>如果忽略q最后一?extensionQ用户就需要?<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>插件添加到 ResourceQ或其它Q透视图?</P> <P><A name=4><span id="wqsu2ig" class=atitle2>插g源代?/SPAN></A><BR>代码生成向导生成?jin)两?Java 源文Ӟ打开 PDE Package Explorer 中的 src 文g夹就可以看到它们。第一个文?<CODE>HelloPlugin.java</CODE> 是插件类Q它l承?<CODE>AbstractUIPlugin</CODE> 抽象cR?<CODE>HelloPlugin</CODE> 负责理插g的生命周期,在更为扩展的应用E序中,它负责维护诸如对话框讄和用户首选项{内宏V?<CODE>HelloPlugin</CODE> 要做的事p么多Q?</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>W二个源文g <CODE>SampleAction.java</CODE> 包含的类执行在清单文g的操作集合中指定的操作?<CODE>SampleAction</CODE> 实现?<CODE>IWorkbenchWindowActionDelegate</CODE> 接口Q它允许 Eclipse 使用插g的代理,q样不是在万不得已的情况下,Eclipse 无需装入插gQ这优化工作在装入插件时发生内存和性能斚w的问题降到最低)(j)?<CODE>IWorkbenchWindowActionDelegate</CODE> 接口Ҏ(gu)使插件可以与代理q行交互Q?</P><A name=code6><B>清单 6. IWorkbenchWindowActionDelegate 接口Ҏ(gu)</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 id="q0seeqm" class=atitle2>q行和调试插?/SPAN></A><BR>当开?Eclipse 的插件时Q必d?Eclipse q用新的插g重新启动它以便进行测试和调试Q这很笨拙。幸好,Eclipse PDE 提供?jin)一个自托管Qself-hostedQ的开发环境,它让(zhn)无需插件安装在工作台的单独实例中即可运行?/P> <P>要运?Hello 插gQ选择 <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 实例Q而该实例d?jin)插件的菜单选项和工hQ如?5 所C?</P> <P><A name=figure5><B>?5. 在运行时工作Cq行?Hello 插g </B></A><BR><IMG height=448 alt="Hello 插g" 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”菜单激zL件。Q何一U方法都?x)生成一个框Q其标题是“Hello Plug-in”,内容是“Hello, Eclipse world”,以及(qing)一?OK 按钮Q按该按钮可以关闭这个框?/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>Q按cM的方法调试插件。这ơ,当插件在W二个工作台实例中运行时Q我们可以在最初的工作C单步执行源代码,以及(qing)(g)查变量等?</P> <P>一旦插件经q测试ƈ准备发布Q我们就需要将它适当打包Q以便在 Eclipse 中安装?/P> <P><A name=6><span id="akocqm2" class=atitle2>打包插g</SPAN></A><BR>Eclipse 在启动时?x)查看其插g目录来确定要装入哪些插g。要安装插gQ我们需要在插g目录中创Z个子目录Qƈ程序文件和清单文g复制到那里。徏议目录名U能表示插g的标识,q且后面跟下划线和版本号Q但是这U做法不是必需的。假?Eclipse 安装?C:\eclipse 中;我们要创Z个目录:(x)</P> <P><CODE>C:\eclipse\plugins\com.example.hello_1.0.0. </CODE></P> <P>按照 Java E序的标准,我们的程序文仉要归档到 <CODE>.jar</CODE> 文g??我们的插件清单文Ӟ(zhn)也许记得它包含q个:(x) </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> 文gQ我们可以通过H出昄目名称Qƈ?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>Q以导出插g文g。选择 JAR 文g作ؓ(f)导出方式Q按 NextQ然后浏览到我们为它创徏的目录。下一步,我们q需要将 plugin.xml 文g复制到这个目录。也可以使用 <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>菜单选项Q但误C选择 File System 作ؓ(f)导出目的圎ͼ(j)?</P> <P>q就是安装插件所需的全部操作,但?zhn)需要停止ƈ重新启动 EclipseQ以便能识别q个新的插g。从帮助菜单中选择“About Eclipse Platform”,可以扑ֈ关于已安装插件的信息Q包括版本号。在出现的屏q上有一个按钮是 Plug-in DetailsQ向下滚动列表来L Hello 插g?qing)其版本受?/P> <P><A name=7><span id="skwecgo" class=atitle2>更新插g版本</SPAN></A><BR>在目录名UC包含版本L(fng)目的是允许在同一台机器上共存某个插g的多个版本(每次只装入一个版本)(j)。我们可以通过创徏一?Hello 插g的已更新版本来看看这是如何工作的Q例如,?plugin.xml 文g中的版本hҎ(gu)?.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 形式导出到新的插件目录,例如Q?<CODE>com.example.hello_1.0.1</CODE> 。将修订q的 plugin.xml 文g复制到同一个目录中。当停止q新启?Eclipse Ӟ只会(x)装入已更新的插g?</P> <P><A name=8><span id="cu2y0aa" class=atitle2>插g片段和功能部?/SPAN></A><BR>Eclipse 由插件组成,但在开?Eclipse 的插件时Q还要慎重考虑另外两个U别的组??插g片段和功能部件?/P> <P>插g <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>Q如名称所暗示的)(j)是完整插件的l成部分 ?<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>插g。片D|供的功能与目标插件的功能合ƈ。片D可以用于将插g本地化成各种语言Q在无需形成一个全新发行版的情况下Q以增量形式功能部件添加到现有插gQ或者提供特定于q_的功能。在许多斚wQ片D与插g一栗主要的区别是片段没有插gc??片段的生命周期由其目标插件管理。此外,片段的清单文件叫?fragment.xmlQ它列出?jin)目标插件的标识和版本号Q以?qing)片D늚标识和版本号?</P> <P>另一斚wQ插?<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">功能部g</I>Ҏ(gu)不包含编码。在 Eclipse 体系l构术语中,功能部g是将一l相x(chng)件打包到完整的品中。例如,JDT 是包含了(jin)?Java ~辑器、调试器和控制台q样的插件的功能部g。名?feature.xml 的清单文件描qC(jin)一个功能部件归档文件。在其中Q该清单文g包含?jin)对该功能部件所包含的插件和其它资源的引用、关于如何更新该功能部g的信息、版权信息和许可证信息?</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">d能部?/I>讄?Eclipse q_的外观。主功能部g旨在定诸如l予 Eclipse 其n份的闪屏和其它特征之cȝ东西。Eclipse 只允怸个主功能部g。用q种方式Q通过创徏一l插Ӟ它们打包到功能部g中,q且使这个功能部件成Z功能部gQ就可以重新创徏 Eclipse 的品牌,q将它用于创建全C不同的品。如果从 Eclipse.org 下蝲Q缺省主功能部g?<CODE>eclipse.org.platform</CODE> ?</P> <P><A name=9><span id="ga2iiqa" class=atitle2>后箋(hu)步骤</SPAN></A><BR>在插件的介绍里我们只是稍微了(jin)解一些插件的必要用法。学?fn)插件的更多知识的最?jng)_考资料是 <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>Q可以从 Eclipse 中的帮助菜单中获得该指南。该文档包含?jin)编E指南、Eclipse API 和插件扩展点的参考大全、Eclipse.org 上可用的~程CZ的指南,以及(qing)常见问题列表。另一个优U参考资料是 Eclipse 本n的源代码。根据?zhn)的兴,?zhn)也许想要查找一些示例,以了(jin)解不同工作台功能部gQ如视图和编辑器Q是如何扩展的,或者如何?SWTQEclipse 囑Ş APIQ。此外,下面?<A 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>可以帮助(zhn)学到更多知识?</P> <P><A name=resources><span id="wqgoee4" class=atitle2>参考资?</SPAN></A> <UL> <LI>(zhn)可以参阅本文在 developerWorks 全球站点上的 <A 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 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 的文档、文章以?qing)下?Eclipse?<BR><BR> <LI>览完整?<A 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 插g列表</A>?<BR><BR> <LI>q可以获得更多的 <A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dw="http://www.ibm.com/developerworks/" xmlns:h="http://www.w3.org/1999/xhtml">插g信息Q法语)(j)</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 知识Q? <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 >Getting started with the Eclipse Platform</A>”( <I>developerWorks</I>Q?002 q?11 月)(j) <LI>?<A >Plug a Swing-based development tool into Eclipse</A>”( <I>developerWorks</I>Q?002 q?10 月)(j) <LI>?<A >Internationalizing your Eclipse plug-in</A>”( <I>developerWorks</I>Q?002 q?6 月)(j) <LI>?<A >Testing your internationalized Eclipse plug-in</A>”( <I>developerWorks</I>Q?002 q?7 月)(j) <LI>?<A >Working XML: Use Eclipse to build a user interface for XM</A>”( <I>developerWorks</I>Q?002 q?10 月)(j) <LI>?<A >采访 Marc EriksonQEclipse 代码捐赠</A>”( <I>developerWorks</I>Q?001 q?11 月)(j) <LI>?<A >Working the Eclipse Platform</A>”( <I>developerWorks</I>Q?001 q?11 月)(j) <LI>?<A >Getting to know WebSphere Studio Application Developer</A>”( <I>developerWorks</I>Q?001 q?11 月)(j) <LI>?<A >Help for reusing your assets</A>”( <I>developerWorks</I>Q?001 q?11 月)(j) <LI>?<A >Create native, cross-platform GUI applications</A>”( <I>developerWorks</I>Q?002 q?4 月)(j) </LI></UL><BR> <LI>有关插g开发的更多详细信息Q请参阅 <A 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 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 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>中查找?zhn)需要的参考资料?<BR></LI></UL><img src ="http://m.tkk7.com/qq13367612/aggbug/17811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/qq13367612/" target="_blank">Sung</a> 2005-11-02 14:56 <a href="http://m.tkk7.com/qq13367612/articles/17811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse?qing)其插g介绍和下?/title><link>http://m.tkk7.com/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://m.tkk7.com/qq13367612/articles/17167.html</guid><wfw:comment>http://m.tkk7.com/qq13367612/comments/17167.html</wfw:comment><comments>http://m.tkk7.com/qq13367612/articles/17167.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/qq13367612/comments/commentRss/17167.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/qq13367612/services/trackbacks/17167.html</trackback:ping><description><![CDATA[0.Eclipse下蝲<BR>EMF,GEF - Graphical Editor Framework,UML2,VE - Visual Editor都在q里下蝲<BR><A >http://www.eclipse.org/downloads/index.php</A><BR> (tng)<BR>0.5.lomboz J2EE插g,开发JSP,EJB<BR><A >http://forge.objectweb.org/projects/lomboz</A><BR>1.MyEclipse J2EE开发插Ӟ支持SERVLET/JSP/EJB/数据库操U늭 <BR><A >http://www.myeclipseide.com</A><BR> (tng)<BR>2.Properties Editor (tng) ~辑java的属性文Ӟq可以自动存盘(sh)ؓ(f)Unicode格式 <BR><A >http://propedit.sourceforge.jp/index_en.html</A> <BR> (tng) <BR>3.Colorer Take (tng) Z癄cd的文件按语法着?<BR><A >http://colorer.sourceforge.net/</A> <BR> (tng) <BR>4.XMLBuddy ~辑xml文g<BR><A >http://www.xmlbuddy.com</A> <BR> (tng) <BR>5.Code Folding (tng) 加入多种代码折叠功能Q比eclipse自带的更多)(j) <BR><A >http://www.coffee-bytes.com/servlet/PlatformSupport</A> <BR> (tng) <BR>6.Easy Explorer (tng) 从eclipse中访问选定文g、目录所在的文g?<BR><A >http://easystruts.sourceforge.net/</A> <BR> (tng) <BR>7.Fat Jar 打包插gQ可以方便的完成各种打包dQ可以包含外部的包等 <BR><A >http://fjep.sourceforge.net/</A> <BR> (tng) <BR>8.RegEx Test 试正则表达?<BR><A >http://brosinski.com/stephan/archives/000028.php</A> <BR> (tng) <BR>9.JasperAssistant 报表插gQ强Q要qQ?<BR><A >http://www.jasperassistant.com/</A> <BR> (tng) <BR>10.Jigloo GUI Builder QAQӞ的GQテ~辑插g <BR><A >http://cloudgarden.com/jigloo/</A> <BR> (tng) <BR>11.Profiler 性能跟踪、测量工P能跟t、测量Q程?<BR><A >http://sourceforge.net/projects/eclipsecolorer/</A> <BR> (tng) <BR>12.AdvanQas 提供对if/else{条件语句的提示和快捷帮助(自动更改l构{)(j) <BR><A >http://eclipsecolorer.sourceforge.net/advanqas/index.html</A> <BR> (tng) <BR>13.Log4E Log4j插gQ提供各U和Log4j相关的Q务,如ؓ(f)Ҏ(gu)、类d一个logger{?<BR><A >http://log4e.jayefem.de/index.php/Main_Page</A> <BR> (tng) <BR>14.VSSPlugin VSS插g <BR><A >http://sourceforge.net/projects/vssplugin</A> <BR> (tng) <BR>15.Implementors 提供跌{C个方法的实现c,而不是接中的功能Q实?Q?<BR><A >http://eclipse-tools.sourceforge.net/implementors/</A> <BR> (tng) <BR>16.Call Hierarchy 昄一个方法的调用层次Q被哪些Ҏ(gu)调,调了(jin)哪些Ҏ(gu)Q?<BR><A >http://eclipse-tools.sourceforge.net/call-hierarchy/index.html</A> <BR> (tng) <BR>17.EclipseTidy (g)查和格式化HTML/XML文g <BR><A >http://eclipsetidy.sourceforge.net/</A> <BR> (tng) <BR>18.Checkclipse (g)查代码的风格、写法是否符合规?<BR><A >http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm</A> <BR> (tng) <BR>19.Hibernate Synchronizer Hibernate插gQ自动映等 <BR><A >http://www.binamics.com/hibernatesync/</A> <BR> (tng) <BR>20.VeloEclipse (tng) Velocity插g <BR><A >http://propsorter.sourceforge.net/</A> <BR> (tng) <BR>21.EditorList 方便的列出所有打开的Editor <BR><A >http://editorlist.sourceforge.net/</A> <BR> (tng) <BR>22.MemoryManager 内存占用率的监视 <BR><A >http://cloudgarden.com/memorymanager/</A> <BR> (tng)<BR>23.swt-designer java的GUI插g<BR><A >http://www.swt-designer.com/</A><BR> (tng)<BR>24.TomcatPlugin 支持Tomcat插g <BR><A >http://www.sysdeo.com/eclipse/tomcatPlugin.html</A><BR> (tng)<BR>25.XML Viewer <BR><A >http://tabaquismo.freehosting.net/ignacio/eclipse/xmlview/index.html</A><BR> (tng)<BR>26.quantum 数据库插?BR><A >http://quantum.sourceforge.net/</A><BR> (tng)<BR>27.Dbedit 数据库插?BR><A >http://sourceforge.net/projects/dbedit</A><BR> (tng)<BR>28.clay.core 可视化的数据库插?<BR><A >http://www.azzurri.jp/en/software/index.jsp</A> <BR><A >http://www.azzurri.jp/eclipse/plugins</A><BR> (tng)<BR>29.hiberclipse hibernate插g <BR><A >http://hiberclipse.sourceforge.net</A><BR><A >http://www.binamics.com/hibernatesync</A><BR> (tng)<BR>30.struts-console Struts插g<BR><A >http://www.jamesholmes.com/struts/console/</A><BR> (tng)<BR>31.easystruts Struts插g<BR><A >http://easystruts.sourceforge.net</A> <BR> (tng)<BR>32.veloedit Velocity插g<BR><A >http://veloedit.sourceforge.net/</A><BR> (tng)<BR>33.jalopy 代码整理插g<BR><A >http://jalopy.sourceforge.net/</A><BR> (tng)<BR>34.JDepend 包关pd?BR><A >http://andrei.gmxhome.de/jdepend4eclipse/links.html</A><BR> (tng)<BR>35.Spring IDE Spring插g<BR><A >http://springide-eclip.sourceforge.net/updatesite/</A><BR> (tng)<BR>36.doclipse 可以产生xdoclet 的代码提C?BR><A >http://beust.com/doclipse/</A><BR><img src ="http://m.tkk7.com/qq13367612/aggbug/17167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/qq13367612/" target="_blank">Sung</a> 2005-10-28 14:21 <a href="http://m.tkk7.com/qq13367612/articles/17167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse插g内幕-插g开?如何定制一个向?/title><link>http://m.tkk7.com/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://m.tkk7.com/qq13367612/articles/15978.html</guid><wfw:comment>http://m.tkk7.com/qq13367612/comments/15978.html</wfw:comment><comments>http://m.tkk7.com/qq13367612/articles/15978.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/qq13367612/comments/commentRss/15978.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/qq13367612/services/trackbacks/15978.html</trackback:ping><description><![CDATA[前段旉Q我C(jin)个很的、口袋式的电(sh)子通讯ѝ我一直随w带着它,直到有一天,它坏?jin)。我联系?jin)卖Ӟ?gu)告诉我,他们没有办法l修Q但是可以给我换个新的,在q个时候,我意识到?jin)数据的重要性。和存储的信息相比,q个发明简直一文不倹{?BR><BR>在这个文章系列中Q第一部分向读者介l了(jin)Eclipse的插件开发环境,q开发了(jin)一个简单的插gQ第二部分添加了(jin)工具栏按钮、一个菜单项和对话框。一个小发明q不能ؓ(f)我们做什么事情,它仅仅将h信息按照某个字体格式昄l我们,那么我们要做的是教会(x)它去处理实际的数据。我们要通知那些插gQ让它们按照我们的需要来工作。本文讨Z(jin)如何来定制一个编辑文件的向导?BR><BR><B><SPAN style="FONT-SIZE: 16px">一 Invokatron的故?/SPAN></B><BR><BR>首先Q我们来?jin)解一下InvokatronQ在前面的文章中Q我们也提到?jin)Invokatron是一个生Java代码的图形化工具Q用q个工具Q你可以方便的采用拖放方式来创徏一个Java Class。这个“dragged-in”方法被~辑好的Ҏ(gu)调用QinvokedQ,q就是它名字的由来。我们将采用数据驱动的方式来设计我们的系l?BR><BR>在下面的章节中,我们开发这个图形应用接口程序。从现在开始我们需要列出插件输入和存储的重要数据。这是我们常说的应用程序的模型。在接下来的文章中,我们制作这个图形化界面。目前我们需要考虑的仅仅是提取出哪些信息是我们的插仉要存攄重要数据。这部分通常被称作是应用的模?BR>QModelQ部分。以下是设计pȝ旉要考虑的东西:(x)<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)哪部分数据是需要保存的Q?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)这些数据用什么样的存储结构来表示他们QPOJOQJavaBeanQ还是EJBQ?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)这些数据如何进行持久化Q用数据库中的表QXML文gQ属性文件还是一个序列化的二q制文Ӟ<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)数据的d采用哪些途径Q用新建文件向|其他cd的向|一个弹出式的对话框Q一个图形化的编辑器Q文本编辑器q是使用文g属性页Q?BR>在我们l前行之前,q些问题必须解决。没有一U答案是适用于所有项目的Q这些答案是Z目需求。我为我们的目做了(jin)以下的定义:(x)<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)一个Javacd含类名,一个包Q一个父c,q实现某些接口。我们先定义q些Q在后面的文章中添加一些其他的数据信息?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)这些数据将׃个承自Propertiescȝ子类来表C。这些构成了(jin)~辑器的“文档类”?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)我们将采用一cd性文件来实现转换。利用Propertiesc,q样的操作很Ҏ(gu)实现?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)采用一个新建文件向导来初始化数据,接着Q我们让用户在属性窗口或者文本编辑器中修Ҏ(gu)据。这步操作将在下面的文档中进行说明?BR><BR><B><SPAN style="FONT-SIZE: 16px">?文档c?/SPAN></B><BR><BR>接下来要做的是写文档cR创Z个名为invokatron.model的包Q然后创Z个名为InvokatronDocument的类。这是我们最初的文档c:(x)<BR><BR><PRE class=overflow title="pre code">public class InvokatronDocument<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)extends Properties<BR>{<BR> (tng) (tng) (tng) (tng)public static final String PACKAGE = "package";<BR> (tng) (tng) (tng) (tng)public static final String SUPERCLASS = "superclass";<BR> (tng) (tng) (tng) (tng)public static final String INTERFACES = "interfaces";<BR>}</PRE><BR><BR>使用Propertiescd以简单的实现数据的{换和保存操作。其中,getter和setterҎ(gu)q不是必ȝQ如果你x(chng)加这些方法的话,你可以添加它们。这个类q没有写完,在后面,我们给它加上Eclipse需要用的接口。对q个c而言Q要取得一个属性,只需要这L(fng)操作Q?BR><BR><PRE class=overflow title="pre code">String package =<BR> (tng) (tng) (tng) (tng)document.getProperty(InvokatronDocument.PACKAGE);</PRE><BR><BR><B><SPAN style="FONT-SIZE: 16px">?定制一个向?/SPAN></B><BR><BR><BR>看一下我们在之前的文章中使用到的向导Q如果你现在q没有源代码Q请?A target=_new>q里下蝲</A>Q。记住,你可以通过我们d的工h按钮或者菜单项来打开q个向导。请看图1Q?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>? 以前的向?BR><BR>q个向导只有一,在右上角也没有图片。我们想d更多的信息ƈ且有个漂亮的囄。换句话_(d)我们惛_制这个向对{?BR><BR>首先让我们来剖析一下向对{打开InvokatronWizard.java文gQ注意这个类l承?jin)Wizardq且实现?jin)InewWizard接口。这里有很多你必ȝ道的Ҏ(gu)。定制我们的向导Q只需要简单的调用或者重写这些方法。这里有一些重要介l:(x)<BR><BR><BR><B><SPAN style="FONT-SIZE: 12px">3.1 关于生命期的Ҏ(gu)</SPAN></B><BR>我们需要重写这些方法来加入关于那些初始化和销毁定制的向导代码?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)构造器。这个方法将在向D行实例化的时候、ƈ且Eclispe向它传送信息之前调用。是向导的常规信息初始化的实现。通常情况下你?x)调用“美化方法”(见下面)(j)来给对话框做默认讄?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)init(IWorkbench workbench, IStructuredSelection editorSelection)Q这个方法由Eclipse调用Q它l向导提供一些工作取信息。重写这个方法来处理Iworkbench和之后将使用的对象。如果这是个~辑向导而不是新建向|我们需要将当前~辑器的选择也作ؓ(f)一个参数?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dispose()Q由Eclipse调用来处理回收。重写这个方法来回收向导所占用的资源?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)finalize()Q对于回收处理,采用dispose()Ҏ(gu)调用?BR><BR><B><SPAN style="FONT-SIZE: 12px">3.2 化Ҏ(gu)</SPAN></B><BR>以下的方法将装饰q个向导H口Q?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setWindowTitle(String title)Q调用这个方法来取得标题栏字W?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setDefaultPageImageDescriptor(ImageDescriptor image)Q调用这个方法来取得昄在所有向导页右上角的囄?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setTitleBarColor(RGB color)Q调用这个方法来来定义标题栏的颜艌Ӏ?BR><BR><B><SPAN style="FONT-SIZE: 12px">3.3 按钮的常用方?/SPAN></B><BR>下面的方法控制向g的按钮的可用性和它的操作?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)boolean canFinish()Q重写这个方法,Ҏ(gu)向导的状态来指明Finish按钮是否可用?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)boolean performFinish()Q重写这个方法,实现q个向导最Ҏ(gu)的业务逻辑。如果向g能完成(产生错误Q则q回false?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)boolean performCancel()Q重写这个方法,当用户单击Cancel按钮的时候做清除操作。如果这个向g能取消,q回false?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)boolean isHelpAvailable()Q重写这个方法,定义Help按钮是否可见?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)boolean needsPreviousAndNextButtons()Q重写这个方法,定义Previous和Next按钮是否可见?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)boolean needsProgressMonitor()Q重写这个方法,指明q程监听器控件是否可见。它?yu)在单击“Finish”按钮后调用performFinish()Ҏ(gu)的时候出现?BR><BR><B><SPAN style="FONT-SIZE: 12px">3.4 面的常用方?/SPAN></B><BR>下面的方法将控制面的出玎ͼ(x)<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)addPages()Q当向导框出现的时候调用。重写这个方法给向导d新页面?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)createPageControls(Composite pageContainer)QEclipse调用q个Ҏ(gu)向g的所有页面(׃面的addPages()Ҏ(gu)d的)(j)实例化。重写这个方法,d向导中一直可见的控gQ不仅仅是页面)(j)?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)WizardPage getStartingPage()Q重写这个方法来定义向导的第一个页面?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)WizardPage getNextPage(IWizardPage nextPage)Q在默认情况下,单击Next按钮得到addPages()Ҏ(gu)提供的页面数l中的下一c(din)你可能需要根据用L(fng)选择而{向不同的面。重写这个方法来得到下个面?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)WizardPage getPreviousPage(IWizardPage previousPage)Q与getNextPage()Ҏ(gu)cMQ用来计得到前一个页面?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)int getPageCount()Q返回用addPages()Ҏ(gu)d的页面个数。你不需要重写这个方法,除非你想昄和页面实际数量不一致的数量?BR><BR><B><SPAN style="FONT-SIZE: 12px">3.5 其他有用的方?/SPAN></B><BR>q里有很多有用的辅助性方法:(x)<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setDialogSettings(IDialogSettings settings)Q你可以加蝲对话框的讄q调用init()Ҏ(gu)来发布其中的数据。典型的Q向g的问题设|是默认的,在这里(DialogSettingsQ察看更多的信息?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)DialogSettings getDialogSettings()Q用这个方法可以找回需要的数据。在performFinish()Ҏ(gu)的最后,你可以将数据再次存入文g?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)WizardContainer getContainer()Q可以得到Shell对象Q运行后台线E,hH口Q等{?BR><BR><B><SPAN style="FONT-SIZE: 12px">3.6 向导|?/SPAN></B><BR>我们已经看到Q一个向导是一个或者多个页面的l合。这些页面扩展了(jin)WizardPagecdƈ实现?jin)IwizardPage接口。ؓ(f)?jin)定制一个个性化的向|q有很多Ҏ(gu)是必L握的。这里介l一些比较重要的Ҏ(gu)Q?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)构造器Q初始化面<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dispose()Q重写这个方法,实现清除代码?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)createControl(Composite parent)Q重写这个方法,个页面添加控制器?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Wizard getWizard()Q用来得到向导对象。在调用getDialogSettings()Ҏ(gu)的时候有用?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setTitle(String title)Qؓ(f)向导的标题区提供昄的文字?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setDescription(String description)Q提供显在在标题文字下的信息?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setImageDescriptor(ImageDescriptor image)Q得C个图片,用来取代西安在在向导右上角的默认囄?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setMessage(String message)Q在描述信息的下Ҏ(gu)C的文本信息Q一般用来提C或者警告用戗?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setErrorMessage(String error)Q在描述信息的下面高?sh)度昄一个字W串。它表示向导在处理完错误信息之前不能做下一步的操作?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setPageComplete(boolean complete)Q如果输入参数是trueQ那么Next按钮可以使用?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)performHelp()Q重写这个方法,提供内容敏感的帮助。这个将在Help按钮被按下的时候被向导调用?BR><BR><BR><B><SPAN style="FONT-SIZE: 16px">?为向导编?/SPAN></B><BR><BR>q些Ҏ(gu)使得我们开发一个可扩展的向导成为可能。我们现在来修改q个在前面文章中创徏的Invokatron向导Q给他添加一个页面来h原始的文档数据,q添加一个图片。下面的代码中粗体部分是新增加的Q?BR><BR><PRE class=overflow title="pre code">public class InvokatronWizard extends Wizard<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)implements INewWizard {<BR> (tng) (tng) (tng) (tng)private InvokatronWizardPage page;<BR> (tng) (tng) (tng) (tng)private InvokatronWizardPage2 page2;<BR> (tng) (tng) (tng) (tng)private ISelection selection;<BR><BR> (tng) (tng) (tng) (tng)public InvokatronWizard() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)super();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setNeedsProgressMonitor(true);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)mageDescriptor image =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)AbstractUIPlugin.<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)imageDescriptorFromPlugin("Invokatron",<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) "icons/InvokatronIcon32.GIF");<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setDefaultPageImageDescriptor(image);<BR> (tng) (tng) (tng) (tng)}<BR><BR> (tng) (tng) (tng) (tng)public void init(IWorkbench workbench,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)StructuredSelection selection) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)this.selection = selection;<BR> (tng) (tng) (tng) (tng)}</PRE><BR><BR>在构造函CQ我们打开?jin)过E监听器qؓ(f)向导讄?jin)图片。你可以通过右键下蝲q个新图标:(x)<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文g夹下。ؓ(f)?jin)?j)q图片的加蝲Q我们用了(jin)AbstractUIPlugin.imageDescriptorFromPlugin()Ҏ(gu)?BR><BR>注意Q你必须知道Q尽这个向导是InewWizardcd的向|但ƈ不是所有的向导是用来生新文档的。要想知道怎么LCZ个“独立”的向导Q请参看文章最后的资源部分?BR>接下来是addPages()Ҏ(gu)Q?BR><BR><PRE class=overflow title="pre code"> (tng) (tng) (tng) (tng)public void addPages() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page=new InvokatronWizardPage(selection);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)addPage(page);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page2 = new InvokatronWizardPage2(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)selection);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)addPage(page2);<BR> (tng) (tng) (tng) (tng)}</PRE><BR><BR>在这个方法中Q我们添加了(jin)一个名为InvokatronWizardPage2的新面Q我们待?x)就会(x)写q个面。接下来是用h下向g的Finish按钮后会(x)调用的方法:(x)<BR><BR> (tng) (tng) (tng) (tng)<PRE class=overflow title="pre code">public boolean performFinish() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//First save all the page data as variables.<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final String containerName =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page.getContainerName();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final String fileName =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page.getFileName();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final InvokatronDocument properties =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new InvokatronDocument();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties.setProperty(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)nvokatronDocument.PACKAGE,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page2.getPackage());<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties.setProperty(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)nvokatronDocument.SUPERCLASS,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page2.getSuperclass());<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties.setProperty(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)nvokatronDocument.INTERFACES,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page2.getInterfaces());<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//Now invoke the finish method.<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)RunnableWithProgress op =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new IRunnableWithProgress() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void run(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)ProgressMonitor monitor)<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throws InvocationTargetException {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)doFinish(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)containerName,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)fileName,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (CoreException e) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throw new InvocationTargetException(e);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} finally {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.done();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)};<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getContainer().run(true, false, op);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (InterruptedException e) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return false;<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (InvocationTargetException e) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Throwable realException =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)e.getTargetException();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)MessageDialog.openError(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getShell(),<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"Error",<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)realException.getMessage());<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return false;<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return true;<BR> (tng) (tng) (tng) (tng)}</PRE><BR><BR>现在我们需要作一些数据保存的工作。这个工作将被向导的容器QEclipse工作区)(j)执行Q所以必d现IrunnableWithProgress接口Q这个接口只包含一个run()Ҏ(gu)。IprogressMonitor允许输出d的过E信息。这是我们接下来会(x)看到的。真正的数据保存操作在辅助性方法中QdoFinish()Q?BR><BR> (tng) (tng) (tng) (tng)<PRE class=overflow title="pre code">private void doFinish(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String containerName,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String fileName,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Properties properties,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)ProgressMonitor monitor)<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throws CoreException {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// create a sample file<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.beginTask("Creating " + fileName, 2);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)WorkspaceRoot root = ResourcesPlugin.<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getWorkspace().getRoot();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Resource resource = root.findMember(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Path(containerName));<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (!resource.exists() ||<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)!(resource instanceof IContainer)) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throwCoreException("Container \"" +<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)containerName +<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"\" does not exist.");<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Container container =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)(IContainer)resource;<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final IFile iFile = container.getFile(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Path(fileName));<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)final File file =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)iFile.getLocation().toFile();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)OutputStream os =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new FileOutputStream(file, false);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)properties.store(os, null);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)os.close();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (IOException e) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)e.printStackTrace();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throwCoreException(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"Error writing to file " +<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)file.toString());<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//Make sure the project is refreshed<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//as the file was created outside the<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//Eclipse API.<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)container.refreshLocal(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Resource.DEPTH_INFINITE, monitor);<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.worked(1);<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.setTaskName(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"Opening file for editing...");<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getShell().getDisplay().asyncExec(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Runnable() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void run() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)WorkbenchPage page =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)PlatformUI.getWorkbench().<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getActiveWorkbenchWindow().<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getActivePage();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)DE.openEditor(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)page,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)iFile,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)true);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch (PartInitException e) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)});<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)monitor.worked(1);<BR> (tng) (tng) (tng) (tng)}</PRE><BR><BR>q里Q我们做?jin)很多工作?x)<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)我们得C(jin)想保存的q个文g的\径(作ؓ(f)Eclipse的IFilec)(j)<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)我们也得到了(jin)与之等L(fng)File<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)我们将属性保存到?jin)相应的路径?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)接着Q我们请求Eclipse工作台刷新项目,q样Q这个新的文件就昄出来?jin)?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)最后,我们制定为将来制定了(jin)一个工作计划。这些工作包括在~辑器中打开一个新的文件?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)我们传递一个参敎ͼ调用IprogressMonitor对象的方法,使用戯接收到整个工作过E的信息?BR><BR>最后一个方法是当保存文件失败的情况下,在向g昄错误信息的辅助性方法:(x)<BR><BR> (tng) (tng) (tng) (tng)<PRE class=overflow title="pre code">private void throwCoreException(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String message) throws CoreException {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Status status =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Status(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Status.ERROR,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"Invokatron",<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Status.OK,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)message,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)null);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throw new CoreException(status);<BR> (tng) (tng) (tng) (tng)}<BR>}</PRE><BR><BR>一个CoreException被向导捕P接着Q它所包含的Status对象信息呈现给用户。这Ӟ向导q没有关闭?BR><BR><BR><B><SPAN style="FONT-SIZE: 16px">?为新建向导页~程</SPAN></B><BR><BR>接着Q我们来写InvokatronWizardPage2。这个类是一个新d的文Ӟ(x)<BR><BR><PRE class=overflow title="pre code">public class InvokatronWizardPage2 extends WizardPage {<BR> (tng) (tng) (tng) (tng)private Text packageText;<BR> (tng) (tng) (tng) (tng)private Text superclassText;<BR> (tng) (tng) (tng) (tng)private Text interfacesText;<BR> (tng) (tng) (tng) (tng)private ISelection selection;<BR><BR> (tng) (tng) (tng) (tng)public InvokatronWizardPage2(ISelection selection) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)super("wizardPage2");<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setTitle("Invokatron Wizard");<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setDescription("This wizard creates a new"+<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)" file with *.invokatron extension.");<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)this.selection = selection;<BR> (tng) (tng) (tng) (tng)}<BR><BR> (tng) (tng) (tng) (tng)private void updateStatus(String message) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setErrorMessage(message);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setPageComplete(message == null);<BR> (tng) (tng) (tng) (tng)}<BR><BR> (tng) (tng) (tng) (tng)public String getPackage() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return packageText.getText();<BR> (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng)public String getSuperclass() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return superclassText.getText();<BR> (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng)public String getInterfaces() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return interfacesText.getText();<BR> (tng) (tng) (tng) (tng)}</PRE><BR><BR>上面的构造函数设|了(jin)面的标题(它将高(sh)昄在标题栏下)(j)。我们也有一些辅助性方法。updateStatus管理显C出的这个特定页面的错误信息。如果没有错误信息,Q那p明页面完成了(jin)Q这ӞNext按钮变成可用的状态。这里对数据属性内容设|了(jin)getterҎ(gu)。接下来是createControl()Ҏ(gu)Q它?yu)创建页面上所有可见的l徏?BR><BR> (tng) (tng) (tng) (tng)<PRE class=overflow title="pre code">public void createControl(Composite parent) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Composite controls =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Composite(parent, SWT.NULL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridLayout layout = new GridLayout();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)controls.setLayout(layout);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)layout.numColumns = 3;<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)layout.verticalSpacing = 9;<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Label label =<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new Label(controls, SWT.NULL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("&Package:");<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)packageText = new Text(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)controls,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)SWT.BORDER | SWT.SINGLE);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridData gd = new GridData(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridData.FILL_HORIZONTAL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)packageText.setLayoutData(gd);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)packageText.addModifyListener(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new ModifyListener() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void modifyText(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ModifyEvent e) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dialogChanged();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)});<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("Blank = default package");<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("&Superclass:");<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)superclassText = new Text(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)controls,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)SWT.BORDER | SWT.SINGLE);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)gd = new GridData(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridData.FILL_HORIZONTAL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)superclassText.setLayoutData(gd);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)superclassText.addModifyListener(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new ModifyListener() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void modifyText(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ModifyEvent e) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dialogChanged();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)});<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("Blank = Object");<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("&Interfaces:");<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)interfacesText = new Text(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)controls,<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)SWT.BORDER | SWT.SINGLE);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)gd = new GridData(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)GridData.FILL_HORIZONTAL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)interfacesText.setLayoutData(gd);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)interfacesText.addModifyListener(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)new ModifyListener() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public void modifyText(<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ModifyEvent e) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dialogChanged();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)});<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label = new Label(controls, SWT.NULL);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)label.setText("Separated by ','");<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dialogChanged();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)setControl(controls);<BR> (tng) (tng) (tng) (tng)}</PRE><BR><BR>你需要了(jin)解SWT来书写这些代码。如果你对SWT不了(jin)解,在文章的最后有一些链接,q些链接可以告诉你学?fn)SWT的地斏V基本上q个Ҏ(gu)创徏?jin)标{、输入框q对他们q行?jin)布局。每ơ输入框的改变,它的数据也通过dialogChanged()Ҏ(gu)来进行修改:(x)<BR><BR> (tng) (tng) (tng) (tng)<PRE class=overflow title="pre code">private void dialogChanged() {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String aPackage = getPackage();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String aSuperclass = getSuperclass();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String interfaces = getInterfaces();<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String status = new PackageValidator().isValid(aPackage);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if(status != null) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)updateStatus(status);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return;<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)status = new SuperclassValidator().isValid(aSuperclass);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if(status != null) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)updateStatus(status);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return;<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)status = new InterfacesValidator().isValid(interfaces);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if(status != null) {<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)updateStatus(status);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return;<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)updateStatus(null);<BR> (tng) (tng) (tng) (tng)}<BR><BR>}</PRE><BR><BR>q些工作利用?个工L(fng)来完成:(x)PackageValidatorQSuperclassValidator和InterfacesValidator。我们将在后面来完成q三个类?BR><BR><B><SPAN style="FONT-SIZE: 12px">5.1 验证c?/SPAN></B><BR><BR>在用戯入数据后Q验证工作可以在插g的Q何部分完成。所以,验证代码放在一个可重用的类中是有意义的Q这h验证代码四处拷贝要好得多。下面是一个验证类的例子:(x)<BR><BR><PRE class=overflow title="pre code">public class InterfacesValidator implements ICellEditorValidator<BR>{<BR> (tng) (tng) (tng) (tng)public String isValid(Object value)<BR> (tng) (tng) (tng) (tng){<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if( !( value instanceof String) )<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return null;<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String interfaces = ((String)value).trim();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if( interfaces.equals(""))<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return null;<BR><BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String[] interfaceArray = interfaces.split(",");<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)for (int i = 0; i < interfaceArray.length; i++)<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng){<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)Status status = JavaConventions<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng).validateJavaTypeName(interfaceArray[i]);<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (status.getCode() != IStatus.OK)<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return "Validation of interface " + interfaceArray[i]<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)+ ": " + status.getMessage();<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}<BR> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return null;<BR> (tng) (tng) (tng) (tng)}<BR>}</PRE><BR><BR>其他的验证类跟这个十分相似——参见文档最后的源代码?BR>另一个Eclipse工厂中的漂亮的类是JavaConventionsQ它?yu)?f)我们验证数据。它包含?jin)很多验证方法,例如Q?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)validateJavaTypeName()用来(g)查类和接口的名称<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)validatePackageName()用来(g)查包?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)validateFieldName()用来(g)查数据成员的名称<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)validateMethodName()用来(g)查方法名U?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)validateIdentifierName()用来(g)查变量名U?BR>我们目前不需要用ICellEditorValidator接口Q但是在下一文章中Q我们将使用到它?BR><BR><B><SPAN style="FONT-SIZE: 16px">?l果</SPAN></B><BR>到这里,我们已经完成?jin)一个有囄q由W二늚向导Q它?yu)初始化Invokatron文档。图2是l果Q?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>? 自定义的向导<BR><BR><B><SPAN style="FONT-SIZE: 16px">?耀眼的发?/SPAN></B><BR><BR>正如我们所看到的,很多应用都是数据驱动的。表现方式也很重要。一个糟p的发明是卖不出去的,但是一个耀眼的发明却可以卖出厅R但是数据,才是我们q些E序员的Ҏ(gu)?BR>在这文章中Q我们首先决定了(jin)那些数据是需要处理的。接着Q我们通过定制的向导可视化地捕获了(jin)q些数据。下文章将在表现方式上q行q一步阐qͼq将包括一个定制的~辑器和一个属性页?BR><BR><B><SPAN style="FONT-SIZE: 16px">?资源</SPAN></B><BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)PluginTest3.zip CZ代码:[<A >下蝲文g</A>]<BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng)?A target=_new>“Eclipse Platform Online Help: Wizards?/A><BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng)?A target=_new>“Creating JFace Wizards?/A>阐述?jin)如何创建独立的向?BR>●?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?A target=_new>q些文档</A>来学?fn)SWT。一定要阅读“SWT: The Standard Widget Toolkit”的W一和第二部分,q有“Understanding Layouts in SWT”?BR><BR><BR><B><SPAN style="FONT-SIZE: 16px">?作者和译者简?/SPAN></B><BR>作者:(x)Emmanuel Proulx 是一位J2EE和EJB斚w的资׃Ӟ也是一位WebLogic Server 7.0鉴定工程师。他L?sh)信和网l开发领域?BR>译者:(x)<A target=_new>hopeshared</A> 是一位在读MSEQ目前从事Eclipse插g研究与开发工作?BR><BR><B><SPAN style="FONT-SIZE: 16px">?相关文档</SPAN></B><BR><A target=_new>Eclipse Plugins Exposed, Part 2: Simple GUI Elements</A><BR>Eclipse由大量的插gl成Q但是你不能随意的编写代码然后简单的与之合ƈh。在Emmanuel Proulxq个关于Eclipse的文章系列的W二部分中,他通过创徏一个工h按钮、菜单项、对话框{介l了(jin)Eclipse的“扩展点”…?BR><BR><A target=_new>Eclipse Plugins Exposed, Part 1: A First Glimpse</A><BR>很多开发者仅仅将Eclipse作ؓ(f)一个集成开发环境来使用Q从来不d强大的可扩展性。就像Emmanuel Proulx在这个系列文章的开始所展示的,Eclipse的插件系l提供给你一个可定制的工作^収ͼq样Q你可以定制Eclipse来适应开发的需求…?BR><img src ="http://m.tkk7.com/qq13367612/aggbug/15978.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/qq13367612/" target="_blank">Sung</a> 2005-10-16 13:00 <a href="http://m.tkk7.com/qq13367612/articles/15978.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://m.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://https357171.com" target="_blank">ҹëƬ</a>| <a href="http://97aimeili.com" target="_blank">޹a˾Ʒ</a>| <a href="http://246210.com" target="_blank">պƷƵѹۿ</a>| <a href="http://js-jiarui.com" target="_blank">ۺ</a>| <a href="http://8222se.com" target="_blank">þþþƵ</a>| <a href="http://1992zyzp.com" target="_blank">avĻ</a>| <a href="http://zhuguangbaoyu.com" target="_blank">aëƬվ</a>| <a href="http://xxx2222.com" target="_blank">AVվ߹ۿ</a>| <a href="http://www876444.com" target="_blank">avһ</a>| <a href="http://628669.com" target="_blank">AVƬ߹ۿ</a>| <a href="http://anhuish.com" target="_blank">㽶Ƶѿ</a>| <a href="http://51jingpai.com" target="_blank">Ļ߹ۿ</a>| <a href="http://theav25.com" target="_blank">aëƬȫѲ</a>| <a href="http://guoyit.com" target="_blank">AVô뾫Ʒ </a>| <a href="http://kkxzz.com" target="_blank">޾Ʒ·һ߹ۿ</a>| <a href="http://bovch.com" target="_blank">պëƬһƵ</a>| <a href="http://583s.com" target="_blank">޾Ʒר2</a>| <a href="http://saozib.com" target="_blank">Ƶ</a>| <a href="http://717795.com" target="_blank">޹Ʒ۲ӰԺ߹ۿ </a>| <a href="http://35633487.com" target="_blank">jizzѹۿ</a>| <a href="http://doubiseo.com" target="_blank">ҹþþþ</a>| <a href="http://www22432.com" target="_blank">aaaƬѿ</a>| <a href="http://bz600.com" target="_blank">þƷAV鶹Ƭ </a>| <a href="http://27simnjingmiguan.com" target="_blank">þѿٸ߳VƬػ</a>| <a href="http://www-36664.com" target="_blank">޹Ʒһþ</a>| <a href="http://583s.com" target="_blank">Ʒ˳ɵӰ߹ۿ</a>| <a href="http://tuopumao.com" target="_blank">޳aƬ77777Ⱥɫ</a>| <a href="http://hkcdk.com" target="_blank">Ƶۿ </a>| <a href="http://68996500.com" target="_blank">?VþþƷ</a>| <a href="http://miyatb.com" target="_blank">˳ӰԺ</a>| <a href="http://sdshfengji.com" target="_blank">ۺϾƷվ߹ۿ</a>| <a href="http://tsxyhq.com" target="_blank">һ˿Ƶ</a>| <a href="http://www998xe.com" target="_blank">޾Ʒ</a>| <a href="http://gyqcy.com" target="_blank">ѹۿ߹ۿİ </a>| <a href="http://655060.com" target="_blank">Ƭ91Ʒѹۿ</a>| <a href="http://vvihh.com" target="_blank">߹ۿ</a>| <a href="http://www9797nn.com" target="_blank">ѿһ</a>| <a href="http://xmllhb.com" target="_blank">ƵѲ</a>| <a href="http://www52a.com" target="_blank">AVר4SE</a>| <a href="http://gujingyuye.com" target="_blank">þþƷѹۿ</a>| <a href="http://350725.com" target="_blank">ŷպĶ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>