freemarker入门级学习笔记

什么是FreeMarker?

本章节内容大多来自官方文档:http://freemarker.foofun.cn/

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

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

freemarker入门级学习笔记_第1张图片

这种方式通常被称为 MVC (模型 视图 控制器) 模式,对于动态网页来说,是一种特别流行的模式。 它帮助从开发人员(Java 程序员)中分离出网页设计师(HTML设计师)。设计师无需面对模板中的复杂逻辑, 在没有程序员来修改或重新编译代码时,也可以修改页面的样式。

而FreeMarker最初的设计,是被用来在MVC模式的Web开发框架中生成HTML页面的,它没有被绑定到 Servlet或HTML或任意Web相关的东西上。它也可以用于非Web应用环境中。

FreeMarker 是 免费的, 基于Apache许可证2.0版本发布。

应用场景

适合使用在访问量、页面数据量大,但是并发量以及修改量不高(较少与后台交互)的情况,比如某小说网站详情页面等。

使用前的准备之入门demo

1. 引入依赖包(首先创建一个maven项目)


<dependency>
    <groupId>org.freemarkergroupId>
    <artifactId>freemarkerartifactId>
    <version>2.3.28version>
dependency>

<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    <version>1.18.12version>
dependency>

2. 创建类和相关文件

2.1 创建实体类

package org.feng.freemarker.v1;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

/**
 * 动物实体
 *
 * @author Feng
 * @date 2020/5/23 11:53
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Animal {
    private String name;
    private LocalDate birthday;
    private String info;
}

2.2 创建测试类

package org.feng.freemarker.v1;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Freemarker 的入门案例
 *
 * @author Feng
 * @date 2020/5/23 11:01
 */
public class HelloFreemarker {
    public static void main(String[] args) throws IOException, TemplateException {
        String dir = "D:\\ideaProjects\\freemarker-demo\\src\\main\\resources\\ftl";
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        File file = new File(dir);

        // 模板所在路径,一个File
        configuration.setDirectoryForTemplateLoading(file);
        // 加载模板
        Template template = configuration.getTemplate("/Hello.ftl");
        Map<String, Object> data = new HashMap<>(16);
        // 增加数据
        data.put("user", "FengJinSong");
        List<Animal> animals = new ArrayList<>();
        animals.add(new Animal("小花", LocalDate.now(), "暂无"));
        animals.add(new Animal("小明", LocalDate.now(), "小明是个龟"));
        animals.add(new Animal("小花", LocalDate.now(), "暂无"));
        data.put("animals", animals);

        // 定义输出
        Writer out = new FileWriter(dir + "/Hello.html");
        template.process(data, out);
        System.out.println("模板转换成功。");
        out.flush();
        out.close();
    }
}

2.3 创建ftl模板

该模板文件所在的文件夹及文件路径是:src\main\resources\ftl\Hello.ftl

<html>
<head>
    <title>你好 freemarkertitle>
head>
<body>
<#--user为null ,不展示-->
<h1>你好${user!}!h1>
<div>
    当前动物列表数是:
    <table>
        <tr><th>编号th><th>名字th><th>生日th><th>备注th>tr>
        <#---循环输出-->
        <#list animals as animal>
            <tr>
                <#--序号-->
                <td>${animal_index}td>
                <td>${animal.name}td>
                <td>${animal.birthday}td>
                <td>${animal.info}td>
            tr>
        #list>
    table>
div>
body>
html>

2.4 运行测试

运行 HelloFreemarker.java 类,将会在 ftl 文件夹下生成 Hello.html 文件。

生成的文件内容是:

<html>
<head>
    <title>你好 freemarkertitle>
head>
<body>
<h1>你好FengJinSong!h1>
<div>
    当前动物列表数是:
    <table>
        <tr><th>编号th><th>名字th><th>生日th><th>备注th>tr>
            <tr>
                <td>0td>
                <td>小花td>
                <td>2020-05-23td>
                <td>暂无td>
            tr>
            <tr>
                <td>1td>
                <td>小明td>
                <td>2020-05-23td>
                <td>小明是个龟td>
            tr>
            <tr>
                <td>2td>
                <td>小花td>
                <td>2020-05-23td>
                <td>暂无td>
            tr>
    table>
