FreeMaker入门

2024-04-14 09:38
文章标签 入门 freemaker

本文主要是介绍FreeMaker入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

第一章 简介

 

1 什么是FreeMaker

 

FreeMaker是一款模板引擎,即基于模板,用来生成文本的工具。可以用来实现MVC模式。FreeMaker基于BSD协议。是ISO认证的开源软件。

 

2. 简介

 

如果你的在线商店需要这样的页面如:

 

<html> 
<head> <title>Welcome!</title> 
</head> 
<body> <h1>Welcome tntxia!</h1> <p>Our latest product: <a href="products/greenmouse.html">green mouse</a>! 
</body> 
</html>

 

这里tntxia是用户名。应该使用动态。

 

FreeMaker是这样实现的。

 

<html> 
<head> <title>Welcome!</title> 
</head> 
<body> <h1>Welcome ${user}!</h1> <p>Our latest product: <a href="${latestProduct.url}">${latestProduct.name}</a>! 
</body> 
</html>   

 

FreeMaker可以使用Map、List对象,也可以自定义的数据模型。

 

${…}:FreeMaker会使用动态的数据改成$里面的内容。

 

FTL tags 标签(FreeMarker  模板的语言标签) :与HTML标签相似,一般以#开关,但也可以自定义。

 

Comments 注释:<#--    -->

 

 

 

 

 

 

可以增加一个Servlet:

 

package com.tntxia.freemaker.test;import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;public class HelloFreeMarker extends HttpServlet {/*** */private static final long serialVersionUID = 6255189103129788283L;public HelloFreeMarker() {super();}// 负责管理FreeMarker模板的Configuration实例private Configuration cfg = null;public void init() throws ServletException {// 创建一个FreeMarker实例cfg = new Configuration();// 指定FreeMarker模板文件的位置cfg.setServletContextForTemplateLoading(getServletContext(),"/WEB-INF/templates");}public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doPost(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 建立数据模型Map root = new HashMap();root.put("message", "hello world");root.put("name", "聂靖宇");root.put("num", 5);DataModel data = new DataModel();root.put("data", data);// root.put("personList", list);// 获取模板文件Template t = cfg.getTemplate("test1.ftl");// 开始准备生成输出// - 使用模板文件的Charset作为本页面的charset// - 使用text/html MIME-typeresponse.setContentType("text/html; charset=" + t.getEncoding());Writer out = response.getWriter();// 合并数据模型和模板,并将结果输出到out中try {t.process(root, out); // 往模板里写数据} catch (TemplateException e) {e.printStackTrace();}}public void destroy() {super.destroy();}
}

 

 在WEB-INF里面增加一个template的文件,增加一个FTL文件:

 

test1.ftl

 

<html><head>      <title>Hello Word</title>     </head> <body>        
<#--  测试注释                    -->
<h3>${message},${name}    ${data.test}</h3> <#if num > 5 >num  is 5</#if></body> </html>

 


 

1.1 指令

 

1.1.1 if指令

 

<#if user == "Big Joe">, our beloved leader</#if>!

 

通过if指令,可以让符合条件的内容显示。

 

当condition 的判断结果为 false(布尔值)时,在<#if condition>和</#if>标签之间的内容将会被略过。

 

使用<#else>标签可以指定当条件为假时程序执行的内容。例如:

 

<#if animals.python.price < animals.elephant.price> Pythons are cheaper than elephants today. 
<#else> Pythons are not cheaper than elephants today. 
</#if>      

 

1.1.2 list指令

 

用List指令可以实现循环输出

 

如:

 

<p>We have these animals:
<table border=1><tr><th>Name<th>Price<#list animals as being><tr><td>${being.name}<td>${being.price} Euros</#list>
</table> 

 

  list 指令的一般格式为:
  <#list sequence as loopVariable>repeatThis</#list>
  repeatThis 部分将会在给定的sequence 遍历时在每项中重复,从第一项开始,
一个接着一个。在所有的重复中,loopVariable 将持有当前项的值。这个循环变量仅
存在于<#list …>和</#list>标签之间。

 

1.1.3  include指令

 

引入一个模板:

 

<#include "test.ftl">
 
使用

 

<#include "/test.ftl">
 
是一样的效果

 

文件的位置与模板文件夹一致。

 

1.1.4 不存在的变量的处理

 

${user!"Asynonymous"}<#if user??>welcome ${user}<#else>Asynonymous Again</#if>

 

 FreeMaker容器:

 

2.2.3  容器
  这些值存在的目的是为了包含其他变量,它们仅仅作为容器。被包含的变量通常是子变
量。容器的类型有:
 哈希表:每个子变量都可以通过一个唯一的名称来查找,这个名称是不受限制的字
符串。哈希表并不确定其中子变量的顺序,也就是说没有第一个变量,第二个变量
这样的说法,变量仅仅是通过名称来访问的。 (就像 Java 语言中的 HashMap 一样,
是实现了 Hash 算法的 Map,不记录内部元素的顺序,仅仅通过名称来访问。译者
注)
  序列:每个子变量通过一个整数来标识。 第一个子变量的标识符是 0,第二个是 1,
