看见群里在说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 啊什么的,算了自己想吧~ 手里有锤子就好哈哈~
点个赞呗~