zoukankan      html  css  js  c++  java
  • [ SSH框架 ] Struts2框架学习之三(OGNL和ValueStack值栈学习)

    一、OGNL概述

    1.1 什么是OGNL

      OGNL的全称是对象图导航语言( object-graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现必要的类型转换。如果把表达式看作是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。

    1.2 OGNL的作用  

    Struts2默认的表达式语言就是OGNL,它具有以下特点:
      ●  支持对象方法调用。例如: objName. methodName( )。
      ●  支持类静态方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[ 方法名|值名 ]。例如:@ java.lang.String@format("foo%s","bar")。
      ●  支持赋值操作和表达式串联,例如: price=100, discount=0.8, calculateP
    rice( ),在方法中进行乘法计算会返回80

      ●  访问OGNL上下文( OGNL context)和 ActionContext。
      ●  操作集合对象。

    1.3 OGNL的要素 

    了解了什么是OGNL及其特点后,接下来,分析一下OGNL的结构。OGNL的操作实际上就是围绕着OGNL结构的三个要素而进行的,分别是表达式( Expression)、根对象( Root Object)、上下文环境( Context),下面分别讲解这三个要素,具体如下。
      1、表达式
      表达式是整个OGNL的核心,OGNL会根据表达式去对象中取值。所有OGNL操作都是针对表达式解析后进行的。它表明了此次OGNL操作要“做什么”。表达式就是一个带有语法含义的字符串,这个字符串规定了操作的类型和操作的内容。OGNL支持大量的表达式语法,不仅支持这种“链”对象访问路径,还支持在表达式中进行简单的计算。
      2、根对象(Root)

      Root对象可以理解为OGNL的操作对象,表达式规定了“做什么”,而Root对象则规定了“对谁操作”。OGNL称为对象图导航语言,所谓对象图,即以任意一个对象为根,通过OGNL可以访问与这个对象关联的其它对象。
      3、 Context对象
      实际上OGNL的取值还需要一个上下文环境。设置了Root对象,OGNL可以对Root对象进行取值或写值等操作,Root对象所在环境就是OGNL的上下文环境( Context)。上下文环境规定了OGNL的操作“在哪里进行”。上下文环境 Context是一个Map类型的对象,在表达式中访问 Context中的对象,需要使用“#”号加上对象名称,即“#对象名称”的形式。

    1.4 OGNL入门

     下面通过一个示例来演示OGNL如何访问对象的方法:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s" %>    
    
    <html>
      <head>
        <title>My JSP 'ognl.jsp' starting page</title>
      </head>
      
      <body>
        <!-- 
        使用struts2+ognl计算字符串长度
        value属性值:ognl表达式
         -->
         <s:property value="'Kevin'.length()" />
      </body>
    </html>

     在上面的测试中,我们调用了字符串的length方法,其中"'Kevin'.length( )"就是OGNL的表达式,最终输出结果为5。

    二、值栈概述

    2.1 什么是值栈

      ValueStack是Struts的一个接口,字面意义为值栈, OgnlValueStack是ValueStack的实现类,客户端发起一个请求 struts2架构会创建一个action实例同时创建一个 OgnlValueStack 值栈实例,OgnlValueStack贯穿整个 Action的生命周期, struts2中使用OGNL将请求 Action的参数封装为对象存储到值栈中,并通过OGNL表达式读取值栈中的对象属性值。

    2.2 值栈的内部结构

      在OgnlValueStack中包括两部分:值栈和map。

    ●  Context:即 OgnlContext上下文,它是一个map结构,上下文中存储了一些引用, parameters、request、 session、 application等,上下文的Root为 Compoundroot。

      Ognlcontext中的一些引用:

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

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

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

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

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

    ●  CompoundRoot:存储了 action实例,它作为 OgnlContext的Root对象

      CompoundRoot继承 ArrayList实现压栈和出栈功能,拥有栈的特点,先进后出,后进先出,最后压进栈的数据在栈顶。我们把它称为对象栈。

      struts2对原OGNL作出的改进就是Root使用 CompoundRooti(自定义栈),使用OgnlValueStack的findValue方法可以在 CompoundRoot中从栈顶向栈底找查找的对象的属性值。

      CompoundRoot作为 OgnlContext的Root对象,并且在 CompoundRoot中action实例位于栈顶,当读取 action的属性值时会先从栈顶对象中找对应的属性,如果找不到则继续找栈中的其它对象,如果找到则停止查找。

    2.3 获取值栈对象

    【通过ActionContext获取值栈对象】:常用方式

    //第一种方式:获取值栈对象,
            ActionContext context=ActionContext.getContext();
            ValueStack stack=context.getValueStack();

     【通过request域获取值栈对象

    //第二种方式:获取值栈对象
            ValueStack stack2=(ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

    2.4 操作值栈

    ●  使用Action中的属性提供的get方法

    ●  调用值栈的push和set方法手动操作值栈

            //调用值栈对象的set方法
            stack.set("setname", "Kevin");
            
            //调用值栈对象的push方法
            stack.push("Brank");

     

    三、从值栈中获取数据

    1. 字符串存取

    【向值栈中存入字符串数据】

    第一步:定义对象变量并生成变量的get方法

        //向值栈中存入字符串数据
        private String username;
        public String getUsername(){
            return username;
        }

    第二步:在执行方法中给变量赋值

        public String execute() throws Exception {
            //给字符串复制
                username="Kevin";    
        
            return SUCCESS;
        }    

    【从值栈中获取字符串数据】

        <!-- 从值栈中获取字符串值 -->
        <h3>获取字符串</h3>
        <s:property value="username"/><br/>

    2. 对象存取

    【向值栈中存入 对象数据】

    第一步:定义对象变量并声称get方法

        //向值栈中存入对象数据
        private User user=new User();
        public User getUser() {
            return user;
        }

    第二步:在执行方法中给对对象赋值

        public String execute() throws Exception {
            
            //给对象赋值
            user.setAddress("China");
            user.setPassword("admin");
            user.setUsername("Kevin");
            
            return SUCCESS;
        }

    【从值栈中获取 对象数据】

    <!-- 从值栈中获取对象 -->
        <h3>获取对象</h3>
        <s:property value="user.username"/>
        <s:property value="user.password"/>
        <s:property value="user.address"/>

    3. List集合存取

    【向值栈中存入 List集合

    第一步:定义集合变量并生成get方法

        //向值栈中存入列表数据
        private List<User> list=new ArrayList<User>();
        public List<User> getList() {
            return list;
        }

    第二步:在执行方法中给list集合赋值

        public String execute() throws Exception {
            
            //在执行方法中给变量赋值
            User user1=new User();
            user1.setAddress("America");
            user1.setPassword("admin");
            user1.setUsername("Kevin");
            
            User user2=new User();
            user2.setAddress("British");
            user2.setPassword("admin");
            user2.setUsername("Brank");
            
            list.add(user1);
            list.add(user2);
            
            return SUCCESS;
        }

    【从值栈中获取 List集合

        <!-- 从值栈中获取列表 -->
        <h3>获取列表第一种方式</h3>
        <s:property value="list[0].username" />
        <s:property value="list[0].password" />
        <s:property value="list[0].address" />
        <br/>
        <s:property value="list[1].username" />
        <s:property value="list[1].password" />
        <s:property value="list[1].address" />
        <br/>
        
        <h3>获取列表第二种方式</h3>
        <!-- 使用struts2标签   类似于jstl的foreach循环
            s:iterator  遍历值栈的list集合
            
            c:foreach items="" var="user"
                ${user.username}
            /foreach    
        -->  
        <s:iterator value="list">
               <!-- 遍历list得到list里面的每个user对象 -->
               <s:property value="username"/>
               <s:property value="password"/>
               <s:property value="address"/>
               <br/>
         </s:iterator>    
         
         <h3>获取列表第三种方式</h3>    
        <s:iterator value="list" var="user">
        <!-- 遍历值栈list集合,得到每个user对象
             机制:把每次遍历出来的user对象放到context里
             获取context里的数据特点:写ognl表达式    
             使用特殊符号#    
        -->
            <s:property value="#user.username"/>  
            <s:property value="#user.password"/> 
            <s:property value="#user.address"/>  
            <br/>         
        </s:iterator>
        
        <h3>使用foreach标签+EL表达式获取list方法设置的值</h3>
        <!-- 使用foreach标签+EL表达式获取值栈list集合数据 -->
        <c:forEach items="${list }" var="user">
            ${user.username }
            ${user.password }
            ${user.address }
        </c:forEach>

     

  • 相关阅读:
    BZOJ 3881: [Coci2015]Divljak
    BZOJ 2434: [Noi2011]阿狸的打字机
    BZOJ 2580: [Usaco2012 Jan]Video Game
    BZOJ 3940: [Usaco2015 Feb]Censoring
    BZOJ 3942: [Usaco2015 Feb]Censoring
    PTA L2-002 链表去重 团体程序设计天梯赛-练习集
    PTA L2-001 紧急救援-最短路(Dijkstra)多条最短路找最优解并输出路径 团体程序设计天梯赛-练习集
    PTA L1-020 帅到没朋友 团体程序设计天梯赛-练习集
    Codeforces 429 B. Working out-dp( Codeforces Round #245 (Div. 1))
    HDU 6467.简单数学题-数学题 (“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛)
  • 原文地址:https://www.cnblogs.com/Kevin-ZhangCG/p/9023509.html
Copyright © 2011-2022 走看看