springboot 集成 Freemaker生成 PDF

前言

最近收到一个生成 PDF 的需求,后端使用的是 springboot 集成 Freemaker 模板引擎,调用第三方接口生成 PDF。

需求细节

PDF 页面表格样式

后端接口入参

java 复制代码
{
    "teamCode":"20240808001A",
    "tourTeamList":[
        {
            "teamName":"AAAA",
            "teamInfoList":[
                {
                    "number":"1",
                    "accumulate":"666.2",
                    "remark":"YIUY"
                },
                {
                    "number":"2",
                    "accumulate":"666.2",
                    "remark":"YIUY"
                },
                {
                    "number":"3",
                    "accumulate":"666.2",
                    "remark":"YIUY"
                }
            ]
        }
    ]
}

如 "前端表格样式" 所示,数据的展示并不是传统的横向展示,而是纵向进行展示,这个时候就需要对接口入参的集合进行特殊处理。

设计思路

根据页面可知,需要将入参的集合左右排列纵向展示:

  1. 将一个大集合分割成两个小集合,分别表示左排数据和右排数据,要注意分割集合的时候区分集合元素数量是偶数个还是奇数个
  2. 从下面的图片可知,一行数据下,虽然左三列和右三列相同,但是为了展示数据,一行数据可以看成是一个 Java 实体,这个实体有6个成员变量,表示这一行数据的6列
  3. 将集合分割成两个小集合后,可知左排集合的第一个元素表示左排三列数据,右排数据的第一个元素表示右排三列数据,所以两个集合的第一个元素组成完整的第一行数据,同理,两个集合的第二个元素组成第二行数据,依此类推。

步骤3的设计代码实现:

(1)左/右两部分table实体

java 复制代码
import java.io.Serializable;

public class Table implements Serializable {

    private static final long serialVersionUID = -1627345966155980666L;

    private String            data1;

    private String            data2;

    private String            data3;

    public String getData1() {
        return data1;
    }

    public void setData1(String data1) {
        this.data1 = data1;
    }

    public String getData2() {
        return data2;
    }

    public void setData2(String data2) {
        this.data2 = data2;
    }

    public String getData3() {
        return data3;
    }

    public void setData3(String data3) {
        this.data3 = data3;
    }

}

(2)表示一整行数据的Java实体

java 复制代码
import java.io.Serializable;

public class TableForPdf implements Serializable {

    private static final long serialVersionUID = -1627345456155980666L;

    private String            leftData1;

    private String            leftData2;

    private String            leftData3;

    private String            rightData1;

    private String            rightData2;

    private String            rightData3;

    public String getLeftData1() {
        return leftData1;
    }

    public void setLeftData1(String leftData1) {
        this.leftData1 = leftData1;
    }

    public String getLeftData2() {
        return leftData2;
    }

    public void setLeftData2(String leftData2) {
        this.leftData2 = leftData2;
    }

    public String getLeftData3() {
        return leftData3;
    }

    public void setLeftData3(String leftData3) {
        this.leftData3 = leftData3;
    }

    public String getRightData1() {
        return rightData1;
    }

    public void setRightData1(String rightData1) {
        this.rightData1 = rightData1;
    }

    public String getRightData2() {
        return rightData2;
    }

    public void setRightData2(String rightData2) {
        this.rightData2 = rightData2;
    }

    public String getRightData3() {
        return rightData3;
    }

    public void setRightData3(String rightData3) {
        this.rightData3 = rightData3;
    }

}

(3)分割及组装

