Struts:标签库

1,Struts2标签库

1.1,概述

Struts2标签库相对于Struts1进行了巨大的改进,支持OGNL表达式,不依赖任何表现层技术(可以在各种表现层技术中使用)。

我们可以在struts2-core-xxx.jar压缩文件的META-INF目录下找到struts-tags.tld文件,这个文件里定义了Struts2的标签。

Struts2对整个标签库提供了严格的分类,Strut2把所有标签都定义在一个s标签库里。虽然Struts2把所有的标签都定义在URI为"/struts-tags"的空间下,但依然可以对Struts2标签进行简单的分类。

Struts2可以将所有标签分成三类:

(1)用户界面标签(UI标签):主要用来生成HTML元素的标签。

  • 表单标签:主要用于生成HTML页面的FORM元素,以及普通表单元素的标签。
  • 非表单标签:主要用于生成页面上的tree,Tab页等。

(2)非用户界面标签(非UI标签):主要用于数据访问,逻辑控制。

  • 数据访问标签:主要包含用于输出值栈(ValueStack)中的值,完成国际化等功能的标签。
  • 流程控制标签:主要包含用于实现分支,循环等流程控制的标签。

(3)AJAX标签:用于支持Ajax效果

1.2,使用Struts2标签

struts2-core-2.5.26.jar下的META-INF/struts-tags.tld文件,这是Struts2的标签库定义的文件。

根据自定义标签,在标签库定义文件中<uri.../>元素很重要,该URI实际上相当于该标签库的唯一标识。 为了让JSP页面使用Struts2标签,通过jsp的代码的顶部加入以下的代码:

<%@ taglib prefix="s" uri="/struts-tags" %>

2,OGNL表达式

OGNL的全称是对象图导航语言,它是一种功能强大的开源表达式语言,同时也是Struts2的默认表达式语言。比EL(只能从域或内置对象中)表达式更强大。

OGNL的特点:

  • OGNL可以存取Java任意对象的任意属性,调用Java对象的方法
  • ONGL能够自动实现必要的类型转换。

OGNL上下文中的根对象可以直接访问,而引用上下文中的其他对象则需要使用“#”来标记 ;值栈中的任何对象都可以直接访问,而不需要使用 “#”

OGNL的参数:表达式、跟对象和上下文环境。

  • 表达式:表达式是OGNL的核心,所有的OGNL操作都是通过解析表达式后进行的。表达式指出了OGNL操作要做的工作。例如,name、student.name等表达式,表示取name或者student中的name的值。
  • 跟对象:OGNL的取值还需要一个上下文环境。设置了Root对象,OGNL可以对Root对象进行取值或写值等操作,Root对象所在环境就是OGNL的上下文环境(Context)。根对象是OGNL要操作的对象,在表达式规定了要完成的工作后,需要指定工作的操作对象。
  • 上下文环境:上下文环境规定了OGNL的操作"在哪里进行"。上下文环境Context是一个Map类型的对象,在表达式中访问Context中对象,需要使用"#"号加上对象名称,即"#对象名称"的形式。例如<s:property value="#request.name"/>中,request就是对象,这个对象取出name属性的值。

OGNL的结构:

struts2标签的属性按照下列的三个规则进行计算:

(1)所有的字符串属性类型都会解析“%{…}”这样的语法。

(2)所有的非字符属性类型都不会被解析,而是直接被看作一个OGNL表达式进行求值

(3)对于第二个规则的例外情况是,如果非字符串属性使用了“%{…}”语法,那么%{…}将被忽略,花括号中的内容将作为表达式计算。

如果大家在使用标签时, 忘记了某个属性是字符串类型,还是非字符串类型,那么有一个简单的方法,那就是不考虑它是什么类型,统一使用“%{…}”语法

OGNLStruts2的结合:

  • Struts 2中的OGNL Context即为ActionContext
  • 当Struts2接受一个请求时,会迅速创建ActionContext,再创建ValueStack、action ,然后把action存放进ValueStack,所以action的实例变量可被OGNL访问。
  • StackContext(map):stack上下文,它包含一系列域对象包括request、session、attr、application等。访问Stack Context中的对象的属性时要使用"#对象名.属性名"的方式,例如#application、#session。

2.1,值栈-ValueStack

本质是一个ArrayList,充当OGNL的root,给一次请求中共享数据的功能。

之前web阶段,在servlet里面进行操作,把数据放到域对象里面,在页面中使用el表达式获取到。域对象在一定范围内存值和取值。在struts2里面提供了本身的一种存储机制,类似于域对象,是值栈可以存值和取值。在action里面把数据放到值栈里面,在页面中获取到值栈的数据。

(1)向值栈中存放数据

  • 获取值栈对象,调用值栈对象里面的 set 方法,在用set方法添加值栈数据之后,会在root栈顶多一个HashMap对象。
ValueStack stack=ActionContext.getContext().getValueStack();
stack.set("username","燕双嘤");
  • 获取值栈对象,调用值栈对象里面的 push 方法,调用push之后,就会在root栈顶放入一个String类型的对象!
ActionContext.getContext().getValueStack().push(xxx);
  • 在action定义变量,生成变量的get方法(主要),struts2并不会在值栈root的栈顶放入新的对象,它的存储路径还是存储在action里面,所以这就起到了资源的合理应用,当想要获取name属性的时候,就会在值栈里面调用action的getName方法。这也就是为什么会在值栈里面存储action的原因了。
public class pr_action{
    private String name;
    public String getName(){
        return name;
    }
    public String execute(){
        name="FireLang";
        return "success";
    }
}

(2)向值栈中存放对象

  • 第一步:定义对象变量
  • 第二步:生成变量的get方法
  • 第三步:在执行的方法里面向对象中设置值
public class LoginAction extends ActionSupport {
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String execute(){
        return "success";
    }
}

(3)向值栈中存放List对象

  • 第一步:定义List集合变量
  • 第二步:生成变量的get方法
  • 第三步:在执行的方法里面向List集合设置值
public class Pr_fangList {
    private List<User> lu;
    public String execute(){
        lu=new ArrayList<User>();
        User u1=new User();
        u1.setName("燕双嘤");
        u1.setPassword("123");
        lu.add(u1);
        User u2=new User();
        u2.setName("杜马");
        u2.setPassword("456");
        lu.add(u2);
        System.out.println(lu);
        return "success";
    }
    public List<User> getLu() {
        return lu;
    }
}

