1. OGNL表达式
1.1 OGNL表达式概述
1.1.1 什么是OGNL表达式
OGNL的全称是对象图导航语言(Object-Graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现必要的类型转换。如果把表达式看作是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。
1.1.2 OGNL表达式的由来
它原本是xwork2中的默认表达式语言,当年OpenSymphony和apache在合作开发struts2框架时,把这个表达式也引进来了,所以就变成了struts2的默认表达式语言。
1.1.3 OGNL表达式的使用要求
要想使用ognl表达式,一般情况下都得需要使用struts2的标签库。
1 | <%@ taglib uri="/struts-tags" prefix="s" %> |
1.1.4 它的特点
它不仅可以用于取值,显示。还可以赋值。取值是我们程序员使用框架做的事情。赋值是框架为我们做的。
1.2 OGNL表达式的基本用法
1.2.1 s:property标签输出内容到浏览器
1.2.1.1 s:property的用法
1 | <%--要想使用OGNL表达式获取数据,此时需要借助struts2的标签库 |
1.2.1.2 OGNL表达式和字符串的转换
1 | <%--OGNL表达式和字符串的转换 |
1.2.2 OGNL表达式访问对象的方法
1 | <%--OGNL表达式访问对象的方法 --%> |
1.2.3 OGNL表达式访问类的静态属性和静态方法
1 | <%--OGNL表达式访问类的静态成员(静态属性) |
1 | <%--OGNL表达式访问类的静态方法 |
1.2.4 OGNL表达式操作集合
1.2.4.1 list集合
1 | <%--操作List集合 |
1.2.4.2 map集合
1 | <%--操作Map集合 |
2. OGNL上下文
2.1 ContextMap
2.1.1 ContextMap概述
它是OGNL上下文对象,是struts2中封装数据最大的对象。我们一次请求中所有用到的信息都可以在它里面找到。它是一个Map结构的对象,其中key是字符串,value是一个Object。
2.1.2 ContextMap中封装的数据
我们把这些内容拿出来逐个分析一下,得到下面的表格:
Map的key(类型是String) | Map的Value (类型是Object) | 说明信息 |
---|---|---|
application | Java.util.Map<String,Object> | 封装的应用域中的所有数据 |
session | Java.util.Map<String,Object> | 封装的会话域中的所有数据 |
request | Java.util.Map<String,Object> | 封装的请求域中的所有数据 |
valueStack(特殊) | com.opensymphony.xwork2.ognl.OgnlValueStack | 它是List结构 |
parameters | Java.util.Map<String,String[]> | 封装的是请求参数 |
attr | Java.util.Map<String,Object> | 封装的是四大域的组合数据,从最小的域开始搜索 |
action | com.opensymphony.xwork2.ActionSupport | 当前执行的动作类对象 |
2.2 ActionContext
2.2.1 ActionContext对象概述
它是一个工具类,是struts2框架提供给我们的,可以让我们调用其中的方法,快速的操作ContextMap。用它操作OGNL上下文对象,比直接操作ContextMap要方便很多。
2.2.2 ActionContext对象与ContextMap的关系
ActionContext就相当于对ContextMap进行了一次再封装。
2.2.3 ActionContext何时创建
由于ActionContext是操作的ContextMap,而ContextMap中封了我们一次请求的所有数据,所以它的创建应该是每次请求访问Action时,即核心控制器(StrutsPrepareAndExecuteFilter)的doFilter方法执行时,下图是代码截取:
2.2.4 ActionContext的线程安全
我们都知道,java的web工程是多线程的,那么每个线程在访问Action时,都会创建自己的ActionContext,那么是如何保证在获取ActionContext时,每个线程都能获取到自己的那个呢?
答案就是,每次创建ActionContext时,把对象绑定到当前线程上。下图是代码截取:
2.2.5 ActionContext的获取
使用ActionContext类中的静态方法getContext()从当前线程上获取
2.2.6 获取ContextMap中的数据
2.2.6.1 s:debug标签的使用
1 | <%-- 引入标签库 --%> |
2.2.6.2 使用OGNL表达式获取Map中的数据
动作类存数据:
1 | /** |
在页面中使用OGNL表达式获取:
1 | <%--借助struts2的s:property标签和OGNL表达式获取ActionContext存入的数据 |
2.3 ValueStack对象
2.3.1 ValueStack对象概述
ValueStack是Struts的一个接口,字面意义为值栈,OgnlValueStack是ValueStack的实现类,客户端发起一个请求struts2架构会创建一个action实例同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿整个 Action 的生命周期。
它是ContextMap中的一部分,里面的结构是一个List,是我们可以快速访问数据一个容器。它的封装是由struts2框架完成的。
通常情况下我们是从页面上获取数据。它实现了栈的特性(先进后出)。
2.3.2 ValueStack的内部结构
在 OnglValueStack 中包含了一个CompoundRoot的对象,该对象继承了ArrayList,并且提供了只能操作集合第一个元素的方法,所以我们说它实现了栈的特性。同时,它里面定义了一个ContextMap的引用,也就是说,我们有值栈对象,也可以通过值栈来获取ContextMap。
2.3.3 获取ValueStack中的数据
2.3.3.1 值栈中都有什么
首先我们要明确,值栈中存的都是对象。因为它本质就是一个List,List中只能存对象。
值栈中包含了我们通过调用push方法压栈的对象,当前执行的动作了和一个名称为DefaultTextProvider的类。值栈中的内容如下图:
2.3.3.2 在动作类中往值栈中存入数据
1 | /** |
2.3.3.3 我们可以获取值栈中的什么
一般情况下,我们都是根据debug标签中显示的Property Name来获取Property Value。
当然我们也可以获取栈顶对象。
2.3.3.5 在页面上使用OGNL表达式获取数据
1 | <%--获取值栈的数据也需要借助于struts2的标签库 |
2.3.3.6 OGNL表达式执行时调用的方法
1 | <%--s:property在通过OGNL表达式获取数据时,所调用的方法:ValueStack中的findValue(String expr); --%> |
3. Struts2中使用EL表达式
3.1 EL表达式回顾
EL表达式的写法:${表达式}。
它是从四大域中,由小到大逐个域搜索,根据名称获取值。只要找到了,就不再继续搜索。
它的原理:使用的是PageContext类中的findValue方法。
3.2 Struts2对EL表达式的改变
Struts2框架中对EL表达式做了如下改变:
1 | EL表达式原来的搜素顺序: |
struts2框架对request对象进行了包装,并且对getAttribute方法进行了增强,代码如下:
4. OGNL表达式中的各种符号总结
4.1 %
1 | 1、把OGNL表达式转成普通字符串 %{""} |
4.2 #
1 | 1、获取ContextMap中的数据。#key |
4.3 $
1 | 1、EL表达式使用 |
5. 案例-优化客户列表的展示
5.1 改造Action
我们把之前查询所有客户的动作方法改造一下,之前我们是把查询结果存入请求域中了,而此时我们只需要在Action中定义一个集合,并且提供get/set方法,它就会出现在值栈中。就可以在页面中使用OGNL表达式获取。
1 | /** |
5.2 改造jsp
在显示客户列表时,我们之前采用的是jstl标签库的c:forEach标签,今天我们将使用struts2提供的迭代标签s:iterator。
1 | <%-- |
-------------本文结束感谢您的阅读-------------
本文标题: Struts2(三)
本文链接: https://wgy1993.gitee.io/archives/4179e9cb.html
版权声明: 本作品采用 CC BY-NC-SA 4.0 进行许可。转载请注明出处!
