struts2中的OGNL

最近学习了struts2中OGNL(Object Graph Navigation Language)对象图表导航语言。

1.OGNL是用来干什么的呢?

①把GUI(图形用户界面)元素绑定到模型对象,以及把数据值从一种类型转换到另外一种类型。

②把通用标签与模型对象绑定到一起。

③即使创建List和Map的映射关系与GUI对象配合使用。

④调用对象的方法,而不是仅限于对对象属性的读取和设置的方法。

2.OGNL从哪里获得对象或者说从哪里获得数据呢?

其实我们的struts2中有一个很重要的对象,它是OGNL操作数据对象的来源。他就是我们的Value Stack被称之为值栈。

3.值栈的生命周期

当浏览器没发出一次请求action的时候,struts2都为为每一个action创建一个与之对应的value stack对象,在struts2对Action实例进行属性设置和其他操作之前,value stack就已经被创建并且等待struts2将数据往里面存储。所以简而言之,value stack的生命周期是一次action请求,值栈相当于数据的中转站,在其中保存Action实例和其他对象,当请求结束与之对应的value stack也就被销毁。

4.值栈中包含哪些内容呢?

说了这么多值栈到底包括哪些内容,其实值栈中包含两个逻辑部分,一个是Object Stack另一个是Context Map,如下图所示:


①Object Stack是一个CompoundRoot类型的对象,是一个真正意义的stack,其中存储的是Action实例和与之相关的对象,或者是我们添加到栈中的对象。

②Context Map实际上是对ActionContext对象的引用,是一个OgnlContext类型的对象实际是个map,里面存储的是各种各样的map映射关系。其中尤其和使用比较多的有如下几个:

session:该map包含session域对象中存储的属性

request:该map包含request域对象中存储的属性

parameters:该map包含请求的请求参数

application:该map包含application域对象中存储的属性

attr:该map按照如下顺序检索某个属性---->request,session,application

5.值栈中的属性值

①Object Stack中的都是对象栈中的某个对象的属性

②Context Map中的是request,session,application,parameter中的属性值

6.那么我们如何通过OGNL来访问值栈中的数据,并且在GUI中做显示呢?

①首先我们来说一说通过OGNL来获取Object Stack对象栈中的对象的属性。

1)访问的形式有如下三种:object.propertyName,object['propertyName'],object["propertyName"]

2)Object Stack中的对象可以使用从0~n的下表来引用。例如Object Stack中栈顶的对象就可以通过使用[0]来引用,栈顶下面的元素就可以通过[1]来引用,依次往后推。

3)这里需要注意的一点是例如[n].message它的含义是从第n个对象开始检索message属性值,而不是只检索第n个。如果第n个对象中包含message属性那么就返回该值,如果没有message属性值那么就从n继续往后检索message属性值。

4)如果从栈顶开始检索属性值则可以省略[0]部分例如从栈顶开始检索message属性的值,就可以直接写成message即可。

5)知道了如何获得对象属性值,我们就只需要结合OGNL的<s:property />标签就可以在GUI中来显示这些属性值了。例如<s:property value="[0].message" />或者<s:property value="message" />

6)默认情况下Action实例会被放到Object Stack对象的栈顶。

②接下来就要说一下如何通过OGNL来获得Context Map里面的属性值了。

1)访问的形式和访问Object Stack有唯一的区别就是需要在之前加上#,其访问的形式也有三种#object.propertyName,#object['propertyName'],#object["propertyName"],例如我需要访问session中的code属性#session.code,需要返回request中user属性的name属性#request.user.name,按照request,session,application顺序检索code属性#attr.code。
2)同样结合OGNL的<s:property />标签就可以在GUI中来显示这些属性值了。例如<s:property value="#request.user.message" />或者<s:property value="#attr.user.message" />

7.上面我们大致的知道了如何获得Object Stack和Context Map值栈中对象的属性,那么接下来我们具体讲讲如何调用字段和方法呢?

①可以利用OGNL调用任何一个普通java类的公共静态方法和静态属性和被压入到Object Stack栈中对象的公共方法和属性。

1)如何调用一个普通java类的公共静态方法和公共静态的属性呢?

首先struts2默认是禁止调用公共静态方法的,所以我们需要在struts.xml文件中做如下配置允许调用公共静态方法,配置截图如下:


具体的调用公共静态属性的语法如下:@fullyQulifiedClassName@fieldName例如:@java.lang.Math@PI

具体调用公共静态方法的语法如下:@fullyQulifiedClassName@methodName()例如:@java.lang.Math@cos(0)

2)调用Object Stack中对象的属性和方法则更简单,object是Object Stack中的一个对象,语法如下:

调用对象栈中对象的属性object.filedName例如[0].message,调用对象栈中对象的方法object.methodName(param)例如[0].setAge(age)。

8.如果我们值栈中属性是个数组对象我们该如何访问其属性?

①我们通过下标的形式访问数组对象的属性例如对象为colors={'a','b','c'},可以通过colors[2]获得数组属性c。

②可以通过调用length属性获得数组的长度,例如colors.length。

9.如果我们值栈中属性是个List对象我们该如何访问其属性呢?

