`

Tapestry 5 组件参数

阅读更多
Tapestry 5 组件参数
 
 
本文根据http://tapestry.apache.org/tapestry5/tapestry-core/guide/parameters.html翻译整理过来,请高手指正,转载请注明出处!
 
 
组件参数是Tapestry一个重要的方面。组件类实例的存在还不够,它必须还要配置以达到处理正确的事情。配置依据组件参数。
 
一个组件可以带有许多参数,每一个参数都有一个明确的名字、明确的Java类型(可以是一个简单类型),是可选的或必须的。
 
参数的定义是通过在私有属性上放置一个Parameter annotation
 
以下列出的是一个循环组件;通过它的startend参数(用来设置循环的边界),组件的body将多次呈现(renders)。组件可以更新value参数(参数所在容器的属性),它能依据startend哪一个大来自动加减:
 
package org.example.app.components;
 
import org.apache.tapestry.annotations.AfterRender;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.annotations.SetupRender;
 
public class Count
{
    @Parameter
    private int _start = 1;
 
    @Parameter(required = true)
    private int _end;
 
    @Parameter
    private int _value;
 
    private boolean _increment;
 
    @SetupRender
    void initializeValue()
    {
        _value = _start;
 
        _increment = _start < _end;
    }
 
    @AfterRender
    boolean next()
    {
        if (_increment)
        {
            int newValue = _value + 1;
 
            if (newValue <= _end)
            {
                _value = newValue;
                return false; 
            }
        }
        else
        {
            int newValue = _value - 1;
 
            if (newValue >= _end)
            {
                _value = newValue;
                return false; 
            }
        }
 
        return true;
    }
}
 
参数名字来自属性名(去掉首字符"_" "$")——实际情况是匹配getter方法"get"后字串。这里的参数名字是:"start", "end" "value"
 
绑定参数
 
上例中的组件可被其他组件或页面的模板(template)引用:
 
<html t:type="layout" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <p> Merry Christmas: <t:count end="3"> Ho! </t:comp>
    /p>
/html>
 
end属性用来绑定Count组件的end参数,这里它被绑定到一个字符值"3",它将被Tapestry自动强制转换为int3
 
许多参数都可以采用这种绑定方式。
 
组件参数也可以通过在组件类中使用Component annotation来绑定。
 
当两者绑定发生冲突时,用Component annotation绑定的参数要优先于模板绑定的参数。
 
表达式绑定
 
前面例子模板中的值“3”是一个表达式绑定。通过在参数值前面使用不同的前缀,我们可以改变Tapestry如何解释表达式的剩余部分(冒号后面的部分):
 

前缀
描述
block
模板中blockid
component
同一模板中另一组件的id
literal
字面字符常量。
message
从分类信息文件(message catalog)中查找值。
prop
容器组件属性名,用于读写。
translate
配置的translator的名字。
validate
被用来创建许多字段校验的校验说明。

 
参数有一个默认前缀,通常是"prop:",未指定前缀时用此前缀。
 
属性绑定
 
"prop:"绑定前缀意味着属性绑定。
 
属性绑定的表达式是一个点分隔的属性名序列。简单的属性表达式就仅仅是一个属性的名字,如:"prop:userName"。复杂的属性表达式可以在属性前加上部分导航来进行读写,如:"prop:userData.name"
 
除了属性名之外,我们还可以调用任意方法,方法必须是公共的、返回一个非void值、抛出的异常为非检查型的且是无参的。为区分方法名和属性名,我们需要加上一个圆括号“()”。因此,先前的例可以写成"prop:getUserName()""prop:getUserData().getName()"。注意当表达式最后一项是一个方法名,绑定将是只读的,而非可读写的。
 
这一特性对于访问标准集合类一对的属性(没有命名相应的属性)来说非常有用,如Collection.size()Map.keySet()
 
一但获值失败,会不会因为这一表达式中存在空指针而绊倒?你可以使用"?."替换"."作为分隔符。这会增加一个空值检测,忽略掉表达项的空值。假设"foo?.bar?.baz"foobarnull,表达式将会返回null,与此同时,"foo?.bar?.baz"中如果foobarnull,则更新此表达式将转变为一个空操作。
 
另外,还支持少数特殊的情况。大多数情况下,这些特殊的值可以减少你在值前面添加前缀"literal:"。这些少数情况相当于属性表达式:
  • "true" "false" 将被转换成布尔值。
  • "null" 将被转换成值null
  • "this" 将是组件自己的引用。
  • 简单的数字值也可以被接收,这些将会被解析成LongDouble对象。比如:"prop:3.14"
  • 被句点分隔的一个整数范围。如:"1..10"
  • 单引号里的字面字符串,如:"'Hello World'"
这些情况下,多出的空格将被忽略。对于关键字("true""false""this" "null"),忽略大小写。
这些值都是只读且无变化的。
 
验证绑定
 
绑定前缀"validate:"非常特殊,它允许一个简短的字符串来创建和配置对象执行的表单控制组件的输入验证,如TextField Checkbox
 
这些字符串是一个逗号分隔的验证类型(validator types)列表,验证类型是对象执行验证的简短别名。在许多情况下,验证是多方式可配置的:比如,一个强制最小字符长度验证,想知道最小的字符长度是多少的,这个值被指定在一个等号(=)后面。
 
如:validate:required,minLength=5强制该字段域必填且最少5个字符。
 
TODO: More ability to escape or quote constraint values. Ability to reference methods or properties of the container to perform some of the validation. Links to proper discussion of validation, once the code and documentation is ready.
 
转换绑定
 
绑定前缀"translate:"也可以用在输入验证。它是配置项Translator的名字,主要负责服务端与客户端表现数据转换(例如,客户端字符串与服务端数字值的转换)。
 
有效的转换(translators)列表配置在TranslatorSource服务中。
 
非正式(informal)参数
 
一些组件支持非正式参数,额外的参数超过了正式定义的参数。非正式参数将在组件标签呈现时作为额外的属性输出。一般来说,组件与特有的HTML标签有1:1的对应关系(比如TextFieldinput>支持非正式参数)。
 
非正式参数通常且于设置一个元素的样式,或者指定客户端的事件句柄(处理)。
 
非正式参数默认的绑定前缀依赖于指定的参数绑定方式。如果参数绑定在Java类中的Component annotation里面,这里的默认绑定为"prop:",如果参数绑定在模板中,默认的绑定前缀为"literal:"。这反映出用annotation使参数指定在Java类里,很可能就是一个用来计算的值,反之,一个指定在模板中的值将被简单的拷贝,按照原样输出到HTML(结果)流中。
 
参数双向性
 
参数并非简单的变量;在组件和它的容器组件(包含组件的组件)的属性之间,每一个参数等同于一个连接或者说绑定,当使用前缀prop:时,组件能将改变通过赋值的方式强制到它的容器组件的属性里。
 
<t:layout xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <p> Countdown:
        <t:count start="5" end="1" value="index"> 
          ${index} ... 
        /t:count>
    /p>
</t:layout>
 
因为Count组件更新value参数(_value属性),容器组件的index属性将被更新。在Count的body内,我们通过扩展表达式(等同于JSP中表达式语言)${index}输出当前index属性的值。输出结果大至如下:
    p Countdown: 5 ... 4 ... 3 ... 2 ... 1 ... /p
(尽管空格完全不同)
它们的关系是组件可以读取固定的值或者其容器组件中可变的属性值,同样能更改其容器组件中的属性值。
 
必选参数
 
必选参数必须要绑定。如果一个组件有未绑定的必选参数将会发生运行时异常。
 
可选参数
 
参数不是必要的,是可选的。
我们可以设置可选参数的默认值以提供其他属性使用。在Count组件中,参数 min有默认值为1,如果参数min绑定了一个值,则绑定的值将替代默认值。
参数的默认绑定
Parameter annotationvalue()属性可以用来指定一个绑定的表达式,用以参数未绑定的情况下作为默认绑定。典型地,绑定的表达式是一个属性的名字,这个属性将会在运行时被计算值。
Example:
 @Parameter("defaultMessage")
 private String _message;
  
  @Parameter(required=true)
 private int _maxLength;
  
  public String getDefaultMessage()
 {
    return String.format("Maximum field length is %d.", _maxLength);
 }
 
在其他地方,我们可以在value上使用前缀。一个普通的前缀"message:"用以访问国际化信息(localized message)。
 
 
计算方式的参数默认绑定
 
在少数情况下,我们需要用计算绑定的方式来作为参数的默认值。在此,我们要提供一个默认的无参的绑定方法,方法的返回值用来绑定参数。返回值可以是Binding实例或者简单的值(比较多的使用)。
 
方法名以"default"加上首字母大写的参数名。
 
使用这种方法,先前的例子可以写成:
 
 @Parameter
 private String _message;
  
  @Parameter(required=true)
 private int _maxLength;
  
  @Inject
 private ComponentResources _resources;
  
  @Inject("infrastructure:BindingSource")
 private BindingSource _bindingSource;
  
  Binding defaultMessage()
 {
    return _bindingSource.newBinding("default value", _resources, "defaultMessage");
 }
  
  public String getDefaultMessage()
 {
    return String.format("Maximum field length is %d.", _maxLength);
 }
:
在这个例子中,属性表达式"defaultMessage"用来动态访问信息。
 
以上例子可以写得更简洁:
 
 @Parameter
 private String _message;
  
  @Parameter(required=true)
 private int _maxLength;
  
  @Inject
 private ComponentResources _resources;
  
  @Inject("infrastructure:BindingSource")
 private BindingSource _bindingSource;
  
  String defaultMessage()
 {
    return String.format("Maximum field length is %d.", _maxLength);
 } 
 
这种形式很像使用绑定前缀"literal:",但是字面值是通过defaultMessage()方法计算出来的。
 
显然,这要比简单地指定一个默认的参数值做更多的工作。
In the few real cases where this is approach is used, the default binding method will usually deduce a proper binding, typically in terms of the component's id. For example, the TextField component will deduce a value parameter that binds to a property of its container with the same name.
这种方法在一些少量的实际情况中被采用,默认的绑定方法将通常会根据组件的id产生适当的绑定。比如,TextField组件将产生value参数,用它容器中具有相同名字的一个属性绑定到此value参数。
 
默认的绑定方法只有在Parameter annotation未提供默认值时才被调用。
 
未绑定的参数
 
如果一个参数没有被绑定(可选参数),那么它的值可以在任何时候被读写。
 
更新对于未绑定的参数并没有作用。在第一个例子中,Count组件的value参数没有绑定,这完全是可以的。
 
注意:更新对于这个属性是临时性的;当组件完成呈现时,属性将被置为默认值。
 
TODO: This seems contradictory. What does it mean to update an unbound component parameter when the component is not rendering?
参数缓存
 
读取一个参数值会耗费不少资源的(因为类型的强制转换)。因此,缓存参数值是有意义的,至少当组件正在呈现自己时。极少情况下,我们可以通过设置Parameter annotationcache()属性为false来打破这种缓存机制。
 
参数类型的强制转换
 
Tapestry包含自动类型转换(coecing types automatically)机制。大多情况下,它用来将字面字符串转换成相应的值,但在许多情况下,将会发生较复杂的转换。
 
参数名
 
缺省情况,Tapestry将去掉首字母"$" "_"的属性名转换为参数名。
我们也可以使用Parameter annotationname()属性覆盖这种缺省情况。
 
决定是否绑定
 
很少情况,我们需要根据参数是否绑定来产生不同的行为。这可以通过查询组件资源(resources)来完成,组件资源可以通过Inject annotation注入到组件中:
 
public class MyComponent
{
 @Parameter
 private int _myParam;
  
  @Inject
 private ComponentResources _resources;
  
  @BeginRender
 void setup()
 {
      if (_resources.isBound("myParam"))
      {
        . . .
      }
 }
}
 
以上粗略举例这种方法。因为参数类型是简单类型int,我们很难区分没有绑定和显示地绑定0
 
Inject annotation将注入组件的资源(ComponentResources),这些资源是我们写的Java类与Tapestry底层构建我们类的类之间的桥梁。任何情况,资源一但被注入,就可以被访问。
分享到:
评论

相关推荐

    tapestry5 自定义组件

    在 Tapestry 5 框架中,自定义组件是扩展其功能的关键方式,它允许开发者根据特定需求创建个性化和可重用的 UI 元素。Tapestry 5 是一个强大的 Java Web 应用程序开发框架,它强调组件化、模块化以及声明式编程模型...

    tapestry组件

    tapestry部分组件绑定参数的列表!

    Tapestry简单入门.rar_java Tapestry_tapestry

    接下来,我们转向"tapestry组件.docx",组件是Tapestry的核心组成部分,它们是可重用的、自包含的代码单元,可以处理用户交互、展示数据或执行业务逻辑。组件可以是简单的HTML元素,也可以是复杂的UI部件。组件的...

    Tapestry 5开发指南(英文)

    - **链接生成**:生成安全、语义化的链接是Tapestry 5的强项,它会自动处理URL参数和安全需求。 6. **国际化和本地化** - **资源包**:使用资源包来管理多语言文本,支持应用的国际化。 - **时区支持**:...

    tapestry 5 ..........

    在Tapestry中,开发者是通过对象及其方法和属性来构建应用程序的,而不是通过URL和查询参数。这种模式使真正的面向对象开发在Java Web应用程序中成为可能。 #### 2. 设置开发环境 为了开始使用Tapestry 5进行开发...

    Tapestry5开发文档.doc

    5. **URL构建与参数映射**:遵循RESTful原则,Tapestry5支持优雅的URL结构,将URL与页面和操作关联起来,使得URL更具可读性,并且易于SEO优化。 6. **类重加载**:Tapestry5的类重加载特性极大地提升了开发效率,...

    Tapestry 5 Project 5.0.16 API

    3. **类型安全的绑定**:Tapestry 5提供了类型安全的属性绑定,允许将表单字段或URL参数直接绑定到组件或页面的Java对象属性上,无需手动转换数据类型,增强了代码的健壮性。 4. **服务容器**:Tapestry 5使用依赖...

    Tapestry5 使用教程

    Apache Tapestry 5 是一个强大的 Java Web 开发框架,它通过组件化的设计理念,极大地简化了 Web 应用的开发过程。无论是对于初学者还是有经验的开发者来说,Tapestry 都是一个值得学习和使用的框架。通过掌握其核心...

    Tapestry5使用文档

    **自定义组件** 是 Tapestry5 强大的地方之一,下面列举了一些常用的自定义组件: 1. **上传组件 Upload**:支持同步上传。 2. **ajax 上传图片组件 Uploads**:支持异步上传,提高了交互性。 3. **二级省市级联...

    tapestry 实例

    1. **请求处理**:当用户发起HTTP请求时,Tapestry会解析请求参数,确定目标页面和组件。 2. **组件实例化**:根据页面和组件定义,Tapestry 创建必要的组件实例。 3. **状态管理**:Tapestry 自动处理组件状态的...

    Tapestry

    组件之间可以通过参数进行数据传递,实现页面属性和组件属性的联动。 Tapestry遵循MVC(模型-视图-控制器)架构模式。在这里,组件扮演控制器的角色,连接模型层(业务逻辑)和视图层(HTML模板)。页面通过属性...

    Tapestry 5.1 实例教程(全部)

    4. **类型安全的URL**:Tapestry 5.1提供了类型安全的URL映射,避免了传统URL参数的潜在错误。学习如何定义和使用页面链接和页面事件。 **二、高级组件与服务** 1. **内置组件**:Tapestry 5.1内建了许多有用的...

    tapestry学习入门资料

    2. Tapestry 由“对象、方法、域”这些面像对象元素构成,但是它更关注于开发者关心的 Servlet API 的请求,回复,会话,属性,参数,URLs 等等开销。 3. Tapestry 关注的是如何联系用户的动作和这些动作所引响到的...

    Tapestry 重要资料 教你认识tapestry

    页面作为Tapestry组件,可以通过配置属性表达式与模型对象进行数据交互。属性表达式通常使用OGNL(Object Graph Navigation Language)来读取和更新Java Bean属性。OGNL是Tapestry中不可或缺的一部分,它简化了对象...

    Tapestry5开发文档.pdf

    总结来说,Tapestry5是一个全面的Web开发解决方案,以其组件化、高效和易用性赢得了开发者们的青睐。通过深入学习和实践,开发者可以利用Tapestry5构建出更优雅、更易用、更安全且更具弹性的Web应用程序。

    Tapestry4.1.2 入门-介绍

    这部分内容没有提供,但通常可以创建一个Tapestry组件或服务,维护一个计数器状态,并在每次页面访问时增加。这将涉及组件的属性、方法以及事件处理。 Tapestry的组件系统非常强大,允许开发者定义自己的可复用...

    Tapestry开发指南

    Tapestry是一款强大的Java Web应用程序框架,由Apache软件基金会维护,它强调了组件化、类型安全和高可测试性。本开发指南将深入探讨Tapestry的核心概念、工作原理以及如何利用它来构建高效、可维护的Web应用。 1. ...

    Tapestry开发

    ##### 第一节:熟悉Tapestry组件 **1. ForEach组件:** - **用途:**用于循环遍历集合或数组。 - **示例代码:** ```xml <tapestry:foreach each="${list}" var="item"> ${item.name} </tapestry:foreach> ``...

Global site tag (gtag.js) - Google Analytics