5、EL和ONGL的对比使用
取Session中的值
${session.user.userId}
${sessionScope.user.userId}
基本语法
一、EL简介
1.语法结构
${expression}
2.[]与.运算符
EL 提供.和[]两种运算符来存取数据。
当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字的符号,就一定要使用 []。例如:
${user.My-Name}应当改为${user["My-Name"] }
如果要动态取值时,就可以用[]来做,而.无法做到动态取值。例如:
${sessionScope.user[data]}中data 是一个变量
3.变量
EL存取变量数据的方法很简单,例如:${username}。它的意思是取出某一范围中名称为username的变量。
因为我们并没有指定哪一个范围的username,所以它会依序从Page、Request、Session、Application范围查找。
假如途中找到username,就直接回传,不再继续找下去,但是假如全部的范围都没有找到时,就回传null。
属性范围在EL中的名称
Page PageScope
Request RequestScope
Session SessionScope
Application ApplicationScope
二、EL隐含对象
1.与范围有关的隐含对象
与范围有关的EL 隐含对象包含以下四个:pageScope、requestScope、sessionScope 和applicationScope;
它们基本上就和JSP的pageContext、request、session和application一样;
在EL中,这四个隐含对象只能用来取得范围属性值,即getAttribute(String name),却不能取得其他相关信息。
例如:我们要取得session中储存一个属性username的值,可以利用下列方法:
session.getAttribute("username") 取得username的值,
在EL中则使用下列方法
${sessionScope.username}
2.与输入有关的隐含对象
与输入有关的隐含对象有两个:param和paramValues,它们是EL中比较特别的隐含对象。
例如我们要取得用户的请求参数时,可以利用下列方法:
request.getParameter(String name)
request.getParameterValues(String name)
在EL中则可以使用param和paramValues两者来取得数据。
${param.name}
${paramValues.name}
3.其他隐含对象
cookie
JSTL并没有提供设定cookie的动作,
例:要取得cookie中有一个设定名称为userCountry的值,可以使用${cookie.userCountry}来取得它。
header和headerValues
header 储存用户浏览器和服务端用来沟通的数据
例:要取得用户浏览器的版本,可以使用${header["User-Agent"]}。
另外在鲜少机会下,有可能同一标头名称拥有不同的值,此时必须改为使用headerValues 来取得这些值。
initParam
initParam取得设定web站点的环境参数(Context)
例:一般的方法String userid = (String)application.getInitParameter("userid");
可以使用 ${initParam.userid}来取得名称为userid
pageContext
pageContext取得其他有关用户要求或页面的详细信息。
${pageContext.request.queryString} 取得请求的参数字符串
${pageContext.request.requestURL} 取得请求的URL,但不包括请求之参数字符串
${pageContext.request.contextPath} 服务的web application 的名称
${pageContext.request.method} 取得HTTP 的方法(GET、POST)
${pageContext.request.protocol} 取得使用的协议(HTTP/1.1、HTTP/1.0)
${pageContext.request.remoteUser} 取得用户名称
${pageContext.request.remoteAddr } 取得用户的IP 地址
${pageContext.session.new} 判断session 是否为新的
${pageContext.session.id} 取得session 的ID
${pageContext.servletContext.serverInfo} 取得主机端的服务信息
三、EL运算符
1.算术运算符有五个:+、-、*或$、/或div、%或mod
2.关系运算符有六个:==或eq、!=或ne、<或lt、>或gt、<=或le、>=或ge
3.逻辑运算符有三个:&&或and、||或or、!或not
4.其它运算符有三个:Empty运算符、条件运算符、()运算符
例:${empty param.name}、${A?B:C}、${A*(B+C)}
四、EL函数(functions)。
语法:ns:function( arg1, arg2, arg3 …. argN)
其中ns为前置名称(prefix),它必须和taglib 指令的前置名称一置
---------------------------------------------
补充:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
FOREACH:
var="item"
begin="0"
end="9"
step="1"
varStatus="var">
……
OUT:
c:out>将value 中的内容输出到当前位置,这里也就是把logininfo 对象的
username属性值输出到页面当前位置。
${……}是JSP2.0 中的Expression Language(EL)的语法。它定义了一个表达式,
其中的表达式可以是一个常量(如上),也可以是一个具体的表达语句(如forEach循环体中
的情况)。典型案例如下:
? ${logininfo.username}
这表明引用logininfo 对象的username 属性。我们可以通过“.”操作符引
用对象的属性,也可以用“[]”引用对象属性,如${logininfo[username]}
与${logininfo.username}达到了同样的效果。
“[]”引用方式的意义在于,如果属性名中出现了特殊字符,如“.”或者“-”,
此时就必须使用“[]”获取属性值以避免语法上的冲突(系统开发时应尽量避免
这一现象的出现)。
与之等同的JSP Script大致如下:
LoginInfo logininfo =
(LoginInfo)session.getAttribute(“logininfo”);
String username = logininfo.getUsername();
可以看到,EL大大节省了编码量。
这里引出的另外一个问题就是,EL 将从哪里找到logininfo 对象,对于
${logininfo.username}这样的表达式而言,首先会从当前页面中寻找之前是
否定义了变量logininfo,如果没有找到则依次到Request、Session、
Application 范围内寻找,直到找到为止。如果直到最后依然没有找到匹配的
变量,则返回null.
如果我们需要指定变量的寻找范围,可以在EL表达式中指定搜寻范围:
${pageScope.logininfo.username}
${requestScope.logininfo.username}
${sessionScope.logininfo.username}
${applicationScope.logininfo.username}
在Spring 中,所有逻辑处理单元返回的结果数据,都将作为Attribute 被放
置到HttpServletRequest 对象中返回(具体实现可参见Spring 源码中
org.springframework.web.servlet.view.InternalResourceView.
exposeModelAsRequestAttributes方法的实现代码),也就是说Spring
MVC 中,结果数据对象默认都是requestScope。因此,在Spring MVC 中,
以下寻址方法应慎用:
${sessionScope.logininfo.username}
${applicationScope.logininfo.username}
? ${1+2}
结果为表达式计算结果,即整数值3。
? ${i>1}
如果变量值i>1的话,将返回bool类型true。与上例比较,可以发现EL会自
动根据表达式计算结果返回不同的数据类型。
表达式的写法与java代码中的表达式编写方式大致相同。
IF / CHOOSE:
*
判定条件一般为一个EL表达式。
并没有提供else子句,使用的时候可能有些不便,此时我们可以通过
tag来达到类似的目的:
*
!
类似Java 中的switch 语句,提供了复杂判定条件下的简化处理手法。其
中子句类似case子句,可以出现多次。上面的代码,在奇数行时输出“*”号,
而偶数行时输出“!”。
---------------------------------------------
再补充:
1 EL表达式用${}表示,可用在所有的HTML和JSP
标签 中 作用是代替JSP页面中复杂的JAVA代码.
2 EL表达式可操作常量 变量 和隐式对象. 最常用的 隐式对象有${param}和${paramValues}. ${param}表示返回请求参数中单个字符串的值. ${paramValues}表示返回请求参数的一组值.pageScope表示页面范围的变量.requestScope表示请求对象的变量. sessionScope表示会话范围内的变量.applicationScope表示应用范围的变量.
3 <%@ page isELIgnored="true"%> 表示是否禁用EL语言,TRUE表示禁止.FALSE表示不禁止.JSP2.0中默认的启用EL语言.
4 EL语言可显示 逻辑表达式如${true and false}结果是false 关系表达式如${5>6} 结果是false 算术表达式如 ${5+5} 结果是10
5 EL中的变量搜索范围是:page request session application 点运算符(.)和"[ ]"都是表示获取变量的值.区别是[ ]可以显示非词类的变量
OGNL
OGNL是Object Graph Navigation Language的简称,详细相关的信息可以参考:http://www.ognl.org。这里我们只涉及Struts2框架中对OGNL的基本支持。
OGNL是一个对象,属性的查询语言。在OGNL中有一个类型为Map的Context(称为上下文),在这个上下文中有一个根元素(root),对根元素的属性的访问可以直接使用属性名字,但是对于其他非根元素属性的访问必须加上特殊符号#。
当struts2框架接收到一个HTTP请求时,它立刻创建一个ActionContext、ValueStack、Action对象
在Struts2中上下文为ActionContext,根元素位Value Stack(值堆栈,值堆栈代表了一族对象而不是一个对象,其中Action类的实例也属于值堆栈的一个)。
ActionContext 中的内容如下图:
|
|--application
|
|--session
context map---|
|--value stack(root)
|
|--request
|
|--parameters
|
|--attr (searches page, request, session, then application scopes)
|
因为Action实例被放在Value Stack中,而Value Stack又是根元素(root)中的一个,所以对Action中的属性的访问可以不使用标记#,而对其他的访问都必须使用#标记。
一个OGNL表达式,必须选择ActionContext中的一个对象作为根对象(root),默认情况下,是选择valueStack作为根对象,如果需要使用另外5个对象作为根对象,需要加上#前缀
在
标签 的属性里时,要看这个属性定义的类型是什么,如果是string类型,那么属性的值会被当做普通的string,如果不是string类型,那么属性的值会被直接当成OGNL的表达式
比如说 ,这个
标签 的value属性的类型是object,那么这个value的值,就会被直接作为OGNL表达式进行解析
如果想在string类型的属性中使用OGNL表达式,就需要加上${}或者%{} --------------************************取表达式的值
在jsp页面的其他地方时(即不在
标签 内部),任何情况下都会当成string来处理,这时候如果想使用OGNL表达式,也需要加上${}或者%{}
*****************************************************举例*******************************************************
structs2 中使用el表达式和ognl表达式获得后台实体类中的List值失败
java后台实体类中的结构为:有一个employee对象,employee对象中有自己的属性值,另外还有一个名为degreeList的
list对象,该list对象存的是degree实体,degree实体中含有d_name等属性。现在我想通过上面jsp代码(第一种和第二种)得到这个d_name的值,
正解:
${degree.d_name}是EL,不能用在struts2
标签 里,得用OGNL,试试value
="%{#degree.d_name}"
引用Action的属性
ActionContext中的其他非根(root)元素的属性可以按照如下的方式访问:
or
or
Action类可以使用ActionContext中的静态方法来访问ActionContext。
ActionContext.getContext().getSession().put("mySessionPropKey", mySessionObject);
OGNL与Collection(Lists,Maps,Sets)
生成List的语法为: {e1,e2,e3}.
list="{'name1','name2','name3'}" value="%{'name2'}" />
上面的代码生成了一个HTML Select对象,可选的内容为: name1,name2,name3,默认值为:name2。
生成Map的语法为:#{key1:value1,key2:value2}.
list="#{'foo':'foovalue', 'bar':'barvalue'}" />
上面的代码生成了一个HTML Select对象,foo名字表示的内容为:foovalue,bar名字表示的内容为:barvalue。
判断一个对象是否在List内存在:
muhahaha
boo
muhahaha
boo
取得一个List的一部分:
? – 所有满足选择逻辑的对象
^ - 第一个满足选择逻辑的对象
$ - 最后一个满足选择逻辑的对象
例如:
person.relatives.{? #this.gender == 'male'}
上述代码取得这个人(person)所有的男性(this.gender==male)的亲戚(relatives)
Lambda 表达式
OGNL支持简单的Lambda表达式语法,使用这些语法可以建立简单的lambda函数。
例如:
Fibonacci:
if n==0 return 0;
elseif n==1 return 1;
else return fib(n-2)+fib(n-1);
fib(0) = 0
fib(1) = 1
fib(11) = 89
OGNL的Lambda表达式如何工作呢?
Lambda表达式必须放在方括号内部,#this表示表达式的参数。例如:
#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)]定义了一个Lambda表达式,
#fib(11) 调用了这个表达式。
所以上述代码的输出为:89
在JSP2.1中#被用作了JSP EL(表达式语言)的特殊记好,所以对OGNL的使用可能导致问题,
一个简单的方法是禁用JSP2.1的EL特性,这需要修改web.xml文件:
*.jsp
true
"font-size: large;">"font-size: large;"><%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
OGNL的使用
OGNL的使用
访问Action中的普通属性:
访问Action中的对象属性:
访问Action中的Set属性:
访问Action中的List属性:
访问Action中的Map属性的键:
访问Action中的Map属性的值:
访问Action中的Map属性的指定键对应的值:
访问Action中的Map属性的大小:
访问ActionContext中的普通属性:
访问ActionContext中的对象属性:
访问Action中的普通方法:
访问ActionContext中的某个对象上的普通方法:
访问静态属性:
访问静态方法:
访问Math类中的静态方法:
调用java.util.Date的构造方法:
调用java.util.Date的构造方法创建对象,再调用它的方法:
投影查询:获取userList中所有loginname的列表:
选择查询:获取userList中所有score大于60的loginname列表:60.0}.{loginname}"/>
选择查询:获取userList中所有score大于60并且gender为true的loginname列表:60.0 && #this.gender)}.{loginname}"/>
选择查询:获取userList中所有score大于60并且gender为true的第一个元素的loginname:60.0 && #this.gender)}.{loginname}"/>
选择查询:获取userList中所有score大于60并且gender为true的最后一个元素的loginname:60.0 && #this.gender)}.{loginname}"/>
访问名为xxx的请求参数对应的第一个值:
访问通过ActionContext中放入Request中的属性:
访问通过ServletActionContext中放入Request中的属性:
访问通过ActionContext中放入Session中的属性:
访问通过ServletActionContext中放入Session中的属性:
访问通过ActionContext中放入ServletContext中的属性:
访问通过ServletActionContext中放入ServletContext中的属性:
直接访问属性域中指定名称的属性对应的值:
"color: red">
: ,
"color: blue">
: ,
4.为何使用EL表达式能够访问valueStack中对象的属性
原因是Struts2对HttpServletRequest作了进一步的封装。简略代码如下:
public class StrutsRequestWrapper extends HttpServletRequestWrapper { public StrutsRequestWrapper(HttpServletRequest req) { super(req); } public Object getAttribute_r(String s) { ...... ActionContext ctx = ActionContext. getContext_r(); Object attribute = super. getAttribute_r(s);//先从request范围获取属性值 if (ctx != null) { if (attribute == null) {//如果从request范围没有找到属性值,即从ValueStack中查找对象的属性值 ...... ValueStack stack = ctx. getValueStack_r(); attribute = stack.findValue(s); ...... } } return attribute; } }
5.采用OGNL表达式创建List/Map集合对象
如果需要一个集合元素的时候(例如List对象或者Map对象),可以使用OGNL中同集合相关的表达式。 使用如下代码直接生成一个List对象:
生成一个Map对象: =
Set标签 用于将某个值放入指定范围。 scope:指定变量被放置的范围,该属性可以接受application、session、request、 page或action。如果没有设置该属性,则默认放置在OGNL Context中。 value:赋给变量的值.如果没有设置该属性,则将ValueStack栈顶的值赋给变量。
6.采用OGNL表达式判断对象是否存在于集合中 对于集合类型,OGNL表达式可以使用in和not in两个元素符号。其中,in表达式用来判断某个元素是否在指定的集合对象中;not in判断某个元素是否不在指定的集合对象中,如下所示。 in表达式: 在 不在
not in表达式: 不在 在
7.OGNL表达式的投影功能 除了in和not in之外,OGNL还允许使用某个规则获得集合对象的子集,常用的有以下3个相关操作符。 ?:获得所有符合逻辑的元素。 ^:获得符合逻辑的第一个元素。 $:获得符合逻辑的最后一个元素。 例如代码: - $ 在上面代码中,直接在集合后紧跟.{}运算符表明用于取出该集合的子集,{}内的表达式用于获取符合条件的元素,this指的是为了从大集合books筛选数据到小集合,需要对大集合books进行迭代,this代表当前迭代的元素。本例的表达式用于获取集合中价格大于35的书集合。 public class BookAction extends ActionSupport { private List books; .... @Override public String execute() { books = new LinkedList(); books.add(new Book("A735619678", "spring", 67)); books.add(new Book("B435555322", "ejb3.0",15)); } }
8.property标签 property标签 用于输出指定值: default:可选属性,如果需要输出的属性值为null,则显示该属性指定的值 escape:可选属性,指定是否格式化HTML代码。 value:可选属性,指定需要输出的属性值,如果没有指定该属性,则默认输出ValueStack栈顶的值。 id:可选属性,指定该元素的标识
9. iterator标签 iterator标签 用于对集合进行迭代,这里的集合包含List、Set和数组。 redblue > value:可选属性,指定被迭代的集合,如果没有设置该属性,则使用ValueStack栈顶的集合。 id:可选属性,指定集合里元素的id。 status:可选属性,该属性指定迭代时的IteratorStatus实例。该实例包含如下几个方法: int getCount_r(),返回当前迭代了几个元素。 int getIndex_r(),返回当前迭代元素的索引。 boolean isEven(),返回当前被迭代元素的索引是否是偶数 boolean isOdd(),返回当前被迭代元素的索引是否是奇数 boolean isFirst(),返回当前被迭代元素是否是第一个元素。 boolean isLast(),返回当前被迭代元素是否是最后一个元素。
10.if/elseif/else标签 23 21 都不等
10.url标签
生成类似如下路径: /struts/test/helloworld_add.action?personid=23 红色部分为内容路径。
当标签 的属性值作为字符串类型处理时, “%”符号的用途是计算OGNL表达式的值。 输出结果: #myurl http://www.foshanshop.net
11.表单标签 _checkboxlist复选框
如果集合为list 生成如下html代码: Java .Net RoR PHP
如果集合为MAP 生成如下html代码: 瑜珈用品 户外用品 球类 自行车
12. 表单标签 _checkboxlist复选框 如果集合里存放的是javabean <% Person person1 = new Person(1,"第一个"); Person person2 = new Person(2,"第二个"); List list = new ArrayList(); list.add(person1); list.add(person2); request.setAttribute("persons",list); %> Personid和name为Person的属性
生成如下html代码: 第一个 第二个
13.表单标签 _radio单选框 该标签 的使用和checkboxlist复选框相同。 如果集合里存放的是javabean(personid和name为Person的属性) < s:radio name="beans" list="#request.persons" listKey="personid" listValue="name"/> 生成如下html代码: 第一个 第二个 如果集合为MAP 生成如下html代码: 瑜珈用品 户外用品 球类 自行车 如果集合为list 生成如下html代码: Java .Net
14.表单标签 _select下拉选择框 Java .Net 第一个 第二个 瑜珈用品 户外用品 球类 自行车
总结:
在上边大家都好奇为什么都用struts的S标签 ,因为OGNL是通常要结合Struts 2的标志一起使用,如 等
Action类与JSP页面之间的数据传递
1) 通过HttpServletRequest,HttpSession,ServletContext来传递数据。
a) Action中传数据:在Action类的请求处理方法中先获取各个作用域对象
ServletActionContext.getRequest();
ServletActionContext.getRequest().getSession();
ServletActionContext.getServletContext();
然后调用相应的setAttribute(String "键", Object 值);
b) 在JSP页面中取数据:可以使用EL表达式或代码片段来取出对应作用域中属性值。
c) 页面中的请求参数传递到Action中时,Action中直接定义对应名称的属性,并提供setter方法即可封装此数据。
2) 通过ActionContext实例来传递数据。 ActionContext针对每个正在执行Action的线程中绑定一份。
a) Action中通过ActionContext传递数据。
ActionContext提供了put(String "键", Object 值); //数据不会映射到HttpServletRequest中。
ActionContext提供的getSession().put(String "键", Object 值); //数据会自动映射到HttpSession中。
ActionContext提供的getApplication().put(String "键", Object 值); //数据会自动映射到ServletContext中。
b) 在JSP页面取数据:struts2推荐使用OGNL来取ActionContext中的数据。
1. Struts2中的OGNL的使用。
2. OGNL:对象图导航语言。通过OGNL表达式可以获取对象的属性,调用对象的方法,或构造出对象。
1) OGNL上下文中有一个根对象。这个根对象可以直接获取。不需要#。
2)支持常量:
字符串常量、字符常量、
数值常量:int、long、float、double
布尔常量:true、false
Null常量 : null
支持操作符:支持Java的所有操作符,还支持特有的操作符: ,、 {}、in、not in;
Struts2中的OGNL:
1) Struts2将ActionContext设置为OGNL上下文,并将值栈(ValueStack)作为OGNL的根对象放置到ActionContext中。
2) Struts2总是把当前Action实例放置在值栈的栈顶。所以,在OGNL中引用Action中的属性也可以省略“#”。
常用标签
1)
2)
3)
★4) ...
5)
6、关于JSP的 默认语法、EL、Ognl表达式,Struts Tag 和JSTL标签 库等
JavaWeb 默认的语法,除HTML 外,共有:
1、<% 可以使用Java语言 %>
2、<%! 可以使用Java 语言定义变量或函数,是public 类型的 %>
3、<%= 变量 %> 可以取值
4、<%@ 指令元素 %>
5、 默认标签 语言
以上五种是Javaweb 默认语法,除第五种是标签 语言外,其余上四种都是JavaWeb 默认的语法格式。
此后,JSP2.0之后,引入了 EL 表达语言和 扩展了 标签 语言 称为:JSTL 。
EL 表达式语言,其实可以说是一套独立的编程语言,有自己的语法格式,算式运算符,关系运算符,逻辑运算符,条件运算符等等完整的体系,加上还有一些内置的对象,虽然这些内置的对象都需要Java 支持,但也不失为一套完善的编程语言了。
EL 主要编写在 后缀为.jsp 的页面中,虽然它有自己的语法格式,但其实它的本质是Java类,它会通过Web容器转为特定的Java代码,而后运行在Java虚拟机中,只是为了规范 和方便,所以SUN公司推出了它,但发展到现在,它已经称为JavaWeb不可分割的一部分(虽然JSP页面如今少写业务逻辑)
JSTL 是 JSP2.0 后引入的默认标签 库,记得默认语法中,第五条就是 ,而JSTL可以说是那个的升级版,增加了很多可以直接在 jsp 页面中使用,而格式跟普通HTML类似的标签 。
接下来,谈谈,Struts2.x 中的OGNL 表达式 和 标签 Struts Tag 。
Struts2.x 中的 OGNL 可以说是取代了 默认的EL表达式,它自身本就是 EL 表达式,它与默认的EL表达式语言,区别共有多少,我没有仔细去了解,只能说说大致了解的。
1、 取值范围:
a) 默认的EL表达式的格式 ${ },它能单独使用,默认取值范围在 :page (PageContext)
b) OGNL 表达式常用的格式为 # ,还有 $ % 等,默认的取值范围是:valueStack 值栈。
2、 使用范围
a) 默认的EL表达式能单独使用。
b) OGNL 需要和 标签 Struts Tag 联合使用
3、 优势
a) EL 表达式 在于有完整的体系,功能完善,
b) OGNL 没有那些运算,关系,条件,逻辑等等运算符,但它在于能单独访问对象(类),包括静态类,静态方法等
4、 搭档
a) EL + JSTL 。默认的EL虽然能完成大部分功能,但天生缺少的一些,比如遍历等,就需要配合JSTL使用,功能更为完善。
b) OGNL + Struts Tag 。OGNL 负责取值,Struts Tag 负责控制流程。分工明确!
Struts 2.x 的 Struts Tag ,是Struts 默认的标签 库,和OGNL 一起使用功能更强大。一般来说,OGNL 取值,而Struts Tag 控制流程和显示。
它取代了 默认的JSTL标签 库。
7、struts2中#、%和$这三个符号的使用方法
一、"#"的用法
1、 访问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属性,直到找到为
2、用于过滤和投影(projecting)集合,如books.{?#this.price<100};
3、构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
二、"%"的用法
“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:
%的用途
三、"$"的用法
1、用于在国际化资源文件中,引用OGNL表达式
2、在Struts 2配置文件中,引用OGNL表达式
例如:
ListPhotos.action? albumId=${albumId}