1,截取字符串
有的时候我们在页面中不需要显示那么长的字符串,比如新闻标题,这样用下面的例子就可以自定义显示的长度
< lt. <= lte. > gt. >= gte
<#if jstbqkVO.gzdd?length lt 8>

           <a href>${jstbqkVO.gzdd?default("")}</a>

      <#else>

           <a href title="${jstbqkVO.gzdd}">${jstbqkVO.gzdd[0..3]?default("")}...</a>

</#if>意思就是如果这个字符串的长度小于8,那么就正常显示,反之则取4位
        
2.连接字符串
                     ${"Hello," + user + "!"} //输出结果为:hello,gs!
                     
3,日期格式和boolean 类型,转化为string类型
                     例子2:
                            ${lastUpdate?string("yyyy-MM-dd HH:mm:ss zzzz")}      
                            ${lastUpdate?string("EEE,MMM d, ''yy")}
                            ${.................("EEEE,MMM dd,yyyy, hh:mm:ss a '('zzz')'")}
                            输出结果如下:
                                   2003-04-08 21:24:44 Pacific Daylight Time
                                   Tue,Apr 8,'03
                                   Tuesday,April 08,2003,09:24:44 PM (PDT)
                     
                     例子3:
                            <#assign foo=true/>
                            ${foo?string("yes","no")}     //输出结果:yes
4,排序:
1.升序.sort_by()
<#list list?sort_by("字段") as x> 

</#list>2.降序.sort_by()?reverse
<#list list?sort_by("字段")?reverse as x>

</#list>5去空格:
${xx?trim}
 
6数值精度控制

                     mX:小数部分最小X位。
                     MX:小数部分最大X位。
                     例子:
                            <#assign x=2.582/>
                            <#assign y=4/>
                            #{x; M2}             //2.58
                            #{y; M2}             //4
                            #{x; m1M2}        //2.58
                            #{y; m1M2}        //4.0
 
