Struts2学习(七)-----------OGNL

Struts 2框架使用OGNL作为默认的表达式语言

使用 OGNL,可以用简洁的语法来完成对 java 对象的导航。通常来说:通过一个“路径”来完成对象信息的导航,这个“路径”可以是到 java bean 的某个属性,或者集合中的某个索引的对象,等等,而不是直接使用 get 或者 set 方法来完成

在struts2中,OGNL表达式需要配合Struts标签才可以使用


OGNL三要素

  • 表达式:OGNL根据表达式解析该干什么,表达式就是有语法结构的字符串
  • Root对象:也是ValueStack(值栈),可以理解为OGNL的操作对象。当我们指定了一个表达式的时候,需要针对Root对象来进行OGNL表达式的计算并且返回结果。
  • 上下文(context):有lRoot对象和表达式,我们就可以使用OGNL进行简单的操作了,如对Root对象的赋值与取值操作。但是,实际上在OGNL的内部,所有的操作都会在一个特定的数据环境中运行。这个数据环境就是上下文环境(Context)。OGNL的上下文环境是一个Map结构,称之为OgnlContext。Root对象也会被添加到上下文环境当中去

 


 Ognl 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了java.utils.Map接口

Struts 2中的OGNL Context实现者为ActionContex。当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action ,然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。


 

1. 访问值栈中的action的普通属性

首先struts.xml文件如下:配置文件模块化,包含ognl.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />
    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
	<include file="com/bjsxt/struts2/ognl/ognl.xml"/>
    
</struts>

ognl.xml配置如下:把constant常量的配置放在主配置文件struts2.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>
	<package name="user" namespace="/user" extends="struts-default">
		<action name="user" class="xidianlili.struts2.user.action.UserAction">
		<result>/ognl.jsp</result>
		</action>		
	</package>
</struts>

找到对应的action类是UserAction类:有两个属性,可以进行值接受参数,当struts2接到请求,先创建actioncontext,valuestack,在加载这个action类,再把类中的内容放到valuestack中

package xidianlili.struts2.user.action;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
	private String name;
	private String password;

	public String getName() {
		return name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

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

ognl.jsp文件如下:

<?xml version="1.0" encoding="GB18030" ?>
<%@ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding="GB18030"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030" />
<title>OGNL表达式语言学习</title>
</head>
<body>
	<ol>
		<li>访问值栈中的action的普通属性: name = <s:property value="name"/> </li>
        <li>访问值栈中的action的普通属性: password = <s:property value="password"/> </li>
	</ol>	
	<s:debug></s:debug>
</body>
</html>

访问的url是http://localhost:8088/myStrutsDemo03/user/user?name=lili&password=666666

这里都是搭配struts2的property标签,用来输出指定的值

结果:可以看到值栈中的内容是action类中的内容,根据 <s:property value="name"/>可以获得。其中vlaue的值就是ognl的表达式,value属性被定义成object对象,所以struts不会把"name"解析成字符串。

2.访问值栈中对象的普通属性

在action类UserAction中添加属性User,以及其set get方法

User类的代码如下:有属性age以及空构造器

package com.bjsxt.struts2.ognl;

public class User {
	private int age = 8;
	public User() {
		
	}
	public User(int age) {
		super();
		this.age = age;
	}

	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "user" + age;
	}
}

ognl.jsp文件如下:

<li>访问值栈中对象的普通属性(get set方法):<s:property value="user.age"/> </li>

这里的ognl表达式是user.age,我们想通过ognl表达式来访问user.age的值,这里区别于domin model接受参数,下面会讲到。那么访问结果是什么样的

可以看到这个时候值栈的user是空的,我们并没有访问到age ,按理说我们可以访问到值栈中的password和name就应该可以访问user,但是这里并没有根据ognl的表达式给我们构造user对象,让我们用

回顾domin model接受参数,我们也并没有对user进行初始化构造,但是我们通过在url后面传入参数就可以接受,所以这里的原因就是我们没有给user对象传递参数。

修改url,后面传入user.age=18,可以看到我们访问到对象,所以我们可以得到ognl的结论 :

  • 我们使用如user.age这样的ognl表达式,必须通过向domin model那样先传入参数,才会构造user对象,调用其age的set get等方法让我们访问到值,这个时候要注意,在user里面一定要有参数为空的构造方法,否则user也为空
  • 要是不在url后面传递参数,也可以选择在Action类中自己new User对象

  •  这样结果就是:访问到user中age的默认值,当然也可以在user里添加有参数的构造器来指定age

 3.访问值栈中对象的普通属性(为什么叫OGNL)

我们在action类中在添加一个属性,并添加set get方法

这个时候我们看cat类是这样定义的:它里面有一个属性是Dog类型的,以及一个普通方法

package xidianlili.struts2.user.action;

public class Cat {	
	private Dog friend;
	public Dog getFriend() {
		return friend;
	}
	public void setFriend(Dog friend) {
		this.friend = friend;
	}
	public String miaomiao() {
		return "miaomiao";
	}
}

那我们在看Dog类的定义:有name属性,set get方法 构造器

package xidianlili.struts2.user.action;

public class Dog {	
	private String name;	
	public Dog() {
		
	}
	public Dog(String name) {
		super();
		this.name = name;
	}	
	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "dog: " + name;
	}
}

这个时候ognl.xml中的连接:

  <li>访问值栈中对象的普通属性(get set方法): <s:property value="cat.friend.name"/></li>
