1. 程式人生 > >通過swagger2markup+asciidoctorj生成html和pdf文件並解決asciidoctorj生成的pdf檔案中文顯示不全問題(maven方式及java程式碼方式)

通過swagger2markup+asciidoctorj生成html和pdf文件並解決asciidoctorj生成的pdf檔案中文顯示不全問題(maven方式及java程式碼方式)

通過swagger2markup+asciidoctorj生成html和pdf文件(maven方式及java程式碼方式)

任務:通過同事的json檔案生成相應的html和pdf文件

前言

    開始時swagger2markup和asciidoctorj是什麼都不知道,只能百度,看官方文件(翻譯。。。),
遇到問題就一頭霧水,完全不知道哪裡出了問題,要怎麼決解,百度上資料(中文?)也是寥寥無幾,maven
也是沒有系統學習過,導致很多小問題到了自己這裡變成了大麻煩。在經歷了一個星期的摸索,終於小有所成,
在此寫下自己嘔心瀝血的過程,以免日後自己忘了,也給其他同僚多一份可以參考的資料。

如果有寫的不好的地方,還望指出。

以下是我經歷一個星期的各種碰撞過程
- 使用maven外掛方法生成html和pdf檔案(json檔案生成adoc檔案,adoc檔案再生成html和pdf檔案)
- 使用java程式碼方式生成adoc檔案
- 使用java程式碼方式呼叫cmd執行mvn test命令生成html和pdf檔案
出現問題:生成的pdf中文顯示不全
解決:
- 使用asciidoctorj工具(單獨)在cmd裡生成pdf檔案
- 使用java程式碼方式直接生成pdf檔案(需adoc檔案)

目錄

生成html和pdf文件

1、使用maven外掛方法生成html和pdf檔案 (json檔案生成adoc檔案, adoc檔案再生成html和pdf檔案)

參考文件

這裡寫圖片描述

  • 匯入eclipse後發現只有幾個可用
    這裡寫圖片描述
    • 可以看到pom.xml檔案內有如下配置檔案
<!-- 一些引數 -->
<properties>
    <java.version>1.8</java.version>
    <swagger2markup.version>1.2.0</swagger2markup.version>
    <asciidoctor.input.directory>${project.basedir}/src/docs/asciidoc</asciidoctor.input.directory
