当前位置: 首页 > news >正文

【Java】Springboot集成itextpdf制作pdf(内附pdf添加表格、背景图、水印,条形码、二维码,页码等功能)

目录

  • 前言
    • 一、引入依赖
    • 二、整体思路与步骤
    • 三、代码实现(完整例子)
      • 1、创建一个接口
      • 2、创建自定义事件处理器
      • 3、创建一个实现类
      • 4、写一个控制器调用接口
      • 5、启动springboot项目,浏览器调用接口

前言

  iTextPDF 是一个用于创建和操作 PDF 文档的 Java 库。它功能强大,支持生成、修改、加密、签名 PDF 文件,二维码、条形码生成等操作,本文使用iTextPDF的8.0.5版本,总结了利用iTextPDF技术来实现pdf生成的各种操作,如果大家在项目中有pdf生成的需求可以按照此篇文章的例子来实现。

一、引入依赖

  在pom文件中引入如下依赖
1、itextpdf核心包

<dependency><groupId>com.itextpdf</groupId><artifactId>itext-core</artifactId><version>8.0.5</version><type>pom</type>
</dependency>

2、中文字体支持包

<dependency><groupId>com.itextpdf</groupId><artifactId>font-asian</artifactId><version>8.0.5</version>
</dependency>

3、二维码和条形码包

<dependency><groupId>com.itextpdf</groupId><artifactId>barcodes</artifactId><version>8.0.5</version>
</dependency>

4、加密相关包(如无pdf加密可以不引入)

<dependency><groupId>com.itextpdf</groupId><artifactId>kernel</artifactId><version>8.0.5</version>
</dependency>

二、整体思路与步骤

  一般情况下我们生成的pdf大概包含标题、正文、页眉、页脚、字体、背景、水印、表格、加密等这些元素,由于生成的pdf可能存在多页,所以像是页眉、页脚、背景、水印这些元素需要每一页都存在,特别是页脚中的页码数字还需要随着页数增加自动填充,iTextPDF 提供了一个IEventHandler(事件处理器)接口,我们通过实现这个接口就可以自定义实现上述效果,可以在每一页插入元素。
  整体的pdf生成思路如下:

1、创建ByteArrayOutputStream输出流对象,用于存放数据
2、创建WriterProperties配置项对象,此配置可以设置pdf加密等内容
3、创建PdfDocument文档对象并且添加流对象和配置对象
4、创建自定义事件处理器并添加,用于处理页眉页脚等内容
5、创建字体PdfFont对象,用于pdf文档统一字体
6、创建PageSize页面尺寸对象,用于设置pdf尺寸,一般也就是A4
7、通过PdfDocument对象创建Document文档对象并且设置尺寸
8、通过Document文档对象设置字体、创建标题、段落、表格等等我们业务所需要的内容
9、上述步骤处理完毕后数据就已经存在于ByteArrayOutputStream输出流中,然后将流响应到浏览器下载

三、代码实现(完整例子)

  根据上述步骤进行详细代码编写,本篇文章通过实现一个接口实现pdf生成并响应到浏览器下载的效果,这也是常见的开发需求,如果大家在项目中有遇到的可以直接看这个例子,只需要根据自己的业务删减修改即可。

1、创建一个接口

  创建一个生成pdf接口PdfService,创建一个生成pdf的方法generatePdf传入一个响应对象用于后续调用时候响应到浏览器下载

import javax.servlet.http.HttpServletResponse;/*** @Author: 你住过的屋檐* @aphorism You are lucky to have someone to help you.No one to help you, is just fate.No one should do anything for you, because life is your own, you are responsible for yourself*/
public interface PdfService {
/*** 生成pdf* @param response*/void generatePdf(HttpServletResponse response);
}

2、创建自定义事件处理器

  事件处理器中处理页眉、页脚、二维码、条形码、背景等内容,下面代码中每一处都有详细的说明,大家一看就可以明白

