欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【翻译】Wicket启示录——理论与实践(一)

程序员文章站 2022-03-13 23:30:02
...

Wicket,当多数人看到它时,也许又是带着惯性思考 java又出新玩具啦???”。下面是在wicket官方贴出的一个关于现今Java web框架的列表:

 

Echo

Cocoon Millstone OXF
Struts SOFIA Tapestry WebWork
RIFE Spring MVC Canyamo Maverick
JPublish JATO Folium Jucas
Verge Niggle Bishop Barracuda
Action Framework Shocks TeaServlet wingS
Expresso Bento jStatemachine jZonic
OpenEmcee Turbine Scope Warfare
JWAA Jaffa Jacquard Macaw
Smile MyFaces Chiba JBanana
Jeenius JWarp Genie Melati
Dovetail Cameleon JFormular Xoplon
Japple Helma Dinamica WebOnSwing
Nacho Cassandra Baritus Stripes
Click GWT    

 

说实话,这里我所认识的不超过10个.那么既然有这么现成的web框架了,干什么还要重新发明*,弄出个wicket?官方给了一句爽快的豪言壮语:这一次,我们会把“*”造的非常完美.姑且不论是不是带有噱头,但既然敢这么说,咱们就来看看Wicket到底卖的什么关子.最后结论到底是Java的“a big thing还是a toy”,相信在看完本文后,每个人心中的答案自然揭晓。

WicketEchoTapestry类似,而且与Tapestry最为接近,如果熟悉这两种web框架的话,Wicket自然不必多说.但如果一直使用Struts,Webwork,Spring MVC等框架的话,最好先运行我给出的demo,再看文本也没有什么障碍。不然如果10分钟,还无法运行一个Wicket程序的话,我也不会给大家介绍了.本文适合繁忙的程序员,如果你无暇亲自去关注当今的Java框架技术的话,相信本文会是一个不错的导论.总之,关键还是在于思考而非盲从.

本文的作者Nick HeudeckerSystem Mobile软件咨询公司的创建人,该公司位于芝加哥,专门从事Java web应用程序开发.

 

 

正文

 

第一部分 理论 

 

深入Wicket核心

 

当我们学习一门新技术或框架时,先会去理解其术语和概念,然后将所学的拼凑在一起来运用.Wicket只有很少一部分核心概念需要掌握,并且一旦你理解了,你会发现这个框架相对于其它框架来说更易于接受.那么就请先让我从核心词汇“组件(components)”谈起吧.

 

组件

 

如果你是一名软件开发人员,那么组件的概念再熟悉不过了:组件就是在相同接口下,可以替换其他组成部分的可复用的软件组成部分.在Wicket里,组件就是诸如links, textimages此类的东西.当然,组件也可能是一大块标记(markup),将其它组件纳入其中,或者你也可以用来显示国际化的图片.

所有的Wicket组件都被设计成可扩展的并且扩展相当简单,比如说一个匿名类可以跳转到另一个页面.如果你服务器端有很多重复的组件(比如说“查找模块”),你可以将其封装成简单可复用的组件.

组件可以被添加到其它特殊的一类组件中去,比如说MarkupContainerMarkupContainer的特殊之处在于除了必要的Java代码之外,还与标记文件(markup fileHTML)关联在一起.PagesPanels是最常用的两个MarkupContainer子类.在稍后的例子中,我们将会看到.

现在我们来看一个包括一些组件的简单页面:

 

【翻译】Wicket启示录——理论与实践(一)
            
    
    博客分类: 专家文章翻译 wicket领域模型框架TapestryWebwork 

 

在上面的图例中,我们的页面对象(Page Object)有多个组件,包括两个Panels,一个From

Form里面有drop downtext filed, radio buttons等,最后还有一个Link。这些被添加的子组件和其父组件结构上其实就是一棵倒立的树.

 

在页面上,组件的引用必须与后台代码结构一致.举例来说,如果你将一个Buttons放在<form>元素块外面,那么就会抛出一个异常(这类异常通常很难捕捉到,因此如果你在于开发模式下,Wicket为你提供了错误页面来显示相关信息)

 

【翻译】Wicket启示录——理论与实践(一)
            
    
    博客分类: 专家文章翻译 wicket领域模型框架TapestryWebwork 

 

【翻译】Wicket启示录——理论与实践(一)
            
    
    博客分类: 专家文章翻译 wicket领域模型框架TapestryWebwork 

 

 

模型(Models)

除非有特定领域数据(domain-specific data)需要通过组件来显示或操作,否则组件是没有意义的.尽管如此,除非组件知道如何去识别你应用程序中的每一个领域对象(domain object),否则你随便将一个域对象扔给组件也无济于事。因此,我们需要在组件与领域对象之间还存在一层抽象――它就是模型.在Wicket模型继承中,处于最顶层是IDetachable IModel

 

【翻译】Wicket启示录——理论与实践(一)
            
    
    博客分类: 专家文章翻译 wicket领域模型框架TapestryWebwork 

 

IDetachable的存在主要是为了支持模型的集群和分离,稍后我们会探讨一下.但多数情况下,你是不需要关心这个接口的.

模型封装了领域对象,为组件提供了可访问的数据模型.由模型所包含的对象叫模型对象(model object),下面是一个最简单的模型示例:

IModel nameModel = new Model("Chauncey Billups");




在上面的例子里,我们建了一个实现了IModel接口的模型对象,并且构造函数的参数是一个string.因为org.apache.wicket.model.Model类实现了java.io.Serializable接口,所以,传一个String参数完全没有问题.要使用Model的话,直接将它传给一个组件即可:

  Label playerName = new Label("playerName", nameModel);


当组件标记生成时,组件会调用IModelgetObject()方法将所得到的数据显示出来.


关于Wicket的状态管理(通过http://wicket.apache.org/introduction.html,你可以得到更加详细的内容),我们知道IModels是存在用户的session里面的,这就意味着被IModels所持有的模型对象也是存在session中.那么我们刚才传递的字符串“Chauncey Billups”同样也会占据session的一些空间.这对于类似于这样的小对象来说,根本不是问题.但如果是一些装有大的二进制图片对象的话,那很快就会让你焦头烂额.这个时候分离模型(detachable models)可以大显身手了.

分离模型,就是当用户的请求完成时将模型对象从模型中分离出来,确保在模型和组件存储完成后,当前模型对象不再占用任何资源.分离模型通常只要将最小限度的数据保存在对象上.如果你使用了持久层解决方案,这个数据也许仅仅就是便加载对象的主键.现在我们用分离模型来改写刚才的例子:

IModel nameModel = new LoadableDetachableModel() { 
    public Object load() { 
        return playerService.getPlayerName(); 
   }
}




LoadableDetachableModel实现了IModel接口,因此用法与其它模型类一样.现在我们看看LoadableDetachableModelgetObject()方法是怎么实现的:

  public Object getObject() {
      if (!attached) {
         attached = true;
         transientModelObject = load();
         if (log.isDebugEnabled()) {
              log.debug("...");
        }
       onAttach();
    }
    return transientModelObject;
}


 

getObject()方法实际上非常简单.如果你使用Hiberante或其它持久层方案,尽可能的多使用LoadableDetachableModels从而确保你的对象不会占用过多不必要的session资源.

到目前为止,我们已经看了两个IModel实现了,但当我们开始Wicket之旅时,还有一些更有用的组件.你可以使用熟悉的装饰器模式将这些模型整合在一起.假设你的一个领域模型在某个页面多处被使用.没有必要为每个组件加载一遍对象.CompoundPropertyModel就可以轻松帮你搞定:

IModel playerModel =

new CompoundPropertyModel(new LoadableDetachableModel(){
public Object load() {
        return playerService.getPlayer();
});
setModel(playerModel);

 

 

Wicket是通过组件的ID来访问页面上的模型属性的.假设我们为该页面设置好了模型,组装这些模型值的组件非常麻烦:

add(new Label("firstName"));




注意此时Label组件会从模型对象中找一个叫“getFirstName”的方法.要是当前的Wicket ID值没有与设置的在页面上的模型对象属性相匹配怎么办?这时,我们可以使用PropertyModel来指定其它的属性名.

add(new Label("fname", new PropertyModel(getModel(), "firstName"));




除了访问属性更简单外,PropertyModel来可以访问集合或元素.

Wicket新手通常很难理解模型的概念,尤其是没有做过类似于Swing这样的框架开发的人更是一头雾水.记住,模型只有一个目的――为你的组件提供数据.那什么时候该用模型呢?永远只将模型传给组件,而不是领域对象.如果你现在还不是完全理解模型,别担心,接来的实例会更进一步的帮你理解模型的概念.

好了,我们已经回顾了组件(包括pagespanels)和模型的概念.接下来,我们开始研究WicketApplication class(注意,这里说的Application不是指应用程序,而是与Wicket有关的类).

 

源代码在下面的复件里面,JavaEye的编辑器还是有问题,一编辑后,代码就变成这模样了,等稳定了,我再调整一下吧.