参考资料:www.cnblogs.com/wangpeng00700/p/8418594.html

概括:

根据不同的流程实体类并且通过在实体类字段上加上注解,通过反射拿到实体类的注解属性和属性值,通过属性值判断是什么类型的数据,依次给pdf模板中的不同类型的占位符赋值,打印此流程的pdf。

所需依赖:

<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.4.3</version>
</dependency>   

上代码:

package com.example.demo.utils;/*** @ClassName:PDFUtils* @Package:com.example.demo.utils* @Description: com.example.demo.utils.PDFUtils:* @date:2022/2/24 10:27* @author:bsm*/import com.example.demo.PDFFill;
import com.example.demo.TestPojo;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Slf4j
public class PdfUtils {public static String toPDF(int flowType, Object data) {Map<String, String> datamap = new HashMap();Map<String, String> imgmap = new HashMap();Map<String, Object> resultMap = new HashMap();String templatePath = "";String newPDFPath = "";if(System.getProperty("os.name").toLowerCase().contains("win")){templatePath = "E:\\shengtingPDF\\src\\main\\resources\\pdflocation\\"+ flowType +".pdf";newPDFPath = "E:\\shengtingPDF\\src\\main\\resources\\pdflocation\\"+ flowType +"out.pdf";}else{templatePath = "/home/pdflocation/"+ flowType +".pdf";newPDFPath = "/home/pdflocation/"+ flowType +"out.pdf";}//        a) 获取标有自定义注解的属性Class clazz = data.getClass();//获取当前类所有属性List<Field> fieldList = Arrays.asList(clazz.getDeclaredFields());//获取当前类所有方法(get and set)List<Method> methodList = Arrays.asList(clazz.getDeclaredMethods());for (Field field : fieldList) {// b) 根据自定义注解中的类型和占位符名称,将实体类中属性值替换到PDF文件try {//获取当前字段注解PDFFill fieldAnnotation = field.getDeclaredAnnotation(PDFFill.class);//获取get方法Method fieldGetMethod = methodList.stream().filter(method -> method.getName().equalsIgnoreCase("get" + field.getName())).findFirst().get();//注解字段名name:跟实体类的名称对应上String fieldname = fieldAnnotation.name();//实体类中的字段值String fieldString = (String) fieldGetMethod.invoke(data);if (fieldAnnotation.fieldType() == PDFFill.FieldType.STRING) {datamap.put(fieldname, fieldString);}if (fieldAnnotation.fieldType() == PDFFill.FieldType.IMG_URL) {imgmap.put(fieldname, fieldString);}} catch (Exception ex) {log.error("反射异常!", field.getName(), ex);}}resultMap.put("datamap", datamap);resultMap.put("imgmap", imgmap);resultMap.put("templatePath",templatePath);resultMap.put("newPDFPath",newPDFPath);pdfout(resultMap);
//        c) 最终生成PDF文件,返回文件路径return newPDFPath;}// 利用模板生成pdfpublic static void pdfout(Map<String, Object> o) {// 模板路径String templatePath = o.get("templatePath").toString();// 生成的新文件路径String newPDFPath = o.get("newPDFPath").toString();PdfReader reader;FileOutputStream out;ByteArrayOutputStream bos;PdfStamper stamper;try {BaseFont bf = BaseFont.createFont("c://windows//fonts//simsun.ttc,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//            Font FontChinese = new Font(bf, 2, Font.NORMAL);out = new FileOutputStream(newPDFPath);// 输出流reader = new PdfReader(templatePath);// 读取pdf模板bos = new ByteArrayOutputStream();stamper = new PdfStamper(reader, bos);AcroFields form = stamper.getAcroFields();//文字类的内容处理Map<String, String> datemap = (Map<String, String>) o.get("datamap");form.addSubstitutionFont(bf);for (String key : datemap.keySet()) {String value = datemap.get(key);//设置字体大小
//                form.setFieldProperty(key, "textsize", new Float(10), null);form.setField(key, value);}//图片类的内容处理Map<String, String> imgmap = (Map<String, String>) o.get("imgmap");for (String key : imgmap.keySet()) {String value = imgmap.get(key);String imgpath = value;int pageNo = form.getFieldPositions(key).get(0).page;Rectangle signRect = form.getFieldPositions(key).get(0).position;float x = signRect.getLeft();float y = signRect.getBottom();//根据路径读取图片Image image = Image.getInstance(imgpath);//获取图片页面PdfContentByte under = stamper.getOverContent(pageNo);//图片大小自适应image.scaleToFit(signRect.getWidth(), signRect.getHeight());//添加图片image.setAbsolutePosition(x, y);under.addImage(image);}stamper.setFormFlattening(true);// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑stamper.close();Document doc = new Document();
//            Font font = new Font(bf, 2);PdfCopy copy = new PdfCopy(doc, out);doc.open();PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);copy.addPage(importPage);doc.close();} catch (IOException e) {System.out.println(e);} catch (DocumentException e) {System.out.println(e);}}public static void main(String[] args) {log.info("生成pdf中.......");TestPojo testPojo = new TestPojo();String pdfPath = toPDF(1, testPojo);log.info("生成pdf完毕.......");log.info("pdf路径:"+pdfPath);}
}
package com.example.demo;import lombok.Data;/*** @ClassName:TestPojo* @Package:com.example.demo* @Description: com.example.demo.TestPojo:* @date:2022/2/24 16:38* @author:bsm*/
@Data
public class TestPojo {@PDFFill(name = "fill1",fieldType = PDFFill.FieldType.STRING)private String fill1 = "aaa";@PDFFill(name = "fill2",fieldType = PDFFill.FieldType.STRING)private String fill2 = "aaa";@PDFFill(name = "fill3",fieldType = PDFFill.FieldType.STRING)private String fill3 = "aaa";@PDFFill(name = "fill4",fieldType = PDFFill.FieldType.STRING)private String aaa = "12321321311232131";@PDFFill(name = "img",fieldType = PDFFill.FieldType.IMG_URL)private String img = "C:\\Users\\bsm\\Desktop\\ceshiPDF\\img.jpg";}
package com.example.demo;import java.lang.annotation.*;/*** @ClassName:Tee* @Package:com.example.demo* @Description: com.example.demo.Tee:* @date:2022/2/24 14:52* @author:bsm*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public  @interface  PDFFill {String name()   default "";FieldType fieldType() default FieldType.STRING;enum FieldType {STRING,INTEGER,DOUBLE,IMG_URL}}

程序中的字体在这:

先放个效果图:(字体默认的是在设置的框内,可以在设计pdf模板的时候设置字体的大小,也可以在程序中设置字体大小<在for循环中的那个注释打开>,通过程序设置的是统一的字体格式,可以使用自定义注解属性注解实体类中的需要单独样式的字段,然后在for循环中判断有无这个注解属性来并且根据这个注解属性的值去设置此字段的字体格式)

下面是详细的步骤:

1.首先,新建一个word文档,内容如下,另存为pdf格式,我的命名:testform.docx。testform.pdf。

2.下载Adobe Acrobat DC,打开并且如下操作:

选择刚刚转好的pdf:

打开之后在需要填充字段的地方加上占位符:(可以ctrl+左箭头复制也可以点击如下图的位置:)

文本域和img都要和程序中的名称一 一对应。

然后将带有占位符的文件保存为:testformfimished.pdf,并且这个文件的位置写在程序中

templatePath的值上。

修改程序中的

newPDFPath(打印的位置)

运行程序:

打开testout1.pdf:

java(itextpdf)根据不同实体类后台打印对应pdf(与thymeleaf或者freemarker不同的是:不需要写html,css等前端内容)相关推荐

  1. java中如何遍历实体类的属性和数据类型以及属性值

    package com.walkerjava.test;import java.lang.reflect.Field;import java.lang.reflect.InvocationTarget ...

  2. js转Java的list_JS之JSON字符串到后台用Java转换成List实体类

    重点:JAVA之JSON字符串转换LIST实体类 ​​​​​​​Listlist = new ArrayList(); list = JSONObject.parseArray(strResult, ...

  3. java实现ListObject转List实体类,java实现Object转对象,java实现Object转实体类

    摘要:在java开发中,我们常常会遇到Object转对象的情况,最近我就遇到了这个问题,现在记录一下,方便日后自己查看复习! 一:查询Object类型的集合对象的方法如下: List topicLis ...

  4. JAVA——实现json bean实体类的传参校验模板及注解详解

    关注微信公众号:CodingTechWork,一起学习进步. 引言   在java开发中,经常需要和外界系统进行参数对接,api设计中难免会遇到json传参不一致的情况,虽然纸面或者接口规范约束了应该 ...

  5. java vo转map_javabean实体类对象转为Map类型对象的方法(转发)

    //将javabean实体类转为map类型,然后返回一个map类型的值 public static Map beanToMap(Object obj) { Map params = new HashM ...

  6. java中的万能实体类

    版权声明 万能实体类可以少写一些代码,挺方便的一个工具包 版权声明:本文由 低调小熊猫 发表于 低调小熊猫的博客 转载声明:自由转载-非商用-非衍生-保持署名,非商业转载请注明作者及出处,商业转载请联 ...

  7. [JAVA EE]常用的实体类注解

    注解 作用 @Entity 指定当前类是实体类,对应数据库中的一个表. @Table 指定表名,当实体类与其映射的数据库表名不同名时需要使用 @Table注解说明,同名则可省略. @Id 定当前字段是 ...

  8. java 怎么快速创建实体类_java编程使用eclipse如何快速创建一个实体类

    一. 创建一个实体类如下package pojo; public class GoodsModel { private String goodsname; private double goodspr ...

  9. 【java学习】常用实体类--String、StringBuffer\StringTokenizer

    文章目录 参数传递 String String类有两个常用构造方法: 引用String常量 String类的常用方法 StringBuffer和StringBuilder StringBuilder中 ...

最新文章

  1. java kryo_Kryo框架使用方法代码示例
  2. JavaWeb中使用session保持用户登录状态
  3. OSMboxPost()
  4. 第三章 python数据规整化
  5. Intel Realsense D435 pyrealsense2 get_option_range() 获取rs.option中参数值取值范围 获取默认值
  6. php mongodb连接数据库,PHP下 Mongodb 连接远程数据库的实例代码
  7. 在php100 防恶意注册这个需要怎么填,WordPress防止恶意注册代码
  8. CodeForces 139C Literature Lesson(模拟)
  9. Stata和Matlab联合处理金融数据
  10. 相对开音节java,L314 单音节词读音规则(二)-元音字母发音规则
  11. linux/centos shell脚本中非交互式修改密码
  12. android9.0官方下载,安卓9.0系统安装包下载
  13. 微信小程序开源源码汇总
  14. java栅格化,UI设计要不要用栅格化布局?
  15. WebRTC 非常适用于智能家庭安防摄像头
  16. 配置 hosts 浏览器访问仍然不生效
  17. 国产分布式数据库在证券行业的应用及实践
  18. Project2019安装步骤
  19. 【区块链】从一笔交易看区块链运作流程
  20. ubuntu windows双系统时间不一致

热门文章

  1. seo是什么?seo技术又是什么?
  2. 解决SQLSERVER2019无法通过SQLCMD登陆找不到或无法访问服务器。请检查实例名称是否正确
  3. 项目经理必读的500页!PMBOK图解项目管理!「PMP经典最全PPT」
  4. 明哥之家的又一个博客
  5. 干翻Mybatis源码系列之第八篇:Mybatis二级缓存的创建和存储
  6. maven中央仓库地址(支持db2,informix等)
  7. AI热门有趣的免费应用工具和资源分享(部分免费免登录)
  8. mysql 修改端口 用户名密码_MYSQL修改端口及密码
  9. 用云理念进行3D打印——魔猴网创始人张勇访谈
  10. Mac开机后键盘和触控板失灵