struts2总结(二)

GNL表达式入门


OGNL表达式概述什么是OGNL表达式

OGNL的全称是对象图导航语言(Object-Graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现必要的类型转换。如果把表达式看作是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。

 

 

OGNL表达式的由来:

它原本是xwork2中的默认表达式语言,当年OpenSymphony和apache在合作开发struts2框架时,把这个表达式也引进来了,所以就变成了struts2的默认表达式语言。

结论:在struts2中,ognl表达式就是默认的表达式语言。

 

 

OGNL表达式的使用要求:

要想使用ognl表达式,一般情况下都得需要使用struts2的标签库。

例如:

struts2: <s:textfield name="username" lable="用户名"/>

html:  用户名:<input type="text" name="username"/>

细节:

struts2框架本身有可能把html中的某些字符串看成是ognl表达式。用来给属性赋值。

 

OGNL表达式的基本用法


借助s:property标签输出内容到浏览器


s:property的作用


写法:
	<%--导入标签库--%>
	<%@ taglib uri="/struts-tags" prefix="s" %>
	<%--要想使用OGNL表达式,需要借助struts2的标签--%>
	<s:property value="OGNLExpression"/>
作用:
	把value属性取值所对应的内容输出到浏览器上。注意:它不是把value的值输出到浏览器上。
属性:
	value:取值是一个OGNL表达式。
运行结果:
	此时浏览器不会有任何内容显示。究其原因,我们先要理解【把value属性取值所对应的内容输出到浏览器上】这句话。这句话中有【所对应的内容】这几个字,这几个字就说明它要去某个地方找数据,那自然是找到了就显示,找不到就什么都不显示了。

 

 

 

 

 

把一个OGNL表达式看成字符串的方式

把一个OGNL表达式看成是字符串的方式是:

%{'OGNL表达式'}或者是%{"OGNL表达式"}

到底是使用单引号还是双引号,是由外层引号决定的。以上两种都可以实现。

我们也可以简写,就是把外面的%{}去掉,直接用引号括住表达式。

'OGNL表达式'或者是"OGNL表达式"

 示例代码:

<s:property value="%{'OGNLExpression'}"/> 

<s:property value='%{"OGNLExpression1"}'/>

 

 

 

把一个字符串看成OGNL表达式的方式

把一个字符串看成是OGNL表达式的方式是: %{字符串}

 

 

OGNL表达式调用普通方法

OGNL表达式的强大之处在于它可以让我们在表达式中访问对象的方法,例如下面的代码:


长度:<s:property value="'OGNLExpression'.length()"/><br/>
转大写:<s:property value="'OGNLExpression'.toUpperCase()"/><br/>
分隔:<s:property value="'OGNLExpression'.split('E')"/><br/>

 

 

OGNL表达式访问静态属性和静态方法

OGNL表达式还支持访问静态成员,这其中包括静态属性和静态方法,但是必须按照提供的格式编写,格式是:@包名.包名...类名@静态属性名称。这其中...的含义表示有几级包,就写几个包名。

示例代码如下:

int的最大值:<s:property value="@java.lang.Integer@MAX_VALUE"/>


<%--但是会议用OGNL表达式访问静态方法,需要开启对静态方法访问的支持。
struts2框架默认不支持OGNL表达式的静态方法调用,开启的方式如下:
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
--%>
随机数:<s:property value="@java.lang.Math@random()"/>

OGNL表达式创建集合


list集合 


用HTML在浏览器上输出一个单选性别:
<input type="radio" name="gender" value="男"/>男
<input type="radio" name="gender" value="女"/>女
<br/>
用Struts2的单选按钮标签输出一个单选
<%--s:radio用于在浏览器上显示一个单选按钮
list属性取值是一个OGNL表达式
	{}就表示创建了一个List集合 List list = new ArrayList();
	{'男','女'}
	list.add("男");list.add("女");
--%>
<s:radio name="gender" list="{'男','女'}" label="性别"/>

map集合 


用HTML在浏览器上输出一个单选性别:Map结构
<input type="radio" name="gender" value="male"/>男
<input type="radio" name="gender" value="female"/>女
<br/>
<%--#{}就表示创建了一个Map
	里面的写法
		#{'key':'value','key':'value'......}
 --%>
<s:radio name="gender" list="#{'male':'男','female':'女'}" label="性别"/>

 

ContextMap

ContextMap概述

它是OGNL上下文对象,是struts2中封装数据最大的对象。我们一次请求中所有用到的信息都可以在它里面找到。它是一个Map结构的对象,其中key是字符串,value是一个Object。

 

 

ContextMap中封装的数据

下图是我们在struts2官方文档中找到的,请以此为准:

 

我们把这些内容拿出来逐个分析一下,得到下面的表格:

Map的key(类型是String)

Map的Value (类型是Object)

说明信息

application

Java.util.Map<String,Object>

封装的应用域中的所有数据

    session

Java.util.Map<String,Object>

封装的会话域中的所有数据

    request

Java.util.Map<String,Object>

封装的请求域中的所有数据

    valueStack(特殊)

com.opensymphony.xwork2.ognl.OgnlValueStack

它是List结构

    parameters

Java.util.Map<String,String[]>

封装的是请求参数

    attr

Java.util.Map<String,Object>

封装的是四大域的组合数据,从最小的域开始搜索

    action

com.opensymphony.xwork2.ActionSupport

当前执行的动作类对象

用颜色把它区分开,目的是让我们明确一件事:

蓝色的:是我们已经会了的。

四大域对象在jsp那天就已经学过了。

绿色的:是我们不用管的。

parameters:现在我们已经会用模型驱动了,所以再也不用自己取了。

attrs:由于ContextMap中已经包含了三大域,page域的范围又太小了。

action:在后面我们讲的值栈中,会提供这个当前执行的动作类。

红色的:它是我们第一次接触的,以前不会。而且是struts2中经常用的,所以它是重点!

我们关心的部分,结构如下图所示

 

ActionContext

ActionContext对象概述

它是一个工具类,是struts2框架提供给我们的,可以让我们调用其中的方法,快速的操作ContextMap。用它操作OGNL上下文对象,比直接操作ContextMap要方便很多。

 

 

ActionContext对象以及和ContextMap的关系

ActionContext就相当于对ContextMap进行了一次再封装。

 

 

ActionContext何时创建

由于ActionContext是操作的ContextMap,而ContextMap中封了我们一次请求的所有数据,所以它的创建应该是每次请求访问Action时,即核心控制器(StrutsPrepareAndExecuteFilter)的doFilter方法执行时,

 

 

 

ActionContext的线程安全

我们都知道,java的web工程是多线程的,那么每个线程在访问Action时,都会创建自己的ActionContext,那么是如何保证在获取ActionContext时,每个线程都能获取到自己的那个呢?

答案就是,每次创建ActionContext时,把对象绑定到当前线程上。

 

这是ActionContext类中的方法:

 

 

 

ActionContext的获取

使用ActionContext类中的静态方法,如下图所示:

图中的actionContext到底是什么数据类型呢?

既然说ActionContext是对ContextMap的再封装,那么它是怎么封装的呢?

 

 获取ContextMap中的数据


s:debug标签的使用


<%-- 引入标签库 --%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%--1、struts2的debug标签
	它是一个用于开发阶段的标签,查看我们OGNL上下文中内容的标签 --%>
<s:debug/>

使用OGNL表达式获取Map中的数据

获取Map中的数据,包括ContextMap,以及三大域中的数据。
我们首先往Map和三大域中存入一些数据: 


/**
 * 对ContextMap
 * 	和
 * 	三大域(ServletContext,HttpSession,ServletRequest)
 * 	的存值操作
 */
public class Demo1Action extends ActionSupport {

	/**
	 * Map部分的存值操作
	 * @return
	 */
	public String demo1(){
		//1.获取ActionContext对象		他就是一个Map结构
		ActionContext context = ActionContext.getContext();//从当前线程上获取ActionContext对象
		//2.往Map存入数据
		context.put("contextMap", "hello context map");
		
		//3.获取key为application的Map对象
		//第一种方式:使用map操作,叫解耦的方式,不依赖原始ServletAPI对象
		Map<String,Object> applicationMap = context.getApplication();//(Map<String, Object>) context.get("application");
		applicationMap.put("applicationMap", "hello application map");
		//第二种方式:使用原始ServletAPI对象操作,方便的方式。
		ServletContext application = ServletActionContext.getServletContext();
		application.setAttribute("applicationAttr", "hello application attr");
		return SUCCESS;
	}
}

在页面中使用OGNL表达式获取: 


<%--2、使用OGNL表达式获取Map中的数据 需要借助s:property
获取map的数据:都是根据Key获取value,所以我们要提供的是key。
如何表示key:使用#,后面的内容就表示key
写法:
	#key
--%>
获取ContextMap中的数据:<s:property value="#contextMap"/>
<hr/>
<%--3、使用OGNL表达式获取三大域中的数据
也需要使用s:property标签
写法就是
	#key.key
 --%>
获取key为application的map中的数据
<s:property value="#application.applicationMap"/><br/>
<s:property value="#application.applicationAttr"/>

ValueStack对象


ValueStack对象概述


    ValueStack是Struts的一个接口,字面意义为值栈,OgnlValueStack是ValueStack的实现类,客户端发起一个请求struts2架构会创建一个action实例同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿整个 Action 的生命周期。
    它是ContextMap中的一部分,里面的结构是一个List,是我们可以快速访问数据一个容器。它的封装是由struts2框架完成的。
    通常情况下我们是从页面上获取数据。它实现了栈的特性(先进后出)。

 

ValueStack的内部结构


在 OnglValueStack 中包含了一个CompoundRoot的对象,该对象继承了ArrayList,并且提供了只能操作集合第一个元素的方法,所以我们说它实现了栈的特性。同时,它里面定义了一个ContextMap的引用,也就是说,我们有值栈对象,也可以通过值栈来获取ContextMap。

 

获取ValueStack中的数据

值栈中都有什么

首先我们要明确,值栈中存的都是对象。因为它本质就是一个List,List中只能存对象。

值栈中包含了我们通过调用push方法压栈的对象,当前执行的动作了和一个名称为DefaultTextProvider的类

在我们不操作值栈时,默认的栈顶对象是当前执行的动作类。

在动作类中往值栈中存入数据


/**
 * 对ContextMap中ValueStack的压栈操作
*/
public class Demo2Action extends ActionSupport {	
	private String name = "呵呵";

	/**
	 * 往ValueStack中压栈
	 * @return
	 */
	public String demo2(){
		//1.获取ActionContext对象
		ActionContext context = ActionContext.getContext();
		//2.获取ValueStack对象
		ValueStack vs = context.getValueStack();
		//3.压栈操作
		Student s = new Student();
		s.setName("泰斯特");
		s.setAge(18);
		vs.push(s);
		return SUCCESS;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}	
}

Student类:
/**
 * 一个学生的模型
*/
public class Student implements Serializable {

	private String name;
	private Integer age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}

 

我们可以获取值栈中的什么

一般情况下,我们都是根据debug标签中显示的Property Name来获取Property Value。

当然我们也可以获取栈顶对象。

 

如何让Action中定义的成员出现在值栈中

 

在Action定义一个私有属性,并且提供公有get/set方法,那么该属性就会出现在值栈的Property Name中。显示的名称是根据get/set方法后面的内容决定的,与私有成员变量名称叫什么无关。

 

在页面上使用OGNL表达式获取数据


<%--1、获取值栈中的数据  需要借助struts2的标签s:property
明确的事情:
	1、获取值栈中的数据,我们只能根据值栈中对象的property name获取property value。
	2、获取值栈中的数据,都是直接写属性名称,获取的就是值,并不需要使用任何符号。
它是把value属性的取值作为值栈中对象的property name,在值栈中从栈顶逐个查找,只要找到了就返回结果,并且不再继续查找。
--%>
<s:property value="name"/><br/>
<s:property value="age"/>
<hr/>
<%--2、默认的栈顶对象是:当前执行的动作类 
获取栈顶对象的方式:
	使用s:property标签,不要写value属性
--%>
<s:property/>
<hr/>
<%--3、获取指定位置的对象中的属性值 --%>
<s:property value="[0].name"/><br/>
<s:property value="[1].name"/>


OGNL表达式执行时调用的方法

<%--4、ValueStack中的findValue方法 --%>
<%
ActionContext context = ActionContext.getContext();
ValueStack vs = context.getValueStack();
//其实之前的所有OGNL的操作,最终调用的方法都是findValue.  
//Object value = valueStack.findValue(String expression);
Object o1 = vs.findValue("name");
out.print("findValue方法输出的:"+o1+"<br/>");

Object o2 = vs.findValue("[1].name");
out.print("findValue方法输出的:"+o2+"<br/>");

Object o3 = vs.findValue("#application.applicationMap");
out.print("findValue方法输出的:"+o3+"<br/>");
%>

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值