OGNL
我们在上一节struts的基础上进行了解ognl
1、 OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言
修改过的类:
public class HelloAction implements ModelDriven<Cal>,ServletRequestAware{
private HttpServletRequest req;
private Cal cal1 = new Cal();
private Cal cal2;
private String sex;
private String num1;
public String getNum1() {
return num1;
}
public void setNum1(String num1) {
this.num1 = num1;
}
public Cal getCal2() {
return cal2;
}
public void setCal2(Cal cal2) {
this.cal2 = cal2;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String add() {
System.out.println("调用add方法.........");
return "rs";
}
public String del() {
System.out.println("调用del方法.........");
return "rs";
}
/**
* implements ModelDriven 接收参数值
* @return
*/
public String accept1() {
System.out.println("cal1:"+cal1);
System.out.println("num1:"+num1);
// req.setAttribute("cal1", cal1);
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("cal1", cal1);
// 非注入耦合
// ActionContext context = ActionContext.getContext();
// context.get("ccc");
return "rs";
}
/**
* 类实例.属性名 接收参数值
* @return
*/
public String accept2() {
System.out.println("cal2:"+cal2);
return "rs";
}
/**
* set/get 接收参数值
* @return
*/
public String accept3() {
System.out.println(sex);
return "rs";
}
@Override
public Cal getModel() {
return cal1;
}
@Override
public void setServletRequest(HttpServletRequest req) {
this.req = req;
}
}
2、OGNL的两大方法
public class OnglExpression {
private OnglExpression() {
}
/**
* 根据OGNL表达式进行取值操作
*
* @param expression
* ognl表达式
* @param ctx
* ognl上下文
* @param rootObject
* ognl根对象
* @return
*/
public static Object getValue(String expression, OgnlContext ctx,
Object rootObject) {
//${book.c.name} 意味着你要在jsp上获取书籍的类别的名称 ctx.get(#{name})
// ctx.get(${book.c.name})
try {
return Ognl.getValue(expression, ctx, rootObject);
} catch (OgnlException e) {
throw new RuntimeException(e);
}
}
/**
* 根据OGNL表达式进行赋值操作
*
* @param expression
* ognl表达式
* @param ctx
* ognl上下文
* @param rootObject
* ognl根对象
* @param value
* 值对象
*/
public static void setValue(String expression, OgnlContext ctx,
Object rootObject, Object value) {
try {
Ognl.setValue(expression, ctx, rootObject, value);
} catch (OgnlException e) {
throw new RuntimeException(e);
}
}
}
注:
1、一个上下文中只有一个根对象
2、取跟对象的值,只需要直接通过根对象属性即可
3、非根对象取值必须通过指定的上下文容器中的#key.属性去取。
了解方法后去我们去建几个实体类,
/**
* 地址类
* @author 雷神
*
*/
public class Address {
private String city;
private String country;
public Address() {
super();
}
public Address(String city, String country) {
super();
this.city = city;
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString() {
return "Address [city=" + city + ", country=" + country + "]";
}
}
/**
* 员工类
* @author 雷神
*
*/
public class Employee {
private String name;
private Address address;
private Integer salary;
public Employee() {
super();
}
public Employee(String name, Integer salary) {
super();
this.name = name;
this.salary = salary;
}
public Integer getSalary() {
return salary;
}
public void setSalary(Integer salary) {
this.salary = 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;
}
@Override
public String toString() {
return "Employee [name=" + name + ", address=" + address + ", salary=" + salary + "]";
}
}
/**
* 管理类
* @author 雷神
*
*/
public class Manager {
private String name;
public Manager() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Manager [name=" + name + "]";
}
}
/**
* 学生类
* @author 雷神
*
*/
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 + "]";
}
}
然后写一个main方法了解ongl的输出方式:
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);//小芳
}
}
这里可以看出,修改的类里面的num1未获取到值
因为ongl是属于堆栈结构,所以它会遵循先进后出的原则,找不到会继续往下找,直到找到为止!
3、了解值栈
写一个实例来实现值栈的使用
public class Demo7 {
/**
*
* 值栈的使用
*
*/
public static void main1(String[] args) {
// 栈:表示一个先进后出的数据结构
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());
}
/**
* 此例用于模拟struts2的值栈计算过程
*
* @param args
*/
public static void main(String[] args) {
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"));
ActionContext ac = ActionContext.getContext();
}
}
写一个值栈的action类来实现调用
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("salary"));
ActionContext ac = ActionContext.getContext();
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";
}
}
自己去配置一下路径就好了,然后在昨天写好的jsp页面实现该方法
<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?sex=nv">ognl</a>
</body>
结果如下:
最后,补一张自己画的理解图
剩下那个可以自己去调用看一下哦,谢谢