Struts 2的深入使用-------学习笔记

深入使用Struts 2
4.1 详解Struts 2的类型转换
4.2 使用Struts 2的输入校验
4.3 使用Struts 2控制文件上传
4.4 使用Struts 2控制文件下载
4.5 详解Struts 2的拦截器机制
4.6 使用Struts 2的Ajax支持
4.7 本章小结

[b][color=blue]深入使用Struts 2[/color][/b]

回忆内容:
上一章介绍了Struts 2框架的基本知识,包括Struts 2框架的核心知识、常规配置、Convention插件提供的约定支持、异常配置、国际化和标签库的内容。

本章内容:
这一章将介绍类型转换器、输入校验器、文件上传、拦截器、Struts 2的AJAX支持和使用JSON插件进行开发。


[b]4.1 详解Struts 2的类型转换[/b]

1、所有MVC框架,都需负责解析HTTP请求参数,并将请求参数传给控制器组件。此时问题出现了:HTTP请求参数都是字符串类型,但Java是强类型的语言,因此MVC框架必须将这些字符串参数转换成相应的数据类型。

Struts 2的类型转换可以基于OGNL表达式,只要我们把HTTP请求参数命名为合法的OGNL表达式,就可以充分利用Struts 2的类型转换机制。

【Struts 2内建的类型转换器】

对于常用的类型,开发者无需理会类型转换,这是通过Struts2内建的类型转换器完成的。
如下:String、boolean和Boolean、char和Character、int和Integer、long和Long、float和Float、double和Double、Date、数组、集合(集合元素类型是String).

【基于OGNL的转换】

借助于内置的类型转换器,Struts 2可以完成字符串和基本类型之间的类型转换。除此之外,借助于OGNL表达式,Struts 2允许以另外一种简单方式将请求参数转换成复合类型。

<s:textfield name=”user.name” label=”用户名”/>
//该表单域封装的请求参数为user.name,Struts 2会把user.name参数的值赋给Action实例的user属性的name属性。

我的问题:user--实例化User对象这种关系如何完成?也就是说在给出user怎么就知道要实例化User对象呢?


指定集合元素的类型:
我们可以在使用集合时使用泛型,这种泛型可以让Struts 2了解集合元素的类型,Struts 2即可通过反射来创建对应类的对象,并将对象添加到集合中去。

但当不使用泛型时,Struts 2还知道使用类型转换器来处理users属性吗?当然不知道。但有解决方法:
1、 通过局部类型转换文件来指定集合元素的类型,类型转换文件就是一个普通的properties文件,里边提供了类型转换相关的配置信息。该文件存放在对应Action的路径下。



总之:为了让Struts 2能了解集合属性中元素的类型,可使用如下两种方式:
一、通过集合属性指定泛型
二、通过Action的局部类型转换文件中指定集合元素类型。


【自定义类型转换器】
利用Struts 2提供的类型转换器和OGNL表达式实现的类型转换机制,就能满足大部分类型转换需求,但有时候需将一个字符串转换成一个复合对象时,这就需要自定义类型转换器。
实际上Struts 2的类型转换器依然基于OGNL框架的,在OGNL框架中有一个TypeConverter接口,这个接口就是自定义类型转换器必须实现的接口,OGNL还为该接口提供了一个实现类DefaultTypeConverter,需重写convertValue()方法。

当为应用提供类型转换器后还不够,因为Struts 2依然不知道何时使用这种类型转换器,所以必须将类型转换器注册到Web应用中去,Struts 2才可以正常使用该类型转换器。
注册方式有三:
一、注册为局部类型转换器,局限在某个Action中起作用:使用局部类型转换文件实现。
二、注册全局类型转换器:需提供一个xwork-conversion.properties文件,全局类型转换文件
三、通过注释注册类型转换器(没说明,不懂)。


【基于Struts 2的自定义类型转换器】

以上的类型转换器基于DefaultTypeConverter类是双向实现的,这必须通过toType参数来判断方向。
为了简化类型转换器的实现,Struts 2提供了一个StrutsTypeConverter抽象类,该类是DefaultTypeConverter的子类它把两个不同转换方向替换成不同方法,convertToString()和convertFromString()。


【处理Set集合】

不建议在Action中使用 Set集合属性。P285


【类型转换中的错误处理】
表现层数据涉及两个处理:数据校验和类型转换。
Struts 2提供了一个conversionError的拦截器,这个拦截器注册在默认的拦截器栈中,在、Struts 2的默认配置文件struts-default.xml中可查看到。该拦截器负责将对应的错误封装成表单域错误(FieldError),并将这些错误信息放入ActionContext中。

