Struts2与OGNL的联系
Posted Dream
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Struts2与OGNL的联系相关的知识,希望对你有一定的参考价值。
1、Struts与OGNL的结合原理
(1)值栈:
OGNL表达式要想运行就要准备一个OGNLContext对象,Struts2内部含有一个OGNLContext对象,名字叫做值栈。
值栈也由两部分组成,一部分叫做root,里面放置的是栈,另一部分是context放入的是数据中心。
(2)栈:
利用了栈先进先出的特点,每次放入元素的时候是放入到索引为零的位置,取出的时候也是取出索引为零的元素,即:从下图的最上方元素取,符合栈的先进先出的特性。
2、<s:debug>标签(查看值栈中的内容)
(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对象压入栈顶。
源码分析:
<interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="i18n"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="datetime"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="debugging"/> <interceptor-ref name="deprecation"/> </interceptor-stack>
在众多的拦截器中,params拦截器位置相对靠后,因此需要将params拦截器放到prepare拦截器的位置,以实现赋值前将user压入栈顶。
那么如何操作呢?打开prepare拦截器的源码可知要调用prepare拦截器需要实现Preparable接口并调用 prepare()方法。
配置Struts的配置文件、创建表单、User类后将表单数据提交给Action:
<body>
<form action="${pageContext.request.contextPath}/s/ActionStack">
用户名:<input type="text" name="username"/><br>
<input type="submit" value="提交"/>
</form>
</body>
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,:
<struts> <package name="action" namespace="/a" extends="struts-default"> <action name="Action2" class="pers.zhb.hello.Action2" method="execute"> <result name="success" type="dispatcher">hello.jsp</result> </action> <action name="Action1" class="pers.zhb.hello.Action1" method="execute"> <result name="success" type="redirectAction"> <param name="actionName">Action2</param> <param name="namespace">/a</param> <param name="name">${name}</param> </result> </action> </package> </struts>
(3)访问Action1:
也就是说在配置struts.xml配置文件的时候,在<param>标签内部将name属性的值设置为属性不能识别的值,就可以在重定向的时候将参数加到另外一个Action。
以上是关于Struts2与OGNL的联系的主要内容,如果未能解决你的问题,请参考以下文章
Struts2学习笔记三:OGNL表达式学习Struts2与Ognl表达式的结合原理