Struts2之OGNL表达式语言

 2023-09-11 阅读 13 评论 0

摘要:1.OGNL是Object-GraphNavigationLanguage的缩写,是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。其中OGNL用得最多的地方就是和Str

1.OGNL是Object-Graph Navigation Language的缩写,是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。其中OGNL用得最多的地方就是和Struts2的标签绑定,也可以在配置文件中通过${}使用OGNL表达式。



2.OGNL表达式中有几个常用的符号,下面介绍这三种符号的使用:

(1).OGNL中$号的使用:第一种,可以在国际化资源文件中引用OGNL表达式。第二种,可以在struts.xml配置文件中引用OGNL表达式。

struct用法、(2).OGNL中%号的使用:%符号的用途是在标志属性为字符串类型时,计算OGNL表达式的值。

~使用%{}可以取出保存在值堆栈中的Action对象,直接调用它的方法。

~如果Action类继承了ActionSupport类,那么在页面标签中可以使用%{getText('key')}获取国际化信息。

(3).OGNL中#号的使用:OGNL中的#号可以取出堆栈上下文中存放的对象,访问OGNL上下文和Action上下文。#相当于ActionContext.getContext()。

~其中在栈的上下文中有5个对象(attr,request,session,application,parameters):

attr:用于按request>>session>>application顺序访问其属性,#attr.userName,相当于按顺序从三个范围读取userName属性,直到找到为止。

编写一个程序将两个字符串连接起来、request:包含当前HttpServletRequest的属性的Map,#request.userName,相当于request.getAttribute("userName")。

session:包含当前HttpSession的属性的Map,#session.userName,相当于session.getAttribute("userName")。

application:包含当前应用的ServletContext的属性的Map,#application.userName,相当于application.getAttribute("userName")。

parameters:包含当前HTTP请求参数的Map,#parameters.id[0],相当于request.getParameter("id")。



spring表达式语言,3.获取Action中的属性值或者Action中的对象的某某属性值:

利用<s:property/>标签可以直接获取Action中的引用类型user里面的userName属性,同样可以通过user.address.addr获取user中引用类型address中的addr属性的值,像这种一层层往下传递的访问方式,即所谓的导航,也就是一步步往下调用。



4.调用Action的对象里面的普通方法:

默认的会把Action放到值栈里面去,而值栈在访问的时候,并不需要值栈的名字,当我们使用<s:property value="user.getVOMethod()"/>的时候,它会自动到值栈里面查找Action对象里面有没有user对象,如果发现有user对象,然后它就再找user里面有没有getVOMethod()方法,如果发现有,于是调用getVOMethod()这个方法。

struts和struts2?实际上调用getVOMethod()方法的过程与获取表单中的姓名密码的方式都是相同的,都是到值栈里面去查找,找是否存在user对象,如果存在,接着查找user中是否存在某某属性或方法。



5.调用Action中的静态方法:

我们可以在JSP页面中使用OGNL表达式调用Action中的静态方法,调用Action中的静态方法时,与上面调用user对象的getVOMethod()方法的过程,是截然不同的。此时value的写法是固定的,以@开头,后面跟上具体的包名,然后@加上静态方法,比如<s:property value="@com.gk.action.LoginAction@getStaic()"/>。另外user对象只是LoginAction中的一个属性,这个属性会自动放到值栈里面,而值栈调用的时候,不用加上@或者包名等等,所以直接user.getVOMethod()就可以了。


string str1="hello"。

6.调用JDK类中的静态方法:

可以使用<s:property value="@@floor(46.68)"/>输出floor()的执行结果,这就意味着如果不在@@中指定类的话,默认就表示java.lang.Math类,当前大多数情况下,都不会省略这个类,都会写全了的,然后在后面加上静态方法。



7.集合的伪属性:OGNL能够引用集合的一些特殊的属性,这些属性并不是JavaBean模式,例如size(),length(),当表达式引用这些属性时,OGNL会调用相应的方法,这就是伪属性,比如获取一个List的大小,可以使用<s:property value="testList.size()"/>。

struts2的执行流程,List的伪属性:size,isEmpty,iterator。

