自己模拟的ftl 用法:
基类 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 用法:的更多相关文章
- C# keybd_event模拟对照表以及用法.
Windows提供了一个模拟键盘API函数Keybd_event(),该函数能触发一个按键事件,也就是说会产生一个WM_KEYDOWN或WM_KEYUP消息. [DllImport("use ...
- curl_multi_*模拟多线程异步用法
测试环境: PHP版本:php7.0.10 mysql版本:5.7.14 测试用例:循环插入两千行数据到数据库 public function test_syn($pc){ // $pc = trim ...
- C# 模拟Windows键盘事件
发送键盘消息 [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true) ...
- 图片轮播(淡入淡出)--JS原生和jQuery实现
图片轮播(淡入淡出)--js原生和jquery实现 图片轮播有很多种方式,这里采用其中的 淡入淡出形式 js原生和jQuery都可以实现,jquery因为封装了很多用法,所以用起来就简单许多,转换成j ...
- JDicom使用指南
适用条件本指南用于使用JDicom进行环境模拟.产品调试. 一.安装JDicom运行JDicom安装程序之前,需安装JRE 1.3及以上版本.否则,弹出如下图所示报错 安装JRE 1.4:双击运行可执 ...
- Linux下高并发socket链接数测试
一.如何增大service进程的max open files ulimit -n 只能改小max open files,不能改大.需要按照以下步骤: 修改/etc/security/limits.co ...
- oracle 有用站点
使用oradebug修改数据库scn – 提供专业ORACLE技术咨询和支持@Phone13429648788 - 惜分飞 Solaris上使用DTrace进行动态跟踪 老熊的三分地-Oracle及数 ...
- oracle 常用博客网址
使用oradebug修改数据库scn – 提供专业ORACLE技术咨询和支持@Phone13429648788 - 惜分飞 Solaris上使用DTrace进行动态跟踪 老熊的三分地-Oracle及数 ...
- Mock.js:前后端分离开发工具
概述 Mock.js实现的功能 基于 数据模板 生成数据 基于 HTML模板 生成数据 拦截并模拟 Ajax请求 用法 浏览器: <!-- (必选)加载 Mock --> <scri ...
随机推荐
- Jenkins+Ant+JMeter集成
Tomcat是jenkins运行的容器,jenkins实际上是依赖于Tomcat才能启动的.Jenkins可以调度ant的脚本. Ant和maven类似,maven是执行pom文件,ant是执行bui ...
- P5020 货币系统 题解
原题链接 简要题意: 求一个长度最小的货币系统与给出的货币系统等价.求这个货币系统的长度.等价的定义详见题目,不再赘述. 本文可能用到一些集合论,请放心食用. 算法一 \(n=2\) 时,只需判断两个 ...
- Anomaly Detection-异常检测算法(Coursera-Ng-ML课程)
现实生活中有许多需要提前预防一些异常问题出现的情况,例如在飞机起飞前,对飞机各部分进行评估,看发动机等各个零件是否性能正常,若有潜在的问题(可能出现异常情况),则需要及时检修或更换. 那么我们如何去评 ...
- python 产生随机数,随机字符串
import randomimport string#随机整数:print random.randint(1,50)#随机选取0到100间的偶数:print random.randrange(0, 1 ...
- python之道14
看代码写结果: def wrapper(f): def inner(*args,**kwargs): print(111) ret = f(*args,**kwargs) print(222) ret ...
- VBScript 打开含有"空格"的路径 (Open Path with Space)
记录,VBScript 如何打开,含有"空格"的路径.这个问题和常见,却总是忘! 直接上代码了,多说无益. Option Explicit Dim obj Dim path Set ...
- 初始化一个vue项目
1.安装node 端开发框架和环境都是需要 Node.js ,先安装node.js开发环境,vue的运行是要依赖于node的npm的管理工具来实现,下载https://nodejs.org/en/,安 ...
- Codeforces 杂题集 2.0
记录一些没有写在其他随笔中的 Codeforces 杂题, 以 Problemset 题号排序 1326D2 - Prefix-Suffix Palindrome (Hard version) ...
- [vijos1554&bzoj1411]硬币游戏<快速幂>
题目链接:https://vijos.org/p/1554 http://www.lydsy.com/JudgeOnline/problem.php?id=1411 这题真的淫*QAQ... 一看题还 ...
- [bzoj1191]超级英雄hero<二分图匹配*匈牙利算法>
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1191 今天随便在bzoj找了一题做,题一读完就发现是个匈牙利算法的裸题,原本以为可以一次过 ...