介绍

本指南旨在帮助用户在 Java 中为 Maven 开发报告插件,这些插件将有助于生成的maven-site-plugin站点或生成的站点 PDF 文档maven-pdf-site

首先,报告插件是一个Maven 插件,强烈建议先阅读Java 插件开发指南以正确理解其核心机制。

插件本身实际上并不是报表插件。但是它的一个(或几个)目标或Mojo可能被专门用于调用maven-site-plugin,通常在site构建生命周期中。

因此,Maven 插件可以实现常规目标和报告目标。下面详细介绍了如何编写一个Mojo 它将被.maven-site-plugin

这个怎么运作

  1. 常规 Maven 项目通常通过在其部分中声明此类插件来调用插件的报告目标,如下例所示: <reporting>pom.xml
    <project>
      ...
      <reporting>
        <plugins>
          <plugin>
            <groupId>com.mycompany.maven</groupId>
            <artifactId>simple-maven-plugin</artifactId>
            <version>1.0-SNAPSHOT</version>
          </plugin>
        </plugins>
      </reporting>
      ...
  2. maven-site-plugin被调用时(例如使用mvn site命令),指定的插件被加载并且generate()每个 Mojo 类的方法MavenReport被执行。
  3. generate()方法通过 Maven 的Doxia Sink API生成一个文档。本文档由标题、标题、文本、链接、表格等基本元素组成。这是您将根据 Maven 项目的内容放置报表逻辑、组装元素的地方。
  4. 这些文档元素被传递给 Doxia 以生成 HTML 文档,该文档本身被包装到Maven Skin中,如项目中指定的那样./src/site/site.xml
  5. 结果会在./target/site您的项目目录中生成一个 HTML 文件。

有关 Doxia 站点渲染器的更多详细信息

报表Mojo的基本要求

每个目标或Mojo都使用单独的 Java 类实现。一个Mojo要成为一个报表 Mojo,它需要实现org.apache.maven.reporting.MavenReport(除了org.apache.maven.plugin.Mojo)。

实现接口MojoMavenReport接口的一种简单方法是扩展由org.apache.maven.reporting.AbstractMavenReport提供的类maven-reporting-impl(而不是org.apache.maven.plugin.AbstractMojo常规Mojo)。

该类将需要实现以下方法:

  • public String getOutputName():返回将要生成的页面的名称
  • public String getName(Locale locale):返回报告的显示名称
  • public String getDescription(Locale locale):返回报告的描述
  • protected void executeReport(Locale locale) throws MavenReportException:生成实际报告

要构建包含报告 Mojos的 Maven 插件,pom.xml您的项目需要将项目声明为常规插件,并包含报告Mojos所需的特定依赖项:

一份(非常)简单的报告

让我们在一个非常简单的 Maven 插件中编写一个非常简单的报告 Mojo :

  • 插件名称:简单插件
  • 插件的神器坐标:com.mycompany.maven:simple-maven-plugin:1.0-SNAPSHOT
  • 目标一:简单
  • 结果之一:simple-report.html

我们的 Maven 插件项目只有 2 个文件:

  • ./pom.xml
  • ./src/main/java/com/mycompany/maven/SimpleReport.java

以下示例可以作为模板复制和粘贴。

./pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompany.maven</groupId>
    <artifactId>simple-maven-plugin</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>maven-plugin</packaging>

    <name>Simple Plugin</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <doxiaVersion>1.10</doxiaVersion>
        <doxiaSitetoolsVersion>1.10</doxiaSitetoolsVersion>
    </properties>

    <dependencies>
        <!-- Doxia API and Doxia Sitetools -->
        <dependency>
            <groupId>org.apache.maven.doxia</groupId>
            <artifactId>doxia-sink-api</artifactId>
            <version>${doxiaVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.doxia</groupId>
            <artifactId>doxia-site-renderer</artifactId>
            <version>${doxiaSitetoolsVersion}</version>
        </dependency>

        <!-- reporting API -->
        <dependency>
            <groupId>org.apache.maven.reporting</groupId>
            <artifactId>maven-reporting-impl</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.reporting</groupId>
            <artifactId>maven-reporting-api</artifactId>
            <version>3.0</version>
        </dependency>

        <!-- plugin API and plugin-tools -->
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.5.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.shared</groupId>
            <artifactId>maven-shared-utils</artifactId>
            <version>3.2.0</version>
        </dependency>

    </dependencies>


    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
            </plugin>
            <plugin>
                <artifactId>maven-install-plugin</artifactId>
                <version>2.5.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <goalPrefix>simple</goalPrefix>
                </configuration>
                <executions>
                    <execution>
                        <id>default-descriptor</id>
                        <phase>process-classes</phase>
                    </execution>
                    <execution>
                        <id>generated-helpmojo</id>
                        <goals>
                            <goal>helpmojo</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

./src/main/java/com/mycompany/maven/SimpleReport.java

package com.mycompany.maven;

import java.util.Locale;

import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;

/**
 * Builds an simple report page as an example.
 *
 * <p>
 * This example show how easy it is to build your own reporting plugin
 * (or, for that matter, your own reporting Mojo)
 *
 */
@Mojo(
       name = "simple",
       defaultPhase = LifecyclePhase.SITE,
       requiresDependencyResolution = ResolutionScope.RUNTIME,
       requiresProject = true,
       threadSafe = true
     )
public class SimpleReport extends AbstractMavenReport {

    public String getOutputName() {
        // This report will generate simple-report.html when invoked in a project with `mvn site`
        return "simple-report";
    }

    public String getName(Locale locale) {
        // Name of the report when listed in the project-reports.html page of a project
        return "Simple Report";
    }

    public String getDescription(Locale locale) {
        // Description of the report when listed in the project-reports.html page of a project
        return "This simple report is a very simple report that does nothing but "
        + "shows off Maven's wonderful reporting capabilities.";
    }

    /**
     * Practical reference to the Maven project
     */
    @Parameter(defaultValue = "${project}", readonly = true)
    private MavenProject project;

    @Override
    protected void executeReport(Locale locale) throws MavenReportException {

        // Get the logger
        Log logger = getLog();

        // Some info
        logger.info("Generating " + getOutputName() + ".html"
                + " for " + project.getName() + " " + project.getVersion());

        // Get the Maven Doxia Sink, which will be used to generate the
        // various elements of the document
        Sink mainSink = getSink();
        if (mainSink == null) {
            throw new MavenReportException("Could not get the Doxia sink");
        }

        // Page title
        mainSink.head();
        mainSink.title();
        mainSink.text("Simple Report for " + project.getName() + " " + project.getVersion());
        mainSink.title_();
        mainSink.head_();

        mainSink.body();

        // Heading 1
        mainSink.section1();
        mainSink.sectionTitle1();
        mainSink.text("Simple Report for " + project.getName() + " " + project.getVersion());
        mainSink.sectionTitle1_();

        // Content
        mainSink.paragraph();
        mainSink.text("This page provides simple information, like its location: ");
        mainSink.text(project.getBasedir().getAbsolutePath());
        mainSink.paragraph_();

        // Close
        mainSink.section1_();
        mainSink.body_();

    }

}

构建简单的插件

通过在插件项目的根目录中执行以下命令来构建插件:

$ mvn install

该命令将:

  • 编译你的代码
  • 生成插件 JAR 工件 ( ./target/simple-maven-plugin-1.0-SNAPSHOT.jar)
  • 将工件复制到您的本地存储库,以便其他项目可以“使用”它(这是插件的目的,对吗?)。

为了确保一切顺利并正确声明,您现在可以在任何其他 Maven 项目目录中执行以下命令:

$ mvn com.mycompany.maven:simple-maven-plugin:1.0-SNAPSHOT:help

[INFO] --- simple-maven-plugin:1.0-SNAPSHOT:help (default-cli) @ hardware-connectors ---
[INFO] Simple Plugin 1.0-SNAPSHOT


This plugin has 2 goals:

simple:help
  Display help information on simple-maven-plugin.
  Call mvn simple:help -Ddetail=true -Dgoal=<goal-name> to display parameter
  details.

simple:simple
  Builds an simple report page as an example.
  This example show how easy it is to build your own reporting plugin (or, for
  that matter, your own reporting Mojo)


[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

调用简单插件

要在另一个 Maven 项目中调用我们插件的报告 Mojo,我们只需要在其<reporting>部分中声明插件,pom.xml如下例所示:

<project>
  ...
  <reporting>
    <plugins>
      <plugin>
        <groupId>com.mycompany.maven</groupId>
        <artifactId>simple-maven-plugin</artifactId>
        <version>1.0-SNAPSHOT</version>
      </plugin>
    </plugins>
  </reporting>
  ...
</项目>

注意:当没有指定特定的报告时,插件中所有声明为“报告”的Mojo都将被执行。有关配置报告的更多信息

更多信息

Doxia Sink API

在您的executeReport()方法中,您将利用Doxia Sink API向报告文档添加元素。

您将使用与Sink报告关联的对象:

Sink sink = getSink();

此对象允许您将新元素附加到报表文档(最初为空)。与某些 DOM 操作 API 不同,您不能在现有元素中插入元素或删除元素。

如果您具有 HTML 的基本知识,您附加到文档的元素看起来很熟悉。大多数元素都有开始和结束标记,例如sink.body()(开始)和sink.body_()(结束)。

  • sink.head()sink.head_()
  • sink.paragraph()sink.paragraph_()
  • sink.section1()sink.section1_()
  • sink.bold()sink.bold_()
  • 等等。

不要忘记关闭元素!

至少,一份文件应包括以下内容:

  • 标题和标题(sink.head()sink.title()
  • 身体 ( sink.body())
  • 第 1 节的标题 (sink.section1()sink.sectionTitle1())

Sink对象允许您使用rawText()方法添加原始文本。更准确地说,它允许您将原始 HTML 代码添加到文档中以获得完全的灵活性。但是,您应该限制此方法的使用,因为您可能会添加非 HTML 渲染器不支持的元素(如maven-pdf-site)。

Doxia Sink API 允许您为每个元素指定SinkEventAttributes,即 HTML 属性,特别是对象的类和 ID,这允许使用适当的 CSS(由指定的 Maven 皮肤或项目本身提供)轻松自定义)。

创建多个文档

您可能需要创建的不仅仅是一个 HTML 文件,而是其中的几个(如 Javadoc 为每个 Java 类生成一个 HTML 文件)。为此,您需要为需要生成的每个 HTML 文件获取一个新的接收器。这是通过使用您可以通过您的实例的方法SinkFactory轻松获得的对象来实现的,如下例所示。getSinkFactory()AbstractMavenReport

public class SimpleReport extends AbstractMavenReport {

  ...

  /**
   * Where the HTML pages of the report will be created.
   */
  @Parameter( defaultValue = "${project.reporting.outputDirectory}", property = "outputDirectory", required = true )
  private File outputDirectory;

  ...

  @Override
  protected void executeReport(Locale locale) throws MavenReportException {

    ...

    // Create a new sink
    String pageFilename = "other-report.html";
    Sink otherSink;
    try {
      otherSink = getSinkFactory().createSink(outputDirectory, pageFilename);
    } catch (IOException e) {
      throw new MavenReportException("Could not create sink for " + pageFilename + " in " + outputDirectory.getAbsolutePath(), e);
    }

    // Create the "other" report
    otherSink.head();
    otherSink.title();
    otherSink.text("The Other Report");
    ...

上面的示例将创建一个other-report.htmlHTML 文件以及simple-report.html.

注意:尽管您将创建额外的 HTML 文件,但$currentFileName传递给site.vmMaven 皮肤脚本的 Velocity 变量将保留原始报告的名称(即您的getOutputName()方法的结果)。有关速度变量的更多信息

资源

  1. 开发 Java 插件指南:起点,因为报告插件是插件...
  2. Maven Reporting API:当 Mojo 为站点提供报告时实现的报告 API。
  3. Maven 报告实现:报告 API 和插件 API 的基本实现。
  4. Doxia Sink API:生成内容的 API。