Struts 框架之构建 Model组件

1/5/2008来源:Java教程人气:5862


  Model就是在对用户请求的整个控制过程中,真正处理用户请求并保存处理结果的对象,在整个过程中,我们一般利用javaBean来把一些信息保存起来以便在各个对象之间传递。因为在框架中,Model对象是真处理商业逻辑功能的对象,因此也就是框架中应用需求实现相关性最大的的部分。在Struts的实现里,Model的具体表现形式就是ActionForm对象和与其对应的Action对象了。对用户提交表单的数据进行校验,甚至对数据进行预处理都能在ActionForm中完成。通常的应用中,一般是一个Model对象和一个请求页面对应的关系,但也可以一个Model对象对应多个页面请求。假如struts-config.xml配置文件没有指定一个Model对象对应的Action,那么控制器将直接把(通过Model对象完成数据封装的)请求转到一个View对象。下图表示的是Model layer 的层次结构。
  
  在Struts中Model以一个或多个java bean的形式存在。这些bean分为三类:Action Form、Action、JavaBean or EJB。Action Form通常称之为FormBean,封装了来自于Client的用户请求信息,如表单信息。Action通常称之为ActionBean,获取从ActionSevlet传来的FormBean,取出FormBean中的相关信息,并做出相关的处理,一般是调用JavaBean或EJB等。
  
  许多需求文档将构建Web应用的焦点集中在视图上。我们必须确保每一个提交的请求都在模型视图中都已经被定义。通常,开发者在模型组件中关注于开发JavaBean类以实现所有的功能需求。 应用应该准确的使用哪些beans,根据其需求不同而差异巨大,但是,在经过区分后通常都能分被为若干个类别。
  
  创建Model 组件
  1、JavaBeans
  
  在一个Web基础的应用中,能使用许多不同的"属性(attributes)"集合来保存(和访问)JavaBeans。 每个集合都有它自己不同的生命周期和beans存储在哪里的可见度。 同时,beans通过 作用域 来定义生命周期和可见度规则。 在JavaServer Pages (jsp)规范中定义了作用域选择使用以下几项(在括号中是servlet API中的等价概念定义)。
  
  page :Beans只会在一个JSP页中可见,只在当前的请求周期中存在。 (在 service 方法中的本地变量)
  
  request : Beans只会在一个JSP页中可见,与page相同或servlet包含本页,或转发到本页。 (Request属性)
  
  session :Beans能被所有的JSP页和servlet通过特定的用户session来使用, 它可以跨越一个或多个请求。 (Session属性)
  
  application :Beans能被Web应用中的所有JSP页和servlets来使用。 (Servlet context属性)
  我们需要记住的是在一个web应用中JSP页面和servlet会共享bean集合的设置。 例如在一个servlet中将一个bean存储到attribute中如下:
  
  MyStudy Mystudy = new MyStudy(...);
  request.setAttribute("cart", MyStudy);
  
  在这个servlet将请求转发给一个JSP页面后,我们马上可以使用标准的动作标签(tag)来看到相应的值:
  
  < jsp:useBean id="cart" scope="request" class="com.mycompany.MyApp.MyStudy"/ >
  
  2、ActionForm Beans
  
  在 actionform beans频繁地有属性相当于属性在我们的model beans的时候,那form beans它们自己应该考虑成为一个控制器组件。 同样地,他们能在模型和视图层之间传递资料。
  
  Struts框架通常假定我们在我们的应用中已经为输入定义一个 ActionForm beans(简而言之,一个扩展自 ActionForm 类的Java类)。 ActionForm beans有时仅仅调用表单beans(form beans)。 这可能会是一个细粒度的对像,它让每个表单对应一个bean,还有就是一个bean服务于若干个表单甚至全部应用形成粗粒度的情况。
  
  假如在我们的Struts配置文件中定义了bean,Struts的controller servlet在调用适当的 Action 方法前将自动为我们提供如下服务:
  
  使用适当的要害字检查在用户适当的作用域(request或session)中是否有适当类的bean的一个实例。
  假如没有这样的实例可用,则自动建立一个新的bean实例并将期加入到适当的作用域中(request或session)。
  
  对于每个请求参数通过其名称来对应到bean的一个属性(PRoperty)上,并调用相应的setter方法来设置属性值。 这个方法类似于标准JSP中以以通配符"*"来使用 < jsp:setProperty > 标记。
  更新后的 ActionForm bean被传递给 Action 类[ org.apache.struts.Action ] 的 execute 方法, 以使这些值能被我们的系统状态和业务逻辑bean来使用。
  
  我们应该注重一个"表单(form)"在这里并不是必须对应于用户界面中一个单独的JSP页面。 在很多应用程序中一个"表单"(从用户的观点)延伸至多个页面也是很平常的。 想想看,例如,在新程序的安装时所使用的导航程序的用户界面。 Struts鼓励我们定义一个包含所有字段属性的单独的 ActionForm bean, 而不用管这些字段实际显示于哪个页面上。同样的,同一表单的不同页面应提交到相同的Action类。 假如我们遵照这个建议,在大多数情况下,页面设计者可以重新组织不同页面中的字段而不需要改变处理逻辑。
  
  一个小的应用也许只需要一个ActionForm来为所有的输入表单提供服务。 其它应用可以为每个大的子系统来分别使用一个ActionForm。 还有一些人可能更喜欢为每一个输入表单或工作流分别使用不同的ActionForm类。 真正如何使用ActionForm完全在于我们,框架自身并不在意的。
  
  ActionForm 接口本身不需要非凡的实现方法。它是用来标识这些特定的beans在整个体系结构中的作用。典型情况下,一个 ActionForm bean只包括属性的get方法和set方法,没有商业逻辑。
  
  通常在一个 ActionForm bean中只有很少的输入验证逻辑。这样的beans存在的主要理由是保存用户为相关的表单所输入的大部分近期值,这样同样的页面可以被重建,伴随有一组出错信息,这样用户仅仅需要纠正错误的字段。用户输入的验证应该在 Action 类中执行(假如是很简单的话),或者在适当的商业逻辑beans中执行。
  
  为每个表单中出现的字段定义一个属性(用相关的getXxx()和setXxx()方法)。字段名和属性名必须按照JavaBeans的约定相匹配。例如,一个名为 username 的输入字段将引起 setUsername() 方法被调用。
  
  下面是ActionForm类的具体描述:
  
  ActionForm类
  框架假设用户在应用程序中为每个表单都创建了一个ActionForm bean,对于每个在struts-config.xml文件中定义的bean,框架在调用Action类的perform()方法之前会进行以下操作:
  
  1、在相关联的要害字下,它检查用于适当类的bean实例的用户会话,假如在会话中没有可用的bean,它就会自动创建一个新的bean并添加到用户的会话中。
  
  2、对于请求中每个与bean属性名称对应的参数,Action调用相应的设置方法。
  
  3、当Action perform()被调用时,最新的ActionForm bean传送给它,参数值就可以立即使用了。
  
  ActionForm类扩展org.apache.struts.action.ActionForm类,程序开发人员创建的bean能够包含额外的属性,而且ActionServlet可能使用反射(答应从已加载的对象中回收信息)访问它。
  
  ActionForm类提供了另一种处理错误的手段,提供两个方法:
  
  Public ActionErrors validate(ActionMappin mapping,ServletRequest request)
  Public ActionErrors validate(ActionMappin mapping,HttpServletRequest request)
  
  我们应该在自己的bean里覆盖validate()方法,并在配置文件里设置<action>元素的validate为true。在ActionServlet调用Action类前,它会调用validate(),假如返回的ActionErrors不是null,则ActinForm会根据错误要害字将ActionErrors存储在请求属性列表中。
  
  假如返回的不是null,而且长度大于0,则根据错误要害字将实例存储在请求的属性列表中,然后ActionServlet将响应转发到配置文件<action>元素的input属性所指向的目标。
  
  假如需要执行特定的数据有效性检查,最好在Action类中进行这个操作,而不是在ActionForm类中进行。
  
  方法reset()可将bean的属性恢复到默认值:
  
  public void reset(ActionMapping mapping,HttpServletRequest request)
  public void reset(ActionMapping mapping,ServletRequest request)
  
  典型的ActionFrom bean只有属性的设置与读取方法(getXXX),而没有实现事务逻辑的方法。只有简单的输入检查逻辑,使用的目的是为了存储用户在相关表单中输入的最新数据,以便可以将同一网页进行再生,同时提供一组错误信息,这样就可以让用户修改不正确的输入数据。而真正对数据有效性进行检查的是Action类或适当的事务逻辑bean。
  
  3、系统状态Beans
  
  系统的实际状态通常表示为一组一个或多个JavaBean类,其属性定义了当前的状态。 例如,在一个购物车系统中,将包括一个表示购物车的bean,这个bean为每个购物者所维护, 它包括了购物者所选择购买的物品条目。 另外,系统也包括保存用户信息(包括他们的信用卡和送货地址)、可获得的条目和当前库存水平这些不同的bean。
  
  对于小规模系统,或是对于不需要长时间保存的状态信息,一组系统状态bean可以包含 所有系统曾经经历的特定细节的信息。 或者经常是,系统状态bean会表示永久保存在一些外部数据库中的信息(例如 CustomerBean 对象对应于CUSTOMERS表中特定的一行数据), 在需要时从服务器的内存中创建或清除。Entity Enterprise JavaBeans也是用于这种用途的。
  
  4、商业逻辑Beans
  
  我们应该把