JSF和MVC

来源:互联网 发布:数据库批处理 编辑:程序博客网 时间:2024/05/22 18:45
1.    JSFMVC
JSF 是几年前学过的在 Java 平台上改进 Web 开发技术的课程的结果。这一趋势开始于 JSP 技术,这一技术很好,只是很容易在 HTML(和类 HTML)页面中混合 Java 代码。下一次提高是 Model 1 架构,它让开发人员将大多数后端代码放入 JavaBeans 组件中,然后用 <jsp:useBean> 标签将 JavaBeans 组件导入 Web 页面。这对于简单的 Web 应用程序工作得很好,但是许多 Java 开发人员不喜欢 JSP 技术这种与 C++ 特性(比如静态包含)的协作。所以引入了 Model 2 架构。
本质上,Model 2 架构是用于 Web 应用程序的 MVC 的打了折扣的版本。在 Model 2 架构中,控制器是由 Servlets 来表示的,而显示则委派给 JSP 页面。Struts 是一种简化的 Model 2 实现,其中的 Actions 代替了 Servlets。在 Struts 中,应用程序的控制器逻辑是与它的数据(由 ActionForms 表示)相分离的。对于 Struts 的主要抱怨是,它感觉上更像过程化的,而不像面向对象的。WebWork 和 Spring MVC 是另外两个 Model 2 架构,它们更加不像过程化的,在 Struts 的基础上有所改进,但是它们仍然没有 Struts 那样被广泛接受(或者没有那么成熟,有人可能对此有争议)。并且也不提供像 JSF 提供的那些组件模型。
关于大多数 Model 2 框架的实际问题是,事件模型太简单了(本质上是一个非常缩小的 MVC), 这就给开发人员留下了太多的工作。更丰富的事件模型使得创建大多数用户期望的交互更加容易。像 JSP 技术一样,大多数 Model 2 也很容易利用 GUI 自定义标签来混合 HTML 布局和格式化,这些标签有点类似于组件。而有些 Model 架构(比如 Struts)出现分离行为与状态的错误,这让许多 Java 开发人员感觉自己是在进行 COBOL 编程。
2.    更丰富的 MVC 环境
       JSF 提供一个组件模型和一个比大多数 Model 2 实现更丰富的 MVC 环境。本质上,JSF 比 Model 2 架构更加接近于真正的 MVC 编程环境,尽管它仍然是一种无状态的协议。JSF 也比 Model 2 架构更方便构建更加细致的事件驱动 GUI。尽管 JSF 给了您很多事件选项(菜单项选择、按钮单击,等等),但是大多数 Model 2 依赖于更加简单的“请求接受”。
       JSF 的良好调优的事件模型,允许您的应用程序与 HTTP 细节的联系更少,并简化了开发。通过使得更加容易将表示和业务逻辑移出控制器,以及将业务逻辑移出 JSP 页面,JSF 也在传统的 Model 2 架构上有了一些改进。事实上,简单的控制器类根本与 JSF 没有联系,这使得它们更加容易测试。与真正的 MVC 架构不一样,JSF 模型层不可能发出许多必须在多个视窗(viewport)中解决的事件;此外,我们仍然在处理无状态的协议,所以这是没必要的。用于更改或更新视图的系统事件几乎总是用户请求。
3.    JSFMVC 实现细节
       JSF MVC 实现中,mapping backing beans(映射支持 beans)在视图和模型之间调停。因此,限制 backing beans 中的业务逻辑和持久性逻辑很重要。一个常见的替代方法是,将业务逻辑委派给应用程序模型。在这种情况下,backing beans 也映射模型对象,其中视图可以显示它们。另一种选项是,将业务逻辑放在 Business 代表中,后者充当模型。
       与 JSP 技术不一样,JSF 的视图实现是一个有状态的组件模型。JSF 视图包含两个部分:视图根和 JSP 页面。视图根是 UI 组件集合,这些组件维护 UI 的状态。与 Swing 和 AWT 一样,JSF 组件使用 Composite 设计模式来管理组件树(简单地说,容器包含组件,容器也是一个组件)。JSP 页面将 UI 组件绑定到 JSP 页面,并允许您将字段组件绑定到 backing beans 的属性(或者属性的属性),以及将按钮绑定到事件处理器和操作方法。
 