Set的伪属性:size,isEmpty,iterator。

Map的伪属性:size,isEmpty,keys,values。

Iterator(迭代)的伪属性:next,hasNext。

Enumeration(枚举)的伪属性:next,hasNext,nextElement,hasMoreElements。


c语言中的表达式有哪些,

8.获取集合中元素的实质就是调用它的toString()方法:

OGNL表达式还可以直接获取集合中的元素,事实上是在调用集合的toString()方法,所以我们可以根据实际情况通过重写集合的toString()方法来实现个性化输出,甚至它还可以像访问数组那样,直接testList[2]获取集合的元素,但这种方法只适用于List,不适用于Map。因为Map的索引是key,不是数值,另外,由于HashSet的元素是没有顺序的,所以也不能用下标获取单个元素。



9.利用投影获取属性:利用投影获取List中对象的userName属性时,其中{}表示的是一个集合,stus.{userName}就表示将stus中所有的userName属性取出组成一个新的列表。

c语言关系表达式。


10.利用选择获取属性:

OGNL表达式是很灵活的,可以同时使用选择技术与投影技术获得属性,#this代表当前元素, 问号?是把所有满足条件的元素都取出来,上箭头^是开始的意思,美元符号$是结束的意思,并且这三个符号返回的都是List列表。



c语言语法表达式要求,11.补充:

(1).OGNL取不到值的时候,它不会报错,而是什么都不显示

(2).<s:property value="[0]"/>返回的是ValueStack中从上至下的所有的Object<s:property value="[1]"/>返回的是ValueStack中从上至下的第二个Objec

(3).<s:property value="[0].username"/>返回的是成员变量username的值假设ValueStack中存在两个Action的话,如果第一个Action如果没有username变量那么它会继续找第二个Action。那么在什么情况下ValueStack中会存在两个Action    

答案是在struts.xml中配置的是从一个Action通过<result type="chain">跳转到另一个Action

(4).<constant name="struts.ognl.allowStaticMethodAccess" value="true"/> 在Struts2.1.6中必须设置struts.ognl.allowStaticMethodAccesstrue之后才允许使用OGNL访问静态方法。而在Struts2.0.11则无需设置,即可直接访问





12.接下来附上一个例子,通过这个例子可以了解如何通过OGNL表达式获取Action中的属性值或者Action对象中的某个属性值,也可以知道如何调用Action中对象里面的普通方法和Action类的普通方法:

(1).新建一个struts2项目,项目名为Struts2_OGNL,首先新建一个Action类,此类继承于ActionSupport类,代码如下:
package com.gk.action;import com.gk.bean.Cat;
import com.gk.bean.User;
import com.opensymphony.xwork2.ActionSupport;public class OgnlAction extends ActionSupport {private String username;private String password;private User user=new User();private Cat cat=new Cat();public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}public Cat getCat() {return cat;}public void setCat(Cat cat) {this.cat = cat;}public String execute(){return SUCCESS;}}


(2).其中又有几个JavaBean类,分别为User,Cat,Dog类,代码分别如下:
User.java文件代码:
package com.gk.bean;public class User {private int age = 8;public User() {}public User(int age) {this.age = age;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "user"+age;}}

