一、OGNL
OGNL:OGNL 是 Object-Graph Navigation Language
的缩写,从语言角度来说:它是一个功能强大的表达式语言,用来获取和设置 java 对象的属性 , 它旨在提供一个更高抽象度语法来对 java
对象图进行导航
1.1 OGNL在struts2环境的使用
- 调用对象的方法
在jsp页面中使用对象的防范,需添加struts2的tags标签
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>OGNL在struts2环境中的入门</h1>
<h3>调用对象的方法</h3>
<s:property value="'struts'.length()"/>
</body>
</html>
结果如下:
- 调用对象的静态方法
@类名@方法名
默认关闭访问静态方法,需开启常量。
struts.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>
<!-- 配置struts2的常量 -->
<!-- 开启静态方法访问-->
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
</struts>
jsp页面
<h3>调用对象的静态方法</h3>
<s:property value="@java.lang.Math@random()"/>
结果如下:
二、值栈
2.1 值栈(ValueStack):
在struts2中使用ONGL将请求Action的参数封装为对象存储到值栈中,并通过OGNL表达式读取值栈中的对象属性
值栈贯穿整个Action的生命周期。Action一旦创建,框架就会创建一个ValueStack对象。struts2使用OGNL将请求Action的参数封装为对象存储在值栈中,并通过OGNL表达式读取值栈中的对象属性值
2.2 值栈的内部结构
值栈内部有两个区域:
- root:
真实对象为CompoundRoot,继承ArrayList
root放置的是Object对象
获取root中的数据不需要加#
操作值栈一般为操作root区
- context:
真实对象为OGNLContext,实现了Map接口
context中存有root的引用,还有request、session、application、parameters、attr的web开发对象引用
获取context中的数据需要加#
内部结构查看:
Action类:
package com.struts2.valuestack.demo01;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
/*
* ValueStack的内部结构
*/
public class ValueStackDemo01 extends ActionSupport{
@SuppressWarnings("unused")
@Override
public String execute() throws Exception {
//获得值栈
ValueStack valueStack = ActionContext.getContext().getValueStack();
return SUCCESS;
}
}
success.jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>查看值栈内部结构</h1>
<s:debug></s:debug>
</body>
</html>
结果如下:
2.3 值栈与ActionContext的关系
创建ActionContext时,创建了ValueStack对象,将ValueStack对象传递给了ActionContext对象,所有可以通过ActionContext获得ValueStack对象
所以在 Struts(二) 可以通过ActionContext对象访问Servlet API,因为在ActionContext内部有值栈,而值栈内部有常见的web开发对象的引用。
2.4 获得值栈
可以通过两种方式,Action初始化时,valueStack也被存入request中一份
package com.struts2.valuestack.demo01;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
/**
* 获取值栈对象
* @author cf
*
*/
public class ValueStackDemo02 extends ActionSupport {
@Override
public String execute() throws Exception {
//通过ActionContext获得
ValueStack valueStack1 = ActionContext.getContext().getValueStack();
//通过request获得
ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
//判断是否是同一个
System.out.println(valueStack1 == valueStack2);
return NONE;
}
}
结果如下:
2.5 操作值栈
- 通过在Action类中的get方法存入数据
默认情况下,Action对象被亚茹值栈,其属性也被压入值栈
Action类:
package com.struts2.valuestack.demo01;
import com.opensymphony.xwork2.ActionSupport;
import com.struts2.domain.Product;
/**
* 操作ValueStack
* @author cf
*
*/
public class ValueStackDemo03 extends ActionSupport{
private Product product;
public Product getProduct() {
return product;
}
@Override
public String execute() throws Exception {
//向ValueStack中存值
product = new Product("iphoneXR",new Double(4999),"手机数码");
return SUCCESS;
}
}
结果:
在jsp中使用property获取值
<s:property value="product.name"/>
<s:property value="product.price"/>
<s:property value="product.category"/>
结果如下:
- 通过值栈中的方法存入数据
set后压入值栈,取出的属性只能是最靠近栈顶的属性,因此name属性被覆盖
package com.struts2.valuestack.demo01;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
import com.struts2.domain.Product;
/**
* 调用值栈中的方法操作值栈
* @author cf
*
*/
public class ValueStackDemo04 extends ActionSupport{
@Override
public String execute() throws Exception {
//获得值栈对象
ValueStack valueStack = ActionContext.getContext().getValueStack();
//pusth(Obejct obj);对象 set(String key, Object(obj));集合
Product product = new Product("iphoneXR",new Double(4999),"手机数码");
valueStack.push(product);
valueStack.set("name", "iphoneXS");
return SUCCESS;
}
}
jsp页面:
<s:property value="name"/>
<s:property value="price"/>
<s:property value="category"/>
结果:
set压入的map在栈顶
2.6 获取值栈中的数据
使用OGNL表达式来取值
Action类存值:
package com.struts2.valuestack.demo01;
import java.util.ArrayList;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.struts2.domain.Product;
/**
* 获取值栈的数据
* @author cf
*
*/
public class ValueStackDemo05 extends ActionSupport{
@Override
public String execute() throws Exception {
//向值栈中保存对象
Product product = new Product("iphoneXR",new Double(4999),"手机数码");
ActionContext.getContext().getValueStack().push(product);
//向值栈中保存集合
List<Product> list = new ArrayList<Product>();
list.add(new Product("iphoneXS",new Double(6999),"手机数码"));
list.add(new Product("iphoneXS MAX",new Double(8999),"手机数码"));
list.add(new Product("P30",new Double(3999),"手机数码"));
ActionContext.getContext().getValueStack().set("list", list);
//向Context中保存数据,即向作用域中保存数据
ServletActionContext.getRequest().setAttribute("name", "request中的数据");
ServletActionContext.getRequest().getSession().setAttribute("name", "session中的数据");
ServletActionContext.getServletContext().setAttribute("name", "application中的数据");
return SUCCESS;
}
}
success.jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>查看值栈内部数据</h1>
<s:debug></s:debug>
<%-- <s:property value="product.name"/> --%>
<%-- <s:property value="product.price"/> --%>
<%-- <s:property value="product.category"/> --%>
<%-- <s:property value="name"/> --%>
<%-- <s:property value="price"/> --%>
<%-- <s:property value="category"/> --%>
<h3>取对象中的值</h3>
<s:property value="name"/>
<s:property value="price"/>
<s:property value="category"/>
<h3>取list中的值</h3>
<s:property value="list[0].name"/>
<s:property value="list[0].price"/>
<s:property value="list[0].category"/><br>
<s:property value="list[1].name"/>
<s:property value="list[1].price"/>
<s:property value="list[1].category"/><br>
<s:property value="list[2].name"/>
<s:property value="list[2].price"/>
<s:property value="list[2].category"/><br>
<h3>取Context中的值, 需使用#号</h3>
<s:property value="#request.name"/><br>
<s:property value="#session.name"/><br>
<s:property value="#application.name"/><br>
</body>
</html>
结果: