基类

public class Ftl_object_data_model  {
//三种基本属性
private boolean canRead=true;//是否能读取
private int length=;//长度
private String content;//内容
//内部小vo对象属性
private Ftl_object_data_model_inner fi = new Ftl_object_data_model_inner(); //非属性内部方法1
public boolean isCanWrite() {
return true;
}
//非属性内部方法2
public boolean canSend() {
return true;
} public boolean isCanRead() {
return canRead;
} public void setCanRead(boolean canRead) {
this.canRead = canRead;
} public int getLength() {
return length;
} public void setLength(int length) {
this.length = length;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public Ftl_object_data_model_inner getFi() {
return fi;
} public void setFi(Ftl_object_data_model_inner fi) {
this.fi = fi;
} // @Override
// public Object exec(List arg0) throws TemplateModelException {
// return new SimpleNumber(((SimpleScalar)arg0.get(1)).getAsString().indexOf(((SimpleScalar)arg0.get(0)).getAsString()));
// }
// public TemplateModel exec(List arg0) throws TemplateModelException {
// return new SimpleNumber(((String)arg0.get(1)).indexOf((String)arg0.get(0)));
// }
} 基类中小vo 的类 public class Ftl_object_data_model_inner {
private boolean canRead=true;//是否能读取
private int length;//长度
private String content;//内容 public boolean isCanRead() {
return canRead;
} public void setCanRead(boolean canRead) {
this.canRead = canRead;
} public int getLength() {
return length;
} public void setLength(int length) {
this.length = length;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
}
} main启动测试类 public class FtlTest {
public static void main(String[] args) throws IOException {
Configuration cfg = new Configuration();
cfg.setDirectoryForTemplateLoading(new File("F:\\king\\proj\\TKCard\\TKCard_cn_cn_Server\\src\\test\\java\\general\\ftl_test"));
// cfg.setObjectWrapper(ObjectWrapper.DEFAULT_WRAPPER);
cfg.setObjectWrapper(new DefaultObjectWrapper());
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER); //生成数据模型
//用map封装的数据模型
// Object root = testMapDataModel();
//直接用对象封装的数据模型
Object root = testObjectDataModel();
// 通过freemarker解释模板,首先需要获得Template对象
//用map封装的数据模型对应的模板
// Template template = cfg.getTemplate(testMapDataModelTemplate());
//直接用对象封装的数据模型对应的模板
Template template = cfg.getTemplate(testObjectDataModelTemplate()); // 定义模板解释完成之后的输出
//PrintWriter out = new PrintWriter(new BufferedWriter( new FileWriter(dir+"/out.txt")));
//直接控制台打印
OutputStreamWriter out = new OutputStreamWriter(System.out);
try {
// 解释模板
template.process(root, out);
} catch (TemplateException e) {
e.printStackTrace();
}
} /**
* 测试用map封装的数据模型
* @return
*/
public static Object testMapDataModel(){
Map root = new HashMap();
root.put("name1", "世界,你好");//模板里需要几个值,这边数据模型里就必须要塞几个值,缺一个就会报错(多塞不会报错),因为freeworker 不支持null,所以少塞会报错
root.put("name2", "我is大开发建设领导看风景");
root.put("name3", new Ftl_object_data_model());//如果传的是方法则上边map类型的数据模型的map只能去掉泛型了,不能用key为value皆为string的泛型了
return root;
}
/**
* 测试用map封装的数据模型对应的数据模板
* @return
*/
public static String testMapDataModelTemplate(){
return "ftl_map_data_model.ftl";
} /**
* 测试用vo对象封装的数据模型
* @return
*/
public static Object testObjectDataModel() {
Ftl_object_data_model fm = new Ftl_object_data_model();
return fm;
}
/**
* 测试用vo对象封装的数据模型对应的数据模板
* @return
*/
public static String testObjectDataModelTemplate(){
return "ftl_object_data_model.ftl";
}
} 数据模板 ---------------------------------------- 一、------------------------------------- <#-- 一、整个vo对象直接作为数据模型数据的基类Ftl_object_data_model 对象中的属性拿取方式-->
<#--基础属性直接拿取,无需带上对象变量(由于这边无需变量名,所以此基类变量名既不是root又不是fm)-->
<#--${root.length} 错误的写法,无需带root-->
<#--${fm.length} 错误的写法,无需带fm-->
<#--基类属性读取直接拿即可,其他属性一样,包括方法,直接拿取-->
${length}
<#--由于ftl一般都以字符串形式打印,所以Boolean类型的读取要特殊处理-->
<#--${canRead} 内部Boolean类型属性错误读取-->
<#--${canread} 内部Boolean类型属性错误读取-->
<#--${isCanRead()} 内部Boolean类型属性错误读取-->
<#--Boolean类型正确读写 固定格式 var?c -->
<#--boolean第一种读取,结果打印true or false-->
${canRead?c}
<#--Boolean第二种读取,结果打印yes or no 当canRead为真则取第一个参数值即yes,否则取第二个参数no-->
${canRead?string('yes','no')}
<#--非属性 的 Boolean类型get方法读取,即这个get方法拿的不是对象的属性,而仅仅是类中一个返回值为Boolean类型的方法-->
方法1:<#--${CanWrite()?c} 拿对象中非属性内部方法1错误拿法-->
方法1:<#--${canWrite()?c} 拿对象中非属性内部方法1错误拿法-->
方法1:<#--${canwrite()?c} 拿对象中非属性内部方法1错误拿法-->
方法1:<#--<#if CanWrite >true</#if> 拿对象中非属性内部方法1错误拿法-->
方法1:<#--<#if canwrite >true</#if> 拿对象中非属性内部方法1错误拿法--> 方法1:${isCanWrite()?c} <#-- 拿对象中非属性内部方法1正确拿法1-->
方法1:<#if isCanWrite() >true</#if> <#--拿对象中非属性内部方法1正确拿法-->
方法1:<#if canWrite >true</#if> <#--拿对象中非属性内部方法1正确拿法,这种方法是一种特殊的拿取方式,必须是在严格的is打头的get方法时才有用--> 方法2:<#--${cansend()?c} 拿对象中非属性内部方法2错误拿法-->
方法2:<#--<#if canSend >true</#if> 拿对象中非属性内部方法2错误拿法-->
方法2:<#--<#if cansend >true</#if> 拿对象中非属性内部方法2错误拿法--> 方法2:${canSend()?c} <#-- 拿对象中非属性内部方法2正确拿法1-->
方法2:<#if canSend() >true</#if> <#--拿对象中非属性内部方法2正确拿法--> ---------------------------------------- 二、------------------------------------- <#-- 二、整个vo对象直接作为数据模型数据的基类Ftl_object_data_model 对象中的子类属性 小vo对象中的属性拿取方式-->
<#--直接用小vo 被new 时的变量名.属性 或 .方法即可 拿取 方式和直接拿基类中的属性一样的-->
${fi.length}
${fi.isCanRead()?c}
<#if fi.isCanRead() >true</#if>
<#if fi.canRead >true</#if> <#-- 注:几个重要的语法规则: 、FreeMarker的插值有如下两种类型:,通用插值${expr};,数字格式化插值:#{expr}或#{expr;format}
、??:判断某个变量是否存在,返回boolean值 类似 var?if_exists
、var!xxx:指定缺失变量的默认值 类似 var?default(xxx) 而 ${!var?c}表明非var,即当var为真时结果求假,!此表非含义
、使用lt、lte、gt和gte来替代<、<=、>和>= 也可以使用括号<#if (x>y)>
、内置函数: 调用区别于属性的访问,属性访问用.访问,而内置函数用?访问如var?if_exists
、注意${}为变量的渲染显示,而<>为定义等操作符的定义
、对于库中的变量修改,使用in关键字 <#assign mail="jsmith@other.com" in my>
、stringA[M .. N] 取子字符串,类似substring(stringA, M, N)
、List片段可以采用: products[..] or products[..] 的格式进行定义,当只局限于数字
<#assign c= [,,,,,,,]>
<#list c[..] as v>
${v}
</#list>
、freemarker可用"["代替"<".在模板的文件开头加上[#ftl].
、注释语法 <#-- 注释部分 -->
<#-- 由于杀念11注释语法破坏了整体的注释,所以这边由加了个注释头标签
、 数字输出的另外一种方式 #{c.a;m0} 区别于${x},这个例子是用于输出数字的格式化,保留小数的位数,详细如下
数字格式化插值可采用#{expr;m1M2}形式来格式化数字,其中: m1:小数部分最小1位 M2:小数部分最大2位 即大小m代表不同含义
、在定义字符串的时候,可以使用''或者"",对特殊字符,需要使用\进行转义
、如果存在大量特殊字符,可以使用${r"..."}进行过滤 如 ${r"${foo}"} ${r"C:\foo\bar"}
、Map对象的key和value都是表达式,但是key必须是字符串 可以混合使用.和[""]访问 book.author["name"] //混合使用点语法和方括号语法
、为了处理缺失变量,FreeMarker提供了两个运算符: 用于防止对象不存在而导致的异常 !:指定缺失变量的默认值 ??:判断某个变量是否存在,返回boolean值
、noparse指令指定FreeMarker不处理该指定里包含的内容,该指令的语法格式如下: <#noparse>...</#noparse>
、?html 用于将字符串中可能包含的html字符,进行过滤.
${firstName?html} 使用?html对html字符进行过滤、格式化处理 escape , noescape指令,对body内的内容实用统一的表达式
看如下的代码:
<#escape x as x?html>
First name:${firstName}
Last name:${lastName}
Maiden name:${maidenName}
</#escape>
上面的代码等同于:
First name:${firstName?html}
Last name:${lastName?html}
Maiden name:${maidenName?html}
、<#assign name1=value1 name2=value2 / > 可以同时定义多个变量
也可以使用循环来给变量赋值
<#assign x>
<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n>
n:${n}
</#list>
</#assign>
x:${x} 执行结果:
x:
n:星期一
n:星期二
n:星期三
n:星期四
n:星期五
n:星期六
n:星期天
说明:不是先打印n:${n}的循环值,而是先打印 x:${x}的值。含义就是先定义一个x,x的内容为 循环list,每次循环渲染显示的内容
n:${n} 的值 为x中的一个元素,全部循环完,x的值也组装完了,结果打印显示x:${x}。记住不是说list为x中的list,即不是为x注入一个list(这
就是为啥最后打印x时前边都有n:而不是和原list内容一样的原因,表明此list不是x中的属性,即此list和x没什么关系,此仅借用一下list机制而已),
而是通过list机制 进行循环得出临时值作为x的元素。
、setting指令,用于动态设置freeMarker的运行环境:
该指令用于设置FreeMarker的运行环境,该指令的语法格式如下:<#setting name=value>,在这个格式中,name的取值范围包含如下几个:
locale:该选项指定该模板所用的国家/语言选项
number_format:指定格式化输出数字的格式
boolean_format:指定两个布尔值的语法格式,默认值是true,false
date_format,time_format,datetime_format:指定格式化输出日期的格式
time_zone:设置格式化输出日期时所使用的时区
、<#return> 用于退出宏的运行
、调用Java方法:
如:
public class A implements TemplateMethodModelEx{
@Override
public Object exec(List arg0) throws TemplateModelException {
return new SimpleNumber(((SimpleScalar)arg0.get()).getAsString().indexOf(((SimpleScalar)arg0.get()).getAsString()));
}

public TemplateModel exec(List arg0) throws TemplateModelException {
return new SimpleNumber(((String)arg0.get()).indexOf((String)arg0.get()));
}
}
封装数据模型时用map模型(如果用vo对象模型的话可能需要vo中有个map,此map的效果等同于直接用map模型),直接 map.put("method",new A()); method可以任意变量名
由于此要put一个对象,所以此map模型用到的map就不能用Map<String,String>了,即不用带泛型,用 Map root = new HashMap();
下边就是到模板了,模板里表达式格式为:<#assign x = "something"> ${method("met",x)} 即先定义一个变量x,然后调用表达式method("met",x),此表达式传2个
参数,当解析模板执行到此表达式时会将此表达式的2个参数直接传到A类中的exec方法中的参数,exec方法参数为list,那模板中传几个参数都是以String类型或
SimpleScalar(ftl包装string用的对象,可以调用getAsString()得到string内容)类型直接传到exec的参数list中的,传几个过来就都封装到这个list中,exec执行
结果返回给模板 ${结果} 渲染显示出来。 说明:调用Java方法时需要java类实现TemplateMethodModel 或 TemplateMethodModelEx接口,但是好像会覆盖掉属性的访问,即这个类中的其他属性可能就没法访问了(这个是否能访问没测过)
即要调用的java方法所在类 必须实现TemplateMethodModel接口,即实现 exec方法 即 public TemplateModel exec(List arg0) throws TemplateModelException
或 public Object exec(List list) throws TemplateModelException 方法。
在模板解析时模板中调用表达式时会立即调用到java类中的上边实现的exec方法,exec方法返回值 返回给 模板中表达式处 渲染显示出来。 -->

自己模拟的ftl 用法:的更多相关文章

  1. C# keybd_event模拟对照表以及用法.

    Windows提供了一个模拟键盘API函数Keybd_event(),该函数能触发一个按键事件,也就是说会产生一个WM_KEYDOWN或WM_KEYUP消息. [DllImport("use ...

  2. curl_multi_*模拟多线程异步用法

    测试环境: PHP版本:php7.0.10 mysql版本:5.7.14 测试用例:循环插入两千行数据到数据库 public function test_syn($pc){ // $pc = trim ...

  3. C# 模拟Windows键盘事件

    发送键盘消息 [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true) ...

  4. 图片轮播(淡入淡出)--JS原生和jQuery实现

    图片轮播(淡入淡出)--js原生和jquery实现 图片轮播有很多种方式,这里采用其中的 淡入淡出形式 js原生和jQuery都可以实现,jquery因为封装了很多用法,所以用起来就简单许多,转换成j ...

  5. JDicom使用指南

    适用条件本指南用于使用JDicom进行环境模拟.产品调试. 一.安装JDicom运行JDicom安装程序之前,需安装JRE 1.3及以上版本.否则,弹出如下图所示报错 安装JRE 1.4:双击运行可执 ...

  6. Linux下高并发socket链接数测试

    一.如何增大service进程的max open files ulimit -n 只能改小max open files,不能改大.需要按照以下步骤: 修改/etc/security/limits.co ...

  7. oracle 有用站点

    使用oradebug修改数据库scn – 提供专业ORACLE技术咨询和支持@Phone13429648788 - 惜分飞 Solaris上使用DTrace进行动态跟踪 老熊的三分地-Oracle及数 ...

  8. oracle 常用博客网址

    使用oradebug修改数据库scn – 提供专业ORACLE技术咨询和支持@Phone13429648788 - 惜分飞 Solaris上使用DTrace进行动态跟踪 老熊的三分地-Oracle及数 ...

  9. Mock.js:前后端分离开发工具

    概述 Mock.js实现的功能 基于 数据模板 生成数据 基于 HTML模板 生成数据 拦截并模拟 Ajax请求 用法 浏览器: <!-- (必选)加载 Mock --> <scri ...

随机推荐

  1. 深入分析mysql为什么不推荐使用uuid或者雪花id作为主键

    前言:在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建 ...

  2. 数据库表结构查询SQL

    今天给大家送上两个SQL查询的方法,也许在项目中你都用过,但是,没关系,仅仅记录下,以便后面不用去查找.针对与经常写SQL的同行来说,应该是非常简单的. 查询表结构数据 SELECT t.COLUMN ...

  3. 面试刷题12:zero copy是怎么回事?

    文件copy是java的io部分不可忽视的内容. 我是李福春,我在准备面试,今天的问题是: zero-copy是怎么回事? 操作系统的空间划分为内核态空间, 用户态空间: 内核态空间相对操作系统具备更 ...

  4. 题解 P4302 【[SCOI2003]字符串折叠】

    讲讲我的做法 题目大意:对一个字符串进行折叠是它长度最小 看一眼数据范围:哇!字符串长度不超过100!这是一道省选题,不可能给你太宽裕的时限,所以,题目基本暗示你要用\(n^{3}\)多一些的算法复杂 ...

  5. 图-连通分量-DFS-749. 隔离病毒

    2020-03-17 21:56:20 问题描述: 病毒扩散得很快,现在你的任务是尽可能地通过安装防火墙来隔离病毒. 假设世界由二维矩阵组成,0 表示该区域未感染病毒,而 1 表示该区域已感染病毒.可 ...

  6. vue采坑记录

    1.项目在浏览器运行的时候没有ico图标 <link rel="shortcut icon" type="image/x-icon" href=" ...

  7. k8s可视化工具kubernetes-dashboard部署——小白教程

    参考资料: kubernetes官方文档 官方GitHub 创建访问用户 解决chrome无法访问dashboard 官方部署方法如下: kubectl apply -f https://raw.gi ...

  8. coding++:Semaphore—RateLimiter-漏桶算法-令牌桶算法

    java中对于生产者消费者模型,或者小米手机营销 1分钟卖多少台手机等都存在限流的思想在里面. 关于限流 目前存在两大类,从线程个数(jdk1.5 Semaphore)和RateLimiter速率(g ...

  9. Git入门操作(一)

    最近真正用到了Git,感觉还是需要好好整理一下最最基础用法,与萌新共享.^_^ 关于Git的基础介绍,这里不再赘述,下面撸代码了(主要是命令行的操作,属于linux操作系统的,可能没听过,但记住就好了 ...

  10. 深入调研Linq to Objects Join Linq to Entity

    最近工作中遇到数据库组合查询带来的一些问题,因此有必要调研一下Linq to Objects Join Linq to Entity.参考一些网友的代码案例,深入实践了一下使用EntityFramew ...