分享

Struts2 ONGL表达式

 dna26 2013-11-19
 
OGNL表达相当于JSP+Servlet模式中JSTL的地位,但是它的功能要比JSTL强大,在学习OGNL表达式时,你需要忘掉JSTL.

OGNL能够访问系统中OgnlContext中的对象, OgnlContext对象是OGNL表达式的下上文对象,即所有通过OGNL表达式取出的数据都是从上下文对象取出来的, OGNL的上下文环境是一个Map结构,称之为OgnlContext。

OgnlContext中包括以下几个内置对象
ValueStack:
存放在OgnlContext的第一位,是根对象,访问这里面的内容有点特殊,不用指定范围, Struts2框架总是把Action实例放在栈顶。因为Action在值栈中,而值栈又是OGNL中的根,所以引用Action的属性可以省略“#”标记,这也是为什么我们在结果页面中可以直接访问Action的属性的原因。
request:
模拟了HttpServletRequest对象,取这里面的值就相当于调用了request.getAttribute(“key”),访问这里面的属性形式: #request['user']或#request.user
session:
模拟了HttpServletSession对象,取这里面的值就相当于调用了session.getAttribute(“key”),
访问这里面的属性形式: #session['user']或#session.user
application:
模拟了HttpServletApplication对象,取这里面的值就相当于调用了servletContext.getAttribute(“key”),访问这里面的属性形式: #application['user']或#application.user
attr:
如果PageContext可用,则访问PageContext,否则依次搜索request、session和application对象。访问形式: #attr['user']或#attr.user
parameters:
用于访问请求参数,相当于调用了HttpServletRequest对象的getParameter()方法。也相当于JSTL中的 ${ param.id },访问形式: :#parameters['id']或#parameters.id

记住一点,不要和EL表达式混用,如果你用了EL表达式,就全用EL表达式,如果用了OGNL,就全用OGNL.

按道理来说,EL表达式只能访问request/session/page/application中的数据,但是我们现在又说了,Action中的属性值都是放在ValueStack中的,那为什么我们在先前的示例中,EL表达式能够访问ValueStack中的数据呢?
原因是:Struts2对request对象进行装饰,所用的类是org.apache.struts2.dispatcher.StrutsRequestWrapper
查看该类源码,发现它重写了getAttribute()方法:
通过查看源代码我们找到了原因:
会先前reuqest中查找属性值:
ActionContext ctx = ActionContext.getContext();
Object attribute = super.getAttribute(s);
如果没有找到,再从 ValueStack中查找
if (attribute == null) {
….
attribute = stack.findValue(s); //从ValueStack查找
….
}
这里就说明了为什么Struts2中EL表达式能够取出Action中的值了,但是一定要记住Action中的值是存储在ValueStack中的

首先我们来看看怎么用OGNL表达式取值
取ValueStack中的值
Action中:
public String method1(){
setMessage("取ValueStack中的值");
return "method1";
}

JSP页面:
<s:property value="message"/>

XML配置:
<action name="method1" class="chapter10.action.Chapter10Action" method="method1">
<result name="method1">/WEB-INF/JspPage/chapter10/success.jsp</result>
</action>

取request其它对象中的值
Action:
public String method1(){
request.setAttribute("message", "request中的值");
session.put("message", "session中的值");
request.getSession().getServletContext().setAttribute("message", "ServletContext中的值");
return "method1";
}

JSP页面:
<s:property value="#request.message"/> | <s:property value="#request['message']"/><br />
<s:property value="#session.message"/> | <s:property value="#session['message']"/><br />
<s:property value="#application.message"/> | <s:property value="#application['message']"/><br />
<s:property value="#attr.message"/>
可以看到attr对象是用来取值用的,它取出的值是顺着pagerequestsessionapplication

取parameters中的值
Action
public String method1() {
setMessage("parameters");
return "method1";
}

XML:
<action name="method1" class="chapter10.action.Chapter10Action" method="method1">
<result name="method1" type="redirect">/success.jsp?message=${message}</result>
</action>

JSP:
<s:property value="#parameters.message"/> | <s:property value="#parameters['message']"/><br />
注意type="redirect"时,JSP页面不能放在web-inf下

访问Action的中的方法
在Action中增加一个方法
public String test() {
return "Action Method";
}

JSP页面:
<s:property value="test()" /><br />

XML:
<action name="method1" class="chapter10.action.Chapter10Action" method="method1">
<result name="method1">/WEB-INF/JspPage/chapter10/success.jsp</result>
</action>

访问Action中属性的方法
增加一个User Model
public class User {
private String userName;

public User() {
super();
}

public User(String userName) {
super();
this.userName = userName;
}

@Override
public String toString() {
return "姓名:" + getUserName();
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}
}
修改Action,增加一个构造:
public Chapter10Action() {
user = new User("wdpc");
}
public String method1() {
return "method1";
}
XML
<action name="method1" class="chapter10.action.Chapter10Action" method="method1">
<result name="method1">/WEB-INF/JspPage/chapter10/success.jsp</result>
</action>
JSP
<s:property value="user.toString()" /><br />

访问属性的内置方法
Action:
public String method1() {
setMessage("调用字符串的length方法");
return "method1";
}
JSP:
<s:property value="message" />的长度是:<s:property value="message.length()" />

