学习内容

Struts 2标签库

OGNL

能力目标

熟练使用Struts 2常用标签

熟练使用OGNL

本章简介

前面我们编写的案例使用的都是HTML标签,这些标签并不能很好的与Struts 2框架结合,Struts 2和Struts 1一样都自带了功能强大、成熟完善的标签库供我们使用,通过使用这些标签库可以大大提高开发效率和代码的可维护性。

其实Struts 2的标签库是建立在OGNL基础上的,OGNL是一种功能强大的表达式语言,通过简单的语法即可存取对象的属性、调用对象的方法、遍历等功能。

本章将学习OGNL和Struts 2标签库,包括数据访问标签、控制标签

核心技能部分

6.1 OGNL

6.1.1 ActionContext

Struts 2中的ActionContext、ValueStack和StackContext对象与OGNL密切相关,理解这三个对象时学习OGNL的前提。

在前面的学习中,我们已经在使用ActionContext、ValueStack和StackContext对象了,这三个对象的作用及其之间的关系如图6.1.1所示。

图6.1.1 ActionContext

1. ActionContext对象

ActionContext(com.opensymphony.xwork.ActionContext)是Action执行时的上下文。我们可以把上下文看作是一个容器,用于存放Action执行时需要使用的对象信息,例如请求的参数(Parameter)、会话(Session)、Servlet上下文(ServletContext)等。在每次请求执行Action之前都会创建新的ActionContext。保存到ActionContext对象中的数据可以通过Struts2标签和OGNL表达式语言进行访问。

2. StackContext对象

StackContext对象是ActionContext上下文中的一个类型为java.utiI.Stack的实例。上面提到的请求参数(Parameter)、会话(Session)、Servlet上下文(ServletContext)等对象,实际上都存储在ActionContext上下文中的StackContext对象中。

3. ValueStack对象

Struts2会为每一次Action的请求创建与之对应的ValueStack,并将所有Action属性数据存储到ValueStack中,再将ValueStack 暴露给视图页面,这样页面就可以直接访问Action中的属性值。

6.1.2 使用OGNL

OGNL即(Object-Graph Navigation Language),是对象图导航语言的缩写,它是一个开源项目,工作在视图层,用来取代页面中的Java脚本,简化数据访问操作。

OGNL是一种比EL功能更强大的表达式语言。通过其简单一致的表达式语法,可以存取对象的属性、调用对象的方法、遍历以及进行类型转换等功能。Struts 2框架默认使用OGNL作为表达式语言。

1. 访问上下文中的数据

ActionContext是Struts 2中OGNL的上下文环境,即ActionContext中的数据(实际存储在StackContext中)都可以通过OGNL来访问。而ActionContext又包括Request、Session、ValueStack等对象,所以通过OGNL也可以访问存储在这些对象中的数据。

ValueStack是OGNL的根,同时由于OGNL上下文中的根对象可以直接访问,所以通过OGNL访问ValueStack中的数据时,不需要使用任何特殊的标记,而访问ActionConext中的其他对象时则需要使用“#”标记。Struts 2中提供了<s:property>标签来显示OGNL上下文中的数据,在实际应用中通常分为以下四种情况:

(1)<s:property  value=”uid”/>: Struts2会在ValueStack中查找名为uid的项,并输出其值。

(2)<s:property  value=”#uid”/>: Struts2会在StackContext中查找名为uid的项,并输出其值。

(3)<s:property  value=”#session.uid”/>: Struts2会在StackContcxt中的Session作用域中查找名为uid的项,并输出其值。这里的session也可以更换为request和application,以便在Request和Application作用域中查找指定的项。

(4) <s:property  value =”#attr.uid”/>: Struts2会依次在StackContext的Page、 Request、Session、Application作用域内查找对应的uid中的值。

2. 访问JavaBean属性

通过OGNL可以非常方便的访问JavaBean,假设现在ValueStack中存在StudentAction,该Action的属性有name、age等。

(1) <s:property value=”name”/>:Struts2会执行StudentAction对象的getName()方法来获得并输出name属性的值

(2) <s:property value=”age”/>:Struts2会执行StudentAction对象的getAge()方法来获得并输出age属性的值

由于ValueStack是OGNL的根,所以此时在使用<s:property>标签时无需“#”标记。

3.  执行JavaBean方法

OGNL不仅可以自动执行getter方法,而且能够执行JavaBean的其他方法。更重要的是,还能够在执行方法的时候传入参数,OGNL执行的方法可以是静态方法和非静态方法。执行静态方法的格式为:@类的全类名@方法名(参数)。为了能够让OGNL执行静态方法,还必须在struts.xml配置文件中配置常量参数,才可以开启OGNL调用静态方法的功能,配置代码如下:

<constantname="struts.ognl.allowStaticMethodAccess" value="true" />

示例6.1演示了使用OGNL执行JavaBean方法。

示例6.1

