Swagger UI 导出文档
生成静态 HTML 文档
使用 Swagger2markup
Swagger2markup 是一个能将 Swagger JSON 或 YAML 文件转换为 AsciiDoc 或 Markdown 文档的工具。结合 AsciiDoctor,可以将文档转换为 HTML 或 PDF 格式。
添加 Maven 依赖:
实例
<dependencies>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>1.3.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>2.2.2</version>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.6.2</version>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>target/asciidoc</sourceDirectory>
<outputDirectory>target/generated-docs</outputDirectory>
<backend>html5</backend> <!-- 或者 'pdf' -->
<attributes>
<toc>left</toc>
<toclevels>3</toclevels>
</attributes>
</configuration>
</plugin>
</plugins>
</build>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>1.3.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>2.2.2</version>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.6.2</version>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>target/asciidoc</sourceDirectory>
<outputDirectory>target/generated-docs</outputDirectory>
<backend>html5</backend> <!-- 或者 'pdf' -->
<attributes>
<toc>left</toc>
<toclevels>3</toclevels>
</attributes>
</configuration>
</plugin>
</plugins>
</build>
创建测试类生成文档:
实例
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.net.URL;
import java.nio.file.Paths;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class SwaggerDocumentationTest {
@Test
public void generateAsciiDoc() throws Exception {
// 设置输出目录
final String outputDir = "target/asciidoc";
// Swagger2Markup 配置
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.ASCIIDOC)
.withOutputLanguage(java.util.Locale.CHINA)
.withGeneratedExamples()
.withPathsGroupedBy(io.github.swagger2markup.GroupBy.TAGS)
.build();
// 从 OpenAPI JSON 文件生成 AsciiDoc 文件
Swagger2MarkupConverter.from(new URL("http://localhost:8080/v3/api-docs"))
.withConfig(config)
.build()
.toFolder(Paths.get(outputDir));
}
}
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.net.URL;
import java.nio.file.Paths;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class SwaggerDocumentationTest {
@Test
public void generateAsciiDoc() throws Exception {
// 设置输出目录
final String outputDir = "target/asciidoc";
// Swagger2Markup 配置
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.ASCIIDOC)
.withOutputLanguage(java.util.Locale.CHINA)
.withGeneratedExamples()
.withPathsGroupedBy(io.github.swagger2markup.GroupBy.TAGS)
.build();
// 从 OpenAPI JSON 文件生成 AsciiDoc 文件
Swagger2MarkupConverter.from(new URL("http://localhost:8080/v3/api-docs"))
.withConfig(config)
.build()
.toFolder(Paths.get(outputDir));
}
}
运行测试并生成文档:
# 生成 AsciiDoc mvn test # 将 AsciiDoc 转换为 HTML mvn asciidoctor:process-asciidoc # 生成的文档位于 target/generated-docs 目录
生成 PDF 文档
使用 Asciidoctor-PDF
基于前面生成的 AsciiDoc 文件,可以使用 Asciidoctor-PDF 生成 PDF 文档:
1. 修改 Maven 配置:
实例
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>2.2.2</version>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.6.2</version>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>target/asciidoc</sourceDirectory>
<outputDirectory>target/generated-docs</outputDirectory>
<backend>pdf</backend>
<attributes>
<toc>left</toc>
<toclevels>3</toclevels>
<icons>font</icons>
<source-highlighter>coderay</source-highlighter>
<pagenums>true</pagenums>
<pdf-stylesdir>${project.basedir}/src/main/resources/theme</pdf-stylesdir>
<pdf-style>custom</pdf-style>
<pdf-fontsdir>${project.basedir}/src/main/resources/fonts</pdf-fontsdir>
</attributes>
</configuration>
</plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>2.2.2</version>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.6.2</version>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>target/asciidoc</sourceDirectory>
<outputDirectory>target/generated-docs</outputDirectory>
<backend>pdf</backend>
<attributes>
<toc>left</toc>
<toclevels>3</toclevels>
<icons>font</icons>
<source-highlighter>coderay</source-highlighter>
<pagenums>true</pagenums>
<pdf-stylesdir>${project.basedir}/src/main/resources/theme</pdf-stylesdir>
<pdf-style>custom</pdf-style>
<pdf-fontsdir>${project.basedir}/src/main/resources/fonts</pdf-fontsdir>
</attributes>
</configuration>
</plugin>
自定义 PDF 样式 src/main/resources/theme/custom-theme.yml
:
实例
font:
catalog:
# 中文字体配置
Noto Sans SC:
normal: NotoSansSC-Regular.ttf
bold: NotoSansSC-Bold.ttf
italic: NotoSansSC-Regular.ttf
bold_italic: NotoSansSC-Bold.ttf
# 英文字体配置
Roboto:
normal: Roboto-Regular.ttf
bold: Roboto-Bold.ttf
italic: Roboto-Italic.ttf
bold_italic: Roboto-BoldItalic.ttf
fallbacks:
- Noto Sans SC
- Roboto
page:
layout: portrait
margin: [0.75in, 1in, 0.75in, 1in]
size: A4
base:
font_color: #333333
font_family: Noto Sans SC
font_size: 10
line_height_length: 17
line_height: $base_line_height_length / $base_font_size
title_page:
align: center
logo:
image: image:logo.png[pdfwidth=60%]
title:
top: 40%
font_size: 24
font_color: #262626
subtitle:
font_size: 18
font_style: bold_italic
font_color: #666666
authors:
font_size: 14
font_color: #181818
revision:
font_size: 12
font_color: #181818
header:
height: 0.75in
line_height: 1
border_color: #dddddd
border_width: 0.25
font_size: 10
background_color: #f5f5f5
padding: [4, 4, 4, 4]
vertical_align: middle
footer:
height: 0.75in
line_height: 1
border_color: #dddddd
border_width: 0.25
font_size: 10
padding: [4, 4, 4, 4]
vertical_align: middle
heading:
font_color: #262626
font_family: Roboto
h1_font_size: 18
h2_font_size: 16
h3_font_size: 14
h4_font_size: 12
h5_font_size: 10
h6_font_size: 10
line_height: 1.2
margin_bottom: $base_line_height_length
link:
font_color: #1565C0
code:
font_family: Courier
font_size: 9
background_color: #f5f5f5
border_color: #dddddd
border_radius: 4
catalog:
# 中文字体配置
Noto Sans SC:
normal: NotoSansSC-Regular.ttf
bold: NotoSansSC-Bold.ttf
italic: NotoSansSC-Regular.ttf
bold_italic: NotoSansSC-Bold.ttf
# 英文字体配置
Roboto:
normal: Roboto-Regular.ttf
bold: Roboto-Bold.ttf
italic: Roboto-Italic.ttf
bold_italic: Roboto-BoldItalic.ttf
fallbacks:
- Noto Sans SC
- Roboto
page:
layout: portrait
margin: [0.75in, 1in, 0.75in, 1in]
size: A4
base:
font_color: #333333
font_family: Noto Sans SC
font_size: 10
line_height_length: 17
line_height: $base_line_height_length / $base_font_size
title_page:
align: center
logo:
image: image:logo.png[pdfwidth=60%]
title:
top: 40%
font_size: 24
font_color: #262626
subtitle:
font_size: 18
font_style: bold_italic
font_color: #666666
authors:
font_size: 14
font_color: #181818
revision:
font_size: 12
font_color: #181818
header:
height: 0.75in
line_height: 1
border_color: #dddddd
border_width: 0.25
font_size: 10
background_color: #f5f5f5
padding: [4, 4, 4, 4]
vertical_align: middle
footer:
height: 0.75in
line_height: 1
border_color: #dddddd
border_width: 0.25
font_size: 10
padding: [4, 4, 4, 4]
vertical_align: middle
heading:
font_color: #262626
font_family: Roboto
h1_font_size: 18
h2_font_size: 16
h3_font_size: 14
h4_font_size: 12
h5_font_size: 10
h6_font_size: 10
line_height: 1.2
margin_bottom: $base_line_height_length
link:
font_color: #1565C0
code:
font_family: Courier
font_size: 9
background_color: #f5f5f5
border_color: #dddddd
border_radius: 4
生成 PDF 文档:
mvn asciidoctor:process-asciidoc@pdf
使用工具直接导出
使用 wkhtmltopdf 工具
1. 安装 wkhtmltopdf:
# Ubuntu/Debian sudo apt-get install wkhtmltopdf # CentOS/RHEL sudo yum install wkhtmltopdf # macOS brew install wkhtmltopdf
2. 创建导出脚本 export-docs.sh
:
实例
!/bin/bash
# 设置变量
SWAGGER_URL="http://localhost:8080/swagger-ui/index.html"
OUTPUT_DIR="./api-docs"
FILENAME="api-documentation.pdf"
HTML_FILENAME="api-documentation.html"
# 创建输出目录
mkdir -p $OUTPUT_DIR
# 使用 curl 下载 HTML 文档
echo "正在下载 Swagger UI HTML..."
curl -s $SWAGGER_URL > $OUTPUT_DIR/$HTML_FILENAME
# 使用 wkhtmltopdf 生成 PDF
echo "正在生成 PDF 文档..."
wkhtmltopdf \
--enable-javascript \
--javascript-delay 5000 \
--no-stop-slow-scripts \
--page-size A4 \
--title "API 文档" \
--margin-top 20 \
--margin-right 20 \
--margin-bottom 20 \
--margin-left 20 \
--header-line \
--header-center "API 文档中心" \
--footer-line \
--footer-center "页码 [page] / [topage]" \
--footer-right "生成日期: $(date +%Y-%m-%d)" \
$OUTPUT_DIR/$HTML_FILENAME $OUTPUT_DIR/$FILENAME
echo "文档已生成:"
echo "HTML: $OUTPUT_DIR/$HTML_FILENAME"
echo "PDF: $OUTPUT_DIR/$FILENAME"
# 设置变量
SWAGGER_URL="http://localhost:8080/swagger-ui/index.html"
OUTPUT_DIR="./api-docs"
FILENAME="api-documentation.pdf"
HTML_FILENAME="api-documentation.html"
# 创建输出目录
mkdir -p $OUTPUT_DIR
# 使用 curl 下载 HTML 文档
echo "正在下载 Swagger UI HTML..."
curl -s $SWAGGER_URL > $OUTPUT_DIR/$HTML_FILENAME
# 使用 wkhtmltopdf 生成 PDF
echo "正在生成 PDF 文档..."
wkhtmltopdf \
--enable-javascript \
--javascript-delay 5000 \
--no-stop-slow-scripts \
--page-size A4 \
--title "API 文档" \
--margin-top 20 \
--margin-right 20 \
--margin-bottom 20 \
--margin-left 20 \
--header-line \
--header-center "API 文档中心" \
--footer-line \
--footer-center "页码 [page] / [topage]" \
--footer-right "生成日期: $(date +%Y-%m-%d)" \
$OUTPUT_DIR/$HTML_FILENAME $OUTPUT_DIR/$FILENAME
echo "文档已生成:"
echo "HTML: $OUTPUT_DIR/$HTML_FILENAME"
echo "PDF: $OUTPUT_DIR/$FILENAME"
3. 运行脚本:
chmod +x export-docs.sh ./export-docs.sh
使用 Puppeteer 导出 PDF
对于 Node.js 环境,可以使用 Puppeteer 导出 PDF。
1. 创建导出脚本 export-pdf.js
:
实例
const puppeteer = require('puppeteer');
const path = require('path');
const fs = require('fs');
(async () => {
// 创建输出目录
const outputDir = path.join(__dirname, 'api-docs');
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}
// 启动浏览器
const browser = await puppeteer.launch();
const page = await browser.newPage();
// 访问 Swagger UI 页面
await page.goto('http://localhost:8080/swagger-ui/index.html', {
waitUntil: 'networkidle0',
timeout: 60000
});
// 等待 Swagger UI 加载完成
await page.waitForSelector('.swagger-ui .information-container', { timeout: 10000 });
// 展开所有 API 节点
await page.evaluate(() => {
document.querySelectorAll('.opblock').forEach(el => {
if (!el.classList.contains('is-open')) {
el.querySelector('.opblock-summary').click();
}
});
});
// 等待展开动画完成
await page.waitForTimeout(2000);
// 添加自定义页眉页脚样式
await page.addStyleTag({
content: `
@page {
margin: 20mm 15mm;
}
.page-header {
width: 100%;
text-align: center;
font-size: 16px;
color: #333;
padding: 10px 0;
border-bottom: 1px solid #ddd;
}
.page-footer {
width: 100%;
text-align: center;
font-size: 12px;
color: #666;
padding: 10px 0;
border-top: 1px solid #ddd;
}
`
});
// 生成 PDF
await page.pdf({
path: path.join(outputDir, 'api-documentation.pdf'),
format: 'A4',
printBackground: true,
displayHeaderFooter: true,
headerTemplate: `<div class="page-header">API 文档中心</div>`,
footerTemplate: `<div class="page-footer">
<span>页码 <span class="pageNumber"></span> / <span class="totalPages"></span></span>
<span style="margin-left: 20px;">生成日期: ${new Date().toLocaleDateString()}</span>
</div>`,
margin: {
top: '40px',
bottom: '40px',
left: '20px',
right: '20px'
}
});
// 生成 HTML
const htmlContent = await page.content();
fs.writeFileSync(path.join(outputDir, 'api-documentation.html'), htmlContent);
// 关闭浏览器
await browser.close();
console.log('文档已生成在目录:', outputDir);
})();
const path = require('path');
const fs = require('fs');
(async () => {
// 创建输出目录
const outputDir = path.join(__dirname, 'api-docs');
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}
// 启动浏览器
const browser = await puppeteer.launch();
const page = await browser.newPage();
// 访问 Swagger UI 页面
await page.goto('http://localhost:8080/swagger-ui/index.html', {
waitUntil: 'networkidle0',
timeout: 60000
});
// 等待 Swagger UI 加载完成
await page.waitForSelector('.swagger-ui .information-container', { timeout: 10000 });
// 展开所有 API 节点
await page.evaluate(() => {
document.querySelectorAll('.opblock').forEach(el => {
if (!el.classList.contains('is-open')) {
el.querySelector('.opblock-summary').click();
}
});
});
// 等待展开动画完成
await page.waitForTimeout(2000);
// 添加自定义页眉页脚样式
await page.addStyleTag({
content: `
@page {
margin: 20mm 15mm;
}
.page-header {
width: 100%;
text-align: center;
font-size: 16px;
color: #333;
padding: 10px 0;
border-bottom: 1px solid #ddd;
}
.page-footer {
width: 100%;
text-align: center;
font-size: 12px;
color: #666;
padding: 10px 0;
border-top: 1px solid #ddd;
}
`
});
// 生成 PDF
await page.pdf({
path: path.join(outputDir, 'api-documentation.pdf'),
format: 'A4',
printBackground: true,
displayHeaderFooter: true,
headerTemplate: `<div class="page-header">API 文档中心</div>`,
footerTemplate: `<div class="page-footer">
<span>页码 <span class="pageNumber"></span> / <span class="totalPages"></span></span>
<span style="margin-left: 20px;">生成日期: ${new Date().toLocaleDateString()}</span>
</div>`,
margin: {
top: '40px',
bottom: '40px',
left: '20px',
right: '20px'
}
});
// 生成 HTML
const htmlContent = await page.content();
fs.writeFileSync(path.join(outputDir, 'api-documentation.html'), htmlContent);
// 关闭浏览器
await browser.close();
console.log('文档已生成在目录:', outputDir);
})();
2. 安装依赖并运行:
npm install puppeteer node export-pdf.js
总结
Swagger UI 是一个强大的 API 文档工具,通过正确配置和使用,可以大大提高 API 的可用性和开发效率。
通过以上内容我们了解了 Swagger UI 的基本概念、集成方法、文档编写、自定义配置、文档发布、样式定制以及文档导出等内容。
记住以下关键点:
- 选择适合项目技术栈的 Swagger 集成方式
- 精心设计和编写 API 文档注解或注释
- 根据需要自定义 Swagger UI 界面和样式
- 添加品牌标识使文档更具专业性
- 选择合适的文档发布和导出方式
- 遵循最佳实践,确保文档的准确性和安全性
通过合理使用 Swagger UI,您可以为您的 API 提供专业、交互式的文档,让您的 API 更易于理解和使用。
点我分享笔记