struts2之OGNL表达式和各种符号说明
1 OGNL概述
OGNL
是对象图导航语言Object-Graph Navigation Language
的缩写,它是一种功能强大的表达式语言(Expression Language
,简称为EL
),通过它简单一致的表达式语法,可以存取对象的属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。
在登录页面输入框的name
用到的名字就是OGNL
的表达式,比如:
“账号:<input type="text" name="account">”,
在欢迎页面使用“<s:property value="account"/>”
两个account
表达式都是相同的,但前一个保存对象属性的值,后一个是取得对象属性的值。表达式语言简单、易懂却又功能强大
2 OGNL的基本使用
2.1 常量与操作符
在OGNL
中,可以使用Java
的常量操作和数学运算。需要注意的是,String
常量可以使用单引号或者双引号括起来,但是 单个字符也是使用单引号
,所以只有在超过一个字符的时候,使用单引号界定的常量才是String
类型的。如果需要只定义一个包含单个字符的String
常量,就需要使用转义。
比如:<s:property value=' "account" '/>
这句话里面的account
就是个字符串,因为它是用单引号
括起来的。
或者<s:property value="7+8"/>
这句话,输出就是15
,也就是数学运算后的值。
2.2 方法调用
OGNL
支持方法的调用,这个在后面有演示,比如访问静态方法,访问集合对象的方法等。
2.3 设置数值及表达式列表
OGNL
让你可以在单条语句中执行逗号分隔的多个表达式,最后一个表达式的返回值作为整条语句的输出。
2.4 使用OGNL访问ValueStack
在OGNL
中,没有前缀代表了访问当前值栈。比如前面的示例中,在欢迎页面中使用的<s:property value="account"/>
,这句话中<s:property>
标签的value
属性的值就是使用的ognl
,它没有任何前缀,就表示直接访问值栈。访问到值栈过后,会按照从栈顶到栈底的顺序,寻找第一个匹配的对象,那就会找到Action
中的account
属性,然后就取到值了
2.5 使用OGNL访问ActionContext
在ognl
中,可以通过符号#
来访问ActionContext
中除了值栈之外的各种值,典型如:
#parameters
:当前请求中的参数,对应request.getParameter(name)
#request
:请求作用域中的属性,对应request.getAttribute(name)
#session
:会话作用域中的属性,对应session.getAttribute(name)
#application
:应用程序作用域的属性#attr
:按照页面page
、请求request
、会话session
和应用application
的顺序,返回第一个符合条件的属性
在引用的时候,需要加上前缀#
,并指定范围,然后写出要引用哪个属性,形如:#paramters.account
2.6 应用示例
这里我们在登陆的例子上稍加修改,来试验一下这些知识。
修改action
,然后设置Session
和Application
的属性值,示例如下:
public class HelloWorldAction extends ActionSupport {
private String account;
private String password;
private String submitFlag;
public String execute() throws Exception {
this.businessExecute();
ActionContext c = ActionContext.getContext();
c.getSession().put("account", "session中的account");
c.getApplication().put("account", "application中的account");
return "toWelcome";
}
/**
* 示例方法,表示可以执行业务逻辑处理的方法,
*/
public void businessExecute(){
System.out.println("用户输入的参数为==="+"account="+account+",password="+password+",submitFlag="+submitFlag);
}
//属性对应的getter/setter方法,省略了
}
修改欢迎页面,在页面上通过OGNL
来获取这些值,示例如下:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%@ taglib prefix="s" uri="/struts-tags"%>
欢迎账号为<s:property value="account"/>的朋友来访
<br>
请求参数中的帐号:<s:property value="#parameters.account"/>
<br>
<%request.setAttribute("account","request的account");%>
请求属性中的帐号:<s:property value="#request.account"/>
<br>
会话属性中的帐号:<s:property value="#session.account"/>
<br>
应用属性中的帐号:<s:property value="#application.account"/>
<br>
attr中的帐号:<s:property value="#attr.account"/>
</body>
</html>
备注
:在ognl
中还有另一种稍稍麻烦的写法来访问属性,形如#request[‘account’]
,等价于使用#request.account
,在访问更复杂对象的时候,两种方法可以混用。一般建议:如果访问对象的属性,建议使用“.”的方式来访问;如果访问Map
等复杂对象结构的时候,建议使用[]
的方式来访问
2.6.1 访问静态方法和静态属性
在OGNL
中,可以通过关键字@
来访问任意类中的静态方法和静态属性,格式为@类的全路径名@属性名称
,或者@类的全路径名@方法名称(参数列表)
。这里要注意一点,在低版本的Struts2
中,默认是开启了访问类的静态方法的,但是在高版本的Struts2
中,比如写作本书使用的2.1.8的版本,默认是关闭了访问类的静态方法的。也就是说,要想访问类的静态方法,需要去开启设置。配置非常简单,在struts.xml
中,添加开启访问类的静态方法的配置,示例如下:
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
写一个类,里面有一个静态方法和一个静态属性供外界访问,示例如下:
package cn.javass.hello.struts2impl.action;
public class MyStatic {
public static String staticTest = "staticTestValue"; // 静态属性
//静态方法
public static void testMethod() {
System.out.println("+++++++++++++++++++static test method.++++++++++++++++++");
}
}
在欢迎页面中添加访问它们的语句,示例如下:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%@ taglib prefix="s" uri="/struts-tags"%>
欢迎账号为<s:property value="account"/>的朋友来访
<br>
静态属性值为:<s:property value="@cn.javass.hello.struts2impl.action.MyStatic@staticTest"/>
<br>
调用静态方法
<s:property value="@cn.javass.hello.struts2impl.action.MyStatic@testMethod()"/>
</body>
</html>
3 ognl中符号#,@,%,$
3.1 #符号
#
符号的用途一般有三种:
3.1.1 访问OGNL上下文和Action上下文
访问OGNL
上下文和Action
上下文#
相当于ActionContext.getContext();
下表有几个ActionContext
中有用的属性:
parameters
包含当前HTTP
请求参数的Map #parameters.id[0]
作用相当于request.getParameter ("id")
request
包含当前HttpServletRequest
的属性(attribute
)的Map
#request.userName
相当于request.getAttribute("userName")
session
包含当前HttpSession
的属性(attribute
)的Map #session.userName
相当于session.getAttribute("userName")
application
包含当前应用的ServletContext
的属性(attribute
)的Map #application.userName
相当于application.getAttribute("userName")
attr
用于按request > session > application
顺序访问其属性(attribute
) #attr.userName
相当于按顺序在以上三个范围(scope
)内读取userName
属性,直到找到为止
3.1.2 过滤和投影集合
过滤和投影(projecting
)集合,如示例中的persons.{?#this.age>20}
3.1.3 构造map
用来构造Map
,例如示例中的#{’foo1′:’bar1′, ’foo2′:’bar2′}
3.2 %符号
%
符号的用途是在标志的属性为字符串类型时,转换为计算OGNL
表达式的值。如下面的代码所示:
构造Map
<s:set name=”foobar” value=”#{’foo1′:’bar1′, ‘foo2′:’bar2′}” />
The value of key “foo1″ is <s:property value=”#foobar['foo1']” />
不使用%:<s:url value=”#foobar['foo1']” />
使用%:<s:url value=”%{#foobar['foo1']}” />
3.3 $符号
$
符号主要有两个方面的用途
3.3.1 引用OGNL
在国际化资源文件中,引用OGNL
表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在${min}同${max}之间
在Struts 2
框架的配置文件中引用OGNL
表达式,例如下面的代码片断所示:
<validators>
<field name=”intb”>
<field-validator type=”int”>
<param name=”min”>10</param>
<param name=”max”>100</param>
<message>BAction-test校验:数字必须为${min}为${max}之间!</message>
</field-validator>
</field>
</validators>
3.3.2 动态的结果集
动态的结果集(dynamic result
)
<struts>
<constant name="struts.devMode" value="true" />
<package name="user" namespace="/user" extends="struts-default">
<action name="user" class="com.bjsxt.struts2.user.action.UserAction">
<result>${r}</result>
</action>
</package>
</struts>
注:${}
:作用是用于在配置文件中从Value stack
(值栈)中取值。
例如:${r}
表示从Value stack
(值栈)中取Action
的(成员属性)的值。注意这个成员属性必需存在
注:此处的${}
不是el
表达式。
get/set
方法。
Action
类中指定了r的值。这样就动态确定了Result
的值
public class UserAction extends ActionSupport {
private int type;
private String r;
public String getR() {
return r;
}
public void setR(String r) {
this.r = r;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public String execute() throws Exception {
if(type == 1) r="/user_success.jsp";
else if (type == 2) r="/user_error.jsp";
return "success";
}
}
3.4 @符号
package com. wjt276.struts2.ognl;
public class S {
public static String STR = "STATIC STRING";
public static String s() {
return "static method";
}
}
<li>
访问静态方法:<s:property value="@com.wjt276.struts2.ognl.S@s()"/></li>
<li>
访问静态属性:<s:property value="@com.wjt276.struts2.ognl.S@STR"/></li>
<li>
访问Math
类的静态方法:<s:property value="@@max(2,3)" /></li>
// 两个@符号
3.5 小结
struts2各个符号总结
$
用于i18n
和Struts
配置文件#
取得ActionContext
的值%
将原本的文本属性解析为ognl
,对于本来就是ognl
的属性不起作用@
用于静态方法或属性的调用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了