• 沒有找到結果。

第一部分:

N/A
N/A
Protected

Academic year: 2022

Share "第一部分:"

Copied!
418
0
0

加載中.... (立即查看全文)

全文

(1)

第一部分:Strust2 快速入门

随着计算机技术的不断发展,计算机软件变得越来越复杂,花费在软件开发上的时间越 来越多,然而程序代码的可读性,可维护性却不断下降。就拿 Java Web 开发来说,现在网 络流行的开源框架就有好几十种,然而这些开源框架都或多或少存在着一些缺陷。如何从这 些开源框架中选择一种最优的开发框架确实是一个难题。

在本部分中,我们首先介绍 Web 开发技术的发展历程,以 Web 开发事实标准的 MVC 模式为基础引入 Strust2 框架,简要介绍了 Strust2 的基本特性及其与其它 Web 开发框架的比 较,最后回顾了其发展历史,展望了其未来的发展趋势。

第一部分主要内容如下:

 第 1 章向读者展示了当前基于 MVC 架构的流行的 J2EE 框架的基本原理,同时我 们展示了作为其代表的 Strust2 的所有特性,并将其与若干流行的开源框架作了详 细的比较,让读者对 Strust2 的优异性有充分的认识。

 第 2 章则详细的介绍了如何编写一个简单的 Strust2 应用程序,同时读者将学习到 Strust2 的一些高级特性的使用。

(2)

第二部分:Struts2 框架核心

本部分首先向读者展示了 Struts2 最核心内容:控制器(Action)、拦截器(Interceptor),

以及返回类型(Result)。这些是 Struts2 最基础的概念,也是理解 Struts2 架构的关键所在。

此外,本部分还介绍了 Struts2 框架中的一些其它核心技术,包括内建的标签库,对表 达式语言的支持,对多视图的支持以及 Web 应用经常要解决的数据持久化问题。

读者学习完本部分之后,就能采用 Struts2 框架搭建最基本的 Web 应用,解决最基 本的页面视图设计,业务逻辑模型处理以及后台数据持久化。

第二部分主要内容如下:

 第 3 章从 Struts2 的源代码入手,为读者剖析控制器中的一些基本概念,并详细 介绍了如何使用两种不同的方法构建自己的控制器(Action)。

 第 4 章同样从 Struts2 的源代码入手,介绍了 Struts2 框架实现解耦合的拦截器

(Interceptor)技术,详细介绍了如何构建适合的拦截器来满足用户的需要。

 第 5 章从一个常见的误解入手,向读者解释返回类型(Result)的含义,读者 在这里不仅可以详细的了解 Struts2 框架定义的各种返回类型,同时还可以掌握 自定义返回类型的方法。

 第 6 章向读者介绍了 Struts2 为支持多视图技术提供的一套标签库,通过这一节 的学习读者可以熟悉 Struts2 标签库中的各种类型的标签的使用方法。

 第 7 章介绍的是视图层里的控制技术,通过学习表达式语言的编写,读者可以 摒弃 JSP 中复杂的代码,从而大大减小编写视图的代码量。

 第 8 章多视图技术是 Struts2 框架的一大亮点,通过这一章节的学习,读者可以 学习到如何使用这项技术,来定制自己所需要的视图,为自己的应用系统提供 更丰富的功能。

 第 9 章向读者展示了如何使用 Hibernate 控制框架模型层来完成对数据持久化 的需求。通过这一章的学习,读者可以学习到如何使用数据库为 Web 应用持久 化数据。

带格式的: 字体: 小一

带格式的: 字体: 11 磅

带格式的: 缩进: 首行缩进: 2 字

(3)

第三部分:Struts2 高级特性

本部分将在第二部分 Struts2 框架核心的基础之上,学习应用 Struts2 的高级特性去解决 Web 应用中所经常遇到的一些基本问题,比如数据校验、类型转换和国际化等高级话题。

然后还向读者展示如何调试基于 Struts2 框架的 Web 应用,并采用调试手段展示了 Struts2 框架核心的内部结构和运行原理。

此外,我们简要介绍了三个能够与 Struts2 很好整合的开源框架:SiteMesh、Quartz 和 Acegi。最后向读者详细讲解了 Struts2 测试的相关内容。通过这一部分的学习,相信读者对 Struts2 的理解将提高一个层次。

第三部分主要内容如下:

 第 10 章讨论的数据验证是在 Web 应用程序开发过程中经常要使用的技术,这一章 节的例子的详细构建过程,是编写校验器的优秀参考。

 第 11 章向读者展示了 Struts2 框架优秀的特性类型转换,结合框架源代码的分析,

读者不仅可以了解 Struts2 类型转换进行的过程,更可以参照章节给出的例子,编 写自己的类型转换器。

 第 12 章国际化将向读者展示如何为一个 Struts2 应用程序添加多语言的支持,并且 讨论了国际化的方方面面,在全球化日益明显的今天,这一点也是不容忽视的。

 第 13 章调试是十分实用的章节,在简单回顾了如何调试 Java 应用程序之后,通过 一个例子向读者展示了如何调试基于 Struts2 框架的 Web 应用程序。

 第 14 章深入 Struts2 框架的底层代码,通过“调试”这一利器,层层的抽丝剥茧,

为读者展示 Struts2 的内部结构和运行层次,同时向读者阐述了“反转控制”这一 设计模式在 Struts2 架构中的使用。

 第 15 章简单介绍了能够与 Struts2 配合发挥特殊作用的其他开源框架,向读者展示 了 SiteMesh、Quartz、Acegi 开源框架与 Struts2 整合应用的概况。

 第 16 章主要介绍了 JUnit4 的特性以及使用方法,详细讲解了在 Eclipse 下使用 JUnit4 的步骤,通过使用 JUnit4 可以更高效的完成测试工作。

(4)

第四部分:Struts2 综合实践

本部分从 Struts2 框架核心和高级特性的学习转入到综合实战,通过两个完整的中型应 用迭代开发过程,让读者对使用 Struts2 框架进行 Web 应用开发有一个直观的感受,同时进 一步加强对 Struts2 的整体认识。

在这两个 Web 应用的开发过程中,依据 XP 编程思想,将整个开发过程分割成多个开 发迭代过程,按照需求分析得来的系统用例来逐步实现其具体功能。读者在整个开发过程中 能够很好的体会到基本的软件工程思想和 XP 编程的应用实践理念。

 第 17 章向读者展示了“网络商店系统”的构建的全过程,迭代实现游客浏览商品,

用户管理,购物车管理以及后台管理员等功能。读者将了解到如何使用所学的 Struts2 开发一个完整的工程。

 第 18 章则利用了 Struts2 提供的一个上传文件的拦截栈,构建了一个“网络文件管 理系统”,迭代实现上传、下载、删除文件,用户管理,消息与备忘录管理,后台 管理员等功能。和上一章类似,在本章中读者可以了解整个系统构建的全过程。

(5)

目 录

第一篇 Struts2 快速入门

第一章 Struts2 概述

1.1 Struts2 的起源和背景

1.1.1 Struts1 简介及存在的问题 1.1.2 WebWork 简介

1.1.3 Struts2 起源 1.2 MVC 思想概述

1.2.1 Model1 和 Model2 1.2.2 MVC 思想及其优势 1.2.3 常用的 MVC 框架 1.3 Struts2 体系介绍

1.3.1 Struts2 的大致架构 1.3.2 Struts2 的配置文件 1.3.3 Strut2 的标签库 1.3.4 Struts2 的控制器组件 1.4 本章小结

第二章 第一个 Struts2 应用

2.1 Struts2 开发环境配置

2.1.1 JDK1.5.10 和 Tomcat 的安装与配置 2.1.1 MyEclipse 的安装和配置

2.1.3 Struts2 的安装 2.2 创建配置文件

