OGNL表达式与值栈

之前的javaweb中,在页面中做显示,我们很快就能想到

         Javaweb 页面显示 : JSP + JSTL + EL

         Struts2 页面显示支持 JSP 、Freemarker, Velocity ,引入非常强大表达式语言 OGNL

OGNL 五个功能

         1) 支持对象 实例方法调用

         2) 支持静态方法调用

         3)表达式赋值

         4) 访问OGNL上下文(OGNL context)和ActionContext  ------ 值栈操作 (重要)

         5) 操作集合对象  构造List  构造Map

 

1、 调用静态方法和 实例方法, 都需要通过<s:property > 标签完成使用struts2标签要导入标签库

         <%@tagliburi="/struts-tags" prefix="s"%>

实例方法 <s:propertyvalue="'abcd'.length()"/>

静态方法 <s:propertyvalue="@java.lang.String@format('你好, %s','小明')"/>         默认没有被解析

         备注:%s相当于占位符,例子中用小明来代替了。

         * 如果使用静态方法调用,需要在struts.xml中设置<!--支持OGNL 静态方法调用 -->

    <constantname="struts.ognl.allowStaticMethodAccess"value="true"></constant>

 

2、ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础

 ValueStack值栈对象,是Action 实例拥有,每次访问 都会有新的Action实例, 每次访问都会有一个新的值栈  

         ValueStack(值栈):贯穿整个 Action 的生命周期(每个 Action类的对象实例都拥有一个ValueStack对象). 相当于一个数据的中转站.在其中保存当前Action 对象和其他相关对象.

         Struts 框架把 ValueStack对象保存在名为struts.valueStack”的请求属性中,request

 

获得值栈对象

方式:    

         第一种 ValueStack valueStack = (ValueStack)ServletActionContext.getRequest().getAttribute("struts.valueStack");(通过request域获取)

         第二种 ValueStackvalueStack2 = ActionContext.getContext().getValueStack();(通过actionContext获取)

 

值栈ValueStack 由两个部分组成

        

         第一部分ObjectStack (保存root属性,类型CompoundRoot) ----- ArrayList

         第二部分 ContextMap(保存context属性, 类型  ) ------ Map

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

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

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

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

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

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

注:CompoucdRoot继承了ArrayList,实际上就是一个集合,用于存储元素的数据,OgnlContext实现了Map     其中持有CompoucdRoot对象的引用,其key_root

JSP中的数据访问

JSP页面内,通过 <s:property>等标签去访问值栈的数据,访问root中数据,不需要#访问 Context中数据必须以#开始

         之前在取数据的时候用的方法实际上就是在操作值栈

         ServletActionContext.getRequest().setAttribute("requestmsg","requestinfo");

         ServletActionContext.getRequest().getSession().setAttribute("sessionmsg","session info");

         ServletActionContext.getServletContext().setAttribute("applicationmsg",applicationinfo");

         现在在页面中取数据

         <s:propertyvalue="#request.requestmsg"/> <br/>

         <s:propertyvalue="#session.sessionmsg"/> <br/>

         <s:propertyvalue="#application.applicationmsg"/> <br/>

         <s:propertyvalue="#attr.requestmsg"/>       arr:会自动搜索 request session application中的这个数据

 

当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。

Action对象会被保存root 对象栈中,Action所有成员变量属性,都位于root中 ,访问root中数据不需要#

         <s:propertyvalue="company" />  实际上是访问到Action 中 getCompany() 方法

 

向值栈保存数据

         1) 只要定义到Action 成员变量,提供get方法,该数据就在值栈中

         在jsp中 <s:debug> 进行值栈调试

         2) valueStack 对象 提供 push方法,用来将一个对象压入 root栈

         3) 调用valueStack 的set方法,向root中保存数据,如果执行set,将在root中创建一个map对象

        

         * 向context保存数据 valueStack.getContext().put("addr", "西三旗金燕龙"); (一般不向其保存,因为root                                                                                                                                                              就够用了)

