Java EE框架开发技术与案例教程
上QQ阅读APP看书,第一时间看更新

4.3 Struts 2常用标签

Struts 2框架提供了丰富的标签库用来构建视图组件。Struts 2标签库简化了视图页面的开发,并且提高了视图组件的可维护性。

在JSP页面中使用Struts 2标签,首先要在JSP页面中使用标签库指令,引入Struts 2的标签库,格式如下。

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

在本节中,只介绍最常用的几种标签,对于没有涉及的标签,在项目开发中若需要,可以查看Struts 2官方文档。

4.3.1 Struts 2的通用标签与应用案例

Struts 2的通用标签主要有数据访问、超链接等有关标签,这里介绍最常用的几种。

1.<s:property>标签

该标签用来输出值栈中的指定对象及属性的值,通常与OGNL结合使用。如下面的代码所示。

    <s:property value="#request.name"/>    功能:显示对象request中的属性name的值

2.a标签

该标签实现超链接,例如,下面的语句是超链接Action(也可以超链接JSP页面)。

    <s:a href="register.action">注册</s:a>

3.<s:param>标签

该标签主要用于为其他标签提供参数,格式如下。

    <s:param name="***" value="***"/>

其中,name用于指定需要设置参数的参数名;value用于指定需要设置参数的参数值。

注意:①无论在给出value值时有没有使用%{}, Struts 2都会对它进行ognl求值。②如果要传递String类型的字符串作为参数值,必须用单引号括起来。③可以把value属性的值写在开始标签和结束标签之间,从而可以传递一个EL表达式的值。

4.<s:bean>标签

该标签将创建一个JavaBean对象,并把它压入ContextMap中。在创建JavaBean实例时,可以使用<s:param>标签为JavaBean实例传入参数。格式如下。

    <s:bean name="类路径" var="对象名称">
      <s:param name="属性名"value="属性值"/>  //注意:若为字符串常量必须用单引号括起来
      ……………..
    </s:bean>

其中:name用于指定要实例化的JavaBean的实现类;var用于设置实例名称。

例如,利用【例4-1】中的Person类,在JSP页面中创建对象并显示。其关键代码如下。

    <s:bean name="com.edu.ognl.action.Person" var="s" >
      <s:param name="name" value="'zhangsan'"/>
    </s:bean>
    <s:property value="#s.name"/>

运行该JSP页面时,显示结果为zhangsan。

5.<s:set>标签

set标签用来在以下Map对象(ContextMap值栈,session、application和request等域对象)中创建一个键值对。其中ContextMap值栈为默认对象。其常用属性如下。

● name:指定新变量的名称,是必选项。

● scope:指定作用域request、response、session或application。默认值为default。

● value:为新变量赋值,可以是集合值。

(1)创建一个属性并存储

如下面的代码所示。

    <s:set name="age" value="20" scope=" request" />

(2)创建一个对象并赋值

例如,利用【例4-1】中的Person类,在JSP页面中创建一个Bean对象,然后再赋值给一个变量并显示该变量的值。其关键代码如下。

    <s:bean name="com.edu.ognl.action.Person" id="s" >
      <s:param name="name" value="'张三'"/>
    </s:bean>
    <s:set name="user" value="#s" scope="request"/>
    scope属性值为request范围:<s:property value="#request.user.name" />

运行该页面时,首先形成对象s(保存在ContextMap子栈内),然后又形成对象user(保存在ContextMap子栈的request对象内),然后显示对象user的值(name属性值)。

(3)创建list集合并存储,在访问单个元素时,可以按其下标(下标从0开始访问)。

如下面的代码所示。

    <s:set name="list" value="{'a', 'b', 'c', 'd'}"></s:set>

(4)创建map集合并存储

    Map集合的语法格式:#{key:value, key1:value1, key2:value2, .....}

