欢迎光临
我们一直在努力

Eclipse入门– Eclipse的使用简介及插件开发(二)-JSP教程,资料/其它

建站超值云服务器,限时71元/月

二.开发eclipse插件(plug-ins)

eclipse最有魅力的地方就是它的插件体系结构。在这个体系中重要的概念是扩展点(extension points),也就是为插件提供的接口。每一个插件都是在现有的扩展点上开发,并可能还留有自己的扩展点,以便在这个插件上继续开发。

由于有了插件,eclipse系统的核心部分在启动的时候要完成的工作十分简单:启动平台的基础部分和查找系统的插件。在eclipse中实现的绝大部分功能是由相应的插件完成的,比如wrokbench ui插件完成界面的外观显示,resource management插件完成维护或生成项目或文件等资源管理工作(在下面的第二个例子就会用到这个插件),而version and configuration management (vcm)插件则负责完成版本控制功能,等等。虽然以上提到的每一个功能都是绝大多数ide环境所必备的功能,eclipse却也把它们都做成了插件模式,甚至用来开发java程序的开发环境(java development tooling,jdt)也只不过是eclipse系统中的一个普通插件而已。整个eclipse体系结构就象一个大拼图,可以不断的向上加插件,同时,现有插件上还可以再加插件。下面的插件开发示例就是在workbench ui插件中的观察窗口扩展点上开发的。

本文第一部分介绍过eclipse的开发界面其中之一就是观察窗口,它通常配合编辑窗口显示一些有用的信息,在这里我们只简单生成一个显示欢迎信息的观察窗口,假设新插件的名子叫welcome。

第一步,先用向导新建一个java项目。我们可以在菜单栏选择fileànew,或用工具栏的向导按键,或是在资源窗口用鼠标右键菜单中的new,打开向导对话框,然后用缺省方式创建项目。并在项目中建立一个welcome.java文件,代码如下:

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() {
    }
}

为使这个程序能正常编译,要配置它的编译环境,即指定所需的classpath。在eclipse中可以用几种方法,常用的是两种:第一是在资源窗口或java包窗口选中该项目,点击鼠标右键,在打开的菜单中选择属性(properties),之后在属性对话框中选择java build pathàlibraries,用add external jars功能添加三个包,它们都是eclipse的现有插件的类包,可以在"你的eclipse安装路径\plugins"下面的相应路径中找到。分别是org.eclipse.core.runtime插件中的runtime.jar,org.eclipse.swt中的swt.jar和org.eclipse.ui中的workbench.jar。第二种指定classpath的方法是先将以上提到的三个包直接导入到eclipse中的某下一个项目中。如果导入到和welcome.java相同的项目中,则无需进一步指定classpath,否则需要在项目的属性菜单中选择java build pathàprojects,然后选中这三个包所在的项目。

在我们的项目中还要生成一个xml文件,它的名字必须plugin.xml。代码如下:

<?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>

在plugin.xml中一共有四个主要的标签:plugin,requires,runtime,extension。其中plugin标签的属性提供的是我们要开发的welcome插件的基本信息,除了name,version,provider-name等,最重要的是id,它要求不能和现有的eclipse插件id有冲突,因此我们用包名作为插件的id。requires标签中所列出的是需要的插件,这里我们要用到eclipse workbench和swt api,因此导入了org.eclipse.ui插件。runtime标签指明的是我们开发的插件所在jar包的文件名。extension标签是插件扩展点的信息。org.eclipse.ui.views是eclipse系统提供的观察窗口扩展点,我们的例子是一个观察窗口(view),这表明我们是要在 org.eclipse.ui.views扩展点上进一步开发。extension中还包括category和view两个标签,在后续的启动welcome插件步骤中,我们就会知道这两个标签的含义。要注意的是category和view标签的id的唯一性,并且在view的属性中声明了welcome插件的类名。

在eclipse中为plugin.xml提供了缺省可视化的编辑器,在编写plugin.xml过程中可以借助这个编辑器完成一些工作。如果你直接录入了plugin.xml文件源代码,还可以用这个编辑器校验你的代码:如果编辑器不能正确读入,就表明你的plugin.xml有一些问题。

