FreeMarker 网页静态化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/l1336037686/article/details/82054648

1.FreeMarker入门

1.1 FreeMarker简介

这里写图片描述

1.2 FreeMarker官方文档

官方中文文档http://freemarker.foofun.cn/toc.html
官方文档https://freemarker.apache.org/

1.3 Maven仓库地址

地址: http://mvnrepository.com/artifact/org.freemarker/freemarker

<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.28</version>
</dependency>

2.使用程序开发

2.1入门小Demo,使用FreeMarker生成简单网页

2.1.1 创建Maven工程,引入FreeMarker依赖

<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.28</version>
</dependency>

2.1.2 基本结构

这里写图片描述

2.1.2 简单的Demo

Demo01

public class Demo01 {
    public static void main(String[] args) throws Exception {
        //1.创建配置类  Configuration.VERSION_2_3_28 版本
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);

        //2.设置模板所在目录
        cfg.setDirectoryForTemplateLoading(new File("E:\\基础项目\\Java_Project\\java_project_idea\\other-farmework\\freemarker-demo\\src\\main\\resources\\"));

        //3.设置编码方式
        cfg.setDefaultEncoding("UTF-8");

        //4.设置错误显示方式
        //IGNORE_HANDLER 这只是跳过失败的指令,让模板继续执行。
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

        //5.设置数据模型
        Map<String, Object> dataModel = new HashMap<String, Object>();
        dataModel.put("content", "Hello World");

        //6.设置模板
        Template temp = cfg.getTemplate("freemarkerForHtmlTemplate.ftl");

        //7.创建输出流,设置生成文件
        Writer out = new FileWriter("D:\\page\\index.html");

        //8.生成页面
        temp.process(dataModel, out);

        //9.关闭输出流
        out.close();
    }
}

freemarkerForHtmlTemplate.ftl 模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    ${content}
</body>
</html>

结果:
这里写图片描述

2.2 基本数据模型

2.2.1基本标量

4种类型的标量

  • 布尔值
  • 数字
  • 字符串
  • 日期类型(子类型: 日期(没有时间部分 date),时间(time)或者日期-时间(datetime))

每一种标量类型都是 TemplateTypeModel 接口的实现,这里的 Type 就是类型的名称。这些接口只定义了一个方法: type getAsType();。 它返回变量的Java类型(boolean, Number, String 和 Date 各自代表的值)。

2.2.1.1 常见的标量类型

类名 属性
SimpleDate Date
SimpleHash Map
SimpleNumber 数字
SimpleScalar 字符串
SimpleList List
SimpleSequence 序列
SimpleCollection 集合

2.2.1.2 分析SimpleNumber的实现

/**
 * A simple implementation of the <tt>TemplateNumberModel</tt>
 * interface. Note that this class is immutable.
 *
 * <p>This class is thread-safe.
 */
public final class SimpleNumber implements TemplateNumberModel, Serializable {

    /**
     * @serial the value of this <tt>SimpleNumber</tt> 
     */
    private final Number value; 

    public SimpleNumber(Number value) {
        this.value = value;
    }

    public SimpleNumber(byte val) {
        this.value = Byte.valueOf(val);
    }

    public SimpleNumber(short val) {
        this.value = Short.valueOf(val);
    }

    public SimpleNumber(int val) {
        this.value = Integer.valueOf(val);
    }

    public SimpleNumber(long val) {
        this.value = Long.valueOf(val);
    }

    public SimpleNumber(float val) {
        this.value = Float.valueOf(val);
    }

    public SimpleNumber(double val) {
        this.value = Double.valueOf(val);
    }

    public Number getAsNumber() {
        return value;
    }

    @Override
    public String toString() {
        return value.toString();
    }
}

可以看出

  • 1.SimpleNumber是通过实现TemplateTypeModel 的Number类型来实现操作数字
  • 2 .SimpleNumber通过Number代表的值,由此得出我们根据需要的类型可以使用boolean, Number, String 和 Date 代表各自需要的值

2.2.2 容器类型

这里写图片描述

2.3 自定义方法

2.3.1 文档位置

文档位置:http://freemarker.foofun.cn/pgui_datamodel_method.html

2.3.2创建自定义方法具体步骤

  • 1.创建自定义方法类实现TemplateMethodModelEx或者TemplateMethodModel,TemplateMethodModelEx 接口扩展了 TemplateMethodModel
  • 2.重写exec(List args)方法
  • 3.将方法作为数据添加到数据模型中,由模板调用

2.3.3 例子:

AddMethod 自定义方法类

/**
 * 创建一个两个数字相加的方法
 * TemplateMethodModelEx 接口扩展了 TemplateMethodModel
 *
 * @author LGX_TvT
 * @date 2018-08-26 20:40
 *
 */
public class AddMethod implements TemplateMethodModelEx {

    public Object exec(List args) throws TemplateModelException {
        if(args.size() != 2){
            throw new TemplateModelException("Wrong arguments");
        }
        return new SimpleNumber(Integer.parseInt(args.get(0).toString()) + Integer.parseInt(args.get(1).toString()));
    };
}

Demo01

public class Demo01 {
    public static void main(String[] args) throws Exception {
        ...
        ...
        //代码与前面一样
        ...
        ...

        //5.设置数据模型
        Map<String, Object> dataModel = new HashMap<String, Object>();
        dataModel.put("content", "Hello World");

        // ==> 添加自定义方法
        dataModel.put("AddMethod",new AddMethod());

        //6.设置模板
        ...
        ...

    }
}

freemarkerForHtmlTemplate.ftl 模板调用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    ${content}<br>
    <#--调用自定义方法-->
    ${AddMethod(1,2)}
</body>
</html>

结果:
这里写图片描述

2.4 自定义指令

2.4.1 文档位置

自定义指令文档地址:http://freemarker.foofun.cn/pgui_datamodel_directive.html

2.4.2 具体步骤

  • 1.创建自定义指令类实现TemplateDirectiveModel接口,重写execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)方法
  • 2.根据params获取参数,按照需求处理数据
  • 3.使用IO流将处理后数据输出

2.4.3 实现例子

创建自定义指令将英文字符串首字母转换为大写

UpperInitials

/**
 * 自定义首字母大写指令
 * @author LGX_TvT
 * @date 2018-08-26 21:21
 */
public class UpperInitials implements TemplateDirectiveModel {

    private static final String PARAM_NAME_COUNT = "value";

    /**
     *
     * @param env 用于设置环境
     * @param params 用于获取参数
     * @param loopVars
     * @param body 用于操作标签body,如<xxx>标签body</xxx>
     */
    public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
        String  upperStr = "";
        if (loopVars.length != 0) {
            throw new TemplateModelException("This directive doesn't allow loop variables.");
        }
        if (params.isEmpty()){
            throw new TemplateModelException("params(Value) is Empty");
        }
        //获取参数
        Iterator paramIter = params.entrySet().iterator();
        //遍历Map集合
        while (paramIter.hasNext()) {
            Map.Entry ent = (Map.Entry) paramIter.next();
            //获取Key与Value
            String paramName = (String) ent.getKey();
            TemplateModel paramValue = (TemplateModel) ent.getValue();
            if (PARAM_NAME_COUNT.equals(paramName)){
                //判断value是不是字符串
                if (paramValue instanceof TemplateScalarModel){
                    String value = ((TemplateScalarModel) paramValue).getAsString();
                    if (!"".equals(value)){
                        //首字母转换为大写
                        upperStr = value.substring(0, 1).toUpperCase() + value.substring(1);
                    }
                }else{
                    throw new TemplateModelException("Type error.This is not TemplateScalarModel(String)");
                }
            }
            //通过env获取输出流输出
            Writer out = env.getOut();
            out.write(upperStr);
            out.flush();

            //输出在标签体里面:例如<xxx>body输出内容</xxx>
            //if (body != null) {
            //    out.write(" this is body!!!");
            //    body.render(env.getOut());
            //} else {
            //    throw new RuntimeException("missing body");
            //}
        }
    }
}

Demo01

public class Demo01 {
    public static void main(String[] args) throws Exception {
        ...
        ...
        //代码与前面一样
        ...
        ...

        //5.设置数据模型
        Map<String, Object> dataModel = new HashMap<String, Object>();
        dataModel.put("content", "Hello World");

        // ==> 添加自定义方法
        dataModel.put("AddMethod",new AddMethod());

        // ==> 添加自定义指令
        dataModel.put("UpperInitials",new UpperInitials());

        //6.设置模板
        ...
        ...
    }
}

freemarkerForHtmlTemplate.ftl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    ${content}<br>
    <#--调用自定义方法-->
    ${AddMethod(1,2)}

    <#--使用自定义指令-->
    <@UpperInitials value="hello" />
</body>
</html>

结果:
这里写图片描述

3.模板语言

模板文件中四种元素
1、文本:直接输出的部分
2、注释:<#– xxxx –>格式不会输出
3、插值:即${..}部分,将使用数据模型中的部分替代输出
4、FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出。

3.1 FTL指令

3.1.1 assign指令

作用: 此指令用于在页面上定义一个变量

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <#assign name="zhangsan">
    ${name}
</body>
</html>

结果:
这里写图片描述

3.1.2 include指令

作用:此指令用于模板文件的嵌套

head.ftl

<h1>Hello World</h1>

模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <#--测试include指令-->
    <#include "head.ftl">

    <#--测试assign指令-->
    <#assign name="zhangsan">
    ${name}

</body>
</html>

结果:

3.1.3 if指令

作用:判断
在freemarker的判断中,可以使用= 也可以使用==

    <#assign num = 0>

    <#if num gt 0>
        num > 0
    <#elseif num lt 0>
        num < 0
    <#else>
        num == 0
    </#if>

结果:
这里写图片描述

3.1.4 list指令

作用:用于循环

添加数据

        //设置数据模型
        Map<String, Object> dataModel = new HashMap<String, Object>();
        List<String> list = new ArrayList<String>();
        list.add("篮球");
        list.add("足球");
        list.add("排球");
        dataModel.put("playList",list);
    <#list playList as boal>
        序号 ${boal_index}: 名称 ${boal}: 是否还有下一个 ${boal_has_next?c}
    </#list>

结果:
这里写图片描述



其他的可以查看官方中文文档
http://freemarker.foofun.cn/ref_directives.html

3.2 内建函数

内建函数语法格式: 变量+?+函数名称

3.2.1 size

作用:获取集合大小

    <#--测试size函数-->
    一共${playList?size}条数据

结果


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        一共3条数据
</body>
</html>

3.2.2 eval

作用:转换JSON字符串为对象

在数据模型中添加数据

dataModel.put("person","{'name':'zhangsan','age':14}");
    <#assign p=person?eval />
    ${p.name}
    ${p.age}

这里写图片描述

3.2.3

作用:日期格式化

添加数据

dataModel.put("today", new Date());
当前日期:${today?date} <br>
当前时间:${today?time} <br>   
当前日期+时间:${today?datetime} <br>        
日期格式化:${today?string("yyyy年MM月")}

结果:
这里写图片描述

3.2.4 c

作用:数字转换为字符串

添加数据

dataModel.put("number",123456789);

3.2.4.1 若没有使用c函数

${number}

结果:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    123,456,789
</body>
</html>

3.2.4.2 使用c函数

${number?c}

结果:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    123456789
</body>
</html>

3.3 基本运算符

3.3.1 算术运算符

+, - , * , / , %

3.3.2 逻辑运算符

逻辑与:&&
逻辑或:||
逻辑非:!

3.3.3 空值运算符

3.3.3.1 ??

作用:使用??判断某一变量是否存在

用法为:

变量??

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

3.3.3.2 !

缺失变量默认值:“!”
作用:若该变量不存在可以使用!来设置默认值

${value!'hello'}

若value不存在则输出hello

3.4 保留名称

true:布尔值”true”

false:布尔值”false”

gt:比较运算符”大于”

gte:比较运算符”大于或等于”

lt:比较运算符”小于”

lte:比较运算符”小于或等于”

as:由少数指令使用

in:由少数指令使用

using:由少数指令使用

猜你喜欢

转载自blog.csdn.net/l1336037686/article/details/82054648