重要概念
上一节我们讨论了Jenkins的插件项目的创建和运行,而这一节,我们将会讨论Jenkins插件编写的几个重要概念。
@Extension 和 ExtensionPoint
Jenkins的插件之所以这么丰富和强大,很大原因上是因为Extension和ExtensionPoint的设计。
ExtensionPoint定义了一系列的切入点,它可以表示项目构建的不同的阶段,可以是表示某个事件,可以表示某个特定类型,可以表示某个位置。
通过实现不同的ExtensionPoint,我们可以灵活控制插件的执行。ExtensionPoint不仅是只能有Jenkins提供,不同的插件也提供了自己的ExtensionPoint。我们自己也可以定义一个ExtensionPoint然后找到其它人在其它插件对我们的ExtensionPoint的实现。
@Extension则是让我们的类被Jenkins自动登记(类似于Spring中的@Bean),Jenkins依据ExtensionPoint为我们控制插件的执行。
下面是上一节中的项目原型的代码。
1 | public class HelloWorldBuilder extends Builder implements SimpleBuildStep { |
1 | :::表示继承,---表示实现 |
从上面的类关系图中,我们看到HelloWorldBuild
实现了BuildStep
这个ExtensionPoint,表示这个类的可能会在项目的构建,运行和完成期间被一次或多次调用。
Jenkins会找到这个类,依据它的ExtensionPoint在合适的时间帮我们调用代码。1
2
3
4
5
6
7
8
public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException {
if (useFrench) {
listener.getLogger().println("Bonjour, " + name + "!");
} else {
listener.getLogger().println("Hello, " + name + "!");
}
}
上面这段就是这个ExtensionPoint中会被Jenkins执行的代码,在我们配置好name后会在Console Output中输出Hello, [name]
。
但是有个问题,之前我们说过,Jenkins要自动登记我们的类,类必须有@Extension
这个注解。但是这个类上并没有这个注解。
这里又有一个重要的概念。
Descriptor和Describable
Descriptor包含一个Describable对象的元数据,同时充当这个Describable对象的工厂类。
在Jenkins依据我们的代码创建一个实现了ExtensionPoint的Extension时候,要对这个对象进行配置(就像上一节填入name那样)和其它操作。Descriptor可以对我们的配置进行检验,依据我们的配置创建出对象,为我们的对象设置各种元属性。
1 | "greet") ( |
如上面代码所示,在这个类上使用@Extension
后,Jenkins就会通过这个Descriptor
工厂类创建HelloWorldBuild
(如上面类图所示我们的HelloWorldBuild实现了Describable),并且可以为这个BuildStep检验参数,设置Display Name(上一节中的Say hello world)和其它属性。
但是上一节中我们看到的配置的表单在哪呢?它又是如何映射到我们的对象的字段呢?
Config
在src\main\resources\org\jenkinsci\plugins\sample\HelloWorldBuilder\
中我们可以看到一个名字是config.jelly的文件。
通过在resources中的和类对应的目录下创建config.jelly文件,就可以为我们的类提供配置的表单。(在同级目录下我们可以看到一些properties文件,这些是用来做本地化用的)
1 | <?jelly escape-by-default='true'?> |
Jenkins使用Apache Jelly编写UI。从上面我们可以看出,通过目录对应一个类,通过field属性对应一个字段,这样对一个对象进行配置。
后面我们将会从头创建一个简单的记录code coverage结果并显示出来的插件。