【学习笔记】Struts2--03

本文深入解析OGNL(对象图导航语言)的语法与特性,包括取值、赋值、调用方法等操作,并详细介绍其与Struts2框架的集成方式,涵盖值栈原理、参数接收与配置文件的应用。

1.OGNL表达式介绍及语法

ognl表达式的结构图:(根对象和Context对象)

ognl:对象图导航语言.  ${user.addr.name} 这种写法就叫对象图导航.

ognl是一种功能强大的开源表达式语言,可以存取Java对象的任意属性,调用Java对象的方法,能够自动实现类型转换。

struts2中使用OGNL表达式的准备工作:

(1)导包---struts2的包中已经包含了OGNL所需的包

(2)代码示范OGNL表达式语法:取值,赋值,调用方法,调用静态方法,创建对象(List、Map):

package cn.itheima.a_ognl;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

import cn.itheima.bean.User;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;

//展示OGNL语法
public class Demo {
	@Test
	//准备工作
	public void fun1() throws Exception{
		//准备OGNLContext
			//准备Root
			User rootUser = new User("tom",18);
			//准备Context
			Map<String,User> context = new HashMap<String,User>();
			context.put("user1", new User("jack",18));
			context.put("user2", new User("rose",22));
		OgnlContext oc = new OgnlContext();
		//将rootUser作为root部分
		oc.setRoot(rootUser);
		//将context这个Map作为Context部分
		oc.setValues(context);
		//书写OGNL
		Ognl.getValue("", oc, oc.getRoot());
	}
	
	@Test
	//基本语法演示
	//(1)取出root中的属性值
	public void fun2() throws Exception{
		//准备ONGLContext
			//准备Root
			User rootUser = new User("tom",18);
			//准备Context
			Map<String,User> context = new HashMap<String,User>();
			context.put("user1", new User("jack",18));
			context.put("user2", new User("rose",22));
		OgnlContext oc = new OgnlContext();
		oc.setRoot(rootUser);
		oc.setValues(context);
		//书写OGNL
		
		//取出root中user对象的name属性
		String name = (String) Ognl.getValue("name", oc, oc.getRoot());
		Integer age = (Integer) Ognl.getValue("age", oc, oc.getRoot());
		System.out.println(name);
		System.out.println(age);
	}
	@Test
	//基本语法演示
	//(2)取出context中的属性值
	public void fun3() throws Exception{
		//准备ONGLContext
			//准备Root
			User rootUser = new User("tom",18);
			//准备Context
			Map<String,User> context = new HashMap<String,User>();
			context.put("user1", new User("jack",18));
			context.put("user2", new User("rose",22));
		OgnlContext oc = new OgnlContext();
		oc.setRoot(rootUser);
		oc.setValues(context);
		//书写OGNL
		
		//取出context中键为user1对象的name属性
		String name = (String) Ognl.getValue("#user1.name", oc, oc.getRoot());
		String name2 = (String) Ognl.getValue("#user2.name", oc, oc.getRoot());
		Integer age = (Integer) Ognl.getValue("#user2.age", oc, oc.getRoot());
		System.out.println(name);
		System.out.println(name2);
		System.out.println(age);
	}
	
	@Test
	//基本语法演示
	//(3)为属性赋值
	public void fun4() throws Exception{
		//准备OGNLContext
			//准备Root
			User rootUser = new User("tom",18);
			//准备Context
			Map<String,User> context = new HashMap<String,User>();
			context.put("user1", new User("jack",18));
			context.put("user2", new User("rose",22));
		OgnlContext oc = new OgnlContext();
		oc.setRoot(rootUser);
		oc.setValues(context);
		//书写OGNL
		
		//将root中的user对象的name属性赋值
		Ognl.getValue("name='jerry'", oc, oc.getRoot());
		String name = (String) Ognl.getValue("name", oc, oc.getRoot());
		//也可以写一起,但返回值只有一个,就是最后一个。所以多个有返回值的表达式不能写一起
		String name2 = (String) Ognl.getValue("#user1.name='郝强勇',#user1.name", oc, oc.getRoot());
		System.out.println(name);
		System.out.println(name2);
	}
	
	@Test
	//基本语法演示
	//(4)调用方法
	public void fun5() throws Exception{
		//准备ONGLContext
			//准备Root
			User rootUser = new User("tom",18);
			//准备Context
			Map<String,User> context = new HashMap<String,User>();
			context.put("user1", new User("jack",18));
			context.put("user2", new User("rose",22));
		OgnlContext oc = new OgnlContext();
		oc.setRoot(rootUser);
		oc.setValues(context);
		//书写OGNL
		
		//调用root中user对象的setName方法
		Ognl.getValue("setName('lilei')", oc, oc.getRoot());
		String name = (String) Ognl.getValue("getName()", oc, oc.getRoot());
		//多个表达式可以写一起,但返回值只有一个,就是最后一个
		String name2 = (String) Ognl.getValue("#user1.setName('lucy'),#user1.getName()", oc, oc.getRoot());
		
		
		System.out.println(name);
		System.out.println(name2);
	}
	
	
	@Test
	//基本语法演示
	//(5)调用静态方法
	public void fun6() throws Exception{
		//准备ONGLContext
			//准备Root
			User rootUser = new User("tom",18);
			//准备Context
			Map<String,User> context = new HashMap<String,User>();
			context.put("user1", new User("jack",18));
			context.put("user2", new User("rose",22));
		OgnlContext oc = new OgnlContext();
		oc.setRoot(rootUser);
		oc.setValues(context);
		//书写OGNL
		//@完整类名@方法名,某些类可以省略类名
		String name = (String) Ognl.getValue("@cn.itheima.a_ognl.HahaUtils@echo('hello 强勇!')", oc, oc.getRoot());
		//Double pi = (Double) Ognl.getValue("@java.lang.Math@PI", oc, oc.getRoot());
		Double pi = (Double) Ognl.getValue("@@PI", oc, oc.getRoot());
		System.out.println(name);
		System.out.println(pi);
	}	
	
