【Java EE (Struts2 + Spring + Hibernate)开发】: Struts2(一)之 【Struts2标签库】

【Java EE (Struts2 + Spring + Hibernate)开发】: Struts2(一)之 【Struts 2标签库】
本文地址:http://blog.csdn.net/shanglianlm/article/details/50009957

1 Struts 2 标签库概述

这里写图片描述

2 使用 Struts 2 标签

导入:

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

使用:

<!-- 使用以 s 作为前缀的标签 -->
<s:abc ... />

3 Struts 2 的 OGNL 表达式语言

这里写图片描述
这里写图片描述

命名对象:

这里写图片描述

元素存储在 Stack Context 中,使用这些对象时需要使用 # 前缀来说明。
元素存储在 ValueStack 中,无需书写 # 即可访问 Action 属性。

Struts2中的OGNL详解
Struts2中的OGNL

4 OGNL 中的集合操作

4-1 集合对象:List 和 Map

List:

{e1, e2, e3 ...}

Map:

#{key1:value1, key2:value2, ...}

4-2 两个操作运算符: in 和 not in

<!-- 如果指定集合中包含 foo 元素 -->
<s:if test="'foo' in {'foo', 'bar'}">
包含
</s:if>
<s:else>
不包含
</s:else>
<!-- 如果指定集合中不包含 foo 元素 -->
<s:if test="'foo' not in {'foo', 'bar'}">
包含
</s:if>
<s:else>
不包含
</s:else>

4-3 取子集的三个操作符

?:取出所有符合选择逻辑的元素。
^:取出符合选择逻辑的第一个元素。
$:取出符合选择逻辑的最后一个元素。

person.relatives.{? #this.gender == 'male'}

取出 person 的所有性别为 male 的 relatives(亲戚)集合

5 访问静态成员

在 struts2 中打开 OGNL 访问静态成员方法。

<!-- 设置允许 OGNL 允许访问静态成员 -->
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />

访问静态成员

@className@staticField
@className@staticMethod(val...)

例(JSP 页面)

访问系统环境变量:<s:property value="@java.lang.System@getenv('JAVA_HOME')" /><br />
圆周率的值:<s:property value="@java.lang.Math@PI" />

6 Lambda 表达式

Lambda ( λ ) 表达式
斐波那契数列 求第 11 个元素的值

<s:property value="#fib =:[#this==0 ? 0 :#this==1 ? 1 : #fib(#this-2) + #fib(#this-1)], #fib(11)" />

7 控制标签

这里写图片描述

7-1 if/elseif/else 标签

<!-- 在Stack Context中定义一个age属性,其值为29 -->
<s:set name="age" value="29"/>
<!-- 如果Stack Context中的age属性大于60 -->
<s:if test="#age>60">
    老年人
</s:if>
<!-- 如果Stack Context中的age属性大于35 -->
<s:elseif test="#age>35">
    中年人
</s:elseif>
<!-- 如果Stack Context中的age属性大于15 -->
<s:elseif test="#age>15">
    青年人
</s:elseif>
<s:else>
    少年
</s:else>

7-2 iterator 标签

属性:

  • value:被迭代的集合
  • id:指定集合里面的元素的id
  • status 迭代元素的索引

方法:

  • even : boolean - 如果当前迭代位置是偶数返回true
  • odd : boolean - 如果当前迭代位置是奇数返回true
  • count : int - 返回当前迭代位置的计数(从1开始)
  • index : int - 返回当前迭代位置的编号(从0开始)
  • first : boolean - 如果当前迭代位置是第一位时返回true
  • last : boolean - 如果当前迭代位置是最后一位时返回true
  • modulus(operand : int) : int - 返回当前计数(从1开始)与指定操作数的模数

使用 iterator 迭代 list

<table border="1" width="300">
<s:iterator value="{'疯狂Java讲义',
    '轻量级Java EE企业应用实战',
    '经典Java EE企业应用实战'}"
    id="name">  
    <tr>
        <td><s:property value="#st.count"/>
        <s:property value="name"/></td>
    </tr>
</s:iterator>
</table>

使用 iterator 迭代 map

