本人是一个el(expression language,以下译为表达式语言)的支持者。因为我对<% %>写法极为反感,忘记了在那本书上看到的一句话——“使用标志(tag)的一个目的就是避免在jsp页面中出现过多的<%%>的语句,使页面与后台代码分离。”
表达式语言主要有以下几大好处:
- 避免(mytype) request.getattribute()和mybean.getmyproperty()之类的语句,使页面更简洁;
- 支持运算符(如 -*/),比普通的标志具有更高的自由度和更强的功能;
- 简单明了地表达代码逻辑,使用代码更可读与便于维护。
struts 2中的表达式语言
struts 2支持以下几种表达式语言:
- 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的用法
ognl是通常要结合struts 2的标志一起使用,如等。大家经常遇到的问题是#、%和$这三个符号的使用。下面我想通过例子讲述这个问题:
首先新建名为struts2_ognl的web工程,配置开发环境。之前很多朋友在使用struts 2的过程中都遇到乱码问题。当然乱码问题由来已久,而且涉及多方面的知识,所以并非三言两语可以说明白,而且互联网上也已经有很多这方便的文章,大家可以google一下。不过,如果你在开发的过程,多注意一下,避免乱码问题也不难。乱码多数是由于编码与解码所使用的方式不同造成的,所以我建议大家将编码方式都设为“utf-8”,如<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8" %>。另外,在配置web.xml时使用actioncontextcleanup过滤器(filter),如下面代码所示:
xml version="1.0" encoding="utf-8"?>
<web-app id="webapp_9" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xsi:schemalocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>struts 2 ognldisplay-name>
<filter>
<filter-name>struts-cleanupfilter-name>
<filter-class>
org.apache.struts2.dispatcher.actioncontextcleanup
filter-class>
filter>
<filter-mapping>
<filter-name>struts-cleanupfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter>
<filter-name>struts2filter-name>
<filter-class>
org.apache.struts2.dispatcher.filterdispatcher
filter-class>
filter>
<filter-mapping>
<filter-name>struts2filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<welcome-file-list>
<welcome-file>index.htmlwelcome-file>
welcome-file-list>
web-app>
清单1 webcontent/web-inf/web.xml
“#”主要有三种用途:
- 访问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属性,直到找到为止 |
- 用于过滤和投影(projecting)集合,如books.{?#this.price<100};
- 构造map,如#{'foo1':'bar1', 'foo2':'bar2'}。
下面让我们它们的具体写法,首先是action类代码:
package tutorial.action;
import java.util.linkedlist;
import java.util.list;
import java.util.map;
import javax.servlet.servletcontext;
import javax.servlet.http.httpservletrequest;
import org.apache.struts2.interceptor.servletrequestaware;
import org.apache.struts2.interceptor.sessionaware;
import org.apache.struts2.util.servletcontextaware;
import tutorial.model.book;
import com.opensymphony.xwork2.actionsupport;
publicclass ognlaction extends actionsupport implements servletrequestaware, sessionaware, servletcontextaware {
privatestaticfinallong serialversionuid =1l;
private httpservletrequest request;
private map<string, string> session;
private servletcontext application;
private list<book> books;
publicvoid setservletrequest(httpservletrequest request) {
this.request = request;
}
@suppresswarnings("unchecked")
publicvoid setsession(map session) {
this.session = session;
}
publicvoid setservletcontext(servletcontext application) {
this.application = application;
}
public list<book> getbooks() {
return books;
}
@override
public string execute() {
request.setattribute("username", "max from request");
session.put("username", "max from session");
application.setattribute("username", "max from application");
books =new linkedlist<book>();
books.add(new book("978-0735619678", "code complete, second edition", 32.99));
books.add(new book("978-0596007867", "the art of project management", 35.96));
books.add(new book("978-0201633610", "design patterns: elements of reusable object-oriented software", 43.19));
books.add(new book("978-0596527341", "information architecture for the world wide web: designing large-scale web sites", 25.19));
books.add(new book("978-0735605350", "software estimation: demystifying the black art", 25.19));
return success;
}
}
清单2 src/tutorial/action/ognlaction.java
以上代码分别在request、session和application的范围内添加“username”属性,然后再在jsp页面使用ognl将其取回。我还创建了book对象的列表用于演示“用于过滤和投影(projecting)集合”的功能,至于book的代码大家可以在我前一文章《》看到。
下面是ognl.jsp的代码,内容如下:
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>struts ognl demotitle>
head>
<body>
<h3>访问ognl上下文和action上下文h3>
<p>parameters: <s:property value="#parameters.username"/>p>
<p>request.username: <s:property value="#request.username"/>p>
<p>session.username: <s:property value="#session.username"/>p>
<p>application.username: <s:property value="#application.username"/>p>
<p>attr.username: <s:property value="#attr.username"/>p>
<hr />
<h3>用于过滤和投影(projecting)集合h3>
<p>books more than $35p>
<ul>
<s:iterator value="books.{?#this.price > 35}">
<li><s:property value="title"/> - $<s:property value="price"/>li>
s:iterator>
ul>
<p>the price of "code complete, second edition" is: <s:property value="books.{?#this.title=='code complete, second edition'}.{price}[0]"/>p>
<hr />
<h3>构造maph3>
<s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}"/>
<p>the value of key "foo1" is <s:property value="#foobar['foo1']"/>p>
body>
html>
清单3 webcontent/ognl.jsp
以上代码值得注意的是“”,因为“books.{?#this.title=='code complete, second edition'}.{price}”返回的值是集合类型,所以要用“[索引]”来访问其值。
最后是struts 2的配置文件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.devmode" value="true"/>
<package name="struts2_ognl_demo" extends="struts-default">
<action name="ognl" class="tutorial.action.ognlaction">
<result>/ognl.jspresult>
action>
package>
struts>
清单4 src/struts.xml
发布运行应用程序,结果如下所示:
清单5 示例运行结果1
“%”符号的用途是在标志的属性为字符串类型时,计算ognl表达式的值。例如在ognl.jsp中加入以下代码:
<hr />
<h3>%的用途h3>
<p><s:url value="#foobar['foo1']"/>p>
<p><s:url value="%{#foobar['foo1']}"/>p>
清单6 演示%用途的代码片段
刷新页面,结果如下所示:
清单7 示例运行结果2
“$”有两个主要的用途
- 用于在国际化资源文件中,引用ognl表达式,例子请参考《》
- 在struts 2配置文件中,引用ognl表达式,如
<action name="addphoto" class="addphoto">
<interceptor-ref name="fileuploadstack"/>
<result type="redirect">listphotos.action?albumid=${albumid}result>
action>
清单8 演示$用途的代码片段
总结
ognl是一种功能很大的表达式语言,熟悉它可以使我们的开发变得更快捷。
posted on 2007-04-28 19:43
max 阅读(66468)
评论(46) 所属分类:
struts 2.0系列