一、分析

二、

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);

取值:

 <table cellpadding="0" cellspacing="0" class="mainForm">
<tr>
<td width="100">岗位名称</td>
<td><s:textfield name="name" cssClass="InputStyle" /> *</td>
</tr>
<tr>
<td>岗位说明</td>
<td><s:textarea name="description" cssClass="TextareaStyle"></s:textarea></td>
</tr>
</table>

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

2.El表达式

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

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

 /*
* $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;
}
}

例如:

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

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

3.ModelDriven

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

源码如下:

  @Override
public String intercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction(); if (action instanceof ModelDriven) {
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
Object model = modelDriven.getModel();
if (model != null) {
stack.push(model);
}
if (refreshModelBeforeResult) {
invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
}
}
return invocation.invoke();
}

用法如:

         <s:form action="role_add">
<s:textfield name="name"></s:textfield>
<s:textarea name="description"></s:textarea>
<s:submit value="提交"></s:submit>
</s:form>

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

  @Override
public String intercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction(); if (action instanceof ModelDriven) {
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
Object model = modelDriven.getModel();
if (model != null) {
stack.push(model);
}
if (refreshModelBeforeResult) {
invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
}
}
return invocation.invoke();
}

OA学习笔记-010-Struts部分源码分析、Intercepter、ModelDriver、OGNL、EL的更多相关文章

  1. Nginx学习笔记(五) 源码分析&内存模块&内存对齐

    Nginx源码分析&内存模块 今天总结了下C语言的内存分配问题,那么就看看Nginx的内存分配相关模型的具体实现.还有内存对齐的内容~~不懂的可以看看~~ src/os/unix/Ngx_al ...

  2. Nginx学习笔记(四) 源码分析&socket/UDP/shmem

    源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_socket.h&Ngx_s ...

  3. Nginx学习笔记(六) 源码分析&启动过程

    Nginx的启动过程 主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程. 涉及到的基本函数 源码: /* * ...

  4. 五毛的cocos2d-x学习笔记02-基本项目源码分析

    class AppDelegate : private cocos2d::Application private表示私有继承,cocs2d是一个命名空间.私有继承下,Application类中的pri ...

  5. Bootstrap学习笔记上(带源码)

    阅读目录 排版 表单 网格系统 菜单.按钮 做好笔记方便日后查阅o(╯□╰)o bootstrap简介: ☑  简单灵活可用于架构流行的用户界面和交互接口的html.css.javascript工具集 ...

  6. Redis学习之zskiplist跳跃表源码分析

    跳跃表的定义 跳跃表是一种有序数据结构,它通过在每个结点中维持多个指向其他结点的指针,从而达到快速访问其他结点的目的 跳跃表的结构 关于跳跃表的学习请参考:https://www.jianshu.co ...

  7. Java显式锁学习总结之六:Condition源码分析

    概述 先来回顾一下java中的等待/通知机制 我们有时会遇到这样的场景:线程A执行到某个点的时候,因为某个条件condition不满足,需要线程A暂停:等到线程B修改了条件condition,使con ...

  8. Python学习---Django的request.post源码分析

    request.post源码分析: 可以看到传递json后会帮我们dumps处理一次最后一字节形式传递过去

  9. Java显式锁学习总结之五:ReentrantReadWriteLock源码分析

    概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和 ...

  10. 大数据学习笔记——HDFS写入过程源码分析(2)

    HDFS写入过程注释解读 & 源码分析 此篇博客承接上一篇未讲完的内容,将会着重分析一下在Namenode获取到元数据后,具体是如何向datanode节点写入真实的数据的 1. 框架图展示 在 ...

随机推荐

  1. ecshop在PHP 5.4以上版本各种错误问题处理

    在php5.4版本之后有很多的函数与功能进行丢弃与升级功能了,现在国内很多CMS都还未按php5.4标准来做了,下面我整理了一些在ecshop在PHP 5.4以上版本各种错误问题处理. 1.PHP 5 ...

  2. YII缓存Cache

    缓存Cache 定义:将数据暂时存放在一个存储速度更快的介质上,下次读取数据时就可以从这个介质上来读取数据 介质:内存.文件.数据库(优化好的数据库) Yii缓存的分类:(framework/cach ...

  3. 20151217jquery学习笔记--注册表单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. WCF学习系列一_创建第一个WCF服务

    原创作者:灰灰虫的家http://hi.baidu.com/grayworm WCF开发实战系列一:创建第一个WCF服务 在这个实战中我们将使用DataContract,ServiceContract ...

  5. Objective-c单例模式详解

    转载自:http://www.jianshu.com/p/85618bcd4fee 单例模式出现以后,关于它的争执就一直存在.在开发项目中,有很多时候我们需要一个全局的对象,而且要保证全局有且仅有一份 ...

  6. VBA 打印设置相关属性及方法

    打印设置说明,以下均为默认值. With ActiveSheet.PageSetup .PrintTitleRows = "" '工作表打印标题:顶端标题行(R) .PrintTi ...

  7. Codevs 1958 刺激

    1958 刺激 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description saffah的一个朋友S酷爱滑雪,并且追求刺激(exitement, ...

  8. (hdu)5391 Zball in Tina Town

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5391 Problem Description Tina Town is a friendl ...

  9. Sdut 2165 Crack Mathmen(数论)(山东省ACM第二届省赛E 题)

    Crack Mathmen TimeLimit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Since mathmen take security ...

  10. MySQL存储引擎,优化,事务

    1唯一约束unique和主键key的区别?     1.什么是数据的存储引擎?       存储引擎就是如何存储数据.如何为存储的数据建立索引和如何更新.查询数据等技术的实现方法.因为在关系数据库中数 ...