首页 > 代码库 > OGNL表达式
OGNL表达式
Struts2的一个关键特性就是它可以对Action携带的数据进行读写访问,例如在前面我们在表单中使用username指定数据传递给Action的username属性,在<s:property>元素中使用username来获取用户的名字,这是通过表达式语言(Expression Language,EL)来实现的,这种表达式语言就是OGNL。
OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,让你通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。
一、为什么要使用OGNL
视图层的表达式语言通常是用来简化数据的访问操作,取代Java脚本代码,提供更清晰的视图层实现。例如,在JSP页面中使用JSP2.0内置的表达式语言获取user对象的username属性,可以简写为${user.username},如果换作Java脚本代码,则需要写为:
<%@ page language="java" import="java.util.*,com.bim.pojo.User" pageEncoding="gbk"%>
<%
User user = (User)request.getAttribute("user");
String username = user.getUsername();
out.print(username);
%>
哪一种方法更为简捷,相信大家已经一目了然了。
既然JSP2.0已经内置了一种表达式语言,那么为什么还要使用OGNL呢?
相对于其它的表达式语言而言,OGNL的功能更为强大,它提供了很多高级而必须的特性,例如强大的类型转换功能,静态或实例方法的执行,跨集合投影(projection),以及动态lambda表达式定义等。
二、 OGNL的原理--ActionContext
ActionContext:是Struts的核心数据区,是Action和页面进行数据交换的“共享数据区”,也叫做Action的OGNL上下文
(补充:上下文是一种非常泛化的概念,大致意思就是“与现在这个工作相关的周围环境”。一般存储了该环境的一些属性值。 )
ActionContext的结构:包含值栈和非值栈。当Action被请求时会被创建Action对象,且会把该对象放到值栈中。
值栈的概念:值栈是OGNL表达式的根对象; Struts总是将当前访问的Action对象存放在栈顶;OGNL表达式对值栈中的任何对象直接访问,而不需要使用“#”标记 (Struts提供了一个特殊的OGNL PropertyAccessor接口,此接口可以自动查找值栈内的、从栈顶到栈底的所有对象,直到找到对象为止 )
怎么访问值栈中的值:根对象可以缺省#。OGNL直接访问属性:user.userName
怎么访问非值栈区的中的值: #key,如#request.loginID
根对象的属性直接访问案例
userInert.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags"%> <% String path = request.getContextPath();%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘MyJsp.jsp‘ starting page</title> </head> <body> <form action="userAction" method="post"> <table> <tr> <td> 用户名: </td> <td> <input type="text" name="user.userName"> </td> </tr> <tr> <td> 用户所在组名: </td> <td> <input type="text" name="user.group.groupName"> </td> </tr> <tr> <td> 用户所在组的机构编号: </td> <td> <input type="text" name="user.group.org.orgId"> </td> </tr> <tr> <td> 用户所在组的机构名字: </td> <td> <input type="text" name="user.group.org.orgName"> </td> </tr> <tr> <td> <input type="submit" name="submit" value=http://www.mamicode.com/"添加"> </td> <td> <input type="reset" name="reset" value=http://www.mamicode.com/"取消"> </td> </tr> </table> </form> </body> </html>
|
userShow.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP ‘userShow.jsp‘ starting page</title> </head> <body> <s:debug></s:debug> <form action="userAction" method="post"> <table> <tr> <td> 用户名: </td> <td> <s:property value=http://www.mamicode.com/"user.userName" /> </td> </tr> <tr> <td> 用户所在组名: </td> <td> <s:property value=http://www.mamicode.com/"user.group.groupName" /> </td> </tr> <tr> <td> 用户所在组的机构编号: </td> <td> <s:property value=http://www.mamicode.com/"user.group.org.orgId" /> </td> </tr> <tr> <td> 用户所在组的机构名字: </td> <td> <s:property value=http://www.mamicode.com/"user.group.org.orgName" /> </td> </tr> <tr> <td> <input type="submit" name="submit" value=http://www.mamicode.com/"确认"> </td> <td> <input type="reset" name="reset" value=http://www.mamicode.com/"取消"> </td> </tr> </table> </form> <br> </body> </html>
|
Struts.xml
<action name="userAction" class="com.inspur.actions.UserAction"> <result name="show">/user/userShow.jsp</result> </action> |
Web.xml
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> |
userAction.java
package com.inspur.actions; import com.inspur.pojo.User; import com.opensymphony.xwork2.ActionSupport; public class UserAction extends ActionSupport{ private User user;
public User getUser() { return user; }
public void setUser(User user) { this.user = user; } @Override public String execute() throws Exception{ return "show"; } }
|
User.java
package com.inspur.pojo; public class User { private String userName; private Group group; get/set…… }
|
Ogr.java
package com.inspur.pojo; public class Org { private String orgId; private String orgName; get/set…… }
|
Group.java
package com.inspur.pojo; public class Group { private String groupName; private Org org; get/set…… } |
非根对象的属性使用“#”访问 案例(只写出了部分代码)
Login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>login page</title> </head> <body> <form action="loginAction"> <font color="red"><s:property value=http://www.mamicode.com/"#request.msg"/></font> <table align="center"> <tr><td>用户名:<input type="text" name="uname"></td></tr> <tr><td>密 码:<input type="password" name="upass"></td></tr> <tr><td><input type="submit" value=http://www.mamicode.com/"登录"></td></tr> </table> </form> </body> </html> |
LoginAction.java
public String login(){ //第一种方式:actioncontext类 ActionContext context = ActionContext.getContext(); Map<String, String> requestMap = (Map<String, String>) context.get("request"); Map<String, Object> sessionMap = (Map<String, Object>) context.getSession(); if("ross".equals(this.uname) && "111".equals(this.upass)){ sessionMap.put("uname", uname); return SUCCESS; }else{ requestMap.put("msg", "登录名或密码错误"); return ERROR; } } |
Index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>用户登录成功界面</title> </head> <body> <p> 欢迎您,<s:property value=http://www.mamicode.com/"#session.uname"/>,用户登录成功! </p> </body> </html>
|
Struts.xml
<!-- 配置请求和Action组件的映射关系 --> <action name="loginAction" class="com.inspur.actions.LoginAction" method="login"> <result name="success">/index.jsp</result> <result name="error">/login.jsp</result> <result name="input">/login.jsp</result> </action> |
三、OGNL访问数组、list、map、set
访问数组元素:array[0]
访问List元素:{‘name1‘,‘name2‘}[0]
访问map元素:mymap[‘key’]或者mymap.key
访问set中元素:userSet
案例代码:
页面生成数组和list: <tr> <td>用户的爱好: </td> <td> 篮球<input type="checkbox" name="likes" value=http://www.mamicode.com/"篮球"> 足球<input type="checkbox" name="likes" value=http://www.mamicode.com/"足球"> 羽毛球<input type="checkbox" name="likes" value=http://www.mamicode.com/"羽毛球"> </td> </tr> <tr> <td>用户熟悉的计算机语言: </td> <td> Java<input type="checkbox" name="language" value=http://www.mamicode.com/"java"> c<input type="checkbox" name="language" value=http://www.mamicode.com/"c"> c#<input type="checkbox" name="language" value=http://www.mamicode.com/"c#"> </td> </tr>
Action里: private String likes[]; private List<String> language; private Map<String,String> books = new HashMap<String,String>(); private Set<String> set = new HashSet<String>(); get/set…… public String execute() throws Exception{ books.put("1","红楼梦"); books.put("2","三国演义"); set.add("tom"); set.add("joy"); return "show"; }
页面显示 数组: 取所有元素<s:property value="http://www.mamicode.com/likes" /> 取第一个元素<s:property value="http://www.mamicode.com/likes[0]" />
List: 取所有元素<s:property value="http://www.mamicode.com/language" /> 取第一个元素<s:property value="http://www.mamicode.com/language[0]" />
Map: 取所有元素<s:property value="http://www.mamicode.com/books" /> 取第一个元素<s:property value="http://www.mamicode.com/books[‘1‘]" /> <p><s:property value=http://www.mamicode.com/"books.1" /></p> 取所有key值<p><s:property value=http://www.mamicode.com/"books.keys" /></p> 取所有value值<p><s:property value=http://www.mamicode.com/"books.values" /></p>
Set: 取所有set值<p><s:property value=http://www.mamicode.com/"set" /></p> 取set大小<p><s:property value=http://www.mamicode.com/"set.size" /></p> |
四、投影和选择
投影:OGNL提供了一种简单的方式在一个集合中对每一个元素调用相同的方法,或者抽取相同的属性,并将结果保存为一个新的集合,称为投影。例如,users是一个包含了user对象的列表,那么#users.{name}将返回所有人的名字和列表。在投影期间,使用#this变量来引用迭代中的当前元素
选择:OGNL提供了一种简单的方式来使用表达式从集合中选择某些元素,并将结果保存到新的集合中,称为选择。如#users.{?#this.salary>3000}将返回薪水大于3000 的所有人的列表。#users.{^#this.salary>3000}将返回第一个薪水大于3000人。#users.{$#this.salary>3000}将返回最后一个薪水大于3000的人。
案例
//Action里面定义一个list放入user对象: private List<User> userList = new ArrayList(); //给user对象添加一个年龄属性,并书写对应构造方法 userList.add(new User("rechel",28)); userList.add(new User("joy",32));
页面显示: <h4>访问类方法</h4> <s:property value=http://www.mamicode.com/"new com.inspur.actions.UserAction().showString()"/> <h4>选择所有用户的名字</h4> <s:property value=http://www.mamicode.com/"userList.{userName}"/> <!-- 验证--> <hr> <h4>选择年龄>30的用户信息</h4> <s:property value=http://www.mamicode.com/"userList.{?#this.age>30}"/> <h4>选择年龄>30的用户信息中用户名</h4> <s:property value=http://www.mamicode.com/"userList.{?#this.age>30}.{userName}"/> <h4>选择第一个年龄>30的用户信息中用户名</h4> <s:property value=http://www.mamicode.com/"userList.{^#this.age>30}.{userName}"/> <h4>选择最后一个年龄>30的用户信息中用户名</h4> <s:property value=http://www.mamicode.com/"userList.{$#this.age>30}.{userName}"/> |
OGNL表达式