`

struts2 值栈 和 ognl

 
阅读更多

众所周知,Strut 2的Action类通过属性可以获得所有相关的值,如请求参数、Action配置参数、向其他Action传递属性值(通过chain结果)等等。要获得这些参数值,我们要做的唯一一件事就是在Action类中声明与参数同名的属性,在Struts 2调用Action类的Action方法(默认是execute方法)之前,就会为相应的Action属性赋值。

  要完成这个功能,有很大程度上,Struts 2要依赖于ValueStack对象。这个对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当Struts 2接收到一个.action的请求后,会先建立Action类的对象实例,但并不会调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点(ValueStack对象相当于一个栈)。只是所有的属性值都是默认的值,如String类型的属性值为null,int类型的属性值为0等。

  在处理完上述工作后,Struts 2就会调用拦截器链中的拦截器,当调用完所有的拦截器后,最后会调用Action类的Action方法,在调用Action方法之前,会将ValueStack对象顶层节点中的属性值赋给Action类中相应的属性。大家要注意,在这里就给我们带来了很大的灵活性。也就是说,在Struts 2调用拦截器的过程中,可以改变ValueStack对象中属性的值,当改变某个属性值后,Action类的相应属性值就会变成在拦截器中最后改变该属性的这个值。

  从上面的描述很容易知道,在Struts 2的的Action类可以获得与属性同名的参数值就是通过不同的拦截器来处理的,如获得请求参数的拦截器是params,获得Action的配置参数的拦截器是staticParams等。在这些拦截器内部读取相应的值,并更新ValueStack对象顶层节点的相应属性的值。而ValueStack对象就象一个传送带,将属性值从一个拦截器传到了另一个拦截器(当然,在这其间,属性值可能改变),最后会传到Action对象,并将ValueStack对象中的属性的值终值赋给Action类的相应属性


 拦截器的源代码:packageinterceptors;
importjava.util.Enumeration;
importjava.util.Map;
importjava.util.Properties;
importjava.io.InputStream;
importjava.io.FileInputStream;
importcom.opensymphony.xwork2.ActionContext;
importcom.opensymphony.xwork2.ActionInvocation;
importcom.opensymphony.xwork2.config.entities.ActionConfig;
importcom.opensymphony.xwork2.interceptor.AbstractInterceptor;
importcom.opensymphony.xwork2.util.ValueStack;
publicclassPropertyInterceptorextendsAbstractInterceptor
{
  privatestaticfinalStringDEFAULT_PATH_KEY="path";
  privatestaticfinalStringDEFAULT_ENCODING_KEY="encoding";
  privatestaticfinalStringDEFAULT_SEPARATOR_KEY="separator";
  protectedStringpathKey=DEFAULT_PATH_KEY;
  protectedStringencodingKey=DEFAULT_ENCODING_KEY;
  protectedStringseparatorKey=DEFAULT_SEPARATOR_KEY;
  publicvoidsetPathKey(StringpathKey)
  {
    this.pathKey=pathKey;
  }
  publicvoidsetEncodingKey(StringencodingKey)
  {
    this.encodingKey=encodingKey;
  }
  publicvoidsetSeparatorKey(StringseparatorKey)
  {
    this.separatorKey=separatorKey;
  }
  @Override
  publicStringintercept(ActionInvocationinvocation)throwsException
  {
    ActionConfigconfig=invocation.getProxy().getConfig();
    Map<String,String>parameters=config.getParams();
    if(parameters.containsKey(pathKey))
    {
      Stringpath=parameters.get(pathKey);
      Stringencoding=parameters.get(encodingKey);
      Stringseparator=parameters.get(separatorKey);
      if(encoding==null)
        encoding="UTF-8";
      if(separator==null)
        separator="";
      path=invocation.getAction().getClass().getResource(path)
          .getPath();
      Propertiesproperties=newProperties();
      InputStreamis=newFileInputStream(path);
      java.io.Readerreader=newjava.io.InputStreamReader(is,encoding);
      
      properties.load(reader);
      ActionContextac=invocation.getInvocationContext();
      ValueStackstack=ac.getValueStack();
      System.out.println(stack.hashCode());
      Enumerationnames=properties.propertyNames();
      while(names.hasMoreElements())
      {
        // 下面会使用setValue方法修改ValueStack对象中的相应属性值
        Stringname=names.nextElement().toString();
        if(!name.contains("."))
          stack.setValue(name,properties.get(name));
        StringnewName=null;
        newName=parameters.get(name.replaceAll(".",""));
        if(newName!=null)
          stack.setValue(newName,properties.get(name));
        if(!separator.equals(""))
        {
          newName=name.replaceAll(".","");
          stack.setValue(newName,properties.get(name));
        }        
        newName=name.replaceAll(".",separator);
        stack.setValue(newName,properties.get(name));
      }
    }
    returninvocation.invoke();
  }
}  

 

 

 

ognl标签用法:

访问属性

 

名字属性获取 :<s:property value="user.username"/><br>

地址属性获取 :<s:property value="user.address.addr"/><br>

访问方法

 

调用值栈中对象的普通方法: <s:property value="user.get()"/><br>

访问静态属性和方法

 

调用 Action 中的静态方法: <s:property value="@struts.action.LoginAction@get()"/>

调用 JDK 中的类的静态方法: <s:property value="@java.lang.Math@floor(44.56)"/><br>

调用 JDK 中的类的静态方法 ( 同上 ) <s:property value="@@floor(44.56)"/><br>

调用 JDK 中的类的静态方法: <s:property value="@java.util.Calendar@getInstance()"/><br>

调用普通类中的静态属性: <s:property value="@struts.vo.Address@TIPS"/><br>

访问构造方法

 

调用普通类的构造方法 :<s:property value="new struts.vo.Student(' 王老吉 ' , ' 爱国饮料 ' , 3 , 99).username"/>

 

1.5. 访问数组

 

获取 List:<s:property value="testList"/><br>

获取 List 中的某一个元素 ( 可以使用类似于数组中的下标获取 List 中的内容 ):

<s:property value="testList[0]"/><br>

获取 Set:<s:property value="testSet"/><br>

获取 Set 中的某一个元素 (Set 由于没有顺序,所以不能使用下标获取数据 ):

<s:property value="testSet[0]"/><br> ×

获取 Map:<s:property value="testMap"/><br>

获取 Map 中所有的键 :<s:property value="testMap.keys"/><br>

获取 Map 中所有的值 :<s:property value="testMap.values"/><br>

获取 Map 中的某一个元素 ( 可以使用类似于数组中的下标获取 List 中的内容 ):

<s:property value="testMap['m1']"/><br>

获取 List 的大小 :<s:property value="testSet.size"/><br>

 

访问集合 投影、选择 (? ^ $)

 

利用选择获取 List 中成绩及格的对象 :<s:property value="stus.{?#this.grade>=60}"/><br>

利用选择获取 List 中成绩及格的对象的 username:

<s:property value="stus.{?#this.grade>=60}.{username}"/><br>

利用选择获取 List 中成绩及格的第一个对象的 username:

<s:property value="stus.{?#this.grade>=60}.{username}[0]"/><br>

利用选择获取 List 中成绩及格的第一个对象的 username:

<s:property value="stus.{^#this.grade>=60}.{username}"/><br>

利用选择获取 List 中成绩及格的最后一个对象的 username:

<s:property value="stus.{$#this.grade>=60}.{username}"/><br>

利用选择获取 List 中成绩及格的第一个对象然后求大小 :

<s:property value="stus.{^#this.grade>=600}.{username}.size"/><br>

集合的伪属性

OGNL 能够引用集合的一些特殊的属性 , 这些属性并不是 JavaBeans 模式 , 例如 size(),length() 等等 . 当表达式引用这些属性时 ,OGNL 会调用相应的方法 , 这就是伪属性 .

 

集合

伪属性

Collection(inherited by Map, List & Set)

size ,isEmpty

List

iterator

Map

keys , values

Set

iterator

Iterator

next , hasNext

Enumeration

next , hasNext , nextElement , hasMoreElements

 

  Lambda   :[…]

格式: :[…]

 

使用 Lambda 表达式计算阶乘 :

<s:property value="#f = :[#this==1?1:#this*#f(#this-1)] , #f(4)"/><br>

OGNL # 的使用

# 可以取出堆栈上下文中的存放的对象 .

 

名称

作用

例子

parameters

包含当前 HTTP 请求参数的 Map

#parameters.id[0] 作用相当于

request.getParameter("id")

request

包含当前 HttpServletRequest 的属性( attribute) Map

#request.userName 相当于

request.getAttribute("userName")

session

包含当前 HttpSession 的属性( attribute )的 Map

#session.userName 相当于

session.getAttribute("userName")

application

包含当前应用的 ServletContext 的属性( attribute )的 Map

#application.userName 相当于

application.getAttribute("userName")

attr

用于按 request > session > application 顺序访问其属性( attribute

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

获取 Paraments 对象的属性: <s:property value="#parameters.username"/>

OGNL % 的使用

%{} 可以取出存在值堆栈中的 Action 对象 , 直接调用它的方法 .

例如你的 Action 如果继承了 ActionSupport . 那么在页面标签中,用 %{getText('key')} 的方式可以拿出国际化信息 .

  OGNL $ 的使用

$ ”有两个主要的用途

l          用于在国际化资源文件中,引用 OGNL 表达式

l          Struts 2 配置文件中,引用 OGNL 表达式

  值栈

ValueStack 对象。这个对象贯穿整个 Action 的生命周期(每个 Action 类的对象实例会拥有一个 ValueStack 对象)。当 Struts 2 接收到一个 .action 的请求后,会先建立 Action 类的对象实例,但并不会调用 Action 方法,而是先将 Action 类的相应属性放到 ValueStack 对象的顶层节点( ValueStack 对象相当于一个栈)。

Action 中获得 ValueStack 对象: ActionContext.getContext().getValueStack()

l          Top 语法

使用 Top 获取值栈中的第二个对象 :<s:property value="[1].top. 对象 "/>

l          N 语法

使用 N 获取值栈中的第二个对象 :<s:property value="[1]. 对象 "/>

l          @ 语法

调用 action 中的静态方法: <s:property value="@vs1@ 静态方法 "/> vs :值栈 1 :表示第一个。

分享到:
评论

相关推荐

    struts2--3.Ognl与值栈

    在实际开发中,了解并熟练掌握OGNL和值栈的使用,能显著提高Struts2应用的开发效率和代码可维护性。通过阅读`struts_3`和`struts3_web`这两个文件,你可以进一步深入学习Struts2框架的这些关键特性,并通过实践加深...

    Struts2_OGNL

    在掌握Struts2和OGNL的基础上,开发者可以进一步学习Struts2的其他组件和特性,如标签库、异常处理、国际化支持、拦截器机制、输入校验、文件上传和下载等,这些都是构建复杂Web应用不可或缺的组件和功能。

    struts2 标签 OGNL

    在Struts2中,OGNL被广泛用于访问Action中的属性,以及在视图层(如JSP)中绑定和操作数据。 首先,OGNL使得访问对象属性变得非常直观。它支持点符号(.)和方括号([''])两种方式来访问属性。例如,如果在Action...

    struts2中的ognl

    使用OGNL时,通常配合Struts2的标签,比如`s:property`,通过值栈来访问和显示数据。 3. **EL与值栈的区别**: - Expression Language(EL)虽然也能访问值栈,但它只能从栈顶开始查找,而OGNL可以更灵活地遍历...

    struts2 ognl用法项目

    1. **值栈访问**:Struts2使用值栈存储请求中的所有对象,OGNL可以从值栈顶部找到并访问对象。例如,`#request.user.name`表示从HTTP请求对象中获取`user`属性的`name`。 2. **动态方法调用**:OGNL支持直接调用...

    Struts2 使用OGNL表达式

    Struts2是一个流行的Java web应用程序框架,它极大地简化了MVC(模型-视图-控制器)架构的实现。...如果你想要深入学习Struts2和OGNL,可以参考给出的博客链接,或者查阅官方文档和其他相关的技术资源。

    struts2-xwork-ognl的源文件(jar包)

    XWork的ActionContext对象持有与当前请求相关的所有上下文信息,如值栈(Value Stack)和Action实例。 `ognl-3.0.6-sources.jar` 包含了OGNL的源代码,这是一门强大的表达式语言,用于在Struts2中访问和操作对象图...

    Struts2的标签库及OGNL表达式语言

    开发者可以通过OGNL表达式从值栈中轻松获取和修改数据。 1. **OGNL的属性访问** - 使用`.`或`['']`访问对象属性。例如,`object.property`和`object['property']`都是访问对象的`property`属性。当属性名包含特殊...

    struts2 OGNL

    4. **上下文访问**:OGNL可以访问当前作用域内的所有对象,包括ActionContext中的值栈和请求、会话等范围的属性。 5. **方法调用**:不仅可以获取属性值,还可以直接调用对象的方法,如`#{user.save()}`。 6. **集合...

    struts2标签和OGNL表达式.pdf

    在Struts2中,OGNL被用于处理各种对象,包括值栈(Value Stack)、请求、会话、应用范围的属性等。它能够对这些对象进行查询、操作和修改。OGNL表达式的格式通常包括对对象、属性和方法的引用。例如,可以使用OGNL...

    ognl.rar_OGNL API_struts2 ognl api_struts2帮助文档

    OGNL(Object-Graph Navigation Language)是Struts2框架中重要的表达式语言,它用于在应用程序中进行数据绑定和表达式求值。这篇文档将详细解释OGNL API及其在Struts2框架中的应用。 首先,OGNL是一个强大的、动态...

    struts2标签和OGNL表达式

    栈顶对象是指在ValueStack(值栈)中位于最顶层的对象,ValueStack是一个特殊的对象列表,它包含了一系列的Action对象,便于OGNL查找和访问属性。 ValueStack是Struts2的核心组件,它是一个OgnlValueStack实例,...

    struts2_ognl实验代码

    通过这个实验,你可以深入了解Struts2如何结合OGNL表达式实现数据的传递和显示,以及如何有效地利用值栈。记住,理解并熟练掌握OGNL是成为Struts2开发者的关键步骤,因为它在Struts2的许多核心功能中都起着关键作用...

    struts2中的ognl.jar

    - 值栈:Struts2的值栈是一个存储Action对象和其他辅助对象的数据结构,OGNL可以方便地从值栈中查找和操作对象。 - 视图渲染:在JSP或FreeMarker模板中,OGNL表达式用于从值栈中提取数据并显示在页面上。 - 动态...

    Struts2中的OGNL

    Struts2是一个强大的Java Web应用程序框架,它极大地简化...无论是数据绑定、值栈操作还是JSP标签,OGNL都是Struts2不可或缺的一部分,它的灵活性和强大功能使得开发者能更专注于业务逻辑,而不是繁琐的数据交换细节。

    详解Java的Struts框架中栈值和OGNL的使用

    在Struts 2框架中,值栈和OGNL的使用大大简化了数据在模型、视图和控制器之间的传递,使得开发者可以更专注于业务逻辑,而不是繁琐的数据绑定。通过对值栈的管理和利用OGNL表达式,开发者能够高效地在Web应用的各个...

    Struts 2中的OGNL .rar

    以下是一些关于Struts 2和OGNL的关键知识点: 1. **OGNL表达式**:OGNL表达式可以访问对象的属性,包括方法调用、索引访问、集合和映射操作。例如,`person.name`可以获取`person`对象的`name`属性,而`list[0]`...

    struts2-OGNL表达式测试

    2. **值栈操作**:Struts2使用值栈存储请求相关的数据。OGNL可以直接访问值栈中的任何对象,例如`&lt;s:property value="#session.user.name" /&gt;`将显示会话中用户对象的姓名。 3. **动态方法调用**:OGNL支持对对象的...

    ognl 源码: struts2 所用的 ognl 包源码

    Struts2 的核心功能之一就是允许开发者通过 OGNL 表达式在 JSP 页面、Action 类以及值栈之间灵活地传递数据。 源码分析: 1. **OGNL 源码结构**: OGNL 的源码通常包含多个模块,如解析器(Parser)、编译器...

    Struts2 & OGNL

    总结,Struts2和OGNL的结合提供了强大的数据绑定和表达式能力,极大地简化了Java Web开发。然而,理解其内部工作原理,掌握安全最佳实践,是充分利用这个框架并避免潜在问题的关键。通过深入学习和实践,开发者可以...

Global site tag (gtag.js) - Google Analytics