java 复制代码
  /**
     * 
     * @Description:将一个完整的集合分割成两个小集合
     * @param list: 返回结果描述
     * @return void: 返回值类型
     * @throws
     */
    public List<TableForPdf> separateList(List<Table> list) {
        List<TableForPdf> tableList = new ArrayList<>();
        if (list.size() > 0 && list != null) {
            List<Table> leftDataList = new ArrayList<>();
            List<Table> rightDataList = new ArrayList<>();
            int size = list.size();
            //  不能被2整除即为奇数个。
            if (size % 2 == 1) {
                for (int i = 0; i < size; i++) {
                    if (i < (size / 2 + 1)) {
                        leftDataList.add(list.get(i));
                    } else {
                        rightDataList.add(list.get(i));
                    }
                }
                rightDataList.add(new Table());// 这一步是为了保证两个集合元素数量的平衡
            } else {
                for (int i = 0; i < size; i++) {
                    if (i < (size / 2)) {
                        leftDataList.add(list.get(i));
                    } else {
                        rightDataList.add(list.get(i));
                    }
                }
            }
            tableList = createPdfTable(leftDataList, rightDataList);
        }
        return tableList;
    }

    /**
     * 
     * @Description:通过分割的两个集合组成table的一行数据
     * @param leftDataList
     * @param rightDataList
     * @return: 返回结果描述
     * @return List<TableForPdf>: 返回值类型
     * @throws
     */
    private List<TableForPdf> createPdfTable(List<Table> leftDataList, List<Table> rightDataList) {
        List<TableForPdf> tableList = new ArrayList<>();
        for (int i = 0; i < leftDataList.size(); i++) {
            for (int j = 0; j < rightDataList.size(); j++) {
                if (i == j) {
                    TableForPdf tableForPdf = new TableForPdf();
                    tableForPdf.setLeftData1(leftDataList.get(i).getData1());
                    tableForPdf.setLeftData2(leftDataList.get(i).getData2());
                    tableForPdf.setLeftData3(leftDataList.get(i).getData3());
                    tableForPdf.setRightData1(rightDataList.get(j).getData1());
                    tableForPdf.setRightData2(rightDataList.get(j).getData2());
                    tableForPdf.setRightData3(rightDataList.get(j).getData3());

                    tableList.add(tableForPdf);
                }
            }
        }
        return tableList;
    }
}

代码示例

1、创建接口入参实体

(1)团队人员信息实体

java 复制代码
import java.io.Serializable;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "团队人员信息", description = "团队人员信息")
public class TourMember implements Serializable {

    private static final long serialVersionUID = -1627345966155980666L;

    @ApiModelProperty(value = "人员编号")
    private String            number;

    @ApiModelProperty(value = "旅行费用")
    private String            accumulate;

    @ApiModelProperty(value = "注意事项")
    private String            remark;

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getAccumulate() {
        return accumulate;
    }

    public void setAccumulate(String accumulate) {
        this.accumulate = accumulate;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

}

(2)团队信息实体

java 复制代码
import java.io.Serializable;
import java.util.List;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "团队信息", description = "团队信息")
public class TourTeam implements Serializable {

    private static final long serialVersionUID = -1632145966155980666L;

    @ApiModelProperty(value = "团队名称")
    private String            teamName;

    @ApiModelProperty(value = "团队人员信息")
    private List<TourMember>  teamInfoList;

    public String getTeamName() {
        return teamName;
    }

    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }

    public List<TourMember> getTeamInfoList() {
        return teamInfoList;
    }

    public void setTeamInfoList(List<TourMember> teamInfoList) {
        this.teamInfoList = teamInfoList;
    }

}

(3)入参实体

java 复制代码
import java.io.Serializable;
import java.util.List;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "接口入参", description = "接口入参")
public class TourInDTO implements Serializable {

    private static final long serialVersionUID = -1627345966155980666L;

    @ApiModelProperty(value = "团队编码")
    private String            teamCode;

    @ApiModelProperty(value = "团队信息")
    private List<TourTeam>    tourTeamList;

    public String getTeamCode() {
        return teamCode;
    }

    public void setTeamCode(String teamCode) {
        this.teamCode = teamCode;
    }

    public List<TourTeam> getTourTeamList() {
        return tourTeamList;
    }

    public void setTourTeamList(List<TourTeam> tourTeamList) {
        this.tourTeamList = tourTeamList;
    }
}

2、创建调用生成PDF API入参实体

(1)团队人员 pdf 信息实体

java 复制代码
import java.io.Serializable;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "团队人员pdf信息", description = "团队人员pdf信息")
public class TourMemberPdf implements Serializable {

    private static final long serialVersionUID = -1627345966155980666L;

    @ApiModelProperty(value = "左列人员编号")
    private String            leftNumber;

