OGNL表达式
无敌全面Action与Servelet-参数接收-下载-上传一文全有
文章目录
OGNL 是 Object Graphic Navigation Language(对象图导航语言)的缩写,是一个使用简单、功能强大的、开源的表达式语言,可以方便地 操作任何的对象属性、方法等。
Struts2 框架使用 OGNL 作为默认的表达式语言,主要用于页面的取值。它类似于 EL 表达式语言,但比 EL 语法强大很多。
EL Expression Language 表达式语言, 主要用来获取 JSP 页面四个域范围数据 (page、request、 session、 application )OGNL = EL +对象操作 ${name.toUpperCase()}
OGNL 表达式的三个要素
表达式 – OGNL 的表达式,编写表达式,OGNL 负责解析表达式,从而存值和取值
Root 对象 - 根对象
Context 对象 – OGNL 的上下文对象,运行的环境
TestOGNL
package com.igeek.ognl;
import org.junit.Test;
import com.igeek.domain.Customer;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class TestOGNL {
@Test
public void testOgnl_01() throws OgnlException{
//创建OgnlContext对象
//通过ognl来操作对象的方法
OgnlContext context = new OgnlContext();
//第一个参数表达式,第二个参数上下文,第三个是root
Object obj =Ognl.getValue("'helloworld'.length()", context, context.getRoot());
System.out.println(obj);
}
@Test
public void testOgnl_02() throws OgnlException{
//创建OgnlContext对象
//通过ognl来获取map集合中的值
OgnlContext context = new OgnlContext();
//数据格式为Map
context.put("name", "美美");
//使用#key的方式获取
Object obj =Ognl.getValue("#name", context, context.getRoot());
System.out.println(obj);
}
@Test
public void testOgnl_03() throws OgnlException{
//创建OgnlContext对象
//通过ognl来获取map集合中的值
OgnlContext context = new OgnlContext();
//创建一个客户对象
Customer c = new Customer();
c.setCust_name("冠希");
c.setAge(18);
//把客户放入root栈
context.setRoot(c);
//如果取root栈中的值,不需要家#
Object obj =Ognl.getValue("age", context, context.getRoot());
System.out.println(obj);
}
}
OGNL 的用法详解
1.Java对象的直接访问
例如:<s:propertyvalue="'igeek'"/>
2.实例方法调用:访问对象的方法
语法:object.doSomething(),object是对象实例
例如:<s:propertyvalue="'igeek'.toUpperCase()"/>
3.静态方法调用(类的静态方法或静态变量的访问)
语法:@[类全名(包括包路径)]@[方法名|值名]
例如:<s:propertyvalue="@java.lang.Math@max(10,21)"/>类的静态方法或静态变量的调用访问。
格式:@[类全名(包括包路径)]@[方法名|值名],如:@java.lang.Math@max(10,20)、@com.igeek.MyConstant@APP_NAME
注意:必须通过配置struts2的常量来开启静态方法调用功能:
struts.ognl.allowStaticMethodAccess=true
4.赋值操作或表达式串联。–可以运算
例如:<s:propertyvalue=*"1+2"*/>
OGNL可以访问上下文(OGNL Context)和ActionContext。(值栈相关访问-重要)
OGNL.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
//引入标记库
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>访问java对象</h3>
<s:property value="'igeek'"/>
<h3>操作对象的属性</h3>
<s:property value="'igeek'.toUpperCase()"/>
<h3>静态方法的访问 </h3>
<h3>语法:@包名+类名@方法名(参数)</h3>
<h3>需要开启静态方法访问</h3>
<s:property value="@java.lang.Math@max(10,21)"/>
<h3>类似EL表达式,进行数值运算</h3>
<s:property value="1+2"/>
</body>
</html>
静态方法的调用,开启常量
struts.xml
<!-- 开启静态访问常量 -->
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
值栈概述(掌握)
值栈(ValueStack)是什么
值栈(ValueStack),是 Struts2 的数据中转站,栈中自动保存了当前 Action 对象和其他相关对象(包括常用的 Web 对象的引用,如 request、session、application 等),也可以手动保存自己的数据对象,同时也可以随时随地将对象从值栈取出或操作(通过 OGNL 表达式)
值栈(ValueStack),实际是一个接口的对象的称呼,接口是 ValueStack 类,实现类是OgnlValueStack 类,该对象是 Struts2 利用 OGNL 的基础,或者说 Struts2 中 Ognl 使用都是基于值栈完成的。
Struts2 框架将 ValueStack 对象保存在 request 域中,键为“struts.valueStack”,即值栈是request 域中的一个对象,一个请求对应一个 Action 实例和一个值栈对象。
【示例 1】值栈的获取方式:
1) request.getAttribute(“struts.valueStack”):用的较少
2) ActionContext.getContext().getValueStack():用的非常多:底层使用的还是第一种方式获取ActionContext(Action 上下文,工具类)
ValueStackAction1 值栈的获取方式
package com.igeek_02_valuestack;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class ValueStackAction1 extends ActionSupport{
@Override
public String execute() throws Exception {
//获取值栈
//1.从request域中获取
ValueStack vs1 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
//2.通过ActionContext对象获取
ValueStack vs2 = ActionContext.getContext().getValueStack();
System.out.println(vs1 == vs2);
System.out.println(vs1.hashCode());
System.out.println(vs2.hashCode());
//两种方式创建的 ValueStack 是一致的
//每一次请求都会创建新的 ValueStack
return NONE;
}
}
ValueStackAction2 ValueStack 的存储结构
package com.igeek_02_valuestack;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class ValueStackAction2 extends ActionSupport{
@Override
public String execute() throws Exception {
ValueStack vs = ActionContext.getContext().getValueStack();
//往值栈中放数据
vs.push("柳岩");
vs.push("刘德华");
vs.push("刘亦菲");
//使用k-v结构存储值 推荐使用
vs.set("name", "范冰冰");
vs.set("age", 18);
//总结:使用push和set方法都会把数据放入root栈中
return NONE;
}
}
ValueStackAction3 把数据放入map栈中
package com.igeek_02_valuestack;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class ValueStackAction3 extends ActionSupport{
@Override
public String execute() throws Exception {
ActionContext context = ActionContext.getContext();
//把数据放入map栈中
context.put("name", "柳岩");
context.put("age", 20);
return NONE;
}
}
值栈的操作(掌握重要)
3.1 值栈的存值机制
【回顾知识了解】
栈的概念:栈是一种数据结构,它按照先进后出的原则存储数据,即先进入的数据被压入栈底,最后进入的数据在栈顶,需要读取数据的时候,从栈顶开始弹出数据(即最后一个数据被第一个读出来)。栈也被称为先进后出表,可进行插入和删除操作,插入称之为进栈(压栈)(push),删除称之为退栈(pop),允许操作的一端称为栈顶(top),另外一端就称为栈底(bottom)。栈底固定,而栈顶浮动。对于栈就只能每次访问它的栈顶元素。
3.2 值栈的取值机制
OgnlValueStack 类包含两个重要的属性,一个 root(CompoundRoot)和一个 context(OgnlContext)。OGNL Context 是 struts2 的数据中心,其结构示意图:

在这个 OgnlContext 对象中,有一个默认的顶层对象 root(引用),俗称 root 栈,下面一个对象称之为 Map 栈。
对 OGNL 表达式的操作都是基于 OgnlContext(map 栈)对象,访问的规则如下:
如果访问 root 栈内容(CompoundRoot 对象栈内容), 不需要#,直接通过元素的名称来访问。
如果访问 Map 栈内容 (如 request、response、session、servletContext、attr、parameters), 需要#key 来引用访问,例如 #request.name 相当于request.getAttribute(“name” )
Action
package com.igeek_03_valuestack;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class ValueStackAction1 extends ActionSupport{
@Override
public String execute() throws Exception {
ValueStack vs1 = ServletActionContext.getContext().getValueStack();
vs1.push("柳岩");
vs1.push("刘亦菲");
//通过k-v的形式把数据放入root栈
vs1.set("name", "刘德华");
//map栈放数据
ActionContext.getContext().put("name", "张三");
return SUCCESS;
}
}
jsp取值
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>获取栈顶元素</h3>
<s:property value="top"/> -- <s:property value="[0].top"/>
<h3>获取栈中第二个元素</h3>
<s:property value="[1].top"/>
<h3>取root栈中k-v形式存的数据</h3>
<s:property value="name"/>
<h3>取map栈中的数据</h3>
<s:property value="#name"/>
</body>
</html>
值栈的默认搜索
在实际开发中,使用 OGNL 表达式时,会经常用到值栈的默认搜索,即自动搜索值栈,找到所需要的值。
Action
package com.igeek_03_valuestack;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class ValueStackAction2 extends ActionSupport{
@Override
public String execute() throws Exception {
//map栈放数据
ActionContext.getContext().put("name", "张三");
//root栈
ServletActionContext.getContext().getValueStack().set("username", "柳岩");
//map栈
ActionContext.getContext().put("username", "刘亦菲");
//从root栈中取数据
String username1 = ActionContext.getContext().getValueStack().findString("username");
//从map栈中取数据
String username2 = ActionContext.getContext().getValueStack().findString("#username");
System.out.println("root栈:"+username1);
System.out.println("map栈:"+username2);
return SUCCESS;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>获取map栈中的数据</h3>
<h3>不加#的情况下:先搜索root栈,如果没有,再搜索map栈</h3>
<h3>加#的情况下,直接搜索map栈</h3>
*<h3>实际开发中,单个数据直接放入root栈,k-v形式的数据放入map栈</h3>
<s:property value="name"/>
</body>
</html>
模型驱动优先属性驱动接收参数
【问题】为什么在赋值的时候,模型驱动的属性会优先赋值?模型驱动是如何具备更高的优先级别?
模型驱动获取参数优先于属性驱动
package com.igeek_03_valuestack;
public class User {
private String username;
private String password;
}
Action
package com.igeek_03_valuestack;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class ValueStackAction3 extends ActionSupport implements ModelDriven<User>{
//模型驱动
private User user = new User();
//属性驱动
private String username;
@Override
public User getModel() {
return user;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>s:debud标签可以在html页面上查看值栈内容</h3>
<s:debug></s:debug>
</body>
</html>
Struts2使用表达式语言来操作值栈
Struts 2 支持以下几种表达式语言:
OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言;
EL(Expression Language),可以方便的操作 JSP 页面四个域范围数据 (page、 request、session、 application );
JSTL(JSP Standard Tag Library),JSP 2.0 集成的标准的表达式语言;
Groovy,基于 Java 平台的动态语言,它具有时下比较流行的动态语言(如 Python、Ruby和 Smarttalk 等)的一些起特性;
Velocity,严格来说不是表达式语言,它是一种基于 Java 的模板匹配引擎,据说性能要比 JSP 好。
Struts 2 默认的表达式语言是 OGNL,原因是它相对其它表达式语言更简单、强大,最重要的是可以直接操作值栈。
OGNL对Struts2的值栈的操作方式
明确一点:OGNL 表达式对值栈的操作,必须依赖 Struts2 的标签,所以每个 jsp 页面都需要引入 struts2 的标签库
Struts2 通过值栈存放数据,那如何取数据呢? 通过 Ognl 表达式访问值栈中的数据
在 Struts2 中,OGNL 表达式三种特殊符号的使用方式 :
# 号用法
OgnlAction1
package struts2_d04_c04;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class OgnlAction1 extends ActionSupport{
@Override
public String execute() throws Exception {
//把数据放入request、session、application3个域中
ServletActionContext.getRequest().setAttribute("name", "request数据");
ServletActionContext.getRequest().getSession().setAttribute("name", "session数据");
ServletActionContext.getServletContext().setAttribute("name", "application数据");
return SUCCESS;
}
}
ognl1.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>OGNL表达式获取request域中的数据</h3>
<s:property value="#request.name"/> | ${requestScope.name}
<h3>OGNL表达式获取session域中的数据</h3>
<s:property value="#session.name"/> | ${sessionScope.name}
<h3>OGNL表达式获取application域中的数据</h3>
<s:property value="#application.name"/> | ${applicationScope.name}
<h3>如何获取page域的数据</h3>
<%
pageContext.setAttribute("name", "page数据");
%>
<s:property value="#attr.name"/> | ${name}
<h3>获取地址栏的信息</h3>
<s:property value="#parameters.name"/>
</body>
</html>
% 号用法 强制解析
Action
package struts2_d04_c04;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class OgnlAction2 extends ActionSupport{
@Override
public String execute() throws Exception {
ServletActionContext.getContext().getValueStack().set("username", "tom");
return SUCCESS;
}
}
jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>文本框 获取值栈中的值 ,使用%强制解析值栈中的值</h3>
<s:textfield value="%{username}"></s:textfield> //tom
<h3>强制不解析</h3>
<s:property value="%{'username'}"/> //username
</body>
</html>
$ 号用法
此处的 不能理解为 e l 表达式,因为此处的 不能理解为 el 表达式,因为此处的 不能理解为el表达式,因为此处的必须用在 struts 特有的文件中,只能用在 struts2的文件中
用法:是用在 struts2 特有的文件中的 主要作用:允许我们在配置文件中使用 O G N L 表达式, ( 换句话说: 主要作用:允许我们在配置文件中使用 OGNL 表达式,(换句话说: 主要作用:允许我们在配置文件中使用OGNL表达式,(换句话说:可以在 xml 文件中获取值栈的值。)
配置文件主要指:struts.xml、国际化的文件(xxx.properties)、校验配置文件(xxx-validation.xml)。
OgnlAction3
package struts2_d04_c04;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class OgnlAction3 extends ActionSupport{
@Override
public String execute() throws Exception {
//如果要在xml或properties文件中获取值栈的值,值不能是中文
ServletActionContext.getContext().getValueStack().set("productName", "iphone");
return SUCCESS;
}
}
messages.properties
productInfo=\u6B22\u8FCE\u4F7F\u7528${productName}\u4EA7\u54C1
struts.xml
<!-- 配置国际化常量 -->
<constant name="struts.custom.i18n.resources" value="messages"></constant>
jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>获取国际化文件中的值</h3>
<s:text name="productInfo"></s:text>
</body>
</html>
第二种用法struts中配置
jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>获取URL中的参数</h3>
<s:property value="#parameters.productName"/>
</body>
</html>
struts.xml
<action name="ognl4" class="struts2_d04_c04.OgnlAction4">
<!-- 获取值栈中的产品名称,当做参数传给页面 -->
<result type="redirect">/c_ognl/ognl4.jsp?productName=${productName}</result>
</action>
EL表达式获取值栈的数据
jsp
<body>
<h3>EL表达式获取值栈中的值</h3>
${productName}
</body>
394

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



