欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Struts2 的OGNL与值栈学习

程序员文章站 2022-04-18 11:47:38
...

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("@[email protected]()", 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="@[email protected]()" />
</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>

上一篇: 索引

下一篇: 索引丢失情况