(1)创建JavaBean ,命名为“OgnlInfo.java”。

public class OgnlInfo {
//定义静态方法
public static String sayBye(String name)
{
return name + "再见!";
}
//定义非静态方法
public String sayHello(String name)
{
return name + "你好!";
}
}

(2)创建index.jsp。

<body><%//实例化ognl对象OgnlInfo ognlInfo = new OgnlInfo();//将ognlinfo对象存入request作用域内request.setAttribute("ognlInfo",ognlInfo);  %><!-- 执行ognl对象非静态方法 --><s:property value="#request.ognlInfo.sayHello('jack')"/><!-- 执行ognl对象静态方法 --><s:property value="@com.zzab.entity.OgnlInfo@sayBye('tom')"/></body>

4.   OGNL操作符

OGNL表达式中能使用的操作符基本与Java中的操作符相同,除了能使用+、—、*、/、==、!=、=等操作符之外,还能使用mod(取余)、in、not in等操作符。

5. “%”号

“%”号用于对属性为字符串类型的OGNL表达式的值进行计算,“%”符号在OGNL中的使用方法如下:

<body>

<%

String value="确定";

pageContext.setAttribute("val", value);

%>

不使用%符号,会按原样显示<br>

<s:submit value="#attr.val"/>

<br>

使用%符号,会计算OGNL表达式的值<br>

<s:submit value="%{#attr.val}"/>

</body>

运行结果如图6.1.2所示。

图6.1.2 %的使用

6. OGNL的集合操作

(1)生成List类型的集合。具体语法为{e1,e2,e3,...}。此语法将直接生成一个list类型集合,该集合包含3个元素:e1,e2,e3。如果需要更多的元素,则多个元素之间以英文逗号隔开。

(2)生成Map类型的集合。具体语法为#{key1,key2,key3...}。此语法将直接生成一个Map类型集合,该Map中每个key-value对象之间以英文冒号隔开,如果需要更多的元素,则多个元素之间以英文逗号隔开。

(3)使用in和not in 运算符。对于集合,OGNL提供元素符in与not in。其中,in用于判断某个元素是否在指定集合内;not in 则用于判断某个元素是否不在指定的集合中。In和 not in 的用法如下:

<!-- 判断java是否在指定集合中-->

<s:if test="'java' in {'java','jsp','html'}">

存在

<s:else>

不存在

</s:else>

</s:if>

(4)   获取集合的子集。OGNL允许通过某个规则取得集合的子集,取得子集时有以下三种操作符:

1)“?”操作符:取出所有符合选择逻辑的元素。

2)“^”操作符:取出符合选择逻辑的第一个元素。

3)“$”操作符:取出符合选择逻辑的最后一个元素。

假设现在Session中存在名为StudentList的集合,该集合存储了多个Student对象。Student类中存在一个age属性,这三种操作的语法如下:

#session.StudentList.{?#this.age>20}用于取出年龄大于20的子集合。

#session.StudentList.{^#this.age>20}用于取出第一个年龄大于20的Student对象。

#session.StudentList.{$#this.age>20}用于取出最后一个年龄大于20的Student对象。

6.2 Struts 2的标签库

Struts 2作为一个优秀的MVC框架,它为开发人员提供了一个功能强大、支持广泛、高扩展性的标签库,完全能满足Web页面复杂、多变的需求。

Struts 2的标签库大大简化了视图页面的代码编辑工作,提高了视图页面的维护效率。与Struts 1的标签库相比,Struts 2的标签库不但功能强大,而且更加简单易用。

在Struts 1的标签库中,它分别提供了html、bean、logic等几个标签库。Struts 2标签库并没有严格的对标签进行分类,而是把所有标签整合到了一个标签库中。为了使初学者对Struts 2标签库能有更加清晰的认识,我们可以将Struts 2的标签库分成三大类(如图6.1.3所示):

UI标签:主要用于生成HTML页面元素。

非UI标签:主要用于逻辑控制、数据访问等操作。

Ajax标签:主要用于支持Ajax访问。

其中又可以把UI标签分为如下两类:

表单标签:主要用于生成HTML中的表单元素。

非表单标签:主要包含一些常用的功能标签,例如显示日期或树形菜单。

对于非UI标签,也可以再细分为如下两类:

数据访问标签:主要用于获得或输出ValueStack中的值。

逻辑控制标签:主要用于数据访问中的条件分支、循环等流程控制。

图6.1.3 标签库分类

使用Struts2标签库之前,也需要在JSP页面中导入。现在的Web应用一般都使用Servlet 2.4以上的规范,因此我们就无须在web.xml文件中对标签库进行配置,因为Servlet 2.4以上的规范可以直接读取标签库定义文件(TLD文件),在JSP页面中直接通过下面一行代码就可以导入Struts 2标签库。

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

6.2.1 数据访问标签

