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;
    }
}
相关推荐
暮乘白帝过重山2 分钟前
Singleton和Prototype的作用域与饿汉式/懒汉式的初始化方式
spring·原型模式·prototype·饿汉式·singleton·懒汉式
腥臭腐朽的日子熠熠生辉31 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian33 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之38 分钟前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
俏布斯1 小时前
算法日常记录
java·算法·leetcode
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen1 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算
松韬2 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存