如何在 Spring Boot 產製專案的 API 文件並自動合併到 site 文件站台 | The Will Will Web

The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何在 Spring Boot 產製專案的 API 文件並自動合併到 site 文件站台

我前陣子分享過 如何讓 Spring Boot 與 Maven 專案成功產製文件站台 文章,當時由於 Spring Boot 預設的 maven-site-plugin v3.3 版本有問題,導致無法成功產生 site 文件站台,因此我們必須明確定義 maven-site-plugin版本定義才正常。這篇文章我打算分享如何在 site 文件站台上加入 Javadoc 產生的 API 文件,更加豐富我們專案的開發文件!

首先要提醒大家的地方是,JDK 11 與 JDK 8 所附的 javadoc 工具有些不太一樣,所以你要設定正確的 JAVA_HOMEPATH 才能讓團隊或 CI 的時候產生相同規格的文件檔案!

  1. 查詢 maven-javadoc-plugin 版本

    由於 Spring Boot 本身就包含了 Apache Maven Javadoc Plugin 外掛套件,但是非常的不明顯,必須透過以下命令取得完整的 POM 資訊,才能得知這件事:

    mvn help:effective-pom
    
    <plugin>
        <artifactId>maven-javadoc-plugin</artifactId>
        <version>3.2.0</version>
    </plugin>
    
  2. 記得設定 maven-site-plugin Plugin 到 pom.xmlbuild > plugins 設定中

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-site-plugin</artifactId>
        <version>3.9.1</version>
    </plugin>
    

    如果要更精細的定義 JavaDoc 的行為,可以參考以下設定值

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
        <version>3.3.0</version>
        <configuration>
            <defaultAuthor>Duotify Team</defaultAuthor>
            <fixTags>author,param,return,throws,link</fixTags>
            <level>private</level>
        </configuration>
    </plugin>
    

    我對於 javadoc:fix 文件上的 Optional Parameters 理解好久,最後才嘗試出來是向上面這樣,必須設定在 build > plugins 區段內,以及設定在 <configuration> 裡面才有效果!

  3. 加入 maven-javadoc-plugin Plugin 到 pom.xmlreporting > plugins 設定中

    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <show>private</show>
                </configuration>
                <reportSets>
                    <reportSet>
                        <id>default</id>
                        <reports>
                            <report>javadoc</report>
                            <!-- <report>test-javadoc</report> -->
                        </reports>
                    </reportSet>
                </reportSets>
            </plugin>
        </plugins>
    </reporting>
    

    因為我們有用 Lombok 來自動產生 Getter/Setter 方法,所以我們會需要連 private 成員也都產生文件!

預設 Spring Boot 無法產生報表的原因

我第一次在設定 maven-javadoc-plugin Plugin 的時候,覺得網路上找到的資料都很混亂,官網的範例也非常多,琳瑯滿目的,不知道要參考哪一個,其中最簡單的設定,其實是以下這個:

<reporting>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-javadoc-plugin</artifactId>
    </plugin>
  </plugins>
</reporting>

不過,使用 maven-javadoc-plugin 的預設值,有很大的機會將無法產生報告,並出現 Error generating maven-javadoc-plugin:3.2.0:test-aggregate-no-fork report 錯誤,詳細的錯誤訊息如下:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-site-plugin:3.9.1:site (default-site) on project demo1: Error generating maven-javadoc-plugin:3.2.0:test-aggregate-no-fork report:
[ERROR] Exit code: 1 - javadoc: error - No public or protected classes found to document.
[ERROR]
[ERROR] Command line was: cmd.exe /X /C ""C:\Program Files\AdoptOpenJDK\jdk-11.0.11.9-hotspot\bin\javadoc.exe" @options @packages"
[ERROR]
[ERROR] Refer to the generated Javadoc files in 'g:\Projects\demo1\target\site\testapidocs' dir.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

image

我第一次看到的時候,其實很難理解為什麼會出這個問題,而且後來有發現,使用 mvn javadoc:javadoc 是可以成功產生文件的,但是用 mvn site 就是不行,所以我沒辦法自動將 Javadoc 產製的 API 文件整合到 site 文件網站中。

如果你從錯誤訊息內容中抽絲剝繭,可以發現這個問題「可能」跟 test 有關係,因為他無法產生 Javadoc 檔案到 target\site\testapidocs 目錄中。如果再搭配著看 No public or protected classes found to document 這段,組合在一起才是有意義的。原來是因為在我們的測試程式中,找不到任何一個公開(public)的或受保護(protected)的類別(class),因此無法產生任何一份測試類別的 Javadoc 文件。

所以解決方法有兩種:

  1. 設定 <reportSets> 並僅設定針對 javadoc 報表進行輸出

    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <reportSets>
                    <reportSet>
                        <reports>
                            <report>javadoc</report>
                            <!-- <report>test-javadoc</report> -->
                        </reports>
                    </reportSet>
                </reportSets>
            </plugin>
        </plugins>
    </reporting>
    
  2. 調整 maven-javadoc-pluginshow 參數設定

    這裡的 package 所代表的,就是同一個 package 內的類別都可以存取的範圍,在 Java Access Modifiers 文件中,被定義為 Default 層級。只要你切換為 package 就可以正確輸出測試程式的 API 文件。

    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <configuration>
                  <show>package</show>
                </configuration>
            </plugin>
        </plugins>
    </reporting>
    

    上述 <show>package</show> 預設為 protected,代表可以產生所有 publicprotected 的類別與成員。如果你修改成 public 的話,就會僅產生 public 公開的類別與成員。設定成 private 的話,意味著能產生所有存取等級(access level)的類別與成員。我上述的例子是用 package,這意味著只要類別沒有明確定義private 的話,就會也會產生 API 文件。

後記

Java 世界的 Javadoc 工具比我想像的還強大許多,不但功能相當完整,第三方的整合工具也相當全面,像是 Spring Boot 跟 Maven 就與 Javadoc 整合的相當完美。不過相對的,當遇到問題的時候,解決問題的複雜度自然也會高出一些,而且網路上的資訊相當亂,比較難有完整且全面的文件可以帶領初學者上手。

相關連結