import com.itextpdf.barcodes.Barcode128;
import com.itextpdf.barcodes.BarcodeQRCode;
import com.itextpdf.barcodes.qrcode.EncodeHintType;
import com.itextpdf.barcodes.qrcode.ErrorCorrectionLevel;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.AffineTransform;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Div;
import com.itextpdf.layout.element.Image;
import lombok.Data;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;/*** @Author: 你住过的屋檐* @aphorism You are lucky to have someone to help you.No one to help you, is just fate.No one should do anything for you, because life is your own, you are responsible for yourself* 该类实现了给pdf添加背景图、水印,条形码、二维码,页码功能,大家有需要自行看代码,注释写的很详尽*/
@Data
public class PdfHeaderFooter implements IEventHandler {@Overridepublic void handleEvent(Event event) {if (event instanceof PdfDocumentEvent) {PdfDocumentEvent e = (PdfDocumentEvent) event;//获取pdf文档对象PdfDocument pdfDocument = e.getDocument();//获取当前文档的页面对象,PdfPage 表示 PDF 文档中的单个页面,提供了对该页面的操作接口PdfPage page = e.getPage();//获取当前页面尺寸信息Rectangle pageSize = page.getPageSize();float pageWidth = page.getPageSize().getWidth() ;float pageHeight = page.getPageSize().getHeight() ;//获取当前页页码int pageNumber = pdfDocument.getPageNumber(page);//获取总页数int totalPages = pdfDocument.getNumberOfPages();//转换为文档对象,该对象可以用来添加元素,比如文本、图片、表格等Document document = new Document(pdfDocument);//创建字体PdfFont chineseFont;try {chineseFont = PdfFontFactory.createFont("font/SimHei.ttf");} catch (IOException ex) {throw new RuntimeException(ex);}//一、添加背景图**************************************************************************try {ImageData image = ImageDataFactory.create("src/main/resources/images/理查德.jpg");PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDocument);// 设置透明度,setFillOpacity(0.5f)将透明度设置为50%PdfExtGState gState = new PdfExtGState();gState.setFillOpacity(0.2f); // 设置透明度,0.0完全透明,1.0完全不透明//保存当前的 PDF 绘制状态canvas.saveState();//设置扩展图形状态,这里是设置透明度canvas.setExtGState(gState);/*用于在 PDF 页面上添加图像,并允许通过变换矩阵来控制图像的位置、大小和旋转等属性addImageWithTransformationMatrix方法一共有8个参数,第一个参数是图片数据,最后一个参数代表是否将图像内联到 PDF 中。内联图像通常用于小图像,可以减少文件大小,但可能会影响性能。从第二个参数开始a-f,a 和 d:控制图片在 X 和 Y 方向上的缩放。b 和 c:控制图片的旋转和倾斜。e:图片在 X 轴上的偏移量。f:图片在 Y 轴上的偏移量。*///设置图片在x和y方向的缩放为页的尺寸,这样图片就能覆盖整个页面,同事我也不需要旋转和倾斜,所以将b和C参数设置为0canvas.addImageWithTransformationMatrix(image, pageWidth, 0, 0, pageHeight, 0, 0, false);//当调用 restoreState() 时,对应canvas.saveState();,会从内部栈中弹出最近一次保存的状态,并将其应用到当前的 PdfCanvas 上。这样可以确保之前的绘制操作不会影响后续的绘制canvas.restoreState();//二、添加水印**************************************************************************//下面设计一个居中倾斜45度的文字水印String watermarkText = "你住过的屋檐制作";// 旋转水印canvas.saveState();canvas.setFillColor(ColorConstants.LIGHT_GRAY);canvas.setFontAndSize(chineseFont, 30);float fontWidth = chineseFont.getWidth(watermarkText, 30);// 旋转45度(弧度制)double angle = Math.toRadians(45);// 构建旋转矩阵,因为是倾斜45度,根据三角函数计算文字占用宽和高,因为是45度等腰直角三角形,所以宽和高相等double fontWidthHeight = Math.sin(angle) * fontWidth;AffineTransform transform = new AffineTransform(Math.cos(angle), Math.sin(angle), // a, b-Math.sin(angle), Math.cos(angle), // c, d(pageWidth -fontWidthHeight)/ 2, (pageHeight -fontWidthHeight) / 2 // e, f (平移至中心点));canvas.concatMatrix(transform); // 移动到中心canvas.beginText();canvas.showText(watermarkText);canvas.endText();// 恢复画布状态canvas.restoreState();} catch (MalformedURLException ex) {throw new RuntimeException(ex);}//三、添加条形码**************************************************************************String code ="123456789";// 创建一个Code 128类型的高密度条形码Barcode128 code128 = new Barcode128(pdfDocument);StringBuilder sb = new StringBuilder("*");for (int i = 0; i <code.length(); i++) {char c = code.charAt(i);sb.append(c);if (i < code.length() - 1) {sb.append(" ");}}sb.append("*");// 设置条形码的数据code128.setCode(sb.toString());// 设置Code128的密度类型code128.setCodeSet(Barcode128.Barcode128CodeSet.B);// 设置文本基于条形码基线位置code128.setBaseline(code128.getSize() + 10);// 设置数值的堆区方式,默认居中code128.setTextAlignment(Barcode128.ALIGN_CENTER);// 设置条形码宽度code128.fitWidth(180);// 设置条形码高度code128.setBarHeight(42);// 设置条形码文字大小code128.setSize(10);// 转换为formXObject对象和Image对象PdfFormXObject formXObject = code128.createFormXObject(ColorConstants.BLACK, ColorConstants.BLACK, pdfDocument);Image barcodeImage = new Image(formXObject);//Image继承了AbstractElement,正常的一些样式它也有。
//        barcodeImage.setBackgroundColor(new DeviceRgb(0, 0, 0), .1f)
//          .setBorder(new SolidBorder(2)).setBorderRadius(new BorderRadius(3)).setPadding(3);// 创建一个盒子,将条形码放里面Div barcodeDiv = new Div();barcodeDiv
//                .setBorder(new DottedBorder(new DeviceRgb(195, 98, 21), 3))
//                .setBorderRadius(new BorderRadius(5)).add(barcodeImage)// 使用绝对定位.setFixedPosition(40,pageSize.getTop() - 70,barcodeImage.getImageWidth())
//                .setTextAlignment(TextAlignment.CENTER)
//                .setVerticalAlignment(VerticalAlignment.MIDDLE)
//                .setBackgroundColor(new DeviceRgb(187, 255, 255)).setWidth(barcodeImage.getImageWidth() ).setHeight(barcodeImage.getImageHeight());document.add(barcodeDiv);//四、添加二维码**************************************************************************// 设置字符集信息、纠错等级、版本Map<EncodeHintType, Object> hints = new HashMap<>();hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);//hints.put(EncodeHintType.MIN_VERSION_NR,1);// 构建二维码对象,并设置二维码的额外配置BarcodeQRCode qrCode = new BarcodeQRCode("你住过的屋檐", hints);// qrCode.setHints(hints); // 设置二维码的额外配置(这里在构造器上设置了)// 生成PdfFormXObject对象并转换程ImagePdfFormXObject pdfFormXObject = qrCode.createFormXObject( pdfDocument);Image imageA = new Image(pdfFormXObject);// 设置图片的一些样式imageA
//                .setBorder(new SolidBorder(new DeviceRgb(102, 205, 170), 2))
//                    .setBorderRadius(new BorderRadius(5)).setWidth(80).setHeight(80);// 为图片外面套个盒子并定位Div div = new Div().setWidth(80).setHeight(80).add(imageA).setFixedPosition(pageSize.getWidth()-80, pageSize.getHeight()-80,80)
//                .setBorderRadius(new BorderRadius(5))
//                .setBorder(new SolidBorder(new DeviceRgb(102, 205, 170),2))707-12.5-7.5-3.5-20;// 添加二维码document.add(div);//五、添加页脚**************************************************************************//页脚文字内容String pageNumberText = "第" + pageNumber + "页 共" + totalPages + "页";//利用font对象计算文字宽度float fontWidth = chineseFont.getWidth(pageNumberText, 10);float y =10; // 距离底部的距离,可以根据需要调整float x = (pageSize.getWidth()-fontWidth)/2;//这样计算即可实现页码居中显示的效果// 创建画布PdfCanvas canvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDocument);canvas.beginText()//开始文本绘制.moveText(x , y)//设置起始位置(x:从左到右的距离,y:从下到上的距离).setFontAndSize(chineseFont, 10) // 设置字体大小.showText(pageNumberText) //添加页脚内容.endText();//结束文本绘制}}
}

3、创建一个实现类

