基于springboot的freemarker创建指定格式的word文档
在web或其他应用中,经常我们需要导出或者预览word文档,比较实际的例子有招聘网站上预览或者导出个人简历,使用POI导出excel会非常的方便,但是如果想导出word,由于其格式控制非常复杂,故而使用POI将会非常麻烦,而FreeMarker则可以较好的解决这个问题;并且,根据FreeMarker的实现原理,预览word也会变得非常简单。
FreeMarker主要有三个部分:模板,数据源以及数据的存储。可想而知,在导出word的时候,我们必须得告诉FreeMarker我们需要导出的word的格式以及将要填充到这个word中的数据,因而模板和数据源是我们需要准备的部分。这里需要另外说明的是,FreeMarker关心的不是模板文件的类型或具体内容,其关心的是模板文件中的ftl标签和其中获取数据的表达式(这部分将在后续进行讲解)。FreeMarker的强大之处也就在这个位置,这里的模板可以是任意类型的模板,而数据源由我们按照指定的格式封装即可。那么也就是说,对于预览操作,我们如果事先制作一个html模板,点击预览后由FreeMarker向按照该模板向新建的html文件中填充数据,接着在前台js中新开窗口将该html文件(填充数据后即为一个静态页面)显示出来即可达到预览的效果。
这里我们以word文件的导出为例来讲解FreeMarker的使用,我们使用的IDE为Intellij IDEA,框架为springboot,项目是使用Maven构建的。
模板文件的创建可以使用word2007及以上版本完成,首先我们创建一个如下格式的word文档:
创建后将该文件以xml格式存储
使用xml文本编辑器打开该xml文件,检查其中的取值表达式是否发生格式错误,如果发生格式错误就将其中错误的部分删除,使其恢复我们填写的格式(格式错误一般会发生在取值表达式中含有特殊字符的时候)。
如图中所示,${user.password}就发生了格式错误,我们将中间错误部分删除后如下:
接着将该模板文件另存为UserList.ftl,文件格式为全部文件:
将该文件复制到项目中,打开并格式化,找到其中${user.username}和${user.password},仔细分析该ftl文件可以发现,在word文档中表格的每一行在xml文件中即为一个<w:tr></w:tr>标签,而在该标签中,每一个<w:tc></w:tc>则对应一个单元格。了解这个之后,我们就要使用ftl语法对该模板文件进行改造。这里我们需要导出的是一个用户列表的文件,每个用户包含一个用户名和密码,那么这里用户所在的这一行(<w:tr></w:tr>)就需要使用ftl中的<#list></#list>标签包含起来:
<w:tr>
<w:tc>
...
用户名:
...
</w:tc>
<w:tc>
...
${user.username}
...
</w:tc>
<w:tc>
...
密码:
...
</w:tc>
<w:tc>
...
${user.password}
...
</w:tc>
</w:tr>
</#list>
到此为止,我们的ftl模板就制作完毕了。接下来我们创建后台服务端的代码,实体类创建如下:
public class User { private String username;
private String password; public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public User() {
} public User(String username, String password) {
this.username = username;
this.password = password;
}
}
Controller层创建如下:
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; @RestController
@RequestMapping("/word")
public class WordController { @Autowired
private WordService wordService; @RequestMapping(value = "/createUserListWord", method = RequestMethod.GET)
public ResponseEntity<Void> createUserListWord() {
wordService.createUserListWord();
return ResponseEntity.ok().build();
}
}
Service层的接口及其实现类如下:
public interface WordService {
void createUserListWord();
}
import javax.transaction.Transactional; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.springframework.stereotype.Service;
@Service
public class WordServiceImpl implements WordService {
public void createUserListWord() {
Map<?, ?> root = initData(); //数据源对象
String template = "/template/UserList.ftl"; //模板文件的地址
String path = "E:\\UserList.doc"; //生成的word文档的输出地址
WordUtil.process(root, template, path);
} private Map<?, ?> initData() {
Map<String, Object> root = new HashMap<String, Object>(); List<User> users = new ArrayList<User>();
User zhangsan = new User("张三", "123");
User lisi = new User("李四", "456");
User wangwu = new User("王五", "789");
users.add(zhangsan);
users.add(lisi);
users.add(wangwu); root.put("users", users);
root.put("title", "用户列表"); return root;
}
}
这里需要说明的一点是,在FreeMarker中,数据一般是以Map,List以及实体类对象的形式存储,这里数据的初始化函数中则将三种形式的数据存储方式都用到了。在模板中取值的时候,对于Map对象中的数据,使用${key}即可获取,这里key表示Map中的键,对于List,则可以使用下标的方式,也可以使用循环的方式,这里我们是将User对象存储于List中,在模板中则可以使用users[i]来获取List中第i个User对象,如users[i].username;也可以使用循环来对List集合进行遍历,如
<#list users as user>
${user.username}
</#list>
这里users表示存储List的Map的key的值。
最后则是FreeMarker中生成word文档的核心函数:
import freemarker.template.Configuration;
import freemarker.template.Template; import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set; public final class WordUtil {
private static Configuration configuration = null; private WordUtil() {
throw new AssertionError();
} /**
* 根据模板生成相应的文件
* @param root 保存数据的map
* @param template 模板文件的地址
* @param path 生成的word文档输出地址
* @return
*/
public static synchronized File process(Map<?, ?> root, String template, String path) { if (null == root ) {
throw new RuntimeException("数据不能为空");
} if (null == template) {
throw new RuntimeException("模板文件不能为空");
} if (null == path) {
throw new RuntimeException("输出路径不能为空");
} File file = new File(path);
String templatePath = template.substring(0, template.lastIndexOf("/"));
String templateName = template.substring(template.lastIndexOf("/") + 1, template.length()); if (null == configuration) {
configuration = new Configuration(Configuration.VERSION_2_3_23); // 这里Configurantion对象不能有两个,否则多线程访问会报错
configuration.setDefaultEncoding("utf-8");
configuration.setClassicCompatible(true);
}
configuration.setClassForTemplateLoading(WordUtil.class, templatePath); Template t = null;
try {
t = configuration.getTemplate(templateName);
Writer w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8"));
t.process(root, w); // 这里w是一个输出地址,可以输出到任何位置,如控制台,网页等
w.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
return file;
} }
至此,使用FreeMarker生成word文档的核心代码已经全部书写完毕,最后打开浏览器访问http://localhost:8081/word/createUserListWord,在E盘根目录下就会生成一个word文档,其内容如下:
这只是FreeMarker的一个简单应用,关于FreeMarker生成html文件,这里有一点需要说明,word2007及以上版本保存文件的格式可以为xml文件,也可以为html文件,检查该html文件中取值表达式的格式无误之后按照上述步骤也可以生成我们需要的html文件,但是生成的html文件的格式不一定是我们需要的格式,并且在修改ftl模板的时候,由于模板中标签元素的样式等较多,因而修改较为复杂。若想达到预览的效果,我们可以不使用上述方法生成的html模板,而是手动书写一份格式一致的html文件,然后保存为ftl格式模板,这个过程并不复杂,并且可读性较强。
基于springboot的freemarker创建指定格式的word文档的更多相关文章
- POI加dom4j将数据库的数据按一定格式生成word文档
一:需求:将从数据库查处来的数据,生成word文档,并有固定的格式.(dom4j的jar包+poi的jar包) 二:解决:(1)先建立固定格式的word文档(2007版本以上),另存成为xml文件,作 ...
- freemarker导出带图片的word文档
最近做一个关于文档导出功能, 顺便学习了下freemarker,做了个关于导出带图片的word文档,模板并没有写全,只是验证代码的正确性 这只是做一个小功能,故只做了后台代码关于导出的代码,并未与前台 ...
- java 使用 POI 操作 XWPFDocumen 创建和读取 Office Word 文档基础篇
注:有不正确的地方还望大神能够指出,抱拳了 老铁! 参考 API:http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDoc ...
- SpringBoot集成文件 - 如何使用POI导出Word文档?
前文我们介绍了通过Apache POI导出excel,而Apache POI包含是操作Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API.所以 ...
- XWPFDocument创建和读取Office Word文档基础篇(一)
注:有不正确的地方还望大神能够指出,抱拳了 老铁! 参考API:http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDo ...
- Java Web用Freemarker生成带图片的Word文档
步骤一:模板制作 用world2003做一个导出模板,如果有图片则加入一张图片占位,将world另存为xml,将xml中需要导出的内容用Freemarker标签表示,最后另存为.ftl结尾的模板: 步 ...
- PHPcms编辑器如何粘贴带格式的word文档
在之前在工作中遇到在富文本编辑器中粘贴图片不能展示的问题,于是各种网上扒拉,终于找到解决方案,在这里感谢一下知乎中众大神以及TheViper. 通过知乎提供的思路找到粘贴的原理,通过TheViper找 ...
- Java 后台创建word 文档
---恢复内容开始--- Java 后台创建 word 文档 自己总结 网上查阅的文档 分享POI 教程地址:http://www.tuicool.com/articles/emqaEf6 方式一. ...
- Java导出freemarker实现下载word文档格式功能
首先呢,先说一下制作freemarker模板步骤, 1. 在WPS上写出所要的下载的word格式当做模板 2. 把模板内不固定的内容(例:从数据库读取的信息)写成123或者好代替的文字标注 3. 把固 ...
随机推荐
- 自学Zabbix3.1-语言切换
题记: 默认使用的zabbix版本为Zabbix 3.0.8 登陆到zabbix web控制台默认是英文界面,对有些英文不好或者习惯中文的人来说会有不适应. 实际上是切换到中文版本,步骤:点击用户 ...
- Mybatis中模糊查询的各种写法(转)
. sql中字符串拼接 SELECT * FROM tableName WHERE name LIKE CONCAT(CONCAT('%', #{text}), '%');或者 <if test ...
- Error updating database. Cause: java.sql.BatchUpdateException: Field 'id' doesn't have a default value
异常信息 ### Error updating database. Cause: java.sql.BatchUpdateException: Field 'id' doesn't have a de ...
- 以List为例浅谈C#的学习方法
前言:关于学习方法的讨论其实是个比较模糊的概念,对于List的介绍的资料其实已经很多了,但是一般是介绍List本身,我打算分享的是,以温故List为例,来获取新知识的这么一个过程.这里的新知识也不是什 ...
- iOS 类似朋友圈的图片浏览器SDPhotoBrowser
SDPhotoBrowser.Demo 1.在文件SDBrowserImageView.m中有用SDWebImage到网络加载图片 需要的注释去掉即可 #import "ViewContro ...
- iOS 网络状态判断方案(支持iOS11和iPhoneX)
在之前的iPhone中.我们可以根据导航栏上方的网络状态view.来判断网络状态.(这种方案本来就不太好) 这种方案在iPhone X 手机上.不可使用. 我们可以通过 Reachability 来 ...
- Java 伙伴系统(模拟)
参考:https://labrick.cc/2015/10/12/buddy-system-algorithm/ 代码过烂 不宜参考. output: [operating.entity.Heap@4 ...
- bzoj 1196: [HNOI2006]公路修建问题
Description OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发不久,所以那里的交通情况还是很糟糕.所以,OIER Association组织 ...
- rabbitMQ教程(三) spring整合rabbitMQ代码实例
一.开启rabbitMQ服务,导入MQ jar包和gson jar包(MQ默认的是jackson,但是效率不如Gson,所以我们用gson) 二.发送端配置,在spring配置文件中配置 <?x ...
- ioutil包二
ioutil包二 (原创随笔,转载请注明出处 http://www.cnblogs.com/majianguo/p/8016426.html) ioutil包实现了一些I/O实用功能,导出了7个函数和 ...