先导入maven  

<!-- iText 6.5.13 PDF -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>

 注意Itext7和7之下的版本代码不一样,这里我用的是iText 6.5.13 的版本,别怀疑<version>5.5.13</version>就是6的版本 

5的版本和7的版本  贴在下面

<!-- iText 5.5.9 PDF -->
<dependencies>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.5.9</version>
    </dependency>
</dependencies>

<!-- iText 7.1.15 PDF -->
<dependencies>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext7-core</artifactId>
        <version>7.1.15</version>
    </dependency>
</dependencies>

导入demo

/**
     * 解析导入题目word模板
     *
     * @param
     */
    public static void main(String[] args) throws IOException {
        String tiankong = "E:\\填空题.docx";
        // 获取文件流
        FileInputStream fileInputStream = new FileInputStream(tiankong);
        //InputStream fileInputStream = file.getInputStream();
        // 解析文档
        XWPFDocument xd = new XWPFDocument(fileInputStream);
        // 获取全部的文本段落
        List<XWPFParagraph> xwPfParagraphList = xd.getParagraphs();
        // 获取word里的全部表格内容
        List<XWPFTable> tableList = xd.getTables();
        // 过滤掉 标题
        xwPfParagraphList = xwPfParagraphList.stream()
                .filter(xwpfParagraph -> !xwpfParagraph.getText().contains(QuestionTypeEnum.CHOICE.getName()))
                .collect(Collectors.toList());
        /**
         * 文本实现方式:解析读取段落,然后拿到每个段落的文本信息
         * 1、这是一道选择题()。
         * A、选项a
         * B、选项b
         * C、选项c
         * D、选项d
         * 【正确答案:】A
         * 详细:  xwPfParagraphList 拿到全部试题解析后的试题段落信息
         *          String text = xwpfParagraphLis.getText();获取文本
         *        如果当前段落文本不是空,确认true加入一个新的list
         *        然后把text截取标题部分写入list
         *        按照我的格式  我是截取 0-A 为标题  A-B是选项A的内容  然后正确答案之后就是答案,看你们的试题自己制定
         *        如股这个段落是最后一个,创建下一个list,循环下一题往下个list继续添加信息。
         *        因为试题不同,下面代码可以参考一下,有一些疯pi的处理
         *        
         *        表格方式一样,最后的时候删除空的list
         * 
         */
        List<List<String>> strList = new ArrayList<>();
        if (CollectionUtil.isEmpty(xwPfParagraphList)) {
           // return new ArrayList<>();
        }
        strList.add(new ArrayList<String>());
        boolean isStart = false;
        for (int i = 0; i < xwPfParagraphList.size(); i++) {

            XWPFParagraph xwpfParagraphLis = xwPfParagraphList.get(i);
            //获取文本内容
            String text = xwpfParagraphLis.getText();
            //System.out.println("内容: " + text);
            //当前不为空 上一个为空  = 试题开始
            if (StrUtil.isNotEmpty(text)) {
                isStart = true;
            }
            // 处于开始标志时
            if (isStart) {
                // 获取最后一个题目段落列表
                List<String> strLast = strList.get(strList.size() - 1);
                // 为空处理
                strLast = CollectionUtil.isEmpty(strLast) ? new ArrayList<>() : strLast;
                // 将当前段落添加到列表中
                strLast.add(text);
                strList.set(strList.size() - 1, strLast);
                if (text.contains("正确答案")) {
                    // 获取最后一个题目段落列表
                    // 段落列表不为空
                    if (strLast.size() > 0) {
                        // 算做结束段落
                        isStart = false;
                        // 空行不是最后一行时
                        if (i < xwPfParagraphList.size() - 1) {
                            // 继续添加段落列表
                            strList.add(new ArrayList<String>());
                        }
                    }
                }
            }
        }
        //处理word中的表格数据
        if (CollectionUtil.isNotEmpty(tableList)) {
            //因为解析完了文本,已经没有新的newList,这里先加一个
            strList.add(new ArrayList<String>());
            for (XWPFTable xwpfTable : tableList) {
                for (int i = 0; i < xwpfTable.getNumberOfRows(); i++) {
                    XWPFTableRow row = xwpfTable.getRow(i);
                    List<XWPFTableCell> cells = row.getTableCells();
                    // 处理行中的单元格
                    for (XWPFTableCell cell : cells) {
                        // String text = cell.getText();
                        List<XWPFParagraph> xwpfParagraph = cell.getParagraphs();
                        xwpfParagraph = xwpfParagraph.stream().filter(o -> StrUtil.isNotEmpty(o.getText())).collect(Collectors.toList());
                        //for (XWPFParagraph xwp : xwpfParagraph) {
                        for (int j = 0; j < xwpfParagraph.size(); j++) {
                            XWPFParagraph xwp = xwpfParagraph.get(j);
                            String text = xwp.getText();
                            //当前不为空 上一个为空  = 试题开始
                            isStart = false;
                            if (StrUtil.isNotEmpty(text)) {
                                isStart = true;
                            }
                            // 处于开始标志时
                            if (isStart) {
                                // 获取最后一个题目段落列表
                                List<String> strLast = strList.get(strList.size() - 1);
                                // 为空处理
                                strLast = CollectionUtil.isEmpty(strLast) ? new ArrayList<>() : strLast;
                                // 将当前段落添加到列表中
                                strLast.add(text);
                                strList.set(strList.size() - 1, strLast);
                                if (text.contains("正确答案")) {
                                    // 获取最后一个题目段落列表
                                    // 段落列表不为空
                                    if (strLast.size() > 0) {
                                        // 算做结束段落
                                        isStart = false;
                                        // 空行不是最后一行时
                                        if (j < xwpfParagraph.size()) {
                                            // 继续添加段落列表
                                            strList.add(new ArrayList<String>());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        if (CollectionUtil.isNotEmpty(strList)) {
            // 如果最后一项是空的,就删除最后一项
            List<String> stringList = strList.get(strList.size() - 1);
            if (stringList.size() == 0) {
                strList.remove(strList.size() - 1);
            }
        }

    }

简单导出demo

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class PdfCreationDemo {

    public static void main(String[] args) {
        // 创建文档对象
        Document document = new Document();

        try {
            // 创建PdfWriter实例,并指定输出文件路径
            PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));

            // 打开文档
            document.open();

            // 添加内容
            document.add(new Paragraph("Hello, World!"));

            // 关闭文档
            document.close();

            System.out.println("PDF生成成功!");
        } catch (DocumentException | FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

稍微加点处理的(注意,查看自己电脑的字体是tcc还是ttf),不设置字体直接导不出文字信息

public static void pdfExporter(PDFSubjectExaminationVO pdf, HttpServletResponse response) {
        Document document = new Document();
        try {
            //相对路径  生成一个新的pdf
            //PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("sample.pdf"));
            //读取文件
            PdfWriter.getInstance(document, response.getOutputStream());
            document.open();

            // 设置 TTC 字体路径
            String ttcFontPath = "C:\\Windows\\Fonts\\simsun.ttc";
            // 创建 TTC 字体对象
            BaseFont baseFont = BaseFont.createFont(ttcFontPath + ",0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            // 创建自定义字体对象   //使用字体并给出颜色
            Font fontTitle = new Font(baseFont, 10, Font.BOLD);
            Font fontAnswer = new Font(baseFont, 8, Font.NORMAL, BaseColor.RED);
            Font fontContent = new Font(baseFont, 8, Font.NORMAL);
            Font heading = new Font(baseFont, 12, Font.BOLD);
            Font title = new Font(baseFont, 16, Font.BOLD);
            // 设置文本居中
            Rectangle pageSize = document.getPageSize();
            float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
            float y = (pageSize.getTop() + pageSize.getBottom()) / 2;

            //给pdf增加段落
            Paragraph paragraph = new Paragraph();
            //随便往里面加东西喽,我的内容不放出来了,随便搞
            paragraph.add(new Phrase("\t\t\t【正确答案:】:\t" + "answer", fontTitle));
            //设置下划线
            String str = "下划线文本信息";
            Chunk underlineChunk = new Chunk(str, fontTitle);
            // 设置下划线样式
            underlineChunk.setUnderline(0.5f, -1f);
            paragraph.add(underlineChunk);

            document.close();
            System.out.println("PDF导出成功!");

        } catch (DocumentException |
                FileNotFoundException e) {
            System.out.println("PDF导出时发生错误:" + e.getMessage());
        } catch (
                IOException e) {
            e.printStackTrace();
        }

    }