<s:head/>该标签可以导入xhtml主题所需要的一些CSS样式。
<s:fielderror/>该标签显示错误信息,可对Action设置局部资源文件or全局资源文件。


[b]4.2 使用Struts 2的输入校验[/b]

输入校验一般分为客服端校验和服务端校验,客服端主要是过滤正常用户的误操作,主要是通过JS来完成。服务端校验主要在应用中编程实现。

【编写校验规则文件】

校验规则文件的跟元素是<validators>,<validators元素可包含多个<field>or><field-validator>元素,它们都用于配置校验规则,区别是:前者是非字段校验规则,后者是字段校验规则。
校验文件的文件名遵循如下规则:<action名字>-validation.xml,路径与对应的Action路径一致。

【使用客服端校验】

在Struts 2应用中使用客服端校验非常简单,只需在服务端的基础上改变连个地方即可:
1、将输入页面的表单元素改为使用Struts 2标签来生成表单。
2、为该<s:form>元素增加validate=“true”属性。


如果我们希望Struts2的客服端校验能发生,那么我们进入regist.jsp之前必须经过Struts2的核心Filter,而如果直接请求regist.jsp,则并未经过核心控制器。
当地址栏未发生变化时,并未提交到对应的Action,这就表明上面的校验过程是客服端完成的。

客服端校验器仅仅支持如下几种校验器:
Required validator
Requiredstring
Stringlength
Regex
Email
url
int
double

客服端校验需注意三个地方:
1、<s:form../>元素有一个theme属性,不要将该属性设置为simple
2、浏览者不应该直接请求视图资源,这样会引发异常。
3、启用客服端校验的表单页面的action和namespace要分开写。


一旦使用了MVC框架,就应遵循MVC思想。

【字段校验器配置风格】
xwork-validator-1.0.1.dtd文件是校验规则文件的规范要求文件。
【非字段校验器配置风格】

【短路校验器】

采用短路校验器,只需在<validator../>元素或<field-validator../>元素中增加short-circuit=”true”即可。倾向使用字段校验器配置风格


【校验文件的搜索规则】
当一个Action存在多个处理逻辑时,可为每个处理逻辑添加不同的校验规则。

【校验顺序和短路】
校验器增加了短路的特性后,校验器的执行顺序变得非常重要,因为前面执行的结果可能阻止后面校验器的执行。
一般而言,非字段风格的校验器优先于字段校验风格的校验器。


【内建校验器】

Struts 2提供了大量的内建校验器,在xwork2 的jar包中中可找到。
若开发者自己开发了一个校验器,则需建立一个validators.xml文件,则不会再加载默认的default.xml文件。因此,如果开发者提供了自己的校验器注册文件,一定要把default,xml文件里的全部内容复制到validators.xml文件中。

【基于Annotation的校验器】
这种基于Annotation的输入校验实质上是属于Struts 2“零配置”特性的部分。
该功能的实现是Struts 2实现的,这种特性与Convention插件实现的零配置不一样。

【手动完成输入校验】
Struts 2提供了进行手动校验:
在Action里边重写ActionSupport里边的validate()方法;
但如果Action类里边包含多个处理逻辑,不同的逻辑对应不同的校验方法,为了保证实现校验指定处理逻辑的功能,Struts 2提供了一个validateXxx()方法,其中xxx即是Action对应的处理逻辑方法。

Struts 2执行数据校验的流程图。


[b]4.3 使用Struts 2控制文件上传[/b]

为了实现上传文件,必须将表单的method设置为post,将enctype设置成multipart/form-data,只有在这种情况下,浏览器参会把用户选择文件的二进制数据发送到浏览器。
一旦设置enctype为multipart/form-data,浏览器将采用二进制流的方式来处理表单数据。


【Struts 2 的文件上传】

Struts 2并未提供自己的请求解析器,而是调用其他上传框架来支持解析二进制请求数据。
可在struts.properties中设置struts.multipart.parser属性来选择解析器,Struts 2默认使用jakarta的Commons-FileUpload的文件上传。(这也是为什么开发保重有commons-io.jar和commons-fileupload.jar的原因)。


【实现文件上传的Action】

Struts 2的Action无需处理HttpServletRequest请求,正如前面介绍的,Struts 2的Action与Servlet API彻底分离了,Struts 2框架负责解析HttpServlet请求中的参数。
如果表单包含一个name属性为xxx的文件域,则对 Action需要使用三个属性来封装该文件域的信息:1、文件域文件内容 File类型,2、文件域对应的文件的文件名,3、文件域对应的文件的文件类型。