利用该语法,可生成Map类型的集合,该Map对象中的每个key-value对象之间用英文的冒号隔开,多个元素之间用逗号分隔,若是字符串类型,用单引号括起来,如下面的代码所示。

    <s:set name="map" value="#{'1':'laowang', '2':'老王', '3':'猩猩'}"></s:set

6.url标签

url标签用来动态地创建一个URL,其常用属性如下。

● action:指定一个Action作为URL地址。

● method:指定使用Action的方法。

● var:指定压入值栈Map的值。

● value:指定生成URL的地址,若缺省,则使用action属性指定值作为URL地址。

● encode:指定编码请求方法。

● names:指定名称空间。

如下面的代码所示。

    <s:set name="zhangsan1" value="'aaaa'"/>
    <s:set name="zhangsan2" value="'bbbb'"/>
    <s:url action="ognlTest" namespace="/test" var="add">
        <! -- 该格式对应于value,按OGNL解析求值-->
        <s:param name="username1" value="#zhangsan1"/>
      <! -- 单引号括起来,该格式对应于value,不解析,按字符串常量-->
        <s:param name="username2" value="'zhangsan2'"/>
        <s:param name="id">12</s:param>
    </s:url>
    <s:url value="/xyz/input.jsp" var="aaa"></s:url>
    <! --  使用该URL地址  -->
    ${add}<br>
    ${aaa}<br>
    <s:a href="%{add}">测试URL</s:a>

运行后显示的结果如下(注意输出格式)。

    /工程名/test/ognlTest.action? username1=aaaa&username2=zhangsan2&id=12
    /工程名/xyz/input.jsp
    测试URL(超链接地址)

7.<s:action>标签

该标签用于在页面上执行一个Action,并且还将当前Action对象压入ContextMap子栈。常用属性如下。

● var:指定被调用Action的引用,是可选项。

● name:指定Action的名称,是必选项。

● namespace:指定被调用Action所在的namespace,是可选项。

● executeResult:指定将Action处理结果包含到当前页面中,默认值为false。

● ignoreContextParams:指定当前页面的数据是否需要传给被调用的Action,默认值为false,即默认将页面中的参数传给被调用的Action,是可选项。

例如,在【例4-2】中设计并配置的Action,可以在页面中直接调用执行,语句如下。

    <s:action name="ognlTest" namespace="/test"></s:action>

8.<s:date>标签

该标签用于格式化输出日期。该标签有以下几个属性。

● format:若指定该属性值(必须是java.text.SimpleDateFormat类中定义的日期/时间格式之一),将根据该属性指定的格式来格式化日期。

● nice:指定是否输出指定日期和当前时刻之间的时差。默认为false。

● name:属性是必选的,指定要格式化的日期值。

● var:指定格式化后的字符串将被放入ContextMap中。

使用格式如下。

    1)按指定日期格式输出:<s:date name="指定日期取值" format="日期格式"/>
    2)输出时间差:<s:date name="指定日期取值" nice="true"/>
    3)默认格式输出:<s:date name="指定日期取值"/>

例如,date标签的使用(dateTag.jsp)。

    <s:bean name="java.util.Date" var="d">
      <s:param name="date" value="10"></s:param>
    </s:bean>
   (1)nice="false",且指定format="dd/MM/yyyy" <br>
    <s:date name="#d" format="dd/MM/yyyy" nice="false"/><br>
   (2)nice="true",且指定format="dd/MM/yyyy" <br>
    <s:date name="#d" format="dd/MM/yyyy" nice="true"/><br>
   (3)nice="false",没有指定format属性,指定了var <br>
    <s:date name="#d" nice="false" var="abc"/>
    ${requestScope.abc}= =<s:property value="#abc"/>

运行结果如下。

   (1)nice="false",且指定format="dd/MM/yyyy"
      10/09/2015
   (2)nice="true",且指定format="dd/MM/yyyy"
      10 days ago
   (3)nice="false",没有指定format属性,指定了var
      2015-9-10 20:42:08= =2015-9-10 20:42:08