OGNL表达式访问静态属性和方法
首先加入一个开关
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
修改Model,添加一个静态方法,一个静态常量
public static final String CLASSNAME= "wdpc0801";

public static String staticMethod() {
return "Static Method";
}
JSP:
访问静态方法:
<s:property value="@chapter10.model.User@staticMethod()" />
<br />
访问静态属性或常量:
<s:property value="@chapter10.model.User@CLASSNAME" />
<br />
访问静态方法(默认为Math类):@@floor(1.32342):
<s:property value="@@floor(1.32342)" />
<br />
访问System类的静态currentTimeMillis()方法:
<s:property value="@java.lang.System@currentTimeMillis()" />
<br />
就算访问lang包下面类的静态方法都得带包名,除了Math类可以@@floor这样用,其它的类都得带包名.

访问Model类的构造方法
<s:property value="new chapter10.model.User('ZHD')" />
它会自动调用toString()方法来显示model的信息,所以model中最好重写toString()方法

使用OGNL表达式访问集合
修改model:
public class User {
private String userName;
public static final String CLASSNAME = "wdpc0801";

public User() {
super();
}

public User(String userName) {
super();
this.userName = userName;
}

@Override
public boolean equals(Object obj) {
return this.getUserName().equals(((User) obj).getUserName());
}

@Override
public int hashCode() {
return this.getUserName().hashCode();
}

@Override
public String toString() {
return "姓名:" + getUserName();
}

public static String staticMethod() {
return "Static Method";
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}
}
注意,set集合中要判断两个自定义对象是否是相同的,需要重写两个方法hashCode, equals两个方法

Action:
public class Chapter10Action extends BaseAction {
private String message;
private User user;
private List<User> users = new ArrayList<User>();
private Set<User> usersSet = new HashSet<User>();
private Map<String, User> usersMap = new HashMap<String, User>();

public Chapter10Action() {
user = new User("wdpc");
users.add(new User("张三"));
users.add(new User("李四"));
users.add(new User("王五"));

usersSet.add(new User("zhang"));
usersSet.add(new User("hai"));
usersSet.add(new User("hai"));
usersSet.add(new User("dang"));

usersMap.put("u1", new User("赵六"));
usersMap.put("u2", new User("林七"));
usersMap.put("u3", new User("魏八"));
}

public String method1() {
return "method1";
}

public String test() {
return "Action Method";
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

public List<User> getUsers() {
return users;
}

public void setUsers(List<User> users) {
this.users = users;
}

public Set<User> getUsersSet() {
return usersSet;
}

public void setUsersSet(Set<User> usersSet) {
this.usersSet = usersSet;
}

public Map<String, User> getUsersMap() {
return usersMap;
}

public void setUsersMap(Map<String, User> usersMap) {
this.usersMap = usersMap;
}
}
JSP:
<body>
访问User Model的构造方法 访问users:
<s:property value="users" />
<br />
访问指定的元素users[0]:
<s:property value="users[0]" />
<br />
访问users属性的userName集合users.{userName}:
<s:property value="users.{userName}" />
<br />
访问users中指定元素的属性:
<s:property value="users[0].userName" />
|
<s:property value="users.{userName}[0]" />
<br />
访问usersSet:
<s:property value="usersSet" />
<br />
访问usersMap:
<s:property value="usersMap" />
<br />
访问Map中指定的元素usersMap.u1 | usersMap['u1'](key与变量命名规则一致):
<s:property value="usersMap.u1" />
|
<s:property value="usersMap['u1']" />
<br />
访问Map中所有的(usersMap.keys)key:
<s:property value="usersMap.keys" />
<br />
访问Map中所有的(usersMap.values)values:
<s:property value="usersMap.values" />
<br />
</body>
如果要访问key集合中的某一个元素,可以这样访问:
<s:property value="usersMap.keys.{#this}[0]" />

使用OGNL表达式投影(过滤)集合
“?”:投影(过滤)所有符合条件的集合,如:users.{?#this.age > 19};
“^”:投影(过滤)第一个符合条件的元素,如:users.{^#this.age > 19};
“$”:投影(过滤)最后一个符合条件的元素,如:users.{$#this.age > 19} 。
#this代表users集合自己本身
Action:
public class Chapter10Action extends BaseAction {
private List<User> users = null;

public Chapter10Action() {
users = new ArrayList<User>();

users.add(new User("张三", 22));
users.add(new User("李四", 23));
users.add(new User("王五", 24));
users.add(new User("赵六", 22));
users.add(new User("林七", 23));
users.add(new User("魏八", 24));

}

public String index() {
return "index";
}

public List<User> getUsers() {
return users;
}

public void setUsers(List<User> users) {
this.users = users;
}
}

JSP:
<body>
所有符合条件的集合:<s:property value="users.{?#this.age > 22}" /><br />
所有符合条件的集合中指定的元素:<s:property value="users.{?#this.age > 22}[0]" /><br />
第一个符合条件的元素集合:<s:property value="users.{^#this.age > 22}" /><br />
最后一个符合条件的元素集合:<s:property value="users.{$#this.age > 22}" /><br />
</body>

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多