3.3 Struts2标签库应用

放肆的年华 提交于 2019-12-06 20:55:02

        Struts2 把所有标签都定义在URI/struts-tags的命名空间下。可以分为3类:UI标签(主要用于生成HTML元素的标签,可分为表单标签和非表单标签)、非UI标签(主要用于数据访问和逻辑控制等,分为数据标签和控制标签)和Ajax标签(主要用于Ajax支持的标签)。

3.3.1 Struts 2的OGNL表达式

1.OGNL表达式

    OGNL(Object Graphic Navigation Language对象图导航语言),是个开源项目。OGNL是一种功能强大的EL(Expression Language,表达式语言),可以通过简单的表达式来访问Java对象中的属性

    OGNL首先在WebWork项目中得到应用,OGNL是Struts2框架视图默认的表达式语言,OGNL表达式是Struts 2框架的特点之一

    标准的OGNL会设定一个根对象(root对象)。假设使用标准OGNL表达式来求值(不是Struts 2 OGNL),如果OGNL上下文有两个对象,foo对象和bar对象,同时foo对象被设置为根对象(root),则利用下面的OGNL表达式求值。

#foo.blah // 返回foo.getBlah()
#bar.blah // 返回bar.getBlah()
blah // 返回foo.getBlah(),因为foo为根对象

    如果要访问的不是根对象需要使用命名空间,用“#”表示。如果是根对象,则不用指定

    在Struts 2框架中值栈(Value Stack)就是OGNL的根对象。假设值栈中存在两个对象实例Man和Animal,这两个对象实例都有一个name属性,Animal有一个species属性,Man有一个salary属性。假设Animal在值栈的顶部,Man在Animal后面,如图所示。

一个包含了Animal和Man的值栈

 

下面的代码片段能更好地理解OGNL表达式。

species // 调用animal.getSpecies()
salary // 调用man.getSalary()
name // 调用animal.getName(),因为Animal位于值栈的顶部

    最后一行实例代码返回的是animal.getName()返回值,即返回了Animal的name属性,因为Animal是值栈的顶部元素,OGNL将从顶部元素搜索,所以会返回Animal的name属性值。如果要获得Man的name值,则需要如下代码:

man.name

    Struts 2允许在值栈中使用索引,实例代码如下:

[0].name // 调用animal.getName()
[1].name // 调用man.getName()

    Struts 2中的OGNL Context是ActionContext,如图所示。

 

Struts 2的OGNL Context结构示意图

 

    由于值栈是Struts 2中OGNL的根对象。如果用户需要访问值栈中的对象,则可以通过如下代码访问值栈中的属性:

${foo} // 获得值栈中的foo属性

如果访问其他Context中的对象由于不是根对象,在访问时需要加#前缀

  • application对象:用来访问ServletContext,如#application.userName或者#application  ["userName"],相当于调用Servlet的getAttribute("userName")。  

  • session对象:用来访问HttpSession,如#session.userName或者#session["userName"],相当于调用session.getAttribute("userName")。  

  • request对象:用来访问HttpServletRequest属性的Map,如#request.userName或者#request["userName"],相当于调用request.getAttribute("userName")。如在3.2.1节中StrutsAction类中代码:

Map request=(Map)ActionContext.getContext().get("request");
request.put("name",getName());

    这就是先得到request对象,然后把值放进去,在该例的success.jsp中有:

<s:property value="#request.name"/>

    其中#request.name相当于调用了request.getAttribute("name")。

2.OGNL集合操作

    使用如下代码直接生成一个List对象

{e1, e2, e3…}

    下面的代码可以直接生成一个Map对象

#{key: value1, key2: value2, …}

    对于集合类型,OGNL表达式可以使用innot in两个元素符号。其中,in表达式用来判断某个元素是否在指定的集合对象中;not in判断某个元素是否不在指定的集合对象中,代码如下所示:

<s: if test="'foo' in {'foo', 'bar'}">
…
</s: if>


<s: if test="'foo' not in {'foo', 'bar'}">
…
</s: if>

    除了in和not in之外,OGNL还允许使用某个规则获得集合对象的子集,常用的有以下3个相关操作符。 

  • ?:获得所有符合逻辑的元素。  

  • ^:获得符合逻辑的第一个元素  

  • $:获得符合逻辑的最后一个元素。

