这是一篇学习自慕课网视频--《Java模板引擎之Freemarker》的笔记,感谢慕课网和慕课老师们的无私帮助。写这篇博客的目的是为以后工作中使用freemarker,遇到问题方便查阅。
数据模型+模板输出=HTML(输出)
数据模型+模板输出=HTML(输出)2.依次点击Next,输入项目名称,团队名称,其他默认之后继续Next,出现如下窗口
3.如上窗口,依次勾选Core -> DevTools(Springboot热部署)、Web -> Web(Springmvc)、Template Engines -> Freemarker,选好后点击Next ,即可创建一个包含Freemarker的Springboot项目,此创建过程需要联网。
以上是pom文件包含的依赖。
4.项目创建好后,目录结构如下
5.打开application.yaml,加入如下配置项
# 配置freemarker
spring:
freemarker:
# 设置模板后缀名
suffix: .ftl
# 设置文档类型
content-type: text/html
# 设置页面编码格式
charset: UTF-8
# 设置页面缓存
cache: false
# 设置ftl文件路径
template-loader-path: classpath:/templates/
check-template-location: true
expose-request-attributes: true
expose-session-attributes: true
request-context-attribute: request
# 设置静态文件路径,js,css等
mvc:
static-path-pattern: /static/**
server:
port: 8080
servlet:
context-path: /springboot-java
6.创建HelloController,在controller中写入一个控制页面跳转的方法,如下
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
@Controller
public class HelloController {
@RequestMapping("/")
public String welcome(HttpServletRequest request){
request.setAttribute("name","Mr.Yang");
return "index";
}
}
7.在templates文件夹下,新建index.ftl文件,写入如下内容
<#assign base=request.contextPath />
首页
Hello! ${name},glad to see you!
${base}
8.启动DemoApplication,运行Springboot容器
看到如上内容,表示项目已经在tomcat上启动成功了,项目名称是demo,端口是8080,访问地址是http://localhost:8080/demo
9.访问http://localhost:8080/demo,即可看到Freemarker引擎生成的html页面
至此,Springboot集成Freemarker项目创建完毕。
<#assign a=10 />
${a + 100}
自定义对象User变量的属性值获取
- 对象
${(userObj.name)!"默认值"}
输出富文本内容
user.setBrief("我只想早点下班。对不起,你是程序员!");
- 输出富文本内容
${(userObj.brief)!?html}
集合Map的遍历
- 集合map的遍历
<#list map?keys as key>
${key}:${map[key]}
#list>
if语法
- if else指令
<#if myList?exists>
<#list myList as item>
${item}
#list>
#if>
- if多条件 || , && , !
<#assign var='python'>
<#if var == 'python' || var == 'java' || var?length==6>
python or java
#if>
switch语法
switch case break default
<#assgin var == 110 />
<#switch var>
<#case 10>
<#case 11>
10 or 11
<#break>
<#case 100>
100
<#break>
<#default>
other
#switch>
string基本操作命令
<#assign a='hello' />
<#assign b='world'/>
- 连接
${a + b}
- 截取
${(a + b)?substring(5,8)}
- 长度
${(a + b)?length}
- 大写
${(a + b)?upper_case}
- 小写
${(a + b)?lower_case}
- index_of
${(a + b)?index_of('w')}
- last_index_of
${(a + b)?last_index_of('o')}
- replace
${(a + b)?replace('o','xx')}
自定义函数
1,自定义函数(整数排序 sort_int)
<#assign myList=[2,3,4,5,1,8,9,8,7]/>
- 未排序
<#list myList as item>
${item},
#list>
- 已排序
<#list sort_int(myList) as item>
${item},
#list>
在model.tag包下,创建SortMethod类实现TemplateModelEX接口,它就是实现自定义排序函数的类。
package com.example.demo.model.tag;
public class SortMethod implements TemplateMethodModelEx {
@Override
public Object exec(List arguments) throws TemplateModelException {
//获取第一个参数
SimpleSequence arg0=(SimpleSequence)arguments.get(0);
List list=arg0.toList();
Collections.sort(list,new Comparator(){
@Override
public int compare(BigDecimal o1, BigDecimal o2) {
return o1.intValue()-o2.intValue(); //升序
}
});
return list;
}
}
在控制器方法中,加入sort_int函数变量。
@RequestMapping("/")
public String welcome(HttpServletRequest request){
request.setAttribute("name","Mr.Yang");
request.setAttribute("sort_int",new SortMethod());
return "index";
}
运行springboot,查看localhost:8080/demo,结果如下则自定义函数创建成功。
item_index:此变量用于list遍历指令内,表示当前item所在下标,从0开始计数。
sort :内置的list集合排序函数
reverse: 内置的list集合反序函数
size :获取list集合的大小
myList[3]:获取下标为3的集合元素
<#assign base=request.contextPath />
首页
List的指令
1,list常用指令
<#assign myList=[2,3,4,5,1,8,9,8,7] />
<#list myList?sort?reverse as item>
${item_index} : ${item}
#list>
${myList?size}
${myList[3]}
<#assign base=request.contextPath />
index2
自定义指令
1,用户123456是否拥有admin角色,并且返回admin的权限
<@role user='123456' role='admin'; result1 , result2>
<#if result1>
我的角色是admin
#if>
我拥有的权限是:
<#list result2 as item>
${item},
#list>
@role>
在model.tag包下创建RoleDirectiveModel类,实现TemplateDirectiveModel接口,它就是创建role指令的实现类。
package com.example.demo.model.tag;
@Component
public class RoleDirectiveModel implements TemplateDirectiveModel {
/**
*
* @param environment 环境变量
* @param params 指令参数(存储你所需要的值,随便是什么Key-Value你懂的)
* @param loopVars 循环变量 返回值
* @param templateDirectiveBody 指令内容
* 除了params外,其他的都能是Null。
* @throws TemplateException
* @throws IOException
*/
@Override
public void execute(Environment environment, Map params, TemplateModel[] loopVars, TemplateDirectiveBody templateDirectiveBody) throws TemplateException, IOException {
System.out.println("=========");
TemplateScalarModel user=(TemplateScalarModel)params.get("user");
TemplateScalarModel role=(TemplateScalarModel)params.get("role");
if("123456".equals(user.getAsString()) && "admin".equals(role.getAsString()) ){
loopVars[0]=TemplateBooleanModel.TRUE;
}
List otherRights=new ArrayList<>();
otherRights.add("add");
otherRights.add("update");
otherRights.add("delete");
loopVars[1]=new SimpleSequence(otherRights);
templateDirectiveBody.render(environment.getOut());
}
}
在config包下创建FreeMarkerAutoConfiguration类,这是一个java配置类,它用来将自定义指令role注册到freemarker的共享变量中,这样在模板文件中就可以使用role指令了。
package com.example.demo.config;
import com.example.demo.model.tag.RoleDirectiveModel;
import com.example.demo.model.tag.SortMethod;
import freemarker.template.TemplateModelException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Slf4j
@Configuration
public class FreeMarkerAutoConfiguration {
@Autowired
private freemarker.template.Configuration configuration;
@Autowired
private RoleDirectiveModel roleDirectiveModel;
@Autowired
private SortMethod sortMethod;
@PostConstruct
public void setSharedVariable() {
try {
//自定义标签
configuration.setSharedVariable("role", roleDirectiveModel);
configuration.setSharedVariable("sort_int",sortMethod);
} catch (Exception e) {
log.error("Custom tags failed to load:{}", e.getMessage());
}
}
}
//见名知义哈
1.substring , cap_first , ends_with , contains
2. date , datetime , time
3. starts_with , index_of , last_index_of , split , trim
代码示例
内建函数
1,字符串内建函数
<#list "a|b|c|d"?split("|") as item>
- ${item}
#list>
<#assign var1="01/03/2017"?date("MM/dd/yyyy")>
<#assign var2="15:05:30"?time("HH:mm:ss")>
<#assign var3="2016-12-31 03:05 PM"?datetime("yyyy-MM-dd hh:mm")>
- ${var1}
- ${var2}
- ${var3}
处理数字的内建函数
1. string , x?string("0.##")
2. round , floor , ceiling
代码示例
2,数字类型内建函数
<#assign numVar1 = 314.5662 />
- ${numVar1?string("0.##")}
//四舍五入 结果314.57
- ${numVar1?round}
处理List的内建函数
1. first , last, seq_contains, seq_index_of
2. size, reverse, sort, sort_by
3. chunk
代码示例
3,list内建函数
<#assign listVar1 = [1,2,3,4,11,12,13,14,21,22,23,24] />
- ${listVar1?chunk(4)?size}
<#list listVar1?chunk(4)?last as item>
- ${item}
#list>
其他内建函数
1. is函数:is_string, is_number, is_method
2. (), has_content函数
3. eval求值
代码示例
4,其他内建函数
<#assign sVar='hello' />
- ${sVar?is_number?string('yes','no')}
- ${sVar?has_content?string('yes','no')}
- ${'1+2'?eval}
#macro nested return 章节
macro语法:
<#macro macro_name param1 param2 param3 paramN...>
template_code ${param1}
<#nested />
#macro>
调用
<@macro_name param1="value1" param2="value2" />
<@macro_name param1="value1" param2="value2">
nested_template
@macro_name>
#function语法
<#function function_name param1 param2>
<#return param1+param2>
#function>
调用
${doAdd(100,100)}
新建index3 .ftl文件,在其中使用macro宏指令创建共用模板代码,使用function指令创建自定义函数。
<#assign base=request.contextPath />
index3
macro nested return 实战demo
1,macro :宏指令
- 栗子1:无参数的macro
<#macro test>
我是无参数的macro
#macro>
<@test/>
- 栗子2:有参数的macro
<#macro test1 param1 param2>
我是有参数的macro,param1 = ${param1},param2 = ${param2}
#macro>
<@test1 param1="java" param2="python" />
- 栗子3:有默认值参数的macro
<#macro test2 param1 param2="python">
我是有参数的macro,param1 = ${param1},param2 = ${param2}
#macro>
<@test2 param1="java" />
- 栗子4:有多个参数的macro
<#macro test3 param1 param2="python" paramExt...>
我是有参数的macro,param1 = ${param1}, param2 = ${param2}
${paramExt['param3']}
${paramExt['param4']}
#macro>
<@test3 param1="java" param2="hello python" param3="javascript" param4="nodejs"/>
2,nested
<#macro test param1 = "java">
${param1}
<#nested param1,"我的nested 参数">
#macro>
- 调用
<@test param1="java"; loopVar1, loopVar2>
hello ${loopVar1} , ${loopVar2}
@test>
<@test param1="python";loopVar1>
hello ${loopVar1}
@test>
3,函数
<#function doAdd param1 param2>
<#return param1+param2>
#function>
- 调用
你好,我是调用 ${doAdd(100,100)}