struts:Struts用户指南

  1. 介绍

  1.1 Model-View-Controller (MVC) 设计模式

  FIXME - 需要个对该模式般性介绍(译注:可以参考机械工业出版社设计模式)

  1.2 将MVC概念映射到Struts组件中

  Struts 体系结构实现了Model-View-Controller设计模式概念它将这些概念映射到web应用组件和概念中.

  这体系结构中每个主要组件都将在下面做详细讨论

  1.3 Model: 系统状态和商业逻辑JavaBeans

  基于MVC系统中 Model 部分可以细分为两个概念 -- 系统内部状态, 能够改变状态行为用语法术语来说我们可以把状态信息当作名词(事物)把行为当作动词(事物状态改变)

  通常说来应用将系统内部状态表示为个或多个JavaBeans使用属性(properties)来表示状态细节依赖于你应用复杂度这些beans可以是自包含(以某种方式知道怎样永久地保存它们状态信息)或者可以是正面(facades)知道当被请求时怎样从外部数据源(例如数据库)中取得信息Entity EJBs通常也用来表示内部状态

  大型应用经常将系统可能商业逻辑行为表示为可以被维护状态信息beans思路方法举个例子你有个为每个当前用户保存在session中购物车bean里面是表示当前用户决定购买物品属性这个bean有个checkOut思路方法用来验证用户信用卡将定单发给库房以选择货品和出货系统分别地表示同样行为或许使用Session EJBs

  在些小型应用同样行为又可能嵌入到作为Controller部分 Action 类中这在逻辑非常简单或者并不想要在其它环境中重用这些商业逻辑时是恰当Struts框架支持所有这些思路方法但建议将商业逻辑(“做什么”)和 Action 类(“决定做什么”)分离开

  1.4 View: JSP页面和表示组件

  基于Struts应用 View 部分通常使用JSP技术来构建JSP页面包含称为“模版文本”静态HTML(或XML)文本加上插入基于对特殊行为标记解释动态内容JSP环境包括了其用途由JSP规范标准来描述套标准行为标记例如 <jsp:useBean> 另外还有个用来定义你自己标记标准机制这些自定义标记组织在“定制标记库”中

  Struts包括了个广阔便于创建用户界面并且充分国际化定制标记库和作为系统 Model 部分部分ActionForm beans美妙地相互配合这些标记使用将在后面做详细讨论

  除了JSP页面和其包含行为及定制标记商业对象经常需要能够基于它们在被请求时当前状态将自己处理成HTML(或XML)从这些对象处理过输出可以很容易地使用 <jsp:> 标准行为标记包括在结果JSP页面中

  1.5 Controller: ActionServlet和ActionMapping

  应用 Controller 部分集中于从客户端接收请求(典型情况下是个运行浏览器用户)决定执行什么商业逻辑功能然后将产生下步用户界面责任委派给个适当View组件在Struts中controller基本组件是个 ActionServlet 类servlet这个servlet通过定义组映射(由Java接口 ActionMapping 描述)来配置每个映射定义个和所请求URI相匹配路径和个 Action 类(个实现 Action 接口类)完整类名这个类负责执行预期商业逻辑然后将控制分派给适当View组件来创建响应

  Struts也支持使用包含有运行框架所必需标准属性的外附加属性 ActionMapping 类能力这允许你保存特定于你应用附加信息同时仍可利用框架其余特性另外Struts允许你定义控制将重定向到逻辑名这样个行为思路方法可以请求“主菜单”页面(举例)而不需要知道相应JSP页面实际名字是什么这个功能极大地帮助你分离控制逻辑(下步做什么)和显示逻辑(相应页面名称是什么)

  2. 创建Model组件

  2.1 概述

  你用到应用需求文档很可能集中于创建用户界面然而你应该保证每个提交请求所需要处理也要被清楚定义通常说来Model 组件开发者集中于创建支持所有功能需求JavaBeans类个特殊应用要求beans精确特性依赖于具体需求变化会非常但是它们通常可以分成下面讨论几种类型然而首先对“范围”概念做个简短回顾是有用它和beans有关

  2.2 JavaBeans和范围

  在个基于web应用JavaBeans可以被保存在(并从中访问)些区别“属性”集合中个集合都有集合生存期和所保存beans可见度区别规则说来定义生存期和可见度这些规则被叫做这些beans 范围 JSP规范标准中使用以下术语定义可选范围(在圆括号中定义servlet API中等价物):

  page - 在个单独JSP页面中可见Beans生存期限于当前请求(service思路方法中局部变量)

  request - 在个单独JSP页面中可见Beans也包括所有包含于这个页面或从这个页面重定向到页面或servlet(Request属性)

  session - 参和个特定用户session所有JSP和servlet都可见Beans跨越个或多个请求(Session属性)

  application - 个web应用所有JSP页面和servlet都可见Beans(Servlet context属性)

  记住同个web应用JSP页面和servlets共享同样组bean集合是很重要例如个bean作为个request属性保存在个servlet中就象这样:

  MyCart mycart = MyCart(...);

  request.Attribute("cart", mycart);

  将立即被这个servlet重定向到个JSP页面使用个标准行为标记看到就象这样:

  <jsp:useBean id="cart" scope="request"

  ="com.mycompany.MyApp.MyCart"/>

  2.3 ActionForm Beans

  Struts框架通常假定你已经为每个你应用中请求输入创建了个 ActionForm bean(即个实现了 ActionForm 接口类)如果你在你 ActionMapping 配置文件中定义了这样beans(见“创建Controller组件”)Strutscontroller servlet在适当 Action 思路方法前将自动为你执行如下服务:

  用适当关键字检查用户session中是否有适当bean个例子

  如果没有这样session范围bean自动建立个新bean并添加到用户session中

  对每个名字对应于bean中个属性请求参数相应思路方法这个操作类似于当你以通配符“*”选择所有属性使用标准JSP行为标记 <jsp:Property>

  更新ActionForm bean在被时将被传递给Acton类perform思路方法以使这些值能够立即生效

  当你在写你ActionForm beans时记住以下原则:

  ActionForm 接口本身不需要特殊实现思路方法它是用来标识这些特定beans在整个体系结构中作用典型情况下个ActionForm bean只包括属性get思路方法和思路方法没有商业逻辑

  通常在个ActionForm bean中只有很少输入验证逻辑这样beans存在主要理由是保存用户为相关表单所输入大部分近期值 -- 甚至在被检测到时 -- 这样同样页面可以被重建伴随有组出错信息这样用户仅仅需要纠正字段用户输入验证应该在 Action 类中执行(如果是很简单话)或者在适当商业逻辑beans中执行

  为每个表单中出现字段定义个属性(用相关getXxxXxx思路方法)字段名和属性名必须按照JavaBeans约定相匹配例如个名为 username 输入字段将引起 Username 思路方法被

  你应该注意个“表单”在这里讨论时意义并不必须对应于用户界面中个单独JSP页面在很多应用个“表单”(从用户观点)延伸至多个页面也是很平常想想看例如通常在安装新应用时使用导航安装用户界面Struts鼓励你定义个包含所有字段属性单独ActionForm bean不管字段实际上是显示在哪个页面上同样表单区别页面应该提交到相同Action类如果你遵照这个建议在大多数情况下页面设计者可以重新组织区别页面中字段而不需要改变处理逻辑

  2.4 系统状态Beans

  系统实际状态通常表示为个或多个JavaBeans类其属性定义当前状态例如个购物车系统包括个表示购物车bean这个bean为每个单独购物者维护这个bean中包括(在其它事物的中)组购物者当前选择购买项目分别地系统也包括保存用户信息(包括他们信用卡和送货地址)、可获得项目目录和它们当前库存水平区别beans

  对于小规模系统或者对于不需要长时间保存状态信息组系统状态beans可以包含所有系统曾经经历特定细节信息或者经常是系统状态beans表示永久保存在些外部数据库中信息(例如CustomerBean对象对应于表 CUSTOMERS 中特定行)在需要时从服务器内存中创建或清除在大规模应用Entity EJBs也用于这种用途

  2.5 商业逻辑Beans

  你应该把你应用功能逻辑封装成对为此目设计JavaBeans思路方法这些思路方法可以是用于系统状态beans相同部分或者可以是在专门执行商业逻辑独立类中在后种情况下你通常需要将系统状态beans传递给这些思路方法作为参数处理

  为了代码最大可重用性商业逻辑beans应该被设计和实现为它们不知道自己被执行于web应用环境中如果你发现在你bean中你必须import个 javax.servlet.* 类你就把这个商业逻辑捆绑在了web应用环境中考虑重新组织事物使你 Action 类(Controller任务部分在下面描述)翻译所有从HTTP请求中请求被处理为对你商业逻辑beans属性思路方法信息然后可以发出个对 execute 这样个商业逻辑类可以被重用在除它们最初被构造web应用以外环境中

  依赖于你应用复杂度和范围商业逻辑beans可以是和作为参数传递系统状态beans交互作用普通JavaBeans或者使用JDBC访问数据库普通JavaBeans而对于较大应用这些beans经常是有状态或无状态EJBs

  2.6 题外话: 访问关系数据库

  很多web应用利用个关系数据库(通过个JDBC driver访问)来保存应用相关永久数据 其它应用则使用Entity EJBs来实现这个目他们委派EJBs自己来决定怎样维护永久状态如果你是使用EJBs来实现这个目遵照EJB规范标准中描述客户端设计模式

  对于基于直接数据库访问web应用个普通设计问题是当需要访问低层数据库时怎样产生个适当JDBC连接对象解决这个问题有几种思路方法 -- 以下原则描述了推荐种思路方法:

  创建或得到个允许组数据库连接被多个用户共享ConnectionPool类Struts(当前)没有包括这样个类但是有很多这样类可以得到

  当应用化时在应用展开(deployment)描述符中定义个有个“启动时加载”值servlet我们将把这个servlet叫做 启动 servlet在大多数情况下这个servlet不需要处理任何请求所以没有个 <servlet-mapping> 会指向它

  在启动servlet init 思路方法中配置并个ConnectionPool类例子将其保存为个servlet context属性(从JSP观点看等同于个application范围bean)通常基于传递给启动servlet化参数来配置联接缓冲池是很方便

  在启动servlet destroy 思路方法中包含了释放联接缓冲池所打开联接逻辑这个思路方法将在servlet容器结束这个应用时候被

  当 Action 类需要个需要数据库联接商业逻辑bean中思路方法(例如“insert a customer”)时将执行下面步骤:

  为这个web应用从servelt context属性中得到个联接缓冲池对象

  联接缓冲池对象 open 思路方法来得到个在 Action 类中使用联接

  商业逻辑bean中合适思路方法将数据库联接对象作为个参数传递给它

  分配联接中 close 思路方法这将引起这个联接为了以后其它请求重用被返回到缓冲池中

  个通常编程是忘记了把数据库联接返回给缓冲池这将最终导致用完所有联接定要确信 Action 类逻辑总是返回联接甚至在商业逻辑bean抛出个违例时

  遵照上面推荐设计模式意味着你能够编写你商业逻辑类而不需要担心它们怎样得到个JDBC联接来使用-- 简单地在任何需要访问数据库思路方法中包含个Connection参数当你商业逻辑类在个web应用中被利用时分配和释放适当联接是 Action 类责任当你使用相同商业逻辑类时例如个批处理工作中提供个适当联接是那个应用责任(这不需要从缓冲池中获得大多数批处理工作运行于个单线程环境中)

  3. 创建View组件

  3.1 概述

  这章集中于创建应用 View 组件任务主要使用JSP技术建立特别Struts除了提供了和输入表单交互外还提供了建立国际化应用支持几个其它和View相关主题也被简单地讨论

  3.2 国际化消息

  几年的前应用开发者能够考虑到仅仅支持他们本国只使用种语言(或者有时候是两种)和通常只有种数量表现方式(例如日期、数字、货币值)居民然而基于web技术应用爆炸性增长以及将这些应用展开在Internet或其它被广泛访问网络的上已经在很多情况下使得国家边界淡化到不可见这种情况转变成为种对于应用支持国际化(经常被称做“i18n”18是字母“i”和字母“n”的间字母个数)和本地化需求

  Struts建立于Java平台的上为建立国际化和本地化应用提供帮助需要熟悉关键概念是:

  Locale - 基础支持国际化Java类是 java.util.Locale 每个 Locale 代表个特别国家和语言选择(加上个可选语言变量)以及套格式假定例如数字和日期等等

  ResourceBundle - java.util.ResourceBundle 类提供支持多种语言消息基本工具查看文档中有关 ResourceBundle 类以及你JDK版本文档包中有关国际化更多内容

  PropertyResourceBundle - 个 ResourceBundle 类标准实现允许你使用和化properties文件同样“name=value”语法来定义资源这对于使用为用于个web应用消息准备资源包是非常方便这些消息通常都是面向文本

  MessageFormat - java.text.MessageFormat 类允许你使用运行时指定参数替换个消息串中部分(在这种情况下个从个资源包得到消息)这在你创建个句子场合中是有用但是词会以区别语言按照区别顺序出现消息中占位符串{0}用第个运行时参数替换{1}用第 2个运行时参数替换以此类推

  MessageResources - Struts类 org.apache.struts.util.MessageResources 使你能够将套资源包视做个数据库并且允许你为个特定Locale(通常是和当前用户相对应)请求个特定消息而不是为服务器运行在其中缺省Locale请求消息

  对于个国际化应用遵照JDK文档包中国际化文档所描述步骤来创建个包含每种语言消息属性文件下面举个例子介绍说明

  假设你源代码建立在包 com.mycompany.mypackage 中因此它保存于个叫做(相对于你源目录)com/mycompany/mypackage 目录中为创建个叫做 com.mycompany.mypackage.MyResources 资源包你应该在目录 com/mycompany/mypackage 中创建下列文件:

  MyResources.properties - 包含你服务器缺省语言消息如果你缺省语言是英语你可能有个这样条目:

  prompt.hello=Hello

  MyResources_xx.properties - 包含ISO语言编程为“xx”(查看ResourceBundleJava文档页面得到个当前列表联接)同样消息对于上面消息法语版你可以有这个条目:

  prompt.hello=Bonjour

  你可以有你需要任意多语言资源包文件

  当你在web应用展开描述符中配置controller servlet时你需要在化参数中定义件事是应用资源包基础名在上述情况中这应该是 com.mycompany.mypackage.MyResources

  3.3 表单和FormBean交互

  大部分web开发者曾经使用HTML标准性能来建立表单例如使用 <input> 标记用户希望交互具有行为这些期待中个和处理有关 -- 如果用户出现应用应该允许他们仅仅修改需要修改部分 -- 而不需要重新敲入当前页面或表单中任何其它信息

  使用标准HTML和JSP编程来完全实现这个期望是单调而繁重举例来说个用户名字段输入元素看起来可以象是这样(在JSP中)

  <input type="text" name="username"

  value="<%= loginBean.getUsername %>">

  这很难敲对会把没有编程概念HTML开发者搞糊涂并且会在HTML编辑器中造成问题取而代的Struts提供了种全面基于JSP 1.1定制标记库功能机制来建立表单上面情况使用Struts处理后将象是这样:

  <struts:text name="username"/>

  没有必要再显式地涉及到从中获得JavaBean这将由框架自动处理

  3.3.1 使用Struts建立表单

  个完整注册表单将演示Struts相对于直接使用HTML和标准JSP功能怎样极大地减轻了处理表单痛苦考虑以下称为logon.jsp页面(来自Struts例子):

<%@ page language="java" %>
  <%@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %>
  <html>
  <head>
  <title><struts:message key="logon.title"/></title>
  <body bgcolor="white">
  <struts:errors/>
  <struts:form action="logon.do" name="logonForm"
  type="org.apache.struts.example.LogonForm"/>
  <table border="0" width="100%">
  <tr>
  <th align="right">
  <struts:message key="prompt.username"/>
  </th>
  <td align="left">
  <struts:text name="username" size="16"/>
  </td>
  </tr>
  <tr>
  <th align="right">
  <struts:message key="prompt.password"/>
  </th>
  <td align="left">
  <struts:password name="password" size="16"/>
  </td>
  </tr>
  <tr>
  <td align="right">
  <struts:submit>
  <struts:message key="button.submit"/>
  </struts:submit>
  </td>
  <td align="right">
  <struts:re
  <struts:message key="button.re"/>
  </struts:re
  </td>
  </tr>
  </table>
  </struts:form>
  </body> </html>
   下面条目基于这个例子演示在Struts中处理表单关键特性:

Tags:  struts标签 struts2.0 struts2 struts

延伸阅读

最新评论

发表评论