Ognl表达式基本原理和使用方法
Ognl表达式基本原理和使用方法
1.Ognl表达式语言
1.1.概述
OGNL表达式
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,他是一个开源项目。Struts框架使用OGNL作为默认的表达式语言。
OGNL优势
- 支持对象方法调用,如:×××.doSomeSpecial();
- 支持类静态的方法调用和值访问,表达式的格式
@[类全名(包括包路径)]@[方法名 | 值名],例如:
@java.lang.String@format('foo %s', 'bar')
或@tutorial.MyConstant@APP_NAME;
- 支持赋值操作和表达式串联,
如price=100, discount=0.8,calculatePrice(),这个表达式会返回80;
- 访问OGNL上下文(OGNL context)和ActionContext;
- 操作(创建)集合对象。
总结:OGNL 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了java.utils.Map 的接口。
Struts框架默认就支持Ognl表达式语言。(从struts项目必须引入ognl.jar包可以看出)
Ognl表达式语言的作用:
- jsp页面取值用
- EL表达式语言,也用于页面取值,是jsp页面取值的标准(默认就可以使用)
- Ognl表达式语言,Struts标签默认支持的表达式语言,必须配置Struts标签用,不能离开Struts标签直接使用,就是说Ognl必须在Struts中使用
- 对比来看,EL使用范围更广,项目中不限制使用哪一种,哪一种熟悉就使用哪一种
1.2.OgnlContext对象(了解)
OgnlContext对象是ognl表达式语言的核心。
但是项目中不会要求写OgnlContext的代码,Ognl标签其实是调用了OgnlContext对象。所以只做了解即可。
OgnlContext对象在源码中实现了Map接口:
public class OgnlContext implements Map {……}
Ognl表达式语言取值,也是用java代码取值的,原理就是使用OgnlContext和Ognl这两个类,只需要记住,Ognl取根元素不用#号,取非根元素要使用#号:
OgnlContext类
硬编码方式,了解OgnlContext对象,因为OgnlContext对象实现是Map接口,所有OgnlContext本质就是一个Map,可以使用map方法:
OgnlContext context = new OgnlContext();
context.put("uesr",user);
context.put("address",address);
context.setRoot(address);
Ognl类
Ognl类也是Ognl底层运行的代码,常用的api如下:
Object obj1 = Ognl.parseExpression(“country”); 解析ognl表达式
Ognl.getValue(obj1, context, context.getRoot()); 获取ognl的表达式值,obj1是上面一个api,其他两个分别是创建的上下文对象以及一个不用修改的参数
Object obj2 = Ognl.parseExpression(“language.toUpperCase()”); 方法调用
Object obj3 = Ognl.parseExpression("@java.lang.Integer@toBinaryString(10)");等同于上面
Object obj4 = Ognl.parseExpression(“@@min(10,4)”); Math类的方法直接调用,静态方法的调用
代码示例如下:
package o_ognl;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.junit.Test;
/**
* OgnlContext用法
* 1.使用Ognl表达式语言取值,如果取非根元素的值,必须用#号
* 2.使用Ognl表达式语言取值,如果取根元素的值,不用#号
* 3.Ognl可以调用静态方法
*/
public class OgnlDemo {
//非根元素
@Test
public void testOgnl1() throws OgnlException {
//创建一个Ognl上下文对象
OgnlContext context = new OgnlContext();
/**
* 1.OgnlContext放入基本变量数据
*/
//放入数据
context.put("cn","China");
//获取数据(map)
String value = (String)context.get("cn");
System.out.println(value);
/**
* 2.OgnlContext放入对象数据
*/
//创建对象,设置对象属性
User user = new User();
user.setId(100);
user.setName("Jack");
//【往非根元素放入数据,取值的时候表达式要用“#”】
context.put("user",user);
//获取对象属性
//使用这种方式也可以获取
Object s = context.get("user");
System.out.println(s);
//使用Ognl表达式来获取
//举例:例如标签<s:a value="#user.id">取值,实际上就是运行了下面的代码获取的
//先构建一个Ognl表达式,再解析表达式
Object ognl = Ognl.parseExpression("#user.id");//构建Ognl表达式
Object value1 = Ognl.getValue(ognl, context, context.getRoot());//解析表达式
System.out.println(value1);
User user1 = new User();
user1.setId(100);
user1.setName("Jack");
context.setRoot(user1);
Object ognl1 = Ognl.parseExpression("id");//构建Ognl表达式
Object value2 = Ognl.getValue(ognl1, context, context.getRoot());//解析表达式
System.out.println(value2);
}
//根元素,
@Test
public void testOgnl2() throws OgnlException {
OgnlContext context = new OgnlContext();
User user1 = new User();
user1.setId(100);
user1.setName("Jack");
context.setRoot(user1);
//根元素直接使用id,不需要加#号
Object ognl1 = Ognl.parseExpression("id");//构建Ognl表达式
Object value2 = Ognl.getValue(ognl1, context, context.getRoot());//解析表达式
System.out.println(value2);
}
//ognl对静态方法调用的支持
@Test
public void testOgnl3() throws Exception{
//创建一个Ognl上下文对象
OgnlContext context = new OgnlContext();
//Ognl表达式语言,调用类的静态方法
// Object ognl = Ognl.parseExpression("@Math@floor(10.9)");
//由于Math类在开发中比较常用,所有也可以这样写
Object ognl = Ognl.parseExpression("@@floor(10.9)");
Object value = Ognl.getValue(ognl, context, context.getRoot());
System.out.println(value);
}
}
1.3.ValueStack对象
1.ValueStack即值栈对象
ValueStack实际是一个接口,在Struts2中利用Ognl时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用Ognl的基础
2.ValueStack特点
ValueStack贯穿整个Action的生命周期(每个Action类的对象实例都拥有一个ValueStack对象),即用户每次访问struts的action,都会创建一个Action对象、值栈对象、ActionContext对象,然后把Action对象放入值栈中;最后再把值栈对象放入request中,传入jsp页面。相当于一个数据的中转站,在其中保存当前Action对象和其他相关对象。Struts2框架把ValueStack对象保存在名为“struts。valueStack”的request请求属性中。
3.ValueStack存储对象
代码调试的时候,发现有一个root是compundRoot类,继承ArrayList,保存的是action对象;还有一个OgnlContext是继承Map,保存数据。
所以ValueStack存储对象时是分两个地方来存的,也即ValueStack对象的组成是由List栈和Map栈构成的:
ObjectStack:Struts把根元素,即action对象及全局属性存入ObjectStack中---List
list栈主要存储:action对象,Map对象(通过vs.set()设置),通过push方法设置的对象,以及其他代理对象
根元素的存储示例:
//存储值栈对象
ActionContext ac = ActionContext.getContext();
ValueStack vs = ac.getValueStack();
vs.set("user1",new User(100,"Jack1"));//Map
vs.push(new User(100,"Jack2"));//栈顶
ContextMap:Struts把各种各样的映射关系(域数据)存入ContextMap中
Struts会把下面这些映射存入ContextMap中:
- parameter:该Map中包含当前请求的请求参数
- request:该Map中包含当前request对象中的所有属性
- Session:该Map中包含当前Session对象中的所有属性
- application:该Map中包含当前application对象中的所有属性
- attr:该Map按如下顺序来检索某个属性:request,Session,application
非根元素Map中存放数据的方法示例:
//存储值栈对象
ActionContext ac = ActionContext.getContext();
//映射数据
ac.getContextMap().put("request_data", "request_data");
ac.getSession().put("session_data", "session_data");
ac.getApplication().put("application_data","application_data");
从栈中取值的两种方式:
//一、获取值栈对象的两种方式,是等价的
public void getVs() {
//获取值栈对象,方式1:
HttpServletRequest request = ServletActionContext.getRequest();
ValueStack vs1 = (ValueStack) request.getAttribute("struts.valueStack");
/**************************************************/
//获取值栈对象,方式2:
ActionContext ac = ActionContext.getContext();
ValueStack vs2 = ac.getValueStack();
System.out.println(vs1==vs2);//true
}
在jsp页面中,对不同ValueStack中的不同类型取值方法不同,
如果是根元素取值,直接写表达式;
非根元素(request,Session,application,att,parmeters)必须用#号,例#request.cn
1.4.JSP页面中获取ValueStack数据
<%@taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp页面取值</title>
</head>
<body>
index页面
<%--页面,必须要拿到ValueStack--%>
<%--struts的调试标签,可以观测值栈数据--%>
<s:debug/>
<br/>1.取根元素的值<br/>
<s:property value="user.id"/>
<s:property value="user.name"/>
<br/>2.取非根元素<br/>
<s:property value="#request.cn"/>
<s:property value="#request.request_data"/>
<s:property value="#session.session_data"/>
<s:property value="#application.application_data"/><br/>
<%--attr按顺序自动找request/session/application,找到后立刻返回--%>
<s:property value="#attr.application_data"/>
<%--获取请求参数数据--%>
<s:property value="#parameters.userName"/>
</body>
</html>
2.Struts标签
struts标签取值,就使用到ognl表达式语言。
2.1.Ognl使用方式
1.4.中使用的就是Ognl表达式取值。使用方式是:
1.引入<%@taglib prefix="s" uri="/struts-tags" %>
2.使用 <s:property value="user.name"/>标签获取取值,取值的时候要注意根元素(全局变量)不用#号,其他的都用#号
还有一些标签需要学习:
2.2.迭代标签
Iterator:标签用于对集合进行迭代,这里的集合包含List,Set和数组
- value:可选属性,指定被迭代的集合,如果没有设置该属性,则使用ValueStack栈顶的集合。
- var:可选属性,引用变量的名称
- status:可选属性,该属性指定迭代是的IteratorStatus实例,该实例包含一下一个方法;
int getCount(),返回当前迭代了几个元素
int getIndex(),返回当前迭代元素的索引
boolean isEven(),返回当前迭代元素的索引是否是偶数
boolean isOdd(),返回当前迭代元素的索引是否是奇数
boolean isFirst(),返回当前迭代元素是否是第一个元素
boolean isLast(),返回当前迭代元素是否是最后一个元素
代码示例:
<br/>1.list迭代<br/>
<s:iterator var="user" value="#request.list" status="st">
<s:property value="#user.id"/>
<s:property value="#user.name"/>
<s:property value="#st.even"/><br/>
</s:iterator>
<br/>2.map迭代<br/>
<s:iterator var="en" value="#request.map" status="st">
<s:property value="#en.key"/>
<s:property value="#en.value.name"/>
</s:iterator>
2.3.Ognl动态建立集合
<%--Ognl表达式可以取值,也可以构建动态集合--%>
<br/>1.构建list集合<br/>
<s:iterator var="str" value="{'a','b','c'}">
<s:property value="#str"/>
</s:iterator>
<br/>2.构建map集合<br/>
<s:iterator var="en" value="#{'cn':'China','usa':'America'}">
<s:property value="en.key"/>
<s:property value="en.value"/><br/>
</s:iterator>
2.4.简单UI标签
<%@taglib prefix="s" uri="/struts-tags" %>
<%--服务器标签:最终被解析为html标签--%>
<s:form action="/user_login" method="POST" name="frmLogin">
<s:textfield name="user.userName" label="用户名"/>
<s:textfield name="user.pwd" label="密码"/>
<s:submit value="登录"/>
</s:form>
也可以给form指定主题,方法如下:
<!-- 服务器标签 : 最终别解析为html标签-->
<s:form action="/user_login" method="post" name="frmLogin" id="frmLogin" theme="simple">
用户名:<s:textfield name="user.name"></s:textfield>
密码:<s:textfield name="user.pwd"></s:textfield>
<s:submit value="登陆"></s:submit>
</s:form>
注意:
给form指定主题,form下所有的表单元素都应用此主题
对Struts标签默认的主题样式:default.xml/struts.ui.theme=xhtml
可以通过常量修改,改为简单主题:
<!-- 修改主题 (当前项目所有的标签都用此主题)-->
<constant
name="struts.ui.theme" value="simple"></constant>
2.5.Ognl表达式语言几个符号
:获取非根元素,动态创建map集合
$:配置文件取值
%:提供一个ognl表达式运行环境
<body>
<br/>获取request域数据<br/>
<!-- property 标签是对象类型的标签,默认支持ognl表达式, 会从根元素去China名称对应的值 -->
<s:property value="China"/> <br/>
<!-- 如果直接赋值,需要用单引号 -->
<s:property value="'China'"/> <br/>
<s:property value="%{#request.cn}"/> <br/>
<!-- 值类型的标签,value值默认就是值类型,不支持ognl表达式 -->
国家:<s:textfield name="txtCountry" value="%{#request.cn}"></s:textfield>
</body>
Ognl表达式基本原理和使用方法的更多相关文章
- Struts2的OGNL表达式语言
一.OGNL的概念 OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者 ...
- struts2学习笔记--OGNL表达式1
struts2标签库主要使用的是OGNL语言,类似于El表达式,但是强大得多,它是一种操作对象属性的表达式语言,OGNL有自己的优点: 能够访问对象的方法,如list.size(); 能够访问静态属性 ...
- struts2 OGNL表达式
一.OGNL OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者调用对 ...
- OGNL表达式
一.什么是OGNL,有什么特点? OGNL(Object-Graph Navigation Language),大概可以理解为:对象图形化导航语言.是一种可以方便地操作对象属性的开源表达式语言 ...
- OGNL表达式struts2标签“%,#,$”
一.什么是OGNL,有什么特点? OGNL(Object-Graph Navigation Language),大概可以理解为:对象图形化导航语言.是一种可以方便地操作对象属性的开源表达式语言.OGN ...
- JSTL标签,EL表达式,OGNL表达式,struts2标签 汇总
一下纯属个人总结摘抄,总结一起方便查看,解决疑问,有遗漏或错误,还请指出. 1,JSTL标签总结: a).JSTL标签有什么用? JSTL是由JCP(Java Commu ...
- Struts2的标签库(二)——OGNL表达式
Struts2的标签库(二) --OGNL表达式 1.Struts2中的OGNL表达式增加了ValueStack的支持. 注:ValueStack--实际上是一个容器对象,该对象在启动Struts2框 ...
- struts2视频学习笔记 28(OGNL表达式)
课时28 OGNL表达式 OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目. Struts 2框架使用OGNL作为默认的表达式语 ...
- 十七、OGNL表达式
十七.OGNL OGNL简介: OGNL是对象导航图语言.它是一个独立的项目.早期的webwork框架用到了OGNL作为自己的表达式语言, 所以struts2也是用OGNL作为表达式语言,当然也可以使 ...
随机推荐
- win7安装时,避免产生100m系统保留分区的办法
在通过光盘或者U盘安装Win7操作系统时,在对新硬盘进行分区时,会自动产生100m的系统保留分区.对于有洁癖的人来说,这个不可见又删不掉的分区是个苦恼.下面介绍通过diskpart消灭保留分区的办法: ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(74)-微信公众平台开发-自定义菜单
系列目录 引言 1.如果不借用Senparc.Weixin SDK自定义菜单,编码起来,工作量是非常之大 2.但是借助SDK似乎一切都是简单得不要不要的 3.自定义菜单无需要建立数据库表 4.自定义菜 ...
- Angular企业级开发-AngularJS1.x学习路径
博客目录 有链接的表明已经完成了,其他的正在建设中. 1.AngularJS简介 2.搭建Angular开发环境 3.Angular MVC实现 4.[Angular项目目录结构] 5.[SPA介绍] ...
- 15个关于Chrome的开发必备小技巧[译]
谷歌Chrome,是当前最流行且被众多web开发人员使用的浏览器.最快六周就更新发布一次以及伴随着它不断强大的开发组件,使得Chrome成为你必备的开发工具.例如,在线编辑CSS,console以及d ...
- UWP开发之Mvvmlight实践九:基于MVVM的项目架构分享
在前几章介绍了不少MVVM以及Mvvmlight实例,那实际企业开发中将以那种架构开发比较好?怎样分层开发才能节省成本? 本文特别分享实际企业项目开发中使用过的项目架构,欢迎参照使用!有不好的地方欢迎 ...
- DBA成长路线
从开发转为数据库管理,即人们称为DBA的已经有好几年,有了与当初不一样的体会.数据是企业的血液,数据是石油,数据是一切大数据.云计算的基础.作为DBA是数据的保卫者.管理者,是企业非常重要的角色.对于 ...
- 设计模式之创建类模式大PK
创建类模式大PK 创建类模式包括工厂方法模式.建造者模式.抽象工厂模式.单例模式和原型模式,他们能够提供对象的创建和管理职责.其 ...
- http status code
属于转载 http status code:200:成功,服务器已成功处理了请求,通常这表示服务器提供了请求的网页 404:未找到,服务器未找到 201-206都表示服务器成功处理了请求的状态代码,说 ...
- Web开发安全之文件上传安全
很长一段时间像我这种菜鸡搞一个网站第一时间反应就是找上传,找上传.借此机会把文件上传的安全问题总结一下. 首先看一下DVWA给出的Impossible级别的完整代码: <?php if( iss ...
- GitHub管理代码-随笔
公司一直用的SVN进行项目管理,平时便自己折腾了下Git,这里做下GitHub的最简单的记录... 在git上创建仓库等就免谈了,网上也有好多教程,直接从创建之后记录: 在github的readme文 ...