《SpringBoot篇》24.SpringBoot整合Freemarker超详细教程

news2024/12/27 11:34:50
陈老老老板🦸
👨‍💻本文专栏:SpringBoot篇(主要讲一些与springboot整合相关的内容)
👨‍💻本文简述:本文讲一下SpringBoot整合Freemarker的整合教程超详细教程。
👨‍💻上一篇文章: 《SpringBoot篇》23.SpringBoot整合JavaMail实现发送邮件详解
👨‍💻有任何问题,都可以私聊我,我能帮得上的一定帮忙,感谢大佬们支持。
🦹如果喜欢可以投个票吗?在文章最后,感谢感谢!

在这里插入图片描述

一、Freemarker简介

说明:FreeMarker 是一款 免费的模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。(我所接触到的是用Freemarker来导出excel、word、pdf

模板编写为FreeMarker Template Language (FTL)。它是简单的,专用的语言. 那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。

二、Freemarker语法:

说明:这里给大家展示一些常用的语法,这些就足以完成复杂的语法功能。

(1)if elseif,条件判断语句

说明:你可以使用 if, elseif 和 else 指令来条件判断是否越过模板的一个部分。 condition 必须计算成布尔值, 否则错误将会中止模板处理。elseif 和 else 必须出现在 if 内部 (也就是,在 if 的开始标签和结束标签之间)。 if 中可以包含任意数量的 elseif(包括0个) 而且结束时 else 是可选的。比如:

只有 if 没有 elseif 和 else:

<#if x == 1>
  x is 1
</#if>

只有 if 没有 elseif 但是有 else:

<#if x == 1>
  x is 1
<#else>
  x is not 1
</#if>

有 if 和两个 elseif 但是没有 else:

<#if x == 1>
  x is 1
<#elseif x == 2>
  x is 2
<#elseif x == 3>
  x is 3
</#if>

有 if 和三个 elseif 还有 else:

<#if x == 1>
  x is 1
<#elseif x == 2>
  x is 2
<#elseif x == 3>
  x is 3
<#elseif x == 4>
  x is 4
<#else>
  x is not 1 nor 2 nor 3 nor 4
</#if>

(2)list 遍历

说明:list 指令执行在 list 开始标签和 list 结束标签 ( list 中间的部分) 之间的代码, 对于在序列(或集合)中每个值指定为它的第一个参数。 对于每次迭代,循环变量(本例中的 user)将会存储当前项的值。

循环变量(user) 仅仅存在于 list 标签体内。 而且从循环中调用的宏/函数不会看到它(就像它只是局部变量一样)。

假设 users 包含 ['Joe', 'Kate', 'Fred'] 序列:
<#list users as user>
  <p>${user}
</#list>

输出:

  <p>Joe
  <p>Kate
  <p>Fred

(3)assign 在模板中定义变量

说明:在模板中可以定义三种类型的变量:(我们最多就能使用到简单的使用assign就可以了)

  • '‘简单’'变量: 它能从模板中的任何位置来访问,或者从使用 include 指令引入的模板访问。可以使用 assign 指令来创建或替换这些变量。因为宏和方法只是变量,那么 macro 指令 和 function 指令 也可以用来设置变量,就像 assign 那样。

  • 局部变量:它们只能被设置在 宏定义体内, 而且只在宏内可见。一个局部变量的生命周期只是宏的调用过程。可以使用 local指令 在宏定义体内创建或替换局部变量。

  • 循环变量:循环变量是由如 list 指令自动创建的,而且它们只在指令的开始和结束标记内有效。宏 的参数是局部变量而不是循环变量。

  • 全局变量:这是一个高级话题了, 并且这种变量最好别用。即便它们属于不同的命名空间, 全局变量也被所有模板共享,因为它们是被 import进来的, 不同于 include 进来的。那么它们的可见度就像数据模型那样。 全局变量通过 global指令来定义。

<#assign x = 1>  <#-- create variable x -->
${x}
<#assign x = x + 3> <#-- replace variable x -->
${x}

输出:

1
4

(4)字符串切分 (子串)

说明:前面的是对字符串进行分割,后面的在进行遍历的时候需要进行字符串分割。

  • 降序域不允许进行字符串切分。 (因为不像序列那样,很少情况下会想反转字符串。 如果真要这样做了,那就是疏忽。)

  • 如果变量的值既是字符串又是序列(多类型值), 那么切分将会对序列进行,而不是字符串。当处理XML时, 这样的值就是普通的了。此时,可以使用 someXMLnode?string[range]。

  • 一个遗留的bug:值域 包含 结尾时, 结尾小于开始索引并且是是非负的(就像在 “abc”[1…0] 中), 会返回空字符串而不是错误。(在降序域中这应该是个错误。) 现在这个bug已经向后兼容,但是不应该使用它,否在就会埋下一个错误。

<#assign s = "ABCDEF">
${s[2..3]}
${s[2..<4]}
${s[2..*3]}
${s[2..*100]}
${s[2..]}

输出:

CD
CD
CDE
CDEF
CDEF
<#assign seq = ["A", "B", "C"]>

Slicing with length limited ranges:
- <#list seq[0..*2] as i>${i}</#list>
- <#list seq[1..*2] as i>${i}</#list>
- <#list seq[2..*2] as i>${i}</#list> <#-- Not an error -->
- <#list seq[3..*2] as i>${i}</#list> <#-- Not an error -->

Slicing with right-unlimited ranges:
- <#list seq[0..] as i>${i}</#list>
- <#list seq[1..] as i>${i}</#list>
- <#list seq[2..] as i>${i}</#list>
- <#list seq[3..] as i>${i}</#list>

输出:

Slicing with length limited ranges:
- AB
- BC
- C
-

Slicing with right-unlimited ranges:
- ABC
- BC
- C
-

三、SpringBoot整合Freemarker

项目运行环境:

  • idea2020.2
  • jdk1.8
  • springboot 2.7.5

(1)pom.xml文件

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

(2)实体类

说明: 在domain下建立实体类Student

@Data
public class Student {

    private Integer id;

    private String name;
}

项目样图:这里把目录也给大家看一下
在这里插入图片描述

(3)实现类

说明:在Service下创建StudentService,在Impl下创建StudentServiceImpl

public interface StudentService {
    //生成数据方法
    public List<Student> initFillData();
    //生成Excel方法
    public  void parse(String templateDir, String templateName, String excelPath, Map<String, Object> data)throws IOException, TemplateException;
}

项目样图
在这里插入图片描述

@Service
public class StudentServiceImpl  implements StudentService{

    /**
     * 解析模板生成Excel
     * @param templateDir  模板目录
     * @param templateName 模板名称
     * @param excelPath 生成的Excel文件路径
     * @param data 数据参数

     */
    public void parse(String templateDir,String templateName,String excelPath,Map<String,Object> data) throws IOException, TemplateException {
        //初始化工作
        Configuration cfg = new Configuration();
        //设置默认编码格式为UTF-8
        cfg.setDefaultEncoding("UTF-8");
        //全局数字格式
        cfg.setNumberFormat("0.00");
        //设置模板文件位置
        cfg.setDirectoryForTemplateLoading(new File(templateDir));
        cfg.setObjectWrapper(new DefaultObjectWrapper());
        //加载模板
        Template template = cfg.getTemplate(templateName,"utf-8");
        OutputStreamWriter writer = null;
        try{
            //填充数据至Excel
            writer = new OutputStreamWriter(new FileOutputStream(excelPath),"UTF-8");
            template.process(data, writer);
            writer.flush();
        }finally{
            writer.close();
        }
    }
//  生成数据方式
    public  List<Student> initFillData() {
        ArrayList<Student> fillDatas = new ArrayList<Student>();
        for (int i = 1; i < 51; i++) {
            Student fillData = new Student();
            fillData.setId(i);
            fillData.setName("0123456789="+ i);
            fillDatas.add(fillData);
        }
        return fillDatas;
    }

}

项目样图
在这里插入图片描述

(4)测试类

说明:要注意模板位置与excel生成位置,自己更改或先创建目录。

@SpringBootTest
class FreemarkerApplicationTests {

    @Autowired
    private StudentService studentService;

    @Test
    public void excelTest(){
        List<Student> students = studentService.initFillData();
        int totalCount = students.size();
        Map<String,Object> data = new HashMap<String, Object>();
        data.put("studentList", students);
        data.put("totalCount",totalCount);
        try {
            //这里前面是模板位置,后面是生成的excel位置
            studentService.parse("D:\\study\\projecct\\freemarker\\src\\main\\resources\\templates\\", "Freemark.xml",
                    "E:\\excel\\excelTest30.xls", data);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }
    }
    
}

项目样图
在这里插入图片描述

(5)模板

说明: 注意模板中使用了一个list对数据进行遍历。模板名就是测试类中模板名。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office"
          xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
          xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
    <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
        <Author>Apache POI</Author>
        <LastAuthor>chenqingtao</LastAuthor>
        <Created>2020-03-16T08:20:00Z</Created>
        <LastSaved>2022-11-03T07:31:58Z</LastSaved>
    </DocumentProperties>
    <CustomDocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
        <ICV dt:dt="string">9DC2DE9132B4460BB7A5E14BF585E55C</ICV>
        <KSOProductBuildVer dt:dt="string">2052-11.1.0.12650</KSOProductBuildVer>
    </CustomDocumentProperties>
    <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
        <WindowWidth>24225</WindowWidth>
        <WindowHeight>12540</WindowHeight>
        <ProtectStructure>False</ProtectStructure>
        <ProtectWindows>False</ProtectWindows>
    </ExcelWorkbook>
    <Styles>
        <Style ss:ID="Default" ss:Name="Normal">
            <Alignment ss:Vertical="Center"/>
            <Borders/>
            <Font ss:FontName="等线" x:CharSet="134" ss:Size="11" ss:Color="#000000"/>
            <Interior/>
            <NumberFormat/>
            <Protection/>
        </Style>
        <Style ss:ID="s49"/>
        <Style ss:ID="s50">
            <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
            <Borders>
                <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
                <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
                <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
                <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
            </Borders>
            <Font ss:FontName="宋体" x:CharSet="134" ss:Size="14" ss:Bold="1"/>
            <Interior ss:Color="#C0C0C0" ss:Pattern="Solid"/>
        </Style>
    </Styles>

<Worksheet ss:Name="0">
<Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="2" x:FullColumns="1" x:FullRows="1"
       ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">
    <Column ss:Index="1" ss:StyleID="Default" ss:AutoFitWidth="0" ss:Width="120" ss:Span="1"/>
    <Row ss:Height="30">
        <Cell ss:StyleID="s50">
            <Data ss:Type="String">学生姓名</Data>
        </Cell>
        <Cell ss:StyleID="s50">
            <Data ss:Type="String">学生ID</Data>
        </Cell>
    </Row>
    <#list studentList as student>
    <Row>
        <Cell>
            <Data ss:Type="String">${student.name}</Data>
        </Cell>
        <Cell>
            <Data ss:Type="Number">${student.id}</Data>
        </Cell>
    </Row>
</#list>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
    <Header x:Margin="0.3"/>
    <Footer x:Margin="0.3"/>
    <PageMargins x:Left="0.7" x:Right="0.7" x:Top="0.75" x:Bottom="0.75"/>
</PageSetup>
<Selected/>
<TopRowVisible>0</TopRowVisible>
<LeftColumnVisible>0</LeftColumnVisible>
<PageBreakZoom>100</PageBreakZoom>
<Panes>
    <Pane>
        <Number>3</Number>
        <ActiveRow>7</ActiveRow>
        <ActiveCol>3</ActiveCol>
        <RangeSelection>R8C4</RangeSelection>
    </Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
        </Worksheet>
        </Workbook>

项目样图
在这里插入图片描述

生成位置
在这里插入图片描述
生成excel样式
在这里插入图片描述

总结:SpringBoot整合Freemarker超详细教程。希望对您有帮助,感谢阅读

结束语:裸体一旦成为艺术,便是最圣洁的。道德一旦沦为虚伪,便是最下流的。
勇敢去做你认为正确的事,不要被世俗的流言蜚语所困扰。

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

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

相关文章

SPL 和 SQL 能不能融合在一起?

文章目录SPL 和 SQL 能不能融合在一起&#xff1f;SPL资料SPL 和 SQL 能不能融合在一起&#xff1f; SQL和SPL都是面向结构化数据的通用处理技术。SQL普及率高受众广&#xff0c;很多用户天生就会用SQL查询数据&#xff0c;如果数据引擎支持SQL就会很容易上手&#xff0c;而且…

【MySQL】数据库约束与聚合查询和联合查询等进阶操作知识汇总

目录1.数据库约束:1.1 约束的类型:1.2 unique:1.3 primary key:1.3.1 分布式系统下,自增主键如何生成唯一id:1.4 foreign key:1.4.1 逻辑删除:2.表的设计/数据库的设计:2.1 数据库是如何设计的?3.进阶插入操作:4.进阶查询:4.1 聚合查询:4.2 group by 列名:4.3 联合查询/多表查…

2508. 添加边使所有节点度数都为偶数 c++

给你一个有 n 个节点的 无向 图&#xff0c;节点编号为 1 到 n 。再给你整数 n 和一个二维整数数组 edges &#xff0c;其中 edges[i] [ai, bi] 表示节点 ai 和 bi 之间有一条边。图不一定连通。 你可以给图中添加 至多 两条额外的边&#xff08;也可以一条边都不添加&#x…

C51——定时器控制寄存器

定时器的本质原理&#xff1a; 每经过一个一起周期&#xff0c;就加1 在寄存器里加 当我们想要操作寄存器的时候 就要找到TCON 当它开始数数的时候&#xff0c;会有天花板&#xff0c;会有溢出。 那我们怎么知道他溢出了&#xff1f;有TF0&#xff0c;当TF0 出现变化的时…

【剧前爆米花--爪哇岛寻宝】

作者&#xff1a;困了电视剧 专栏&#xff1a;《JavaSE语法与底层详解》 文章分布&#xff1a;这是一篇关于接口的文章&#xff0c;在本篇文章中我会将接口常用的一些实例进行讲解&#xff0c;以及部分方法在重写中的思想。 目录 Comparable和Comparator接口使用 Object类 t…

JDBC的简单使用与封装

目录 1、JDBC 2、JDBC的常用接口 1.Driver接口 2.Connection接口 3.Statement接口 4.ResultSet接口 3、JDBC的基本使用 1&#xff09;、简单的增删查改 Ⅰ、查 Ⅱ、增 Ⅲ、改 Ⅳ、删 2&#xff09;简单封装 1、JDBC 我们先了解JDBC是什么&#xff0c;JDBC的全称是Java数…

2018年全国职业技能大赛中职组“网络安全”赛项—基础题(解析)

2018年全国职业技能大赛中职组“网络安全”赛项—基础题&#xff08;解析&#xff09; 任务一、nmap 1、nmap sP -n 192.168.100.133 //进行ping扫描 1.1、nmap -Pn -n 192.168.100.133 //目标禁用 绕过ping 扫描 2、nmap -A -n ip // 对ip进行综合性扫描 3、nmap -O -n…

TiDB-学习笔记

编写这个笔记&#xff0c;希望能记录下学习TiDB时候的知识点。 目录 第一章 1.事务 1.1 SQL-92标准&#xff1a; 1.2 事务的隔离级别 2.在TiDB学习 SQL 语句 第二章 第三章 第一章 1.事务 事务的特性&#xff08;ACID&#xff09; atomicity原子性、consistency一致性、i…

网上花店网页代码 html静态花店网页设计制作 dw静态鲜花网页成品模板素材网页 web前端网页设计与制作 div静态网页设计

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

全志V853 在 NPU 转换 YOLO V3 模型

NPU 转换 YOLO V3 模型 YOLO 全称是 You Only Look Once&#xff08;你只需看一次&#xff09;&#xff0c;从名称上也能看出这种算法速度快的优势&#xff0c;因此在许多边缘设备上&#xff0c;YOLO 算法的使用十分广泛。YOLOV3 是华盛顿大学研究生 Joseph Redmon 所开发&…

matlab学习笔记(九)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 matlab学习笔记&#xff08;九&#xff09;一、信号采样二、信号重建一、信号采样 信号的采样原理图如下图所示&#xff1a; 其数学模型表示为&#xff1a; 其中的f(t)为原…

11、Mysql高级之SQL优化

11、Mysql高级之SQL优化 文章目录11、Mysql高级之SQL优化0 SQL优化1 大批量插入数据2 优化insert语句3 优化order by语句3.1 环境准备3.2 两种排序方式3.3 Filesort 的优化4 优化group by 语句5 优化嵌套查询6 优化OR条件7 优化分页查询7.1 优化思路一7.2 优化思路二8 使用SQL提…

【Budibase】搭建低代码开发平台

Budibase介绍 Budibase 是一套开源的低代码开发平台&#xff0c;支持一键数据库及API 接入&#xff0c;支持简单的 JS 关联前后端数据&#xff0c;有细致的权限访问管理&#xff0c;对移动端有良好的支持。它主打企业流程自动化&#xff0c;有完善的自动化流程设计&#xff0c…

NETDMIS5.0界面介绍

1.启动界面介绍 双击桌面快捷方式&#xff0c;打开NET.DMISS启动界面如下图&#xff0c;包含三个菜单是文件、设置语言、帮助。 2.工作界面介绍 默认测量界面包括主菜单&#xff0c;工具条&#xff0c;节点程序界面&#xff08;显示测量过程&#xff09;&#xff0c;CAD视窗…

(免费分享)基于ssm简易网盘系统

开发工具&#xff1a;IDEA&#xff0c;mysql5.7 Tomcat8.0&#xff0c;jdk1.8 package cn.tangtj.clouddisk.web;import cn.tangtj.clouddisk.entity.User; import cn.tangtj.clouddisk.utils.UserUtil; import org.apache.logging.log4j.LogManager; import org.apache.loggi…

嵌入式应用开发|Linux文件I/O常用的四种访问方式

在Linux系统中&#xff0c;一切都可以看成"文件"<通常包含&#xff1a;普通文件、驱动文件、网络通信文件等等>&#xff0c;系统中所有的操作都可以通过文件I/O实现&#xff0c;因此&#xff0c;掌握文件常用接口很有必要。 0.前言 屏幕前的你如果懂得main函数…

SAP S4 如何快速配置一家公司

之前配置公司采用的方法是copy的方式来配置&#xff0c;后来在做其他配置的时候发现&#xff0c;copy的方法会把很多不需要的配置也copy进来了。所就我从新定义了一个公司来进行学习研究。配置一定空的公司很简单&#xff0c;只需要三步&#xff1a; 1 定义和分配公司 • 公司…

Java中的异常、IO与NIO面试题

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java面试题…

萤石网络通过注册:9个月净利2亿同比降28% 海康威视为大股东

雷递网 雷建平 12月19日杭州萤石网络股份有限公司&#xff08;简称&#xff1a;“萤石网络”&#xff09;日前通过注册&#xff0c;准备在科创板上市。萤石网络计划募资37.39亿元&#xff0c;其中&#xff0c;22亿元用于萤石智能制造重庆基地项目&#xff0c;8亿元用于新一代物…

论文投稿指南——中文核心期刊推荐(航空、航天)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…