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

来源:互联网 发布:吴昕的淘宝店怎么关了 编辑:程序博客网 时间:2024/06/04 20:06

OGNL表示式使用和值栈

一、介绍

OGNLObject Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。Struts2框架使用OGNL作为默认的表达式语言。

  xwork 提供 OGNL表达式

  ognl-3.0.5.jar

OGNL 是一种比EL强大很多倍的语言

 

OGNL 提供五大类功能

   1、支持对象方法调用,如xxx.doSomeSpecial()

   2、支持类静态的方法调用和值访问

   3、访问OGNL上下文(OGNL context)和ActionContext; (重点 操作ValueStack值栈 )

   4、支持赋值操作和表达式串联

   5、操作集合对象。

 

、 使用OGNL访问 对象方法 和 静态方法

OGNL jsp结合 struts2标签库 使用 , <s:property value="ognl表达式" />执行 ognl表达式

调用 实例方法 对象.方法()  ----  <s:property value="'hello,world'.length()"/>

调用 静态方法 @[类全名(包括包路径)]@[方法名]  --- <s:property value="@java.lang.String@format('您好,%s','小明')"/>

使用 静态方法调用 必须 设置 struts.ognl.allowStaticMethodAccess=true

 

、 访问OGNL上下文(OGNL context)和ActionContext

OGNL上下文(OGNL context) 对象----- 值栈ValueStack

 

问题一 什么是值栈 ValueStack ?

ValueStack struts2提供一个接口,实现类 OgnlValueStack ----值栈对象 (OGNL是从值栈中获取数据的 )

每个Action实例都有一个ValueStack对象 (一个请求 对应 一个ValueStack对象 )

在其中保存当前Action 对象和其他相关对象 (值栈中 是有Action 引用的 )

Struts 框架把 ValueStack对象保存在名为 “struts.valueStack” 的请求属性中,request中 (值栈对象 是request一个属性)

 

问题二 值栈的内部结构

    值栈由两部分组成

ObjectStack: Struts  把动作和相关对象压入 ObjectStack--List

ContextMap: Struts 把各种各样的映射关系(一些Map 类型的对象)压入 ContextMap

Struts 会把下面这些映射压入 ContextMap

parameters: Map中包含当前请求的请求参数

request: Map中包含当前 request对象中的所有属性

session: Map中包含当前 session对象中的所有属性

application:Map中包含当前 application  对象中的所有属性

attr: Map按如下顺序来检索某个属性: request, session, application

 

ValueStack中 存在root属性(CompoundRoot) context 属性 (OgnlContext

   CompoundRoot 就是ArrayList

   OgnlContext 就是 Map

   context 对应Map引入 root对象

   context中还存在 requestsessionapplicationattrparameters 对象引用

   OGNL表达式,访问root中数据时 不需要#, 访问requestsessionapplicationattrparameters 对象数据 必须写#

   操作值栈 默认指 操作 root元素

 

问题三 值栈对象的创建 ValueStack ActionContext是什么关系 ?

值栈对象 是请求时创建的

doFilterprepare.createActionContext(request, response);

创建ActionContext对象过程中,创建 值栈对象ValueStack

ActionContext对象 对 ValueStack对象 有引用的 (在程序中 通过ActionContext 获得 值栈对象 )

DispatcherserviceAction方法中 将值栈对象保存到 request范围

request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

 

问题四 如何获得值栈对象

获得值栈对象 有两种方法

ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

ValueStack valueStack2 = ActionContext.getContext().getValueStack();

问题五: 向值栈保存数据 (主要针对 root

两种方式

// 将数据保存root的索引0位置,放置到第一个元素ArrayList add(0,element);

valueStack.push("itcast");

 

// 在值栈创建参数map, 将数据保存到map

valueStack.set("company", "传智播客");

jsp中 通过 <s:debug /> 查看值栈的内容

 

问题六: JSP中获取值栈的数据

    访问root中数据 不需要#

    访问 其它对象数据 #

通过下标获取root中对象

   <s:property value="[0].top"/> //取值栈顶对象

直接在root中查找对象属性 (自上而下自动查找)

  valueStack:<s:property value="username"/>

 

OgnlContext中获取数据

request:<s:property value="#request.username"/>

session:<s:property value="#session.username"/>

application:<s:property value="#application.username"/>

attr:<s:property value="#attr.username"/>

parameters:<s:property value="#parameters.cid[0]"/>


四、 值栈在开发中应用

主流应用 值栈 解决 ActionJSP传递 数据问题

 

Action JSP传递数据处理结果 ,结果数据有两种形式

1) 消息 String类型数据

this.addFieldError("msg", "字段错误信息");

this.addActionError("Action全局错误信息");

this.addActionMessage("Action的消息信息");

 

  fieldError 针对某一个字段错误信息 (常用于表单校验)、actionError (普通错误信息,不针对某一个字段 登陆失败)actionMessage 通用消息

 

jsp中使用 struts2提供标签 显示消息信息

<s:fielderror fieldName="msg"/>

<s:actionerror/>

<s:actionmessage/>

2) 数据 (复杂类型数据)

使用值栈  valueStack.push(products);

 

哪些数据默认会放入到值栈 

1)每次请求,访问Action对象 会被压入值栈------- DefaultActionInvocation init方法stack.push(action);

    Action如果想传递数据给 JSP,只有将数据保存到成员变量,并且提供get方法就可以了

2ModelDriven接口 有一个单独拦截器

<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>

在拦截器中 ,将model对象 压入了 值栈stack.push(model);

   如果Action实现ModelDriven接口,值栈默认栈顶对象 就是model对象

 

五、 值栈的数据 通过EL访问

问题七:为什么 EL也能访问值栈中的数据

 

StrutsPreparedAndExecuteFilterdoFilter代码中request = prepare.wrapRequest(request);

  Request对象进行了包装 ,StrutsRequestWrapper

  重写requestgetAttribute

Object attribute = super.getAttribute(s);

if (attribute == null) {

   attribute = stack.findValue(s);

}

      访问request范围的数据时,如果数据找不到,去值栈中找

l request对象 具备访问值栈数据的能力 (查找root的数据)

 

 

OGNL表达式 常见使用

#%$符号使用

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: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>

<s:property value="#pname"/></s:iterator>


 

用法四: 使用#构造map集合

经常结合 struts2 标签用来生成 selectcheckboxradio

<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>


 

2) %的使用

   用法一: 结合struts2表单表单使用, 通过%通知struts%{}中内容是一个OGNL表达式,进行解析

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

   用法二: 设置ognl表达式不解析%{'ognl表达式'}

   <s:property value="%{'#request.username'}"/>

 

3$的使用

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

                 properties文件msg=欢迎您, ${#request.username}


   用法二 :在Struts 2配置文件中,引用OGNL表达式

               <!-- Action提供 getContentType方法-->

               <param name="contentType">${contentType}</param>

      ${contentType} 读取值栈中contentType数据,在Action提供getContentType 因为Action对象会被压入值栈,

      contentTypeAction属性,从值栈获得

 

结论: #使用ognl表达式获取数据,%控制ognl表达式是否解析 ,$用于配置文件获取值栈的数据



0 0