龙空技术网

FreeMarker模板引擎

风后奇门柳坤生 906

前言:

如今看官们对“htmlfreemark”大体比较看重,你们都想要剖析一些“htmlfreemark”的相关内容。那么小编也在网上网罗了一些关于“htmlfreemark””的相关内容,希望大家能喜欢,朋友们快快来学习一下吧!

  前言

  FreeMarker是一款模板引擎,即一种基于模板和要改变的数据,并用来生成输出文本的通用工具。

  官方文档:

  日常开发中,我们会有这样的需求:

  1、在页面上填写数据并导出word文档、后台批量设置数据并导出Excel文档(例如我们之前的博客记录:html页面转PDF、图片操作记录)

  2、写一个代码生成工具(例如我们之前的博客记录:写一个简单的代码生成器)

  这种情况下我们可以用FreeMarker模板引擎来实现,本文记录FreeMarker简单操作。

  代码编写

  maven引入依赖

<dependency>    <groupId>org.freemarker</groupId>    <artifactId>freemarker</artifactId>    <version>2.3.31</version></dependency>

  Word/Excel操作

  Word操作

  例如,要导出员工档案,格式如下:

  我们先按照格式要求,写好word文档,然后另存为xml,得到模板文件

  用idea打开word.xml,格式化一下,然后根据FreeMarker的语法表达式读取、设置值

  封装一个方法

    //Word文档操作    private static void createWord(){        System.out.println("开始Word文档操作...");        //指定TemplateLoading模板根路径        String rootPath = "E:\\Java\\test\\";        //模板文件        String templatePath = "word.xml";        //最终输出文件路径        String outFilePath = rootPath+"word_by_freemarker.docx";        //数据        Map<String, Object> data = new HashMap<>();        data.put("company","某某公司");        data.put("number","0001");        data.put("name","huanzi-qch");        data.put("phone","15600000000");        data.put("department","软件开发部");        data.put("post","开发工程师");        ArrayList<Map<String, String>> works = new ArrayList<>();        Map<String, String> work1 = new HashMap<>();        work1.put("company","某某单位1");        work1.put("time","2018-01 - 2019-01");        work1.put("department","研发1部");        work1.put("post","开发工程师");        works.add(work1);        Map<String, String> work2 = new HashMap<>();        work2.put("company","某某单位2");        work2.put("time","2019-01 - 2020-01");        work2.put("department","研发2部");        work2.put("post","开发工程师");        works.add(work2);        data.put("works",works);        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFilePath), StandardCharsets.UTF_8));){            //初始化,指定版本与pom文件相同            Configuration configuration = new Configuration(new Version("2.3.31"));            configuration.setDefaultEncoding(StandardCharsets.UTF_8.toString());            configuration.setDirectoryForTemplateLoading(new File(rootPath));            Template template = configuration.getTemplate(templatePath);            //处理(数据)            template.process(data, writer);        } catch (IOException | TemplateException e) {            e.printStackTrace();        }        System.out.println("Word文档操作结束!");    }

  效果

  Excel操作

  Excel操作同理,也是先创建一个例子,另存为xml格式,再根据FreeMarker的语法表达式设置值

  按照字段名,建Excel例子时直接把取值代码写进去,转成xml后就可能省一点时间

  同样,idea打开后格式化一下,遍历设置值

  封装一个方法

    //Word文档操作    private static void createWord(){        System.out.println("开始Word文档操作...");        //指定TemplateLoading模板根路径        String rootPath = "E:\\Java\\test\\";        //模板文件        String templatePath = "word.xml";        //最终输出文件路径        String outFilePath = rootPath+"word_by_freemarker.docx";        //数据        Map<String, Object> data = new HashMap<>();        data.put("company","某某公司");        data.put("number","0001");        data.put("name","huanzi-qch");        data.put("phone","15600000000");        data.put("department","软件开发部");        data.put("post","开发工程师");        ArrayList<Map<String, String>> works = new ArrayList<>();        Map<String, String> work1 = new HashMap<>();        work1.put("company","某某单位1");        work1.put("time","2018-01 - 2019-01");        work1.put("department","研发1部");        work1.put("post","开发工程师");        works.add(work1);        Map<String, String> work2 = new HashMap<>();        work2.put("company","某某单位2");        work2.put("time","2019-01 - 2020-01");        work2.put("department","研发2部");        work2.put("post","开发工程师");        works.add(work2);        data.put("works",works);        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFilePath), StandardCharsets.UTF_8));){            //初始化,指定版本与pom文件相同            Configuration configuration = new Configuration(new Version("2.3.31"));            configuration.setDefaultEncoding(StandardCharsets.UTF_8.toString());            configuration.setDirectoryForTemplateLoading(new File(rootPath));            Template template = configuration.getTemplate(templatePath);            //处理(数据)            template.process(data, writer);        } catch (IOException | TemplateException e) {            e.printStackTrace();        }        System.out.println("Word文档操作结束!");    }

  效果

  代码生成器

  代码生成器,先把我们之前写好的JDBC连接数据库工具类、字符串处理工具类、表结构信息实体类以及获取表结构信息的方法先拿过来

    /**     * 程序自动设置     */    private static String tableName;//表名    private static String tableComment;//表注释    /**     * 数据连接相关,需要手动设置     */    private static final String URL = "jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&characterEncoding=utf-8";    private static final String USERNAME = "root";    private static final String PASSWORD = "123456";    private static final String DRIVER_CLASSNAME = "com.mysql.cj.jdbc.Driver";    /**     * 字符串处理工具类     */    private static class StringUtil {        /**         * 数据库类型->JAVA类型         *         * @param dbType 数据库类型         * @return JAVA类型         */        private static String typeMapping(String dbType) {            String javaType;            if ("int|integer".contains(dbType)) {                javaType = "Integer";            } else if ("float|double|decimal|real".contains(dbType)) {                javaType = "Double";            } else if ("date|time|datetime|timestamp".contains(dbType)) {                javaType = "Date";            } else {                javaType = "String";            }            return javaType;        }        /**         * 驼峰转换为下划线         */        private static String underscoreName(String camelCaseName) {            StringBuilder result = new StringBuilder();            if (camelCaseName != null && camelCaseName.length() > 0) {                result.append(camelCaseName.substring(0, 1).toLowerCase());                for (int i = 1; i < camelCaseName.length(); i++) {                    char ch = camelCaseName.charAt(i);                    if (Character.isUpperCase(ch)) {                        result.append("_");                        result.append(Character.toLowerCase(ch));                    } else {                        result.append(ch);                    }                }            }            return result.toString();        }        /**         * 首字母大写         */        private static String captureName(String name) {            char[] cs = name.toCharArray();            cs[0] -= 32;            return String.valueOf(cs);        }        /**         * 下划线转换为驼峰         */        private static String camelCaseName(String underscoreName) {            StringBuilder result = new StringBuilder();            if (underscoreName != null && underscoreName.length() > 0) {                boolean flag = false;                for (int i = 0; i < underscoreName.length(); i++) {                    char ch = underscoreName.charAt(i);                    if ("_".charAt(0) == ch) {                        flag = true;                    } else {                        if (flag) {                            result.append(Character.toUpperCase(ch));                            flag = false;                        } else {                            result.append(ch);                        }                    }                }            }            return result.toString();        }    }    /**     * JDBC连接数据库工具类     */    private static class DBConnectionUtil {        static {            // 1、加载驱动            try {                Class.forName(DRIVER_CLASSNAME);            } catch (ClassNotFoundException e) {                e.printStackTrace();            }        }        /**         * 返回一个Connection连接         */        static Connection getConnection() {            Connection conn = null;            // 2、连接数据库            try {                conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);            } catch (SQLException e) {                e.printStackTrace();            }            return conn;        }        /**         * 关闭Connection,Statement连接         */        public static void close(Connection conn, Statement stmt) {            try {                conn.close();                stmt.close();            } catch (SQLException e) {                e.printStackTrace();            }        }        /**         * 关闭Connection,Statement,ResultSet连接         */        public static void close(Connection conn, Statement stmt, ResultSet rs) {            try {                close(conn, stmt);                rs.close();            } catch (SQLException e) {                e.printStackTrace();            }        }    }    /**     * 表结构信息实体类     */    private static class TableInfo {        private String columnName;//字段名        private String dataType;//字段类型        private String columnComment;//字段注释        private String columnKey;//主键        private String extra;//主键类型        public String getColumnName() {            return columnName;        }        public void setColumnName(String columnName) {            this.columnName = columnName;        }        public String getDataType() {            return dataType;        }        public void setDataType(String dataType) {            this.dataType = dataType;        }        public String getColumnComment() {            return columnComment;        }        public void setColumnComment(String columnComment) {            this.columnComment = columnComment;        }        public String getColumnKey() {            return columnKey;        }        public void setColumnKey(String columnKey) {            this.columnKey = columnKey;        }        public String getExtra() {            return extra;        }        public void setExtra(String extra) {            this.extra = extra;        }    }    /**     * 获取表结构信息     * 目前仅支持mysql     */    private static List<TableInfo> getTableInfo() {        Connection conn = null;        PreparedStatement ps = null;        ResultSet rs = null;        ArrayList<TableInfo> list = new ArrayList<>();        try {            conn = DBConnectionUtil.getConnection();            //表字段信息            String sql = "select column_name,data_type,column_comment,column_key,extra from information_schema.columns where table_schema = (select database()) and table_name=?";            ps = conn.prepareStatement(sql);            ps.setString(1, tableName);            rs = ps.executeQuery();            while (rs.next()) {                TableInfo tableInfo = new TableInfo();                //列名,全部转为小写                tableInfo.setColumnName(rs.getString("column_name").toLowerCase());                //列类型                tableInfo.setDataType(rs.getString("data_type"));                //列注释                tableInfo.setColumnComment(rs.getString("column_comment"));                //主键                tableInfo.setColumnKey(rs.getString("column_key"));                //主键类型                tableInfo.setExtra(rs.getString("extra"));                list.add(tableInfo);            }            //表注释            sql = "select table_comment from information_schema.tables where table_schema = (select database()) and table_name=?";            ps = conn.prepareStatement(sql);            ps.setString(1, tableName);            rs = ps.executeQuery();            while (rs.next()) {                //表注释                tableComment = rs.getString("table_comment");            }        } catch (SQLException e) {            e.printStackTrace();        } finally {            if(rs != null){                DBConnectionUtil.close(conn, ps, rs);            }        }        return list;    }

  从原来的代码生成器那里拿一个entity.tlf模板,小改动一下(主要是循环、if判断哪里不一样)

