小白学OGNL

1. OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言
2.它是一种强大的表达式语言,让你通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。

1. OGNL表达式 (对象图导航语言)
OGNL是Object-Graph Navigation Language的缩写,翻译过来就是 对象视图导航语言 ,
它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以实现:

可以存取对象的任意属性,
可以调用对象的方法,
遍历整个对象的结构图,
实现字段类型转化等功能。
它使用相同的表达式去存取对象的属性。
EL(Expression Language) 是为了使JSP写起来更加简单。

表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法,让Jsp的代码更加简化。

EL表达式只能进行读取数据,
而OGNL不仅可以读取数据,更重要是是可以写入数据(赋值)、调用方法 (对象的一般方法、静态方法等);

OGNL表达式代码是由两部分组成的,分别是roo区域t和contextMap区域 ,root是对象栈,context是map值栈,这两个栈合并使用才算是一个完整的OGNL表达式,如下图所示:

2.案例

1.下面创建一个类
表达一下根对象和非根对象取值的特点和OGNL取值赋值。

注意:OGNL并不是struts本身的组件,是一个独立的技术。
struts2框架中使用的表达式并不是EL表达式,不是不能用,而是struts2有自己的一套御用的表达式,名字就叫OGNL表达式,这是struts直接把ognl直接拿过来用了,但并不是struts本身的。

下面通过实例代码在java代码中看如何从root区获取数据
要在Myeclipse中建立一个java project 并且建一个lib的文件夹导入ognl 的jar包。å¨è¿éæå¥å¾çæè¿°

主要实例如下:

其中person实体类有:

public class Person {
    private String name;
    private Integer age;
    private String sex;
    private String mobile;
    
