1.OGNL表达式介绍及语法
ognl表达式的结构图:(根对象和Context对象)

ognl:对象图导航语言. ${user.addr.name} 这种写法就叫对象图导航.
ognl是一种功能强大的开源表达式语言,可以存取Java对象的任意属性,调用Java对象的方法,能够自动实现类型转换。
struts2中使用OGNL表达式的准备工作:
(1)导包---struts2的包中已经包含了OGNL所需的包
(2)代码示范OGNL表达式语法:取值,赋值,调用方法,调用静态方法,创建对象(List、Map):
package cn.itheima.a_ognl;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import cn.itheima.bean.User;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
//展示OGNL语法
public class Demo {
@Test
//准备工作
public void fun1() throws Exception{
//准备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",22));
OgnlContext oc = new OgnlContext();
//将rootUser作为root部分
oc.setRoot(rootUser);
//将context这个Map作为Context部分
oc.setValues(context);
//书写OGNL
Ognl.getValue("", oc, oc.getRoot());
}
@Test
//基本语法演示
//(1)取出root中的属性值
public void fun2() throws Exception{
//准备ONGLContext
//准备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",22));
OgnlContext oc = new OgnlContext();
oc.setRoot(rootUser);
oc.setValues(context);
//书写OGNL
//取出root中user对象的name属性
String name = (String) Ognl.getValue("name", oc, oc.getRoot());
Integer age = (Integer) Ognl.getValue("age", oc, oc.getRoot());
System.out.println(name);
System.out.println(age);
}
@Test
//基本语法演示
//(2)取出context中的属性值
public void fun3() throws Exception{
//准备ONGLContext
//准备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",22));
OgnlContext oc = new OgnlContext();
oc.setRoot(rootUser);
oc.setValues(context);
//书写OGNL
//取出context中键为user1对象的name属性
String name = (String) Ognl.getValue("#user1.name", oc, oc.getRoot());
String name2 = (String) Ognl.getValue("#user2.name", oc, oc.getRoot());
Integer age = (Integer) Ognl.getValue("#user2.age", oc, oc.getRoot());
System.out.println(name);
System.out.println(name2);
System.out.println(age);
}
@Test
//基本语法演示
//(3)为属性赋值
public void fun4() throws Exception{
//准备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",22));
OgnlContext oc = new OgnlContext();
oc.setRoot(rootUser);
oc.setValues(context);
//书写OGNL
//将root中的user对象的name属性赋值
Ognl.getValue("name='jerry'", oc, oc.getRoot());
String name = (String) Ognl.getValue("name", oc, oc.getRoot());
//也可以写一起,但返回值只有一个,就是最后一个。所以多个有返回值的表达式不能写一起
String name2 = (String) Ognl.getValue("#user1.name='郝强勇',#user1.name", oc, oc.getRoot());
System.out.println(name);
System.out.println(name2);
}
@Test
//基本语法演示
//(4)调用方法
public void fun5() throws Exception{
//准备ONGLContext
//准备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",22));
OgnlContext oc = new OgnlContext();
oc.setRoot(rootUser);
oc.setValues(context);
//书写OGNL
//调用root中user对象的setName方法
Ognl.getValue("setName('lilei')", oc, oc.getRoot());
String name = (String) Ognl.getValue("getName()", oc, oc.getRoot());
//多个表达式可以写一起,但返回值只有一个,就是最后一个
String name2 = (String) Ognl.getValue("#user1.setName('lucy'),#user1.getName()", oc, oc.getRoot());
System.out.println(name);
System.out.println(name2);
}
@Test
//基本语法演示
//(5)调用静态方法
public void fun6() throws Exception{
//准备ONGLContext
//准备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",22));
OgnlContext oc = new OgnlContext();
oc.setRoot(rootUser);
oc.setValues(context);
//书写OGNL
//@完整类名@方法名,某些类可以省略类名
String name = (String) Ognl.getValue("@cn.itheima.a_ognl.HahaUtils@echo('hello 强勇!')", oc, oc.getRoot());
//Double pi = (Double) Ognl.getValue("@java.lang.Math@PI", oc, oc.getRoot());
Double pi = (Double) Ognl.getValue("@@PI", oc, oc.getRoot());
System.out.println(name);
System.out.println(pi);
}
@Test
//基本语法演示
//(6)ognl创建对象-list|map
public void fun7() throws Exception{
//准备ONGLContext
//准备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",22));
OgnlContext oc = new OgnlContext();
oc.setRoot(rootUser);
oc.setValues(context);
//书写OGNL
//创建list对象(存放在root中)
Integer size = (Integer) Ognl.getValue("{'tom','jerry','jack','rose'}.size()", oc, oc.getRoot());
String name = (String) Ognl.getValue("{'tom','jerry','jack','rose'}[0]", oc, oc.getRoot());
String name2 = (String) Ognl.getValue("{'tom','jerry','jack','rose'}.get(1)", oc, oc.getRoot());
/*System.out.println(size);
System.out.println(name);
System.out.println(name2);*/
//创建Map对象(存放在Context中)
Integer size2 = (Integer) Ognl.getValue("#{'name':'tom','age':18}.size()", oc, oc.getRoot());
String name3 = (String) Ognl.getValue("#{'name':'tom','age':18}['name']", oc, oc.getRoot());
Integer age = (Integer) Ognl.getValue("#{'name':'tom','age':18}.get('age')", oc, oc.getRoot());
System.out.println(size2);
System.out.println(name3);
System.out.println(age);
}
}
2.OGNL表达式和Struts2的结合
(1)什么是值栈?
ValueStack(值栈)是struts的一个接口,OgnlValueStack是ValueStack的实现类,客户端发起一个请求,struts2架构会创建一个action实例,同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿整个action的生命周期,struts2中使用ognl将请求action的参数封装为对象,存储到值栈中,并通过ognl表达式读取值栈中的对象属性值。
(2)结合原理:
struts2准备了一个OgnlValueStack(值栈),值栈包括root和context。如下:
OgnlContext--->OgnlValueStack
root-->栈
context--->ActionContext
public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {
public static final String THROW_EXCEPTION_ON_FAILURE = OgnlValueStack.class.getName() + ".throwExceptionOnFailure";
private static final long serialVersionUID = 370737852934925530L;
private static final String MAP_IDENTIFIER_KEY = "com.opensymphony.xwork2.util.OgnlValueStack.MAP_IDENTIFIER_KEY";
private static final Logger LOG = LoggerFactory.getLogger(OgnlValueStack.class);
CompoundRoot root;
transient Map<String, Object> context;
.....

栈继承了ArrayList实现了压栈和出栈功能,默认情况下,栈中放置当前访问的Action对象,ActionContext是一个map结构,存储一些ServletAPI。
struts2对ognl的改进就是:root使用CompoundRoot(自定义栈),使用OgnlValueStack的findValue方法可以在CompoundRoot中从栈顶向栈低查找对象的属性值。
(3)栈的原理
(类似弹夹)(使用ArrayList模拟的)

(4)ognl和struts2的结合体现
(4.1)参数接收:
属性驱动:

对象驱动:

模型驱动:

(4.2)体现在配置文件中
package com.xing.ognl;
import com.opensymphony.xwork2.ActionSupport;
public class demo3 extends ActionSupport{
private String name;
@Override
public String execute() throws Exception {
name="毛泽东";
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="showvs" namespace="/" extends="struts-default" >
<action name="Demo1Action" class="cn.itheima.b_showvs.Demo1Action" method="execute" >
<result name="success" type="dispatcher" >/showvs.jsp</result>
</action>
<action name="Demo3Action" class="cn.itheima.d_config.Demo3Action" method="execute" >
<result name="success" type="redirectAction" >
<param name="actionName">Demo1Action</param>
<param name="namespace">/</param>
<!-- 如果添加的参数struts"看不懂".就会作为参数附加重定向的路径之后.
如果参数是动态的.可以使用${}包裹ognl表达式.动态取值
-->
<param name="name">${name}</param>
</result>
</action>
</package>
</struts>
(4.3)struts2的标签(明天讲)
(5)如何获得值栈对象
值栈对象ValueStack与ActionContext对象是互相引用的
//1获得值栈
ValueStack vs = ActionContext.getContext().getValueStack();
//2.操作值栈:将u压入栈顶
vs.push(u);
(6)查看值栈中两部分的内容:
访问action,转发到带有debug标签的jsp页面。
<s:debug></s:debug>

扩展:
struts2中request对象的getAttribute()方法查找顺序:查找原生request域-->查找ValueStack的root部分-->查找ValueStack的Context部分(即ActionContext)
本文深入解析OGNL(对象图导航语言)的语法与特性,包括取值、赋值、调用方法等操作,并详细介绍其与Struts2框架的集成方式,涵盖值栈原理、参数接收与配置文件的应用。
205

被折叠的 条评论
为什么被折叠?