在确认weclome.java和plugin.xml都正确无误之后,可以用eclipse菜单栏中的export命令将weclome.java导出为jar文件,它的名子应该和plugin.xml中runtime声明的jar相一致。同时导出plugin.xml。安装welcome插件的方法和本文第一部分介绍的安装tomcat插件方法是一样的:首先在"eclipse的安装路径\plugins"路径下面建立一个com.nidapeng.eclipse.plugin路径,然后将weclome.jar和plugin.xml拷到这个路径下。之后必需重新启动eclipse,在eclipse启动的时候,它会搜索所有在插件路径下的插件并注册它们(仅仅是注册,只有在需要某个插件的时候,eclipse才会启动它)。在重新启动的eclipse的菜单栏中选择perspectiveàshow viewàothers,在打开的对话框中我们会找到在plugin.xml中extension的category标签中声明的name属性:welcome。在welcome的支结点中包含了view标签name属性:welcome to eclipse。选中它并确认,welcome窗口就会显示在eclipse workbench上的某个位置 。如果在执行了以上操作,但没有显示新窗口,可以再次打开show view菜单,此时在菜单中应该有新一顶选择:welcome to eclipse,然后选中它。

上面我们完成了一个观察窗口的插件,但这个操作过程对开发稍微复杂一些的插件就显得不太方便了:每次测试都要将代码打包,发布,再重新启动eclipse系统!为此eclipse提供了一个专门为开发插件而做插件(有点绕嘴):plug-in development environment(pde)。本文前面曾提到,目前eclipse的release或stable版本缺省提供了这个插件,因此如果安装的eclipse是这两个版本中的一个就可以直接进行下面的步骤。下面我们再用pde环境开发一个稍微复杂一些的插件。

第一步仍然要新建一个项目,只是在向导中不是用java项目,而是plug-in development中的plug-in project。在应用向导生成新项目的时候,要注意两点:第一是pde的项目名称就是plugin的id,因此要保证它的唯一性,这里我们的项目名是com.nidapeng.eclipse.plugin.pde。其次为了进一步说明eclipse插件的结构,在plug-in code generators中,选择用向导模板生成一个缺省的插件,如图六:

图六

这个用缺省方式生成的插件类对于我们将要的代码并不是必需的,也可以用生成空插件的方式建立我们的项目,这样做只是为进一步说明eclipse的插件结构。

项目生成之后,在我们的项目中会包含一个pdeplugin.java文件,它就是以缺省方式生成的插件类。注意到它继承了abstractuiplugin类,而abstractuiplugin类实现了org.eclipse.ui.plugin接口。事实上,所有的eclipse插件都会有一个相应的实现plugin接口的类,这个类将是新插件的主类(类似于有main()函数的java类),它负责管理插件的生存期。在我们的abstractuiplugin继承子类中,可以用singleton模式来保存在eclipse中的生成的该插件的第一个也是唯一实例,一般来说,在该继承子类中也要实现一个getdefault()方法以返回当前插件的实例。而且,当eclipse首次使用该插件的时候,这个主类将是第一个被调用的类,因此我们也可以在它的代码中执行一些初始化的工作。而且如果插件需要使用preferences,dialogs或images资源,也可以通过这个类中的相应方法来得到它们的实例,如用其中的getdialogsettings(),getpreferencestore(),getimageregistry()方法。

但是象前面提到的,pdeplugin.java对下面的例子并不是必需的,我们不用对它进行任何修改。在我们第一个例子中的weclome插件,根本就没有生成abstractuiplugin的继承子类,此时系统会自动为weclome插件生成一个缺省的主类(类似于java类构造函数,如果没有声明,系统会指定一个默认的构造函数)。

下面的代码是才真正实现了我们新插件的功能,假设这个插件名子是noticeview:

package com.nidapeng.eclipse.plugin.pde;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.iresourcechangeevent;
import org.eclipse.core.runtime.coreexception;
import java.util.resourcebundle;
import org.eclipse.swt.widgets.label;
import org.eclipse.swt.widgets.composite;
import org.eclipse.ui.part.viewpart;
import org.eclipse.swt.swt;
import org.eclipse.swt.widgets.display;
public class noticeview extends viewpart implements 
runnable,iresourcechangelistener ,iresourcedeltavisitor{
    private resourcebundle resourcebundle;
    private label label;
    private display disp;
    private string disptxt;
    public noticeview() {
    resourcesplugin.getworkspace().addresourcechangelistener(this,
      iresourcechangeevent.pre_close
      | iresourcechangeevent.pre_delete
      | iresourcechangeevent.pre_auto_build
      | iresourcechangeevent.post_auto_build
      | iresourcechangeevent.post_change);
    }
    public static iworkspace getworkspace() {
        //resourcesplugin插件的主类!
         return resourcesplugin.getworkspace();
     }
    public void createpartcontrol(composite parent) {
           label = new label(parent, swt.wrap);
        label.settext("change your project status…");
         disp = display.getdefault();
     }
    public void setfocus() {
     }
    // 实现iresourcechangelistener接口中的resourcechanged方法
    public void resourcechanged(iresourcechangeevent event) {
          iresource res = event.getresource();
          switch (event.gettype()) {
               case iresourcechangeevent.pre_close :
                    disptxt = res.getfullpath() + " is about to closed!";
                    break;
               case iresourcechangeevent.pre_delete :
                    disptxt = res.getfullpath() + " is about to be deleted!";
                   break;
               case iresourcechangeevent.post_change :
                    try {
                     event.getdelta().accept(this);
                    } catch (coreexception e) {
                         e.printstacktrace();
                    }
                    break;
               case iresourcechangeevent.pre_auto_build :
                    try {
                     event.getdelta().accept(this);
                    } catch (coreexception e) {    
                     e.printstacktrace();
                    }
                    break;
               case iresourcechangeevent.post_auto_build :
                    try {
                     event.getdelta().accept(this);
                    } catch (coreexception e) {
                         e.printstacktrace();
                    }
                    break;
          }
          disp.syncexec(this);
     }
     // 实现iresourcedeltavisitor接口中的visit方法
     public boolean visit(iresourcedelta delta) {
          iresource res = delta.getresource();
          switch (delta.getkind()) {
           case iresourcedelta.added :
                disptxt = "resource "+res.getfullpath()+" was added.";
                break;
           case iresourcedelta.removed:
                disptxt = "resource "+res.getfullpath()+" was removed.";
               break;
           case iresourcedelta.changed :
                disptxt = "resource "+res.getfullpath()+" has changed.";
               break;
          }
          return true; // visit the children
     }
    // 实现runnable接口中的run方法
     public void run() {
          try {
               label.settext(disptxt);
          } catch (exception e) {
               e.printstacktrace();
          }
    }
}

象上面的第一个welcome插件,这个新插件同样继承了viewpart,不同的是实现了三个接口:runnable,iresourcechangelistener ,iresourcedeltavisitor。其中的runnable大家应该很熟悉:多线程的接口。而iresourcechangelistener和iresourcedeltavisitor是eclipse系统中的资源接口,这里的资源是指eclipse中的项目或文件等。在下面运行noticeview插件的过程中你可以通过添加、打开、删除项目或文件来触发这两个接口中的事件,并在我们的观察窗口中显示相关信息。

在程序中比较奇怪部分的是在resourcechanged()函数里面,并没有象大家想象的那样直接调用label.settext()方法来显示信息,而是调用了disp.syncexec(this),其中的disp是display类型的对象。这是因为resourcechanged()方法运行的线程和lable所在插件运行的eclipse主线程并不是同一个线程,如果直接调用label.settext()方法,会抛出一个异常。

下面还需要对项目中的plugin.xml进行一些改动,主要就是加上扩展点声明:

<?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>

这个xml文件和welcome插件的plugin.xml非常接近,这里就不做过多的说明了。

要运行这个插件,可以直接用eclipse中的运行按钮,因为这个项目是一个plug-in project,此时项目会自动以run-time workbench方式运行。运行后,会生成一个和当前eclipse完全一致的平台,在这个平台上可以直接运行noticeview插件,查看这个插件到底会执行什么功能,也可以用直接run-time workbench方式调试插件。这里省去了安装插件,重启动eclipse等过程,可以看到用pde开发插件的过程比直接用java开发环境简洁了很多!

eclipse的开发不仅仅限于插件的开发,它还可以取代java中的标准swing,进行基于java的独立应用程序gui开发。它带来的好处是显而易见的:高速,资源占用低,跨平台,代码开放,有大公司的支持等等。

由于eclipse目前还在开发阶段,笔者在用它调试程序时发现有些性能还不是十分的稳定,一些地方会遇到奇怪的问题,要求使用者能想一些办法解决。不过,以现在eclipse的开发速度,相信过不了多久,它的各种功能会逐步完善。目前eclipse虽然有种种不足,但瑕不掩玉,笔者对eclipse的总体印象还是非常不错的,运行速度,资源占用都要好于ivj,操作起来也大多顺手,而且即使在现阶段也很少有意外退出等重大的bug发生,希望未来的eclipse能真正达到ivj的功能,visualcafe的速度,成为广大程序员开发软件的一大利器!

参考资源:

www.eclipse.org是eclipse的资源总站。

关于作者
倪大鹏,有五年的软件开发经验,其中的近四年时间里是在从事与java相关技术的应用与开发。你可以通过e-mail: ndp@21cn.com与他联系。

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » Eclipse入门– Eclipse的使用简介及插件开发(二)-JSP教程,资料/其它
分享到: 更多 (0)