第三个是 2,这样来类推,而且子变量是有顺序的。这些数字通常被称为是子变量
的索引。序列通常比较密集,也就是所有的索引,包括最后一个子变量的,它们和
子变量都是相关联的,但不是绝对必要的。 子变量的数值类型也并不需要完全一致。 
  集:  从模板设计者角度来看,集是有限制的序列。不能获取集的大小,也不能通过
索引取出集中的子变量,但是它们仍然可以通过 list 指令来遍历。

 

2.2.4 函数

 

The average of 3 and 5 is: ${avg(3, 5)} 
The average of 6 and 10 and 20 is: ${avg(6, 10, 20)} 
The average of the price of a python and an elephant is: 
${avg(animals.python.price, animals.elephant.price)}  

 

输出结果:

 

The average of 3 and 5 is: 4 
The average of 6 and 10 and 20 is: 12 
The average of the price of a python and an elephant is: 
4999.5 

 

 

 2.2.5 自定义方法

 

方法变量在存于实现了 TemplateMethodModel 接口的模板中。这个接口仅包含方法调用表达式调用方法时, exec方法将会被调用。 形参将会包含FTL方法调用形参的值。exec 方法的返回值给出了 FTL 方法调用表达式的返回值。

 

2.2.6 自定义指令

 

  Java程序员可以使用TemplateDirectiveModel 接口在Java代码中实现自定义指令。详情可以参看 API 文档。

 

2.2.6.1  第一个示例

 

模板:

 

 

foo 
<@upper> bar <#-- 这里允许使用所有的 FTL --> <#list ["red", "green", "blue"] as color> ${color} </#list> baaz 
</@upper> 
wombat 
 

 

将会输出:

 

foo
  BAR
    RED
    GREEN
    BLUE
  BAAZ
wombat

 

下面是指令类的源代码:

root.put("upper", new com.example.UpperDirective()); 

 

 

package com.example; 
import java.io.IOException; 
import java.io.Writer; 
import java.util.Map; 
import freemarker.core.Environment; 
import freemarker.template.TemplateDirectiveBody; 
import freemarker.template.TemplateDirectiveModel; 
import freemarker.template.TemplateException; 
import freemarker.template.TemplateModel; 
import freemarker.template.TemplateModelException; 
/** *  FreeMarker的用户自定义指令在逐步改变 
*  它嵌套内容的输出转换为大写形式 
*  <p><b>指令内容</b></p> 
*  <p>指令参数:无 *  <p>循环变量:无 
*  <p>指令嵌套内容:是 
*/ 
public class UpperDirective implements TemplateDirectiveModel 
{ public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { // 检查参数是否传入 if (!params.isEmpty()) { throw new TemplateModelException( "This directive doesn't allow parameters."); } if (loopVars.length != 0) { throw new TemplateModelException("This directive doesn't allow loop variables."); } // 是否有非空的嵌入内容 if (body != null) { // 执行嵌入体部分,和 FTL中的<#nested>一样,除了 // 我们使用我们自己的 writer 来代替当前的 output writer. body.render(new UpperCaseFilterWriter(env.getOut())); } else { throw new RuntimeException("missing body"); } 
} 
/** * {@link Writer}改变字符流到大写形式, 
* 而且把它发送到另外一个{@link Writer}中。 
*/ 
private static class UpperCaseFilterWriter extends Writer { 
private final Writer out; 
UpperCaseFilterWriter (Writer out) { this.out = out; 
} public void write(char[] cbuf, int off, int len) throws IOException { char[] transformedCbuf = new char[len]; for (int i = 0; i < len; i++) { transformedCbuf[i] = Character. 
toUpperCase(cbuf[i + off]); } out.write(transformedCbuf); } public void flush() throws IOException { out.flush(); } public void close() throws IOException { out.close(); } 
} 
}  
 

 

最后,把它放在数据模型里面,如:

 

 

root.put("upper", new com.example.UpperDirective()); 

 

第二个示例 :Repeat

 

 

 

 

 

这篇关于FreeMaker入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/902690

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

C语言指针入门 《C语言非常道》

C语言指针入门 《C语言非常道》 作为一个程序员,我接触 C 语言有十年了。有的朋友让我推荐 C 语言的参考书,我不敢乱推荐,尤其是国内作者写的书,往往七拼八凑,漏洞百出。 但是,李忠老师的《C语言非常道》值得一读。对了,李老师有个官网,网址是: 李忠老师官网 最棒的是,有配套的教学视频,可以试看。 试看点这里 接下来言归正传,讲解指针。以下内容很多都参考了李忠老师的《C语言非

MySQL入门到精通

一、创建数据库 CREATE DATABASE 数据库名称; 如果数据库存在,则会提示报错。 二、选择数据库 USE 数据库名称; 三、创建数据表 CREATE TABLE 数据表名称; 四、MySQL数据类型 MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串类型 4.1 数值类型 数值类型 类型大小用途INT4Bytes整数值FLOAT4By

【QT】基础入门学习

文章目录 浅析Qt应用程序的主函数使用qDebug()函数常用快捷键Qt 编码风格信号槽连接模型实现方案 信号和槽的工作机制Qt对象树机制 浅析Qt应用程序的主函数 #include "mywindow.h"#include <QApplication>// 程序的入口int main(int argc, char *argv[]){// argc是命令行参数个数,argv是