zoukankan      html  css  js  c++  java
  • 自己模拟的ftl 用法:

     基类
    
    public class Ftl_object_data_model  {
         //三种基本属性
         private boolean canRead=true;//是否能读取
         private int length=2;//长度
         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>
     
     
     <#--
     
     注:几个重要的语法规则:
     
     1、FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式化插值:#{expr}或#{expr;format}
     2、??:判断某个变量是否存在,返回boolean值 类似  var?if_exists
     3var!xxx:指定缺失变量的默认值 类似 var?default(xxx) 而 ${!var?c}表明非var,即当var为真时结果求假,!此表非含义
     4、使用lt、lte、gt和gte来替代<、<=、>和>= 也可以使用括号<#if (x>y)>
     5、内置函数: 调用区别于属性的访问,属性访问用.访问,而内置函数用?访问如var?if_exists
     6、注意${}为变量的渲染显示,而<>为定义等操作符的定义
     7、对于库中的变量修改,使用in关键字 <#assign mail="jsmith@other.com" in my>
     8、stringA[M .. N] 取子字符串,类似substring(stringA, M, N)
     9、List片段可以采用: products[10..19] or products[5..] 的格式进行定义,当只局限于数字
         <#assign c= [1,2,3,4,5,6,6,7]>
         <#list c[1..3] as v>
             ${v}
         </#list>
     10、freemarker可用"["代替"<".在模板的文件开头加上[#ftl].
     11、注释语法   <#-- 注释部分 -->
                                                                           <#--  由于杀念11注释语法破坏了整体的注释,所以这边由加了个注释头标签
     12、 数字输出的另外一种方式  #{c.a;m0} 区别于${x},这个例子是用于输出数字的格式化,保留小数的位数,详细如下
             数字格式化插值可采用#{expr;m1M2}形式来格式化数字,其中: m1:小数部分最小1位 M2:小数部分最大2位 即大小m代表不同含义
     13、在定义字符串的时候,可以使用''或者"",对特殊字符,需要使用进行转义
     14、如果存在大量特殊字符,可以使用${r"..."}进行过滤 如  ${r"${foo}"}     ${r"C:fooar"}
     15、Map对象的key和value都是表达式,但是key必须是字符串 可以混合使用.和[""]访问 book.author["name"] //混合使用点语法和方括号语法
     16、为了处理缺失变量,FreeMarker提供了两个运算符: 用于防止对象不存在而导致的异常 !:指定缺失变量的默认值 ??:判断某个变量是否存在,返回boolean值
     17、noparse指令指定FreeMarker不处理该指定里包含的内容,该指令的语法格式如下: <#noparse>...</#noparse>
     18、?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}
     19、<#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的元素。
     20、setting指令,用于动态设置freeMarker的运行环境:
         该指令用于设置FreeMarker的运行环境,该指令的语法格式如下:<#setting name=value>,在这个格式中,name的取值范围包含如下几个:
         locale:该选项指定该模板所用的国家/语言选项
         number_format:指定格式化输出数字的格式
         boolean_format:指定两个布尔值的语法格式,默认值是true,false
         date_format,time_format,datetime_format:指定格式化输出日期的格式
         time_zone:设置格式化输出日期时所使用的时区
     21、<#return> 用于退出宏的运行
     22、调用Java方法:
         如:
         public class A implements TemplateMethodModelEx{
             @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)));
             }
         }
         封装数据模型时用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方法返回值  返回给 模板中表达式处 渲染显示出来。
     
     -->
  • 相关阅读:
    死磕Spring之IoC篇
    死磕Spring之IoC篇
    死磕Spring之IoC篇
    死磕Spring之IoC篇
    Linux解决 -bash: nc: command not found问题
    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/yarn/exceptions/YarnException
    flink配置参数
    Joins in Continuous Queries
    Linux中的tar命令
    Table API&SQL和常见问题总结
  • 原文地址:https://www.cnblogs.com/wzhanke/p/4776240.html
Copyright © 2011-2022 走看看