第4章 对象图形导语言.pptx
http:/第四章第四章对象图形导航语言对象图形导航语言对象图形导航语言对象图形导航语言(OGNL)(OGNL)http:/中国十大品牌IT教育机构本章目标:OGNL表达式。什么是OGNL表达式。1.OGNL表达式,其实是一串特殊的字符串,通过这一串字符串可以快速的操作Java代码,甚至是不允许操作Java代码的地方,如JSP页面。ValueStack中的Context和root。1.Struts2是如何通过ValueStack来操作OGNL的。Struts2经常使用的几个标签1.包:如果只在Java代码中做测试,则只导入ognl.jar即可。http:/中国十大品牌IT教育机构数据传输背后机制:ValueStack(值栈)要了解ValueStack,必须先理解OGNL(ObjectGraphicNavigationLanguage)。OGNL是Struts2中使用的一种表达式语言1.它可以用于JSP的标签中,以便能够方便的访问各种对象的属性;2.它用于界面将参数传递到Action(并进行类型转换)中;3.它还可以用于struts2的配置文件中!所以,非常有必要理解OGNL的基本机制。Root对象1.OGNL称为对象图导航语言。所谓对象图,即以任意一个对象为root根,通过OGNL表达式可以访问与这个对象关联的其它对象。http:/中国十大品牌IT教育机构OGNL的目的:OGNL目的,是为了获取某个对象的值或设置某个对象的值或调用某个对象的方法!OGNL表达式语言的真正目的,是为了在那些不能写JAVA代码的地方执行JAVA代码,或者是为了更方便地执行JAVA代码。Ognl.getValue()方法的第一个参数,就是一条OGNL表达式,第二个参数是指定在表达式中需要用到的root对象!http:/中国十大品牌IT教育机构OGNLOGNL必须拥有一个根root和一个OGNL表达式。可选拥有一个Map类型的Context。OGNLOGNL表达式Context可选newObject()根必须OGNL表达式支持以下操作符:#、(单引号)等。http:/中国十大品牌IT教育机构#符的作用:访问根对象的属性或是方法不需要使用#,但如果非使用#来访问根对象的信息则必须使用#root,即与root关键字共同使用。如果是调用非根对象的方法或属性必须要使用#符。http:/中国十大品牌IT教育机构Context对象在OGNL的表达式中,有可能需要访问到多个毫不相干的对象,这时候,我们需要给OGNL传递一个Map类型的对象,把表达式中需要用到的对象放到Map中即可!这个Map对象,称为context。要在表达式中访问到context中的对象,需要使用“#对象名称”的语法规则。所谓context其实就是一个Map类型的对象。主要是因为在OGNL中,不支持多个root对象,那么如果需要在表达式中访问更多毫不相干的对象时,只能通过一个Map来把这些对象统一传递给OGNL。http:/中国十大品牌IT教育机构只有Context没有根对象的示例:第一个参数为OGNL表达式。第二个参数为Map类型的Context对象。第三个参数为根对象,此根对象为一个空的对象。但必须要传。http:/中国十大品牌IT教育机构同时给OGNL传递Context和root对象:注意是如何获取第三个对象中的值的:http:/中国十大品牌IT教育机构OGNL可以进行赋值操作:仅供了解:仅供了解:1.第一个参数为第一个参数为ONGL表达式。表达式。2.第二个参数为第二个参数为root对象。对象。3.第三个参数为设置的值。第三个参数为设置的值。下图第一个参数为:OGNL表达式,第二个参数为根对象,第三个参数为值。下图第一个参数为:OGNL表达式,第二个参数为Context对象,第三个参数为root对象。第四个参数为值。http:/中国十大品牌IT教育机构利用OGNL表达式调用对象的方法:以下代码通过两种方式调用,第一种方式调用的是非根对象的方法,第二种调用的是根对象的方法。http:/中国十大品牌IT教育机构符的作用:在OGNL中,符用来调用静态属性或是方法。当然必须是公共的。使用符默认调用的是Math中的静态方法,所以在第一种方法对Math类省略了。第二种是书写完整的代码。http:/中国十大品牌IT教育机构利用OGNL创建List和Map集合:以下创建List,第一个参数为OGNL表达式,第二个参数为root.l以下创建Map,第一个参数为OGNL表达式,第二个参数为root.,注意#符的使用。http:/中国十大品牌IT教育机构小结:通过上面的实现我们清楚的知道了两个问题:1.1:OGNL就是用来操作属性和方法的。2.2:OGNL操作的对像可以有两个一个是根root对象,它只能有一个。一个是Map的Context对象,它可以有多个。通过key,value来保存信息。那么Struts2的又是如何使用OGNL的呢?http:/中国十大品牌IT教育机构理解ValueStack的基本机制!对各种现象作出解释ValueStack实际上就是对OGNL的封装,OGNL主要的功能就是赋值与取值,Struts2正是通过ValueStack来进行赋值与取值的!ValueStack是一个接口,而OgnlValueStack是strtus2中的缺省实现。ValueStack中的数据,分两个部分存放:root和context(这与OGNL中的概念一致)。http:/中国十大品牌IT教育机构在ValueStack中有两个方法:见OgnlValueStack的源代码1.getContext()返回非根对象,即一个Map.2.getRoot()返回root根对象。而它是一个List。所以,ValueStack可以有多个根对象。ValueStack中的root对象是CompoundRoot,CompoundRoot继承了ArraryList,提供了额外的方法:push()和pop()方法,用来对root对象中所包含的数据进行存取!我们称为压栈和弹栈。http:/中国十大品牌IT教育机构CompoundRoot的源代码:正如右图所示:CompoundRoot变成了一个栈栈结构!压栈操作,将导致对象被放到CompoundRoot的第0个元素上(第0个元素是栈顶),其它对象被依次往后移动;出栈操作,将导致CompoundRoot的第0个元素被移除(即栈顶元素被弹出),其它对象被依次往前移动!http:/中国十大品牌IT教育机构Struts2的数据标签,是通过直接直接操作ValueStack对象获取数据的:在Struts2中,一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是CompoundRoot中的一个元素。在Struts2中,操作ValueStack的就是struts2的自定义标签,即/struts-tags.http:/中国十大品牌IT教育机构为了能说明问题,先让我们认识它的两个基本数据标签:1.s:property从ValueStack中获取属性输出。2.s:iterator遍历集合,每次遍历都将数据压栈和弹栈,即操作CompoundRoot.图中的第二步即是将Action压入栈顶。http:/中国十大品牌IT教育机构以下演示请求一个Action时,Action对象位于ValueStack的栈顶:第一步、1:在Struts2中,一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是CompoundRoot中的一个元素。看下面的代码:http:/中国十大品牌IT教育机构第一步、2:页面获取数据:JSP页面将能正确将它们的值取出。,意思是调用root对象的getName()方法。Struts2将自动搜索CompoundRoot中有哪些元素(从第0个元素开始搜索),检测这些元素是否有getName()方法,如果第0个元素没有,将继续搜索第1、2、3个元素是否有getName()方法。如果在栈中没有找到getName方法,则再去ActionContext,即request的map中去查找,如果没有则输出空字符串。http:/中国十大品牌IT教育机构注意,此时即使用户通过ActionContext.getContext().getSession().put(“name”,”someName”)也不会输出。因这它并不位于root中,而是位于Context中,对于位于Context中的信息则必须要使用#session.name的方式获取。http:/中国十大品牌IT教育机构以下代码手工将自己封装的对象压入栈顶:第二步:修改第一步的Action代码如下本身Action拥有一个name属性,然后又通过直接操作ValueStack将User类压入栈顶,所以,同样使用第一步2所示的代码,将返回“李四”,而age值则为空。Age返回空的原因为是User这个对象中也有一个age属性。但如果age不是User的属性,则会再找第1.2直到N个元素,真到找不到为止。如果找到就输出它的值。http:/中国十大品牌IT教育机构示例2:遍历Action代码如下:具有相同属性的对象被放到不同的域中http:/中国十大品牌IT教育机构页面遍历:第8行显示的名称为:张三,这很显然,因为是从root中获取。第10行依次显示Jack0.N,并不断的将信息压入栈顶,然后再删除。第13行,如果不使用#root1,则会与11行相同。第16行,显示张三。因为,遍历完成以后,栈又回复到以前的状态。http:/中国十大品牌IT教育机构示例3:当访问实现了ModelDriven接口的Action时在访问Action时,Struts2会做两个事1.先将Action压入栈中。2.再将Model,如User对像压入栈中。此时它位于栈顶。http:/中国十大品牌IT教育机构页面获取示例3的值:http:/中国十大品牌IT教育机构小结:通过以上分析,我们知道了:1.Struts2是通过标签直接与ValueStack打交道的。2.在ValueStack中,保存着一个根对象Root,其实它就是一个List.3.同时保存着一个Map,即Context非根对象。4.如果一个Action实现了ModelDriven接口,此时会先将Action压入栈中,再将Model压入栈中。按后进先出的原则,Model对象则位于栈顶。http:/中国十大品牌IT教育机构struts2中的OGNL上下文|-application|-session|contextmap-|-OgnlValueStack(root)user,action,OgnlUtil,.|-request|-parameters|-attrhttp:/中国十大品牌IT教育机构名称作用示例parameters读取请求参数request读取request中的属性session读取session中的属性application 读取application中的属性attrrequestsessionapplication顺序访问其属性30http:/中国十大品牌IT教育机构Struts2的OGNL操作符再说明:OGNL要结合struts标签来使用。由于比较灵活,也容易把人给弄晕,尤其是“%”、“#”、“$”这三个符号的使用。由于$广泛应用于EL中,这里重点写%和#符号的用法。http:/中国十大品牌IT教育机构%-用于说明内部是OGNL可执行的表达式,类似于eval.#-用于从某个范围中取出数据。$-在struts的配置文件或资源文件中使用。-用于调用某个类的静态方法。1.要打开此功能,请在struts.xml中添加以下配置:2.3.以上所有必须要配合struts2的标签共同使用。http:/中国十大品牌IT教育机构符操作静态成员和方法,必须是public的:http:/中国十大品牌IT教育机构“#”符号有三种用途:1访问属性对像:(1)、访问非根对象(struts中值栈为根对象)如OGNL上下文和Action上下文,#相当于ActionContext.getContext():1.如:,是直接从ActionContext中取数据。2.以下是获取其他数据:3.parameters4.包含当前HTTP请求参数的Map5.#parameters.id0作用相当于request.getParameter(id)6.request7.包含当前HttpServletRequest的属性(attribute)的Map8.#request.userName相当于request.getAttribute(userName)9.session10.包含当前HttpSession的属性(attribute)的Map11.#session.userName相当于session.getAttribute(userName)12.application13.包含当前应用的ServletContext的属性(attribute)的Map14.#application.userName相当于application.getAttribute(userName)15.attr用于按requestsessionapplication顺序访问其属性(attribute),#attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止。http:/中国十大品牌IT教育机构#”符号有三种用途:2操作集合:构造Map,如:#foo1:bar1,foo2:bar2#foo1:bar1,foo2:bar2这种方式常用在给radio或select、checkbox等标签赋值上。如果要在页面中取一个map的值可以这样写:http:/中国十大品牌IT教育机构%的作用:“%”符号的用途是在标签的属性值被理解为字符串类型时,告诉执行环境%里的是OGNL表达式。很有点类似javascript里面的eval()功能。以下将从map中获取一个key值。1.http:/中国十大品牌IT教育机构“$”的其他用途在Struts2配置文件中,引用OGNL表达式则应该使用$.1.listUser.action?msg=$msg