OA学习笔记-010-Struts部分源码分析、Intercepter、ModelDriver、OGNL、EL

一、分析

 

二、

1.OGNL

在访问action前,要经过各种intercepter,其中ParameterFilterInterceptor会把各咱参数放到ValueStack里,从而使OGNL可以访问这些参数,而ValueStack里包含对象stack和map

(1)map

赋值:ActionContext.getContext().put("roleList", roleList);

取值:在jsp中通过ognl取<s:iterator value="#roleList">或<s:iterator value="%{#roleList}">

注:因为struts标签默认使用ognl表达式,所以可以省略“%{}”,而“#”是表示从map中取值,不会去对象栈中去取

(2)对象stack

压栈:ActionContext.getContext().getValueStack().push(role);

取值:

 1 <table cellpadding="0" cellspacing="0" class="mainForm">
 2                     <tr>
 3                         <td width="100">岗位名称</td>
 4                         <td><s:textfield name="name" cssClass="InputStyle" /> *</td>
 5                     </tr>
 6                     <tr>
 7                         <td>岗位说明</td>
 8                         <td><s:textarea name="description" cssClass="TextareaStyle"></s:textarea></td>
 9                     </tr>
10                 </table>

struts标签会自动去对象statck中找%{name}、%{description}

2.El表达式

若使用了struts框架,则request会被装饰类StrutsRequestWrapper代换,StrutsRequestWrapper包装了ServletRequest,也提供了访问valuestack的方法,所以使El表达式可以访问request中的值及访问valuestack,

在jsp中写${name},此时的取值顺序是(1)先以request中取,若取不到就到valuestack取,源码如下:

  1 /*
  2  * $Id$
  3  *
  4  * Licensed to the Apache Software Foundation (ASF) under one
  5  * or more contributor license agreements.  See the NOTICE file
  6  * distributed with this work for additional information
  7  * regarding copyright ownership.  The ASF licenses this file
  8  * to you under the Apache License, Version 2.0 (the
  9  * "License"); you may not use this file except in compliance
 10  * with the License.  You may obtain a copy of the License at
 11  *
 12  *  http://www.apache.org/licenses/LICENSE-2.0
 13  *
 14  * Unless required by applicable law or agreed to in writing,
 15  * software distributed under the License is distributed on an
 16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  * KIND, either express or implied.  See the License for the
 18  * specific language governing permissions and limitations
 19  * under the License.
 20  */
 21 
 22 package org.apache.struts2.dispatcher;
 23 
 24 import com.opensymphony.xwork2.ActionContext;
 25 import com.opensymphony.xwork2.util.ValueStack;
 26 
 27 import javax.servlet.http.HttpServletRequest;
 28 import javax.servlet.http.HttpServletRequestWrapper;
 29 
 30 import static org.apache.commons.lang3.BooleanUtils.isTrue;
 31 
 32 /**
 33  * <!-- START SNIPPET: javadoc -->
 34  *
 35  * All Struts requests are wrapped with this class, which provides simple JSTL accessibility. This is because JSTL
 36  * works with request attributes, so this class delegates to the value stack except for a few cases where required to
 37  * prevent infinite loops. Namely, we don't let any attribute name with "#" in it delegate out to the value stack, as it
 38  * could potentially cause an infinite loop. For example, an infinite loop would take place if you called:
 39  * request.getAttribute("#attr.foo").
 40  *
 41  * <!-- END SNIPPET: javadoc -->
 42  *
 43  */
 44 public class StrutsRequestWrapper extends HttpServletRequestWrapper {
 45 
 46     private static final String REQUEST_WRAPPER_GET_ATTRIBUTE = "__requestWrapper.getAttribute";
 47     private final boolean disableRequestAttributeValueStackLookup;
 48 
 49     /**
 50      * The constructor
 51      * @param req The request
 52      */
 53     public StrutsRequestWrapper(HttpServletRequest req) {
 54         this(req, false);
 55     }
 56 
 57     /**
 58      * The constructor
 59      * @param req The request
 60      * @param disableRequestAttributeValueStackLookup flag for disabling request attribute value stack lookup (JSTL accessibility)
 61      */
 62     public StrutsRequestWrapper(HttpServletRequest req, boolean disableRequestAttributeValueStackLookup) {
 63         super(req);
 64         this.disableRequestAttributeValueStackLookup = disableRequestAttributeValueStackLookup;
 65     }
 66 
 67     /**
 68      * Gets the object, looking in the value stack if not found
 69      *
 70      * @param key The attribute key
 71      */
 72     public Object getAttribute(String key) {
 73         if (key == null) {
 74             throw new NullPointerException("You must specify a key value");
 75         }
 76 
 77         if (disableRequestAttributeValueStackLookup || key.startsWith("javax.servlet")) {
 78             // don't bother with the standard javax.servlet attributes, we can short-circuit this
 79             // see WW-953 and the forums post linked in that issue for more info
 80             return super.getAttribute(key);
 81         }
 82 
 83         ActionContext ctx = ActionContext.getContext();
 84         Object attribute = super.getAttribute(key);
 85 
 86         if (ctx != null && attribute == null) {
 87             boolean alreadyIn = isTrue((Boolean) ctx.get(REQUEST_WRAPPER_GET_ATTRIBUTE));
 88 
 89             // note: we don't let # come through or else a request for
 90             // #attr.foo or #request.foo could cause an endless loop
 91             if (!alreadyIn && !key.contains("#")) {
 92                 try {
 93                     // If not found, then try the ValueStack
 94                     ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.TRUE);
 95                     ValueStack stack = ctx.getValueStack();
 96                     if (stack != null) {
 97                         attribute = stack.findValue(key);
 98                     }
 99                 } finally {
100                     ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.FALSE);
101                 }
102             }
103         }
104         return attribute;
105     }
106 }

