原则 1 – 静态结构,动态行为
「动态行为」的概念非常简单:当构建web应用时,根据不同的用户以及用户状态呈现不同的界面。「静态结构」是什么意思呢? 静态结构就是:当你使用Tapestry构建一个页面时,你可以定义所有的组件来供该页面使用。在渲染或事件触发该页时,你可以动态改变页面组件的内容。
这看起来限制很多....其它的框架允许在流布局中创建新的元素,就像Swing的桌面GUI的通常属性。但对于静态结构来说没有限制。你可以创建新元素(使用其它值重新渲染已存在的组件) 。你有许多选择对静态结构进行动态行为;对于条件判断和循环类似Tapestry的BeanEdit或者Grid的高级组件,Tapestry让你来控制渲染时间和形式,甚至可以指定渲染的位置。Tapestry5.3以后,你还可以使用外部模板文件动态组件 来渲染页面。
为什么Tapestry会使用静态结构作为核心原则呢?肯定是为了满足它的灵活性和扩展性。
灵活性
Tapestry 被设计成了灵活的工作环境;「少编码,多引用」。为了支持大家少编码,Tapestry在首次加载POJO页面和组件时做了很多工作。 它采用了共享页面和组件类的实例方式(在多线程和请求之间共享)。拥有动态修改结构的特性也就意味着每个请求有自己的实例,深一点来讲,它的整个结构将会在请求之间序列化,因此可以存储以及稍后的请求来处理。
Tapestry 在 实时类重载 下,加速开发循环,使其更灵活。Tapestry 监听系统文件的改变比如Java 页面类、组件类、服务实现类、HTML模板和组件属性文件,并热部署到正在运行的应用中而不需要重启或丢掉session 数据。这就提供了其它框架所不能做到的 编码-保存-查看 循环效果。
扩展性
当构建大型可扩展系统时,有必要考虑到:如何利用部署服务器上的资源,服务器之间的如何实现信息共享。静态结构意味着页面实例不需要存在HttpSession,单个浏览用户不需要额外的系统资源。精简的HttpSession用法是Tapestry高度扩展性的关键所在,尤其对于大量的配置。所以链接到特殊客户端的页面实例需要更多的服务端资源而不是单一分享的页面实例。
原则 2 – 适应性的 API
Tapestry 5的一个核心特性是它的适应性 API.
传统的Java 框架 (包括 Struts, JSF ,甚至早期的 Tapestry 4) 期望用户编码符合框架规范。你创建类继承于框架的基类或者实现框架提供的接口。
在更新框架到下个公布版本之前,你的框架运行的很好:在更新后,新的特性经常会让你倒退再次编码,以适应接口或基类的改变。
在 Tapestry 5中,框架接受你的编码。你自己有命名方法,参数接收,返回值的自由。这都会由注解驱动,并告知Tapestry在什么情况下调用你的方法。
比如,有一个登录表单和提交表单的触发方法:
public class
Login
{
@Persist
@Property
private
String userId;
@Property
private
String password;
@Component
private
Form form;
@Inject
private
LoginAuthenticator authenticator;
void
onValidateFromForm()
{
if
(! authenticator.isValidLogin(userId, password))
{
form.recordError(
"Invalid user name or password."
);
}
}
Object onSuccessFromForm()
{
return
PostLogin.
class
;
}
}
|
这个简短的代码解释了一点Tapestry的操作。应用的页面和服务注入了@Inject 注解。方法名:onValidateFromForm()和 onSuccessFromForm() 通知Tapestry什么时候调用本方法。这种便利命名标志了事件被处理 ("validate" and "success") ,组件的id来自事件的触发and the id of the component from which the event is triggered ( "form" 组件).
"validate" 事件在校验表单域时被触发, "success" 事件只会在校验通过后被触发。 onSuccessFromForm()
方法的返回值指导Tapestry下一步怎么做:跳转到应用内的其它页面(这里是页面类的标志,还有其它可选方式)。当异常发生时,页面会重新渲染并展示到用户。
作为比较对象,Tapestry 4 的Form表单组件通过名称name监听参数是否绑定到方法调用。而且,监听方法必须是public。Tapestry 5 的方式不仅支持多参数监听,在Java类里还提供了升级的分隔视图(HTML模板内部)和逻辑处理。
在许多情况下,事件的额外信息是可用的,并且能够以添加参数到方法的方式传递。因此,Tapestry能够接收到你的参数,无论你怎么排序你的参数。
Tapestry 也会节省你的宝贵时间: @Property 注解标记属性可读和可写;Tapestry 会自动提供getter和setter方法。
最后, Tapestry 5 显式分隔action(改变事情的请求)和render(渲染页面的请求)为两个单独的请求。执行action时,比如点击action链接或提交表单,结果会在客户端定向到一个新的页面。这就是 "Post/Redirect/Get" 模式(可选 "Post-Then-Redirect", 或者 "Redirect After Post")。这对于保证浏览器的URL是可添加书签是用帮助的...但在请求之间仍需一点信息来保存到session(使用 @Persist 注解).
原则 3 – 区分 Public vs. 内部 API
关于使用Tapestry差评的话题(4或更早)是关于private ,内部API和public之间缺乏明确的定义。需要要继承基类对象是事实,但基类对象的许多方法是 『不限制』使这个差评更加迷惑。这已经在『深刻学习Tapestry的弧度』作为关键字被明确定义。
基于快速上手的设计, Tapestry 5 对于 internal vs. external上更为严格。
首先,在 org.apache.tapestry5.internal 包内的都是 internal. 这里是Tapestry的实现方式部分。幕后操作都在这里。你应该一直不需要直接使用这些代码。这里这样做并不好,因为内部API 编码也行会在下一次公布升级中修改。
如果你曾发现你必须使用内部API时,请以邮件通知我们的开发邮箱,这样我们才知道哪些服务我们应该暴露成public,以便我们的应用更稳定升级。
原则 4 – 确保回退通用
Tapestry的早期版本每次发布新版本时因为回退通用性问题带来了很多问题。Tapestry 5 甚至没考虑回退Tapestry 4的通用性。取而代之的是,升级通用性。
Tapestry 5的 API 大部分基于便利命名和注解。你的组件只不过是Java 类;注解属性允许Tapestry操作它们的状态或注入资源,你命名的方法(或注解)告诉Tapestry 什么时候调用。
Tapestry 采纳你的类,调用你的方法,通过方法参数传递值。对于修订接口的实现,Tapestry 会采纳你使用便利命名和注解的类。
所以, Tapestry 5 可以在不影响应用其它任何代码的情况下修改内部方法。这是防止回退通用的最后的防线,允许你保证你的应用可以稳定升级到Tapestry的最新版本。
目前已经在 Tapestry 5.1, 5.2 and 5.3 证明 这个新特性的性能提升。100%的回退通用---仍然需要尽量避免临时使用内部API.