在jsp 页面中,用jsp中嵌套html页面Java代码的方式<%%>怎么取出struts2值栈中的对象

Struts2 | 详解如何在jsp页面中获取值栈中的数据 - 简书
Struts2 | 详解如何在jsp页面中获取值栈中的数据
上一篇文章我们已经了解了如何在struts2的值栈中存数据,那么这篇文章我们就一起来了解一下如何在jsp页面中获取值栈中的数据。
1 获取使用set方法存入值栈中的值
在上一篇文章中我们已经了解到,使用set方法向值栈中存值,使用的是map方式,那么就有key和value,取值时我们只需根据key来取就可以了。
代码演示如下:
首先我们使用set方法向值栈中存入一个值,关键代码:
//1 获取值栈对象
ActionContext context = ActionContext.getContext();
ValueStack stack = context.getValueStack();
//2 调用值栈对象中的set方法
stack.set("demo", "DemoData");
return "success";
然后我们在jsp页面中使用struts标签获取值栈中的这条数据,关键代码:
&!--导入struts标签库--&
&%@ taglib uri="/struts-tags" prefix="s"%&
&!-- 获取set方法设置的值
根据名称获取值--&
&s:property value="demo"/&
2 获取使用push方式存入值栈中的值
由上一篇文章可知,push方式存值是没有map结构的,那么没有key,我们如何取值呢?事实上struts2中将push方法存入值栈中的值都放在一个名为top的集合中,那么我们只需利用这个集合便可获取到其中的值
代码示例:
首先我们还是先用push方法将数据放入到值栈中去,关键代码:
//1 获取值栈对象
ActionContext context = ActionContext.getContext();
ValueStack stack = context.getValueStack();
//2 调用值栈对象中的push方法
stack.push("abcd");
return "success";
然后在jsp页面中获取值栈中的值,关键代码:
&!--导入struts标签库--&
&%@ taglib uri="/struts-tags" prefix="s"%&
&!-- 获取push方法设置的值 --&
&s:property value="[0].top"/&
这里需要特别注意jsp页面中使用ognl表达式获取list集合中元素的写法,不是 top[0]
而是 [0].top ,和我们在java代码中取list集合元素的写法是有区别的。
3 获取使用变量的get方法存入值栈中的值
这是往值栈中存值最常用的方法,这里我们将其分为取字符串,取对象和取list集合三种方式分别演示。
1 获取get方式存入值栈中的字符串
首先我们先使用变量方法存入一个字符串到值栈中,关键代码:
public String getUsername(){
public String execute() throws Exception {
username = "demo";
retrun "success";
然后我们在jsp页面中获取这个字符串的值,关键代码:
&!--导入struts标签库--&
&%@ taglib uri="/struts-tags" prefix="s"%&
&!--使用s标签获取username的值--&
&s:property value="username" /&
2 获取get方式存入值栈中的对象
首先将对象存入到值栈中去,关键代码:
private User user = new User();
public User getUser(){
public String execute() throws Exception {
user.setUsername("demo");
user.setPassword(123456);
user.setAddress("beijing");
return "success";
然后在jsp页面中获取这个对象,关键代码:
&!--导入struts标签库--&
&%@ taglib uri="/struts-tags" prefix="s"%&
&!--使用struts2标签获取对象的数据--&
&s:property value="user.username"/&
&s:property value="user.password"/&
&s:property value="user.address"/&
3 获取get方式存入值栈中的list集合
首先将list集合存入值栈,关键代码:
private List&User& list = new ArrayList&User&();
public List&User& getList() {
public String execute() throws Exception {
User user1 = new User();
user1.setUsername("小奥");
user1.setPassword("123");
user1.setAddress("美国");
User user2 = new User();
user2.setUsername("小王");
user2.setPassword("250");
user2.setAddress("越南");
list.add(user1);
list.add(user2);
return "success";
然后在jsp页面中获取list中的数据,在jsp中获取值栈中的list有三种方式,下面我们分别演示,关键代码:
&!--导入struts标签库--&
&%@ taglib uri="/struts-tags" prefix="s"%&
&! 获取值栈list集合数据 --&
获取list的值第一种方式:
&s:property value="list[0].username"/&
&s:property value="list[0].password"/&
&s:property value="list[0].address"/&
&s:property value="list[1].username"/&
&s:property value="list[1].password"/&
&s:property value="list[1].address"/&
获取list的值第二种方式:
&!-- 使用struts2标签 类似jstl的foreach标签
s:iterator:遍历值栈的list集合
&s:iterator value="list"&
&!-- 遍历list得到list里面每个user对象 --&
&s:property value="username"/&
&s:property value="password"/&
&s:property value="address"/&
&/s:iterator&
获取list的值第三种方式:
&s:iterator value="list" var="user"&
遍历值栈list集合,得到每个user对象
机制: 把每次遍历出来的user对象放到 context里面
获取context里面数据特点:写ognl表达式,需要
使用特殊符号 #
&s:property value="#user.username"/&
&s:property value="#user.password"/&
&s:property value="#user.address"/&
&/s:iterator&
这里第一和第二种方法都比较好理解,第三种方法需要注意的地方在:在s:iterator 标签时如果使用了var属性,那么struts2会在值栈的context部分新开辟一个临时空间,并将遍历出来的list集合中的元素放到这个临时空间中,那么这时候再使用ognl表达式获取数据要使用#号,否则无法取出数据。
这样可以避免浪费root部分的空间,加快检索的速度,因为我们通常操作数据都是操作root部分。
以上就是在jsp页面中取出值栈中值的几种办法,其中以第三中方法最常用,每种方法最好都要掌握,灵活运用即可。4235人阅读
Struts2中值栈的理解&
一、拦截器的初始化
&&&& 如图所示呢,在一次请求过程中,拦截器首先会创建以及初始化一个值栈对象以供使用。初始化过程中,在Map对象里面放了request=,session=,application=,sttr=,parameters=,....;在Stack里放了action对象和其他一些对象(注意对象栈是先进后出,类似弹匣)。由此可见值栈的生命周期是一次请求。
&&& 另外的拦截器,比如说ModelDriven和Params也会对值栈对象进行操作。ModelDriven的初始化会把model压到栈顶
Params的初始化会把参数设置到值栈对象里,从栈顶开始先查找对象栈里对象的属性,找到就初始化进去,找不到再放到Map的parameters里面。&&& 例如参数是这样:xx.action?id=3&name=ab&age=20&aaa=100,而栈中从栈顶的对象初始化依次为model(id=3 name=ab)、action(id age=20),而aaa参数会放到Map的parameters里面。
二、操作值栈
&& 1.在action类中对值栈的操作
&&&& 操作Map:&&ActionContext.getContext()
&&&&&&&&&&&&&&&&&&&&&& .put(k, v)
&&&&&&&&&&&&&&&&&&&&&&&.get(k) &
& & & & & & & & & & & 或者
&&&&&&&&&&&&&&&&&&&&&&&ActionContext.getContext().getValueStack()
&&&&&&&&&&&&&&&&&&&&&& .put(k, v)
&&&&&&&&&&&&&&&&&&&&&& .get(k)
& & &操作Stack:&ActionContext.getContext.getValueStack()
& & & & & & & & & & & & & .push(obj)
& & & & & & & & & & & & &.pop()
& & & 2.在Result中操作值栈(大多在jsp文件中的操作)
& & &&通过使用OGNL表达式操作值栈
& & & &格式:struts.xml中,格式如${ognl}
& & & & & & & & & &Jsp文件中,格式如%{ognl},而且必须写在struts2的自定义标签的属性中,在外面不会被解析
& & & &语法:
user & & & & & & & & = findValue(&user&) *
& & & & & & & & & &#user & & & & & & & = map.get(&user&)
& & & & & & & & & &#user.name & & = map.get(&user&).getName()
& & & & &* findValue()的查找顺序:
& & & & ①从对象栈的栈顶开始查找对象的属性,找到返回
& & & & ②如果对象栈中找不到,进Map查找对应key,返回value,找到返回
例子: & & & & & & & & &
&span style=&font-size:18background-color: rgb(255, 255, 255);&&&s:iterator value=&#roleList&&
&s:property value=&id&/&,
&s:property value=&name&/&,
&s:property value=&description&/&,
&s:a action=&role_delete?id=%{id}& onclick=&return confirm('确定要删除吗?')&&删除&/s:a&
&s:a action=&role_editUI?id=%{id}&&修改&/s:a&
&/s:iterator&&/span&
& & 在值栈的Map里面有roleList的List,取出来循环
& & 循环标签还有个特定的功能,循环一次开始后,会把对象拿到栈顶,因此id,name,dedcription会取到当前对象的属性,这里的“%{}”可以省略。
看官看到这里会有一问:
EL表达式可以使用值栈吗?
& & & &EL表达式原本的查找顺序为:
& & page,request,session,application,找到返回。
& & 值栈并不在EL表达式的作用范围之内,因此不能使用。但是
& & struts2对request对象进行了增强,即StrutsRequestWrapper对象,里面重写了getAttribute()方法:在request找不到之后到值栈里面找,因此
EL表达式的查找顺序变为:page,request,valueStack.findValue(),session,application。
所以上述例子也可以写为:
&s:iterator value=&#roleList&&
${description},
&s:a action=&role_delete?id=%{id}& onclick=&return confirm('确定要删除吗?')&&删除&/s:a&
&s:a action=&role_editUI?id=%{id}&&修改&/s:a&
&/s:iterator&
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:6843次
排名:千里之外Struts2值栈的理解 - 雨打蕉叶 - ITeye博客
博客分类:
数据传输背后机制:ValueStack(值栈)
在这一切的背后,是因为有了ValueStack(值栈)!
ValueStack基础:OGNL
要了解ValueStack,必须先理解OGNL(Object Graphic Navigatino Language)!
OGNL是Struts2中使用的一种表达式语言,它可以用于JSP的标签库中,以便能够方便的访问各种对象的属性;它用于界面将参数传递到Action(并进行类型转换)中;它还可以用于struts2的配置文件中!所以,非常有必要理解OGNL的基本机制。
OGNL称为对象图导航语言。所谓对象图,即以任意一个对象为根,通过OGNL可以访问与这个对象关联的其它对象。如:
.leadfar.struts2.
public class User {
public String getUsername() {
public void setUsername(String username) {
this.username =
public Group getGroup() {
public void setGroup(Group group) {
this.group =
.leadfar.struts2.
public class Group {
public String getName() {
public void setName(String name) {
this.name =
public Organization getOrg() {
public void setOrg(Organization org) {
this.org =
.leadfar.struts2.
public class Organization {
private String orgId;
public String getOrgId() {
return orgId;
public void setOrgId(String orgId) {
this.orgId = orgId;
上面三个类,描述了通过一个User对象,可以导航到Group对象,进而导航到Organization对象,以User对象为根,一个对象图如下所示:
User(root)
&& -- username
&& -- group
&&&&& -- name
&&&&& -- org
&&&&&&&& -- orgId
在真实的环境下,这个对象图可能会极其复杂,但是通过基本的getters方法,都应该能够访问到某个对象的其它关联对象。【对象图的导航,必须通过getters方法进行导航】
下述代码将创建一个User对象,及其相关的一系列对象:
User user = new User();
Group g = new Group();
Organization o = new Organization();
o.setOrgId("ORGID");
g.setOrg(o);
user.setGroup(g);
如果通过JAVA代码来进行导航(依赖于getters方法),导航到Organization的orgId属性,如下所示:
//用JAVA来导航访问
user.getGroup().getOrg().getOrgId();
【注意:导航的目的,是为了获取某个对象的值或设置某个对象的值或调用某个对象的方法!】
【注意:OGNL表达式语言的真正目的,是为了在那些不能写JAVA代码的地方执行JAVA代码,或者是为了更方便地执行JAVA代码】
利用OGNL进行导航的代码如下:
//利用OGNL表达式访问
String value = (String)Ognl.getValue("group.org.orgId", user);
Ognl.getValue()方法的第一个参数,就是一条OGNL表达式,第二个参数是指定在表达式中需要用到的root对象!
完整代码如下:
public void testOgnl01() throws Exception{
User user = new User();
user.setUsername("张三");
//利用OGNL表达式访问user对象的username属性
String value = (String)Ognl.getValue("username", user);
log(value);
public void testOgnl02() throws Exception{
User user = new User();
Group g = new Group();
Organization o = new Organization();
o.setOrgId("ORGID");
g.setOrg(o);
user.setGroup(g);
//用JAVA来导航访问
log(user.getGroup().getOrg().getOrgId());
//利用OGNL表达式访问
String value = (String)Ognl.getValue("group.org.orgId", user);
log(value);
public void testOgnl03() throws Exception{
User user = new User();
Group g = new Group();
Organization o = new Organization();
o.setOrgId("ORGID");
g.setOrg(o);
user.setGroup(g);
//用JAVA来导航访问
log(user.getGroup().getOrg().getOrgId());
//也可以在表达式中使用#root来代表root对象
String value = (String)Ognl.getValue("#root.group.org.orgId", user);
log(value);
private void log(Object o){
System.out.println(o);
Context对象
在OGNL的表达式中,有可能需要访问到多个毫不相干的对象,这时候,我们需要给OGNL传递一个Map类型的对象,把表达式中需要用到的对象放到Map中即可!这个Map对象,称为context。
要在表达式中访问到context中的对象,需要使用“#对象名称”的语法规则。
public void testOgnl04() throws Exception{
User user = new User();
user.setUsername("张三");
Group g = new Group();
Organization o = new Organization();
o.setOrgId("ORGID");
g.setOrg(o);
user.setGroup(g);
User user2 = new User();
user2.setUsername("李四");
Map context = new HashMap();
context.put("u1", user);
context.put("u2", user2);
//在表达式中需通过“#+对象的名称”来访问context中的对象
//如果表达式中没有用到root对象,那么可以用任意一个对象代表root对象!
String value = (String)Ognl.getValue("#u1.username + ',' + #u2.username", context,new Object());
log(value);
public void testOgnl05() throws Exception{
User user = new User();
user.setUsername("张三");
Group g = new Group();
Organization o = new Organization();
o.setOrgId("ORGID");
g.setOrg(o);
user.setGroup(g);
User user2 = new User();
user2.setUsername("李四");
User user3 = new User();
user3.setUsername("王五");
Map context = new HashMap();
context.put("u1", user);
context.put("u2", user2);
//给OGNL传递root对象及context对象,以便解释对应的表达式
String value = (String)Ognl.getValue("#u1.username + ',' + #u2.username + ',' + username", context,user3);
log(value);
利用OGNL表达式进行赋值
OGNL表达式也可以用于赋值操作。
public void testOgnl06() throws Exception{
User user = new User();
//调用setValue()方法来进行赋值
//第一个参数:OGNL表达式
//第二个参数:root对象
//第三个参数:要赋的值
Ognl.setValue("username", user, "张三");
log(user.getUsername());
public void testOgnl07() throws Exception{
User user = new User();
Map context = new HashMap();
context.put("u", user);
//调用setValue()方法来进行赋值
//第一个参数:OGNL表达式
//第二个参数:context对象
//第三个参数:root对象
//第四个参数:要赋的值
Ognl.setValue("#u.username", context, new Object(), "张三");
log(user.getUsername());
public void testOgnl08() throws Exception{
User user = new User();
Map context = new HashMap();
context.put("u", user);
//利用赋值符号"="来进行赋值
Ognl.getValue("#u.username = '李四'", context, new Object());
log(user.getUsername());
public void testOgnl09() throws Exception{
User user1 = new User();
User user2 = new User();
Map context = new HashMap();
context.put("u1", user1);
context.put("u2", user2);
//在一个表达式中可以用逗号分隔,同时执行多个表达式
Ognl.getValue("#u1.username = '李四',#u2.username='王五'", context, new Object());
log(user1.getUsername());
log(user2.getUsername());
利用OGNL调用对象的方法
public void testOgnl10() throws Exception{
User user = new User();
//如果是调用root对象的方法,可以直接使用方法的名称来调用方法
Integer value = (Integer)Ognl.getValue("addSomething(1,1)", user);
log(value);
public void testOgnl11() throws Exception{
User user = new User();
user.setUsername("李四");
//如果是调用root对象的方法,可以直接使用方法的名称来调用方法
String value = (String)Ognl.getValue("getUsername()", user);
log(value);
public void testOgnl12() throws Exception{
User user = new User();
Ognl.getValue("setUsername('王五')", user);
String value = (String)Ognl.getValue("getUsername()", user);
log(value);
public void testOgnl13() throws Exception{
User user = new User();
user.setUsername("王五");
//调用静态变量
//注意:out是System中的静态变量,out是PrintStream类型的一个对象
//而println()则是out这个对象中的实例方法(不是静态方法)
//调用静态方法,需要在类名和变量名前面加上@来调用,对于实例方法,用"."来调用
Ognl.getValue("@System@out.println(username)", user);
public void testOgnl14() throws Exception{
User user = new User();
user.setUsername("wangwu");
//调用静态方法,注意使用全路径类名
Ognl.getValue("@System@out.println(@cn.com.leadfar.utils.Utils@toUpperCase(username))", user);
利用OGNL访问数组、集合对象
public void testOgnl15() throws Exception{
Object root = new Object();
Map context = new HashMap();
//利用OGNL创建java.util.List对象
List list = (List)Ognl.getValue("{123,'xxx','kdjfk'}", context, root);
context.put("list", list);
//利用OGNL创建数组
int[] intarray = (int[])Ognl.getValue("new int[]{23,45,67}", context, root);
context.put("intarray", intarray);
//利用OGNL表达式创建java.util.Map对象
Map mapvalue = (Map)Ognl.getValue("#{'listvalue':#list,'intvalue':#intarray}", context, root);
context.put("mapvalue", mapvalue);
//利用OGNL表达式访问这些数组和集合对象
Ognl.getValue("@System@out.println(#list[1])", context,root);
Ognl.getValue("@System@out.println(#intarray[2])", context,root);
Ognl.getValue("@System@out.println(#mapvalue.listvalue[0])", context,root);
Ognl.getValue("@System@out.println(#mapvalue['intvalue'][0])", context,root);
public void testOgnl16() throws Exception{
List root = new ArrayList();
User user1 = new User();
user1.setUsername("张三");
User user2 = new User();
user2.setUsername("李四");
root.add(user1);
root.add(user2);
//如果root对象是List类型
log(Ognl.getValue("#root[0].username", root));
log(Ognl.getValue("#root[1].username", root));
更多的特性,请参考官方的文档
OGNL官方文档地址:/ognl/html/LanguageGuide/index.html
应用:ValueStack
理解ValueStack的基本机制!对各种现象作出解释。
ValueStack实际上就是对OGNL的封装,OGNL主要的功能就是赋值与取值,Struts2正是通过ValueStack来进行赋值与取值的!
ValueStack是一个接口,而OgnlValueStack是strtus2中的缺省实现。ValueStack中的数据,分两个部分存放:root和context(这与OGNL中的概念一致),同时ValueStack暴露相关的接口:
void setValue(String expr, Object value);
Object findValue(String expr);
用来通过OGNL表达式对ValueStack中的数据进行操作!
ValueStack中的root对象是CompoundRoot,CompoundRoot继承了ArraryList,提供了额外的方法:push()和pop()方法,用来对root对象中所包含的数据进行存取!
public class CompoundRoot extends ArrayList {
public CompoundRoot() {
public CompoundRoot(List list) {
super(list);
public CompoundRoot cutStack(int index) {
return new CompoundRoot(subList(index, size()));
public Object peek() {
return get(0);
public Object pop() {
return remove(0);
public void push(Object o) {
add(0, o);
正是通过这两个方法,CompoundRoot变成了一个栈结构!压栈操作,将导致对象被放到CompoundRoot的第0个元素上(第0个元素是栈顶),其它对象被依次往后移动;出栈操作,将导致CompoundRoot的第0个元素被移除(即栈顶元素被弹出),其它对象被依次往前移动!
OGNL不支持多个root对象,而struts2能够支持多个root对象,它对OGNL做了扩展。
如果某个OGNL表达式被传递给ValueStack(即调用ValueStack的setValue或findValue方法),而表达式中包含有对root对象的访问操作,ValueStack将依次从栈顶往栈底搜索CompoundRoot对象中所包含的对象,看哪个对象具有相应的属性,找到之后,立刻返回。
在Struts2中,一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是CompoundRoot中的一个元素。看下面的代码:
public class UserAction {
//查看用户的详细信息
public String detail(){
username = "张三";
return "detail";
在Action中,给Action的username/age/valid赋值。Detail页面如下:
username:&s:property value="username"/& &br/&
valid:&s:property value="valid"/& &br/&
age:&s:property value="age"/& &br/&
上述JSP页面将能正确将它们的值取出。&s:property value=”ognl表达式”/&。在s:property标签中的OGNL表达式,最终会交给ValueStack来解释。username就是一个OGNL表达式,意思是调用root对象的getUsername()方法。Struts2将自动搜索CompoundRoot中有哪些元素(从第0个元素开始搜索),检测这些元素是否有getUsername()方法,如果第0个元素没有getUsername()方法,将继续搜索第1、2、3……个元素是否有getUsername()方法。
在上面的例子中,CompoundRoot中只有一个对象,就是userAction对象,而这个对象中正好有getUsername()方法,所以,上述JSP代码将能够将值正确取出。
再看下面的例子:
public class UserAction {
//查看用户的详细信息
public String detail(){
username = "张三";
name = "王五";
User u = new User();
u.setUsername("赵毅");
ActionContext.getContext().getValueStack().push(u);
return "detail";
在上面这个UserAction的代码中,我们直接调用ActionContext.getContext().getValueStack().push()方法,把一个User对象(这个对象拥有getUsername()和setUsername()方法)直接压入到ValueStack中,这时候,在ValueStack的CompoundRoot中将有两个元素:第0个元素是刚刚压入的user对象[赵毅],而第1个元素是userAction对象[张三],如果在JSP中使用下面的表达式来取值:
&s:property value=”username”/& ,那么输出的值将是“赵毅”!道理上面已经讲过了,struts2将会从第0个元素开始搜索CompoundRoot中的对象,第0个元素正是刚刚压入的那个user对象!
如果在JSP中使用&s:property value=”name”/&来取值,将取出“王五”,因为第0个元素user对象没有name属性,所以,会继续搜索第1个元素userAction对象,在这个对象中就有name属性了!
再看下面的代码:
public class UserAction {
//查看用户的详细信息
public String detail(){
username = "张三";
List list = new ArrayList();
for(int i=0; i&10; i++){
User user = new User();
user.setUsername("User"+i);
list.add(user);
ActionContext.getContext().put("users", list);
User u = new User();
u.setUsername("赵毅");
ActionContext.getContext().getValueStack().push(u);
return "detail";
对应的JSP如下:
&s:property value="username"/& &br/&
&s:iterator value="#users"&
&s:property value="username"/&
&s:property value="#root[2].username"/&&br/&
&/s:iterator&
&s:property value="username"/&
&s:property value="#root[1].username"/& &!-- 张三 --&
根据刚才的示例,我们知道,第1行的username是“赵毅”(因为JSP在执行这行代码的时候,CompoundRoot中有两个元素:第0个是“user对象赵毅”,第1个是“userAction对象张三”),因此第1行的username将取出CompoundRoot中第0个元素的username属性:赵毅
第2行代码是iterator标签,只定义了一个value属性,iterator标签将循环访问users这个List中的User对象,并把当前循环的user对象压入到CompoundRoot中!所以,在第3行和第4行代码被执行的时候,CompoundRoot中总共有3个元素:第0个元素是被iterator标签压入的当前循环的user对象;第1个元素是“user对象赵毅”;第2个元素是“userAction对象张三”,因此第3行代码的执行结果就是输出“UserX”,即当前循环的user对象的username属性!iterator标签将会依次取出List中的user对象,并不断压入/弹出user对象(每次循环,都将执行一遍压入/弹出)。而第4行代码取第2个元素的username属性,即userAction对象的username属性:张三。
第5行代码执行完成之后,在CompoundRoot中将剩下2个元素,与第2行代码被执行之前一样。所以,第6行代码的输出和第1行代码的输出结果是一样的,而第7行代码将取出userAction对象的username属性:张三
浏览 10519
浏览: 156150 次
来自: 成都
你真的很厉害,懂得不懂得,都跟我们讲清楚了。你这才叫学知识,透 ...
第一种方法: 过滤器不太好,建议在service层时 由于se ...
您好,看了您的这个教程受益不小,我就是想问问您在sha1后面加 ...
OGNL表达式,context, valueStack都讲清楚 ...

我要回帖

更多关于 jsp页面嵌套java代码 的文章

 

随机推荐