`

【zk开发】zk注解的秘密

    博客分类:
  • ZK
阅读更多

 

 

The DataBinder that reads ZUML annotations to create binding info.

You have two ways to annotate ZK components. For ZK data binding, you can use @{...} annotaion expression or <a:bind> annotation expression.

To use <a:bind> annotation expression, in the ZUML page you must declare the XML namespace,xmlns:a="http://www.zkoss.org/2005/zk/annotation" first. Then declare <a:bind> before component to make the annotation.

We suggest annotating directly on the component property with intuitive @{...} expression because it is more readable.(我们建议直接在组件属性中使用注解指令,因为这样可读性更强)

For example, the following annotation associates the attribute "value" of the component "textbox" to the bean's value "person.address.city".

@{...} way:

 <textbox value="@{person.address.city}"/>
 

The @{...} pattern tells the ZUML parser that this is for annotation.

<a:bind> way:

 <a:bind value="person.address.city"/>
 <textbox/>
 

You can put more metainfo inside the @{...} or <a:bind> so this DataBinder knows what to do. The complete format is like this:

@{...} way:

 <componentX attrY="@{bean's value,[tag='expression']...}"/>
 

<a:bind> way:

 <a:bind attrY="bean's value;[tag:expression]..."/>
 <componentX/>
 

This associates the componentX's attribute attrY to the bean's value. The bean's value is something in the form of beanid.field1.field2... You can either call DataBinder.bindBean(java.lang.String, java.lang.Object) to bind the beanid to a real bean object or you can neglect it and this DataBinder would try to find it from the variables map via Page.getZScriptVariable(java.lang.String) thenComponent.getVariable(java.lang.String, boolean) method. That is, all those variables defined in zscript are also accessible by this DataBinder. Note that you can choose either two formats of annotations as your will and you can even hybrid them together though it is not generally a good practice.

The tag='expression' or tag:expression is a generic form to bind more metainfo to the attrY of the componentX. The currently supported tags includes "load-when", "save-when", "access", "converter", "load-after"(since 3.6.1), and "save-after"(since 3.6.1).

  • load-when. You can specify the events concerned when to load the attribute of the component from the bean. Multiple definition is allowed and would be called one by one. Note that binding is executed BEFORE other event listeners you defined. (If you want the loading to be executed AFTER your event listener, use load-after). For example, the following code snip tells DataBinder that the attribute "value" of Label "fullName" will load from "person.fullName" when the Textbox "firstName" or "lastName" fire "onChange" event.

    The @{...} way that specify directly on the Component's attribute:

       注意第三个组件示例中load-when发生的时机:compId.onEventNameXXXX

     <textbox id="firstname" value="@{person.firstName}"/>
     <textbox id="lastname" value="@{person.lastName}"/>
     <label id="fullname" value="@{person.fullName, load-when='firstname.onChange,lastname.onChange'}"/>
     

    Or the <a:bind> way that declare in front of the Component:

     <a:bind value="person.firstName"/>
     <textbox id="firstname"/>
    
     <a:bind value="person.lastName"/>
     <textbox id="lastname"/>
    
     <a:bind value="person.fullName; load-when:firstname.onChange; load-when:lastname.onChange"/>
     <label id="fullname"/>
     
  • (Since 3.6.1) load-after. Similar to load-when. You can specify the events concerned when to load the attribute of the component from the bean. The only difference is that the loading is done AFTER other event listeners listening to the same event are processed; while in load-when the loading is done BEFORE other event listeners listening to the same event are processed.
  • save-when. You can specify the events concerned when to save the attribute of the component into the bean. Since ZK version 3.0.0, you can specify multiple events in save-when tag (i.e. before ZK 3.0.0, you can specify only one event). The events specified, if fired, will trigger this DataBinder to save the attribute of the component into the specified bean. Note that binding is executed BEFORE other event listeners you defined. (If you want the saving to be executed AFTER your event listener, use save-after). For example, the following code snip tells DataBinder that the property "value" of Textbox "firstName" will save into "person.firstName" when the Textbox itself fire "onChange" event.

    The @{...} way that specify directly on the Component's attribute:

     <textbox id="firstName" value="@{person.firstName, save-when='self.onChange'}"/>
     

    Or the <a:bind> way that declare in front of the Component:

     <a:bind value="person.firstName; save-when:self.onChange"/>
     <textbox id="firstName"/>
     

    However, you don't generally specify the save-when tag. If you don't specify it, the default events are used depends on the natural characteristic of the component's property as defined in lang-addon.xml. For example, the save-when of Label.value is default to "none" while that of Textbox.value is default to "self.onChange". That is, the following example is the same as the above one.

    The @{...} way that specify directly on the Component's attribute:

     <textbox id="firstName" value="@{person.firstName}"/>
     

    Or the <a:bind> way that declare in front of the Component:

     <a:bind value="person.firstName"/>
     <textbox id="firstName"/>
     

    On the other hand, you might not specify the save-when tag nor you want the default events to be used. Then you can specify a "none" keyword or simply leave empty to indicate such cases.

      以下配置情况采用默认事件触发

     <textbox id="firstName" value="@{person.firstName, save-when='none'}"/>
     
    or
     <textbox id="firstName" value="@{person.firstName, save-when=''}"/>
     
    or
     <a:bind value="person.firstName; save-when:none;"/>
     <textbox id="firstName"/>
     
    or
     <a:bind value="person.firstName; save-when: ;"/>
     <textbox id="firstName"/>
     
  • (Since 3.6.1) save-after. Similar to save-when. You can specify the events concerned when to save the attribute of the component to the bean. The only difference is that the saving is doneAFTER other event listeners listening to the same event are processed; while in save-when the saving is done BEFORE other event listeners listening to the same event are processed.
  • access. You can set the access mode of the attrY of the componentX to be "both"(load/save), "load"(load Only), "save"(save Only), or "none"(neither). save允许修改bean值,load仅访问属性值,both具有save/load二者功能 Multiple definition is NOT allowed and the later defined would override the previous defined one. The access mode would affects the behavior of the DataBinder's loadXxx and saveXxx methods. The DataBinder.loadAll() andDataBinder.loadComponent(org.zkoss.zk.ui.Component) would load only those attributes with "both" or "load" access mode. The DataBinder.saveAll() andDataBinder.saveComponent(org.zkoss.zk.ui.Component) would save only those attributes with "both" or "save" access mode. If you don't specify it, the default access mode depends on the natural characteristic of the component's attribute as defined in lang-addon.xml. For example, Label.value is default to "load" access mode while Textbox.value is default to "both" access mode. For example, the following code snips tells DataBinder that Textbox "firstName" would allowing doing save into bean only not the other way.

    The @{...} way that specify directly on the Component's attribute:

     <textbox id="firstName" value="@{person.firstName, access='save'}"/>
     

    Or the <a:bind> way that declare in front of the Component:

     <a:bind value="person.firstName;access:save;"/>
     <textbox id="firstName"/>
     
  • converter. 可以指定实现TypeConverter接口的converter类名字,它将负责组件属性和bean属性之间的互相转换.converter不允许配置多个,如果定义多个那么后一个将覆盖前一个。大多说情况下你无需指定它,因为DataBinder支持大多说通常使用的类型,然后如果你指定TypeConverter类名,那么DataBinder实例化这个转换器,替代默认转换器转换

(Since 3.1)如果你指定了其他的非特定的标签,那么他们将被放入map参数中,作为组件属性(key=bindingArgs)存储在组件作用域内,例如 <label id="mylabel" value="@{person.name, answer='yes'}" style="@{person.mystyle, question='no'}">


 然后 mylabel.getAttribute("bindingArgs") 将返回{answer=yes, question=no}两个记录, (自从 3.1)我们支持"distinct" 的概念,用于具有model属性的组件(即Grid, Listbox, Comobobox, 等等.).你可以像下面那样指定该属性告诉 Data Binder 多条记录中或许有相同的对象


 <grid model="@{persons, distinct=false}" ...>
    ...
 </grid>
 

or


 <a:bind model="persons; distinct:false"/>
 <grid ...>
    ...
 </grid>
 

The default value for distinct is "true". However, if you specify distinct=false, the DataBinder will scan the whole ListModel to find out all items with the specified objects (thus worse performance if a big ListModel).

 

自从 3.6.2,如果你指定非特定标签,那么他们将被放入map参数中,并存储在以Xxx_bindingArgs命名的组件作用域内容, 其中Xxx表示注解组件属性的名字


 <label id="mylabel" value="@{person.name, answer='yes'}" style="@{person.mystyle, question='no'}"> 
 

然后 mylabel.getAttribute("value_bindingArgs") 返回{answer=yes} , mylabel.getAttribute("style_bindingArgs") 返回另外一个map{question=no} entry.

 

自从3.0.0,DataBinder支持保存前验证阶段,注:DataBinder "save"由save-when或者save-after指定事件触发时执行的行为。 在保存之前,首先触发注解绑定组件的onBindingSave事件,然后在触发onBindingValidate事件 ,在实际保存组件属性内容到bean属性之前触发 ,因此应用开发者可以在保存之前处理输入值的验证, 在下面的例子中,当user点击savebtn按钮结束以后,onBindingSave发送到firtName和lastName文本框,然后onBindingValidate事件发送到savebtn按钮.应用开发者可以注册适当的事件处理程序做他们想做的事情

 <textbox id="firstName" value="@{person.firstName, save-when="savebtn.onClick"}" onBindingSave="..."/>
 <textbox id="lastName" value="@{person.lastName, save-when="savebtn.onClick"}" onBindingSave="..."/>
 <button id="savebtn" label="save" onBindingValidate="..."/>
 

注意:textbox原有的约束机制让然起作用,该DataBinder验证阶段仅是一个附加特性,它可以用于所有组件的所有属性,

 

 

Since:
2.4.0 Supporting @{...} annotations., 3.0.0 Supporting multiple events of save-when tag and validation phase., 3.1.0 Supporting bidningArgs; suport "distinct" on collection data binding., 3.6.1 Support load-after, save-after, 3.6.2 Support Xxx_bindingArgs
Author:
Henri Chen


以下内容摘自官网,版权归zkoss.org


注释

注释提供了关于一个组件的数据,这些数据并不属于组件本身。它们在所注释组件的操作上并没有直接的影响。而是,它们在运行时被检测(examine),主要由工具或管理者(a tool or a manager)使用。注释的内容和意义完全取决于开发人员使用的工具或管理者。例如,一个数据绑定(data-binding)管理者可以检测注释,以知道组件值要被存储的数据源。

注释ZUML页面

注释可被用于ZUML页面中组件和属性的声明。有两种注释方式:标准的方式和简单的方式(the classic way and the simple way)。选择娜种看你的喜好。若喜欢的话可以在同一页面内混合使用它们。

注释组件声明的标准方式

注释要放在你想注释的元素声明之前:

 

 

 

<window xmlns:a="http://www.zkoss.org/2005/zk/annotation">
   <vbox>
      <a:author name="John Magic" date="3/17/2006"/>
      <listbox>
      </listbox>
...

 

annotation为http://www.zkoss.org/2005/zk/annotation空间内的一个元素。元素的名字和属性可以是依赖于你所使用工具的一切。你可以使用几个注释为相同的组件声明注释:

 

 

 

<a:author name="John Magic"/>
<a:editor name="Mary White" date="4/11/2006"/>
<listbox/>

 

author和editor为注释的名称,而name和date为属性名称。换言之,注释由名称和属性映射组成。

若两个注释有相同的名称,则它们会被合并为一个注释。例如,

 

 

 

<a:define var1="auto"/>
<a:define var2="123"/>
<listbox/>

 

等价于

 

 

 

<a:define var1="auto" var2="123"/>
<listbox/>

 

[注]: 注释不支持EL表达式。

注释属性(Property)声明的标准方式

为注释一个属性声明,你可以将注释放置于属性声明之前,如下所示。

 

 

 

<listitem a:bind="datasource='author',name='name'" value="${author.name}"/>

 

或者,你可以使用attribute元素,然后简单的注释属性声明,类似于为组件声明注释。换言之,上面的注释等价于下面的注释:

 

 

 

<listitem>
   <a:bind datasource="author" name="name"/>
   <attribute name="value">${author.name}</attribute>
</listitem>

 

注:若忽略了属性名称,则名称为value。例如,

 

 

 

<listitem a:bind="value='selected'" value=""/>

 

等价于

 

 

 

<listitem a:bind="selected" value=""/>

 

注释属性声明的简单方式

除了如上描述的使用特定XMl命名空间进行注释,有一种简单的注释属性的方法:为要注释的属性使用注释表达式指定一个值,如下所示。

 

 

 

<listitem label="@{bind(datasource='author',selected)}"/>

 

注释表达式的格式为@{ annot-name ( attr-name1 = attr-value1,attr-name2=attr-value2 )}。换言之,若属性值为一个注释表达式,则会被认为是为相应属性的注释,而不是其值。在上面的例子中,名为bind的注释为label属性注释。因此,其等价于

 

 

 

<listitem a:bind=" datasource='author',selected" label=""/>

 

若没有指定注释名称,则假定名称为default。例如,下面的代码片断使用了default作为注释名称为label属性注释,且注释有一个属性,名称和值分别为valueselected.name

 

 

 

<listitem label="@{selected.name}"/>

 

换言之,等价于下面的代码片断:

 

 

 

<listitem label="@{default(value='selected.name')}"/>

 

注:你可以使用多个注释为相同的属性注释,如下所示。

 

 

 

<listitem label="@{ann1(selected.name) ann2(attr2a='attr2a',attr2b)}"/>

 

注释组件声明的简单方式

类似的,你可以通过为一个名为self的特定属性指定注释表达来注释一个组件。

 

 

 

<listitem self="@{bind(each=person)}"/>

 

self为一个关键字,表示注释被用于注释组件声明,而不是任何属性。换言之,等价于

 

 

 

<a:bind each="person"/>
<listitem/>

 

手动注释组件

通过使用org.zkoss.zk.ui.sys.ComponentCtrl接口的addAnnotation 方法,你可以在运行时注释一个组件。

 

 

 

Listbox listbox = new Listbox();
listbox.addAnnotation("some", null);

 

获取注释

可以在运行时取回(retrieved back)注释。通常由工具获取,例如数据绑定管理者,而不是应用程序。换言之,为某一特定目的,应用程序注释ZUML页面以告诉工具如何处理组件。

下面为转储(dump)一个组件所有注释的例子:

 

 

 

void dump(StringBuffer sb, Component comp) {
   ComponentCtrl compCtrl = (ComponentCtrl)comp;
   sb.append(comp.getId()).append(": ")
     .append(compCtrl .getAnnotations()).append('\n');

   for (Iterator it = compCtrl.getAnnotatedProperties().iterator(); it.hasNext();) {
      String prop = it.next();
      sb.append(" with ").append(prop).append(": ")
         .append(compCtrl .getAnnotations(prop)).append('\n');
   }
}

 





















分享到:
评论
3 楼 sunflowers 2011-01-10  
tsinglongwu 写道
引用
converter. 可以指定实现TypeConverter接口的converter类名字,它将负责组件属性和bean属性之间的互相转换.converter不允许配置多个,如果定义多个那么后一个将覆盖前一个。大多说情况下你无需指定它,因为DataBinder支持大多说通常使用的类型,然后如果你指定 TypeConverter类名,那么DataBinder实例化这个转换器,替代默认转换器转换

Hi sunflowers,
请问转换器怎么和spring整合呢?我想在zul页面对converter引用一个sping bean。
谢谢。。



我已很少访问本博客,已移动到http://sun4love.iteye.com,

1,converter的值是一个字符串,不是一个bean实例,所以不能使用spring bean

2,使用spring bean无非是想注入什么东西,像converter仅是一个简单的转换器,注入bean太过复杂,理一下思路看是否走了弯路

请访问到新博客,这样我可以及时关注你的回复
2 楼 tsinglongwu 2011-01-06  
引用
converter. 可以指定实现TypeConverter接口的converter类名字,它将负责组件属性和bean属性之间的互相转换.converter不允许配置多个,如果定义多个那么后一个将覆盖前一个。大多说情况下你无需指定它,因为DataBinder支持大多说通常使用的类型,然后如果你指定 TypeConverter类名,那么DataBinder实例化这个转换器,替代默认转换器转换

Hi sunflowers,
请问转换器怎么和spring整合呢?我想在zul页面对converter引用一个sping bean。
谢谢。。

1 楼 pen_xian 2010-10-29  
还是你这里的zk资料最全了!

相关推荐

    zk框架中的注解使用

    zk框架中的一些注解使用,项目中的需要用到的,各位可以了解一下,希望可以帮到大家!今后可以多交流,相互学习,共同进步。

    zk+spring+hibernate(全部用注解)

    zk+spring+hibernate spring bean的管理全部使用注解,hibernate也全部使用注解

    Zk中注解的使用(ZkDemo系列)

    NULL 博文链接:https://sunflowers.iteye.com/blog/620821

    zul页面和java注解

    整理的比较全面的zul页面注解和java注解,初学zk框架的朋友可以看看,了解注解的功能,便于框架的学习。

    springboot+dubbo+zk

    springboot注解方式集成dubbo,摒弃xml配置方式,使开发更高效

    基于Actor模型的RPC

    4、使用ZK进行集群状态管理 备注: 1、使用自定义注解进行服务注册及辅助控制(线程数量、方法名称设置等)不带路由测试示例代码入口: cn.bossfridy.rpc.test.actorsystem.Bootstrap 2、带路由测试示例代码入口...

    基于redis的java分布式代理锁

    分布式代理锁,动态的锁后缀采用ThreadLocal或者参数名获取 锁粒度自定义选择,目前实现基于redis,后续扩展zk等 SpringBoot,默认使用redisson链接redis,可以更改注解参数使用Spring redis工具 key分为:无后缀、...

    收集优秀的编程资源(Java为主).zip

    涵盖:Java面试、求职、电子书籍、计算机网络、操作系统、前端、 Redis、Mysql、Nginx、ZK、MQ、机器学习、NPL、架构、算法 Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布...

    school-parent.zip

    初学springboot+mybatis+mysql+dubbo+zk整合,便于后期深入学习用IDE整理一个demo,主要学习springboot的注解和配置

    基于springBoot自研微服务框架+源代码+文档说明

    orion-register-zk-starter cp orion-register-etcd-starter cp orion-register-nacos-starter ap orion-register-eureka-starter ap #### 支持自定义熔断策略 //TODO #### 支持可...

    JAVA上百实例源码以及开源项目

    此时此景,笔者只专注Android、Iphone等移动平台开发,看着这些源码心中有万分感慨,写此文章纪念那时那景! Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这...

    JAVA上百实例源码以及开源项目源代码

    此时此景,笔者只专注Android、Iphone等移动平台开发,看着这些源码心中有万分感慨,写此文章纪念那时那景! Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这...

    java开源包1

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

    java开源包11

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

    java开源包2

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

    java开源包3

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

    java开源包6

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

    java开源包5

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

    java开源包10

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

    java开源包4

    AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器...

Global site tag (gtag.js) - Google Analytics