论坛首页 入门技术论坛

《WebWork in action》第八章

浏览 2848 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-09-26  
第八章: 利用表达式语言获取数据

WebWork的EL-对象图导航语言(Object Graph Navigation Language, 缩写为OGNL)是作为Web页面脚本的最佳选择。

一. 基本特性

    1. 访问bean属性

       根据JavaBean的规范,bean属性使用诸如getXxx(), setXxx(), isXxx()或者hasXxx()这样标准形式的getter方法或
       setter方法。其中, isXxx()和hasXxx()形式用于boolean属性。在WebWork中,访问这些属性(不管是获取数据还是
       设置数据)都使用形式为xxx的属性引用。

       示例:
 
       a. action

    package ch8;

    import ch4.User;
    import com.opensymphony.xwork.ActionSupport;

    public class OgnlTest extends ActionSupport{
        private User user;

        public String execute() {
            user = new User();
            user.setName("zs");
            user.setPassword("password");
           
            return SUCCESS;
        }
        //setter和getter方法
    }   

       b. result

        <action name="ognlTest" class="ch8.OgnlTest">
            <result name="success">ognl.jsp</result>
        </action> 

       c. jsp

    <%@page contentType="text/html;charset=UTF-8" %>
    <%@taglib uri="webwork" prefix="ww" %>
    <html>
        <body>
            <ww:property value="user.name"/>    <!--其中value中内容为ognl表达式-->
            <ww:property value="user.password"/>
        </body>
    </html>

    2. 常量

       OGNL表达式常量与EL类型,

       常量类型                    范例
       ------------                             --------------
       char                    'a'
       String                    "hello world"
       boolean                     true false

      另String常量可以使用单引号或双引号括起来,示例:

       <ww:property value="\"a\""/>并不等同于 <ww:property value='a'/>

    3. 操作符

       OGNL支持所有Java操作

       运算                    范例
       ------------                             --------------
       递增                    ++foo
       递减                    foo++
       等于                    foo == bar
       不等于                    foo != bar
       in                                       foo in someList
       not in                                   foo not in someList
       赋值(=)                    foo = 123

    4. 方法调用

       提供调用非属性相关的方法;

       示例:假设ch4.User类中有一方法(静态方法亦可) :

             public String sayHello() {
               return "hello world";
         }

             使用以下形式可以在浏览器上输出:hello world

             <ww:property value="user.sayHello()"/>

    5. 设置数值及表达式列表

       在单条语句当中执行以逗号分隔的多个表达式,最后一个表达式的返回值作为整条语句的输出结果。

       例如foo值为123,而bar值为789,则以下形式输入 789:

       <ww:property value="foo,bar"/>

    6. 访问静态方法和类变量

       使用@[className]@[Field Or Method]调用静态类变量和方法,类名必须使用包括包在内的完整类名;

       示例:假设ch4.User类中有一方法(静态方法亦可) :

             public static String sayHello() {
               return "hello world";
         }

             使用以下形式可以在浏览器上输出:hello world

             <ww:property value="@ch4.User@sayHello()"/>
   
       另OGNL也可使用vs(vs代表Value Stack,就是值栈)前缀调用保存于值栈中的类的静态属性和静态方法;

       <ww:property value="@vs@sayHello()"/>
      
       一般来说,只有在一直了解值栈中包含什么对象的情况下,使用vs的形式才是有用的,否则建议使用完整的包
       名和类名比较好。

    7. 访问OGNL上下文及ActionContext

       示例:

       Java代码:                                                      OGNL表达式
       -------------------------------------------------------         ---------------------
       ActionContext().getContext().getParameters()                    #parameters
       ActionContext().getContext().getParameters().size()             #parameters.size
       ((Kermit)ActionContext().getContext().get("kermit")).getAge()   #kermit.age
 
       WebWork中另提供一些更短标识符方便访问:
       . parameters :    一个包含当前请求中所有HttpServletRequest参数的map;
       . request    :    一个包含当前请求中所有HttpServletRequest属性的map;
       . session    :    一个包含当前请求中所有HttpSession属性的map;
       . application:    一个包含当前请求中所有ServletContext属性的map;
       . attr       :    一个依次从请求、会话和应用程序的Map中搜索属性的map;

       示例:

       a. action

    package ch8;

    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;

    import com.opensymphony.webwork.interceptor.ServletRequestAware;
    import com.opensymphony.xwork.ActionSupport;

    public class ScopeTest extends ActionSupport implements ServletRequestAware{
        private HttpServletRequest request;
       
        @Override
        public void setServletRequest(HttpServletRequest arg0) {
            request = arg0;
        }

        @Override
        public String execute() {
            HttpSession session = request.getSession();
            ServletContext context = session.getServletContext();
           
            request.setAttribute("req","request0");
            session.setAttribute("ses","session1");
            context.setAttribute("app","application2");
           
            return SUCCESS;
        }
    }

       b. result

        <action name="scopeTest" class="ch8.ScopeTest">
            <result name="success">scopeTest.jsp</result>
        </action>

       c. jsp

    <%@page contentType="text/html;charset=UTF-8" %>
    <%@taglib uri="webwork" prefix="ww" %>
    Request parameter: <ww:property value="#parameters['name']"/><br>
    Request attribute: <ww:property value="#request['req']"/><br>
    Session attribute: <ww:property value="#session.ses"/><br>
    Application attribute: <ww:property value="#application.app"/><br>
    Request attribute: <ww:property value="#attr.req"/><br>
    Session attribute: <ww:property value="#attr.ses"/><br>
    Application attribute: <ww:property value="#attr.app"/><br>

