Java模板引擎之Freemarker学习笔记

这是一篇学习自慕课网视频--《Java模板引擎之Freemarker》的笔记,感谢慕课网和慕课老师们的无私帮助。写这篇博客的目的是为以后工作中使用freemarker,遇到问题方便查阅。

 什么是Freemarker

  1. Freemarker是一款模板引擎
  2. Freemarker不是web框架,它只是一个Java组件,提供MVC设计模式中视图层的功能

数据模型+模板输出=HTML(输出)

数据模型+模板输出=HTML(输出)
数据模型+模板输出=HTML(输出)

创建Springboot集成Freemarker的项目

  1. 打开IntelliJ IDEA,依次点击File > new Project ,弹出窗口中选择Spring Initializr,出现如下窗口

 

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 />
<!DOCTYPE html>
<html lang="zh">
<head>
    <base id="base" href="${base}">
    <title>首页</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
Hello! ${name},glad to see you!<br/>
${base}
</body>
</html>

8.启动DemoApplication,运行Springboot容器

看到如上内容,表示项目已经在tomcat上启动成功了,项目名称是demo,端口是8080,访问地址是http://localhost:8080/demo 

9.访问http://localhost:8080/demo,即可看到Freemarker引擎生成的html页面

 至此,Springboot集成Freemarker项目创建完毕。

Freemarker内置指令

  1. 变量创建和赋值和运算
    <#assign a=10 />
    <font color="red">${a + 100}</font>

     

  2.  自定义对象User变量的属性值获取

    <ul>
    <li>对象</li>
    <font color="red">${(userObj.name)!"默认值"}</font><br/>
    </ul>
    <!-- (userObj.name)! 表示对userObj和name两个变量依次进行是否为空判断,如果有一个为空,则输出默认值 -->

     

  3.  输出富文本内容

    user.setBrief("<font color='red'>我只想早点下班。对不起,你是程序员!</font>");
    
    <ul>
    <li>输出富文本内容</li>
    ${(userObj.brief)!?html}
    </ul>
    
    <!-- 在(userObj.brief)!之后加上?html 表示调用freemarker的内置函数html 这样会输出html内容的源代码,不加就会输出html内容 -->

     

  4.  集合Map的遍历

    <ul>
    <li>集合map的遍历</li>
    <#list map?keys as key>
        <font color="red">${key}:${map[key]}</font><br/>
    </#list>
    </ul>

     

  5.  if语法

    <ul>
    <li>if else指令</li>
    <#if myList?exists>        <!-- 也可写作 myList?? ,用来判断myList是否存在,不存在则不执行list循环 -->
        <#list myList as item>
            ${item}
        </#list>
    </#if>
    
    <li>if多条件 || , && , !</li>
    <#assign var='python'>
    <#if var == 'python' || var == 'java' || var?length==6>
        <font color="red">python or java</font><br/>
    </#if>
    </ul>

     

  6.  switch语法

    <h2>switch case break default</h2>
    <ul>
        <#assgin var == 110 />
        <#switch var>
            <#case 10>
            <#case 11>
            10 or 11<br/>
            <#break>
            <#case 100>
            100<br/>
            <#break>
    
            <#default>
                other
        </#switch>
    </ul>

     

  7.  string基本操作命令

    <ul>
    <#assign a='hello' />
    <#assign b='world'/>
    <li>连接</li>
    <font color="red">${a + b}</font><br/>
    <li>截取</li>
    <font color="red">${(a + b)?substring(5,8)}</font><br/>
    <li>长度</li>
    <font color="red">${(a + b)?length}</font><br/>
    <li>大写</li>
    <font color="red">${(a + b)?upper_case}</font><br/>
    <li>小写</li>
    <font color="red">${(a + b)?lower_case}</font><br/>
    <li>index_of</li>
    <font color="red">${(a + b)?index_of('w')}</font><br/>
    <li>last_index_of</li>
    <font color="red">${(a + b)?last_index_of('o')}</font><br/>
    <li>replace</li>
    <font color="red">${(a + b)?replace('o','xx')}</font><br/>
    </ul>

     

Freemarker自定义函数

  1. 编辑index.ftl文件,使用sort_int函数对集合list进行升序排序
    <h1>自定义函数</h1>
    <h2>1,自定义函数(整数排序 sort_int)</h2>
    <div class="demo-div">
        <ul>
            <#assign myList=[2,3,4,5,1,8,9,8,7]/>
            <li>未排序</li>
            <#list myList as item>
                ${item},
            </#list>
    
            <li>已排序</li>
            <#list sort_int(myList) as item>
                ${item},
            </#list>
        </ul>
    </div>

     

  2. 在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<BigDecimal> list=arg0.toList();
    
            Collections.sort(list,new Comparator<BigDecimal>(){
                @Override
                public int compare(BigDecimal o1, BigDecimal o2) {
                    return o1.intValue()-o2.intValue(); //升序
                }
            });
    
            return list;
        }
    }
    

     

  3. 在控制器方法中,加入sort_int函数变量。

    @RequestMapping("/")
        public String welcome(HttpServletRequest request){
            request.setAttribute("name","Mr.Yang");
            request.setAttribute("sort_int",new SortMethod());
            return "index";
        }

     

  4. 运行springboot,查看localhost:8080/demo,结果如下则自定义函数创建成功。 

     

     

 list排序内置函数和常用指令

item_index:此变量用于list遍历指令内,表示当前item所在下标,从0开始计数。

sort :内置的list集合排序函数

reverse: 内置的list集合反序函数

size :获取list集合的大小

myList[3]:获取下标为3的集合元素

<#assign base=request.contextPath />
<!DOCTYPE html>
<html lang="zh">
<head>
    <base id="base" href="${base}">
    <title>首页</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>List的指令</h1>
<h2>1,list常用指令</h2>
<div class="demo-div">
    <ul>
        <#assign myList=[2,3,4,5,1,8,9,8,7] />
        <#list myList?sort?reverse as item>
            ${item_index} : ${item}<br/>
        </#list>
        
        ${myList?size}<br/>
        ${myList[3]}<br/>
    </ul>
</div>
</body>
</html>

