看见群里在说Enjoy除了能渲染页面还能干什么用?
看见“@毛斯特洛夫斯基”说:
“
你用的到模版的时候,就能体会到enjoy的优点
用不到的时候,不要手里有锤子就看谁都像是钉子
”
笑坏我了哈哈~ 嗯,我来分享一个小工具吧, 我自己这边一直在用的偏方。。。
上 石马 吧~
FileTemplateRender.java
package com.momathink.common.plugin.xls;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.StrKit;
import com.jfinal.render.FileRender;
import com.jfinal.render.TemplateRender;
import com.jfinal.template.Engine;
/***
* 文件模版 渲染后 输出 , 应用场景: 拼接XLS文件 , 在线代码生成下载 , 等...
*
* @author 杜福忠 2018-12-14 10:53:12 改进
*/
public class FileTemplateRender extends TemplateRender {
protected static Engine MyEngine = null;
/*
* 自定义 Engine
*/
public static void setEngine(Engine jfEngine) {
if (jfEngine == null) {
throw new IllegalArgumentException("engine can not be null");
}
MyEngine = jfEngine;
}
protected static String downloadPath = getDownloadPath();
/*
* 临时文件地址
*/
protected static String getDownloadPath() {
String path = PathKit.getWebRootPath() + "/download/FileTemplateRender";
new File(path).mkdirs();
return path;
}
protected String downloadFileName = null;
protected Callback callback = null;
/**
* 渲染文件
*
* @param view
* @param downloadFileName
*/
public FileTemplateRender(String view, String downloadFileName) {
super(view);
this.downloadFileName = downloadFileName;
}
/**
* 文件渲染下载后会回调 run(File file)方法
*/
public static abstract class Callback {
public abstract void run(File file);
}
/**
* 渲染后下载完回调文件处理
*
* <pre>
* new FileTemplateRender(view, downloadFileName,
* new FileTemplateRender.Callback() {
*
* public void run(File file) {
* // 处理 file
* }
* });
* </pre>
*
* @param view
* @param downloadFileName
* @param callback
* 回调函数
*/
public FileTemplateRender(String view, String downloadFileName,
Callback callback) {
this(view, downloadFileName);
this.callback = callback;
}
@Override
public void render() {
File file = null;
try {
file = renderFile();
// 转FileRender进行下载文件
FileRender fr = new FileRender(file, downloadFileName);
fr.setContext(request, response);
fr.render();
} finally {
// 下载完是否回调, 不回调就删除掉临时文件
if (null != callback) {
callback.run(file);
} else if(null != file){
file.delete();
}
}
}
/**
* 渲染模版文件
*
* @return 渲染后的文件
*/
protected File renderFile() {
Map<Object, Object> data = new HashMap<>();
for (Enumeration<String> attrs = request.getAttributeNames(); attrs
.hasMoreElements();) {
String attrName = attrs.nextElement();
data.put(attrName, request.getAttribute(attrName));
}
StringBuilder pathname = new StringBuilder(downloadPath).append("/")
.append(StrKit.getRandomUUID()).append(downloadFileName);
File file = new File(pathname.toString());
getEngine().getTemplate(view).render(data, file);
return file;
}
/**
* 优先使用自定义Engine没有设置的时候使用全局的
*
* @return
*/
protected Engine getEngine() {
return null == MyEngine ? engine : MyEngine;
}
/***
* 文件名称 自动加上时间戳
*/
public FileTemplateRender setDate() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm_");
String dateStr = dateFormat.format(new Date());
downloadFileName = dateStr.concat(downloadFileName);
return this;
}
}
控制器使用姿势:(貌似这个轮子用的较多的地方就是导出XLS文件了, 而且可以和其他的函数使用同一个方法,这个G点自己体会吧)
/**
* 导出
* /weisite/wxcourse/order/toExcel
*/
public void toExcel() {
// 可设置默认值query
setAttr( "recordList", srv.paginate(getLoginAccount(), getQueryParamExport()).getList());
//注意文件后缀名 .xls 或者叫 .csv
render(new FileTemplateRender("wxCouseOrderExcelList.html", "约课列表.xls").setDate());
//调试的时候可以开启这个 注掉上面的,就可以实现预览了
//render("wxCouseOrderExcelList.html");
}
/**
* 单页应用列表数据
* /weisite/wxcourse/order/oneListJson
*/
public void oneListJson() {
renderJsonPage(srv.paginate(getLoginAccount(), getQueryParam()));
}模版文件: #(i18n.get('xxx')) 是我自己造的国际化数据库存储方式轮子这里就不说明了,只是表示这里是可以国际化的,和普通渲染是一样的。如:
.xls 这种适合复杂表头各种跨行跨列都可以, 使用在线表格HTML生成工具合成复杂的表头等信息,再把代码复制过来当模板:
https://www.tablesgenerator.com/html_tables
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=UTF-8">
<meta name=ProgId content=Excel.Sheet>
<meta name=Generator content="Microsoft Excel 15">
</head>
<body topmargin=0 leftmargin=0 >
<table border='1' cellspacing="0" cellpadding="0" >
<thead>
<tr>
<th>序号</th>
<th>学生</th>
<th>班级</th>
<th>#(i18n.get('课程'))</th>
<th>#(i18n.get('教师'))</th>
<th>#(i18n.get('教室'))</th>
<th>#(i18n.get('预约时间'))</th>
<th>#(i18n.get('状态'))</th>
<th>#(i18n.get('请假备注'))</th>
<th>#(i18n.get('签到情况'))</th>
<th>#(i18n.get('签到时间'))</th>
</tr>
<thead>
<tbody>
#for(record : recordList)
<tr>
<td>#(for.count)</td>
<td>#(record.userName)</td>
<td>#(record.className)</td>
<td>#(record.courseName)</td>
<td>#(record.teacherName)</td>
<td>#(record.classRoomName)</td>
<td>#date(record.createTime, "yyyy-MM-dd HH:mm")</td>
<td>#(record.type)</td>
<td>#(record.remark)</td>
<td>#(record.sign)</td>
<td>#date(record.signTime")</td>
</tr>
#end
</table>
</body>
</html>这个不好的地方是第一次会提示 文件不安全, 选择是就可以了, 其他模版则不会

.csv 这种模版比较简单了 (由@三圣乡吴彦祖@简单代码 反馈)
序号,学生,班级,课程,教师,教室,预约时间,状态,请假备注,签到情况,签到时间 #for(record : recordList) #(for.count),#(record.userName),#(record.className),#(record.courseName),#(record.teacherName),#(record.classRoomName),#date(record.createTime, "yyyy-MM-dd HH:mm"),#(record.type),#(record.remark),#(record.sign),#date(record.signTime") #end
.xxx 其他类型的。。。@社友们有其他想法的模版,可在下方评论处贴上 <pre class="brush:java;toolbar:false">你的代码</pre>
导出word文档@zeroabc分享 https://jfinal.com/share/2411
(可选项)
JFinalConfig 中使用同一个Engine
@Override
public void configEngine(Engine me) {
//自定义 模版插件: 如XLS文件导出
FileTemplateRender.setEngine(me);
。。。
}很多时候只是想导出数据,而不是非得弄个真的XLS文件啊,
所以这个可比POI导出XLS爽多了~
当然导出SQL 啊什么的,算了自己想吧~ 手里有锤子就好哈哈~
点个赞呗~