<table border="1" width="300">
<!-- 迭代输出List集合 -->
<s:iterator value="{'疯狂Java讲义',
    '轻量级Java EE企业应用实战',
    '经典Java EE企业应用实战'}"
    id="name" status="st">
    <tr <s:if test="#st.odd">
        style="background-color:#bbbbbb"</s:if>>
        <td><s:property value="name"/></td>
    </tr>
</s:iterator>
</table>
<table border="1" width="350">
    <tr>
        <th>书名</th>
        <th>作者</th>
    </tr>
<!-- 对指定的Map对象进行迭代输出,并指定status属性 -->
<s:iterator value="#{'疯狂Java讲义':'李刚',
    '轻量级Java EE企业应用实战':'李刚' ,
    '经典Java EE企业应用实战':'李刚'}"
    id="score" status="st">
    <!-- 根据当前被迭代元素的索引是否为奇数来决定是否使用背景色 -->
    <tr <s:if test="#st.odd">
        style="background-color:#bbbbbb"</s:if>>
        <!-- 输出Map对象里Entry的key -->
        <td><s:property value="key"/></td>
        <!-- 输出Map对象里Entry的value -->
        <td><s:property value="value"/></td>
    </tr>
</s:iterator>
</table>

7-3 append 标签

使用s:append标签拼接两个集合

<!-- 使用append标签将两个集合拼接成新的集合,
    新集合的名字是newList,新集合放入Stack Context中 -->
<s:append var="newList">
    <s:param value="{'疯狂Java讲义',
        '轻量级Java EE企业应用实战',
        '经典Java EE企业应用实战'}" />
    <s:param value="{'http://www.crazyit.org', 
        'http://blog.crazyit.org'}" />
</s:append>
<table border="1" width="260">
<!-- 使用iterator迭代newList集合 -->
<s:iterator value="#newList" status="st" id="ele">
    <tr>
        <td><s:property value="#st.count"/></td>
        <td><s:property value="ele"/></td>
    </tr>
</s:iterator>
</table>

使用s:append标签拼接集合和Map

<!-- 使**重点内容**用append将List和Map集合拼接在一起
    新集合实际上是Map集合,其名字为newList -->
<s:append var="newList">
    <s:param value="#{'疯狂Java讲义':'李刚',
        '轻量级Java EE企业应用实战':'李刚',
        '经典Java EE企业应用实战':'李刚'}" />
    <s:param value="#{'http://www.crazyit.org', 
        'http://blog.crazyit.org'}" />
</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>

7-4 generator 标签

属性

  • count属性:指定生成集合中元素的总数。可选属性。
  • val属性:必填属性,指定被解析的字符串。
  • separator属性:这是一个必填属性,指定用于分割字符串的分隔符。
  • converter属性:可选属性,指定一个转换器,转换器负责将生成的集合中的每个字符串转换成对象,通过这个转换器可以将一个含有分隔符的字符串解析成对象的集合。转换器必须一个继承org.apache.struts2.util.IteratorGenerator.Converter的对象。
  • var属性,可选属性。如果指定了该属性,则将生成的集合保存在Stack Context中。如果不指定该属性,则将生成的集合放入ValueStack的顶端,该标签一结束,生成的集合就被移除。该属性也可替换成id。

使用s:generator生成集合

<table border="1" width="240">
<!-- 使用generator标签将指定字符串解析成Iterator集合
    在generator标签内,得到的List集合位于ValueStack顶端 -->
<s:generator val="'疯狂Java讲义
    ,轻量级Java EE企业应用实战,
    经典Java EE企业应用实战'" separator=",">
<!-- 没有指定迭代哪个集合,直接迭代ValueStack顶端的集合 -->
<s:iterator status="st">
    <tr <s:if test="#st.odd">
        style="background-color:#bbbbbb"</s:if>>
        <td><s:property/></td>
    </tr>
</s:iterator>
</s:generator>
</table>

使用s:generator生成集合

<!-- 使用generator将一个字符串解析成一个集合
    ,指定了var和count属性 -->
<s:generator val="'疯狂Java讲义
    ,轻量级Java EE企业应用实战,
    经典Java EE企业应用实战'" separator=","
    var="books" count="2"/>
<table border="1" width="300">
<!-- 迭代输出Stack Congtext中的books集合 -->
<s:iterator value="#books">
    <tr>
        <td><s:property/></td>
    </tr>
</s:iterator>
</table>
${requestScope.books}

