OGNL全称是Object-Graph Navigation Language(对象图形导航语言),相对于EL语言,除了保持EL语言的优点外,他的其他优点如下:
- 能够访问对象的普通方法
- 能够访问类的静态属性和静态方法
- 强大的操作集合类对象的能力
- 支持赋值操作和表达式串联
- 访问OGNL上下文和ActionContext
为了测试OGNL,我们写一个基本的TestOGNLAction,以及一个显示结果的页面ok.jsp。同时为了配合操作,我们写两个javabean:User和Address,他们的内容和配置如下:
package com.bjsxt.struts.test;
public class Address { private String country; private String city; private String street; //限于篇幅,get和set方法省略! public Address(String country, String city, String street) { super(); this.country = country; this.city = city; this.street = street; }
public Address() { } }
|
package com.bjsxt.struts.test;
public class User { private int id; private String uname; private String pwd; private Address addr;
public User(int id, String uname, String pwd) { super(); this.id = id; this.uname = uname; this.pwd = pwd; } public User(String uname, String pwd) { super(); this.uname = uname; this.pwd = pwd; } public User() { } //限于篇幅,get和set方法省略! } |
package com.bjsxt.struts.test;
import com.opensymphony.xwork2.ActionSupport;
public class TestOGNLAction extends ActionSupport{
private String uname; private User user;
public String execute() throws Exception { //在此处增加测试代码 return this.SUCCESS; }
public String getUname() { return uname; }
public void setUname(String uname) { this.uname = uname; }
public User getUser() { return user; }
public void setUser(User user) { this.user = user; } } |
<?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.i18n.encoding" value="gbk" /> <constant name="struts.devMode" value="true" /> <package name="test" namespace="/" extends="struts-default"> <action name="testOgnl" class="com.bjsxt.struts.test.TestOGNLAction"> <result name="success">/ok.jsp</result> </action> </package> </struts> |
<%@ page language="java" import="java.util.*" pageEncoding="gbk"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>测试OGNL</title> </head> <body>
</body> </html> |
OGNL获得上下文中的属性和对象导航
- 操作OgnlValueStack中属性
private String uname; private User user;
public String execute() throws Exception { //增加测试代码 uname="老高"; user = new User("root","123456"); user.setAddr(new Address("中国","北京","海淀区")); return this.SUCCESS; } |
<body> <p><s:property value="uname" /></p> <p><s:property value="user.addr.country" /></p> <s:debug></s:debug> <!-- 我们可以通过debug标签查看ActionContext中的情况 --> </body> |
结果如下: |
- 操作AcitionContext其他域中的属性
public String execute() throws Exception { //增加测试代码 User u = new User("root","123456"); u.setAddr(new Address("中国","北京","海淀区"));
ActionContext context = ActionContext.getContext(); context.put("a", "ActionContext中的值"); ((Map)context.get("request")).put("b","request中的值"); ((Map)context.get("session")).put("c","session中的值"); ((Map)context.get("application")).put("d","session中的值");
return this.SUCCESS; } |
<body> <% request.setAttribute("r","rrr"); pageContext.setAttribute("p","ppp"); %>
<p><s:property value="#a" /></p> <p><s:property value="#request.b" /></p> <p><s:property value="#parameters.param1[0]" /></p> <p><s:property value="#session.c" /></p> <p><s:property value="#application.d" /></p> <p><s:property value="#attr.p" /></p> <s:debug></s:debug> <!-- 我们可以通过debug标签查看ActionContext中的情况 --> </body> |
结果如下: |
OGNL中运算符
- .和[]操作符
<body> <% request.setAttribute("r","rrr"); %>
<p><s:property value="#request.r" /></p> <p><s:property value='#request["r"]' /></p> <p><s:property value='#request[#parameters.param2[0]]' /></p> <s:debug></s:debug> <!-- 我们可以通过debug标签查看ActionContext中的情况 --> </body> |
测试:
|
通过上面测试,我们总结:
-
-
- 点运算符操作方便,较常用。
- []运算符操作不方便,但是功能强大,可以传入变量值,动态取值!
-
- 普通运算符
OGNL支持所有的JAVA运算符。
<body> <% request.setAttribute("r","rrr"); %> <p><s:property value="3*3" /></p> <p><s:property value="3==3" /></p> <p><s:property value="#request.r==null" /></p> <p><s:property value="3+3" /></p> <p><s:property value="3+'3'" />--${3+'3'}</p> <!-- 字符串连接符,这点不同于EL表达式--> <p><s:property value="3>2&&1>2" /></p> <p><s:property value="3>2?'aa':'bb'" /></p> <hr/> <s:debug></s:debug> <!-- 我们可以通过debug标签查看ActionContext中的情况 --> </body> |
结果: |
- 赋值操作
<body> <% request.setAttribute("r","rrr"); request.setAttribute("r2","r2r2"); %> <p><s:property value="#request.r='ppp'" /></p> <p><s:property value="#request.r=#request.r2" /></p> <hr/> <s:debug></s:debug> </body> |
结果: |
OGNL操作集合
- List/ Set
List的语法:{e1,e2,e3}。
<body> <s:set var="list" value="{'a','b','c'}" scope="request"></s:set> <p><s:property value="#request.list.get(2)" /></p> </body> |
结果: |
- Map
<body> <% request.setAttribute("a","123456"); %> <s:set var="m" value="#{'name':'老高','pwd':#request.a}" scope="request"></s:set> <p><s:property value="#request.m.name" /></p> <p><s:property value="#request.m.pwd" /></p> </body> |
结果: |
- 集合中查找元素:in和not in操作符
<body> <s:set var="s" value="{'a','b','c'}" scope="request"></s:set> <s:set var="m" value="#{'name':'老高','pwd':'123456'}" scope="request"></s:set> <p><s:property value="'a' in {'a','b','c'}" /></p> <p><s:property value="'a' not in #request.s" /></p> <p><s:property value="'name' in #request.m.keys" /></p> <p><s:property value="'老高' in #request.m.values" /></p> </body> |
- 过滤/投影
我们把过滤集合中的元素产生一个子集合,叫做投影
?---符合选择逻辑的所有元素
^---符合选择逻辑的第一个元素
$---符合选择逻辑的最后一个元素
#this---表示集合中的元素
<%@ page language="java" import="java.util.*,com.bjsxt.struts.test.*" pageEncoding="gbk"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>测试OGNL</title> </head> <body> <% User u1 = new User("张三","123456"); User u3 = new User("王五","123456"); User u5 = new User("高淇","654321"); User u6 = new User("马士兵","654321"); List list = new ArrayList(); list.add(u1); list.add(u3); list.add(u5); list.add(u6); request.setAttribute("s",list); %> <s:set var="s1" value="#request.s.{?#this.pwd=='654321'}" scope="request" ></s:set> <s:iterator value="#request.s1" var="temp" > <p><s:property value="#temp.uname" /></p> </s:iterator> </body> </html> |
执行结果: |