首先声明我的项目是一个web项目,生成的word文件直接通过response响应发送给前端。如果不是web项目的话可以像网上的其他教程一样将生成的word保存在本地。

要利用freemarker生成word文档,首先需要创建word文档模板(即.doc文档),word模板中要动态生成的文字都使用占位符${string}代替,如下图

将word模板另存为xml文件

然后将文件的后缀.xml改为.ftl。
将这个模板(.ftl)文件放到我们项目的resource目录下,这里我是新建了一个wordtemp文件夹,用于放word模板。顺便放两张图片在这个wordtemp目录下。

打开这个模板文件。这里有一个坑,在word另存为xml文件的时候很可能会把我们写好的占位符拆分掉,就像下面这样

我们需要自己手动把占位符${string}恢复,只需把中间多余的标签删除掉就好

然后我们找到<<w:binData>标签,会发现这个标签中有一大堆的英文字符串

这些字符串是图片的base64码。
我们将这些base64码删除掉,用一个占位符替代

为了实现动态的添加表格行数和图片数量,我们还要用到freemarker的<list>标签。
list标签的语法:<#list 集合名 as 迭代元素临时变量名></#list>

<w:tr></w:tr>标签表示word中的表格的一行记录,我们找到<w:tr></w:tr>标签,并用freemarker的<list>标签将其包起来。



找到离我们的图片占位符最近的<w:p></w:p>标签,用list标签将他们括起来

模板文件修改完了,接下来我们开始在代码里为这些占位符填充数据。
引入freemarker依赖:

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

创建一个单例的Configuration对象,真心不推荐像网上的很多教程一样,每次生成word都要重新创建一个Configuration

@org.springframework.context.annotation.Configuration
public class WordConf {/*** 将freemarker的Configuration对象作为一个单例对象,可以避免重复创建的性能开销* 这里我是将Configuration对象作为bean交给spring容器来管理,如果不是spring项目的话可以自己写一个单例模式* 从Configuration类上的注释可以找到说明:Configuration是有状态的,线程不安全的,但是它的各种get方法是线程安全的* 所以一旦这个单例对象被配置好以后就不该再调用它的set方法* @return*/@Beanpublic Configuration wordConfiguration(){Configuration result = new Configuration(DEFAULT_INCOMPATIBLE_IMPROVEMENTS);result.setDefaultEncoding("utf-8");//设置模板加载器result.setClassForTemplateLoading(this.getClass(), "/wordtemp");return result;}
}

书本实体类代码:

@Data
@AllArgsConstructor
public class Book {private String name;private Double price;private Date createTime;
}

controller层代码

@Controller
@Slf4j
public class WordController {@Resource(name = "wordConfiguration")private Configuration wordConfiguration;/*** 导出word* @param response*/@GetMapping("/getBookWord")public void getBookWord(HttpServletResponse response) {//书本集合List<Book> books = new ArrayList<>();books.add(new Book("笑傲江湖", 20.5, new Date()));books.add(new Book("倚天屠龙记", 30.8, new Date()));try {//图片的base64集合List<String> bookImages = new ArrayList<>();String image1 = encodeBase64File("wordtemp/timg.jpg");String image2 = encodeBase64File("wordtemp/timg_2.jpg");bookImages.add(image1);bookImages.add(image2);Map<String, Object> dataModel = new HashMap<>();dataModel.put("shopName", "陈大大出版社");dataModel.put("books", books);dataModel.put("bookImages", bookImages);response.setCharacterEncoding("UTF-8");response.setHeader("Content-Disposition", "attachment; filename=books.doc");//加载模板Template template = wordConfiguration.getTemplate("booksTemp.ftl", "utf-8");template.process(dataModel, response.getWriter());//response的Writer不需要我们手动关,tomcat会帮我们关的} catch (Exception e) {log.error("导出word异常:",  e);}}/*** 将文件转为base64字符串* @param path 文件地址* @return* @throws IOException*/public String encodeBase64File(String path) throws IOException {//读取resource目录下的文件try (InputStream inputStream = WordController.class.getClassLoader().getResourceAsStream(path)){byte[] buffer = new byte[inputStream.available()];inputStream.read(buffer);return new BASE64Encoder().encode(buffer);}}}

启动项目,用浏览器测试一下,成功下载了word


总结一下用freemarker生成word的几个步骤:

  1. 创建word,在word中设计排版,要动态生成的文字使用占位符${string}
  2. 将word另存为xml文件。将保存好的xml文件后缀修改为.ftl
  3. 将模板文件(.ftl)放到项目中,打开文件看看占位符是否被拆分了。
  4. 编写Java代码,给占位符赋值。

PS,由于freemarker每次生成word都要从磁盘中读取.ftl文件,相比于其他纯内存生成word的工具包,freemarker多了一次IO操作,所以性能稍弱,不适用于大并发的场景。

Java使用freemarker生成word文件相关推荐

  1. Java使用freemarker生成word文档并转pdf文档

    Java使用freemarker生成word文档后转pdf 先来看看效果图 进入正题 项目需求: 为订单后生成对应的pdf文档,文档内包含图片. 方案一:使用freemarker和itext把html ...

  2. 若依 springboot 使用freemarker生成word文件,并导出下载

    目录 freemarker生成word文件并导出 一.环境准备 二.编写代码 1.实体类 2.mapper.xml文件 3.mapper.java文件 4.Service.java 5.Service ...

  3. Freemarker生成word文件,打开后页眉和页脚图片不显示

    Freemarker生成word文件,打开后页眉和页脚图片不显示 在我们开发过程中通常会把模板文件Ctrl+Alt+L格式化,方便处理.这样就造成word的标签格式产生多余的换行或者空白,但是word ...

  4. Java 用 Freemarker 生成 Word 时内容换行

    一.原因 试过各种换行符 '\r' '\n' '\r\n' '(char)11' 全部都不行!!! 原因是:Java 用 Freemarker 生成 Word 时的换行符被自动解析忽略掉 二.解决方法 ...

  5. Java技术:SpringBoot集成FreeMarker生成word文件

                    今天给大家分享SpringBoot集成FreeMarker模板引擎生成word文件的用法,感兴趣的可以学一下,完整源码地址在文章末尾处,欢迎互相沟通交流! 一.什么是F ...

  6. Java通过Freemarker生成docx文件

    一:doc和docx文件 首先我们要了解doc和docx两种word文件的相同点和不同点,为什么ftl可以直接生成doc而生成docx就会报错. 1.doc和docx文件构成 我们可以把doc格式的w ...

  7. Java实现freemarker生成word模板

    博主在做的是将word源文件中的内容读取出来,然后按照固定的格式输出,当然,源文件有大量,所以编写了程序来批量自动生成目标文件. 本文要介绍的就是如何生成模板,并将从源文件截取的内容填充到模板文件(即 ...

  8. Java使用iText生成word文件的完美解决方案(亲测可行)

    JAVA生成WORD文件的方法目前有以下种: 一种是jacob 但是局限于windows平台 往往许多JAVA程序运行于其他操作系统 在此不讨论该方案 一种是pio但是他的excel处理很程序 wor ...

  9. Java使用iText生成word文件的解决方案

    JAVA生成WORD文件的方法目前有以下种: 一种是jacob 但是局限于windows平台 往往许多JAVA程序运行于其他操作系统 在此不讨论该方案 一种是pio但是他的excel处理很程序 wor ...

最新文章

  1. 一段C语言和汇编的对应分析,揭示函数调用的本质
  2. linux cmake编译源码,linux安装mysql(源码)以及cmake编译
  3. Windows版本Oracle审计日志,【情报】Oracle ORA-28056: 未能将审计记录写入 Windows 事件日志...
  4. router3 BGP2 属性及选路
  5. MD5 32位加密算法源码(测试通过)(系转载 飞扬天下)
  6. STM32跑分?看看你的能跑多少分!
  7. Google | 突破瓶颈,打造更强大的Transformer
  8. AI 崛起,科学家的天下,程序员的谢幕
  9. [PhalApi实战篇(1)]Redis队列处理异步任务
  10. JAVA-数据类型、变量、常量
  11. python基础语法手册-python语法手册
  12. c 语言重载参数类型不同重载和,C/C++函数重载与缺省参数
  13. 考虑云计算来降成本:良药或毒药?
  14. 电脑计算机推荐笔记本电脑,十佳办公笔记本电脑排名,性价比高的笔记本电脑推荐...
  15. cce是什么意思_CCE 是什么
  16. thunderbird 配置exchange邮箱
  17. lay和lied_高考英语词汇辨析:lie, lay, lain, laid, lying等用法
  18. 如何看懂Elastic解决方案与Gartner的魔力象限
  19. 又省时间又省心,微信小程序记住密码功能大揭秘
  20. Out of range value for column

热门文章

  1. 中文电码查询接口 标准中文电码查询程序结果
  2. Android-生成二维码工具类
  3. 西北乱跑娃 --- python命令行换源配置
  4. c++内存释放的几种方法
  5. GetLastError
  6. Android 攻城狮的进击 1 开发环境搭建HelloWorld.apk
  7. react 和 vue(组件化) 实现两份数据的差异对比 合并及撤销
  8. B站 MySQL学习随手记 全是满满的干货!
  9. 51单片机之温度传感器与液晶显示屏
  10. Java EE项目中异常设计及处理总结