zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    火狐浏览器清理缓存快捷键
    SVN使用教程总结
    如何登陆服务器
    get、put、post、delete含义与区别
    zookeeper 半数可用/选举机制
    zookeeper 分布式安装/配置/启动
    lucene 统计单词次数(词频tf)并进行排序
    selenium 爬取空间说说
    MapReduce自定义InputFormat,RecordReader
    reduce 阶段遍历对象添加到ArrayList中的问题
  • 原文地址:https://www.cnblogs.com/zhai1997/p/12274245.html
Copyright © 2011-2022 走看看