GNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言(Expression Language,简称为EL),通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。
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; 操作集合对象。
1.OGNL访问堆栈
2.OGNL访问静态方法,属性
3.OGNL访问普通类的构造方法
4.OGNL访问List,MAP
5.OGNL中的投影,也就是过滤
公用的index.jsp初始传值页面
<body> //获取上下文路径<br /> String contextPath = request.getContextPath();<br /> 访问属性<br /> <a href="<%=contextPath %>/ognl/ognl.action?userName=credo&passWord=lion">ognl</a> </body>
<!-- 注意这个规则,取的时候从根目录取,就是 "/文件夹/文件名" --> <include file="/org/credo/ognl/ognl.xml" /> <!-- 下面是设定开发模式,设定为true,方便修改action name后的热部署 --> <constant name="struts.devMode" value="true" /> <!-- 允许访问静态方法,默认为false --> <constant name="struts.ognl.allowStaticMethodAccess" value="true" />
<?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> <package name="ognl" extends="struts-default" namespace="/ognl"> <action name="ognl" class="org.credo.ognl.OgnlAction"> <result>/ognl/ognl.jsp</result> </action> </package> </struts>
ognl.jsp页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
String contextPath = request.getContextPath();
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
OGNL表达式是值s:property 中value中的表达式<br>
访问值栈中的action的普通值:<s:property value="userName" /><br>
访问值栈中的普通属性(get,set方法):user.age--><s:property value="user.age"/> <br>
user['age']---> <s:property value="user['age']"/> <br>
user[\"age\"]---><s:property value="user[\"age\"]"/><br>
只有进行从其他页面传参,才可以.或者user在action中new.但是,不new,model user,必须要有默认的构造方法(参数为空的)<br>
<s:debug /><br>
</body>
</html>
package org.credo.ognl; import com.opensymphony.xwork2.ActionSupport; public class OgnlAction extends ActionSupport{ /** * Ognl */ private static final long serialVersionUID = 1L; private String userName; private String passWord; private User user=new User(19); //private User user public OgnlAction(){ //构造方法 } public String execute(){ System.out.println("userName:"+userName); return SUCCESS; } //get and set
静态类:
package org.credo.action.ognl; public class S { public static String STR = "STATIC STRING"; public static String s() { return "static method"; } }
访问静态都方法属性,OGNL都是按@类名@方法名() @类名@属性名
访问静态方法:<s:property value="@org.credo.action.ognl.S@s()"/>
访问静态属性:<s:property value="@org.credo.action.ognl.S@STR"/>
访问Math类的静态方法:<s:property value="@@max(2,3)" />
<s:property value="new org.credo.action.ognl.User(9)"/>
页面代码:
<hr /> <li>访问List:<s:property value="users"/></li> <li>访问List中某个元素:<s:property value="users[1]"/></li> <!-- 下面是把每个users里的age取出,组成一个集合,大括号在OGNL里可以代表一个集合 --> <li>访问List中元素某个属性的集合:<s:property value="users.{age}"/></li> <!-- 第0个位置上的age.第一种不要用,需要用users[0].age --> <li>访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/></li> <li>访问Set:<s:property value="dogs"/></li> <!-- 不可以取下标值 --> <li>访问Set中某个元素:<s:property value="dogs[1]"/></li> <li>访问Map:<s:property value="dogMap"/></li> <!-- 通过key获取map的某个元素,用第一种最好 --> <li>访问Map中某个元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap['dog101']"/> | <s:property value="dogMap[\"dog101\"]"/></li> <li>访问Map中所有的key:<s:property value="dogMap.keys"/></li> <li>访问Map中所有的value:<s:property value="dogMap.values"/></li> <li>访问容器的大小:前为map后为list<s:property value="dogMap.size()"/> | <s:property value="users.size"/> </li> <hr />
import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.opensymphony.xwork2.ActionSupport; public class OgnlAction extends ActionSupport { private Cat cat; private Map<String, Dog> dogMap = new HashMap<String, Dog>(); private Set<Dog> dogs = new HashSet<Dog>(); private String password; private User user; private String username; private List<User> users = new ArrayList<User>(); public OgnlAction() { users.add(new User(1)); users.add(new User(2)); users.add(new User(3)); dogs.add(new Dog("dog1")); dogs.add(new Dog("dog2")); dogs.add(new Dog("dog3")); dogMap.put("dog100", new Dog("dog100")); dogMap.put("dog101", new Dog("dog101")); dogMap.put("dog102", new Dog("dog102")); } public String execute() { return SUCCESS; } public Cat getCat() { return cat; } public Map<String, Dog> getDogMap() { return dogMap; } public Set<Dog> getDogs() { return dogs; } public String getPassword() { return password; } public User getUser() { return user; } public String getUsername() { return username; } public List<User> getUsers() { return users; } public String m() { return "hello"; } public void setCat(Cat cat) { this.cat = cat; } public void setDogMap(Map<String, Dog> dogMap) { this.dogMap = dogMap; } public void setDogs(Set<Dog> dogs) { this.dogs = dogs; } public void setPassword(String password) { this.password = password; } public void setUser(User user) { this.user = user; } public void setUsername(String username) { this.username = username; } public void setUsers(List<User> users) { this.users = users; } }
package org.credo.action.ognl; public class Dog { private String name; public Dog() { } public Dog(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } //重写了toString方法 @Override public String toString() { return "dog: " + name; } }
<!-- 正则表达式中,?代表过滤条件,^代表开始,$代表结束 --> <!-- 拿出age=1的users --> <li>投影(过滤):<s:property value="users.{?#this.age==1}[0]"/></li> <!-- 拿出age大于一的开头的age --> <li>投影:<s:property value="users.{^#this.age>1}.{age}"/></li> <!-- 拿出age大于一的结尾的age --> <li>投影:<s:property value="users.{$#this.age>1}.{age}"/></li> <!-- 判断age大于一的结尾是否存在,用来判断这个集合里是否有东西. --> <li>投影:<s:property value="users.{$#this.age>1}.{age} == null"/></li> <hr /> <!-- 用中括号访问元素,访问的是OGNL里从上到下,某一个成员变量,会按顺序找, --> <!-- 有可能有2个action在里面的时候,如一个action跳到另一个action,这个时候, --> <!-- 用[0]访问,从上到下找,直到找到有值的. --> <li>[]:<s:property value="[0].username"/></li>