div>
body>
html>

页面上的内容展示:

freemarker入门级学习笔记_第2张图片

常见指令

1、if指令

IfDemo.java类的编写

以下程序演示了 if 指令的基本能使用,在java类中生成一个小于100的随机数,将其传递到 ftl模板中。

package org.feng.freemarker.v3;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * if控制语句
 *
 * @author Feng
 * @date 2020/5/24 15:01
 */
public class IfDemo {
    public static void main(String[] args) throws IOException, TemplateException {
        String dir = "D:\\ideaProjects\\freemarker-demo\\src\\main\\resources\\templates";
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        File file = new File(dir);

        // 模板所在路径,一个File
        configuration.setDirectoryForTemplateLoading(file);
        // 加载模板
        Template template = configuration.getTemplate("/if.ftl");
        Map<String, Object> data = new HashMap<>(16);
        // 随机生成一个数
        data.put("random", new Random().nextInt(100));

        Writer out = new FileWriter(dir + "/if.html");
        template.process(data, out);
        System.out.println("模板转换成功。");
        out.flush();
        out.close();
    }
}

if.ftl的编写

<html>
<head>
    <title>你好 freemarkertitle>
head>
<body>
<h1>生成的随机数是:${random}h1>
<#if random gt 60>
    随机数大于60了!
    <#else>
    随机数小于60了!
#if>

<hr>
<#if random gt 90>
    优秀,大于90了!
    <#elseif random gt 80>
    良好,大于80了!
    <#else>
    一般般了!
#if>

body>
html>

运行生成if.html

<html>
<head>
    <title>你好 freemarkertitle>
head>
<body>
<h1>生成的随机数是:43h1>
    随机数小于60了!

<hr>
    一般般了!

body>
html>

2、macro 自定义指令

MacroDemo.java类的编写

package org.feng.freemarker.v4;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * macro 定义宏
 *
 * @author Feng
 * @date 2020/5/24 18:53
 */
public class MacroDemo {
    public static void main(String[] args) throws IOException, TemplateException {
        String dir = "D:\\ideaProjects\\freemarker-demo\\src\\main\\resources\\templates";
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        File file = new File(dir);

        // 模板所在路径,一个File
        configuration.setDirectoryForTemplateLoading(file);
        // 加载模板
        Template template = configuration.getTemplate("/macro.ftl");
        Map<String, Object> data = new HashMap<>(16);

        Writer out = new FileWriter(dir + "/macro.html");
        template.process(data, out);
        System.out.println("模板转换成功。");
        out.flush();
        out.close();
    }
}

macro.ftl的编写

定义两个宏,一个是没有参数的,一个是有3个参数的,并调用。

<html>
<head>
    <title>你好 freemarkertitle>
head>
<body>
    <#--无参数的宏-->
    <#macro m1>
        <h3>m1m1m1m1h3>
    #macro>
    <#--有3个参数的宏-->
    <#macro m2 a b c>
        ${a}+${b}+${c}=${a + b + c}
    #macro>

    <hr>
    <#--调用无参数的宏-->
    <@m1>@m1>
    <#--调用有3个参数的宏-->
    <@m2 a=10 b=20 c=30/>
body>
html>

运行生成macro.html

<html>
<head>
    <title>你好 freemarkertitle>
head>
<body>
    
    <hr>
        <h3>m1m1m1m1h3>
        10+20+30=60
body>
html>

3、nested指令嵌入内容

NestedDemo.java类的编写

package org.feng.freemarker.v4;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * nested 指令
 *
 * @author Feng
 * @date 2020/5/24 21:45
 */
public class NestedDemo {
    private static String ftl = "/nested.ftl";
    private static String to = "/nested.html";

