ognl和值栈

前言:

 值栈的解析:
    前面学到取web作用域对象:request,session,servletcontext,然后通过setAttribute()和getAttribute()存入或取出作用域中的数据。
    那Struts2也提供了一套可以存放数据的地方:值栈,我们可以将数据存放在值栈上进行使用。ognl是针对值栈做些操作。

一、 ognl

1.ognl概述


    在web阶段学过el表达式,用于jsp中获取域对象里面的值。
    ognl也是一种表达式,功能强大。
    (1)在struts2里面操作值栈数据  ValueStack
    (2)一般把ognl在struts2操作,和struts标签一起操作值栈。

    ognl不是struts2的一部分,单独的项目,只是和struts2一起使用。
    (1)使用ognl时,先导jar包:ognl-3.0.6.jar
    
    入门案例:
    
    a. 引入struts2的标签库:和jsp中引用jstl差不多
        <%@ taglib uri = "/struts-tags" prefix="s" %>
    b. 使用struts2的标签
        ognl与struts2中的<property>标签配合使用。
        <s:property value="'haha'.length()" />    //可以调方法,测试'haha'的长度

    

2.OGNL的#、%的使用:

    1. #使用
    使用#来获取context里面的数据
    <s:property value="#request.req" />
    //格式:#context的key名称.域对象名称

    2. %使用
    在struts2标签中表单标签
    (1)在struts2标签里使用ognl表达式,如果直接在struts2表单标签里面使用ognl表达式不识别,要加%

    <s:textfield name="username" value="#request.req"></s:textfield>
    运行后可以看它的源代码:即多了个<tr></tr>
    value="#request.req"这样写,它不认识#request.req这种ognl表达式的写法,只有加上%才能识别
    <s:textfield name="username" value="%{#request.req}"></s:textfield>

    ----------------------------------------------------------