(4)从值栈里面取数据:使用struts2的标签+OGNL表达式获取值栈数据:<s:property value="OGNL表达式"/>

  • 获取set值
<!—通过直接key值,从root域里面取对应值 -->
<s:property value="us"/><br><br>
<s:property value="lang"/>
//us、lang均为key值
  • 获取push值
//这里要注意的是push方法是直接把数据存放在root中的。不像set一样可以通过key来取值。
//push的取值方法有点特殊,是通过直接把栈顶元素取出来的。
<s:property value="[0].top"/>//取第一个
<s:property value="[1].top"/>//取第二个,这里的top是root的域实体对象名称,也就是List对象的名称
  • 获取action中的属性字段
<s:property value="name"/>
<!-- 这里的name是OGNL表达式。表示获取action中的name字段值,必须要写get方法,因为字段读或者写的功能按照规定,都必须通过读或者写方法来给变量赋值 -->
  • 获取对象
//再次强调必须要get方法。
<s:property value="us.name" /><br>
<!-- value中的值是OGNL表达式 -->
<s:property value="us.password" />
<!-- 获取到us对象后,再获取us中的name属性和password属性,再次强调获取字段基本上都是按照规定通过get和set方法进行操作! -->
  • 获取List集合
第一种方式:
//这种代码非常不好,在很多时候你永远不可能知道服务端传来的List里面到底有多少参数。
<s:property value="usl[0].name"/>
<s:property value="usl[0].password"/>
--------------------------------------------
第二种方式:
类似jstl中的foreach标签
<s:iterator value="usl">
    <s:property value="name"/>
    <s:property value="password"/>
    <br><hr><br>
</s:iterator>
--------------------------------------------
第三种方式:
/*第三种方式较第二种方式多加了一个var,根本区别就是iterator把遍历出来的值放进了值栈的第二部分空间
context,contex因为是Map结构的所以要加上一个键作为取值方式,也就是var的值作为context的键,其实这
种方式算是一种优化,不用在root中去拿值了。而第二种方式还会到root里面去拿值。速度没有在context中的快*/
<s:iterator value="usl" var="singleus">
    <s:property value="#singleus.name"/>
    <s:property value="#singleus.password"/>
</s:iterator>

2.2,“#”声明OGNL表达式

作用:访问OGNL上下文和Action上下文

主要有3种用途:

(1)能够访问OGNL上下文与ActionContext资源,相当于ActionContext.getContext()。

  • parameters:包含当前HTTP请求参数的Map,#parameters.id[0]作用相当于request.getParameter("id")。
  • request:包含当前HttpServletRequest的属性(attribute)的Map,#request.userName相当于request.getAttribute("userName")。
  • session:包含当前HttpSession的属性(attribute)的Map, #session.userName相当于session.getAttribute("userName")。
  • application:包含当前应用的ServletContext的属性的Map,#application.userName相当于application.getAttribute("userName")。
  • attr:用于按page->request->session->application顺序访问其属性。#attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止 。

(2)用于过滤或筛选集合

