|
经过前一篇文章的步骤,在我们的指定目录下已经生成了一个Hudson 插件的项目文件夹。在Eclipse中导入这个项目,我们可以看见项目有如下的结构:
+ src
+ main
+ java
+ full.package.name
+- HelloWorldBuilder.java
+- PluginImpl.java
+resources
+ full.package.name
+- config.jelly
+- global.jelly
+- index.jelly
+ webapp
+- help-globalConfig.html
+- help-projectConfig.html
PluginImpl.java:
这个类是用于插件注册扩展点(Extension points)的一个类,在这里,我们注册了一个Builder。其实在Hudson 中有很多不同种类的扩展点,比如Publisher、Recorder 等等。详细的说明可以参考Hudson 的网站。
public class PluginImpl extends Plugin { public void start() throws Exception { BuildStep.BUILDERS.add(HelloWorldBuilder.DESCRIPTOR); }}
HelloWorldBuilder.java
这个类就是具体实现某一扩展点的一个类,在这里由于要扩展Builder这个扩展点,所以继承了 Builder 这个类
public class HelloWorldBuilder extends Builder { private final String name; @DataBoundConstructor public HelloWorldBuilder(String name) { this.name = name; } /** * We'll use this from the <tt>config.jelly</tt>. */ public String getName() { return name; } public boolean perform(Build build, Launcher launcher, BuildListener listener) { // this is where you 'build' the project // since this is a dummy, we just say 'hello world' and call that a build // this also shows how you can consult the global configuration of the builder if(DESCRIPTOR.useFrench()) listener.getLogger().println("Bonjour, "+name+"!"); else listener.getLogger().println("Hello, "+name+"!"); return true; } public Descriptor<Builder> getDescriptor() { // see Descriptor javadoc for more about what a descriptor is. return DESCRIPTOR; } /** * Descriptor should be singleton. */ public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); /** * Descriptor for {@link HelloWorldBuilder}. Used as a singleton. * The class is marked as public so that it can be accessed from views. * * <p> * See <tt>views/hudson/plugins/hello_world/HelloWorldBuilder/*.jelly</tt> * for the actual HTML fragment for the configuration screen. */ public static final class DescriptorImpl extends Descriptor<Builder> { /** * To persist global configuration information, * simply store it in a field and call save(). * * <p> * If you don't want fields to be persisted, use <tt>transient</tt>. */ private boolean useFrench; DescriptorImpl() { super(HelloWorldBuilder.class); } /** * Performs on-the-fly validation of the form field 'name'. * * @param value * This receives the current value of the field. */ public void doCheckName(StaplerRequest req, StaplerResponse rsp, @QueryParameter final String value) throws IOException, ServletException { new FormFieldValidator(req,rsp,null) { /** * The real check goes here. In the end, depending on which * method you call, the browser shows text differently. */ protected void check() throws IOException, ServletException { if(value.length()==0) error("Please set a name"); else if(value.length()<4) warning("Isn't the name too short?"); else ok(); } }.process(); } /** * This human readable name is used in the configuration screen. */ public String getDisplayName() { return "Say hello world"; } public boolean configure(StaplerRequest req, JSONObject o) throws FormException { // to persist global configuration information, // set that to properties and call save(). useFrench = o.getBoolean("useFrench"); save(); return super.configure(req); } /** * This method returns true if the global configuration says we should speak French. */ public boolean useFrench() { return useFrench; } }}
是不是看得有点头晕,呵呵,下面我来逐步分析这些代码
@DataBoundConstructor public HelloWorldBuilder(String name) { this.name = name; } /** * We'll use this from the <tt>config.jelly</tt>. */ public String getName() { return name; }
这段代码用于构造这个Bulider并且从相应的config.jelly中获取相应的参数。Hudson使用了一种叫structured form submission的技术,使得可以使用这种方式活动相应的参数。
public boolean perform(Build build, Launcher launcher, BuildListener listener) { // this is where you 'build' the project // since this is a dummy, we just say 'hello world' and call that a build // this also shows how you can consult the global configuration of the builder if(DESCRIPTOR.useFrench()) listener.getLogger().println("Bonjour, "+name+"!"); else listener.getLogger().println("Hello, "+name+"!"); return true; }
方法perform()是个很重要的方法,当插件运行的的时候这个方法会被调用。相应的业务逻辑也可以在这里实现。比如这个perform()方法就实现了怎么说 “Hello”
接下来,在HelloBuilder 这个类里面有一个叫 DescriptorImpl 的内部类,它继承了Descriptor。在Hudson 的官方说明文档里说Descriptor包含了一个配置实例的元数据。打个比方,我们在工程配置那里对插件进行了配置,这样就相当于创建了一个插脚的实例,这时候就需要一个类来存储插件的配置数据,这个类就是Descriptor。
public String getDisplayName() { return "Say hello world"; }
如上面的代码,可以在Descriptor的这个方法下设置插件在工程配置页面下现实的名字
public boolean configure(StaplerRequest req, JSONObject o) throws FormException { // to persist global configuration information, // set that to properties and call save(). useFrench = o.getBoolean("useFrench"); save(); return super.configure(req); }
如同注释属所说,这个方法用于将全局配置存储到项目中
快下班了,待续,呵呵 |
|