二、值栈 ValueStack


    2.1.值栈是干什么的?
    存数据的,用在struts2里
    相当于servlet中的域对象(page,request,session,application)

   2. 2. servlet和action的区别(面试题):
    servlet:单对象(单例模式)
    默认在第一次访问时创建,创建一次;(生命周期)--------单实例对象

    action:多实例对象
    访问时创建,每次访问action时,都会创建action对象,每次访问都是不同对象。-------多实例对象
    可通过构造方法输出测试。


   2. 3.值栈存储位置:(每个对象中)
    (1)每次访问action时,都会创建action对象
    (2)在每个action对象里面都会有一个值栈对象。(也就是说实例化一个action对象,就会配一个值栈,没有第二个哦)


    2.4.获取值栈对象
    
    有多种方式获取,其中常用就两种:
    第一种:使用ActionContext类中的方法获得值栈对象。

    public class OneAction extends ActionSupport{

        public String execute(){

            ActionContext ac = ActionContext.getContext();
            ValueStack stack1 = ac.getValueStack();    //获得值栈    Stack值栈

            //可以验证一个action对象中只有一个值栈
            ValueStack stack2 = ac.getValueStack();

            System.out.println(stack1 == stack2);

            return "success";
        }
    }

    2.5.值栈内部结构
        栈的特点:先进后出
        将后来的数据压在前来的数据上叫:压栈
        栈最上面的叫:栈顶


    内部结构分两部分:
    第一部分:root,结构是list集合
        一般都是操作root结构。

    第二部分:context,结构是map集合

    ******************************
    通过debug方式可以查看内部结构:
        context        OgnlContext(id = xx)  --- 没源代码,但上面写了implement Map
        root        CompoundRoot(id = xx)  --- 查看这个CompoundRoot类源代码(ctrl+shift+t)
        oqnlUtil
        overrides
        ……
    ******************************
    
    画图解析context存储的对象引用(不是真正的对象,只是对象的引用):
        key        value
    --------------------------------------------------------
        request        request对象的引用
        session        HttpSession对象引用
        application    ServletContext对象引用
        parameters    传递相关的参数
        attr        这里一个操作----------------》三个域对象,向三个域对象放值,名称都相同:setAttribute("name",value);,使用attr操作时获取域对象里的值,获取最小域对象里的值。

    2.6.向值栈放数据

    (1)<s:debug>标签用于查看值栈,用于测试。
        访问action,执行action的方法返回值,配置返回值到jsp页面中,在jsp页面中使用这个标签。

        查看结果:上面是root ,下面是context
        主要看root会发现:
            Object项里放着action类,这和前面讲的action对象中有值栈,值栈中难道又放了action对象?错,这里放的是对象的引用,并非真正的对象
    

    (2)如何向值栈中放数据
        有多种方式:主要讲三种,第三种最常用。

        第一种:获取值栈对象  getValueStack();
            调用值栈对象里面的 set()方法。
    
        public String execute() throws Exception{
            //1.获取值栈对象
            ActionContext ac = ActionContext.getContext();
            ValueStack stack = ac.getValueStack();
            
            //2.调用值栈对象的set方法
            stack.set("username", "administrator");

            return "success";
        }

    
            
        第二种:获取值栈对象,调用值栈对象里的 push()方法
        public String execute() throws Exception{
            //1.获取值栈对象
            ActionContext ac = ActionContext.getContext();
            ValueStack stack = ac.getValueStack();
            
            //2.调用值栈对象的set方法
            stack.set("username", "administrator");

            //3.push方法
            stack.push("abcd");    //栈顶

            return "success";
        }
        


        第三种:在action定义变量,生成变量的get()方法
        //1.定义变量
        private String name;
        //2.生成变量的get方法
        public String getName(){
            return name;
        }

        public String execute() throws Exception{
            //3.向变量设置值
            name = "abcd";
            return "success";
        }
        

        案例:向值栈中放对象
              向值栈中放list集合
        ---------------------------------------------
        //1.定义对象
        private User user = new User();
        //2.生成get方法
        public User getUser(){
            return user;
        }

        public String execute() throws Exception{
            //3.向值栈中放数据
            user.setUserName("admin");
            user.setPassWord("123456");
        
            return "success";
        }
        ---------------------------------------------
        //1.定义list集合
        private List<User> list = new ArrayList<User>();
        //2.生成get方法
        public List<User> getList(){
            return list;
        }

        public String execute() throws Exception{
            //3.向值栈中放数据
            //生成两个用户对象放入集合
            User user1 = new User();
            user1.setUserName("admin1");
            user1.setPassWord("1234");

            User user2 = new User();
            user2.setUserName("admin2");
            user2.setPassWord("1234");

            list.add(user1);
            list.add(user2);
        
            return "success";
        }


    


   2. 7.从值栈中获取

        7.1 使用struts2的标签+ognl表达式获取值栈数据
            <s:property value="ognl表达式" />        

        (1)取字符串
        ------------------------------------------------
        //1.定义变量
        private String name;
        //2.生成变量的get方法
        public String getName(){
            return name;
        }

        public String execute() throws Exception{
            //3.向变量设置值
            name = "abcd";
            return NONE;
        }
        --------------------------------------------------
        <s:property value="name" />    //获取值栈中字符串name的值


    
        (2)取对象
        ------------------------------------------------
        //1.定义对象
        private User user = new User();
        //2.生成对象的get方法
        public User getUser(){
            return user;
        }

        public String execute() throws Exception{
            //3.向对象设置值
            user.setName("admin");
            user.setAge(18);
            return NONE;
        }
        --------------------------------------------------
        <s:property value="user.name" />    //获取值栈中user对象name属性的值
        <s:property value="user.age" />


        (3)取list集合
        有多种方式获取值栈中的list集合。
        第一种:
            <s:property value="list[0].name" />
            <s:property value="list[0].age" />

            <s:property value="list[1].name" />
            <s:property value="list[1].age" />
            缺点:写死了


        第二种:使用struts2标签,类似jstl中的<c:foreach>标签
            <s:iterator value="list">    //相当于遍历list集合中的一个对象
                <s:property value="name" />
                <s:property value="age" />
            </s:iterator>

            
        第三种:使用较多,稍复杂(推荐)
            <s:iterator value="list" var="user">
                //遍历值栈list集合,得到每个user对象
                //底层实现机制:把每次遍历出来的user对象放到context里面。
                //获取 context里面数据特点:写ognl表达式,使用#
                <s:property value="#user.name" />
                <s:property value="#user.age" />
            </s:iterator>

    值栈    root    
        context    

        注意:<!--   -->不能注释<s:>标签。


   2. 8.获得set方法设置的值:根据名称获取值
        <s:property value="username" />

      获得push方法设置的值:
        push没有名称,只有设置的值,怎么取?
        向值栈放数据,把向值栈放数据存到数组里面,数组名称为top

        <s:property value="[0].top" />    //[0]表示数组中的第一个值,也就是栈顶的值


  2. 9.el表达式也能获取值栈数据
      使用<s:foreach>+el表达式也能取到值栈的数据。
    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

银色亡灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值