	@Test
	//基本语法演示
	//(6)ognl创建对象-list|map
	public void fun7() throws Exception{
		//准备ONGLContext
			//准备Root
			User rootUser = new User("tom",18);
			//准备Context
			Map<String,User> context = new HashMap<String,User>();
			context.put("user1", new User("jack",18));
			context.put("user2", new User("rose",22));
		OgnlContext oc = new OgnlContext();
		oc.setRoot(rootUser);
		oc.setValues(context);
		//书写OGNL
		
		//创建list对象(存放在root中)
		Integer size = (Integer) Ognl.getValue("{'tom','jerry','jack','rose'}.size()", oc, oc.getRoot());
		String name = (String) Ognl.getValue("{'tom','jerry','jack','rose'}[0]", oc, oc.getRoot());
		String name2 = (String) Ognl.getValue("{'tom','jerry','jack','rose'}.get(1)", oc, oc.getRoot());
	
		/*System.out.println(size);
		System.out.println(name);
		System.out.println(name2);*/
		//创建Map对象(存放在Context中)
		Integer size2 = (Integer) Ognl.getValue("#{'name':'tom','age':18}.size()", oc, oc.getRoot());
		String name3  = (String) Ognl.getValue("#{'name':'tom','age':18}['name']", oc, oc.getRoot());
		Integer age  = (Integer) Ognl.getValue("#{'name':'tom','age':18}.get('age')", oc, oc.getRoot());
		System.out.println(size2);
		System.out.println(name3);
		System.out.println(age);
	}	

}

2.OGNL表达式和Struts2的结合

(1)什么是值栈?

ValueStack(值栈)是struts的一个接口,OgnlValueStack是ValueStack的实现类,客户端发起一个请求,struts2架构会创建一个action实例,同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿整个action的生命周期,struts2中使用ognl将请求action的参数封装为对象,存储到值栈中,并通过ognl表达式读取值栈中的对象属性值。

(2)结合原理

struts2准备了一个OgnlValueStack(值栈),值栈包括root和context。如下:

OgnlContext--->OgnlValueStack
root-->栈
context--->ActionContext

public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {

    public static final String THROW_EXCEPTION_ON_FAILURE = OgnlValueStack.class.getName() + ".throwExceptionOnFailure";

    private static final long serialVersionUID = 370737852934925530L;

    private static final String MAP_IDENTIFIER_KEY = "com.opensymphony.xwork2.util.OgnlValueStack.MAP_IDENTIFIER_KEY";
    private static final Logger LOG = LoggerFactory.getLogger(OgnlValueStack.class);

    CompoundRoot root;
    transient Map<String, Object> context;
   .....

栈继承了ArrayList实现了压栈和出栈功能,默认情况下,栈中放置当前访问的Action对象,ActionContext是一个map结构,存储一些ServletAPI。

struts2对ognl的改进就是:root使用CompoundRoot(自定义栈),使用OgnlValueStack的findValue方法可以在CompoundRoot中从栈顶向栈低查找对象的属性值。

(3)栈的原理

(类似弹夹)(使用ArrayList模拟的)

(4)ognl和struts2的结合体现

(4.1)参数接收:

属性驱动:

对象驱动:

模型驱动:

(4.2)体现在配置文件中

package com.xing.ognl;

import com.opensymphony.xwork2.ActionSupport;

public class demo3 extends ActionSupport{

	private String name;
	
	@Override
	public String execute() throws Exception {
		name="毛泽东";
		return SUCCESS;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	
}
<?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="showvs" namespace="/" extends="struts-default" >
		<action name="Demo1Action" class="cn.itheima.b_showvs.Demo1Action" method="execute" >
			<result name="success" type="dispatcher" >/showvs.jsp</result>
		</action>
		<action name="Demo3Action" class="cn.itheima.d_config.Demo3Action" method="execute" >
			<result name="success" type="redirectAction" >
				<param name="actionName">Demo1Action</param>
				<param name="namespace">/</param>
				<!-- 如果添加的参数struts"看不懂".就会作为参数附加重定向的路径之后.
					 如果参数是动态的.可以使用${}包裹ognl表达式.动态取值
				 -->
				<param name="name">${name}</param>
			</result>
		</action>
	</package>
</struts>

(4.3)struts2的标签(明天讲)

(5)如何获得值栈对象

值栈对象ValueStack与ActionContext对象是互相引用的

//1获得值栈
ValueStack vs = ActionContext.getContext().getValueStack();
//2.操作值栈:将u压入栈顶
vs.push(u);

(6)查看值栈中两部分的内容

访问action,转发到带有debug标签的jsp页面。

<s:debug></s:debug>

 

扩展:

struts2中request对象的getAttribute()方法查找顺序:查找原生request域-->查找ValueStack的root部分-->查找ValueStack的Context部分(即ActionContext)

 

 

转载于:https://my.oschina.net/u/3943244/blog/2120963

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值