Struts2 的OGNL与值栈学习

1.OGNL的概述

1.1什么是OGNL
  • OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。
  • OGNL:对象图导航语言,是第三方的表达式语言,比EL表达式强大很多倍,可以调用对象的方法和获取Struts2的值栈的数据。
1.2.为什么要学习OGNL?
  • 支持对象方法的调用
  • 支持类静态方法的调用和值访问,与EL表达式一样,可以取值
  • 支持赋值操作和表达式串联
  • 支持访问OGNL上下文和ActionContext
  • 可以操作(创建)对象集合
  • 可以直接new一个对象
1.3 OGNL的作用
  • 用于JSP页面的取值
  • EL表达式语言也用于页面取值,不需要配置就可以直接使用,是JSP页面默认的取值标准
  • OGNL表达式语言是Struts标签默认支持的表达式语言,必须配置Struts标签用!!!
1.4.OGNL使用的要素
  • 表达式
    • 表达式就是一个带有语法含义的字符串,这个字符串规定了操作的类型和操作的内容,OGNL支持大量的表达式语法,不仅支持“链式”对象访问路径,还支持在表达式中进行简单额计算。
  • 根对象
  • Context
1.5.OGNL在java环境的入门
  • 1.调用对象方法
// OGNL调用对象的方法
	@Test
	public void demo1() throws OgnlException {
		//获取context
		OgnlContext context=new OgnlContext();
		//获取根对象
		Object root =context.getRoot();
      //执行表达式
		Object obj=Ognl.getValue("'hello'.length()", context, root);
		System.out.println(obj);
	}
  • 2.访问对象的静态方法
//访问对象的静态方法
	@Test
public void demo2() throws OgnlException {
	//获取context
			OgnlContext context=new OgnlContext();
			//获取根对象
			Object root =context.getRoot();
			//执行表达式:@类名@方法名
Object obj = Ognl.getValue("@java.lang.Math@random()", context, root);
			System.out.println(obj);
	}
  • 3.获取Root中的数据
//访问root中的数据,不加#
	@Test
	public void demo3() throws OgnlException {
		//获取context
		OgnlContext context=new OgnlContext();
		//new一个对象出来(一个实体User类,提供get、set,无参、有参)
		User user=new User("aaa","123");
		//向root中存储值
		context.setRoot(user);
		//获取根对象
		Object root =context.getRoot();
		//执行表达式
String username = (String) Ognl.getValue("username", context, root);
String password = (String) Ognl.getValue("password", context, root);
		System.out.println(username+" "+password);
	}
  • 4.访问context中的数据
//访问context中的数据,需要加#
	@Test
	public void demo4() throws OgnlException {
		//获取context
		OgnlContext context=new OgnlContext();
		//获取根对象
		Object root =context.getRoot();
		//向context中存入数据
		context.put("name", "老王");
		Object value = Ognl.getValue("#name", context,root);
		System.out.println(value);
	}
1.6 OGNL在Struts2环境下的入门
  • 1.可以直接访问对象的方法
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
	<h1>OGNL在Struts2环境中的入门</h1>
	<s:property value="'struts'.length()" />
	-------------------------------
	<h3>调用对象的静态方法</h3>
	<!--静态方法访问在Struts2中默认是关闭的,需要开启一个常量-->
	<s:property value="@java.lang.Math@random()" />
</body>
</html>
  • 2.对象的静态方法的访问
<!--在struts.xml中开启静态方法访问  -->
	<constant name="struts.ognl.allowStaticMethodAccess"
	value="true"></constant>

2.值栈的概述

2.1.什么是值栈
  • ValueStack是Struts的一个接口,字面意思是值栈,OgnlValueStack是ValueStack的实现类,客户端发起一个请求struts2架构会创建一个action实例同时创建OgnlValueStack值栈实例,OgnlValueStack贯穿整个Action的生命周期,struts2中使用OGNL将请求Action的参数封装为对象存储到值栈中,并通过OGNL表达式读取值栈中的对象属性值。
  • ValueStack其实就类似于数据的中转站(Struts2中的数据都保存在ValueStack中)
2.2.值栈的内部结构
  • ValueStack中主要有两个区域
    • root区域:就是一个ArrayList,里面一般放置对象,获取root的数据不需要加#

    • context区域:就是一个Map,里面放置的是web开发常用的对象数据的引用。获取数据时加#,下面是常见的web对象的引用

      > request
      > session
      > application
      > parameters
      > attr
      
