07-freemarker概述和入门

一、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}
posted @   OnlyOnYourself-Lzw  阅读(235)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示