简介:为了方便配置,增强配置,tapestry提供了许多绑定
(binding),如:asset,bean,component,hivemind,listener,literal,message,ognl,
state,translator,validator,validators...
其中最常用的ognl,它表示后面的是ognl表达式。
利用绑定,开发人员可以增强页面/组件规范文件或模板文件中可配置的功能。
问题:现在有一个问题是,ImageSubmit组件需要设置一个属性image,其值必须是IAsset,tapestry本身提供的做法是,在规范文件中设置一个asset,如:
<asset name="help" path="images/help.png"/>
然后,再引用该asset,
<component id="help" type="ImageSubmit">
<binding name="listener" value="listener:helpSubmit"/>
<binding name="image" value="asset:help"/>
</component>
注意:引用时,使用了asset绑定。
这岂不太麻烦了,有没有简化的办法呢?本人经过研究,决定增加一个绑定来搞定这个问题。
改进:增加一个contextasset绑定,在需要asset的地方如下方式使用,
<binding name="image" value="contextasset:/images/help.png"/>
也许这种方法更符合web开发人员的习惯,您说呢?
实现:
1,增加绑定工程类
public class ContextAssetBindingFactory extends AbstractBindingFactory {
public IBinding createBinding(IComponent root,
String bindingDescription, String expression, Location location) {
return new ContextAssetBinding(bindingDescription,getValueConverter(), location,root,expression);
}
}
2,增加绑定类
public class ContextAssetBinding extends AbstractBinding {
private final IComponent _component;
private final String _path;
protected ContextAssetBinding(String description,
ValueConverter valueConverter, Location location,
IComponent component, String path) {
super(description, valueConverter, location);
this._component = component;
this._path = path;
}
public Object getObject() {
Resource rootResource = this._component.getPage().getRequestCycle()
.getInfrastructure().getContextRoot();
String[] paths = _path.split(",");
// only one asset
if (paths.length == 1)
return this.getOneObject(rootResource, _component, _path);
//many assets
ContextAsset[] ca = new ContextAsset[paths.length];
for (int i = 0; i < paths.length; i++) {
ca[i] = null;
}
for (int i = 0; i < paths.length; i++) {
ca[i] = this.getOneObject(rootResource, _component, paths[i]);
}
return ca;
}
private ContextAsset getOneObject(Resource rootResource,
IComponent component, String path) {
Resource resource = rootResource.getRelativeResource(path);
//支持本地化资源,多谢冰太阳的提醒resource=resource.getLocalization(component.getPage().getLocale());
ContextAsset ca = null;
ca = new ContextAsset(component.getPage().getRequestCycle()
.getInfrastructure().getContextPath(), resource,
new LocationImpl(resource));
if (ca == null)
throw new BindingException(BindingMessages.missingAsset(component,
path), component, getLocation(), this, null);
return ca;
}
}
3,增加配置
<!-- add a binding named "ContextAsset Binding"
usage: <binding name="image" value="contextasset:/imgs/login.gif"/>
-->
<service-point id="ContextAssetBindingFactory" interface="org.apache.tapestry.binding.BindingFactory">
<invoke-factory>
<construct class="mycom.binding.ContextAssetBindingFactory">
<set-object property="valueConverter" value="infrastructure:valueConverter"/>
</construct>
</invoke-factory>
</service-point>
<contribution configuration-id="tapestry.bindings.BindingFactories">
<binding prefix="contextasset" service-id="ContextAssetBindingFactory"/>
</contribution>
总结:通过这个简单而实用的绑定类,可以很方便的在组件中引用资源(图片或CSS)了,本绑定类支持多个资源,其中以逗号分隔,从而也可以在Shell组件中使用,如:
<html jwcid="@Shell" stylesheets="contextasset:/css/a.css,/css/b.css" title="test">
您也可以根据这个绑定类,发挥您宝贵的想像力,创造出更实用的绑定,编程岂不快哉?! |