二. 操作集合(Collections)

    1. 操作列表(list)和数组(array)

       Java代码                                         OGNL表达式
       -------------------------                        ----------------------------------
       list.get(0)                                      list[0]
       array[0]                                         array[0]
       ((User)list.get(0)).getName()                    list[0].name
       array.length                                     array.length
       list.size()                                      list.size
       list.isEmpty()                                   list.isEmpty

       除了访问列表的数值外,OGNL还可以动态地创建列表:使用大括号将元素括起来,元素间使用逗号分隔。

       Java代码                                         OGNL表达式
       -------------------------                        ----------------------------------
       List list = new ArrayList(3);                    {1,3,5}
       list.add(1);                    
       list.add(3);
       list.add(5);
       return list;
       -------------------------                        ----------------------------------
       List list = new ArrayList(2);                    {"foo","bar"}[1]
       list.add("foo");
       list.add("bar");
       return list.get(1); 
    
    2. 操作Map

       Java代码                                         OGNL表达式
       -------------------------                        ----------------------------------
       map.get("foo")                                   map['foo']
       map.get(new Integer(1))                          map[1]
       User user = (User)map.get("zs");                 map['zs'].name
       return user.getName();
       map.put("foo","bar");                            map['foo']='bar'
       map.size();                                      map.size
       map.isEmpty();                                   map.isEmpty

       除了访问Map的数值外,OGNL还可以动态地创建Map。必须在左边的大括号之前放置一个#号。

       Java代码                                         OGNL表达式
       -------------------------                        ----------------------------------
       Map map = new HashMap(2);                        #{"foo":"bar","baz":"whazzit"}
       map.put("foo","bar");
       map.put("baz","whazzit");
       return map;

       Map map = new HashMap(2);                        #{1:"one",2:"two"}
       map.put(new Integer(1),"one");
       map.put(new Integer(2),"two");
       return map;

       Map map = new HashMap(2);                        #{#user1.name:#user1.mother.name,
       map.put(user1.getName(),user1.getMother()          #user2.name:#user2.mother.name}
    .getName());
       map.put(user2.getName(),user2.getMother()
    .getName());
       return map;

       ActionContext.getContext().                      #parameters['id']
            getParameters().get("id");

       String name = user.getName();                    #session["user-"+name]
       Map map = ActionContext.getContext()
       .getSession();
       return map.get("user-"+name);

       session.put("user",user);                        #session['user'] = user

    3. 对集合进行筛选(filtering)和投影(projecting)

       筛选:以一个集合为基础生成一个新集合的技术,而新集合中只包含可以通过筛选的对象。语法:
             collection.{? expression}

             以上expression是真正意义上的筛选器, 会对集合中的每个对象进行求值。而#this这个特殊的变量
             则是用于标识正在进行求值的对象。例,要从Kemit的孩子们中筛选出年龄等于2或者小于2的孩子,表
             达式为:

             #this.age <= 2

       投影:根据投影规则对集合中的元素进行转换。语法:

             collection.{ expression }

             其中expression用来对原始集合中被循环迭代到的对象进行求值。

       筛选返回的集合中的元素与原始集合中的是一样的,但数量有可能要少;
       投影返回的集合中的元素与原始集合中的有可能不一样,但数量一样多;

       示例:

       OGNL表达式                                       描述
       -------------------------                        ----------------------------------
       children.{name}                                  投影的结果为所有孩子的姓名
       children.{?#this.age > 2}                        筛选的结果为年龄大于2的孩子
       children.{?#this.age<=2}.{name}                  选筛选出年龄小于等于2的孩子,再对结果列进行投影操作,得
                                                        到孩子的名字
       children.{name +'->'+mother.name}                投影的结果为符合"名字->母亲名字"样式的字符串列表

    4. "#"的多种用途

       . 引用ActionContext中的值:     #foo
       . 动态构建Map                  #{1:'one',2:'two'}
       . 对集合进行筛选和投影操作     children.{?#this.age > 2}

三. 表达式语言的高级特性

    正是这些高级特性令WebWork能够在众多的MVC框架中脱颖而出。

    1. 将值栈和表达式语言联系起来

       在WebWork中,整个值栈就是上下文(context)中的根对象。WebWork提供了与OGNL特别的集成:根据表达式自动查找整
       个栈(从上而下),直至找到了一个包含了所需的属性的对象。

       举例:栈中有两个对象:Muppet和Person,两个对象都有name属性;Muppet有lifeSized属性而Person有salary属性。
             Muppet对象在栈顶,而Person对象在其下面。如下图:

             -------------------------------------
             |               Muppet              |
             |            ------------           |
             |              name                 |
             |              lifeSized            |
             |                                   |
             |               Person              |
             |            ------------           |
             |              name                 |
             |              salary               |
             |                                   |
             |                                   |
             -------------------------------------

       OGNL表达式                                       描述
       -------------------------                        ----------------------------------
       lifeSized                                        调用muppet.isLifeSized()
       salary                                           调用person.getSalary()
       name                                             因为muppet位于person之上,所以调用muppet.getName()
       [1].name                                         由于[1]这个语法指明了WebWork将从位置1开始往下查找,所以
                                                        调用person.getName();
       top                                              返回muppet
       [1].top                                          由于[1]返回的是一个范围较小的值栈,而表达式top是基于它的,
                                                        所以整个表达式返回结果是person。因person位于这个新的,范围
                                                        较小的值栈的顶部。

    2. 数据类型转换

       OGNL表达式                                       描述
       -------------------------                        ----------------------------------      
       #kermit.age = "25"                               为一个int型变量设置String值,该String值随后会被转换为25
       #kermit.name = 25                                为一个String型变量设置int值,该int值随后会被转为"25"

    3. 处理null属性的访问

       OGNL在检测出访问了一个null对象的属性时,就会提供一种方式将null对象转化为真实对象。

    4. 动态创建lambda表达式

       定义语法::[...]

                 lambda表达式只能使用一个参数,该参数可通过#this引用。示例:

                 #isKermit = :[#this.name == @vs@OG_MUPPET ? true : false]

                 定义好之后,可将其置于OGNL上下文中,然后通过以下形式调用:

       OGNL表达式                               描述
       -------------------------                ----------------------------------  
       #isKermit(top)                           判断位于栈顶的对象是否拥有Kermit这样的名字;
       #isKermit(#kermit)                       kermit是Kermit类型吗?
 
   发表时间:2008-07-23  
顶邓老师  顶邓老师
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics