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的生命周期

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

 

posted @ 2017-01-14 16:42  麦子TMAC  阅读(691)  评论(0编辑  收藏  举报