关于ValueStack

关于ValueStack的描述:

1、  ValueStack其实就是一个放置Java对象的堆栈而已,唯一特别的是可以使用EL来获得值堆栈中对象属性的数据,并可以为值堆栈的对象属性赋值。

2、  EL,全称Express Language,即表达式语言。不要被语言吓倒,它是简单的对象导航语言。有字符串(例如:方法名)和特殊字符组成(例如用.表示调用对应的属性方法)。通过EL,我们可以存、取对象数据,而且还可以直接访问类的静态数据,调用静态方法。

3、  WebWork的ValueStack底层有第三方开源项目OGNL实现。所以EL也都遵循OGNL的规范。我们在开发中,几乎不需要知道OGNL的细节。

4、  WebWork为每一次请求构建一个ValueStack,并将所有相关的数据对象(例如:Action对象、Model对象等)放到ValueStack中。再将ValueStack暴露给视图页面,这样页面就可以直接访问后台处理生成的数据。

下面我们用一个雇员类为例,使用Junit框架(单元测试框架)来展示ValueStack的功能。

我们有一个Employee类,它有两个属性:姓名,地址。姓名是一个字符串,地址是一个对象,地址类有国家、城市、街道三个属性。代码如下:


Employee.java代码如下:

public class Employee { 

      private String name;     

      private Address address; 

      

      public Employee() { 

      }      

      public String getName() { 

            return name; 

      }  

      public void setName(String name) { 

            this.name = name; 

      }  

      public Address getAddress() { 

            if(address == null) 

                  address = new Address(); 

            return address; 

      }      

      public void setAddress(Address address) { 

            this.address = address; 

      } 

} 

 

Address.java代码如下:

public class Address {

            private String country;

            private String city;

            private String street;

            

            ……

            //默认的Get和Set方法,省略

            

}


下面出场的是OgnlValueStackTest,它有两个测试方法。分别测试使用EL从ValueStack中取值和存值。代码如下:

import com.opensymphony.xwork.util.OgnlValueStack;

import junit.framework.TestCase;

  

public class OgnlValueStackTest extends TestCase {

            private OgnlValueStack valueStack;

            private Employee employee;

            

            @Override

            protected void setUp() throws Exception {

                        valueStack = new OgnlValueStack();

                        employee = new Employee();

                        valueStack.push(employee);

            }

  

            public void testCouldGetDataFromObjectInOgnlValueStackByEL() throws Exception{

                        employee.setName("Moxie");

                        Address address = new Address();

                        address.setCountry("China");

                        employee.setAddress(address);

                        

                        assertEquals("Moxie",valueStack.findValue("name"));

                        assertEquals("China",valueStack.findValue("address.country"));

            }

            

            public void testCouldSetDataForObjectInOgnlValueStackByEL() throws Exception{

                        valueStack.setValue("name","Moxie");

                        valueStack.setValue("address.country","China");

                        

                        assertEquals("Moxie",employee.getName());

                        assertEquals("China",employee.getAddress().getCountry());

            }

}

这是一个Junit Test,关于Junit的使用不是本篇文章的范畴。作为一个Java开发者,熟悉这样的测试框架是最基本的要求。setUp方法在每个测试方法调用之前都会执行,它用来初始化每个测试方法都需要的对象和数据。我们的setUp方法首先创建两个对象:valueStack对象和employee对象,然后将employee对象入栈。这样,emloyee对象就在值堆栈的最上端。

第一个测试方法testCouldGetDataFromObjectInOgnlValueStackByEL测试可以用表达式语言取得值堆栈里的对象数据。我们首先为值堆栈里的employee对象设置数据,设置了用户名和用户地址所在的国家。

第一个验证断言             assertEquals("Moxie",valueStack.findValue("name"))解释为:我们期望使用表达式语言“name”去ValueStack中查找得到的对象是”Moxie”。即期望valueStack.findValue("name")语句执行返回的数据是”Moxie”对象。再深入下去,这条语句会调用ValueStack里对象的getName方法(即employee对象的getName方法),并返回这个方法返回的数据。

第二个断言assertEquals("China",valueStack.findValue("address.country"))。它期望表达式语言“address.country”取得的数据是对象的address属性对象的country属性,即取得雇员对象的地址所在的国家。深入下去,它也就是调用对象employee的getAddress().getCountry()方法。  第二个测试方法testCouldSetDataForObjectInOgnlValueStackByEL测试通过表达式语言为ValueStack中的对象设置数据。

第一个设值语句valueStack.setValue("name","Moxie"),它通过表达式语言“name”将“”Moxie””赋值给ValueStack里的对象,即调用值堆栈中的对象的setName方法,并把后面的值作为方法的参数。同理,第二个设置语句会调用值堆栈中的对象的getAddress().setCountry()方法,把后面的数据作为setCountry方法的参数。

 

看了这个例子,我们就会知道如何通过ValueStack进行数据的存取。在我们使用ValueStack时需要注意:

1、  所有存取操作的目标对象都是已放入ValueStack中的对象。所以在使用之前,必须要先将对象入栈。例如我们在setup方法中的语句:valueStack.push(employee)。

2、  每一次WebWork请求,在创建Action对象之前都会先生成一个ValueStack对象,再将Action对象入栈。这样我们就可以通过表达式语言来直接存取action对象的数据,所以在WebWork中,action具有数据模型的功能。

3、  在对ValueStack进行存取操作时,我们的操作指令(表达式语言)并不知道它是对哪个对象进行操作。例如,我们在获取员工姓名时,我们给的操作指令是”name”,这时,并不知道ValueStack里面的对象一定就是employee。ValueStack会从上而下,遍历栈里面的对象,并试图调用当前遍历对象的getName方法,当它找到了这个方法,并执行之后,就会将执行得到的数据返回。这就是那神秘的ValueStack。

4、  关于值堆栈的context map,它是一个放置值堆栈上下文数据的对象。通过符号“#“再加上对象的名称,可以访问这些数据(只可以访问)。一些JavaServlet相关的数据都放在这个容器中。这个对webwork的标签库特别有用,这样我们可以直接通过表达式语言去访问request、attribute、session、application里的数据。例如:用property标签库打印出所有请求参数的数据,代码如下:<ww:property value="%{#request}"/>。

5、  其它。“top”是ValueStack里面的关键字,通过它可以找到ValueStack中最上面的那个对象。可以试着打印一下valueStack.findValue("top"))看看。表达式语言除了可以调用基于JavaBean规范的get和set方法之外,还可以调用一般的Java方法(这是需要使用方法的全名,并传入需要的参数),也可以直接访问Java类的静态字段和静态方法。具体的使用,可以查看WebWork的官方文档。

 

你可能感兴趣的:(框架,单元测试,JUnit,Webwork)