例如:books.{?#this.price<20},表示所有的price<20的书。

作用:用表达式从集合中选择某些元素,并将结果保存到新的集合中。

特殊符号:——所有满足选择逻辑的对象;^——第一个满足选择逻辑的对象;$——最后一个满足选择逻辑的对象。

(3)构造Map

创建set集合对象:

<s:set name="books" value="#{'book1':'23', 'book2':'55'}" />
<p>book1的价格是: <s:property value="#books['book1']" /></p>
注意:Set由于是无序的,所以不能使用下标获取数据即不能使用#books[0]

2.3,其他符号

$:用于在国际化资源文件中,引用OGNL表达式 Struts 2框架的配置文件中引用OGNL表达式。

<action name=“AddPhoto” class=“addPhoto”>
    <interceptor-ref name=“fileUploadStack” /> 
    <result type=“redirect”>/register.jsp?name=${name}</result>
</action> 

%:显示声明OGNL表达式。某些标签种既能接收字符串,又能接收OGNL表达式。标记%的被当作OGNL表达式并被执行,没有标记%的被当作普通的字符串。

<s:label label=”#request.account”></s:label>	//普通字符串,输出#request.account
<s:label label=”%{#request.account}”</s:label>  //OGNL,输出request的account属性值

 ‘(字符串常量):以单引号或双引号码括起的字符串,单个字符的字符串常量需用双引号。

<s:property value="'ysy'"/>
说明:不能少单引号,否则会当成根对象的属性名。

,:用于分隔两个以上独立的表达式,整个表达式的值是最后一个子表达式的值.

例如:name, #manager.name

()(数值常量):用单引号括起来的字符。

<s:property value="(123)"/>

{}:用于创建列表,其中元素之间使用逗号分隔。

<s:set name="books" value="#{'book1':'23', 'book2':'55'}" />

in和not in操作符:用于判断一个值是否在集合中。

例如:判断一个对象是否存在List集合中?
<s:if test="'foo' in {'foo','bar'}">
    muhahaha
    </s:if>
    <s:else>
        boo
</s:else>

调用静态方法和静态字段

@class@method()   //调用静态方法
@class@field      //调用静态字段

说明:class须给出完整的类名,若省略,默认值java.lang.Math

例如:@@max(5,3)     //调用java.lang.Math的max方法

在struts.xml中加入(<constant name="struts.OGNL.allowStaticMethodAccess" value="true"></constant> )表示可以访问静态方法。

PS:因为安全问题,访问静态方法不安全,用最新版本,无法获得方法返回值。

调用构造方法

作用:OGNL支持对构造方法的调用,从而创建一个新的对象

例如:new java.util.ArrayList()    //须用完整的限定类名

数组和列表索引

数组:array[0],list[0]                      //得到第1元素
表达式:{‘wang’,‘zhang’,‘li’}[1]    //得到结果是第2元素,即list.get(1)

创建列表List

语法:{e1,e2,e3}

示例:<s:select label="label" name="name" list="{'name1','name2','name3'}" value="%{'name2'}" />
结果:生成了一HTML Select对象,可选的内容为: name1,name2,name3,默认值为:name2。

创建数组[]

例如:new int[]{1,2,3}
      new int[5]   //数组中的元素初始化为0
索引:new int[]{1,2,3}[1]

注意:数组特殊的属性length,OGNL中可访问:array.length。

[N]语法

【提问】访问employee的name属性,应该如何写表达式呢?

格式[N].xxx  (N是从0开始的整数)

作用使用[N].xxx这样的语法来指定从哪一个位置开始向下查找对象的属性,表达式[1].name访问的就是employee对象的name属性。

注意在使用[N].xxx语法时,要注意位置序号的含义,它并不是表示“获取栈中索引为N的对象”,而是截取从位置N开始的部分栈。

示例栈中有三个对象:Object0,Object1和Object2都有name属性

  • 表达式name访问的是Object0的name属性
  • [1].name访问的是Object2的name属性,因为[1]是一个包含Object1和Object2的部分栈,而且只有Object2有name属性。

top关键字

top用于获取栈顶的对象,结合[N].xxx语法,就可获取栈中任意位置的对象。

[0].top获取Object0(等同于top),
[1].top获取Object1
[2].top获取Object2,
[2].top.name访问Object2中的name属性

3,Struts2控制标签

控制标签主要用来完成流程的控制,如条件分支、循环操作,也可以实现对集合的排序和合并。

  • if:用于控制选择输出。
  • elseif:同if标签结合使用,用来控制选择输出。
  • else:同if标签结合使用,用来控制选择输出。
  • append:用来将多个集合拼接为一个新的集合。
  • generator:为一个字符串解析器,用来将一个字符串解析为一个集合。
  • iterator:迭代器,用来迭代输出集合数据。
  • merge:用来将多个集合拼接为一个新的集合,同append有所区别。
  • sort:用来对集合排序。
  • subset:用来截取集合的部分集合,开成新的集合子集合。

3.1,if/elseif/else标签

if/elseif标签属性test:为必填属性,是一个Boolean类型值,决定是否显示if标签内容。

<s:if test="#parameters.name[0] == 'Kurt'">
    Hello, Kurt. 
</s:if >
<s:elseif test="#parameters.name[0] == 'Matt'">
    Hello, Matt. 
</s:elseif >
<s:else>
    Hello, Other Buddies. 
</s:else>
<!-- 利用 action 属性判断 -->
<s:if test="name == 'Kurt'">
    Hello, Kurt. 
</s:if >
<s:elseif test="name == 'Matt'">
    Hello, Matt. 
</s:elseif >
<s:else>
    Hello, Other Buddies. 
</s:else>

3.2,iterator(迭代标签)

iterator标签主要是对集合进行迭代操作,集合可以使List、Map、Set和数组。

使用iterator标签对集合进行迭代输出时,可以指定如下三个属性:

  • value这是一个可选的属性;用于指定被迭代的集合,被迭代的集合通常都使用OGNL表达式指定。如果没有指定value属性,则使用ValueStack栈顶的集合。
  • id这是一个可选属性;指定了集合里元素的ID,可以用var代替。
  • status这是一个可选的属性,指定迭代时的IteratorStatus实例,通过该实例可以判断当前迭代元素的属性。
<table border="1" width="300">
    <s:iterator value="{'Java Web整合开发','轻量级Java EE企业应用实战','Java Web开发经典'}"
                var="name">
        <tr>
            <td><s:property value="name" /></td>
        </tr>
    </s:iterator>
</table>

常用的方法有:

  • int getCount():返回当前迭代元素的个数。
  • int getIndex():返回当前迭代元素的索引值。
  • boolean isEven():返回当前迭代元素的索引值是否为偶数。
  • boolean isOdd():返回当前迭代元素的索引值是否为奇数。
  • boolean isFirst():返回当前迭代元素的是否是第一个元素。
  • boolean isLast():返回当前迭代元素的是否是最后一个元素。

使用iterator标签的属性status时,其实例对象包含以上的方法,而且也包含的有对应的属性,如#status.count#status.even#status.odd#status.first等。

<table border="1" width="300">
    <tr>
        <th>序号</th>
        <th>书名</th>
    </tr>
    <!-- 迭代输出List集合 -->
    <s:iterator value="{'Java Web整合开发','轻量级Java EE企业应用实战','Java Web开发经典'}"
                var="name" status="st">
        <tr
                <s:if test="#st.odd">
                    style="background-color:#bbbbbb"
                </s:if>>
            <td><s:property value="#st.index+1" /></td>
            <td><s:property value="name" /></td>
        </tr>
    </s:iterator>
</table>
<table border="1" width="300">
    <tr>
        <th>序号</th>
        <th>书名</th>
    </tr>
    <!-- 迭代输出List集合 -->
    <s:iterator value="#attr.u" var="u1" status="st">
        <tr>
            <td><s:property value="name" /></td>
            <td><s:property value="age" /></td>
        </tr>
    </s:iterator>
</table>
<table border="1" width="350">
    <tr>
        <th>序号</th>
        <th>书名</th>
        <th>作者</th>
    </tr>
    <!-- 对指定的Map对象进行迭代输出,并指定status属性 -->
    <%-- <s:iterator value="#{'Java Web整合开发':'张三','轻量级Java EE企业应用实战':'李四' ,'Java Web开发经典':'王五'}"
id="score" status="st"> --%>
    <s:iterator value="myMap" var="score" status="st">
        <!-- 根据当前被迭代元素的索引是否为奇数来决定是否使用背景色 -->
        <tr
                <s:if test="#st.odd">
                    style="background-color:#bbbbbb"
                </s:if>>
            <!-- 输出Map对象里Entry的key -->
            <td><s:property value="#st.index+1" /></td>
            <td><s:property /></td>
        </tr>
    </s:iterator>
</table>

3.3,append标签

用来将多个集合拼接为一个新的集合。目的就是可以将多个集合使用一个<iterator />标签完成迭代。

  • 使用append标签时需要指定一个var属性(也可以使用id属性),该属性确定拼接生成的新集合的名字,该新集合被放入StackContext中。
  • append标签可以接受多个<s:param>子标签,每个子标签指定一个集合,<s:append>标签负责将<s:param>标签指定的多个集合拼接成一个集合。
<!-- 使用append标签将两个集合拼接成新的集合,
新集合的名字是newList,新集合放入Stack Context中 -->
<s:append var="newList">
    <s:param
            value="{'Java程序设计与项目实训教程', 'JSP程序设计与项目实训教程','Web框架技术(Struts2+Hibernate+Spring3)教程'}" />
    <s:param value="{'Java程序设计', 'JSP程序设计','SSH技术'}" />
</s:append>
<table border="1" width="260">
    <!-- 使用iterator迭代newList集合 -->
    <s:iterator value="#newList" status="st" var="ele">
        <tr>
            <td><s:property value="#st.count" /></td>
            <td><s:property value="ele" /></td>
        </tr>
    </s:iterator>
</table>

<s:append var="newList">
    <s:param
            value="#{'Java Web整合开发':'张三','轻量级Java EE企业应用实战':'李四' ,'Java Web开发经典':'王五'}" />
    <s:param value="#{'http://www.abc.com',
		'http://www.def.com'}" />
</s:append>
<table border="1" width="280">
    <!-- 使用iterator迭代newList集合 -->
    <s:iterator value="#newList" status="st">
        <tr
                <s:if test="#st.odd">
                    style="background-color:#bbbbbb"
                </s:if>>
            <td><s:property value="key" /></td>
            <td><s:property value="value" /></td>
        </tr>
    </s:iterator>
</table>

3.4,merge标签

merge标签append标签所实现的功能一样,也是将多个集合连接成一个新集合,但是在两个标签生成的新集合中,元素的排序方式有所不同。

3.5,generator标签

用来将指定的字符串按规定的分隔符分解为多个子字符串,生成的多个子字符串可以使用iterator标签输出。

  • 可以理解为generator将一个字符串转化成一个Iterator集合。有点类似于String对象的split()方法,但功能更加强大。
  • 在该标签的标签体内,整个临时生成的集合将位于ValueStack的顶端,但一旦该标签结束,该集合将被移除ValueStack。

属性:

  • count:可选,指定生成集合中元素的总数。
  • separator:必选,解析字符串的分隔符。
  • val:必选,被解析的字符串。
  • converter:可选,指定一个转换器,负责将集合中的每个字符串转换程对象。属性值必须是一个。org.apache.Struts2.until.IteratorGenerator.Converter对象。
  • var:可选,如果指定该属性,将生成的Iterator对象放入StackContext中,必须通过#name形式访问;如果不指定,只能在标签内部进行访问。
 <!-- 使用generator标签将指定字符串解析成Iterator集合
在generator标签内,得到的List集合位于ValueStack顶端 -->
    <s:generator val="'疯狂Java讲义
		   ,轻量级Java EE企业应用实战
		   ,疯狂iOS讲义'"
                 separator="," var="test">
        <!-- 没有指定迭代哪个集合,直接迭代ValueStack顶端的集合 -->
    </s:generator>
    <s:iterator status="st" value="#test">
        <tr
                <s:if test="#st.odd">
                    style="background-color:#bbbbbb"
                </s:if>>
            <td><s:property /></td>
        </tr>
    </s:iterator>

3.6,subset标签

subset标签用于筛选集合里元素,它使用一个Filter(可以由开发者自定义截取标准),将不合格的元素过滤掉,剩下原集合的一个子集。

在subset标签内,生成的子集合放在ValueStack的栈顶;如果该标签结束后,生成的子集合将被移除ValueStack栈。

属性:

  • count:可选属性,指定子集中元素的个数;如果不指定该属性,则默认取得资源集合的全部资源。
  • source:可选属性,指定源集合;如果不指定,默认取得ValueStack栈顶的集合。
  • start:可选属性,指定子集从源集合的第几个元素开始截取;默认从第一个元素(0)开始。
  • decider:可选属性,指定开发者自己决定是否选中该元素;该属性必须指定一个。org.apache.strtuts2.util.SubsetIteratorFilter.Decider对象。
  • var:可选属性,如果指定则生成的Iterator对象设置成page范围的属性。

Struts2允许自定义截取标准,如果要实现自定义截取标准,则需要实现一个Decider类,Decider类需要实现SubsetIteratorFilter.Decider接口,并且实现一个boolean decide(Object element)方法,表示如果返回真,则该元素将被选入子集中。

3.7,sort标签

Sort标签根据comparator属性指定的比较器对集合进行排序,并将排序后的迭代器压入值栈的栈顶。在sort标签的内部,你可以使用iterator标签取出栈顶的迭代器对排序后的元素进行迭代。当sort标签结束时,栈顶的迭代器将被删除。

sort标签进行排序时,必须提供自己的排序规则,即实现自己的Comparator,而且Comparator需要实现java.util.Comparator接口。

属性:

  • comparator:必选属性,指定进行排序的Comparator对象。
  • source:可选属性,指定被排序的集合;如果不指定,则对ValueStack栈顶的集合进行排序。
  • var:可选属性,如果指定则生成的Iterator对象设置成page范围的属性。
<!-- 定义一个Comparator实例 -->
<s:bean var="mycomparator" name="until.MyComparator" />
<!-- 使用自定义的排序规则对目标集合进行排序 -->
<s:sort
        source="{'Java程序设计与项目实训教程', 'JSP程序设计与项目实训教程','JSP程序设计技术教程','Struts2+Hibernate框架技术教程','Web框架技术(Struts2+Hibernate+Spring3)教程'}"
        comparator="#mycomparator" var="sortedList" />
<table border="1" width="300">
    <!-- 迭代page范围内的sortedList属性 -->
    <s:iterator status="st" value="#attr.sortedList">
        <tr <s:if test="#st.odd">
            style="background-color:#bbbbbb"</s:if>>
            <td><s:property /></td>
        </tr>
    </s:iterator>
</table>

4,Struts2数据标签

数据标签主要用于提供各种数据访问相关的功能,包含显示一个Action里的属性,生成国际化输出等功能。

4.1,property标签

property标签用于输出值栈中的对象的属性(property)值,使用value属性来指定要输出的对象属性,如果没有指定value属性,那么默认输出栈顶对象。

属性:

  • default:可选属性,如果需要输出属性值null,则显示default属性指定的值。
  • escape:可选属性,指定是否需要escape HTML代码;默认值为true。
  • value:可选属性,指定需要输出的属性值,如果没有指定则输出ValueStack栈顶值。

4.2,set标签

set标签将一个值赋给指定范围内变量,且将一个已有的值复制给新变量,并且可以将新变量放到指定的范围内。

属性:

  • scope:可选属性,指定变量范围,可以接受application、session、request、page或action(request范围,并且放入StackContext);默认值action。
  • value:可选属性,指定赋给变量的值;如果没有指定,则将ValueStack栈顶的值赋给新变量。
  • var:可选属性,如果指定了该属性,则会将该值放入ValueStack中。
<!-- 使用bean标签定义一个JavaBean实例 -->
<s:bean name="Bean.Person" var="p">
    <s:param name="name" value="'张三'"/>
    <s:param name="age" value="29"/>
</s:bean>
将Stack Context中的p值放入默认范围(action)内。
<br/>
<s:set value="#p" var="xxx"/>
Stack Context内xxx对象的name属性:
<s:property value="#xxx.name"/>
<br/> Stack Context内xxx对象的age属性:
<s:property value="#xxx.age"/>
<br/>

<s:property value="#request.xxx.name"/>
<br/>
<s:property value="#request.xxx.age"/>
<hr/>
将Stack Context中的p值放入application范围内。
<br/>
<s:set value="#p" var="yyy" scope="application"/>
application范围的yyy对象的name属性:
<s:property value="#application.yyy.name"/>
<br/> application范围的yyy对象的age属性:
<s:property value="#application.yyy.age"/>
<br/>
<hr/>
将Stack Context中的p值放入session范围内。
<br/>
<s:set value="#p" var="zzz" scope="session"/>
session范围的zzz对象的name属性:
<s:property value="#session.zzz.name"/>
<br/> session范围的zzz对象的age属性:
<s:property value="#session.zzz.age"/>

4.3,push标签

push标签用于把一个值压入值栈(位于栈顶),注意和set标签的区别,set标签是将值放到action上下文中。当push标签结束后,push标签放入值栈中的对象将被删除,换句话说,要访问push标签压入栈中的对象,需要在标签内部去访问。

<h2>使用s:push来将某个值放入ValueStack的栈顶</h2>
<!-- 使用bean标签创建一个JavaBean实例,
指定var属性,并将其放入Stack Context中 -->
<s:bean name="Bean.Person" var="p">
    <s:param name="name" value="'张三'" />
	<s:param name="age" value="29" />
</s:bean>
<!-- 将Stack Context中的p对象放入ValueStack栈顶-->
<s:push value="#p">
<!-- 输出ValueStack栈顶对象的name和age属性 -->
ValueStack栈顶对象的name属性:<s:property value="name" />
<br />
ValueStack栈顶对象的age属性:<s:property value="age" />
<br />
</s:push>

4.4,param标签

param标签被用作其他标签的子标签,用于为其他标签提供参数,例如:为bean标签和include标签提供参数。

–	name:可选属性,参数名;
–	value:可选属性,参数值

用法:

(1)<param name=”color”>blue</param>

(2)<param name=”color” value=”blue”/>      //blue对象,不存在为null

         <param name=”color” value=”’blue’”/>   //blue字符串

4.5,bean标签

bean标签用于实例化一个JavaBean对象(必须遵照JavaBean规范),bean标签的标签体内可以包含多个param标签,用于设置Bean的属性(必须有相应的setter方法)。

如果需要使用<param.../>标签获取或传入JavaBean属性值应该为该JavaBean提供对应settergetter方法。

–	name:必选属性,JavaBean的实现类
–	var:必选属性,对象名

注意:在bean标签体内,bean标签创建的对象位于ValueStack顶端,一旦该标签结束了,则bean标签创建的对象被移除ValueStack,将无法再次访问,除非指定了var属性,则可通过StackContext来访问该对象。

<body>
	<!-- 使用bean标签创建一个Person类的实例 -->
	<s:bean var="p" name="Bean.Person">
		<!-- 使用param标签为Person类的实例传入参数 -->
		<s:param name="name" value="'张三'" />
		<s:param name="age" value="29" />
		<!-- 因为在bean标签内,Person实例位于ValueStack的栈顶,
			Person实例的name为:<s:property value="name"/><br/>
	Person实例的age为:<s:property value="age"/>故可以直接访问lee.Person实例 -->
	</s:bean>
	<s:property value="#request.p.name"/>
	<s:property value="#p.age"/>
	<br/>
	<s:bean var="t" name="ex.test" />
	<s:property value="#t.test_get('测试')" />
</body>

4.6,action标签

使用action标签可以允许在JSP页面中直接调用Action,需要指定name及namespace;如果指定了executeResult参数的属性值为true,该标签还会把Action的处理结果包含到本页面中。

–	var:可选属性,一旦定义该属性,该Action放入Stack Context中
–	name:必选属性,决定调用哪个Action
–	namespace:调用Aciton所在的namespace
–	executeResult:可选属性,指定是否要将result包含到页面中;默认为false
–	ignoreContextParams:可选属性,页面请求参数是否传入调用的Action;默认值为false
<body>
	下面调用第一个Action,并将结果包含到本页面中。
	<br />
	<s:action name="tag1" executeResult="true" ignoreContextParams="true" />
	<hr />
	下面调用第二个Action,并将结果包含到本页面中。
	<br /> 但阻止本页面请求参数传入Action。
	<br />
	<s:action name="tag2" executeResult="true" ignoreContextParams="true" />
	<hr />
	下面调用第三个Action,且并不将结果包含到本页面中。
	<br />
	<s:action name="tag2" executeResult="flase">
	</s:action>
	本页面是否可访问?
	<s:property value="author" />
</body>

4.7,include标签

include标签用来在页面上包含一个JSP页面或者Servlet文件。

–	value:必选属性,指定需要包含的JSP页面或Servlet

4.8,date标签

date标签用于格式化输出一个日期,计算指定日期和当前时刻的时间差。

–	format:可选属性,如果指定了该属性,根据属性指定的格式来格式化日期
–	nice:可选属性,指定是否输出指定日期和当前时刻之间的差值;默认为false
–	name:必选属性,指定格式化的日期值
–	var:可选属性

注意:nice属性和format属性不能同时指定;如果既指定了nice=“true”,也指定了format属性,则会输出时间差。

<body>
	<s:bean var="now" name="java.util.Date" />
	<s:bean var="tom" name="Bean.DateProce" />
	nice="false",且指定format="dd/MM/yyyy"
	<br />
	<s:date name="#now" format="dd/MM/yyyy" nice="false" />
	<hr />
	nice="true",且指定format="dd/MM/yyyy"
	<br />
	<s:date name="#tom" format="dd/MM/yyyy" nice="true" />
	<hr />
	指定nice="true"
	<br />
	<s:date name="#tom.getTomorrow()" nice="true" />
	<hr />
	nice="false",且没有指定format属性
	<br />
	<s:date name="#now" nice="false" />
	<hr />
	nice="false",没有指定format属性,指定了var
	<br />
	<s:date name="#now" nice="false" var="abc" />
	<hr />
	${requestScope.abc}
	<s:property value="#abc" />
</body>

4.9,debug标签

主要用于辅助调试,它在页面上生成一个超链接,通过该链接可以查看到ValueStack和StackContext中所有的值信息。

5,Struts2表单标签

Struts的表单标签,可以分为两种:form标签本身单个表单元素的标签。

所有表单标签处理类都继承了UIBeanUIBean包含了一些通用属性,这些通用属性分为三种:模板相关属性、JavaScript相关属性、通用属性。

模板相关属性

–	templateDir:指定表单所用的模板文件目录
–	theme:指定该表单所用的主题
–	template:指定表单所用的模板

Struts2提供了四种主题ajax, simple, css_xhtml,xhtml,它默认的是xhtml主题,开发时我们一般都选simple。这4个主题的模板文件放在Struts2的核心类库里(struts2-core.jar包)。

设置主题的方式:

  1. 通过设定特定UI标签上的theme属性来指定主题。
  2. 通过设定特定UI标签外围的Form标签的theme属性来指定主题。
  3. 通过取得page会话范围内以theme为名称的属性来确定主题。
  4. 通过取得request会话范围内以theme为名称的属性来确定主题。
  5. 通过取得session会话范围内以theme为名称的属性来确定主题。
  6. 通过取得application会话范围内以theme为名称的属性来确定主题。
  7. 通过取得名为struts.ui.theme的常量(默认值是xhtml)来确定主题,该常量可以在struts.properties文件或者struts.xml文件中确定。如:<constantname="struts.ui.theme" value="simple" />

JavaScript相关属性

通用属性

Struts2中大部分表单标签和HTML表单元素一一对应,<form.../>标签不仅生成<form>标记,还会生成<table>标记。

对于表单标签而言,namevalue属性之间存在一个特殊的关系:

  • 因为每个表单元素会被映射成Action属性,所以如果某个表单对应的Action已经被实例化(表单被提交)、且属性有值时,则该Action对应表单里的元素会显示出该属性的值,这个值作为表单标签的value值。
  • name属性设置表单元素的名字,表单元素的名字实际上封装着一个请求参数,而请求参数是被封装到Action属性的值,所以在使用Struts2的标签库时,无须指定value属性,Struts2标签会自动处理。

5.1,select标签

select标签用于生成一个下拉列表框,使用该标签必须指定list属性,系统会使用list属性指定的集合来生成下拉列表框的选项。

属性:

−	list:要迭代的集合,使用集合中的元素来设置各个选项,如果list的属性为Map则Map的key成为选项的value,Map的value会成为选项的内容
−	listKey:指定集合对象中的哪个属性作为选项的value
−	listValue:指定集合对象中的哪个属性作为选项的内容
−	headerKey:设置当用户选择了header选项时提交的value,如果使用该属性,不能为该属性设置空值
−	headerValue:显示在页面中header选项内容
−	emptyOption:是否在header选项后面添加一个空选项
−	multiple:是否多选
−	size:显示的选项个数
<body>
	<h3>使用s:select生成下拉选择框</h3>
	<s:form>
		<!-- 使用简单集合来生成下拉选择框 -->
		<s:select name="a" label="请选择您喜欢的图书" labelposition="top"
			multiple="true"
			list="{'Java程序设计与项目实训教程', 'JSP程序设计与项目实训教程','Web框架技术(Struts2+Hibernate+Spring3)教程'}" />
		<!-- 使用简单Map对象来生成下拉选择框 -->
		<s:select name="b" label="请选择您想选择出版日期" labelposition="top"
			list="#{'疯狂Java讲义':'2008年9月',
	'轻量级Java EE企业应用实战':'2008月12月', 
	'SSH程序设计':'2014年1月'}" />
		<!-- 创建一个JavaBean实例 -->
		<s:bean name="service.BookService" var="bs" />
		<!-- 使用集合里放多个JavaBean实例来生成下拉选择框 -->
		<s:select name="c" label="请选择您喜欢的图书" labelposition="top"
			multiple="true" list="#bs.books" listKey="author" listValue="name" />
	</s:form>
</body>

5.2,optgroup标签

optgroup标签用于生成一个下拉列表框的选项组。

该标签必须放在<s:select.../>中使用,一个下拉列表可以包含多个选项组,使用optgroup标签时,一样需要指定list、listKey和listValue等属性。

optgroup标签可以指定label属性,而该label属性时选项组的组名,浏览者无法选中选项组的label。

<body>
	<h3>使用s:optgroup生成下拉选择框的选项组</h3>
	<s:form>
		<!-- 直接使用Map为列表框生成选项 -->
		<s:select label="选择您喜欢的图书" name="book" size="7"
			list="#{'Java程序设计与项目实训教程', 'JSP程序设计与项目实训教程','Web框架技术(Struts2+Hibernate+Spring3)教程'}"
			listKey="value" listValue="key">
			<!-- 使用Map对象来生成选择框的选项组 -->
			<s:optgroup label="Rod Johnson"
				list="#{'Expert One-on-One J2EE Design and Development':'Johnson'}"
				listKey="value" listValue="key" />
			<s:optgroup label="David Flanagan"
				list="#{'JavaScript: The Definitive Guide':'David'}" listKey="value"
				listValue="key" />
		</s:select>
	</s:form>
</body>

5.3,updownselect标签

类似select标签,区别是该标签生成的列表可以上下移动选项。另外与select相同都要指定list、listkey和listvalue等属性。

其他属性:

–	allowMoveUp:是否显示“上移”按钮,默认为true
–	allowMoveDown:是否显示“下移”按钮,默认为true
–	allowSelectAll:是否显示“全选”按钮,默认为true
–	moveUpLabel:设置“上移”按钮文本,默认是“^”
–	moveDownLabel:设置“下移”按钮文本,默认是“v”
–	selectAllLabel:设置“全选”按钮文本,默认是“*”
<body>
	<h3>使用s:updownselect生成可上下移动选项的下拉选择框</h3>
	<s:form>
		<!-- 使用简单集合来生成可上下移动选项的下拉选择框 -->
		<s:updownselect name="a" label="请选择您喜欢的图书" labelposition="left"
			moveUpLabel="向上移动"
			list="{'Java程序设计与项目实训教程', 'JSP程序设计与项目实训教程','Web框架技术(Struts2+Hibernate+Spring3)教程'}" />
		<!-- 使用简单Map对象来生成可上下移动选项的下拉选择框 
	 且使用emptyOption="true"增加一个空选项-->
		<s:updownselect name="b" label="请选择您想选择出版日期" labelposition="top"
			moveDownLabel="向下移动"
			list="#{'疯狂Java讲义':'2008年9月'
	,'轻量级Java EE企业应用实战':'2008月12月'
	,'疯狂iOS讲义':'2014年1月'}"
			listKey="key" emptyOption="true" listValue="value" />
		<s:bean name="service.BookService" var="bs" />
		<!-- 使用集合里放多个JavaBean实例来可上下移动选项的生成下拉选择框 -->
		<s:updownselect name="c" label="请选择您喜欢的图书的作者" labelposition="top"
			selectAllLabel="全部选择" multiple="true" list="#bs.books"
			listKey="author" listValue="name" />
	</s:form>
