一、OGNL

1.1 概述

  • OGNLObject-Graph Navigation Language的缩写,它是一种功能强大的表达式语言.比el表达式功能强大。Struts2ognl表达式语言,集成当sturts2框架中,做为它的默认表达式语言。
  • OGNL中有一个OgnlContext,它可以设置root与非root .root中数据获取时,不需要加#,而非root中数据在获取时,需要加上#

1.2 OGNL 五大类功能

  • 1、支持对象方法调用,如xxx.doSomeSpecial();
  • 2、支持类静态的方法调用和值访问
  • 3、访问OGNL上下文(OGNL context)和ActionContext; (重点 操作ValueStack值栈 )
  • 4、支持赋值操作和表达式串联
  • 5、操作集合对象。

1.3 演示

  • 在struts2中使用ognl表达式
  • 需要结合struts2的标签使用`

    <s:property value="'abc'.length()"/>  演示对象调用方法
    <s:property value="@java.lang.Math@max(10,20)"/> 演示静态成员访问.
  • 注意:在struts2中使用静态成员访问,必须设置一个常量:struts.ognl.allowStaticMethodAccess=false


ognl对象导航操作

二、ValueStack

2.1 概述

  • ValueStack,它是一个接口com.opensymphony.xwork2.util.ValueStack。我们使用它是将其做为一个容器,用于携带action数据到页面.在页面上通过ognl表达式获取数据
  • ValueStack主要是将action数据携带到页面上,通过ognl获取数据
    • 1.ValueStack有一个实现类叫OgnlValueStack.

      • 2.每一个action都有一个ValueStack.(一个请求,一个request,一个action,一个valueStack) ValueStack生命周期就是request生命周期。
      • 3.ValueStack中存储了当前action对象以及其它常用web对象(request,session,application.parameters)
      • 4.struts2框架将valueStack以“struts.valueStack”为名存储到request域中。

2.2 ValueStack结构

  • ValueStack中 存在root属性 (CompoundRoot) 、 context 属性 (OgnlContext
  • CompoundRoot 就是ArrayListlist集合中存储的是action相关信息,
  • OgnlContext 就是 Mapmap集合中存储的是相关映射信息,包含 paramters,request,session,application attr等。
  • 我们想要从list中获取数据,可以不使用#号.(它就是ognl的root)
  • 如果从map中获取数据,需要使用#. (其实在struts2中的map--context其实就是ognlContext)

2.3 结论

  • ValueStack它有两部分 List Map
  • 在struts2中List就是root Map就是ognlContext.
  • 默认情况下,在struts2中从valueStack获取数据从root中获取。

  • 值栈对象的创建 ,ValueStack 和 ActionContext 是什么关系 ?

    ActionContext ctx = ActionContext.getContext();
    if (ctx != null) {
    stack = ctx.getValueStack();
    }
  • ValueStack是每一次请求时,都会创建.

  • 在ActionContext中持有了valueStack的引用。

2.3 一些问题

  • 获得值栈对象
  • 对于ValueStack获取有两种方式:

    • 1.通过 request获取
    ValueStack vs=(ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
    • 2.通过ActionContext获取.
    ValueStack vs=ActionContext.getContext().getValueStack();
  • 向值栈保存数据 (主要针对 root),主要有两个方法

    • push(Object obj)------->底层就是 root.add(0,obj) 将数据存储到栈顶。
    • set(String name,Object obj);----->底层是将数据封装到HashMap中,在将这个HashMap通过push存储。
      • 在jsp中 通过 查看值栈的内容
  • 在JSP中获取值栈的数据

    • root中数据不需要#,而context中数据需要#
    1.如果栈顶是一个Map集合,获取时,可以直接通过Map集合的key来获取value.
    <s:property value="username"/>
    2.如果栈顶数据不是一个Map,没有key值,可以使用序号来获取。
    <s:property value="[0]"> 从0的位置向下查找所有。
    <s:property value="[0].top"> 只查找0位置上数据。
  • 如何获取OgnlContext中数据:

    1.request数据    request.setAttribute()
    2.session数据 session.setAttribute()
    3.application数据 application.setAttribute()
    4.attr 依次从request,session.application中查找
    5.parameters 获取请求参数
  • ValueStack主流应用:就是解决将action数据携带到jsp页面。

  • 1.文本(字符串)

    1.fieldError   校验数据错误信息提示
    2.actionError 关于逻辑操作时错误信息(例如登录失败)
    3.message 就是一个信息.
    this.addFieldError("msg", "字段错误信息");
    this.addActionError("Action全局错误信息");
    this.addActionMessage("Action的消息信息");
    * fieldError 针对某一个字段错误信息 (常用于表单校验)、actionError (普通错误信息,不针对某一个字段 登陆失败)、 actionMessage 通用消息
    在jsp中使用 struts2提供标签 显示消息信息
    <s:fielderror fieldName="msg"/>
    <s:actionerror/>
    <s:actionmessage/>
    • 2.复杂数据
    可以使用valueStack存储.
    在action中存储数据:
    List<User> users = new ArrayList<User>();
    users.add(new User("tom", "123", 20, "男"));
    users.add(new User("james", "456", 21, "男"));
    users.add(new User("fox", "789", 26, "男"));
    vs.push(users);
    在页面上获取数据:
    使用了<s:iterator>标签来迭代集合。
    <s:iterator value="[0].top" var="user"> 这是将集合中迭代出来每一个元素起个名称叫user,而user是存储在context中,不在root中.l
    <s:iterator value="[0].top" var="user">
    username:<s:property value="#user.username"/><br>
    password:<s:property value="#user.password"/>
    <hr>
    </s:iterator>
    注意:如果我们在使用<s:iterator>进行迭代时,没有给迭代出的元素起名.
    <s:iterator value="[0].top">
    username:<s:property value="username"/><br>
    password:<s:property value="password"/>
    <hr>
    </s:iterator>
  • 关于默认压入到valueStack中的数据.

    • 1.访问的action对象会被压入到valueStack中.

      • DefaultActionInvocation 的 init方法 stack.push(action);
      • Action如果想传递数据给 JSP,只有将数据保存到成员变量,并且提供get方法就可以了
    • 2.ModelDriveInterceptor会执行下面操作

      ModelDriven modelDriven = (ModelDriven) action;
      ValueStack stack = invocation.getStack();
      Object model = modelDriven.getModel();
      if (model != null) {
      stack.push(model);
      }
      • 将实现了ModelDrive接口的action中getModel方法的返回值,也就是我们所说的model对象压入到了valueStack.
  • 为什么el表达式可以访问valueStack中数据?

    • struts2框架中所使用的request对象,是增强后的request对象。
    • ${username}---->request.getAttribute("username");
    • 增强后的request,会首先在request域范围查找,如果查找不到,会在valueStack中查找
    • StrutsPreparedAndExecuteFilterdoFilter代码中
    • `request = prepare.wrapRequest(request);
    • 对Request对象进行了包装 ,StrutsRequestWrapper
    • 重写request的 getAttribute

      Object attribute = super.getAttribute(s);
      if (attribute == null) {
      attribute = stack.findValue(s);
      }
    • 访问request范围的数据时,如果数据找不到,去值栈中找 request对象 具备访问值栈数据的能力 (查找root的数据)

