Jakarta Struts学习之新手上路
作者:Wingc 文章来源:www.ccidnet.com
发布日期:2004年09月20日 浏览次数:5387次
Web应用开发早期曾经是那么的“简单”,那个时候还只是纯HTML页面和浏览器特效而已。由于还涉及不到动态数据操作和商业应用,也就省去了很多麻烦。但是这样的“简单”只是过眼云烟,如今我们不得不为复杂的基于Web的商业应用开发采用诸多技术。 本文将介绍如何利用Struts进行应用开发的前台整合的开发过程。Struts是一个为开发基于模型(Model)-视图(View)-控制器(Controller)(MVC)模式的应用架构的开源框架,是利用Java Servlet和JSP构建Web应用的一项非常有用的技术。
阅读本文需要读者具有以下几方面的开发经验:JSP、Servlet、自定义标签库(custom tag library)和XML。如果读者想补一补自定义标签库的知识,可以参考作者以前关于这方面的文章。而本文也是关于介绍如何使用Struts系列文章的上半部分,本系列暂定分为上下两部分。
新手上路注意事项
Struts是一个基于Sun J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。其最初萌芽于Craig McClanahan的构思,诞生至今也一年有余了(译注2)。现在,Struts是Apache软件基金会旗下Jakarta项目组的一部分,其官方网站是http://jakarta.apache.org/struts。由于Struts能充分满足应用开发的需求,简单易用,敏捷迅速,在过去的一年中颇受关注。Struts把Servlet、JSP、自定义标签和信息资源(message resources)整合到一个统一的框架中,开发人员利用其进行开发时不用再自己编码实现全套MVC模式,极大的节省了时间,所以说Struts是一个非常不错的应用框架。
目前的Struts 1.0修正版包括完整的文档,既可以说是用户文档又是开发指导文档。如果读者是JSP新手,或者对MVC设计模式不是太熟的话,可能刚上路时会比较慢,不过不用担心,要相信自己会尽快赶上的:)
此外,应该注意到尽管当前Struts只是1.0版,但已经相当稳定了,作者从Struts 0.9版就在一个大规模的项目中应用了(最近升级到1.0版),至今还没有遇到什么麻烦问题。实际上,Struts在这个要开发复杂用户界面的项目中,为我们团队大大的缩短了开发时间,在此衷心的感谢Struts项目团队的所有开发人员。
哦,还有,如果读者开始上路了,要知道Struts的邮件列表可是有相当分量的,在这里混混才可保证能及时跟上Jakarta项目的最新动态哦 http://jakarta.apache.org/site/mail.html。
开始上路!
Struts框架可分为以下四个主要部分,其中三个就和MVC模式紧密相关: 1、模型(Model),本质上来说在Struts中Model是一个Action类(这个会在后面详细讨论),开发者通过其实现商业逻辑,同时用户请求通过控制器(Controller)向Action的转发过程是基于由struts-config.xml文件描述的配置信息的。
2、视图(View),View是由与控制器Servlet配合工作的一整套JSP定制标签库构成,利用她们我们可以快速建立应用系统的界面。
3、控制器(Controller),本质上是一个Servlet,将客户端请求转发到相应的Action类。
4、一堆用来做XML文件解析的工具包,Struts是用XML来描述如何自动产生一些JavaBean的属性的,此外Struts还利用XML来描述在国际化应用中的用户提示信息的(这样一来就实现了应用系统的多语言支持)。
好,下一步咱们来看看构成这个框架的各个部分以及相互之间是怎样运作的吧!
搞定配置
在使用Struts之前,咱们必先设置好JSP服务器,以便让服务器在用户请求时,知道该如何将指定后缀的请求转到相应的Controller-Struts ActionServlet处理,当然,这些配置信息都一般在服务器启动时通过web.xml文件读入的。我们可以在web.xml定义多个Controlloer,为每一个应用定义一个。一个典型的web.xml文件配置如下,其中有相应的注释,很好懂的,在后面讨论Action的时候,我们将主要分析strutc-config.xml。
<web-app>
<servlet>
<!--
以下配置信息声明了Struts中的ActionServlet,即一个名为OreillyAction的Servlet,其具体实现为org.apache.struts.action.ActionServlet。在这个配置中还有这个Servlet的两个参数:debug level和detail,此处这两个参数的值都设为了2,此外还设置了在启动载入时创建两个实例。
-->
<servlet-name>OreillyActionServlet</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!--
设置所有后缀为.action的请求,都转发到OreillyActionServlet
-->
<servlet-mapping>
<servlet-name> OreillyActionServlet </servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!--
将初始请求页面设置为login.jsp
-->
<welcome-file-list><welcome-file>login.jsp</welcome-file></welcome-file-list>
<!--
设置Struts的JSP页面要用到的标签库和她们的路径
-->
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
</web-app>
控制器(Controller)
Controller是这个框架中扮演“交通警察”的角色,当客户端与服务器有交互动作时,都由她来控制。Controller将HTTP请求封包并转发到框架中相应的对象,这些对象可能是一个JSP页面或一个Action。
Controller在web.xml中设置为org.apache.struts.action.ActionServlet的一个实例,在本例中,这个实例就是OreillyActionServlet。在一个完整的控制过程中,也就是处理一个HTTP请求时,在控制过程之初,这个Servlet会从一个配置文件struts-config.xml中获取请求与控制动作向对应的配置信息,这个我们会在后面详细讨论,Controller通过这些配置信息来决定HTTP请求该往何处转发,而这些Action在接收到转发来的请求后,实现真正的商业逻辑。我们要注意的非常重要的一点是Action对象要能够调用这个ActionServlet的若干方法,通过这个有力的特性,当Action对象在控制过程中将请求再向别的Action对象转发时(最初的请求是由ActionServlet获取,向Action对象转发,而Action对象还可以再转发到别的对象),我们可以将一些需要共享的数据对象通过调用一些方法放入这个Servlet相关的一些标准容器中捎带过去。
模型(Model)
所谓Model就是在对用户请求的整个控制过程中,真正处理用户请求并保存处理结果的对象,在整个过程中,我们一般利用JavaBean来把一些信息保存起来以便在各个对象之间传递。因为在框架中,Model对象是真正处理商业逻辑功能的对象,因此也就是框架中应用需求实现相关性最大的部分。在Struts的实现里,Model的具体表现形式就是ActionForm对象和与其对应的Action对象了。对用户提交表单的数据进行校验,甚至对数据进行预处理都能在ActionForm中完成。通常的应用中,一般是一个Model对象和一个请求页面对应的关系,但也可以一个Model对象对应多个页面请求。如果struts-config.xml配置文件没有指定一个Model对象对应的Action,那么控制器将直接把(通过Model对象完成数据封装的)请求转到一个View对象。
struts-config.xml
前面多次提到的struts-config.xml配置文件是整个框架的主心骨。web.xml文件定义了一个请求到来应向何处转发后,后面的工作就全权由struts-config.xml管理控制了。可以说struts-config.xml就是整个Struts框架的“扛把子”,只有这位“老大”清楚所有请求与动作的映射关系,要是他那里没有搞定或不爽的话,整个“社团”就什么也摆不平了:)如今的应用系统,XML形式的配置文件越来越多,如果整个系统只使用一个这样的配置文件的话,那么保持整个系统的模块化和可维护性都非常的轻松。使用配置文件来描述请求-动作的控制过程和相互关系,而不是在代码中将对象之间的调用关系写死,那么都应用系统有变动时,我们只用修改配置文件就行了,而不是再重新编译发布程序了。
Controller通过struts-config.xml文件的配置信息确定当有请求时应该调用那个对象来处理,从效率的角度出发,这些信息都是在系统启动时读入并存在内存中的。下面我们将讲解一个极短小的struts-config.xml文件,文件中定义了一个与登录请求对应的登录动作,请求到达后将被转发到com.oreilly.ui.authentication.actions.LoginAction这个Action对象,该对象处理的结果决定向用户返回的页面。这个例子同时还示范了一个Action对象将请求转发到别的Action对象,而例子中另一个返回的对象则是一个View对象,即我们看到的login.jsp页面。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd";>
<struts-config>
<!-- ========== Action 映射定义 =================== -->
<action-mappings>
<!-- <action> 属性的说明 -->
<!-
type - 完整的Action实现类名
name - 该Action要用到的ActionForm名
path - 请求该Action的URI
unknown ? 如果将该属性设置为true,那么就是声明这个Action将处理整个应用中所有未找到相应处理Action的请求,当然,一个应用系统中也只会有一个Action的unknown属性可以设为true了
validate - 如果本属性为true则在Action动作之前其对应的ActionForm的validate方法会自动被调用,一般用以校验用户输入的数据
-->
<!-- ~~~~~~~~~~~~~~~~~~~~~ -->
<!-- O'Reilly Main Actions -->
<!-- ~~~~~~~~~~~~~~~~~~~~~ -->
<action path="/Login"
type="com.oreilly.ui.authentication.actions.LoginAction">
<forward name="success" path="/DisplayMainPage.action"/>
<forward name="failure" path="/login.jsp"/>
</action>
</action-mappings>
</struts-config>
视图(View)
View对象通常来说都是指的JSP页面。Struts框架实际上并没有真正的JSP的要求规范,而是提供了大量的标签库来为开发者更简便的将JSP整合到Struts框架中。在Struts中通过标签定义方式的JSP页面能够将用户通过表单输入的数据存入一个JavaBean中,也就是我们前面提到的ActionForm bean。通过Action类调用(自动或手动)ActionForm的校验方法来检查用户输入的数据,如果发现不合法的数据,再通过Struts的一个通用机制将错误信息返回给用户显示。
Struts框架提供了若干个标签库,它们有各自不同的用途。由于这些库还可以脱离Struts框架单独使用,这样我们也可以在其他系统中尝试使用这些标签库,它们包括:
* struts-html - 这个标签库用来创建动态的HTML页面和表单。
* struts-bean - 提供了类似甚至更强于中的功能。
* struts-logic - 用于在页面输出文本信息时的条件、循环等流程的控制。
* struts-template - 用于产生有共同风格的动态JSP页面模板。
此外,可定制标签库在Struts中还有一大用处是,通过资源文件的方式来实现应用系统的多语言特性,应用Struts的系统若想将系统中的用户交互信息换一种语言的会很简单,更换一个不同的资源文件就可以了。
大家都开始应用Struts吧!
Struts框架可能对于大多数开发人员来说,是一门比较新的技术。但我们现在已经可以在不少的应用系统中看到Struts的身影了,而我们大可在新的应用或正在开发的JSP项目中使用Struts框架。
例如,在作者现在正在为客户开发的一个大型数据库应用系统中,商业逻辑都是通过EJB来实现的,用户界面则是JSP页面。在struts-config.xml文件中定义了用户输入表单和对应的Action类,当一个请求发生时,即用户数据以ActionForm的形式封装提交到Action时,Action先调用ActionForm的校验方法,数据检查校验通过后,Action再调用相应的EJB中的方法来完成数据操作,操作的结果以XML的形式返回,XML解析后再放入我们数据的封装传递JavaBean - ActionForm中显示到JSP页面里返回用户。
整个的控制流程(包括Action调用后的不同的返回结果)都尽在struts-config.xml中所掌握,这种“中央集权”的方式非常便于应用流程的调整。而不管是Servlet还是JSP页面中(甚至在一些n层的应用架构)都无需撰写如何获取显示数据的代码。
由于目前作者所开发的是一个较大型的系统,有很多的JSP页面和用户要提交的ActionForm类型,因此发现Struts的一个麻烦的地方,那就是:我们要为如此多页面和ActionForm开发对应的Action类来完成控制,因为我们目前JSP和ActionForm与Action是一对一的关系。不过我认为如果在项目前期分析和设计时多下些功夫,做出更完美一些的设计方案的话,这样的情况是可以避免的,当然,在新产品的开发过程中,想一步就把所有需求弄清楚明白那也是不可能的。我们不是都有这样的经历吗?在开发中的应用系统正一步一步走向成熟的时候,更新和更明确的需求才会被提出来。不过,像我们手里这个利用Struts开发了六个月的系统也确实少见了,呵呵。除去这些非技术因素不谈,Struts框架为我们实现MVC模式节省了大量的时间,并且开发出的系统相当的稳定,可以说是很成熟的产品了。
在本系列文章的第二部分,我们将把各小段代码集成起来,完成一个完整的Struts应用的实例,希望大家继续和作者一起学习Struts!
待续
作者简介
Sue Spielman是ONJava.com的副编辑,主要擅长于JSP和Servlet技术,她还是Switchback Software LLC公司的总裁和高级技术咨询专家。
本文是三篇学习Struts框架系列文章的第二篇。在本系列的的第一篇中,我们大致浏览了Struts框架,框架的功能以及框架中应用到的各个模块。而本文,我将利用Struts 1.0为大家演示建立一个简单的应用;在第三篇文章中将介绍如何利用Struts的标签在JSP中访问ApplicationResource文件中的信息。 我们在这篇文章将会一步一步的讲解Struts的应用,以这样的形式打开Struts一道道神秘的大门,通过这样的过程,相信也能激起你在应用开发中如何应用Struts的灵感。如果你对Struts的一些术语不是很清楚的话,可以参考本系列前一篇对Struts作大体介绍的文章。
再次重复一遍,本文需要读者有如下几方面的知识和经验:JSP,Servlets,自定义标签库(Custom Tag libraries)和XML。此外,在本文中,我还会用到Jakarta项目组其他一些好东东,比如Tomcathttp://jakarta.apache.org/tomcat/index.html(实现Java Servlet和JSP官方标准的Servlet容器,通俗的讲就是一个JSP的Web Server啦)和Anthttp://jakarta.apache.org/ant/index.html(基于Java的自动编译发布工具,这可是好东东啊)。
作为一名一直使用前沿技术开发了诸多应用的技术人员,我一直坚信掌握新技术,理解该技术开发的逻辑是至关重要的。但这往往就是陷住我们学习步伐的泥潭,正因如此,我打算将利用Struts开发的一套完整流程作为我们教学的案例。该流程的这个案例可谓“麻雀虽小、五脏据全”,你完全可以将这个流程应用到你手头那些复杂庞大的项目中,至少在我们的大项目中应用这个流程效果不错。
有开发复杂商业应用的开发人员都知道,客户的需求总是在不停变幻,所以如果有一套规范的开发流程来遵循,当客户提出新的需求时,我们至少可以明确哪些“无理”需求其实是合理可行的。好,接下里我将在我的这个例子中向各位展示和应用整个流程。
本文中的示例代码是StrutsSample应用中的一部分,包括build.xml的完整代码可以到此处http://www.onjava.com/onjava/2001/10/31/examples/StrutsPartII.jar下载。
Struts开发过程
从Struts发布的版本号可以看出,Struts是个新玩意,她有好几个部分组成,明智的你如果搞清楚了何时该开发完成合适的部分,那将会更好的利用我们的开发时间。从我所开发的几个利用Struts应用中,我大致总结出如下这个比较有效的开发步骤:
1,明确应用需求;
2,由用户输入和获取数据的角度出发,明确和设计出每一个用户界面;
3,确定用户界面的进入路径;
4,由应用逻辑信息确定动作映射表(ActionMapping);
5,由设计完成的用户界面开发其所用到的类和应用函数;
6,由用户界面中的数据信息开发ActionForm和相应的数据校验方法;
7,ActionMapping中将会被调用相应的Action或转到相应的JSP页面,这一步我们先开发这些Action;
8,开发商业应用逻辑,就是相应的JavaBean、EJB或其他东东;
9,开发由ActionMapping定义的系统工作流程完成对应的JSP页面;
10,完成系统配置文件:struts-config.xml和web.xml;
11,编译/测试/发布。
明确应用需求
开发任何应用系统的第一步就是收集用户需求信息。不管一个用户逻辑初看上去多么合理,但总有可能在开发时才发现它比看上去要难得多。所以,建议拟一份明确的用户需求列表,这不只是出于开发的目的,还能通过该表分析用户需求以确定哪些地方可能需要花更多的精力。
在我们这个StrutsSample项目中,应用需求就是:
作为一个展示Struts框架应用的完整例子,本示例完成的功能是用户登录。目的只为明确Struts的应用,本示例将不会涉及到一般复杂应用系统中可能应用的安全、数据库、EJB开发等等相关技术。
设计用户界面
这个应用中,包括如下三个用户界面:
1)登录界面,用于用户名和密码输入;
2)当登录用户为合法用户时的欢迎界面;
3)当登录失败时的错误提示界面。
确定用户界面的进入路径
1)登录界面作为这个应用的默认页面;
2)欢迎界面只有当成功登录后才能进入;
3)任何可能发生错误的页面能可以进入错误提示界面;
由应用逻辑信息确定ActionMapping ActionMapping为整个应用确定的“线路图”,在配置文件struts-config.xml对ActionMapping进行定义,通过转发请求(forward)来理顺应用的处理流程,确定应用中每个用户请求对应的动作。 通常我们在开发过程中就逐步确定了ActionMapping所需的信息,开发代码的过程就是在由草稿开始一步步完善struts-config.xml的过程。当Action类处理完用户请求后,其返回的的forward就是在ActionMapping中定义的一个。一个Action返回的forward完全有多种可能,尽管一个Action一般只定义其相关的几个forward。那么,如果有多个Action都可能返回的同一个forward,那么就可以将其定义为全局转发(global forward)。这类似于C中的头文件中全局变量,如果在struts-config.xml描述信息中,某一个forward并不是在当前Action描述中定义的而是全局定义的,那么这个全局的将起作用,同样,一个Action中当前定义的forward将覆盖全局定义。在我们所给的这个简单实例中,我们定义了全局forward――“error”,当某Action返回的forward是“error”这个映射,那么Errorpage.jsp页面将会显示给用户,尽管当前Action并没有对其定义。 我们继续不断的开发,项目日渐完善,项目相关的配置文件也会越来越详细。在下面的例子中,我们将以StrutsSample中用到的struts-confug.xml文件为例,学习global forward和一个Action中相关映射的定义。下面定义了一个名为“login”的Action,其为com.oreilly.actions.LoginAction的实例,当Action处理用户登录成功后将一个名为"success"的forward返回,用户也就会看到Welcome.jsp页面,如果登录失败,Action将返回对应的forward以再显示Login.jsp给用户,而如果处理过程中发生其他错误,Action将返回全局定义的forward――“error”,用户也就会看到错误提示页面Errorpage.jsp。
<!-- ========== Global Forward 定义 -->
<global-forwards>
<forward name="login" path="/Login.jsp"/>
<forward name="error" path="/Errorpage.jsp"/>
</global-forwards>
<!-- ========== Action Mapping 定义 -->
<action-mappings>
<!-- <action>元素的相关属性 -->
<!--
以下只列出常用属性,其他请参考org.apache.struts.action.ActionMapping的相关文档
path - 当前Action对应的用户请求URI路径
type - 实现当前Action的Java class的完整名字
name - 当前Action中用到的ActionForm的名字,其具体信息在配置文件其他地方另有详细定义
unknown - 如果将该属性设置为true,那么就是声明这个Action将处理整个应用中所有未找到相应处理Action的请求,当然,一个应用系统中也只会有一个Action的unknown属性可以设为true
scope - Action中所用到的ActionForm的生存期,可以为“request”或“session”,随着生存期的设置,该Action也会在相应的时间被创建
input - 该Action中相关ActionForm获取用户输入的输入页面,当将ActionForm设为自动验证输入数据,发现不合法数据返回错误时,将返回该页面
validate - 如果本属性为true则在Action动作之前其对应的ActionForm的validate方法会自动被调用,一般用以验证用户输入的数据
forward 元素 - 定义当前Action相关的ActionForward
-->
<!-- =================== -->
<!-- O'Reilly Struts Sample Main Actions -->
<!-- =================== -->
<action path="/login"
type="com.oreilly.actions.LoginAction"
name="loginForm"
scope="request"
input="/Login.jsp">
<forward name="success" path="/Welcome.jsp"/>
<forward name="failure" path="/Login.jsp"/>
</action>
</action-mappings>
在前一篇文章中,我们曾说过,struts-config.xml就是MVC模式的的Controller。在确定struts-config.xml中的配置信息时,应该多花些时间精力在上面,以保证每一个Action定义及其相关定义是符合应用的需求的。如果在项目开始没有详细的设计其定义,当将所有代码和配置集成到一起的时候,我们将不可避免的将各部分的代码和配置完全重新组织一遍。 我们当前的例子StrusSample因为只是处理用户登录,所以只需要一个Action。一个应用系统中所要用到的Action的多少完全依应用的大小而定。一旦整套Action的映射完全的定义出来后,我们就可以一个一个开发其具体实现的Action和ActionForm类,并逐渐将完成的部分一点一点集成起来。
由设计完成的用户界面开发其所用到的类和应用函数 所有ActionForm的实现类都是org.apache.struts.ActionForm的子类。一个ActionForm是与页面上的输入表单相关联的,而且ActionForm的实现还可以对用户输入数据的合法性进行验证。作为一个Java Bean,ActionForm有Set和Get方法,当一个页面中表单被提交时,系统将自动调用Set方法将数据放入ActionForm中,而Get方法将为在Action中操作这些数据所提供。一般来说,处理表单中的所有数据,并进行合法性验证都完全可以交由ActionForm来完成。在应用中,就我个人而言,倾向于将ActionForm和Action划分到不同的包中,因为当一个页面中要用到几对ActionFrom和Action时,都放在一个包内会混淆的。下面的代码,就是实例中登录页面用到的ActionForm的代码。
/*
* LoginForm.java
*/
package com.oreilly.forms;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
/**
* 验证用户要用到的两个数据
*
* username - 登录用户名
* password - 用户密码
*
*/
public final class LoginForm extends ActionForm {
private String userName = null;
private String password = null;
/**
* userName的Get方法
* @return String
*/
public String getUserName() {
return (userName);
}
/**
* userName的Set方法
* @param userName
*/
public void setUserName(String newUserName) {
userName = newUserName;
}
/**
* password的Get方法
* @return String
*/
public String getPassword() {
return (password);
}
/**
* password的Set方法
* @param password
*/
public void setPassword(String newPassword) {
password = newPassword;
}
/**
* 重置所有数据
*
* @param mapping 当前的ActionMapping
* @param request 当前Server正在处理的HttpServletRequest
*/
public void reset(ActionMapping mapping, HttpServletRequest request) {
userName = null;
password = null;
}
/**
* 验证当前HTTP请求提交上来的数据
* 如果数据验证发现不合法数据,将返回一个封装
* 所有验证错误的ActionErrors对象
* 如果数据验证通过,该方法返回null或者一个
* 没有封装任何验证错误的ActionErrors对象
*
* @param mapping 当前的ActionMapping
* @param request 当前Server正在处理的HttpServletRequest
*/
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
// 当前ActionForm中,只需要检查用户输入的用户名数据
if( userName == null || userName.length()==0 ){
errors.add("userName",new ActionError("error.userName.required"));
}
return (errors);
}
}
以上的代码,只有两点和一般的Java Bean有所不同。其一是reset方法,方法中设置的值将在表单被reset时反应到其对应的表单项上,即将表单项的数据恢复到默认值。其二是validate方法,是用来验证用户在表单中所输入数据的方法。在当前这个例子中,我们只验证用户输入的用户名。因为一个用户名其对应的密码可能为空,所以我们的逻辑就是验证时不去检查密码。验证用户名,当发现输入的用户名为空时,方法就会产生一个错误对象(ActionError)。
在Struts中用ActionErrors来装载多个错误,从ActionErrors结尾的那个“s”就可以知道她是一个ActionError对象的集合。在验证用户输入时,可以验证完表单中所有数据后,再将可能发现的多个错误通过ActionErrors返回给用户,这样的逻辑应该是想当然的啦,不可能用户有五个不同的输入错误,却要分五次提示,让用户修改提交五遍吧,呵呵。
同时,要知道在我们这个例子中,我们将错误信息提示给用户是通过ApplicationResource.properties文件。这个文件在Tomcat启动时通过web.xml中的定义为这个应用所使用。通常每一个应用都在其WEB-INF目录下都有web.xml文件来描述系统,而关于部署应用时具体的结构信息,请参考Tomcathttp://jakarta.apache.org/tomcat/index.html等Server相关的用户手册。
ApplicationResource.properties文件中可以定义应用中所要用到的提示信息的字符串,字符串都通过一个键值来唯一确定其位置。在我们这个例子中,键值error.userName.required所对应的字符串信息是“A username is required”,在给用户显示错误信息时,也就通过键值确定的错误提示显示该字符串。通过这样的机制,为我们在系统中实现多语言提供了便利,将该文件中的这些字符串翻译成相应的语言,我们的系统就可以实现西班牙语、德语、法语和汉语等等语言的版本了。
下面这些ApplicationResource.properties中的信息对于我们这个简单的示例中已经够用了:
login.title=Login Struts Sample
error.userName.required=A username is required
error.login.authenticate=Invalid username/password
errors.footer=</ul><hr>
errors.header=<h3><font color="red">Page
Validation</font></h3>Please correct the
following error(s) before contiuing:<ul>
applicationResources=Cannot load application resources bundle
{0}
页面的标题,按钮或其他什么需要文本提示的地方都可以通过这个文件来定义显示用字符串。我们将在该系列的最后一篇文章,也就是后续几个开发步骤中讲解如何通过Struts的标签从这个文件中获取显示用字符串。
待续
作者简介:
Sue Spielmanhttp://www.onjava.com/pub/au/113是ONJava.com的副编辑,主要擅长于JSP和Servlet技术,她还是Switchback Software LLChttp://www.switchbacksoftware.com/公司的总裁和高级技术咨询专家。