# gok-train-task03 **Repository Path**: zhqwang/gok-train-task03 ## Basic Information - **Project Name**: gok-train-task03 - **Description**: 国科训练营freemark案例 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-12-20 - **Last Updated**: 2020-12-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### GokTask03 - Freemark生成模板化word #### 任务目标 掌握使用freemarker生成word的解决方案 #### 目前实现效果 - 支持给定模板的word简历生成 - 支持基本信息的校验 - 支持时间格式、图片格式 ##### 效果预览 ![](https://cdn.jsdelivr.net/gh/qinwant/Figurebed/img/20201220110842.gif) **生成效果** ![image-20201220111305487](https://cdn.jsdelivr.net/gh/qinwant/Figurebed/img/20201220111308.png) #### 实现过程 ##### 1. 导入依赖 ```xml org.springframework.boot spring-boot-starter-freemarker ``` ##### 2. 核心方法 ```java //预览作用,非可用代码,详情见WordExportUtil.class public void createWord(Map dataMap, String templateName, String saveFilePath) { //加载模板(路径)数据 config.setClassForTemplateLoading(this.getClass(), ""); //设置异常处理器 这样的话 即使没有属性也不会出错 如:${list.name}...不会报错 config.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER); Template template = null; template = config.getTemplate(templateName + ".ftl"); File outFile = new File(saveFilePath); if(!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } Writer out = null; FileOutputStream fos = null; fos = new FileOutputStream(outFile); out = new BufferedWriter(new OutputStreamWriter(fos)); //将模板中的预先的代码替换为数据 template.process(dataMap, out); } ``` ##### 3. 具体思路 - 新建word模板 - 模板另存为`.xml`格式 - 更改`.xml`后缀为`.ftl` - 使用`freemark`语法替换模板 ##### 4. 采坑 - 关于另存为`.xml`格式的坑 > 文件另存为时请选择纯xml文件格式,不要选择wordXML格式。否则会报错 ![image-20201220120915245](https://cdn.jsdelivr.net/gh/qinwant/Figurebed/img/20201220120916.png) - 关于已封装对象在freemark中获取不到属性的问题 > 在对象属性实际有值的情况下任然报错:`The following has evaluated to null or missing` 这是由于实体类的属性命名不规范导致 ```java 学历:${Resume.RsEducation}//无法获取到RsEducation 学历:${Resume.rsEducation}//成功获取到rsEducation ``` - 关于图片显示 阅读ftl发现图片是用base64表示的,所以只需要把后台接受的图片转成**base64**替换即可解决 - 关于word中序号实现 使用`<#list>`循环,并且指定`_index` #### 总结 ##### 1. 关于freemarker - 需要知道基本原理 ![image-20201220123417623](https://cdn.jsdelivr.net/gh/qinwant/Figurebed/img/20201220123420.png) - 需要掌握基本语法 - [FreeMarker教程网](http://www.freemarker.net/) - [什么是 FreeMarker? - FreeMarker 中文官方参考手册 (foofun.cn)](http://freemarker.foofun.cn/) - 需要了解用途(使用场景) ##### 2. 关于前端 在调试页面期间也花费了许多功夫,还是特别不熟练,特别是对表单的校验,ajax请求,数据的传输,文件的上传 - 需要熟练掌握一个前端UI模板 - 以前大多是直接拿页面改,很多前端都没写过,需要多花时间亲手写一写 ##### 3. 关于后端 - 文件上传代码没有规范化(大部分都是copy改写,没理解实质) - 图片转码(在线图片、本地图片转base64)类似这样的可以收集以后直接当成工具类使用,避免临时找 ##### 4. 问题反馈 ![image-20201220125756975](https://cdn.jsdelivr.net/gh/qinwant/Figurebed/img/20201220125758.png) build生成时不会在classes下生成该文件,每次都要手动加,求助解决方案。 ### 未完结 该文档是最初级的一个demo。时间有限,只能以后有时间再一点一点磨,后续的想法 - 如何解决多图片问题 - 如何解决复杂的列表显示 - 特殊元素是否解析正确(公式、特殊字符、转义字符等) - 如何嵌入文件 ##### 兼容性 - word2003、2010等不同版本是否兼容 - wps和office是否兼容 - .doc和.docx是否兼容 ##### 实际可用性 - 生成的文件是否总体效果还行 - 是否支持用户人性化操作