三、OGNL表达式常见使用符号

3.1 #号

  • 用法一,#代表 ActionContext.getContext() 上下文


    <s:property value="#request.name" /> ActionContext().getContext().getRequest().get("name");
    #request
    #session
    #application
    #attr
    #parameters
  • 用法二,不写# 默认在 值栈中root中进行查找

    <s:property value="name" /> 在root中查找name属性
    * 查询元素时,从root的栈顶元素 开始查找, 如果访问指定栈中元素
    <s:property value="[1].name" /> 访问栈中第二个元素name属性
    * 访问第二个元素对象 <s:property value="[1].top" />
  • 用法三,进行投影映射 (结合复杂对象遍历 )

    1)集合的投影(只输出部分属性
    <h1>遍历集合只要name属性</h1>
    <s:iterator value="products.{name}" var="pname">
    <s:property value="#pname"/>
    </s:iterator>
    2)遍历时,对数据设置条件
    <h1>遍历集合只要price大于1500商品</h1>
    <s:iterator value="products.{?#this.price>1500}" var="product">
    <s:property value="#product.name"/> --- <s:property value="#product.price"/>
    </s:iterator>
    3)综合
    <h1>只显示价格大于1500 商品名称</h1>
    <s:iterator value="products.{?#this.price>1500}.{name}" var="pname">
    <s:property value="#pname"/>
    </s:iterator>
  • 用法四,使用#构造map集合

经常结合 struts2 标签用来生成 select、checkbox、radio
<h1>使用#构造map集合 遍历</h1>
<s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry">
key : <s:property value="#entry.key"/> , value: <s:property value="#entry.value"/> <br/>
</s:iterator>

3.2 %号

  • 有些标签的value属性自动解析ognl表达式,
  • 比如 <s:property value="表达式" />
  • 但是有些标签是不自动解析的
  • 比如:<s:textfild value="表达式"/>
  • %作用:就是用于设定当前是否要解析其为 ognl表达式.

  • %{表达式} 当前表达式会被做为ognl解析.

  • %{'表达式'} 当前表达式不会被做为ognl解析。

