Gradle環(huán)境下導(dǎo)出Swagger為PDF的步驟詳解
說明
我個人是一直使用Swagger作為接口文檔的說明的。但是由于在一些情況下,接口文檔說明需要以文件的形式交付出去,如果再重新寫一份文檔難免有些麻煩。于是在網(wǎng)上看到了Swagger2Markup + asciidoctor導(dǎo)出PDF的方法,百度一番后感覺網(wǎng)上的文章還是有很多沒有描述清楚的地方,遂還是硬著頭皮把官方的英文文檔大致瀏覽了一下,按照自己的思路整理出具體的步驟。
本文用到的工具:
- Gradle - 4.10.3
- SpringBoot - 2.1.6.RELEASE
- Swagger - 2.9.2
- Swagger2Markup - 1.3.3
- asciidoctor
- spring-restdocs-mockmvc
準(zhǔn)備Swagger數(shù)據(jù)
SpringBoot中使用Swagger的過程就不再贅述了,下面是本文使用的范例:
@Configuration @EnableSwagger2 class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.jptangchina.gradle.controller")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Swagger2Markup Test Api") .version("1.0") .build(); } }
@RestController @RequestMapping("/user") @Api(tags = "用戶接口") public class UserController { @ApiOperation("用戶登錄") @ResponseBody @PostMapping("/login") public Result<Void> login( @ApiParam(value = "用戶名", example = "jptangchina", required = true) @RequestParam String username, @ApiParam(value = "密碼", example = "jptangchina", required = true) @RequestParam String password) { return Result.ok(); } }
使用org.asciidoctor.convert生成PDF(個人不推薦使用)
官方教程地址:https://github.com/Swagger2Markup/spring-swagger2markup-demo
僅為了簡單的導(dǎo)出PDF而言,本文針對官方案例均有所改動,去掉了部分沒有用到的配置。
1. 獲取Swagger json文件
Swagger頁面本質(zhì)上也就是對json文件進(jìn)行解析。這里需要先編寫單元測試訪問/v2/api-docs接口并將json文件保存到本地。
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc class SwaggerTest { @Autowired private MockMvc mockMvc; @Test public void generateAsciiDocsToFile() throws Exception { String outputDir = System.getProperty("io.springfox.staticdocs.outputDir"); MvcResult mvcResult = this.mockMvc.perform(get("/v2/api-docs") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andReturn(); MockHttpServletResponse response = mvcResult.getResponse(); String swaggerJson = response.getContentAsString(); Files.createDirectories(Paths.get(outputDir)); try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputDir, "swagger.json"), StandardCharsets.UTF_8)){ writer.write(swaggerJson); } } }
System.getProperty("io.springfox.staticdocs.outputDir");來自于build.gradle中的配置
2. 將json文件轉(zhuǎn)換為adoc文件
轉(zhuǎn)換json文件需要使用到io.github.swagger2markup插件的convertSwagger2markup方法。
引入相關(guān)依賴:
buildscript { ... dependencies { ... classpath 'io.github.swagger2markup:swagger2markup-gradle-plugin:1.3.3' } } apply plugin: 'io.github.swagger2markup'
配置convertSwagger2markup:
ext { asciiDocOutputDir = file("${buildDir}/asciidoc") swaggerOutputDir = file("${buildDir}/swagger") } test { systemProperty 'io.springfox.staticdocs.outputDir', swaggerOutputDir } convertSwagger2markup { dependsOn test swaggerInput "${swaggerOutputDir}/swagger.json" outputDir asciiDocOutputDir config = [ 'swagger2markup.pathsGroupedBy' : 'TAGS', ] }
更多config配置可以參考:http://swagger2markup.github.io/swagger2markup/1.3.3/#_swagger2markup_properties
3. 將adoc文件轉(zhuǎn)換為PDF文件
轉(zhuǎn)換PDF文件需要用到org.asciidoctor.convert插件的asciidoctor方法。
引入相關(guān)依賴:
buildscript { ... dependencies { ... classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.3' } } apply plugin: 'org.asciidoctor.convert'
手動編寫index.adoc文件,放置到${asciiDocOutputDir.absolutePath}中:
include::{generated}/overview.adoc[] include::{generated}/paths.adoc[] include::{generated}/definitions.adoc[] include::{generated}/security.adoc[]
{generated}默認(rèn)值為${build}/asciidoc,參見:https://github.com/Swagger2Markup/swagger2markup-gradle-project-template
配置asciidoctor:
asciidoctor { dependsOn convertSwagger2markup // sourceDir中需要包含有之前手動編寫的index.adoc文件 sourceDir(asciiDocOutputDir.absolutePath) sources { include "index.adoc" } backends = ['pdf'] attributes = [ doctype: 'book', toc: 'left', toclevels: '3', numbered: '', sectlinks: '', sectanchors: '', hardbreaks: '', generated: asciiDocOutputDir ] }
4. 編寫一個自定義task用來執(zhí)行上述流程:
task genPdf(type: Test, dependsOn: test) { include '**/*SwaggerTest.class' exclude '**/*' dependsOn(asciidoctor) }
執(zhí)行g(shù)enPdf,就可以生成Swagger對應(yīng)的PDF文件。
5. 小結(jié)
使用此方法步驟還是比較繁瑣的,總體來講就是json -> adoc -> pdf,并且使用此種方法目前有幾個比較大的問題我仍然沒有找到解決方案:
- 從官方文檔中可以看到支持的語言默認(rèn)有EN, DE, FR, RU。沒錯,不支持CN,從導(dǎo)出的文檔也可以看到,部分中文無法顯示,目前我也尚未找到是否有配置可以實現(xiàn)這個功能。網(wǎng)上的文章部分是通過替換源代碼包里面的字體文件來實現(xiàn),但是由于后面有更好的解決方案,這里就不再討論。
- 從asciidoctorj-pdf的1.5.0-alpha.16版本以后(目前最新是1.5.0-alpha.18),這種方式生成文件會拋出異常,我個人并沒有深究這個異常,有興趣的讀者可以通過修改版本號試一試。
- 生成的adoc文件一般包含overview.adoc、paths.adoc、definitions.adoc、security.adoc一共4個文件,這也是為什么要手動編寫index.adoc進(jìn)行整合的原因,感覺不太方便。
綜上,我個人并不推薦采用此方式生成PDF。
build.gradle完整文件參考:
buildscript { ext { springbootVersion = '2.1.6.RELEASE' } repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } dependencies { classpath "org.springframework.boot:spring-boot-gradle-plugin:${springbootVersion}" classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.3' classpath 'io.github.swagger2markup:swagger2markup-gradle-plugin:1.3.3' } } repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } apply plugin: 'java' apply plugin: 'maven' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' apply plugin: 'io.github.swagger2markup' apply plugin: 'org.asciidoctor.convert' group 'com.jptangchina' version '1.0-SNAPSHOT' sourceCompatibility = 1.8 targetCompatibility = 1.8 ext { asciiDocOutputDir = file("${buildDir}/asciidoc") swaggerOutputDir = file("${buildDir}/swagger") swaggerVersion = '2.9.2' } dependencies { compile 'org.springframework.boot:spring-boot-starter-web' compile "io.springfox:springfox-swagger2:${swaggerVersion}" compile "io.springfox:springfox-swagger-ui:${swaggerVersion}" compile 'io.github.swagger2markup:swagger2markup:1.3.3' asciidoctor 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.16' testCompile 'org.springframework.boot:spring-boot-starter-test' testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc' } test { systemProperty 'io.springfox.staticdocs.outputDir', swaggerOutputDir } convertSwagger2markup { dependsOn test swaggerInput "${swaggerOutputDir}/swagger.json" outputDir asciiDocOutputDir config = [ 'swagger2markup.pathsGroupedBy' : 'TAGS', ] } asciidoctor { dependsOn convertSwagger2markup sourceDir(asciiDocOutputDir.absolutePath) sources { include "index.adoc" } backends = ['pdf'] attributes = [ doctype: 'book', toc: 'left', toclevels: '3', numbered: '', sectlinks: '', sectanchors: '', hardbreaks: '', generated: asciiDocOutputDir ] } task genPdf(type: Test, dependsOn: test) { include '**/*SwaggerTest.class' exclude '**/*' dependsOn(asciidoctor) }
使用asciidoctor-gradle-plugin生成PDF(推薦)
asciidoctor-gradle-plugin也是官方推薦的使用方式。相對前面的方式,使用起來更加簡單,也可以修改配置輸出中文。
1. 引入插件
plugins { id 'org.asciidoctor.jvm.pdf' version '2.2.0' }
2. 編寫測試類生成adoc
與第一中方法不同的是,不需要再將json文件保存到本地了。
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class SwaggerTest { @Autowired private MockMvc mockMvc; @Test public void generateAsciiDocsToFile() throws Exception { String outputDir = System.getProperty("io.springfox.staticdocs.outputDir"); MvcResult mvcResult = this.mockMvc.perform(get("/v2/api-docs") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andReturn(); Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder() .withMarkupLanguage(MarkupLanguage.ASCIIDOC) .withOutputLanguage(Language.ZH) .withPathsGroupedBy(GroupBy.TAGS) .withGeneratedExamples() .withoutInlineSchema() .build(); MockHttpServletResponse response = mvcResult.getResponse(); String swaggerJson = response.getContentAsString(); Swagger2MarkupConverter.from(swaggerJson) .withConfig(config) .build() .toFile(Paths.get(outputDir + "/swagger")); } }
有興趣的讀者可以閱讀下toFile方法的源碼,里面對第一種方法生成的4個文件進(jìn)行了整合,這也是不再需要手動編寫index.adoc文件的原因。
3. 配置asciidoctorPdf
ext { asciiDocOutputDir = file("${buildDir}/asciidoc") // 創(chuàng)建字體與主題的文件夾 pdfFontsDir = file("${buildDir}/fonts") pdfThemesDir = file("${buildDir}/themes") swaggerVersion = '2.9.2' } pdfThemes { local 'basic', { styleDir = pdfThemesDir // styleName會被程序用于匹配${styleName}-theme.yml,如default-styleName-theme.yml styleName = 'default' } } asciidoctorPdf{ sourceDir(asciiDocOutputDir.absolutePath) sources { include "swagger.adoc" } fontsDir(pdfFontsDir.absolutePath) theme("basic") }
本文字體與主題文件均來自于asciidoctorj-pdf-1.5.0-alpha.18.jar源碼包,其路徑位于:gems/asciidoctorj-pdf-1.5.0-alpha.18/data
4. 復(fù)制并修改default-theme.yml文件配置
為了解決中文無法顯示的問題,首先需要自行下載一個支持中文的字體文件。
修改主題文件,將mplus1p-regular-fallback.ttf替換為自己下載的字體文件的名稱。
M+ 1p Fallback: normal: your-font.ttf bold: your-font.ttf italic: your-font.ttf bold_italic: your-font.ttf
由于手動指定了字體文件的路徑,所以除了中文以外,還需要將源碼中的其他字體文件一并復(fù)制到${pdfFontsDir}文件夾。如果不愿意使用官方的字體,也可以考慮將default-theme.yml中其他的字體文件都修改為自己想要的文件。
保持task genPdf不變,再次運行即可生成PDF文件,生成的文件默認(rèn)路徑為${build}/docs/asciidocPdf
小結(jié)
asciidoctor-gradle-plugin的方式可以支持配置字體與主題,通過配置不僅規(guī)避了中文無法顯示的問題,同時使用起來也更加簡單。需要注意的是,采用此種方案生成出的文檔會在封面寫有項目的版本號,此版本號為build.gradle中的version,而非SwaggerConfig類中的version。
官方提供了很多配置,可以自行參考官方文檔查看。
build.gradle完整文件參考:
buildscript { ext { springbootVersion = '2.1.6.RELEASE' } repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } dependencies { classpath "org.springframework.boot:spring-boot-gradle-plugin:${springbootVersion}" } } plugins { id 'org.asciidoctor.jvm.pdf' version '2.2.0' } repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } apply plugin: 'java' apply plugin: 'maven' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group 'com.jptangchina' version '1.0-SNAPSHOT' sourceCompatibility = 1.8 targetCompatibility = 1.8 ext { asciiDocOutputDir = file("${buildDir}/asciidoc") pdfFontsDir = file("${buildDir}/fonts") pdfThemesDir = file("${buildDir}/themes") swaggerVersion = '2.9.2' } dependencies { compile 'org.springframework.boot:spring-boot-starter-web' compile "io.springfox:springfox-swagger2:${swaggerVersion}" compile "io.springfox:springfox-swagger-ui:${swaggerVersion}" compile 'io.github.swagger2markup:swagger2markup:1.3.3' testCompile 'org.springframework.boot:spring-boot-starter-test' testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc' } test { systemProperty 'io.springfox.staticdocs.outputDir', asciiDocOutputDir } pdfThemes { local 'basic', { styleDir = pdfThemesDir styleName = 'default' } } asciidoctorPdf{ sourceDir(asciiDocOutputDir.absolutePath) sources { include "swagger.adoc" } fontsDir(pdfFontsDir.absolutePath) theme("basic") } task genPdf(type: Test, dependsOn: test) { include '**/*SwaggerTest.class' exclude '**/*' dependsOn(asciidoctorPdf) }
參考
- https://github.com/Swagger2Markup/swagger2markup
- https://github.com/Swagger2Markup/spring-swagger2markup-demo
- http://swagger2markup.github.io/swagger2markup/1.3.3
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。
相關(guān)文章
Java 實戰(zhàn)項目之誠途旅游系統(tǒng)的實現(xiàn)流程
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SpringBoot+Vue+maven+Mysql實現(xiàn)一個精美的物流管理系統(tǒng),大家可以在過程中查缺補漏,提升水平2021-11-11Java實現(xiàn)FTP文件的上傳和下載功能的實例代碼
FTP 是File Transfer Protocol(文件傳輸協(xié)議)的英文簡稱,而中文簡稱為“文傳協(xié)議”。接下來通過本文給大家實例講解Java實現(xiàn)FTP文件的上傳和下載功能,需要的的朋友一起看看吧2016-11-11IDEA MyBatis Plugins自動生成實體類和mapper.xml
這篇文章主要介紹了IDEA MyBatis Plugins自動生成實體類和mapper.xml,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07SpringBoot如何配置數(shù)據(jù)庫主從shardingsphere
這篇文章主要介紹了SpringBoot如何配置數(shù)據(jù)庫主從shardingsphere問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04詳解如何使用Jersey客戶端請求Spring Boot(RESTFul)服務(wù)
本篇文章主要介紹了詳解如何使用Jersey客戶端請求Spring Boot(RESTFul)服務(wù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01