回顾 一、Servlet的API ActionContext对象 ServletActionContext对象 二、结构类型的跳转 全局结果 局部结构 type属性 三、数据的封装 属性驱动方式 模型驱动方式 实现ModelDrivern 接口 四、拦截器(自定义拦截器) OGNL表达式概述 一、OGNL是Object Navigation Language(对象图导航语言) 所谓对象图,即以任意一个对象为根,经过OGNL能够访问与这个对象关联的其余对象 经过它简单一致的表达式语法,能够存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。使用相同的表达式去存取对象的属性 二、Struts2框架使用OGNL做为默认的表达式语言 OGNL是一种比EL强大不少倍的语言 xwork提供OGNL表达式 ognl-3.0.5.jar 三、OGNL提供五大类功能 支持对象方法调用 支持类静态的方法调用和值访问 访问OGNL上下文(OGNL context)和ActionContext 支持赋值操做和表达式串联 操做集合对象 一、什么是值栈 值栈就至关于Struts2框架的数据的中转站,向值栈存入一些数据,从值栈中获取到数据 ValueStack 是Struts2提供一个接口,实现类OgnlValueStack--值栈对象(OGNL是从值栈中获取数据的) Action是多例的,有一块儿请求,建立Action实例,建立一个ActionContext对象,表明的是Action的上下文对象,还会建立一个ValueStack对象 每一个Action实例都有一个ValueStack对象(一个请求,对应一个ValueStack对象) 在其中保存当前Action对象和其余相关对象 Struts框架把ValueStack对象保存在名为“struts.valueStack”的请求属性中,request中(值栈对象是request一个属性) ValueStack vs = (ValueStack)request.getAttribute("struts.valueStack"); 二、值栈的内部结构 值栈由两部分组成 root Struts把动做和相关对象压入ObjectStack中--List context Struts把各类各样的映射关系(一些Map类型的对象)压入ContextMap中 Struts会默认把下面这些映射压入ContextMap(Context)中 request表明的是Map集合的key值,value值其实也是一个Map值 parameters:该Map中包含当前请求的请求参数?name=xxx&password=123 request:该Map中包含当前request对象中的全部属性 session:该Map中包含当前session对象中的全部属性 application:该Map中包含当前application对象中的全部属性 attr:该Map按以下顺序来检索某个属性:request、session、application ValueStack存在root属性(CompoundRoot)context属性(OgnlContext)、 CompoundText就是ArrayList OgnlContext就是Map context对应Map引入root对象 context中还存在request、session、application、attr、parameters对象引用 OGNL表达式访问值栈中的数据 访问root中数据时,不须要# 访问request、session、application、attr、parameters对象数据必须写# 操做值栈默认指操做root元素 三、值栈对象的建立,ValueStack和ActionContext是什么关系 值栈对象是请求时建立的 ActionContext是绑定到当前的线程上,那么在每一个拦截器或者Action中获取的ActionContext是同一个 ActionContext中存在一个Map集合,该Map集合和ValueStack的contextMap是同一个地址 ActionContext中能够获取到ValueStack的引用 四、获取值栈对象 (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack"); (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY); ActionContext.getContext().getValueStack(); 五、向值栈保存数据(主要针对root栈) valueStack.push(Object obj) push方法的底层调用root对象的push方法(把元素添加到0位置) valueStack.set(String key,Object obj) 源码获取map集合(map多是已经存在的,有多是新建立的)把map集合push到栈顶,再把数据存入到map集合中 在jsp中经过<s:debug/>查看值栈的内容 六、从值栈中获取值 访问root中数据 不须要# 访问context其余对象数据 加# 若是向root中存入对象的话 优先使用push方法 若是向root中存入集合的话,优先要使用set方法 在OGNLContext中获取数据 在Action中向与对象中存入值 xxxx:<s:property value="#xxxx.属性"/> request、session、application、attr、parameters 七、获取到值栈中的数据 为何EL也能访问值栈中的数据 StrutsPreparedAndExecuteFilter的doFilter代码中 request = prepare.wrapRequest(request) 对request对象进行了保证,StrutsRequestWrapper org.apache.struts2.dispatcher.StrutsRequestWrapper 加强了request的getAttribute Object attribute = super.getAttribute(key); if (ctx != null && attribute == null) { boolean alreadyIn = isTrue((Boolean) ctx.get(REQUEST_WRAPPER_GET_ATTRIBUTE)); // note: we don't let # come through or else a request for // #attr.foo or #request.foo could cause an endless loop if (!alreadyIn && !key.contains("#")) { try { // If not found, then try the ValueStack ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.TRUE); ValueStack stack = ctx.getValueStack(); if (stack != null) { attribute = stack.findValue(key); } } finally { ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.FALSE); } } 访问request范围的数据时,若是数据找不到,在值栈中找 request对象 具有访问值栈数据的能力(查找root的数据) OGNL的特殊符号 一、#符号的用法 获取contextMap中的数据 <s:property value="#xxxx.属性"/> request/session/application/attr/parameters 构建一个集合 性别<s:radio name="sex" list="{'男','女'}"></s:radio> 性别<s:radio name="sex" list="#{'1':'男','2':'女'}"></s:radio> 二、%符号的用法 强制字符串解析成OGNL表达式 例如:在request域中存入值,而后在文本框(<s:textfield>)中取值,如今到value上 <s:textfield value="%{#request.msg}"/> {}中值用''引发来,此时再也不是ognl表达式,而是普通的字符串 <s:property value="%{'#request.msg'}"/> <s:property value="'aaa'"/> 三、$符号的用法 在配置文件中可使用OGNL表达式,例如:文件下载的配置文件 <action name="download" class="my.demo2.DownLoadAction"> <result> <param name="contentType">${contentType}</param> <param name="contentDisposition">attachment:filename=${downFilename}</param> </result> </action>