posts - 78, comments - 34, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2010-02-23 传智播客—Struts2

Posted on 2010-02-23 23:39 長城 阅读(524) 评论(0)  编辑  收藏

       Struts2第三天。如果老张他喜欢头发,他肯定会把头上的头发有多少根,一根一根的数出来。他搞的太细了!

 

       今天的重点内容是国际化、表单与Action数据交互、表单校验,不多说了开始总结。

 

一、Struts2国际化

       在我们学习WEB基础的时候就讲到了国际化,Struts2中的国际化实现方式与我们之前所学习到的国际化相同。但是Struts2中对国际化做了强化支持!

 

       我们通过在struts.xml文件中加入”<constant name="struts.custom.i18n.resources" value="*.properties"></constant>”为指定全局国际化资源文件。Struts2会根据浏览器设置的语言信息运行对应的国际化文件,如果没找到就根据操作系统的语言查找指定的文件,还是没有,那就使用默认的。我们必须在struts.xml中使用定义在struts-default.xml文件中的defaultStack拦截器堆栈。使用defaultStack我们必须在package中添加extends="struts-default"属性。如果在我们的Action中没有使用任何拦截器,defaultStack默认被使用。如果有使用任何其他拦截器,我们必须手动加入defaultStack拦截器堆栈。Struts2将使用defaultStack拦截器堆栈中的i18n拦截器,为我们提供国际化支持。

 

       引入多个全局资源包的方法是在上面的value属性中添加以”,”分隔的多个资源文件。排在最后的资源包的优先级别最高(如果有重复的资源名称)。那如果有时我想在JSP页面中使用第一个资源包中的资源怎么办?Struts2为我们提供了一个标签“<s:i18n name="first.properties"></s:i18n>”,在标签体内使用到的国际化资源,全以first.properties为先。

 

       我们可以为每个Action指定一个资源包,资源包的名称与Action的名称相同。Struts2的国际化模块会先找与Action对应的资源包,如果没有就找它上一级的资源包,就这样逐级向上。如果直到类所在包的是后一层目录也没找到就使用全局资源。这有什么好处?我们可能会有多个Action使用同一个或多个相同的资源,难道我们要在每个Action对应的资源包里定义它吗?当然不需要,我们只需要把它定义在这几个Action的上级且同一目录即可。

 

       我们如何在JSP页面有使用国际化资源?Struts2tags为我们提供了“<s:text name=""></s:text>”标签,它是专门用来访问国际化资源的。除此之外我们也可以使用“<s:property value=”getText(key)”>”,这个getText()是哪来的?当然是ValueStack中的某个对象的方法喽!是类型为com.opensymphony.xwork2.DefaultTextProvider对象的。Struts2中使用OGNL操作ValueStackContextMapOGNL看到getText(key)时,它会在ValueStack中从上向上反射每一个对象,如果哪一个对象最先具有这个方法,则OGNL就调用这个对象的getText(key)方法。

 

       除了在JSP页面中需要使用到国际化资源,我们在Action中也需要使用国际化资源。此时,我们需要将我们的Action类继承自ActionSupport类,它实现了专门用于操作国际化的接口TextProviderActionSupport还实现了其他非常有用的接口,我们在下面会总结。此后,我们只需要调用getText()方法,即可获得相应的资源信息。我们的Action也可以继承自DefaultTextProvider类,但它默认情况下去搜索全局资源包,不会找Action的资源包。而ActionSUpport正如我们在上面所说,以Action的资源包优先级最高...

 

       我们知道我们可以为国际化资源指定参数,比如“regNameError={0} is invalid.”。我们在JSP页面中可以通过<s:param></s:param>标签来指定,如:

<s:text name=”regNameError”>

       <s:param></s:param>

</s:text>

<s:text name=”getText('regNameError','xxx')”></s:text>。在Action中直接使用getText(“regNameError”,”xxx”)

 

       我们之所以能够如此方便的使用国际化支持,JDK中的java.util.Locale为此做了很大的贡献。目前我们使用国际化操作,无不基于java.util.Locale。因为OGNL的强大,我们也可以在JSP页面中使用java.util.Locale还记得吗?在OGNL中调用XXX类的静态方法或成员的方式,比如调用java.util.LocalegetCountry()<s:property value=”@java.util.Locale@getDefault()”/>

 

