SpringBoot整合Freemarker导出word文档表格

freemarker模板里面的template.process()方法里传入的第一个参数Object类型,如果是一个实体类对象在模板上怎么进行渲染,将实体类的值取出

freemarker会调用ObjectWrapper对传入的对象进行warp,具体类型在代码里面用instanceof进行判断。一般类型的实体对象,使用BeanModel进行解析,通过invoke getter方法取到对应的值。

所谓的object类型其实它并不是指所有类型,必须是Collection类型的

文章目录

  • 1、pom.xml
  • 2、制作.ftl模板
    • 2.1 创建word模板
    • 2.2 另存为xml格式,进行简单处理
    • 2.3 创建实体类
    • 2.4处理xml文件
    • 2.5修改后缀为ftl
  • 3、导出word方法
    • 3.1将demo.ftl放入resources/template
    • 3.2通用的word导出方法
    • 3.3执行导出方法
    • 3.4测试效果
  • 4、遇到的坑

1、pom.xml

在pom.xml文件中添加freemarker的依赖包

	<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency>

2、制作.ftl模板

2.1 创建word模板

创建word文档,制定表格。其中需要根据实际替换的元素用${...}书写。
主要包含几种情况:
1)正常需要替换的元素
2)“判断a”、“判断b”演示需要判断是否显示整行
3)“循环合并行”演示没有内容右边为空,有多条数据右边分行显示,左边自动合并。

在这里插入图片描述

2.2 另存为xml格式,进行简单处理

将word文档另存为xml格式。

1)首先找到之前写的替换元素,确保${…}和单词是连在一起的,如果不在一起,就把中间的删掉,处理到一起。
在这里插入图片描述
2)我习惯把xml文件按行给他格式化好
<w:tbl></w:tbl> 表示表格
<w:tr></w:tr> 表示行
<w:tc></w:tc> 表示列
在这里插入图片描述

2.3 创建实体类

public class DemoWordDetail {private String title;private String type;private String time;private String aaa;private int isShowA=1;//控制行显示private String bbb;private int isShowB=1;//控制行显示private List<CyclicModel> cyclics;//合并数据}public class CyclicModel {private String cyclic;/*** 合并标志;第一行"<w:vMerge w:val='restart'/>",后边行"<w:vMerge/>"*/private String merge;}

2.4处理xml文件

1)对于正常需要替换的元素可以不用做任何操作
2)“判断a”、“判断b”演示需要判断是否显示整行,定义字段isShowA、isShowB来控制

在行<w:tr></w:tr>的外层添加<#if></#if>标签,如果isShowA==1则显示这一行,如果为其他值则不显示。

在这里插入图片描述
3)“循环合并行”处理

采用<#if>显示处理数据<#else>显示空白,把${…}删掉</#if>
cyclics.merge处理第一列合并问题;将之前的{cyclics.merge}处理第一列合并问题; 将之前的cyclics.merge处理第一列合并问题;将之前的{cyclic}替换成${cyclics.cyclic}

在这里插入图片描述

2.5修改后缀为ftl

3、导出word方法

3.1将demo.ftl放入resources/template

在这里插入图片描述

3.2通用的word导出方法

@Service
public class WordService {public void exportWord(HttpServletRequest request, HttpServletResponse response, String fileName , String templeteName, Object dataModel){Configuration configuration=new Configuration();configuration.setDefaultEncoding("utf-8");configuration.setEncoding(Locale.getDefault(),"utf-8");try {configuration.setClassicCompatible(true);//处理dataModel中如果为null的情况//既能保证本地运行找得到模板文件,又能保证jar包运行能找到得到模板文件configuration.setClassForTemplateLoading(this.getClass(),"/template");configuration.setTemplateLoader(new ClassTemplateLoader(this.getClass(),"/template"));//            configuration.setDirectoryForTemplateLoading(new File(CommonUtil.getTempletePath()+"/template/"));Template t=configuration.getTemplate(templeteName,"utf-8");response.setContentType("application/msword; charset=UTF-8");// application/x-downloadresponse.setHeader("Content-Disposition", "attachment; "+ encodeFileName(request, fileName+".doc"));OutputStream outputStream = response.getOutputStream();Writer out=new OutputStreamWriter(outputStream);// 重要方法 <-----------------t.process(dataModel, out);outputStream.close();out.close();} catch (IOException | TemplateException e) {e.printStackTrace();}}public static String encodeFileName(HttpServletRequest request, String fileName)throws UnsupportedEncodingException{String new_filename = URLEncoder.encode(fileName, "UTF8").replaceAll("\\+", "%20");String agent = request.getHeader("USER-AGENT").toLowerCase();if (null != agent && -1 != agent.indexOf("msie")){/*** IE浏览器,只能采用URLEncoder编码*/return "filename=\"" + new_filename +"\"";}else if (null != agent && -1 != agent.indexOf("applewebkit")){/*** Chrome浏览器,只能采用ISO编码的中文输出*/return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\"";} else if (null != agent && -1 != agent.indexOf("opera")){/*** Opera浏览器只可以使用filename*的中文输出* RFC2231规定的标准*/return "filename*=" + new_filename ;}else if (null != agent && -1 != agent.indexOf("safari")){/*** Safani浏览器,只能采用iso编码的中文输出*/return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\"";}else if (null != agent && -1 != agent.indexOf("firefox")){/*** Firfox浏览器,可以使用filename*的中文输出* RFC2231规定的标准*/return "filename*=" + new_filename ;} else{return "filename=\"" + new_filename +"\"";}}}

3.3执行导出方法

        DemoWordDetail demoWordDetail=new DemoWordDetail();//一系列处理wordService.exportWord(request, response, "title", "demo.ftl", demoWordDetail);

3.4测试效果

判断a、判断b均显示,循环合并行多条数据

img

判断a这行不显示,循环合并行无数据

img

4、遇到的坑

1)导出对象字段有为null时,报错,加上“configuration.setClassicCompatible(true);2)idea运行能正常导出,jar运行不能找到模板,代码中给出了解决
3)cmd运行jar,能正常导出word,但是打开错误。经过测试发现导出word文档乱码,发现是是cmd默认编码问题,在cmd执行时加上:start javaw -Dfile.encoding=utf-8 -jar xxx.jar

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554822.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ambari 修改服务器名,Ambari修改主页面方法

分享下Ambari修改主页面方法&#xff0c;希望对大家有用。[roothdp159 ambari-web]# brunch watch --serverOct 10:22:43 - info: application started on http://localhost:3333/Oct 10:22:47 - info: compiled 891 files into 5 files, copied 260 in 3988msOct 10:23:12 - i…

快速向服务器传文件格式,客户端如何向服务器传文件格式

客户端如何向服务器传文件格式 内容精选换一换语音通话平台通过此接口向客户推送语音通话业务用户呼叫时的状态信息&#xff0c;如呼入、呼出、振铃、应答、挂机等状态的信息。语音通话平台(客户端) → 客户服务器(服务端)前提条件SP在开发应用时&#xff0c;若需订阅呼叫状态通…

MyBatis-Plus--解决逻辑删除与唯一索引的问题--方法/实例

文章目录简介问题复现依赖**建库建表**代码测试解决方案方案1&#xff1a;将字段设置为id&#xff08;推荐&#xff09;建库建表修改Entity测试方案2&#xff1a;将字段设置为当前时间&#xff08;不推荐&#xff09;建库建表修改Entity测试简介 说明 本文用示例介绍MyBatis-…

MybatisPlus 实体类与数据库表映射关系MybatisPlus:ORM思想

实体类与数据库表映射关系 使用mybatisPlus时&#xff0c;会确定实体类和数据的映射关系 具体的映射方法有两种 1、默认&#xff1a;采用驼峰映射规则 例如MyUserTable 对应的数据库表为 my_user_table ; TEMyUserTable 对应表名为t_e_my_user_table; 2、注解TableName 在…

Spring Boot——maven项目常用打包配置

文章目录一、简介二、pom.xml三、效果图3.1 所有的资源打包到指定的目录maven3.2 所有的配置文件都放到config目录3.3 所有的配置文件都不在jar里&#xff0c;防止敏感信息泄露结语一、简介 maven项目打包是我们程序员经常遇到的事&#xff0c;今天就来弄一个常用的打包方式&a…

史上最全ThreadLocal 详解

文章目录一、ThreadLocal简介二、ThreadLocal与Synchronized的区别三、ThreadLocal的简单使用四、ThreadLocal的原理4.1 ThreadLocal的set()方法&#xff1a;4.2 ThreadLocal的get方法4.3 ThreadLocal的remove方法4.4、ThreadLocal与Thread&#xff0c;ThreadLocalMap之间的关系…

Java递归构建树形结构

记录&#xff1a;在Java后台利用递归思路进行构建树形结构数据&#xff0c;返回给前端&#xff0c;能以下拉菜单等形式进行展示。 简明&#xff1a;为了简化代码&#xff0c;引入Lombok的Jar包&#xff0c;可省略实体类set()、get()方法。 <dependency><groupId>or…

HTTP状态码含义:428、429、431、511431状态码详解

1、428 Precondition Required (要求先决条件) ​ 先决条件是客户端发送 HTTP 请求时&#xff0c;必须要满足的一些预设条件。一个好的例子就是 If-None-Match 头&#xff0c;经常用在 GET 请求中。如果指定了 If-None-Match &#xff0c;那么客户端只在响应中的 ETag 改变后才…

Java 异常——Exception详解

