1、主要目录
2、maven依赖
<!--工具类依赖-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.19</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<!--pdf-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>font-asian</artifactId>
<version>7.2.3</version>
</dependency>
3、新建一个demo.html静态文件,后续导出模板就是按照此文件进行的
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
</head>
<body>
<div class="contianer">
<div class="bg-img-container">
</div>
<h1>模板pdf</h1>
<div class="flex-div">
<p>表1</p>
</div>
<table border="1" cellSpacing="1">
<tr>
<th>姓名</th>
<td colspan="3">$!{name}</td>
</tr>
<tr>
<th #if($!{gender}==1) class="blue" #else class="red" #end>性别</th>
<td colspan="3">
#if($!{gender}==1)
男
#else
女
#end
</td>
</tr>
<tr>
<th>出生日期</th>
<td>$!{birthDate}</td>
<th>联系方式</th>
<td>$!{phone}</td>
</tr>
</table>
<h1>双重For循环取值</h1>
<div class="flex-div">
<p>表2</p>
</div>
<table border="1" cellSpacing="1">
<tr>
<th>学历</th>
<th>学科</th>
<td class="gray-bg">分数</td>
</tr>
#foreach($item in $eduList)
<tr>
<th #set($len= $item.size+1) rowspan="$len">$item.name</th>
#foreach($result in $item.itemList)
<tr>
<td>$velocityCount、$result.subject</td>
<td #if($result.num > 60) class="green" #else class="red" #end>$result.num</td>
</tr>
#end
</tr>
#end
</table>
</div>
</body>
<style>
.blue {
color: #244385;
margin-left: 30px;
}
.green {
color: #52c41a;
margin-left: 30px;
}
.red {
color: #c1181e;
margin-left: 30px;
}
.flex-div {
margin: 30px 0 15px;
display: flex;
align-items: center;
}
.line {
width: 540px;
height: 0px;
border: dashed 1px #edf0f5;
}
table {
width: 700px;
border-collapse: collapse;
/*border-spacing: 0;*/
border-left: 1px solid #edf0f5;
border-top: 1px solid #edf0f5;
}
th, td {
border-right: 1px solid #edf0f5;
border-bottom: 1px solid #edf0f5;
padding: 5px 15px;
}
h1 {
text-align: center;
font-family: 'Microsoft YaHei';
line-height: 60px;
letter-spacing: 8px;
color: #244385;
}
p {
font-family: 'Microsoft YaHei';
font-size: 20px;
font-weight: normal;
color: #244385;
margin: 0 16px;
}
th {
background-color: rgba(0, 0, 0, 0.01);
width: 90px;
min-width: 90px;
max-width: 90px;
text-align: left;
text-indent: 10px;
font-family: 'Microsoft YaHei';
font-size: 16px;
font-weight: normal;
font-stretch: normal;
line-height: 48px;
letter-spacing: 2px;
color: #666666;
}
td {
font-size: 16px;
color: #000000;
text-align: left;
text-indent: 10px;
padding-right: 20px;
height: 50px;
}
table,tr, th, td {
border: solid 1px #edf0f5;
}
.gray-bg {
background-color: rgba(0, 0, 0, 0.01);
}
</style>
</html>
4、新建PdfUtil工具类
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.font.FontProvider;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
/**
* PDF工具
*
* @author ppp
* @date 2022/8/5
*/
public class PdfUtil {
static {
// Velocity初始化
Velocity.setProperty(RuntimeConstants.OUTPUT_ENCODING, StandardCharsets.UTF_8);
Velocity.setProperty(RuntimeConstants.INPUT_ENCODING, StandardCharsets.UTF_8);
Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
Velocity.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
Velocity.init();
}
/**
* 据模板生成pfd格式文件
*
* @param context 上下文对象
* @param template pdf模板
* @param outputStream 生成ofd文件输出流
*/
public static void pdfFile(Context context, String template, OutputStream outputStream) {
try (PdfWriter pdfWriter = new PdfWriter(outputStream)) {
PdfDocument pdfDocument = new PdfDocument(pdfWriter);
pdfDocument.setDefaultPageSize(PageSize.A4);
ConverterProperties properties = new ConverterProperties();
FontProvider fontProvider = new FontProvider();
// 字体设置,解决中文不显示问题
PdfFont sysFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H");
fontProvider.addFont(sysFont.getFontProgram(), "UniGB-UCS2-H");
properties.setFontProvider(fontProvider);
Template pfdTemplate = Velocity.getTemplate(template, "UTF-8");
StringWriter writer = new StringWriter();
pfdTemplate.merge(context, writer);
HtmlConverter.convertToPdf(writer.toString(), pdfDocument, properties);
pdfDocument.close();
} catch (Exception e) {
throw new RuntimeException("PFD文件生成失败", e);
}
}
}
5、Controller接口测试,也可以根据业务来分层service
package com.example.springboot3.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.URLUtil;
import com.example.springboot3.utils.PdfUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.velocity.VelocityContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@RestController
@RequestMapping("/velocity")
public class PdfController {
@GetMapping("/getPdf")
public void get(HttpServletResponse response){
response.reset();
response.setContentType("application/pdf");
String filename = System.currentTimeMillis()+".pdf";
response.addHeader("Content-Disposition", "inline; filename=" + URLUtil.encode(filename, CharsetUtil.CHARSET_UTF_8));
VelocityContext context = new VelocityContext();
context.put("name", "彭也行");
context.put("gender", 1);
context.put("birthDate", DateUtil.formatDateTime(new Date()));
context.put("phone", "13666666666");
List<Map<String, Object>> eduList = new ArrayList<>();
// 小学
Map<String, Object> primarySchoolMap = new HashMap<>();
primarySchoolMap.put("name", "小学");
List<Map<String, Object>> scoreList = new ArrayList<>();
// 语文成绩
Map<String, Object> chineseScore = new HashMap<>();
chineseScore.put("subject", "语文");
chineseScore.put("num", 60);
// 数学成绩
Map<String, Object> mathScore = new HashMap<>();
mathScore.put("subject", "数学");
mathScore.put("num", 99);
scoreList.add(chineseScore);
scoreList.add(mathScore);
primarySchoolMap.put("itemList", scoreList);
primarySchoolMap.put("size", scoreList.size());
// 初中
Map<String, Object> middleSchoolMap = new HashMap<>();
middleSchoolMap.put("name", "初中");
List<Map<String, Object>> middleScoreList = new ArrayList<>();
// 语文成绩
Map<String, Object> middleChineseScore = new HashMap<>();
middleChineseScore.put("subject", "语文");
middleChineseScore.put("num", 60);
// 数学成绩
Map<String, Object> middleMathScore = new HashMap<>();
middleMathScore.put("subject", "数学");
middleMathScore.put("num", 99);
// 英语
Map<String, Object> middleEnScore = new HashMap<>();
middleEnScore.put("subject", "英语");
middleEnScore.put("num", 55);
middleScoreList.add(middleChineseScore);
middleScoreList.add(middleMathScore);
middleScoreList.add(middleEnScore);
middleScoreList.add(middleEnScore);
middleScoreList.add(middleEnScore);
middleScoreList.add(middleEnScore);
middleScoreList.add(middleEnScore);
middleScoreList.add(middleEnScore);
middleSchoolMap.put("itemList", middleScoreList);
middleSchoolMap.put("size", middleScoreList.size());
eduList.add(primarySchoolMap);
eduList.add(middleSchoolMap);
context.put("eduList", eduList);
try(ServletOutputStream outputStream = response.getOutputStream()){
PdfUtil.pdfFile(context, "static/demo.html", outputStream);
}catch (Exception e){
e.printStackTrace();
}
}
}
6、调用接口浏览器预览
本文转载自: https://blog.csdn.net/weixin_41463944/article/details/137065045
版权归原作者 程序员阿明 所有, 如有侵权,请联系我们删除。
版权归原作者 程序员阿明 所有, 如有侵权,请联系我们删除。