Freemarker自定义指令

  1. 创建index2.ftl,写入如下内容,使用自定义指令role,自定义以@开头
    <#assign base=request.contextPath />
    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <base id="base" href="${base}">
        <title>index2</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <h1>自定义指令</h1>
    <h2>1,用户123456是否拥有admin角色,并且返回admin的权限</h2>
    <div class="demo-div">
        <ul>
            <@role user='123456' role='admin'; result1 , result2>
                <#if result1>
                    我的角色是<font color="red">admin</font><br/>
                </#if>
                我拥有的权限是:<font color="red">
                <#list result2 as item>
                    ${item},
                </#list>
            </font><br/>
            </@role>
        </ul>
    </div>
    </body>
    </html>

     

  2.  在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<String> otherRights=new ArrayList<>();
            otherRights.add("add");
            otherRights.add("update");
            otherRights.add("delete");
            loopVars[1]=new SimpleSequence(otherRights);
    
            templateDirectiveBody.render(environment.getOut());
        }
    }
    

     

  3.  在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());
            }
        }
    }
    

     

  • 重启Springboot项目,看到如下内容则表示自定义指令运行成功。 

     FreeMarker内建函数

  1.  处理字符串内建函数
    //见名知义哈
    
    1.substring , cap_first , ends_with , contains
    
    2. date , datetime , time
    
    3. starts_with , index_of , last_index_of , split , trim

    代码示例

    <h1>内建函数</h1>
    <div class="demo-div">
        <ul>
            <h2>1,字符串内建函数</h2>
            <#list "a|b|c|d"?split("|") as item>
                <li>${item}</li>
            </#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")>
            <li>${var1}</li>
            <li>${var2}</li>
            <li>${var3}</li>
        </ul>
    </div>

     

  2.  处理数字的内建函数

    1. string , x?string("0.##")
    
    2. round , floor , ceiling
    

    代码示例

    <h2>2,数字类型内建函数</h2>
    <!-- 数字类型内建函数 -->
    <#assign numVar1 = 314.5662 />
    <li>${numVar1?string("0.##")}</li>        //四舍五入 结果314.57
    <li>${numVar1?round}</li>

     

  3.  

    处理List的内建函数

     

    1. first , last, seq_contains, seq_index_of
    
    2. size, reverse, sort, sort_by
    
    3. chunk

    代码示例

    <h2>3,list内建函数</h2>
    <#assign listVar1 = [1,2,3,4,11,12,13,14,21,22,23,24] />
    <li>${listVar1?chunk(4)?size}<?li>
    <#list listVar1?chunk(4)?last as item>
    <li>${item}</li>
    </#list>

     

  4. 其他内建函数

    1. is函数:is_string, is_number, is_method
    
    2. (), has_content函数
    
    3. eval求值

    代码示例

    <h2>4,其他内建函数</h2>
    <#assign sVar='hello' />
    <li>${sVar?is_number?string('yes','no')}</li>
    <li>${sVar?has_content?string('yes','no')}</li>
    <li>${'1+2'?eval}</li>

    Macro宏指令、function函数指令 

 

  1. 下面是macro指令和function指令的语法
    #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)}
    

     

  2. 新建index3 .ftl文件,在其中使用macro宏指令创建共用模板代码,使用function指令创建自定义函数。

    <#assign base=request.contextPath />
    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <base id="base" href="${base}">
        <title>index3</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <style type="text/css">
            div {
                font-size: 20px;
            }
            .demo-div ul li {
                font-weight: bold;
                font-size: 20px;
                margin: 15px 0px 5px 0px;
            }
        </style>
    </head>
    <body style="padding-left: 50px;">
    <h1>macro nested return 实战demo</h1>
    <h2>1,macro :宏指令</h2>
    <div class="demo-div">
        <ul>
            <li>栗子1:无参数的macro</li>
            <div>
                <#macro test>
                    <font color="red">我是无参数的macro</font>
                </#macro>
                <@test/>
            </div>
    
            <li>栗子2:有参数的macro</li>
            <div>
                <#macro test1 param1 param2>
                    <font color="red">我是有参数的macro,param1 = ${param1},param2 = ${param2}</font>
                </#macro>
                <@test1 param1="java" param2="python" />
            </div>
    
            <li>栗子3:有默认值参数的macro</li>
            <div>
                <#macro test2 param1 param2="python">
                    <font color="red">我是有参数的macro,param1 = ${param1},param2 = ${param2}</font>
                </#macro>
                <@test2 param1="java" />
            </div>
    
            <li>栗子4:有多个参数的macro</li>
            <div>
                <#macro test3 param1 param2="python" paramExt...>
                    <font color="red">我是有参数的macro,param1 = ${param1}, param2 = ${param2}</font>
                    <br/>
                    <font color="red">${paramExt['param3']}</font><br/>
                    <font color="red">${paramExt['param4']}</font>
                </#macro>
                <@test3 param1="java" param2="hello python" param3="javascript" param4="nodejs"/>
            </div>
        </ul>
    </div>
    
    <h2>2,nested</h2>
    <div class="demo-div">
        <ul>
            <#macro test param1 = "java">
                ${param1}<br/>
                <#nested param1,"我的nested 参数"><br/>
            </#macro>
    
            <li>调用</li>
            <div>
                <@test param1="java"; loopVar1, loopVar2>
                    <font color="red">hello ${loopVar1} , ${loopVar2}</font>
                </@test>
    
                <@test param1="python";loopVar1>
                    hello ${loopVar1}<br/>
                </@test>
            </div>
        </ul>
    </div>
    
    <h2>3,函数</h2>
    <div class="demo-div">
        <ul>
            <#function doAdd param1 param2>
                <#return param1+param2>
            </#function>
            <li>调用</li>
            <div>你好,我是调用 ${doAdd(100,100)}</div>
        </ul>
    </div>
    
    </body>
    </html>

     

  3. 运行springboot项目,在浏览器中访问 localhost:8080/index3,可看到如下结果:

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值