Action的属性还可通过Struts 2配置文件进行配置,接受Struts 2框架的注入,允许在配置文件中为该属性动态指定值。

【配置文件上传的Action】

配置文件上传的Action与普通 Action并无太大区别,区别是,该Action还配置了<param…/>元素。

简单的上传把文件保存到服务器时该文件的文件名依然没有发生改变,这需要改进,建议使用java.util.UUID工具类来生成唯一的文本名。

Struts 2实现文件上传的编程关键,就是使用三个属性来封装文件域,分别对应文件名,文件类型,文件内容。


【手动实现文件过滤】

在Action里边有两个方法分别用于获取文件类型和文件大小,完全可以通过判断两个方法的返回值来实现文件过滤。


【拦截器实现文件过滤】

手动实现虽简单,但要写大量代码。
Struts 2提供了一个文件上传的拦截器,通过配置该文件可实现更轻松地文件过滤。拦截器是fileUpload,为了让该拦截器起作用,只需在Action中配置该拦截器引用即可,可谓该拦截器制定两个参数:allowTypes、maximumSize。

如使用文件上传拦截器,则必须显示配置引用Struts默认的拦截器栈:default Stack,而fileUpload必须配置在default Stack拦截器栈之前。

【输出错误提示】

开发者只需使用<s:fielderror/>来显示输出上传失败的校验提示。

【文件上传的常量配置】

即可在struts.properties里边配置,又可在struts.xml文件中配置。

default.propertiesstruts.properties
struts-default.xml->struts-plugin.xml->struts.xml->web.xml


[b]4.4 使用Struts 2控制文件下载[/b]

Struts 2提供了一个stream结果类型,该结果类型专门用于支持文件下载功能的。指定stream结果类型时,需要指定一个inputName参数,该参数指定了一个输入流,这个输入流是被下载文件的入口。

【实现文件下载的Action】

Struts 2的文件下载Action与普通 Action无太大区别,仅仅是该Action提供了一个返回InputStream流的方法,该输入流代表了被下载文件的入口。


【配置Action】

只需配置一个类型为stream的结果,该结果将使用对文件下载作为响应。
该stream类型有4个属性:contentType:被下载文件的类型
inputName:入口输入流
contentDisposition:指定下载的文件名。
bufferSize:下载时的缓冲大小。


[b]4.5 详解Struts 2的拦截器机制[/b]


拦截器体系是Struts 2框架的重要组成部分,可把Struts 2理解成一个容器,而内建的拦截器完成了该框架的大部分操作,比如:
params拦截器负责解析http请求的参数,并配置Action的属性、
servlet-config拦截器:直接将HTTP请求中的HttpServletRequest和HttpServletResponse实例传给Action。
fileUpload拦截器:负责解析请求参数中的文件域,并将一个文件与=域设置成Action的三个属性。
等等等………………


Struts 2拦截器是可插拔式的设计,需用使用的时候,只需在配置文件中设置该拦截器即可。拦截器由struts-default.xml和struts.xml等配置文件管理。


【拦截器在Struts 2中的作用】

Struts 2框架的大部分功能都是通过拦截器来实现的,当StrutsPrepareAndExecuteFilter拦截到用户请求后,大量拦截器将会到用户请求进行处理,然后才调用用户开发的Action来处理请求。
实际上,Struts 2已默认启用了大量通用功能的拦截器,只要在struts-default包中配置了,这些拦截器都会起作用。


【Struts 2内建的拦截器】

Strus 2拦截器几乎完成了Struts 2框架的70%的工作。


【配置拦截器】

在struts.xml文件中定义拦截器只需为拦截器类指定一个拦截器名,就完成了拦截器的定义,注意:所有的拦截器或拦截器栈都在<interceptors….>元素下定义。
最简单的格式:<interceptor name=”拦截器名” class=”拦截器实现类”/>
如需在拦截器时传入参数:
<interceptor…..>
<param name=”参数名”>参数的值</param>
<interceptor>


另外,可把多个拦截器连在一起组成一个拦截器栈,一个拦截器栈包含了多个拦截器,但从程序的功能上看,拦截器和拦截器栈是统一的,实际上,我们完全可把拦截器栈当成一个更大的拦截器。

配置拦截器的语法格式:
<interceptor-stack name=”拦截器栈名”>
<interceptor-ref name=”拦截器名”/>
……..
</interceptor-stack>

系统为拦截器指定参数有如下两个时机:定义拦截器时、使用拦截器时。

【使用拦截器】