</body>

5.4,doubleselet标签

级联列表,当选择第一个列表时,第二个列表框的内容会随之改变。

属性:

因为两个都是下拉列表,因此需要指定两个下拉列表框的选项
–	list:指定输出第一个下拉列表框中选项集合
–	listKey:第一个下拉列表框的值
–	listValue:第一个下拉列表框的标签
–	doubleList:指定输出第二个下拉列表框中选项集合
–	doubleListKey:第二个下拉列表框的值
–	doubleListValue:第二个下拉列表框的标签
–	doubleName:第二个下拉列表框的name属性
<s:form >
	<s:doubleselect
		label="请选择您喜欢的图书"
		name="author" list="{'张三', '李四'}"
		doubleList="top == '张三' ? {'轻量级Java EE企业应用实战',
		'J2EE','SSH'}:
		{'JavaScript: The Definitive Guide'}" 
		doubleName="book"/>	
</s:form>

 注意:使用doubleselect标签时,必须放在<s:form.../>标签中使用;默认情况下,第一个下拉列表框只支持两项,如果要包含更多的值list和doubleList就不能直接设定;可以采用一种迂回方式来实现,首先定义一个Map对象,该Map对象的value都是集合,这样就能以Map对象的多个key创建第一个下拉列表框的列表项,而每个key对应的集合则用于创建第二个下来列表框的列表项。

