草庐IT

07-freemarker概述和入门

OnlyOnYourself-lzw 2023-04-15 原文

一、freemarker介绍

  • FreeMarker 是一款 模板引擎
    • 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件
  • 模板编写为FreeMarker Template Language(FTL)
    • 它是简单的,专用的语言,不是像PHP那样成熟的变成语言。那就意味着要准备数据在在真实编程语言中来显示,比如数据库查询和业务运算,之后模板显示以及准备好的数据。在模板中,可以更加专注于如何展现数据,而在模板之外可以专注于要展示什么数据

二、freemarker环境搭建&&快速入门

需要创建Spring Boot + Freemarker 工程用于测试模板

2.1、创建测试工程

  • 创建一个freemark-demo的测试工程用于freemarker的功能测试与模板测试

  • POM文件如下所示

    • <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
      
          <groupId>com.coolman</groupId>
          <artifactId>freemarker-demo</artifactId>
          <version>1.0-SNAPSHOT</version>
      
          <properties>
              <maven.compiler.source>8</maven.compiler.source>
              <maven.compiler.target>8</maven.compiler.target>
          </properties>
          <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <!--freemarker springboot starter-->
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-freemarker</artifactId>
              </dependency>
      
              <!-- lombok -->
              <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
              </dependency>
          </dependencies>
      </project>
      

2.2、配置文件

  • application.yml文件如下所示

    • server:
        port: 9527
      spring:
        application:
          name: freemarker-demo # 指定服务名
        freemarker:
          cache: false  # 关闭缓存,方便测试
          settings:
            template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试
          suffix: .ftl               #指定Freemarker模板文件的后缀名
          template-loader-path: classpath:/templates  #指定模板文件存放的位置
      

2.3、创建启动类

  • 启动类如下所示

    • package com.coolman.freemarker;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      
      @SpringBootApplication
      public class FreemarkerApplication {
          public static void main(String[] args) {
              SpringApplication.run(FreemarkerApplication.class, args);
          }
      }
      
      

2.4、创建模型类

  • 在freemarker的测试工程下创建模型类型用于测试

    • package com.coolman.freemarker.model;
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class Person {
      
          private String name;
          private Integer age;
      }
      
      

2.5、创建模板

  • 在resources下创建templates,并创建模板文件freemarker.ftl文件(模板中的插值表达式最终会被freemarker替换成具体的数据)

    • 编写一个简单的HTML模板

    • <!DOCTYPE html>
      <html>
      <head>
          <meta charset="utf-8">
          <title>Hello Freemarker!</title>
      </head>
      <body>
      <b>普通文本 String 展示:</b><br><br>
      Welcome to SuperCoolMan's home !! <br>
      I’m 99 years old this year !! <br>
      <hr>
      <hr>
      </body>
      </html>
      

2.6、创建测试类并测试

  • 创建Controller类,添加数据,最后返回模板文件

    • 测试1:

      • package com.coolman.freemarker.controller;
        
        import freemarker.template.Configuration;
        import freemarker.template.Template;
        import freemarker.template.TemplateException;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RestController;
        
        import java.io.FileWriter;
        import java.io.IOException;
        import java.util.HashMap;
        
        @RestController
        @RequestMapping("/freemarker")
        public class FreemarkerController {
        
            // 引入freemarker.template包下的Configuration类,用来获取指定的模板对象
            @Autowired
            private Configuration configuration;
        
            /**
             * 通过模板文件,生成html文件
             */
            @GetMapping("/test")
            public String getHtml() {
                try {
                    // 使用Configuration的getTemplate方法,指定模板文件,获取模板对象
                    Template template = configuration.getTemplate("HelloFreemarker.ftl");
        
                    // 绑定数据
                    // 数据1:
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("name", "SuperCoolMan");
                    map.put("age", 99);
        
                    FileWriter fileWriter = new FileWriter("E:\\系统默认\\桌面\\news-init\\freemarker-demo\\src\\main\\resources\\testHtml\\HelloFreemarker.html");
                    template.process(map, fileWriter);
        
                    return "SUCCESS!";
                } catch (IOException | TemplateException e) {
                    e.printStackTrace();
                }
                return "ERROR!";
            }
        }
        
        
      • 浏览器打开生成的静态文件

  • 修改Controller中的方法,添加Person对象数据

    • package com.coolman.freemarker.controller;
      
      import com.coolman.freemarker.model.Person;
      import freemarker.template.Configuration;
      import freemarker.template.Template;
      import freemarker.template.TemplateException;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      import java.io.FileWriter;
      import java.io.IOException;
      import java.util.HashMap;
      
      @RestController
      @RequestMapping("/freemarker")
      public class FreemarkerController {
      
          // 引入freemarker.template包下的Configuration类,用来获取指定的模板对象
          @Autowired
          private Configuration configuration;
      
          /**
           * 通过模板文件,生成html文件
           */
          @GetMapping("/test")
          public String getHtml() {
              try {
                  // 使用Configuration的getTemplate方法,指定模板文件,获取模板对象
                  Template template = configuration.getTemplate("HelloFreemarker.ftl");
      
                  // 绑定数据
                  // 数据1:
                  HashMap<String, Object> map = new HashMap<>();
                  map.put("name", "SuperCoolMan");
                  map.put("age", 99);
      
                  // 数据2:
                  map.put("person", new Person("超级猛男", 18));
      
                  FileWriter fileWriter = new FileWriter("E:\\系统默认\\桌面\\news-init\\freemarker-demo\\src\\main\\resources\\testHtml\\HelloFreemarker.html");
                  template.process(map, fileWriter);
      
                  return "SUCCESS!";
              } catch (IOException | TemplateException e) {
                  e.printStackTrace();
              }
              return "ERROR!";
          }
      }
      
      
    • 修改模板

      • <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <title>Hello Freemarker!</title>
        </head>
        <body>
        <b>普通文本 String 展示:</b><br><br>
        Welcome to ${name}'s home !! <br>
        I’m ${age} years old this year !! <br>
        <hr>
        <b>对象Person中的数据展示:</b><br/>
        姓名:${person.name}<br/>
        年龄:${person.age}
        <hr>
        </body>
        </html>
        
    • 浏览器打开生成的静态文件

