一:Action中获取参数值
在Servlet中,我们通过doGet()/doPost()方法中的参数,获取request/response对象,然后提取参数值;
处理请求结束后,有数据需要携带返回客户端时,servlet中是通过request.setAttribute()的方式携带属性值返回客户端。
而在Action中,提供了三种方式获取参数、返回结果:
1:Action全局变量法
在Action中定义一系列全局变量,以及它们的getter/setter方法。则在请求分发到action时,会自动提取request中的同名参数值,注入到action实例的全局变量中。
action返回result时,Structs2默认全局变量值都内置到了request中了,只需转发request到结果页面,在结果页面通过EL表达式,根据参数名获取值即可。
2:面向对象思想接收参数(用此方法则不能用法一)
如果action需要接收的参数比较多时,需要借助MVC架构中的VO对象思想。
此时,我们可以定义一个实体类 xxVO,实体类中定义一系列属性,对应客户端需要传递过来的值,并定义每个属性的getter/setter方法。
然后,在action中,我们只需引入一个xxVO的成员变量并定义其setter、getter方法即可,然后在action中通过 vo.getXX() 使用参数。
最后,我们在页面端通过 参数名 来为vo对象的属性进行赋值:如:<input name="vo.属性名">
在接收到请求后,Structs2会自动根据参数名,创建一个vo对象调用setter方法把属性值赋值,然后把vo对象注入到action中。
返回结果数据同法1,此action中的属性变量均可以在页面端以EL表达式获取。
3:优化法2——实现ModelDriven接口
法2中,页面端参数名需要使用 vo对象名.属性名 的格式,这样如果action中的vo对象名改变的话,页面端参数名都需要更改,比较麻烦。法3可以解决这个问题。
定义action时,实现ModelDriven接口;
声明并通过new VO()实例化vo成员变量;//注意:这里是使用new实例化变量,不是注入。
最后,在页面端,参数名只需与vo类中的属性名相同即可,无需指明是action中哪个vo对象的哪个属性。
页面端的参数,可以通过 []运算符、 点运算符进行复杂的参数赋值,如:为action中的list对象的元素赋值,可以:name="list[i].vo.属性名" 这样赋值。
二:Action中获取request、response、application等对象
有些情况下的确需要用到request、response、application等对象时,可以在定义action时实现资源接口xxxAware来达到。
定义Action时,实现RequestAware/SessionAware/ApplicationAware接口,并在Action中定义相应类型的变量,如:HttpSession session;然后实现接口的方法setXX(){this.XX=XX;}即可把相应的Servlet内置对象获取到action中来使用。
三:Action命名空间影响action的搜索
客户端请求action的url的格式为:web项目url+命名空间+action名
命名空间是为了模块化地管理action而配置的package属性,提供精准的action匹配,所以客户端应该严格按照正确的路径来编写URL。
四:配置Action的动态方法调用——通配符法
通常,我们把Action作为模块的单位,即:一个模块的所有请求处理都在一个action中处理,如:登录模块的相关请求都在loginAciton中定义方法来处理。但是,我们在配置action时,默认是执行action的execute()方法,如果需要调用其他方法,则需要为每种情况配置一个action标签,十分麻烦。
Structs2提供了一种通配符的方法,根据客户端传过来的URL内容,动态地匹配具体的action、具体的方法。
action标签的name属性:采用 * 代替具体内容,采用 _ 作为间隔。
URL的拼写:用 _ 作为间隔,指明具体的url。
在class属性值、method属性值、<result>标签内容等地方:采用 {x} 获取name属性值中 第几个* 的值作为具体值,动态匹配具体的action、方法、以及页面响应。
五:默认action
当用户输入了非法的url时,由于服务端没有对应的资源可以响应,就会返回404错误或者跳转到报错页面,这样用户体验是非常差的。因此,我们可以定义一个action,默认返回一个友好的ERROR提示页面。然后在structs.xml中配置默认action,引用该错误提示action进行返回。
六:后缀配置
Structs默认使用action处理请求,action的是 .action 后缀的文件,因此可以不写后缀编写url。如果需要使用其他后缀,如:.do、.html、.jsp等(注:这里是指使用这些后缀,而非真正的使用这些类型的文件。如:处理登录页面的loginAction类,配置扩展后缀 .jsp,则核心控制器获取到请求后如果是loginAction.jsp则仍然是把请求分发给loginAction而不是login页面)
<constant name="struts.action.extension" value="action,do,..." />
七:action结果响应
1:结果集
Action默认封装了一些字符串常量,表示某种结果类型。Structs2根据结果字符串进行不同的响应,这些都是通过<result>标签来配置的。
<result>默认结果是SUCCESS,当action返回结果是SUCCESS字符串时,重定向到标签间页面。
我们可以通过name属性值,配置不同返回结果的响应内容:
除此之外,我们也可以返回自定义的字符串,只需配置好name属性为返回结果字符串的result标签即可。
2:返回结果——INPUT
上面5个返回值中,INPUT比较特殊,它是Structs提供给我们的礼物之一——INPUT结果值表示自动返回前一个接收输入的页面,并保留了原先接收到的输入内容。
比如:登录页面接收username和password,传递给loginAction;若发现密码错误,需要返回登录页面时,action返回INPUT结果,则Structs2自动跳转到login页面,并保留原来输入的username和password内容在输入框内。
这样做的好处是,当某一些需要接收很多输入的页面(如:注册)传递过来的参数有少数没通过验证时,用户无需重复进行大量输入,只需修改部分不符合要求的输入即可。
有两种方法使用INPUT:
1)在action的普通方法中,如果验证不通过,则显式 return INPUT;
2)重写validate()方法,如果验证不通过,则添加错误信息(见下面第八点);在方法结束前,会自动检查错误信息map,如果不为空则说明验证不通过,自动返回INPUT。
3:全局结果
全局结果:放在action标签之外配置,在同一package内的所以action都可以使用这个结果,通常用来配置一些共用的结果值,如:404
4:结果响应方式——type属性
result标签的type属性定义了以什么样的方式来响应,重定向?还是转发?还是其他?默认是内部转发dispatcher。
type属性有以下几种:
chain:用来处理Action链,被跳转的action中仍能获取上个页面的值,如request信息.
dispatcher:用来转向页面,通常处理JSP.
freemaker:处理FreeMarker模板.
httpheader:控制特殊HTTP行为的结果类型.
redirect:重定向到一个URL,被跳转的页面中丢失传递的信息,如request.
redirectAction:重定向到一个Action,跳转的页面中丢失传递的信息.
stream:向浏览器发送InputSream对象,通常用来处理文件下载,还可用于返回AJAX数据.
velocity:处理Velocity模板.
xslt:处理XML/XLST模板.
plainText:显示原始文件内容,例如文件源代码,相当于out.write()
redirect和redirectAction的区别:前者跳转到一个页面,后者跳转到一个action。
八:错误信息
在Servlet编程中,服务器端校验不通过时,是通过 out.write()方法输出错误信息到客户端的,十分麻烦,还需要自己拼接前端页面代码。
在Struts2中提供了一个错误信息map,以键值对的方式添加错误信息;在页面端,通过structs2的标签,用key获取具体的错误信息内容即可,十分方便。
1:在action中添加错误信息,如:
2:在页面端使用标签获取错误信息
首先,引入标签库
然后,通过 name属性获取错误信息