    @ApiModelProperty(value = "左列旅行费用")
    private String            leftAccumulate;

    @ApiModelProperty(value = "左列注意事项")
    private String            leftRemark;
    @ApiModelProperty(value = "右列人员编号")
    private String            rightNumber;

    @ApiModelProperty(value = "右列旅行费用")
    private String            rightAccumulate;

    @ApiModelProperty(value = "右列注意事项")
    private String            rightRemark;

    public String getLeftNumber() {
        return leftNumber;
    }

    public void setLeftNumber(String leftNumber) {
        this.leftNumber = leftNumber;
    }

    public String getLeftAccumulate() {
        return leftAccumulate;
    }

    public void setLeftAccumulate(String leftAccumulate) {
        this.leftAccumulate = leftAccumulate;
    }

    public String getLeftRemark() {
        return leftRemark;
    }

    public void setLeftRemark(String leftRemark) {
        this.leftRemark = leftRemark;
    }

    public String getRightNumber() {
        return rightNumber;
    }

    public void setRightNumber(String rightNumber) {
        this.rightNumber = rightNumber;
    }

    public String getRightAccumulate() {
        return rightAccumulate;
    }

    public void setRightAccumulate(String rightAccumulate) {
        this.rightAccumulate = rightAccumulate;
    }

    public String getRightRemark() {
        return rightRemark;
    }

    public void setRightRemark(String rightRemark) {
        this.rightRemark = rightRemark;
    }
}

(2)团队信息pdf 实体

java 复制代码
import java.io.Serializable;
import java.util.List;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "团队信息pdf", description = "团队信息pdf")
public class TourTeamPdf implements Serializable {

    private static final long   serialVersionUID = -1632145966155980666L;

    @ApiModelProperty(value = "团队名称")
    private String              teamName;

    @ApiModelProperty(value = "团队人员信息")
    private List<TourMemberPdf> tableList;

    public String getTeamName() {
        return teamName;
    }

    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }

    public List<TourMemberPdf> getTableList() {
        return tableList;
    }

    public void setTableList(List<TourMemberPdf> tableList) {
        this.tableList = tableList;
    }
}

(3)pdf接口入参

java 复制代码
import java.io.Serializable;
import java.util.List;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "pdf接口入参", description = "pdf接口入参")
public class TourPdfInDTO implements Serializable {

    private static final long serialVersionUID = -1627345966155980666L;

    @ApiModelProperty(value = "团队编码")
    private String            teamCode;

    @ApiModelProperty(value = "团队信息")
    private List<TourTeamPdf> tourTeamList;

    public String getTeamCode() {
        return teamCode;
    }

    public void setTeamCode(String teamCode) {
        this.teamCode = teamCode;
    }

    public List<TourTeamPdf> getTourTeamList() {
        return tourTeamList;
    }

    public void setTourTeamList(List<TourTeamPdf> tourTeamList) {
        this.tourTeamList = tourTeamList;
    }
}
相关推荐
Algorithm15763 分钟前
JVM是什么,与Java的关系是什么,以及JVM怎么实现的跨平台性
java·开发语言·jvm
遇见你真好。1 小时前
SpringBoot整合quartz定时任务
java·springboot·quartz
一颗甜苞谷1 小时前
开源一款基于 JAVA 的仓库管理系统,支持三方物流和厂内物流,包含 PDA 和 WEB 端的源码
java·开发语言·开源
攻心的子乐1 小时前
idea使用svn
java·ide·intellij-idea
程序员大佬超1 小时前
IDEA解决 properties 文件乱码问题
java·ide·intellij-idea
秋恬意1 小时前
LinkedList 源码分析
java·开发语言·面试
隔窗听雨眠1 小时前
深入理解Redis的四种模式
java·redis·mybatis
lexusv8ls600h1 小时前
微服务设计模式 - 重试模式(Retry Pattern)
java·spring boot·微服务
Viktor_Ye2 小时前
高效数据集成:易仓退款订单与金蝶销售退货单的自动化对接
java·运维·自动化
liuxin334455662 小时前
SpringBoot助力大型商场应急预案自动化
spring boot·后端·自动化