例如:

1         <s:iterator value="#roleList">
2             ${id},
3             ${name},
4             ${description}, 
5             <s:a action="role_delete?id=%{id}" onclick="return confirm('确定要删除吗?')">删除</s:a>,
6             <s:a action="role_editUI?id=%{id}">修改</s:a>
7             <br/>
8         </s:iterator>

分析:s:iterator每次循环都会把当前对象压栈,循环结束就弹栈,${id}的访问顺序时先到对象栈里找,再到map里找,所以肯定可以找到

 

3.ModelDriven

ModelDriven的原理是,访问action前,ModelDrivenInterceptor会把model压到对象栈里,从而页面提交的比如id,name等字段会优先封闭到model里

源码如下:

 1  @Override
 2     public String intercept(ActionInvocation invocation) throws Exception {
 3         Object action = invocation.getAction();
 4 
 5         if (action instanceof ModelDriven) {
 6             ModelDriven modelDriven = (ModelDriven) action;
 7             ValueStack stack = invocation.getStack();
 8             Object model = modelDriven.getModel();
 9             if (model !=  null) {
10                 stack.push(model);
11             }
12             if (refreshModelBeforeResult) {
13                 invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
14             }
15         }
16         return invocation.invoke();
17     }

 

用法如:

1         <s:form action="role_add">
2             <s:textfield name="name"></s:textfield>
3             <s:textarea name="description"></s:textarea>
4             <s:submit value="提交"></s:submit>
5         </s:form>

一提交,字段会自动封装到role里去,因为RoleAction实现了ModelDriven

 1  @Override
 2     public String intercept(ActionInvocation invocation) throws Exception {
 3         Object action = invocation.getAction();
 4 
 5         if (action instanceof ModelDriven) {
 6             ModelDriven modelDriven = (ModelDriven) action;
 7             ValueStack stack = invocation.getStack();
 8             Object model = modelDriven.getModel();
 9             if (model !=  null) {
10                 stack.push(model);
11             }
12             if (refreshModelBeforeResult) {
13                 invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
14             }
15         }
16         return invocation.invoke();
17     }

 

posted @ 2016-02-29 13:49  shamgod  阅读(354)  评论(0编辑  收藏  举报
haha