Java EE SSH框架之Struts2 (5)—— Struts2与OGNL表达式的结合
一、OGNL表达式
1.1、OGNL表达式简单介绍
OGNL:对象视图导航
不仅仅可以视图导航,支持比EL表达式更加丰富的功能。
使用OGNL表达式之前要先导包
了解下OGNL表达式取值范围:
1.2、OGNL表达式语法
参考下例:
User.java
package com.zl.beans;
public class User {
private String name;
private Integer age;
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
HuiYing.java
package com.zl.staticsDemo;
public class HuiYing {
//专门用于测试,传什么参数返回什么参数
public static Object echo(Object o) {
return o;
}
}
Demo1.java
package com.zl.grammer;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import com.zl.beans.User;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
//基本OGNL语法
public class Demo1 {
@Test
public void fun1() throws OgnlException {
//准备OGNLContext
//准备Root
User rootUser = new User("Tom",18);
//准备Context
Map<String,User> context = new HashMap<String,User>();
context.put("user1", new User("Jack",18));
context.put("user2", new User("Rose",20));
OgnlContext oc = new OgnlContext();
oc.setRoot(rootUser);//将rootUser作为root部分
oc.setValues(context);//将context这个Map作为Context部分
//书写OGNL
//取值
//1.1取出root中User对象的name属性、age属性
String name = (String)Ognl.getValue("name", oc, oc.getRoot());
Integer age = (Integer)Ognl.getValue("age", oc, oc.getRoot());
System.out.println("root中User的name、age:"+name+"\t"+age);
//1.2取出context中User对象的name、age属性
String name1 = (String) Ognl.getValue("#user1.name", oc, oc.getRoot());
Integer age1 = (Integer) Ognl.getValue("#user1.age", oc, oc.getRoot());
System.out.println("Context中两个User的name、age:"+name1+"\t"+age1+"\n");
//赋值
//2.1给root中的user对象属性name重新赋值
String name2 = (String)Ognl.getValue("name='汤姆'", oc,oc.getRoot());
//2.2给context中的user1对象的属性name重新赋值
String name3 = (String) Ognl.getValue("#user1.name='杰克'", oc, oc.getRoot());
System.out.println("root、context里重新赋值后的name值分别为:"+name2+"\t"+name3+"\n");
//3.调用方法
//3.1调用root中的方法,setName()、getName()
Ognl.getValue("setName('李磊')", oc,oc.getRoot());
String name4 = (String) Ognl.getValue("getName()", oc, oc.getRoot());
//3.2调用Context中的方法setName()、getName()
Ognl.getValue("#user1.setName('Lucky')", oc,oc.getRoot());
String name5 = (String) Ognl.getValue("#user1.getName()", oc,oc.getRoot());
System.out.println("分别调用root中user和Context中user1的setName方法后的name值分别为:"+name4+"\t"+name5+"\n");
//3.3调用静态方法
String str = (String)Ognl.getValue("@aaa@qq.com('hello 侬好!')",oc,oc.getRoot());
System.out.println("调用静态方法"+str);
//3.4访问静态属性PI(double)
//double pi = (double)Ognl.getValue("@aaa@qq.com",oc,oc.getRoot());
double pi = (double)Ognl.getValue("@@PI",oc,oc.getRoot());
System.out.println(pi);
System.out.println();
//4、创建对象
//4.1创建List对象
Integer size = (Integer)Ognl.getValue("{'blue','red','pink'}.size", oc,oc.getRoot());
String color = (String)Ognl.getValue("{'blue','red','pink'}[0]", oc,oc.getRoot());
String color2 = (String)Ognl.getValue("{'blue','red','pink'}.get(2)", oc,oc.getRoot());
System.out.println("list的长度:"+size+",list第1个元素:"+color+",List第3个元素:"+color2);
//4.2创建Map对象
Integer size1 = (Integer)Ognl.getValue("#{'sky':'blue','blood':'red','face':'pink'}.size", oc,oc.getRoot());
String sky = (String)Ognl.getValue("#{'sky':'blue','blood':'red','face':'pink'}['sky']", oc,oc.getRoot());
String blood = (String)Ognl.getValue("#{'sky':'blue','blood':'red','face':'pink'}.get('blood')", oc,oc.getRoot());
System.out.println("map的长度:"+size1+",map中键为sky的值:"+sky+",map中键为blood的值:"+blood);
}
}
Run As ->Junit Test, 运行结果:二、Struts2 与OGNL的结合
2.1、Struts2与OGNL结合原理
OGNL表达式想要运行,需要准备一个OGNLContext,Struts2就准备了一个OGNLContext,名叫ValueStack。ValueStack由两部分构成。一部分叫做Root,放置的是一个栈。一部分叫做Context,是将我们之前学过的ActionContext(数据中心)放入。
补充:栈是先进后出,有push压栈方法、pop弹栈方法
ValueStack是一个接口,OgnlValueStack为其实现类
OgnlValueStack中定义了两个属性:
CompoundRoot root;——栈(CompoundRoot类中定义了push和pop方法)
transient Map<String,Object> context; ——数据中心
默认情况下,stack(栈)中放置当前访问的Action对象!ActionContext(数据中心)中放置的是request、response、ServletContext、requestScope、sessionScope、applicationScope、params和attrs!
2.2、参数赋值
模型驱动中,
将对象user压入栈顶:
1.获得值栈
ValueStack vs = ActionContext.getContext().getValueStack();
2.将user压入栈顶
vs.push(user);
将上述语句加到prepare()方法中,该Action要实现Preparable接口,prepare()为Preparable接口的方法,保证该方法可以在params拦截器给user对象的name属性赋值之前执行。
上述方法过于繁琐,需要非常了解Struts2,下面这钟方式更推荐使用:
实现ModelDriven<User>接口(<User>泛型,这里只是举例),重写getModel()方法,直接return user;
上一篇: 基于ssm框架上传下载的实现