    private Address address;
    private List<String> favorites;
    private Map<String,Integer> scores;

getter 和setter方法,构造方法省略

Address实体类有:

public class Address {
    private String street;
    private String zipCode;
getter 和setter方法,构造方法省略


测试类如下:

import com.macw.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ognl.Ognl;
import ognl.OgnlException;

import com.macw.entity.Address;
import com.macw.entity.Person;

public class TestOgnl1 {
    public static void main(String[] args) throws OgnlException {
        //通过ongl从root区(对象)中获取属性值
        Address address = new Address("丰乐路博颂路","450000");
        Person p = new Person("xushy",18,"男","18530031576",address);
        
        //获取name属性
        p.getName();
        //获取street子属性
        p.getAddress().getStreet();
        
        //获取root区的属性
        System.out.println(Ognl.getValue("name", p));
        //获取root区对象的属性的子属性
        System.out.println(Ognl.getValue("address.street", p));
        
        List<String> favorites = new ArrayList<String>();
        Collections.addAll(favorites, "唱","跳","rap","篮球");
        
        p.setFavorites(favorites);
        //获取p对象的List集合属性的某一个元素
        System.out.println(Ognl.getValue("favorites[0]", p));
        
        Map<String,Integer> scores = new HashMap<String,Integer>();
        scores.put("语文", 100);
        scores.put("数学",60);
        scores.put("英语", 85);
        
        p.setScores(scores);
        
        //获取Map属性的键值对数据
        System.out.println(Ognl.getValue("scores[\"语文\"]", p));
        System.out.println(Ognl.getValue("scores['语文']", p));
        
        //Ognl的运算
        /*
         * 数学运算 + - * / %
         * 比较运算 > >= < <= == != 
         * 逻辑运算 && || !
         * 三目运算符:         ? :
         */
        
        System.out.println(Ognl.getValue("age > 16", p));
        System.out.println(Ognl.getValue("age + 16", p));
        System.out.println(Ognl.getValue("age >= 18 ? '青年':'少年'", p));
        
        //Ognl表达式调用方法
        System.out.println(Ognl.getValue("name.toUpperCase()",p));
        System.out.println(Ognl.getValue("name.length()", p));
        
        System.out.println(Ognl.getValue("favorites.size()", p));
        
        System.out.println(Ognl.getValue("name.charAt(0)", p));
    }
}


从中可以看到,ognl表达式获取数据语法为:


1    Ognl.getValue("属性名", 对象)
2,从从contextMap中获取数据
实体类还和上面的一样,用person对象和address对象

public class TestOgnl2 {
    public static void main(String[] args) throws OgnlException {
        //contextMap区  map集合
        Address address = new Address("河南农业大学","450000");
        Person p = new Person("macw",18,"男","13598051718",address);
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("p", p);
        
        System.out.println(Ognl.getValue("#p", map, new Object()));
        System.out.println(Ognl.getValue("#p.name", map,new Object()));
        System.out.println(Ognl.getValue("#p.address.zipCode", map,new Object()));
        
        List<String> favorites = new ArrayList<String>();
        Collections.addAll(favorites, "唱","跳","rap","篮球");
        
        p.setFavorites(favorites);
        System.out.println(Ognl.getValue("#p.favorites[0]", map,new Object()));
        Map<String,Integer> scores = new HashMap<String,Integer>();
        scores.put("语文", 100);
        scores.put("数学",60);
        scores.put("英语", 85);
        p.setScores(scores);
        System.out.println(Ognl.getValue("#p.scores['英语']", map,new Object()));
    }
}


获取ContextMap中的数据:

Ognl.getValue("#对象名", map,new Object()
1
1.到contextmap区域获取ognl表达式的语法需要以#为前缀。
2.#后面跟map里面的key。
3.Key后面跟root区域取数据的语法是一模一样的。
 

package com.yinyi.test;

import ognl.OgnlContext;
import ognl.OgnlException;

public class Demo1 {

    /**
     * @param args
     * @throws OgnlException
     */
    public static void main(String[] args)  {
        //叫小李的员工
        Employee e = new Employee();
        e.setName("小李");
        
        //
        Manager m = new Manager();
        m.setName("张经理");

        // 创建OGNL下文,而OGNL上下文实际上就是一个Map对象
        OgnlContext ctx = new OgnlContext();

        // 将员工和经理放到OGNL上下文当中去
        ctx.put("employee", e);
        ctx.put("manager", m);
        
        
//        一个公司有很多的老板,只有一个员工叫小李
        ctx.setRoot(e);// 设置OGNL上下文的根对象

        /** ********************** 取值操作 *************************** */
        // 表达式name将执行e.getName(),因为e对象是根对象(请注意根对象和非根对象表达式的区别)
        String employeeName = (String) OnglExpression.getValue("name", ctx, e);
        System.out.println(employeeName);//小李

        // 表达式#manager.name将执行m.getName(),注意:如果访问的不是根对象那么必须在前面加上一个名称空间,例如:#manager.name
        String managerName = (String) OnglExpression.getValue("#manager.name",
                ctx, e);
        System.out.println(managerName);//张经理

        // 当然根对象也可以使用#employee.name表达式进行访问
        employeeName = (String) OnglExpression.getValue("#employee.name", ctx,
                e);
        System.out.println(employeeName);//

        /** ********************** 赋值操作 *************************** */
        OnglExpression.setValue("name", ctx, e, "小明");
        employeeName = (String) OnglExpression.getValue("name", ctx, e);
        System.out.println(employeeName);//小明

        OnglExpression.setValue("#manager.name", ctx, e, "孙经理");
        managerName = (String) OnglExpression.getValue("#manager.name", ctx, e);
        System.out.println(managerName);//孙经理

        OnglExpression.setValue("#employee.name", ctx, e, "小芳");
        employeeName = (String) OnglExpression.getValue("name", ctx, e);
        System.out.println(employeeName);//小芳
    }

}

 

jsp页面

 


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>动态方法调用</h3>
<a href="${pageContext.request.contextPath }/sy/demo_add.action">新增</a>
<a href="${pageContext.request.contextPath }/sy/demo_del.action">删除</a>

<h3>后台接收jsp传递参数的三种方式</h3>
<a href="${pageContext.request.contextPath }/sy/demo_accept1.action?num1=20&&num2=5">accept1</a>
<a href="${pageContext.request.contextPath }/sy/demo_accept2.action?cal2.num1=20&&cal2.num2=5">accept2</a>
<a href="${pageContext.request.contextPath }/sy/demo_accept3.action?sex=nv">accept3</a>

<h3>讲解OGNL</h3>
<a href="${pageContext.request.contextPath }/sy/stack_test1.action">ognl1</a>

</body>
</html>

 

 

创建一个类写我们得到方法

 

package com.yinyi.test;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;

public class DemoAction {
    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("salary2"));//2000
        return "rs";
    }
    
    public String test2() { 
        // 栈:表示一个先进后出的数据结构
        ValueStack vs = ServletActionContext.getContext().getValueStack();
                
        // push方法把项压入栈顶
        vs.push(new Employee("zs", 22));
        vs.push(new Employee("ls", 22));
        vs.push(new Employee("ww", 22));

        // pop方法移除栈顶对象并作为此函数的值返回该对象
        Employee e = (Employee) vs.pop();
        System.out.println(e.getName());
        e = (Employee) vs.pop();
        System.out.println(e.getName());
        e = (Employee) vs.pop();
        System.out.println(e.getName());
        return "rs";
    }
}

 

3.El表达式和OGNL的区别
1.El表达式方便在9大内置对象取值

2.OGNLContext通透来讲就是map集合,非根集合需要通过Key访问,根对象可以不用


4.总结
1、OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言
2、OgnlContext(ongl上下文)其实就是Map (教室、老师、学生)
3、根对象和非根对象的理解
4、ValueStack
    同一请求中只创建一个上下文
    先压action,再呀modeldriven
    从上往下找值

5、struts2中传递数据
 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

从入门小白到小黑

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

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

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

打赏作者

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

抵扣说明:

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

余额充值