一旦定义了拦截器和拦截器栈后,就可使用拦截器或拦截器栈来拦截Action了,拦截器(包含拦截器栈)的拦截行为将会在Action的execute方法执行之前被执行。

配置格式:
<action…..>

<interceptor-ref name=”拦截器名”>
<param name=””>….</param>
</interceptor>
..........
</action>


【配置默认拦截器】

一旦为某个包配置了默认拦截器,如果该包中没有显示应用了某个拦截器,则默认拦截器将会起作用;如果Action还需使用默认拦截器,则需手动配置该默认拦截器的引用。
<default-interceptor-ref name=”默认拦截器名或拦截器栈名”/>


【实现拦截器类】

如果用户要开发自己的拦截器类,应该实现com.opensymphony.xwork2.interceptor,Interceptor接口。该接口包含三个方法:
Init():拦截实例化后,执行该方法
Destroy():该方法与inti()方法对应,在拦截器实例被销毁钱调用该方法,用于销毁init()方法里边打开的资源。
Intercept(ActionInvocation invocate):该方法是用户要实现的拦截动作,就像Action里边的execute方法。该方法返回一个字符串,系统将会跳转到逻辑试图对应的实际视图资源,不会调用被拦截的Action。该方法的ActionInvocation参数包含了被拦截Action的引用,一旦获得了Action的实例,几乎获得了全部的控制权,还可以调用该参数的invoke()方法,将控制权转给另外一个拦截器或转给Action的execute方法。


另外Struts 2提供了一个AbstractInterceptor类,该类提供了一个init()和destroy()方法的空实现。


【使用拦截器】

使用拦截器需要两个步骤:
1、通过<interceptor../>元素来定义拦截器
2、通过<interceptor-ref../>元素来使用拦截器。


【拦截方法的拦截器】


在默认情况下,我们为某个Action定义了拦截器,则这个拦截器会拦截该Action的所有方法,但在某些情况下,我们不想拦截所有方法,只需制定方法,此时就需要Struts 2拦截器的方法过滤特性。

为实现过滤方法,Struts 2提供了一个MethodFilterInterceptor类,该类是AbstractInterceptor类的子类,而AbstractInterceptor实现了拦截器Interceptor接口。
MethodFilterInterceptor—》AbstractInterceptor—》Interceptor


MethodFilterInterceptor类相对于其父类,提供了一个doIntercept(AbstractInvocation invocation)抽象方法。


在MethodFilterInterceptor方法中,额外增加如下两个方法:
Public void setExcludeMethods(Strinig excludeMethods);列出的方法不被拦截
Public void setIncludeMethods(String includeMsthods); 列出的方法将被拦截

在使用拦截器的时候(即在struts.xml文件中)设置excludeMthods属性指定不被拦截的方法。也可设置includeMethods属性指定需要被拦截的方法。
特别地,当excludeMethods和includeMethods的值存在冲突时,以includeMethods参数指定为胜。


【拦截器的执行顺序】

随着配置拦截器的顺序的不同,系统中的拦截器的执行顺序也不同,通常认为先配置的会先执行,但有些时候可能会少许出入。

对于在执行execute方法之前,位于拦截器链前的拦截器将先发生作用。在执行execute方法后,位于拦截器链前面的拦截器将后发生作用。

【拦截结果的监听器】

为了精确定义在execute方法执行结束后,在处理物力资源转向之前的动作,Struts 2提供了用于拦截结果的监听器,这个监听器是通过手动注册在拦截器内部的。

拦截结果的监听器接口:PreResultListener
如在Action中注册这个监听器,则只对该Action有效;
如注册在拦截器(或栈)中,则只要拦截器其作用的地方,这个拦截器接口都会被触发。

该监听器接口有个方法:
Public void beforeResult(ActionInvocation invocation,String returnCode);
注意:虽然beforeResult()方法可获得ActionInvocation实例,但千万不要通过该实例再次调用invoke方法,这将会再次执行Action处理,Action处理之后紧跟beforeResult()方法,这样会造成死循环。


【覆盖拦截器栈里特定拦截器的参数】

如需在使用拦截器栈时直接覆盖栈内某个拦截器的属性值,则在指定需要被覆盖的属性时,不能只指定属性名,还需加上该属性名的拦截栈名,如<拦截器名>.<属性名>


【使用拦截器完成权限控制】!!!

完成权限控制是拦截器的实用功能。

Action在实际处理逻辑之前,应该先执行权限检查,将权限检查放在拦截器中进行将会更加优雅。