下面是一个从 MVC 角度来看的示例应用程序。
4.    示例应用程序:
1.     问题描述:该例是一个简单的 计算器 应用程序。
       创建该应用程序的目标是向终端用户呈现一个页面,让他/她输入两个数值。因此,该页面具有两个文本字段、两个标签、两个错误消息位置和一个 Submit 按钮。文本字段用于输入数值。标签用于标注字段。错误消息位置用于显示针对文本字段的验证或数据转换错误消息。
2.     分析:
       1) 视图:存在二个 JSP 页面:
       calculator.jsp,它呈现前面提到的 GUI;
       results.jsp,它显示结果。
2) 控制器(充当从模型到视图的粘合剂):一个叫做 CalculatorController 的托管 bean 充当 calculator.jsp 和 results.jsp 的 backing bean。
    3) 模型:Calculator类,负责实现两个数的加、减、乘、除的业务逻辑。
3.     示例应用程序的MVC 视图:
4.     构建应用程序:
       1) 创建名为calculatorApp的web应用程序:并配置好JSF环境
       2) 创建业务逻辑类:Calculator.java
package org.qiujy.service;
 
 
/**
 *计算器业务逻辑类
 *@authorAdministrator
 */
publicclass Calculator {
   
    /**
     *加法运算
     *@paramafirstNumber
     *@parambsecondNumber
     *@returnresult
     */
    publicdouble add(double a, double b){
        return a + b;
    }
    /**
     *减法运算
     *@parama
     *@paramb
     *@return
     */
    publicdouble subtract(double a, double b){
        return a - b;
    }
    /**
     *乘法运算
     *@parama
     *@paramb
     *@return
     */
    publicdouble multiply(double a, double b){
        return a * b;
    }
    /**
     *除法运算
     *@parama
     *@paramb
     *@return
     */
    publicdouble divide(double a, double b){
        return a / b;
    }
}
       3) 创建控制器(受管Bean)来粘接模型和视图:CalculatorController.java。
       控 制器的目标是充当从模型到视图的粘合剂。Controller 对象的其中一个功能是保持模型对于视图技术不可知。正如从下面可以看到的,控制器指定三个 JavaBeans 属性,这些属性将用于收集输入和显示结果。这三个属性是:results(输出)、firstNumber(输入)和 secondNumber(输入)。Controller 也呈现四个操作,它们委派给 Calculator 对象中相同名称的操作。
      
package org.qiujy.controller;
 
import org.qiujy.service.Calculator;
 
/**
 *受管Bean
 *
 *@authorAdministrator
 *
 */
publicclass CalculatorController {
    /** Representthemodelobject.*/
    private Calculator calculator = new Calculator();
    /**Firstnumberusedinoperation.*/
    privatedoublefirstNumber = 0;
    /**Resultofoperationonfirstnumberandsecondnumber.*/
    privatedoubleresult = 0;
    /**Secondnumberusedinoperation.*/
    privatedoublesecondNumber = 0;
 
    public Calculator getCalculator() {
        returncalculator;
    }
 
    publicvoid setCalculator(Calculator calculator) {
        this.calculator = calculator;
    }
 
    publicdouble getFirstNumber() {
        returnfirstNumber;
    }
 
    publicvoid setFirstNumber(double firstNumber) {
        this.firstNumber = firstNumber;
    }
 
    publicdouble getResult() {
        returnresult;
    }
 
    publicvoid setResult(double result) {
        this.result = result;
    }
 
    publicdouble getSecondNumber() {
        returnsecondNumber;
    }
 
    publicvoid setSecondNumber(double secondNumber) {
        this.secondNumber = secondNumber;
    }
 
    /**
     *Addsthefirstnumberandsecondnumbertogether.
     *@returnnextlogicaloutcome.
     */
    public String add() {
        result = calculator.add(firstNumber, secondNumber);
        return"success";
    }
 
    public String subtract() {
        result = calculator.subtract(firstNumber, secondNumber);
        return"success";
    }
 
    /**
     *Multipliesthefirstnumberandsecondnumbertogether.
     *@returnnextlogicaloutcome.
     */
    public String multiply() {
        result = calculator.multiply(firstNumber, secondNumber);
        return"success";
    }
 
    public String divide() {
        result = calculator.divide(firstNumber, secondNumber);
        return"success";
    }
}
       4) 在faces-config.xml文件中声明受管Bean和导航规则:
<managed-bean>
    <managed-bean-name>CalcBean</managed-bean-name>
    <managed-bean-class>
        org.qiujy.controller.CalculatorController
    </managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>
       上面的配置告诉 JSF,您想要将一个 受管bean 添加到叫做 CalcBean 的 JSF 上下文。您可以向自己的受管 bean 调用任何事情。
      
<navigation-rule>
    <from-view-id>/calculator.jsp</from-view-id>
    <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/result.jsp</to-view-id>
    </navigation-case>
</navigation-rule>
       上面的导航规则指出,如果一个操作从 /calculator.jsp 视图返回逻辑结果“success”,那么就会将用户转向 /results.jsp 视图。
       5) 创建calculator.jsp和result.jsp:
<%@ page language="java" pageEncoding="GBK"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
 
<html>
         <head>
                   <title>My JSF 'calculator.jsp' starting page</title>
         </head>
 
         <body>
                   <f:view>
                            <h:form id="calcForm">
                                     <h:panelGrid columns="3">
                                               <h:outputLabel value="第一个数" for="firstNumber" />
                                               <h:inputText id="firstNumber" value="#{CalcBean.firstNumber}"
                                                        required="true" />
                                               <h:message for="firstNumber" />
                                               <h:outputLabel value="第二个数" for="secondNumber" />
                                               <h:inputText id="secondNumber" value="#{CalcBean.secondNumber}"
                                                        required="true" />
                                               <h:message for="secondNumber" />
                                     </h:panelGrid>
                                     <h:panelGroup>
                                               <h:commandButton id="submitAdd" action="#{CalcBean.add}"
                                                        value="" />
                                               <h:commandButton id="submitSubtract" action="#{CalcBean.subtract}"
                                                        value="" />
                                               <h:commandButton id="submitMultiply" action="#{CalcBean.multiply}"
                                                        value="" />
                                               <h:commandButton id="submitDivide" action="#{CalcBean.divide}"
                                                        value="" />
                                     </h:panelGroup>
 
                            </h:form>
                   </f:view>
         </body>
</html>
       命令按钮使用 action="#{CalcBean.add}" 将按钮绑定到 backing bean 上的一个方法。因此,当用按钮提交表单时,关联的方法就会被调用。
<%@ page language="java" pageEncoding="GBK"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
 
<html>
         <head>
                   <title>My JSF 'calculator.jsp' starting page</title>
         </head>
 
         <body>
                   <f:view>
                   第一个数: <h:outputText id="firstNumber" value="#{CalcBean.firstNumber}" />
                            <br />
                第二个数: <h:outputText id="secondNumber" value="#{CalcBean.secondNumber}" />
                            <br />
                结果: <h:outputText id="result" value="#{CalcBean.result}" />
                            <br />
                   </f:view>
         </body>
</html>
 
       6) 部署,调试:
 
源码:
 无法上传附件,需要都与我联系。
5.    小结:
       以防您还认为用 Struts 编写应用程序容易一些,我做了一个估计,创建本文的这个简单的 JSF 应用程序的 Struts 版本,至少要花费相当于这里所花费的两倍的精力。要用 Struts 构建这个相同的示例应用程序,需要两个操作类用于两个按钮,每个类又需要它自己的一组操作映射。您还需要一个操作映射用于加载第一个页面,这是在至少假设 您遵循 Model 2 推荐的条件下的情况。要模仿 JSF 默认错误处理和验证,还必须配置 Struts 使用验证器框架,或者在 ActionForm 上的 validate 方法中实现等价的操作。您必须要么在 Struts 配中声明一个 DynaValidatorForm,要么创建一个 ActionForm 并覆盖 validate 方法,要么使用 ValidatorForm 的子类,并在验证器框架中放置钩子。最后,可能需要配置一些转向(可能是每个操作两组)或者一些由所有操作使用的全局转向。
       除了加倍编码工作之外,Struts 要花费新开发人员更多的精力去学习它。开发人员学习 JSF 容易,而学习 Struts 困难。我相信,JSF 设计中比 Struts 中考虑了更多的长远因素。JSF 只是更加逻辑性一些,但是它也是直观的。Struts 是被收集和演变的。JSF 是被指定和创建的。
 
原创粉丝点击