二、表单与Action数据交互

       相比Struts1,在Strut2中的一大变化是我们不需要ActionForm了。我们在使用Struts1时,为了操作表单数据,我们需要额外定义一个继承自ActionFormFormBean。然后再将FormBean中的数据CopyBean中。

 

       Struts2是如何实现对表单数据的操作呢?Struts2ValueStack一直发辉着它的作用,ValueStack像是能完成Struts2的在所在操作,上面的国际化也是使用的ValueStack存储的。在Struts2中操作表单数据,我们需要在我们Action定义属性。在Action添加的属性可以是基本数据类型也可以是复合类型。

 

       进行表单与Action数据交互时,我们的Action类无需实现任何接口或继承自任何类。但是,我们必须在struts.xml中使用定义在struts-default.xml文件中的defaultStack拦截器堆栈。使用defaultStack我们必须在package中添加extends="struts-default"属性。如果在我们的Action中没有使用任何拦截器,defaultStack默认被使用。如果有使用任何其他拦截器,我们必须手动加入defaultStack拦截器堆栈。

 

       Struts2正是使用在defaultStack中的params拦截器,来为我们的Action设置属性值。如何使用基本类型属性和复合类型属性与JSP页面交互呢?比如在我们的RegUserAction中有一个User属性和一个字符串型的password2属性。那么我们在JSP页面中应该这样使用:

<s:form action=”RegUserAction”>

    <s:textfield name=”user.name”/>

    <s:textfield name=”user.password”/>

    <s:textfield name=”user.email”/>

    <s:textfield name=”password2”/>

    <s:submit value=”注册”></s:submit>

</s:form>

 

       点击注册按钮后,Struts2正是使用params拦截器将数据设置到RegUserAction的属性中。

 

       因为这些表单字段数据是被保存在ValueStack中,所以我们在JSP页面我们可以使用EL表达试,如:${user.name},也可以使用OGNL表达式,如:<s:property value=”user.name”/>来获取数据。

 

       除此之外,我们可以让Action实现ModelDriven接口,并将User做为它的泛型参数。如果被ModelDriven接管的实体类型中有与我们的Action属性相同的,ModelDriven的优先级高。Struts2会设置ModelDriven接管的实体类型的是属性,而忽略Action的同名属性。但这并不会引起错误,因为我们的数据全部放在ValueStack中,使用OGNL可以正确获取。我们不推荐使用ModelDriven

 

三、表单校验

       表单校验在Struts2中实现比较简单,表单数据的校验分为前台校验和后台校验。同样我们需要开启defaultStack拦截器堆栈,首先我们来看看后台校验。

 

       后台校验,我们的Action可以继承ValidationAwareSupport类和实现Validateable接口。因为我们同时需要在类中使用到国际化表单校验,所以我们可以直接继承ActionSupport类。Action类需要实现validate方法。

 

       validate方法中进行Action的属性校验,并且我们可以调用ActionSupport类的addActionError(String)方法,添加错误信息。我们可以在这里使用国际化支持,而在JSP页面中需要使用<s:fieldError>取出所有错误信息,或者指定字段名而取出某个字段的错误信息。

 

       但有一个问题,一个Action类可以有多个方法分别用于处理不同的请求。Struts2每当调用其中一个方法时都会进行表单校验,这没必要啊!所以我们在不需要进行表单校验的方法上添加“@SkipValiation”注解,这样就会被Struts2过滤掉。

 

       我们也可以添加”ActionClassName-validation.xml”配置文件,来为指定名称的Action(ActionClassName)添加表单校验。具体的配置可以参看struts2包中所带的例子程序。我们也可以使用“ActionClassName-actionname-validation.xml”来为Action类中的某个具体方法指定表单校验。

 

       前台校验,前台校验的好处不再说明了。前提我们以配置文件的方式为Action指定的表单校验,那么在JSP页面中,我们可以直接引用配置文件中的数据,实现前台校验。Struts2中的struts-tags为我们提供的表单标签中可以引用配置文件中对应的校验数据。在我们访问到某个JSP页面时,Struts2的标签会为我们自动生成相应的JavaScript代码,但Struts2的表单前台校验的这种功能还不够强大。在此就不多做总结了。

 

       老张讲得比较细致,我也仅仅是泛泛而总结。按照正常的进程,我们明天还有一天的Struts2课程,但由于时间不够,老张决定哪天同学们休息时再为我们补一天,太好了!


只有注册用户登录后才能发表评论。


网站导航: