1、Struts与OGNL的结合原理
(1)值栈:
OGNL表达式要想运行就要准备一个OGNLContext对象,Struts2内部含有一个OGNLContext对象,名字叫做值栈。
值栈也由两部分组成,一部分叫做root,里面放置的是栈,另一部分是context放入的是数据中心。
(2)栈:
利用了栈先进先出的特点,每次放入元素的时候是放入到索引为零的位置,取出的时候也是取出索引为零的元素,即:从下图的最上方元素取,符合栈的先进先出的特性。
2、
(1)root(栈)
默认情况下栈中存放当前访问的Action。
(2)context:
存放以下这些东西:
即:
3、Struts2与OGNL结合的体现
(1)Action以属性名的方式获取数据解析:
直接输出属性名,保持和表单的name属性的值相同。
表单将数据提交给拦截器,拦截器获取到“name=zhai”后,交给OGNL处理,OGNL从root中拿到name属性并赋值为“zhai”,由此,Action获取到了表单提交的数据。
(2)对象方式:
表单:
获取:
OGNL从栈顶获得user对象后,获得其name属性并将其值设置为“zhai”,由此,Action获取到了表单提交的数据。
(3)模型驱动
OGNL获取到name=zhai后,在值栈的root中,将user压入栈顶,并给user中的name赋值,也就是说从栈顶取元素并赋值。
原理演示:
创建一个Action:
public class ActionStack extends ActionSupport implements Preparable { User user=new User(); public String execute(){ System.out.println(user); return "success"; } @Override public void prepare() throws Exception { ValueStack valueStack=ActionContext.getContext().getValueStack(); valueStack.push(user); } }
实现Preparable接口的原因:
要在赋值前将user压入栈顶 ,而将获取栈的代码和将user对象压入栈顶的代码写入到prepare()函数中的目的正是获取栈并在赋值前将user对象压入栈顶。
源码分析:
input,back,cancel,browse input,back,cancel,browse
在众多的拦截器中,params拦截器位置相对靠后,因此需要将params拦截器放到prepare拦截器的位置,以实现赋值前将user压入栈顶。
那么如何操作呢?打开prepare拦截器的源码可知要调用prepare拦截器需要实现Preparable接口并调用 prepare()方法。
配置Struts的配置文件、创建表单、User类后将表单数据提交给Action:
public class ActionStack extends ActionSupport implements Preparable { User user=new User(); public String execute(){ System.out.println(user); return "success"; } @Override public void prepare() throws Exception { ValueStack valueStack=ActionContext.getContext().getValueStack(); valueStack.push(user); } }
4、在struts.xml配置文件中的使用
(1)创建两个Action:
Action1:
public class Action1 extends ActionSupport { private String name; public String execute(){ name="zhang"; return "success"; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Action2:
public class Action2 extends ActionSupport { public String execute(){ return "success"; } }
(2)配置Struts.xml配置文件,使得访问Action1的时候能够重定向到Action2,:
<package name="action" namespace="/a" extends="struts-default"> class="pers.zhb.hello.Action2" method="execute"> hello.jsp class="pers.zhb.hello.Action1" method="execute"> package>Action2 /a ${name}
(3)访问Action1:
也就是说在配置struts.xml配置文件的时候,在标签内部将name属性的值设置为属性不能识别的值,就可以在重定向的时候将参数加到另外一个Action。