
ssh框架之struts的ognl表达式语言、onglcontext对象:一、概述:ognl表达式,ognl是(对象图导航语言)的缩写struts2ognl表达式和运算符,它是一个开源项目。ognl是object-graph navigation language(对象图导航语言)的缩写,它是一种功能强大的表达式语言,通过简单一致的表达式语法,可以存取对象的任何属性,调用对象的方法,遍历整个对象的,实现字段类型转化等功能、它使用相同的表达式去存取对象的属性。ognl是object-graph navigation language对象图导航语言的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的,实现字段类型转化等功能。
Struts2框架使用OGNL作为默认的表达式语言,主要用于页面的取值。它类似于EL表达式语言,但比EL语法强大很多。
EL Expression Language 表达式语言, 主要用来获取 JSP页面四个域范围数据 (page、 request、 session、 application )
1. 导入的jar包:
ognl-xxx.jar : ognl的核心环境
javassist-xxx.jar : ognl的依赖,提供字节码修改能力。
2. 使用ognl表达式的jsp页面需要导入struts2的标签库
<%@ taglib prefix="s" uri="/struts-tags"%>
3. 几种基本的使用方式:
1. Java对象的直接访问 :
<s:property value="'name'"/><br/>
2. 实例方法调用
<s:property value="'name'.length()"/><br/>
3. 赋值操作或表达式串联
<s:property value="1+1" /><br/>
4. 静态方法调用(类的静态方法或静态变量的访问) 不推荐
语法:@[类全名(包括包路径)]@[方法名|值名]
例如:<s:property value="@java.lang.Math@max(10,20)"/><br/>
但是!!!在使用静态方法之前必须在struts.xml中开启静态方法调用功能
<!-- 开启ognl表达式静态方法调用 -->
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
5. OGNL上下文(OGNL Context)和ActionContext的访问。(值栈相关访问-重要)
6. 集合对象的操作
值栈(ValueStack),是Struts2的数据中转站,其中自动保存了当前Action对象和其他相关对象(包括常用的Web对象的引用,如request等),也可以手动保存自己的数据对象struts2ognl表达式和运算符,同时也可以随时随地将对象从值栈取出或操作(通过OGNL表达式)
了解:值栈的生命周期,和request一样或action,生命周期都一样
在Action动作类中获取值栈对象有两种方式:
@Override
public String execute() throws Exception {
//目标 :获取值栈对象
//方式一 : 通过request对象直接获取
ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
//方式二 : 通过struts2提供的api来获取(底层还是1方式)
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
//测试是否是同一个对象
System.out.println(valueStack == valueStack2);
return NONE;
}
在值栈的内部有两个逻辑部分:
值栈ValueStack(OgnlValueStack实现类)中有两块区域 :
一块是CompoundRoot对象栈(也称为Root栈),它实质上是使用List集合来存放对象,存入对象压栈从栈顶往下压。
一块是OgnlContext上下文栈(也称为Map栈)。
Map栈中有两个区域,_root用于存放对象栈(Root栈)的引用
_values实质上使用Map集合键值对的形式存放对象

img12.png
值栈是在请求对象引用了一块存储空间。

