在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>标签包含起来:

<#list users as user>
<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文档的更多相关文章

  1. POI加dom4j将数据库的数据按一定格式生成word文档

    一:需求:将从数据库查处来的数据,生成word文档,并有固定的格式.(dom4j的jar包+poi的jar包) 二:解决:(1)先建立固定格式的word文档(2007版本以上),另存成为xml文件,作 ...

  2. freemarker导出带图片的word文档

    最近做一个关于文档导出功能, 顺便学习了下freemarker,做了个关于导出带图片的word文档,模板并没有写全,只是验证代码的正确性 这只是做一个小功能,故只做了后台代码关于导出的代码,并未与前台 ...

  3. java 使用 POI 操作 XWPFDocumen 创建和读取 Office Word 文档基础篇

    注:有不正确的地方还望大神能够指出,抱拳了 老铁! 参考 API:http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDoc ...

  4. SpringBoot集成文件 - 如何使用POI导出Word文档?

    前文我们介绍了通过Apache POI导出excel,而Apache POI包含是操作Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API.所以 ...

  5. XWPFDocument创建和读取Office Word文档基础篇(一)

    注:有不正确的地方还望大神能够指出,抱拳了 老铁!   参考API:http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDo ...

  6. Java Web用Freemarker生成带图片的Word文档

    步骤一:模板制作 用world2003做一个导出模板,如果有图片则加入一张图片占位,将world另存为xml,将xml中需要导出的内容用Freemarker标签表示,最后另存为.ftl结尾的模板: 步 ...

  7. PHPcms编辑器如何粘贴带格式的word文档

    在之前在工作中遇到在富文本编辑器中粘贴图片不能展示的问题,于是各种网上扒拉,终于找到解决方案,在这里感谢一下知乎中众大神以及TheViper. 通过知乎提供的思路找到粘贴的原理,通过TheViper找 ...

  8. Java 后台创建word 文档

    ---恢复内容开始--- Java 后台创建 word 文档 自己总结  网上查阅的文档 分享POI 教程地址:http://www.tuicool.com/articles/emqaEf6 方式一. ...

  9. Java导出freemarker实现下载word文档格式功能

    首先呢,先说一下制作freemarker模板步骤, 1. 在WPS上写出所要的下载的word格式当做模板 2. 把模板内不固定的内容(例:从数据库读取的信息)写成123或者好代替的文字标注 3. 把固 ...

随机推荐

  1. JavaScript获取浏览器版本等信息

    ** 不同浏览器版本可能存在差异,使用时请测试自己的环境 ** 测试时各个浏览器版本 IE: 11.953.14393.0 Edge: Microsoft Edge 38.14393.0.0;Micr ...

  2. 【Web性能进阶】1.无线网络基础

    一.无所不在的连接 针对不通的使用场景,无线网络技术有很多种. 鉴于无线网络技术如此多样,笼统地概括所有无线网络的性能优化手段是不可能的.好在大多数无线技术的原理都是相通的,衡量性能的指标和约束条件也 ...

  3. Python编程和 Lua编程的比较

    Python编程和 Lua编程的比较 2016.4.21 定义函数: python: def functionname( parameters ): "函数_文档字符串" func ...

  4. Caused by: org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2

    异常信息 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with na ...

  5. cron任务解释

    cron本来是在linux下的一个定时任务执行工具,现在很多语言都支持cron,本文参考https://en.wikipedia.org/wiki/Cron,解释一下cron配置. 概述 cron配置 ...

  6. 挂载mount、卸载umount、挂载光盘U盘

    mount [root@localhost ~]# mount sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel) ...

  7. 谈谈CommonsChunkPlugin抽取公共模块

    引言 webpack插件CommonsChunkPlugin的主要作用是抽取webpack项目入口chunk的公共部分,具体的用法就不做过多介绍,不太了解可以参考webpack官网介绍: 该插件是we ...

  8. spring boot + Thymeleaf开发web项目

    "Spring boot非常适合Web应用程序开发.您可以轻松创建自包含的HTTP应用.web服务器采用嵌入式Tomcat,或者Jetty等.大多数情况下Web应用程序将使用 spring- ...

  9. 阅读MDN文档之基本盒模型(三)

    Box properties Margin collapsing Adjacent siblings(相邻兄弟) Parent and first/last child Empty blocks Ac ...

  10. 封装数据库配置文件App配置文件

    <connectionStrings>   <add name="strCon" connectionString="Data Source=.;Ini ...