>
<swagger.output.dir>${project.build.directory}/swagger</swagger.output.dir> <swagger.snippetOutput.dir>${project.build.directory}/asciidoc/snippets</swagger.snippetOutput.dir> <generated.asciidoc.directory>${project.build.directory}/asciidoc/generated</generated.asciidoc.directory> <asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory> <asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory> <swagger.input>${swagger.output.dir}/swagger.json</swagger.input> </properties> <!-- 首先是兩個遠端倉庫 --> <pluginRepositories> <pluginRepository> <id>jcenter-snapshots</id> <name>jcenter</name> <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url> </pluginRepository> <pluginRepository> <id>jcenter-releases</id> <name>jcenter</name> <url>http://jcenter.bintray.com</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> <repositories> <repository> <id>jcentral</id> <name>bintray</name> <url>http://jcenter.bintray.com</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>jcenter-snapshots</id> <name>jcenter</name> <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url> </repository> </repositories> <!-- 以下用於生成adoc檔案的配置 --> <plugin> <groupId>io.github.swagger2markup</groupId> <artifactId>swagger2markup-maven-plugin</artifactId> <version>${swagger2markup.version}</version> <dependencies> <dependency> <groupId>io.github.swagger2markup</groupId> <artifactId>swagger2markup-import-files-ext</artifactId> <version>${swagger2markup.version}</version> </dependency> <dependency> <groupId>io.github.swagger2markup</groupId> <artifactId>swagger2markup-spring-restdocs-ext</artifactId> <version>${swagger2markup.version}</version> </dependency> </dependencies> <configuration> <swaggerInput>${swagger.input}</swaggerInput> <outputDir>${generated.asciidoc.directory}</outputDir> <config> <swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage> <swagger2markup.pathsGroupedBy>TAGS</swagger2markup.pathsGroupedBy> <swagger2markup.extensions.dynamicOverview.contentPath>${project.basedir}/src/docs/asciidoc/extensions/overview</swagger2markup.extensions.dynamicOverview.contentPath> <swagger2markup.extensions.dynamicDefinitions.contentPath>${project.basedir}/src/docs/asciidoc/extensions/definitions</swagger2markup.extensions.dynamicDefinitions.contentPath> <swagger2markup.extensions.dynamicPaths.contentPath>${project.basedir}/src/docs/asciidoc/extensions/paths</swagger2markup.extensions.dynamicPaths.contentPath> <swagger2markup.extensions.dynamicSecurity.contentPath>${project.basedir}src/docs/asciidoc/extensions/security/</swagger2markup.extensions.dynamicSecurity.contentPath> <swagger2markup.extensions.springRestDocs.snippetBaseUri>${swagger.snippetOutput.dir}</swagger2markup.extensions.springRestDocs.snippetBaseUri> <swagger2markup.extensions.springRestDocs.defaultSnippets>true</swagger2markup.extensions.springRestDocs.defaultSnippets> </config> </configuration> <executions> <execution> <phase>test</phase> <goals> <goal>convertSwagger2markup</goal> </goals> </execution> </executions> </plugin> <!-- 以下配置用於生成html和pdf --> <plugin> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <version>1.5.3</version> <dependencies> <dependency> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctorj-pdf</artifactId> <version>1.5.0-alpha.10.1</version> </dependency> <dependency> <groupId>org.jruby</groupId> <artifactId>jruby-complete</artifactId> <version>1.7.21</version> </dependency> </dependencies> <configuration> <sourceDirectory>${asciidoctor.input.directory}</sourceDirectory> <sourceDocumentName>index.adoc</sourceDocumentName> <attributes> <doctype>book</doctype> <toc>left</toc> <toclevels>3</toclevels> <numbered></numbered> <hardbreaks></hardbreaks> <sectlinks></sectlinks> <sectanchors></sectanchors> <generated>${generated.asciidoc.directory}</generated> </attributes> </configuration> <executions> <execution> <id>output-html</id> <phase>test</phase> <goals> <goal>process-asciidoc</goal> </goals> <configuration> <backend>html5</backend> <outputDirectory>${asciidoctor.html.output.directory}</outputDirectory> </configuration> </execution> <execution> <id>output-pdf</id> <phase>test</phase> <goals> <goal>process-asciidoc</goal> </goals> <configuration> <backend>pdf</backend> <outputDirectory>${asciidoctor.pdf.output.directory}</outputDirectory> </configuration> </execution> </executions> </plugin>
  • 將以上配置放入pom.xml後替換你的json檔案到
    ${project.build.directory}1/swagger/swagger.json
  • 執行maven test後將在
    ${project.build.directory}/asciidoc/html

    ${project.build.directory}/asciidoc/pdf
    目錄下分別生成html和pdf檔案

可能出現的異常

1.[ERROR] Failed to execute goal io.github.swagger2markup:swagger2markup-maven-plugin:1.2.0:convertSwagger2markup (default) on project csdnTest: Execution default of goal io.github.swagger2markup:swagger2markup-maven-plugin:1.2.0:convertSwagger2markup failed: Unable to load the mojo 'convertSwagger2markup' in the plugin 'io.github.swagger2markup:swagger2markup-maven-plugin:1.2.0' due to an API incompatibility: org.codehaus.plexus.component.repository.exception.ComponentLookupException: io/github/swagger2markup/Swagger2MarkupMojo : Unsupported major.minor version 52.0
<!-- 請使用JDK 1.8版本 -->

附圖

1.新建一個maven專案
這裡寫圖片描述
2.更改或新增至如下
這裡寫圖片描述
pom.xml內容上面已經給出,你可能需要自己新增以下等配置

<build>
<plugins>
</plugins>
</build>

index.adoc檔案內容為

include::{generated}/overview.adoc[]
include::{generated}/paths.adoc[]
include::{generated}/security.adoc[]
include::{generated}/definitions.adoc[]

3.執行以下操作後等程式執行完再重新整理一下就能看到生成的文件了
這裡寫圖片描述
這裡寫圖片描述

2、使用java程式碼方式生成adoc檔案

使用程式碼的方式相對較為靈活,下面上程式碼

import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;

import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.builder.fluent.Configurations;


public class Swagger2Markup {

    //指定adoc檔案生成路徑
    public Path outputDirectory = Paths.get("target/asciidoc/generated");

    //通過配置檔案生成swagger2markup的引數
    public Swagger2MarkupConfig config;

