• struts2 ognl表达式访问值栈


    1:简单的说,值栈是对应每一个请求对象的轻量级的数据存储中心,在这里统一管理着数据,供Action、Result、Interceptor等Struts2的其他部分使用,这样数据被集中管理起来而不凌乱。

          简单的说,值栈能够线程安全的为每个请求提供公共的数据存取服务。

          当有请求的时候,Struts2会为每个请求创建一个新的值栈,也就是说,栈和请求是一一对应的,不同的请求,值栈也不一样,而值栈封装了一次请求所有需要操作的相关的数据。

         正是因为值栈和请求的对应关系,因此值栈能保证线程安全的为每个请求提供公共的数据存取服务。

    2:狭义值栈

         通常是指com.opensymphony.xwork2.util.ValueStack接口的对象,目前就是com.opensymphony.xwork2.ognl.OgnlValueStack对象。

         狭义值栈主要用来存放动态EL(表达式语言)运算需要的值和结果,当然OgnlValueStack对象主要是用来支持OGNL(对象图导航语言)运算的。

         狭义值栈中存放着一些OGNL可以访问的数据,如下:

            a:action的实例,这样就可以通过OGNL来访问Action实例中的属性的值了。

            b:OGNL表达式运算的值,可以设置到值栈中,可以主动访问值栈对象,强行设置。

            c:OGNL表达式产生的中间变量,比如使用Struts2标签的时候,使用循环标签,自然会有循环的变量,这些都放在值栈中。

     

    3:广义值栈

       通常是ActionContext对象,ActionContext是Action运行的上下文,每个ActionContext是一个基本的容器,包含着Aciton运行需要的数据,比如请求参数,会话等。

      ActionContext也是线程安全的,每个线程都有一个独立的ActionContext,这样就不用担心值栈中值得线程安全问题了。

      ActionContext里面存储着很多值,如下:

         a:Request的Parameters,请求中的参数,注意这里的数据是从数据对象中复制来的,因此这里的数据的变化是不会影响到请求对象里面的参数的值的。

         b:Request的Attribute,请求中的属性,这里是一个Map,存放着请求对象的属性数据,这些数据和请求对象的Attribute是联动的。

         c:Application的Attribute,应用的属性,这里是一个Map,存放着应用对象的属性数据,这些数据和应用对象的attribute是联动的。

         d:ValueStack,也就是狭义值栈,ActionContext是以value stack作为被OGNL访问的根,简单的说,OGNL在没有特别指明的情况下,访问的就是value stack的值。

         e:attr,在所有的属性范围中获取值,依次搜索page, request, session 和applicaion

     

    4:ActionContext的使用

       获取,通过两种方式,第一种,使用ActionContext自身的方法来获取

         ActionContext ctx = ActionContext.getContext();

       第二种,使用ActionInvocation来获取

         ActionContext ctx = actionInvocation.getInvocationContext();

       它的典型方法如下:

       

     Objectget(String key):Returns a value that is stored in the current ActionContext by doing a lookup using the value's key.
    
      void put(String key,Object value):Stores a value in the current ActionContext.
    
      Map<String,Object>getApplication():  Returns a Map of the ServletContext when in a servlet environment or a generic application level Map otherwise.
    
                                             即返回ServletContext中返回的值
    
      Map<String,Object>getSession():Gets the Map of HttpSession values when in a servlet environment or a generic session map otherwise.
    
      Map<String,Object>getContextMap():Gets the context map.
    
      Map<String,Object>getParameters(): Returns a Map of the HttpServletRequest parameters when in a servlet environment or a generic Map of parameters otherwise.
    
      

    5:ValueStack的使用

       ValueStack有一个特点,如果访问的值栈里有多个对象,且相同的属性在多个对象中同时出现,则值栈会按照从栈顶到栈底的顺序,寻找第一个匹配的对象。

       ValueStack的获取:直接由ActionContext对象的getValueStack()方法即可获得。

       使用函数:

      

      ObjectfindValue(String expr): Find a value by evaluating the given expression against the stack in the default search order.
    
        voidsetValue(String expr,Object value):  Attempts to set a property on a bean in the stack with the given expression using the default search order.
    
         Object peek():Get the object on the top of the stack without changing the stack.
    
         Objectpop():Get the object on the top of the stack and remove it from the stack.
    
         voidpush(Object o):Put this object onto the top of the stack

    6:例子,修改用户输入的参数信息,如下图所示,

      


          图:用户输入了aa的username

     


                       图:用户提交后发现username属性的值发生了变化

    实现:

      首先定义一个实现PreResultListener接口的类:MyPreResultListener

      

    [html] view plain copy
     
    import com.opensymphony.xwork2.ActionInvocation;  
    import com.opensymphony.xwork2.interceptor.PreResultListener;  
      
    public class MyPreResultListener implements PreResultListener {  
      
        @Override  
        public void beforeResult(ActionInvocation invocation, String resultCode) {  
            System.out.println("现在处理Result执行前的功能, result=" + resultCode);  
              
            //在Result处理之前修改value stack里面的username对应的值  
            invocation.getInvocationContext().getValueStack().setValue("username", "被修改了");  
      
        }  
      
    }  
    
    
     
    
    然后在相应的Action中进行注册:
    
      
    
    [java] view plain copy
     
    import com.capinfotech.listener.MyPreResultListener;  
    import com.opensymphony.xwork2.ActionContext;  
    import com.opensymphony.xwork2.ActionSupport;  
      
    public class PreResultAction extends ActionSupport {  
      
        private String username;  
        private String password;  
      
        public String getUsername() {  
            return username;  
        }  
      
        public void setUsername(String username) {  
            this.username = username;  
        }  
      
        public String getPassword() {  
            return password;  
        }  
      
        public void setPassword(String password) {  
            this.password = password;  
        }  
          
        public String execute() {  
            System.out.println("用户输入的参数为,username:" + username + ", password:" + password);  
              
            ActionContext context = ActionContext.getContext();  
            MyPreResultListener preListener = new MyPreResultListener();  
            context.getActionInvocation().addPreResultListener(preListener);  
              
            return "success";  
              
        }  
      
    }  
    /*
     * $Id$
     *
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     *  http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */
    
    package org.apache.struts2.dispatcher;
    
    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.util.ValueStack;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    
    import static org.apache.commons.lang3.BooleanUtils.isTrue;
    
    /**
     * <!-- START SNIPPET: javadoc -->
     *
     * All Struts requests are wrapped with this class, which provides simple JSTL accessibility. This is because JSTL
     * works with request attributes, so this class delegates to the value stack except for a few cases where required to
     * prevent infinite loops. Namely, we don't let any attribute name with "#" in it delegate out to the value stack, as it
     * could potentially cause an infinite loop. For example, an infinite loop would take place if you called:
     * request.getAttribute("#attr.foo").
     *
     * <!-- END SNIPPET: javadoc -->
     *
     */
    public class StrutsRequestWrapper extends HttpServletRequestWrapper {
    
        private static final String REQUEST_WRAPPER_GET_ATTRIBUTE = "__requestWrapper.getAttribute";
        private final boolean disableRequestAttributeValueStackLookup;
    
        /**
         * The constructor
         * @param req The request
         */
        public StrutsRequestWrapper(HttpServletRequest req) {
            this(req, false);
        }
    
        /**
         * The constructor
         * @param req The request
         * @param disableRequestAttributeValueStackLookup flag for disabling request attribute value stack lookup (JSTL accessibility)
         */
        public StrutsRequestWrapper(HttpServletRequest req, boolean disableRequestAttributeValueStackLookup) {
            super(req);
            this.disableRequestAttributeValueStackLookup = disableRequestAttributeValueStackLookup;
        }
    
        /**
         * Gets the object, looking in the value stack if not found
         *
         * @param key The attribute key
         */
        public Object getAttribute(String key) {
            if (key == null) {
                throw new NullPointerException("You must specify a key value");
            }
    
            if (disableRequestAttributeValueStackLookup || key.startsWith("javax.servlet")) {
                // don't bother with the standard javax.servlet attributes, we can short-circuit this
                // see WW-953 and the forums post linked in that issue for more info
                return super.getAttribute(key);
            }
    
            ActionContext ctx = ActionContext.getContext();
            Object attribute = super.getAttribute(key);
    
            if (ctx != null && attribute == null) {
                boolean alreadyIn = isTrue((Boolean) ctx.get(REQUEST_WRAPPER_GET_ATTRIBUTE));
    
                // note: we don't let # come through or else a request for
                // #attr.foo or #request.foo could cause an endless loop
                if (!alreadyIn && !key.contains("#")) {
                    try {
                        // If not found, then try the ValueStack
                        ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.TRUE);
                        ValueStack stack = ctx.getValueStack();
                        if (stack != null) {
                            attribute = stack.findValue(key);
                        }
                    } finally {
                        ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.FALSE);
                    }
                }
            }
            return attribute;
        }
    }
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="s" uri="/struts-tags" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ page isELIgnored="false" %>
    <html>
    <body>
    <h2>Hello World!</h2>
    <h1><s:iterator value="list">
        <s:property value="userName"></s:property>
    </s:iterator></h1>
    
    <s:iterator value="list" var="item">
        <s:property value="#userName"></s:property>
    </s:iterator>
    
    
    <h3><s:property value="#info.userName"></s:property></h3>
    <s:debug></s:debug>
    </body>
    </html>
  • 相关阅读:
    双向循环链表
    字符串拷贝
    div样式调整.txt
    解析xml的单个节点值和循环节点消息体
    C++中的string
    正则表达式教程
    一个很好的Qt教程个人主页
    单射、双射与满射
    ISO C++ forbids declaration of * with no type
    一个中学生的个人主页
  • 原文地址:https://www.cnblogs.com/wei-91/p/6534878.html
Copyright © 2020-2023  润新知