2.7、总结

三、freemarker语法指令

3.1、基础语法

3.1.1、注释

  • 注释,即<#-- -->,介于其之间的内容会被freemarker忽略

    • <#-- 我是一个freemarker的注释-->
      

3.1.2、插值

  • 插值(Interpolation):即${...}部分,freemarker会用真实的值代替${}(PS:如果返回的数据中没有该真实值,freemarker服务会直接报错)

    • Welcome to ${name}'s home
      

3.1.3、FTL指令

  • FTL指令:和HTML标记类似,名字前加#予以区分,Freemarker会解析标签中的表达式或逻辑

    • <# > FTL指令 </#>
      

3.1.4、文本

  • 文本,仅文本信息,这些不是freemarker的注释、插值、FTL指令的内容会被freemarker忽略解析,直接输出内容

    • <#--freemarker中的普通文本-->
      我是一个普通的文本
      

3.2、集合指令(List、Map)

接下来的测试,只截取部分代码,直接在原代码的基础上增加即可

  • 为了Controller尽可能简略,创建一个getData方法,返回一个Map集合,Controller方法直接调用这个getData生成测试数据即可

    •     private Map<String, Object> getData() {
              HashMap<String, Object> map = new HashMap<>();
              // String类型:
              map.put("name", "SuperCoolMan");
              map.put("age", 99);
      
              // Person类型:
              map.put("person", new Person("超级猛男", 18));
              
              // 
              return map;
          }
      

3.2.1、List集合

  • Controller

    • // List集合类型
              ArrayList<Person> list = new ArrayList<>();
              list.add(new Person("瞳夕", 18));
              list.add(new Person("二呆", 18));
              list.add(new Person("嘿嘿", 18));
              map.put("wifeList", list);
      
  • 模板

    • <b>List类型中的数据展示:</b><br/>
          <#list wifeList as wife>
              序号:${wife_index + 1} <br/>   <#--freemarker中FTL指令自带的序号属性,默认从0开始-->
              姓名:${wife.name} <br/>
              年龄:${wife.age}  <br/><br/>
          </#list>
      <hr>
      
  • 最终效果

3.2.2、Map集合

  • Controller

    • // Map集合类型
              HashMap<String, Object> anOtherMap = new HashMap<>();
              anOtherMap.put("smallWife1", new Person("莫妮卡", 18));
              anOtherMap.put("smallWife2", new Person("玛丽莲梦露", 18));
              map.put("smallWife", anOtherMap);
      
  • 模板

    • <b>Map + Person 类型中的数据展示:</b><br/>
          <b>方式一:通过map['keyname'].property 输出对应信息:</b><br/>
              性别:${wifeMap['smallWife1'].name} <br/>
              年龄:${wifeMap['smallWife1'].age} <br/>
          <b>方式二:通过map.keyname.property 输出对应信息:</b><br/>
              性别:${wifeMap.smallWife2.name} <br/>
              年龄:${wifeMap.smallWife2.age} <br/>
      <hr>
      
  • 最终效果

  • 遍历Map集合

    • 模板

      • <b>遍历Map中多个Person信息:</b><br/>
            <#list wifeMap?keys as key>
                序号:${key_index} <br/>
                性别:${key.name} <br/>
                年龄:${key.age} <br/><br/>
            </#list>
        <hr>
        
    • 最终效果

