OGNL表达式语言介绍
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,
它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
OGNL相对其它表达式语言具有下面几大优势:
- 支持对象方法调用,如xxx.doSomeSpecial();
支持类静态的方法调用和值访问,表达式的格式:
@[类全名(包括包路径)]@[方法名 | 值名],例如:
@java.lang.String@format(‘foo %s’, ‘bar’)
或@tutorial.MyConstant@APP_NAME;支持赋值操作和表达式串联,如price=100, discount=0.8,
calculatePrice(),这个表达式会返回80;访问OGNL上下文(OGNL context)和ActionContext;
操作集合对象。
Ognl 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了java.utils.Map的接口.
理解Struts2中的 ValueStack
ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础
- ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个 ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前 Action 对象和其他相关对象.
Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中,request中
在 ValueStack 对象的内部有两个逻辑部分:
- ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中–List
- ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中
Struts 会把下面这些映射压入 ContextMap 中 - parameters: 该 Map 中包含当前请求的请求参数
- request: 该 Map 中包含当前 request 对象中的所有属性
- session: 该 Map 中包含当前 session 对象中的所有属性
- application:该 Map 中包含当前 application 对象中的所有属性
- attr: 该 Map 按如下顺序来检索某个属性: request, session,
application
断点执行如下代码:
Object ctx = ServletActionContext.getRequest().getAttribute("struts.valueStack");
理解OGNL Context
OgnlValueStack 类包含两个重要的属性 一个root和一个context。
- 其中root本质上是一个ArrayList.
- 而context 是一个Map(更确切的说是一个OgnlContext对象)
在这个OgnlContext对象(context)中,有一个默认的顶层对象
_root,OGNL访问context中这个默认顶层对象中的元素时,是不需要#号的,直接通过元素的名称来进行访问,而访问其他对象时,如 request、session、attr等,则需要#号引用。
注:Struts2将OgnlValueStack的root对象赋值给了OgnlContext 中的_root对象,在OgnlValueStack的root对象中,保存着调用Action的实例,因此,在页面上通过Struts2标签访问Action
的属性时,就不需要通过#号来引用总结:ognl Context包含 ObjectStack属性和ContextMap属性
OGNL Context是struts2的数据中心 结构示意图如下:
当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。
注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:
理解ActionContext
通过代码获取ValueStack对象
1. 编写jsp测试页面和跳转页面
<%@ page language="java" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
测试值栈:<br>
<a href="${pageContext.request.contextPath}/ognl/ValueStackAction_test.action">test</a><br>
<br>
<br>
<br>
</html>
<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="description" content="This is my page">
</head>
<body>
valueStack.jsp页面<br>
</body>
</html>
2.配置struts_ognl.xml文件
<?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="ognl" namespace="/ognl" extends="struts-default">
<action name="*_test" class="cn.itcast.ognl.{1}" method="test">
<result name="ValueStack">/ognl/ValueStackAction.jsp</result>
</action>
</package>
</struts>
3.在struts.xml文件中引入自定义配置文件
<include file="cn/itcast/ognl/struts_ognl.xml"></include>
4.编写Action文件
在文件中编写代码获取ValueStack对象
package cn.itcast.ognl;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
import com.sun.org.apache.bcel.internal.generic.NEW;
@SuppressWarnings("serial")
public class ValueStackAction extends ActionSupport {
public String test(){
System.out.println("ValueStackAction ************ test()");
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("username", "username_request");
request.setAttribute("password", "password_request");
Map sessionMap = ServletActionContext.getContext().getSession();
sessionMap.put("username", "username_session");
sessionMap.put("password", "password_session");
ServletContext sc = ServletActionContext.getServletContext();
sc.setAttribute("username", "username_application");
sc.setAttribute("password", "password_application");
//方法一:获取ValueStack对象
ValueStack valueStack1 = (ValueStack)request.getAttribute("struts.valueStack");
System.out.println("valueStack = "+valueStack1);
/*
* 插入的内容,实际上是先放置在一个map集合中,又把这个map集合放置在对象栈里
*/
valueStack1.set("error", "error_valueStack");
valueStack1.set("msg", "msg_valueStack");
// valueStack1.getRoot().add(0, new Person());
//方法二:获取ValueStack对象
/*ValueStack valueStack2 = ServletActionContext.getContext().getValueStack();
System.out.println("valueStack = "+valueStack2);*/
return "ValueStack";
}
}