2.2.1 配置 web.xml 文件 2.2.2 配置 Struts2.xml 文件 2.2.3 配置 Struts2.properties 文件

2.3 第一个 Action

2.3.1 创建 helloworld.action 2.3.2 在 struts.xml 中配置 Action 2.3.3 创建视图 hello.jsp

2.3.4 测试 Action 2.4 体会 Struts2 更高级功能

2.4.1 处理输入 2.4.2 执行结果 2.4.3 拦截器 2.5 小结

(6)

第二篇 Struts2 框架核心

第三章 Action

3.1 Action 简介 3.1.1 返回类型 3.1.2 execute()方法 3.2 Action 接口

3.3 ActionSupport 基类 3.4 Action 实例

3.4.1 实现 Action 接口的实例 3.4.2 实现 ActionSupport 基类的实例 3.5 在 Action 中实现基本校验

3.5.1 使用 Action 的 execute()方法

3.5.2 使用 ActionSupport 的 validate()方法 3.5.3 使用注释实现校验

3.5 小结

第四章 Interceptor

4.1 Interceptor 基础

4.1.1 Interceptor 何时调用 4.1.1 Interceptor 接口 4.1.2 Interceptor 相关类 4.2 使用预定义的 Interceptor

4.2.1 预定义 Interceptor 类 4.2.2 LoggingInterceptor 实例 4.3 使用自定义的 Interceptor

4.3.1 自定义 Interceptor 的配置 4.3.2 实现自己的 Interceptor 4.4 Interceptor 应用实例

4.4.1 execAndWait 拦截器源码分析 4.4.2 项目概述

4.4.3 JAVA 控制文件 4.4.4 页面文件 4.4.5 配置文件 4.4.6 运行 4.5 小结

第五章 Result

5.1 自定义的 Result

5.1.1 实现自定义的 Result 5.1.2 配置自己的 Result

(7)

5.1.3 运行测试 Result 5.2 常用的 Result

5.2.1 Dispatcher 5.2.2 Redirect 5.2.3 Chain 5.3 其他的 Result 5.4 小结

第六章 标签

6.1 标签介绍 6.2 自定义标签

6.2.1 标签的实现 6.2.2 标签的配置 6.2.3 运行 6.3 Struts2 标签概览 6.4 非 UI 标签

6.4.1 数据标签 6.4.2 控制标签 6.4.3 其他标签 6.5 UI 标签

6.5.1 通用属性 6.5.2 简单 UI 标签 6.5.3 高级 UI 标签 6.6 小结

第七章 表达式语言 OGNL

7.1 OGNL 的基本特性 7.1.1 常量的声明 7.1.2 方法调用 7.1.3 变量引用 7.2 操作集合

7.2.1 操作列表 Lists 7.2.2 操作映射 Maps 7.2.3 操作数组 Array 7.2.4 集合操作 7.3 OGNL 的高级特性

7.3.1 类型转换 7.3.2 与值栈的联系 7.3.3 lamu da 表达式 7.3.4 Java 和 OGNL 的比较 7.4 在 JSP 中使用 OGNL

7.4.1 项目概述

(8)

7.4.2 工程代码编写 7.4.3 运行

7.5 小结

第八章 多视图

8.1 Velocity

8.1.1 Velocity 简介 8.1.2 语法

8.1.3 Velocity 实例分析 8.2 FreeMarker

8.2.1 FreeMarker 简介 8.2.2 语法

8.2.3 FreeMarker 实例分析

8.2.4 FreeMarker 和 Velocity 的比较 8.3 JasperReport

8.3.1 JasperReport 介绍 8.3.2 JasperReport 实例分析 8.4 小结

第九章 数据持久化——使用 HIbernate

9.1 数据持久化与 Hibernate 基础 9.1.1 数据持久化基础 9.1.2 Hibernate 基础 9.2 Hibernate 简单应用 9.3 Hibernate 核心

9.3.1 Hibernate 的核心接口 9.3.2 Hibernate 的配置文件 9.3.3 Hibernate 的对象映射关系 9.3.4 Hibernate 的检索方式 9.4 Hibernate 实例

9.5 小结

第十章 校验框架

10.1 使用 Struts2 自带的校验器 10.1.1 配置拦截器 10.1.2 配置校验器 10.1.3 自带校验器实例 10.2 使用自定义校验器

10.2.1 创建自定义校验器 10.2 2 自定义校验器注册 10.2.3 自定义校验器实例 10.3 小结

(9)

第十一章 类型转换

11.1 为什么需要类型转换

11.1.1 没有类型转换的实例 11.1.2 类型转换带来的好处 11.2 Struts2 自带的转换器

11.2.1 自带转换器的类型 11.2.2 转换器的源码分析 11.3 自定义转换器

11.3.1 编写转换器类 11.3.2 配置

11.4 高级类型转换器 11.4.1 空值属性处理 11.4.2 类型转换错误处理 11.5 小结

第十二章 国际化

12.1 国际化基础 12.2 Struts2 与国际化

12.2.1 Struts2 对国际化的支持 12.2.2 资源包相关

12.3.3 国际信息获取 12.3 Struts2 国际化实现

12.3.1 初始页面国际化 12.3.2 Action 的国际化 12.3.3 校验的国际化 12.4 国际化实例

12.4.1 项目配置与开发 12.4.2 结果测试 12.5 小结

第十三章 Struts2 调试

13.1 MyEclipse 中的 Java 程序调试 13.1.1 调试配置

13.1.2 调试视图 13.1.3 控制程序执行 13.2 调试 Struts2 程序

13.2.1 调试入门

13.2.2 连接 Struts2 的源代码 13.3 Struts2 调试应用

13.3.1 实例的概述 13.3.2 实例工程的源文件

(10)

13.3.3 调试工程 13.4 小结

第十四章 Struts2 原理探究

14.1 控制反转

14.1.1 什么是控制反转 14.1.2 控制反转的设计模式 14.1.3 Struts2 中的控制反转 14.2 源码探究

14.2.1 Struts2 启动 14.2.2 Action 处理过程 14.2.3 Interceptor 工作机制 14.2.4 ActionContext 14.3 小结

第十五章 Struts2 与其他网络框架整合

15.1 与 SiteMesh 整合 15.1.1 SiteMesh 简介 15.1.2 SiteMesh 的安装 15.1.3 SiteMesh 应用实例 15.2 Quartz 作业调度

15.2.1 Quartz 简介 15.2.2 作业调度简介 15.2.3 Quartz 应用实例 15.3 Acegi-Security 用户管理

15.3.1 Acegi-Security 简介 15.3.2 Acegi 认证过程 15.3.3 保护 Web 应用 15.4 小结

第十六章 Struts2 测试

16.1 软件测试基础 16.2 JUnit 基础 16.3 JUnit 的使用

16.3.1 JUnit 的安装 16.3.2 开始使用 JUnit

16.3.3 在 Eclipse 中使用 JUnit 16.4 JUnit 高级

16.4.1 类别级的 fixtrue 16.4.2 限时测试

(11)

16.4.3 异常测试 16.4.4 忽略测试 16.4.5 测试运行器 16.4.6 测试套件 16.4.7 参数化测试 16.5 小结

第十七章 网络商店实例编程

17.1 项目概述

17.1.1 网络商店概括 17.1.2 网络商店的需求分析 17.1.3 网络商店的业务建摸 17.1.4 迭代式开发介绍 17.1.5 项目功能模块分割 17.2 迭代一,游客浏览商品

17.2.1 本阶段迭代的目标 17.2.2 本阶段页面概述

17.2.3 商品的数据模型和数据库设计 17.2.4 实现步骤

17.3 迭代二,用户管理

17.3.1 本阶段迭代的目标 17.3.2 本阶段页面概述

17.3.3 用户数据模型和数据库设计 17.3.4 实现步骤

17.4 迭代三,购物车管理 17.3.1 本阶段迭代的目标 17.3.2 本阶段页面概述

17.3.3 购物车的功能需求和设计实现 17.3.4 实现步骤

17.5 最终迭代,后台管理员功能 17.3.1 本阶段迭代的目标 17.3.2 本阶段页面概述 17.3.3 实现步骤 17.6 小结

第十八章 网络文件管理系统实例编程

18.1 项目概述

18.1.1 网络文件管理系统概括 18.1.2 网络文件管理系统需求分析 18.1.3 网络文件管理系统业务建摸 18.1.4 项目功能模块分割

18.2 迭代一,实现上传、下载、删除文件 17.2.1 本阶段迭代的目标

(12)

17.2.2 本阶段页面概述 17.2.3 文件的数据模型 17.2.4 实现步骤 18.3 迭代二,添加用户管理

17.3.1 本阶段迭代的目标 17.3.2 本阶段页面概述

17.3.3 用户以及用户空间数据模型 17.3.4 实现步骤

18.4 迭代三,添加消息处理,备忘录管理 17.3.1 本阶段迭代的目标

17.3.2 本阶段页面概述

17.3.3 消息和备忘录的数据模型 17.3.4 实现步骤

18.5 最终迭代,添加管理员的数据模型 17.3.1 本阶段迭代的目标

17.3.2 本阶段页面概述 17.3.3 管理员的数据模型 17.3.4 实现步骤

18.6 小结

(13)

第二章 第一个 Struts2 应用

本章将通过一个简单的例子向读者展示 Struts2 的魅力,虽然只是惊鸿一瞥,但是通过 这个例子读者将初步掌握 Struts2 的开发环境配置,以及基于 Struts2 的 web 应用开发的基本 方法,还为这个例子增加一些高级特性――拦截器。在了解了这些特性之后希望读者能对 Struts2 的优点有进一步的了解。

在这章中,将从最基本的工具安装开始说起,包括开发环境的建立和配置,如 TOMCAT,

JDK 的安装配置,Eclipse 的安装配置以及使用。接下就会了解 Struts2 的一些 jar 文件,以 及怎样配置成功一个 Struts2 的项目,怎样添加 jar 包等等知识。有了上面的基础之后就来欣 赏一个 Struts2 的基本 Action 示例,通过一个完整的 Action 的例子为读者介绍 Action 的基本 方面,最后通过一个高级输入特性向读者展示 Struts2 的特性,而且在本章后面读者可以了 解到一个最简单的自定义拦截器的实现方式。

2.1 Struts2 开发环境配置

本书中进行 Struts2 开发的环境是 JDK1.5.10+Tomcat5.5.20+Struts2.0.9。这三款软件可以 到 Sun & Open Symphony & Apache 站点进行下载。在调试和运行书中所提供的代码时,推 荐使用与本书相同的配置进行开发,因为在 Struts2 的开发环境中,并不一定是越是新的就 越好。而且新的版本可能会存在与旧的版本以及其它软件版本环境之间的兼容性问题。

2.1.1 JDK1.5.10 和 Tomcat 的安装与配置

JDK1.5.10 的安装与配置

1. 从 SUN 的官方网站上下载 JDK1.5.10 for windows installer 并双击安装,如图 2-1。

图 2-1 安装初始画面

2. 一路按提示下去就可以正确的安装,安装完毕之后就是一些环境变量的设置:

(14)

 在本例中设置 JAVA_HOME=D:\java\jdk-1.5.10。

 将 JAVA_HOME\bin 路径添加到环境变量 path。

读者首先新建一个变量,命名为 JAVA_HOME,填入相应路径。再在环境变量 Path 中 添加相应路径即可。

3. 测试,在命令行模式下输入 javac 命令,如果显示相应的选项则表示安装成功。

注意:由于 NETBEANS IDE 是和 JDK 捆绑在一起的,接下来安装 NETBEANS IDE,但是 不用担心,如果不喜欢的话,安装完毕之后卸载即可。

TOMCAT 容器的安装和配置

进行 Java Web 开发的时候,编写的服务器端程序如(JSP | Servlet),其本身并不是可执行 的文件,需要一个环境来运行它。

在 Struts2 的开发过程中,需要一个容器环境来试运行 Struts2 应用,这样的容器有很多,

比如 Resin,Weblogic,JBoss 以及 TOMCAT。在这里推荐使用 TOMCAT,首先因为它是开 源的;其次,其配置也是最简单的,当然在轻量级的应用中它也是最常用和最受欢迎的。

Apache Tomcat 的下载地址:http://tomcat.apache.org/

Tomcat 在 Windows 下的安装是十分简单的,读者只需要从其官方站点下载其自解压安 装版本 For Windows Installer,一路往下点击安装即可。

安装开始的界面如图 2-2 所示:

图 2-2 安装的初始画面:

在提示选择安装的组件的时候,建议选择完全安装并勾选所有的组件,以避免在后期的 开发调试过程中遇到不必要的麻烦,如图 2-3。

(15)

图 2-3 组件选择界面

接下来的画面是提示对 TOMCAT 的管理进行一些最基本的配置,如图 2-4

图 2-4 管理员密码设置画面

此处设置 TOMCAT 服务的端口号,一般设为 8080(缺省值),TOMCAT 管理员账号和密 码,请记住自己的设置,因为在后来的管理和配置过程中,TOMCAT 会要求输入这个账号 和密码。

然后选择 JDK 的位置,请正确配置 JDK 的位置,否则可能造成 TOMCAT 无法启动,

(16)

如图 2-5 所示。

图 2-5 JDK 的配置页面

继续点击直到安装完成,安装完成后设置好 TOMCAT_HOME 和 CATALINA_HOME 这 两个环境变量就可以了,在本例中应该这样配置:

TOMCAT_HOME= D:\Program Files\Apache Foundation\Tomcat5.5 CATALINA_HOME== D:\Program Files\Apache Foundation\Tomcat5.5

配置完毕之后,在浏览器的地址栏里面输入 http://localhost:8080/如果出现下面的一张图,

TOMCAT 已经可以正常工作了,成功页面如图 2-6。

图 2-6 登录成功页面

(17)

2.1.2 MyEclipse 的安装和配置

在这里向大家介绍一个工具,便于开发。MyEclipse 相信大家都很熟悉的,它是 Eclipse 的一个插件,现在来看看安装与配置。

大家先上网下载 Eclipse 压缩包和 MyEclipse 插件。Eclipse 解压就可以用了,而 MyEclipse 是要安装的。在这里提醒一句,Eclipse 是可以汉化,至于怎么汉化,大家上网可以下载一 个汉化的插件,覆盖就可以了。笔者在这里用的版本是 Eclipse3.2.0。把 Eclipse 压缩包解压 到自己喜欢的目录下,然后再把汉化包覆盖一下,这样可以完全汉化 MyEclipse。下面是 MyEclipse 安装的初始画面,如图 2-7:

图 2-7 安装初始界面

然后按照向导一路安装下去,在这提醒一句,当出现下面这个画面时,如图 2-8:

图 2-8 选择 Eclipse 的路径

(18)

这里选择的是刚才 Eclipse 解压到的路径。这样就完成安装了,再打开 Eclipse 就可以看 到如图 2-9 的画面。

图 2-9 安装好的 Eclipse

在圆圈处是配置 Tomcat 和 JDK 的图表标示,点击之后会出现如如图 2-10 的画面,:

图 2-10 Tomcat 配置界面

(19)

在红色标记的地方点击之后会出现右边界面,在箭头处选择 Tomcat 安装的路径,在上 面界面中要选择 Enable,一切完成后,进入 JDK 配置,还是在红色标记处,选择 JDK,会 弹出一个下面画面,选择 Add,如图 2-11:

图 2-11 JDK 配置界面 在图 2-11 中选选择 JDK 路径就可以了。

现在可以测试一下 Tomcat 有没有配置成功,点击先前的配置图标启动 Tomcat,如图 2-12 所示:

图 2-12 启动 Tomcat

这样 Tomcat 配置成功之后,会在控制台见到这样的画面,如图 2-13:

(20)

图 2-13 登陆成功界面

红色标记的地方表示 Tomcat 配置成功,如果有错误,也会在控制台展示哪里出现了错 误。

2.1.3 Struts2 的安装

到 Struts 的官方网站上去下载 Struts2.0.9 压缩包,将其解压到适当的文件夹。解压之后 的目录下有下面的一些文件夹:

 apps —存放的是一些 Struts2 自带的样例,是可以在 Tomca 下直接部署的 twar 包。

 docs -里面存放的是一些文档,有各种详细的说明,读者可以仔细看看,很有帮 助。不过最新的文档还是上官方网的在线文档

 lib -里面存放着要用到的.jar 文件,不过不是很全面,许多需要读者自己下载。

 src —存放是一些有用资源文件。

 j4 —存放的是一些 Struts2 自带的样例,但它们都没有编译,读者要用的话直 接部署是没用的。

在开发最经常用到的是 lib 文件夹下面的一些.jar 文件。一般 Struts2 项目必须的.jar 文件 如下:

struts2-core-2.0.9.jar , ognl-2.6.11.jar , freemarker-2.3.8.jar , xwork-2.0.4.jar , tiles-jsp-2.0.4.jar,commons-logging-1.0.4.jar。

本书中使用 Eclipse 作为开发工具,下面来看看在 Eclipse 中怎么添加 Struts2 项目。

首先打开 Eclipse,新建一个 web project 项目,在包资源管理器视图下,在这个项目点 击右键,选择构建路径下的配置构建路径,如图 2-14 所示:

(21)

图 2-14 构建路径的选择 将会出现如图 2-15 所示的界面:

图 2-15 添加外部的 jar

点击箭头所指的选项,把 lib 目录下的 dafault 文件夹中所有的 jar 文件全部导入。添加 jar 包后将会出现如图 2-16 所示的界面:

图 2-16 包资源管理器视图下的目录

最后,还要将刚刚导入的 jar 文件拷贝到新建的工程的\WebRoot\WEB-INF\lib 目录下面,

拷贝完成后刷新导航器视图将可以看到如图 2-17 的界面:

(22)

图 2-17 导航器的 lib 目录

后面就可以在 Eclipse 项目里面通过添加一些文件来配置的项目了。下面将会进入第一 个 Struts2 应用的开发。

2.2 创建配置文件

配置文件在某种意义上说是 Web 应用的关键,在开发过程中遇到的很多莫名其妙的错 误可能就来源于配置文件的设置。作为一个流行的 Web 框架,Struts2 有很多的配置文件,

这里先介绍几个最基本的。web.xml 是所有 Web 应用不可或缺的配置文件,Struts2 也不例 外。作为一个支持很多高级特性的 Web 框架 Struts2 也有其特有的配置文件,例如 struts.xml 和 struts.properties,下面将逐个讲述在第一个 Struts2 应用里中这些配置文件的详细内容。

Struts2 项目必须的配置文件:web.xml,struts.xml。Struts2.properties 这个文件是在有些 项目才需要配置的。下面来看看具体怎么去配置。

2.2.1 配置 web.xml 文件

在编写 web.xml 中至少要包含以下两部分的内容:定义<filter>的节点,定义<filter>所 映射 URL 模式。还可以定义一个项目默认访问的首页。

在下面的例子中,<filter>节点对应的类为 org.apache.struts2.dispatcher.FilterDispatcher;

其 URL 模式为*,即匹配所有的 URL 模式;默认的首页为 index.html。这是可应用于 Struts2 的 web.xml 的最基本形式了。当然,也可以在 web.xml 中增加更多的其它的配置项,比如增 加对 spring 等其它开源项目的支持。

web.xml 是任何 Web 应用都不能少的配置文件,它存放的路径是在 WebRoot 这个目录下 的,千万不要存放错位置。

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_9" version="2.4"

xmlns="http://java.sun.com/xml/ns/j2ee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<!-- 在 Tomcat 中对项目的描述部分 -->

<display-name>Struts 2 </display-name>

<!-- 在部署之前,先清除环境 -->

<filter>

<filter-name>struts-cleanup</filter-name>

<filter-class>

org.apache.struts2.dispatcher.ActionContextCleanUp

(23)

</filter-class>

</filter>

<filter-mapping>

<filter-name>struts-cleanup</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<!-- 部署 filter 的名称以及对应的类 -->

<filter>

<filter-name>struts2</filter-name>

<filter-class>

org.apache.struts2.dispatcher.FilterDispatcher </filter-class>

</filter>

<!-- 配置 filter 对应的 url 模式 -->

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<!-- 配置这个项目对应的默认的首页 -->

<welcome-file-list>

<welcome-file>index.html</welcome-file>

</welcome-file-list>

</web-app>

第一句代码是为了标识文件的编码风格,形成统一的编码标准,可以避免乱码现象。接 下来就是 DTD 的配置,关于 DTD 的相关知识不再介绍。文件前面两个节点的配置,在上 面没有提到,其实它的配置并不是必须的,只是一种好的风格。作用就是,在部署这个项目 之前先清除以前在 Tomcat 中遗留的一些干扰信息,这样就不会对新的项目部署产生干扰。

整个 web.xml 就是在项目中要先配置一个 FilterDispatcher,拦截类似于.jsp、.vm 的请求,然 后寻求相应的 Action 去执行。当然还可以使用 Struts2 提供的标签,其他的框架为了使用标 签就是要单独配置一个标签的节点,譬如 WebWork,但是 Struts2 为我们提供了方便,进行 了默认的配置。其实大多数 web 应用的 web.xml 文件都是按照这样配置。

注意:在做上传文件的时候,一定要在 web.xml 中增加 ActionContextCleanUp 这个 filter,

如果不增加,会发生第一次上传取不到文件的情况。

2.2.2 配置 Struts2.xml 文件

作为 Struts2 最核心的配置文件,Struts2 所有高级特性的相关特性都在这里进行定义,

包括 Action,Interceptor,Velocity 视图等等。下面的 Struts2.xml 所示的是这一章后面实例 的所有配置,有<Action>结点是对 Struts2 的 Action 的配置,有<Interceptor>结点是对 Struts2 拦截器的配置,还有 Velocity 视图模板结点的配置。

Struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

(24)

<struts>

<constant name="struts.devMode" value="true" />

<!-- 在包中导入 Struts 自带的配置文件 struts-default.xml -->

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

<!-- 配置自己定义的拦截器 -->

<interceptors>

<interceptor name="greeting" class="example.GreetingInterceptor"></interceptor>

</interceptors>

<!-- 配置系统自带的拦截器栈 -->

<default-interceptor-ref name="completeStack"></default-interceptor-ref>

<!-- 配置自己定义的 Action -->

<action name="helloworld" class=" example.helloworld">

<result name="success">hello.jsp</result>

<result name="input">name.jsp</result></action>

<action name="greeting" class=" example.GreetingAction">

<result name="success" type="velocity">ex01-result.vm</result>

<!-- 显示使用自己定义的拦截器 -->

<interceptor-ref name="greeting"></interceptor-ref>

</action>

</package>

</xwork>

第一句代码的功能也是为了统一的字符编码,和 web.xml 采用一样的编码风格。接下也 是对应的 DTD 的说明。<constant name="struts.devMode" value="true" />这个标签是表示现在 采用的是否为 struts2 开发模式,在开发模式下会报错,如果是在开发阶段值就要设置为

“true”,便于开发,如果是最终完成后就设置为“false”。

在 struts.xml 文件中,需要配置拦截器,以及自己添加的 Action,是在一个 package 标 签之间配置的,通过 extends 属性把 Struts 自带的配置文件 struts-default.xml 导入。上面关于 自己定义的拦截器配置是后面的例子要用到的,以及第二个 greeting Action 也是的。在 helloworld 这个例子中,默认的 Struts2 文件一定要导入,其次就是配置 helloworld Action。

在页面上会提交数据给 Action,然后 Struts2 就会根据给的 Action 名字,就到 struts.xml 文件 中查找,找到 Action 对应的类,最后就给相应的类进行处理。还可以根据执行的不同返回 结果,选择不同的返回页面。

在这个配置文件里,重点是声明自定义的拦截器,通过 interceptor 标签的声明告诉系统 自定义的拦截器。

注意:struts.xml 和 web.xml 处于不同的目录下。struts.xml 存放在\WebRoot\WEB-INF\classes 下,而 web.xml 存放在\WebRoot 目录下,大家切记。

2.2.3 配置 Struts2.properties 文件

Struts2.properties 是用来定义 application 范围的设置,以及那些能够改变框架功能的配 置参数。虽然它不是必须的,当打算改变其默认情况时,必须修改对应的部分。

由于应用很简单所以这个配置文件只有一句代码:

struts.properties

Struts.tag.altSyntax=true

这 行 代 码 是 告 诉 Struts2 将 使 用 新 的 标 签 语 法 。 这 个 文 件 是 存 放 在

(25)

\WebRoot\WEB-INF\classes 下的,千万不要放错了。所以要用 Eclipse 来开发,这样可以避 免要在不同的目录下切换。

这样,基本配置算是完成了。下面具体来看 Action 了。

2.3 第一个 Action

这个 Action 就是在浏览器地址栏输入指定的 URL 之后,将会产生出现一个拥有问候信 息”Hello World”的页面。

2.3.1 创建 helloworld.action

在 Struts2 里面所有的控制部分都是由 Action 来完成的,虽然可以把这句问候信息直接 加到 JSP 页面里面,但是为了展示 Struts2 的魅力,在这里暂且大材小用,用 Action 来完成 这个功能。

这段代码要完成的功能很简单,当浏览器向服务端请求这个 Action 的时候,服务端启 动编译并运行这个 Action,在这个页面里面设置了一个 message 字段。而这个字段将被后续 的页面使用到。设置完 Action 的 message 字段之后,服务端简单的把请求转向 hello.jsp 页面。

这个 Action 存放的目录是:\ww\src\example 下。

helloworld.java package example;

import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")

public class helloworld extends ActionSupport{

public String message;

public String execute(){

message = "hello world!\n";

return SUCCESS;

}

public String getMessage(){

return message;

} }

在这个 Action 中,有一个成员变量 message,并且定义了 getter 方法,这是一种 JavaBean 模式,通过这种模式 Action 中的成员可以从页面获取,在 execute()函数中只是简单为 message 赋值,最后返回一个成功的字符串,作为整个 Action 的返回类型,通过返回类型就 可以在 struts.xml 文件找到对应的返回页面。execute 方法是任何一个 Action 都必须实现的方 法,也是 Action 中核心的操作。

注意:@SuppressWarnings("serial")这句代码 MyEclipse 为了除去警告而添加的,无关紧要的。

2.3.2 在 struts.xml 中配置 Action

在有了这段代码之后,为了使用Struts2提供的基础框架,必须向Struts2注册这个Action。

(26)

于是在struts.xml中添加action子元素。对应的配置代码如下所示:

<action name="helloworld" class=" example.helloworld">

<result name="success">hello.jsp</result>

</action>

这段 XML 告知 Struts2 基础框架,将要使用一个名为 helloworld 的 Action,这个 Action 对应的类的位置为 example.helloworld.java。它有一个名为 success 的结果页面 hello.jsp 与之 对应。

2.3.3 创建视图 hello.jsp

下面要写一个显示页面来输出 hello world!的字样,也就是上面 Action 中定义的 message 中的内容,至于为什么会联系起来,那将会在后面的章节进行讲解,希望读者继续下去。

hello.jsp 存放的目录是:\ww\WebRoot。

hello.jsp

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

<html>

<head>

<title>Hello Page</title>

</head>

<body>

The message generated by my first action is:

<s:property value="message" />

</body>

</html>、

第一句代码是表明前缀 s 和 Struts2 标签路径 URI 之间建立映射关系,这个 URI 就是前 面提到的,Struts 为我们默认定义的。前缀 s 就是表明所有用到 Struts2 标签的地方就要加上 前缀 s。在这个页面上就是使用了一个 property 标签,这个标签包含了一个 value 属性值,

通过设置 values 的值,标签就可以从 Action 中获得相应表达式的内容,也就是通过上面 Action 中定义的 getMessage()函数来完成的。

2.3.4 测试 Action

所用文件编辑完成后,最终的文件目录层次结构将如图 2-18 所示。实际有用的文件都 是在 WebRoot 目录下的。

注意:图中的文件目录还包含后面的拦截器例子,大家可以先不管它。有一个细节要告诉读 者,在 src 的文件夹下可以放 struts.xml 文件,它会自动在相应的目录下复制一个。一般.java 的文件都在 src 目录下,它们会自动编译生成.class 文件存在/WEB-INF/classes 目录下,这些 才是可以执行的。

(27)

图 2-18 Web 项目的目录层次结构示意图

接下来要看看怎么用 Eclipse 去部署这个 web 项目,如图 2-19 所示,点击红色区域所示 的工具按钮来部署。

图 2-19 部署按钮

点击图 2-19 所示的按钮后将会如图 2-20 所示的界面。在弹出窗口中选择 add 按钮,在 新弹出的窗口中选择 Server 为 Tomcat5,点击确定按钮,如图 2-20 所示。

图 2-20 配置界面

这样配置就完成了,最后如图 2-21 所示就表明部署成功了。

(28)

图 2-21 部署成功界面 然后就可以直接在 Eclipse 下打开 Tomcat,进行检测。

注意:如果在运行 Tomcat 之前,如果修改了.xml、.java 文件或者是增减 jar 包,都要重新部 署这个项目,只要点击图上的红色标记的 Redeploy 按钮就可以重新部署项目。

按上面步骤编辑和部署完之后,如果没有什么特殊情况,那么在浏览器输入:

http://localhsot:8080/ww/helloworld.action

将看到一个 Web 页面,只有一行问候语:"The Message Generated by my first Action is:

Hello World."这是一个最基本的 Struts2 应用,如图 2-22 所示。

图 2-22 成功的显示页面

2.4 体验 Struts2 更高级功能

在体验了解最简单的应用之后是不是有一种意犹未尽的感觉呢?是不是觉得这个程序

(29)

实在是太简单呢?接下来将在上一小节例子的基础上继续展示 Struts2 的拦截器技术和 Velocity 视图技术。

2.4.1 处理输入

显然,2.3 小节的例子实在是太简单了,它甚至连个标签都没有,而且结果也过于单一,

似乎其中的 Action 也没发挥其作为控制器根据不同结果转向不同页面的作用,下面就来看 看控制器的真面目。本节将深化上一小节的例子,该例子的功能大致如下:

在 name.jsp 页面将提示先输入一个用户名,然后页面转向 helloworld.action 对输入进行 分析和处理,根据情况的不同,如果输入不合法,那么控制器 helloworld.action 就把页面转 向到 name.jsp 给出出错提示信息,并要求继续输入。如果输入合法,那么控制器就会把页 面转向到 hello.jsp 给出友好的欢迎信息。页面的大致流程如图 2-23。

图 2-23 页面流转图 name.jsp

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

<html>

<head>

<title>Enter your name</title>

</head>

<body>

<s:if test="message != null">

<font color="red">

<s:property value="message"/>

</font>

</s:if>

Please enter your name:

<s:form action = "helloword.action">

< s:textfield name ="name"/>

<s:submit/>

</s:form>

</body>

</html>

(30)