<!-- 创建一个复杂的Map对象,key为普通字符串,value为集合 -->
<s:set var="bs" value="#{'张三':{'轻量级Java EE企业应用实战',
		'J2EE','SSH'},
	'David': {'JavaScript: The Definitive Guide'},
	'Johnson': {'Expert One-on-One J2EE Design and Development'}}"/>
<!-- 使用Map对象来生成级联列表框 -->
<s:form action="x">
	<s:doubleselect
		label="请选择您喜欢的图书"
		size="3"
		name="author" list="#bs.keySet()"
		doubleList="#bs[top]" 
		doubleSize="3"
		doubleName="book"/>	
</s:form>

keySet将map集合中所有的键存入到Set集合,因为Set具备迭代器。 所有可用迭代方式取出所有的键,再根据get方法,获取每一个键对应的值。

5.5,optiontransferselect标签

联动列表,optiontransferselect会生成两个列表选择框,并生成系列的按钮用于控制各选项在两个下拉列表之间的移动、升降等;当提交表单时,两个列表框对应的请求参数都会提交。

属性:

–	addAllToLeftLabel:设置全部移动到左边按钮的文本
–	addAllToRightLabel:设置全部移动到右边按钮的文本
–	addToLeftLabel:设置左移动按钮的文本
–	addToRightLabel:设置右移动按钮的文本
–	allowAddAllToLeft:设置是否出现全部移动到左边的按钮
–	allowAddAllToRight:设置是否出现全部移动到右边的按钮
–	allowAddToLeft:设置是否出现全部移动到左边的按钮
–	allowAddToRight:设置是否出现全部移动到右边的按钮
–	leftTitle:设置左边列表的标题
–	rightTitle:设置右边列表的标题
–	allowSelectAll:设置全选按钮
–	list:第一个下拉选择框的集合
–	listKey:第一个下拉选择框的value属性
–	listValue:第一个下拉选择框的label属性
–	name:设置第一个下拉选择框的name属性
–	value:设置第一个下拉选择框的value属性
–	multiple:设置第一个下拉选择框是否允许多选
–	doubleList:第二个下拉选择框的集合,必选属性
–	doubleListKey:第二个下拉选择框的value属性
–	doubleListValue:第二个下拉选择框的label属性
–	doubleName:设置第二个下拉选择框的name属性,必选
–	doubleValue:设置第二个下拉选择框的value属性,必选
–	doubleMultiple:设置第二个下拉选择框是否允许多选
<body>
	<h3>使用s:optiontransferselect来生成可移动列表项的下拉列表框</h3>
	<s:form>
		<!-- 使用简单集合对象来生成可移动的下拉列表框 -->
		<s:optiontransferselect label="请选择你喜欢的图书" name="cnbook"
			leftTitle="中文图书:" rightTitle="外文图书"
			list="{'Java程序设计与项目实训教程', 'JSP程序设计与项目实训教程','Web框架技术(Struts2+Hibernate+Spring3)教程'}"
			multiple="true" addToLeftLabel="向左移动" selectAllLabel="全部选择"
			addAllToRightLabel="全部右移" headerKey="cnKey"
			headerValue="--- 选择中文图书 ---" emptyOption="true"
			doubleList="{'Expert One-on-One J2EE Design and Development',
		'JavaScript: The Definitive Guide'}"
			doubleName="enBook" doubleHeaderKey="enKey"
			doubleHeaderValue="--- 选择外文图书 ---" doubleEmptyOption="true"
			doubleMultiple="true" />
	</s:form>
</body>

5.6,radio、checkbox、checkboxlist标签

checkbox属性:

−	id和name:指的是该标签的标识id和标识名。
−	value:指是否选中,其值只能为True或False,相当于传统checkbox中的checked。
−	fieldValue:相当于传统checkbox中的value值。
−	label:对于该checkbox显示在页面上方框后面的描述。
<body>
	<h3>使用s:radio生成多个单选框</h3>
	<s:form>
		<!-- 使用简单集合来生成多个单选框 -->
		<s:radio name="a" label="请选择您喜欢的图书" labelposition="top"
			list="{'Java程序设计与项目实训教程', 'JSP程序设计与项目实训教程','Web框架技术(Struts2+Hibernate+Spring3)教程'}" />
		<!-- 使用简单Map对象来生成多个单选框 -->
		<s:radio name="b" label="请选择您想选择出版日期" labelposition="top"
			list="#{'疯狂Java讲义':'2008年9月'
				   ,'轻量级Java EE企业应用实战':'2008月12月'
				   ,'SSH程序设计':'2014年1月'}"
			listKey="key" listValue="value" />
		<!-- 创建一个JavaBean实例 -->
		<s:bean name="service.BookService" var="bs" />
		<!-- 使用集合里放多个JavaBean实例来生成多个单选框 -->
		<s:radio name="c" label="请选择您喜欢的图书" labelposition="top"
			list="#bs.books" listKey="author" listValue="name" />
	</s:form>