检查用户是否登录,跟踪用户的Session来完成的,通过ActionContext即可访问到sessions属性,而拦截器的ActionInvocation实例可轻易地访问到ActionContext实例。

为避免为每个Action重复配置拦截器,可将拦截器配制成一个默认的拦截栈(这个拦截栈应包括default-stack拦截器栈和权限拦截器),并在制定的包中引用改权限,则该包中的所有Action都会自动增加权限检查功能。

[b]4.6 使用Struts 2的Ajax支持[/b]


Ajax,即异步JavaScript和XML技术,也是Web 2.0的核心。
通过Ajax技术,浏览者和服务器之间采用异步通信机制,从而避免了浏览者的等待。用户可连续发送多次异步请求,而无需等待服务器响应,当服务器响应成功返回浏览器时,浏览器使用DOM将服务器响应装载到当前页面的指定容器内。

Ajax的关键点在于异步请求。

【使用stream类型的Result实现Ajax】

Struts 2支持一种stream类型的Resut,这种类型的Result,允许直接向客服端浏览器生成二进制响应、文本响应等。
处理Ajax的Action与普通的Action无多大差异,它提供了一个返回二进制流的方法:
getResult()方法:返回的二进制流将会直接输出给浏览者。

JQuery是一个非常优秀的、轻量级的Ajax函数库,不仅提供了大量方便的工具函数,还对Ajax的支持既简单又强大。


【JSON的基础知识】

JSON的全程是JavaScript对象符号,它是一种轻量级的数据交换格式。最开始它是一种JavaScript语言的数据交换格式,后来慢慢地变为与语言无关的数据格式。这一点与XML类似。

JSON的主要数据结构有两种:

1、由key-value对组成的数据结构,这种数据结构在不同的语言中有不同的实现,例如在JavaScript中是一个对象,在Java中是一种Map结构,在C中是一个struct。
2、有序集合。这种数据结构在不同的语言中都有对应的实现,可能有list/vector/数组/序列等。


使用JSON语法创建对象:
通常创建对象:
//定义一个函数,作为构造器
Function Person(name,sex){
This.name=name;
This.sex=sex;
}
//创建一个Person实例
Var p=new Person(‘43’,’34’);
Alert(p.name);

从JavaScript1.2开始,创建对象有了一种更快捷的方法:
Var p={“name”:”dsf”,”sex”:”dsf”};
Alert(p.name);
这就是一种JSON语法。

创建JSON对象,总以{开始,以}结束,对象的每一个属性值名和属性值之间宜英文冒号“:”隔开,而多个属性定义之间以英文都好“,”隔开。

当然,使用JSON语法创建对象时,属性值不仅可以是普通字符串,也可以是任何基本数据类型,还可以是数组、函数甚至是一个JSONlingi语法创建的对象。

使用JOSN语法创建数组:
Attr=[value1,value2…..]

JSON语法简单易用,而且作为数据传输载体时,数据量更小,因此在Ajax交互中,往往不使用XML作为数据交换格式。
当服务器返回一个J满足JSON格式的字符串,利用json的扩展的方法,将该字符串转换为一个JSON格式的JavaScript对象。
Json2.js文件,该文件提供了一个全局的JSON对象,该对象包含两个方法:stringify和parse,
其中前者负责把一个JOSN对象转换为JSON格式的字符串,后者则负责把JSON格式的字符串转换为JSON对象。


【实现Action逻辑】
@JSON(name=”dsfasf”,……)
在Action中可使用JSON注释,注释指定了name属性,name属性用于改变JSON对象的属性名字,除此之外,JSON注释还支持这几属性:
Serialize:设置是否序列化该属性
Deserialize:设置是否反序列化该属性
Format:设置用于格式输出、解析日期表单域的格式。


【json插件及json类型的Result】
JSON插件提供了一种json类型的Result,一旦为某个Action指定了一个类型为json的Result,
则该Result无需映射到任何视图资源。
JSON插件会将Action里边的状态信息序列化成JSON格式的字符串,把字符串传给客服端浏览器。


需注意两点:
1、AJAX的post请求都是以UTF-8的方式进行编码的。
2、在struts.xml中配置包时,自己定义的包继承了json-default包,而不是再继承默认的struts-default包,应为只有在该包下才有jsonl类型的Result。

【实现JSP页面】

把JS框架jQuery和扩展方法包json2.js导入<script>标签中,编写触发函数。

4.7 本章小结

本章是Struts 2的高级内容,主要讲解了:
类型转换和输入校验、
文件上传和文件下载、
深入讲解了Struts 2的拦截器、
Ajax的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值