• OGNL表示式使用和值栈


    另外值得参考博客:http://blog.csdn.net/resigshy/article/details/7560573

    OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。Struts2框架使用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()"/>
    <!--调用静态方法:@[类全名(包括包路径)]@[方法名]-->
    <!--使用静态方法调用必须设置struts.ognl.allowStaticMethodAccess=true-->
    <s:property value="@java.lang.String@format('您好,%s','小明')"/>

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

    什么是值栈ValueStack ?
      ValueStack是struts2提供一个接口,实现类OgnlValueStack----值栈对象(OGNL是从值栈中获取数据的 ),每个Action实例都有一个ValueStack对象(一个请求对应一个ValueStack对象 ),在其中保存当前Action对象和其他相关对象(值栈中是有Action引用的),Struts框架把ValueStack对象保存在名为“struts.valueStack”的请求属性中(值栈对象是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中还存在request、session、application、attr、parameters对象引用
      OGNL表达式,访问root中数据时不需要#,访问request、session、application、attr、parameters对象数据必须写#
      操作值栈默认指操作 root 元素
    值栈对象的创建,ValueStack和ActionContext是什么关系 ?

    //Struts2源码
    ActionContext ctx = ActionContext.getContext();
    if (ctx != null){
      stack = ctx.getValueStack();
    }    

      每一次请求时,都会创建valueStack,在ActionContext中持有了valueStack的引用。
    如何获得值栈对象
      获得值栈对象有两种方法

    ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
    ValueStack valueStack2 = ActionContext.getContext().getValueStack();

    向值栈保存数据(主要针对root)

    //两种方式 
    //将数据保存root的索引0位置,放置到第一个元素ArrayList.add(0,element);
    valueStack.push("tom");
    //在值栈创建参数map,将数据保存到map中
    valueStack.set("username", "tom");    

      在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]"/>
    值栈在开发中应用
      主流应用:值栈解决Action向JSP传递数据的问题
      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方法就可以了
      2)ModelDriven接口有一个单独拦截器
        <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
        在拦截器中,将model对象压入了值栈stack.push(model),如果Action实现了ModelDriven接口,值栈默认栈顶对象就是model对象
    为什么EL也能访问值栈中的数据
      struts2框架中所使用的request对象,是增强后的request对象,增强后的request,会首先在request域范围查找,如果查找不到,会在valueStack中查找。
      StrutsPreparedAndExecuteFilter的doFilter代码中request=prepare.wrapRequest(request),对Request对象进行了包装,重写了request的getAttribute方法

    //源码
    Object attribute = super.getAttribute(s);
    if (attribute == null) {
      attribute = stack.findValue(s);//访问request范围的数据时,如果数据找不到,去值栈中找
    }

    OGNL表达式常见使用(#,%,$符号使用)
      1)#的使用
        用法一:#代表ActionContext.getContext()上下文
          <s:property value="#request.name" />-----> ActionContext().getContext().getRequest().get("name");
        用法二:不写#默认在值栈中root中进行查找
          <s:property value="name" />
          查询元素时,从root的栈顶元素开始查找,如果访问指定栈中元素

    <s:property value="[1].name" /><!--访问栈中第二个元素name属性--> 
    <s:property value="[1].top" /><!--访问第二个元素对象(会包含Struts2本身的一些属性值,如{username=tom, com.opensymphony.xwork2.util.OgnlValueStack.MAP_IDENTIFIER_KEY=})-->

        用法三:进行投影映射(结合复杂对象遍历)
          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:property value="#pname"/>
    </s:iterator>

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

    <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}
          在页面

    <!--自动将值栈的username 结合国际化配置信息显示-->
    <s:i18n name="messages">
      <s:text name="msg"></s:text>
    </s:i18n>

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

    <!-- 在Action 提供 getContentType方法 -->
    <param name="contentType">${contentType}</param>    

          ${contentType}读取值栈中contentType数据,在Action提供getContentType方法,因为Action对象会被压入值栈,
    结论:#使用ognl表达式获取数据,%控制ognl表达式是否解析,$用于配置文件获取值栈的数据
    ognl操作集合(了解)
      <s:property value="products[0].name"/> 访问集合第一个元素name属性
      <s:property value="map['name']"/> 访问map中key为name的值
      {} 直接构造List 元素、 #{} 直接构造 Map元素

    <s:iterator value="{'aaa','bbb'}" var="s">
      <s:property value="#s"/>
    </s:iterator>
    <s:iterator value="#{'ccc':'111','ddd':'222' }" var="entry">
      <s:property value="#entry.key"/>
    </s:iterator>
  • 相关阅读:
    简单的股票分析系统
    gtest日志在工程项目中的应用
    doctest初次体验
    python写的读取json配置文件
    logbook日志系统
    python3 pyodbc简单使用
    numpy中dtype
    python获取代码行号
    Python操作SQLServer示例(转)
    log4j与log4j.properties的配置
  • 原文地址:https://www.cnblogs.com/fengmingyue/p/6159749.html
Copyright © 2020-2023  润新知