name.jsp 的功能很简单,提示用户输入 name 然后将页面转向 helloworld.action。在这个 action 里面,将处理用户的输入,用户的输入保存在 name 字段里面。在控制器将结果转向 页面的时候,不希望页面输出一个空的名字,所以空的名字是不被允许的,同时出于实验的 目的,禁止用户输入“w”这个名字。如果字段合法,那么就把用户转向 hello.jsp 如果不合 法,则设置出错信息同时将页面返回 name.jsp 重新输入。修改后的 helloworld.java 如下所示:

helloworld.java package example;

import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")

public class helloworld extends ActionSupport {

public String message;

public String name;

public String execute() {

if ( name == null || "".equals(name)||"w".equals(name)) {

message="Blank names or 'w' not allowed";

return INPUT;

}

message = "hello "+name+"!\n";

return SUCCESS;

}

public String getMessage() {

return message;

}

public void setName(String name) {

this.name = name;

}

public String getName() {

return name;

} }

与前面 Action 不同之处就在于增加一个成员 name,因为要从页面接受输入的消息,就 要设置成 JavaBean 模式,再添加一个 setter 方法。再看看 execute 方法中通过一个 if 语句对 输入的 name 进行判断,如果合法就返回成功 SUCCESS 字符串,不合法的话就返回 INPUT 字符串,同时还把出错消息赋给 message 变量,在页面上显示出来。当然不同的返回类型对 应了不同的页面。

现在要配置 struts.xml,这次增加了一个页面 name.jsp,要在 Action 返回 SUCCESS 的 时候进入 hello.jsp,而在返回 INPUT 的时候重新回到 name.jsp,就是在输入姓名时输入‘w’

(31)

时就返回重新输入。struts.xml 配置如下:

<action name="helloworld" class=" example.helloworld">

<result name="success">hello.jsp</result>

<result name="input">name.jsp</result>

</action>

具体的为什么会这样配置,在以后章节会一步步揭晓谜底。

2.4.2 执行结果

在浏览器中输入 http://localhsot:8080/ww/name.jsp,然后再在弹出的页面的姓名框中输 入‘w’,就会出现如图 2-24 界面:

图 2-24 输入‘w’之后的界面

通过阅读代码,也许读者能猜到这个 Action 的作用了。它对用户在表单中所输入的 name 进行校验,校验的规则是:空名字以及名字为"w"是不允许的。如果用户的输入是这两种 情况,那么毫无疑问将会被 Struts2 的 Dispather 推回到 name 页面。同时在输入的上方提示 出错信息。可以看到简单的几行代码就完成了很强大复杂的功能,这种高效率的代码正是 Web 程序员所需要的,也是 Struts2 的魅力所在。现在不必深究每行代码的具体含义,在后 面的章节里面将向读者展示这些神奇的功能是如何实现的。

2.4.3 拦截器

现在,再看看 Struts2 的其它技术,将其与一些 Java Web 框架比较也许读者会有更多更 新的感受。

在这里实现一个简单的拦截器"GreetingInterceptor"。它的功能就是在 GreetingAction 发生之前将其捕获,然后向其 Action 上下文的 Session 里面添加问候信息,供 GreetingAction 使用。

(32)

拦截器在 GreetingAction 发生之前将其捕获,并向其 ActionContext 加入名为 greeting 的 问候字段信息。然后唤醒 Action,使其得以继续执行。

GreetingInterceptor.java

package example;

import java.util.Calendar;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

@SuppressWarnings("serial")

public class GreetingInterceptor extends AbstractInterceptor {

public void init() { } public void destroy() { }

@SuppressWarnings("unchecked")

public String intercept(ActionInvocation invocation) throws Exception {

ActionContext ac = invocation.getInvocationContext();

//取得 Action 的执行的上下文

HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);

//通过上下文获得 REQUEST 对象

Calendar calendar = Calendar.getInstance();

int hour = calendar.get(Calendar.HOUR_OF_DAY);

String greeting = (hour < 6) ? "Good evening" : ((hour < 12) ? "Good morning":

((hour < 18) ? "Good afternoon": "Good evening"));

String name = request.getParameter("name");

//从 REQUEST 对象获得 NAME

greeting = name + " " +greeting;

//初始化 greeting 对象

invocation.getInvocationContext().getSession().put("greeting", greeting);

//将信息放入 SESSION

String result = invocation.invoke();

return result;

} }

在这段代码里面,实现了一个简单的拦截器 greeting,这个拦截器完成的功能就是初始 化一段欢迎信息供页面使用,首先从控制器上下文里面取出 Request 对象,从而获得用户的 用户名信息,同时从取得当前系统时间,然后使用此信息初始化一段欢迎信息,并将其放入 Session 供页面使用。

GreetingAction.java 这个 Action 的功能很简单,其什么事都不需要做,只要将页面转向 其结果集 SUCCESS 就行了。

GreetingAction.java

(33)

package example;

import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")

public class GreetingAction extends ActionSupport{

public String execute() throws Exception{

return SUCCESS;

} }

跟随着 GreetingAction,接着跳转到视图,而这个视图将使用 Velocity 来实现,比较一 下,Velocity 和传统的 JSP 页面有什么异同呢?

在 html 文件的代码中可以看到,它只是简单的输出了一个字段而已。

ex01-result.vm

<html>

<head>

<title>Struts2 Tutorial - Lesson 5 - Example 1</title>

</head>

<body>

#set ($ses = $request.getSession())

<p>

<b>

${ses.getAttribute('greeting')}! <!—从 session 中取出欢迎信息-->

</b>

</p>

</body>

</html>

注意:既然用到了 Velocity 技术,那么项目中导入的包也会有所不同,会增加很多包,具体 增加什么包,在第八章有详细说明,读者配置这个项目时,导入包的时候可以参考第八章的 图 8-1。

大家肯定不熟悉这种页面编程技术,这是采用了 Velocity 技术,这种技术在 Struts2 中 已经集成的很好,在后面的章节会详细介绍。它与代码的交互似乎十分简捷便利,当然,这 还不是全部,在后面的例子里面读者将会发现它的使用给页面带来的极大便利。

至此,代码已经全部完成,缺的只是配置。要把自己添加的拦截器配置之后才可以使用,

修改 struts.xml 如下:

struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constant name="struts.devMode" value="true" />

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

<interceptors>

<interceptor name="greeting" class="example.GreetingInterceptor"></interceptor>

</interceptors>

<default-interceptor-ref name="completeStack"></default-interceptor-ref>

<action name="greeting" class="example.GreetingAction">

<result name="success" type="velocity">ex01-result.vm</result>

(34)

<interceptor-ref name="greeting"></interceptor-ref>

</action>

</package>

</struts>

从字面上大概也能看出个所以然,这个配置文件的意思就是向 Struts2 框架注册一个拦 截器,使得在 Action 发生的时候能够截获这个 Action 并进行相应的处理。如果没有什么意 外的话,那么该 Web 应用将顺利的在 TOMCAT 下面部署并运行起来。至于具体的含义大家 可以在学习后面章节后就会明白了。

下面来测试一下结果,在浏览器输入:http://localhsot:8080/ww/name.jsp,会弹出一个输 入姓名的页面,在页面中输入“xuxinpeng”提交会后出现下面如图 2-25 的页面。

图 2-25 成功页面

2.5 小结

这章一开始先安装 JDK,Tomcat,配置 Tomcat,还有 Struts2 的安装和 MyEclipse 的配 置等等工作是整个开发的最基础部分。然后通过一个简单的 helloworld 例子展示了一下 Struts2 的基本功能,而后通过一个高级的输入处理例子进一步展示 Struts2 的魅力,不过这 些都是对 Struts2 中 Action 的展示。所以在接下来的部分就对 Struts2 另一个重要的组成部分 interceptor 也举了一个例子,而且和前面的例子实现的功能相同。侧面比较两种方式的不同,