3.3、if指令

  • if指令即判断指令,是常用的FTL指令,freemarker在解析的时候遇到if会进行判断,条件为真则输出if中间的内容,否则跳过内容不在输出

    • 指令格式

      • <#if >...</#if>
        
  • Controller

    • // if test
      map.put("score", 88);
      
  • 模板

    • <b>if指令测试:</b><br/>
          <#if (score > 90)>
              继续努力
          <#elseif (score > 80)>
              面包总会有的
          <#else>
              革命尚未成功,同志仍需努力
          </#if>
      <hr>
      
  • 最终效果

3.4、空值处理

3.4.1、判断某变量是否存在

  • 语法格式

    • variable??
  • 如果该变量存在,返回true,否则返回false

  • 如下例所示

    • <#if stus??>
          <#list stus as stu>
          ......
          </#list>
      </#if>
      

3.4.2、缺失变量默认值

  • 使用!要指定一个默认值,当变量为空的时候显示默认值
    • 例:${name!'默认值'}表示如果name为空,显示默认值
  • 如果是嵌套对象则建议使用()括起来
    • 例:${(stu.bestFriend.name)!"默认值"}表示如果stu或者bestFriend或者name为空默认显示默认值

3.5、内建函数

3.5.1、获取集合大小

  • 模板中直接取值
    • ${集合名?size}

3.5.2、日期格式化

  • 后端返回一个Date对象,模板要取值,则如下所示
    • map.put("today",new Date())
    • 显示年月日
      • ${today?date}
    • 显示时分秒
      • ${today?time}
    • 显示日期+时间
      • ${today?datetime}
    • 自定义格式化
      • ${today?string("yyyy年MM月")}

3.5.3、内建函数c(数字格式化)

  • 后端返回一串数字,模板可以对其进行格式化,如下所示
    • map.put("point", 102920122);
  • point是数字型,使用${point}会显示这个数字的值,每三位使用逗号隔开
  • 如果不像显示为每三位分隔的数字,可以使用c函数将数字转成字符串输出
  • 指令格式如下所示
    • ${point?c}

有关07-freemarker概述和入门的更多相关文章

  1. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  2. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  3. 阿里云RDS——产品系列概述 - 2

    基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于

  4. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  5. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  6. 区块链入门教程(6)--WeBASE-Front节点前置服务安装 - 2

    文章目录1.任务背景2.任务目标3.相关知识点4.任务实操4.1安装配置JDK4.2启动FISCOBCOS4.3下载解压WeBASE-Front4.4拷贝sdk证书文件4.5启动节点4.6访问节点4.7检查运行状态5.任务总结1.任务背景FISCOBCOS其实是有控制台管理工具,用来对区块链系统进行各种管理操作。但是对于初学者来说,还是可视化界面更友好,本节就来介绍WeBASE管理平台,这是一款微众银行开源的自研区块链中间件平台,可以降低区块链使用的门槛,大幅提高区块链应用的开发效率。微众银行是腾讯牵头设立的民营银行,在国内民营银行里还是比较出名的。微众银行参与FISCOBCOS生态建设,一定

  7. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

  8. Simulink方法总结和避坑指南(一)——Simulink入门与基本调试方法 - 2

    文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景  最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。  在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记

  9. ESP32学习入门:WiFi连接网络 - 2

    目录一、ESP32简单介绍二、ESP32Wi-Fi模块介绍三、ESP32Wi-Fi编程模型四、ESP32Wi-Fi事件处理流程 五、ESP32Wi-Fi开发环境六、ESP32Wi-Fi具体代码七、ESP32Wi-Fi代码解读6.1主程序app_main7.2自定义代码wifi_init_sta()八、ESP32Wi-Fi连接验证8.1测试方法8.2服务器模拟工具sscom58.3测试代码8.4测试结果前言为了开发一款亚马逊物联网产品,开始入手ESP32模块。为了能够记录自己的学习过程,特记录如下操作过程。一、ESP32简单介绍ESP32是一套Wi-Fi(2.4GHz)和蓝牙(4.2)双模解决方

  10. ruby-on-rails - Rails 还是 Sinatra? PHP程序员入门学习哪个好? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。我使用PHP的时间太长了,对它感到厌倦了。我也想学习一门新语言。我一直在使用Ruby并且喜欢它。我必须在Rails和Sinatra之间做出选择,那么您会推荐哪一个?Sinatra真的不能用来构建复杂的应用程序,它只能用于简单的应用程序吗?

随机推荐