2.2简单的HelloWorld示例23 再次强调,如果你不熟悉Servlet规范,可以去快速阅读一下。为了便于讲述,我们会列出最 重要的方面。首先,所有的第一层目录(除了WEB-NF之外)都在Wb应用程序的文档根目录中。 通常情况下,所有JSP文件都放在这些目录中。也可以在这些目录中放置FreeMarker或者Velocity 的模板文件,我们就是这样做的,当然这些资源也可以从类路径下的J八R文件中加载。在示例应 2 用程序中,我们根据SP隶属的章节来组织它们。关于文档根目录需要注意的一项非常重要的事 情是,其中的资源可以被Servlet溶器潜在地当做静态内容。如果不对这种访问加以保护, 一个直 接指向文档根目录中资源的URL可能会导致Servlet容器将这个资源送出。因此,文档根目录不是 存放敏感信息的安全场所】 所有重要的内容都放在WEB-NF目录下。如图2-3所示,WEB-NF的顶级目录下应包含两个 目录1ib、classes和一个文件web.xml。注意,还有一个src目录,其中包含项目的源代码。但src目 录不是Wb应用程序目录结构所必需的-部分。为了方便,我们把它放在这里。根据你的构建过 程的细节,你可以把它放在任何地方。最终,你可能不想让源代码出现在生产环境的Wb应用程 序中。我们可以以一种方便、构建不可知的方式来处理它。 但是,另外两个目录(Iib和classes)是必需的。lib目录用来存放所有应用程序需要的JAR文 件。在示例应用程序中我们放置了所有Struts2应用程序常用的JAR文件。注意,Struts2非常灵活, 如果你添加了一些本书没有使用的特性,你可能需要添加其他的JAR文件。另外还要注意,如果 你想查看Struts2必需的最小的JAR文件的集合,可以参看之前讲解的Hello World.war文件。classes 目录用来存放应用程序需要使用的所有Java类文件。这些内容与ib中的资源没有本质区别,但是 classes目录包含展开的目录结构,其中包含class文件而不是JAR文件,在图2-3中你可以看到classes 目录下有一个叫做manning的子目录,它是我们的应用程序Java包结构的根目录。classes目录还包 含了几个其他类路径下的资源文件,例如属性文件和我们讨论过的struts.xml文件。 除了Iib目录和classes目录,wWEB-NF中也包含了整个应用程序的中心配置文件web.xml。这 个文件的正式名称是部署描述符(deployment descriptor),它包含了Web应用程序中所有的Servlet、 Servleti过滤器和其他Servlet API组件的定义。代码清单2-3展示了示例应用程序的web.xml文件。 代码清单2-3示例应用程序的web.xml部署描述符 version="1. .sun.com/xml/ns/j2ee" tp:// xsi:schem ocation="ht /52e http://java.sun.com/xml/ns/j2ee/web-app_2_4.x cdioplay-names62 Example Application Chapter 1-Hello Morld sfilter-name>strute2</filter-name s2从这里开 iorg-apacherutdiepatcher. cinit-param cparam-namexactionPa kages/ae name> 在 ning</param
24第2章初识Struts2 <filter-mapping> </filter-mapping> 之 et-na cservlet-class>manning.servlet.Anotherservlet</servlet-claas> </servlet> aecDgothereEv1etcBeElet-nae, e/evEppgothesevetc/eipat2n -mapping. <welcome-file-list, </web-app> 对于Struts2应用程序来说,部署描述符中最重要的元素是fi1ter和filter-mapping,这些 元素建立了Struts2的FilterDispatcher。.这个Servleti过滤器是Struts2框架的基础。它检查所有 的传入请求,查找指向Struts2动作的请求。注意,这个Servleti过滤器映射到的URL模式是“/*”。 这意味着这个过滤器会检查所有的请求。关于FilterDispatcher配置的另外一件重要的事情是 我们传入的初始化参数。如果想在应用程序中使用注解,那么就必须要设置actionPackagesi这 个初始化参数。它告诉框架在哪些包中扫描注解。在稍后讲解到注解版本的Hello World应用程序 时我们会详细探讨。 另外一个需要说明的有趣的地方是,在这个Web应用程序中包含了一个非Struts2的Servlet 像前面讲述的那样,web应用程序被定义为打包在一起的一系列Servlet。很多Struts2应用程序不 包含其他的Servlet。事实上,由于Struts2使用Servleti过滤器而不是Servlet,所以很多Struts2应用 程序不会包含任何Servlet,,除非JSP编译得到的Servlet也算在内。由于整合框架和其他的Servlet 并不罕见,所以我们在Web应用程序包含了另一个Servlet,.如代码清单2-3所示。本书后续的内容 会展示如何使用这个Servlet。. 现在你应该已经知道了如何建立一个Sus2应用程序的基础结构.示例应用程序中的所有内 容都根据本书中的内容而来,除了WEB-NF下面的src目录。如前面所讲述的,这主要是为了方 便。你很可能会按照业界最佳实践建立你的结构,我们并没有提供这样的结构是因为它只是让学 习曲线更复杂了。下面来看看Hello World应用程序。 2.2.2探索HelloWorld应用程序 构建HelloWorld应用程序的目的是提供最简单的Struts2的介绍。然而,它也尝试使用了Struts 2的所有核心架构组件。这个应用程序的工作流很简单。应用程序从表单中收集用户姓名,用这 个姓名为用户构建一个自定义问候语,之后呈现给用户一个显示自定义问候语的网页。虽然工作
2.2简单的HelloWorld示例25 流极为简单,但却能够清楚地展示Suts2所有组件(动作、结果和拦截器)的功能和使用方法 另外,它还展示了数据如何在框架中流动的机制,包括ValueStack和OGNL。Struts2是一个非 常复杂的框架,HelloWorld/应用程序将只涉及视图。放心,本书的剩余内容会花费足够的时间来 逐一讲解这些主题。 2 1.HelloWorld用户手册 首先,让我们看看Hello Worldl应用程序实际要做什么。假设你已经将示例应用程序部署到了 Servlet容器中,从先前看过的菜单中单击Hello Worldt链接。注意,我们从XML版本的应用程序开 始,不是注解版本的应用程序。你将会看到一个简单的表单,如图24所示,这个表单要求你输 入名字。 Enter your name so that we can customize a greeting just for you! Your name:harle jod Submit」 图24第一个页面收集用户姓名 输入名字,单击Submit(提交)按钮。应用程序会为你准备自定义问候语,之后返回一个新 页面,如图2-5所示。 图2-5显示了由动作构建,并通过JSP页面显示的问候语消息。就是这样。现在,看看这个示 例应用程序的Strtus2构架是什么样子 Custom Greeting Pege Hello Charlle Joo 图25第二个页面显示了基于提交的姓名构建的自定义问候语 2.HelloWorld细节 我们从查看HelloWorld.用到的Struts2架构组件开始。这个版本的HelloWorld应用程序使用 XML声明它的架构。我们说过,XML声明性架构的入口点是struts.xml文件。我们也说过,许多 开发人员使用这个根文档包含其他的L文档,以便模块化。示例应用程序就是这样做的一 按照章来分模块。代码清单24展示了WEB-NF/classes//struts.xml文件,其中最重要的方面是使用 include元素引入模块化的XML文档。 代码清单24基于XML的声明性架构的入口点 ?xm n-1 0
26第2章初识Struts2 cstrute> ①使用常量调整 Struts的属性 <constant names"struts.devMode"value="true"/> "default"namespace-"/extends-"struts-default"> Mau动作属 /ac sults/menu/Menu.jap</result> 于歌认包 </package> 块化T%表 <include file-"manning/chapterEight/chapterEight.xml"/> </struts 这里需要说明常量元素①可以用来设置框架的属性,这里我们把框架设置为运行在开发模 式。也可以使用属性文件设置,稍后会说明。同时还需要说明struts.xml文件是在默认包内定义全 局动作的好地方。由于主菜单不属于任何模块化的迷你应用程序,所以我们把它放在这里。回到 原来的话题,来看看struts..xml文件最重要的方面,一个长长的包含列表将所有按照章节组织的文 档引入到声明性架构。所有的这些文件会按照内联的方式被引入到主文档,以创建一个大XML 文档。 HelloWorld应用程序在示例代码的第2章。代码清单2-5展示了WEB-NF/classes/manning/ chapterTwo/chapterTwo.xml文件的内容。 代码清单2-5使用XML的声明性架构 <?xml version-"1.0"encoding="UTF-8?> <IDOCTYPE struts PUBLIC <struts> saction name="Name"> I name-SUCCESS-=7chaptertvo/H6ilomorid.1p/Teu1 <action name </package </atrute> 注意,应用程序中的真实文件包含不同元素的详细注释,本书所有的示例都是这样,但是在 这里打印代码清单的时候,为了更加清晰,我们移除了这些注释。这个示例应用程序只有两个动 作,其中一个几乎什么也没有做。Name和He1 loWorldz动作都声明了-一些它们自己使用的结果
2.2简单的HelloWorld示例27 每一个结果都命名了一个用来呈现结果页面的SP页面。这里仅有的其他元素是strutst根元素和 package元素。struts元素是所有Struts2XML文件的强制性的文档根元素,package元素是一 个重要的容器元素,用来组织应用程序的动作元素、结果元素和其他组件元素。 现在,对于package元素,唯一需要注意的地方是它声明了一个当框架将URL映射到动作时 2 会用到的命名空间(namespace)。图2-6展示了如何使用包的命名空间来决定映射到动作的URL http://+localhost:8080 + manningSampleApp+ /chapterTwo+/HelloWorld action 协议 主机名:端口 Servlet上下文 包命名空闻 动作名.action 图2-6URL剖析:URL命名空间如何映射到Struts2动作命名空间 映射关系很简单,URL组合了Servlet.上下文、包的命名空间以及动作的名字。注意,动作名 字带有.action扩展名。第3章将详细讲解命名空间的机制。第一个动作(Name动作)没有任何真 正的后台处理,它只是转到呈现给用户一个收集名字的表单的页面。 最佳即使是一个简单的没有动态处理的SP页面,也要用空的动作组件来转到你的结果。这可 实践以让应用程序的架构保持一致,可以预先防备工作流预计增加的复杂度,并且可以将资 源的真正结构隐藏在Struts2动作的逻辑命名空间之后, 虽然从技术上来说我们可以使用一个URL直接指向一个表单SP,但是一个被广泛接受的最 佳实践是,尽管有没有真正的处理,也使用动作来转发这些请求。如你所看到的那样,这样转发 用的动作不需要指定一个实现类。它们会自动地转到自己声明的结果页面。上述的这个动作直接 指向NameCollector.jsp页面,它呈现收集用户名的表单。代码清单2-6展示了/cpaterTwo/Name Collector.jsp文件的内容。 代码清单2-6使用Suts2UI组件标签呈现表单 】标准的JSP指令 <html> chead title>Name Collector</title> </head> <body> <h4zEnter your name </h4> <s:form actio abel-"Your name"/>