数据访问标签主要用来获得或输出各种数据的功能,常应用于显示Action中的属性以及国际化输出等场合。常见的数据标签主要包含以下几个:

action标签:该标签用于在JSP页面中直接调用一个Action 。

include标签:该标签用于在JSP页面中包含其他页面资源。

param标签:该标签用于设置一个参数,通常用作bean、url标签的子标签。

property标签:该标签用于输出某个值。

set标签:该标签用于设置一个新变量。

text标签:该标签用于输出国际化消息。

url标签:该标签用于生成一个URL地址。

date标签:该标签用于格式化输出一个日期。

1. action标签

该标签可以在JSP页面中直接调用Action,并可以把执行的结果包含在标签的位置,这时需要指定Action的name和namespace等属性。下面是该标签的几个主要属性:

id属性:该属性用来指定被调用的Action的引用ID。

name属性:该属性用来指定被调用的Action的名字。

namespace属性:该属性用来指定被调用的Action所在的namespace。

executeResult属性:该属性用来指定是否将Action的处理结果包含到当前页面中,该

属性的默认值是false,即不包含。

示例6.2

下面我们通过一个实例来介绍action标签的具体应用,首先编写一个简单的Action类,代码如下所示。

public class TagAction

{

private String name;

//省略getter和setter方法

public String exec()

{

return "ok";

}

}

通过上述代码可以看到该Action只包含了一个exec业务方法。下面是该Action在struts.xml文件中的配置:

<struts><package name="struts2_Tags" extends="struts-default"namespace="/tags">
<action name="tag1" class="com.zy.TagAction" method="exec">
<result name="ok">succ.jsp</result>
</action></package>
</struts>

下面是succ.jsp视图文件的代码:

<body>

<br>

调用Action!!

</body>

下面是使用action标签的s-action_Tag.jsp文件,代码如下所示:

<body>

下面调用Action,并将结果包含到本页面中。<br>

<s:action name="tag1" executeResult="true" namespace="/tags"/>

</body>

上述代码使用<s:action />标签调用了名字为tag1的逻辑action,并通过设置executeResult属性为true将结果包含到了本页面中。

图6.1.4  action标签的应用

2. property标签

该标签的作用就是输出ActionContext中对象的值或者Action、JavaBean的属性值,通常结合OGNL使用。该标签有如下几个属性:

Ø value,该属性用来指定要输出的属性或OGNL表达式。

Ø default,该属性用来指定当value指定的属性值为null时输出的值。

Ø escape,该属性用来指定是否生成HTML代码,默认为true,表示在浏览器上输出表达式的值;如果为false,则把表达式的值作为HTML代码嵌入。

示例6.3

下面是应用property标签的简单示例。

<body>

<%

String url="<a href='index.jsp'>超链接</a>";

pageContext.setAttribute("su",url);

%>

<s:property value="#attr.su"/><hr>

<s:property value="#attr.su" escape="false"/><hr>

<s:property value="#attr.uid" default="找不到uid"/>

</body>

运行效果如图6.1.5所示。

图6.1.5 property标签

3. include标签

该标签用来将一个JSP或Servlet等资源包含到当前页面中,使用起来非常简单。该标签主要包含value属性,用来指定被包含的JSP或Servlet等资源文件。

示例6.4

接下来通过一个简单的例子来介绍include标签的具体应用,首先是被包含的include-file.jsp页面的代码:

<%@ page contentType="text/html; charset=GBK" language="java"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
</head>
<body>
---------------------------
<h3>这是被包含的页面</h3>
</body>
</html>
下面是包含include-file.jsp这个页面的s-include_Tag.jsp文件,代码如下所示:
<%@ page contentType="text/html; charset=utf-8" language="java"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>使用include标签来包含目标页面</title>
</head>
<body>
<h2>使用include标签来包含目标页面</h2>
<s:include value="include-file.jsp"/>
</body>
</html>

上述代码通过使用include标签包含了include-file.jsp页面,运行效果如图6.1.6所示。

图6.1.6 include标签

4. set标签

该标签用来定义一个变量,并把这个变量放到指定的范围内,例如application范围、session范围等。该标签有以下一些常用属性:

Ø id属性:该属性用来定义变量的名字。

Ø scope属性:该属性用来定义变量被放置的范围,可选的值有application、session、request、response、page和StackContext。

Ø value属性:该属性用来定义将要赋给变量的固定值或者另一个已经定义的变量。

示例6.5

下面我们通过一个示例来介绍set标签的具体应用,首先我们定义一个变量p,并把“小样儿”这个字符串赋值给它,然后定义另一个变量user,并把p赋值给user。代码如下所示:

<body>

<h2>使用set标签设置一个新变量</h2>

<s:set id="p" value="'小样儿'"/>

<s:property value="#attr.p"/><br>

将p变量赋值给user变量并放入session范围内<br>

<s:set value="#p" id="user" scope="session"/>

<s:property value="#session.user"/><br>