异常的介绍 异常的概念 异常 &#xff1a;指的是程序在执行过程中&#xff0c;出现的非正常的情况&#xff0c;最终会导致JVM的非正常停止。 在Java等面向对象的编程语言中&#xff0c;异常本身是一个类&#xff0c;产生异常就是创建异常对象并抛出了一个异常对象。Java处理…

Java中的URL类根据url获取网络文件快速入门Java中的URL(网络编程)

Java中的URL类 远程连接来实现应用。而且&#xff0c;这个平台现在已经可 以对国际互联网以及URL资源进行访问了。Java的URL类可以让访问网络资源就像是访问你本地的文件夹一样方便快捷。我们通过使用Java的URL类 就可以经由URL完成读取和修改数据的操作。 通过一个URL连接&a…

SpringMVC中Controller为什么能够处理并发访问?Springboot中的定时任务是否会发生阻塞?

文章目录SpringMVC中Controller为什么能够处理并发访问&#xff1f;当多个请求同时访问服务器的时候Controller、Service、DAO是线程安全的吗&#xff1f;关于类中的变量Controller、Service、DAO等类都默认为单例模式Controller、Service、DAO等类中的方法当中的并发问题关于D…

Java进阶 - 易错知识点整理

转载&#xff1a;https://blog.csdn.net/qq_33934427/article/details/125903960 文章目录1、JavaEE2、网络基础3、Mysql4、Spring/SpringMVC&#xff08;IOC装配、AOP增强、常用注解&#xff09;5、Spring Boot/Spring Cloud1&#xff09;SpringBoot部分2&#xff09;SpringCl…

MySQL 视图(详解) navicat如何创建视图

文章目录MySQL 视图&#xff08;详解一&#xff0c;视图概念使用视图的原因二&#xff0c;创建视图&#xff08;1&#xff09;基本语法&#xff08;2&#xff09;创建基于单表的视图【实例 1】【实例 2】&#xff08;3&#xff09;创建基于多表的视图【实例 3】&#xff08;4&a…

使用set集合去除重复元素@EqualsAndHashCode注解

如何使用set集合去重 ​ 我们都知道&#xff0c;set集合是无序的&#xff0c;这样也导致set集合里面的元素是不能重复的&#xff0c;因为这一个特性&#xff0c;所以我们经常用set集合进行去重操作&#xff0c;我们下面以一个简单的例子说明set集合是如何进行去重的。 创建去…

缺少构造方法:Cause java.sql.SQLDataException Unsupported conversion from LONG to java.sql.Timestamp

今天遇到了一个奇怪的错误&#xff0c;报错如下图所示&#xff1a; org.springframework.dao.DataIntegrityViolationException: Error attempting to get column question_id from result set. Cause: java.sql.SQLDataException: Unsupported conversion from LONG to java…

SpringBoot瘦身打包部署

一、前言 最近做的项目由于引入第三方库导致在运行mvn clean package 打jar时&#xff0c;编译出来的 Jar 包很大&#xff08;服务器多达500MB&#xff09;。 二、瘦身前的Jar包 SpringBoot编译出来的Jar包中&#xff0c;磁盘占用大的&#xff0c;是一些外部依赖库&#xff…

XShell直接拖拽文件到服务器,不使用Xftp等文件上传工具

很多情况下&#xff0c;我们使用 Xshell 工具时&#xff0c;如果遇到文件的上传和下载会不可避免的要用到另外一个工具 Xftp&#xff0c;但是频繁的使用 Xftp 会比较麻烦&#xff0c;那么有没有一种更加直接简单的方法呢&#xff1f; 当我们所需要上传的文件比较小的时候&…

System.getProperty()方法获取系统变量

今天在阅读JDBC的DriverManager类源码时&#xff0c;看到了这么一句代码&#xff1a; System.getProperty(“jdbc.drivers”)&#xff1b;getProperty()这个方法是获取指定键指示的系统属性的&#xff0c;也就是说上面的代码获取的是jdbc.drivers这个属性。我写了个测试测试输…

局部变量为什么必须赋值才可以使用

在java内存模型中规定&#xff0c;一个新的变量只能在主存中初始化&#xff0c;不允许在工作内存中直接使用一个未被初始化的变量。 工作内存可以理解为局部变量定义的内存区域&#xff0c;也就是线程的工作内存。所谓局部变量就是线程私有的不共享的空间。 类加载准备阶段 类变…

Java 赋值 “=” 讲解

前言 我们从接触java第一天&#xff0c;就是到 是赋值的意思&#xff0c;把等号右边结果的值&#xff0c;赋给等号左边的变量&#xff0c;那具体是怎样赋值呢&#xff1f;你有了解过吗&#xff1f; 1.0版本 大家都知道&#xff0c;java中有 8大基本类型&#xff0c;对于基本…