7-5 merge 标签

merge 和 append很类似,不同之处在于
A {1, 2, 3} B{1, 2, 3}
append: 1, 2, 3, 1, 2, 3
merge: 1, 1, 2, 2, 3, 3

7-6 subset 标签

属性

  • count: 可选属性,指定子集中元素的个数.在不指定该属性情况下,默认取得源集合的全部元素
  • source: 可选属性,指定源集合.若不指定,默认取得ValueStack栈顶的集合.
  • start:可选属性,指定子集从源集合中的第几个元素开始截取.默认从第一个开始截取,默认值为0
  • decider:可选属性,指定由开发者自己决定是否选中该元素.

使用s:subset标签截取集合元素

<table border="1" width="300">
<!-- 使用subset标签截取目标集合的4个元素,从第2个元素开始截取 -->
<s:subset source="{'疯狂Java讲义'
    ,'轻量级Java EE企业应用实战'
    ,'经典Java EE企业应用实战'
    ,'疯狂Ajax讲义'
    ,'疯狂XML讲义'}" 
    start="1" count="4">
    <!-- 使用iterator标签来迭代目标集合,因为没有指定value属性值,
        故迭代ValueStack栈顶的集合 -->
    <s:iterator status="st">
        <!-- 根据当前迭代元素的索引是否为奇数决定是否使用CSS样式 -->
        <tr <s:if test="#st.odd">
            style="background-color:#bbbbbb"</s:if>>
            <td><s:property/></td>
        </tr>
    </s:iterator>
</s:subset>
</table>

使用s:subset标签自定义标准截取集合元素

//用户自定义的Decider类,实现了SubsetIteratorFilter.Decider接口
public class MyDecider 
    implements SubsetIteratorFilter.Decider
{
    //实现Decider接口必须实现的decide方法,
    //该方法决定集合中的元素是否被选入子集
    public boolean decide(Object element) throws Exception
    {
        String str = (String)element;
        //如果集合元素(字符串)中包含Java EE子串,即可被选入子集
        return str.indexOf("Java EE") > 0;
    }
}
<!-- 定义一个Decider Bean -->
<s:bean var="mydecider" name="org.crazyit.app.util.MyDecider"/>
<!-- 使用自定义的Decider实例来截取目标集合,生成子集
    指定var属性,将生成的Itertor放入pageScope中 -->
<s:subset source="{'疯狂Java讲义'
    ,'轻量级Java EE企业应用实战'
    ,'经典Java EE企业应用实战'
    ,'疯狂Ajax讲义'
    ,'疯狂XML讲义'}" 
    decider="#mydecider"
    var="newList"/>
直接输出page范围的newList属性:<br/>
${pageScope.newList}
<table border="1" width="240">
<!-- 迭代page范围内的newList属性 -->
<s:iterator status="st" value="#attr.newList">
    <tr <s:if test="#st.odd">
        style="background-color:#bbbbbb"</s:if>>
        <td><s:property/></td>
    </tr>
</s:iterator>
</table>

7-7 sort 标签

属性

  • comparator: 实现Comparator的类
  • source: 集合
public class MyComparator implements Comparator
{
    //决定两个元素大小的方法
    public int compare(Object element1, Object element2)
    {
        //根据元素字符串长度来决定大小    
        return element1.toString().length()
            - element2.toString().length();
    }
}
<!-- 定义一个Comparator实例 -->
<s:bean var="mycomparator" name="org.crazyit.app.util.MyComparator"/>
<!-- 使用自定义的排序规则对目标集合进行排序 -->
<s:sort source="{'疯狂Java讲义'
    ,'轻量级Java EE企业应用实战'
    ,'经典Java EE企业应用实战'
    ,'疯狂Ajax讲义'
    ,'疯狂XML讲义'}" 
    comparator="#mycomparator"
    var="sortedList"/>