①我们通过下标的形式访问List对象的属性例如对象为colors=['a','b','c'],可以通过colors[2]获得List属性c。

②可以通过size()方法和size属性来获得List对象的长度,例如colors.size或者colors.size();

③可以通过isEmpty方法和isEmpty属性来获得List对象是否为空。例如colors.isEmpty()或者colors.isEmpty。

10.如果我们值栈中属性是个Map对象我们该如何访问其属性呢?

①我们通过下标的形式访问List对象的属性例如对象为colors={'age':“13”,“name”:"user"},可以通过colors['age']获得属性age对象的键值‘13’。

②可以通过size()方法和size属性来获得Mapt对象的长度,例如colors.size或者colors.size();

③可以通过isEmpty方法和isEmpty属性来获得Map对象是否为空。例如colors.isEmpty()或者colors.isEmpty。

11.最后一点也是很重要的,我们可以使用原始的EL来访问值栈中属性,例如 <s:property value="#request.message" />可以写程${message},所以EL和OGNL结合使用才会更方便。

下面就可大家展示一个java代码实例有助于理解:

index.jsp页面代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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>首页</title>
</head>
<body>
	<form action="/Struts2_4_2/user/user-login.action" method="post">
		用户名<input type="text" name="name"><br>
		爱好<input type="checkbox" name="hobby" value="basketball">篮球<br/>
		<input type="checkbox" name="hobby" value="fish">钓鱼<br/>
		<input type="submit" value="提交">
	</form>
</body>
</html>
struts.xml配置如下:

<?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>
	<!-- 设置允许使用ognl调用静态方法  -->
	<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
	<package name="user" extends="struts-default" namespace="/user">
		<action name="user-login" class="com.yd.action.User" method="getObject">
			<result name="user">/show.jsp</result>
		</action>
	</package>
</struts>

Action类User的代码:

package com.yd.action;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.util.ValueStack;

public class User implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private String hobby;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getHobby() {
		return hobby;
	}
	public void setHobby(String hobby) {
		this.hobby = hobby;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", hobby=" + hobby + "]";
	}
	public String getObject(){
		//System.out.println(this);
		//获得值栈
		ValueStack valueStack=ActionContext.getContext().getValueStack();
		//获得Context Map  contextmap其实就是actioncontext的一个引用里面的内容一样
		Map<String, Object> contextMap=valueStack.getContext();
		contextMap.put("test", "test");
		Map<String, Object> request=(Map<String, Object>) contextMap.get("request");
		Object user=contextMap.get("action");
		//String name=(String) contextMap.get("name");
		//System.out.println(contextMap+"上下文Map中的hobby:"+hobby+",name:"+name);
		//contextMap.put("name", "My name is dog");
		//System.out.println(request.get("name")+"==="+user);
		//获得对象栈Object Stack
		CompoundRoot root=valueStack.getRoot();
		//创建一个stack对象
		Stack stack=new Stack();
		stack.setLength("99");
		stack.setName("My name is list");
		stack.setUser((User)user);
		root.push(stack);
		//在值栈中加入一个数组
		List<String> list=new ArrayList<>();
		list.add("AA");
		list.add("BB");
		root.push(list);
		String[] strs={"AA","BB","CC","DD"};
		root.push(strs);
		return "user";
	}
}
普通java类Stack用于往Object Stack中存储的对象,java代码如下:

package com.yd.action;

import java.util.ArrayList;
import java.util.List;

import com.sun.corba.se.impl.orbutil.StackImpl;

public class Stack extends ArrayList{
	public static String age="ssss";
	private String length;
	private String name;
	private User user;
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	public static String getAge(){
		return age;
	}
	public String getLength() {
		return length;
	}
	public void setLength(String length) {
		this.length = length;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
show.jsp页面的代码:

<%@page import="com.yd.action.User"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>
	<!-- 方法对象栈中的name属性 -->
	<s:property value="[0]['name']"/><br/>
	<!-- 方法上下文map中的action对象的name属性 -->
	<s:property value="#action.name"/>
	<!-- 调用对象栈中的方法 -->
	对象栈的方法:<s:property value="[0].getAge()"/><br>
	<!-- 访问静态变量 -->
	<s:property value="@com.yd.action.Stack@age"/>
	<!-- 访问静态变量的方法 -->
	<s:property value="@com.yd.action.Stack@getAge()"/>
	<br>
	<%
		//创建一个数组
		String[] strs={"AA","BB","CC","DD"};
		//创建一个list
		User user=new User();
		user.setName("aa");
		user.setHobby("bb");
		List list=new ArrayList();
		list.add("QQ");
		list.add("TEL");
		list.add(user);
		//创建一个map
		Map map=new HashMap();
		map.put("id","001");
		map.put("age", "27");
		request.setAttribute("strs", strs);
		request.setAttribute("list", list);
		request.setAttribute("map", map);
	%>
	<!-- ognl来访问数组 -->
	数组元素:<s:property value="#request.strs[3]"/><br>
	链表元素:<s:property value="#request.list[2].hobby"/><br>
	map元素:<s:property value="#request.map['id']"/><br>
	<s:property value="#test"/>
	<s:debug></s:debug>
</body>
</html>
运行结果如下:


















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值