freemarker
1,截取字符串
有的时候我们在页面中不需要显示那么长的字符串,比如新闻标题,这样用下面的例子就可以自定义显示的长度
<lt.<=lte.>gt.>=gte
<#ifjstbqkVO.gzdd?lengthlt8>
<ahref>${jstbqkVO.gzdd?default("")}</a>
<#else>
<ahreftitle="${jstbqkVO.gzdd}">${jstbqkVO.gzdd[0..3]?default("")}...</a>
</#if>
意思就是如果这个字符串的长度小于8,那么就正常显示,反之则取4位
2.连接字符串
${"Hello,"+user+"!"}//输出结果为:hello,gs!
3,日期格式和boolean类型,转化为string类型
例子2:
${lastUpdate?string("yyyy-MM-ddHH:mm:sszzzz")}
${lastUpdate?string("EEE,MMMd,''yy")}
${.................("EEEE,MMMdd,yyyy,hh:mm:ssa'('zzz')'")}
输出结果如下:
2003-04-0821:24:44PacificDaylightTime
Tue,Apr8,'03
Tuesday,April08,2003,09:24:44PM(PDT)
例子3:
<#assignfoo=true/>
${foo?string("yes","no")}//输出结果:yes
4,排序:
1.升序.sort_by()
<#listlist?sort_by("字段")asx>
</#list>
2.降序.sort_by()?reverse
<#listlist?sort_by("字段")?reverseasx>
</#list>
5去空格:
${xx?trim}
6数值精度控制
mX:小数部分最小X位。
MX:小数部分最大X位。
例子:
<#assignx=2.582/>
<#assigny=4/>
#{x;M2}//2.58
#{y;M2}//4
#{x;m1M2}//2.58
#{y;m1M2}//4.0
7特殊字符串的转义
\":双引号\\:反斜杠\r:回车\b:退格键
\':单引号\n:换行\t:Tab\f:Formfeed
\l:<\g:>\a:&\{:{
\xCode:直接通过4位的十六进制数来指定Unicode码
,输出改Unicode对应的字符。
8.顶层变量
*所谓顶层变量就是直接放在数据模型中的值。
Maproot=newHashMap();
root.put("name","yeeku");//name是一个顶层对象
*对于顶层变量,直接使用${variableName}来输出变量值
9.集合连接运算符
*集合连接运算是将两个集合连接成一个新的集合,连接集合的运算符是'+'.
<#list["一","二","三"]+["四","五","六"]asx>
${x}
</#list>
//输出结果如下:
一二三四五六
10算术运算符
*取整运算
<#assignx=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
Horse
14.运算符优先级
*推荐使用括号来决定运算优先级.
1>.一元运算符:!
2>.内建函数:?
3>.乘除法:*,/,%
4>.加减法:+,-
5>.比较:<,>,<=,>=(lt,lte,gt,gte)
6>.相等:==(=),!=
7>.逻辑与:&&
8>.逻辑或:||
9>.数字范围:..
15,freemarker判断返回值是否为空,null的方法
对于null,或者missvalue,freemarker会报错
!:defaultvalueoperator,语法结构为:unsafe_expr!default_expr,比如${mouse!"Nomouse."}当mouse不存在时,返回defaultvalue;
(product.color)!"red"这种方式,能够处理product或者color为missvalue的情况;
而product.color!"red"将只处理color为missvalue的情况
??:Missingvaluetestoperator,测试是否为missingvalue
unsafe_expr??:product.color??将只测试color是否为null
(unsafe_expr)??:(product.color)??将测试product和color是否存在null
?exists:旧版本的用法
比如:<#ifmouse??>
Mousefound
<#else>
Nomousefound
</#if>
Creatingmouse...
<#assignmouse="Jerry">
<#ifmouse??>
Mousefound
<#else>
Nomousefound
</#if>
FreeMarker的常用指令
1>.if指令
<#ifcondifition>
...
<#elseifcondifition>
...
<#else>
...
</#if>
2>.switch、case、default、break指令
<#switchvalue>
<#caserefValue1>
...
<#break>
<#caserefValue2>
...
<#break>
<#default>
...
</#switch>
3>.list、break指令
<#listsequenceasitem>
...
</#list>
*item_index:当前变量的索引值.
*item_has_next:是否存在下一个对象.
例子:
<#list["星期一","星期二","星期三","星期四","星期五","星期六"]asx>
${x_index+1}.${x}
<#ifx_has_next>,</#if>
<#ifx="星期四"><#break></#if>
</#list>
输出结果:
1.星期一,
2.星期二,
3.星期三,
4.兴趣四,
4>.include指令
:用于指定包含指定页面.
<#includefilename[options]>
*filename:该参数指定被包含的模板文件.
*options:该参数可以被省略,指定包含时的选项,包含encoding和parase两个选项.
5>.import指令
<#importpathasmapObject>
*path:指定要被导入的模板文件.
*mapObject:是一个Map对象.
意思:将path路径中的变量都放在mapObject中.
例子:<#import"/lib/common.ftl"ascom>
6>.noparser指令
noparse指令指定FreeMarker不处理该指令里包含的内容.
<#noparse>...</#noparse>
7>.escape指令
*escape:该指令导致body区的插值都会被自动加上escape表达式.
*escape指令解析模板时起作用,而不是在运行时起作用.
*escape指令也嵌套使用,子escape继承父escape的规则.
*如果需要指定某些插值无需添加escape表达式,则应该使用noescape指令.
<#escapeidentifierasexpression>
...
<#noescape>...</#noescape>
...
</#escape>
8>.assign指令
*它用于为该模板页面创建或替换一个(顶层)或多个变量.
第一种用法:<#assignname="value"[innamespacehash]>
in子句用于将创建的name变量放入namespacehash命名空间中.
第二种用法:<#assignname1=value1name2=value2...nameN=valueN[innamespacehash]>
第三种用法:是指将assign指令的内容赋值给name变量.
<#assignname[innamespacehash]>
capturethis
</#assign>
例子:
<#assignx>
<#list["一","二","三"]asn>
${n}
</#list>
</#assign>
${x}
补充.global指令,全局变量赋值
9>.setting指令
:该指令用于设置FreeMarker的运行环境.
<#settingname=value>
name的取值范围如下:
locale:该指令指定该模板所使用的国家语言/语言选项.
number_format:该指令指定格式化输出数字的选项.
boolean_format:该指令指令两个布尔值的语法格式,默认值是"false".
date_format、time_format、datetime_format:格式化输出日期的格式.
time_zone:设置格式化输出日期时所使用的时区.
10>.macro、nested、return指令
宏和变换器变量是两种不同类型的用户自定义指令,他们的区别是:
宏可以在模板中用macro指令来定义
变换器是在模板外由程序定义
1、宏:和某个变量关联的模板片段,以便在模板中通过用户自定义指令使用该变量
1-1、基本用法:
例如:
<#macrogreet>
<fontsize="+2">HelloJOE!</font>
</#macro>
使用时:
<@greet></@greet>
如果没有体内容也可以用
<@greet/>
1-2、变量:
1)、可以在宏定义之后定义参数,宏参数是局部变量,只在宏定义中有效。如:
<#macrogreetperson>
<fontsize="+2">Hello${person}!</font>
</#macro>
使用时:
<@greetperson="emma">and<@greetperson="LEO">
输出为:
<fontsize="+2">Helloemma!</font>
<fontsize="+2">HelloLEO!</font>
注意:宏的参数是FTL表达式,所以,person=emma和上面的例子中具有不同的意义,这意味着将变量emma的值传给person,这个值可能是任意一种数据类型,甚至是一个复杂的表达式。
宏可以有多个参数,使用时参数的次序是无关的,但是只能使用宏中定义的参数,并且对所有参数赋值。如:
<#macrogreetpersoncolor>
<fontsize="+2"color="${color}">Hello${person}!</font>
</#macro>
使用时:
<@greetcolor="black"person="emma"/>正确
<@greetperson="emma"/>错误,color没有赋值,此时,如果在定义宏时为color定义缺省值<#macrogreetpersoncolor="black">这样的话,这个使用方法就是正确的。
<@greetcolor="black"person="emma"bgcolor="yellow"/>错误,宏greet定义中未指定bgcolor这个参数
11>自定义函数的使用
.编写函数
packagecom.freemarker.test;
importjava.text.SimpleDateFormat;
importjava.util.Date;
importjava.util.List;
importfreemarker.template.TemplateMethodModel;
importfreemarker.template.TemplateModelException;
publicclassSqlGetSysdateMethodimplementsTemplateMethodModel
{
publicObjectexec(Listargs)throwsTemplateModelException
{
//得到函数第一个参数,得到的字符串两头会有引号,所以replace
StringdatePattern=(args.get(0).toString()).replace(,);
Datedate=newDate();
SimpleDateFormatsdf=newSimpleDateFormat(datePattern);
returnsdf.format(date);
}
}
2.注册与使用
有两种方式:
(1).在模板文件中注册,在模板中使用
<#assigngetSysdate=packagecom.freemarker.test.SqlGetSysdateMethod?new()>
<#assigncurdate=getSysdate(yyyy-MM-ddt)/>
(2).处理模板文件时注册关键代码:
Map<String,Object>root=newHashMap<String,Object>();
root.put(getSysdate,newStringLengthMethod());
Configurationconfig=newConfiguration();
Filefile=newFile(templatePath);
//并加载模板文件
config.setDirectoryForTemplateLoading(file);
//设置包装器,并将对象包装为数据模型
config.setObjectWrapper(newDefaultObjectWrapper());
//获取模板,并设置编码方式,这个编码必须要与页面中的编码格式一致
Templatetemplate=config.getTemplate(templateName,templateEncoding);
//合并数据模型与模板
template.process(root,out);
12>使用宏写一个简单的分页实例
<#macropaginationtotalCountpageSize>
<#--声明一个函数transform转换uri,在新的uri上pager_offset参数-->
<#assigntransform="util.TransformURI"?new()>
<#--声明一个函数,得到当前页码-->
<#assignpagerOffset="util.PagerOffset"?new()>
<#--声明一个函数,根据传入的totalCount,pageSize得到总页数-->
<#assignpagerCount="util.PageCount"?new()>
<#assignpageCount=pagerCount(totalCount,pageSize)>
<#--得到当前的URI和请求参数,得到当前的页码-->
<#ifrequest.queryString?exists>
<#assignuri=request.requestURI+"?"+request.queryString>
<#assignpageIndex=pagerOffset(uri)>
<#assignnew_uri=transform(uri)>
<#else>
<#assignuri=request.requestURI>
<#assignpageIndex=pagerOffset(uri)>
<#assignnew_uri=transform(uri)>
</#if>
<#if(pageIndex>pageCount)>
<#assignpageIndex=pageCount>
</#if>
<#if(pageIndex>1)>
<ahref="${new_uri+1}"title="首页"><<</a>
</#if>
<#--如果前面页数过多,显示"..."-->
<#if(pageIndex>5)>
<#assignprevPages=pageIndex-9>
<#ifprevPageslt1>
<#assignprevPages=1>
</#if>
<#assignstart=pageIndex-4>
<ahref="${new_uri+prevPages}"title="向前5页">...</a>
<#else>
<#assignstart=1>
</#if>
<#--显示当前页附近的页-->
<#assignend=pageIndex+4>
<#if(end>pageCount)>
<#assignend=pageCount>
</#if>
<#liststart..endasindex>
<#ifpageIndex==index>
<b>${index}</b>
<#else>
<ahref="${new_uri+index}">${index}</a>
</#if>
</#list>
<#--如果后面页数过多,显示"...":-->
<#if(endltpageCount)>
<#assignendend=end+5>
<#if(end>pageCount)>
<#assignend=pageCount>
</#if>
<ahref="${new_uri+end}"title="向后5页">...</a>
</#if>
<#--显示"下一页":-->
<#if(pageIndexltpageCount)>
<ahref="${new_uri+pageCount}"title="末页">>></a>
</#if>
</#macro>
自定义了三个方法:
PageCount.java
packageutil;
importjava.util.List;
importfreemarker.template.TemplateMethodModel;
importfreemarker.template.TemplateModelException;
/**
*根据传入的参数,计算出所有的页数
*@authorlegolas
*/
publicclassPageCountimplementsTemplateMethodModel{
@Override
publicObjectexec(Listargs)throwsTemplateModelException{
IntegertotalCount=0;
IntegerpageSize=0;
try{
totalCount=Integer.parseInt((String)args.get(0));
pageSize=Integer.parseInt((String)args.get(1));
}catch(NumberFormatExceptione){
thrownewTemplateModelException("请输入正确的总记录数和页面记录数");
}
IntegerpageCount=totalCount/pageSize
+(totalCount%pageSize==0?0:1);
returnpageCount;
}
}
TransformURI.java
packageutil;
importjava.util.List;
importfreemarker.template.TemplateMethodModel;
importfreemarker.template.TemplateModelException;
/**
*根据传入的uri,在uri后面加上分页参数
*@authorlegolas
*
*/
publicclassTransformURIimplementsTemplateMethodModel{
@Override
publicObjectexec(Listargs)throwsTemplateModelException{
Stringuri=(String)args.get(0);
intn=uri.lastIndexOf("?");
if(n==-1){
returnuri+"?pager_offset=";
}
if(uri.lastIndexOf("?pager_offset")!=-1){
uri=uri.substring(0,uri.lastIndexOf("=")+1);
returnuri;
}
StringqueryString=uri.substring(n+1,uri.length());
Stringsuburi=uri.substring(0,n+1);
String[]strings=queryString.split("&");
for(inti=0;i<strings.length;i++){
if(strings[i].startsWith("pager_offset")){
continue;
}
suburi+=strings[i];
suburi+="&pager_offset=";
}
returnsuburi;
}
}
PagerOffset.java
packageutil;
importjava.util.List;
importfreemarker.template.TemplateMethodModel;
importfreemarker.template.TemplateModelException;
/**
*得到当前的页码
*@authorlegolas
*
*/
publicclassPagerOffsetimplementsTemplateMethodModel{
@Override
publicObjectexec(Listargs)throwsTemplateModelException{
Stringuri=(String)args.get(0);
String[]string=uri.split("pager_offset=");
if(string.length==1){
return1;
}else{
Integerpager_offset=1;
try{
pager_offset=Integer.parseInt(string[1]);
}catch(NumberFormatExceptione){
pager_offset=1;
}
returnpager_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('ognlexpr')}
action:代表刚刚执行过的Action实例.
response:代表HttpServletResponse实例.
request:代表HttpServletRequest实例.
res:代表HttpServletRequest实例.
session:代表HttpSession实例.
application:代表ServletContext实例.
base:代表用户请求的上下文路径.
9>.访问Servlet/JSp范围对象
1.访问Application范围内的属性.
<#ifApplication.attributeName?exists>
${Application.attributeName}
</#if>
使用struts2标签输出:<@s.propertyvalue="%{Application.attributeName}"/>
2.访问HttpServletRequest中的参数
<#ifParameter.parameter?exists>
${Parameter.parameter}
</#if>