输出page范围的sortedList属性:<br/>
${pageScope.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>

8 数据标签

这里写图片描述
这里写图片描述

8-1 action 标签

属性

  • id:可选属性,该属性将会作为该Action的引用ID
    • name:必填属性,指定该标签调用哪个Action
    • namespace:可选,指定该标签调用的Action所在的namespace.
    • executeResult:可选,指定是否要将Action的处理结果页面包含到本页面。默认是false,即不包含。
    • ignoreContextParams:可选,它指定该页面中的请求参数是否需要传入调用的Action、默认是false,即将本页的请求参数传入被调用的Action。

使用s:action标签在页面中调用Action

public class TagAction extends ActionSupport
{
    //封装用户请求参数的author属性
    private String author;

    //author属性的setter和getter方法
    public void setAuthor(String author)
    {
        this.author = author;
    }
    public String getAuthor()
    {
        return this.author;
    }
    //定义第一个处理逻辑
    public String execute() throws Exception
    {
        return "done";
    }
    //定义第二个处理逻辑
    public String login() throws Exception
    {
        ActionContext.getContext().
            put("author", getAuthor());
        return "done";
    }
}

struts.xml

<struts>
    <constant name="struts.custom.i18n.resources" value="mess"/>
    <constant name="struts.i18n.encoding" value="GBK"/>

    <package name="lee" extends="struts-default">
        <!-- 定义第一个Action,使用TagAction的
            execute方法作为控制处理逻辑 -->
        <action name="tag1" class="org.crazyit.app.action.TagAction">
            <result name="done">succ.jsp</result>
        </action>
        <!-- 定义第二个Action,使用TagAction的
            login方法作为控制处理逻辑 -->
        <action name="tag2" class="org.crazyit.app.action.TagAction"
            method="login">
            <result name="done">loginSucc.jsp</result>
        </action>
        <action name="">
            <result>.</result>
        </action>
    </package>
</struts>
下面调用第一个Action,并将结果包含到本页面中。<br/>
<s:action name="tag1" executeResult="true"/>
<hr/>
下面调用第二个Action,并将结果包含到本页面中。<br/>
但阻止本页面请求参数传入Action。<br/>
<s:action name="tag2" executeResult="true"
    ignoreContextParams="true"/>
<hr/>
下面调用第三个Action,且并不将结果包含到本页面中。<br/>
<s:action name="tag2" executeResult="false"/>
本页面是否可访问?<s:property value="author"/>

8-2 bean 标签

属性

  • name:必选属性,指定要实例化的 JavaBean 的实现类。
  • var:可选属性,如果指定该属性,则该 JavaBean 实例会被放入 Stack Context 中,并放入 requestScope 中。

使用s:bean标签创建JavaBean的实例

public class Person
{
    private String name;
    private int age;

    //name属性的setter和getter方法
    public void setName(String name)
    {
        this.name = name;
    }
    public String getName()
    {
        return this.name;
    }

    //age属性的setter和getter方法
    public void setAge(int age)
    {
        this.age = age;
    }
    public int getAge()
    {
        return this.age;
    }
}
<!-- 使用bean标签创建一个Person类的实例 -->
<s:bean name="org.crazyit.app.dto.Person">
    <!-- 使用param标签为Person类的实例传入参数 -->
    <s:param name="name" value="'yeeku'"/>
    <s:param name="age" value="29"/>
    <!-- 因为在bean标签内,Person实例位于ValueStack的栈顶,
        故可以直接访问lee.Person实例 -->
    Person实例的name为:<s:property value="name"/><br/>
    Person实例的age为:<s:property value="age"/>
</s:bean>
<!-- 使用bean标签创建一个Person类的实例,为其指定了var属性 -->
<s:bean name="org.crazyit.app.dto.Person" var="p">
    <!-- 使用param标签为Person类的实例传入参数 -->
    <s:param name="name" value="'yeeku'"/>
    <s:param name="age" value="29"/>
</s:bean>
<!-- 根据JavaBean实例指定的var属性来访问JavaBean实例 -->
Person实例的name为:<s:property value="#p.name"/><br/>
Person实例的age为:<s:property value="#p.age"/><br/>
${requestScope.p}

8-3 date 标签

属性

  • format: 可选,如指定该属性,将根据该属性指定的格式来格式化日期
  • nice: 可选,值为true或者false,用于指定是否输出指定日期和当前时刻的时差。默认是false,即不输出
  • name: 必填,指定要格式化的日期
  • var: 可选,如果指定了改属性,则该事件对象将被放到ValueStack中,改属性也可以用id来代替,推荐使用var!

使用s:date标签格式化日期

<s:bean var="now" name="java.util.Date"/>
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="#now" format="dd/MM/yyyy" nice="true"/><hr/>
指定nice="true"<br/>
<s:date name="#now" 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"/>
#国际化资源文件中指定 struts 2 默认的时间格式
struts.date.format=yyyy年MM月dd日

8-4 debug 标签

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

<s:debug />

8-5 include 标签

使用s:include标签来包含目标页面,包括 JSP 页面和 Servlet 。此外,可以为 标签添加

<!-- 使用include标签来包含其他页面 -->
<s:include value="included-file.jsp"/>
<!-- 使用include标签来包含其他页面,并且传入参数 -->
<s:include value="included-file.jsp">
    <s:param name="author" value="'yeeku'"/>
</s:include>
<h3>被包含的页面</h3>
author参数值为:${param.author}

8-6 param 标签

<param name="color">blue</param>

<param name="color" value="blue" />

如果为字符串

<param name="color" value="'blue'" />

8-7 push 标签

Push标签是将值存在值栈中,在设置push标签时应将标签放在使用属性之前。

<!-- 使用bean标签创建一个JavaBean实例,
    指定var属性,并将其放入Stack Context中 -->
<s:bean name="org.crazyit.app.dto.Person" var="p">
    <s:param name="name" value="'yeeku'"/>
    <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>

只有在 push 标签内时,被 push 标签放入 ValueStack 中的对象才存在;一旦离开了 push 标签,则刚刚被放入的元素将立即被移出 ValueStack 。

8-8 set 标签

使用s:set设置一个新变量

<!-- 使用bean标签定义一个JavaBean实例 -->
<s:bean name="org.crazyit.app.dto.Person" id="p">
    <s:param name="name" value="'yeeku'"/>
    <s:param name="age" value="29"/>
</s:bean>
将Stack Context中的p值放入默认范围(action)内。<br/>
<s:set value="#p" name="xxx"/>
 Stack Context内xxx对象的name属性:<s:property value="#xxx.name"/><br/>
 Stack Context内xxx对象的age属性:<s:property value="#xxx.age"/><br/>
 request范围的xxx对象的name属性:${requestScope.xxx.name}<br/>
 request范围的xxx对象的age属性:${requestScope.xxx.age}<hr/>
将Stack Context中的p值放入application范围内。<br/>
<s:set value="#p" name="yyy" scope="application"/>
 application范围的yyy对象的name属性:${applicationScope.yyy.name}<br/>
 application范围的yyy对象的age属性:${applicationScope.yyy.age}<hr/>
将Stack Context中的p值放入session范围内。<br/>
<s:set value="#p" name="zzz" scope="session"/>
 session范围的zzz对象的name属性:${sessionScope.zzz.name}<br/>
 session范围的zzz对象的age属性:${sessionScope.zzz.age}

8-9 url 标签

属性

这里写图片描述

s:url来生成一个URL地址

只指定value属性的形式。<br/>
<s:url value="editGadget.action"/>
<hr/>
指定action属性,且使用param传入参数的形式。<br/>
<s:url action="showBook">
    <s:param name="author" value="'yeeku'" />
</s:url>
<hr/>
既不指定action属性,也不指定value属性,且使用param传入参数的形式。<br/>
<s:url includeParams="get"  >
    <s:param name="id" value="%{'22'}"/>
</s:url>
<hr/>
同时指定action属性和value属性,且使用param传入参数的形式。<br/>
<s:url action="showBook" value="xxxx">
    <s:param name="author" value="'yeeku'" />
</s:url>

这里写图片描述

8-10 property 标签

这里写图片描述
这里写图片描述

9 主题与模板

Struts 2 所有的UI标签都是基于主题和模板的,主题和模板是 Struts 2 所有 UI 标签的核心。

设定主题的方法:

这里写图片描述

前面的优先级高。

模板目录是存放所有模板文件的地方,所有的模板文件以主题的方式来组织,模板目录下有图示目录结构:

这里写图片描述

这里写图片描述

这里写图片描述

struts 2 默认提供了三个主题

  • simple:最简单的主题,最底层的结构,主要用于构建 HTML UI 组件。
  • xhtml:struts 2 默认的主题。
  • css_xhtml:在 xhtml 主题基础上加入了 CSS 样式控制。

从 struts 2.1 开始, struts 2 核心包不再提供 Ajax 主题,而是由 struts2-dojo-plugin-2.2.1.jar 来提供 Ajax 主题。

10 自定义主题

10-1 开发者完全实现一个全新的主题

需要很大工作量,一般不推荐。

10-2 包装一个现有的主题

这里写图片描述

10-3 扩展一个现有的主题

<#include "/${parameters.templateDir}/xhtml/controlheader.ftl" />
<#include "/${parameters.templateDir}/simple/select.ftl" />
<#include "/${parameters.templateDir}/xhtml/controlfooter.ftl" />
parent=xhtml
<s:select name="aa" theme="lee" list="{'hhh', 'fff', 'ggg'}" size="5" />

11 表单标签

所有表单标签处理类都继承了 UIBean 类,UIBean 包含了一些通用属性,
模板相关属性

这里写图片描述

Javascript 相关通用属性

这里写图片描述
这里写图片描述

与 Tooltip 相关的通用属性

这里写图片描述
这里写图片描述
这里写图片描述

11-1 表单标签的 name 和 value 属性

<!-- 将下面文本框的值绑定到 Action 的 person 属性的 firstName 属性 -->
<s:textfield name="person.firstName" />

11-2 checkboxlist 标签

属性

这里写图片描述

使用s:checkboxlist生成多个复选框

<s:form>
<!-- 使用简单集合来生成多个复选框 -->
<s:checkboxlist name="a" label="请选择您喜欢的图书" 
    labelposition="top" list="{'轻量级Java EE企业应用实战'
    , '经典Java EE企业应用实战'
    , '疯狂Java讲义'}"/>
