针对 数据库巡检报告 这一特定场景(含 图表、数据表格、文本结论),我重新筛选了最符合要求的方案。
核心需求分析
| 需求 | 重要性 | 说明 |
|---|---|---|
| 图表支持 | ⭐⭐⭐⭐⭐ | 巡检报告核心,需支持柱状图、折线图、饼图等 |
| 数据表格 | ⭐⭐⭐⭐⭐ | 数据库指标、性能数据通常以表格呈现 |
| 多格式输出 | ⭐⭐⭐⭐ | PDF(归档)、Word(可编辑)、MD(快速预览) |
| 纯 Java 部署 | ⭐⭐⭐⭐⭐ | 不能依赖外部软件 |
| 免费开源 | ⭐⭐⭐⭐⭐ | 无商业授权费用 |
筛选后的推荐方案
🏆 最佳组合方案(强烈推荐)
采用「分格式专用引擎」策略,每种格式用最合适的库,图表统一生成图片后嵌入。
┌─────────────────────────────────────────────────────────────┐
│ 数据库巡检报告生成架构 │
├─────────────────────────────────────────────────────────────┤
│ 数据层 │
│ ├── 数据库指标数据 (JDBC/MyBatis) │
│ └── 巡检结论数据 (Java Object) │
├─────────────────────────────────────────────────────────────┤
│ 图表层 (统一) │
│ ├── JFreeChart (纯 Java 生成图表图片) │
│ └── 或 ECharts (前端生成后转 PNG 给后端) │
├─────────────────────────────────────────────────────────────┤
│ 文档层 (分格式) │
│ ├── PDF → Thymeleaf(Freemarker) + OpenHTMLtoPDF + 图表图片 │
│ ├── Word → poi-tl + 图表图片 │
│ └── MD → Freemarker + 图表图片 (Base64 或路径) │
└─────────────────────────────────────────────────────────────┘
方案一:HTML 中转法(PDF 首选)⭐⭐⭐⭐⭐
最适合 PDF 归档报告,图表支持最好
技术选型
| 组件 | 库 | 版本 | 许可证 |
|---|---|---|---|
| 模版引擎 | Freemarker |
2.3.32 | Apache 2.0 |
| PDF 渲染 | OpenHTMLtoPDF |
1.0.10 | LGPL |
| 图表生成 | JFreeChart |
1.5.3 | Apache 2.0 |
| 图片处理 | Apache Commons Imaging |
1.0 | Apache 2.0 |
Maven 依赖
<!-- 模版引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
<!-- PDF 生成 -->
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-pdfbox</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-java2d</artifactId>
<version>1.0.10</version>
</dependency>
<!-- 图表生成 -->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.5.3</version>
</dependency>
核心代码示例
1. 生成图表图片(JFreeChart)
public byte[] generateChartImage(String title, double[] data) throws IOException {
// 创建数据集
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (int i = 0; i < data.length; i++) {
dataset.addValue(data[i], "指标", "Item-" + i);
}
// 创建图表
JFreeChart chart = ChartFactory.createBarChart(
title, "项目", "数值", dataset,
PlotOrientation.VERTICAL, false, true, false
);
// 设置中文支持
chart.getTitle().setFont(new Font("SimHei", Font.BOLD, 16));
chart.getCategoryPlot().getDomainAxis().setLabelFont(new Font("SimHei", Font.PLAIN, 12));
chart.getCategoryPlot().getRangeAxis().setLabelFont(new Font("SimHei", Font.PLAIN, 12));
// 输出为 PNG 字节数组
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ChartUtilities.writeChartAsPNG(baos, chart, 800, 400);
return baos.toByteArray();
}
2. 图表转 Base64 嵌入 HTML
public String imageToBase64(byte[] imageBytes) {
return "data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes);
}
// 放入数据模型
dataMap.put("cpuChart", imageToBase64(generateChartImage("CPU 使用率", cpuData)));
dataMap.put("memoryChart", imageToBase64(generateChartImage("内存使用率", memoryData)));
3. HTML 模版 (report.html.ftl)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
.chart { width: 100%; text-align: center; margin: 20px 0; }
.chart img { max-width: 800px; height: auto; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #4CAF50; color: white; }
.page-break { page-break-after: always; }
</style>
</head>
<body>
<h1>数据库巡检报告 - ${reportDate}</h1>
<h2>1. 性能概览</h2>
<div class="chart">
<img src="${cpuChart}" alt="CPU 使用率"/>
</div>
<h2>2. 资源使用详情</h2>
<table>
<tr><th>指标</th><th>当前值</th><th>阈值</th><th>状态</th></tr>
<#list metrics as metric>
<tr>
<td>${metric.name}</td>
<td>${metric.value}</td>
<td>${metric.threshold}</td>
<td>${metric.status}</td>
</tr>
</#list>
</table>
<div class="page-break"></div>
<h2>3. 内存分析</h2>
<div class="chart">
<img src="${memoryChart}" alt="内存使用率"/>
</div>
</body>
</html>
4. PDF 生成(含中文字体)
public void generatePdf(Map<String, Object> dataMap, OutputStream outputStream) throws Exception {
// 1. 渲染 HTML
String htmlContent = renderFreemarker("report.html.ftl", dataMap);
// 2. 配置 PDF 渲染器
PdfRendererBuilder builder = new PdfRendererBuilder();
builder.useFastMode();
builder.toStream(outputStream);
builder.withHtmlContent(htmlContent, "/");
// 3. 注册中文字体(从 classpath 加载)
FontResolver resolver = builder.getFontResolver();
try (InputStream fontStream = getClass().getResourceAsStream("/fonts/SimHei.ttf")) {
resolver.addFont(FontSource.createFontSource(fontStream), "SimHei",
FontResolver.FontType.TRUETYPE, true, false);
}
// 4. 执行渲染
builder.run();
}
优点:
- ✅ 图表支持完美(图片嵌入)
- ✅ 表格样式灵活(CSS 控制)
- ✅ 分页控制简单(CSS)
- ✅ 纯 Java 部署
缺点:
- ⚠️ 不适合转 Word(样式会丢失)
方案二:Word 原生模版法(Word 首选)⭐⭐⭐⭐⭐
最适合可编辑报告,表格支持最好
技术选型
| 组件 | 库 | 版本 | 许可证 |
|---|---|---|---|
| Word 生成 | poi-tl |
1.12.1 | Apache 2.0 |
| 图表生成 | JFreeChart |
1.5.3 | Apache 2.0 |
Maven 依赖
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.1</version>
</dependency>
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.5.3</version>
</dependency>
核心代码示例
1. Word 模版制作
在 Word 中设计模版,使用以下占位符:
- 文本:
{{title}} - 图片:
{{chart}} - 表格:
{{table}}
2. 图表插入 Word
public void generateWord(Map<String, Object> dataMap, OutputStream outputStream) throws Exception {
// 1. 生成图表图片
byte[] chartImage = generateChartImage("CPU 使用率", cpuData);
// 2. 配置 poi-tl 图片渲染
Configure config = Configure.builder()
.bind("chart", new PictureRenderPolicy()) // 图片占位符
.bind("table", new TableRenderPolicy()) // 表格占位符
.build();
// 3. 准备数据
dataMap.put("chart", Pictures.ofBytes(chartImage).size(800, 400).create());
dataMap.put("table", createTableData(metrics)); // 表格数据
// 4. 从 classpath 加载模版
try (InputStream templateStream = getClass().getResourceAsStream("/templates/inspection.docx")) {
XWPFTemplate template = XWPFTemplate.compile(templateStream, config).render(dataMap);
template.writeAndClose(outputStream);
}
}
3. 表格数据构造
private TableRenderData createTableData(List<Metric> metrics) {
Rows rows = Rows.of(
Row.of("指标", "当前值", "阈值", "状态")
);
for (Metric m : metrics) {
rows.addRow(Row.of(m.getName(), m.getValue(), m.getThreshold(), m.getStatus()));
}
return rows.create();
}
优点:
- ✅ Word 样式完美(原生支持)
- ✅ 表格支持最好
- ✅ 用户可编辑
- ✅ 纯 Java 部署
缺点:
- ⚠️ 需要单独维护.docx 模版
- ⚠️ 图表需转图片插入
方案三:积木报表(数据密集型备选)⭐⭐⭐
适合以数据表格为主的巡检报告
技术选型
| 组件 | 库 | 版本 | 许可证 |
|---|---|---|---|
| 报表引擎 | JimuReport |
1.6.0 | Apache 2.0 |
Maven 依赖
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
<version>1.6.0</version>
</dependency>
适用场景
- ✅ 大量数据表格
- ✅ 内置图表支持
- ✅ Web 可视化设计模版
- ⚠️ Word 导出效果一般
- ❌ 不支持 Markdown
最终推荐架构
┌─────────────────────────────────────────────────────────────────┐
│ 数据库巡检报告生成服务 │
├─────────────────────────────────────────────────────────────────┤
│ 输入:数据库巡检数据 (JDBC/MyBatis) │
├─────────────────────────────────────────────────────────────────┤
│ 处理层 │
│ ├── 图表生成服务 (JFreeChart → PNG → Base64) │
│ ├── 数据聚合服务 (指标计算、状态判断) │
│ └── 模版渲染服务 (Freemarker) │
├─────────────────────────────────────────────────────────────────┤
│ 输出层 │
│ ├── PDF → OpenHTMLtoPDF (归档用) │
│ ├── Word → poi-tl (可编辑用) │
│ └── MD → Freemarker 文本 (快速预览用) │
├─────────────────────────────────────────────────────────────────┤
│ 资源文件 │
│ ├── /templates/report.html.ftl (PDF 模版) │
│ ├── /templates/inspection.docx (Word 模版) │
│ ├── /templates/report.md.ftl (MD 模版) │
│ └── /fonts/SimHei.ttf (中文字体) │
└─────────────────────────────────────────────────────────────────┘
选型决策表
| 需求优先级 | 推荐方案 | 理由 |
|---|---|---|
| PDF 归档 | HTML 中转法 | 样式灵活、图表支持好、分页控制简单 |
| Word 可编辑 | poi-tl 原生模版 | Word 样式完美、表格支持最好 |
| MD 快速预览 | Freemarker 文本 | 轻量、无依赖、生成快 |
| 图表统一 | JFreeChart | 纯 Java、免费、支持多种图表类型 |
| 部署简单 | 以上组合 | 纯 Jar 包、无外部依赖、免费开源 |
关键实施建议
- 图表统一生成:用 JFreeChart 生成 PNG 图片,三种格式都复用同一套图片(Base64 嵌入)
- 字体打包:将
SimHei.ttf打入 Jar 包,避免服务器无中文字体 - 异步生成:巡检报告生成耗时,建议放入线程池异步处理
- 模版外部化:模版文件可放 OSS/数据库,支持动态更新无需重启
- 内存控制:大图表数据流式输出,避免 OOM
这个组合方案完全满足 数据库巡检报告 的所有核心需求,且保持 纯 Java 部署 + 免费开源。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