  创建一个实现类PdfServiceImpl,实现generatePdf方法,用于写具体pdf生成逻辑

import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.EncryptionConstants;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.WriterProperties;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.UnitValue;
import com.technology.learning.service.PdfService;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.UUID;
/*** @Author: 你住过的屋檐* @aphorism You are lucky to have someone to help you.No one to help you, is just fate.No one should do anything for you, because life is your own, you are responsible for yourself*/
@Service
public class PdfServiceImpl implements PdfService {@Overridepublic void generatePdf(HttpServletResponse response) {//开始生成pdftry {//创建输出流ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();String userPassword = "123"; // 用户密码(打开PDF时需要)String ownerPassword = "456"; // 所有者密码(用于修改权限)WriterProperties writerProperties = new WriterProperties().setStandardEncryption(userPassword.getBytes(), // 用户密码ownerPassword.getBytes(), // 所有者密码EncryptionConstants.ALLOW_PRINTING, // 允许打印EncryptionConstants.ENCRYPTION_AES_256 // 使用AES-256加密,这个在jdk1.8是不支持的需要换高级版本或者);// 创建并初始化一个PDF文档和文档的创建PdfDocument pdfDocument = new PdfDocument(new PdfWriter(byteOutputStream,writerProperties));// 添加一个事件处理器,设置页眉和页脚,END_PAGE页面结束时处理,通过处理器可以设置pdf在每页都显示的元素,比如页眉、页脚等,PdfHeaderFooter是一个自定义的实现类pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new PdfHeaderFooter());/*** STSongStd-Light: 这是一种简体中文字体,类似于宋体(Song Style),但较轻(Light)。它通常用于在 PDF 文档中显示简体中文文本。* UniGB-UCS2-H: 这是字符编码集,表示使用 Unicode 编码来处理字符。UniGB-UCS2-H 特别用于简体中文字符集。*/PdfFont chineseFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H");//内置字体// 定义页面大小PageSize pageSize = new PageSize(PageSize.A4);//A4/* 为什么要通过PdfDocument创建Document?PdfDocument 的作用PdfDocument 是一个低级别的 API,用于直接操作 PDF 文件的底层结构。它负责管理 PDF 的页面、对象、加密、事件等底层内容。通过 PdfDocument,你可以创建和管理 PDF 的物理结构。Document 的作用Document 是一个高级别的 API,提供更友好的接口来布局和添加内容到 PDF 中。它封装了复杂的布局逻辑,允许开发者以更简单的方式添加段落、表格、图片等内容。Document 会自动处理分页、文本对齐、缩进等排版问题。为什么要进行转换?Document 类通过封装 PdfDocument,提供了更高层次的抽象,使开发者能够更方便地向 PDF 添加内容。*/Document document = new Document(pdfDocument,pageSize);document.setFont(chineseFont);// 设置文本颜色//document.setFontColor(ColorConstants.WHITE);document.setTopMargin(80);//创建一个黑体字体给标题,这里我加载的本地字体文件,提前将字体文件放入resources/font目录下,字体文件大家可以在windows下C:\Windows\Fonts目录下找,也可以自行网络查找PdfFont fontHei = PdfFontFactory.createFont("font/SimHei.ttf");// 设置文本的字体、大小、颜色、背景颜色、对齐方式、垂直对其方式Paragraph title1 = new Paragraph("梦中的婚礼").setFontSize(20).setFont(fontHei).setBold().setMarginTop(5f).setTextAlignment(TextAlignment.CENTER);
//                .setVerticalAlignment(VerticalAlignment.BOTTOM);document.add(title1);//副标题Paragraph title2 = new Paragraph("Marry in Dream").setFontSize(12).setFont(chineseFont).setTextAlignment(TextAlignment.CENTER).setPaddingTop(0);document.add(title2);//演奏者Paragraph musician = new Paragraph("理查德 克莱德曼").setFontSize(12).setFont(chineseFont).setTextAlignment(TextAlignment.RIGHT).setPaddingTop(0);document.add(musician);Paragraph content = new Paragraph("梦之国的边境,一堆篝火冉冉升起,绵延,缭绕……望着远处高高的城堡,他又回想起过去的一切。这次回来,他不知道是对是错,但他却无法不回到梦之国。离开6年,是该回来了。暗夜里流星划过,留下了一道道眩目的光辉。他依然记得第一次看到流星时,他的心中忽然有一种很失落的感觉:流星是不幸的,它的爱在天上,但是,从它成为陨落的那一刻起,它就注定了永远不能拥有它追求的爱。然而,他的老师却对他说,一个人在最幸福的时候死去,那么,他的灵魂就会成为一颗流星。他永远都不能理解这种想法,离开心中的爱,那么幸福还能存在吗?那些伤心的记忆,又一幕幕的在他脑中重现。那一年的冬天,也是下着雪。至今,他还是觉得那一年,就像一场梦。只是,这场梦,他永远都不会醒。认识她的时候,他只是一个14岁的少年,在魔法学院里,他第一次见到了她。那一刻,他有一种感觉:他的生活,将会改变。是的,他的生活,的确改变了,他想不到这位让他以为是上帝遗留在人间的天使的女孩竟是梦之国的公主,他更想不到,他和她竟会成为朋友。然而,他心里却十分清楚的知道,他,永远不可能只当她是朋友。因为,从看到她的那一刻开始,他,就注定了永远逃不掉爱上她的命运。这也注定了他从此将生活在痛苦中。他知道,即使他是多么的爱她,而她却永远不可能爱上一个平凡的人。这使他不敢将这份爱对她说,只能将爱深埋在心底。但是,有一天,他终于压抑不住心中澎湃的感情了,他向她表达了他的爱意……他伤心地离开了梦之国,流浪在外的他,在寒冬中遇到了他正在教他的老师。他的老师收留了他,并教会他种种技能。六年,一转眼过去了。在这六年中,他一直遗忘过去的那一份情感。可思念却像面粉一样不断发酵,随着时间的推移,他反而发现自己更爱她了。六年中,他无时无刻不想她,无时无刻不爱她……告别了老师,他要回梦之国找她。如今他回到了记忆中。当太阳从地平线升起时,他在阳光中走向城堡。城堡中一片喜庆的气氛,到处都挂满了彩旗,人们都欢乐的歌唱着。“今天,难道有什么喜事吗?”他问一位路人。“今天,公主将和邻国的王子举行婚礼!”一刹那,他听到了梦破碎的声音。他呆住了,六年的期盼,在一瞬间,划过他的脸,坠落在雪中。一轮明月升上天空。当教堂的钟声响起时,他缓缓的朝教堂走去。无论如何,他都要见她一面。人们早已在王宫到教堂的路上等候着公主的到来。他站在人群中,静静地等待着。当公主牵着王子的手,走出王宫时,人群沸腾了。他注视着公主的脸,这是他最后一次看到她了,从今以后,他将永远离开梦之国,他立誓要忘掉所有的记忆,忘掉所有的痛,忘掉深深的爱……当她走过他前面时,他们的眼神碰到了一起。忽然,他拨开阻挡着人群的卫兵,冲上前去。卫兵拔出配剑,但是迟了,他已冲到了公主前面,他张开了手臂,那一刻,他看到了公主惊恐的表情。“别怕,我会保护你的。”他轻轻地说。他感到后背一阵刺痛,他听到了利箭穿过身体的声音。缓缓的,他倒在她脚下。在刚才,没有人看到,对面的人群中,一支弓箭对着公主。他睁开眼,她穿着婚纱,含笑看着他。在他们旁边,天使为他们唱着。“这是梦吗?”他喃喃的说。“有梦,就够了。”他握紧了她的手。一颗流星划过城堡的上空,仿如一滴幸福的泪……").setFontSize(12).setFont(chineseFont).setTextAlignment(TextAlignment.JUSTIFIED)//设置首行缩进两个字符,两个字符距离我们可以用PdfFont的getWidth方法计算得出.setFirstLineIndent(chineseFont.getWidth("字符",12));document.add(content);//发行信息Paragraph title3 = new Paragraph("发行信息").setFontSize(12).setFont(fontHei).setTextAlignment(TextAlignment.LEFT).setBold();document.add(title3);//生成表格Table table = generateTable();document.add(table);document.close();// 创建输入流资源ByteArrayInputStream in = new ByteArrayInputStream(byteOutputStream.toByteArray());// 设置响应头,通知浏览器下载response.setContentType("application/force-download");String fileName= URLEncoder.encode(UUID.randomUUID().toString() +".pdf","utf-8");response.setHeader("Content-disposition", "attachment; filename="+fileName );response.setContentLength(in.available());OutputStream out = response.getOutputStream();byte[] b= new byte[1024];int len;while((len=in.read(b))!=-1){out.write(b,0,len);}//用于强制将缓冲区中的数据立即写入到目标输出流中,避免数据丢失。out.flush();//关闭输出流并释放资源out.close();//关闭输入流并释放资源in.close();} catch (IOException e) {throw new RuntimeException(e);}}/*** 生成一个表格* @return*/private Table generateTable() {Table table = new Table(10);//宽度设置为页面宽度的 100%自动适应页面大小table.setWidth(UnitValue.createPercentValue(100));//通过addHeaderCell()方法添加表头,new Cell()可以传入两个数字参数,代表合并行和列,默认为1(不合并)table.addHeaderCell(new Cell().add(new Paragraph("发行日期").setBold()));table.addHeaderCell(new Cell().add(new Paragraph("收录专辑").setBold()));table.addHeaderCell(new Cell().add(new Paragraph("唱片公司").setBold()));table.addHeaderCell(new Cell().add(new Paragraph("发行形式").setBold()));//第二行table.addCell(new Cell().add(new Paragraph("1979年1月1日")));table.addCell(new Cell().add(new Paragraph("《Lettre à ma mère》")));table.addCell(new Cell().add(new Paragraph("Union Square Music")));table.addCell(new Cell().add(new Paragraph("随专辑发行")));return table;}
}

4、写一个控制器调用接口