</body>

运行效果如图6.1.7所示。

图6.1.7 set标签的应用

5. url标签

该标签用来生成一个URL地址,我们也可以通过嵌套param标签来为URL指定发送参数。该标签主要有以下一些常用属性:

Ø includeParams属性:该属性用来指定是否在生成的URL参数中追加本页面接收到的请求参数,有3个值可供选择,none, get和all,分别代表“不包含”、“包含get方法传递的参数”和“所有的参数”。

Ø value属性:该属性用来指定要生成的URL的地址值。

Ø action属性:该属性用来指定一个Action作为URL地址值。

Ø namespace属性:该属性用来指定命名空间。

Ø method属性:该属性用来指定调用Action的方法名。

Ø includeContext属性:该属性用来指定是否把当前上下文包含在URL地址值中。

在上述属性中,action和value属性只需指定其一即可,如果两个都未指定,就以当前页面作为URL地址值。下面是一个应用URL标签的示例。

示例6.6

<body>
<h3>使用url标签</h3>
<hr>
指定action属性,且使用param标签传入参数。<br>
<s:url action="showPerson"><s:param name="name" value="'Jack'" />
</s:url>
<hr>
指定value属性,且使用param标签传入参数。<br>
<s:url value="http://localhost:8080/firstStruts2/news.jsp"><s:param name="name" value="'Jack'" />
</s:url>
</body>

该页面的运行效果如图6.1.8所示。

图6.1.8 URL标签的应用

6. date标签

date标签用来按指定的格式输出一个日期,还可以计算指定日期到当前时间的时差。该标签主要有如下一些属性:

Ø format属性:该属性用来指定日期输出的格式,例如“yyyy-MM-dd”。

Ø name属性:该属性用来指定要被格式化输出的日期值。

示例6.7

我们看下面的实例代码,用“年/月/日”的完整格式显示当前日期:

<body>
<h3>date标签的使用</h3>
<%
java.util.Date now = new java.util.Date();
pageContext.setAttribute("now" , now);
%>
<s:date name="#attr.now" format="yyyy/MM/dd" nice="false"/><hr><br>
</body>

该页面的运行效果如图6.1.9所示。

图6.1.9 date标签的使用

7. <s:bean>标签

<s:bean>用来创建JavaBean实例,创建JavaBean实例的时候,可以在该标签内部使用<param/>标签为该JavaBean实例传入属性。其常见属性如下:

Ø Id:指定创建JavaBean的引用id.

Ø name:指定需要实例化的JavaBean的实现类

<s:bean>标签用法的如下:

(1) 创建JavaBean,命名为Book.java。

public class Book {
private String isbn;
private String name;
private double price;
public Book() {
super();
}
public Book(String isbn, String name, double price) {
super();
this.isbn = isbn;
this.name = name;
this.price = price;
}
public String[] getAllBooks()
{
String[] books = {"JAVA","JSP","ASP.NET","C#"};
return books;
}
}

(2) 创建Jsp页面.

<!-- 实例化book JavaBean对象,并存储到StackContext中 -->

<s:bean id="book" name="com.zzab.entity.Book">

<s:param name="isbn" value="'621345'"/>

<s:param name="name" value="'HTML'"/>

</s:bean>

<!-- 输出bean对象的值 -->

book对象属性值:<br>

isbn:<s:property value="#book.isbn"/><br/>

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

调用book对象的getAllBooks方法获取全部书籍列表:<br/>

<c:forEach var="book" items="${book.allBooks}">

<div>${book }</div>

</c:forEach>

<s:bean id="book" name="com.zzab.entity.Book">
<s:param name="isbn" value="'621345'"/>
<s:param name="name" value="'HTML'"/>
</s:bean>
<!-- 输出bean对象的值 -->
book对象属性值:<br>
isbn:<s:property value="#book.isbn"/><br/>
name:<s:property value="#book.name"/><br/>
调用book对象的getAllBooks方法获取全部书籍列表:<br/>
<c:forEach var="book" items="${book.allBooks}">
<div>${book }</div>
</c:forEach>

6.2.2 逻辑控制标签

Struts 2的逻辑控制标签主要用于程序流程的逻辑控制,例如选择、分支、循环等操作,常见的逻辑控制标签主要有以下五个标签:

Ø if标签:用于控制选择流程的标签。

Ø elseif标签:与if标签结合使用。

Ø else标签:与if标签结合使用。

Ø generator标签,用于将一个字符串解析成一个集合。

Ø iterator标签:这是一个迭代器,用于将集合进行循环输出。

1. if/elseif/else标签

if/elseif/else这三个标签通常结合使用,都是用于进行程序分支逻辑控制,跟多数编程语言中的if/elseif/else语句的功能相似,test属性用来设置比较表达式,具体语法如下所示:

<s:if test="表达式">

标签体

<s:elseif test="表达式">

标签体

<s:else>

