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