package cn.huanzi.qch.baseadmin.sys.${entityToLowerCase}.pojo;import lombok.Data;import javax.persistence.*;import java.io.Serializable;import java.util.Date;/** * ${tableComment} 实体类 * * ${author} * ${date} */@Entity@Table(name = "${tableName}")@Datapublic class ${entity} implements Serializable {  <#list tableInfos as tableInfo>    <#if tableInfo.columnKey == "PRI">@Id</#if>    <#if tableInfo.extra == "auto_increment">@GeneratedValue(strategy= GenerationType.IDENTITY)</#if>    private ${tableInfo.dataType} ${tableInfo.columnName};//${tableInfo.columnComment}  </#list>}

  封装一个方法

    //代码生成    private static void autoGenerator(String tName){        System.out.println("开始代码生成操作...");        tableName = tName;        //指定TemplateLoading模板根路径        String rootPath = "E:\\Java\\test\\";        //模板文件        String templatePath = "entity.tlf";        //最终输出文件路径        String outFilePath = rootPath+"entity.java";        //数据        Map<String, Object> data = new HashMap<>();        //驼峰标识映射后的表名        String captureName = StringUtil.captureName(StringUtil.camelCaseName(tableName));        //获取表信息,并进行处理        List<TableInfo> tableInfoList = getTableInfo();        ArrayList<Map<String, String>> tableInfos = new ArrayList<>();        for (TableInfo info : tableInfoList) {            HashMap<String, String> hashMap = new HashMap<>();            hashMap.put("columnName", StringUtil.camelCaseName(info.getColumnName()));            hashMap.put("dataType", StringUtil.typeMapping(info.getDataType()));            hashMap.put("columnComment", info.getColumnComment());            hashMap.put("columnKey", info.getColumnKey());            hashMap.put("extra", info.getExtra());            tableInfos.add(hashMap);        }        data.put("entityToLowerCase",captureName.toLowerCase());        data.put("tableComment",tableComment);        data.put("author","作者:Auto Generator By 'huanzi-qch'");        data.put("date","生成日期:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));        data.put("tableName",tableName);        data.put("entity",captureName);        data.put("tableInfos",tableInfos);        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFilePath), StandardCharsets.UTF_8));){            //初始化,指定版本与pom文件相同            Configuration configuration = new Configuration(new Version("2.3.31"));            configuration.setDefaultEncoding(StandardCharsets.UTF_8.toString());            configuration.setDirectoryForTemplateLoading(new File(rootPath));            Template template = configuration.getTemplate(templatePath);            //处理(数据)            template.process(data, writer);        } catch (IOException | TemplateException e) {            e.printStackTrace();        }        System.out.println("代码生成操作结束!");    }

  效果

  完整代码

import freemarker.template.Configuration;import freemarker.template.Template;import freemarker.template.TemplateException;import freemarker.template.Version;import java.io.*;import java.nio.charset.StandardCharsets;import java.sql.*;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Date;public class Test {    //Word文档操作    private static void createWord(){        System.out.println("开始Word文档操作...");        //指定TemplateLoading模板根路径        String rootPath = "E:\\Java\\test\\";        //模板文件        String templatePath = "word.xml";        //最终输出文件路径        String outFilePath = rootPath+"word_by_freemarker.docx";        //数据        Map<String, Object> data = new HashMap<>();        data.put("company","某某公司");        data.put("number","0001");        data.put("name","huanzi-qch");        data.put("phone","15600000000");        data.put("department","软件开发部");        data.put("post","开发工程师");        ArrayList<Map<String, String>> works = new ArrayList<>();        Map<String, String> work1 = new HashMap<>();        work1.put("company","某某单位1");        work1.put("time","2018-01 - 2019-01");        work1.put("department","研发1部");        work1.put("post","开发工程师");        works.add(work1);        Map<String, String> work2 = new HashMap<>();        work2.put("company","某某单位2");        work2.put("time","2019-01 - 2020-01");        work2.put("department","研发2部");        work2.put("post","开发工程师");        works.add(work2);        data.put("works",works);        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFilePath), StandardCharsets.UTF_8));){            //初始化,指定版本与pom文件相同            Configuration configuration = new Configuration(new Version("2.3.31"));            configuration.setDefaultEncoding(StandardCharsets.UTF_8.toString());            configuration.setDirectoryForTemplateLoading(new File(rootPath));            Template template = configuration.getTemplate(templatePath);            //处理(数据)            template.process(data, writer);        } catch (IOException | TemplateException e) {            e.printStackTrace();        }        System.out.println("Word文档操作结束!");    }    //Excel文档操作    private static void createExcel(){        System.out.println("开始Excel文档操作...");        //指定TemplateLoading模板根路径        String rootPath = "E:\\Java\\test\\";        //模板文件        String templatePath = "excel.xml";        //最终输出文件路径        String outFilePath = rootPath+"excel_by_freemarker.xlsx";        //数据        Map<String, Object> data = new HashMap<>();        ArrayList<Map<String, String>> persons = new ArrayList<>();        Map<String, String> person1 = new HashMap<>();        person1.put("name","huanzi-qch1");        person1.put("phone","15600000000");        person1.put("company","某某单位1");        person1.put("time","2018-01 - 2019-01");        person1.put("department","研发1部");        person1.put("post","开发工程师");        persons.add(person1);        Map<String, String> person2 = new HashMap<>();        person2.put("name","huanzi-qch2");        person2.put("phone","15600000000");        person2.put("company","某某单位2");        person2.put("time","2019-01 - 2020-01");        person2.put("department","研发2部");        person2.put("post","开发工程师");        persons.add(person2);        data.put("persons",persons);        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFilePath), StandardCharsets.UTF_8));){            //初始化,指定版本与pom文件相同            Configuration configuration = new Configuration(new Version("2.3.31"));            configuration.setDefaultEncoding(StandardCharsets.UTF_8.toString());            configuration.setDirectoryForTemplateLoading(new File(rootPath));            Template template = configuration.getTemplate(templatePath);            //处理(数据)            template.process(data, writer);        } catch (IOException | TemplateException e) {            e.printStackTrace();        }        System.out.println("Excel文档操作结束!");    }    //代码生成    private static void autoGenerator(String tName){        System.out.println("开始代码生成操作...");        tableName = tName;        //指定TemplateLoading模板根路径        String rootPath = "E:\\Java\\test\\";        //模板文件        String templatePath = "entity.tlf";        //最终输出文件路径        String outFilePath = rootPath+"entity.java";        //数据        Map<String, Object> data = new HashMap<>();        //驼峰标识映射后的表名        String captureName = StringUtil.captureName(StringUtil.camelCaseName(tableName));        //获取表信息,并进行处理        List<TableInfo> tableInfoList = getTableInfo();        ArrayList<Map<String, String>> tableInfos = new ArrayList<>();        for (TableInfo info : tableInfoList) {            HashMap<String, String> hashMap = new HashMap<>();            hashMap.put("columnName", StringUtil.camelCaseName(info.getColumnName()));            hashMap.put("dataType", StringUtil.typeMapping(info.getDataType()));            hashMap.put("columnComment", info.getColumnComment());            hashMap.put("columnKey", info.getColumnKey());            hashMap.put("extra", info.getExtra());            tableInfos.add(hashMap);        }        data.put("entityToLowerCase",captureName.toLowerCase());        data.put("tableComment",tableComment);        data.put("author","作者:Auto Generator By 'huanzi-qch'");        data.put("date","生成日期:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));        data.put("tableName",tableName);        data.put("entity",captureName);        data.put("tableInfos",tableInfos);        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFilePath), StandardCharsets.UTF_8));){            //初始化,指定版本与pom文件相同            Configuration configuration = new Configuration(new Version("2.3.31"));            configuration.setDefaultEncoding(StandardCharsets.UTF_8.toString());            configuration.setDirectoryForTemplateLoading(new File(rootPath));            Template template = configuration.getTemplate(templatePath);            //处理(数据)            template.process(data, writer);        } catch (IOException | TemplateException e) {            e.printStackTrace();        }        System.out.println("代码生成操作结束!");    }    /**     * 程序自动设置     */    private static String tableName;//表名    private static String tableComment;//表注释    /**     * 数据连接相关,需要手动设置     */    private static final String URL = "jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&characterEncoding=utf-8";    private static final String USERNAME = "root";    private static final String PASSWORD = "123456";    private static final String DRIVER_CLASSNAME = "com.mysql.cj.jdbc.Driver";    /**     * 字符串处理工具类     */    private static class StringUtil {        /**         * 数据库类型->JAVA类型         *         * @param dbType 数据库类型         * @return JAVA类型         */        private static String typeMapping(String dbType) {            String javaType;            if ("int|integer".contains(dbType)) {                javaType = "Integer";            } else if ("float|double|decimal|real".contains(dbType)) {                javaType = "Double";            } else if ("date|time|datetime|timestamp".contains(dbType)) {                javaType = "Date";            } else {                javaType = "String";            }            return javaType;        }        /**         * 驼峰转换为下划线         */        private static String underscoreName(String camelCaseName) {            StringBuilder result = new StringBuilder();            if (camelCaseName != null && camelCaseName.length() > 0) {                result.append(camelCaseName.substring(0, 1).toLowerCase());                for (int i = 1; i < camelCaseName.length(); i++) {                    char ch = camelCaseName.charAt(i);                    if (Character.isUpperCase(ch)) {                        result.append("_");                        result.append(Character.toLowerCase(ch));                    } else {                        result.append(ch);                    }                }            }            return result.toString();        }        /**         * 首字母大写         */        private static String captureName(String name) {            char[] cs = name.toCharArray();            cs[0] -= 32;            return String.valueOf(cs);        }        /**         * 下划线转换为驼峰         */        private static String camelCaseName(String underscoreName) {            StringBuilder result = new StringBuilder();            if (underscoreName != null && underscoreName.length() > 0) {                boolean flag = false;                for (int i = 0; i < underscoreName.length(); i++) {                    char ch = underscoreName.charAt(i);                    if ("_".charAt(0) == ch) {                        flag = true;                    } else {                        if (flag) {                            result.append(Character.toUpperCase(ch));                            flag = false;                        } else {                            result.append(ch);                        }                    }                }            }            return result.toString();        }    }    /**     * JDBC连接数据库工具类     */    private static class DBConnectionUtil {        static {            // 1、加载驱动            try {                Class.forName(DRIVER_CLASSNAME);            } catch (ClassNotFoundException e) {                e.printStackTrace();            }        }        /**         * 返回一个Connection连接         */        static Connection getConnection() {            Connection conn = null;            // 2、连接数据库            try {                conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);            } catch (SQLException e) {                e.printStackTrace();            }            return conn;        }        /**         * 关闭Connection,Statement连接         */        public static void close(Connection conn, Statement stmt) {            try {                conn.close();                stmt.close();            } catch (SQLException e) {                e.printStackTrace();            }        }        /**         * 关闭Connection,Statement,ResultSet连接         */        public static void close(Connection conn, Statement stmt, ResultSet rs) {            try {                close(conn, stmt);                rs.close();            } catch (SQLException e) {                e.printStackTrace();            }        }    }    /**     * 表结构信息实体类     */    private static class TableInfo {        private String columnName;//字段名        private String dataType;//字段类型        private String columnComment;//字段注释        private String columnKey;//主键        private String extra;//主键类型        public String getColumnName() {            return columnName;        }        public void setColumnName(String columnName) {            this.columnName = columnName;        }        public String getDataType() {            return dataType;        }        public void setDataType(String dataType) {            this.dataType = dataType;        }        public String getColumnComment() {            return columnComment;        }        public void setColumnComment(String columnComment) {            this.columnComment = columnComment;        }        public String getColumnKey() {            return columnKey;        }        public void setColumnKey(String columnKey) {            this.columnKey = columnKey;        }        public String getExtra() {            return extra;        }        public void setExtra(String extra) {            this.extra = extra;        }    }    /**     * 获取表结构信息     * 目前仅支持mysql     */    private static List<TableInfo> getTableInfo() {        Connection conn = null;        PreparedStatement ps = null;        ResultSet rs = null;        ArrayList<TableInfo> list = new ArrayList<>();        try {            conn = DBConnectionUtil.getConnection();            //表字段信息            String sql = "select column_name,data_type,column_comment,column_key,extra from information_schema.columns where table_schema = (select database()) and table_name=?";            ps = conn.prepareStatement(sql);            ps.setString(1, tableName);            rs = ps.executeQuery();            while (rs.next()) {                TableInfo tableInfo = new TableInfo();                //列名,全部转为小写                tableInfo.setColumnName(rs.getString("column_name").toLowerCase());                //列类型                tableInfo.setDataType(rs.getString("data_type"));                //列注释                tableInfo.setColumnComment(rs.getString("column_comment"));                //主键                tableInfo.setColumnKey(rs.getString("column_key"));                //主键类型                tableInfo.setExtra(rs.getString("extra"));                list.add(tableInfo);            }            //表注释            sql = "select table_comment from information_schema.tables where table_schema = (select database()) and table_name=?";            ps = conn.prepareStatement(sql);            ps.setString(1, tableName);            rs = ps.executeQuery();            while (rs.next()) {                //表注释                tableComment = rs.getString("table_comment");            }        } catch (SQLException e) {            e.printStackTrace();        } finally {            if(rs != null){                DBConnectionUtil.close(conn, ps, rs);            }        }        return list;    }    public static void main(String[] args) {//        createWord();//        createExcel();//        autoGenerator("tb_user");    }}

  后记

  通过FreeMarker,按照固定格式,快速生成Word、Excel文档,或者生成代码,简单高效。

  生成文档,数据来源可能是直接读库获取,也有可能是要用户在页面上填写,再传入后台,这时候就可以将我们的模板文件,另存为html格式,小调整之后就可以展示给用户,最大程度保证了用户看到的文档页面跟生成、导出的文档格式是一致的。

版权声明

作者:huanzi-qch

出处:

若标题中有“转载”字样,则本文版权归原作者所有。若无转载字样,本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.

标签: #htmlfreemark