2.3.值栈与ActionContext的关系
  • ServletContext:Servlet的上下文
  • ActionContext:Action的上下文
    • 通过源码查看到,当请求过来的时候,执行过滤器中的doFilter方法,在这个方法中创建ActionContext,在创建的过程中,创建了ValueStack对象,将ValueStack对象传递给ActionContext对象,所以可以通过ActionContext获取值栈对象。
    • ActionContext对象之所以能够访问Servlet的API(访问的是域对象的数据),因为在其内部有值栈的引用。
2.4.获取值栈的方法
  • 1.通过ActionContext对象获取值栈
public class ValueStackDemo2 extends ActionSupport {
//获得ValueStack对象方式一
	@Override
	public String execute() throws Exception {
   ValueStack valueStack1 = ActionContext.getContext().getValueStack();
	return NONE;
  • 2.在Struts2的内部,将值栈存入request中一份。
ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest().
getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
  • 注意:一个Action的实例,只会创建一个ValueStack的对象
2.5操作值栈–>向值栈中存入数据
  • 1.在Action中提供属性的get方法
    • 默认情况下,将Action对象压入到值栈,Action的属性也会在值栈
public class ValueStackDemo3 extends ActionSupport {
	private User user;
	public User getUser() {
		return user;
	}
	//操作ValueStack
	@Override
	public String execute() throws Exception {
		user=new User("李佳","22222");
		return SUCCESS;
	}
}
  • 2.使用ValueStack中本身的方法

public class ValueStackDemo4 extends ActionSupport {
 @Override
public String execute() throws Exception {
//向值栈中保存数据
	 //获得值栈对象
	 ValueStack valueStack = ActionContext.getContext().getValueStack();
	 
	 User user=new User("李佳","2333");
	 //现在user在栈顶
	 valueStack.push(user);
	 
	 valueStack.set("name", "小李子");
	 return SUCCESS;
}

2.6获取值栈的数据

  • 1.获取值栈中的数据就是在页面中使用OGNL表达式即可。
public class ValueStackDemo5 extends ActionSupport {

	@Override
	public String execute() throws Exception {
   //获取值栈的数据
		
		//向值栈中保存一个对象
		User user=new User("aaa","1223");
		ActionContext.getContext().getValueStack().push(user);
		
		//向值栈中保存一个集合
		List<User> list = new ArrayList<User>();
		list.add( new User("aaa", "111"));
		list.add( new User("bbb", "222"));
		list.add( new User("ccc", "333"));
		list.add( new User("ddd", "444"));
		ActionContext.getContext().getValueStack().set("list",list);
		
		//向context中存入数据
	ServletActionContext.getRequest().setAttribute("name", "问天");
ServletActionContext.getRequest().getSession().setAttribute("name", "李");
ServletActionContext.getServletContext().setAttribute("name", "砂皮");
		return super.execute();
	}
  • 页面取值手段
<body>
	<h1>查看值栈的数据</h1>
	<s:debug></s:debug>

	<!--获取一个对象的数据  -->
	<s:property value="username" />
	<s:property value="password" />

	<!-- 获取集合中的数据 -->
	<s:property value="list[0].username" />
	<s:property value="list[0].password" />
	<s:property value="list[1].username" />
	<s:property value="list[1].password" />
	<s:property value="list[2].username" />
	<s:property value="list[2].password" />


	<!--获取context中的数据  -->
	<s:property value="#request.name" />
	<s:property value="#session.name" />
	<s:property value="#application.name" />
	<s:property value="#attr.name" />
</body>

2.7 OGNL表达式中的特殊字符

  • #的用法
<h1>#符号的用法</h1>
	<h3>获取context中的数据</h3>
	<%
		request.setAttribute("name", "阿尔法");
	%>
	<s:property value="#request.name" />

	<h3>构建map集合</h3>
	<!-- list集合 -->
	<s:iterator value="{'aaa','bbb','ccc'}">
		<s:property value="i" />
		<s:property value="#i" />
	</s:iterator>
	<!--map集合  -->
	<s:iterator value="#{'a':'10','b':'20','c':'30','d':'40'}">
	<s:property value="key"/>=
	<s:property value="value"/>
	</s:iterator>
  • %的用法
<body>
	<h1>%的用法</h1>
	<%
		request.setAttribute("name", "家家");
	%>
	姓名:
	<s:textfield name="name" value="%{#request.name}"></s:textfield>
	<!--这中方式不可以,被识别成字符串  -->
	<s:property value="%{#request.name}" />
</body>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值