前一段时间,有关chain的机制着实困绕了许久.尽管网上有许多关于chain的解说,但要不是只谈大理论,不结合实例;要不就是只有示例,没有挖出示例背后的意义.
先解释下chain吧:
Chain:基本用途是构造成一条动作链。前一个动作将控制权转交给后一个动作,而前一个动作的状态在后一个动作里仍然保持着。动作链由Chaining拦截器负责处理,因为这个拦截器是defaultStack拦截器栈的一份子,多以你随时都可以使用动作链。
有人说:chain是共享valuestack;也有人说chain是共享表单参数.就我个人而言,以上两种说法都不见完全正确.
先看一个chain的例子:
struts.xml:
<package name="default" extends="struts-default"> <action name="action1" class="web.action.Action1"> <result type="chain">action2</result> </action> <action name="action2" class="web.action.Action2"> <interceptor-ref name="defaultStack"></interceptor-ref> <result>/result2.jsp</result> </action> </package>
Action1.java
public class Action1 extends ActionSupport { private String str1; private String str2; public String execute() throws Exception { return SUCCESS; } public String getStr1() { return str1; } public void setStr1(String str1) { this.str1 = str1; } public String getStr2() { return str2; } public void setStr2(String str2) { this.str2 = str2; } }
Action2.java
public class Action2 extends ActionSupport { private String str1; private String str2; public String execute() throws Exception { return SUCCESS; } public String getStr1() { return str1; } public void setStr1(String str1) { this.str1 = str1; } public String getStr2() { return str2; } public void setStr2(String str2) { this.str2 = str2; } }
接着再上jsp文件:
result1.jsp
<form action="action1.action" method="post"> str1:<input type="text" name="str1"><br/> str2:<input type="text" name="str2"><br/> <input type="submit"> </form>
result2.jsp
<s:debug/> str1:${str1 } <br/> str2:${str2 }
其实整个流程如下图所示:
运行结果也很简单,没有悬念:
在result1.jsp输入:str1=111,str2=222
在result2.jsp显示:str1=111,str2=222
下面进入探讨阶段:
首先修改下action1.java,在action1中,修改valuestack中的str1的,如下所示:
public class Action1 extends ActionSupport { private String str1; private String str2; public String execute() throws Exception { str1="set in action1"; return SUCCESS; } //省掉get,set }
再次来运行.
在result1.jsp输入:str1=111,str2=222
在result2.jsp显示:str1=111,str2=222
结果很奇怪?为什么在result2.jsp不是显示str1=set in action1? 难道action1.java中修改过后的str1的值没有写入valuestack
那我们看看result2.jsp中通过<s:debug/>打印出来的信息.
从debug信息可以看出:
1)在action1的valuestack中,str1的确被成功修改了.
2)但是action2中的valuestack中,str1还是停留在页面上输入的str1的值
难道action1中的valuestack没有共享到action2中的valuestack?
为了进一步了解事实真相,我们继续来做实验:
接下来,我在action2.java中的setStr1(String str)中设置断点,跟踪action2中str1的赋值情况
发现:str1其实是被赋了两次值:第一次是"set in action1",而第二次是"111"
如此就得到了如上所示的运行结果.
很奇怪是吧?
我猜测第二次赋值中的"111"来自jsp提交过后产生的表单参数对象,即parameters.
为了验证猜测,我们把result1.jsp中的str1的输入去掉,如下代码所示:
<form action="action1.action" method="post"> str2:<input type="text" name="str2"><br/> <input type="submit"> </form>
然后重新运行result1.jsp
运行过程所下:
在result1.jsp中输入str2=222
在result2.jsp中显示:str1=set in action1,str2=222
OK,如此,我们在action1中的对str1的修改成功传递给了action2,而action2中setStr1()也只执行了一次.
真相呼之欲出了,我们还是用一幅图来表示整个过程
如此,在执行第四步的时候,如果表单参数中和action1的valuestack中同时有str1这一项,
则表单参数中str1会覆盖action1的valuestack中的str1,最终action2的str1是以表单参数中的str1为准
好了,以上仅是根据运行结果作出的猜测和解释.
若想进一步了解事实的真相,从源代码的角度解释这一现象,可参考我接下来要写的<<浅谈struts2之chain[2]>>
先吃饭.下午接着写<<浅谈struts2之chain[2]>>