3.3 $号

  • $作用:就是在配置文件中使用ognl表达式来获取valueStack中数据.
  • 1.struts.xml

    <result type="stream">
    <param name="contentType">${contentType}</param>
    </result>
    (在Action中有一个getContentType() 方法)此处在上传文件的地方有讲解
  • 2.在校验文件中使用

    ${min}  ${max}
    ${minLength} ${maxLength}
  • 3.在国际化文件中使用

    在properties文件中
    username=${#request.username}
    在jsp页面
    <s:text name="username">
  • 总结: #就是用于获取数据 %就是用于设置是否是ognl表达式 $就是在配置文件中使用ognl.


1.valueStack内部结构


2.关于默认压入的model分析


3.关于压入到valuestack中的model分析-增强-


4.关于valueStack相关的结构分析

【Struts2】Ognl与ValueStack的更多相关文章

  1. Struts2第九篇【OGNL、valueStack详解】

    什么是OGNL表达式? OGNL是Object Graphic Navigation Language 是操作对象属性的开源表达式. Struts2框架使用OGNL作为默认的表达式语言. 为什么我们学 ...

  2. Struts2【OGNL、valueStack】就是这么简单

    什么是OGNL表达式? OGNL是Object Graphic Navigation Language 是操作对象属性的开源表达式. Struts2框架使用OGNL作为默认的表达式语言. 为什么我们学 ...

  3. [ SSH框架 ] Struts2框架学习之三(OGNl和ValueStack值栈学习)

    一.OGNL概述 1.1 什么是OGNL OGNL的全称是对象图导航语言( object-graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可 ...

  4. struts2 OGNL ValueStack概念理解 # % $ 的区别

    http://blog.csdn.net/tjujacob/article/details/8117659 —————————————————————————————————————————————— ...

  5. Struts2之OGNL与ValueStack

    时间:2017-1-12 12:02 --OGNL1.OGNL表达式是什么    OGNL的全称是Object-Graph Navigation Language的缩写,中文名是对象图导航语言,它是一 ...

  6. Struts2(Ognl)

    OGNL(Object-Graph Navigation Language)全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者调用对象的方法,能够遍历整 ...

  7. 【Java EE 学习 36】【struts2】【struts2系统验证】【struts2 ognl值栈】【struts2 ongl标签】【struts2 UI标签】【struts2模型驱动和令牌机制】

    一.struts2系统验证 1.基于struts2系统验证的方式实际上就是通过配置xml文件的方式达到验证的目的. 2.实际上系统校验的方法和手工校验的方法在底层的基本实现是相同的.但是使用系统校验的 ...

  8. 十九、利用OGNL获取ValueStack中:根栈和contextMap中的数据

    利用OGNL获取ValueStack中:根栈和contextMap中的数据 原则:OGNL表达式如果以#开头,访问的contextMap中的数据 如果不以#开头,是访问的根栈中的对象的属性(List集 ...

  9. struts2 与 OGNL 表达式,jsp中 利用ognl 在valuestack中取值

    在Struts2中,一个请求在终于到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是 ...

随机推荐

  1. linux rz sz替代方案

    SFTP是基于SSH的文件传输协议,与ZMODEM相比具有更加安全且更为快速的文件传输功能. 如何利用SFTP接收文件: 1. 在本地提示以sftp命令登陆拟要接收文件的主机.Xshell:\> ...

  2. golang web框架设计4:日志设计

    beego的日志设计思路来自于seelog,根据不同的level来记录日志,beego设计的日志是一个轻量级的,采用系统log.Logger接口,默认输出到os.Stdout,用户可以实现这个接口然后 ...

  3. SpringCloud 与 Dubbo区别

    总览   Dubbo SpringCloud 服务注册中心 Zookeeper Spring Cloud Netfix Eureka 服务调用方式 RPC REST API 服务监控 Dubbo-mo ...

  4. 【转】TCP/IP网络协议各层首部

    ​ 数据包封装流程(逐层封装,逐层解封) 二层帧(二层帧中目的地址6个字节,源地址6个字节,长度/类型2个字节,二层帧共18个字节) ip头部(ip头部20字节) tcp头部(tcp头部20个字节): ...

  5. shell脚本中set -e作用

    最近学习shell脚本想到一个问题,如果脚本中出现了一条异常语句,甚至可以影响整个脚本的使用,那么是否有一旦出现问题就可以及时停止的方法呢?在shell脚本中set命令就可以轻松实现.set命令的-e ...

  6. 关于使用Arduino做开发的理解

    转载自arduino中文社区 https://www.arduino.cn/thread-5414-1-1.html 见到很多人对Arduino的开发方法 .应用场景有误解,特别开个帖子说明下. 误解 ...

  7. C/C++编程

    基本的数据类型: 整型 浮点型(单精度.双精度) 在c语言中,所有的变量声明必须在任何执行语句之前(对当前域来说), 否则编译的时候会出现变量是未声明的标识符的错误. main 入口参数:argc 和 ...

  8. 【计算机视觉】特征脸EigenFace与PCA

    [计算机视觉]特征脸EigenFace与PCA 标签(空格分隔): [图像处理] 版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/lg1259156776/. 说 ...

  9. AndroidMainfest详解

    基于TV settings和SettingsProvider Android启动模式对activity行为的影响 AndroidManifest.xml文件详解 Manifest文件中,applica ...

  10. 常用的API

    API (application programming Interface)应用程序编程接口 java 是字典 Scanner类的功能可以实现从键盘输入到程序当中. 引用类型的一般使用步骤 ·1导包 ...