框架:闲谈JavaServer Faces的解决方案

 

当我们点击其中一个edit时,我们打开editname.jsp来编辑选中的用户姓名。问题来了,如何在显示网页之前,先将First name及Last name的值设好?

可有两种解决方案。

第 一种静态绑定。这是从网页开发者的角度为出发点,将editname.jsp文件中First name与Last name的域与某个backing bean的属性相绑定,然后在跳转页面前在backing bean中先将First name与Last name的值设好。

例 如,当用户点击edit时,其backing bean(这里假设为tableData)马上通过一个实例变量currentName将当前的name记下来。然后,返回一个页面导航的字符串,将 request转至editname.jsp。而editname.jsp文件中通过以下代码,将tableData中currentName的 firstName与lastName读取过来:

< h:inputText id="firstName" value="#{tableData.currentName.first}" />
< h:inputText id="lastName" value="#{tableData.currentName.last}" />

这种方式比较直观,但也有几个缺点:
一是需要设置额外的类变量,如currentName。
二是需要进行额外的操作,在页面跳转前需设置currentName的值。
三 是引用属性的层数不能超过3层,如tableData.currentName.first,已经是3层。假如我们将name放在一个名为User的对象 中,引用将变成tableData.currentUser.name.first。此时,JSF将不能设置first的值,如果后面紧跟着页面跳转,则 页面跳转失败,总是返回到当前页中,却不会发出任意错误提示。尤其是在这种场合下使用< h:selectOneMenu>等控件,问题更加扑朔迷离而不易解决。

第 二种方案,是从Java编程的角度出发的,通过设置控件的binding属性,将控件与backing bean中相应的控件直接绑定,并在backing bean的Java代码中进行赋值操作。这种方法的优点是我们可以在Java代码中直接访问控件,并很方便地设置其各类属性。在jsp中设置组件 binding属性的方法如下:

< h:inputText binding="#{tableData.firstNameControl}" />
< h:inputText binding="#{tableData.lastNameControl}" />


而在TableData中,必须为它们设置相应的控件:

public class TableData {
    private HtmlInputText firstNameControl;
    private HtmlInputText lastNameControl;

    private ArrayDataModel model;
   
    private Name[] names = new Name[] {
        new Name("William", "Dupont"),
        new Name("Anna", "Keeney"),
        new Name("Mariko", "Randor"),
        new Name("John", "Wilson")
    };

    public DataModel getNames() {
        model = new ArrayDataModel(names);
        return model;
    }

    public String editName() {
        FacesContext fc = FacesContext.getCurrentInstance();
        Application app = fc.getApplication();
       
        if (firstNameControl == null) {
            firstNameControl = (HtmlInputText)app.createComponent(HtmlInputText.COMPONENT_TYPE);
        }
        if (lastNameControl == null) {
            lastNameControl = (HtmlInputText)app.createComponent(HtmlInputText.COMPONENT_TYPE);
        }

        Name currentName = (Name)model.getRowData();
       
        firstNameControl.setId("firstName");
        firstNameControl.setValue(currentName.getFirst());
       
        lastNameControl.setId("lastName");
        lastNameControl.setValue(currentName.getLast());
       
        return "editName";
    }

    public HtmlInputText getFirstNameControl() {
        return firstNameControl;
    }

    public void setFirstNameControl(HtmlInputText firstNameControl) {
        this.firstNameControl = firstNameControl;
    }

    public HtmlInputText getLastNameControl() {
        return lastNameControl;
    }

    public void setLastNameControl(HtmlInputText lastNameControl) {
        this.lastNameControl = lastNameControl;
    }
 …
}

关于TableData的几点说明:
1. Java代码的HtmlInputText与jsp中的< h:inputText>相对应。
2. 方法getNames()返回一个DataModel而不是Name[],是因为DataModel可以感知用户点击了哪一项记录。因此,我们可以使用 Name currentName = (Name)model.getRowData();来自动获取所点击的记录。
3. 当用户点击edit时,转入执行editName()方法。此时editname.jsp页面还未显示,该页面中的< h:inputText binding="#{tableData.firstNameControl}" />及< h:inputText binding="#{tableData.lastNameControl}" />还未创建。因此需要在代码中创建它们。
4. 创建后,通过model.getRowData()获取当前用户点击的名字,并分别赋值于它们。
5. 最后,给Navigation返回一个表示页面跳转的字符串,转至显示editname.jsp。
6. 由于TableData已经为创建好组件,editname.jsp就可以正常显示了。

这两种方案,第一种比较直观,比较适合页面编辑人员。第二种比较灵活,比较适合喜欢在后台“搞鬼”的Java编程人员。

熟 悉Struts的用户对比之后,会感觉还是Struts比较方便,设置相应的action,为此action指定相应的form,然后在Action的 execute()方法中设置form就行了。的确,在这一点上,Struts的Action与Form分离得很好,但太严的规则往往意味着不自由。尤其 是Action,一是必须逐一设置,设多了比较累人;二是不是任何场合下都可以自由使用Action,这是Struts最大的弊端。

JavaServer Faces最大的特点是让用户不再与HttpRequest这种比较底端的对象直接打交道,即使在页面编写过程中,也是通过各种控件来构建Html页面, 并编写各种事件处理方法。这种方式,与传统的桌面程序开发很类似,与VB,.Net的解决方案很相似。一旦习惯于这种思维方式,就会觉得 JavaServer Faces更加贴切于用户。而一旦决定使用JavaServer Faces,就必须学会从它的角度来思考问题,解决问题。

当然,最佳的选择是认真研究与比较JSF与Struts的特点与区别,扬长避短,在普遍使用JSF的同时,逐渐融进Struts的思想,将使我们的程序更加强大与稳健。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值