9.actionerror和actionmessage标签

actionerror和actionmessage这两个标签都是在页面上输出Action中方法添加的信息。其中,actionerror标签输出的是Action中addActinErrors()方法添加的信息;而actionmessage标签输出的是Action中AddActionMessage()方法添加的信息。

例4-4】在Action中,利用addActinErrors()方法添加信息;而在JSP中利用actionerror标签和actionmessage标签输出Action中添加的信息。

1)设计添加信息的Action:ActionErrorActionMessage。

    package com.edu.ognl.action;
    import org.apache.struts2.convention.annotation.*;
    import com.opensymphony.xwork2.ActionSupport;
    @Namespace("/test")
    @ParentPackage("struts-default")
    @Results({ @Result(name = "success", location = "/showErrorActionMessage.jsp") })
    public class ActionErrorActionMessage extends ActionSupport {
        private static final long serialVersionUID = 1L;
        @Action("messageTest")
        public String execute() {
            // 使用addActionError()方法添加信息
            addActionError("使用ActionError添加错误信息!");
            addActionMessage("使用ActionMessage添加普通信息!");
            return SUCCESS;
        }
    }

2)设计JSP:showErrorActionMessage.jsp,输出由Action中AddActionMessage()方法添加的信息。

    <%@page contentType="text/html" import="java.util.*" pageEncoding="UTF-8"%>
    <%@taglib prefix="s" uri="/struts-tags"%>
    <html>
        <head> <title>actionerror标签和actionmessage标签的使用</title> </head>
        <body>
          <s:actionerror/>
          <s:actionmessage/>
        </body>
    </html>

3)启动服务器,在地址栏输入如下请求。

    http://localhost:8080/c4_ognl_tag/test/messageTest

运行程序,在页面上将显示如下信息。

    使用ActionError添加错误信息!
    使用ActionMessage添加普通信息!

4.3.2 Struts 2的控制标签与应用案例

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

1.if、elseif和else标签

这3个标签是用来控制流程的,与Java语言中的if、elseif、else语句相似。在该标签中,使用test属性作为测试条件。例如下面的代码,首先创建一个变量score,并赋值为86,然后利用判定标签,显示相应的信息。在这里,显示“良好”。

    <s:set name="score" value="86"/>
    <s:if test="#score>=90">优秀</s:if>
    <s:elseif test="#score>=80">良好</s:elseif>
    <s:elseif test="#score>=70">中等</s:elseif>
    <s:elseif test="#score>=60">及格</s:elseif>
    <s:else>不及格</s:else>

2.iterator标签

该标签用于遍历集合,可以遍历一个数组、Collection(List、Set)或Map,并把这个可遍历对象中的每一个元素依次压入和弹出ValueStack栈。格式如下。

    <s:iterator value=""  var=""  status="">…</s:iterator>

其中,常用属性如下。

● value:指定迭代输出的集合对象,可以是OGNL,或通过Action返回的集合。

● var:指定集合中每个元素的引用变量(可选项)。

● status:指定集合中元素的status属性(可选项),且该属性的属性值如表4-1所示。

表4-1 status属性的属性值

1)遍历访问List集合,如下面的代码所示(注意代码中给出的注释说明)。

    <! -- 说明:设置set集合(创建list对象并存放到request中),给value赋值;-->
    <! -- 利用value="#request.list" 获取集合对象,并指定迭代时的IteratorStatus实例,其中
      statu.odd返回当前被迭代元素的索引是否是奇数  -->
    <s:set name="list" value="{'a', 'b', 'c', 'd'}" scope="request">></s:set>
    <s:iterator var="ent" value="#request.list" status="st">
        <font color=<s:if test="#st.odd">red</s:if><s:else>blue</s:else>>
          <s:property value="#ent" />
      </font><br>
    </s:iterator>