Cat.java文件代码:
package com.gk.bean;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.java文件代码:
package com.gk.bean;public class Dog {private String name;public Dog(){}public Dog(String name){this.name=name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String toString(){return "dog"+name;}
}

(3).其中又有两个JSP页面,一个是index.jsp页面,一个为ognl.jsp页面,代码分别如下:
index.jsp文件代码:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><base href="<%=basePath%>"><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body><a href="ognl?username=u&password=p">ognl</a></body>
</html>

ognl.jsp代码如下,通过struts2的标签和OGNL表达式来获取Action的属性:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<%String path = request.getContextPath();String basePath = request.getScheme() + "://"+ request.getServerName() + ":" + request.getServerPort()+ path + "/";
%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"><title>My JSP 'ognl.jsp' starting page</title><meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body><ol><li>访问值栈中的:username = <s:property value="username " /></li><li>访问值栈中的:password=<s:property value="password" /></li><li>访问值栈中对象的普通属性(get set方法):<s:property value="user.age" /></li><li>访问值栈中对象的普通属性(get set方法):<s:property value="cat.friend.name" /></li><li>访问值栈中对象的普通方法<s:property value="cat.miaomiao()"/></li></ol><s:debug></s:debug>
</body>
</html>

(4).struts.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="true"></constant>
<constant name="struts.devMode" value="true"></constant><package name="ognl" namespace="/" extends="struts-default"><action name="ognl" class="com.gk.action.OgnlAction"><result>/ognl.jsp</result></action></package>
</struts>




13.此时我们访问index.jsp页面,结果如下图所示:


点击此链接:


查看一下值栈的内容和上下文环境:


(1).我们可以看到通过超链接传入参数username和password,然后取出值栈里的username和password的属性,然后我们又看到值栈内容中有user属性,我们通过<s:property value="user.age" />获取到了8,原因是我们在User类里面把age初始化为8,在Action类中使用User user=new User这行代码实例化了user对象,然后通过toString方法输出来,所以值栈中user属性的值为user8。


(2).我们通过<s:property value="cat.friend.name" />想要获取cat对象中的friend属性的名字,但是取不出来,是因为我们没有把cat.friend.name这个参数传进去,如果我们输入地址:http://localhost:8083/Struts2_OGNL/ognl?username=u&password=p&cat.friend.name=Lc 的话,就可以取出来了,这也是OGNL如何访问值栈中的内容。



(3)如果我们输入http://localhost:8083/Struts2_OGNL/ognl?username=u&password=p&user.age=90 这个地址的话,年龄就会变为90岁了:



(4).如果我们把User.java文件中public User(){}这个无参构造方法删除掉,然后在OgnlAction中的代码中不实例化这个User类,即OgnlAction.java文件代码如下:
package com.gk.action;import com.gk.bean.Cat;
import com.gk.bean.User;
import com.opensymphony.xwork2.ActionSupport;public class OgnlAction extends ActionSupport {private String username;private String password;private User user;private Cat cat=new Cat();public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}public Cat getCat() {return cat;}public void setCat(Cat cat) {this.cat = cat;}public String execute(){return SUCCESS;}}

Use.java文件代码修改成:
package com.gk.bean;public class User {private int age = 8;public User(int age) {this.age = age;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "user"+age;}}

然后在输入http://localhost:8083/Struts2_OGNL/ognl?username=u&password=p 发现age内容为空了。

如果我们输入地址为:http://localhost:8083/Struts2_OGNL/ognl?username=u&password=p&user.age=23 看能否把age的值23传进去,发现报了个错误,这个错误是实例化User出错,所以一般我们的域模型,即JavaBean对象永远都要提供一个无参的构造方法,要不然就不知道实例化哪个类了。


(5).我们通过<s:property value="cat.miaomiao()"/>这个标签可以直接获取cat对象的miaomiao()方法。如果想取得OgnlAction类的普通方法的话,即Action类普通方法,假如Action类中有个返回类型为String的普通方法mm()的话,可以直接使用<s:property value="mm()"/>,这样就可以获得该Action类普通方法的返回值。


(6).其中为什么OGNL叫对象图导航语言呢?从上面这个例子来说,访问OgnlAction类的user对象的age属性,就可以使用user.age来取到,如果访问OgnlAction类中的cat对象的miaomiao方法,可以使用cat.miaomiao(),如果想访问cat对象的friend对象中的name属性,就用cat.friend.name,这样就可以取得Dog的friend对象的name属性,但是必须要传入参数值进去。




14.本来还想再附上多两个例子的,其中一个例子是使用OGNL来访问静态方法和静态属性的,但是昨天晚上写代码时发现了一些警告和错误,想专门写一篇博客来记录,所以就先写到这,基本的做法和说明都在上面已经讲述。后面我写好访问静态方法和静态属性的那篇文章后,再附上地址。那篇文章我已经写好,对于使用OGNL访问静态方法时出现的问题进行了介绍并解决,文章地址如下:http://blog.csdn.net/u012561176/article/details/44958915



15.以上内容仅供大家学习和参考,谢谢!


版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/47501.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息