8第1章Struts2:现代Web框架 助我们快速开发:第一,尽量自动化wb应用程序开发过程中的常见问题:第二,尽量提供优秀 的架构解决方案来优化Wb应用程序中常见的工作流。 定义Wb应用程序框架是一种结构化的软件,它提供了该领域中常见任务的自动化实现,同时 作为一个内置的架构解决方案可以被在其上实现的应用程序轻松地继承 1。框架自动化了常见任务 不要“重新发明车轮”。任何好的框架都提供了领域内常见任务的方便或者自动化的解决机 制,以此来节省开发人员“重新发明车轮”的精力。回想一下Wb应用程序领域常见任务的讨论 我们就能推断出,Wb应用程序框架将会提供某种内建的机制来完成诸如将数据从HTTP字符串 表示转换为Java数据类型、数据验证、从Web相关工作中分离出对业务和数据层调用、国际化、 表示层内容呈现等任务。好的框架提供透明(即使不透明也会很优雅)的机制来将开发人员从烦 琐的任务中解放出来 2.框架提供了架构解决方法 虽然框架自动完成了烦琐的任务,但是从宏观的角度来看框架结构化的特性可能更重要。框 架的结构来源于内建的接口、类对工作流的抽象。作为一个面向动作的框架,Struts2架构核心的 关键抽象是动作。稍后会讲解其他内容。当基于一个框架构建应用程序的时候,你已经引入了它 的架构。有些时候你可以反抗框架的架构规则,但框架通常以一种很难被拒绝的方式提供它的构 架。如果框架的架构非常好,那么为什么不让你的应用程序优雅地继承这个架构呢? 1.2.2为什么使用框架 不是必须使用框架。有几种选择。对新手来说,可以完全忘记框架。但是除非应用程序非常 简单,否则不必说自己解决所有的架构问题,只看实现自己版本的所有常见领域任务的工作就会 很快让你无法前行。随着21世纪的到来,越来越多新的Wb应用程序平台吹嘘快速开发周期以及 敏捷接口。在Java Web应用程序领域,使用优雅的新框架是利用这些优势的一种方式. 如果愿意,可以构建自己的框架。这也不是个坏主意,但是需要基于两点假设。第一,假设 有足够多聪明的开发人员:第二,假设有足够的时间和金钱能够投入在这个大项目上,从业务需 求的角度看似乎有些离题。即使同时拥有了聪明的开发人员、金钱和时间,自己开发框架还是有 缺点的。我曾经在一家用自己的框架构建产品的公司工作过。框架还不错,但是两个突出的问题 不容忽视。第一,新开发人员总是必须从基础开始学习这个框架。如果你使用一个主流框架,会 有很多训练有素的开发人员等着你雇佣。第二,内部框架不能跟上行业的步伐持续地修订。随着 岁月的流逝,内部框架会遭受构架的侵蚀,并且会生硬地接纳很多扩展。 最终,很难根象不使用某种框架创建21世纪的b应用程序。如果你有足够的时间可以花费 在项目上,可以把它们花在更高级别的问题上,而不是常见工作流和基础任务上。或许是否使用 框架不是问题,但是这些框架提供了你需要的解决方案。考虑到这点,就可以开始了解Sus2 以及它到底提供了什么样的现代化便利了
1.3 Struts2框架9 1.3 Struts2框架 Apache Struts2是一个全新的、非常先进的Web应用程序框架。像我们之前说过的那样,Struts 2不只是原来Suts1框架的一个新版本。它基于备受崇敬的OpenSymphony WebWork框架,是 个全新的框架。到现在为止,你应该已经了解Wb应用程序框架能够提供些什么。说到常见的领 域任务,Sus2能够很好完成它们。它能够处理我们已知的所有任务(甚至更多)。在本书中, 你会逐个学习如何使用这些特性米解决每一个任务。在此介绍阶段,重点讲解框架架构特性会更 有意义。在本节中,我们会讲述Struts2如何构造wcb应用程序的工作流。在接下来的几节中,我 们会关注Struts2的基础,看看这些基础如何影响更高级的架构,同时稍微详细地研究一下Struts2 框架处理实际请求的过程。 1.3.1 Struts2简史 Struts2是实现MVC(Model-View-Controller)设计模式的第二代web应用程序框架。它建立 在最佳实践以及被证明有效且被社区广泛接受的设计模式之上。当然第一代的Sus框架也是如 此。实际上,第一代Struts的主要目的是把MVC模式从桌面应用程序引入到web应用程序。这个 合成的模式偶尔也被称为Model2模式。这是设计良好的Web应用程序进化过程中非常关键的 步,因为它提供能轻松达到MVC分离的基础设施。这可以让开发人员根据这些构架方面的细微 区别使用几个资源以接入到现成的最佳实践解决方案。在过去的10年中,使用Suts1建立了很多 设计优良的Wb应用程序。 在某个时候,Struts社区开始意识到第一代Suts框架的局限性。有一个如此活跃的社区,识 别框架的弱点和不灵活之处并不是太难。Struts2充分利用了学到的经验和教训,提供了一个更加 整洁的MVC实现。同时,它还引入了几个新的架构特性,从而使这个框架更加清晰、更加灵活。 这些新特性包括:用来从动作逻辑中分层出横切关注点的拦截器,为了减少或者消除XML配置 基于注解(annotation)的配置方式,一个贯穿整个框架的强大的表达式语言OGNL(Object--Graph Navigation Language,对象图导航语言),支持可变更和可重用UI组件的基于微型MVC模式 (mini-MVC-based)的标签API。此时,我们只能抛出这些特性的名字。我们会有足够的时间来深 入研究每一个这样的特性。我们需要从框架的宏观概览开始。首先,介绍Struts2如何实现MVC。 然后,介绍在处理一个请求时,框架的各部分如何协同工作。 说明从Struts 1到Struts2一因为前面强调过Struts2确实是一个全新的框架,所以你可能会怀 疑从Struts1迁移到Struts2将会很困难。有些东西需要学习,特别是拦截器和OGNL.但是 虽然这是一个新框架,它仍然是一个面向动作的MVC框架,MVC模式的最大用途就是提 供常见问题的重用的解决方案。架构级别的重用解决方案可以让你的知识和经验能够方 便地共享。如果你用过Struts1,那么应该已经理解了MVC模式的工作原理,这些知识在 Struts2中仍然适用.因为Struts2是MVC模式的一个改进实现,我们相信Struts I开发人员 不但会发现很容易迁移到Suts2,而且他们可能还会说:“早就该这样了!
10第1章Struts2:现代Web框架 1.3.2 Struts2概览:MVC模式 Struts2的高层设计遵循公认的MVC(Model-.View-Controller)设计模式。在本节中,我们会 告诉你框架的哪个部分解决MVC模式的不同关注点。MVC模式提供的关注点分离非常适用于 Wb应用程序。关注点分离让我们能够通过将它们分为高级别组件的方式来管理复杂的大型软 件系统。MVC设计模式有3个关注点:模型、视图和控制器。在Struts2中,它们分别通过动作 (action)、结果(result)和过滤分配器(FilterDispatcher)实现。图1-3展示了Struts2的MVC 实现如何处理Wb应用程序的工作流。 Weh 测堕器客户 控制器 现页面 调用动作 模型 视围 (动作】 选择结果 (结果) 图1-3 Struts2MVC通过3个核心框架组件实现:动作、结果和i1 terDispatcher 请仔细观察图1-3中的各部分。我们将会简要地介绍各个MVC关注点的职责,以及对应的 Struts2组件如何履行这些职责。 1.控制器 我们从控制器开始。在谈论Web应用程序的时候,从这里开始会更有意义。事实上,Struts 中使用的MVC变体经常被称为是前端控制器(front controller)MVC。这意味着控制器在最前端, 是请求处理过程中第一个被触发的组件。可以在图13中清楚地看到这点。控制器的工作是将请 求映射到动作,在Web应用程序中,传入的HTTP请求可以被视为用户向Wb应用程序发送的命令。 wb应用程序的一个基本任务是将这些请求路由到Wb应用程序中需要执行的一系列动作。控制 器的工作就像是交通警察或者空中交通管制员。从某些方面来看,这个工作具有管理性质,但又 不是核心业务逻辑的一部分。 控制器的角色是由Struts2的FilterDispatcher米扮演的。这个重要的对象是一个Servleti过 滤器,它检查每一个传入请求,决定哪个Sus2动作处理这个请求。框架帮助你完成所有控制器 的任务。你只需要告诉框架哪个请求URL需要映射到哪个动作即可。可以通过基于XML的配置 文件或者Java注解来完成这个任务。下一章会同时演示这两种方法
to f. t:f: Struts 2: JJ!.ft Web .fJi* 1.3.2 Struts 211~ , MVC.>t Struts21¥1jQj~l2:iti!~~-v..tr9MVC (Model-View-Controller) iQittli\:. 11:*'W ...... ft{n~ I'i IHF IIB.! a<J ~1-l1IH)" !l<MYC$>I: a<J '" 1"1 ~ Il' !Ii. • MYCl!! jJ: !!lilt a<J ~Il' Ii ;) II! 1~ 1it iIi!!l 'j' W,bJ!<lftl'll'l' • "'1t.<Ii." ill U: llI. il I fJ!lJ!; i!i U ~ 't: ill !)" ,,!Jl J'!I!II i'f a<J 11 it JI< 1'i' JlI!l! il;a<J;Io 1\1 tt i'f :Ii!Jf. MVCil!it 1II.t 'lfl 1-~1l' Ii , lII!1! • ~ III flll>2i1'1l11 . i'EStru~ 2 <1' . .;;; HH) Y/I iii UiOJ f; (action), ~ru ( result) :fUMiI!?t~~ ( Filt.erDispatcher) ~.fJt . OO I-3Ji{ff-TStruts 2!rJMVC ?J; ll!~ M'I:J!I. w,bJil!!lfllf-~J I f;~[ . (Pi l t ertJ1111)$ t<::het" ) ilIIlU~ tit'" (~n;) • iIIff!llil'i!!f;OO 1-1* ~J&llI17t . llI.ilJ~~mJfJt!!M6~1- MVC~It!li. ~J~\il1 . 1;(.1"'1 J!< a<J Stru" 2t1l i'fIJJ!<'l iIIlTlA"'IIJli!!. 1. m:!iIlIl- rllterDi.-patcher llI. ill M j>1 "'I lII!flt!. a '" ~ W,bJ!<fflll!1l' a<J or!;l. MlA lI!!f I<!~ l!!'1LQJ(. l/lJl;.t. Stru~ <I' «!1Il ~JMYC;!I; 1$1&'* il'f!: J'JJHl' ",JU'i a ( fro", ,ontroll,,, MVC. lag "'~ j>1jf>HIII 'l101i! "I'll. j,HI' '" J<I:!!I.tll'l <I' l!!- 1-il'l!I!;jt ~J til i'f. lif 1;(i'E 111 1-1 'N~ II! IMt ~llAli . j>1$llII ~JI f; J.l ~ il'I *""~;~liOJf; . 'llOW,bJilIftll!1¥1' .1. A~J TT il'''' lifW,;l!!"IftJ" r"JW,bJ!<!!lll!fl' :&-;;;~J0-+ . W,bJ!<!!l M a<J - 1-J;J; *iH, Jll ~ lA "iIl*i!I ill '!1IW,bm11ft fil'l' T iitJl'!J\ IT a<J- *JlI ;;IJf;. j>1l1>1 It ~JI f;lI!:i#J1d~iIi 'II~"j't'i!T~i!i 'ol'lMM . MJo["'11iliJl<OIi. lA1-I f;jHfl1!!1.tt8l. {§J< ~; J.llM.· '" # Jl' \11 f1<J - Sil;) • .J!;!$IIl/t 1¥l1fJ ~~ m Struts 21'fl Fi 1 t.erDispa t.cher;}/o!;"!9j'if (j(J . .it 1-m~ rn ~t#:M: 1- Servletrl iJt~. .;;; ttll'lII- 1-i'i A iI'f"'. !i<)E~ 1-S",, ~ 2iOJf; J<i:!!I.lA 1-iIIlR. II<~ IlIIl1J ~''i'G/JtJjjlj'j>,lM III a<Jt£ # . ~>R ilIJlf I!i iI1l1iM~1- .1* URL iii ~q<M l'JI~1- iOJ f; I!!l0l. 01 I;( llI!tlJ;J;'f XML~J tEll: Jt i'f ,1<'It J • .,IH'* *J&lA 1-t£ #. l'-.~ 1"1 r>ti1ii "'lA jIIj i'I':JJI!
1.3 Struts2框架11 说明Struts2朝着零配置(zero-configuration)的Web应用程序进行了长期的探索与研究.零配 1 置的目的在于从约定而不是配置得到应用程序的元数据,例如哪个URL映射到哪个动作。 在零配置的模式中,Jav注解起了重要的作用。尽管零配置还没有完全实现,但现在你可 以使用Java注解和约定来大幅度地减少基于ML的配置文件. 第2章的HelloWorld/应用程序将示范Struts2web应用程序的一般结构和部署细节 2.模型——动作 从图1-3可以很容易地看出,模型由Sus2动作组件实现。但是准确地讲,什么是模型?我 发现模型是MVC的3个概念中最模糊的。从某些方面来说,模型像是一个包含应用程序内容的黑 盒子。其他的一切仅仅是用户界面或者它们之间的连接。模型是事物本身。用更专业的词汇解释 模型是应用程序的内部状态。这个状态由数据模型和业务逻辑共同组成。宏观上看,数据和业务 逻辑融合在一起构成了应用程序的整体状态。例如,如果你要登录一个程序,业务逻辑和数据库 中存放的数据都会参与身份验证过程。最可能的情况是,业务逻辑提供了身份验证的方法,这个 方法接收用户名、密码,并且根据来源于数据库的持久化数据验证它们。在这种情况下,数据和 业务逻辑联合形成了两个状态中的一个一通过身份验证和未通过身份验证。仅有数据,或者仅 有业务逻辑都不能生成这些状态。 考虑到上述内容,Suts2的动作组件有两个作用。首先,一个动作将业务逻辑调用封装到 个单独的工作单元中。其次,动作是一个数据传输的场所。在这里讲解详细的内容还为时过早, 在本书后面的内容中会深入讲解这个主题。现在,考虑一个应用程序中包含任意数量的动作来处 理任何一系列它提供给客户的命令。如图13所示,控制器在收到请求之后,必须通过映射来决 定哪个动作处理这个请求。一旦找到了适当的动作,控制器会调用这个动作并将请求处理的控制 权转交给它。由框架负责管理的调用过程既准备必要的数据又执行动作的业务逻辑。动作完成它 的工作之后,就该向提交请求的用户返回视图了。为此,动作会将结果转发到Suts2视图组件。 现在我们来看一看结果。 3.视图—结果 视图是MVC模式的呈现组件。回顾图1-3可以发现,结果向Wb浏览器返回了页面。这个页 面是用户界面,向用户呈现应用程序的状态。它们通常是JSP页面、Velocity模板或者用其他表示 层技术呈现的页面。虽然视图有多种选择,但是视图的作用很清楚一将应用程序的状态转换为 一种用户可以与之交互的可视化的表示。富客户和Ajx技术的出现让视图的细节变得更加复杂 拥有整洁的MVC关注点分离变得更加重要。良好的MVC模式为轻松地管理最复杂的前端奠定了 基础。 说明Struts2的一个有趣特性是整洁的架构为新技术铺平了道路.Struts2的结果组件是这个特 性的一个很好的展示。结果组件提供了整洁的封装,将处理的控制转交给其他要向客月 写响应的对象。这样,将其他可选的响应(例如XML代码段或者XLST变换)集成进框架 就会很客易
12第1章Struts2:现代web框架 回头看看图13你会发现,动作负责选择哪一个结果来呈现响应。动作可以从任意数量的结 果中选择。常见的选择是动作组件处理结果的有意义表述,例如“success'”、“cror”等。Struts2 为使用很多常见的表示层技术生成结果提供了原生的支持。这些表示层技术包括JSP、Velocity、 FreeMarker以及XSLT等。更好的是,Struts2整洁的架构可以确保构造更多的结果类型以处理新 的响应类型。 备受背睐的MVC模式已经存在了几十年,MVC模式中的各个成员既能很好地分离,又能很 好地连接。当我向学生解释的时候,我称它为“Rese巧克力花生酱杯①”原理。它是巧克力味还 是花生酱味?当你尝上一口的时候,两种味道都有!怎么用巧克力花生酱做出花生酱果冻三明 治?或者用技术术语说,如何获得你想要的丰富的功能,而不把所有的因素搅在一起呢?现在收 获了一些知识,继续阅读学习Struts2以及框架处理请求工厂。 1.3.3 Struts2的工作原理 本节将详细讲述框架如何处理一个请求。如你将要看到的那样,框架不仅包含MC组件。 我们说Suts2提供了一个更整洁的MVC实现。这些整洁的线条依赖于其他几个参与每一个请求 处理的关键架构组件的帮助。这些架构组件主要包括拦截器、OGNL和ValueStack。在下面的 Suts2请求处理的过程中我们会逐一讲解这些组件的用途。图1-4显示了请求处理的工作流。 调用动作 结界 调用结果 结男 OGNL alueStack请求会话圆 图14Sus2请求处理使用在动作和结果之前或之后调用的拦截器 http://en.wikipedia.org/wiki/Reese's. 一译者注