5.4.1 内置扩展#
Java扩展为在视图层的模版中调用对象提供了更加便捷的方式,并让表达式可以表示更多的内容。接下来是Play中Java扩展的例子,每个例子的运行结果紧跟在代码之后。
集合扩展#
join(separator)
使用给定的分隔符连接集合中的条目。返回类型:String。
${['red', 'green', 'blue'].join('/')}
运行结果:
red/green/blue
pluralize()
当集合的数量不为1的时候,返回字符串+“s”(即英语中的复数表示)。返回值:String。
colour${['red', 'green', 'blue'].pluralize()}
运行结果:
colours
pluralize(plural)
当集合的数量不为1的时候,该扩展方法将返回一个给定字符,用于展现复数形式。返回值:String。
box${['red', 'green', 'blue'].pluralize('es')}
运行结果:
boxes
journ(singular, plural)
当集合的数量为1的时候,该扩展方法将返回一个给定字符,用于展现单数形式,当数量不为1的时候,该扩展方法将返回一个给定字符,用于展现复数形式。返回值:String。
journ${['red'].pluralize('al', 'aux')}
运行结果:
journal
journ${['red', 'green', 'blue'].pluralize('al', 'aux')}
运行结果:
journaux
日期扩展#
format(format)
根据给定的日期格式化字符串,并返回格式化后的日期。返回:String。
${new Date(1275910970000).format('dd MMMM yyyy hh:mm:ss')}
运行结果:
07 June 2010 01:42:50
format(format, language)
同上个扩展类似,不过用language来指定了日期所采用的国际化语言。返回:String。
${new Date(1275910970000).format('dd MMMM yyyy hh:mm:ss', 'fr')}
运行结果:
07 juin 2010 01:42:50
since()
将日期格式化为一个相对的时间,相对现在的时刻,比如3分钟之前。返回:String。
${new Date(new Date().getTime() - 1000000).since()}
运行结果:
16 minutes ago
利用下面的消息可以自定义输出相对时间的形式:since.seconds,since.minutes,since.hours,since.days,since.months和since.years。
since(condition)
同样是格式化日期为相对现在的某个相对时间。如果给定的condition为true,则当日期是在一个月之前的话会格式化为一个日期;如果给定的condition为false,效果与since()相同。
同样也可以使用与since()相同的消息来自定义输出的相对时间的形式,也可以使用since.format的方式自定义一个月之前的日期的输出形式。
${new Date(1262350000000).since(false)}
运行结果:
5 months ago
${new Date(1262350000000).since(true)}
运行结果:
Jan 1, 2010
长整型扩展#
asdate(format)
将时间戳格式化为日期。返回:String。
${1275910970000.asdate('dd MMMM yyyy hh:mm:ss')}
运行结果:
07 June 2010 01:42:50
asdate(format, language)
使用给定的语言将时间戳格式化为日期。返回:String。
${1275910970000.asdate('dd MMMM yyyy hh:mm:ss', 'fr')}
运行结果:
07 juin 2010 01:42:50
formatSize()
将字节数格式化为文件大小。
${726016L.formatSize()}
运行结果:
709KB
Map 扩展#
asAttr()
将map中的key和value格式化为HTML中的属性。返回值:play.templates.Template.ExecutableTemplate.RawData。
${[id:'42', color:'red'].asAttr()}
运行结果:
id="42" color="red"
asAttr(condition)
当condition为true时,将map中的key和value格式化为HTML中的属性。返回值:play.templates.Template.ExecutableTemplate.RawData。
${[id:'42', color:'red'].asAttr(true)}
运行结果
id="42" color="red"
数字扩展#
divisibleBy(divisor)
返回数字是否可以被给定的除数整除。返回值:boolean。
${42.divisibleBy(7)}
运行结果:
true
format(format)
将数字用指定的数字格式化字符串进行格式化。返回值:String。
${42.format('000.00')}
运行结果:
042.00
formatCurrency(currencyCode)
将数字根据给定的货币代码格式化为货币表现形式,货币代码EUR表示欧元。返回值: String。
${42.formatCurrency('EUR').raw()}
运行结果:
€ 42.00
page(pageSize)
通过给定的分页大小返回页数。返回值:Integer。
${42.page(10)}
运行结果:
5
对象扩展#
addSlashes()
为字符串中的单引号或双引号添加转义符。返回值:String。
${"single quote (')".addSlashes().raw()} ${'double quote (")'.addSlashes().raw()}
运行结果:
single quote (\') double quote (\")
capAll()
将字符串中每个单词的首字母变为大写。
${"lorum ipsum dolor".capAll()}
运行结果:
Lorum Ipsum Dolor
capFirst()
将字符串中第一个单词的首字母变为大写。
${"lorum ipsum dolor".capFirst()}
运行结果:
Lorum ipsum dolor
cut(substring)
从对象中删除给定的子字符串,返回删除后的字符串。返回值:String。
${"lorum ipsum dolor".cut('um')}
运行结果:
lor ips dolor
escape()
将对象中的字符串中的HTML字符变为带转义符的形式。返回值:String。
${"The <blink>tag</blink> is evil".escape().raw()}
运行结果:
The <blink>tag</blink> is evil
nl2br()
将‘\n’替换为HTML <br /> 标签。返回值:String。
${"one\ntwo".nl2br()}
运行结果:
one<br/>two
raw()
直接返回对象的内容,跳过模板转义处理。返回值:play.templates.Template.ExecutableTemplate.RawData。
${'<'}
运行结果:
<
${'<'.raw()}
运行结果:
<
raw(condition)
当给定的condtion为true时,直接返回对象的内容,而不经模板转义处理。返回值:play.templates.Template.ExecutableTemplate.RawData。
${'<'.raw(true)}
运行结果:
<
yesNo('yes', 'no')
如果对象为真,就返回第一个参数('yes'),反之返回第二个参数('no')。返回值:Sring。
${"".yesno('yes', 'no')}
运行结果:
no
${"not empty".yesno('yes', 'no')}
运行结果:
yes
字符串扩展#
asXml()
解析给定的XML字符串。返回值:groovy.util.slurpersupport.GPathResult。
camelCase()
将字符串格式化为camel形式(即骆驼命名法),类似于Java推荐的类命名形式。返回值:String。
${"lorum ipsum dolor".camelCase()}
运行结果:
LorumIpsumDolor
capitalizeWords()
将字符串中每个单词的首字母变为大写。返回值:String。
${"lorum ipsum dolor".capitalizeWords()}
运行结果:
Lorum Ipsum Dolor
escapeHtml()
将字符串中的HTML字符变为带转义符的形式。返回值:String。
${"The <blink>tag</blink> is evil".escape().raw()}
运行结果:
The <blink>tag</blink> is evil
escapeJavaScript()
将字符串中出现的JavaScript字符替换为转义符的形式。返回值:String。
${"single quote (') double quote (\")".escapeJavaScript().raw()}
运行结果:
single quote (\') double quote (\")
escapeXml()
将字符串中的XML字符变为带转义符的形式。返回值:String。
${"<>\"&".escape().raw()}
运行结果:
<>"&
last()
返回列表中的最后一项。返回值:Object。
${['red', 'green', 'blue'].last()}
运行结果:
Blue
noAccents()
将字符串中带有重音符号的字母替换为不带重音符号的字母。返回值:String。
${"Stéphane Épardaud".noAccents()}
运行结果:
Stephane Epardaud
pad(length)
在字符串后增加给定length长度的 (HTML空格转义符)字符。返回值:String。
${"x".pad(4).raw()}${"x"}
运行结果:
x x
slugify()
将字符串格式化为用“-”连接字符串中的每个单词,并将原有的标点符号去除。主要用于生成URL,避免与URL的保留字符冲突。
${"The Play! framework’s manual".slugify()}
运行结果:
the-play-framework-s-manual
urlEncode()
将URL查询字符串中的字符变为转义输出的形式。返回值:String。
${"!@#\$%^&()".urlEncode()}
运行结果:
%21%40%23%24%25%5E%26%28%29
字符串数组扩展#
add(value)
在数组末尾增加数据。返回值:String[]。
${(["red", "green", "blue"] as String[]).add('pink').join(' ')}
运行结果:
red green blue pink
contains(string)
如果数组中存在给定的字符串,返回true,反之返回false。返回值:boolean。
${(['red', 'green', 'blue'] as String[]).contains('green')}
运行结果:
True
remove(string)
在数组中删除给定的字符串,并返回删除后的字符串数组。返回值:String[]。
${(['red', 'green', 'blue'] as String[]).remove('green').join(' ')}
运行结果:
red blue
5.4.2 自定义扩展#
我们也可以在Java代码中自定义标签,封装一些更为复杂的功能。如果读者希望自定义Java标签,需要先创建继承于play.templates.FastTags的类。
package utils; public class MyFastTag extends FastTags { ... }
每个我们想要作为标签(tag)运行的方法都具有固定的声明方式,具体如下:
public static void _tagName(Map<?, ?> args, Closure body, PrintWriter out, ExecutableTemplate template, int fromLine)
注意:
别漏了标签名前面的下划线。
为了进一步了解如何创建标签,我们先来看看两个Play内置标签的例子(这两个标签已经被Play封装,在play/framework/src/play/templates/FastTags.java文件中可以查看)。
#{verbatim}标签只是简单的调用了从JavaExtensions传递过来的toString()方法,直接在模板上打印了标签体中的内容:
public static void _verbatim(Map<?, ?> args, Closure body, PrintWriter out, ExecutableTemplate template, int fromLine) { out.println(JavaExtensions.toString(body)); }
该标签的具体使用方法如下,从标签的开始到结束都是标签体内容:
#{verbatim}My verbatim #{/verbatim}
模板中将会打印出标签体内容:
My verbatim
第二个Play内置标签例子是#{option},它要稍微复杂一点,因为它的实现依赖于父标签#{select}(Play也封装了#{select}标签,在play/framework/templates/tags/select.tag文件中可以查看具体定义)。
public static void _option(Map<?, ?> args, Closure body, PrintWriter out, ExecutableTemplate template, int fromLine) { Object value = args.get("arg"); Object selection = TagContext.parent("select").data.get("selected"); boolean selected = selection != null && value != null && selection.equals(value); out.print("<option value=\"" + (value == null ? "" : value) + "\" " + (selected ? "selected=\"selected\"" : "") + "" + serialize(args, "selected", "value") + ">"); out.println(JavaExtensions.toString(body)); out.print("</option>"); }
该Java标签的原理是封装了HTML的<option>标签,用于实现下拉列表实例,并且从父标签#{select}中获取被默认选中(selected)的值。方法体最开始的三行用于设定输出的变量,最后的三行则输出了标签的结果。该标签的具体使用方法如下:
#{select name:"country",value:"中国"} #{option arg:"英国"}英国#{/option} #{option arg:"中国"}中国#{/option} #{option arg:"美国"}美国#{/option} #{option arg:"日本"}日本#{/option} #{/select}
这里需要对父标签#{select}的使用做一些简单说明:country是#{select}标签的name属性,是必选的;中国是#{select}标签的value属性,用于标识selected元素,是可选的。
标签的命名空间 实际项目中可能会自定义大量的标签,标签命名不规范可能会造成一些不必要的麻烦(比如与已定义的标签重名,或是与Play框架的核心标签冲突)。为了解决这个问题,Play可以使用@FastTags.Namespace注解来设定命名空间。对于my.tags命名空间中的#{hello}标签我们需要做以下工作:
@FastTags.Namespace("my.tags") public class MyFastTag extends FastTags { public static void _hello (Map<?, ?> args, Closure body, PrintWriter out, ExecutableTemplate template, int fromLine) { ... } }
然后在模板中可以通过以下方式来调用#{hello}标签:
#{my.tags.hello/}