</body>
<body>
	<h3>使用s:checkbox生成多个复选框</h3>
	<s:form>
		<!-- 使用简单集合来生成多个单选框 -->
		<s:iterator
			value="#{'Java Web整合开发':'张三','轻量级Java EE企业应用实战':'李四' ,'Java Web开发经典':'王五'}"
			var="score" status="st">
			<s:checkbox name="a" value="false" fieldValue="%{key}"
				label="%{value}" labelposition="right" />
		</s:iterator>
		
</s:form>
</body>
<body>
	<h3>使用s:checkboxlist生成多个复选框</h3>
	<s:form>
		<!-- 使用简单集合来生成多个复选框 -->
		<s:checkboxlist name="a" label="请选择您喜欢的图书" labelposition="top"
			list="{'Java程序设计与项目实训教程', 'JSP程序设计与项目实训教程','Web框架技术(Struts2+Hibernate+Spring3)教程'}" />

		<s:checkboxlist name="b" label="请选择您想选择出版日期" labelposition="top"
			list="#{'疯狂Java讲义':'2008年9月'
	,'轻量级Java EE企业应用实战':'2008月12月'
	,'疯狂iOS讲义':'2014年1月'}"
			listKey="key" listValue="value" />
		<!-- 创建一个JavaBean对象,并将其放入Stack Context中 -->
		<s:bean name="service.BookService" var="bs" />
		<!-- 使用集合里放多个JavaBean实例来生成多个复选框
	使用集合元素里name属性作为复选框的标签
	使用集合元素里author属性作为复选框的value-->
		<s:checkboxlist name="b" label="请选择您喜欢的图书" labelposition="top"
			list="#bs.books" listKey="author" listValue="name" />
	</s:form>
</body>

5.7,hidden标签

hidden标签输出一个HTML隐藏表单元素,等价于HTML代码:<input type=“hidden”…/>。

5.8,submit标签

submit标签输出一个提交按钮。 submit标签和form标签一起使用可以提供异步表单提交功能。

submit标签可以输出以下三种类型的提交按钮:
−	input:等价于HTML代码<input type=“submit”…>
−	image:等价于HTML代码<input type=“image”…>
−	button:等价于HTML代码<input type=“submit”…>

struts2提供的一种特性,即使用一些预定义的前缀来命名一个按钮,通过按钮的名字来改变执行的行为。Struts2定义了4个前缀,如下:

−	method:使用method前缀,来取代action默认的execute()方法的执行
−	action:使用action前缀,取代form标签指定的action,将请求导向到另外的action进行处理。
−	redirect:使用redirect前缀将请求重定向到其他的URL,甚至可以是Web应用程序外部的URL。
−	redirection-action:使用redirect-action前缀将请求重定向到其他的action。在内部,struts2使用ServletRedirectResult来执行这个任务。

使用formaction属性可以实现取代form标签指定的action

	<s:form action="userManager">
		<s:textfield label="用户名" name="username" />
		<s:password label="密码" name="password" />
		<s:submit value="登录" name="method:login" />
		<s:submit value="注册" name="method:regist" />
	</s:form>

5.9,reset标签

reset标签输出一个重置按钮。

<s:reset value=“重置”  />
<s:reset  type=“button”  label=“重置” />
如果是类型为input的重置按钮,则只能通过value属性来设置重置按钮上的文本。

5.10,lablel标签

Xhtml主题下的label标签输出两个HTML的label标签(simple主题下的label标签只输出一个HTML label标签),分别位于一行的两列,左边的label标签起提示作用,右列的label标签用于显示只读的action属性数据。

<body>
	<s:bean name="Bean.Person" var="p">
		<s:param name="name" value="'张三'" />
		<s:param name="age" value="19" />
	</s:bean>
	<s:label label="姓名" name="#p.name" />
</body>

5.11,token标签

防止重复提交表单;如果需要该标签起作用,则应该在Struts2的配置启动TokenInterceptor拦截器或TokenSessionStoreInterceptor拦截器。

原理:在表单中增加一个隐藏域,每次加载该页面时,该隐藏域的值都不相同。而TokenInterceptor拦截器则拦截所有用户请求,如果两次请求时该token对应的隐藏域的值相同(前一次提交时token隐藏域的值保存在session里),则阻止表单提交。

<body>
	<h3>使用s:token防止重复提交</h3>
	<s:form action="pro">
		<!-- 普通表单域 -->
		<s:textfield name="book" label="书名" />
		<!-- 用于防刷新的token -->
		<s:token />
		<s:submit value="提交" />
	</s:form>
</body>

6,非表单标签

6.1,component标签

使用component标签可以自定义组件,当需要多次使用某些代码段是,就可以自定义一个组件在页面中使用component标签多次调用。

属性:

−	theme属性:该属性用来指定自定义组件所使用的主题,默认值为xhtml。
−	templateDir属性:该属性用来指定自定义组件使用的主题目录,默认值为template。
−	template属性:该属性用来指定自定义组件所使用的模板文件,自定义模板文件可以采用JSP、FreeMarker和Velocity这3中技术编写代码。
<body>
<s:set value="#p" var="p_l" />
	<!--使用component标签调用模版-->
	<s:component template="myTemplate.jsp">
		<s:param name="songList" value="{'中国人','真心英雄','青花瓷','传奇','北京欢迎你'}" />
	</s:component>
	<hr />
	使用自定义主题,自定义主题目录
	<br /> 使用myAnotherTemplate.jsp作为视图组件
	<s:component templateDir="/myTemplateDir" theme="myTheme"
		template="myAnotherTemplate.jsp">
		<s:param name="songList" value="{'中国人','真心英雄','青花瓷','传奇','北京欢迎你'}" />
</s:component>
</body>

6.2,actionerror、actionmessage、fielderror标签

actionerror和actionmessage用法一样,都是负责输出Action对象封装的信息。

区别:actionerror标签负责输出Action对象的getActionError()方法的返回值,而actionmessage负责输出Action对象的getActionMessages()方法的返回值

<head>
	<title>使用s:actionerror和s:actionmessage标签生成错误提示</title>
<s:head/>
</head>
<body>
	<s:action name="msgdemo" executeResult="true"/>
</body>

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值