不灭的火

革命尚未成功,同志仍须努力下载JDK17

作者:AlbertWen  添加时间:2021-05-26 12:26:49  修改时间:2025-06-25 21:43:55  分类:01.Python基础  编辑

一、Spring Boot如何集成FreeMarker模板引擎?

添加依赖

1
2
3
4
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

配置属性文件

.properties版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 是否允许HttpServletRequest属性覆盖(隐藏)控制器生成的同名模型属性。
spring.freemarker.allow-request-override=false
# 是否允许HttpSession属性覆盖(隐藏)控制器生成的同名模型属性。
spring.freemarker.allow-session-override=false
# 是否启用模板缓存。
spring.freemarker.cache=false
# 模板编码。
spring.freemarker.charset=UTF-8
# 是否检查模板位置是否存在。
spring.freemarker.check-template-location=true
# Content-Type value.
spring.freemarker.content-type=text/html
# 是否启用freemarker
spring.freemarker.enabled=true
# 设定所有request的属性在merge到模板的时候,是否要都添加到model中.
spring.freemarker.expose-request-attributes=false
# 是否在merge模板的时候,将HttpSession属性都添加到model中
spring.freemarker.expose-session-attributes=false
# 设定是否以springMacroRequestContext的形式暴露RequestContext给Spring’s macro library使用
spring.freemarker.expose-spring-macro-helpers=true
# 是否优先从文件系统加载template,以支持热加载,默认为true
spring.freemarker.prefer-file-system-access=true
# 设定模板的后缀.
spring.freemarker.suffix=.ftl
# 设定模板的加载路径,多个以逗号分隔,默认:
spring.freemarker.template-loader-path=classpath:/templates
# 设定FreeMarker keys.
spring.freemarker.settings.template_update_delay=0
spring.freemarker.settings.default_encoding=UTF-8
spring.freemarker.settings.classic_compatible=true

.yml版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
spring: 
  # FreeMarker模板引擎
  freemarker:
    # 是否允许HttpServletRequest属性覆盖(隐藏)控制器生成的同名模型属性。
    allow-request-override: false
    # 是否允许HttpSession属性覆盖(隐藏)控制器生成的同名模型属性。
    allow-session-override: false
    # 是否启用模板缓存。
    cache: false
    # 模板编码。
    charset: UTF-8
    # 是否检查模板位置是否存在。
    check-template-location: true
    # Content-Type value.
    content-type: text/html
    # 是否启用freemarker
    enabled: true
    # 设定所有request的属性在merge到模板的时候,是否要都添加到model中.
    expose-request-attributes: false
    # 是否在merge模板的时候,将HttpSession属性都添加到model中
    expose-session-attributes: false
    # 设定是否以springMacroRequestContext的形式暴露RequestContext给Spring’s macro library使用
    expose-spring-macro-helpers: true
    # 是否优先从文件系统加载template,以支持热加载,默认为true
    prefer-file-system-access: true
    # 设定模板的后缀.
    suffix: .ftl
    # 设定模板的加载路径,多个以逗号分隔,默认:
    template-loader-path: classpath:/templates
    # 设定FreeMarker keys.
    settings:
      template_update_delay: 0
      default_encoding: UTF-8
      classic_compatible: true

编写Controller

1
2
3
4
5
6
7
8
@Controller
public class FreemarkController {
 
    @RequestMapping("/")
    public String index(Model model) {
        return "/index";
    }
}

页面

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
    <title>SpringBoot + Freemarker</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1>Hello boy,</h1><br>
    <p>当前时间:${.now?string("yyyy-MM-dd HH:mm:ss.sss")}</p>
</body>
</html>

二、常用的FreeMarker语法

下面详细介绍在ftl模板中如何使用列表、map、字符串、数字、日期、switch以及macro宏指令等语法。

修改下controller,传递一些需要处理的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RequestMapping("/")
public String index(Model model) {
    Map map = new LinkedHashMap<>();
    for (int i = 0; i < 5; i++) {
        map.put("key" + i, "value" + i);
    }
    model.addAttribute("list", Arrays.asList("string1", "string2", "string3", "string4", "string5", "string6"));
    model.addAttribute("map", map);
    model.addAttribute("name", "   htTps://wWw.zHyD.mE   ");
    model.addAttribute("htmlText", "<span style=\"color: red;font-size: 16px;\">html内容</span>");
    model.addAttribute("num", 123.012);
    model.addAttribute("null", null);
    model.addAttribute("dateObj", new Date());
    model.addAttribute("bol", true);
    return "/index";
}

重写index.ftl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Freemarker 语法大全</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <style>
        html {
            font-size: 14px;
            font-weight: 400;
        }
        .exp {
            font-size: 12px;
            color: lightgray;
        }
    </style>
</head>
<body>
<p>当前时间:${.now?string("yyyy-MM-dd HH:mm:ss.sss")}</p>
<dl>
    <dt>list长度:<span class="exp">${list?size}</span></dt>
    <dt>列表</dt>
        <#list list as item>
            <dd>${item }, 索引:${item_index },hasNext:${item_has_next}</dd>
        </#list>
 
    <dt>数字遍历</dt>
        <#list 1..3 as item>
            <dd>数字${item}</dd>
        </#list>
 
    <dt>map</dt>
       <#if map?exists>
        <#list map?keys as key>
        <dd>${map[key]}, 索引:${key_index },hasNext:${key_has_next}</dd>
        </#list>
       </#if>
</dl>
<dl>
    <dt>字符串</dt>
    <dd>普通字符串:<span class="exp">${name}</span></dd>
    <dd>非html编码:<span class="exp">${htmlText}</span></dd>
    <dd>html编码:<span class="exp">${htmlText?html}</span></dd>
    <dd>首字母大写:<span class="exp">${name?cap_first}</span></dd>
    <dd>首字母小写:<span class="exp">${name?uncap_first}</span></dd>
    <dd>全小写:<span class="exp">${name?lower_case}</span></dd>
    <dd>全大写:<span class="exp">${name?upper_case}</span></dd>
    <dd>去除首位空格:<span class="exp">${name?trim}</span></dd>
    <dd>空字符串:<span class="exp">${null?if_exists}</span></dd>
    <dd>是否包含某个字符串:<span class="exp">${name?contains("wWw")?string}</span></dd>
    <dd>默认值:<span class="exp">${null?default("空值默认")}</span></dd>
    <dd>“${name}”字符串长度:<span class="exp">${name?length}</span></dd>
    <dd>定义字符串:<span class="exp">str=码一码<#assign str="码一码"/></span></dd>
    <dd>字符串拼接(1):<span class="exp">${"字符串拼接 + " + str}</span></dd>
    <dd>字符串拼接(2):<span class="exp">${"字符串拼接 + ${str}"}</span></dd>
    <dd>字符串截取单个字符(1):<span class="exp">${str[1]}</span></dd>
    <dd>字符串截取(2):<span class="exp">${str?substring(1)}</span></dd>
    <dd>字符串截取(3):<span class="exp">${str?substring(1,2)}</span></dd>
    <dd>indexOf:<span class="exp">${str?index_of("一")}</span></dd>
    <dd>split分割字符串:<span class="exp">
    <#list "a|b|c"?split("|") as item>
        ${item}
    </#list>
    </span></dd>
    <dd>if...elseif...else:<span class="exp">
            <#if null == ''>
                匹配if显示
            <#elseif null == '1'>
                匹配elseif显示
            <#else>
                匹配else显示
            </#if></span>
    </dd>
</dl>
 
<dl>
    <dt>switch</dt>
    <dd>
        <#switch str>
            <#case "你好">
                匹配“你好”
                <#break >
            <#case "码一码">
                匹配“码一码”
                <#break >
            <#default>
                默认匹配
        </#switch>
    </dd>
</dl>
 
<dl>
    <dt>数字</dt>
    <dd>普通数字:<span class="exp">${num}</span></dd>
    <dd>数字类型:<span class="exp">${num?string.number}</span></dd>
    <dd>货币类型:<span class="exp">${num?string.currency}</span></dd>
    <dd>百分比类型:<span class="exp">${num?string.percent}</span></dd>
    <dd>格式化数字:<span class="exp">${num?string("#.###")}</span></dd>
    <dd>取数字的整数部分:<span class="exp">${num?int}</span></dd>
</dl>
 
<dl>
    <dt>运算符</dt>
    <dd>不等于:!= <span class="exp">例如:${(1 != 2)?string('1 != 2', '1 == 2')}</span></dd>
    <dd>等于:== <span class="exp">例如:${(1 == 1)?string('1 == 1', '1 != 1')}</span></dd>
    <dd>大于(1):> <span
            class="exp">例如:${(2 > 1)?string('2 > 1', '2 < 1')}。<strong>注:使用> 时必须加括号,否则可能会被当成普通的标签闭合符号而引起报错</strong></span>
    </dd>
    <dd>大于(2):gt <span class="exp">例如:${(2 gt 1)?string('2 gt 1', '2 lte 1')}</span></dd>
    <dd>大于等于:gte <span class="exp">例如:${(2 gte 2)?string('2 gte 2', '2 lt 2')}</span></dd>
    <dd>小于(1):< <span
            class="exp">例如:${(1 < 2)?string('1 < 2', '1 > 2')}。<strong>注:使用< 时必须加括号,否则可能会被当成普通的标签闭合符号而引起报错</strong></span>
    </dd>
    <dd>小于(2):lt <span class="exp">例如:${(1 lt 2)?string('1 lt 2', '1 gte 2')}</span></dd>
    <dd>小于等于:lte <span class="exp">例如:${(2 lte 2)?string('2 lte 2', '2 gt 2')}</span></dd>
</dl>
 
<dl>
    <dt>boolean</dt>
    <dd>普通boolean输出:<span class="exp">${bol}</span></dd>
    <dd>boolean判断输出:<span class="exp">${bol?string('true的时候显示','false的时候显示')}</span></dd>
</dl>
 
<dl>
    <dt>日期</dt>
    <dd>${dateObj?date}</dd>
    <dd>${dateObj?time}</dd>
    <dd>${dateObj?string("yyyy-MM-dd HH:mm:ss.SSS")}</dd>
</dl>
 
<dl>
    <dt>import</dt>
    <dd>
        <#import "import.ftl" as importObj>
        <p>${importObj.importStr}</p>
        <p>${importObj.importStr1}</p>
    </dd>
</dl>
 
<dl>
    <dt>macro宏模板</dt>
    <dd>
        <#macro listMacro title items>
            <p>${title?cap_first}:
            <ul>
               <#list items as item>
                   <li>${item?cap_first}</li>
               </#list>
            </ul>
            <#nested >
        </#macro>
    </dd>
    <dd>
        <@listMacro items=["item1", "item2", "item3"] title="Items">
            nested标签表示可以插入自定义的内容
        </@listMacro>
    </dd>
</dl>
 
 
 include
<#include "eclipse.ftl">
</body>
</html>

 

三、通过FreeMarker生成静态html

首先需要编写一个可以在普通类中获取到SpringBean的工具类SpringContextHelper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.wanma.helper;
 
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
 
/**
 * Spring上下文 组手类
 */
@Component
public class SpringContextHelper implements ApplicationContextAware {
    private static ApplicationContext appContext = null;
 
    /**
     * 通过name获取 Bean.
     */
    public static Object getBean(String name) {
        return appContext.getBean(name);
 
    }
 
    /**
     * 通过class获取Bean.
     */
    public static <T> T getBean(Class<T> clazz) {
        return appContext.getBean(clazz);
    }
 
    /**
     * 通过name,以及Clazz返回指定的Bean
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return appContext.getBean(name, clazz);
    }
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (appContext == null) {
            appContext = applicationContext;
        }
    }
}

然后编写一个生成静态html文件的工具类FreemarkerHelper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.wanma.helper;
 
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
 
import java.io.IOException;
import java.util.Map;
 
/**
 * Freemarker 助手类
 */
public class FreemarkerHelper {
    public static Configuration cfg = SpringContextHelper.getBean(Configuration.class);
 
    /**
     * 解析模板
     */
    public static String parseTpl(String tplName, Map<String, Object> params) {
        String html = "";
        Template tpl;
 
        try {
            tpl = cfg.getTemplate(tplName + ".ftl");
            html = FreeMarkerTemplateUtils.processTemplateIntoString(tpl, params);
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
 
        return html;
    }
}

为了方便查看, 添加一个mapping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RequestMapping("/createHtml")
@ResponseBody
public String createHtml(Model model){
    Map map = new LinkedHashMap<>();
    for (int i = 0; i < 5; i++) {
        map.put("key" + i, "value" + i);
    }
    model.addAttribute("list", Arrays.asList("string1", "string2", "string3", "string4", "string5", "string6"));
    model.addAttribute("map", map);
    model.addAttribute("name", "   htTps://wWw.zHyD.mE   ");
    model.addAttribute("htmlText", "<span style=\"color: red;font-size: 16px;\">html内容</span>");
    model.addAttribute("num", 123.012);
    model.addAttribute("null", null);
    model.addAttribute("dateObj", new Date());
    model.addAttribute("bol", true);
    return FreemarkerHelper.parseTpl("index", model.asMap());
}

ok,访问/createHtml

到此为止,本篇已详细介绍了freemarker的使用方法。

 

源码:

https://github.com/zhangyd-c/springboot-learning

https://gitee.com/yadong.zhang/springboot