    public Swagger2Markup(String Json) throws Exception{
        //讀取配置檔案
        Configuration configuration = new Configurations().properties("config.properties");
        config = new Swagger2MarkupConfigBuilder(configuration).build();
        if(Json.startsWith("http")){
            //獲取遠端json資料
            createAdocFile(new URL(Json));
        }else{
            //獲取本地json資料
            createAdocFile(Paths.get(Json));
        }
    }
    /**
     * 通過url生成adoc檔案
     */
    public void createAdocFile(URL remoteSwaggerFile){
        Swagger2MarkupConverter.from(remoteSwaggerFile)
                                .withConfig(config)
                                .build()
                                .toFolder(outputDirectory);
    }
    /**
     * 通過json檔案生成adoc檔案
     */
    public void createAdocFile(Path localSwaggerFile){
        Swagger2MarkupConverter.from(localSwaggerFile)
                                .withConfig(config)
                                .build()
                                .toFolder(outputDirectory);
    }
    public static void main(String[] args) throws Exception{
        //指定本地json檔案路徑
        new Swagger2Markup("target/swagger/swagger.json");
        //指定遠端json檔案路徑
    //  new Swagger2Markup("http://petstore.swagger.io/v2/swagger.json");

    }
}

config.properties檔案內容如下

swagger2markup.markupLanguage = ASCIIDOC
swagger2markup.outputLanguage = EN

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>swaggerTest</groupId>
    <artifactId>swaggerTest</artifactId>
    <version>1.0</version>

    <repositories>
        <repository>
            <id>jcentral</id>
            <name>bintray</name>
            <url>http://jcenter.bintray.com</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>jcenter-snapshots</id>
            <name>jcenter</name>
            <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>io.github.swagger2markup</groupId>
            <artifactId>swagger2markup</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>
</project>

執行main方法後將會在target/asciidoc/generated/下生成4個adoc檔案

附圖

這裡寫圖片描述

3、使用程式碼方式呼叫cmd執行mvn test命令生成html和pdf檔案

在用程式碼方式生成adoc檔案之後就想著能不能再用程式碼的方式省略掉手工步驟,結果苦尋無門,最後想出了最笨的方法算是實現了。。。

結構圖

這裡寫圖片描述

檔案內容

Swagger2Markup檔案內容

package com.swaggerTest.base;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.file.Paths;


public class Swagger2Markup {

    public Swagger2Markup() throws Exception{
        createHtmlFile();
    }
    /**
     * 建立html和pdf檔案
     * @throws Exception
     */
    public void createHtmlFile() throws Exception{
        //獲取pom.xml的絕對路徑
        String path = returnPath("pom.xml");

        //生成bat檔案的內容
        StringBuilder batFileContent = new StringBuilder(path.substring(0, 2)).append("\r\n");
        batFileContent.append("cd ").append(path.substring(0,path.length()-7)).append("\r\n");
        batFileContent.append("mvn test");

        //寫入到bat檔案
        writeInBatFile("src/cmd/bat.bat",batFileContent.toString().replace("/", "\\"));

        //生成vbs檔案內容
        StringBuilder vbsFileContent = new StringBuilder("Set ws = CreateObject(\"Wscript.Shell\")").append("\r\n");
        vbsFileContent.append("ws.run \"cmd /c ").append(returnPath("src/cmd/bat.bat").replace("/", "\\")).append("\",vbhide");

        //寫入vbs檔案
        writeInBatFile("src/cmd/vbs.vbs",vbsFileContent.toString());

        //生成執行vbs檔案命令(用vbs隱藏bat檔案執行時的視窗)
        StringBuilder cmd = new StringBuilder("cmd /c CScript ").append(returnPath("src/cmd/vbs.vbs"));

        System.out.println(cmd.toString());

        Process process = Runtime.getRuntime().exec(cmd.toString());

        System.out.println(process.waitFor());
    }
    /**
     * 生成檔案
     * @param content
     */
    public void writeInBatFile(String fileName,String content){
        File batFile = new File(returnPath(fileName));
        //如果檔案存在,則刪除
        if(batFile != null && batFile.exists()){
            batFile.delete();
        }
        try {
            //建立gbk格式的檔案(utf-8中文在cmd裡亂碼)
            OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(batFile),"GBK");
            BufferedWriter bw = new BufferedWriter(out);
            bw.write(content);
            bw.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 獲取指定檔案路徑
     * @param filePath
     * @return
     */
    public String returnPath(String filePath){
        return Paths.get(filePath).toAbsolutePath().toString();
    }
    public static void main(String[] args) throws Exception{
        new Swagger2Markup();
    }
}

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>swaggerTest</groupId>
    <artifactId>swaggerTest</artifactId>
    <version>1.0</version>


    <properties>
        <asciidoctor.input.directory>${project.basedir}/src/docs/asciidoc</asciidoctor.input.directory>
        <generated.asciidoc.directory>${project.build.directory}/asciidoc/generated</generated.asciidoc.directory>
        <asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
        <asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
    </properties>