标签体

</s:else>

下面是一个实例的代码片段:

示例6.8

<s:set name="dengji" value="85"/>
<s:if test="#dengji>=90">成绩优秀
</s:if>
<s:elseif test="#dengji>=80">成绩良好
</s:elseif>
<s:elseif test="#dengji>=60">
成绩合格
</s:elseif>
<s:else>成绩不合格
</s:else>

上述代码先通过set标签定义了一个名为dengji的属性并赋值为85,然后通过if/elseif/else标签根据dengji属性的值的范围来控制输出成绩的评价是“优秀”、“良好”、“合格”或“不合格”。运行效果如图6.1.10所示。

图6.1.10 if/elseif/else标签的应用

 

2. iterator标签

该标签主要用于对集合类型的变量进行迭代输出,这里的集合类型包括List、Set、数组和Map等。该标签主要有三个属性:

Ø value属性:该属性用来指定被迭代输出的集合,被迭代的集合可以由OGNL表达式指

定也可以通过Action返回一个集合类型的变量。

Ø id属性:该属性用来指定集合中元素的ID属性。

Ø status属性:该属性可以实现一些附加功能,详见后面讲解。

下面是一个实例的代码片段:

示例6.9

<h3>iterator的用法</h3>

<%

List bookList=new ArrayList();

bookList.add("Spring3.0技术宝典");

bookList.add("Struts2权威指南");

bookList.add("JavaScript技术大全");

bookList.add("JSP技术详解");

bookList.add("Ajax实战");

pageContext.setAttribute("bookList",bookList);

%>

<s:iterator value="#attr.bookList" id="bookname">

<li><s:property value="bookname" /></li>

</s:iterator>

上述代码通过iterator标签的value属性指定了一个集合,并指定它的id属性为bookname,然后就可以通过<s:property value="bookname" />输出集合中每个元素的值。该页面的运行效果如图6.1.11所示。

图6.1.11 iterator标签的应用

iterator标签的status属性很有用,利用它可以实现一些很实用的功能。指定该属性后,每次迭代都会以此属性为名称创建一个IteratorStatus的实例对象,该实例对象包含了以下几个属性:

Ø count:返回当前迭代了几个元素。

Ø index:返回当前迭代元素在集合中的索引值。

Ø even:返回当前迭代元素的索引值是否为偶数。

Ø odd:返回当前迭代元素的索引值是否为奇数。

Ø first:返回当前迭代元素是否是第一个元素。

Ø last:返回当前迭代元素是否是最后一个元素。

我们看下面的代码片段:

<table border="1" width="200">

<s:iterator value="#attr.bookList" id="name" status="st">

<tr <s:if test="#st.odd">style="background-color:#bbbbbb"</s:if>>

<td><s:property value="#st.index"/></td>

<td><s:property value="name"/></td>

</tr>

</s:iterator>

</table>

上述代码以表格的形式输出了集合中的每个元素和元素的索引值,并通过iterator标签的status属性控制奇数行的背景色,运行效果如图6.1.12所示。

图6.1.12 status属性的应用

 

 

3. generator标签

 

该标签可以将一个字符串按指定的分隔符分隔成多个子串,新生成的多个子串可以使用iterator标签进行迭代输出。generator标签常见的属性如下:

Ø count属性:该属性用来指定所生成集合中元素的总数。

Ø separator属性:该属性用来指定分隔符。

Ø converter属性:该属性指定了一个转换器,该转换器负责将集合中的每个字符串转换成

对象。

Ø id属性:如果指定了该属性,则新生成的集合会以此为名称,被放在pageContext中。

我们来看下面的代码片段:

示例6.10

<s:generator val="'Spring技术宝典,Ajax实战,Struts2权威指南,JSP技术详解,

JavaScript技术大全'" separator="," id="generList"/>

<table border="1" width="320">

<caption>迭代输出由generator标签产生的集合</caption>

<s:iterator value="#attr.generList" id="name" status="st">

<tr>

<td><s:property value="#st.index"/></td>

<td><s:property value="name"/></td>

</tr>

</s:iterator>

</table>

上述代码使用generator标签把一个字符串按逗号进行了分割,并把产生的集合按照指定的“generList”为id保存在pageContext中,接下来使用iterator标签迭代输出generList集合中的元素,运行效果如图6.1.13所示。

图6.1.13 generator标签的应用


本章总结

Ø ActionContext对象。ActionContext(com.opensymphony.xwork.ActionContext)是Action执行时的上下文。我们可以把上下文看作是一个容器,用于存放Action执行时需要使用的对象信息。

Ø StackContext对象。请求参数(Parameter)、会话(Session)、Servlet上下文(ServletContext)等对象,实际上都存储在ActionContext上下文中的StackContext对象中。

Ø ValueStack对象。Struts2会为每一次Action的请求创建与之对应的ValueStack,并将所有Action属性数据存储到ValueStack中,再将ValueStack 暴露给视图页面,这样页面就可以直接访问Action中的属性值。