  创建一个端点调用,pdf需要背景图,背景图我附在后面了,大家可以随意换一个图也行

import com.technology.learning.service.PdfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
/*** @Author: 你住过的屋檐* @aphorism You are lucky to have someone to help you.No one to help you, is just fate.No one should do anything for you, because life is your own, you are responsible for yourself*/
@RestController
@RequestMapping()
public class PdfController {@Autowiredprivate PdfService pdfService;@GetMapping("/generatePdf")public void generatePdf(HttpServletResponse response){pdfService.generatePdf(response);}
}

理查德·克莱德曼

5、启动springboot项目,浏览器调用接口

  浏览器输入127.0.0.1:8080/generatePdf
在这里插入图片描述
打开pdf输入我们设定的密码,如下所示效果

在这里插入图片描述

为了帮助更多像你一样的读者,我将持续在专栏中分享技术干货和实用技巧。如果你觉得这篇文章对你有帮助,可以考虑关注我的专栏,谢谢。


http://www.mrgr.cn/news/95876.html

相关文章:

  • 从医疗大模型到综合医疗智能体:算法、架构与路径全流程分析
  • aws S3利用lambda edge实现图片缩放、质量转换等常规图片处理功能
  • Java 线程池全面解析
  • Linux输入系统应用编程
  • 【linux重设gitee账号密码 克隆私有仓库报错】
  • 3、孪生网络/连体网络(Siamese Network)
  • 【WebGIS教程1】WebGIS学习初步知识了解 · 概述
  • 2025最新版Ubuntu Server版本Ubuntu 24.04.2 LTS下载与安装-详细教程,细致到每一步都有说明
  • Linux--环境变量
  • 向量数据库学习笔记(1) —— 基础概念
  • djinn: 1靶场渗透测试
  • 微服务面试题:分布式事务和服务监控
  • 中学数学几百年重大错误:将无穷多各异假R误为R——两数集相等的必要条件
  • 万字C++STL——vector模拟实现
  • STM32内部时钟输出比较OC(学习笔记)
  • 常用的离散时间傅里叶变换(DTFT)对
  • Langchain中的表格解析:RAG 和表格的爱恨情仇
  • 深入 SVG:矢量图形、滤镜与动态交互开发指南
  • Python进阶编程总结
  • 定长内存池原理及实现