在struts2中,我们应该知道,如果我们没有往值栈(根)中放入数据的话,那么我们的动作类默认是在值栈的栈顶。
我们知道EL表达式是从四大域对象中依次查找属性。搜索范围是由小到大。
page Scope————>request Scope————>sessionScope————>application Scope
现在如下:
public class Demo3Action extends ActionSupport {
//这是动作类中的属性。动作类的对象引用默认是在ValueStack的栈顶
private String name = "动作类中的name";
public String execute(){
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("name", "request中name");//这是在大Map中一个key为request的小Map中的是
ServletContext application = ServletActionContext.getServletContext();
application.setAttribute("name", "应用域中的name");
//获取ActionContext对象
ActionContext context = ActionContext.getContext();
context.put("name", "ActionContext中的name");
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
jsp代码:
EL表达式:${name}<%--pageContext.findAttribute("name") --%>
<hr/>
OGNL表达式:<s:property value="name"/>
执行结果没问题
现在把上面execute()方法当中的前两两行代码注释掉
// HttpServletRequest request = ServletActionContext.getRequest();
// request.setAttribute("name", "request中name");//这是在大Map中一个key为request的小Map中的是
执行结果如下:
按照EL的执行顺序应该是EL表达式上的结果是“应用域中的name”才对但是却不是,而是valueStack上的数据。
这就是struts2对EL表达式的改变,从valueStack当中request的引用就可以看出,Struts2对request进行了包装
我们来看这个类中的getAttribute()方法
这里就很清楚的说明了原因了,当EL表达式在request对象当中找不到时,获查找valuestack,而且当valuestack中没有时,获查找contextMap,找到了就返回,找不到就继续查找sessionsSope,applicationScope
Struts2中EL查找顺序改变:
EL表达式: page Scope————>request Scope————>sessionScope————>application Scope
OGNL表达式:page Scope————>request Scope————>valueStack(根中)————>contextMap————>sessionScope————>application Scope
OGNL配合通用标签的其他使用
1、iterator标签
public class Demo4Action extends ActionSupport {
//Action动作类的引用,默认情况下就在ValueStack的栈顶
private List<Student> students;
public String findAll(){
students = new ArrayList();
students.add(new Student("张三",21));
students.add(new Student("李四",22));
students.add(new Student("王五",23));
return SUCCESS;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
<table width="500px" border="1" align="center">
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
<%-- s:iterator:struts2的迭代标签
属性详解:
begin,end,step和jstl的forEach标签是一样的
value属性:要遍历的集合,是OGNL表达式。
var属性:取值就是一个字符串
如果写了该属性:把var的值作为key,把当前遍历的元素作为value。存到ActionContext这个大Map中
如果不写该属性:把当前遍历的元素压入valuestack的栈顶
status属性:遍历时的一些计数信息。
int getIndex() 从0开始
int getCount() 从1开始
boolean isFirst()
boolean isLast()
boolean isOdd()
boolean isEven()
--%>
<s:iterator value="students" var="s" status="st">
<tr>
<td><s:property value="#st.index" />
</td>
<td><s:property value="#s.name" />
</td>
<td><s:property value="#s.age" />
</td>
</tr>
</s:iterator>
</table>
<hr/>
<table width="500px" border="1" align="center">
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
<s:iterator value="students" status="st">
<tr>
<td><s:property value="#st.count" />
</td>
<td><s:property value="name" />
</td>
<td><s:property value="age" />
</td>
</tr>
</s:iterator>
</table>
<hr/>
结果:
2、OGNL投影(了解)
- 使用过滤条件投影
<%--OGNL的投影:(以下内容全是了解)添加过滤条件
a.“?#”:过滤所有符合条件的集合,如:users.{?#this.age > 19}
b.“^#”:过滤第一个符合条件的元素,如:users.{^#this.age > 19}
c.“$#”:过滤最后一个符合条件的元素,如:users.{$#this.age > 19}
--%>
<table width="500px" border="1" align="center">
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
<s:iterator value="students.{?#this.age>21}" status="st">
<tr>
<td><s:property value="#st.count" />
</td>
<td><s:property value="name" />
</td>
<td><s:property value="age" />
</td>
</tr>
</s:iterator>
</table>
- 投影指定属性
<%--OGNL的投影:指定输出内容
students.{name}========{"name1","name2","name3"}
--%>
<hr/>
<table width="500px" border="1" align="center">
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
<s:iterator value="students.{name}" status="vs" >
<tr>
<td><s:property value="#vs.count"/></td>
<td><s:property /></td>
<td><s:property /></td>
</tr>
</s:iterator>
</table>