Ø OGNL即(Object-Graph Navigation Language),是对象图导航语言的缩写,它是一个开源项目,工作在视图层,用来取代页面中的Java脚本,简化数据访问操作。

(1)访问上下文中的数据。ValueStack是OGNL的根,同时由于OGNL上下文中的根对象可以直接访问,所以通过OGNL访问ValueStack中的数据时,不需要使用任何特殊的标记,而访问ActionConext中的其他对象时则需要使用“#”标记。

(2)执行JavaBean方法。OGNL不仅可以自动执行getter方法,而且能够执行JavaBean的其他方法。更重要的是,还能够在执行方法的时候传入参数,OGNL执行的方法可以是静态方法和非静态方法。

Ø Struts 2的标签库

(1)Struts2标签库的分类。我们可以将Struts 2的标签库分成三大类:UI、非UI、ajax标签,其中UI标签又可分为表单 、非表单标签,非UI标签可分为数据访问、逻辑控制标签。

(2)数据访问标签。常见的数据标签主要包含action、include、param 、property、set、text、url、date等。

(3)逻辑控制标签。逻辑控制标签主要用于程序流程的逻辑控制,例如选择、分支、循环等操作,常见的逻辑控制标签主要有五个标签:if 、elseif、 else 、generator 、iterator。


任务实训部分

1:查询管理员

训练技能点

Ø OGNL

Ø property标签

Ø iterator标签

需求说明

在前面章节的任务实训部分,我们实现了管理员的增、删、改、查等功能,现在要求在查询管理员时,使用OGNL和iterator、property等标签显示查询到的管理员列表,并且只显示密码长度小于3的管理员信息。

  关键代码

<s:iterator value="#attr.adminList.{?#this.pwd.length()>3}" id="admin">

<tr>

<td align="center"><s:property value="id"/></td>

<td align="center"><s:property value="name"/></td>

<td align="center"><s:property value="pwd"/></td>

</tr>

</s:iterator>

2:查询图书

训练技能点

Ø OGNL

Ø property标签

Ø iterator标签

需求说明

在前面章节的任务实训部分,我们实现了查询图书的案例,现在要求使用OGNL和iterator、property等标签显示查询到的图书列表,并且设置偶数行的背景色为灰色。

3:查找客户信息

训练技能点

Ø OGNL

Ø 数据访问标签

Ø 控制标签

需求说明

实现输入客户编号时,查找对应的客户是否存在,若不存在,则输出无法查找到此客户的提示;若存在,则进一步显示客户的订单信息。

实现思路

(1) 创建用于描述订单的实体类,命名为Order.java。

public class Order implements Serializable{

//订单Id

private String orderId;

//订单日期

private Date orderDtm;

//订单状态 0:禁用 1:启用

private int state;

//无参构造函数

public Order() {

super();

// TODO Auto-generated constructor stub

}

//有参构造函数

public Order(String orderId, Date orderDtm, int state) {

super();

this.orderId = orderId;

this.orderDtm = orderDtm;

this.state = state;

}

//getter setter省略......

}

(2) 创建用于描述客户的实体类,命名为Cust.java。

public class Cust implements Serializable{

//客户编号

private String custId;

//客户名称

private String custName;

//电话

private String tel;

//订单集合

private List<Order> orders = new ArrayList<Order>();

//无参构造函数

public Cust() {

super();

// TODO Auto-generated constructor stub

}

//有参构造函数

public Cust(String custId, String custName, String tel) {

super();

this.custId = custId;

this.custName = custName;

this.tel = tel;

}

//getter setter省略......

}

(3) 创建用于处理业务逻辑的JavaBean,命名为CustService.java。

