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);
取值:
<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的更多相关文章
- Nginx学习笔记(五) 源码分析&内存模块&内存对齐
Nginx源码分析&内存模块 今天总结了下C语言的内存分配问题,那么就看看Nginx的内存分配相关模型的具体实现.还有内存对齐的内容~~不懂的可以看看~~ src/os/unix/Ngx_al ...
- Nginx学习笔记(四) 源码分析&socket/UDP/shmem
源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_socket.h&Ngx_s ...
- Nginx学习笔记(六) 源码分析&启动过程
Nginx的启动过程 主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程. 涉及到的基本函数 源码: /* * ...
- 五毛的cocos2d-x学习笔记02-基本项目源码分析
class AppDelegate : private cocos2d::Application private表示私有继承,cocs2d是一个命名空间.私有继承下,Application类中的pri ...
- Bootstrap学习笔记上(带源码)
阅读目录 排版 表单 网格系统 菜单.按钮 做好笔记方便日后查阅o(╯□╰)o bootstrap简介: ☑ 简单灵活可用于架构流行的用户界面和交互接口的html.css.javascript工具集 ...
- Redis学习之zskiplist跳跃表源码分析
跳跃表的定义 跳跃表是一种有序数据结构,它通过在每个结点中维持多个指向其他结点的指针,从而达到快速访问其他结点的目的 跳跃表的结构 关于跳跃表的学习请参考:https://www.jianshu.co ...
- Java显式锁学习总结之六:Condition源码分析
概述 先来回顾一下java中的等待/通知机制 我们有时会遇到这样的场景:线程A执行到某个点的时候,因为某个条件condition不满足,需要线程A暂停:等到线程B修改了条件condition,使con ...
- Python学习---Django的request.post源码分析
request.post源码分析: 可以看到传递json后会帮我们dumps处理一次最后一字节形式传递过去
- Java显式锁学习总结之五:ReentrantReadWriteLock源码分析
概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和 ...
- 大数据学习笔记——HDFS写入过程源码分析(2)
HDFS写入过程注释解读 & 源码分析 此篇博客承接上一篇未讲完的内容,将会着重分析一下在Namenode获取到元数据后,具体是如何向datanode节点写入真实的数据的 1. 框架图展示 在 ...
随机推荐
- Python之路【第二十二篇】:Django之Model操作
Django之Model操作 一.字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bi ...
- C#的类型、变量和值
大学学了C#,工作也是使用C#,虽然在日常的开发中没什么大的问题,但个人觉得在C#的理解还不是很清晰,所以决定花一定的时间来理一理学过的知识,顺便革新下脑袋里的知识,因为坑爹的学校在教.net的时候, ...
- 了解JavaScript的执行上下文
转自http://www.cnblogs.com/yanhaijing/p/3685310.html 什么是执行上下文? 当JavaScript代码运行,执行环境非常重要,有下面几种不同的情况: 全局 ...
- imageWithContentsOfFile读取全路径返回的image为空的解决方法
下载图片缓存到本地沙盒里,发现用 imageWithContentsOfFile去读取的时候,40%左右的几率会读取为空. 查找资料和文档后找到解决方法 路径:当这次的时候是/var/mobile/C ...
- webui layout like desktop rich client
similarity similarlike desktop js frameworklike extj js frameworklike rich client js frameworkjs lay ...
- Sublime Text3 个人使用心得
sublime与webstorm的比较: webstorm真心很强大,强大到能够几乎满足所有前端开发者编程的需求,方便的快捷键操作.代码提示.浏览器查看.工程管理.历史记录(可以找到之前编辑的内容,即 ...
- php文件锁解决少量并发问题
阻塞(等待)模式: <?php $fp = fopen("lock.txt", "r"); if(flock($fp,LOCK_EX)) { //..处理 ...
- php随机生成福彩双色球号码
发布:thebaby 来源:net [大 中 小] 不瞒您说,俺也是个双色球爱好者,经常买,但迟迟没有中过一等奖,哈哈.这里为大家介绍用php随机生成福彩双色球号码的二种方法,供朋友们学习 ...
- MyEclipse创建WebService
使用Eclipse的话还要装web tool platform很多东西,用MyEclipse一步到位,创建WebService很方便. MyEclipse中有自己的Tomcat,要把事先在电脑上独立安 ...
- 分享一下 Eclipse 插件 PyDev 的安装
想趁暑假学习一下python,学好语言好的开发环境是基础.因为安装有eclipse,所以想安装PyDev插件作为python开发环境.本来以为是一件简单的事情,结果整整弄了一下午各种装不上,度娘上的几 ...