如下面的代码:

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

    该代码可以获得Person的所有性别为male的relatives集合

3.3.2 数据标签

    数据标签属于非UI标签,主要用于提供各种数据访问相关的功能,数据标签主要包括以下几个。

  • property:用于输出某个值。  

  • set:用于设置一个新变量。  

  • param:用于设置参数,通常用于bean标签和action标签的子标签。  

  • bean:用于创建一个JavaBean实例。  

  • action:用于在JSP页面直接调用一个Action。    

  • date:用于格式化输出一个日期。  

  • debug:用于在页面上生成一个调试链接,当单击该链接时,可以看到当前值栈和Stack  Context中的内容  

  • il8n:用于指定国际化资源文件的baseName。  

  • include:用于在JSP页面中包含其他的JSP或Servlet资源。  

  • push:用于将某个值放入值栈的栈顶。  

  • text:用于输出国际化(国际化内容会在后面讲解)。  

  • url:用于生成一个URL地址。

1. s:property 标签

    property标签的作用是输出指定值。property标签输出value属性指定的值。如果没有指定的value属性,则默认输出值栈栈顶的值。该标签有如下几个属性:

  • default:该属性是可选的,如果需要输出的属性值为null,则显示default属性指定的值 

  • escape:该属性是可选的,指定是否escape  HTML代码。  

  • value:该属性是可选的,指定需要输出的属性值,如果没有指定该属性,则默认输出值栈栈顶的值。该属性也是最常用的,如前面用到的:

<s:property value="#request.name"/>
  •  id:该属性是可选的,指定该元素的标志

2. s:set 标签

    对值栈中的表达式进行求值,并将结果赋给特定作用域中的某个变量名该标签有如下几个属性: 

  • name:该属性是必选的,重新生成新变量的名字  

  • scope:该属性是可选的,指定新变量的存放范围。一般为application、session、request、page和action。如果没有指定该属性,则默认放置在值栈中  

  • value:该属性是可选的,指定赋给新变量的值。如果没有指定该属性,则将值栈栈顶的值赋给新变量  

  • id:该属性是可选的,指定该元素的引用id。

    下面是一个简单例子,展示了property标签访问存储于session中的user对象的多个字段:

<s:property value="#session['user'].username"/>
<s:property value="#session['user'].age"/>
<s:property value="#session['user'].address"/>

    由于每次都要重复使用#session['user'],不仅烦人还容易引发错误,更好的做法是定义一个临时变量,使用set标签使得代码易于阅读:

<s:set name="user" value="#session['user'] " />
<s:property value="#user.username"/>
<s:property value="#user.age" />
<s:property value="#user.address" />

3. s:param 标签

    param标签主要用于为其他标签提供参数,该标签有如下几个属性:

  • name:该属性是可选的,指定需要设置参数的参数名。  

  • value:该属性是可选的,指定需要设置参数的参数值。  

  • id:该属性是可选的,指定引用该元素的id。

例如,要为name为fruit的参数赋值:

<s:param name= "fruit">apple</s:param>

或者

<s:param name="fruit" value="apple" />

    指定一个名为fruit的参数,该参数的值为apple对象的值如果该对象不存在,则fruit的值为null

    如果想指定fruit参数的值为apple字符串,则应该这样写:

<s:param name="fruit" value="'apple'" />

4. s:bean 标签

    用于创建一个JavaBean实例。创建JavaBean实例时,可以在该标签内使用param标签为该JavaBean实例传入属性。如果要使用param标签传入属性值,则应该为该JavaBean类提供setter方法。如果还希望访问该属性值,则必须为该属性提供getter方法。该标签有如下几个属性:

  • name:该属性是必选的,用来指定要实例化的JavaBean的实现类。  

  • id:该属性是可选的,如果指定了该属性,则该JavaBean实例会被放入Stack Context中,从而允许直接通过id属性来访问该JavaBean实例。下面是一个简单的例子:

    有一个Student类,该类中有name属性,并有其getter和setter方法:

public class Student {
    private String name;
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name=name;
    }
}

    然后在JSP文件的body体中加入下面的代码:

<s:bean name="Student">
    <s:param name="name" value="'zhangsan'"/>
    <s:property value="name"/>
</s:bean>

    在项目中导入Struts 2的Jar包,再把Student类放在项目的src文件夹下(如果Student类在在某个包下面,那么<s:bean>标签的name要加上包名。例如org.bean.Student),<s:bean>标签内容放在一个JSP文件的body体内,再修改web.xml文件,就可以部署运行该项目,会得到如图所示的界面。

bean标签实例界面

    也可以把bean标签的内容改为:

<s:bean name="Student" id="s" >
    <s:param name="name" value="'zhangsan'"/>
</s:bean>
<s:property value="#s.name"/>

5. s:action 标签

    使用action标签可以允许在JSP页面中直接调用Action。该标签有以下几个属性:

  • id:该属性是可选的,该属性将会作为该Action的引用标志id。  

  • name:该属性是必选的,指定该标签调用哪个Action。  

  • namespace:该属性是可选的,指定该标签调用的Action所在的namespace。  

  • executeResult:该属性是可选的,指定是否要将Action的处理结果页面包含到本页面。如果值为true,就是包含,false就是不包含,默认为false  

  • ignoreContextParam:该属性是可选的,指定该页面中的请求参数是否需要传入调用的Action。如果值为false,将本页面的请求参数传入被调用的Action。如为true,不将本页面的请求参数传入到被调用的Action。

6. s:date 标签

    date标签主要用于格式化输出一个日期。该标签有如下属性:

  • format:该属性是可选的,如果指定了该属性,将根据该属性指定的格式来格式化日期。  

  • nice:该属性是可选的,该属性的取值只能是true或false,用于指定是否输出指定日期和当前时刻之间的时差默认为false,即不输出时差。  

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

  • id:属性是可选的,指定引用该元素的id值。

    nice属性为true时,一般不指定format属性。因为nice为true时,会输出当前时刻与指定日期的时差,不会输出指定日期。当没有指定format,也没有指定nice="true"时,系统会到国际化资源文件中寻找key为struts.date.format的消息将该消息当成格式化文本来格式化指定日期如果无法找到,则默认采用DateFormat.MEDIUM格式输出。其用法为:

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

例子:

java

import java.util.Date;
public class Student {
    private Date birthday;
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

jsp

  1.     <s:bean name="Student">
            <s:param name="birthday" value="'2011-12-10'"/>
            <s:date name="birthday" /><br/>
            <s:date name="birthday" format="yyyy-MM-dd hh:mm:ss"/><br/>
            <s:date name="birthday" nice="true"/><br/>
        </s:bean>


7. s:include 标签

    include标签用于将一个JSP页面或一个Servlet包含到本页面中。该标签有如下属性: 

  • value:该属性是必选的,指定需要被包含的JSP页面或Servlet。  

  • id:该属性是可选的,指定该标签的id引用。

用法如下:

<s:include value="JSP或Servlet文件" id="自定义名称"/>


3.3.3 控制标签

    属于非UI标签,主要用于完成流程的控制,以及对值栈的控制。控制标签有以下几个:

  • if:用于控制选择输出的标签。  

  • elseif:用于控制选择输出的标签,必须和if标签结合使用。  

  • else:用户控制选择输出的标签,必须和if标签结合使用。  

  • append:用于将多个集合拼接成一个新的集合。  

  • generator:用于将一个字符串按指定的分隔符分隔成多个字符串,临时生成的多个子字符串可以使用iterator标签来迭代输出  

  • iterator:用于将集合迭代输出。  

  • merge:用于将多个集合拼接成一个新的集合,但与append的拼接方式不同。  

  • sort:用于对集合进行排序。  

  • subset:用于截取集合的部分元素,形成新的子集合。

1. s:if, s:elseif, s:else标签