7特殊字符串的转义
                     \":双引号    \\:反斜杠     \r:回车         \b:退格键
                     \':单引号     \n:换行        \t:Tab           \f:Form feed
                     \l:<         \g:>        \a:&              \{:{
           \xCode:直接通过4位的十六进制数来指定Unicode码
,输出改Unicode对应的字符。
                     
8.顶层变量
                     * 所谓顶层变量就是直接放在数据模型中的值。
                            Map root = new HashMap();
                            root.put("name","yeeku");  //name是一个顶层对象
                     * 对于顶层变量,直接使用${variableName}来输出变量值
              
9.集合连接运算符
* 集合连接运算是将两个集合连接成一个新的集合,连接集合的运算符是'+'.
                            <#list ["一","二","三"] + ["四","五","六"] as x>
                                   ${x}
                            </#list>
                     //输出结果如下:
                                   一二三四五六
10 算术运算符
                     * 取整运算
                            <#assign x=5>
                            ${(x/2)?>int}       //2
                            ${1.1?int}            //1
                            ${1.999?int} //1
                            ${-1.1?int}          //-1
11 比较运算符
                         =(==)     :判断两个值是否相等
                            !=           :............不相等
                            >(gt)      :判断左边是否大于右边
                            >=(gte)  :.....
                            <(lt)       :.....
                            <=(lte)    :.....
12 逻辑运算符
                        * 逻辑运算符只能作用于布尔值,否则将产生错误.
                            逻辑与:&&
                            逻辑或:||
                            逻辑非:!

13  内置函数
html:字符串中所有的特殊HTML字符都需要用实体引用来代替(比如<代替<)

 cap_first:字符串的第一个字母变为大写形式

lower_case:字符串的小写形式

upper_case:字符串的大写形式

trim:去掉字符串首尾的空格序列使用的内建函数:

size:序列中元素的个数

 数字使用的内建函数:

int:数字的整数部分(比如-1.9?int就是-1)9>.空值运算符length:字符串的长度
string :把其他格式的数据,转化为string类型
例:
${test?html}

${test?upper_case?html}假设字符串test存储”Tom & Jerry”,那么输出为:
Tom & Jerry

TOM & JERRY${seasons?size}

${seasons[1]?cap_first} ${"horse"?cap_first}
假设seasons存储了序列"winter", "spring", "summer", "autumn",那么上面的输出将会是:
4

Spring

Horse14.运算符优先级
                     * 推荐使用括号来决定运算优先级.
                            1>.一元运算符: !
                            2>.内建函数  : ?
                            3>.乘除法    : *,/,%
                            4>.加减法    : +,-
                            5>.比较              : <,>,<=,>=(lt,lte,gt,gte)
                            6>.相等              : ==(=),!=
                            7>.逻辑与   : &&
                            8>.逻辑或   : ||
                            9>.数字范围      : ..
       
15,freemarker判断返回值是否为空,null的方法
对于null,或者miss value,freemarker会报错

!:default value operator,语法结构为:unsafe_expr!default_expr,比如 ${mouse!"No mouse."} 当mouse不存在时,返回default value;

(product.color)!"red"   这种方式,能够处理product或者color为miss value的情况; 

而product.color!"red"将只处理color为miss value的情况 

??: Missing value test operator ,测试是否为missing value 

unsafe_expr?? :product.color??将只测试color是否为null 

(unsafe_expr)??:(product.color)??将测试product和color是否存在null 

?exists:旧版本的用法 

比如:<#if mouse??>

   Mouse found

<#else>

   No mouse found

</#if>

Creating mouse...

<#assign mouse = "Jerry">

<#if mouse??>

   Mouse found

<#else>

   No mouse found

</#if>FreeMarker的常用指令
1>.if指令
                     <#if condifition>
                            ...
                     <#elseif condifition>
                            ...
                     <#else>
                            ...
                     </#if>
2>.switch、case、default、break指令
                     <#switch value>
                            <#case refValue1>
                                   ...
                            <#break>
                            <#case refValue2>
                                   ...
                            <#break>
                            <#default>
                                   ...
                     </#switch>
3>.list、break指令
                     <#list sequence as item>
                            ...
                     </#list>
                     * item_index  :当前变量的索引值.
                     * item_has_next    :是否存在下一个对象.
                     例子:
                      <#list ["星期一","星期二","星期三","星期四","星期五","星期六"] as x>
                                   ${x_index + 1}.${x}
                                   <#if x_has_next>,</#if>
                                   <#if x="星期四"><#break></#if>
                            </#list>
                            输出结果:
                                   1.星期一,
                                   2.星期二,
                                   3.星期三,
                                   4.兴趣四,
4>.include指令      
:用于指定包含指定页面.
                     <#include filename [options]>
                     * filename:     该参数指定被包含的模板文件.
                     * options :      该参数可以被省略,指定包含时的选项,包含encoding和parase两个选项.   
5>.import指令
                     <#import path as mapObject>
                            * path            :指定要被导入的模板文件.
                            * mapObject   :是一个Map对象.
                            意思:将path路径中的变量都放在mapObject中.
                            例子:<#import "/lib/common.ftl" as com>
6>.noparser指令
                     noparse指令指定FreeMarker不处理该指令里包含的内容.
                     <#noparse>...</#noparse>
7>.escape指令
                     * escape:该指令导致body区的插值都会被自动加上escape表达式.
                     * escape指令解析模板时起作用,而不是在运行时起作用.
                     * escape指令也嵌套使用,子escape继承父escape的规则.
                     * 如果需要指定某些插值无需添加escape表达式,则应该使用noescape指令.
                     <#escape identifier as expression>
                            ...
                            <#noescape>...</#noescape>
                            ...
                     </#escape>
8>.assign指令
                     * 它用于为该模板页面创建或替换一个(顶层)或多个变量.
                     第一种用法:<#assign name="value" [in namespacehash]>
                            in子句用于将创建的name变量放入namespacehash命名空间中.
                     第二种用法:<#assign name1=value1 name2=value2 ... nameN=valueN [in namespacehash]>
                     第三种用法:   是指将assign指令的内容赋值给name变量.
                                          <#assign name [in namespacehash]>
                                                 capture this
                                          </#assign>
                                   例子:
                                   <#assign x>
                                          <#list ["一","二","三"] as n>
                                                 ${n}
                                          </#list>
                                   </#assign>
                                   ${x}
              补充.global指令,全局变量赋值
 
9>.setting指令 
:该指令用于设置FreeMarker的运行环境.
                     <#setting name=value>
                     name的取值范围如下:
                            locale:该指令指定该模板所使用的国家语言/语言选项.
                            number_format:该指令指定格式化输出数字的选项.
                            boolean_format:该指令指令两个布尔值的语法格式,默认值是"false".
                            date_format、time_format、datetime_format:格式化输出日期的格式.
                            time_zone: 设置格式化输出日期时所使用的时区.
10>.macro、nested、return指令
宏和变换器变量是两种不同类型的用户自定义指令,他们的区别是:


宏可以在模板中用macro指令来定义

变换器是在模板外由程序定义


1、宏:和某个变量关联的模板片段,以便在模板中通过用户自定义指令使用该变量

1-1、基本用法:

例如:

<#macro greet>

<font size="+2"> Hello JOE!</font>

</#macro>



使用时:

<@greet></@greet>

如果没有体内容也可以用

<@greet />


1-2、变量:


1)、可以在宏定义之后定义参数,宏参数是局部变量,只在宏定义中有效。如:


<#macro greet person>

<font size="+2"> Hello ${person}!</font>

</#macro>

使用时:

<@greet person="emma"> and <@greet person="LEO">

输出为:

<font size="+2"> Hello emma!</font>

<font size="+2"> Hello LEO!</font>


注意:宏的参数是FTL表达式,所以,person=emma和上面的例子中具有不同的意义,这意味着将变量emma的值传给person,这个值可能是任意一种数据类型,甚至是一个复杂的表达式。


宏可以有多个参数,使用时参数的次序是无关的,但是只能使用宏中定义的参数,并且对所有参数赋值。如:

<#macro greet person color>

<font size="+2" color="${color}"> Hello ${person}!</font>

</#macro>


使用时:

<@greet color="black" person="emma" />正确

<@greet person="emma" />错误,color没有赋值,此时,如果在定义宏时为color定义缺省值<#macro greet person color="black">这样的话,这个使用方法就是正确的。

<@greet color="black" person="emma" bgcolor="yellow" />错误,宏greet定义中未指定bgcolor这个参数11>自定义函数的使用
              . 编写函数
 
package com.freemarker.test;
 
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import java.util.List;
  import freemarker.template.TemplateMethodModel;
  import freemarker.template.TemplateModelException;
 
  
 public class SqlGetSysdateMethod implements TemplateMethodModel
 {
 
     
     public Object exec( List args ) throws TemplateModelException
     {
                 //得到函数第一个参数,得到的字符串两头会有引号,所以replace
         String datePattern=(args.get( 0 ).toString()).replace( ,  );
         
         Date date = new Date();
         SimpleDateFormat sdf =new SimpleDateFormat(datePattern);
         
         return sdf.format( date );
     }

 } 
    2.注册与使用
        有两种方式:
      (1).在模板文件中注册,在模板中使用
<#assign getSysdate= package com.freemarker.test.SqlGetSysdateMethod?new()>
<#assign curdate= getSysdate(yyyy-MM-ddt)/>

(2).处理模板文件时注册关键代码:


Map<String,Object> root=new HashMap<String, Object>();  

root.put(getSysdate, new StringLengthMethod());

Configuration config=new Configuration();  

            File file=new File(templatePath);  

            //并加载模板文件  

            config.setDirectoryForTemplateLoading(file);  

            //设置包装器,并将对象包装为数据模型  

            config.setObjectWrapper(new DefaultObjectWrapper());  

              

            //获取模板,并设置编码方式,这个编码必须要与页面中的编码格式一致  

            Template     template=config.getTemplate(templateName,templateEncoding); 

            //合并数据模型与模板  

            template.process(root, out);<#macro pagination totalCount pageSize>  
<#--声明一个函数transform 转换uri,在新的uri上pager_offset参数  -->  
    <#assign transform = "util.TransformURI"?new()>  
    <#--声明一个函数,得到当前页码-->  
    <#assign pagerOffset = "util.PagerOffset"?new()>  
    <#--声明一个函数,根据传入的totalCount,pageSize得到总页数-->  
    <#assign pagerCount = "util.PageCount"?new()>  
    <#assign pageCount=pagerCount(totalCount,pageSize)>  
    <#--得到当前的URI和请求参数,得到当前的页码-->  
    <#if request.queryString?exists>  
        <#assign uri=request.requestURI+"?"+request.queryString>  
        <#assign pageIndex=pagerOffset(uri)>  
        <#assign new_uri=transform(uri)>  
    <#else>  
        <#assign uri=request.requestURI>  
        <#assign pageIndex=pagerOffset(uri)>  
        <#assign new_uri=transform(uri)>  
    </#if>  
    <#if (pageIndex>pageCount)>  
        <#assign pageIndex=pageCount>  
    </#if>  
    <#if (pageIndex>1)>  
        <a href="${new_uri+1}" title="首页"><<</a>  
    </#if>  
    <#--如果前面页数过多,显示"..."-->  
    <#if (pageIndex>5)>  
        <#assign prevPages=pageIndex-9>  
        <#if prevPages lt 1>  
            <#assign prevPages=1>  
        </#if>  
        <#assign start=pageIndex-4>  
        <a href="${new_uri+prevPages}" title="向前5页">...</a>  
    <#else>  
        <#assign start=1>  
     </#if>  
    <#-- 显示当前页附近的页-->  
    <#assign end=pageIndex+4>  
    <#if (end>pageCount)>  
        <#assign end=pageCount>  
    </#if>  
    <#list start..end as index>  
        <#if pageIndex==index>  
            <b>${index}</b>  
        <#else>  
            <a href="${new_uri+index}">${index}</a>  
        </#if>  
    </#list>  
    <#--如果后面页数过多,显示"...":-->  
    <#if (end lt pageCount)>  
        <#assign endend=end+5>  
        <#if (end>pageCount)>  
            <#assign end=pageCount>  
        </#if>  
        <a href="${new_uri+end}" title="向后5页">...</a>  
    </#if>  
    <#-- 显示"下一页":-->  
    <#if (pageIndex lt pageCount)>  
        <a href="${new_uri+pageCount}" title="末页">>></a>  
    </#if>  
</#macro>  
自定义了三个方法:
PageCount.Java
package util;   
import java.util.List;   
import freemarker.template.TemplateMethodModel;   
import freemarker.template.TemplateModelException;   
/**  
 * 根据传入的参数,计算出所有的页数  
 * @author legolas  
 */  
public class PageCount implements TemplateMethodModel {
    @Override  
    public Object exec(List args) throws TemplateModelException {
        Integer totalCount = 0;   
        Integer pageSize = 0;   
        try {   
            totalCount = Integer.parseInt((String) args.get(0));  
            pageSize = Integer.parseInt((String) args.get(1));   
        } catch (NumberFormatException e) {   
    throw new TemplateModelException("请输入正确的总记录数和页面记录数");   
        }   
        Integer pageCount = totalCount / pageSize   
          + (totalCount % pageSize == 0 ? 0 : 1);   
        return pageCount;   
    }   
}  
TransformURI.java
 package util;   
import java.util.List;   
import freemarker.template.TemplateMethodModel;   
import freemarker.template.TemplateModelException;   
/**  
 * 根据传入的uri,在uri后面加上分页参数  
 * @author legolas  
 *  
 */  
public class TransformURI implements TemplateMethodModel{   
    @Override  
    public Object exec(List args) throws TemplateModelException {
        String uri = (String) args.get(0);   
        int n = uri.lastIndexOf("?");   
        if (n == -1) {   
            return uri + "?pager_offset=";   
        }   
        if (uri.lastIndexOf("?pager_offset") != -1) {   
            uri = uri.substring(0, uri.lastIndexOf("=") + 1);   
            return uri;   
        }   
        String queryString = uri.substring(n + 1, uri.length());  
        String suburi = uri.substring(0, n + 1);   
        String[] strings = queryString.split("&");   
        for (int i = 0; i < strings.length; i++) {   
            if (strings[i].startsWith("pager_offset")) {   
                continue;   
            }   
            suburi += strings[i];   
            suburi += "&pager_offset=";   
        }  
        return suburi;   
    }
}
PagerOffset.java
package util;   
  
import java.util.List;   
import freemarker.template.TemplateMethodModel;   
import freemarker.template.TemplateModelException;   
/**  
 * 得到当前的页码  
 * @author legolas  
 *  
 */  
public class PagerOffset implements TemplateMethodModel {   
    @Override  
    public Object exec(List args) throws TemplateModelException {  
        String uri = (String) args.get(0);   
        String[] string = uri.split("pager_offset=");   
        if (string.length == 1) {   
            return 1;   
        } else {   
            Integer pager_offset = 1;   
            try {   
                pager_offset = Integer.parseInt(string[1]);   
            } catch (NumberFormatException e) {   
                pager_offset = 1;   
            }   
            return pager_offset;   
        }   
    }   
}  

 
7>.关于在FreeMarker中使用Struts2标签
              * FreeMarker作为视图组件是由Servlet负责加载该模板,并使用数据模型填充该模板,并且将填充后
                     的标准HTML响应输出给浏览者.
              * 在Struts2框架的支持下,Struts2框架充当了之前的Servlet角色.
              * 为了使所有的用户请求都经过Struts2框架处理,我们将所有的FreeMarker模板放在WEB-INF/ftl路径下.
              * 放在WEB-INF/路径下可以提供更好的安全性,因为Web容器会保证浏览者无法访问到WEB-INF/路径下的资源.       
       
8>.解析模板中的变量
* Struts2解析FreeMarker模板中变量的顺序如下:
                     1>.FreeMarker模板内建的变量
                     2>.ValueStack中的变量.
                     3>.ActionContext中的变量.
                     4>.HttpServletRequest范围的属性.
                     5>.HttpSession范围的属性.
                     6>.ServletContext范围的属性.
* FreeMarker模板的内建变量如下:
                     stack:代表ValueStack本身,可这样访问其中变量:${stack.findString('ognl expr')}
                     action:代表刚刚执行过的Action实例.
                     response:代表HttpServletResponse实例.
                     request:代表HttpServletRequest实例.
                     res:代表HttpServletRequest实例.
                     session:代表HttpSession实例.
                     application:代表ServletContext实例.
                     base:代表用户请求的上下文路径.
9>.访问Servlet/JSp范围对象
1.访问Application范围内的属性.
                     <#if Application.attributeName?exists>
                            ${Application.attributeName}
                     </#if>
                     使用struts2标签输出:<@s.property value="%{Application.attributeName}"/>
2.访问HttpServletRequest中的参数
                     <#if Parameter.parameter?exists>
                            ${Parameter.parameter}
                     </#if>