Struts2
1.MVC模式
MVC即模型(Model),视图(View),控制器(Control)的简写,是一个分工明确的架构模式;
Model:模型,负责封装应用的状态,并实现应用的功能,用分为数据模型和业务逻辑模型,数据模型用来存放业务数据,业务逻辑模型包含应用的业务操作。
View:视图,用来将模型的内容呈现给用户,用户可以通过视图来请求模型进行更新,视图从模型中获取要展示的数据,然后用特定的方式呈现给用户,同时,用户可以通过在视图上的操作,来向控制器发出请求。
Control:控制器,用来进行请求的转发以及控制应用程序的流程。当控制器接受到用户的请求后,调用模型来实现用户请求的功能,然后控制器会选择用于响应的视图,把模型更新后的数据展示为用户。
2.Struts2的系统架构
架构模块解释:
FilterDispacther:是Struts的调度中心,根据ActionMapper的结果来决定是否处理请求,如果请求URL应该被处理,则将会执行Action处理,并停止过链上还没有执行的过滤器。
ActionMapper:提供Http请求与Action执行之间的映射,即进行判断该请求是否被Struts2进行处理。
ActionProxy:位于Action和xwork之间,使得后期引入更多的实现方式。
ConfigurationManager:是xwork配置的管理中心,可以看做struts.xml配置文件在内存中的对应。
ActionInvocation:调用并执行Action,拥有一个Action实例,和这个Action所依赖的***实例,ActionInvocation会执行这个***,Action,以及对应的Result。
Interceptor:自动拦截Action,给开发者提供了在Action运行之前或Result运行之后来执行一些功能代码的机会。
Action:执行单元,用来封装业务所需要的数据。
Result:不同视图类型的抽象封装模型,不同的视图类型会对应不同的Result实现,Struts2支持多种视图类型。
Templates:各种视图类型的页面模板。
Tag Subsystem:Struts2的标签库。
3.Action
是用户操作的执行单元,在View视图中,一个action请求就对应着后台的一个Action类,即一个Action类对应着一个Action请求。Action在MVC中扮演的角色,一般认为Action作为MVC中的模型角色来看,虽然Action中也涉及控制器功能的部分,但是Struts在运行的时候,Struts的前端控制器FilterDispatcher分发并调度相应的Action,此时这个Action仅仅相当于一次请求的命令处理,
⑴Action的配置
在Struts.xml文件中通过在action标签中的class属性中,将其对应的Action类的全类名赋值该class值即可。
①<package>配置
package元素可以把逻辑上相关的一组Action,Result,Intercepter等元素封装起来,形成一个独立的模块,package也可以继承其他的package,package元素的属性有:
name - > 包名
extend ->需要继承的包
namespce -> 包的命名空间
abstract ->定义包为抽象的。
namespace:是包的命名空间,同一个命名空间中不能有相同的名字的action,但在不同的namespace中可以有,如果不配置namespce,则表示默认的enamespce,则在进行访问的时候不需要添加namespace前缀。如果使用了namespce,则在访问的时候需要添加namespace前缀的。
<action>配置:
是package的子元素,需要配置name属性和class属性,method属性,name为必须的,其他子元素有param,result,interceptor-ref.<action>元素的配置也支持使用通配符进行配置,例如:
<action name="*_*" class="com.dong.action.{1}Action" method="[2]">
name属性的*代表任意字符,因此想要和这个action匹配,只要中间带有_即可,例如:Action的名为hellword_query.action,这样class属性使用第一个通配符,(使用{1}作为占位),method属性使用第二个通配符。
默认的配置方式:
在配置struts.xml的时候,对于action来说,name属性时必须的,class可省略,class属性的默认值为com.opensymphony.xwork2.ActionSupport.如果没有class属性,则由于package元素的extends属性配置的是struts-default,即继承了一个叫struts-default的包,包下有一个struts-default.xml文件,这是struts2默认配置好的各个<package>元素的公用配置。在这个文件中,有一个配置<default-class-ref class = "com.opensymphony.xwork2.ActionSupport"/>,说明<action>元素不写class属性的时候,默认配置就是使用ActionSupport类。
⑵Action的实现
①POJO的实现
即不需要实现任何的接口或者继承特殊的类,仅仅是POJO(Plain Old Java Object,简单的Java对象)就可以,但需要有一个公共的空参的构造方法,还要有一个execute方法。execute方法需要是公共的,无参的,返回一个字符串。
②继承ActionSupport类
ActionSupport类本身实现了Action接口,ActionSupport还实现了其他几个接口,提供更多的功能。例如:validate()方法,用来为Action增加验证的功能;getLocale()方法来获取本地消息。
⑶Action中的数据
Action中的数据就是用户在登录界面填写的数据,即这些数据来源于用户请求对象,就是Request对象。页面的值如何和Action的属性进行对应。
①属性驱动
分两种:1.基本数据类型的属性对应为属性驱动、2.JavaBean风格的属性对应为直接使用域对象。
1.基本类型的属性驱动:
Web页面上提交的HTML控件的name属性和Action的属性或者与属性相对应的getter/setter相对应。即当页面提交时,Struts2会自动从request对象里面吧数据提取出来,然后按照名称进行对应,自动设置到Action的属性里面去。action类的属性都是私有的,通过get/set方法访问,如果不想使用get/set方法,则可以将属性设置为public即可,但是建议设置为private。
2.直接使用域对象的属性驱动
把属性和对应的get/set方法从Action类中移除出去,单独做成一个域对象,然后再域对象中直接使用这个对象可以。
Action发生变化,在相应的HTML页面也需要改动,负责数据无法进行对应,即在相应的属性前面加上一个域对象的前缀,指明这个值到底对应到哪一个域对象里面去。
②模型驱动
Action类实现一个ModelDriven的接口,这个接口我们需要实现一个getModel的方法,这个方法返回的就是Action所使用的数据模型对象。当然在登录界面也需要调整,即直接使用name属性即可,不需要添加域对象的前缀。
⑷非String类型的传入
对于从页面传入的非String类型的值,Struts2会进行自动转换类型为Action类的类型,例如将页面接受到的数字字符转为Action类的int类型,但是当传入的是一个Null值,则会报错,因为Null不能转化为别的类型。
当我们使用包装类型时,如果页面的数据没有填入,则会默认传入的值为Null,
⑸传入多个值
在Action类中,我们有两种方法解决方法:
1.定义一个私有的String数组类型的属性,提供相应的get/set方法,当然直接定义一个public的String数组类型的属性也可以。
2.定义一个私有的集合类型的属性,例如List类型,提供相应的get/set方法。
⑹调用非execute方法
当需要调用非execute方法的时候,需要进行如下配置,首先在Action中实现被调用的方法,这个方法除了名字和execute不一样,其他的均一样,可见性为public, 无参。
4.Result
Result返回一个字符串,这个字符串指示了Action执行完成后,下一个页面在哪里。
ResultType类型指的是具体执行Result的类,有它来决定采用哪一种视图技术,将执行结果展现用户。
⑴预定义的Result的字符常量
SUCCESS:表示Action执行成功,显示结果视图给用户,值为字符串‘success';
NONE:表示执行成功,不需要显示视图给用户;
ERROR:表示Action执行失败,显示错误页面给用户
INPUT:表示执行Action需要更多的输入信息,回到input对应的页面
LOGIN:表示因为用户没有登录而没有正确的执行,将返回该登录视图。
⑵ResultType
Struts2中预定了很多ResultType,通过在struts-default包下的strut2-default.xml中,可以找到关于<result-type>的定义,显示了每一个<result-type>元素以及相应的实现方式。
⑶配置Result
配置name属性,name属性时用来跟Action的execute方法返回的字符串相对应的,用来标识Action运行后跳转到下一个页面,name可以是任意字符。如果不进行设置,默认为“success",正好与Action中的”SUCCESS"这个常量对应,这样的话,execute方法就应该返回SUCCESS。
配置type属性,在没有自定义的情况下,type属性值是在strut2-default.xml中定义的<result-type>的name属性值,默认的type为dispatcher,默认的可以不用配置,
result type的类型:
dispatcher:对应的实现类是ServletDispatcherResult,通过RequestDispatcher来进行页面的跳转,将会保持是同一个请求,即意味着是同一个请求对象,有着同样的数据。
redirect:可在struts2-default.xml文件中查看它所对应的类,它是一个全新的请求,即本次请求和跳转到下一个页面的请求是不同的对象。
chain:将Action执行完后链接到另一个action中继续执行,新的Action使用上一个Action,数据也会进行传递。一般是在一个请求被一个Action处理过后,不是立即产生响应,而是传递到下一个Action中继续处理的时候,这个时候可以使用类型为chain的result来满足需求。使用的时候需要在result标签的type属性设置为chain,同时再其下添加一个子标签,名为<param> 然后指定想要跳转的下一个Action。注意chain不能再result配置的时候传递参数。
...等等等。
⑷全局和局部Result
前面介绍的Result都是局部的,只对其包含的Action有用,如果想对所有的action建立一个公有的Result,则可以使用全局的Result。
配置方式为:
在package元素下使用<global-results></global-results>,剩下的配置和局部的Result没有区别。
Action运行后,根据execute方法返回值寻找Result顺序是:在自己的action元素内的result进行匹配,如果有,则执行这个result,无,则进行下一步 ---》然后再自己的action所在的package的全局Result进行匹配, 如果有,则执行这个result,无,则进行下一步,---》然后递归的寻找自己的包的父包,祖父包的全局Result,有,执行Result 无 则抛出异常。
5.Struts2的异常映射
局部异常映射
在Action元素中设置<exception-mapping>元素,可以指定在execute方法抛出指定错误的时候,跳转到哪个指定的页面。exception属性用来指定Exception的全类名。如果抛出的方法是这个Exception类的实例或其派生类的实例,则会跳转到对应的result属性所指定的结果。eg:
<action name="xxxAction" class="com.dong.xxxx" >
<exception-mapping result="math-exception" exception="java.lang.AritheticException"/>
<result name="math-exception"> /xxx.jsp</result>
<result name="success"> /xxx.jsp</result>
</action>
全局异常映射
和局部Result与全局Result是一样的,全局局部映射仍然是<exception-mapping>元素,只不过不在是<action>元素的子元素,而是<global-exception-mappings>元素的子元素,而<global-exception-mappings>元素是<package>元素的子元素,同时它的子元素也改为相应的<global-results> </globale-results>。
当发生异常的时候,对于其搜索结果和全局Result的搜索结果是一致的,从小范围到大范围慢慢扩张。
想在页面输出异常信息:可以使用Struts2提供的标签:<s:property value="exception"/>仅仅简单的打印exception对象的信息,<s:property value="exceptionstack"/> 可以打印出exception的堆栈信息,注意使用Struts2提供的标签需要进行标签的导入。
6.PreResultListener
在实际开发中,当执行完action后,而result还没有开始时,如果需要进行一些处理,可以使用preResultListener。
实现方式:
创建一个实现PreResultListener接口的类,然后再Action的execute方法里面,注册这个***对象
public class MypreResult implements PreResultListener{
'''
}
public string exectue() throws Exception{
PreResultListener pr = new MypreResult();
ActionContext.getContext().getActionInvocation().addPreResultListener(pr);
return this.SUCCESS;
}
参考《研磨Struts2》,建议亲自阅读此书,加深理解。