ognl的表达式是cat.friend.name,我们根据结构UserAction对象包含Cat,Cat包含Dog,所以这个ognl全称是Object graph Navigation Language对象导航图语言就是说明了对象之间的关系,通过表达式中的"."可以看出来

我们看一下UserAction中值栈的内容,增加了Cat的内容但是为空,根据上面的内容我们没有传递所以是空的

进行参数传递:可以访问对象到dog的name,这里进行值传递的时候,我们是从cat开始的,cat在值栈中有标签,然后根据ognl表达式一直找到name进行赋值

 

4.访问值栈中对象的普通方法

上面两个内容都是通过ognl表达式访问值栈对象的属性,比如name,password,我们也可以通过ognl表达式访问这样对象的普通方法。访问password是String类,有length(),方法,以及Cat类中我们自定义一个miaomiao()方法,我们就通过ognl表达式访问这些方法的返回值

  •         <li>访问值栈中对象的普通方法:<s:property value="password.length()"/></li>
            <li>访问值栈中对象的普通方法:<s:property value="cat.miaomiao()" /></li>

结果:注意的是这里也要给cat传递参数要不然没有cat对象

 或者就在在Action类中自己构建Cat对象

 就可以直接进行访问:

5.访问Action中对象的普通方法 

在UserAction中定义一个普通方法

我们就可以通过ognl表达式来访问,直接给出方法返回的字符串,这个时候值栈中的内容并没有增加

         <li>访问值栈中action的普通方法:<s:property value="m()" /></li>

6.访问静态方法 静态属性以及Math中的静态方法

  • 普通类中的静态属性和方法

  • 不需要在Action类中添加有静态属性和方法的类的对象作为属性

首先定义一个类,包含静态属性,静态方法如下:

package xidianlili.struts2.user.action;

public class S {
	public static String STR = "STATIC STRING";
	
	public static String s() {
		return "static method";
	}
}

然后用ognl表达式访问:第一个@后面加类名第二个@后面加要访问的静态属性和静态方法
    <li>访问静态方法:<s:property value="@xidianlili.struts2.user.action.S@s()"/></li>
    <li>访问静态属性:<s:property value="@xidianlili.struts2.user.action.S@STR"/></li>

但是结果我们并没有访问到静态方法

问题:找到源文件的常量说明发现静态加载默认是false

 解决:在struts.xml文件中添加就可以成功访问

    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>

  • Math类中的静态方法

固定用法,只有math可以使用的ognl表达式的格式:就是两个@@后加Math类的静态方法

  <li>访问Math类的静态方法:<s:property value="@@max(2,3)" /></li>

7.OGNL表达式投影(过滤)就是根据List来访问元素

首先在Action类中定义一个List叫users,元素的属性是User类,里面有一个属性age,有带参数的构造方法

我们在UserAction的构造方法里初始化users,增加元素

 

OGNL表达式为:

         <li>投影(过滤):<s:property value="users.{?#this.age==1}[0]"/></li>
        <li>投影:<s:property value="users.{^#this.age>1}.{age}"/></li>
        <li>投影:<s:property value="users.{$#this.age>1}.{age}"/></li>
        <li>投影:<s:property value="users.{$#this.age>1}.{age} == null"/></li>

1. 是正则表达式的知识,把users中的对象挨个拿过来匹配,直到对象的age==1取出这样的集合,[0]的第一个返回

#this.age>1  是意思是把users里面的对象age大于1的拿出来,我们这里是uesr2和user3满足 。

^是取出开始元素        $是取出末尾元素    ==null  是判断满足条件的集合是否为空

    <li>投影(过滤):<s:property value="users.{?#this.age==1}[0].{age}"/></li>
     <li>投影:<s:property value="users.{?#this.age>1}"/></li>

8.OGNL表达式访问list set map元素

        <li>访问List:<s:property value="users"/></li>
        <li>访问List中某个元素:<s:property value="users[1]"/></li>
        <li>访问List中元素某个属性的集合:<s:property value="users.{age}"/></li>
        <li>访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> |                         
        <s:property value="users[0].age"/></li>
        <li>访问Set:<s:property value="dogs"/></li>
        <li>访问Set中某个元素:<s:property value="dogs[1]"/></li>
        <li>访问Map:<s:property value="dogMap"/></li>
        <li>访问Map中某个元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap['dog101']"/> | <s:property value="dogMap[\"dog101\"]"/></li>
        <li>访问Map中所有的key:<s:property value="dogMap.keys"/></li>
        <li>访问Map中所有的value:<s:property value="dogMap.values"/></li>
        <li>访问容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/> </li>

9.[]访问action对象 

<li>[]:<s:property value="[0].name"/></li> 

 <li>[]:<s:property value="[0]"/></li>     [0]返回的值栈中所有的action对象

 比如我们利用服务器端跳转action,

<struts>
	<package name="user" namespace="/user" extends="struts-default">
		<action name="user" class="xidianlili.struts2.user.action.UserAction">
		<result>/ognl.jsp</result>
		</action>
		<action name="test" class="xidianlili.struts2.user.action.TestAction">
		<result type="chain">user</result>
		</action>
	</package>
</struts>

 访问http://localhost:8088/myStrutsDemo03/user/test,结果还是到ognl.jsp,利用[]访问action对象,将用到的action对象依次压入值栈中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值