前边我们们讲了action节点的通配符映射、result节点和action节点默认的处理类ActionSupport。今天我们来讲一讲OGNL和声明式异常。
1.OGNL
OGNL的全称是对象导航图语言,即Object graph navigator language。它的作用是在JSP页面使用来获取值栈封装域的对象、Action对象、请求参数对象和Map。
2.值栈
值栈是一个中转站,负责让JSP页面之间,Action处理类之间共享对象及其中的属性。值栈贯穿整个请求action的生命周期,每个action请求都对应一个值栈的对象。值栈当中存储了域对象封装成的Map、Action对象(不直接包含域对象)。它的逻辑存储主要分为两部分
① Map栈
实际上为OGMLContext类型代表的,是Map的子类,里边只有一个键值对,是ActionContext(这也是为什么我们可以在Action中通过ActionContext对象获取各种Map的原因)。里边保存着各种域对象对应的Map:如requestMap sessionMap applicationMap parameterMap 和 attrMap(这个map按照request-session-application来检索属性)。
② 对象栈
实际上是一个CompoundRoot类型代表的,是一个继承ArrayList接口的栈。内含和Action实例相关的对象。是一个数据结构意义上的栈,是符合先进后出的原则的,这一点我们通过观察CompoundRoot类的remove(0)方法就可以得出。
③ 值栈ValueStack对象可以在Action类中用ActionSupport对象来获取,从而向值栈栈顶亚入对象。
2. 用OGNL获取值栈中的内容
① 用OGNL获取值栈中对象栈的对象
Struts2用<s:property></s:property>标签获取值栈中对象的属性值。
格式:<s:property value="object.propertyname'></s:property> object.propertyname也可以表示为object['propertyname']
对象栈里的对象可以通过一个从0开始的下标来引用:[0].propertyname 。
当从值栈中直接搜索属性而未明确指定对象时,将按照从栈顶依次向下的策略进行搜索。[0]的含义是从第一个对象开始搜索而不是仅仅代表第一个对象。
默认情况下,Action通过反射创建的实例对象,会被自动放到值栈的栈顶。这个操作是在到大Action的处理方法之前就进行的,所以如果我们在Action方法中手动的向值栈压入一个对象,则这个对象是在Action实例对象之上的。
② OGNL读取值栈中的Map栈的内容
若希望在JSP页面中访问Map栈的内容,格式是:<s:property value="#object.propertyname"></s:property> (和访问对象栈唯一不同的是需要在对象前加一个井号#)。这样就确保搜索在Map栈中进行,而不会跑到对象栈中。
3.OGNL和EL的区别
显然,OGNL和标签结合的威力大大大于EL表达式的功能!
① OGNL调用值栈中任意一个对象的静态字段和静态方法
需要注意的是,OGNL默认不支持调用静态的方法,我们需要在struts.xml文件中设置一个常量的值为true才可以。
② 访问对象的数组类型的属性
值栈中的对象的属性有时可能是一个数组类型:如String[] 数组。我们可以像访问其他对象的属性那样访问他们,并且通过下标的方式确定访问数组中指定的元素,我们还可以访问属性的length属性来获取数组对象中元素的个数。
③ 访问List,和访问数组类似。
④ 访问值栈中Map类型的对象
我们可以像平常访问Map对象那样,通过map[key] map[value] map.size()分别获取Map对象的键 值 和 长度。
4. 声明式异常
① 声明式异常机制是由ExceptionMappingInterceptor拦截器负责处理异常的(再次证明了Struts框架的工作其实大部分是靠一系列拦截器来完成的)。当某个exception-mapping节点声明的异常类型对象被捕获时,ExceptionMappingInterceptor拦截器就会向值栈栈顶中压入两个对象:exception(是被捕获异常的对象)和exceptionStack(是被捕获异常的栈)。
② exception-mapping 节点
我们可以在struts.xml文件中的action节点下配置一个eexception-mapping节点,指明请求中出现的异常类型,并指明当出现此类型的异常时要去往的result的页面(result属性中指明配置的一个result节点的name属性值)。这个声明式异常仅仅可以在这个action请求中使用。
我们还可以配置一个全局的声明式异常及全局的result相应页面,让所有的action请求发生异常时,都去到指明的全局result相应页面。
<global-exception-mappings>
<exception-mapping class="" result="1">
</global-exception-mappings>
<global-results>
<result name="1">/xxx.jsp</result>
</global-results>