    public static void main(String[] args) throws IOException, TemplateException {
        String dir = "D:\\ideaProjects\\freemarker-demo\\src\\main\\resources\\templates";
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        File file = new File(dir);

        // 模板所在路径,一个File
        configuration.setDirectoryForTemplateLoading(file);
        // 加载模板
        Template template = configuration.getTemplate(ftl);
        Map<String, Object> data = new HashMap<>(16);
        data.put("td", "这是表格中的一句话");

        Writer out = new FileWriter(dir + to);
        template.process(data, out);
        System.out.println("模板转换成功。");
        out.flush();
        out.close();
    }
}

nested.ftl的编写

<html>
<head>
    <title>嵌入title>
head>

<body>
<#--定义宏,内容使用 nested标签-->
<#macro border>
    <table border=4 cellspacing=0 cellpadding=4>
        <tr><td><#nested>td>tr>
    table>
#macro>
<@border>${td}@border>
body>
html>

运行生成nested.html

<html>
<head>
    <title>嵌入title>
head>

<body>
    <table border=4 cellspacing=0 cellpadding=4>
        <tr><td>这是表格中的一句话td>tr>
    table>

body>
html>

注意,这个指令也可以配合macro的传入参数的方式进行使用。

命名空间

当运行FTL模板时,就会有使用 assign 和 macro指令创建的变量的集合(可能是空的),可以从前一章节来看如何使用它们。像这样的变量集合被称为 namespace,即命名空间。

在简单的情况下可以只使用一个命名空间,称之为 main namespace 主命名空间。因为通常只适用本页上的命名空间,所以就没有意识到这点。

如果想创建可以重复使用的宏,函数和其他变量的集合,通常用术语来说就是引用 library库。使用多个命名空间是必然的。只要考虑你在一些项目中,或者想和他人共享使用的时候,你是否有很大的宏的集合。但要确保库中没有宏(或其他变量)名和数据模型中变量同名,而且也不能和模板中引用其他库中的变量同名。通常来说,变量因为名称冲突也会相互冲突。所以要为每个库中的变量使用不同的命名空间。

使用的案例

NamespaceDemo.java类的编写

package org.feng.freemarker.v5;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * 命名空间测试
 *
 * @author Feng
 * @date 2020/5/24 22:13
 */
public class NamespaceDemo {

    private static String ftl = "/namespace.ftl";
    private static String to = "/namespace.html";
    public static void main(String[] args) throws IOException, TemplateException {
        String dir = "D:\\ideaProjects\\freemarker-demo\\src\\main\\resources\\templates";
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        File file = new File(dir);

        // 模板所在路径,一个File
        configuration.setDirectoryForTemplateLoading(file);
        // 加载模板
        Template template = configuration.getTemplate(ftl);
        Map<String, Object> data = new HashMap<>(16);

        Writer out = new FileWriter(dir + to);
        template.process(data, out);
        System.out.println("模板转换成功。");
        out.flush();
        out.close();
    }
}

namespace_demo.ftl的编写

这个文件是用来被引用的,在其他的ftl文件中引用,并显示出内容。

<#macro var var1>
    <p>var1=${var1}p>
#macro>
<#assign var2="[email protected]">

namespace.ftl的编写

<html>
<head>
    <title>命名空间title>
head>
<body>
    <#--引入***.ftl文件-->
    <#import "namespace_demo.ftl" as varn/>
    <@varn.var var1="20200520"/>
    ${varn.var2}
    <#assign var2="[email protected]"/>
    ${var2}
    <#--给varn.var2改值-->
    <#assign var2="[email protected]" in varn/>
    ${varn.var2}
body>
html>

运行生成namespace.html

<html>
<head>
    <title>命名空间title>
head>
<body>
        <p>var1=20200520p>
    [email protected]
    [email protected]
    [email protected]
body>
html>

命名规则

着重注意不能使用驼峰命名,一般使用下划线分隔(_

附录

这个笔记是属于 Freemarker 的一个入门级学习笔记。

随着后期的深入学习,会继续追更的!保持饥饿,热爱学习。

参考视频: https://www.bilibili.com/video/BV1e7411W7d1?t=1255&p=2

你可能感兴趣的:(Freemarker)