<!-- 使用简单Map对象来生成多个复选框
    使用Map对象的key(书名)作为复选框的value,
    使用Map对象的value(出版时间)作为复选框的标签-->
<s:checkboxlist name="b" label="请选择您想选择出版日期" 
    labelposition="top" list="#{'疯狂Java讲义':'2008年9月'
    ,'轻量级Java EE企业应用实战':'2008月12月'
    ,'经典Java EE企业应用实战':'2010年8月'}"
    listKey="key"
    listValue="value"/>
<!-- 创建一个JavaBean对象,并将其放入Stack Context中 -->
<s:bean name="org.crazyit.app.service.BookService" id="bs"/>
<!-- 使用集合里放多个JavaBean实例来生成多个复选框
    使用集合元素里name属性作为复选框的标签
    使用集合元素里author属性作为复选框的value-->
<s:checkboxlist name="b" label="请选择您喜欢的图书" 
    labelposition="top"
    list="#bs.books"
    listKey="author"
    listValue="name"/>
</s:form>
public class BookService
{
    public Book[] getBooks()
    {
        return new Book[]
        {
            new Book("疯狂Java讲义","李刚"),
            new Book("轻量级Java EE企业应用实战","李刚"),
            new Book("经典Java EE企业应用实战","李刚"),
            new Book("疯狂Ajax讲义","李刚")
        };
    }
}
public class Book
{
    private String name;
    private String author;
    //无参数的构造器
    public Book()
    {
    }
    //初始化全部属性的构造器
    public Book(String name , String author)
    {
        this.name = name;
        this.author = author;
    }

    //name属性的setter和getter方法
    public void setName(String name)
    {
        this.name = name;
    }
    public String getName()
    {
        return this.name;
    }

    //author属性的setter和getter方法
    public void setAuthor(String author)
    {
        this.author = author;
    }
    public String getAuthor()
    {
        return this.author;
    }
}

11-3 doubleselect 标签

使用s:doubleselect生成级联下拉列表框

<s:form action="x">
    <s:doubleselect
        label="请选择您喜欢的图书"
        name="author" list="{'李刚', 'David'}"
        doubleList="top == '李刚' ? {'轻量级Java EE企业应用实战',
        '经典Java EE企业应用实战','疯狂Java讲义'}:
        {'JavaScript: The Definitive Guide'}" 
        doubleName="book"/> 
</s:form>

这里写图片描述

默认情况下,第一个下拉列表框只支持两项,如果第一个下拉列表要包含三项或以上,可以这样实现:
首先定义一个 map 对象,该 map 对象的 value 都是集合,这样就能以 map 对象的多个 key 创建第一个下拉列表框的列表项,而每个 key 对应的集合则用于创建第二个下拉列表框的列表项:

<!-- 创建一个复杂的Map对象,key为普通字符串,value为集合 -->
<s:set name="bs" value="#{'李刚': {'疯狂Java讲义', 
    '轻量级Java EE企业应用实战','经典Java EE企业应用实战'},
    '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>