    这3个标签可以组合使用,但只有if标签可以单独使用,而elseif和else标签必须与if标签结合使用。if标签可以与多个elseif标签结合使用,但只能与一个else标签使用。其用法格式如下:

<s:if test="表达式">
标签体
</s:if>
<s:elseif test="表达式">
标签体
</s:elseif>
<!--允许出现多次elseif标签-->
...
<s:else>
标签体
</s:else>

2. s:iterator 标签

    该标签主要用于对集合进行迭代,这里的集合包含List、Set,也可以对Map类型的对象进行迭代输出。该标签的属性如下: 

  • value:该属性是可选的,指定被迭代的集合,被迭代的集合通常都由OGNL表达式指定。如果没有指定该属性,则使用值栈栈顶的集合  

  • id:该属性是可选的,指定集合元素的id。  

  • status:该属性是可选的,指定迭代时的IteratorStatus实例,通过该实例可判断当前迭代元素的属性。如果指定该属性,其实例包含如下几个方法:   

    • int getCount():返回当前迭代了几个元素    

    • int getIndex():返回当前被迭代元素的索引。    

    • boolean isEven:返回当前被迭代元素的索引元素是否是偶数    

    • boolean isOdd:返回当前被迭代元素的索引元素是否是奇数。    

    • boolean isFirst:返回当前被迭代元素是否是第一个元素。    

    • boolean isLast:返回当前被迭代元素是否是最后一个元素。

应用举例:

<%@ page language="java" pageEncoding="utf-8"%>
<%@taglib uri="/struts-tags" prefix="s" %>
<html>
    <head>
        <title>控制标签</title>
    </head>
    <body>
        <table border="1" width="200">
            <s:iterator value="{'apple','orange','pear','banana'}"id="fruit" status="st">
                <tr <s:if test="#st.even">style="background-color:silver"</s:if>>
                    <td><s:property value="fruit"/></td>
                </tr>
            </s:iterator>
        </table>
    </body>
</html>

    通过添加Struts 2必须的Jar包,再建立上面JSP文件,修改web.xml后,就可以部署运行,运行结果如图所示。

iterator标签实例运行结果

 

3. s:append 标签

    用于将多个集合对象拼接起来,组成一个新的集合。必须指定一个id属性,该属性确定拼接的新集合的名称。该标签通过param标签来指定每一个集合,然后把这些集合拼接起来。

    应用举例,可以把上例的JSP文件进行修改,其代码为:

<%@ page language="java" pageEncoding="utf-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
    <head>
        <title>控制标签</title>
    </head>
    <body>
        <s:append id="newList">
            <s:param value="{'apple','orange','pear','banana'}"></s:param>
            <s:param value="{'chinese','english','french'}"></s:param>
        </s:append>
        <table border="1" width="200">
            <s:iterator value="#newList" id="fruit" status="st">
                <tr <s:if test="#st.even">style="background-color:silver"</s:if>>
                    <td>
                        <s:property value="fruit" />
                    </td>
                </tr>
            </s:iterator>
        </table>
    </body>
</html>

    部署运行,运行结果如图所示。

append标签实例运行界面

4.  s:merge 标签

    与append标签的区别,只是拼接方式不同

    假设有2个集合,第一个集合包含3个元素,第二个集合包含2个元素,分别用append标签和merge标签方式进行拼接,它们产生新集合的方式有所区别。下面分别列出:

用append方式拼接,新集合元素顺序为: 

  • 第1个集合中的第1个元素  

  • 第1个集合中的第2个元素  

  • 第1个集合中的第3个元素  

  • 第2个集合中的第1个元素  

  • 第2个集合中的第2个元素

用merge方式拼接,新集合元素顺序为: 

  • 第1个集合中的第1个元素  

  • 第2个集合中的第1个元素  

  • 第1个集合中的第2个元素  

  • 第2个集合中的第2个元素  

  • 第1个集合中的第3个元素

代码如下:

<%@ page language="java" pageEncoding="utf-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
    <head>
        <title>控制标签</title>
    </head>
    <body>
        <s:merge id="newList2">
            <s:param value="{'apple','orange','pear','banana'}"></s:param>
            <s:param value="{'chinese','english','french'}"></s:param>
        </s:merge>
        <table border="1" width="200">
            <s:iterator value="#newList2" id="fruit2" status="st2">
                <tr <s:if test="#st2.even">style="background-color:silver"</s:if>>
                    <td>
                        <s:property value="fruit2" />
                    </td>
                </tr>
            </s:iterator>
        </table>
    </body>
</html>

3.3.4 表单标签