值栈包括两部分: 对象栈(CompoundRoot,继承List接口)和OGNL上下文栈(OgnlContext,实现Map接口)
10. 一个文件映射对象的映射视图维持着对象的内部引用,直到所有的引用被释放,文件映射对象才能够被关闭。11.注意,虽然createfilemapping会增加文件对象计数,mapviewoffile会增加映射对象的计数(也就是说,在unmapviweoffile之前这两个内核对象就可以被closehandle了),但是如果太早关闭映射对象,其他地方要打开映射对象时会失败(即openfilemapping失败或者createfilemapping的lasterror不是error_already_exists),也就是说,内核通过视图对映射对象的引用,不能被用户模式代码检测到,因此最好还是按传统顺序先unmapviewoffile再closehandle。struts2将ognl上下文设置为struts2中的actioncontext(内部使用的仍然是ognlcontext),并将值栈设为ognl的根对象。
栈的概念:
栈是一种数据结构,它按照先进后出的原则存储数据,即先进入的数据被压入栈底,
最后进入的数据在栈顶,需要读取数据的时候,从栈顶开始弹出数据(即最后一个数据被第一个读出来)。
栈也被成为先进后出表,可进行插入和删除操作,插入称之为进栈(压栈)(push),
删除称之为退栈(pop),允许操作的两端分别称为栈顶(top)和栈底(bottom)。栈底固定,而栈顶浮动。
对于栈就只能每次访问它的栈顶元素,从而可以达到保护栈顶元素以下的其他元素的目的。
@Override
public String execute() throws Exception {
// 目标 :向root栈和map栈中分别存入数据
String msg = "我爱java";
// 获取值栈对象
ValueStack valueStack = ActionContext.getContext().getValueStack();
//向root栈中存值(压栈),匿名,
valueStack.push(msg);
//root栈中存值(压栈),有名字
valueStack.set("msg2", "我爱C++");
//向Root栈中存值(键值对)
ActionContext.getContext().put("msg3", "我爱Python");
return SUCCESS;
}
struts.xml 配置跳转页面 :
<action name="valueStack2" class="com.itdream.a_valueStack.ValueStack2Action">
<result>/a_ognl/result.jsp</result>
</action>
result.jsp :
<%@ taglib prefix="s" uri="/struts-tags"%>
<!-- 取出存在值栈中的值 -->
<!-- push方法,匿名压入Root栈的数据,第一个被压入 -->
<s:property value="[1].top"/><br/>
<!-- set方法,Struts2帮我们创建一个map集合存储数据压入Root栈的数据,map的key就是数据的名字,通过key取值 -->
<s:property value="msg2"/><br/>
<!-- put方法,放入Map栈中,通过加#号定向到Map栈中找 -->
<!-- 也可以不加#号使用默认查找机制,但这样先从Root栈先找,再到Map栈找key,如果在Root栈找到就找不到Map栈的数据了 -->
<s:property value="#msg3"/>|<s:property value="msg3"/><br/>
<!-- 用来查看值栈的内容 -->
<s:debug/>

img14.png
点击Debug查看值栈的内容:
页面中直接查看值栈的元素的方法。
struts2为我们提供了一个标签:<s :debug/>,只要将其加在页面中即可。
Root栈:
数据从栈顶往下压,push方法直接压入String对象,此时它是栈顶,索引为0
然后使用set方法,创建了一个HashMap存储数据的值,作为对象存入Root栈,此时栈顶是这个HashMap对象,String对象的索引变为1

img15.png

Map栈:
put方法,以键值对形式存储数据

img16.png
1. 每次请求都会创建一个ActionContext对象和一个OnglValueStack值栈对象,这时在Root栈中放入了一个textProvider.
2. 紧接着,Struts2将与Servket有关的Response,Request,Session等对象放入到Map栈中,此时Map栈中有Servlet的对象引用.
3. 之后就准备执行Action动作类 ,创建Action动作的代理对象。Action是在执行的时候才进行初始化,初始化完成后,
将Action对象压入Root栈栈顶,并在Map栈的_root中放入一个引用:key - action
到这里,Root栈中有一个textProvider与一个Action对象,Map栈中有Servlet相关的数据以及Action对象的引用,
两个Action是同一个
4. 初始化完成,ActionProxy代理对象在执行时,会先执行,再执行Action,
这个时候,如果有Action实现了ModelDriven接口,模型驱动就将模型对象压入栈顶。
了解原理的目的:
知道值栈的初始化时机,访问action的时候,才创建(这个过程中会创建actionProxy对象,并且同时创建值栈,并且,将一些对象放入值栈。)
值栈初始化之后,里面主要默认有:root栈(textProvider、action类对象、model(user)),map栈(servlet相关对象、action对象一个引用)
哪些对象在栈顶!因为后面我们从值栈取值,都从栈顶往下取。所以,一定要知道哪个对象在栈上面。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-115359-1.html
而且这次派出的052D也是旧军舰了
况且国内形式也需要一场外部战争来提高国民的凝聚力