2)遍历访问Map集合,如下面的代码所示(注意代码中给出的注释说明)。

    <h3>Map集合</h3>
    <! --  说明:Map集合语法格式:#{key:value, key1:value1, key2:value2, .....} 该语法直接生成了一
        个Map类型的集合,该Map对象中的每个key-value对象之间用英文的冒号隔开,多个元
        素之间用逗号分隔。
      首先创建Map对象,然后对Map对象进行遍历,并显示其对应的“健”---“值”-->
    <s:set var="map" value="#{'1':'张三', '2':'李四', '3':'王五'}"></s:set>
    遍历Map:<br />
    <s:iterator value="#map">
        <s:property value="key"/>  --对应于--  <s:property value="value"/><br/>
    </s:iterator>

3)对集合变量进行遍历访问。

例如,假设users是User的对象集合,并存储在session对象内,age(年龄)是User中的一个属性。

    <h3>遍历集合</h3>
    <! -- 遍历出年龄大于30的所有人员 -->
    <s:iterator var="user" value="#session.users">
      <s:if test="%{#user.age>30}">
          <s:property value="#user.age"/>
      </s:if>
    </s:iterator>
    <! --遍历出年龄大于30的最后一名人员。
      注意,运算符“$”表示取出满足条件的最后一个值 -->
    <s:iterator var="u" value="#session.users.{$(#this.age>30)}">
        <s:property value="#u.age"/>
    </s:iterator>

4.3.3 Struts 2的表单标签与应用案例

Struts 2的表单标签将在HTM文档里被呈现为一个表单元素。使用Struts 2的表单标签具有以下优点。

● 可以实现表单回显,对于修改信息特别方便。

● 对页面进行自动布局和排版。

●标签的属性可以被赋值为一个静态的值或一个OGNL表达式,如果在赋值时使用了一个OGNL表达式并把它用%{}括起来,这个表达式将会被求值。

Struts 2中的大部分表单标签和HTML表单元素一一对应,表4-2给出了常用的几个标签,表4-3给出了表单标签的共同属性。

表4-2 Struts 2常用的表单标签

表4-3 表单标签常用的共同属性

1.form标签

form标签用来呈现HTML语言中的表单元素,其主要属性如表4-4所示。

表4-4 form标签的主要属性

在默认情况下,form标签将被呈现为一个表格形式的HTML表单,嵌套在form标签里的输入字段将被呈现为一个表格行,每个表格行由两个字段组成,一个对应行标,一个对应输入元素,提交按钮将被呈现为一个横跨两列单元格的行。

2.textfield标签、password标签和hidden标签

● textfield标签:生成一个单行的文本输入框。

● password标签:生成一个密码域。

● hidden标签:生成一个隐藏域。

语法格式如下。

    <s:标签名label="***"name="***"size="***"maxlength="***"/>

其中,label是文本框提示,size是文本框宽度,maxlength是最大字符数。对于password标签有showPassword属性,其属性值是布尔型,默认值为false,决定着在表单回显时是否显示输入的密码。

3.textarea标签:生成一个多行文本框

语法格式如下。

    <s:textarea label="***" name="***" cols= "***" rows="***"/>

4.checkbox标签:复选框标签

该复选框元素用于提交一个布尔值,如果该框被选中了,它的值将为true。

语法格式如下。

    <s:checkbox label="***" name="***" value="true"/>

5.checkboxlist标签、select标签和radio标签

这3个标签有3个非常重要的属性:list、listKey和listValue。

可以将Map、Lits集合类型的对象赋给list属性;同时可以把用来提供选项值的属性赋给listKey属性,把用来提供选项行标的属性赋给listValue属性(这两个属性相当于Map类型的键值对)。

1)checkboxlist标签:形成多选复选框,如下面的代码所示。

    <s:checkboxlist label="个人爱好" list="{'学习', '看电影', '编程序'}" name="love"/>

