java 代码实现电子签章(表格+签章)简单版本 注:使用的是springcloud项目
导入依赖 注:导入依赖不只有pdf的还有其他依赖
<dependencies> <!--eureka 注册中心的客户端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--加入ribbon的配置--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>com.zhenzikj</groupId> <artifactId>zhenzisms</artifactId> <version>2.0.2</version> </dependency> <!--hystrix 依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <!--加入openfegin依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--监控程序依赖--> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-client</artifactId> <version>2.2.4</version> </dependency> <!--加入配置中心的依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!--springboot web程序--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--mybatis-plus依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency> <!--mybatis-plus-generator 代码生成器--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.1</version> </dependency> <!--mysql的驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> </dependency> <!--redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--引入支付sdk--> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.31.72.ALL</version> </dependency> <!--xxl-job 分布式任务调度依赖--> <dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.3.0</version> </dependency> <!--alibaba easyexcel--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.5</version> </dependency> <!--bootstrap 通过配置中心更改微服务配置--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> <version>3.1.1</version> </dependency> <!--发送邮件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <!--kafka的配置--> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency> <!-- 字体 --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency> <!-- 设置pdf文件密码 --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.54</version> </dependency> <!-- pdf 转 图片 --> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.12</version> </dependency> <!-- pdf --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-image-generator</artifactId> <version>7.0.0.Beta2</version> </dependency> <!--svg转png--> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-transcoder</artifactId> <version>1.13</version> </dependency> <dependency> <groupId>batik</groupId> <artifactId>batik-util</artifactId> <version>1.6-1</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-codec</artifactId> <version>1.7</version> </dependency> <!--引入email--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-core</artifactId> <version>1.5.22</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.9</version> </dependency> </dependencies>
加入配置yml文件 注:application.yml没有pdf配置,配置直接写在controller类中
server: port: 80 #pdf: # enable: true # domain: http://localhost:${server.port}/ # pdf-ks: D:\keystore\server.keystore # pdf-ks-pass: 123456 # x: 400 # y: 400 # width: 200 # height: 200 # sign-pic-name: sign.png # path: D:\pic\ # font: D:\fonts\simsun.ttc spring: application: name: leavepdf datasource: url: jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true username: xxx password: xxx type: com.alibaba.druid.pool.DruidDataSource //日志 注:类别info logging: level: root: info
整体代码 注:别导错包
package com.bw.controller; import java.io.*; import java.net.URLEncoder; import java.security.*; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.util.List; import java.util.UUID; import cn.hutool.core.util.IdUtil; import com.bw.domain.Leave; import com.bw.domain.User; import com.bw.service.LeaveService; import com.bw.service.UserService; import com.itextpdf.kernel.font.PdfSimpleFont; import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; import org.bouncycastle.jce.provider.BouncyCastleProvider; import com.itextpdf.text.pdf.security.BouncyCastleDigest; import com.itextpdf.text.pdf.security.DigestAlgorithms; import com.itextpdf.text.pdf.security.ExternalDigest; import com.itextpdf.text.pdf.security.ExternalSignature; import com.itextpdf.text.pdf.security.MakeSignature; import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard; import com.itextpdf.text.pdf.security.PrivateKeySignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.print.Doc; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import static com.bw.controller.Hello.*; @RequestMapping("pdf") @RestController public class pdfController { public static final String KEYSTORE="ks/whj.p12"; public static final char[] PASSWORD="123456".toCharArray(); @Autowired UserService userService; @RequestMapping("pdflist") public String pdflist(HttpServletResponse response) throws DocumentException, GeneralSecurityException, IOException { List<User> list = userService.list(); //生成唯一的文件名 String filename = IdUtil.getSnowflakeNextIdStr()+".pdf"; //必要响应代码,必须写 response.setContentType("application/pdf"); //加上这行代码就是下载,不加就是预览 // response.addHeader("Content-Disposition","attachment;filename="+filename); //开启pdf Document document = new Document(); PdfWriter instance = PdfWriter.getInstance(document, new FileOutputStream(filename)); document.open(); //更改pdf的字体问题,防止因为字体出现乱码 //解决乱码问题 BaseFont baseFont = null; baseFont=BaseFont.createFont("D:/fonts/SIMLI.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); Font font = new Font(); font.setColor(BaseColor.BLUE); font.setSize(12); //开始进行pdf的表格的设置 注:参数为数据库有几个字段就写几 PdfPTable pdfPTable = new PdfPTable(3); pdfPTable.addCell(new Paragraph("id",font)); pdfPTable.addCell(new Paragraph("name",font)); pdfPTable.addCell(new Paragraph("password",font)); //循环列表将pdf存入 for (User user:list){ pdfPTable.addCell(new Paragraph(user.getId()+"",font)); pdfPTable.addCell(new Paragraph(user.getName()+"",font)); pdfPTable.addCell(new Paragraph(user.getPassword()+"",font)); } document.add(pdfPTable); document.close(); //https://kb.itextpdf.com/home/it5kb/examples/digital-signatures-chapter-2#Digitalsignatureschapter2-c2_07_signatureappearances //c2_07_signatureappearances第二段代码 BouncyCastleProvider provider = new BouncyCastleProvider(); Security.addProvider(provider); KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(new FileInputStream(KEYSTORE), PASSWORD); String alias = (String)ks.aliases().nextElement(); PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD); Certificate[] chain = ks.getCertificateChain(alias); //需要更改的图片路径 Image image = Image.getInstance("D:/pic/36693-111jpg/sign.png"); //https://kb.itextpdf.com/home/it5kb/examples/digital-signatures-chapter-2#Digitalsignatureschapter2-c2_07_signatureappearances //c2_07_signatureappearances第一段代码 //加入文件的名称 PdfReader reader = new PdfReader(filename); //本行注释,文件的流在下面设置 // FileOutputStream os = new FileOutputStream(dest); //输出流 通过响应创建一个 ServletOutputStream outputStream = response.getOutputStream(); PdfStamper stamper = PdfStamper.createSignature(reader,outputStream, '\0'); PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); //更改reason和location内容为String类型即可,可随意 appearance.setReason("原因"); appearance.setLocation("位置"); //签章的位置,参数尽量固定 appearance.setVisibleSignature(new Rectangle(400,100,100,780),1,"sig"); //这行可以注释,没有作用 // appearance.setLayer2Text("Signed on " + new Date().toString()); //粘贴后加入的新数据(两行),尽量固定 appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS); appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC); appearance.setSignatureGraphic(image); // Creating the signature下面一行无用注释 // PrivateKeySignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider); ExternalDigest digest = new BouncyCastleDigest(); //新加入的字段 PrivateKeySignature signature = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, provider.getName()); //三个参数 MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, MakeSignature.CryptoStandard.CMS); outputStream.close(); return "111111111"; } }