OGNL

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

二、OgnlContext(ongl上下文)其实就是Map (教室、老师、学生)
分为两个对象:根对象(Root)和非根对象
举例:
map : 教室(容器)
OgnlContext=根对象(1)+非根对象(N)
老师 teacher:根对象 (1)
学生 stu:非根对象
非根对象要通过"#key"访问,根对象可以省略"#key"
如果我们想要取老师:String teacher= (String) OnglExpression.getValue(“name”, ctx, e);
由于老师是根对象,所以"#“可以不用
如果我们想取学生:String stu= (String) OnglExpression.getValue(”#stu.name", ctx, e);
由于学生是非根对象,所以要使用"#"
总结:
1、一个上下文中只有一个根对象
2、取跟对象的值,只需要直接通过根对象属性即可
3、非根对象取值必须通过指定的上下文容器中的#key.属性去取。

struts2中ognl结构图:

在这里插入图片描述
三、案例测试:
根对象取值和非根对象取值的现象,以及OGNL取值和赋值的案例
实体类:

package com.swxognl;

public class Teacher {
 private String name;
 private Address address;
 private Integer salary;
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public Address getAddress() {
	return address;
}
public void setAddress(Address address) {
	this.address = address;
}
public Integer getSalary() {
	return salary;
}
public void setSalary(Integer salary) {
	this.salary = salary;
}
public Teacher(String name, Address address, Integer salary) {
	super();
	this.name = name;
	this.address = address;
	this.salary = salary;
}
public Teacher(String name,  Integer salary) {
	super();
	this.name = name;
	this.salary = salary;
}
public Teacher() {
	super();
}
@Override
public String toString() {
	return "Teacher [name=" + name + ", address=" + address + ", salary=" + salary + "]";
}
 
 
 
}


package com.swxognl;

public class Student {
	private String name;

	private String number;

	public Student() {
		super();
	}

	public Student(String name, String number) {
		super();
		this.name = name;
		this.number = number;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", number=" + number + "]";
	}

}

测试类:

package com.swxognl;

import ognl.OgnlContext;

/**
 * 测试ognl
 * @author 10570
 *
 */
public class Demo {
    public static void main(String[] args) {
		Teacher t = new Teacher();
		t.setName("晓哥");
		
		Student s = new Student();
		s.setName("大飞");
		// 创建OGNL下文,而OGNL上下文实际上就是一个Map对象
				OgnlContext ctx = new OgnlContext();

				// 将老师和学生放到OGNL上下文当中去
				ctx.put("teacher", t);
				ctx.put("stu", s);
				ctx.setRoot(t);// 设置OGNL上下文的根对象

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

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

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

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

				OnglExpression.setValue("#stu.name", ctx, s, "孙悟空");
				stuName = (String) OnglExpression.getValue("#stu.name", ctx, s);
				System.out.println(stuName);

				OnglExpression.setValue("#teacher.name", ctx, t, "小芳");
				teacherName = (String) OnglExpression.getValue("name", ctx, t);
				System.out.println(teacherName);
		 
	}
}

结果:
在这里插入图片描述
2. OGNL向ValueStack压栈
2.1 值栈
先进后出的数据结构,弹夹 push/pop
2.2 为什么要使用ValueStack作为根对象
放到值栈中的对象都可视为根对象

package com.swxognl;

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

public class Demo2 {
	/**
	 * 
	 * 值栈的使用
	 * 
	 */
	public String test1() {
		// 栈:表示一个先进后出的数据结构
		ValueStack vs = ActionContext.getContext().getValueStack();
		// push方法把项压入栈顶
		vs.push(new Teacher("zs", 22));
		vs.push(new Teacher("ls", 22));
		vs.push(new Teacher("ww", 22));

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

	/**
	 * 此例用于模拟struts2的值栈计算过程
	 * 
	 * @param args
	 */
	public String test2() {
		ValueStack vs = ActionContext.getContext().getValueStack();
		vs.push(new Teacher("张老师", 2000));// 1
		vs.push(new Student("小明同学", "s001"));// 0
		System.out.println(vs.findValue("name"));//值栈取值从上往下,取到为止,如果已经拿到,不再往下找。
		System.out.println(vs.findValue("salary2"));//属性不存在 所以找不到 为null
		System.out.println(vs.findValue("salary"));//一直找,找到该属性为止
		ActionContext ac = ActionContext.getContext();
		return "rs";
	}
}

配置struts-sy.xml

<action name="ognl_*" class="com.swxognl.Demo2" method="{1}">
	<result name="rs">/rs.jsp</result>
	</action>

前台代码:

<h3>讲解ognl值栈</h3>
<a href="${pageContext.request.contextPath}/sy/ognl_test1.action">测试ognl1</a>
<a href="${pageContext.request.contextPath}/sy/ognl_test2.action">测试ognl2</a>

结果:
在这里插入图片描述
在这里插入图片描述
注意:
1、ActionContext一次请求创建一次
2、值栈取值从上往下,取到为止,如果已经拿到,不再往下找。

后台定义属性和实现modelDriver接口,并提供get和set方法


package com.swxstruts.jsp;

import com.opensymphony.xwork2.ModelDriven;

/**
 * jsp传递参数到后台的三种方式:
 * 1、set传参
 * 2、实现modeldriven接口传参(自定义mvc做法)
 * 3、类实例.属性传参
 * @author 10570
 *
 */
public class DemoAction implements ModelDriven<User>{
private String sex;
private User user1 = new User();//不给它提供set方法
private User user2;

private String uname;

public String getUname() {
	return uname;
}

public void setUname(String uname) {
	this.uname = uname;
}

@Override
public User getModel() {
	// TODO Auto-generated method stub
	return user1;
}

public String getSex() {
	return sex;
}

public void setSex(String sex) {
	this.sex = sex;
}

public User getUser2() {
	return user2;
}

public void setUser2(User user2) {
	this.user2 = user2;
}
/**
 * set传参是否成功
 * @return
 */
public String test1() {
	System.out.println(sex);
	return "rs";
}
/**
 * modeldriven接口传参是否成功
 * @return
 */
public String test2() {
	System.out.println(user1);
	return "rs";
}
/**
 * 类实例.属性传参是否成功
 * @return
 */
public String test3() {
	System.out.println(user2);
	return "rs";
}

}

解释为什么user1.uname有值,而uname却取不到值?
struts后台取值方法有3种,一种实现接口,一种通过get和set方法取,还有一种通过对象点属性名,我已经提供了get方法,其实应该是能取到的,但是取不到。
其实这和ValueStack的压栈有关系了,因为压栈的结构是先进后出,而ValueStack的取值是取到了值就会返回,不会往下取了。
而ValueStack对取值的压栈是先把xxxAction也就是我们通过set和get方法取值的方式先压入栈底,然后再把ModelDriver压入,所有会先取到通过ModelDriver来获取值的,而获取到了就返回了,导致后面的值不会获取了
ValueStack
同一请求中只创建一个上下文
先压action,再呀modeldriven
从上往下找值

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值