其实 Struts2 在执行 Action 之前都会先运行 Action 对应的拦截器,然后才会执行 Action,所 以在拦截器的例子中把所有功能都已经放在拦截器中执行了,故 Action 中不用处理。在这 要提醒大家,核心的操作最好还是要放在 Action 中执行,不要任何功能都放在拦截器中执 行,通过后面的章节学习读者会知道什么时候要借助拦截器的帮忙。

在这一章向读者展示了 Struts2 的一些基础和特色,相信通过这几个例子,大家对 Struts2 的优点一定有所了解了,也许理解的不够深刻,不过没关系,罗马不是一天建成的。虽然展 示的只是最简单的代码,但是它们可都是 Struts2 的最核心技术。本章的目的只是让读者在 宏观上对 Struts2 的技术有所了解。至于这些技术的详情和内幕将在后面的章节里面向读者 逐步阐述。

(35)

第三章 Action

在前面提到 MVC 模式中,需要一个控制器来负责浏览器与服务器的通讯,实现处理用 户与服务器的交互。而在 Struts2 框架中,实现这一功能就是 Action,它是整个框架的最核 心部分,Action 的使用反应了应用程序的功能需求,Action 负责存储数据和状态,与应用的 具体业务逻辑打交道。

在本章中将关注如何在具体的应用中根据不同的需要实现 Action,讨论 Action 如何提 供 Web 应用中所需要的通用功能。除了 Action 接口之外,Struts2 Action 也可以实现其框架 中它模块的一些功能,例如校验、国际化、异常处理等等。

3.1 Action 简介

实现 Struts2 框架的 Action 有两种方案。一种是实现框架所提供的 Action 接口,另一种 则是使用框架提供的 ActionSupport 基类。Struts2 规定,无论使用哪种方法,在最后编写的 Action 类中都必须实现 execute()这个方法。在 Action 中首先会涉及到返回类型的概念,下 面就让我们来仔细分析它们。

3.1.1 返回类型

返回类型就是 Action 执行完后,返回的结果字符串,根据它才能控制页面的跳转。Struts2 预定义的返回类型定义在 com.opensyphony.xwork2.action 这个文件中,它是框架所定义的接 口。下面就分析一下该文件,看看框架都预定义了哪些返回类型。

com.opensyphony.xwork2.action

package com.opensymphony.xwork2;

public interface Action {

public static final String SUCCESS = "success";

public static final String NONE = "none";

public static final String ERROR = "error";

public static final String INPUT = "input";

public static final String LOGIN = "login";

public String execute() throws Exception;

}

上面的代码可以从 Xwork2 提供的源文件里找到,这里省略了原文档的部分注释。

注意:对于返回类型的含义没有强制性的要求,用户可以在控制器出错的情况下返回 SUCCESS,并为之配置出错的返回页面,系统不会报错,但是出于对代码可读性和可维护 性的考虑,建议读者按照返回类型的字面含义去配置它,例如 Action 正确执行则返回 SUCCESS,出错则返回 ERROR,需要返回到输入页面则返回 INPUT 等等。

在该文件中可以发现有很多预定义的静态字符串常量,其中有非常眼熟的字符串常量 SUCCESS,INPUT 等等,也就是上述的返回类型。接着来看看在实际的应用中如何配置返 回类型。

struts.xml

(36)

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constant name="struts.devMode" value="true" />

<package name="default" extends="struts-default"><!--包含默认配置文件,这样就不必对每个参 数详细配置-->

<interceptors>

<interceptor name="greeting" class="example.GreetingInterceptor"></interceptor>

</interceptors>

<!-- 使用默认的拦截器栈的配置 - ->

<default-interceptor-ref name="completeStack"></default-interceptor-ref>

<!-- 配置控制器 class 属性指向对应的源代码文件 - ->

<action name="greeting" class="example.GreetingAction">

<!-- 为此控制器添加对应的 SUCCESS 返回类型,并关联一个页面 -->

<result name="success" type="velocity">ex01-result.vm</result>

<interceptor-ref name="greeting"></interceptor-ref>

</action>

</package>

</struts>

下面让我们来看看对应控制器的源代码。

Example Action package example;

import com.opensymphony.xwork2.ActionSupport;

public class Greeting extends ActionSupport { public String execute() throws Exception {

return SUCCESS;

} }

代码中加粗的部分就是在框架中所预定义的返回类型,在 Action 中用到的是大写的返 回类型名,而在配置文件 struts.xml 中用到的则是对应的小写字符串值,由这两者的一一对 应关系将 Action 和 Result 一一对应起来。返回类型是沟通 Action 与 Result 的一座桥梁。

3.1.2 execute()方法

在 Struts2 中所有的 Action 都要实现 execute()方法。用户的业务逻辑就是在该方法中处 理,然后通过返回类型回到对应的视图,Action 的作用就相当于在前述章节中讲解 Struts2 改进 MVC 模式的派发器作用。

要实现 execute()方法有两种方法,一种是实现 com.opensyphony.xwork2.action 接口,还 有一种则是从 com.opensymphony.xwork2.ActionSupport 基类派生。两种方法各有优劣,下面 分别举例说明:

 方法一:实现 Action 接口 我们选取了第二章的例子作演示:

HelloWorld.java package example;

(37)

import com.opensymphony.xwork2.Action;

public class helloworld implements Action {

public String message;

//欢迎消息

public String execute() {

//添加欢迎消息

message = “helloworld\n”

return SUCCESS;

}

/*省略语句*/

}

可以看出实现这样的一个接口要求很简单,同时分析上文给出的 Action 源文件可以发现 它的功能也有局限,没有给开发者提供任何额外的功能,因此这样的实现方法比较适合简单 的 Action。对于稍复杂的应用应该考虑使用继承 ActionSupport 基类。

 方法二:继承 ActionSupport 基类

同样,为简单起见,我们选取了第一部分 2.4.1 的例子作说明:

helloworld.action package example;

import com.opensymphony.xwork2.ActionSupport;

public class helloworld extends ActionSupport {

public String message;

public String name;

public String execute(){

if ( name == null || "".equals(name)||"w".equals(name)) {

//如果用户的输入不合法,那么给出出错信息

addFieldError("name","Blank names or 'w' not allowed");

//返回输入页面 return INPUT;

}

//添加欢迎消息

message = "hello "+name+"!\n";

return SUCCESS;

} }

表面上看,似乎这个 Action 和前一个例子没有太大的差别,都是实现了 execute()方法,

然后返回一个返回类型。然而注意 execute()里面黑体的部分读者也许就能发现,这里 ActionSupport 提供了出错处理的一个函数。其实远远不止这一个简单的功能,ActionSupport 还提供了近 30 个成员函数涵盖了国际化、校验、出错处理等各个方面来处理用户的业务逻 辑。所以如果用户的业务逻辑不是足够简单的话,那么应该选择从 ActionSupport 基类中派 生出自己的 Action,这样就可以使用框架所带来的种种便捷。

(38)

3.2 Action 接口

有了上面的分析,下面让我们直接来看一下 com.opensyphony.xwork2.action 接口的源代 码:(上面已经给出,这里为了和下面的比较,不妨再次给出)。

com.opensyphony.xwork2.action

package com.opensymphony.xwork2;

public interface Action {

public static final String SUCCESS = "success";

public static final String NONE = "none";

public static final String ERROR = "error";

public static final String INPUT = "input";

public static final String LOGIN = "login";

public String execute() throws Exception;

}

当从页面提交请求到一个 action 的时候,应用就会跳转到相应的 action 中去执行 execute() 方法。所以当编写自己的 action 的时候,如果是实现这个接口,那么只要在 execute()方法中 添加相应的功能代码就可以了,但是这并不是一个好的实现业务逻辑的方法,因为这样对于 只有很少代码的应用或许是可以的,但是如果是对有比较多的代码的应用,那么必定会造成 逻辑的混乱,对以后的维护、修改等都是不利的。在后面,读者将会看到,我们将会把实现 代码放在相应的类中,而在 action 的 execute()方法中只是调用这些方法,以此来达到便于管 理的目的。