2)select标签:生成一个下拉列表框,如下面的代码所示。

    <s:select label="选择星期" headerValue="---请选择---" headerKey="1"
          list="{'星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'}"/>

3)radio标签:为一个单选框,如下面的代码所示。

    <s: radio label="性别" list="{'男', '女'}" name="sex"></s: radio>

6.file标签

用于在页面上生成一个上传文件的元素。

语法格式如下。

    <s:file name="***" label ="***"/>

7.标签的主题

为了让所有的UI标签能够产生同样的视觉效果而归集到一起的一组模板,即风格相近的模板被打包成一个主题。

1)主题类型:在Struts 2中给出了以下几个主题。

● simple:把UI标签翻译成最简单的HTML对应元素,而且会忽视行标属性。

● xhtml:xhtml是默认的主题,使用一个布局表格提供了一种自动化的排版机制。

● css_xhtml:与xhtml主题里的模板很相似,但它们将使用css来进行布局和排版。

● ajax:以xhtml主题里的模板为基础,但增加了Ajax功能。

2)修改主题:通常采用以下方法修改主题。

● 通过UI标签的theme属性。

● 在表单里,若没有给出某个UI标签的theme属性,它将使用这个表单的主题。

●修改struts.properties文件中的struts.ui.theme属性。

例4-5】 Struts 2的表单标签应用示例。利用Struts 2的表单标签设计下面的JSP页面(在代码中给出了相关的注释),并与如图4-5所示的运行界面对照,理解各标签的使用格式与功能。

图4-5 【例4-5】的运行页面

1)设计界面:form.jsp,其主要代码如下。

    <%@ taglib prefix="s" uri="/struts-tags"%>
    <html><head><title>表单设计演示</title></head>
    <body>
        <h3>FORM表单</h3>
        <s:form action="" name="test">
            <s:textfield label="用户名" name="uname"/>
            <s:password label="密码" name="upass"/>
            <s:file name="file" label="上传文件"/>
            <s:hidden name="id" value="1"/>
          <! --  基于Map类型,设计列表框 -->
            <s:select list="#{'1':'博士', '2':'硕士'}" name="edu" label="学历"
                listKey="key" listValue="value"></s:select>
          <! --  基于集合类型,设计列表框,其中,value值设置为默认选中项  -->
            <s:select  label="lanuage"list="{'java', '.net', ''}"value="{'.net'}"></s:select>
            <! --单选复选框的设计,必须有name -->
            <s:checkbox label="爱好 "name="checkboxFiled1"value="true"></s:checkbox>
            <! -- 基于数组类型实现多个checkbox,并指定默认选中项 -->
            <s:checkboxlist list="{'java', 'css', 'html', 'struts2'}" label="喜欢的编程语言1"
                  name="box" value="{'css', 'struts2'}"></s:checkboxlist>
            <! --  基于Map集合实现多选复选框,注意:前要加#,并指定默认选中项-->
            <s:checkboxlist
                  list="#{1:'java',2:'css',3:'html',4:'struts2',5:'spring'}"
                  label="喜欢的编程语言2" name="boxs" value="{1,2}"></s:checkboxlist>
            <! --radio标签的使用,并模拟从后台传进选中的默认值 -->
            <%  //从服务器传过来的值用于设置单选按钮的默认值
                request.setAttribute("sex", "男");
                session.setAttribute("sex1", "1"); %>
            <s:radio label="性别1" list="{'男', '女'}" name="sex1" value="#request.sex"/>
            <s:radio label="性别2" list="#{'1':'男', '2':'女'}" name="sex2" listKey="key"
                listValue="value" value="#session.sex1"></s:radio>
            <! --  textarea标签的使用  -->
            <s:textarea name="rmake" cols="40" rows="5" label="备注"/>
            <! -- 防止表单重复提交的方式 -->
            <s:token></s:token>
            <s:submit value="提交"></s:submit>
        </s:form>
    </body>
    </html>

2)运行界面如图4-5所示。