Struts——一种开源MVC的实现这篇文章介绍Struts,一个使用servlet和JavaServer Pages技术的一种Model-View-Controller的实现。
Struts可以帮助你控制Web项目中的变化并提高专业化。
即使你可能永远不会用Struts实现一个系统,你可以获得一些想法用于你未来的servlet和JSP网页的实现中。
简介在小学校园里的小孩子们都可以在因特网上发布HTML网页。
然而,有一个重大的不同在一个小学生和一个专业人士开发的网站之间。
网页设计师(或者HTML开发人员)必须理解颜色、用户、生产流程、网页布局、浏览器兼容性、图像创建、JavaScript等等。
设计漂亮的网站需要做大量的工作,大多数Java开发人员更注重创建优美的对象接口,而不是用户界面。
JavaServer Pages(JSP)技术为网页设计人员和Java开发人员提供了一种联系钮带。
如果你开发过大型Web应用程序,你就理解“变化”这个词语。
“模型-视图-控制器”(MVC)就是用来帮助你控制变化的一种设计模式。
MVC减弱了业务逻辑接口和数据接口之间的耦合。
Struts是一种MVC实现,它将Servlet2.2和JSP 1.1标记(属于J2EE规范)用作实现的一部分。
你可能永远不会用Struts实现一个系统,但了解一下Struts或许使你能将其中的一些思想用于你以后的Servlet和JSP实现中。
模型-视图-控制器(MVC)JSP标签只解决了我们问题中的一部分。
我们依然有验证、流控制、以及更新应用程序结构的问题。
这就是MVC从哪儿来以及来干嘛的。
MVC通过把问题分成三类来帮助解决一些与单模块相关的问题:∙Model(模型)模块包括应用程序功能的核心。
模型封装着应用程序的各个结构。
有时它所包含的唯一功能就是结构。
它对于视图或者控制器一无所知。
∙View(视图)视图提供了模型的演示。
它是应用程序的外表。
视图可以进入模型获得者,但是它对于设置者一无所知。
除此之外,它对于控制器也是一无所知。
视图仅仅当模型发生改变的时候才被通知。
∙Controller(控制器)控制器对于用户的输入做出反应。
它创造和设置模型。
MVC模型2Web给软件开发人员带来了一些独特的挑战,最显著的就是客户端和服务器端的无结构连接。
这种无结构连接行为使得模型很难知道视图的改变。
在Web上,浏览器必须重复询问服务器端以此来发现应用程序结构的改变。
另外一个显而易见的改变就是相对于模型或者控制器,视图采用了不同的技术。
当然,我们可以使用Java(或者PERL、C/C++或之前的其他代码)代码来生成HTML。
这种方法存在一些弊端:∙Java程序员应该开发服务,而不是HTML。
∙布局的改变将需要改变代码。
∙服务的客户将有能力去创造一些页面去满足他们的一些特殊需求。
∙页面设计人员将不能直接介入到页面的开发中。
∙嵌入在代码中的HTML将会变得丑陋。
对于Web,MVC的经典形式将需要改变。
图4展示了MVC的Web适应,也就是通常所说的MVC模型2或者MVC2。
.图 4.MVC模型2Struts,MVC2的一种实现Struts是一组相互协作的类、servlet和JSP标记,它们组成一个可重用的MVC2设计。
这个定义表示Struts是一个框架,而不是一个库,但Struts也包含了丰富的标记库和独立于该框架工作的实用程序类。
图5显示了Struts的一个概览。
图 5.Struts概览Struts概览∙客户端浏览器一个来自客户端浏览器的HTTP创建一个事件。
Web容器将会用一个HTTP 响应来作出响应。
∙控制器控制器接收来自浏览器的请求,并决定发送请求到何处。
就Struts而言,控制器就是一个以servlet执行的一个命令设计模式。
struts-config.xml文件配置控制器。
∙业务逻辑业务逻辑更新模型的状态,并帮助控制应用程序的流。
就Struts而言,这就是通过作为实际业务逻辑“瘦”包装的Action类完成的。
∙模型状态模型代表了应用程序的状态。
业务对象更新应用程序的状态。
ActionFormbean在会话级或请求级表示模型的状态,而不是在持久级。
JSP文件使用JSP标记读取来自ActionForm bean的信息。
∙视图视图就是一个JSP文件。
其中没有流程逻辑,没有业务逻辑,也没有模型信息--只有标记。
标记是使Struts有别于其他框架(如Velocity)的因素之一。
Struts详细资料在图6中展示了一个无其他附属设备的阿帕奇struts的action包的UML图表。
图6显示了ActionServlet(Controller)、ActionForm(Form State)和Action(Model Wrapper)之间的最小关系。
图 6.命令(ActionServlet)与模型(Action&ActionForm)之间的关系的UML 图ActionServlet类你还记得使用函数映射的日子吗?你会映射一些输入时间到一个函数的一个指针。
如果你很老练,你可以把这些配置信息放进一个文件里并且在运行时加载该文件。
函数指针装扮了在C语言结构化程序设计中的旧时光。
现在日子好过多了,自从我们有了Java技术、XML、J2EE等等之后。
Struts控制器是一个映射事件(事件通常是一个HTTP post)到类的一个servlet。
猜猜怎么着--控制器用一个配置文件以致于你不必非硬编码这些值。
生活变了,但方法依然如此。
ActionServlet是MVC实现的命令部分并且它是框架的核心。
ActionServlet (Command)创建并使用Action、ActionForm和ActionForward。
正如前面所提及的,struts-config.xml文件配置Command。
在Web工程创建期间,Action和ActionForm被扩展用来解决特殊的问题空间。
文件struts-config.xml指导ActionServlet如何扩展这些类。
这种方法有几个优点:∙网页设计人员不必费力地通过Java代码来理解应用程序的流程。
∙当流程发生改变时Java开发人员不需要重新编译代码。
∙通过扩展ActionServlet命令函数可以被添加进来。
ActionForm类ActionForm维持着Web应用程序的会话状态。
ActionForm是一个必须为每个输入表单模型创建该类的子类的抽象类。
当我说输入表单模型时,我就是说ActionForm代表了一个由HTML表单设置或更新的一般意义上的数据。
例如,你可能有一个由HTML表单设置的UserActionForm。
Struts框架将会:∙检查UserActionForm是否存在;如果不存在,它将会创建该类的一个实例。
∙Struts将使用HttpServletRequest中相应的域设置UserActionForm的状态。
没有太多糟糕的请求.getParameter()调用。
例如,Struts框架将从请求流中提取fname并调用UserActionForm.setFname()。
∙Struts框架在将在传递它到业务包装UserAction之前将更新UserActionForm的状态。
∙在传递它到Action类之前,Struts将还会对UserActionForm调用validation()方法进行表单验证。
备注:这样做通常并不明智。
别的网页或业务对象可能有方法使用UserActionForm,然而验证可能不同。
在UserAction类中进行状态验证可能更好。
∙UserActionForm能够维持一个会话级别。
备注:∙struts-config.xml文件控制着HTML表单请求与ActionForm之间的映射。
∙多重请求会被映射到UserActionForm。
∙UserActionForm可被映射到诸如向导之类的多重页面的东西上。
Action类Action类是一个围绕业务逻辑的一个包装器。
Action类的目的就是将HttpServletRequest翻译给业务逻辑。
要使用Action,需重写process()原理。
ActionServlet(命令)通过使用perform()原理将参数化的类传递给ActionForm。
此外,没有太多讨厌的request.getParameter()调用。
通过事件到达这里的时间,输入表单数据(或HTML表单数据)已经被从请求流中翻译出来并进入ActionForm类中。
注:扩展Action类时请注意简洁。
Action类应该控制应用程序的流程,而不应该控制应用程序的逻辑。
通过将业务逻辑放在单独的包或EJB中,我们就可以提供更大的灵活性和可重用性。
考虑Action类的另一种方式是Adapter设计模式。
Action的用途是“将类的接口转换为客户机所需的另一个接口。
Adapter使类能够协同工作,如果没有Adapter,则这些类会因为不兼容的接口而无法协同工作。
”(摘自Gof所著的Design Patterns-Elements of Reusable OO Software)。
本例中的客户机是ActionServlet,它对我们的具体业务类接口一无所知。
因此,Struts提供了它能够理解的一个业务接口,即Action。
通过扩展Action,我们使得我们的业务接口与Struts业务接口保持兼容。
(一个有趣的发现是,Action是类而不是接口)。
Action 开始为一个接口,后来却变成了一个类。
真是金无足赤。
)Error类UML图(图6)还包括ActionError和ActionErrors。
ActionError封装了单个错误消息。
ActionErrors是ActionError类的容器,View可以使用标记访问这些类。
ActionError是Struts保持错误列表的方式。
图mand(ActionServlet)与Model(Action)之间的关系的UML图ActionMapping类输入事件通常是在HTTP请求表单中发生的,servlet容器将HTTP请求转换为HttpServletRequest。
控制器查看输入事件并将请求分派给某个Action类。
struts-config.xml确定Controller调用哪个Action类。
struts-config.xml配置信息被转换为一组ActionMapping,而后者又被放入ActionMappings容器中。
(你可能尚未注意到这一点,以s结尾的类就是容器)ActionMapping包含有关特定事件如何映射到特定Action的信息。
ActionServlet(Command)通过perform()方法将ActionMapping传递给Action 类。