Struts推荐使用功能更加强大的Ognl表达式。El可以完成的功能,Ognl也可以,El不能完成的功能,Ognl也可以。
但是有些程序员,已经习惯了jsp中结合jstl和el表达式,我们可以有两种解决方案:
1.使用struts2自带的标签库,jsp中使用ognl进行操作。
2.不是用struts2自带的标签库,jsp直接结合jstl+el进行操作。
jsp2.0中默认启动对el表达式的支持的。但从Struts2.0.11起,Struts2标签库将不再支持El表达式。
struts2.0.11版本不支持el,因而以前在低版本下写的程式将不能正常运行:
下面是一段分页所用的循环:
<c:forEach var="i" begin="1" end="${requestScope.page.afterPage}" step="1">
<c:if
test="${requestScope.page.indexPage<requestScope.page.totalPage && requestScope.page.indexPage+i<requestScope.page.totalPage}">
<s:url id="afterUrl" value="/photoItemsList.html">
<s:param name="indexPage" value="${requestScope.page.indexPage+i}" /><!-- struts2.0.11中已不支持el,因而<s:url>将取不到相关值-->
</s:url>
<s:a theme="ajax" href="%{afterUrl}" indicator="indicator" showLoadingText="false" targets="pageItems">
<c:out value="${requestScope.page.indexPage+i}" /> </s:a>
</c:if>
</c:forEach>
修改成如下:
<c:forEach var="i" begin="1" end="${requestScope.page.afterPage}" step="1">
<c:set value="${i}" var="var"/>
<c:if test="${requestScope.page.indexPage<requestScope.page.totalPage && requestScope.page.indexPage+i<requestScope.page.totalPage}">
<s:url id="afterUrl" value="/photoItemsList.html">
<s:param name="indexPage" value="#request.page.indexPage+#attr.var" />
</s:url>
<s:a theme="ajax" href="%{afterUrl}" indicator="indicator" showLoadingText="false" targets="pageItems">
<c:out value="${requestScope.page.indexPage+i}" /> </s:a>
</c:if>
</c:forEach>
但我们使用第二种方式时,el可以访问struts2,valuestack中的值。
El表达式使用,还是像以前一样的,但是struts2中添加了一个值栈对象,所以有些小小的变动,搜索的顺序是Page,Reqeust,ValueStack,Session,Application。
值栈中存储的是Action类中的全局变量(在servlet,struts中是不支持直接读取Action类中的值得,要设置到Request,Session等中,进行值得传递)。
测试程序(服务器端):
package com.helloweenvsfei.struts2.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class OgnlElAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
private int i;//来自客户端,能取得
private String j;//额外定义,能取得
private String c="C";//没有get,set方法,EL不能获取
public String getJ() {
j="J";
return j;
}
public void setJ(String j) {
this.j = j;
}
@Override
public String execute() throws Exception {
i=i+100;
String a="wla";//不能获取,除非设值到request等范围
String b="wlb";//不能获取,除非设值到request等范围
HttpServletRequest request=ServletActionContext.getRequest();
// request.setAttribute("a", "locala");
// HttpSession session=request.getSession();
// session.setAttribute("b", "localb");
//要是在取值是没有响应的属性,就是默认值。
request.setAttribute("f", "localf");
request.setAttribute("d", "four local");
HttpSession session=request.getSession();
session.setAttribute("d", "locald");
// 以上三句说明,是按照顺序进行查找的。
//request.setAttribute("j", "action");
//session.setAttribute("j", "action");
//总结出EL的访问顺序,Page,Request,ValueStack,Session,Application
return SUCCESS;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
}
客户端:
<body>
<%-- <% String j="page"; %>
<% pageContext.setAttribute("j","MLDN") ;
%>
--%>
This is my JSP page. <br>
Action:${i};<br/>
Action:${j};<br/>
Action:${c};<br/>
Execute:${requestScope.a};<br/>
Execute:${sessionScope.b};<br/>
Execute:${d};<br/>
Execute:${f};<br/>
<!-- Execute:${requestScope.a};
Execute:${sessionScope.b}; -->
<!--<s:property value="#session.i"/>-->
</body>
关于OGNL:
OGNL全称为Object-Graph Navigation Language,是一种表达式语言(EL)。
EL的支持者认为,在JSP页面中应尽可能地避免 <% %> 这样的标记,而代之以Tag,以使页面更简洁,并体现页面与后台代码分离的设计原则。对此我持保留意见,因为我并不认为使用Tag后的页面的可读性要高于使用<% %>。
Struts 2支持如下几种EL:
· OGNL(Object-Graph Navigation Language): 可以方便地操作对象属性的开源表达式语言
· JSTL(JSP Standard Tag Library): JSP 2.0集成的标准的表达式语言
· Groovy: 基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python、Ruby和Smarttalk等)的一些新特性
· Velocity: 严格来说不是表达式语言,它是一种基于Java的模板匹配引擎
Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:
· 支持对象方法调用,如xxx.doSomeSpecial()
;
· 支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名]
,例如:
@java.lang.String@format('foo %s', 'bar')
或
@tutorial.MyConstant@APP_NAME;
· 支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice()
,这个表达式会返回80;
· 访问OGNL上下文(OGNL context)和ActionContext;
· 操作集合对象。
OGNL是通常要结合Struts 2的标志一起使用,如等。大家经常遇到的问题是#
、%
和$
这三个符号的使用。下面我讲述这个问题:
4.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)的Ma, #session.userName
相当于session.getAttribute("userName")
· application
:包含当前应用的ServletContext
的属性(attribute)的Map,#application.userName
相当于application.getAttribute("userName")
· attr
:用于按request > session > application顺序访问其属性(attribute),#attr.userName
相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止
过滤和投影(projecting)集合
如
books.{?#this.price<100}
构造Map
如
#{'foo1':'bar1', 'foo2':'bar2'}
4.2 %的用法
“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:
<h3>%的用途</h3>
<p>
<s:url value="#foobar['foo1']" />
</p>
<p>
<s:url value="%{#foobar['foo1']}" />
</p>
刷新页面,显示以下内容
%的用途#foobar['foo1']bar1
4.3
的用法“
”有两个主要的用途:
1. 用于在国际化资源文件中,引用OGNL表达式
2. Struts 2配置文件中,引用OGNL表达式,如
<action name="AddPhoto" class="addPhoto"> <interceptor-ref name="fileUploadStack" /> <result type="redirect">ListPhotos.action?albumId=${albumId}</result></action>