    大部分的表单标签和HTML表单元素是一一对应的关系,如下面的代码片段:

<s:form action="login.action" method="post"/>

对应着:

<form action="login.action" method="post"/>


<s:textfield name="username" label="用户名" />

对应着:

用户名:<input type="text" name="username">


<s:password name="password" label="密码"/>

对应着:

密码:<input type="password" name="pwd">

     还有下面这种情况,如果有这样一个JavaBean类,类名为“User”,该类中有两个属性:一个是username;另一个是password,并分别生成它们的getter和setter方法,在JSP页面的表单中可以这样为表单元素命名:

<s:textfield name="user.username" label="用户名" />
<s:password name="user.password" label="密码"/>

下面介绍和HTML标签元素不是一一对应的几个重要的表单标签:

1. s:checkboxlist 标签

    创建多个复选框。该标签需要指定一个list属性。用法举例:

<s:checkboxlist label="请选择你喜欢的水果" list="{'apple','oranger','pear','banana'}" name="fruit">
</s:checkboxlist>

    或者为:

<s:checkboxlist label="请选择你喜欢的水果" list="#{1:'apple',2:'oranger',3:'pear',4:'banana'}" name="fruit">
</s:checkboxlist>

这两种方式的区别:前一种根据name取值时取的是选中字符串的值;后一种在页面上显示的是value的值,而根据name取值时取的却是对应的key,这里就是1、2、3或4。

 

2. s:combobox 标签

    combobox标签生成一个单行文本框和下拉列表框的组合。两个表单元素只能对应一个请求参数,只有单行文本框里的值才包含请求参数,下拉列表框只是用于辅助输入,并没有name属性,故不会产生请求参数。用法举例:

<s:combobox label="请选择你喜欢的水果" list="{'apple','oranger','pear','banana'}" name="fruit">
</s:combobox>

3. s:datetimepicker 标签

    datetimepicker标签用于生成一个日期、时间下拉列表框。当使用该日期、时间列表框选择某个日期、时间时,系统会自动将选中日期、时间输出指定文本框中。用法举例:

<s:form action="" method="">
    <s:datetimepicker name="date" label="请选择日期"></s:datetimepicker>
</s:form>

    注意:在使用该标签时,要在HTML的head部分加入<s:head/>

 

4. s:select 标签

    select标签用于生成一个下拉列表框,通过为该元素指定list属性的值,来生成下拉列表框的选项。用法举例:

<s:select list="{'apple','oranger','pear','banana'}"  label="请选择你喜欢的水果"></s:select>

或者为:

<s:select list="fruit" list="#{1:'apple',2:'oranger',3:'pear',4:'banana'}"  listKey="key"listValue="value"></s:select>

 

5. s:radio 标签

    radio标签的用法与checkboxlist用法很相似,唯一的区别就是checkboxlist生成的是复选框,而radio生成的是单选框。用法举例:

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

或者为:

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

 

6. s:head 标签

    head标签主要用于生成HTML页面的head部分。在介绍<s:datetimepicker>标签时说过,要在head中加入该标签,主要原因是<s:datetimepicker>标签中有一个日历小控件,其中包含了JavaScript代码,所以要在head部分加入该标签。

    如果需要在页面中使用Ajax组件,就需要在head标签中加入theme="ajax"属性

3.3.5 非表单标签

    非表单标签主要用于在页面中生成一些非表单的可视化元素。这些标签不经常用到,下面大致介绍一下这些标签:

  • a:生成超链接。

  • actionerror:输出Action实例的getActionMessage()方法返回的消息。

  • component:生成一个自定义组件。

  • div:生成一个div片段。

  • fielderror:输出表单域的类型转换错误、校验错误提示。  

  • tablePanel:生成HTML页面的Tab页。

  • tree:生成一个树形结构。

  • treenode:生成树形结构的节点。

 

附:目录《JavaEE基础实用教程》笔记说明

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!