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的模板匹配引擎,据说其性能要比JSP好
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的标志一起使用,如<s:property value="xx" />等。大家经常遇到的问题是#、%和$这三个符号的使用。下面我讲述这个问题:
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>