    <repositories>
        <repository>
            <id>jcentral</id>
            <name>bintray</name>
            <url>http://jcenter.bintray.com</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>jcenter-snapshots</id>
            <name>jcenter</name>
            <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.asciidoctor</groupId>
                <artifactId>asciidoctor-maven-plugin</artifactId>
                <version>1.5.3</version>
                <dependencies>
                    <dependency>
                        <groupId>org.asciidoctor</groupId>
                        <artifactId>asciidoctorj-pdf</artifactId>
                        <version>1.5.0-alpha.10.1</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jruby</groupId>
                        <artifactId>jruby-complete</artifactId>
                        <version>1.7.21</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <sourceDirectory>${asciidoctor.input.directory}</sourceDirectory>
                    <sourceDocumentName>index.adoc</sourceDocumentName>
                    <attributes>
                        <doctype>book</doctype>
                        <toc>left</toc>
                        <toclevels>3</toclevels>
                        <numbered></numbered>
                        <hardbreaks></hardbreaks>
                        <sectlinks></sectlinks>
                        <sectanchors></sectanchors>
                        <generated>${generated.asciidoc.directory}</generated>
                    </attributes>
                </configuration>
                <executions>
                    <execution>
                        <id>output-html</id>
                        <phase>test</phase>
                        <goals>
                            <goal>process-asciidoc</goal>
                        </goals>
                        <configuration>
                            <backend>html5</backend>
                            <outputDirectory>${asciidoctor.html.output.directory}</outputDirectory>
                        </configuration>
                    </execution>

                    <execution>
                        <id>output-pdf</id>
                        <phase>test</phase>
                        <goals>
                            <goal>process-asciidoc</goal>
                        </goals>
                        <configuration>
                            <backend>pdf</backend>
                            <outputDirectory>${asciidoctor.pdf.output.directory}</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

index.adoc檔案內容不變

include::{generated}/overview.adoc[]
include::{generated}/paths.adoc[]
include::{generated}/security.adoc[]
include::{generated}/definitions.adoc[]

asciidoc/generated/下的四個檔案是上一節生成的。

執行main方法後重新整理一下(生成pdf時間比較久)
這裡寫圖片描述

解決上面生成的pdf檔案中文顯示不全問題

1、使用asciidoctorj工具(單獨)在cmd裡生成pdf檔案

首先需要安裝一個 Chocolatey (不想安裝的可以跳過看下一個節點)
使用cmd.ext進行安裝,執行一下命令

@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
C:\> choco install asciidoctorj
C:\> where asciidoctorj
C:\ProgramData\chocolatey\bin\asciidoctorj.exe   進入asciidoctorj目錄
C:\> asciidoctorj -b pdf index.adoc 生成pdf檔案

在C:\ProgramData\chocolatey\lib\asciidoctorj\tools\asciidoctorj-1.5.6\lib目錄下有一個asciidoctorj-pdf-1.5.0-alpha.16.jar檔案

這裡寫圖片描述

將gems\asciidoctor-pdf-1.5.0.alpha.16\data下的fonts資料夾和gems\asciidoctor-pdf-1.5.0.alpha.16\data\themes下的default-theme.yml檔案複製到本地

這裡寫圖片描述
這裡寫圖片描述
替換fonts裡的四個檔案(正常字型,斜體,粗體,粗斜體)或者修改theme.yml(default-theme.yml)檔案指向的字型
這裡寫圖片描述
這裡寫圖片描述

替換好後在cmd上執行命令 :
asciidoctorj -a pdf-style=d:\pdfTest\theme.yml -a pdf-fontsdir=d:\pdfTest\fonts -b pdf d:\pdfTest\index.adoc
將會在當前目錄下生成pdf檔案
這裡寫圖片描述

2、使用java程式碼方式直接生成pdf檔案(需adoc檔案)

在用cmd執行的時候出現錯誤,發現其呼叫的是class檔案,然後想著手動去呼叫他的main方法。
這裡寫圖片描述

pom.xml檔案需要新增依賴

    <dependencies>
        <dependency>
            <groupId>org.asciidoctor</groupId>
            <artifactId>asciidoctorj-pdf</artifactId>
            <version>1.5.0-alpha.10.1</version>
        </dependency> 
    </dependencies>

程式碼部分,重點是最後一行就可以了


//樣式
String style = "pdf-style=d:\\pdfTest\\theme.yml";
//字型
String fontsdir = "pdf-fontsdir=d:\\pdfTest\\fonts";
//需要指定adoc檔案位置
String adocPath = "d:\\pdfTest\\index.adoc";
org.asciidoctor.cli.AsciidoctorInvoker.main(new String[]{"-a",style,"-a",fontsdir,"-b","pdf",adocPath});
  1. ${project.build.directory}是maven生成的檔案的根目錄:target的絕對路徑