3、 ognl 表达式写法

 第一类符号 # , 使用# 访问 OGNL Context中数据  , 访问root 数据不需要添加 #

 <s:propertyvalue="#parameters.name" /> --------->request.getParameter("name");

 <s:property value="#request.name"/> --------- > request.getAttribute("name");

 <s:property value="#session.name"/>  -------- >session.getAttribute("name");

 <s:propertyvalue="#application.name" /> ------ >application.getAttribute("name");

 <s:property value="#attr.name"/>  ------- 依次查找request 、session 、application 中 name数据

         #request ---相当于---- ActionContext.getContext().getRequest()

 

使用EL表达式,能否访问 值栈中 root中数据 ???

         request对象struts2被装饰了, getAttribute 方法被重写了,如果request.getAttribute找不到对应属性,会自动去值栈root中找,因此使用EL表达式能够访问valueStack中对象的属性

结论: 值栈root对象中所有数据,都可以通过 request进行访问 !!!!!!!!!

         值栈数据 通过 JSTL + EL 遍历显示 

 

4通过OGNL去遍历值栈中集合(投影过滤显示)  ---------很重要!!!!

         将集合对象,保存到Action成员变量,自动加入值栈,传递jsp

         在jsp页面内,通过 <s:iterator> 迭代标签<s:property>取值标签   去遍历显示值栈中 List数据

         例:

         <s:iteratorvalue="#request.products" var="product">

                   <!-- 显示product数据,每个product对象会被保存到 root context 中各一份 -->

                   访问root中的<s:propertyvalue="name"/> <s:property value="price"/>

                   访问context中的<s:propertyvalue="#product.name"/> <s:propertyvalue="#product.price"/>

                   两个地方都能取到

         </s:iterator>

 

投影过滤(遍历的时候加入表达式)

         语法  集合name.{表达式}

         例如 : value="products.{name}" ----- 只获取每个商品name属性

         例:

         <h1>投影案例---- 只获得每个商品名称显示</h1>

         <s:iteratorvalue="products.{name}" var="name">

                   <s:propertyvalue="#name"/>

         </s:iterator>

        

         value="products.{?#this.price >3000}"  过滤所有价格大于3000手机

         value="products.{^#this.price >3000}"  只要价格大于3000 第一条信息

         value="products.{$#this.price >3000}"  只要价格大于3000 最后一条信息

         value="products.{?this.prive>3000}.{name}"  显示价格大于3000所有手机的name

 

5、 #可以用来构造 List 或者 Map 对象, 主要用于表单 select radio checkbox 按钮生成(放到form标签)

         <s:radio list=“#{‘male’:‘男’,‘female’:‘女’}”  name=“sex” label=“性别” />

运行结果是相当于之前标签的两个radio

     <input type="radio"name="sex" id="sexmale" value="male"/>男

     <input type="radio"name="sex" id="sexfemale" value="female"/>女

 

6、 %的使用  控制转义 (使用OGNL被是否被解析或者忽略 )

         在很多struts2 标签中, 通过% 指定 OGNL表达式 是否进行解析 

         例:

         控制ognl表达式 不被解析:<s:property value="%{'#request.company'}"/>加‘’

         控制目标 OGNL表达式 被解析:<s:textfieldlabel="%{#request.company}"></s:textfield>不加‘’

        

7、$ 的使用 (用于配置文件,读取一个变量信息)

         1) 用于国际化文件,读取变量信息

         2) struts.xml 中使用 ${contentType} 会自动读取 值栈数据

         例:在国际化文件 添加 msg = 我们的城市是${#request.city}  ---- 可以在值栈根对象中保存city, 通                过request保存

         <%

                   // 在request范围保存数据,在国际化文件 ${#request.city} 获得信息

                   ServletActionContext.getRequest().setAttribute("city","北京");

         %>

         <s:i18n name="message">

                   <s:textname="msg"></s:text>

         </s:i18n>

 

面试题: # 、 % 、 $ 区别

                   # 在jsp中读取 Ognl Context中数据, 投影过滤,构造List和Map

                   % 控制struts2 标签中 OGNL表达式是否解析 , %{表达式} ---- 解析 、 %{'表达式'} ---- 不会解析

                   $ 在struts2 配置文件(struts.xml 国际化文件),定义变量,读取值栈信息 ${city} 读取root                      中city  ${#session.info} 读取session 中 info信息

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值