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 {//非根元素@Testpublic 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);}//根元素,@Testpublic 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对静态方法调用的支持@Testpublic 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"));//Mapvs.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>

原文地址:https://www.cnblogs.com/cenyu/p/6233942.html

Ognl表达式基本原理和使用方法相关推荐

  1. Struts2中使用OGNL表达式语言访问静态方法和静态属性以及我遇到的问题和解决方法

    1.上一篇文章,我介绍了OGNL表达式语言,本来想在那篇文章上加上一个使用OGNL访问静态方法和静态属性的例子,但是昨天晚上我写代码时,报了一个警告,获取得到静态属性的值,却获取不到静态方法的返回值, ...

  2. OGNL表达式的使用方法

    OGNL表达式的使用方法 定义: OGNL是对象图导航语言(即该表达式访问的是对象及对象的属性) 知识点: 1.基本属性的访问 1.1 访问值栈中action的普通属性 [xhtml:nogutter ...

  3. OGNL表达式的使用

    1.OGNL技术的使用 1).什么是OGNL 源于ognl.jar工具包     Object Graphics Navigation Language(对象图导航语言)    主要用于访问对象的数据 ...

  4. 深入理解Struts2中的OGNL表达式

    Struts 2中的表达式语言 Struts 2支持以下几种表达式语言: OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言: JST ...

  5. 为了熟练掌握动态SQL你必须要知道Mybatis中的OGNL表达式

    前言 OGNL是个什么东西?很多刚入门Java的同学会有点陌生.但是在Structs流行的时代OGNL可是必会的数据渲染技术.它全称Object Graph Navigation Language,作 ...

  6. OGNL表达式语言中的#和$的区别

    Struts2使用标准的Context来进行OGNL表达式语言求值,OGNL的顶级对象是一个Context,这个Context对象就是一个Map类型实例,其根对象就是 ValueStack,如果需要访 ...

  7. Struts(十):OGNL表达式(一)

    Struts2 用s:porperty标签和OGNL表达式来读取值栈中的属性值: I.值栈中的属性值: 1.对象栈:读取对象栈中的某一个对象的属性值: 2.Map栈 :request,session, ...

  8. Struts2漏洞分析之Ognl表达式特性引发的新思路

    摘要 在Ognl表达式中,会将被括号"()"包含的变量内容当做Ognl表达式执行.Ognl表达式的这一特性,引发出一种新的攻击思路.通过将恶意代码存储到变量中,然后在调用Ognl表 ...

  9. struts2教程(9)--OGNL表达式使用

    OGNL表示式使用和值栈 一.介绍 OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目. Struts2框架使用OGNL作为默认的 ...

  10. struts2的OGNL表达式(二)

    下面说说OGNL表达式的访问情况: OGNL表达式能访问:访问属性,访问方法,访问字体对象,访问静态属性和方法,访问构造方法,访问数组,访问集合 – 投影.选择(? ^ $) 1,OGNL输出常量值 ...

最新文章

  1. ASP.NET前台代码绑定后台变量方法总结
  2. 对高性能Web服务的研究笔记
  3. Java生成pgp密钥对_在Javascript中生成PGP密钥对,并使用加密的PGP私钥对文本进行签名...
  4. kind富文本编辑器_在项目中集成富文本编辑器
  5. oracle 感叹号,Oracle错误案例:ORA-00922
  6. OAuth2.0_授权服务配置_Spring Security OAuth2.0认证授权---springcloud工作笔记140
  7. 不限流量的物联卡是否真存在
  8. 网络管理员考试串讲视频教程
  9. eova1.4版本下拉框没有滚动条
  10. 高维数据软子空间聚类FSC
  11. 用Python爬取28010条《隐秘的角落》评论,我发现了这些...
  12. 如何解决:使用Xbrowser软件连接服务器显示灰屏
  13. 阿里云CDN边缘图像处理功能内测
  14. 引爆寒假招生——圣诞节活动方案大放送
  15. 小霸王其乐无穷~FC红白机游戏600合集(支持mac 12.x系统)
  16. 将SSH密匙添加到云效并下载代码
  17. 第八周编程题在线测试
  18. C#不用ArcEngine,生成Shp文件(五)---------读取.shx文件和生成.shx文件
  19. 4种公众号文章编辑器亲测对比
  20. 【3D建模制作技巧分享】zbrush中如何卡硬边?

热门文章

  1. matlab中bp神经网络梯度怎么调精度,如何提高BP神经网络模型的预测精度?
  2. 京东秒杀倒计时(js)
  3. php递归函数理解,详解php递归函数
  4. vue报错RangeError: Maximum call stack size exceeded
  5. IIS5 IIS6 IIS7区别
  6. 算法64-荷兰国旗问题
  7. BestCoder #88(1001 1002)
  8. Android11(RK3568)自定义服务制作(3)-Hardware制作和权限管理
  9. 基于MATLAB的PID控制器设计
  10. WIN10环境JAVA的JDK环境变量设置教程