Struts 是一种开源框架,可用来构建 Web 应用程序,它基于流行的 Model-View-Controller (MVC2) 设计范型。该框架构建在一些标准的技术之上,比如 Java Servlets、JavaBeans、ResourceBundles 和 XML,并且可提供灵活和可扩展的组件。Struts 以 ActionServlet
的形式实现了 Controller 层,并建议使用 JSP 标记库构建 View 层。Struts 通过 Action
类提供了围绕 Model 层的包装器。图 1 展示了基于 Model-View-Controller 设计的 Struts 框架。
|
首先,我们在最佳实践上下文中解释 Struts 组件,以及它们在 Web 应用程序开发中所起的作用。
应用程序的每个 Action
都会扩展 Struts 的 org.apache.struts.action.Action
类。这些 Action
类为应用程序的 Model 层提供了一个接口,充当围绕业务逻辑的包装器。每个 Action
类都必须向 perform()
方法提供其特定于用例的实现。perform()
方法经常返回类型 ActionForward
的一个值。
应用程序的 ActionForm
扩展了 Struts 的 org.apache.struts.action.ActionForm
类。ActionForm
是一些封装和验证请求参数的简单 JavaBean。要验证请求数据,ActionForm
的 validate()
方法必须给出一个特定于该情况的实现。ActionForm
作为运载工具,向 Action
类提供请求数据。一个 JSP 对象与各自的 ActionForm
对象相结合,构成应用程序的 View 层。在该层,几乎 JSP 对象的每个表单字段都映射到相应的 ActionForm
的属性。
JSP 定制标记库是用标记表示的一组行为的集合。这是 JSP Specification 1.1 的一个强大特性;它将其他应用程序层的表示区别了开来。这些库易于使用,而且可以以一种类似 XML 的方式来读取。只要尽量少地在其中使用 Java scriptlet,就可以轻松维护 JSP 组件。Struts 提供的 JSP 标记包括 HTML、逻辑和 bean 标记。
可以使用 ActionError
来支持异常处理。ActionError
捕捉应用程序异常,并将其传送给 View 层。每个异常都是一个 ActionError
实例的集合。ActionError
可以封装错误消息,而 Presentation 层中的 </html:errors>
可以呈现 ActionError
集合内的所有错误消息。
|
熟悉了 Struts 组件之后,就可以继续学习如何充分利用这一框架。首先,Struts 建议将每个 JSP 对象与一个 ActionForm
相关联,后者可以封装屏幕上显示的数据。可以通过 ActionForm
内的附加方法来访问 JSP 对象内的表单数据。清单 1 展示了 ActionForm
标记在 View 层中的传统方法。
<html:form action="/bp1"> <html:text property="attrib1" /> </html:form > |
这个 ActionForm
被称为 “BP1AForm
”,它包括属性 attrib1
及其 getter 和 setter 方法。在配置文件 struts-config.xml
中,行为 “/bp1
” 通过 name
属性映射到 bp1AForm
。这有助于在 JSP 中显示数据。
要实现这一最佳实践,Struts 建议您进行以下两个操作:
- 创建一个 JavaBean(
BP1BForm
),且其属性是BP1AForm
属性的子集,还要创建这些属性的 getter 和 setter 方法。 - 通过将这个 bean 与
BP1AForm
关联,用 beanBP1BForm
的属性替代BP1AForm
中的属性。现在就可以通过BP1BForm
访问BP1AForm
中的属性子集了。清单 2 展示了访问的方式。
<html:form action="/bp1"> <bean:define name="bp1AForm" property="bp1BForm" id="bp1B" type="com.ibm.dw.webarch.struts.BP1BForm" /> <html:text name="bp1B" property="subsetAtt1" /> </html:form > |
这种实践的主要优势是可用于多个 ActionForm
访问一个属性集。在遵循这一最佳实践的同时,需要记住以下几点:
- Struts 实现
<bean:define/>
标记。 - 当代码
<%@ taglib uri="struts-bean.tld" prefix="bean" %>
指向struts-bean.tld
时,<bean:define/>
标记开始在 JSP 组件内工作。 - 由
ActionForm
扩展而来的BP1AForm
验证框架必须验证BP1BForm
的数据。
当在应用程序中创建 Action
类时,不需要直接扩展 org.apache.struts.action.Action
,可以通过扩展 org.apache.struts.action.Action
创建一个 Action
类(IntermediateAction
),用于处理应用程序中的常见事务。所有其他的 Action
类都扩展 IntermediateAction
类。
|
通常,在使用这个 Struts 框架时,对于 JSP 组件请求应用程序执行的每个动作,应用程序都必须扩展 Struts 的 org.apache.struts.action.Action
以创建 Action
类。在处理请求时,单个的 Action
类与应用程序的 Model 层连接。
要实现这一最佳实践,Struts 建议您遵循以下步骤:
- 通过扩展
org.apache.struts.action.Action
创建一个Action
类,比如BP2Action
。 - 通过扩展
BP2Action
在 Web 应用程序中创建所有其他Action
类。 - 在
BP2Action
类中创建一个方法performTask()
,就像在公共抽象类ActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
中一样。 - 在
BP2Action
类中向应用程序添加一个或多个泛型方法,比如serverSideValidate()
。考虑以下因素后决定方法的访问修饰符:- 如果所有
Action
类都必须实现此方法,则让其为抽象。 - 如果某些
Action
类提供一个特定的实现,则将此方法声明为受保护,并给它一个默认实现。
- 如果所有
- 在
BP2Action
类中,将方法perform()
声明为 final。调用上述的泛型方法(通常在处理请求前调用该方法)。现在调用 步骤 3 中创建的方法performTask()
。 - 在每个扩展
BP2Action
的Action
类,添加具有特定实现的方法performTask()
。
这一实践有两个主要优势。首先,它避免了 Web 应用程序中每个 Action
类的冗余代码。其次,通过将 Action
类的行为集中在一起,使应用程序能够更多地控制通用的任务。
|
在一个基于 Struts 的 Web 应用程序中,每个 ActionForm
都扩展 org.apache.struts.action.ActionForm
类。这些 ActionForm
封装页面数据,并提供一个验证框架来验证请求参数。
大多数 Web 应用程序都在会话中保持数据,使其在整个应用程序过程中可用。这种最佳实践实现了这种 Web 应用程序特性。它允许方法 toSession()
和 fromSession()
将会话数据移动到表单数据或从表单数据移回。因此,它实现了在 Web 应用程序中保持会话数据。
要遵循一最佳实践,执行以下步骤:
- 通过扩展
org.apache.struts.action.ActionForm
创建一个名为BP3Form
的抽象类。 - 在
BP3Form
类中,添加具有访问修饰语的方法,就像在公共抽象类void toSession(SessionData sessionData)
和void fromSession(SessionData sessionData)
中一样。 - 在每个
ActionForm
类中,扩展BP3Form
并实现这些抽象方法(表单数据通过它们传递到会话或从会话传回)。 - 相应的
Action
类可以决定这些方法的调用顺序。例如,可以在决定actionForward
之前调用ActionForm
上的方法toSession()
。
这一实践最适用于:会话数据是单一对象和/或每个页操作或使用会话数据。
|
传统地,当在 Action
类中发生应用程序异常时,异常首先被写入日志。然后此类创建一个 ActionError
并在合适的作用域中存储它。然后 Action
类再将控制转交给合适的 ActionForward
。清单 3 展示了 Action
类是如何处理异常的。
try { //Code in Action class } catch (ApplicationException e) { //log exception ActionErrors actionErrors = new ActionErrors(); ActionError actionError = new ActionError(e.getErrorCode()); actionErrors.add(ActionErrors.GLOBAL_ERROR, actionError); saveErrors(request, actionErrors); } |
传统的异常处理过程在每个 Action
类中保存异常信息,而最佳实践 4 则在处理异常时避免冗余代码。
要使用这一最佳实践,Struts 建议您遵循以下步骤:
- 通过扩展
org.apache.struts.action.Action
创建一个Action
类,比如BP4Action
。 - 通过扩展
BP4Action
在 Web 应用程序中创建所有其他Action
类。 - 在
BP4Action
中声明变量ActionErrors actionErrors = new ActionErrors();
。 - 在
BP4Action
中创建方法performTask()
,就像在公共抽象类ActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, ActionErrors actionErrors) throws IOException, ServletException
中一样。 - 在
BP4Action
中将方法perform()
声明为 final。然后调用泛型方法(这些方法总是在处理请求前调用)。现在调用在前一个步骤中创建的performTask()
。 - 在每个
Action
类中实现方法performTask()
的同时(通过扩展BP4Action
),像清单 4 那样处理应用程序异常。
try { //Code in Action class } catch(ApplicationException appException) { //Log exception //Add error to actionErrors actionErrors.add(ActionErrors.GLOBAL_ERROR, new ActionError(appException.getErrorCode())); } |
在 BP4Action
中,调用方法 performTask()
之后,通过 saveErrors(request, errors)
保存 ActionErrors
。
这一实践主要的优势是:避免了每个处理 ActionErrors
的 Action
类中的代码冗余。
|
对开发团队而言,构建易于维护的 Web 应用程序是一项非常具有挑战性的任务。使用 Struts 等成熟的框架有助于实现通常与构建应用程序相关的基础设施代码。Struts 框架提供了一组标准接口,用于将业务逻辑插入到应用程序中。此外,还提供了一种跨开发团队的一致机制,用于执行用户数据验证、屏幕导航等任务,以及用于简化开发屏幕的一组定制标记库。
本文给出的 4 种最佳实践对您充分利用这种框架的特性十分重要。它们不仅能够提高代码的模块化程度和应用程序的可重用性,还能减少代码冗余。对于构建可扩展的 Web 应用程序,这是至关重要的。