一、什么是iText?

iText 是一个非常著名的能够快速产生 PDF 文件的 Java 类库。支持文本,表格,图形的操作,可以方便的跟 Servlet 进行结合。

二、项目集成iText

 1、pom文件引入依赖

<!--生成pdf 写pdf文件-->
<!--pdf start-->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.6</version>
</dependency>
<!-- pdf写中文文本必备 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>
<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.7</version>
</dependency>
<!--pdf end-->

2、页码工具类(生成的pdf会显示页码)

package com.baosight.wbplat.common.pdf;


import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import java.io.IOException;


public class PDFBuilder extends PdfPageEventHelper {






    /**
     * 页眉
     */
    //public String header = "itext测试页眉";


    /**
     * 文档字体大小,页脚页眉最好和文本大小一致
     */
    public int presentFontSize = 12;


    /**
     * 文档页面大小,最好前面传入,否则默认为A4纸张
     */
    public Rectangle pageSize = PageSize.A4;


    // 模板
    public PdfTemplate total;


    // 基础字体对象
    public BaseFont bf = null;


    // 利用基础字体生成的字体对象,一般用于生成中文文字
    public Font fontDetail = null;


    /**
     *
     * Creates a new instance of PdfReportM1HeaderFooter 无参构造方法.
     *
     */
    public PDFBuilder() {


    }


    /**
     *
     * Creates a new instance of PdfReportM1HeaderFooter 构造方法.
     *
     * @param
     *
     * @param presentFontSize
     *            数据体字体大小
     * @param pageSize
     *            页面文档大小,A4,A5,A6横转翻转等Rectangle对象
     */
//    public PDFBuilder(String yeMei, int presentFontSize, Rectangle pageSize) {
//        this.header = yeMei;
//        this.presentFontSize = presentFontSize;
//        this.pageSize = pageSize;
//    }
    public PDFBuilder( int presentFontSize, Rectangle pageSize) {
        this.presentFontSize = presentFontSize;
        this.pageSize = pageSize;
    }


//    public void setHeader(String header) {
//        this.header = header;
//    }


    public void setPresentFontSize(int presentFontSize) {
        this.presentFontSize = presentFontSize;
    }


    /**
     *
     * TODO 文档打开时创建模板
     *
     * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(com.itextpdf.text.pdf.PdfWriter,
     *      com.itextpdf.text.Document)
     */
    public void onOpenDocument(PdfWriter writer, Document document) {
        total = writer.getDirectContent().createTemplate(50, 50);// 共 页 的矩形的长宽高
    }


    /**
     *
     * TODO 关闭每页的时候,写入页眉,写入'第几页共'这几个字。
     *
     * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(com.itextpdf.text.pdf.PdfWriter,
     *      com.itextpdf.text.Document)
     */
    public void onEndPage(PdfWriter writer, Document document) {
        this.addPage(writer, document);
        //this.addWatermark(writer);
    }


