day33Struts2Day03(OGNL表达式、值栈)

回顾
1、Servlet的API
    ActionContext对象
    ServletActionContext对象
2、结构类型的跳转
    全局结果
    局部结构 type属性
3、数据的封装
    属性驱动方式
    模型驱动方式 实现ModelDrivern 接口
4、拦截器(自定义拦截器)

OGNL表达式概述
1、OGNL是Object Navigation Language(对象图导航语言)
    所谓对象图,即以任意一个对象为根,通过OGNL可以访问与这个对象关联的其他对象 
    通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。使用相同的表达式去存取对象的属性

2、Struts2框架使用OGNL作为默认的表达式语言
    OGNL是一种比EL强大很多倍的语言
    xwork提供OGNL表达式
    ognl-3.0.5.jar

3、OGNL提供五大类功能
    支持对象方法调用
    支持类静态的方法调用和值访问
    访问OGNL上下文(OGNL context)和ActionContext
    支持赋值操作和表达式串联
    操作集合对象

1、什么是值栈
    值栈就相当于Struts2框架的数据的中转站,向值栈存入一些数据,从值栈中获取到数据
    ValueStack 是Struts2提供一个接口,实现类OgnlValueStack--值栈对象(OGNL是从值栈中获取数据的)
    Action是多例的,有一起请求,创建Action实例,创建一个ActionContext对象,代表的是Action的上下文对象,还会创建一个ValueStack对象
    每个Action实例都有一个ValueStack对象(一个请求,对应一个ValueStack对象)
    在其中保存当前Action对象和其他相关对象
    Struts框架把ValueStack对象保存在名为“struts.valueStack”的请求属性中,request中(值栈对象是request一个属性)
        ValueStack vs = (ValueStack)request.getAttribute("struts.valueStack");

2、值栈的内部结构
    值栈由两部分组成
        root        Struts把动作和相关对象压入ObjectStack中--List
        context     Struts把各种各样的映射关系(一些Map类型的对象)压入ContextMap中

    Struts会默认把下面这些映射压入ContextMap(Context)中
        request代表的是Map集合的key值,value值其实也是一个Map值
        parameters:该Map中包含当前请求的请求参数?name=xxx&password=123
        request:该Map中包含当前request对象中的所有属性
        session:该Map中包含当前session对象中的所有属性
        application:该Map中包含当前application对象中的所有属性
        attr:该Map按如下顺序来检索某个属性:request、session、application

    ValueStack存在root属性(CompoundRoot)context属性(OgnlContext)、
        CompoundText就是ArrayList
        OgnlContext就是Map

    context对应Map引入root对象
        context中还存在request、session、application、attr、parameters对象引用

        OGNL表达式访问值栈中的数据
            访问root中数据时,不需要#
            访问request、session、application、attr、parameters对象数据必须写#
        操作值栈默认指操作root元素

3、值栈对象的创建,ValueStack和ActionContext是什么关系
    值栈对象是请求时创建的
    ActionContext是绑定到当前的线程上,那么在每个拦截器或者Action中获取的ActionContext是同一个
    ActionContext中存在一个Map集合,该Map集合和ValueStack的contextMap是同一个地址
    ActionContext中可以获取到ValueStack的引用

4、获取值栈对象
    (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
    (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

    ActionContext.getContext().getValueStack();

5、向值栈保存数据(主要针对root栈)
    valueStack.push(Object obj)
        push方法的底层调用root对象的push方法(把元素添加到0位置)

    valueStack.set(String key,Object obj)
        源码获取map集合(map可能是已经存在的,有可能是新创建的)把map集合push到栈顶,再把数据存入到map集合中

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

6、从值栈中获取值
    访问root中数据 不需要#
    访问context其他对象数据 加#
    如果向root中存入对象的话 优先使用push方法
    如果向root中存入集合的话,优先要使用set方法

    在OGNLContext中获取数据
        在Action中向与对象中存入值
        xxxx:<s:property value="#xxxx.属性"/>
        request、session、application、attr、parameters

7、获取到值栈中的数据
    为什么EL也能访问值栈中的数据
        StrutsPreparedAndExecuteFilter的doFilter代码中 request = prepare.wrapRequest(request)
        对request对象进行了保证,StrutsRequestWrapper
    org.apache.struts2.dispatcher.StrutsRequestWrapper  
        增强了request的getAttribute
             Object attribute = super.getAttribute(key);
              if (ctx != null && attribute == null) {
            boolean alreadyIn = isTrue((Boolean) ctx.get(REQUEST_WRAPPER_GET_ATTRIBUTE));

            // note: we don't let # come through or else a request for
            // #attr.foo or #request.foo could cause an endless loop
            if (!alreadyIn && !key.contains("#")) {
                try {
                    // If not found, then try the ValueStack
                    ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.TRUE);
                    ValueStack stack = ctx.getValueStack();
                    if (stack != null) {
                        attribute = stack.findValue(key);
                    }
                } finally {
                    ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.FALSE);
                }
            }
        访问request范围的数据时,如果数据找不到,在值栈中找
        request对象 具备访问值栈数据的能力(查找root的数据)

OGNL的特殊符号
1、#符号的用法
    获取contextMap中的数据
        <s:property value="#xxxx.属性"/>
        request/session/application/attr/parameters
    构建一个集合
        性别<s:radio name="sex" list="{'男','女'}"></s:radio> 
        性别<s:radio name="sex" list="#{'1':'男','2':'女'}"></s:radio>

2、%符号的用法
    强制字符串解析成OGNL表达式
        例如:在request域中存入值,然后在文本框(<s:textfield>)中取值,现在到value上
        <s:textfield value="%{#request.msg}"/>
    {}中值用''引起来,此时不再是ognl表达式,而是普通的字符串
        <s:property value="%{'#request.msg'}"/>
        <s:property value="'aaa'"/> 
3、$符号的用法
    在配置文件中可以使用OGNL表达式,例如:文件下载的配置文件
    <action name="download" class="my.demo2.DownLoadAction">
            <result>
                <param name="contentType">${contentType}</param>
                <param name="contentDisposition">attachment:filename=${downFilename}</param>
            </result>
        </action>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值