参考(http://www.cnblogs.com/wang-meng/)
Struts2框架的大致处理流程如下:
1、加载类(FilterDispatcher)2、读取配置(struts配置文件中的Action)3、派发请求(客户端发送请求)4、调用Action(FilterDispatcher从struts配置文件中读取与之相对应的Action )5、启用拦截器(WebWork拦截器链自动对请求应用通用功能,如验证)6、处理业务(回调Action的execute()方法)7、返回响应(通过execute方法将信息返回到FilterDispatcher)8、查找响应(FilterDispatcher根据配置查找响应的是什么信息如:SUCCESS、ERROER,将跳转到哪个jsp页面)9、响应用户(jsp--->客户浏览器端显示)10、struts2标签库(相比struts1的标签库,struts2是大大加强了,对数据的操作功能很强大)
我们在书写Action的时候有哪几种方式?他们有什么区别?
有三种方式:
①普通POJO(简单Java对象),这种方式我们不需要继承任何父类,实现任何接口。Struts2框架读取struts.xml文件,获得完整的action类名。
obj =Class.forName("完整类名").newInstance();
Method m =Class.forName("完整类名").getMethod("execute");
m.invoke(obj);//通过反射 执行execute()方法
②编写Action实现Action接口
Action接口中,定义默认五种逻辑视图名称
// 数据处理成功 (成功页面)
publicstatic final String SUCCESS ="success";
// 页面不跳转 return null; 效果一样
publicstatic final String NONE ="none";
// 数据处理发送错误 (错误页面)
publicstatic final String ERROR ="error";
// 用户输入数据有误,通常用于表单数据校验 (输入页面)
publicstatic final String INPUT ="input";
// 主要权限认证 (登陆页面)
publicstatic final String LOGIN ="login";
③编写Action继承ActionSupport(推荐)
在Action中使用表单校验、错误信息设置、读取国际化信息三个功能
代理模式,控制目标对象访问
/hello.action 请求时StrutsPrepareAndExecuteFilter的 doFilter一定执行
//判断配置文件中有没有对应Action
ActionMapping mapping = prepare.findActionMapping(request, response,true);
//根据配置创建代理对象
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, method, extraContext,true,false);
执行时:先执行interceptor的intercept拦截方法,最后指向action的execute
Action的相关配置?
1)必须要为<action>元素 配置<package>元素 (struts2 围绕package进行Action的相关配置 )
配置package 三个常用属性
<packagename="default"namespace="/"extends="struts-default">
①name包名称,在struts2的配置文件中,包名不能重复,name并不是真正包名,只是为了管理Action
②namespace和 <action>的name属性,决定 Action的访问路径 (以/开始 )
namespace="" :默认的名称空间
namespace="/" :根名称空间
namespace="/aa/" :带有名称空间的路径
namespace="/" :根名称空间
namespace="/aa/" :带有名称空间的路径
③extends继承哪个包,通常开发中继承struts-default包 (struts-default包在 struts-default.xml中定义 )【可以使用包中默认的拦截器和结果集】
2)Action是通过<action>元素配置
<action name="hello"class="cn.itcast.struts2.demo1.HelloAction" method="execute">
①<action>的name和 <package>的namespace属性共同决定 Action的访问路径
②class:类全路径
③method:执行的方法,默认为execute()方法
例如:
<package name="default"namespace="/user" extends="struts-default">
<action name="hello"class="cn.itcast.struts2.demo1.HelloAction">
<result name="success">/demo1/success.jsp</result>
</action>
</package>
Action访问Servlet API有哪几种方式,简单的介绍一下
①.方式一:使用ActionContext对象(在Action中解耦合方式间接访问Servlet API)
在struts2中Action API已经与Servlet API 解耦合(没有依赖关系),开发简单,便于测试。
Servlet API 常见操作 : 表单提交请求参数获取,向request、session、application三个范围存取数据
②.方式二:使用接口注入的方式操作Servlet API(藕合)
通过Aware接口,在构造Action时,自动注入需要操作Servlet对象(需要哪个对象就实现哪个Aware接口)
③.方式三:在Action中直接通过 ServletActionContext 获得Servlet API
静态方法返回request,不会有线程问题(使用了ThreadLocal来实现的)
总结:理论来说,第一种方式最好,实现了解耦和,但是第三种我们使用最为简单,企业中没有很大的限制,自己熟悉哪种就使用哪种。
如何防止表单重复提交?
哪些情况会导致重复提交?
服务器处理服务后,转发页面,客户端点击刷新(重定向)
客户端网络过慢,按钮连续点击(按钮点击一次后,禁用按钮)
使用令牌机制
拦截器和过滤器有什么区别?
1、①拦截器是基于java的反射机制的,而过滤器是基于函数回调
2、②过滤器依赖与servlet容器,而拦截器不依赖与servlet容器
3、③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
4、④拦截器可以访问action上下文、值栈里的对象,而过滤器不能
5、⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
拦 拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
Struts2请求流程
1、客户端发送请求
2、请求先通过ActionContextCleanUp-->FilterDispatcher
3、FilterDispatcher通过ActionMapper来决定这个Request需要调用哪个Action
4、如果ActionMapper决定调用某个Action,FilterDispatcher把请求的处理交给ActionProxy,这儿已经转到它的Delegate--Dispatcher来执行
5、ActionProxy根据ActionMapping和ConfigurationManager找到需要调用的Action类
6、ActionProxy创建一个ActionInvocation的实例
7、ActionInvocation调用真正的Action,当然这涉及到相关拦截器的调用
8、Action执行完毕,ActionInvocation创建Result并返回,当然,如果要在返回之前做些什么,可以实现PreResultListener。添加PreResultListener可以在Interceptor中实现。