    //加分页
    public void addPage(PdfWriter writer, Document document){
        //设置分页页眉页脚字体
        try {
            if (bf == null) {
                bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
            }
            if (fontDetail == null) {
                fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


        // 1.写入页眉
//        ColumnText.showTextAligned(writer.getDirectContent(),
//                Element.ALIGN_LEFT, new Phrase(header, fontDetail),
//                document.left(), document.top() + 20, 0);
        // 2.写入前半部分的 第 X页/共
        int pageS = writer.getPageNumber();
        //String foot1 = "第 " + pageS + " 页 /共";
        String foot1 = pageS  +"/";
        Phrase footer = new Phrase(foot1, fontDetail);


        // 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,字体长度也要计算进去 = len
        float len = bf.getWidthPoint(foot1, presentFontSize);


        // 4.拿到当前的PdfContentByte
        PdfContentByte cb = writer.getDirectContent();


        // 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0F
        // 再给偏移20F适合人类视觉感受,否则肉眼看上去就太偏左了
        // ,y轴就是底边界-20,否则就贴边重叠到数据体里了就不是页脚了;注意Y轴是从下往上累加的,最上方的Top值是大于Bottom好几百开外的。
        ColumnText
                .showTextAligned(
                        cb,
                        Element.ALIGN_CENTER,
                        footer,
                        (document.rightMargin() + document.right()
                                + document.leftMargin() - document.left() - len) / 2.0F ,
                        document.bottom() - 10, 0);


        // 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,X=(右边界-左边界 - 前半部分的len值)/2.0F +
        // len , y 轴和之前的保持一致,底边界-20
        cb.addTemplate(total, (document.rightMargin() + document.right()
                        + document.leftMargin() - document.left()) / 2.0F ,
                document.bottom() - 10); // 调节模版显示的位置


    }


//    //加水印
//    public void addWatermark(PdfWriter writer){
//        // 水印图片
//        Image image;
//        try {
//            image = Image.getInstance("./web/images/001.jpg");
//            PdfContentByte content = writer.getDirectContentUnder();
//            content.beginText();
//            // 开始写入水印
//            for(int k=0;k<5;k++){
//                for (int j = 0; j <4; j++) {
//                    image.setAbsolutePosition(150*j,170*k);
//                    content.addImage(image);
//                }
//            }
//            content.endText();
//        } catch (IOException | DocumentException e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        }
//    }


    /**
     *
     * TODO 关闭文档时,替换模板,完成整个页眉页脚组件
     *
     * @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(com.itextpdf.text.pdf.PdfWriter,
     *      com.itextpdf.text.Document)
     */
    public void onCloseDocument(PdfWriter writer, Document document) {
        // 7.最后一步了,就是关闭文档的时候,将模板替换成实际的 Y 值,至此,page x of y 制作完毕,完美兼容各种文档size。
        total.beginText();
        total.setFontAndSize(bf, presentFontSize);// 生成的模版的字体、颜色
        //String foot2 = " " + (writer.getPageNumber()) + " 页"; //页脚内容拼接  如  第1页/共2页
        String foot2 = String.valueOf(writer.getPageNumber()); //页脚内容拼接  如  第1页/共2页
        total.showText(foot2);// 模版显示的内容
        total.endText();
        total.closePath();
    }


}

3、创建pdf格式及内容

package com.baosight.iplat4j.test.soa;


import com.baosight.wbplat.common.pdf.PDFBuilder;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import org.junit.Test;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;




public class PDFTest {
    @Test
    public  void pdfTest(){
        try{
            Document document = new Document(PageSize.A4,30,30,40,40);
            try {
                // 中文文本
                BaseFont bfChinese= BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                Font subjectFont=new Font(bfChinese,20,Font.BOLD);
                Font titleFont=new Font(bfChinese,15,Font.BOLD);
                Font keyFont=new Font(bfChinese,10,Font.BOLD);
                Font textFont=new Font(bfChinese,10,Font.NORMAL);
                //获取桌面路径
                File desktopDir = FileSystemView.getFileSystemView() .getHomeDirectory();
                String desktopPath = desktopDir.getAbsolutePath();
                System.out.println("您的桌面路径:"+desktopPath);
                String fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+"_试卷.pdf";
                PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(desktopPath+"/"+fileName));
                System.out.println("您生成的pdf文件路径在:"+desktopPath+"下,文件名为:"+fileName);
                //添加水印和页码
                //如果要打印页面,则还需要 增加 PDFBuilder 工具类 
                writer.setPageEvent( new PDFBuilder());
                document.open();


                Paragraph titlePara = new Paragraph("主标题",subjectFont);
                titlePara.setAlignment(Element.ALIGN_CENTER);
                document.add(new Paragraph(titlePara));


                //第一个小标题
                document.add(new Paragraph("机电",titleFont));
                document.add(new Paragraph("\r\n")); // 换行
                //生成表格内容
                PdfPTable table = createTable(writer, keyFont, textFont);
                document.add(table);


                //第二个小标题
                document.add(new Paragraph("BAS",titleFont));
                document.add(new Paragraph("\r\n")); // 换行
                //生成表格内容
                PdfPTable table2 = createTable(writer, keyFont, textFont);
                document.add(table2);
                System.out.println("生成pdf完成。。。。。。");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                document.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }


    }


    public static PdfPTable createTable(PdfWriter writer, Font keyfont,Font textfont) throws DocumentException, IOException {
        PdfPTable table = new PdfPTable(1);//生成一个两列的表格
        PdfPCell cell;
        int size = 50;
        cell = new PdfPCell(new Paragraph("正义永远不会缺席",textfont));
        cell.setFixedHeight(size);//设置高度
        cell.setBorder(0);//表格无边框
        table.addCell(cell);
        cell = new PdfPCell(new Paragraph("正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席正义永远不会缺席",textfont));
        cell.setFixedHeight(size);
        table.addCell(cell);
        cell.setBorder(0);
        cell = new PdfPCell(new Paragraph("正义永远不会缺席",textfont));
        cell.setFixedHeight(size);
        table.addCell(cell);
        cell = new PdfPCell(new Paragraph("正义永远不会缺席",textfont));
        cell.setFixedHeight(size);
        table.addCell(cell);
        cell = new PdfPCell(new Paragraph("正义永远不会缺席",textfont));
        cell.setFixedHeight(size);
        table.addCell(cell);
        cell = new PdfPCell(new Paragraph("正义永远不会缺席",textfont));
        cell.setFixedHeight(size);
        table.addCell(cell);
        cell = new PdfPCell(new Paragraph("正义永远不会缺席",textfont));
        cell.setFixedHeight(size);
        table.addCell(cell);
        cell = new PdfPCell(new Paragraph("正义永远不会缺席",textfont));
        cell.setFixedHeight(size);
        table.addCell(cell);
        cell = new PdfPCell(new Paragraph("正义永远不会缺席",textfont));
        cell.setFixedHeight(size);
        table.addCell(cell);
        cell = new PdfPCell(new Paragraph("正义永远不会缺席",textfont));
        cell.setFixedHeight(size);
        table.addCell(cell);
        return table;
    }


}

4、生成pdf效果图

spring boot PDF文件打印 spring boot 生成pdf_页眉

 ps:iText类库还是很不错的,不过拓展性不强,现在都在用poi导出啦,后面我会出利用poi插件导出的示例代码