六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 115|回复: 0

Hudson 插件开发 (Part 2: 插件结构解读 I )

[复制链接]

升级  72%

8

主题

8

主题

8

主题

童生

Rank: 1

积分
36
 楼主| 发表于 2013-2-7 19:08:10 | 显示全部楼层 |阅读模式
经过前一篇文章的步骤,在我们的指定目录下已经生成了一个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);        }
如同注释属所说,这个方法用于将全局配置存储到项目中

快下班了,待续,呵呵
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表