3.3 ActionSupport 基类

ActionSupport 是编写设计业务逻辑 Action 的强有力支持。它提供的功能也十分强大。

下面将会仔细的介绍一些常用的 ActionSupport 的成员函数,并且详细的了解 ActionSupport 的原理。下面列出了 ActionSupport 基类的大部分成员函数以及相关描述:

表3-1 ActionSupport的成员函数

返回类型 成员函数 描述

void addActionError(Sting anErrorMessage) 向 Action 添加一个 Action 级别的错误

void addActionMessage(String aMessage) 向 Action 添加一个 Action 级别的信息

void

addFieldError(String fieldName ,

String errorMessage) 为指定的域添加一个出错信息

void clearErrorsAndMessages() 清除所有的错误和信息

String execute() 其缺省的实现仅返回 SUCCESS

Collection getActionErrors() 获得 Action 级别的错误集合

Collection getActionMessages() 获得 Action 级别的信息集合

Map getFieldErrors() 获得与域相关的错误信息的集合

String getText(String aTextName) 基于键获得指定的键值,不存在则返回 NULL

String getText(String aTextName, List args)

基于键和附加参数获得指定的键值,不存在则返 回 NULL

String getText(String aTextName , 基于键获得指定的键值,不存在则返回缺省值

(39)

String defaultValue)

boolean hasActionErrors() 是否有 Action 级别的错误

boolean hasActionMessages() 是否有 Action 级别的信息

boolean hasErrors() 是否有错误,包括域和 Action 级别

boolean hasFieldErrors() 是否有域级别的错误

void pause(String result)

暂停 Action 的执行,抛出异常,并转向对应返回 类型

void setActionErrors(Collection errorMessages) 设置 Action 级别的所有错误

void setActionMessages(Collection messages) 设置 Action 级别的所有信息

void setFieldErrors(Map errorMap) 设置域级别的所有错误

void validate() 默认的空校验器

我们在编写控制器的时候,能够使用的框架的 API 也就是这些了,当然不是所有的都 经常使用,一般常用的是出错处理的一些函数,如 hasErrors()、hasFieldErrors()等等。读者 可以对照自己的需求合理的选取和使用自己所需的 API。

为了更好的理解 Struts2,下面我们对 ActionSupprot 的源代码进行剖析:

com.opensyphony.xwork2.ActionSupport package com.opensymphony.xwork2;

/*省略代码*/

public class ActionSupport implements Action,, Validateable,, ValidationAware,, TextProvider,,

LocaleProvider,, Serializable,, ContinuableObject {

protected transient static final Log LOG = LogFactory.getLog(ActionSupport.class);

private transient final TextProvider textProvider = new TextProviderSupport(getClass(),, this);

private final ValidationAwareSupport validationAware = new ValidationAwareSupport();

public void setActionErrors(Collection errorMessages) { validationAware.setActionErrors(errorMessages);

}

public Collection getActionErrors() {

return validationAware.getActionErrors();

}

/*省略语句*/

public Map getErrors() { return getFieldErrors();

}

/*省略语句*/

public Locale getLocale() {

return ActionContext.getContext().getLocale();

}

public String getText(String aTextName) { return textProvider.getText(aTextName);

}

/*省略语句*/

public void addActionError(String anErrorMessage) { validationAware.addActionError(anErrorMessage);

}

/*省略语句*/

public String doInput() throws Exception {

(40)

return INPUT;

}

/*省略语句*/

public boolean hasActionErrors() {

return validationAware.hasActionErrors();

}

/*省略语句*/

public void clearErrorsAndMessages() {

validationAware.clearErrorsAndMessages();

}

public void validate() { }

public void pause(String result) { }

}

从上述代码中可以发现 ActionSupport 基类实现了很多的接口,但是仔细的观察上面列 出的函数不难发现,它所提供的接口都是围绕着控制器的核心出错处理来完成的,如 hasActionErrors()等等。

纵观整个文件,所有的操作都围绕着 validationAware 这个类展开,validationAware 对于 ActionSupport 来说是非常重要的一部分,所有的 Error,Message,FieldError 都间接的存放在 validationAware 这个类中。那么 validationAware 这个类究竟是什么样子的一个类呢?下面就 来看看它的庐山真面目:

com.opensyphony.xwork2. validationAware /*省略代码*/

public class ValidationAwareSupport implements ValidationAware, Serializable { private Collection actionErrors;

private Collection actionMessages;

private Map fieldErrors;

/*省略语句*/

}

看到这里就恍然大悟了,actionErrors 和 actionMessages 实际是用 Collection 这个数据结 构存放的,fieldErrors 则是用 Map 这个数据结构存放的,所有 Action 对这三个变量的操作 实际上都是间接的对这三个数据结构的操作。以后用到这三个类的时候自然就有了经验。

3.4 Action 实例

作为示例,我们在这里提供两种不同功能 Action 的完全实现,供读者参考和练习。

 实现 Action 接口;

 继承 ActionSupport 基类;

3.4.1 实现 Action 接口的实例

这里我们使用 Action 完成一个有趣的应用:由服务端动态生成颜色代码供客户端显示 时使用,这样在客户端每一次刷新页面的时候,文字的颜色就改变一次。下面详细讲解如何 实现该应用。

为了实现这个应用,我们需要编写一个控制器、一个页面以及与之对应的配置文件,下

(41)

面让我们来一步一步的完成它。

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_9" version="2.4"

xmlns="http://java.sun.com/xml/ns/j2ee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<display-name>Struts 2 First</display-name>

<filter>

<filter-name>struts-cleanup</filter-name>

<filter-class>

org.apache.struts2.dispatcher.ActionContextCleanUp </filter-class>

</filter>

<filter-mapping>

<filter-name>struts-cleanup</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<filter>

<filter-name>struts2</filter-name>

<filter-class>

org.apache.struts2.dispatcher.FilterDispatcher </filter-class>

</filter>

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<welcome-file-list>

<welcome-file>index.html</welcome-file>

</welcome-file-list>

</web-app>

这个文件是所有 Web 应用都要有的配置文件,但是对于不同的框架,实现的方法和语 法是不尽相同的。

web.xml 是 SUN servlet 规范的标准配置文件,所有的 Java 的 Web 开发项目都要配置文 件,我们发现 Struts2 在 web.xml 里面配置了 filter,由此也可以看出,Struts2 框架是作为一 个过滤器来处理所有的 Web 请求的。

从上面的配置文件可以看出,web.xml 指定容器在捕获到 Web 请求之后将其转交给 Struts2,那么 Struts2 又是如何来处理这些请求的呢?这就要观察 Struts2 的配置文件 struts.xml 了。

struts.xml

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constant name="struts.devMode" value="true" />

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

數據

表 5-1 Result 类型列表
表 6-2 property 标签的属性
表 6-12 列出了 url 标签的属性。
表 9-1 Hibernate 的核心 API

參考文獻

相關文件

Don Knuth James Morris Vaughan Pratt..

public static double calculate(int i, int j) throws ArithmeticException,

EdD, MEd, BEd Adjunct Assistant Professor Department of Early Childhood Education Member, Centre for Child and Family Science The Education University of Hong

final instance variable: accessed through instance, and assigned once (in declaration or every instance constructor) final instance method: cannot be overriden (≈ assigned once)

/** Class invariant: A Person always has a date of birth, and if the Person has a date of death, then the date of death is equal to or later than the date of birth. To be

To convert a string containing floating-point digits to its floating-point value, use the static parseDouble method of the Double class..

source:PTR BYTE, ; source string target:PTR BYTE ; target string. INVOKE Str_length,source ; EAX =

[r]