Gradle環(huán)境下導(dǎo)出Swagger為PDF的步驟詳解
說(shuō)明
我個(gè)人是一直使用Swagger作為接口文檔的說(shuō)明的。但是由于在一些情況下,接口文檔說(shuō)明需要以文件的形式交付出去,如果再重新寫(xiě)一份文檔難免有些麻煩。于是在網(wǎng)上看到了Swagger2Markup + asciidoctor導(dǎo)出PDF的方法,百度一番后感覺(jué)網(wǎng)上的文章還是有很多沒(méi)有描述清楚的地方,遂還是硬著頭皮把官方的英文文檔大致瀏覽了一下,按照自己的思路整理出具體的步驟。
本文用到的工具:
- 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的過(guò)程就不再贅述了,下面是本文使用的范例:
@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(個(gè)人不推薦使用)
官方教程地址:https://github.com/Swagger2Markup/spring-swagger2markup-demo
僅為了簡(jiǎn)單的導(dǎo)出PDF而言,本文針對(duì)官方案例均有所改動(dòng),去掉了部分沒(méi)有用到的配置。
1. 獲取Swagger json文件
Swagger頁(yè)面本質(zhì)上也就是對(duì)json文件進(jìn)行解析。這里需要先編寫(xiě)單元測(cè)試訪問(wè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");來(lái)自于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'
手動(dòng)編寫(xiě)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,參見(jiàn):https://github.com/Swagger2Markup/swagger2markup-gradle-project-template
配置asciidoctor:
asciidoctor {
dependsOn convertSwagger2markup
// sourceDir中需要包含有之前手動(dòng)編寫(xiě)的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. 編寫(xiě)一個(gè)自定義task用來(lái)執(zhí)行上述流程:
task genPdf(type: Test, dependsOn: test) {
include '**/*SwaggerTest.class'
exclude '**/*'
dependsOn(asciidoctor)
}
執(zhí)行g(shù)enPdf,就可以生成Swagger對(duì)應(yīng)的PDF文件。
5. 小結(jié)
使用此方法步驟還是比較繁瑣的,總體來(lái)講就是json -> adoc -> pdf,并且使用此種方法目前有幾個(gè)比較大的問(wèn)題我仍然沒(méi)有找到解決方案:
- 從官方文檔中可以看到支持的語(yǔ)言默認(rèn)有EN, DE, FR, RU。沒(méi)錯(cuò),不支持CN,從導(dǎo)出的文檔也可以看到,部分中文無(wú)法顯示,目前我也尚未找到是否有配置可以實(shí)現(xiàn)這個(gè)功能。網(wǎng)上的文章部分是通過(guò)替換源代碼包里面的字體文件來(lái)實(shí)現(xiàn),但是由于后面有更好的解決方案,這里就不再討論。
- 從asciidoctorj-pdf的1.5.0-alpha.16版本以后(目前最新是1.5.0-alpha.18),這種方式生成文件會(huì)拋出異常,我個(gè)人并沒(méi)有深究這個(gè)異常,有興趣的讀者可以通過(guò)修改版本號(hào)試一試。
- 生成的adoc文件一般包含overview.adoc、paths.adoc、definitions.adoc、security.adoc一共4個(gè)文件,這也是為什么要手動(dòng)編寫(xiě)index.adoc進(jìn)行整合的原因,感覺(jué)不太方便。
綜上,我個(gè)人并不推薦采用此方式生成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也是官方推薦的使用方式。相對(duì)前面的方式,使用起來(lái)更加簡(jiǎn)單,也可以修改配置輸出中文。
1. 引入插件
plugins {
id 'org.asciidoctor.jvm.pdf' version '2.2.0'
}
2. 編寫(xiě)測(cè)試類生成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方法的源碼,里面對(duì)第一種方法生成的4個(gè)文件進(jìn)行了整合,這也是不再需要手動(dòng)編寫(xiě)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會(huì)被程序用于匹配${styleName}-theme.yml,如default-styleName-theme.yml
styleName = 'default'
}
}
asciidoctorPdf{
sourceDir(asciiDocOutputDir.absolutePath)
sources {
include "swagger.adoc"
}
fontsDir(pdfFontsDir.absolutePath)
theme("basic")
}
本文字體與主題文件均來(lái)自于asciidoctorj-pdf-1.5.0-alpha.18.jar源碼包,其路徑位于:gems/asciidoctorj-pdf-1.5.0-alpha.18/data
4. 復(fù)制并修改default-theme.yml文件配置
為了解決中文無(wú)法顯示的問(wèn)題,首先需要自行下載一個(gè)支持中文的字體文件。
修改主題文件,將mplus1p-regular-fallback.ttf替換為自己下載的字體文件的名稱。
M+ 1p Fallback: normal: your-font.ttf bold: your-font.ttf italic: your-font.ttf bold_italic: your-font.ttf
由于手動(dòng)指定了字體文件的路徑,所以除了中文以外,還需要將源碼中的其他字體文件一并復(fù)制到${pdfFontsDir}文件夾。如果不愿意使用官方的字體,也可以考慮將default-theme.yml中其他的字體文件都修改為自己想要的文件。
保持task genPdf不變,再次運(yùn)行即可生成PDF文件,生成的文件默認(rèn)路徑為${build}/docs/asciidocPdf
小結(jié)
asciidoctor-gradle-plugin的方式可以支持配置字體與主題,通過(guò)配置不僅規(guī)避了中文無(wú)法顯示的問(wèn)題,同時(shí)使用起來(lái)也更加簡(jiǎn)單。需要注意的是,采用此種方案生成出的文檔會(huì)在封面寫(xiě)有項(xiàng)目的版本號(hào),此版本號(hào)為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é)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
- Android Gradle依賴管理、去除重復(fù)依賴、忽略的方式
- android studio更新gradle錯(cuò)誤構(gòu)建項(xiàng)目失敗的解決方法
- Android Studio和Gradle使用不同位置JDK的問(wèn)題解決
- gradle+shell實(shí)現(xiàn)自動(dòng)系統(tǒng)簽名
- Jenkins使用Gradle編譯Android項(xiàng)目詳解
- Android Studio Gradle依賴沖突解決方法
- 關(guān)于gradle你應(yīng)該知道的一些小事
- 基于Java Gradle復(fù)制項(xiàng)目模塊過(guò)程圖解
相關(guān)文章
Java 實(shí)戰(zhàn)項(xiàng)目之誠(chéng)途旅游系統(tǒng)的實(shí)現(xiàn)流程
讀萬(wàn)卷書(shū)不如行萬(wàn)里路,只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SpringBoot+Vue+maven+Mysql實(shí)現(xiàn)一個(gè)精美的物流管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2021-11-11
Java實(shí)現(xiàn)FTP文件的上傳和下載功能的實(shí)例代碼
FTP 是File Transfer Protocol(文件傳輸協(xié)議)的英文簡(jiǎn)稱,而中文簡(jiǎn)稱為“文傳協(xié)議”。接下來(lái)通過(guò)本文給大家實(shí)例講解Java實(shí)現(xiàn)FTP文件的上傳和下載功能,需要的的朋友一起看看吧2016-11-11
java運(yùn)行windows的cmd命令簡(jiǎn)單代碼
這篇文章主要介紹了java運(yùn)行windows的cmd命令簡(jiǎn)單代碼,有需要的朋友可以參考一下2013-12-12
IDEA MyBatis Plugins自動(dòng)生成實(shí)體類和mapper.xml
這篇文章主要介紹了IDEA MyBatis Plugins自動(dòng)生成實(shí)體類和mapper.xml,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
Mybatis無(wú)法獲取帶有下劃線前綴的字段的值問(wèn)題
這篇文章主要介紹了Mybatis無(wú)法獲取帶有下劃線前綴的字段的值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
SpringBoot如何配置數(shù)據(jù)庫(kù)主從shardingsphere
這篇文章主要介紹了SpringBoot如何配置數(shù)據(jù)庫(kù)主從shardingsphere問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
詳解如何使用Jersey客戶端請(qǐng)求Spring Boot(RESTFul)服務(wù)
本篇文章主要介紹了詳解如何使用Jersey客戶端請(qǐng)求Spring Boot(RESTFul)服務(wù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01

