• Struts2第三天:Struts2的值栈和OGNL表达式


    目录

    1.OGNL

    1.1OGNL概述

    1.1.1什么是OCNL

    1.1.2为什么学习OGNL

    1.1.3OGNL使用的要素

    1.2OGNL的Java环境入门(了解)

    1.2.1访问对象的方法

    1.2.2访问对象的静态方法

    1.2.3获得root中的数据

    1.2.4获得OgnlContext中的数据

    1.3OGNL的Struts2环境入门

    1.3.1访问对象的方法

    1.3.2访问对象的静态方法

    2.值栈

    2.1值栈的概述

    2.1.1什么是值栈

    2.1.2值栈的内部结构

    2.1.3值栈与ActionContext的关系

    2.1.4获得值栈对象

    2.1.5操作值栈

    2.1.6获得值栈数据

    2.1.7EL为何能访问值栈数据

    3OGNL中的特殊字符

    3.1#号

    3.2%号

    3.3$符号


     

    1.OGNL

    1.1OGNL概述

    1.1.1什么是OCNL

    OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。

    OGNL:对象图导航语言,比EL表达式强大很多倍的语言。El从域对象中获取数据,OGNL调用对象的方法获取Struts2值栈的数据。OGNl其实是第三方的表达式语言。

     

    1.1.2为什么学习OGNL

    1. OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言,使页面更简洁;
    2. 支持运算符(如+-*/),比普通的标志具有更高的自由度和更强的功能;
    3. Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:
    4. 支持对象方法调用,如xxx.doSomeSpecial();
    5. 支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;
    6. 支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(price*discount),这个表达式会返回80;
    7. 访问OGNL上下文(OGNL context)和ActionContext;
    8. 操作集合对象。
    9. 可以直接new一个对象。

     

    1.1.3OGNL使用的要素

    1.表达式

    2.根对象

    3.Context对象

     

    1.2OGNL的Java环境入门(了解)

    1.2.1访问对象的方法

    /**  
    
    
    
    * @Title: Ognl01.java
    
    
    
    * @Package top.yangxianyang.struts2.ognl
    
    
    
    * @Description: TODO(ognl入门)
    
    
    
    * @author A18ccms A18ccms_gmail_com  
    
    
    
    * @date 2018年11月29日 下午3:01:43
    
    
    
    * @version V1.0  
    
    
    
    */
    
    
    
    package top.yangxianyang.struts2.ognl;
    
    
    
    import org.junit.Test;
    
    
    
    import ognl.Ognl;
    
    import ognl.OgnlContext;
    
    import ognl.OgnlException;
    
    
    
    /**  
    
    *   
    
    * 项目名称:Strutsday03  
    
    * 类名称:Ognl01  
    
    * 类描述:ognl入门  
    
    * 创建人:yangyangyang  
    
    * 创建时间:2018年11月29日 下午3:01:43  
    
    * 修改人:yangyangyang  
    
    * 修改时间:2018年11月29日 下午3:01:43  
    
    * 修改备注:  
    
    * @version   
    
    *   
    
    */
    
    
    
    public class Ognl01 {
    
          @Test
    
         /*
    
          * OGNL调用对象方法
    
          */
    
          public void demo1() throws OgnlException {
    
               //获得Context
    
               OgnlContext context =new OgnlContext();
    
               //获得对象
    
               Object root=context.getRoot();
    
               //执行表达式
    
               Object b=Ognl.getValue("'helloword'.length()", context, root);
    
            System.out.println(b);
    
          }
    
    }

    1.2.2访问对象的静态方法

    @Test
    
        /*
    
         * OGNL调用静态方法
    
         */
    
          public void demo2() throws OgnlException {
    
               //获得Context
    
               OgnlContext context =new OgnlContext();
    
               //获得对象
    
               Object root=context.getRoot();
    
               //执行表达式 :@类名@方法名
    
               Object b=Ognl.getValue("@java.lang.Math@random()", context, root);
    
            System.out.println(b);
    
          }

    1.2.3获得root中的数据

    @Test
    
        /*
    
         * 获得Root中的数据,不需要加#
    
         */
    
          public void demo3() throws OgnlException {
    
               //获得Context
    
               OgnlContext context =new OgnlContext();
    
               //获得对象
    
               User u=new User("ccc","123");
    
               context.setRoot(u);
    
               Object root=context.getRoot();
    
               //执行表达式
    
               String b=(String) Ognl.getValue("username", context, root);
    
            System.out.println(b);
    
          }

     

     

    1.2.4获得OgnlContext中的数据

    @Test
    
        /*
    
         * 获得Root中的数据,需要加#
    
         */
    
          public void demo4() throws OgnlException {
    
               //获得Context
    
               OgnlContext context =new OgnlContext();
    
               //获得对象
    
               Object root=context.getRoot();
    
               //向Context中存入数据
    
               context.put("name", "数据的神色");
    
               //执行表达式
    
               String b=(String) Ognl.getValue("#name", context, root);
    
            System.out.println(b);
    
          }

    1.3OGNL的Struts2环境入门

    1.3.1访问对象的方法

    <h1>OGNL在Struts2环境中的入门</h1>
    
    <h3>调用对象方法</h3>
    
    <s:property value="'struts'.length()"/>

     

    1.3.2访问对象的静态方法

    先开启支持:

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

     

    页面编写:

    <h3>调用静态对象方法</h3>
    
    <s:property value="@java.lang.Math@random()"/>

     

    2.值栈

    2.1值栈的概述

    2.1.1什么是值栈

    Struts2将XWork对Ognl的扩展这一套机制封装起来,这个对象叫ValueStack。

    ValueStack实际上就是一个容器。它由Struts框架创建,当前端页面如jsp发送一个请求时,Struts的默认拦截器会将请求中的数据进行封装,并入ValueStack的栈顶。

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

     

    2.1.2值栈的内部结构

    ValueStack中有两个主要的区域:

    1. Root区域:主要是一个ArrayList,里面一般放置对象,获得root中的数据不需要加#。

     

    1. Context区域:主要是一个Map,里面放置的是web开发常用的对象数据引用。获取context中的数据需要加#。
        1. Request
        2. Session
        3. Application
        4. Parameters
        5. attr

    操作栈主要指的是操作ValueStack中的root区域。

     

     

    2.1.3值栈与ActionContext的关系

    • ServletContext:Servlet的上下文。
    • ActionContext:Action的上下文。
    • 通过源码查看到:当请求过来的时候,执行过滤器中的doFilter方法,在这个方法中创建ActionContext,在创建ActionContext的过程中,创建ValueStack对象,将ValueStack对象传递给ActionContext对象,所以可以通过ActionContext对象获取ValueStack对象。
    • ActionContext对象之所以能够访问Servlet的API(访问的是对象的引用),就是因为其内部有值栈的引用。

     

    2.1.4获得值栈对象

    public class ValueStackDemo2 extends ActionSupport {
    
          @Override
    
          public String execute() throws Exception {
    
               // 第一种,通过ActionContext获得
    
               ValueStack vs1 = ActionContext.getContext().getValueStack();
    
    
    
               // 第二种 通过request对象获取
    
               ValueStack vs2 = (ValueStack) ServletActionContext.getRequest()
    
                          .getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
    
               System.out.println(vs1 == vs2);
    
               return NONE;
    
          }
    
    }
    
    

    2.1.5操作值栈

    Action编写:

    /**  
    
    
    
    * @Title: ValueStackDemo3.java
    
    
    
    * @Package top.yangxianyang.struts2.ValueStack
    
    
    
    * @Description: TODO(用一句话描述该文件做什么)
    
    
    
    * @author A18ccms A18ccms_gmail_com  
    
    
    
    * @date 2018年11月30日 下午2:47:15
    
    
    
    * @version V1.0  
    
    
    
    */
    
    
    
    package top.yangxianyang.struts2.ValueStack;
    
    
    
    import com.opensymphony.xwork2.ActionContext;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    import com.opensymphony.xwork2.util.ValueStack;
    
    
    
    import top.yangxianyang.struts2.entity.User;
    
    
    
    /**  
    
    *   
    
    * 项目名称:Strutsday03  
    
    * 类名称:ValueStackDemo3  
    
    * 类描述:  操作ValueStack
    
    * 创建人:yangyangyang  
    
    * 创建时间:2018年11月30日 下午2:47:15  
    
    * 修改人:yangyangyang  
    
    * 修改时间:2018年11月30日 下午2:47:15  
    
    * 修改备注:  
    
    * @version   
    
    *   
    
    */
    
    
    
    public class ValueStackDemo3 extends ActionSupport{
    
          private User user;
    
    //   
    
    //    public User getUser() {
    
    //         return user;
    
    //    }
    
    
    
    
    
          @Override
    
          public String execute() throws Exception {
    
               //第一种:在Action中提供属性的get方法
    
               //user=new User("王五","123456");
    
               //第二种,向值栈中保存数据
    
               //获取值栈对象
    
               ValueStack vs=ActionContext.getContext().getValueStack();
    
               //使用push(Object obj);set(String key,Object obj)
    
               user=new User("张丽","123456忐忑");
    
               //现在user在栈顶
    
               vs.push(user);
    
               //创建一个Map集合,将map压入栈顶
    
               vs.set("name", "张家辉");
    
               return SUCCESS;
    
          }
    
    }

    页面编写:

    <body>
    
    <s:debug></s:debug> 
    
    <h3>第一种</h3>
    
    <s:property value="user.username"/> 
    
    <s:property value="user.password"/>
    
    <h3>第二种</h3>
    
    <s:property value="username"/>
    
    <s:property value="password"/>
    
    <s:property value="name"/>
    
    </body>

    2.1.6获得值栈数据

    获取值栈中的数据在页面中使用OGNL表达式即可:

    Action页面

    public class ValueStackDemo4 extends ActionSupport {
    
          @Override
    
          public String execute() throws Exception {
    
              
    
               //获取值栈对象
    
               ValueStack vs=ActionContext.getContext().getValueStack();
    
               //向值栈中保存数据
    
               User user=new User("aaa张丽","123456忐忑");
    
               vs.push(user);
    
              
    
               //向值栈中保存集合
    
               List<User> users =new ArrayList<User>();
    
               users.add(new User("啊啊啊","34esw"));
    
               users.add(new User("哈哈哈","3s4ew"));
    
               users.add(new User("呵呵呵","34esw"));
    
               users.add(new User("嘿嘿","34sdew"));
    
               users.add(new User("悠悠","34dew"));
    
               vs.set("list", users);
    
              
    
              
    
               //向context中存入数据
    
               ServletActionContext.getRequest().setAttribute("name", "嘿嘿嘿嘿嘿嘿");
    
               ServletActionContext.getRequest().getSession().setAttribute("name", "呀呀呀呀呀呀呀呀呀呀呀");
    
               ServletActionContext.getServletContext().setAttribute("name", "youyouiiouuuuuuu");
    
               return SUCCESS;
    
          }
    
    }
    
    

    Jsp页面

    
    <body>
    
    <!-- 获取一个对象的数据 -->
    
    <s:property value="username"/>
    
    <s:property value="password"/>
    
    <br/>
    
    <!-- 获取集合中的数据 -->
    
    <s:property value="list[0].username"/>
    
    <s:property value="list[0].password"/>
    
    <br/>
    
    <s:property value="list[1].username"/>
    
    <s:property value="list[1].password"/>
    
    <br/>
    
    <s:property value="list[2].username"/>
    
    <s:property value="list[2].password"/>
    
    <br/>
    
    <!-- 获取Context中的数据 -->
    
    <s:property value="#request.name"/>
    
    <br/>
    
    <s:property value="#session.name"/>
    
    <br/>
    
    <s:property value="#application.name"/>
    
    <br/>
    
    <s:property value="#parameters.id"/>
    
    <br/>
    
    </body>

    2.1.7EL为何能访问值栈数据

    因为Struts2的框架的底层对request.getAttribute(String name)进行了增强。

     

     

    3OGNL中的特殊字符

    3.1#号

    <body>
    
    <h1>#号的用法</h1>
    
    <h3>获取Context的数据</h3>
    
    <%
    
         request.setAttribute("name", "杨吖颖");
    
    %>
    
    <s:property value="#request.name"/>
    
    <h3>构建Map集合</h3>
    
    <s:iterator var="i" value="{'aaa','bbb','ccc'}">
    
       <s:property value="i"/>--<s:property value="#i"/><br/>
    
    </s:iterator>
    
    
    
    <s:iterator var="m"  value="#{'aaa':'1111','bbb':'222','ccc':'333'}">
    
       <s:property value="key"/>--<s:property value="value"/><br/>
    
       <s:property value="#m.key"/>--<s:property value="#m.value"/><br/>
    
    </s:iterator>
    
    <hr/>
    
    <s:radio list="{'男','女'}" name="sex" label="性别"></s:radio>
    
    </body>
    
    

    3.2%号

    强制解析OGNL

    <body>
    
    <h3>%号的用法</h3>
    
    <s:property value="#request.name"/>
    
    姓名:<s:textfield name="name" value="%{#request.name}"></s:textfield>
    
    </body>

     

    3.3$符号

    在配置文件中使用OGNL

     

    源码:链接: https://pan.baidu.com/s/1q_nkDYAxPQRwAWBG1yg2Sg 提取码: g5xd 复制这段内容后打开百度网盘手机App,操作更方便哦

     

     

  • 相关阅读:
    修改maven远程仓库为阿里的maven仓库(复制)
    Vue下iframe如何实现和父窗口的通信
    Vue在子组件内如何触发父组件的方法
    PhpStorm环境设置Debug
    史上最全的Excel数据编辑处理技巧(转)
    按钮样式
    字符和数字对齐的字体
    使用jquery控制只能输入数字,并且关闭输入法(转)
    Javascript中字符串转换成Date的方法
    MongoDB工具MagicMongoDBTool
  • 原文地址:https://www.cnblogs.com/yangxianyang/p/13675647.html
Copyright © 2020-2023  润新知