首页 > 代码库 > 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>密&nbsp;&nbsp;码:<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("ross",31));

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表达式