SpringBoot集成iText快速生成PDF教程
SpringBoot集成iText 9.4.0生成PDF
2025年iText已發(fā)展到9.x版本,本文將帶你體驗(yàn)最新特性和最佳實(shí)踐
在現(xiàn)代企業(yè)應(yīng)用開發(fā)中,動(dòng)態(tài)生成PDF文檔是一個(gè)常見需求。無論是生成報(bào)表、發(fā)票、合同還是其他業(yè)務(wù)單據(jù),PDF格式因其跨平臺(tái)、保持布局不變的特性而備受青睞。
本文將詳細(xì)介紹如何在SpringBoot項(xiàng)目中集成iText 9.4.0——當(dāng)前最新的版本,來實(shí)現(xiàn)高效、專業(yè)的PDF生成。
一、iText 9新特性與架構(gòu)變革
iText 9.x相比舊版本進(jìn)行了徹底的重構(gòu):
- 模塊化設(shè)計(jì):按功能拆分為多個(gè)獨(dú)立模塊
- 性能提升:底層架構(gòu)優(yōu)化,處理速度更快
- API現(xiàn)代化:更符合現(xiàn)代Java開發(fā)習(xí)慣
- 功能增強(qiáng):支持更多PDF標(biāo)準(zhǔn)和特性
二、環(huán)境準(zhǔn)備與依賴配置
Maven依賴配置
在SpringBoot項(xiàng)目的pom.xml中添加以下依賴:
<properties>
<itext.version>9.4.0</itext.version>
</properties>
<dependencies>
<!-- iText 9 核心模塊 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>io</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>forms</artifactId>
<version>${itext.version}</version>
</dependency>
<!-- 條形碼支持 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>barcodes</artifactId>
<version>${itext.version}</version>
</dependency>
<!-- 中文支持 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>font-asian</artifactId>
<version>${itext.version}</version>
</dependency>
</dependencies>
三、完整的Service層實(shí)現(xiàn)
1. 基礎(chǔ)PDF服務(wù)
@Service
public class PdfService {
/**
* 創(chuàng)建簡單PDF文檔
*/
public void createSimplePdf(OutputStream outputStream) throws IOException {
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc);
// 添加內(nèi)容
document.add(new Paragraph("Hello, iText 9.4.0!")
.setFontSize(20)
.setBold());
document.add(new Paragraph("這是一個(gè)使用SpringBoot和iText 9生成的PDF文檔"));
document.add(new Paragraph("生成時(shí)間: " + new Date()));
// 關(guān)閉文檔
document.close();
}
/**
* 創(chuàng)建帶表格的PDF
*/
public void createTablePdf(OutputStream outputStream) throws IOException {
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc);
// 創(chuàng)建3列表格
Table table = new Table(3);
// 添加表頭
table.addHeaderCell(new Cell().add(new Paragraph("姓名").setBold()));
table.addHeaderCell(new Cell().add(new Paragraph("部門").setBold()));
table.addHeaderCell(new Cell().add(new Paragraph("工資").setBold()));
// 添加數(shù)據(jù)行
table.addCell(new Cell().add(new Paragraph("張三")));
table.addCell(new Cell().add(new Paragraph("技術(shù)部")));
table.addCell(new Cell().add(new Paragraph("8000")));
table.addCell(new Cell().add(new Paragraph("李四")));
table.addCell(new Cell().add(new Paragraph("市場部")));
table.addCell(new Cell().add(new Paragraph("7500")));
table.addCell(new Cell().add(new Paragraph("王五")));
table.addCell(new Cell().add(new Paragraph("財(cái)務(wù)部")));
table.addCell(new Cell().add(new Paragraph("8200")));
document.add(new Paragraph("員工信息表").setFontSize(16).setBold());
document.add(table);
document.close();
}
/**
* 生成帶條形碼的PDF
*/
public void createPdfWithBarcode(OutputStream outputStream, String barcodeData) throws IOException {
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc);
// 添加標(biāo)題
document.add(new Paragraph("條形碼示例文檔")
.setFontSize(18)
.setBold()
.setTextAlignment(TextAlignment.CENTER));
// 添加條形碼
document.add(new Paragraph("條形碼數(shù)據(jù): " + barcodeData));
// 創(chuàng)建Code 128條形碼
Barcode128 barcode = new Barcode128(pdfDoc);
barcode.setCode(barcodeData);
barcode.setFont(null); // 不顯示文本
// 將條形碼轉(zhuǎn)換為圖像
Image barcodeImage = new Image(barcode.createFormXObject(pdfDoc))
.setWidth(200)
.setAutoScaleHeight(true);
document.add(barcodeImage);
document.close();
}
/**
* 生成帶圖片和條形碼的PDF
*/
public void createPdfWithImageAndBarcode(OutputStream outputStream, String imageUrl, String barcodeData) throws IOException {
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc);
// 添加標(biāo)題
document.add(new Paragraph("產(chǎn)品信息卡")
.setFontSize(18)
.setBold()
.setTextAlignment(TextAlignment.CENTER));
// 添加圖片(如果有)
if (imageUrl != null && !imageUrl.trim().isEmpty()) {
try {
Image image = new Image(ImageDataFactory.create(imageUrl))
.setWidth(200)
.setAutoScaleHeight(true)
.setHorizontalAlignment(HorizontalAlignment.CENTER);
document.add(image);
} catch (Exception e) {
document.add(new Paragraph("圖片加載失敗: " + e.getMessage()));
}
}
// 添加條形碼
if (barcodeData != null && !barcodeData.trim().isEmpty()) {
Barcode128 barcode = new Barcode128(pdfDoc);
barcode.setCode(barcodeData);
Image barcodeImage = new Image(barcode.createFormXObject(pdfDoc))
.setWidth(250)
.setAutoScaleHeight(true)
.setHorizontalAlignment(HorizontalAlignment.CENTER);
document.add(new Paragraph("產(chǎn)品條形碼:").setBold());
document.add(barcodeImage);
}
document.close();
}
/**
* 創(chuàng)建報(bào)告PDF
*/
public void createReportPdf(OutputStream outputStream) throws IOException {
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc);
// 報(bào)告標(biāo)題
document.add(new Paragraph("月度銷售報(bào)告")
.setFontSize(24)
.setBold()
.setTextAlignment(TextAlignment.CENTER));
// 報(bào)告信息
document.add(new Paragraph("報(bào)告周期: " + new Date()));
document.add(new Paragraph("生成部門: 銷售部"));
// 銷售數(shù)據(jù)表格
Table salesTable = new Table(4);
salesTable.addHeaderCell(new Cell().add(new Paragraph("產(chǎn)品").setBold()));
salesTable.addHeaderCell(new Cell().add(new Paragraph("季度").setBold()));
salesTable.addHeaderCell(new Cell().add(new Paragraph("銷售額").setBold()));
salesTable.addHeaderCell(new Cell().add(new Paragraph("增長率").setBold()));
// 示例數(shù)據(jù)
String[][] salesData = {
{"產(chǎn)品A", "Q1", "¥120,000", "15%"},
{"產(chǎn)品A", "Q2", "¥138,000", "15%"},
{"產(chǎn)品B", "Q1", "¥85,000", "8%"},
{"產(chǎn)品B", "Q2", "¥92,000", "8%"}
};
for (String[] row : salesData) {
for (String cell : row) {
salesTable.addCell(new Cell().add(new Paragraph(cell)));
}
}
document.add(salesTable);
document.close();
}
/**
* 創(chuàng)建發(fā)票PDF
*/
public void createInvoicePdf(OutputStream outputStream) throws IOException {
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc);
// 發(fā)票標(biāo)題
document.add(new Paragraph("商業(yè)發(fā)票")
.setFontSize(20)
.setBold()
.setTextAlignment(TextAlignment.CENTER));
// 發(fā)票信息表格
Table invoiceTable = new Table(2);
invoiceTable.addCell(new Cell().add(new Paragraph("發(fā)票號(hào)碼:").setBold()));
invoiceTable.addCell(new Cell().add(new Paragraph("INV-2024-001")));
invoiceTable.addCell(new Cell().add(new Paragraph("開票日期:").setBold()));
invoiceTable.addCell(new Cell().add(new Paragraph(new Date().toString())));
invoiceTable.addCell(new Cell().add(new Paragraph("客戶名稱:").setBold()));
invoiceTable.addCell(new Cell().add(new Paragraph("某某科技有限公司")));
document.add(invoiceTable);
// 商品明細(xì)表格
Table itemsTable = new Table(4);
itemsTable.addHeaderCell(new Cell().add(new Paragraph("商品名稱").setBold()));
itemsTable.addHeaderCell(new Cell().add(new Paragraph("數(shù)量").setBold()));
itemsTable.addHeaderCell(new Cell().add(new Paragraph("單價(jià)").setBold()));
itemsTable.addHeaderCell(new Cell().add(new Paragraph("金額").setBold()));
itemsTable.addCell(new Cell().add(new Paragraph("筆記本電腦")));
itemsTable.addCell(new Cell().add(new Paragraph("2")));
itemsTable.addCell(new Cell().add(new Paragraph("¥5,999")));
itemsTable.addCell(new Cell().add(new Paragraph("¥11,998")));
itemsTable.addCell(new Cell().add(new Paragraph("無線鼠標(biāo)")));
itemsTable.addCell(new Cell().add(new Paragraph("5")));
itemsTable.addCell(new Cell().add(new Paragraph("¥89")));
itemsTable.addCell(new Cell().add(new Paragraph("¥445")));
document.add(new Paragraph("商品明細(xì):").setBold());
document.add(itemsTable);
// 總計(jì)
document.add(new Paragraph("總計(jì): ¥12,443").setBold().setFontSize(16));
document.close();
}
}
2. 中文PDF服務(wù)
@Service
public class ChinesePdfService {
/**
* 創(chuàng)建支持中文的PDF文檔
*/
public void createChinesePdf(OutputStream outputStream) throws IOException {
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc);
// 使用中文字體
PdfFont chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", true);
// 添加中文內(nèi)容
document.add(new Paragraph("中文PDF文檔示例")
.setFont(chineseFont)
.setFontSize(20)
.setBold()
.setTextAlignment(TextAlignment.CENTER));
document.add(new Paragraph("企業(yè)名稱:某某科技有限公司")
.setFont(chineseFont));
document.add(new Paragraph("公司地址:北京市海淀區(qū)中關(guān)村大街1號(hào)")
.setFont(chineseFont));
document.add(new Paragraph("聯(lián)系電話:010-12345678")
.setFont(chineseFont));
// 中文表格
Table table = new Table(3);
table.addHeaderCell(new Cell().add(new Paragraph("姓名").setFont(chineseFont).setBold()));
table.addHeaderCell(new Cell().add(new Paragraph("職位").setFont(chineseFont).setBold()));
table.addHeaderCell(new Cell().add(new Paragraph("部門").setFont(chineseFont).setBold()));
table.addCell(new Cell().add(new Paragraph("張三").setFont(chineseFont)));
table.addCell(new Cell().add(new Paragraph("軟件工程師").setFont(chineseFont)));
table.addCell(new Cell().add(new Paragraph("技術(shù)部").setFont(chineseFont)));
table.addCell(new Cell().add(new Paragraph("李四").setFont(chineseFont)));
table.addCell(new Cell().add(new Paragraph("產(chǎn)品經(jīng)理").setFont(chineseFont)));
table.addCell(new Cell().add(new Paragraph("產(chǎn)品部").setFont(chineseFont)));
document.add(table);
document.close();
}
}
3. 模板PDF服務(wù)
@Service
public class TemplatePdfService {
/**
* 基于模板填充PDF表單
*/
public void fillPdfTemplate(OutputStream outputStream, Map<String, String> formData) throws IOException {
// 創(chuàng)建臨時(shí)模板(實(shí)際項(xiàng)目中應(yīng)該從文件系統(tǒng)或數(shù)據(jù)庫讀取模板)
byte[] templateBytes = createTemplatePdf();
// 讀取模板
PdfReader reader = new PdfReader(new ByteArrayInputStream(templateBytes));
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
// 獲取表單
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);
// 填充數(shù)據(jù)
for (Map.Entry<String, String> entry : formData.entrySet()) {
String fieldName = entry.getKey();
String fieldValue = entry.getValue();
PdfFormField field = form.getField(fieldName);
if (field != null) {
field.setValue(fieldValue);
}
}
// 扁平化表單(使字段不可編輯)
form.flattenFields();
pdfDoc.close();
}
/**
* 創(chuàng)建示例模板PDF(實(shí)際項(xiàng)目中應(yīng)使用現(xiàn)有的PDF模板)
*/
private byte[] createTemplatePdf() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(baos);
PdfDocument pdfDoc = new PdfDocument(writer);
// 創(chuàng)建表單
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);
// 添加表單字段
Rectangle rect = new Rectangle(100, 700, 200, 20);
PdfTextFormField nameField = PdfTextFormField.createText(pdfDoc, rect, "name", "");
form.addField(nameField);
rect = new Rectangle(100, 650, 200, 20);
PdfTextFormField emailField = PdfTextFormField.createText(pdfDoc, rect, "email", "");
form.addField(emailField);
rect = new Rectangle(100, 600, 200, 20);
PdfTextFormField phoneField = PdfTextFormField.createText(pdfDoc, rect, "phone", "");
form.addField(phoneField);
// 添加標(biāo)簽
Document document = new Document(pdfDoc);
document.add(new Paragraph("姓名:").setFixedPosition(50, 700, 50));
document.add(new Paragraph("郵箱:").setFixedPosition(50, 650, 50));
document.add(new Paragraph("電話:").setFixedPosition(50, 600, 50));
document.close();
return baos.toByteArray();
}
}
四、完整的PDF生成Controller
@RestController
@RequestMapping("/api/pdf")
@CrossOrigin(origins = "*")
public class PdfGeneratorController {
@Autowired
private PdfService pdfService;
@Autowired
private ChinesePdfService chinesePdfService;
@Autowired
private TemplatePdfService templatePdfService;
/**
* 1. 基礎(chǔ)PDF生成接口
* 生成包含簡單文本的PDF文檔
*/
@GetMapping("/basic")
public ResponseEntity<byte[]> generateBasicPdf() {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pdfService.createSimplePdf(outputStream);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.header("Content-Disposition", "inline; filename=\"basic-document.pdf\"")
.body(outputStream.toByteArray());
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(("PDF生成失敗: " + e.getMessage()).getBytes());
}
}
/**
* 2. 中文PDF生成接口
* 演示中文字體處理和中文內(nèi)容支持
*/
@GetMapping("/chinese")
public ResponseEntity<byte[]> generateChinesePdf() {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
chinesePdfService.createChinesePdf(outputStream);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.header("Content-Disposition", "inline; filename=\"chinese-document.pdf\"")
.body(outputStream.toByteArray());
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(("中文PDF生成失敗: " + e.getMessage()).getBytes());
}
}
/**
* 3. 表格PDF生成接口
* 展示表格創(chuàng)建和數(shù)據(jù)展示功能
*/
@GetMapping("/table")
public ResponseEntity<byte[]> generateTablePdf() {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pdfService.createTablePdf(outputStream);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.header("Content-Disposition", "inline; filename=\"table-document.pdf\"")
.body(outputStream.toByteArray());
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(("表格PDF生成失敗: " + e.getMessage()).getBytes());
}
}
/**
* 4. 條形碼PDF生成接口
* 演示條形碼生成功能(需要barcodes模塊)
*/
@PostMapping("/barcode")
public ResponseEntity<byte[]> generateBarcodePdf(@RequestParam String barcodeData) {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pdfService.createPdfWithBarcode(outputStream, barcodeData);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.header("Content-Disposition", "inline; filename=\"barcode-document.pdf\"")
.body(outputStream.toByteArray());
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(("條形碼PDF生成失敗: " + e.getMessage()).getBytes());
}
}
/**
* 5. 圖片PDF生成接口
* 展示圖片和條形碼的混合文檔
*/
@PostMapping("/image-barcode")
public ResponseEntity<byte[]> generateImageBarcodePdf(
@RequestParam(required = false) String imageUrl,
@RequestParam String barcodeData) {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pdfService.createPdfWithImageAndBarcode(outputStream, imageUrl, barcodeData);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.header("Content-Disposition", "inline; filename=\"image-barcode-document.pdf\"")
.body(outputStream.toByteArray());
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(("圖片條形碼PDF生成失敗: " + e.getMessage()).getBytes());
}
}
/**
* 6. 模板PDF生成接口
* 基于現(xiàn)有PDF模板填充數(shù)據(jù)
*/
@PostMapping("/template")
public ResponseEntity<byte[]> generateTemplatePdf(@RequestBody Map<String, String> formData) {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
templatePdfService.fillPdfTemplate(outputStream, formData);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.header("Content-Disposition", "inline; filename=\"template-document.pdf\"")
.body(outputStream.toByteArray());
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(("模板PDF生成失敗: " + e.getMessage()).getBytes());
}
}
/**
* 7. 報(bào)告PDF下載接口
*/
@GetMapping("/download/report")
public ResponseEntity<byte[]> downloadReportPdf() {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pdfService.createReportPdf(outputStream);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.header("Content-Disposition", "attachment; filename=\"sales-report.pdf\"")
.body(outputStream.toByteArray());
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(("報(bào)告PDF下載失敗: " + e.getMessage()).getBytes());
}
}
/**
* 8. 發(fā)票PDF下載接口
*/
@GetMapping("/download/invoice")
public ResponseEntity<byte[]> downloadInvoicePdf() {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pdfService.createInvoicePdf(outputStream);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.header("Content-Disposition", "attachment; filename=\"invoice.pdf\"")
.body(outputStream.toByteArray());
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(("發(fā)票PDF下載失敗: " + e.getMessage()).getBytes());
}
}
}
五、iText框架優(yōu)劣分析
優(yōu)勢(shì)
- 功能全面:支持文本、表格、圖片、條形碼、表單等幾乎所有PDF功能
- 性能優(yōu)秀:處理大型文檔時(shí)性能表現(xiàn)良好
- 標(biāo)準(zhǔn)兼容:完美支持PDF/A、PDF/UA等國際標(biāo)準(zhǔn)
- 文檔完善:官方文檔詳細(xì),社區(qū)活躍
- 企業(yè)級(jí)支持:提供商業(yè)許可證和技術(shù)支持
劣勢(shì)
- 學(xué)習(xí)曲線:API較為復(fù)雜,新手需要時(shí)間適應(yīng)
- 許可證限制:AGPL協(xié)議對(duì)商業(yè)使用有限制
- 內(nèi)存占用:處理大型文檔時(shí)內(nèi)存消耗較高
- 配置復(fù)雜:模塊化設(shè)計(jì)增加了依賴管理的復(fù)雜度
六、不同版本差異對(duì)比
| 特性 | iText 5.x | iText 7.x/9.x | 說明 |
|---|---|---|---|
| 架構(gòu)設(shè)計(jì) | 單體架構(gòu) | 模塊化設(shè)計(jì) | iText 9按功能拆分為多個(gè)jar |
| API設(shè)計(jì) | 傳統(tǒng)API | 現(xiàn)代化API | iText 9 API更清晰一致 |
| 條形碼支持 | 內(nèi)置核心 | 獨(dú)立模塊 | iText 9需要單獨(dú)引入barcodes |
| 性能表現(xiàn) | 一般 | 優(yōu)化提升 | iText 9底層重構(gòu),性能更好 |
| 學(xué)習(xí)資源 | 豐富 | 相對(duì)較少 | iText 5教程更多,iText 9較新 |
| 維護(hù)狀態(tài) | 維護(hù)模式 | 積極開發(fā) | iText 9是未來發(fā)展方向 |
七、版本選擇建議
選擇iText 5.x的情況
- 維護(hù)遺留項(xiàng)目
- 需要大量現(xiàn)有代碼示例
- 項(xiàng)目對(duì)性能要求不高
- 快速原型開發(fā)
選擇iText 7.x/9.x的情況
- 新項(xiàng)目開發(fā)
- 需要最佳性能
- 長期維護(hù)考慮
- 需要使用最新PDF標(biāo)準(zhǔn)特性
八、最佳實(shí)踐總結(jié)
- 依賴管理:仔細(xì)選擇所需模塊,避免引入不必要的依賴
- 資源清理:使用try-with-resources確保PDF文檔正確關(guān)閉
- 異常處理:妥善處理IO異常和iText特定異常
- 內(nèi)存管理:對(duì)于大文檔,考慮分塊處理和流式輸出
- 字體優(yōu)化:預(yù)加載和復(fù)用字體對(duì)象提升性能
總結(jié)
通過本文的完整示例和詳細(xì)分析,你應(yīng)該能夠在SpringBoot項(xiàng)目中順利集成iText 9.4.0,并根據(jù)具體需求選擇合適的版本和功能模塊。
iText雖然有一定的學(xué)習(xí)成本,但其強(qiáng)大的功能和穩(wěn)定性使其成為企業(yè)級(jí)PDF處理的優(yōu)選方案。
iText官方文檔:https://itextpdf.com/
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot通過接口下載resources下的文件方式
SpringBoot通過接口下載resources目錄文件,解決jar包部署后資源路徑不可直接訪問的問題,利用Resource類加載文件,通過HttpServletResponse返回流,實(shí)現(xiàn)用戶下載功能2025-09-09
SpringBoot Data JPA 關(guān)聯(lián)表查詢的方法
這篇文章主要介紹了SpringBoot Data JPA 關(guān)聯(lián)表查詢的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07
JDK14新特性之switch表達(dá)式的實(shí)現(xiàn)
這篇文章主要介紹了JDK14新特性之switch表達(dá)式的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
SpringCloud之熔斷器Hystrix的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud之熔斷器Hystrix的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
Java正則表達(dá)式之Pattern和Matcher的使用
本文詳細(xì)介紹了Java中處理正則表達(dá)式的Pattern和Matcher類的使用方法和實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-09-09