public class CustService {

//定义客户列表

private static List<Cust> custList = new ArrayList<Cust>();

//静态构造器,初始化客户和订单信息

static{

try {

//用于格式化日期

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

//创建客户c1

Cust c1 = new Cust("c001", "张三", "110");

Order c1Order1  = new Order("OR001", sdf.parse("2012-01-01"), 0);

Order c1Order2  = new Order("OR002", sdf.parse("2012-01-02"), 0);

Order c1Order3  = new Order("OR003", sdf.parse("2012-01-03"), 1);

//添加订单到c1客户

c1.getOrders().add(c1Order1);

c1.getOrders().add(c1Order2);

c1.getOrders().add(c1Order3);

//创建客户c2

Cust c2 = new Cust("c002", "李四", "114");

Order c2Order1  = new Order("OR004", sdf.parse("2012-01-04"), 0);

Order c2Order2  = new Order("OR005", sdf.parse("2012-01-05"), 0);

Order c2Order3  = new Order("OR006", sdf.parse("2012-01-06"), 1);

//添加订单到c2客户

c2.getOrders().add(c2Order1);

c2.getOrders().add(c2Order2);

c2.getOrders().add(c2Order3);

//创建客户c3

Cust c3 = new Cust("c003", "王五", "119");

Order c3Order1  = new Order("OR007", sdf.parse("2012-01-07"), 0);

Order c3Order2  = new Order("OR008", sdf.parse("2012-01-08"), 0);

Order c3Order3  = new Order("OR009", sdf.parse("2012-01-09"), 1);

//添加订单到c3客户

c3.getOrders().add(c3Order1);

c3.getOrders().add(c3Order2);

c3.getOrders().add(c3Order3);

//把客户添加到List列表中

custList.add(c1);

custList.add(c2);

custList.add(c3);

} catch (ParseException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

//

public static Cust findCustById(String custId){

//循环每个客户

for (Cust cust : custList) {

//循环每个客户

if(cust.getCustId().equals(custId)){

return cust;

}

}

//如果找不到则返回空

return null;

}

//

public static List<Order> getCustOrders(String custId){

//循环每个客户

for (Cust cust : custList) {

//循环每个客户

if(cust.getCustId().equals(custId)){

//返回对应客户的订单

return cust.getOrders();

}

}

//如果找不到则返回空

return null;

}

}

(4) 创建用于处理业务逻辑的控制器Action,命名为CustAction.java。

public class CustAction extends ActionSupport {

//封装用户的id

private String custId;

//查找订单

public String findOrder()throws Exception{

//调用业务层

List<Order> orderList = CustService.getCustOrders(custId);

//将订单放到request中

ServletActionContext.getRequest().setAttribute("orderList", orderList);

//返回input逻辑视图

return SUCCESS;

}

/**

* @return

*/

public String findCust() {

// TODO Auto-generated method stub

//调用业务逻辑

Cust cust = CustService.findCustById(custId);

if(cust!=null){

//将cust存储到session中

ServletActionContext.getRequest().getSession().setAttribute("cust", cust);

}

else{

//否则给msg赋值,准备弹出对话框。

ServletActionContext.getRequest().setAttribute("msg","<script>alert('没有此用户');</script>");

}

//返回input逻辑视图

return SUCCESS;

}

//getter setter方法

public String getCustId() {

return custId;

}

public void setCustId(String custId) {

this.custId = custId;

}

}

(5) 创建Jsp页面,命名为jd1.jsp。

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

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

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title>My JSP 'jd1.jsp' starting page</title>

</head>

<body>

<h2>

<form action="custaction!findCust.action" method="post">

完成客户查找功能:<hr>

客户编号:<input type="text" name="custId"> <br/>

<input type="submit" value="查找">

<!-- 如果找到该用户 -->

<s:if test="#session.cust">

<hr/>

编号:${cust.custId}<br/>

姓名:${cust.custName}<br/>

联系方式:${cust.tel}<br/><a href="custaction!findOrder.action?custId=${cust.custId }">查看订单</a>

<hr/>

</s:if>

<!-- 如果存在订单列表 -->

<s:if test="#request.orderList">

<hr/>

<table border="1">

<tr>

<td>订单编号</td>

<td>订单日期</td>

<td>订单状态</td>

</tr>

<s:iterator id="row" value="#request.orderList">

<tr>

<td>${row.orderId }</td>

<td><s:date name="#row.orderDtm" format="yyyy年MM月dd日"/></td>

<td>${row.state==0?"禁用":"启用" }</td>

</tr>

</s:iterator>

</table>

</s:if>

</form>

</h2>

<!-- 执行msg -->

${msg }

</body>

</html>

(6) 配置Struts.xml文件。

<struts>

<!-- 配置字符集 -->

<constant name="struts.i18n.encoding" value="utf-8"></constant>

<!-- 配置主题 -->

<constant name="struts.ui.theme" value="simple"></constant>

<package name="test" extends="struts-default">

<action name="custaction" class="com.zzzy.web.CustAction">

<result >/jd1.jsp</result>

</action>

</package>

</struts>

(7) 运行jd1.jsp页面,效果如图6.2.1所示。

图6.2.1 运行jd1.jsp

在图6.2.1中输入需要查找的客户编号。

若编号不存在,系统将会显示提示消息。 如图6.2.2所示。

图6.2.2 用户不存在

若编号存在,系统将显示该客户对应的详细信息,如图图6.2.3所示。

图6.2.3 查找客户并显示详细信息

在图6.2.3中单击“查看订单”按钮,系统将显示客户对应的订单信息,如图6.2.4所示。

图6.2.4显示客户的订单信息


巩固练习

一、选择题

1. 以下关于OGNL的说法正确的是()。

A. ActionContext是OGNL的上下文环境

B. ValueStack是OGNL的根

C. StackContext是OGNL的上下文环境

D. ActionContext是OGNL的根

2. 假设session中存在名为uid的属性,通过OGNL访问该属性的代码是()。

A. #uid

E. uid

F. #session.uid

G. ${session.uid}

3. 关于“#session.users.{?#this.age>20}”的OGNL代码所表示的意思是()。

A. 从users集合中取出第一个年龄大于20的对象

H. 从users集合中取出所有年龄大于20的对象

I. 从users集合中取出最后一个年龄大于20的对象

J. 该代码有语法错误

4. 假设页面中存在这样一行代码“<s:property />”,则下面说法正确的是()。

A. 编译错误

K. 页面不显示任何内容

L. 输出ValueStack中最上面的对象

M. 以上说法都不正确

5. 以下()不属于Struts 2的数据访问标签。

A. set

B. date

C. text

D. textfield

Struts2标签库和OGNL相关推荐

  1. java struts2标签库 常用标签

    基本概述 对于一个MVC框架而言,重点是实现两部分:业务逻辑控制器部分和视图页面部分.Struts2作为一个优秀的MVC框架,也把重点放在了这两部分上.控制器主要由Action来提供支持,而视图则是由 ...

  2. Struts2标签库常用标签

    Struts2标签库常用标签 基本概述 对于一个MVC框架而言,重点是实现两部分:业务逻辑控制器部分和视图页面部分.Struts2作为一个优秀的MVC框架,也把重点放在了这两部分上.控制器主要由Act ...

  3. Struts2 标签库

    Struts 2标签简介 Struts 标签分类 使用Struts标签库 OGNL OGNL集合运算 OGNL表达式对静态属性的访问 控制标签 if/else if/else iterator gen ...

  4. Struts2标签库整理【完整】

    转自:https://blog.csdn.net/chen_zw/article/details/8161230   Struts2标签库提供了主题.模板支持,极大地简化了视图页面的编写,而且,str ...

  5. Struts2标签库常用标签(转)

    struts2标签讲解 要使用Struts2的标签,只需要在JSP页面添加如下一行定义即可:<%@ taglib prefix="s" uri="/struts-t ...

  6. servlet 和 struts2 同时使用 以及 使用struts2标签库时报错

    做网页的时候 想让 servlet 和 struts 都有效. 但是在过滤的时候出了点问题: 就是 过滤器的*.action 的时候 struts 标签库失效的问题 我觉得以下是个不错的 解决方案: ...

  7. 框架神器:struts2标签库

    楼下的同学讲到了框架struts2,那么我们就提前预习一下功课,继续学习标签的运用,我表示JSP标签学得也是特别的萌啊. 下面就介绍每个标签的具体应用实例说明:按字母排列 A: 1. <s:a ...

  8. Struts2 标签库讲解

    要使用Struts2的标签,只需要在JSP页面添加如下一行定义即可: <%@ taglib prefix="s" uri="/struts-tags"%& ...

  9. Struts2标签库

    这是个音乐播放列表 1.queryMusic.jsp <%@ page language="java" import="java.util.*" page ...

最新文章

  1. cvelist.jsp
  2. FreeMarker插件的安装
  3. 使用Keras进行深度学习:(三)使用text-CNN处理自然语言(上)
  4. 【译】来看看WebWindow,一个跨平台的.NET Core webview 库
  5. MongoDB嵌套数组,多维数组查询
  6. 哈希表 - (代码、分析 )
  7. springboot+hbase 集成
  8. 杨森翔的书法:立马【五绝】
  9. 天呐,你竟然还在用 try–catch-finally
  10. php封隔器座封原理,各种封隔器的特点与坐封原理.ppt
  11. 微型计算机配置单8000,计算机公共基础知识8000题库答案解析
  12. Java项目:小区物业管理系统(java+Springboot+ssm+mysql+maven+jsp)
  13. 关于RS-485总线,这篇很详细
  14. 3dMAX安装异常 - 安装程序无法确定您当前的图形卡。这通常是由于通过远程桌面进行安装,或使用虚拟化软件所致。
  15. 虚拟机上的Linux系统如何联网?
  16. 形式逻辑(03)联言判断 和 推理
  17. 20180814 实习小结关于前端
  18. Who Wants to Be a Millionaire?
  19. 普林斯顿教授:中国学生的功利心妨碍了他们的长远发展
  20. 公民身份号码 校验码 检证程序

热门文章

  1. 深入理解Memory Order
  2. Leet Code OJ 226. Invert Binary Tree [Difficulty: Easy]
  3. spring + maven项目 互相依赖的小坑
  4. 03.body_search
  5. 深入浅出理解 Variable used in lambda expression should be final or effectively final
  6. 【测试点分析】1104 Sum of Number Segments (20 分)
  7. 详解图示+例题演练——BF算法+KMP算法基本原理
  8. python没有pil模块_Python离线安装PIL 模块的方法
  9. 2d的公式_西师大版六年级数学上册全册必背公式+高清版电子课文,收藏预习
  10. js reduce实现中间件_Laravel中间件实现原理及实例分析