• struts2的OGNL


    ONGL简介:

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

      OGNL的要素

        表达式:表达式是整个OGNL的核心,OGNL会根据表达式去对象中取值,所有的OGNL操作都是指对表达式解析后进行的。它表明了此次OGNL操作要做什么。表达式就是一个带有语法含义的字符串,这个字符串规定了操作的类型和操作的内容。OGNL支持大量的表达式语法,不仅支持这种“链式”对象访问路径,还支持在表达式中进行简单的计算。

        根对象(ROOT):Root对象可以理解为OGNL的操作对象,表达式规定了“做什么”,而Root对象则规定了“对谁操作"。OGNL称为对象图导航语言,所谓对象图,就是以任意对象为根,通过OGNL可以访问这个对象关联的其他。

        Context对象:实际上OGNL的取值还需一个上下文环境,设置了Root对象,OGNL可以对root对象进行取值或者写值等操作,root对象所在环境就是OGNL的上下文环境(Context)。上下文环境规定了OGNL的操作”在哪里进行“。上下文环境COntext是一个map类型的对象,在表达式中访问Context中的对象,需要使用”#”号加上对象名称,即“#对象名称”的形式。

      OGNL的取值与赋值方法

    1 /**
     2  * 用于OGNL表达计算的一个工具类
     3  * 
     4  */
     5 public class OnglExpression {
     6     private OnglExpression() {
     7     }
     8 
     9     /**
    10      * 根据OGNL表达式进行取值操作
    11      * 
    12      * @param expression
    13      *            ognl表达式
    14      * @param ctx
    15      *            ognl上下文      map
    16      * @param rootObject
    17      *            ognl根对象
    18      * @return
    19      */
    20     public static Object getValue(String expression, OgnlContext ctx,
    21             Object rootObject) {
    22 //            ${book.c.name} 意味着你要在jsp上获取书籍的类别的名称  ctx.get(#name)  根对象取值
    23 //            ctx.get(${book.c.name})   非根对象取值
    24         try {
    25             return Ognl.getValue(expression, ctx, rootObject);
    26         } catch (OgnlException e) {
    27             throw new RuntimeException(e);
    28         }
    29     }
    30 
    31     /**
    32      * 根据OGNL表达式进行赋值操作
    33      * 
    34      * @param expression
    35      *            ognl表达式
    36      * @param ctx
    37      *            ognl上下文
    38      * @param rootObject
    39      *            ognl根对象
    40      * @param value
    41      *            值对象
    42      */
    43     public static void setValue(String expression, OgnlContext ctx,
    44             Object rootObject, Object value) {
    45         try {
    46             Ognl.setValue(expression, ctx, rootObject, value);
    47         } catch (OgnlException e) {
    48             throw new RuntimeException(e);
    49         }
    50     }
    51 }

      EL表达式和OGNL的区别:

    OGNL表达式只对struts标签管用,在HTML标签中还是要使用EL表达式
    struts2标签中都是用的OGNL表达式,先从栈顶找,找不到就从map域中找,再找不到直接报错
    而常规EL表达式只能从map域中找,不能在栈顶找,找不到什么都不显示。
    搜索顺序为:page>request>session>application
    但是struts2对HttpRequest对象进行了封装StrutsRequestWrapper,此时EL表达式可以在栈顶搜索
    搜索顺序为:page>request>ValueStack>session>application

      OGNL的取值与赋值案列

     1 public class Demo1 {
     2 
     3     /**
     4      * @param args
     5      * @throws OgnlException
     6      */
     7     public static void main(String[] args)  {
     8 //        叫小李的员工
     9         Employee e = new Employee();
    10         e.setName("小李");
    11 //         张经理的管理
    12         Manager m = new Manager();
    13         m.setName("张经理");
    14 
    15         // 创建OGNL下文,而OGNL上下文实际上就是一个Map对象
    16         OgnlContext ctx = new OgnlContext();
    17 
    18         // 将员工和经理放到OGNL上下文当中去
    19         ctx.put("employee", e);
    20         ctx.put("manager", m);
    21 //        小李是根对象   一个公司有很多老板   只有一个员工小李
    22         ctx.setRoot(e);// 设置OGNL上下文的根对象  
    23 
    24         /** ********************** 取值操作 *************************** */
    25         // 表达式name将执行e.getName(),因为e对象是根对象(请注意根对象和非根对象表达式的区别)
    26         String employeeName = (String) OnglExpression.getValue("name", ctx, e);
    27         System.out.println(employeeName); //小李
    28 
    29         // 表达式#manager.name将执行m.getName(),注意:如果访问的不是根对象那么必须在前面加上一个名称空间,例如:#manager.name
    30         String managerName = (String) OnglExpression.getValue("#manager.name",
    31                 ctx, e);
    32         System.out.println(managerName);  //张经理
    33 
    34         // 当然根对象也可以使用#employee.name表达式进行访问
    35         employeeName = (String) OnglExpression.getValue("#employee.name", ctx,
    36                 e);
    37         System.out.println(employeeName);  //小李
    38 
    39         /** ********************** 赋值操作 *************************** */
    40         OnglExpression.setValue("name", ctx, e, "小明");
    41         employeeName = (String) OnglExpression.getValue("name", ctx, e);
    42         System.out.println(employeeName);  //小明
    43 
    44         OnglExpression.setValue("#manager.name", ctx, e, "孙经理");
    45         managerName = (String) OnglExpression.getValue("#manager.name", ctx, e);
    46         System.out.println(managerName);  //孙经理
    47 
    48         OnglExpression.setValue("#employee.name", ctx, e, "小芳");
    49         employeeName = (String) OnglExpression.getValue("name", ctx, e);
    50         System.out.println(employeeName);  //小芳
    51     }
    52 }

    输出结果:

    OGNL在struts2中的应用

        public String test1() {
    //        ValueStack是一个堆栈结构的容器  有压栈操作   先进后出
            ValueStack vs = ServletActionContext.getContext().getValueStack();
            vs.push(new Employee("张雇员", 2000));// 1
            vs.push(new Student("小明同学", "s001"));// 0
            System.out.println(vs.findValue("name"));  //小明
            System.out.println(vs.findValue("salary"));  //2000
            return "rs";
        }

    配置文件设置:

    <action name="/stack_*" class="com.liuwenwu.test.DemoAction" method="{1}">
                <result name="rs">/rs.jsp</result>
            </action>
    

      jsp代码:

    <a href="${pageContext.request.contextPath }/sy/stack_test1.action?sex=nv">ognl1</a>
    

      输出结果:

    证明ValueStack是一个堆栈结构的容器  有压栈操作   先进后出

    valueStack的赋值套路

        private Cal cal1=new Cal();
    
        private String num1;
    
        public String getNum1() {
            return num1;
        }
    
        public void setNum1(String num1) {
            this.num1 = num1;
        }
    
        public String accept1() {
    //        cal使用的是ModelDriven赋值
            System.out.println("cal1:"+cal1);
    //        num使用的是get/set赋值
            System.out.println("num1:"+num1);
    
            return "rs";    
        }

    jsp代码:

    <a href="${pageContext.request.contextPath }/sy/demo_accept1.action?num1=20&&num2=5">accept1</a>
    

      输出结果:

    cal1有值而num1没值  cal1通过ModelDriven接口赋值 num1通过get/set方法赋值  最终压栈的结构 num1在下  cal1在上  所以赋值在cal1上 不会赋值到底部的num1上 所以num1为 null

  • 相关阅读:
    Javascript獲取濟覽器高屏幕寬高
    引用CSS的問題
    轮胎尺寸周长一览表
    C# 配置文件
    C# 正则表达式替换分组内的内容
    按钮的背景图
    WPF 设置全屏
    窗体内嵌外部程序的显示,获取控件的图片
    将图像转换成一个图标
    resharper 6.0 注册码
  • 原文地址:https://www.cnblogs.com/xiatian3452/p/11245516.html
Copyright © 2020-2023  润新知