目录:

一、值栈

二、OGNL表达式

一、值栈(ValueStack)

1.定义

     ValueStack贯穿整个Acton的生命周期,每个Action类的对象实例都拥有一个ValueStack对象,相当于一个数据中转站,在其保存当前的Action对象和其他对象。

 

2.结构

     在ValueStack对象内部有两个逻辑部分。

      ObjectStack:  root属性,是一个ArrayList,包含Action对象和其他对象。

      ContextMap:  context属性,是一个Map,默认压入内容(request、session、application、attr、parameters)。

    

              

     当Struts2接受一个请求时,会创建ActionContext、ValueStack、Action实例。然后action存放进ValueStack,所以Action的实例变量可以被OGNL访问。OGNL表达式需要配合Struts标签才可以使用。

     Struts 的 property 标签用来输出值栈中的一个属性值。

  1. <s:property value="username"/>

     详细流程

    Struts2接受到一个action请求后,会创建Action类的实例,但是并不会调用Action方法,而是先将Action类的相应属性放到ValueStack对象的栈顶,所有的属性值都是默认值。然后Struts2会调用拦截器中链中的拦截器,当调用完所有的拦截器后,最后会调用Action类的Action方法。在调用Action方法之前,会将ValueStack中属性值赋给Action类中的相应属性。可以知道在Struts2的Action类可以获得与属性同名的参数值就是通过不同的拦截器来处理的,如获得请求参数的拦截器是params,获得Action配置参数的拦截器是staticParam等。在这些拦截器内部读取相应的值,然后更新到ValueStack对象栈顶的相应属性。

 

3.值栈的相关操作

(1)如何获取值栈对象

  1. ValueStack vs1 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
  2. ValueStack vs2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
  3. ValueStack vs3 = ActionContext.getContext().getValueStack();

 

(2)向值栈保存数据

A: valueStack.push(Object obj);

     push方法的底层调用root对象的push方法(把元素添加到0位置)。

B:valueStack.set(String key, Object obj);

     获取map集合(map有可能是已经存在的,有可能是新创建的),把map集合push到栈中,再把数据存入到map集合中。

 

(3)EL表达式为什么也能访问值栈中的属性

     在核心过滤器中有个doFilter方法。

    

     在核心过滤器的doFilter方法中,调用request的包装方法wrapRequest,返回request对象。

    

    

     在Dispatcher类中的request对象的包装类中首先判断request对象是否已经被该类包装,如果已经被包装,不需要再次包装,直接返回即可,如果没有被包装,执行下面的if-else语句,在if的判断中,判断其是否是文件上传,如果是创建文件上传的包装类对象,在此我们不讨论这种情况。如果不是文件上传,创建request对象的包装类StrutsReuqestWrapper对象,在参数中传入需要包装的request对象。按住Ctrl键,查看该包装类。

因为上面的每个方法都返回request对象,那么如果执行到这里,核心过滤器中的request对象就是StrutsReuqestWrapper类的实例对象。

StrutsReuqestWrapper该类中有个getAttribute方法,就是这个方法判断从Servlet容器中取值还是从值栈中取值。

  

     总结就是获取request的包装类StrutsReuqestWrapper,获得该类的实例对象。类中有getAttribute方法,在该方法中判断是从Servlet容器中取值,还是从值栈中取值。先调用父类javax.servlet.ServletRequestWrapper的 getAttribute方法,如果获取不到值,就获取值栈对象,调用值栈对象的findValue方法取值。

二、OGNL

     在JSP页面可以利用OGNL(Object-Graph-Navigation-Language)对象导航图语言来访问值栈中的对象属性。

     如希望访问值栈中ContextMap中的数据,需要在表达式加上一个前缀#,如果没有前缀#,则将在ObjecStack里进行。

 

1.如果访问其他Context中的对象,由于它们不是根对象,所以在访问时,需要添加#前缀

    

 

Action中代码

  1. ServletActionContext.getRequest().setAttribute("username","username_request");
  2. ServletActionContext.getContext().getSession().put("username","username_session");
  3. ServletActionContext.getServletContext().setAttribute("username","username_application");
  4. ValueStack valueStack = ServletActionContext.getContext().getValueStack();
  5. valueStack.set("username","username_valueStack");

Jsp页面

  1. <!-- username_request -->
  2. request: <s:property value="#request.username"/><br>
  3.  
  4. <!-- username_session -->
  5. session: <s:property value="#session.username"/> <br>
  6.  
  7. <!-- username_application -->
  8. application: <s:property value="#application.username"/> <br>
  9.  
  10. <!-- username_request -->
  11. attr: <s:property value="#attr.username"/> <br>
  12.  
  13. <!-- username_valueStack -->
  14. valueStack: <s:property value="username"/> <br>
  15.  
  16. <!-- Lynx -->
  17. parameters: <s:property value="#parameters.username[0]"/> <br>

 

    

     (1)在OgnlValueStack类里有一个List类型的root变量,他存放了一组对象。

     (2)处于第一位的对象叫栈顶对象。

     (3)通常我们在OGNL表达式里直接写上属性的名称即可访问root变量里对象的属性。

     (4)搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下访问,直到找到为止。

 

2.集合的过滤

有三种方式:

(1)"?#" : 过滤所有符合条件的集合。user.{?#this.age > 19}

(2)"^#" : 过滤第一个符合条件的元素。

(3)"$#" : 过滤最后一个符合条件的元素。

this表示集合中的元素。

 

Action代码

  1. List<Person> list = new ArrayList<Person>();
  2. list.add(new Person("AAA",22));
  3. list.add(new Person("BBB",23));
  4. list.add(new Person("CCC",19));
  5. list.add(new Person("DDD",17));
  6. ServletActionContext.getRequest().setAttribute("list",list);

 

显示页面

  1. <!-- "?#":过滤所有符合条件的集合 -->
  2. <!-- AAA:22--BBB:23 -->
  3. <s:iterator value="#request.list.{?#this.age > 20}" var="person">
  4. ${person.username} : ${person.age} <br>
  5. </s:iterator>
  6.  
  7. <!-- "$#" : 过滤最后一个符合条件的元素。-->
  8. <!-- DDD:17 -->
  9. <s:iterator value="#request.list.{$#this.age < 20}" var="person">
  10. ${person.username} : ${person.age} <br>
  11. </s:iterator>
  12.  
  13. <!-- "^#" : 过滤第一个符合条件的元素。-->
  14. <!-- CCC:19 -->
  15. <s:iterator value="#request.list.{^#this.age < 20}" var="person">
  16. ${person.username} : ${person.age} <br>
  17. </s:iterator>

 

3.%的用法

     "%"用途是告诉执行环境%{}里的是OGNL表达式。

Action中的代码

  1. ServletActionContext.getRequest().setAttribute("username","username_request");

JSP页面

  1. <s:textfield name="name" label="%{#request.username} "/>

运行结果

  1. username_request : <input type="text" name="name" value="" id="name"/>

 

4.$的用法

     (1)用于在国际化资源文件中,引用OGNL表达式。

     (2)在Struts2配置文件中,引用OGNL表达式。

     在struts2配置文件中引用ognl表达式 ,引用request等作用域中的值

     在项目中使用重定向Action的时候,在此时request作用域失效,可使用该方法传值。

Struts2基础学习(七)—值栈和OGNL的更多相关文章

  1. Struts2知识点小结(三)--值栈与ognl表达式

    1.问题一 : 什么是值栈 ValueStack        回顾web阶段 数据交互问题?        客户端提交数据  到  服务器端    request接受数据+BeanUtils实体封装 ...

  2. 学习Struts--Chap05:值栈和OGNL

    1.值栈的介绍 1.1 值栈的介绍: 值栈是对应每一个请求对象的数据存储中心,struts2会给每一个请求对象创建一个值栈,我们大多数情况下不需要考虑值栈在哪里,里面有什么,只需要去获取自己需要的数据 ...

  3. 走进Struts2(五)— 值栈和OGNL

    值栈 1.值栈是什么? 简单说:就是相应每个请求对象的轻量级的内存数据中心. Struts2引入值栈最大的优点就是:在大多数情况下,用户根本无须关心值栈,无论它在哪里,不用管它里面有什么,仅仅须要去获 ...

  4. Struts2的值栈和OGNL牛逼啊

    Struts2的值栈和OGNL牛逼啊 一 值栈简介: 值栈是对应每个请求对象的一套内存数据的封装,Struts2会给每个请求创建一个新的值栈,值栈能够线程安全的为每个请求提供公共的数据存取服务. 二 ...

  5. 值栈和OGNL 之 7.1 值栈

    7.1  值栈 7.1.1  值栈是什么 简单的说:值栈是对应每一个请求对象的轻量级的内存数据中心. Struts2中一个很激动人心的特性就是引入了值栈,在这里统一管理着数据,供Action.Resu ...

  6. Struts2基础学习2

    Struts2基础学习2 项目结构,测试页面与实体类 <%@ page language="java" contentType="text/html; charse ...

  7. Struts2学习记录-Value Stack(值栈)和OGNL表达式

    仅仅是学习记录.把我知道的都说出来 一.值栈的作用 记录处理当前请求的action的数据. 二,小样例 有两个action:Action1和Action2 Action1有两个属性:name和pass ...

  8. struts2学习(7)值栈简介与OGNL引入

    一.值栈简介: 二.OGNL引入: com.cy.action.HelloAction.java: package com.cy.action; import java.util.Map; impor ...

  9. 关于Struts2中的值栈与OGNL表达式

    1.1.1    OGNL概述: Object Graphic Navigation Language(对象图导航语言)的缩写 * EL     :OGNL比EL功能强大很多倍. 它是一个开源项目. ...

随机推荐

  1. P177 test 6-4 UVa439

    //P177 test 6-4 UVa439 #include<cstdio> #include<cstring> #include<queue> using na ...

  2. git + tortoisegit安装及配置

    1. 下载Git-2.6.3-64-bit.exe 2. 安装Git-2.6.3-64-bit.exe,安装时可全部默认配置(安装路径可选) 3. 下载TortoiseGit-1.8.16.0-64b ...

  3. JavaScript定时器及相关面试题

    在单线程JavaScript这篇文章中,在介绍JavaScript单线程的同时,也介绍了setTimeout是如何工作的.但是对于定时器的一些内容,并没有做深入的讨论.这篇文章,会详细说说JS的两种定 ...

  4. Selenium 显示等待和隐式等待

    1. 设置显示等待 Java代码: 1 2 3 4 5 public static WebElement WaitForElement(WebDriver driver, String locator ...

  5. Android -- 自定义ScrollView实现放大回弹效果

    1,刚刚在别人开源的项目中看到了一个挺不错的用户体验,效果图如下: 2,那下面我们就来实现一下,首先看一下布局,由于一般只是我们包含头像的那部分方法,所以这里我们要把布局分成两部分,对应的布局文件效果 ...

  6. ionic 添加新module

    angular.module 引入新的module: 1. 在index.html中需要引入必须的js文件2. app.js: angular.module('starter', ['ionic',' ...

  7. lnmp pathinfo问题

    location / {              if (!-e $request_filename) {              rewrite  ^/(.*)$  /index.php/$1  ...

  8. JavaWeb之Listener监听器

    监听在Java体系中运用的很广泛,在安卓开发.JavaWeb开发中到处存在,在其他语言也有类似的,如果有了解过设计模式那很容易理解实现的原理.不过对于开发者来说,使用观察者模式只需实现相应的接口就好, ...

  9. java开发中获取路径的一些方式

    1.servlet开发获取WebContent(项目)的绝对路径: System.out.println(getServletContext().getRealPath("")); ...

  10. Hibernate中遇见的问题

    1.在用Hibernate写增删改查时,有两种方式:a.HQL语句,b.原生态sql语句 如果我要执行的语句是:select * from Question HQL是这么写的: Session ses ...