zoukankan      html  css  js  c++  java
  • struts2 ValueStack(值栈)解析

    Struts2一个重要点就是值栈。

    ValueStack,是用来存储一些在各个action,或者说是通过s标签、el表达式等给前台Jsp等页面展示的东西。

      ValueStack是一个接口,其内部接口非常简单:

      1 /*
      2  * Copyright 2002-2007,2009 The Apache Software Foundation.
      3  * 
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  * 
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  * 
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.opensymphony.xwork2.util;
     17 
     18 import java.util.Map;
     19 
     20 /**
     21  * ValueStack allows multiple beans to be pushed in and dynamic EL expressions to be evaluated against it. When
     22  * evaluating an expression, the stack will be searched down the stack, from the latest objects pushed in to the
     23  * earliest, looking for a bean with a getter or setter for the given property or a method of the given name (depending
     24  * on the expression being evaluated).
     25  */
     26 public interface ValueStack {
     27 
     28     public static final String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
     29 
     30     public static final String REPORT_ERRORS_ON_NO_PROP = "com.opensymphony.xwork2.util.ValueStack.ReportErrorsOnNoProp";
     31 
     32     /**
     33      * Gets the context for this value stack. The context holds all the information in the value stack and it's surroundings.
     34      *
     35      * @return  the context.
     36      */
     37     public abstract Map<String, Object> getContext();
     38 
     39     /**
     40      * Sets the default type to convert to if no type is provided when getting a value.
     41      *
     42      * @param defaultType the new default type
     43      */
     44     public abstract void setDefaultType(Class defaultType);
     45 
     46     /**
     47      * Set a override map containing <code>key -> values</code> that takes precedent when doing find operations on the ValueStack.
     48      * <p/>
     49      * See the unit test for ValueStackTest for examples.
     50      *
     51      * @param overrides  overrides map.
     52      */
     53     public abstract void setExprOverrides(Map<Object, Object> overrides);
     54 
     55     /**
     56      * Gets the override map if anyone exists.
     57      *
     58      * @return the override map, <tt>null</tt> if not set.
     59      */
     60     public abstract Map<Object, Object> getExprOverrides();
     61 
     62     /**
     63      * Get the CompoundRoot which holds the objects pushed onto the stack
     64      *
     65      * @return the root
     66      */
     67     public abstract CompoundRoot getRoot();
     68 
     69     /**
     70      * Attempts to set a property on a bean in the stack with the given expression using the default search order.
     71      *
     72      * @param expr  the expression defining the path to the property to be set.
     73      * @param value the value to be set into the named property
     74      */
     75     public abstract void setValue(String expr, Object value);
     76 
     77     /**
     78      * Attempts to set a property on a bean in the stack with the given expression using the default search order.
     79      * N.B.: unlike #setValue(String,Object) it doesn't allow eval expression.
     80      * @param expr  the expression defining the path to the property to be set.
     81      * @param value the value to be set into the named property
     82      */
     83     void setParameter(String expr, Object value);
     84 
     85     /**
     86      * Attempts to set a property on a bean in the stack with the given expression using the default search order.
     87      *
     88      * @param expr                    the expression defining the path to the property to be set.
     89      * @param value                   the value to be set into the named property
     90      * @param throwExceptionOnFailure a flag to tell whether an exception should be thrown if there is no property with
     91      *                                the given name.
     92      */
     93     public abstract void setValue(String expr, Object value, boolean throwExceptionOnFailure);
     94 
     95     public abstract String findString(String expr);
     96     public abstract String findString(String expr, boolean throwExceptionOnFailure);
     97 
     98     /**
     99      * Find a value by evaluating the given expression against the stack in the default search order.
    100      *
    101      * @param expr the expression giving the path of properties to navigate to find the property value to return
    102      * @return the result of evaluating the expression
    103      */
    104     public abstract Object findValue(String expr);
    105 
    106     public abstract Object findValue(String expr, boolean throwExceptionOnFailure);
    107 
    108     /**
    109      * Find a value by evaluating the given expression against the stack in the default search order.
    110      *
    111      * @param expr   the expression giving the path of properties to navigate to find the property value to return
    112      * @param asType the type to convert the return value to
    113      * @return the result of evaluating the expression
    114      */
    115     public abstract Object findValue(String expr, Class asType);
    116     public abstract Object findValue(String expr, Class asType,  boolean throwExceptionOnFailure);
    117 
    118     /**
    119      * Get the object on the top of the stack <b>without</b> changing the stack.
    120      *
    121      * @return the object on the top.
    122      * @see CompoundRoot#peek()
    123      */
    124     public abstract Object peek();
    125 
    126     /**
    127      * Get the object on the top of the stack and <b>remove</b> it from the stack.
    128      *
    129      * @return the object on the top of the stack
    130      * @see CompoundRoot#pop()
    131      */
    132     public abstract Object pop();
    133 
    134     /**
    135      * Put this object onto the top of the stack
    136      *
    137      * @param o the object to be pushed onto the stack
    138      * @see CompoundRoot#push(Object)
    139      */
    140     public abstract void push(Object o);
    141 
    142     /**
    143      * Sets an object on the stack with the given key
    144      * so it is retrievable by {@link #findValue(String)}, {@link #findValue(String, Class)}
    145      *
    146      * @param key  the key
    147      * @param o    the object
    148      */
    149     public abstract void set(String key, Object o);
    150 
    151     /**
    152      * Get the number of objects in the stack
    153      *
    154      * @return the number of objects in the stack
    155      */
    156     public abstract int size();
    157 
    158 }

    和一个普通的栈没多大区别。

    他的实现类就比较复杂了(其实也不复杂...)

     public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack { 

    这里贴一部分。

    现在来说说值栈的具体作用:

    当用户发出一个请求,产生一个request,随即产生一个valueStack,然后Action中的setXX()方法,添加到值栈中,然后struts2根据响应的内容跳转到下一个jsp页面中,这个页面可以通过s标签或者el表达式去获取属性值。

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="s" uri="/struts-tags"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <s:iterator value="list" status="li">
            <s:property value="name"/>
            <s:property value="title"/>
            <s:property value="content"/>
            <s:property value="lastDate"/>
            <form action="reply.action">
            <input type="hidden" name="leaveWord_id" value="${id}">
                <input type="submit" value="回复">
            </form>
            </br>
        </s:iterator>
    </body>
    </html>

    最后,详细的说一下s标签或者el表达式是如何拿到属性值的(值栈的工作原理):

      

     1     /**
     2      * Gets the override map if anyone exists.
     3      *
     4      * @return the override map, <tt>null</tt> if not set.
     5      */
     6     public abstract Map<Object, Object> getExprOverrides();
     7 
     8     /**
     9      * Get the CompoundRoot which holds the objects pushed onto the stack
    10      *
    11      * @return the root
    12      */
    13     public abstract CompoundRoot getRoot();

    上面的root是一个真正的栈结构,而Map就是ActionContext.

    当s标签获取属性值时,先从root中找,看有没有,然后再从map中找。

    另外,值栈的生命周期 = Request的生命周期,ActionContext的生命周期 = session的生命周期

    博文为原创,如需转载,请标注原处,谢谢。

  • 相关阅读:
    图片延迟加载
    Python开发【第一篇】:初识Python
    JavsScript+dom
    Django学习系列18:使用迁移创建生产数据库
    Django学习系列17:在模板中渲染待办事项
    Django学习系列16:处理完POST请求后重定向
    Django学习系列15:把POST请求中的数据存入数据库
    Django学习系列14:第一个数据库迁移
    Django学习系列13:Django ORM和第一个模型
    Django学习系列12:把Python变量传入模板中渲染
  • 原文地址:https://www.cnblogs.com/yzjT-mac/p/6285660.html
Copyright © 2011-2022 走看看