11-4 head 标签

这里写图片描述

11-5 optiontransferselect 标签

这里写图片描述
这里写图片描述
这里写图片描述

<s:form>
<!-- 使用简单集合对象来生成可移动的下拉列表框 -->
 <s:optiontransferselect 
    label="请选择你喜欢的图书"
    name="cnbook" 
    leftTitle="中文图书:"
    rightTitle="外文图书"
    list="{'疯狂Java讲义' ,'Struts 2权威指南',
        '轻量级Java EE企业应用实战','经典Java EE企业应用实战'}" 
    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>

11-6 select 标签

这里写图片描述

<s:form>
<!-- 使用简单集合来生成下拉选择框 -->
<s:select name="a" label="请选择您喜欢的图书" labelposition="top" 
    multiple="true" list="{'疯狂Java讲义','轻量级Java EE企业应用实战',
    'JavaScript: The Definitive Guide'}"/>
<!-- 使用简单Map对象来生成下拉选择框 -->
<s:select name="b" label="请选择您想选择出版日期" labelposition="top" 
    list="#{'疯狂Java讲义':'2008年9月',
    '轻量级Java EE企业应用实战':'2008月12月', 
    '经典Java EE企业应用实战':'2010年7月'}"
    listKey="key"
    listValue="value"/>
<!-- 创建一个JavaBean实例 -->
<s:bean name="org.crazyit.app.service.BookService" id="bs"/>
<!-- 使用集合里放多个JavaBean实例来生成下拉选择框 -->
<s:select name="c" label="请选择您喜欢的图书" labelposition="top"
    multiple="true"
    list="#bs.books"
    listKey="author"
    listValue="name"/>
</s:form>

11-7 radio 标签

<s:form>
<!-- 使用简单集合来生成多个单选框 -->
<s:radio name="a" label="请选择您喜欢的图书" labelposition="top"
    list="{'疯狂Java讲义','轻量级Java EE企业应用实战',
        '经典Java EE企业应用实战'}"/>
<!-- 使用简单Map对象来生成多个单选框 -->
<s:radio name="b" label="请选择您想选择出版日期" labelposition="top"
    list="#{'疯狂Java讲义':'2008年9月'
    ,'轻量级Java EE企业应用实战':'2008月12月'
    ,'经典Java EE企业应用实战':'2010年8月'}"
    listKey="key"
    listValue="value"/>
<!-- 创建一个JavaBean实例 -->
<s:bean name="org.crazyit.app.service.BookService" id="bs"/>
<!-- 使用集合里放多个JavaBean实例来生成多个单选框 -->
<s:radio name="c" label="请选择您喜欢的图书" labelposition="top"
    list="#bs.books"
    listKey="author"
    listValue="name"/>
</s:form>

11-8 optgroup 标签

必须放在

<s:form>
<!-- 直接使用Map为列表框生成选项 -->
<s:select label="选择您喜欢的图书" name="book" size="7"
    list="#{'疯狂Java讲义':'李刚'
        ,'轻量级Java EE企业应用实战':'李刚'
        ,'经典Java EE企业应用实战':'李刚'}"
    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>

11-9 token 标签

防止多次提交表单的标签。

<s:form action="pro">
    <!-- 普通表单域 -->
    <s:textfield name="book" key="book"/>
    <!-- 用于防刷新的token -->
    <s:token/>
    <s:submit value="提交"/>
</s:form>

如果要该标签起作用,则应该在 struts 2 的配置文件中启用 TokenInterceptor 拦截器或 TokenSessionStoreInterceptor 拦截器。

<struts>
    <constant name="struts.custom.i18n.resources" value="mess"/>
    <constant name="struts.i18n.encoding" value="GBK"/>
    <package name="lee" extends="struts-default">

