内置组件<t:beandisplay/>是用BeanModel(内部bean模型)来展示一个bean的属性,输出列表为:一个<dl/>,其内部是包含一系列<dt/>和<dd/>的标签,dl标签的class属性默认值是“t-beandisplay”,查看该组件的tml文件就可以看到了,通过指定一个class的非正式参数值可以覆盖该默认值,dt和dd的class默认值都是属性名,dt的标签text是格式化的属性名(首字母大写并在剩余字符串中的大写字母前面增加一个空格,例如“userName”格式化后就是“User Name”),dd的标签text是属性值,如果属性值为null,则会在输出一个“ ;”,也就是输出一个空格,来实现值的显示不为空,另外,展示过程中只有已知的数据类型才会被输出展示,未知类型需要我们自己注册,然后才能支持,已知类型包括String:、Number、Enum、Boolean、Date和Calendar,这些类型在<t:beandisplay/>中都是输出一个文本格式字符串,因为我们目的是展示bean的属性值,不是编辑(如果使用<t:beanEditForm/>就不同了,它就会根据不同类型来显示不同的展示标签供编辑用)。
下面我们用一个例子来说明问题,首先是我们需要用到的bean
public class Person { private String userName; //已知类型属性 private int age; //已知类型属性 private Date birthday; / /已知类型属性 private Address address ; //未知类型属性,因为是自定义类型 public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
然后是我们的位置类型Address
public class Address { private String street; public Address() { } public Address(String street) { super(); this.street = street; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } }
现在我们先测试一下基本的使用,用下面这个页面
public class Start { @Property private Person person; void onActivate() { person = new Person(); person.setUserName("test"); person.setAddress(new Address("address value")); person.setAge(12); person.setBirthday(new Date()); } }
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" > <head> <title>t:beandisplay</title> </head> <body> <t:beandisplay object="person"/> </body> </html>
发布到tomcat中,然后查看效果为
我们查看一下生成的HTML代码
<dl class="t-beandisplay"> <dt class="age">Age</dt> <dd class="age">12</dd> <dt class="userName">User Name</dt> <dd class="userName">test</dd> <dt class="birthday">Birthday</dt> <dd class="birthday">2011-4-14</dd> </dl>
对比我们前面介绍的内容,看一下dl、dt和dd的显示是否正确?
好了,刚才的例子中,我们只使用了object这一个参数,现在我们增加一个参数lean,这个参数的作用是是否需要显示dt和dd的相应class属性,该属性值如果设置true,则不显示class,否则显示(既然刚才没用这个参数,那么显示当然是默认的了),在前面的代码中
<t:beandisplay object="person"/>
增加一个参数lean,修改为
<t:beandisplay1 object="person" lean="true"/>
看效果
没什么变化,看看HTML
<dl class="t-beandisplay"> <dt>Age</dt><dd>12</dd> <dt>User Name</dt><dd>test</dd> <dt>Birthday</dt><dd>2011-4-14</dd> </dl>
两个标签的class属性没有显示了。
Include参数是用来对需要展示哪些属性来设置,例如:<t:beandisplay1 object="person" lean="true" include="age,birthday"/>就只要求展示age和birthday两个属性,而userName属性则不会再被展示,include属性指定列表使用一个逗号分隔的属性名字符串,指定的列表是已经被排序了的,也就是说,属性展示的时候会按照逗号列表中出现的顺序依次展示,同时该参数是忽略大小写的,自己可以试一下。
Exclude参数和include参数作用则正好相反,是用来对不需要展示的哪些属性来设置,设置方法同样是一个逗号分隔的忽略大小写的属性名字符串。
同时指定Include和Exclude参数,则Exclude的级别要高一点,如Include和Exclude同时包含一个userName属性名,则userName是不展示的。
Reorder参数是用来对需要展示的属性进行展示排序的,设置方法也是一个逗号分隔的忽略大小写的属性名字符串,和include一起使用,顺序也是由reorder来决定,谁让人家就是干这个的呢,如果reorder没有给出某个需要展示的属性,则没有给出的会被增加到给出顺序的后面。
在bean的class上增加一个org.apache.tapestry5.beaneditor.ReorderProperties
类型的注释也可以修改属性的展示顺序,但是只比默认的情况高,比reorder参数指定的要低,使用方法是
@ReorderProperties("userName,age,birthday")
public class Person {//code ....}
关于这个展示属性顺序,这里做一个说明:
默认情况下(未明确给出参数或者在bean中增加注释),则展示顺序是按照bean中的get方法出现顺序,从上大小。
ReorderProperties注释的顺序会覆盖默认情况下的展示顺序。
指定了include,未指定reorder,则顺序按include的顺序展示。
指定了reorder,则顺序按照reorder的顺序展示。
Add参数值是用来临时增加一个展示属性,例如我们将
<t:beandisplay object="person"/>修改为<t:beandisplay object="person" add="version"/>
则会增加一个version的属性列展示,增加的version属性会默认增加到展示顺序的最后,如果需要为增加的属性增加内容可以使用p空间。
以下是示例代码:
<t:beandisplay object="person" add="version"> <p:version> value </p:version> </t:beandisplay>
<p:version>的内容可以是任意的,不一定是文本。
Model参数是用来自己指定一个显示bean的BeanModel,在源码中有这么一段代码
void setupRender() { if (model == null) { model = modelSource.createDisplayModel(object.getClass(), overrides.getContainerMessages()); BeanModelUtils.modify(model, add, include, exclude, reorder); } }
在setupRender阶段会检测标签使用时是否指定了model,如果没有指定(model==null),则由modelSource创建一个默认的BeanModel。
我们就可以知道如果指定了model参数,那么就不会创建默认的BeanModel了,也就不会执行
model = modelSource.createDisplayModel(object.getClass(), overrides.getContainerMessages());
BeanModelUtils.modify(model, add, include, exclude, reorder);
这两句了,那么,add,include,exclude和reorder四个参数就不会产生效果了,这也就是为什么注释中会有“Only used when a default model is created automatically.”一句了,因为只有默认的模型创建才会使这四个参数起作用。
我们自己来创建一个model试一下。
public class Start { @Property private Person person; @Inject private BeanModelSource modelSource; @Property private BeanModel<Person> personModel; @Inject private Messages messages; void onActivate() { person = new Person(); person.setUserName("test"); person.setAddress(new Address("address value")); person.setAge(12); person.setBirthday(new Date()); personModel = modelSource.createDisplayModel(Person.class, messages); //试着修改下面的三行代码的第二个参数值(参数值和标签参数的指定格式一样) BeanModelUtils.add(personModel, "password"); BeanModelUtils.exclude(personModel, "userName"); BeanModelUtils.reorder(personModel, "password,birthday,age"); } }
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" xmlns:p="tapestry:parameter"> <head> <title>t:beandisplay</title> </head> <body> <t:beandisplay object="person" add="version" model="personModel"> <p:version> value </p:version> <p:password> password </p:password> </t:beandisplay> </body> </html>
Add中添加的version没有起作用了,但是在模型中添加的password却被添加了。
至于overrides的作用,暂时还没有搞明白,如果谁懂的话,麻烦给我发个邮件解释一下,谢谢。[email protected]
<t:propertydisplay/>比<t:beandisplay/>简单的多,这里就不多说了。