ThymeleafUtil - 文件生成
- maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 如果生成PDF文件,需要flying-saucer-pdf依赖支持
<dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.0.7</version> </dependency>
- 生成中文PDF需要字体支持(没有资源的朋友,这里给资源链接)
地址 https://download.csdn.net/download/scdncby/11256604
- 模板默认的位置在/src/main/resources/templates ,可以配置文件修改模板位置
- 转html天然转换,完美;
- 转doc直接转就好,输出的就是其内容;
- 转txt和doc差不多,但是会输出所有,doc内容+注释内容;
- 转xls直接转,注意用table控制xls结构样式;
package com.common.utils;
import com.lowagie.text.pdf.BaseFont;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.*;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Thymeleaf 工具类 引用时必须提供 TemplateEngine 对象
* by ChenYb date 2019/6/21
*/
@Component
public class ThymeleafUtil {
private final Logger logger = LoggerFactory.getLogger( this.getClass());
private TemplateEngine templateEngine;
//生成文件地址
private final String CREATE_FILE_ADDRESS = "/src/main/webapp/static/";
//字体文件地址 默认在 /templates 下
private final String FONT_FILE_ADDRESS = "templates/font/simsun.ttf";
public ThymeleafUtil(TemplateEngine templateEngine){
this.templateEngine = templateEngine;
}
/**
* 模板在/src/main/resources/templates 目录下 , 或者配置文件中指定模板根路径
* 默认生成的新文件在/src/main/webapp/static 目录下
* fltFile flt文件名 , fileNameOrSuffix 后缀名(前缀随机)/全名称 , datas 数据集合
* @param htmlTemplate
* @param fileNameOrSuffix
* @param datas
* @return 生成文件路径
*/
public String geneFile(String htmlTemplate, String fileNameOrSuffix, Map<String, Object> datas){
String result = null;
try {
StringBuffer pathBuffer = this.getProject();
//生成文件所在路径
File fileIsExists = new File( pathBuffer.append( this.CREATE_FILE_ADDRESS ).toString());
if (!fileIsExists.exists()){
fileIsExists.mkdirs();
}
pathBuffer.append( this.getRandomName( fileNameOrSuffix ));
result = pathBuffer.toString();
logger.info( "CREATE NEW FILE PATH : {}",result );
Writer file = new FileWriter(new File(result));
Context context = new Context();
context.setVariables(datas);
this.templateEngine.process( htmlTemplate, context ,file);
logger.info( "THYMELEAF CREATE FILE HOME {}",fileIsExists );
}catch (Exception e){
e.printStackTrace();
}
return result;
}
/**
* htmlTemplate 模板 ,默认在 /resources/templates/ 下 ,datas 数据
* @param htmlTemplate
* @param datas
* @return 模板内容 String 类型
*/
public String geneFile(String htmlTemplate , Map datas) {
Context context = new Context();
context.setVariables(datas);
return this.templateEngine.process( htmlTemplate, context );
}
/**
* htmlTemplate html模板地址 默认\resources\templates\
* datas 数据集
* @param htmlTemplate
* @param datas
* @return 文件地址
*/
public String geneFile ( Map datas ,String htmlTemplate ,String fileName){
StringBuffer pathBuffer = this.getProject();
File fileIsExists = new File( pathBuffer.append( this.CREATE_FILE_ADDRESS ).toString());
if (!fileIsExists.exists()){
fileIsExists.mkdirs();
}
Context context = new Context();
logger.info( "THYMELEAF CREATE PDF HOME {}",pathBuffer );
context.setVariables( datas );
String result = "";
try {
//"/contract" 为模板文件,注意路径和“/”
String htmlConText = this.templateEngine.process(htmlTemplate, context);
if (fileName.contains( "\\." ))
throw new RuntimeException( "需要按照正规文件命名规则命名" );
if (StringUtils.isBlank( fileName ))
result = pathBuffer.append( this.getRandomName( "pdf" ) ).toString();
else
result = pathBuffer.append( fileName + ".pdf" ).toString();
this.toPdf(htmlConText,pathBuffer.toString());
} catch (Exception e) {
e.printStackTrace();
}
logger.info( "THYMELEAF CREATE PDF {}",pathBuffer );
return result;
}
private boolean toPdf(String content,String path) throws Exception{
boolean result = false;
ITextRenderer renderer = new ITextRenderer();
ITextFontResolver fontResolver = renderer.getFontResolver();
try {
//设置字体,否则不支持中文,在html中使用字体,html{ font-family: SimSun;}
fontResolver.addFont(this.FONT_FILE_ADDRESS, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.setDocumentFromString(content);
renderer.layout();
renderer.createPDF(new FileOutputStream(new File(path)));
result = true;
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
//工程路径
private StringBuffer getProject (){
StringBuffer pathBuffer = null;
try {
String resourcePath = FreeMarkerUtil.class.getResource( "/" ).toURI().getPath();
resourcePath = resourcePath.substring( 1 , resourcePath.indexOf( "/target" ));
pathBuffer = new StringBuffer( resourcePath );
}catch (Exception e){
e.printStackTrace();
}
return pathBuffer;
}
//文件名处理
private StringBuffer getRandomName ( String fileNameOrSuffix ){
int count = 0;
Pattern element = Pattern.compile("\\.");
Matcher subject = element.matcher( fileNameOrSuffix );
while (subject.find()) {
count++;
}
StringBuffer pathBuffer = new StringBuffer();
if (count < 1)//断言名称类型
pathBuffer.append( new Random().nextInt( 10 ) ).append( "." ).append( fileNameOrSuffix );//避免文件过多
else
pathBuffer.append( fileNameOrSuffix );
return pathBuffer;
}
}
- 测试代码
@Autowired
private TemplateEngine templateEngine;
@Test //创建文件,返回文件地址
public void createFileGetAddressTest () throws Exception{
HashMap<String, Object> map = new HashMap<>();
String fileAddress = new ThymeleafUtil(this.templateEngine).geneFile( "index", "doc", map );
System.out.println(fileAddress);
}
@Test //读取模板 , 返回字符串
public void readTemplateGetStringTest () throws Exception {
HashMap<String, Object> map = new HashMap<>();
String index = new ThymeleafUtil( this.templateEngine ).geneFile( "index", map );
System.out.println(index);
}
- 生成PDF测试代码
@Test
public void createPdf(){
HashMap<String, Object> map = new HashMap<>();
map.put( "name","CHENYB" );
ThymeleafUtil thymeleafUtil = new ThymeleafUtil( this.templateEngine );
String s = thymeleafUtil.geneFile( map ,"test-pdf","爱我中华");
String s1 = thymeleafUtil.geneFile( map ,"test-pdf","");
System.out.println(s);
System.out.println(s1);
}
- 控制层页面跳转
@RestController
public class TestController {
@GetMaping("/test")//这里一定是get请求
public ModeAndView test (ModeAndView mav){
//需要配置视图解析器后缀 , 没有配置换index.html
mav.setViewName("index"); //src/main/resources/templates/ 把index.html放到默认 路径下,就可以实现页面跳转了
return mav;
}
}
- resources/templates/index.html 模板
<!DOCTYPE html>
<!--名称空间-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Thymeleaf 语法</title>
</head>
<body>
<h2>ITDragon Thymeleaf 语法</h2>
<!--th:text 设置当前元素的文本内容,常用,优先级不高-->
<p>thText:</p><p th:text="${thText}" />
<p>thUText:</p><p th:utext="${thUText}" />
<p th:text="${thText}" style="color: #08ad1a;font-family: 仿宋;size: 20px" />
<!--th:value 设置当前元素的value值,常用,优先级仅比th:text高-->
<p>thValue:</p><input type="text" th:value="${thValue}" />
<!--th:each 遍历列表,常用,优先级很高,仅此于代码块的插入-->
<!--th:each 修饰在div上,则div层重复出现,若只想p标签遍历,则修饰在p标签上-->
<p>thEach 1:</p>
<table th:each="message : ${thEach}" > <!-- 遍历整个div-p,不推荐-->
<th style="size: 1px;background-color: #008bbc">TEST:</th>
<td th:text="${message}" />
</table>
<p>thEach 2:</p>
<div> <!--只遍历p,推荐使用-->
<p th:text="${message}" th:each="message : ${thEach}"/>
</div>
<!--th:if 条件判断,类似的有th:switch,th:case,优先级仅次于th:each, 其中#strings是变量表达式的内置方法-->
<p th:text="${thIf}" th:if="${not #strings.isEmpty(thIf)}"></p>
<!--th:insert 把代码块插入当前div中,优先级最高,类似的有th:replace,th:include,~{} :代码块表达式 -->
<!--<div th:insert="~{grammar/common::thCommon}"></div>-->
<!--th:object 声明变量,和*{} 一起使用-->
<!--<div th:object="${thObject}">
<p>ID: <span th:text="*{id}" /></p><!–th:text="${thObject.id}"–>
<p>TH: <span th:text="*{thName}" /></p><!–${thObject.thName}–>
<p>DE: <span th:text="*{desc}" /></p><!–${thObject.desc}–>
</div>-->
</body>
</html>