<!-- 定义名为pro的Action,其实现类为lee.ProAction -->
<action name="pro" class="org.crazyit.app.action.ProAction">
    <!-- 使用系统默认的拦截器栈 -->
    <interceptor-ref name="defaultStack"/>
    <!-- 使用防刷新的token拦截器 -->
    <interceptor-ref name="token"/>
    <!-- 定义重复提交转向的视图,该逻辑视图名必须是invalid.token -->
    <result name="invalid.token">/refresh.jsp</result>
    <!-- 如果处理结果返回success,对应/show.jsp视图资源 -->
    <result name="success">/show.jsp</result>
</action>
        <action name="">
            <result>.</result>
        </action>
    </package>
</struts>

11-10 updownselect 标签

这里写图片描述

<s:form>
<!-- 使用简单集合来生成可上下移动选项的下拉选择框 -->
<s:updownselect name="a" label="请选择您喜欢的图书"
    labelposition="top"
    moveUpLabel="向上移动"
    list="{'疯狂Java讲义' 
    , '轻量级Java EE企业应用实战'
    , '经典Java EE企业应用实战'}"/>
<!-- 使用简单Map对象来生成可上下移动选项的下拉选择框 
     且使用emptyOption="true"增加一个空选项-->
<s:updownselect name="b" label="请选择您想选择出版日期"
    labelposition="top"
    moveDownLabel="向下移动"
    list="#{'疯狂Java讲义':'2008年9月'
    ,'轻量级Java EE企业应用实战':'2008月12月'
    ,'经典Java EE企业应用实战':'2010年6月'}"
    listKey="key"
    emptyOption="true"
    listValue="value"/>
<s:bean name="org.crazyit.app.service.BookService" id="bs"/>
<!-- 使用集合里放多个JavaBean实例来可上下移动选项的生成下拉选择框 -->
<s:updownselect name="c" label="请选择您喜欢的图书的作者"
    labelposition="top" selectAllLabel="全部选择" multiple="true"
    list="#bs.books"
    listKey="author"
    listValue="name"/>
</s:form>

12 非表单标签

  • actionerror
  • actionmessage
  • component
  • fielderror

12-1 actionerror 和 actionmessage 标签

public class DemoAction extends ActionSupport
{
    public String execute()
    {
        //添加两条Error信息
        addActionError("第一条错误消息!"); 
        addActionError("第二条错误消息!"); 
        //添加两条普通信息
        addActionMessage("第一条普通消息!"); 
        addActionMessage("第二条普通消息!"); 
        return SUCCESS;
    }
}
<s:actionerror/>
<s:actionmessage />
<s:action name="demo" executeResult="true" />

12-2 component 标签

常常需要指定如下三个属性:

  • theme:自定义组件所使用的主题,如果不指定该属性,默认使用xhtml主题。
  • templateDir:指定自定义组件的主题目录,如果不指定,默认使用系统的主题目录,即template目录。
  • template:指定自定义组件所使用的模板。
    此外,还可以在 component 标签内使用 param 子标签,向该标签模板传入额外的参数。

使用s:component标签

使用默认主题(xhtml),默认主题目录(template)<br/>  
使用mytemplate.jsp作为视图组件
<s:component template="mytemplate.jsp">
    <s:param name="list" value="{'疯狂Java讲义'
    ,'轻量级Java EE企业应用实战'
    ,'经典Java EE企业应用实战'}"/>
</s:component>
<hr/>
使用自定义主题,自定义主题目录<br/>  
使用myAnotherTemplate.jsp作为视图组件
<s:component
    templateDir="myTemplateDir"
    theme="myTheme"
    template="myAnotherTemplate.jsp">
    <s:param name="list" value="{'疯狂Java讲义'
    ,'轻量级Java EE企业应用实战'
    ,'经典Java EE企业应用实战'}" />
</s:component>
<%@ page contentType="text/html; charset=GBK" language="java"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<div style="background-color:#eeeeee;">
<b>JSP自定义模板<br/>
请选择您喜欢的图书<br/></b>
<s:select list="parameters.list"/>
</div>
<%@ page contentType="text/html; charset=GBK" language="java"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<div style="background-color:#bbbbbb;">
JSP自定义模板<br/>
请选择您喜欢的图书<br/>
<select>
<s:iterator value="%{top.parameters.list}">
    <option><s:property/></option>
</s:iterator>
</select>
</div>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mingo_敏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值