北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 前 言 吾 尝 终 日 而 思 矣, 不 如 须 臾 之 所 学 也 ; 吾 尝 跂 而 望 矣, 不 如 登 高 之 博 见 也 登 高 而 招, 臂 非 加 长 也, 而 见



Similar documents
内 容 提 要 将 JAVA 开 发 环 境 迁 移 到 Linux 系 统 上 是 现 在 很 多 公 司 的 现 实 想 法, 而 在 Linux 上 配 置 JAVA 开 发 环 境 是 步 入 Linux 下 JAVA 程 序 开 发 的 第 一 步, 本 文 图 文 并 茂 地 全 程 指

Java 1 Java String Date

附录J:Eclipse教程

新・解きながら学ぶJava

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

基于CDIO一体化理念的课程教学大纲设计

Java

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

Eclipse C C++, or

2 Java 语 言 程 序 设 计 教 程 简 单 性 Java 语 言 的 语 法 与 C 语 言 和 C++ 语 言 很 接 近, 使 得 大 多 数 程 序 员 很 容 易 学 习 和 使 用 Java 另 一 方 面,Java 丢 弃 了 C++ 中 很 少 使 用 的 很 难

WebSphere Studio Application Developer IBM Portal Toolkit... 2/21 1. WebSphere Portal Portal WebSphere Application Server stopserver.bat -configfile..

Microsoft PowerPoint - ch6 [相容模式]

epub83-1

目 錄 版 次 變 更 記 錄... 2 原 始 程 式 碼 類 型 之 使 用 手 冊... 3 一 安 裝 軟 體 套 件 事 前 準 備... 3 二 編 譯 流 程 說 明

EJB-Programming-4-cn.doc

untitled

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

untitled

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌

chp6.ppt

untitled

untitled

Microsoft Word - 01.DOC

EJB-Programming-3.PDF

untitled

Oracle Solaris Studio makefile C C++ Fortran IDE Solaris Linux C/C++/Fortran IDE "Project Properties" IDE makefile 1.

Oracle Oracle Solaris Studio IDE makefile C C++ Fortran makefile IDE Solaris Linux C/C++/Fortran Oracle IDE "P

Chapter 9: Objects and Classes

Learning Java

RunPC2_.doc

AL-M200 Series

没 有 多 余 的 Contruol 或 Action 了 原 来 Domain 层 被 服 务 层 Service layer 遮 挡, 在 右 边 图 中, 则 Domain 层 直 接 暴 露 给 前 台 了, 没 有 被 遮 挡, 裸 露 了 这 样 一 步 到 位 实 现 领 域 模 型

Microsoft Word - ch04三校.doc

Microsoft Word zw

Microsoft Word - 第3章.doc

Chapter 9: Objects and Classes

《大话设计模式》第一章

IBM Rational ClearQuest Client for Eclipse 1/ IBM Rational ClearQuest Client for Ecl

ebook

优迈科技教学大纲2009版本

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

Symantec™ Sygate Enterprise Protection 防护代理安装使用指南

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

untitled

javaexample-02.pdf

D C 93 2

FileMaker 16 ODBC 和 JDBC 指南

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

untitled

AL-MX200 Series

WinMDI 28

Chapter 2

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

序 言 本 专 业 人 才 培 养 方 案 以 适 应 市 场 需 求 为 目 标, 根 据 学 校 校 企 双 主 体 人 才 培 养 的 要 求 和 移 动 应 用 开 发 专 业 的 特 点 设 置 课 程 体 系, 体 现 了 课 程 为 市 场 服 务 的 特 点 本 专 业 要 求 学

FileMaker 15 ODBC 和 JDBC 指南

使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款

<4D F736F F D20BBF9D3DA416E64726F6964C6BDCCA8B5C4B5E7D7D3C5C4C2F4CFB5CDB32E646F63>

软 件 工 程 专 业 习 指 南 目 录 一 软 件 工 程 专 业 设 置 背 景 与 发 展 前 景... 3 二 软 件 工 程 专 业 实 践 教 条 件... 4 三 软 件 工 程 专 业 课 程 类 型 及 核 方 式 软 件 工 程 专 业 课 程 类 型...7

计算机软件技术专业教学计划

Microsoft Word - 王彬_已修改_.doc

epub 61-2

Windows 2000 Server for T100

untitled

基于ECO的UML模型驱动的数据库应用开发1.doc

RUN_PC連載_12_.doc

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

目 录 目 录 平 台 概 述 技 术 架 构 技 术 特 点 基 于 统 一 平 台 的 多 产 品 线 支 撑 先 进 性 安 全 性 开 放 性 高 性 能 和

IoC容器和Dependency Injection模式.doc

雲端 Cloud Computing 技術指南 運算 應用 平台與架構 10/04/15 11:55:46 INFO 10/04/15 11:55:53 INFO 10/04/15 11:55:56 INFO 10/04/15 11:56:05 INFO 10/04/15 11:56:07 INFO

ebook140-9

Microsoft Word - Learn Objective-C.doc

中 文 摘 要 智 慧 型 手 機 由 於 有 強 大 的 功 能, 以 及 優 渥 的 便 利 性, 還 能 與 網 路 保 持 隨 時 的 鏈 結 與 同 步 更 新, 因 此 深 受 廣 大 消 費 者 喜 愛, 當 然, 手 機 遊 戲 也 成 為 現 代 人 不 可 或 缺 的 娛 樂 之

2/14 Buffer I12, /* x=2, buffer = I 1 2 */ Buffer I243, /* x=34, buffer = I 2 43 */ x=56, buffer = I243 Buffer I243I265 code_int(int x, char *buffer)

Microsoft Word - PS2_linux_guide_cn.doc

JavaIO.PDF

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

1. 访 问 最 新 发 行 公 告 信 息 jconnect for JDBC 访 问 最 新 发 行 公 告 信 息 最 新 版 本 的 发 行 公 告 可 以 从 网 上 获 得 若 要 查 找 在 本 产 品 发 布 后 增 加 的 重 要 产 品 或 文 档 信 息, 请 访

职 位 类 别 : 测 试 工 程 师 工 作 经 验 或 实 习 经 历 : 不 限 岗 位 要 求 : 1. 本 科 及 其 以 上 学 历, 计 算 机 相 关 专 业 2014 届 毕 业 生 ; 2. 实 习 时 间 要 求, 尽 量 一 周 五 个 工 作 日 ; 3. 熟 悉 Wind

<4D F736F F D20C8EDBCFEA1B A1B33136BAC5A3BAB9D8D3DAB7A2B2BC C4EAC8EDBCFEB9A4B3CCCAB5D1B5D6AED0A3C4DABFC6D1D0CFEEC4BFB5C4CDA8D6AA2E646F63>

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

(京)新登字063号

第 15 章 程 式 編 写 語 言 15.1 程 式 編 写 語 言 的 角 色 程 式 編 寫 語 言 是 程 式 編 寫 員 與 電 腦 溝 通 的 界 面 語 法 是 一 組 規 則 讓 程 式 編 寫 員 將 字 詞 集 合 起 來 電 腦 是 處 理 位 元 和 字 節 的 機 器, 與

Guide to Install SATA Hard Disks

NEXT SDT2.51 C:\ARM251 SDT2.51 ARM SDT 2.51 ARM PROJECT MANAGER SDT 2

Java Access 5-1 Server Client Client Server Server Client 5-2 DataInputStream Class java.io.datainptstream (extends) FilterInputStream InputStream Obj

PowerPoint Presentation

序号:001

基于UML建模的管理管理信息系统项目案例导航——VB篇

ebook8-30


<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

XXXXXXXX

填 写 要 求 1. 以 word 文 档 格 式 如 实 填 写 各 项 2. 表 格 文 本 中 外 文 名 词 第 一 次 出 现 时, 要 写 清 全 称 和 缩 写, 再 次 出 现 时 可 以 使 用 缩 写 3. 本 表 栏 目 未 涵 盖 的 内 容, 需 要 说 明 的, 请 在

EK-STM32F

Microsoft Word - template.doc

untitled

LiveBOS产品白皮书

Transcription:

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 前 言 吾 尝 终 日 而 思 矣, 不 如 须 臾 之 所 学 也 ; 吾 尝 跂 而 望 矣, 不 如 登 高 之 博 见 也 登 高 而 招, 臂 非 加 长 也, 而 见 者 远 ; 顺 风 而 呼, 声 非 加 疾 也, 而 闻 者 彰 假 舆 马 者, 非 利 足 也, 而 致 千 里 ; 假 舟 楫 ( 船 桨 ) 者, 非 能 水 也, 而 绝 江 河 君 子 生 非 异 也, 善 假 于 物 也 荀 子 劝 学 关 于 版 权 本 书 由 国 内 知 名 IT 培 训 网 站 北 风 网 (http://www.ibeifeng.com) 讲 师 出 品, 本 书 仅 限 于 北 风 网 内 部 学 员 学 习 交 流, 任 何 个 人 及 机 构 都 无 权 转 载 违 者 必 究! 为 什 么 学 习 MyEclipse Java 的 开 发 中 可 以 有 多 种 开 发 方 式, 最 基 础 的 可 以 使 用 记 事 本, 也 可 以 使 用 智 能 集 成 开 发 工 具 在 理 论 上, 不 管 使 用 什 么 工 具, 都 是 可 以 进 行 项 目 开 发 的, 但 是 开 发 速 度 相 差 是 非 常 大 的 MyEclipse 做 为 一 款 集 成 开 发 工 具, 大 大 节 省 了 程 序 员 的 工 作 范 围, 能 够 很 大 程 度 的 提 高 工 作 效 率, 从 而 使 项 目 开 发 更 快 捷 目 前 开 发 中 可 以 选 择 的 集 成 开 发 工 具 有 很 多, 但 是 使 用 最 多 的 还 是 MyEclipse, 在 绝 大 部 分 的 开 发 公 司 中 都 是 使 用 它 所 以 是 否 能 够 熟 练 使 用 MyEclipse 决 定 了 是 否 能 够 很 好 的 融 入 开 发 团 队 的 关 键 为 什 么 要 写 这 本 书 在 开 发 团 队 中 有 这 样 两 种 人, 一 种 是 对 技 术 了 解 的 非 常 精 通, 但 是 开 发 速 度 很 慢 ; 另 一 种 是 技 术 一 般, 但 是 能 够 快 速 准 确 的 完 成 下 达 的 任 务 ; 请 问 项 目 经 理 会 更 欣 赏 哪 一 个 程 序 员? MyEclipse 的 功 能 是 非 常 强 大 的, 但 是 笔 者 在 培 训 教 学 中, 发 现 学 员 并 没 有 使 用 到 其 中 的 精 髓 功 能, 还 是 使 用 记 事 本 开 发 的 思 想 这 就 好 像 下 面 这 个 故 事 : 现 在 有 木 柱 和 细 木 棍 两 件 东 西, 需 要 使 用 它 们 制 作 出 火 有 些 人 可 能 直 接 进 行 钻 木 取 火, 但 是 有 些 人 可 能 会 使 用 它 们 换 一 个 打 火 机 其 中 钻 木 取 火 就 是 MyEclipse 的 基 本 功 能, 而 换 打 火 机 就 是 MyEclipse 的 精 髓 功 能, 在 本 书 中 就 主 要 对 这 些 精 髓 功 能 进 行 讲 解 通 过 MyEclipse 的 精 髓 功 能 就 能 够 大 大 提 高 程 序 员 的 工 作 效 率, 使 用 它 们 甚 至 可 以 自 动 生 成 150 行 的 代 码 如 果 手 动 编 写 150 行 的 代 码, 可 能 需 要 花 费 1 个 小 时 的 时 间, 但 是 如 果 使 用 其 中 的 功 能, 就 只 需 要 5 秒 钟 笔 者 写 这 本 书 的 目 的, 就 是 尽 可 能 的 让 MyEclipse 完 成 它 能 够 完 成 的 工 作, 只 将 必 要 的 工 作 交 给 程 序 员 完 成, 从 而 加 快 开 发 本 书 有 哪 些 特 点 1 步 骤 清 晰 表 达 准 确 对 于 一 个 非 初 学 者 来 说, 本 书 的 步 骤 可 能 有 些 繁 琐 例 如 描 述 弹 出 菜 单 时, 其 中 会 这 样 讲 解 : 在 编 辑 区 的 程 序 中, 将 鼠 标 指 定 在 Student 类 体 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 XXX 命 令 在 其 中 的 讲 解 中, 有 几 个 关 键 点, 分 别 是 编 辑 区 类 体 中 单 击 右 键, 其

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 中 少 了 哪 一 点 都 是 不 能 执 行 命 令 的 对 于 一 个 非 初 学 者 来 说, 会 觉 得 有 一 点 罗 嗦, 但 是 对 于 初 学 者 而 言 就 能 够 很 容 易 的 按 照 步 骤, 学 会 该 命 令 的 使 用 2 全 面 讲 解 不 留 盲 点 这 里 所 说 的 全 面 讲 解, 并 不 是 指 所 有 功 能, 而 是 指 一 个 功 能 在 很 多 书 中, 说 的 最 多 的 一 句 话 就 是 这 些 选 项 采 用 默 认 值 就 可 以 在 本 书 中, 这 句 话 使 用 的 是 比 较 少 的, 因 为 MyEclipse 中 不 会 集 成 完 成 不 需 要 改 变 的 选 项 在 本 书 中 对 操 作 界 面 进 行 讲 解 中, 会 将 操 作 界 面 中 的 每 一 个 选 项 都 讲 解 到 在 其 中 讲 解 该 选 项 的 作 用, 在 什 么 地 方 用, 实 际 开 发 中 如 何 来 用, 尽 量 不 让 读 者 带 着 疑 惑 进 行 下 面 的 学 习 3 作 者 心 得 经 验 之 谈 在 本 书 的 知 识 讲 解 中, 穿 插 了 大 量 的 作 者 心 得, 其 中 包 括 注 意 点 小 技 巧 和 作 者 的 经 验 之 谈 当 具 有 两 种 都 可 以 用 的 选 择 时, 作 者 通 常 给 出 自 己 的 观 点 或 者 目 前 主 流 选 择, 可 能 和 读 者 所 在 公 司 的 选 择 不 同, 这 种 情 况 下 以 公 司 的 选 择 为 标 准 5 视 频 讲 解 结 合 实 践 本 书 编 写 后, 笔 者 为 本 书 录 制 了 随 书 视 频, 在 视 频 中 涵 盖 书 中 知 识 点, 并 高 于 书 中 讲 解 在 对 书 中 的 知 识 点 讲 解 后, 还 以 5 个 综 合 案 例 讲 解 了 如 何 使 用 MyEclipse 进 行 开 发 读 者 可 以 在 光 盘 中 中 找 到 这 些 内 容 本 书 适 合 哪 些 读 者 对 Java 基 本 了 解, 想 进 一 步 加 快 开 发 速 度 的 程 序 员 各 大 中 专 院 校 培 训 机 构 的 在 校 学 生 和 相 关 授 课 老 师 想 加 快 工 作 效 率 的 开 发 团 队 编 程 爱 好 者 本 书 作 者 : 2011 年 7 月

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 内 容 提 要 本 书 是 一 本 MyEclipse 的 精 装 教 程, 目 前 Java 语 言 的 编 程 工 具 中 最 流 行 的 就 是 MyEclipse 集 成 开 发 工 具 本 书 以 开 发 技 巧 和 案 例 为 主 线, 对 MyEclipse 的 重 要 开 发 功 能 进 行 讲 解 全 书 分 为 3 部 分 第 1 部 分 是 基 础 篇, 讲 解 了 MyEclipse 开 发 环 境 的 搭 建 和 基 本 操 作 命 令, 通 过 使 用 基 本 操 作 命 令 就 可 以 让 MyEclipse 自 动 生 成 程 序 员 想 要 的 代 码 第 2 部 分 是 开 发 篇, 讲 解 了 目 前 最 主 流 的 Java 项 目 开 发 所 使 用 的 框 架, 包 括 Struts Hibernate Spring 和 Struts 2 框 架, 在 其 中 主 要 讲 解 了 MyEclipse 中 对 这 些 框 架 集 成 的 开 发 功 能 第 3 部 分 是 应 用 篇, 讲 解 了 Java 项 目 开 发 中 将 要 使 用 到 的 某 些 技 术, 例 如 在 开 发 之 前 要 使 用 UML 进 行 系 统 分 析 等 工 作 ; 在 开 发 工 程 中 对 程 序 进 行 调 试 和 测 试, 开 发 完 成 后 使 用 CVS 或 者 SVN 对 项 目 和 程 序 进 行 版 本 控 制 通 过 本 书 的 知 识 点, 读 者 就 可 以 全 面 了 解 使 用 MyEclipse 工 具 进 行 Java 项 目 开 发 中 每 一 步 骤 的 操 作

北 风 网 讲 师 原 创 作 品 ----- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 1 章 开 发 环 境 的 搭 建 从 本 章 起, 就 进 入 我 们 的 MyEclipse 的 开 发 之 旅 MyEclipse 是 一 款 强 大 的 智 能 的 集 成 开 发 工 具, 在 理 论 上 只 需 要 安 装 MyEclipse 就 可 以 进 行 日 常 的 开 发, 因 为 在 完 整 的 MyEclipse 中 自 带 来 JRE 数 据 库 应 用 服 务 器 等 工 具 但 是 在 实 际 开 发 中, 这 些 集 成 的 工 具 并 不 完 全 适 合 的, 所 以 MyEclipse 还 需 要 借 助 外 部 的 一 些 工 具 和 开 发 环 境, 在 本 章 中 就 可 以 学 习 一 下 如 何 搭 建 优 秀 的 MyEclipse 开 发 环 境 1.1 下 载 和 安 装 JDK JDK 是 Java 程 序 开 发 最 核 心 的 工 具, 通 过 JDK 可 以 完 成 对 Java 程 序 的 编 译 和 运 行, 所 以 我 们 首 先 要 安 装 JDK 目 前 JDK 的 最 新 版 本 为 7.0, 但 是 还 处 于 测 试 阶 段, 如 果 真 正 用 于 开 发, 它 不 是 稳 定 的, 所 以 这 里 我 们 现 在 目 前 稳 定 的 JDK 6.0 版 本 1.1.1 下 载 JDK 下 载 JDK 可 以 从 SUN 公 司 的 官 方 网 站 进 行 下 载, 官 方 首 页 地 址 为 http://java.sun.com 进 入 首 页 后, 在 横 向 导 航 栏 中, 单 击 Downloads 菜 单, 然 后 在 其 中 选 择 Java SE 选 项, 将 跳 转 到 选 择 JDK 下 载 的 页 面, 如 图 1-1 所 示 图 1-1 选 择 JDK 在 该 页 面 中, 有 多 个 应 用 在 不 同 环 境 中 的 JDK 版 本, 这 里 我 们 选 择 仅 仅 用 于 Java SE 开 发 的 JDK 6 Update 17 单 击 后 面 的 Download 按 钮, 将 进 入 选 择 操 作 系 统 版 本 的 下 载 页 面, 如 图 1-2 所 示

图 1-2 选 择 操 作 系 统 在 其 中 Platform 下 拉 列 表 中 选 择 Windows 选 项, 它 就 表 示 下 载 安 装 在 Windows 操 作 系 统 下 的 JDK, 单 击 下 面 的 Download 按 钮, 将 进 入 下 载 页 面, 如 图 1-3 所 示 说 明 :Java 最 大 的 特 点 就 是 能 够 应 用 在 不 同 操 作 系 统 中, 所 以 JDK 肯 定 也 是 这 样 的, 从 Platform 下 拉 列 表 中 也 可 以 看 到 这 一 点, 其 中 包 括 Windows Linux 和 Solaris 等 多 种 操 作 系 统 图 1-3 下 载 页 面 在 该 页 面 中, 单 击 jdk-6u17-windows-i586.exe 超 链 接, 将 弹 出 下 载 对 话 框, 单 击 保 存 按 钮, 就 可 以 选 择 保 存 到 本 地 硬 盘 中 在 jdk-6u17-windows-i586.exe 超 链 接 上 单 击 右 键, 也 可 以 在 弹 出 菜 单 中 选 择 下 载 工 具 进 行 下 载 1.1.2 安 装 JDK 下 载 完 成 后, 就 可 以 安 装 JDK,Windows 操 作 系 统 中 的 JDK 安 装 是 非 常 简 单 的 双 击 下 载 的 jdk-6u17-windows-i586.exe 文 件, 将 首 先 打 开 许 可 证 协 议 确 认 界 面, 在 其 中 单 击 接 受 按 钮, 将 弹 出 自 定 义 安 装 界 面, 如 图 1-4 所 示

3 图 1-4 安 装 JDK 其 中 列 表 中 给 出 了 可 选 安 装 的 功 能, 默 认 是 全 部 选 中 的, 可 以 单 击 前 面 的 按 钮 取 消 安 装, 这 里 保 持 默 认 值 就 可 以 界 面 下 方 是 给 出 的 安 装 位 置, 单 击 更 改 可 以 安 装 到 其 他 地 方 注 意 : 本 地 安 装 时 就 是 安 装 在 默 认 位 置 下, 读 者 修 改 位 置 后 一 定 要 记 住 具 体 位 置, 因 为 在 后 面 的 学 习 中 将 多 次 使 用 到 它 并 且 JDK 路 径 中 不 要 有 中 文, 不 然 后 面 的 开 发 中 可 能 会 出 现 不 能 识 别 的 问 题 单 击 下 一 步 按 钮, 将 开 始 安 装 JDK 经 过 数 分 钟 后 JDK 完 成 安 装, 将 自 动 打 开 Java 运 行 时 环 境 自 定 义 安 装 界 面 Java 运 行 时 环 境 配 置 和 JDK 配 置 完 全 相 同 配 置 完 成 后 单 击 下 一 步 按 钮 进 入 Java 运 行 时 环 境 安 装 界 面 出 现 安 装 完 成 界 面 后, 单 击 完 成 按 钮, 将 彻 底 完 成 JDK 的 安 装 说 明 :JDK 安 装 完 成 后, 如 果 要 使 用 控 制 台 命 令, 进 行 开 发, 还 需 要 进 行 必 要 的 配 置 但 是 在 本 书 中 是 要 借 助 MyEclipse 开 发, 所 以 是 不 需 要 这 一 步 的 1.2 下 载 和 安 装 MySQL 数 据 库 目 前 开 发 中 主 流 的 数 据 库 有 很 多, 例 如 Orcal DB2 SQL Server 和 MySQL 等 其 中 MySQL 数 据 库 体 积 非 常 小, 速 度 非 常 快, 许 多 中 小 型 网 站 为 了 降 低 网 站 总 体 拥 有 成 本 而 选 择 了 MySQL 作 为 网 站 数 据 库 所 以 在 本 书 中 以 MySQL 数 据 库 为 例 进 行 讲 解, 其 他 数 据 库 的 操 作 也 是 类 似 的 1.2.1 下 载 MySQL 数 据 库 MySQL 数 据 库 的 官 方 网 站 地 址 为 http://www.mysql.com/, 在 其 中 可 以 单 击 导 航 栏 中 的 Downloads 选 项, 将 进 入 版 本 选 择 页 面 目 前 MySQL 数 据 库 的 最 新 版 本 为 5.4 版 本, 但 是 还 是 测 试 版 本, 所 以 这 里 我 们 选 择 5.1 版 本 单 击 对 应 的 超 链 接, 将 进 入 MySQL 5.1 下 载 页 面, 然 后 在 其 中 单 击 MySQL Community Server 下 的 Download

按 钮, 将 跳 转 到 选 择 操 作 系 统 版 本 的 页 面, 如 图 1-5 所 示 图 1-5 下 载 MySQL 数 据 库 在 其 中 选 择 Windows 操 作 系 统 后, 其 中 出 现 三 种 形 式 的 版 本, 其 中 包 括 安 装 和 直 接 解 压 就 可 用 的 这 里 选 择 Windows Essentials (x86) 安 装 版 本, 单 击 后 面 的 Download 按 钮, 将 开 始 下 载 该 版 本 的 MySQL 数 据 库 如 果 单 击 Pick a mirror 超 链 接 将 进 入 注 册 MySQL 数 据 库 用 户 的 页 面, 在 其 中 可 以 单 击 No thanks, just take me to the downloads! 超 链 接 跳 过 该 步, 然 后 选 择 某 一 镜 像 进 行 下 载 1.2.2 安 装 MySQL 数 据 库 下 载 MySQL 数 据 库 后, 就 可 以 来 安 装 它 双 击 下 载 的 mysql-essential-5.1.41-win32.msi 文 件, 将 首 先 弹 出 选 择 安 装 类 型 界 面, 如 图 1-6 所 示 图 1-6 安 装 类 型 其 中 Typical 表 示 典 型 版 本, 通 常 就 选 择 该 选 项, 单 击 Next 按 钮, 将 进 入 安 装 界 面, 如 图 1-7 所 示

5 题 1-7 安 装 界 面 其 中 固 定 了 MySQL 的 安 装 位 置, 是 自 动 安 装 在 C 盘 下, 单 击 Install 按 钮, 将 开 始 安 装 MySQL 数 据 库 安 装 结 束 后, 将 出 现 是 否 配 置 服 务 器 的 界 面, 在 其 中 选 择 Configure the MySQL server now ( 立 即 配 置 服 务 器 ) 复 选 框 单 击 Next 按 钮 后, 可 开 始 设 置 数 据 库 服 务 器 相 关 选 项 在 MySQL Server Instance Configuration 配 置 中 选 择 Standard Configuration ( 标 准 设 置 ) 单 选 按 钮 单 击 Next 按 钮 后, 将 进 入 设 置 服 务 器 选 项 的 界 面 在 设 置 服 务 器 选 项 界 面 中 选 择 Install As Windows Service ( 安 装 为 Windows 服 务 ) 和 Include Bin Directory in Windows PATH ( 添 加 Bin 路 径 到 PATH 环 境 变 量 ) 两 个 复 选 框 单 击 Next 按 钮 后, 将 弹 出 设 置 管 理 员 密 码 的 界 面 设 置 管 理 员 密 码 是 非 常 重 要 的, 读 者 一 定 不 要 忘 记 自 己 设 置 的 密 码, 在 后 面 学 习 数 据 库 操 作 和 Hibernate 时, 将 多 次 使 用 到 该 密 码 单 击 Next 按 钮, 系 统 将 结 束 安 装 向 导, 安 装 MySQL 数 据 库 完 成 1.3 下 载 和 安 装 Tomcat 服 务 器 目 前 主 流 的 应 用 服 务 器 也 是 非 常 多 的, 例 如 JBOSS WebLogic Tomcat 等 Tomcat 服 务 器 是 由 Apache 开 源 组 织 开 发 并 维 护 的, 能 够 支 持 JSP 和 Servlet, 以 及 各 种 开 源 框 架 的 开 发 使 用, 而 且 Tomcat 服 务 器 是 免 费 产 品, 并 且 提 供 了 其 源 代 码 所 以 在 Java Web 开 发 中, 经 常 使 用 Tomcat 服 务 器 来 进 行 操 作 下 载 Tomcat 服 务 器 可 以 通 过 Apache 开 源 组 织 的 官 方 网 站 进 行 下 载, 它 的 地 址 为 http://www.apache.org 在 该 网 站 主 页 右 侧 导 航 栏 中 有 很 多 该 开 源 组 织 开 发 的 项 目, 在 其 中 单 击 Tomcat 超 链 接, 将 进 入 Tomcat 项 目 的 首 页 在 Tomcat 项 目 首 页 的 左 侧 Download 列 表 中, 单 击 Tomcat 6.x 超 链 接, 将 进 入 该 版 本 的 下 载 页 面, 如 图 1-8 所 示

图 1-8 下 载 Tomcat 其 中 Binary Distributions 下 的 文 件 都 是 编 译 好 的 二 进 制 文 件, 而 Source Code Distributions 下 面 的 文 件 为 Tomcat 的 源 代 码, 这 里 选 择 下 载 编 译 好 的 二 进 制 文 件 Binary Distributions 下 又 分 为 两 类, 一 类 是 Core 即 Tomcat 核 心, 一 类 是 Deployer 即 Tomcat 部 署 文 件, 这 里 选 择 下 载 Core 下 的 文 件 Core 下 的 文 件 又 分 为 三 种, 一 种 是 zip 格 式 的, 即 Windows 下 的 压 缩 文 件 ; 一 种 是 tar.gz 格 式, 即 Linux 下 的 压 缩 文 件 ; 一 种 是 Windows Service Installer, 即 Windows 安 装 文 件 技 巧 : 在 下 载 Tomcat 时, 最 好 选 择 zip 格 式, 这 样 直 接 解 压 就 可 以 用 了, 也 不 需 要 多 余 的 配 置 但 是 对 于 例 如 MySQL 数 据 库 这 样 的 软 件 而 说, 虽 然 也 有 解 压 缩 的 安 装 文 件, 但 是 最 好 不 要 选 择, 因 为 后 面 还 会 有 配 置, 显 得 更 麻 烦 下 载 zip 格 式 的 Tomcat 后, 解 压 缩 后 就 表 示 安 装 完 成, 可 以 将 它 安 装 在 任 意 目 录 下, 但 是 一 定 要 记 住 该 目 录, 在 后 面 MyEclipse 中 还 要 通 过 该 目 录 配 置 Tomcat 1.4 MyEclipse 的 环 境 搭 建 搭 建 完 最 基 本 的 开 发 工 具 后, 就 可 以 来 安 装 本 书 最 重 要 的 MyEclipse 在 学 习 MyEclipse 之 前, 读 者 可 能 接 触 过 Eclipse 单 纯 的 Eclipse 只 能 进 行 Java 桌 面 开 发, 如 果 要 进 行 Java Web 开 发, 还 需 要 安 装 Eclipse 插 件 众 多 软 件 厂 商 和 开 源 组 织 开 发 了 相 应 的 插 件, 其 中 以 MyEclipse 插 件 最 为 出 名 并 常 用 注 意 :MyEclipse 的 更 新 在 近 两 年 是 非 常 快 的, 目 前 已 经 出 现 了 8.0 版 本, 但 是 发 布 稳 定 的 最 新 版 本 是 7.5 如 果 读 者 本 地 已 经 安 装 了 6.0 以 上 版 本 的 MyEclipse, 完 全 可 以 使 用 原 版 本 的 MyEclipse 进 行 学 习, 它 们 的 差 别 是 不 大 的

7 1.4.1 下 载 和 安 装 MyEclipse MyEclipse 的 官 方 网 站 为 http://www.myeclipseide.com, 因 为 MyEclipse 是 一 款 非 开 源 的 开 发 工 具, 所 以 只 能 在 官 方 网 站 中 下 载 试 用 版 进 入 官 方 网 站 后, 单 击 左 边 导 航 栏 中 的 Try/Download 链 接, 打 开 下 载 页 面, 然 后 在 其 中 选 择 MyEclipse 7.5GA, 如 图 1-9 所 示 图 1-9 MyEclipse 7.5GA 下 载 页 面 MyEclipse 7.5GA 的 安 装 分 为 两 种, 一 种 是 All in ONE 版 本, 一 种 是 pulse 版 本 其 中 All in ONE 版 本 包 含 MyEclipse 安 装 的 全 部 文 件, 而 pulse 版 本 为 插 件 安 装 版 本, 需 要 事 先 安 装 好 了 相 应 的 Eclipse 这 里 为 了 安 装 方 便, 选 择 下 载 其 中 的 All in ONE 版 本 技 巧 :MyEclipse 的 官 方 网 站 经 常 打 不 开, 可 以 通 过 代 理 服 务 器 进 行 访 问, 也 可 以 在 网 络 中 进 行 搜 索, 查 找 国 内 的 下 载 资 源 进 行 下 载 下 载 完 成 MyEclipse 后, 就 可 以 双 击 下 载 文 件 进 行 安 装 MyEclipse 的 安 装 是 非 常 简 单 的, 它 的 安 装 实 际 上 就 是 将 其 中 的 文 件 解 压 缩 到 硬 盘 中 首 先 出 现 的 是 许 可 证 协 议 界 面, 在 其 中 选 择 I accept the terms of the license agreement, 单 击 Next 按 钮, 将 弹 出 选 择 安 装 目 录 的 界 面, 默 认 是 安 装 在 C 盘, 也 可 以 安 装 在 其 他 地 方 后 面 的 操 作, 只 需 要 单 击 Next 按 钮, 就 能 够 进 行 安 装 MyEclipse 的 安 装 时 要 花 费 一 定 时 间 的, 当 出 现 安 装 完 成 页 面 后, 单 击 Finish 按 钮, 将 彻 底 完 成 MyEclipse 的 安 装 1.4.2 运 行 MyEclipse 安 装 MyEclipse 后, 在 桌 面 上 就 出 现 一 个 启 动 MyEclipse 的 快 捷 方 式, 它 的 图 标 为 双 击 该 快 捷 方 式, 将 开 始 运 行 MyEclipse, 首 先 出 现 的 将 是 定 义 工 作 空 间 的 界 面, 如 图 1-10 所 示

图 1-10 工 作 空 间 工 作 空 间 就 是 用 来 放 置 Java 项 目 文 件 的 目 录, 可 以 任 意 指 定 单 击 Browse 按 钮, 可 以 指 定 当 前 计 算 机 中 的 目 录 下 面 的 Use this as the default and do not ask again, 表 示 是 否 将 当 前 指 定 的 工 作 空 间 做 为 默 认 空 间, 当 选 中 该 选 项 后, 下 次 启 动 MyEclipse 时 就 不 会 提 醒 该 界 面, 从 而 以 当 前 设 置 的 工 作 空 间 启 动 选 择 某 目 录 做 为 工 作 空 间 后, 单 击 OK 按 钮, 将 开 始 启 动 MyEclipse 启 动 MyEclipse 是 要 花 费 一 定 时 间 的, 尤 其 是 当 计 算 机 内 存 比 较 小 时 启 动 MyEclipse 后, 界 面 如 图 1-11 所 示 图 1-11 初 始 界 面 在 MyEclipse 的 初 始 启 动 界 面 中, 将 由 一 个 初 始 布 局, 它 通 常 被 称 为 透 视 图 透 视 图 是 可 以 改 变 的, 可 以 通 过 右 上 角 的 按 钮, 也 可 以 通 过 Window 菜 单 在 后 面 的 讲 解 中, 如 果 用 到 其 他 透 视 图 再 详 细 讲 解 在 一 个 透 视 图 中, 由 多 个 视 图 界 面 组 成, 当 前 MyEclipse 默 认 透 视 图 下, 就 有 以 后 经 常 用 到 的 Package Explo 包 资 源 管 理 器 视 图 界 面 和 Console 控 制 台 视 图 界 面 在 MyEclipse 中, 除 了 视 图 界 面 外, 最 上 部 还 有 菜 单 和 工 具 栏, 在 后 面 的 学 习 中,

9 主 要 是 通 过 它 们 进 行 MyEclipse 的 操 作 当 讲 解 具 体 操 作 时, 我 们 再 对 它 们 进 行 详 细 的 功 能 讲 解 1.5 开 发 HelloWorld 程 序 在 前 面 的 讲 解 中, 已 经 将 开 发 环 境 搭 建 成 功 了, 并 且 已 经 对 MyEclipse 的 每 一 部 分 有 所 了 解 在 本 节 中, 就 来 看 一 下 如 何 使 用 MyEclipse 进 行 项 目 开 发 在 这 里 将 要 开 发 一 个 非 常 简 单 的 HelloWorld 的 Java SE 项 目 1.5.1 创 建 Java 项 目 如 果 不 使 用 MyEclipse 开 发 工 具, 而 是 使 用 记 事 本 开 发 Java 程 序, 那 就 不 需 要 创 建 项 目, 只 需 要 使 用 javac 和 java 命 令 就 可 以 对 Java 程 序 进 行 编 译 和 运 行 但 是 在 MyEclipe 进 行 Java 程 序 开 发, 就 需 要 先 来 创 建 一 个 Java 项 目 在 MyEclipse 的 菜 单 中, 选 择 File New Java Project 命 令, 就 会 弹 出 创 建 Java 项 目 的 界 面, 如 图 1-12 所 示 图 1-12 创 建 Java 项 目 在 创 建 Java 项 目 的 界 面 中, Project name 的 文 本 框 用 来 输 入 新 创 建 Java 项 目 的 项 目 名 称, 这 里 我 们 输 入 HelloWorld 除 此 之 外, 还 有 对 新 建 项 目 进 行 设 置 的 选 项,

依 次 是 创 建 项 目 的 位 置 项 目 使 用 的 JRE 项 目 布 局 和 工 作 集 下 面 我 们 对 每 一 个 选 项 进 行 简 单 讲 解 Creat new project in workspace: 在 工 作 空 间 内 创 建 项 目, 这 是 推 荐 使 用 的 Creat project from existing source: 在 现 有 位 置 中 创 建 项 目, 如 果 选 择 该 选 项, 则 需 要 单 击 Browse 按 钮, 然 后 选 择 项 目 放 置 的 位 置 Use default JRE(Currently com.sun.java.jdk.win32.x86_1.6.0.013 ): 使 用 MyEclipse 默 认 的 JRE, 在 开 发 过 程 中 使 用 该 选 项 就 可 以 Use a project specific JRE: 选 择 项 目 使 用 的 JRE, 其 中 的 选 项 就 是 目 前 MyEclipse 中 已 经 配 置 的 JRE Use an execution environment JRE: 使 用 项 目 运 行 时 选 择 的 JRE Use project folder as root for sources and class files: 使 用 项 目 目 录 做 为 源 文 件 和 编 译 后 的 文 件 根 目 录 使 用 该 选 项 造 成 的 后 果 就 是.java 文 件 和.class 文 件 在 一 个 目 录 中 Create separate folders for sources and class files: 分 开 存 放 源 文 件 和 编 译 后 的 文 件, 默 认 选 择 该 选 项, 也 是 推 荐 使 用 的 Add project to working sets: 添 加 项 目 到 工 作 集 中, 如 果 选 择 该 选 项, 则 需 要 指 定 要 添 加 到 的 工 作 集 通 常 情 况 下 并 不 进 行 工 作 集 操 作, 从 而 也 就 不 选 择 它 从 上 面 的 讲 解 中 可 以 看 到 只 需 要 填 写 项 目 名 称, 其 他 采 用 MyEclipse 默 认 的 选 择 就 可 以 在 创 建 Java 项 目 中 可 以 直 接 单 击 Finisth 按 钮 完 成 创 建 Java 项 目 的 操 作 ; 也 可 以 单 击 Next 按 钮, 继 续 对 Java 项 目 进 行 设 置, 如 图 1-13 所 示

11 图 1-13 创 建 项 目 设 置 在 创 建 项 目 设 置 界 面 中, 可 以 在 选 项 卡 中 对 源 代 码 项 目 库 和 排 序 导 出 进 行 设 置, 这 些 在 后 面 的 讲 解 中 会 学 习 到 在 界 面 的 最 下 面 是 设 置 防 止 编 译 后 文 件 的 文 件 夹, 通 常 我 们 就 是 用 bin 这 个 名 称 单 击 Finish 按 钮, 就 会 完 成 创 建 Java 项 目 的 操 作, 但 是 会 填 出 一 个 选 择 视 图 的 界 面, 如 图 1-14 所 示 图 1-14 项 目 的 视 图 选 择 该 选 择 视 图 界 面 是 让 用 户 选 择 是 否 采 用 Java 视 图 进 行 开 发, 如 果 采 用, 则 单 击 Yes 按 钮 通 常 情 况 下, 我 们 仍 然 采 用 MyEclipse 视 图, 这 是 每 一 个 程 序 员 的 习 惯 有 关 这

里 单 击 No 按 钮, 也 就 是 不 采 用 Java 视 图, 而 是 采 用 MyEclipse 视 图 经 过 上 面 的 操 作, 就 在 MyEclipse 的 工 作 空 间 中 创 建 了 一 个 名 称 为 HelloWorld 的 Java 项 目 该 项 目 会 出 现 在 包 资 源 管 理 器 中, 单 击 项 目 前 的 加 号, 可 以 讲 项 目 中 的 内 容 展 开, 如 图 1-15 所 示 图 1-15 项 目 文 件 结 构 在 生 成 的 项 目 文 件 结 构 中,src 目 录 就 是 用 户 放 置 Java 源 文 件 的 目 录, 下 面 的.jar 文 件 就 是 该 项 目 采 用 的 JRE 文 件, 这 些 都 是 MyEclipse 为 我 们 自 动 生 成 的 说 明 : 在 MyEclipse 中, 创 建 项 目 或 者 程 序 都 有 多 种 方 式 例 如 本 小 节 学 习 的 创 建 Java 项 目 就 有 另 外 一 种 方 式, 在 包 资 源 管 理 器 中 的 空 白 处, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中, 选 择 New Java Project 命 令, 同 样 能 够 进 入 创 建 Java 项 目 的 界 面 中 1.5.2 创 建 Java 类 程 序 创 建 Java 项 目 后, 就 可 以 再 Java 项 目 中 创 建 Java 类 程 序 在 MyEclipse 中, 选 择 File New Class 命 令, 就 会 出 现 创 建 Java 类 程 序 界 面, 如 图 1-16 所 示

13 图 1-16 创 建 Java 程 序 在 创 建 Java 程 序 界 面 中, Source folder 表 示 源 代 码 保 存 的 位 置 Package 表 示 Java 程 序 所 在 的 包, 这 里 我 们 先 采 用 默 认 的 无 包 情 况 Name 表 示 类 名, 这 里 我 们 输 入 Hello, 这 样 就 创 建 了 一 个 名 称 为 Hello 的 类 Modifiers 表 示 类 的 修 饰 符, 在 访 问 修 饰 符 中 可 以 选 择 public 或 者 default, 分 别 是 创 建 公 共 类 和 默 认 访 问 修 饰 类 ; 在 非 访 问 修 饰 符 中 可 以 选 择 abstract 和 final, 虽 然 这 里 将 它 们 设 置 为 复 选 框, 但 是 这 两 个 修 饰 符 是 不 能 同 时 存 在 的 Superclass 表 示 新 创 建 的 类 所 继 承 的 父 类, 因 为 Java 中 的 所 有 的 类 都 继 承 java.lang.object 类, 所 以 默 认 新 建 类 也 是 继 承 它 的, 这 里 也 可 以 输 入 其 他 的 父 类, 或 者 单 击 Browse 按 钮 选 择 要 继 承 的 父 类 Interfaces 表 示 新 创 建 类 所 实 现 的 接 口, 单 击 Add 按 钮 可 以 添 加 要 实 现 的 接 口 因 为 一 个 类 可 以 继 承 多 个 接 口, 所 以 该 操 作 可 以 进 行 任 意 次 如 果 接 口 添 加 错 误, 也 可 以 单 击 Remove 按 钮, 将 选 中 的 接 口 删 除 接 下 来 的 选 项 是 让 程 序 员 选 择 在 程 序 中 创 建 哪 些 方 法 或 者 程 序 段 第 1 个 选 项 就 是 选 择 新 建 Java 类 中 是 否 创 建 main 方 法, 该 方 法 是 Java 程 序 的 入 口 方 法, 这 里 我 们 选 中 该 选 项 第 2 个 选 项 表 示 是 否 生 成 和 父 类 中 相 同 的 构 造 函 数 第 3 个 选 项 表 示 是 否 继 承 抽 象 方 法, 该 抽 象 方 式 可 能 来 自 抽 象 父 类, 也 可 能 来 自 实 现 的 类, 如 果 定 义 的 是 非 抽 象 类, 则 会 自 动 将 抽 象 方 法 实 现 经 过 上 面 的 填 写 和 选 择, 单 击 Finish 按 钮, 就 会 创 建 一 个 类 名 为 Hello, 具 有 main 方 法 的 Java 程 序 创 建 Java 类 程 序 后, 包 资 源 管 理 器 和 编 辑 区 都 会 发 生 改 变,

如 图 1-17 是 包 资 源 管 理 器 的 变 化 图 1-17 包 资 源 管 理 器 的 变 化 从 图 中 可 以 看 到 在 src 下 创 建 了 一 个 Hello.java 文 件, 其 中 default package 并 不 是 包 名, 而 是 只 默 认 包, 也 就 是 没 有 使 用 包 创 建 Java 类 程 序 后, 同 时 会 在 编 辑 区 中 将 创 建 的 Java 类 程 序 的 代 码 显 示 出 来, 代 码 内 容 如 下 : 01 public class Hello { 02 /** 03 * @param args 04 */ 05 public static void main(string[] args) { 06 // TODO Auto-generated method stub 07 } 08 } 其 中 唯 一 改 变 的 就 是 将 其 中 的 空 行 去 掉 在 第 1 行 中 定 义 了 一 个 公 共 的 类, 类 名 为 Hello, 从 第 2 行 到 第 4 行 和 第 6 行 都 是 自 动 生 成 的 注 释 第 5 行 是 我 们 在 创 建 Java 类 程 序 界 面 中 选 择 main 方 法 后 自 动 生 成 的, 如 果 不 选 择 该 选 项, 是 不 会 出 现 该 main 方 法 的 将 其 中 的 第 6 行 注 释 去 掉, 换 成 下 面 的 代 码 : System.out.println("Hello World!!!"); 这 样 Java 类 程 序 就 开 发 完 成 技 巧 : 除 了 这 种 创 建 Java 程 序 的 方 式 外, 还 有 另 外 一 种 更 好 的 方 式, 那 就 是 在 Java 程 序 要 放 置 的 程 序 或 者 包 目 录 上, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中 选 择 New Class 命 令 这 种 方 式 的 好 处 是 直 接 指 定 程 序 的 位 置, 如 果 采 用 菜 单 的 方 式 创 建, 经 常 还 需

15 要 指 定 程 序 位 置 1.5.3 运 行 Java 类 程 序 如 果 不 使 用 MyEclipse 等 集 成 开 发 工 具, 运 行 Java 类 程 序 需 要 使 用 javac 和 java 命 令 如 果 使 用 MyEclipse 开 发 工 具, 它 已 经 将 javac 和 java 命 令 集 成 在 MyEclipse 开 发 工 具 中, 编 译 时 自 动 完 成 的, 也 就 是 说 自 动 生 成 了.class 文 件 这 里 主 要 是 关 心 如 果 运 行 Java 类 程 序, 这 是 需 要 程 序 员 操 作 完 成 的 运 行 Java 类 程 序 有 多 种 方 式, 分 别 是 菜 单 工 具 栏 和 弹 出 菜 单 三 种 方 式 在 MyEclipse 的 菜 单 中, 选 择 Run Run 命 令, 如 果 在 编 写 Java 类 程 序 时 没 有 保 存, 则 会 弹 出 如 图 1-18 的 界 面 图 1-18 选 择 运 行 界 面 因 为 目 前 项 目 中 只 有 Hello.java 这 一 个 类 程 序 处 于 编 写 状 态, 如 果 有 多 个 程 序, 则 都 会 列 在 该 界 面 中, 从 而 选 择 运 行 的 程 序 选 择 后, 单 击 OK 按 钮, 从 而 运 行 选 中 的 程 序 如 果 编 写 的 Java 程 序 已 经 保 存, 则 选 择 Run Run 命 令 后, 直 接 运 行 当 前 保 存 的 程 序 记 忆 : 运 行 程 序 的 快 捷 键 是 Ctrl+F11 在 MyEclipse 中, 大 部 分 操 作 都 有 对 应 的 快 捷 键, 通 过 这 些 快 捷 键 能 够 大 大 加 快 程 序 开 发 速 度 运 行 Java 类 程 序 后, 会 将 运 行 结 果 显 示 到 位 于 MyEclipse 最 下 面 的 控 制 台 中, 如 图 1-19 所 示

图 1-19 控 制 台 其 中 Hello World!!! 就 是 上 一 小 节 中 创 建 的 Java 类 程 序 的 运 行 结 果 说 明 : 除 了 通 过 菜 单 运 行 Java 类 程 序 外, 还 可 以 通 过 工 具 栏 中 的 运 行 按 钮 执 行 直 接 单 击 该 按 钮, 是 对 上 次 运 行 的 程 序 再 次 运 行, 这 通 过 用 在 开 发 过 程 中, 如 果 想 运 行 其 他 程 序, 需 要 通 过 旁 边 的 下 三 角 进 行 选 择 在 编 辑 区 中, 可 以 单 击 鼠 标 右 键, 在 弹 出 菜 单 中, 选 择 Run As Java Application 命 令 对 当 前 程 序 进 行 运 行 1.6 开 发 接 口 程 序 在 上 一 节 中, 我 们 讲 解 了 如 何 进 行 Java 类 程 序 开 发 在 Java 程 序 中, 除 了 类 之 外, 还 有 接 口, 它 也 是 非 常 重 要 的 在 本 节 中, 就 来 学 习 一 下 如 何 创 建 接 口, 以 及 相 关 的 包 和 实 现 接 口 的 类, 这 些 在 Java 项 目 的 开 发 中 都 是 非 常 重 要 的 1.6.1 创 建 包 在 前 面 学 习 创 建 Java 类 程 序 时, 并 没 有 使 用 到 包, 而 是 直 接 放 在 src 目 录 下 在 本 小 节 中 就 来 看 一 下 在 MyEclipse 如 何 创 建 包 在 MyEclipse 菜 单 中, 选 择 File New Package 命 令, 就 会 进 入 创 建 包 界 面, 如 图 1-20 所 示 图 1-20 创 建 包

17 其 中 Source folder 表 示 包 定 义 的 所 在 位 置, Name 表 示 定 义 的 包 名 这 里 的 包 名 可 以 是 一 个 单 词, 例 如 service, 就 是 创 建 一 个 名 称 为 service 的 包, 使 用 该 包 通 常 保 存 Web 项 目 中 的 业 务 逻 辑 层 接 口 包 名 也 可 以 是 多 个 单 词, 中 间 使 用. 连 接, 这 样 表 示 级 联 包, 也 就 是 在 包 下 再 创 建 子 包 例 如 service.impl, 表 示 在 service 包 下 再 创 建 一 个 名 称 为 impl 的 子 包, 使 用 该 包 通 常 保 存 Web 项 目 中 的 业 务 逻 辑 层 实 现 类 开 发 完 上 面 两 个 包 后, 包 资 源 管 理 器 如 图 1-21 所 示 图 1-21 创 建 包 后 从 图 中 可 以 看 到 service 和 service.impl 两 个 包 都 已 经 创 建 成 功 了 在 包 资 源 管 理 器 中 还 有 另 外 一 种 显 示 方 式, 单 击 右 上 角 的 倒 三 角, 选 择 Package Presentation 命 令, 在 该 命 令 下 有 两 个 选 项, 分 别 是 Flat 和 Hierarchical, 它 们 表 示 两 种 显 示 包 的 方 式 默 认 的 是 Flat 方 式, 也 就 是 包 平 面 显 示 方 式, 将 所 有 的 包 并 列 进 行 显 示, 例 如 上 面 的 图 Hierarchical 方 式 是 指 分 层 方 式, 也 就 是 将 子 包 放 在 包 下 我 们 将 包 显 示 方 式 选 择 为 Hierarchical 方 式, 则 包 资 源 管 理 器 变 化 如 图 1-22 所 示 图 1-22 分 层 方 式 显 示 包

从 结 果 中 可 以 看 到 将 两 个 包 重 叠 在 一 起, 这 是 因 为 目 前 包 中 并 没 有 任 何 Java 程 序 造 成 的 结 果 在 后 面 创 建 Java 程 序 后, 读 者 可 以 再 来 进 行 切 换 包 显 示 方 式 操 作 1.6.2 创 建 接 口 接 口 也 是 Java 程 序 中 必 不 可 少 的 一 部 分 在 上 一 小 节 中, 已 经 创 建 了 service 和 service.impl 两 个 包, 在 本 小 节 中 就 在 service 包 下 创 建 一 个 接 口 在 MyEclipse 中 创 建 接 口 也 有 多 种 方 式, 最 常 用 的 就 是 菜 单 和 右 键 弹 出 菜 单 两 种 方 式, 因 为 我 们 这 里 要 将 接 口 创 建 在 指 定 的 包 下, 所 以 建 议 采 用 右 键 弹 出 菜 单 的 方 式 在 service 包 目 录 上, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New Interface 命 令, 就 会 弹 出 创 建 接 口 界 面, 如 图 1-23 所 示 图 1-23 创 建 接 口 界 面 在 创 建 接 口 界 面 中, Source folder 表 示 创 建 的 接 口 程 序 所 在 目 录, Package 表 示 创 建 的 接 口 所 在 的 包, 如 果 采 用 右 键 菜 单 的 方 式 创 建, 会 自 动 出 现 选 择 的 包, 例 如 这 里 的 Service Name 表 示 创 建 的 接 口 名, 这 里 我 们 填 写 UserService, 也 就 是 用 户 业 务 逻 辑 接 口 Modifiers 表 示 接 口 的 修 饰 符, 这 里 可 以 在 public 公 共 修 饰 符 和 默 认 修 饰 符 之 间 选 择 Extended interfaces 表 示 新 建 接 口 继 承 的 父 接 口, 父 接 口 可 以 由 多 个, 单 击 Addd 按 钮 完 成 添 加 填 写 上 述 信 息 后, 单 击 Finish 按 钮, 就 会 完 成 接 口 的 创 建, 从 而 创 建 一 个 接 口 名 为 UserService 的 接 口, 并 在 编 辑 区 中 将 自 动 生 成 的 接 口 代 码 显 示 出 来, 如 下 : 01 package service;

19 02 public interface UserService { 03 04 } 从 代 码 中 可 以 看 到, 在 第 1 行 中 指 定 接 口 所 在 的 包 在 其 中 第 3 行 加 入 用 于 判 断 用 户 是 否 能 够 登 录 的 方 法, 如 下 : public boolean login(string username,string password); 这 样 我 们 的 一 个 接 口 就 创 建 完 成 了 1.6.3 创 建 实 现 接 口 的 类 在 本 小 节 中 就 来 学 习 一 下 如 何 创 建 实 现 接 口 的 类, 这 和 前 面 创 建 普 通 的 类 是 有 所 不 同 的, 我 们 也 就 该 类 创 建 在 包 下 在 service.impl 包 上, 或 者 在 impl 子 包 上, 单 击 鼠 标 右 键, 在 弹 出 的 右 键 菜 单 中, 选 择 New Class 命 令, 将 弹 出 创 建 Java 类 界 面, 如 图 1-24 所 示 图 1-24 创 建 实 现 接 口 的 类 因 为 我 们 是 通 过 在 包 上 的 右 键 菜 单 进 行 创 建, 所 以 会 将 包 自 动 添 加 上 在 Name 中 填 写 UserServiceImpl, 表 示 用 户 业 务 逻 辑 实 现 类 该 类 要 实 现 上 一 小 节 创 建 的 用 户 业 务 逻 辑 接 口, 所 以 要 在 Interfaces 中, 单 击 Add 按 钮, 弹 出 如 图 1-25 的 选 择 接 口 界 面

图 1-25 选 择 要 实 现 的 接 口 在 界 面 中 输 入 要 实 现 的 接 口, 则 在 下 面 会 将 可 以 选 择 的 接 口 列 出 来, 如 果 在 不 同 的 包 中 具 有 同 样 名 称 的 接 口, 则 都 会 列 在 下 面, 并 且 在 接 口 名 的 后 面 还 会 列 出 包 名 选 择 要 实 现 的 接 口, 单 击 OK 按 钮, 就 会 完 成 接 口 的 添 加, 并 且 将 接 口 显 示 到 创 建 类 界 面 中 注 意 : 一 定 要 保 持 创 建 Java 类 程 序 界 面 中 Inherited abstract methods 选 项 的 选 中 状 态 因 为 接 口 中 有 抽 象 方 法, 在 实 现 该 接 口 的 类 中 要 实 现 该 方 法, 通 过 该 选 项 可 以 自 动 实 现 抽 象 方 法, 不 然 需 要 手 动 编 写 单 击 创 建 Java 类 程 序 界 面 中 的 Finish 按 钮, 创 建 实 现 接 口 的 类 的 操 作 就 完 成, 并 且 将 它 的 代 码 显 示 到 编 辑 区 中, 代 码 如 下 : 01 package service.impl; 02 import service.userservice; 03 public class UserServiceImpl implements UserService { 04 public boolean login(string username, String password) { 05 // TODO Auto-generated method stub 06 return false; 07 } 08 } 上 述 代 码 都 是 自 动 生 成 的 代 码, 其 中 第 1 行 是 包 定 义 代 码, 指 定 新 创 建 的 类 在 service.impl 包 下 第 2 行 和 第 3 行 自 动 让 新 创 建 的 类 实 现 UserService 接 口, 如 果 该 接 口 和 实 现 类 不 在 同 一 包 下, 还 会 自 动 导 入 接 口 第 4 行 是 自 动 实 现 接 口 中 的 抽 象 方 法, 程 序 员 可 以 在 其 中 添 加 自 己 的 业 务 操 作

北 风 网 讲 师 原 创 作 品 ----- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 2 章 常 用 开 发 操 作 和 技 巧 在 上 一 章 中 对 MyEclipse 有 了 基 本 了 解 一 下, 在 本 章 中 就 来 学 习 一 些 非 常 重 要 的 常 用 开 发 操 作 和 技 巧 这 些 都 是 后 面 学 习 具 体 开 发 技 术 的 基 础 根 据 操 作 的 内 容 不 同, 可 以 讲 这 些 操 作 分 为 几 类, 例 如 配 置 方 面 的 操 作 源 代 码 方 面 的 操 作, 以 及 包 围 方 式 2.1 常 用 配 置 操 作 MyEclipse 是 一 种 视 图 话 的 开 发 工 具, 所 以 我 们 进 行 设 置 操 作 时 主 要 是 通 过 配 置 的 手 段 来 完 成 这 方 面 的 知 识 点 是 比 较 零 散 的, 而 且 后 面 的 操 作 要 基 于 其 中 的 某 些 配 置, 所 以 我 们 把 这 些 配 置 操 作 先 进 行 讲 解 2.1.1 显 示 行 号 因 为 后 面 讲 解 代 码 时, 经 常 要 说 代 码 的 行 号 的, 所 以 先 来 看 一 下 如 何 为 MyEclipse 中 的 代 码 加 行 号 在 MyEclipse 的 菜 单 中, 选 择 Window Preferences 命 令, 会 弹 出 进 行 设 置 的 界 面, 如 图 2-1 所 示 图 2-1 首 选 项 设 置 在 MyEclipse 中, 大 部 分 的 设 置 都 是 通 过 首 选 项 设 置 界 面 完 成 的 在 其 中 的 左 侧 菜 单 中, 选 择 General Editors Text Editors 命 令, 则 首 选 项 设 置 界 面 如 图 2-2

所 示 图 2-2 设 置 行 号 其 中 Show line numbers 选 项 就 是 用 来 设 置 是 否 显 示 行 号, 选 中 该 选 项, 单 击 OK 按 钮, 就 会 在 MyEclipse 的 编 辑 区 中, 显 示 行 号 说 明 : 显 示 代 码 的 行 号, 还 有 另 外 一 种 简 单 的 设 置 方 法, 那 就 是 在 编 辑 区 的 左 边 界 上, 单 击 右 键, 在 其 中 选 中 Show line numbers 选 项, 从 而 进 行 设 置 具 体 操 作 可 以 观 看 本 书 随 书 光 盘 2.2.2 改 变 编 码 类 型 在 计 算 机 的 信 息 传 输 中, 都 是 通 过 字 节 流 的 形 式 传 递 的, 在 其 中 就 要 用 到 一 个 非 常 重 要 的 概 念, 那 就 是 编 码 通 过 编 码 可 以 讲 文 字 转 换 为 字 节, 也 可 以 讲 字 节 再 转 换 为 文 字 目 前 计 算 机 中 有 多 种 编 码 形 式, 两 种 不 兼 容 的 编 码 是 不 能 够 结 合 使 用 的 例 如 A 编 码 中,123 代 表 书 这 个 字, 我 们 要 传 递 书 这 个 字 时, 接 收 的 就 是 123 但 是 在 反 转 换 时 使 用 的 是 B 编 码, 但 是 在 B 编 码 中,123 对 应 的 是 纸 这 个 字, 那 它 得 到 的 信 息 就 是 纸 这 个 字 了 这 样 就 造 成 传 输 信 息 的 失 败 在 计 算 机 的 操 作 中, 经 常 会 出 现 乱 码 的 情 况, 这 就 和 使 用 的 编 码 有 关 在 MyEclipse 中, 我 们 写 代 码 时 也 会 使 用 到 某 一 种 编 码, 在 团 队 开 发 中 一 定 要 使 用 同 一 种 编 码, 在 本 节 中 就 来 学 习 一 下 如 何 改 变 编 码 类 型

3 在 首 选 项 设 置 界 面 中, 选 择 General Editors Text Editors Spelling 命 令, 就 会 出 现 如 图 2-3 所 示 的 界 面 图 2-3 设 置 编 码 规 则 其 中 Encoding 选 项 就 是 用 来 设 置 代 码 的 编 码 规 则 的, 当 前 默 认 编 码 是 GBK 如 果 想 换 为 其 他 编 号, 可 以 选 择 Other 选 项, 然 后 在 后 面 的 下 拉 列 表 中 选 择 相 应 的 编 码 这 样 就 完 成 改 变 编 码 类 型 的 操 作 说 明 : 在 MyEclipse 中, 还 可 以 为 每 一 种 程 序 进 行 相 应 的 编 码 设 置, 例 如 JSP HTML CSS 等 在 后 面 学 习 具 体 每 一 种 技 术 时 再 进 行 讲 解 2.2.3 导 入 项 目 在 项 目 开 发 中, 经 常 使 用 到 不 同 工 作 空 间 的 两 个 项 目, 或 者 别 人 发 过 来 的 项 目 不 在 工 作 空 间 中, 这 时 候 就 要 用 到 导 入 项 目 的 操 作 通 过 这 种 操 作 可 以 将 项 目 导 入 到 当 前 工 作 空 间 中, 并 显 示 到 MyEclipse 中 在 MyEclipse 的 菜 单 中, 选 择 File Import 命 令, 就 会 进 入 导 入 界 面, 如 图 2-4 所 示

图 2-4 导 入 界 面 在 其 中 选 择 General Existing Projects into Workspace 命 令, 单 击 Next 按 钮, 就 会 进 入 导 入 项 目 的 界 面, 如 图 2-5 所 示 图 2-5 导 入 项 目 界 面 其 中 Select root directory 表 示 选 择 项 目 的 根 目 录, Select archive file 表 示 选

5 择 归 纳 文 件 在 Select root directory 选 项 后, 单 击 Browse 按 钮, 在 界 面 中 可 以 选 择 项 目 的 根 目 录, 也 可 以 选 择 项 目 所 在 的 目 录 如 果 选 择 的 是 项 目 的 根 目 录, 表 示 将 该 项 目 导 入 ; 如 果 选 择 的 是 项 目 所 在 目 录, 就 会 将 该 目 录 下 所 有 的 项 目 导 入 导 入 到 下 面 的 文 本 域 中 后, 还 可 以 通 过 Select All Deselect All 和 Refresh 按 钮 进 行 相 应 操 作 最 后 单 击 Finish 按 钮, 从 而 完 成 导 入 项 目 的 操 作, 在 MyEclipse 中 可 以 看 到 刚 才 选 择 的 项 目 已 经 出 现 在 其 中 2.2.4 导 出 项 目 在 MyEclipse 中, 可 以 将 项 目 导 入 进 来, 也 可 以 将 当 前 项 目 导 入 到 指 定 目 录 下 在 MyEclipse 菜 单 中, 选 择 File Export 命 令, 就 会 进 入 导 入 界 面, 如 图 2-6 所 示 图 2-6 导 出 界 面 在 其 中 选 择 General Archive File 选 项, 单 击 Next 按 钮, 就 会 进 入 导 出 项 目 界 面, 如 图 2-7 所 示

图 2-7 导 出 项 目 界 面 在 导 出 项 目 界 面 中, 在 左 上 角 选 择 你 要 导 出 的 项 目, 这 里 我 们 选 择 上 一 章 创 建 的 HelloWorld 项 目 在 To archive file 选 项 中, 选 择 要 到 处 的 位 置 这 里 通 常 到 处 为 以 项 目 名 为 文 件 名 的 ZIP 文 件 最 后 单 击 Finish 按 钮, 从 而 在 指 定 的 位 置 出 现 一 个 文 件 名 为 HelloWorld.zip 的 文 件, 从 而 完 成 导 出 项 目 的 操 作 2.2.5 修 正 代 码 错 误 MyEclipse 是 一 种 功 能 非 常 强 大 的 集 成 开 发 工 具, 它 会 自 动 提 醒 程 序 开 发 过 程 中 出 现 的 错 误, 在 出 现 错 误 的 代 码 行 上 以 红 叉 的 形 式 标 识, 如 图 2-8 所 示 图 2-8 错 误 提 示 在 该 UserServiceImpl 类 程 序 中, 并 没 有 为 login 方 法 定 义 返 回 值, 所 以 出 现 了 错 误 在 MyEclipse 中, 具 有 对 这 种 错 误 快 速 处 理 的 方 法 单 击 代 码 左 面 的 红 叉, 如 图 2-9 所 示

7 图 2-9 修 改 代 码 错 误 从 图 中 可 以 看 到, 当 单 击 红 叉 时, 会 弹 出 一 个 窗 口, 给 出 两 种 解 决 该 错 误 的 方 法 第 一 种 是 增 加 一 个 返 回 语 句 ; 第 二 种 是 改 变 方 法 的 返 回 类 型 为 void 并 在 后 面 的 窗 口 中 给 出 修 改 后 的 部 分 代 码 具 体 选 择 哪 一 种 修 正 方 式, 由 程 序 员 根 据 实 际 需 要 进 行 选 择, 并 不 是 所 有 的 修 正 方 式 都 是 合 适 的 记 忆 : 修 改 代 码 错 误 的 快 捷 键 是 Ctrl+1, 但 是 一 定 要 首 先 将 鼠 标 放 在 出 现 错 误 的 一 行 才 能 够 使 用 快 捷 键 使 用 快 捷 键 的 效 果 和 单 击 红 叉 的 效 果 相 同 的 说 明 : 在 MyEclipse 中, 除 了 会 显 示 程 序 中 的 错 误 外, 还 会 对 程 序 的 一 些 地 方 提 出 警 告, 在 这 代 码 的 最 左 端 以 点 亮 的 灯 泡 的 形 式 标 识 警 告 并 不 是 错 误, 只 是 给 出 一 种 建 议, 例 如 使 用 集 合 时, 如 果 没 有 使 用 泛 型, 就 会 给 出 警 告 2.2.6 JRE 相 关 操 作 JRE 是 运 行 Java 程 序 所 必 须 的 环 境 集 合, 如 果 只 需 要 运 行 Java 程 序, 只 使 用 JRE 就 可 以 如 果 还 需 要 开 发 Java 程 序, 就 要 使 用 到 前 面 安 装 的 JDK 安 装 MyEclipse 后, 在 MyEclipse 中 就 已 经 存 在 一 个 默 认 的 JRE 但 是 如 果 想 使 用 最 新 版 本 的 JRE, 或 者 想 得 到 更 多 的 源 码 信 息, 就 要 自 己 添 加 JRE 在 首 选 项 设 置 界 面 中, 选 择 Java Installed JREs 命 令, 就 会 出 现 设 置 JRE 界 面, 如 图 2-10 所 示

图 2-10 设 置 JRE 在 其 中 可 以 看 到 默 认 选 中 的 是 名 称 为 com.sun.java.jdk.win32.x86_1.6.0.013 的 JRE, 这 就 是 MyEclipse 默 认 的 JRE 单 击 Add 按 钮, 就 可 以 添 加 外 部 的 JRE, 如 图 2-11 所 示 图 2-11 添 加 JRE

9 在 添 加 JRE 界 面 中, 单 击 JRE home directory 选 项 后 的 Browse 按 钮, 在 弹 出 的 界 面 中 选 择 安 装 JDK 后 的 JRE 根 目 录, 如 果 是 默 认 安 装, 则 根 目 录 为 C:\Program Files\Java\jre6, 单 击 确 定 按 钮, 从 而 完 成 JRE 的 选 择 并 在 添 加 JRE 界 面 中 自 动 填 入 JRE name JRE home directory 和 JRE system libraries 选 项, 单 击 OK 按 钮, 从 而 完 成 JRE 的 添 加 操 作, 从 而 也 在 设 置 JRE 界 面 中 添 加 一 个 新 的 JRE 选 项 添 加 外 部 JRE 后, 就 可 以 在 默 认 和 新 添 加 的 JRE 之 间 进 行 选 择 选 中 外 部 添 加 的 JRE, 还 可 以 通 过 右 边 的 按 钮, 对 它 进 行 编 辑 删 除 等 操 作, 读 者 可 以 自 己 操 作 一 下 2.2.7 导 入 JAR 包 在 开 发 Java 项 目 时, 经 常 要 用 到 已 经 完 成 的 项 目 或 者 程 序, 它 们 通 常 以 JAR 包 的 形 式 出 现 的 例 如 在 进 行 JDBC 操 作 时, 要 导 入 数 据 库 驱 动 包 才 能 够 正 常 操 作 在 开 发 中, 如 果 想 使 用 这 些 JAR 包 就 要 进 行 导 入 JAR 包 操 作 导 入 JAR 包 操 作 有 多 种 方 式, 这 里 我 们 选 择 一 种 最 常 用 最 不 易 出 错 的 导 入 方 式 复 制 要 导 入 的 JAR 包, 在 MyEclipse 中 选 择 项 目 根 目 录, 然 后 执 行 粘 贴 操 作, 这 里 可 以 在 菜 单 中 选 择 Edit Paste 命 令, 也 可 以 直 接 使 用 Ctrl+V 快 捷 键, 从 而 将 JAR 复 制 到 项 目 中 包 资 源 管 理 器 如 图 2-12 所 示 图 2-12 复 制 JAR 包 选 中 导 入 的 JAR 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Build Path Add to Build Path 命 令, 从 而 将 该 JAR 包 导 入 到 Build Path 中 包 资 源 管 理 器 如 图 2-13 所 示

图 2-13 导 入 包 注 意 : 导 入 JAR 包 时, 还 有 其 他 方 式, 可 以 将 外 部 JAR 包 不 进 行 复 制 而 是 直 接 导 入 到 项 目 中, 这 样 做 的 产 生 的 后 果 就 是 JAR 包 和 项 目 的 位 置 都 不 能 变 化, 不 然 就 需 要 重 新 导 入 如 果 已 经 不 再 用 到 导 入 的 JAR 包, 也 可 以 将 它 删 除 选 中 要 删 除 的 JAR 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Build Path Remove from Build Path 命 令, 就 可 以 将 JAR 移 除 项 目 注 意 : 本 小 节 讲 解 的 导 入 JAR 包 都 是 对 于 Java SE 项 目 而 言 的, 如 果 是 Java Web 项 目, 导 入 JAR 包 时 非 常 容 易 的, 只 需 要 将 JAR 包 复 制 到 WebRoot/WEB-INF/lib 目 录 下 说 明 : 在 项 目 进 行 文 件 的 复 制 添 加 删 除 等 操 作 时, 有 时 候 并 不 能 实 现 同 步 操 作, 这 是 和 文 件 类 型 计 算 机 硬 件 有 关 的 如 果 不 能 看 到 操 作 结 果, 可 以 在 菜 单 中 选 择 File Refresh 命 令, 或 者 使 用 F5 快 捷 键 对 项 目 进 行 刷 新, 从 而 看 到 操 作 结 果 2.2 源 代 码 操 作 在 MyEclipse 的 菜 单 中, 有 一 个 Source 菜 单, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 也 有 Source 选 项, 它 们 完 成 的 操 作 几 乎 是 一 样 的 通 过 它 们 可 以 完 成 源 代 码 相 关 的 操 作, 在 后 面 的 讲 解 中, 只 以 其 中 的 右 键 弹 出 菜 单 方 式 进 行 讲 解 记 忆 : 在 右 键 菜 单 中 选 择 Source 命 令 也 是 有 快 捷 键 的, 快 捷 键 为 Alt+Shift+S 在 编 辑 区 中, 使 用 该 快 捷 键, 就 只 会 出 现 Source 命 令 下 的 所 有 选 项

11 2.2.1 添 加 和 删 除 注 释 在 Java 程 序 中, 注 释 是 必 不 可 少 的 一 部 分 通 过 注 释 能 够 使 其 他 程 序 员 很 容 易 的 看 懂 你 的 程 序 在 Java 程 序 中 有 两 种 常 用 的 注 释 方 法, 那 就 是 单 行 注 释 和 多 行 注 释 1. 添 加 和 删 除 单 行 注 释 选 中 要 单 行 注 释 的 行, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Source Toggle Comment 命 令, 就 会 将 该 行 前 面 加 上 //, 从 而 将 当 前 行 注 释 掉 在 该 行 中, 再 次 选 择 Source Toggle Comment 命 令, 就 会 将 该 行 的 注 释 去 掉 记 忆 : 进 行 单 行 注 释 的 快 捷 键 是 Ctrl+7, 不 管 是 加 注 释, 还 是 去 掉 注 释, 都 是 该 快 捷 键 2. 添 加 和 删 除 多 行 注 释 选 中 要 进 行 多 行 注 释 的 所 有 行, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Source Add Block Comment 命 令, 就 会 为 选 中 的 行 加 上 多 行 注 释 再 次 选 择 被 注 释 的 多 行, 选 择 选 择 Source Remove Block Comment 命 令, 就 会 将 多 行 注 释 去 掉 记 忆 : 添 加 多 行 注 释 的 快 捷 键 为 Ctrl+Shift+/, 删 除 多 行 注 释 的 快 捷 键 为 Ctrl+Shift+\ 除 了 单 行 注 释 和 多 行 注 释 外, 还 有 文 档 注 释, 它 是 使 用 比 较 少 的, 通 过 选 择 Source Generate Element Comment 命 令 完 成, 快 捷 方 式 为 Alt+Shift+J 2.2.2 调 整 代 码 格 式 在 调 整 代 码 中, 有 两 种 操 作, 一 种 是 调 整 行 缩 进, 另 外 一 种 就 是 调 整 格 式 我 们 通 过 下 面 打 乱 后 的 HelloWorld 程 序 讲 解 它 们 之 间 的 不 同 01 public class Hello 02 { 03 public static void main(string[] args) 04 { 05 System.out.println("Hello World!!!"); 06 } 07 } 先 来 进 行 缩 进 操 作 全 部 选 中 上 述 代 码, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Source Correct Indentation 命 令, 则 HelloWorld 程 序 的 代 码 调 整 为 : 01 public class Hello 02 { 03 public static void main(string[] args) 04 { 05 System.out.println("Hello World!!!"); 06 } 07 } 上 述 代 码 中, 第 4 行 和 第 6 行 的 花 括 号 的 缩 进 已 经 符 合 规 范 从 代 码 的 变 化 可 以 看

到 Correct Indentation 命令的作用就是调整所有选中行中的缩进 记忆 调整行缩进的快捷键为 Ctrl+I 在编辑区中 使用 Ctrl+Z 快捷键 让代码回到打乱状态 选择 Source Format 命令 则 HelloWorld 程序的代码调整为 01 public class Hello { 02 public static void main(string[] args) { 03 System.out.println("Hello World!!!"); 04 05 } } 从代码的变化可以看到 不但缩进符合的了规范 而且换行也符合了规范 Format 命令的作用就是调整所有选中行的格式 记忆 调整格式的快捷键为 Ctrl+Shift+F 调整格式是包含调整缩进的功能的 所以在开发中完全可以只使用 Format 命令 在当前类中 要实现的接口和类与其 2.2.3 添加和组织导入接口和类 不在同一个包中, 就需要将该接口和 类导入到当前程序中. 当程序中使用的接口或者类和当前程序类不在同一包下 并且接口或者类并不是在 选中"要 java.lang.* 包下 就需要将接口或者类导入到当前程序中 引用的接 导入接口或者类有两种方式 一种是添加导入 另一种是组织导入 添加导入是导 口和类", 入当前选中的接口和类 在编辑区的右键弹出菜单中 选择 Source Add Import 打开右键 命令可以完成该功能 添加导入是将当前程序中需要导入的接口和类一起导入 而且如 菜单, 执 行"Sourc e/add Import 命令可以完成组织导入的功能 Import", 记忆 添加导入的快捷键为 Ctrl+Shift+M 组织导入的快捷键为 Ctrl+Shift+O 则可将接 从两种导入的功能上可以看到组织导入覆盖了添加导入的功能 所以在开发中可以只 口和类所 使用组织导入 在包添加 到当前文 在大部分情况下 直接进行上述操作都是可以完成相应功能的 但是当要导入的接 件中. 果当前导入的接口或者类没有使用 也会被删除掉 在编辑区中 选择 Source Organize 口或者类在多个包中出现时 就要让程序员进行选择 到底要导入哪一个接口或者类 例如在 HelloWorld 程序的 main 方法中 输入如下代码 Date date=new Date(); 再进行添加导入或者组织导入操作时 就会弹出一个选择的界面 如图 2-14 所示

13 图 2-14 选 择 要 导 入 的 类 因 为 Date 类 存 在 多 个 包 下, 所 以 在 下 面 列 出 所 有 的 Date 类, 在 其 中 选 择 要 导 入 的 Date 类, 例 如 选 择 java.util.date, 单 击 Finish 按 钮, 从 而 完 成 导 入 操 作 这 是 在 HelloWorld 程 序 的 最 上 端 就 会 出 现 如 下 代 码 import java.util.date; 2.2.4 重 写 和 实 现 方 法 在 开 发 Java 类 程 序 时, 经 常 要 用 到 继 承 父 类 和 实 现 接 口 如 果 父 类 和 接 口 中 有 抽 象 方 法, 那 在 当 前 类 中 就 要 实 现 这 些 抽 象 方 法 如 果 父 类 中 具 有 非 抽 象 方 法, 在 当 前 类 中 也 可 以 重 写 这 些 方 法 在 MyEclipse 中, 重 写 和 实 现 方 法 是 通 过 一 个 命 令 来 完 成 的 这 里 我 们 使 用 HelloWorld 项 目 中 的 service.impl 包 下 的 UserServiceImpl 程 序 举 例, 首 先 将 它 其 中 的 login 方 法 去 掉, 则 代 码 变 为 : 01 package service.impl; 02 import service.userservice; 03 public class UserServiceImpl implements UserService { 04 05 } 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Source Override/Implement Methods 命 令, 将 弹 出 重 写 和 实 现 方 法 界 面 如 图 2-15 所 示

图 2-15 重 写 和 实 现 方 法 因 为 UserServiceImpl 类 实 现 了 UserService 接 口, 所 以 在 类 中 必 须 实 现 login 方 法 在 重 写 和 实 现 方 法 界 面 中, 首 先 将 继 承 的 父 类 和 实 现 的 接 口 列 出 来, 然 后 在 父 类 或 者 接 口 下 列 出 可 以 重 写 或 者 实 现 的 方 法 必 须 实 现 的 方 法 默 认 情 况 下 是 选 中 的 状 态, 而 可 以 重 写 的 方 法 默 认 情 况 下 是 未 选 中 状 态 在 其 中 选 中 login 和 tostring 方 法, 单 击 OK 按 钮, 从 而 完 成 重 写 和 实 现 方 法 的 操 作, UserServiceImpl 类 程 序 变 为 : 01 package service.impl; 02 import service.userservice; 03 public class UserServiceImpl implements UserService { 04 public boolean login(string username, String password) { 05 // TODO Auto-generated method stub 06 return false; 07 } 08 @Override 09 public String tostring() { 10 // TODO Auto-generated method stub 11 return super.tostring(); 12 } 13 } 在 其 中 第 8 行 使 用 @Override 注 解 标 明 下 面 的 tostring 方 法 是 重 写 的 方 法 2.2.5 生 成 Getter 和 Setter 方 法 在 进 行 Java Web 项 目 开 发 中,JavaBean 是 不 可 缺 少 的 一 部 分 在 标 准 的 JavaBean 中, 应 该 具 有 属 性, 以 及 这 些 属 性 的 Getter 和 Setter 方 法 在 本 小 节 中, 就 来 学 习 一 下 如 何 自 动 生 成 Getter 和 Setter 方 法 在 HelloWorld 项 目 中, 创 建 名 称 为 po 的 包, 然 后 在 该 包 下 创 建 Student 学 生 类, 并 为 该 类 定 义 了 姓 名 年 龄 和 性 别 三 个 属 性, 它 的 程 序 代 码 为 :

15 01 package po; 02 public class Student { 03 private String name; 04 private int age; 05 private boolean sex; 06 } 因 为 设 置 和 获 取 JavaBean 中 的 属 性 值 都 是 通 过 Setter 和 Getter 方 法 完 成 的, 所 以 通 常 将 属 性 设 置 为 private 私 有 访 问 修 饰 符 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Source Generate Getters and Setters 命 令, 就 会 弹 出 生 成 Getter 和 Setter 方 法 的 界 面, 如 图 2-16 所 示 图 2-16 生 成 Getter 和 Setter 方 法 注 意 : 在 进 行 Generate Getters and Setters 命 令 之 前, 要 指 定 Getter 和 Setter 方 法 插 入 的 位 置, 必 须 在 类 中 如 果 鼠 标 放 在 类 后, 或 者 其 他 不 能 插 入 方 法 的 位 置, 是 不 能 使 用 Generate Getters and Setters 命 令 进 行 操 作 的 在 生 成 Getter 和 Setter 方 法 界 面 中 的 最 上 面 的 文 本 域 中, 可 以 选 择 要 自 动 生 成 的 方 法 如 果 选 择 属 性 前 面 的 复 选 框, 则 表 示 该 属 性 的 Getter 和 Setter 方 法 都 生 成 在 文 本 域 的 右 键, 也 有 对 Getter 和 Setter 方 法 进 行 操 作 的 按 钮 Select All 按 钮 表 示 选 中 所 有 属 性, 从 而 将 所 有 属 性 的 Getter 和 Setter 方 法 生 成, 这 也 是 最 常 见 的 操 作 Deselect

All 按 钮 表 示 全 部 不 选 Select Getters 按 钮 表 示 选 择 Getter 方 法, 也 就 是 将 所 有 属 性 的 Getter 方 法 生 产 Select Setter 按 钮 表 示 将 所 有 属 性 的 Setter 方 法 生 成 在 生 产 Getter 和 Setter 方 法 界 面 的 下 半 部 分 中, Insertion point 表 示 生 成 的 Getter 和 Setter 方 法 插 入 的 位 置, 在 其 中 有 三 个 选 项, 默 认 的 是 Cursor position, 表 示 在 鼠 标 光 标 位 置 插 入, 也 就 是 在 执 行 Generate Getters and Setters 命 令 之 前, 鼠 标 的 位 置 First mothod 选 项 表 示 在 所 有 方 法 前 插 入, Last mothod 选 项 表 示 在 所 有 方 法 之 后 插 入 Sort by 表 示 Getter 和 Setter 方 法 的 插 入 顺 序 其 中 Field in getter/setter pairs 是 默 认 选 项, 表 示 依 次 生 成 每 一 个 属 性 的 Getter 和 Setter 方 法 First getters,then setters 选 项 表 示 先 将 所 有 属 性 的 Getter 方 法 生 产, 再 将 所 有 属 性 的 Setter 方 法 生 产 Access modifier 表 示 生 成 的 Getter 和 Setter 方 法 的 访 问 修 饰 符 在 理 论 上 讲 它 们 可 以 使 四 种 访 问 修 饰 符 中 的 任 意 一 种, 并 且 还 可 以 选 择 final 和 synchronized 两 种 非 访 问 修 饰 符 但 是 为 了 让 更 多 的 程 序 使 用 该 程 序 中 的 属 性, 通 常 就 采 用 默 认 的 public 公 共 访 问 修 饰 符 在 这 里 我 们 选 中 所 有 的 属 性, 其 他 选 项 采 用 默 认 选 择, 单 击 OK 按 钮, 从 而 完 成 生 成 Getter 和 Setter 方 法 的 操 作 Student 学 生 类 程 序 变 为 : 01 package po; 02 public class Student { 03 private String name; 04 private int age; 05 private boolean sex; 06 public String getname() { 07 return name; 08 } 09 public void setname(string name) { 10 this.name = name; 11 } 12 public int getage() { 13 return age; 14 } 15 public void setage(int age) { 16 this.age = age; 17 } 18 public boolean issex() { 19 return sex; 20 } 21 public void setsex(boolean sex) { 22 this.sex = sex; 23 } 24 } 从 代 码 中 也 可 以 看 到, 所 有 属 性 的 Getter 和 Setter 方 法 自 动 被 生 成

17 2.2.6 生成代理方法 代理模式是设置模式中非常重要的一种 本小节讲解的内容就要基于代理模式 在 特定情况下 客户程序不想或者不能直接引用对象 这时候就要用到代理 通过生成一 个代理对象做为客户程序和原对象的中介 在代理模式中 应该具有三个角色程序 首先是抽象角色 它是真实对象和代理对 象所在类所实现的接口或者是继承的父类 真实角色是指原对象 也就是客户程序要实 际引用的对象 代理角色是生成的代理类 通过它为客户程序和真实角色之间建立桥梁 在代理角色程序中 要给出真实角色类的引用 并且给出代理方法 该方法的名称 应该和真实角色程序的方法相同 并在其中调用真实角色中的方法 在本节中就来学习 如何使用 MyEclipse 自动生成这样的代理方法 在这里我们单独开发一个项目 名称为 ch2 再在其中创建 proxy 包 在 proxy 包下首先开发抽象角色程序 这里我们使用接口来实现 01 package proxy; 02 public interface AbstractSubject { 03 public void sayhello(); 04 真实对象需要实 现的接口. } 再来开发实现该接口的真实角色 代码为 01 package proxy; 02 public class RealSubject implements AbstractSubject{ 03 04 System.out.println("大家好 我是真实角色"); 05 06 真实对象. public void sayhello() { } } 接下来就是本小节的重点了 开发代理角色 它同样要实现 AbstractSubject 接口 并在代码中具有真实角色类的引用 先只开发这些代码 01 package proxy; 02 public class ProxySubject implements AbstractSubject { 03 private RealSubject realsubject; //真实角色引用 04 05 } 代理对象: 真实 对象作为代理对 象的一个私有成 员. 将鼠标放在第 4 行中 在编辑区右键弹出菜单中 选择 Source Generate Delegate Methods 命令 将会弹出选择代理方法的界面 如图 2-17 所示

图 2-17 生 成 代 理 方 法 在 生 成 代 理 方 法 界 面 中, 会 按 照 给 出 的 引 用, 查 找 该 引 用 类 下 有 哪 些 方 法 可 以 生 成 代 理 方 法 这 里 我 们 选 择 sayhello 方 法 Insertion point 表 示 生 成 代 理 方 法 的 插 入 位 置, 这 里 可 以 选 择 所 有 方 法 前 面, 所 有 方 法 后 面 和 鼠 标 光 盘 位 置 三 种, 这 和 生 产 Getter 和 Setter 方 法 相 同 的 最 后 单 击 OK 按 钮, 就 会 自 动 生 成 代 理 方 法, 则 ProxySubject 代 理 角 色 类 的 代 码 变 为 : 01 package proxy; 02 public class ProxySubject implements AbstractSubject { 03 private RealSubject realsubject; // 真 实 角 色 引 用 04 public void sayhello() { 05 realsubject.sayhello(); 06 } 07 } 从 代 码 中 的 变 化 可 以 看 到, 自 动 生 成 了 一 个 名 称 为 sayhello 的 方 法, 并 在 其 中 使 用 真 实 角 色 引 用 调 用 sayhello 方 法 到 目 前 代 理 方 法 并 没 有 开 发 完, 我 们 要 判 断 真 实 角 色 引 用 是 否 已 经 有 对 象, 也 就 是 是 否 已 经 注 入 对 象, 具 体 如 何 注 入, 这 里 就 不 再 详 细 讲 解 这 里 我 们 通 过 直 接 判 断 的 方 式, 将 ProxySubject 代 理 角 色 类 的 代 码 变 为 : 01 package proxy; 02 public class ProxySubject implements AbstractSubject { 03 private RealSubject realsubject; // 真 实 角 色 引 用 04 public void sayhello() { 05 if(realsubject==null){ 06 realsubject=new RealSubject(); 07 } 08 realsubject.sayhello();

19 09 } 10 } 从 而 已 经 将 代 理 角 色 程 序 开 发 完 成 最 后 就 是 通 过 编 写 一 个 客 户 端 程 序, 来 验 证 代 理 角 色 程 序 是 否 起 到 代 理 的 功 能 01 package proxy; 02 public class TestProxy { 03 public static void main(string[] args) { 04 AbstractSubject abstractsubject = new ProxySubject();// 代 理 对 象 05 abstractsubject.sayhello(); 06 } 07 } 运 行 上 述 代 码, 运 行 结 果 为 : 大 家 好, 我 是 真 实 角 色 从 程 序 和 运 行 结 果 中 可 以 看 到, 在 客 户 端 程 序 中, 虽 然 并 没 有 使 用 真 实 角 色 程 序 引 用 或 者 对 象, 但 是 仍 然 运 行 了 真 实 角 色 程 序 中 的 方 法, 这 就 是 代 理 角 色 中 的 代 理 方 法 起 到 的 作 用 说 明 : 在 Spring 的 框 架 中, 使 用 代 理 模 式 是 非 常 多 的 在 其 中 的 代 理 角 色 中 并 不 需 要 创 建 真 实 角 色 对 象, 而 是 通 过 IoC 技 术 在 代 理 方 法 中, 还 可 以 添 加 其 他 方 法, 从 而 完 善 原 方 法, 使 用 它 最 多 的 就 是 Spring 中 的 AOP 技 术 这 里 我 们 在 后 面 的 学 习 中 都 会 学 习 到 2.2.7 生 成 hashcode 和 equals 方 法 hashcode 和 equals 方 法 是 Object 类 中 的 两 个 方 法, 所 以 在 所 有 类 中 都 可 以 重 写 这 两 个 方 法 在 程 序 中, 调 用 hashcode 方 法 将 返 回 对 象 的 哈 希 码 值 在 Java 应 用 程 序 执 行 期 间, 在 同 一 对 象 上 多 次 调 用 hashcode 方 法 时, 必 须 一 致 地 返 回 相 同 的 整 数 equals 方 法 用 于 判 断 对 象 是 否 和 参 数 对 象 相 等, 这 里 的 相 等 可 以 人 为 指 定, 例 如 规 定 姓 名 和 年 龄 都 相 等 的 学 生 是 相 等 时 在 重 写 equals 方 法 时, 通 常 有 必 要 重 写 hashcode 方 法, 以 维 护 hashcode 方 法 的 常 规 协 定, 该 协 定 声 明 相 等 对 象 必 须 具 有 相 等 的 哈 希 码 在 MyEclipse 中, 定 义 了 相 应 命 令, 可 以 自 动 按 照 程 序 员 的 规 定 来 自 动 生 成 hashcode 和 equals 方 法 例 如 开 发 一 个 Student 学 生 类 程 序, 并 定 义 了 姓 名 和 年 龄 属 性, 代 码 为 : 01 package hashcodeequals; 02 public class Student { 03 String name; 04 int age; 05 06 } 在 第 5 行 中, 在 编 辑 区 右 键 弹 出 菜 单 中, 选 择 Source Generate hashcode() and equals() 命 令, 将 弹 出 生 成 hashcode 和 equals 方 法 的 界 面, 如 图 2-18 所 示

图 2-18 生 成 hashcode 和 equals 方 法 在 生 成 hashcode 和 equals 方 法 界 面 的 文 本 域 中, 选 择 对 哪 些 属 性 操 作, 也 就 是 说 当 哪 些 属 性 相 同 时, 认 为 两 个 对 象 是 相 等 的 在 Insertion point 选 项 是 选 择 生 成 的 方 法 插 入 的 位 置, 和 前 面 两 小 节 中 讲 解 是 相 同 的 最 后 单 击 OK 按 钮, 则 Student 学 生 类 程 序 代 码 变 为 : 01 package hashcodeequals; 02 public class Student { 03 String name; 04 int age; 05 @Override 06 public int hashcode() { // 保 证 相 等 的 对 象 哈 希 码 值 相 等 07 final int prime = 31; 08 int result = 1; 09 result = prime * result + age; 10 result = prime * result + ((name == null)? 0 : name.hashcode()); 11 return result; 12 } 13 @Override 14 public boolean equals(object obj) { 15 if (this == obj) // 如 果 两 个 对 象 相 同, 则 相 等 16 return true; 17 if (obj == null) // 如 果 对 象 为 空, 则 不 相 等 18 return false; 19 if (getclass()!= obj.getclass()) // 如 果 Class 不 同, 则 不 相 等 20 return false; 21 final Student other = (Student) obj;

21 22 if (age!= other.age) // 如 果 年 龄 不 相 等, 则 对 象 不 相 等 23 return false; 24 if (name == null) { // 如 果 姓 名 为 null 25 if (other.name!= null) // 而 参 数 对 象 姓 名 不 为 null 则 不 相 等 26 return false; 27 } else if (!name.equals(other.name)) // 如 果 姓 名 不 相 等, 则 不 相 等 28 return false; 29 return true; // 全 符 合 条 件, 两 个 对 象 相 等 30 } 31 } 其 中 的 注 释 是 后 加 的, 为 了 让 读 者 更 容 易 的 看 懂 代 码 从 代 码 的 变 化 上 可 以 看 到 自 动 生 成 了 hashcode 和 equals 方 法, 它 们 要 比 程 序 员 自 己 写 的 代 码 规 范 的 注 意 : 在 重 写 equals 方 法 时, 一 定 要 进 行 相 应 的 重 写 hashcode 方 法 这 在 使 用 MyEclipse 开 发 工 具 时 是 不 会 出 错 的, 因 为 将 两 个 方 法 绑 定 在 一 起 如 果 手 动 重 写 时, 不 重 写 hashcode 方 法, 在 特 定 情 况 下 就 会 出 现 错 误, 例 如 学 习 HashSet HashMap 等 集 合 时 2.2.8 生 成 构 造 函 数 构 造 函 数 是 Java 程 序 中 非 常 重 要 的 组 成 部 分, 如 果 没 有 人 为 的 定 义 构 造 函 数, 系 统 会 自 动 给 出 一 个 无 参 构 造 函 数 在 MyEclipse 中, 生 成 构 造 函 数 有 两 种 方 式, 一 种 是 使 用 属 性 生 成, 另 一 种 是 从 父 类 中 生 成 1. 使 用 属 性 生 成 使 用 属 性 生 成 构 造 函 数, 是 通 过 使 用 已 有 属 性 做 为 构 造 函 数 参 数 来 生 成 构 造 函 数 在 本 章 项 目 中, 在 创 建 一 个 constructor 包, 在 其 中 创 建 Student 学 生 类 程 序, 并 在 其 中 定 义 姓 名 和 年 龄 两 个 属 性, 代 码 为 : 01 package hashcodeequals; 02 public class Student { 03 String name; 04 int age; 05 06 } 将 鼠 标 放 在 第 5 行, 在 右 键 弹 出 菜 单 中, 选 择 Source Generate Constructor using Fields 命 令, 从 而 弹 出 使 用 属 性 生 成 构 造 函 数 界 面, 如 图 2-19 所 示

图 2-19 使 用 属 性 生 成 在 使 用 属 性 生 成 构 造 函 数 的 界 面 中, 在 上 半 部 分 的 文 本 域 中, 选 择 要 使 用 的 属 性, 默 认 是 全 部 选 择, 从 而 生 成 具 有 所 有 属 性 的 构 造 函 数 也 可 以 选 择 其 中 一 部 分 属 性, 甚 至 不 选 择 任 何 属 性, 这 样 生 成 的 是 无 参 构 造 函 数 在 文 本 域 的 右 边 有 四 个 按 钮 Select All 表 示 选 择 全 部 属 性, Deselect All 表 示 全 部 不 选 择 Up 表 示 向 上 移 动 属 性, Down 表 示 向 下 移 动 属 性 之 所 以 要 移 动 属 性, 是 因 为 在 构 造 函 数 中 参 数 也 是 有 顺 序 的 当 前 情 况 下, 生 成 的 两 参 构 造 函 数, 第 1 个 参 数 是 name, 第 2 个 参 数 是 age 如 果 选 中 name 属 性, 然 后 单 击 Down 按 钮, 则 name 属 性 就 会 出 现 在 age 属 性 的 下 面, 则 生 成 的 构 造 函 数 第 1 个 参 数 是 age, 第 2 个 参 数 是 name 这 两 种 生 成 的 构 造 函 数 是 不 相 同 的 Insertion point 选 项 表 示 构 造 函 数 插 入 的 位 置, 可 以 是 当 前 鼠 标 光 标 位 置, 也 可 以 是 所 有 方 法 前 或 者 所 有 方 法 后 Access modifier 选 项 表 示 生 成 构 造 函 数 的 访 问 修 饰 符, 可 以 在 所 有 四 种 访 问 修 饰 符 中 选 择 Generate constructor comments 选 项 表 示 是 否 生 成 构 造 函 数 注 释, 默 认 是 不 生 成 Omit call to default constructor super() 选 项 表 示 是 否 忽 略 调 用 父 类 无 参 构 造 函 数 的 代 码, 也 就 是 super() 默 认 是 不 忽 略, 也 就 是 生 成 super() 代 码 这 里 我 们 采 用 默 认 选 择, 单 击 OK 按 钮, 从 而 完 成 使 用 属 性 生 成 构 造 函 数 的 操 作, 则 Student 学 生 类 程 序 变 为 : 01 package constructor; 02 public class Student { 03 String name; 04 int age; 05 public Student(String name, int age) {

23 06 super(); 07 this.name = name; 08 this.age = age; 09 } 10 } 注 意 : 不 管 是 否 生 成 super() 代 码, 是 都 会 调 用 父 类 无 参 构 造 函 数 的, 除 非 指 定 调 用 有 参 构 造 函 数 从 这 里 也 可 以 看 到, 在 生 成 有 参 构 造 函 数 后, 最 好 再 给 出 无 参 构 造 函 数 因 为 有 参 构 造 函 数 会 将 系 统 自 动 生 成 的 无 参 构 造 函 数 覆 盖, 但 是 在 子 类 中 会 自 动 调 用 父 类 无 参 构 造 函 数, 如 果 没 有 无 参 构 造 函 数, 程 序 就 会 出 错 2. 从 超 类 中 生 成 从 超 类 中 生 成 构 造 函 数 是 指 在 子 类 中 选 择 生 成 和 父 类 中 相 同 的 构 造 函 数, 例 如 在 父 类 中 具 有 3 种 构 造 函 数, 那 么 在 子 类 中 就 可 以 选 择 生 成 其 中 的 某 几 种 通 过 这 种 方 式 生 成 的 构 造 函 数 是 和 父 类 中 的 构 造 函 数 具 有 相 同 参 数 个 数 类 型 和 顺 序 的 我 们 先 来 开 发 一 个 Person 类, 让 它 做 为 父 类, 在 其 中 具 有 姓 名 和 年 龄 两 个 属 性, 并 具 有 三 种 构 造 函 数, 代 码 为 : 01 package constructor; 02 public class Person { 03 String name; 04 int age; 05 public Person() { 06 super(); 07 } 08 public Person(String name) { 09 super(); 10 this.name = name; 11 } 12 public Person(String name, int age) { 13 super(); 14 this.name = name; 15 this.age = age; 16 } 17 } 然 后 开 发 一 个 Teacher 老 师 类, 让 它 继 承 Person 类, 并 也 为 Teacher 老 师 类 定 义 了 姓 名 和 年 龄 两 个 属 性, 当 前 代 码 为 : 01 package constructor; 02 public class Teacher extends Person { 03 String name; 04 int age; 05 06 } 将 鼠 标 放 在 第 5 行 中, 在 右 键 弹 出 菜 单 中, 选 择 Source Generate Constructor from Superclass 命 令, 会 弹 出 从 超 类 中 生 成 构 造 函 数 的 界 面, 如 图 2-20 所 示

图 2-20 从 超 类 中 生 成 该 界 面 和 通 过 属 性 生 成 构 造 函 数 界 面 相 比, 只 有 上 半 部 分 不 同 在 文 本 域 中 将 父 类 中 三 种 类 型 的 构 造 函 数 列 出 来, 通 过 选 择, 可 以 生 成 Teacher 类 中 的 构 造 函 数 例 如 我 们 选 择 全 部 三 种 构 造 函 数, 单 击 OK 按 钮, 则 Teacher 老 师 类 的 代 码 变 为 : 01 package constructor; 02 public class Teacher extends Person { 03 String name; 04 int age; 05 public Teacher() { 06 super(); 07 // TODO Auto-generated constructor stub 08 } 09 public Teacher(String name, int age) { 10 super(name, age); 11 // TODO Auto-generated constructor stub 12 } 13 public Teacher(String name) { 14 super(name); 15 // TODO Auto-generated constructor stub 16 } 17 } 自 动 生 成 的 三 种 构 造 函 数 的 顺 序 变 化 是 没 有 关 系 的 通 过 这 种 方 式 生 成 的 构 造 函 数 和 父 类 的 具 有 相 同 的 参 数 个 数 类 型 和 顺 序 例 如 父 类 中 的 两 参 构 造 函 数 中, 是 先 name 后 age, 则 在 子 类 中 同 样 也 是 这 样 的 顺 序

25 注 意 : 我 们 完 全 可 以 在 Teacher 老 师 类 中 不 定 义 姓 名 和 年 龄 属 性, 也 能 生 成 这 三 种 构 造 函 数 这 是 因 为 这 两 个 属 性 会 从 父 类 中 继 承 下 来, 这 里 我 们 给 出 了 这 两 个 属 性, 是 因 为 可 以 让 构 造 函 数 看 的 更 明 白 2.3 包 围 方 式 在 Java 语 言 的 流 程 控 制 语 句 中, 大 部 分 语 句 都 是 具 有 固 定 格 式 的 在 控 制 语 句 中, 包 括 条 件 语 句 循 环 语 句 和 异 常 处 理 语 句 等 在 MyEclipse 中, 通 过 命 令 操 作 可 以 自 动 生 成 这 些 语 句, 从 而 减 轻 程 序 员 的 操 作 在 菜 单 中, 选 择 Source Surround With 命 令, 可 以 看 到 包 围 方 式 选 项 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Surround With 命 令 也 可 以 得 到 包 围 方 式 选 项 记 忆 : 在 进 行 包 围 操 作 时, 一 定 首 先 选 择 被 包 围 的 代 码 包 围 方 式 的 快 捷 键 为 Alt+Shift+Z 2.3.1 条 件 语 句 包 围 在 Java 的 条 件 语 句 中 包 括 两 种, 分 别 是 if 条 件 语 句 和 Switch 多 条 件 分 支 语 句 由 于 Switch 语 句 是 比 较 复 杂 的, 所 以 在 MyEclipse 中 并 没 有 集 成 自 动 生 成 该 语 句 的 命 令 所 以 这 里 说 的 条 件 语 句 包 围 就 是 if 条 件 语 句 包 围 这 里 通 过 下 面 的 代 码 讲 解 条 件 语 句 包 围 命 令 01 package surround; 02 public class IfTest { 03 public static void main(string[] args) { 04 System.out.println(" 自 动 生 成 if 条 件 语 句 "); 05 } 06 } 选 中 第 4 行 的 代 码, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Surround With 3 if (if statement) 命 令, 则 代 码 自 动 变 为 : 01 package surround; 02 public class IfTest { 03 public static void main(string[] args) { 04 if (condition) { 05 System.out.println(" 自 动 生 成 if 条 件 语 句 "); 06 } 07 } 08 } 然 后 将 第 4 行 的 condition 换 为 实 际 需 要 的 条 件 表 达 式, 就 完 成 if 条 件 语 句 的 包 围

2.3.2 循 环 语 句 包 围 在 Java 的 循 环 控 制 语 句 中, 包 括 for 循 环 语 句 while 循 环 语 句 和 do-while 循 环 语 句, 它 们 分 别 使 用 不 同 的 命 令 1.for 循 环 语 句 首 先 开 发 一 个 类 名 为 ForTest 的 程 序, 代 码 如 下 : 01 package surround; 02 public class ForTest { 03 public static void main(string[] args) { 04 System.out.println(" 自 动 生 成 for 循 环 语 句 "); 05 } 06 } 选 中 第 4 行 的 代 码, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Surround With 2 for(iterate over array) 命 令, 则 代 码 自 动 变 为 : 01 package surround; 02 public class ForTest { 03 public static void main(string[] args) { 04 for (int i = 0; i < args.length; i++) { 05 System.out.println(" 自 动 生 成 for 循 环 语 句 "); 06 } 07 } 08 } 从 自 动 生 成 的 代 码 可 以 看 到, 是 从 0 开 始, 然 后 到 args 参 数 长 度 结 束 程 序 员 可 以 根 据 自 己 实 际 需 要 进 行 改 动 2.while 循 环 语 句 首 先 开 发 一 个 类 名 为 WhileTest 的 程 序, 代 码 如 下 : 01 package surround; 02 public class WhileTest { 03 public static void main(string[] args) { 04 System.out.println(" 自 动 生 成 while 循 环 语 句 "); 05 } 06 } 选 中 第 4 行 代 码, 在 编 辑 区 中 的 右 键 菜 单 中, 选 择 Surround With 7 while(while loop with condition) 命 令, 则 代 码 自 动 变 为 : 01 package surround; 02 public class WhileTest { 03 public static void main(string[] args) { 04 while (condition) { 05 System.out.println(" 自 动 生 成 while 循 环 语 句 "); 06 } 07 } 08 } 将 其 中 第 4 行 的 condition 换 为 和 实 际 需 求 相 对 应 的 条 件 表 达 式, 则 自 动 生 成 while

27 循 环 语 句 就 完 成 了 3.do-while 循 环 语 句 首 先 开 发 一 个 类 名 为 DoWhileTest 的 程 序, 代 码 如 下 : 01 package surround; 02 public class DoWhileTest { 03 public static void main(string[] args) { 04 System.out.println(" 自 动 生 成 while 循 环 语 句 "); 05 } 06 } 选 中 其 中 的 第 4 行, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Surround With 1 do(do while statement) 命 令, 则 代 码 自 动 变 为 : 01 package surround; 02 public class DoWhileTest { 03 public static void main(string[] args) { 04 do { 05 System.out.println(" 自 动 生 成 while 循 环 语 句 "); 06 } while (condition); 07 } 08 } 然 后 将 第 6 行 的 condition 换 为 和 实 际 需 求 相 对 应 的 条 件 表 达 式, 则 自 动 生 成 do-while 循 环 语 句 完 成 2.3.3 异 常 处 理 语 句 包 围 异 常 处 理 语 句 也 是 流 程 控 制 语 句 的 一 种, 在 很 多 书 上 之 所 以 把 它 放 在 后 面 讲 解 是 因 为 异 常 的 概 念 要 放 在 后 面 讲 解 在 MyEclipse 中, 有 两 种 异 常 处 理 语 句 包 围 方 式, 它 们 之 间 有 所 区 别 1. 简 单 异 常 处 理 语 句 包 围 异 常 处 理 语 句 由 try 语 句 和 catch 语 句 组 成, 在 catch 语 句 中 给 出 异 常 类 型, 如 果 使 用 简 单 异 常 处 理 语 句, 则 直 接 给 出 Exception 先 来 开 发 一 个 类 名 为 TryCatchTest 的 程 序, 代 码 为 : 01 package surround; 02 import java.net.serversocket; 03 public class TryCatchTest { 04 public static void main(string[] args) { 05 ServerSocket socket=new ServerSocket(8888); 06 System.out.println(" 自 动 生 成 异 常 处 理 语 句 "); 07 } 08 } 从 代 码 中 可 以 看 到 在 第 5 行 创 建 服 务 器 端 套 接 字, 该 语 句 会 发 生 IOException 异 常 选 中 第 5 行 代 码, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Surround With 6 try(try catch block) 命 令, 则 代 码 自 动 变 为 : 01 package surround;

02 import java.net.serversocket; 03 public class TryCatchTest { 04 public static void main(string[] args) { 05 try { 06 ServerSocket socket = new ServerSocket(8888); 07 } catch (Exception e) { 08 // TODO: handle exception 09 } 10 System.out.println(" 自 动 生 成 异 常 处 理 语 句 "); 11 } 12 } 从 运 行 结 果 中 可 以 看 到 在 自 动 生 成 的 异 常 处 理 catch 语 句 中, 使 用 Exception 异 常 进 行 判 断, 从 而 进 行 异 常 处 理 2. 匹 配 异 常 处 理 语 句 包 围 匹 配 异 常 处 理 语 句 包 围 是 一 种 更 智 能 的 处 理 方 式, 使 用 它 可 以 判 断 具 体 选 中 代 码 所 发 生 的 异 常, 然 后 使 用 对 异 常 进 行 处 理 仍 然 选 中 原 TryCatchTest 类 程 序 中 的 第 5 行, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Surround With Try/catch Block 命 令, 则 代 码 自 动 变 为 : 01 package surround; 02 import java.io.ioexception; 03 import java.net.serversocket; 04 public class TryCatchTest { 05 public static void main(string[] args) { 06 try { 07 ServerSocket socket=new ServerSocket(8888); 08 } catch (IOException e) { 09 // TODO Auto-generated catch block 10 e.printstacktrace(); 11 } 12 System.out.println(" 自 动 生 成 异 常 处 理 语 句 "); 13 } 14 } 在 自 动 生 成 的 第 8 行 中 可 以 看 到, 使 用 IOException 异 常 进 行 处 理 说 明 : 有 些 读 者 可 能 认 为 匹 配 异 常 处 理 语 句 要 优 于 简 单 异 常 处 理, 这 是 不 全 面 的 答 案 具 体 使 用 哪 一 种 要 看 实 际 的 情 况 如 果 仅 仅 是 让 程 序 能 够 运 行, 而 且 还 要 在 其 中 加 入 其 它 代 码, 这 时 候 就 应 该 采 用 简 单 异 常 处 理 语 句 包 围, 这 样 不 用 进 行 多 catch 语 句 处 理 2.3.4 多 线 程 语 句 包 围 在 多 线 程 的 操 作 中, 线 程 方 法 和 同 步 块 都 是 经 常 使 用 到 的, 线 程 方 法 就 是 run 方 法, 同 步 块 是 使 用 synchronized 关 键 字 定 义, 这 些 都 是 有 固 定 格 式 的 在 MyEclipse 中, 也 定 义 了 相 关 命 令 生 成 这 些 内 容

1. 同 步 块 29 先 来 看 一 下 同 步 块 的 自 动 生 成 首 先 定 义 一 个 类 名 为 SynchronizedTest 的 程 序, 代 码 为 : 01 package surround; 02 public class SynchronizedTest { 03 public static void main(string[] args) { 04 System.out.println(" 自 动 生 成 多 线 程 "); 05 } 06 } 选 中 其 中 的 第 4 行, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Surround With synchronized (synchronized block) 命 令, 在 上 述 代 码 变 为 : 01 package surround; 02 public class SynchronizedTest { 03 public static void main(string[] args) { 04 synchronized (args) { 05 System.out.println(" 自 动 生 成 多 线 程 "); 06 } 07 } 08 } 然 后 将 生 成 的 第 4 行 代 码 中 的 args 换 成 实 际 需 求 的 资 源 对 象, 则 该 同 步 块 就 开 发 完 成 这 里 我 们 主 要 就 是 看 同 步 块 语 句 包 围 方 式 的 使 用, 在 实 际 开 发 中, 是 比 较 上 的 将 同 步 块 定 义 在 main 方 法 中 的 2. 线 程 方 法 在 Java 语 言 中, 线 程 方 法 是 一 种 固 定 方 法 名 的 方 法, 方 法 名 为 run 在 MyEclipse 中, 也 可 以 使 用 命 令 自 动 将 某 些 功 能 代 码 放 到 多 线 程 方 法 中 这 里 我 们 仍 然 以 原 SynchronizedTest 类 程 序 举 例 选 中 其 中 的 第 4 行 代 码, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Surround With runnable (runnable) 命 令, 则 代 码 变 为 : 01 package surround; 02 public class SynchronizedTest { 03 public static void main(string[] args) { 04 new Runnable() { 05 public void run() { 06 System.out.println(" 自 动 生 成 多 线 程 "); 07 } 08 } 09 } 10 } 在 其 中 会 自 动 生 成 一 个 多 线 程 内 部 类, 在 内 部 类 中 定 义 run 线 程 运 行 方 法, 从 而 将 选 中 的 功 能 代 码 放 置 在 其 中 这 样 就 创 建 了 一 个 实 现 Runnable 接 口 的 线 程 对 象, 我 们 可 以 将 该 对 象 封 装 到 Thread 线 程 对 象 中 再 调 用 start 方 法, 从 而 启 动 线 程 注 意 : 在 实 际 开 发 中, 多 线 程 语 句 包 围 使 用 的 是 比 较 少 的 不 是 因 为 功 能 不 强 大,

是 因 为 这 些 语 句 在 开 发 中 使 用 时 非 常 灵 活 的, 自 动 生 成 后, 需 要 程 序 员 进 行 比 较 多 的 改 动 程 序 员 通 常 选 择 自 己 编 写 所 有 相 关 代 码

北风网讲师原创作品----仅供 www.ibeifeng.com 学员内部交流使用 第3章 重构 也就是在MyEclipse中的 Refactor菜单功能. 重构是对软件程序的一种调整 使用重构的目的就是在不改变软件可察行为的前提 下 调整软件结构 从而降低修改成本 重构是软件工程中非常重要的一个概念 只讲 重构的知识点 500 页的书都不能全部包括 在本书中主要来学习 MyEclipse 中支持的 对重构的操作 由于重构的内容比较多 我们按照重构的对象不同 将重构分为物理结构重构 类 内部重构 类层次上重构和引入重构 记忆 在 MyEclipse 的菜单中 Refactor 菜单中包含了所有重构操作 在编辑 区右键弹出菜单中 重构的快捷键为 Alt+Shift+T 这两种方式都可以进行重构操作 但是本书中的重构主要通过常用的包资源管理器节点的方式进行操作 3.1 物理结构重构 物理结构重构是最简单的 最容易被理解的重构方式 包括重命名 移动 改变方 法修饰符等操作 3.1.1 重命名 如果读者使用的是 Windows 操作系统 那么对于重命名操作是不陌生的 通过进行 重命名操作 可以改变文件的名称 但是当该文件被其他程序使用时 是不能进行修改 的 在 MyEclipse 中可以对类名 接口名 甚至是方法名 变量名进行重命名操作 而 且在使用或者调用这些名称的地方都会随着改变 这里我们通过类名来讲解重命名的操 作 说明 重命名操作的对象不同 所经过的操作步骤是不同的 但是操作流程是非 常类似的 读者可以学习完对类名的重命名后 对其他的也进行操作 例如创建两个 Java 类程序 分别是 Student 学生类和 Test 测试类 先来看 Student 学生类代码 01 package refactor; 02 public class Student { 03 String name; 04 int age; 05 public Student() { 06 } 07 public Student(String name, int age) {

08 this.name = name; 09 this.age = age; 10 } 11 public void say(){ 12 System.out.println(" 我 的 名 称 为 "+name+"; 年 龄 为 :"+age); 13 } 14 } 再 来 看 Test 测 试 类 的 代 码 : 01 package refactor; 02 public class Test { 03 public static void main(string[] args) { 04 Student stu=new Student("Tom",21); 05 stu.say(); 06 } 07 } 接 下 来 我 们 就 对 Student 学 生 类 的 类 名 进 行 重 命 名 操 作 首 先 我 们 来 看 一 下 当 前 项 目 的 包 资 源 管 理 器, 如 图 3-1 所 示 图 3-1 包 资 源 管 理 器 该 包 资 源 管 理 器 的 显 示, 可 能 和 读 者 的 有 所 不 同 在 这 里 只 需 要 单 击 节 点 前 面 的 加 号, 就 可 以 展 开 例 如 在 程 序 节 点 下 可 以 有 多 个 类 节 点, 在 类 节 点 下 可 以 有 多 个 变 量 节 点 构 造 函 数 节 点 和 方 法 节 点 在 进 行 重 命 名 操 作 时, 就 在 这 些 节 点 上 操 作 选 中 Student 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中, 选 择 Refactor Rename 命 令, 将 弹 出 重 命 名 界 面, 如 图 3-2 所 示

3 图 3-2 重 命 名 类 名 在 重 命 名 类 名 中, New name 选 项 是 用 来 填 写 重 命 名 后 的 新 类 名, 这 里 填 写 Teacher Update references 选 项 表 示 是 否 更 新 引 用, 默 认 是 选 中 的 状 态, 表 示 将 引 用 该 类 的 地 方 同 时 重 命 名 Update similarly named variables and methods 选 项 表 示 是 否 更 新 以 类 似 方 式 指 定 的 变 量 和 方 法, 默 认 是 不 选 中 的 状 态 下 面 两 个 选 项 是 用 来 判 断 是 否 更 新 注 释 和 非 Java 程 序, 通 常 是 不 选 择 这 两 项 的 按 照 上 述 操 作 后, 可 以 单 击 Finish 按 钮 完 成 操 作, 也 可 以 单 击 Next 按 钮 进 入 预 览 界 面, 如 图 3-3 所 示 图 3-3 重 命 名 预 览 在 重 命 名 预 览 界 面 中, Changes to be performed 栏 中 会 出 现 有 哪 些 程 序 发 生 了 改 变 在 其 中 进 行 选 择, 会 将 改 变 的 细 节 显 示 在 界 面 的 下 半 部 分, 包 括 原 代 码 内 容 查 看

重 命 名 的 预 览 没 有 问 题 后, 单 击 Finish 按 钮, 从 而 完 成 类 名 的 重 命 名 操 作 后 的 Student 学 生 类 代 码 变 为 : 01 package refactor; 02 public class Teacher { 03 String name; 04 int age; 05 public Teacher() { 06 } 07 public Teacher(String name, int age) { 08 this.name = name; 09 this.age = age; 10 } 11 public void say(){ 12 System.out.println(" 我 的 名 称 为 "+name+"; 年 龄 为 :"+age); 13 } 14 } 从 代 码 中 可 以 看 到, 不 但 类 名 由 Student 变 为 了 Teacher, 而 且 其 中 的 构 造 函 数 也 随 着 变 化 再 来 看 使 用 Student 学 生 类 的 Test 类 程 序 代 码 的 变 化 : 01 package refactor; 02 public class Test { 03 public static void main(string[] args) { 04 Teacher stu=new Teacher("Tom",21); 05 stu.say(); 06 } 07 } 从 代 码 中 可 以 看 到, 使 用 Student 类 的 地 方 也 由 Student 变 为 了 Teacher, 这 里 体 现 出 了 重 命 名 操 作 的 强 大 之 处 但 是 类 引 用 时 不 会 改 变 的, 例 如 stu 是 不 会 变 化 的, 如 果 程 序 员 觉 得 该 引 用 名 不 合 适, 需 要 手 动 修 改 技 巧 : 上 述 是 通 过 包 资 源 管 理 器 中 的 节 点 进 行 重 命 名 操 作 的, 该 操 作 也 可 以 在 编 辑 区 中 完 成 选 中 要 进 行 操 作 的 类 名 和 方 法 名, 在 右 键 弹 出 菜 单 中, 选 择 Refactor Rename 命 令, 就 进 入 重 命 名 操 作 界 面, 从 而 进 行 相 应 操 作 记 忆 : 重 命 名 操 作 的 快 捷 方 式 为 Alt+Shift+R, 使 用 该 快 捷 键 可 以 直 接 进 入 重 命 名 操 作 页 面 3.1.2 移 动 在 Windows 操 作 系 统 中, 可 以 对 文 件 进 行 剪 切 操 作 在 文 字 编 辑 工 具 中, 也 可 以 对 文 字 等 信 息 进 行 剪 切 操 作 在 MyEclipse 的 重 构 操 作 中, 也 有 类 似 的 操 作, 通 常 将 它 称 为 移 动 说 明 : 和 移 动 类 似 的 操 作, 那 就 是 复 制 粘 贴 例 如 在 A 包 下 复 制 一 个 Java 程 序, 然 后 选 中 B 包 后 粘 贴, 这 样 就 把 这 个 Java 程 序 复 制 了 一 份 放 到 B 包 中 这 是 比 较 简 单 的, 这 里 就 不 再 进 行 讲 解

5 移 动 操 作 的 对 象 和 重 命 名 操 作 一 样, 可 以 对 类 接 口 方 法 等 进 行 操 作, 同 样 也 会 进 行 相 应 的 改 变 通 常 类 和 接 口 都 会 放 在 包 下, 当 移 动 到 其 他 包 中 后, 则 包 语 句 代 码 会 自 动 变 化, 这 是 比 较 简 单 的 在 本 小 节 中, 主 要 来 学 习 一 下 方 法 的 移 动 由 于 在 上 一 小 节 中 已 经 将 Student 学 生 类 重 命 名 为 Teacher 老 师 类, 所 以 这 里 我 们 可 以 再 创 建 一 个 Student 学 生 类 程 序, 其 代 码 为 : 01 package refactor; 02 public class Student { 03 public static void sayhello(){ 04 System.out.println(" 大 家 好, 我 是 一 个 被 移 动 的 方 法 "); 05 } 06 public static void main(string args[]){ 07 Student.sayHello(); 08 } 09 } 在 包 资 源 管 理 器 中, 选 中 Student 类 节 点 下 的 sayhello 方 法 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 右 键 菜 单 中, 选 择 Refactor Move 命 令, 将 弹 出 移 动 操 作 界 面, 如 图 3-4 所 示 图 3-4 移 动 操 作 单 击 其 中 的 Browse 按 钮, 将 弹 出 填 写 和 选 择 移 动 目 标 的 界 面, 如 图 3-5 所 示

图 3-5 填 写 移 动 目 标 在 其 中 输 入 要 移 动 的 类, 如 果 该 类 出 现 在 多 个 包 下, 还 要 在 下 面 的 文 本 域 中 选 择 某 一 个 包 下 的 类 例 如 这 里 我 们 选 择 和 当 前 Student 学 生 类 在 同 一 包 (refactor 包 ) 下 的 Teacher 类 单 击 OK 按 钮, 从 而 完 成 移 动 目 标 的 选 择 经 过 上 面 的 操 作, 将 回 到 移 动 操 作 界 面 中, 在 其 中 还 可 以 单 击 Preview 按 钮, 看 一 下 移 动 操 作 的 预 览, 如 图 3-6 所 示 图 3-6 移 动 操 作 预 览 在 其 中 可 以 看 到 经 过 移 动 操 作 变 化 的 程 序, 已 经 代 码 的 具 体 变 化, 单 击 OK 按

钮, 完 成 预 览 的 观 看, 并 完 成 移 动 操 作 这 时 候,Teacher 老 师 类 中 的 代 码 变 为 : 01 package refactor; 02 public class Teacher { 03 String name; 04 int age; 05 public Teacher() { 06 } 07 public Teacher(String name, int age) { 08 this.name = name; 09 this.age = age; 10 } 11 public void say(){ 12 System.out.println(" 我 的 名 称 为 "+name+"; 年 龄 为 :"+age); 13 } 14 public static void sayhello(){ 15 System.out.println(" 大 家 好, 我 是 一 个 被 移 动 的 方 法 "); 16 } 17 } 7 可 以 看 到 在 Teacher 老 师 类 中, 多 出 了 一 个 sayhello 方 法, 这 是 因 为 我 们 将 sayhello 方 法 的 移 动 目 标 定 为 Teacher 老 师 类 再 来 看 一 下 Student 学 生 类 程 序 代 码 的 变 化 01 package refactor; 02 public class Student { 03 public static void main(string args[]){ 04 Teacher.sayHello(); 05 } 06 } 从 代 码 中 可 以 看 到,Student 学 生 类 中 的 sayhello 方 法 已 经 被 移 动 在 main 方 法 中, 原 来 由 Student 类 调 用 的 sayhello 方 法, 已 经 变 为 Teacher 老 师 类 进 行 调 用 了, 该 方 法 的 调 用 不 在 Student 类 中, 也 是 不 会 受 到 影 响 的, 从 而 不 影 响 功 能 的 实 现 注 意 : 进 行 移 动 操 作 的 方 法 只 能 是 static 修 饰 符 修 饰 的 静 态 方 法, 这 样 才 能 够 做 到 移 动 后 能 够 通 过 类 名 进 行 调 用, 从 而 不 影 响 原 有 功 能 注 意 : 在 进 行 大 部 分 重 构 操 作 后, 都 可 以 进 行 撤 销 操 作, 快 捷 键 为 Ctrl+Z, 它 不 是 仅 仅 撤 销 当 前 Java 程 序, 而 是 将 重 构 操 作 中 所 有 改 变 的 操 作 都 撤 销 记 忆 : 移 动 操 作 的 快 捷 键 为 Alt+Shift+V, 使 用 该 快 捷 键 可 以 直 接 进 入 移 动 操 作 界 面 中 3.1.3 更 改 方 法 签 名 在 Java 程 序 中, 方 法 中 的 元 素 是 比 较 多 的, 例 如 修 饰 符 返 回 类 型 方 法 名 参 数 和 抛 出 异 常 等 在 MyEclipse 中, 可 以 通 过 界 面 化 的 操 作, 对 这 些 元 素 进 行 更 改

在 包 资 源 管 理 器 中, 选 中 要 更 改 的 方 法 节 点, 例 如 这 里 我 们 更 改 移 动 后 的 sayhello 方 法 单 击 鼠 标 右 键, 在 右 键 弹 出 菜 单 中, 选 择 Refactor Change Method Signature 命 令, 就 会 进 入 更 改 方 法 签 名 界 面, 如 图 3-7 所 示 图 3-7 更 改 方 法 签 名 其 中 Access modifier 选 项 表 示 访 问 修 饰 符, 它 对 应 的 是 一 个 下 拉 列 表, 可 以 在 四 种 访 问 修 饰 符 中 选 择 Return type 选 项 表 示 方 法 的 返 回 类 型, Method name 选 项 表 示 方 法 名 称 接 下 来 有 两 个 选 项 卡, 分 别 是 Parameters 和 Exceptions Parameters 选 项 表 示 方 法 的 参 数, 这 里 可 以 填 写 多 个, 也 可 以 调 整 参 数 顺 序 单 击 Add 按 钮 添 加 一 个 参 数 后, 可 以 调 整 该 参 数 的 类 型 名 称 和 默 认 值, 分 别 由 Type Name 和 Default value 对 应 Exceptions 选 项 表 示 方 法 的 抛 出 异 常 类 型, 也 是 可 以 选 择 多 个 的 在 更 改 方 法 签 名 界 面 中, Methon signature preview 选 项 表 示 方 法 的 简 单 预 览 如 果 想 查 看 详 细 的 预 览, 可 以 单 击 Preview 按 钮, 预 览 界 面 如 图 3-8 所 示

9 图 3-8 更 改 方 法 签 名 预 览 该 预 览 界 面 是 和 前 面 的 重 构 预 览 界 面 非 常 类 似 的, 变 化 的 程 序 中, 不 但 Teacher 老 师 类, 还 有 Student 学 生 类, 因 为 在 Student 学 生 类 中 调 用 了 更 改 的 方 法 单 击 其 中 的 OK 按 钮, 则 完 成 更 改 方 法 签 名 的 操 作 看 下 面 Teacher 老 师 类 的 代 码 变 化 : 01 package refactor; 02 public class Teacher { 03 String name; 04 int age; 05 public Teacher() { 06 } 07 public Teacher(String name, int age) { 08 this.name = name; 09 this.age = age; 10 } 11 public void say(){ 12 System.out.println(" 我 的 名 称 为 "+name+"; 年 龄 为 :"+age); 13 } 14 public static void sayhello(string name){ 15 System.out.println(" 大 家 好, 我 是 一 个 被 移 动 的 方 法 "); 16 } 17 } 可 以 看 到,Teacher 老 师 类 中 的 sayhello 方 法 已 经 发 生 改 变, 其 中 多 出 了 一 个 字 符 串 类 型 的 名 称 为 name 的 参 数 我 们 再 来 看 Student 学 生 类 程 序 的 变 化 : 01 package refactor; 02 public class Student { 03 public static void main(string args[]){

04 Teacher.sayHello("Tom"); 05 } 06 } 可 以 看 到 调 用 该 更 改 方 法 的 代 码 也 发 生 的 改 变, 给 出 了 一 个 字 符 串 类 型 的 参 数 有 些 读 者 可 能 有 这 样 的 疑 问, Tom 参 数 值 是 什 么 地 方 来 的 呢? 它 是 在 更 改 方 法 签 名 界 面 中 设 置 参 数 时, 其 中 的 第 3 项 Default value, 就 是 用 来 设 置 调 用 该 方 法 时, 使 用 的 默 认 值 注 意 : 更 改 方 法 签 名 时, 可 能 会 造 成 程 序 的 错 误 例 如 我 们 将 sayhello 方 法 的 访 问 修 饰 符 该 为 private 私 有 级 别, 这 样 在 其 他 程 序 中 调 用 该 方 法 将 发 生 错 误 记 忆 : 更 改 方 法 签 名 的 快 捷 键 为 Alt+Shift+C, 使 用 该 快 捷 键 将 直 接 进 入 更 改 方 法 签 名 界 面 3.2 类 内 部 重 构 类 内 部 重 构 是 指 在 当 前 操 作 类 类 体 中 进 行 重 构 操 作, 其 中 包 括 抽 取 内 联 和 职 能 转 换 等 操 作 在 抽 取 操 作 中, 又 可 以 分 为 抽 取 方 法 抽 取 局 部 变 量 和 抽 取 常 量 等 具 体 操 作 在 职 能 转 换 操 作 中, 包 括 两 种 内 部 类 的 转 换 和 变 量 间 的 转 换 3.2.1 抽 取 方 法 在 Java 程 序 中, 通 常 将 完 成 特 定 的 功 能 的 代 码 放 在 一 个 方 法 中, 这 样 增 加 了 程 序 的 重 用 性, 也 使 程 序 更 易 读 在 项 目 中, 如 果 在 某 一 方 法 中 有 多 个 功 能 代 码, 或 者 一 段 代 码 在 多 处 使 用, 就 可 以 进 行 抽 取 方 法 操 作, 将 指 定 的 代 码 放 在 一 个 方 法 中 先 来 开 发 进 行 操 作 的 ExtractMethodTest 程 序, 其 代 码 为 : 01 package refactor; 02 public class ExtractMethodTest { 03 public void method1(){ 04 System.out.println(" 这 是 第 一 个 方 法 "); 05 for(int i=0;i<10;i++){ 06 System.out.println(i); 07 } 08 } 09 public void method2(){ 10 System.out.println(" 这 是 第 二 个 方 法 "); 11 for(int i=0;i<10;i++){ 12 System.out.println(i); 13 } 14 } 15 } 选 中 从 第 5 行 到 第 7 行 的 for 循 环 代 码, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Refactor Extract Method 命 令, 将 弹 出 抽 取 方 法 界 面, 如 图 3-9 所 示

11 图 3-9 抽 取 方 法 界 面 其 中 Method name 选 项 用 于 填 写 抽 取 方 法 后 的 方 法 名, Access modifier 选 项 用 于 选 择 抽 取 方 法 的 访 问 修 饰 符 Declare thrown runtime exceptions 选 项 表 示 是 否 声 明 抛 出 的 运 行 时 异 常 Generate method comment 选 项 表 示 是 否 生 成 注 释 Replace 1 occurrence of statements with method 选 项 表 示 将 所 有 的 该 语 句 替 换 成 方 法, 并 给 出 了 有 几 处 需 要 替 换 Method signature preview 选 项 表 示 简 单 预 览, 如 果 想 看 更 详 细 的 代 码 预 览, 可 以 单 击 Preview 按 钮, 读 者 可 以 自 己 查 看, 这 里 就 不 再 给 出 界 面 单 击 OK 按 钮, 从 而 完 成 抽 取 方 法 的 操 作 ExtractMethodTest 程 序 的 代 码 将 变 为 : 01 package refactor; 02 public class ExtractMethodTest { 03 public void method1(){ 04 System.out.println(" 这 是 第 一 个 方 法 "); 05 formethod(); 06 } 07 private void formethod() { 08 for(int i=0;i<10;i++){ 09 System.out.println(i); 10 } 11 } 12 public void method2(){ 13 System.out.println(" 这 是 第 二 个 方 法 "); 14 formethod(); 15 } 16 }

从 代 码 中 可 以 看 到, 从 第 7 行 到 第 11 行 定 义 了 一 个 名 称 为 formethod 的 方 法, 将 for 循 环 放 在 该 方 法 中 而 在 原 来 的 方 法 中 for 循 环 代 码 换 为 了 调 用 formethod 方 法 注 意 : 如 果 被 抽 取 的 代 码 在 静 态 方 法 中, 则 抽 取 后 的 方 法 就 是 静 态 方 法 同 理 如 果 被 抽 取 的 代 码 在 非 静 态 方 法 中, 则 抽 取 后 的 方 法 就 是 非 静 态 方 法 这 样 就 会 产 生 这 样 一 个 问 题, 如 果 被 抽 取 代 码 既 出 现 在 静 态 方 法 中, 又 出 现 在 非 静 态 方 法 中, 抽 取 得 到 非 静 态 方 法 后, 程 序 就 发 生 错 误, 需 要 手 动 修 改 记 忆 : 抽 取 方 法 操 作 的 快 捷 键 为 Alt Shift+M, 在 编 辑 区 中, 选 中 被 抽 取 的 代 码, 使 用 该 快 捷 键 将 自 动 进 入 抽 取 方 法 的 界 面 3.2.2 抽 取 局 部 变 量 在 上 一 小 节 中, 我 们 学 习 了 如 何 将 一 段 功 能 代 码 抽 取 成 一 个 方 法, 在 本 小 节 中 就 继 续 来 学 习 如 何 将 一 个 表 达 式 抽 取 成 局 部 变 量 如 果 在 一 个 程 序 中, 一 个 表 达 式 被 使 用 多 次, 就 可 以 将 该 表 达 式 抽 取 成 一 个 局 部 变 量, 将 使 用 该 表 达 式 的 地 方 都 替 换 为 该 局 部 变 量 首 先 定 义 了 一 个 类 名 为 ExtractLocalVariableTest 的 程 序, 它 的 代 码 为 : 01 package refactor; 02 public class ExtractLocalVariableTest { 03 public static void main(string args[]){ 04 int i=5; 05 boolean b1=(i==5)&true; 06 boolean b2=(i==5) false; 07 } 08 } 选 中 其 中 第 5 行 的 i==5 表 达 式, 在 右 键 弹 出 菜 单 中, 选 择 Refactor Extract Local Variable 命 令, 将 弹 出 抽 取 局 部 变 量 界 面, 如 图 3-10 所 示 图 3-10 抽 取 局 部 变 量 其 中 Variable name 选 项 表 示 抽 取 后 的 局 部 变 量 名 称 Replace alll occurrences of the selected expression with references to the local variable 选 项 表 示 是 否 将 所 有 出 现 该 表 达 式 的 地 方 都 替 换 成 抽 取 后 的 局 部 变 量 引 用, 默 认 是 选 中 的 状 态 Declare the local

variable as final 选 项 是 否 使 用 final 最 终 修 饰 符 修 饰 抽 取 后 的 局 部 变 量 13 在 界 面 中, 可 以 单 击 Preview 按 钮 查 看 改 动 预 览, 也 可 以 单 击 OK 按 钮 完 成 抽 取 局 部 变 量 操 作, 则 操 作 后 的 ExtractLocalVariableTest 程 序 代 码 为 : 01 package refactor; 02 public class ExtractLocalVariableTest { 03 public static void main(string args[]){ 04 int i=5; 05 boolean b = i==5; 06 boolean b1=(b)&true; 07 boolean b2=(b) false; 08 } 09 } 从 代 码 的 变 化 可 以 看 到, 将 i==5 这 个 表 达 式 抽 取 出 来, 赋 值 给 b 变 量, 将 使 用 该 表 达 式 的 地 方 都 替 换 成 了 变 量 b 记 忆 : 抽 取 局 部 变 量 操 作 的 快 捷 键 是 Alt+Shift+L, 使 用 该 快 捷 键 可 以 直 接 进 入 抽 取 局 部 变 量 的 界 面 3.2.3 抽 取 常 量 抽 取 常 量 是 和 抽 取 局 部 变 量 非 常 类 似 的, 但 是 它 的 限 制 要 求 更 多 因 为 常 量 的 修 饰 符 中 有 static 静 态 修 饰 符 和 final 最 终 修 饰 符, 所 以 抽 取 出 来 的 常 量 一 定 在 方 法 外, 也 就 是 在 类 中, 以 成 员 的 形 式 出 现, 这 也 就 造 成 被 抽 取 的 表 达 式 中 使 用 的 变 量 也 要 是 成 员 变 量 先 来 定 义 一 个 类 名 为 ExtractConstantTest 的 程 序, 其 代 码 为 : 01 package refactor; 02 public class ExtractConstantTest { 03 public static final int i=5; 04 public static void main(string args[]){ 05 boolean b1=(i==5)&true; 06 boolean b2=(i==5) false; 07 } 08 } 同 样 选 中 第 5 行 的 i==5 表 达 式, 然 后 在 右 键 弹 出 菜 单 中, 选 择 Refactor Extract Constant 命 令, 将 弹 出 抽 取 常 量 的 界 面, 如 图 3-11 所 示

图 3-11 抽 取 常 量 其 中 Constant name 选 项 表 示 抽 取 后 常 量 的 名 称, 在 Java 的 命 名 规 范 中 通 常 使 常 量 名 大 写 Access modifier 选 项 表 示 抽 取 后 常 量 的 访 问 修 饰 符, 可 以 在 四 种 访 问 修 饰 符 中 任 意 选 Replace alll occurrences of the selected expression with references to the constant 选 项 表 示 是 否 将 所 有 出 现 该 表 达 式 的 地 方 都 替 换 成 抽 取 后 的 常 量 引 用, 默 认 是 选 中 的 状 态 Qualify constant references with type name 选 项 表 示 是 否 使 用 类 型 名 限 定 常 量 引 用 在 抽 取 常 量 界 面 中, 同 样 可 以 单 击 Preview 按 钮 常 量 修 改 后 预 览 也 可 以 单 击 OK 按 钮 完 成 抽 取 常 量 操 作, 则 操 作 后 的 ExtractConstantTest 类 程 序 代 码 变 为 : 01 package refactor; 02 public class ExtractConstantTest { 03 public static final int i=5; 04 private static final boolean BOOLEAN = i==5; 05 public static void main(string args[]){ 06 boolean b1=(boolean)&true; 07 boolean b2=(boolean) false; 08 } 09 } 从 代 码 变 化 上 可 以 看 到 将 第 6 行 和 第 7 行 中 的 i==5 表 达 式 替 换 成 了 常 量, 并 把 表 达 式 赋 值 给 该 常 量 3.2.4 内 联 内 联 是 上 述 三 种 抽 取 操 作 的 反 向 操 作, 它 的 操 作 对 象 是 方 法 局 部 变 量 和 常 量 通 过 内 联 操 作, 可 以 使 用 代 码 代 替 调 用 方 法 或 者 使 用 局 部 变 量 和 常 量 的 地 方 这 里 我 们 通 过 方 法 的 形 式 来 讲 解 内 联 操 作 我 们 先 来 创 建 一 个 类 名 为 InlineTest 的 程 序, 它 的 代 码 为 : 01 package refactor; 02 public class InlineTest { 03 public void method1(){ 04 System.out.println(" 这 是 第 一 个 方 法 ");

15 05 formethod(); 06 } 07 private void formethod() { 08 for(int i=0;i<10;i++){ 09 System.out.println(i); 10 } 11 } 12 public void method2(){ 13 System.out.println(" 这 是 第 二 个 方 法 "); 14 formethod(); 15 } 16 } 读 者 对 该 代 码 应 该 是 不 陌 生 的, 这 就 是 我 们 抽 取 方 法 后 的 代 码 选 中 第 5 行 的 代 码, 在 MyEclipse 菜 单 中, 选 择 Refactor Inline 命 令, 将 弹 出 内 联 操 作 界 面, 如 图 3-12 所 示 图 3-12 内 联 其 中 All invocations 选 项 表 示 是 否 内 联 所 有 调 用 的 地 方, 这 里 选 择 该 选 项 然 后 会 在 该 选 项 下 出 现 一 个 Delete method declaration 选 项, 它 表 示 是 否 删 除 方 法 声 明, 也 就 是 调 用 的 方 法, 通 常 是 选 中 的 状 态 Only the selected invocation 选 项 表 示 仅 仅 内 联 选 择 的 调 用 同 样 在 该 界 面 中, 可 以 单 击 Preview 按 钮, 查 看 代 码 预 览, 也 可 以 单 击 OK 按 钮 完 成 内 联 操 作, 则 InlineTest 类 程 序 变 为 : 01 package refactor; 02 public class InlineTest { 03 public void method1(){ 04 System.out.println(" 这 是 第 一 个 方 法 "); 05 for(int i=0;i<10;i++){ 06 System.out.println(i); 07 } 08 } 09 public void method2(){ 10 System.out.println(" 这 是 第 二 个 方 法 ");

11 for(int i=0;i<10;i++){ 12 System.out.println(i); 13 } 14 } 15 } 从 代 码 的 变 化 可 以 看 到, 将 所 有 调 用 选 中 方 法 的 地 方 都 换 为 了 方 法 中 的 代 码, 而 且 定 义 的 方 法 被 删 除, 这 就 是 内 联 操 作 的 作 用 记 忆 : 内 联 操 作 的 快 捷 键 为 Alt+Shift+I, 使 用 该 快 捷 键 可 以 直 接 进 入 内 联 操 作 界 面, 但 是 要 在 前 面 先 进 行 选 择 对 什 么 对 象 进 行 操 作 3.2.5 将 匿 名 内 部 类 转 换 为 嵌 套 内 部 类 学 习 本 小 节 的 操 作 前, 读 者 一 定 要 先 了 解 Java 程 序 中 的 内 部 类 的 知 识 内 部 类 从 名 称 上 就 可 以 看 出, 它 是 在 一 个 类 的 内 部 再 定 义 另 一 个 类 内 部 类 在 Java 程 序 中 扮 演 两 种 角 色, 在 它 所 在 的 外 部 类 外, 它 可 以 被 看 做 是 外 部 类 的 成 员 在 所 在 的 外 部 类 内, 它 又 可 以 被 看 做 是 一 个 普 通 的 类 内 部 类 根 据 在 外 部 类 中 的 成 员 角 色 不 同 又 可 以 分 为 多 种, 本 节 中 提 到 的 匿 名 内 部 类 和 嵌 套 内 部 类 就 是 其 中 两 个 匿 名 内 部 类 是 指 没 有 自 己 名 称 的 内 部 类, 通 过 使 用 父 类 或 者 实 现 的 接 口 创 建 嵌 套 内 部 类 也 成 为 静 态 内 部 类, 在 外 部 类 中 使 用 static 静 态 修 饰 符 修 饰, 类 似 于 静 态 方 法 在 本 小 节 中, 就 来 看 如 何 使 用 MyEclipse 中 的 命 令 自 动 让 匿 名 内 部 类 转 换 成 嵌 套 内 部 类 先 来 开 发 一 个 具 有 匿 名 内 部 类 的 程 序, 其 代 码 为 : 01 package refactor; 02 public class CovertNestedTest { 03 public static void main(string[] args) { 04 new Runnable(){ 05 public void run(){ 06 System.out.println(" 将 匿 名 内 部 类 转 换 为 嵌 套 内 部 类 "); 07 } 08 }; 09 } 10 } 该 程 序 时 不 陌 生 的, 在 学 习 多 线 程 语 句 包 围 时 看 到 过 该 代 码, 其 中 将 功 能 代 码 包 围 在 线 程 方 法 中 选 中 其 中 的 匿 名 内 部 类 代 码, 也 从 第 4 行 到 第 8 行, 但 是 要 注 意 不 要 选 择 第 8 行 的 分 号, 不 然 不 能 进 行 操 作 在 MyEclipse 的 菜 单 中, 选 择 Refactor Conver Anonymous Class to Nested 命 令, 将 弹 出 进 行 内 部 类 转 换 的 界 面, 如 图 3-13 所 示

17 图 3-13 内 部 类 转 换 界 面 其 中 Access modifier 选 项 表 示 生 成 嵌 套 内 部 类 的 访 问 修 饰 符, 可 以 在 四 种 级 别 的 访 问 修 饰 符 中 选 择 Type name 选 项 表 示 生 成 嵌 套 内 部 类 的 类 名, 这 里 填 写 MyThread Declare the nested type as final 选 项 表 示 是 否 使 用 final 修 饰 生 成 的 嵌 套 内 部 类 单 击 Preview 按 钮 可 以 看 到 转 换 后 的 预 览, 单 击 OK 按 钮 将 完 成 转 换 操 作, 则 CovertNestedTest 类 程 序 代 码 变 为 : 01 package refactor; 02 public class CovertNestedTest { 03 private static final class MyThread implements Runnable { 04 public void run(){ 05 System.out.println(" 将 匿 名 内 部 类 转 换 为 嵌 套 内 部 类 "); 06 } 07 } 08 public static void main(string[] args) { 09 new MyThread(); 10 } 11 } 在 转 换 后 的 代 码 中, 从 第 3 行 到 第 7 行 创 建 一 个 类 名 为 MyThread 的 嵌 套 内 部 类, 它 实 现 Runnable 接 口, 其 中 的 功 能 代 码 是 不 会 发 生 改 变 的 在 第 9 行 中 创 建 了 该 嵌 套 内 部 类 对 象 注 意 : 在 进 行 从 匿 名 内 部 类 向 嵌 套 内 部 类 转 换 时, 一 定 要 仅 仅 选 择 匿 名 内 部 类 的 代 码, 不 要 多 选 了 任 何 内 容, 包 括 最 后 的 分 号, 甚 至 是 前 后 空 格 3.2.6 将 成 员 类 型 内 部 类 转 换 为 顶 级 类 在 上 一 小 节 中, 我 们 学 习 了 如 何 将 匿 名 内 部 类 转 换 成 嵌 套 内 部 类, 在 本 小 节 中 将 继 续 来 学 习 如 何 将 嵌 套 内 部 类 转 换 为 普 通 类 对 于 内 部 类 中 的 成 员 内 部 类 来 说 该 操 作 也 是 适 用 的, 我 们 这 里 仅 使 用 静 态 内 部 类 举 例

这 里 我 们 就 不 再 开 发 举 例 程 序, 而 是 在 变 化 后 的 CovertNestedTest 类 程 序 上 进 行 操 作 选 中 第 3 行 中 的 MyThread 类 名, 在 MyEclipse 的 菜 单 中, 选 择 Refactor Conver Member Type to Top Level 命 令, 将 弹 出 转 换 为 顶 级 类 的 界 面, 如 图 3-14 所 示 图 3-14 内 部 类 向 顶 级 类 转 换 在 界 面 中 将 显 示 变 化 的 代 码, 单 击 Preview 按 钮 可 以 查 看 预 览, 单 击 OK 按 钮 将 完 成 转 换 操 作 CovertNestedTest 类 程 序 变 化 后 的 代 码 为 : 01 package refactor; 02 public class CovertNestedTest { 03 public static void main(string[] args) { 04 new MyThread(); 05 } 06 } 可 以 看 到 其 中 的 嵌 套 内 部 类 已 经 没 有 了, 而 在 refactor 下 多 出 了 一 个 类 程 序, 类 名 为 MyThread, 这 就 是 原 静 态 内 部 类 类 名, 它 的 具 体 代 码 为 : 01 package refactor; 02 final class MyThread implements Runnable { 03 public void run(){ 04 System.out.println(" 将 匿 名 内 部 类 转 换 为 嵌 套 内 部 类 "); 05 } 06 } 从 这 里 可 以 看 到 生 成 后 的 新 类 和 原 嵌 套 内 部 类 的 功 能 相 同 的, 只 是 修 饰 符 不 能 再 是 原 来 的 private 和 static 修 饰 符 注 意 : 将 成 员 内 部 类 转 换 为 顶 级 类 和 将 嵌 套 内 部 类 转 换 为 顶 级 类 是 有 一 些 不 同 的 在 成 员 内 部 类 可 以 调 用 外 部 类 中 的 成 员, 所 以 为 了 不 影 响 功 能, 将 在 转 换 后 的 顶 级 类 中 生 成 一 个 具 有 外 部 类 类 型 参 数 的 构 造 函 数 技 巧 : 在 MyEclipse 中, 并 没 有 定 义 将 匿 名 内 部 类 转 换 为 顶 级 类 的 命 令, 但 是 我

19 们 可 以 将 匿 名 内 部 类 首 先 转 换 为 嵌 套 内 部 类, 再 将 潜 逃 内 部 类 转 换 为 顶 级 类 3.2.7 将 局 部 变 量 转 换 为 成 员 变 量 在 实 际 开 发 中, 定 义 完 局 部 变 量 后, 发 现 该 变 量 将 在 多 个 语 句 块 中 使 用, 这 时 候 就 要 将 该 局 部 变 量 提 升 为 成 员 变 量, 这 在 数 据 库 操 作 中 经 常 出 现 在 本 小 节 中, 就 来 看 一 下 在 MyEclipse 中 如 果 自 动 将 局 部 变 量 转 换 为 成 员 变 量 首 先 来 开 发 进 行 操 作 的 ConvertFieldTest 类 程 序, 其 代 码 为 : 01 package refactor; 02 public class ConvertFieldTest { 03 public void getname(){ 04 int age=21; 05 System.out.println(" 年 龄 为 :"+age); 06 } 07 } 选 中 第 4 行 的 age 变 量, 在 MyEclipse 的 菜 单 中, 选 择 Refactor Convert Local Variable to Field 命 令, 将 弹 出 转 换 成 员 变 量 界 面, 如 图 3-15 所 示 图 3-15 局 部 变 量 转 换 成 员 变 量 在 其 中 Field name 选 项 表 示 转 换 后 的 成 员 变 量 名 称, 通 常 和 原 局 部 变 量 名 称 相 同 Access modifier 选 项 表 示 转 换 后 成 员 变 量 的 访 问 修 饰 符, 可 以 在 四 种 级 别 的 修 饰 符 中 选 择 Initialize in 选 项 表 示 成 员 变 量 的 生 成 位 置, 其 中 Field declaration 表 示 字 段 声 明 处, Current method 表 示 当 前 方 法 前, Class constructor 表 示 类 构 造 函 数 处 Declare field as static 选 项 表 示 是 否 使 用 static 修 饰 符 修 饰 Declare field as final 选 项 表 示 是 否 使 用 final 修 饰 符 修 饰 单 击 Preview 按 钮 可 以 看 到 转 换 后 的 预 览 单 击 OK 按 钮 将 完 成 转 换 操 作, 则 转 换 后 的 ConvertFieldTest 类 程 序 代 码 为 :

01 package refactor; 02 public class ConvertFieldTest { 03 private int age; 04 public void getname(){ 05 age = 21; 06 System.out.println(" 年 龄 为 :"+age); 07 } 08 } 从 变 化 的 代 码 可 以 看 到, 将 第 5 行 的 局 部 变 量 变 为 第 3 行 的 成 员 变 量, 但 是 赋 值 操 作 仍 然 在 方 法 中 进 行, 从 而 不 影 响 程 序 功 能 注 意 : 如 果 局 部 变 量 在 非 静 态 方 法 中, 则 转 换 后 就 是 非 静 态 变 量 ; 如 果 局 部 变 量 在 静 态 方 法 中, 则 转 换 后 就 是 静 态 变 量 如 果 是 进 行 静 态 转 换, 则 Declare field as static 选 项 是 默 认 选 中 的 状 态, 而 且 不 让 修 改 3.3 类 层 次 重 构 类 层 次 重 构 泛 指 父 类 与 子 类 之 间 的 重 构, 也 可 以 是 接 口 和 实 现 类 之 间 的 重 构 其 中 包 括 抽 取 超 类 抽 取 接 口 等 抽 取 操 作, 尽 可 能 使 用 超 类 型 的 操 作, 以 及 对 成 员 进 行 的 下 推 和 上 拉 操 作 3.3.1 抽 取 超 类 抽 取 超 类 就 是 为 当 前 操 作 类 生 成 一 个 超 类, 生 成 的 超 类 可 以 是 非 抽 象 类, 也 可 以 是 抽 象 类 在 抽 取 超 类 中, 可 以 选 择 是 否 抽 取 子 类 中 的 方 法, 如 果 抽 取, 这 些 方 法 将 移 动 到 生 成 的 超 类 中 先 来 看 进 行 操 作 的 ExtractSuperclassTest 类 程 序, 其 代 码 为 : 01 package refactor; 02 public class ExtractSuperclassTest { 03 public void firstmethod(){ 04 System.out.println(" 这 是 第 一 个 方 法 "); 05 } 06 public void secondmethod(){ 07 System.out.println(" 这 是 第 二 个 方 法 "); 08 } 09 } 在 包 资 源 管 理 器 中, 选 中 ExtractSuperclassTest 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Extract Superclass 命 令, 将 弹 出 抽 取 超 类 界 面, 如 图 3-16 所 示

21 图 3-16 抽 取 超 类 其 中 Superclass name 选 项 表 示 抽 取 后 超 类 的 类 名, 这 里 填 写 SuperClass Use the extracted class where possible 选 项 表 示 是 否 尽 可 能 的 使 用 抽 取 的 超 类 来 引 用 子 类 对 象 Use the extracted calss in instanceof expressions 选 项 表 示 是 否 在 instanceof 表 达 式 中 使 用 抽 取 的 超 类 Create necessary methods stubs in non-abstract subtypes of the extracted type 表 示 当 抽 取 抽 象 超 类 时, 是 否 在 子 类 中 保 留 原 方 法 实 现 抽 象 方 法, 只 有 当 超 类 是 抽 象 类 时, 该 选 项 才 可 以 选 择 Type to extract a superclass from 栏 表 示 哪 些 类 将 继 承 抽 取 后 的 超 类, 默 认 的 是 当 前 操 作 类, 也 可 以 单 击 Add 按 钮 进 行 添 加 Specify actions for members 表 示 向 父 类 中 抽 取 哪 些 方 法 在 其 中 选 中 某 一 个 成 员, 例 如 这 里 选 中 firstmethod 方 法, 单 击 Set Action 按 钮, 将 弹 出 对 成 员 操 作 界 面, 如 图 3-17 所 示 图 3-17 成 员 操 作 设 置 其 中 默 认 的 是 extract 选 项, 它 表 示 抽 取 方 法 除 此 之 外, 还 包 括 declare abstract in superclass 选 项 将 抽 取 的 方 法 声 明 为 抽 象 方 法, 如 果 选 择 该 操 作, 则 抽 取 的 超 类 也 就

为 抽 象 类, 这 里 我 们 选 择 该 选 项 最 后 单 击 OK 按 钮 完 成 抽 取 方 法 的 操 作 回 到 抽 取 超 类 界 面 中, 单 击 Next 按 钮, 将 进 入 抽 取 超 类 预 览 界 面, 如 图 3-18 所 示 图 3-18 抽 取 超 类 预 览 在 预 览 界 面 中, 单 击 Finish 按 钮, 将 完 成 抽 取 超 类 的 操 作 在 当 前 refactor 包 下, 将 创 建 一 个 类 名 为 SuperClass 的 程 序, 其 代 码 为 : 01 package refactor; 02 public abstract class SuperClass { 03 public SuperClass() { 04 super(); 05 } 06 public abstract void firstmethod(); 07 } 从 代 码 中 可 以 看 到, 生 成 一 个 类 名 为 SuperClass 的 抽 象 父 类, 并 为 它 自 动 生 成 了 无 参 构 造 函 数 在 第 6 行 中 完 成 firstmethod 的 抽 取, 并 把 它 抽 取 成 抽 象 方 法 再 来 看 抽 取 后 的 ExtractSuperclassTest 类 程 序, 变 化 后 的 代 码 为 : 01 package refactor; 02 public class ExtractSuperclassTest extends SuperClass { 03 @Override 04 public void firstmethod(){ 05 System.out.println(" 这 是 第 一 个 方 法 "); 06 } 07 public void secondmethod(){

23 08 System.out.println(" 这 是 第 二 个 方 法 "); 09 } 10 } 其 中 firstmethod 方 法 是 实 现 的 超 类 中 的 抽 象 方 法 如 果 在 抽 取 超 类 界 面 中, 将 secondmethod 方 法 也 选 中, 并 设 置 操 作 是 抽 取, 则 该 方 法 将 出 现 在 SuperClass 类 程 序 中, 在 ExtractSuperclassTest 类 中 也 就 不 会 再 出 现 注 意 : 如 果 一 个 类 中 有 抽 象 方 法, 则 这 个 类 一 定 是 抽 象 类 但 是 在 抽 象 类 中, 不 一 定 有 抽 象 方 法 在 MyEclipse 中, 正 是 遵 守 该 语 法, 当 抽 取 方 法 是 设 置 操 作 为 抽 象 抽 取, 则 超 类 将 自 动 变 为 抽 象 类 3.3.2 抽 取 接 口 抽 取 接 口 是 和 抽 取 超 类 非 常 类 似 的, 使 用 该 操 作 可 以 从 当 前 操 作 类 抽 取 出 该 类 所 实 现 的 接 口, 在 其 中 也 可 以 将 方 法 抽 取 成 抽 象 方 法 同 样 还 是 开 发 一 个 操 作 类, 类 名 为 ExtractInterfaceTest, 它 的 程 序 代 码 为 : 01 package refactor; 02 public class ExtractInterfaceTest { 03 public void firstmethod(){ 04 System.out.println(" 这 是 第 一 个 方 法 "); 05 } 06 public void secondmethod(){ 07 System.out.println(" 这 是 第 二 个 方 法 "); 08 } 09 } 在 包 资 源 管 理 器 中, 选 中 ExtractInterfaceTest 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Extract Interface 命 令, 将 弹 出 抽 取 接 口 界 面, 如 图 3-19 所 示

图 3-19 抽 取 接 口 其 中 Interface name 选 项 表 示 抽 取 后 的 接 口 名 称, 这 里 填 写 MyInterface Use the extracted interface type where possible 选 项 表 示 是 否 尽 可 能 使 用 抽 取 的 接 口 类 型 引 用 子 类 对 象 Use the extracted interface in instanceof expressions 选 项 表 示 是 否 在 instanceof 表 达 式 中 使 用 抽 取 的 接 口 Declare interface methods as public 选 项 表 示 是 否 抽 取 方 法 后 使 用 public 修 饰 符 修 饰, Declare interface methods as abstract 选 项 表 示 是 否 抽 取 方 法 后 使 用 abstract 修 饰 符 修 饰, 这 两 个 选 项 仅 仅 是 代 码 层 面, 因 为 在 接 口 中, 如 果 你 没 写 这 些 修 饰 符, 系 统 也 会 自 动 加 上 Members to declare in the interface 选 项 栏 中, 用 于 选 择 哪 些 方 法 将 抽 取 到 接 口 中, 这 里 我 们 将 这 两 个 方 法 全 部 选 中 单 击 Preview 按 钮 可 以 看 到 抽 取 接 口 后 的 预 览, 单 击 OK 按 钮, 将 完 成 抽 取 接 口 的 操 作 将 在 refactor 包 下 创 建 一 个 接 口 为 MyInterface 的 接 口 程 序, 其 代 码 为 : 01 package refactor; 02 public interface MyInterface { 03 public abstract void firstmethod(); 04 public abstract void secondmethod(); 05 } 从 接 口 代 码 中 可 以 看 到 将 操 作 类 中 的 两 个 方 法 抽 取 成 抽 象 方 法, 放 置 在 该 接 口 中 再 来 看 ExtractInterfaceTest 类 程 序 变 化 后 的 代 码 : 01 package refactor; 02 public class ExtractInterfaceTest implements MyInterface { 03 /* (non-javadoc)

25 04 * @see refactor.myinterface#firstmethod() 05 */ 06 public void firstmethod(){ 07 System.out.println(" 这 是 第 一 个 方 法 "); 08 } 09 /* (non-javadoc) 10 * @see refactor.myinterface#secondmethod() 11 */ 12 public void secondmethod(){ 13 System.out.println(" 这 是 第 二 个 方 法 "); 14 } 15 } 首 先 在 第 2 行 中 让 原 ExtractInterfaceTest 类 程 序 实 现 抽 取 后 的 MyInterface 接 口 在 其 中 为 每 一 个 方 法 生 成 了 注 释, 表 示 该 方 法 是 实 现 了 接 口 中 的 方 法 说 明 : 抽 取 接 口 在 Java Web 开 发 中 是 经 常 要 到 的 目 前 Web 开 发 中 都 采 用 分 层 思 想, 在 数 据 访 问 层 和 业 务 逻 辑 层 中, 都 是 采 用 接 口 和 实 现 类 的 组 合 在 开 发 完 实 现 类 后, 就 可 以 使 用 抽 取 接 口 操 作, 将 相 应 的 接 口 抽 取 出 来 3.3.3 尽 可 能 使 用 超 类 型 超 类 型 是 指 当 前 操 作 类 的 超 类 类 型 或 者 接 口 类 型 在 Java 语 法 中, 可 以 使 用 父 类 类 型 引 用 或 者 接 口 类 型 应 用 指 向 子 类 对 象, 这 样 使 用 的 优 点 就 是 能 够 实 现 类 层 次 上 的 多 态 在 本 小 节 中, 就 来 学 习 一 下 如 何 使 用 MyEclipse 的 命 令, 来 进 行 尽 可 能 使 用 超 类 型 的 操 作 我 们 在 上 一 小 节 抽 取 接 口 后 的 ExtractInterfaceTest 类 程 序 基 础 上, 添 加 main 入 口 方 法, 其 代 码 为 : 01 package refactor; 02 public class ExtractInterfaceTest implements MyInterface { 03 /* (non-javadoc) 04 * @see refactor.myinterface#firstmethod() 05 */ 06 public void firstmethod(){ 07 System.out.println(" 这 是 第 一 个 方 法 "); 08 } 09 /* (non-javadoc) 10 * @see refactor.myinterface#secondmethod() 11 */ 12 public void secondmethod(){ 13 System.out.println(" 这 是 第 二 个 方 法 "); 14 } 15 public static void main(string[] args) { 16 ExtractInterfaceTest ei=new ExtractInterfaceTest(); 17 ei.firstmethod();

18 ei.secondmethod(); 19 } 20 } 在 包 资 源 管 理 器 中, 选 中 ExtractInterfaceTest 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Refactor Use Supertype Where Possible 命 令, 将 弹 出 选 择 超 类 型 的 界 面, 如 图 3-20 所 示 图 3-20 选 择 使 用 的 超 类 型 因 为 所 有 的 类 都 是 Object 的 子 类, 所 以 在 其 中 肯 定 有 Object 这 一 选 项 如 果 操 作 的 类 继 承 了 超 类, 或 者 实 现 了 接 口, 则 在 该 界 面 中 将 会 把 超 类 和 接 口 的 类 型 显 示 出 来 例 如 ExtractInterfaceTest 类 实 现 了 MyInterface 接 口, 则 在 其 中 显 示 MyInterface, 这 里 我 们 就 选 择 MyInterface 选 项 单 击 Preview 按 钮, 将 看 到 代 码 的 预 览 单 击 OK 按 钮 将 完 成 操 作, 则 ExtractInterfaceTest 类 程 序 变 化 后 的 代 码 为 : 01 package refactor; 02 public class ExtractInterfaceTest implements MyInterface { 03 /* (non-javadoc) 04 * @see refactor.myinterface#firstmethod() 05 */ 06 public void firstmethod(){ 07 System.out.println(" 这 是 第 一 个 方 法 "); 08 } 09 /* (non-javadoc) 10 * @see refactor.myinterface#secondmethod() 11 */ 12 public void secondmethod(){ 13 System.out.println(" 这 是 第 二 个 方 法 "); 14 } 15 public static void main(string[] args) { 16 MyInterface ei=new ExtractInterfaceTest(); 17 ei.firstmethod(); 18 ei.secondmethod(); 19 }

27 20 } 上 述 代 码 中 第 16 行 的 ExtractInterfaceTest 类 引 用 已 经 变 为 了 MyInterface 接 口 引 用, 从 而 就 变 为 使 用 接 口 引 用 指 向 实 现 类 对 象 如 果 代 码 中 有 多 种 同 样 情 况 都 会 使 用 同 种 操 作 更 改 说 明 : 在 JavaWeb 的 分 层 开 发 中, 本 小 节 的 操 作 也 经 常 被 用 到 例 如 在 Spring 框 架 的 开 发 中, 使 用 最 多 的 就 是 使 用 接 口 引 用 指 向 子 类 对 象, 但 是 这 里 的 对 象 是 通 过 系 统 创 建 后 注 入 的, 该 知 识 点 要 到 后 面 的 讲 解 中 才 会 学 到 3.3.4 下 推 下 推 和 上 拉 是 重 构 中 非 常 重 要 的 两 个 概 念, 它 们 的 操 作 对 象 就 是 父 类 和 子 类, 在 本 小 节 中 先 来 学 习 一 下 下 推 使 用 下 推 操 作, 可 以 将 父 类 中 的 成 员 ( 包 括 方 法 和 变 量 ) 移 动 到 它 的 直 接 子 类 中 如 果 操 作 的 是 方 法, 在 父 类 中 可 以 不 保 留 或 者 保 留 该 方 法 的 抽 象 方 法 同 样 还 是 先 来 开 发 进 行 操 作 的 程 序, 这 里 我 们 通 过 Person 类 和 Student 类 表 示 父 类 和 子 类 先 来 看 Person 类 的 代 码 : 01 package ref; 02 public class Person { 03 int time=8; 04 public void sleep(){ 05 System.out.println(" 睡 觉, 时 间 为 "+time+" 小 时 "); 06 } 07 public void eat(){ 08 System.out.println(" 吃 饭 "); 09 } 10 } 然 后 再 来 看 继 承 Person 类 的 Student 类, 其 代 码 为 : 01 package ref; 02 public class Student extends Person { 03 public void study(){ 04 System.out.println(" 学 习 "); 05 } 06 } 因 为 下 推 是 对 父 类 中 的 成 员 进 行 操 作, 所 以 在 包 资 源 管 理 器 中, 选 中 Person 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Push Down 命 令, 将 弹 出 下 推 操 作 界 面, 如 图 3-21 所 示

图 3-21 下 推 其 中 Specify actions for members 选 项 表 示 对 父 类 中 的 哪 些 成 员 进 行 下 推 操 作 在 右 边 有 四 个 按 钮, 其 中 Select All 按 钮 表 示 全 部 选 择, Deselect All 按 钮 表 示 全 部 不 选 择 Set Action 按 钮 表 示 对 成 员 的 操 作 设 置, 例 如 选 择 并 选 中 sleep 方 法, 然 后 单 击 该 按 钮, 将 弹 出 选 择 操 作 界 面, 如 图 3-22 所 示 图 3-22 成 员 下 推 操 作 其 中 有 两 个 选 项, push down 选 项 表 示 进 行 下 推 操 作, 将 选 中 的 方 法 移 动 到 子 类 中, 它 也 是 默 认 选 项 除 此 之 外, leave abstract declaration 选 项 表 示 在 父 类 中 保 留 抽 象 方 法, 如 果 选 择 该 选 项, 则 父 类 自 动 变 为 抽 象 类 在 下 推 操 作 界 面 中, Add Required 按 钮 表 示 将 已 选 择 成 员 所 必 须 的 成 员 也 选 择 上 例 如 在 sleeep 方 法 中 调 用 了 time 变 量, 选 择 sleeep 方 法 后, 单 击 该 按 钮, 将 自 动 将 time 变 量 选 择 上 按 照 上 述 选 择, 单 击 Preview 按 钮, 将 查 看 操 作 预 览 单 击 OK 按 钮 将 完 成 下 推 操 作, 则 Person 类 程 序 将 变 为 : 01 package ref; 02 public class Person { 03 public void eat(){ 04 System.out.println(" 吃 饭 "); 05 } 06 }

29 可 以 看 到 其 中 的 sleep 方 法 和 time 变 量 已 经 消 失, 这 里 就 是 将 它 们 下 推 到 Student 类 中 继 续 来 看 Student 类 的 代 码 : 01 package ref; 02 public class Student extends Person { 03 int time = 8; 04 public void study(){ 05 System.out.println(" 学 习 "); 06 } 07 public void sleep() { 08 System.out.println(" 睡 觉, 时 间 为 "+time+" 小 时 "); 09 } 10 } 可 以 看 到 原 来 属 于 Person 类 的 sleep 方 法 和 time 变 量 移 动 到 它 的 直 接 子 类, 也 就 是 Student 类 中 3.3.5 上 拉 上 拉 和 下 推 正 好 相 反, 它 是 将 子 类 中 的 成 员 移 动 到 它 的 父 类 中 在 操 作 中 也 可 以 选 择 是 整 体 移 动, 还 是 在 父 类 中 保 留 抽 象 方 法 这 里 我 们 开 发 一 个 继 承 Person 类 的 Teacher 类, 其 代 码 为 : 01 package ref; 02 public class Teacher extends Person { 03 public void teach(){ 04 System.out.println(" 讲 课 "); 05 } 06 public void refresher(){ 07 System.out.println(" 复 习 "); 08 } 09 } 在 包 资 源 管 理 器 中, 选 中 Teacher 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 右 键 菜 单 中, 选 择 Refactor Pull Up 命 令, 将 弹 出 上 拉 操 作 界 面, 如 图 3-23 所 示

图 3-23 上 拉 其 中 Select destination type 选 项 表 示 选 择 上 拉 的 目 标 类 型, 也 就 是 将 成 员 上 拉 到 哪 一 个 父 类 中 注 意 : 上 拉 目 标 类 型 可 以 选 择, 并 不 表 示 Java 类 能 够 继 承 多 个 父 类, 这 里 指 的 是 级 联 父 类 例 如 人 类 又 继 承 了 生 物 类, 则 这 里 还 会 出 现 生 物 类 的 选 项 下 面 的 三 个 选 项 在 前 面 已 经 多 次 讲 解 道, 这 里 就 不 再 重 复 讲 解 Specify actions for members 选 项 表 示 对 操 作 类 中 的 哪 些 成 员 进 行 上 拉 操 作, 这 里 和 下 推 操 作 是 非 常 相 似 的 选 择 并 选 中 teach 方 法, 单 击 Set Action 按 钮, 将 弹 出 选 择 上 拉 操 作 界 面, 如 图 3-24 所 示 图 3-24 成 员 上 拉 操 作 其 中 有 两 个 选 项, pull up 选 项 表 示 上 拉 移 动 选 中 的 成 员, 它 也 是 默 认 的 选 项 除 此 之 外, declare abstract in destination 选 项 表 示 将 上 拉 的 方 法 转 换 为 抽 象 方 法, 放 置 在 父 类 中, 如 果 选 择 该 选 项, 则 父 类 中 所 有 子 类 内 都 会 实 现 该 上 拉 的 方 法 读 者 可 以 自 己 进 行 该 选 项 的 操 作, 这 里 我 们 采 用 默 认 的 选 项

31 回 到 原 界 面, 单 击 Next 按 钮 将 查 看 到 代 码 的 变 化 和 预 览 单 击 Finish 按 钮 将 完 成 上 拉 操 作, 则 Teacher 类 的 代 码 将 变 为 : 01 package ref; 02 public class Teacher extends Person{ 03 public void refresher(){ 04 System.out.println(" 复 习 "); 05 } 06 } 可 以 看 到 Teacher 类 中 的 teach 方 法 已 经 消 失, 它 被 上 拉 到 Person 类 中 再 来 看 一 下 Person 类 的 代 码 : 01 package ref; 02 public class Person { 03 public void eat(){ 04 System.out.println(" 吃 饭 "); 05 } 06 public void teach() { 07 System.out.println(" 讲 课 "); 08 } 09 } 可 以 看 到 在 Teacher 类 中 消 失 的 teach 方 法 已 经 移 动 到 Person 类 中, 从 而 完 成 上 拉 操 作 3.4 引 入 重 构 引 入 重 构 是 指 在 原 事 物 的 基 础 上, 引 入 新 事 物, 从 而 进 行 封 装 操 作 其 中 包 括 引 入 间 接 方 法 引 入 工 厂 引 入 参 数 对 象 引 入 参 数 引 入 方 法 封 装 字 段 等 操 作 在 实 际 开 发 中 灵 活 使 用 这 些 引 入 操 作, 能 够 大 大 加 快 开 发 速 度 3.4.1 引 入 间 接 方 法 在 Java 程 序 中, 每 一 个 方 法 完 成 一 个 功 能, 项 目 的 实 现 就 是 通 过 调 用 这 些 方 法 完 成 的 在 项 目 开 发 中 期, 有 可 能 会 发 现 一 些 方 法 的 功 能 并 不 完 善, 但 是 通 常 不 改 变 已 经 测 试 通 过 的 方 法, 而 是 对 这 些 方 法 进 行 重 构, 产 生 间 接 方 法 在 间 接 方 法 中 调 用 原 方 法, 然 后 进 行 功 能 补 充, 让 调 用 原 方 法 的 地 方 调 用 这 个 间 接 方 法 在 本 小 节 中 就 来 学 习 一 下 在 MyEclipse 中, 如 何 使 用 命 令 完 成 该 引 入 间 接 方 法 的 重 构 操 作 这 里 我 们 通 过 电 梯 来 模 拟 该 操 作, 电 梯 最 基 本 的 功 能 就 是 上 下 运 动, 除 此 之 外 还 应 该 有 开 门 和 关 门 的 功 能 来 看 模 拟 电 梯 的 代 码 : 01 package ref; 02 public class Elevator { 03 public void work(){ 04 System.out.println(" 电 梯 上 下 运 动 "); 05 }

06 public void open(){ 07 System.out.println(" 开 门 "); 08 } 09 public void close(){ 10 System.out.println(" 关 门 "); 11 } 12 public static void main(string[] args) { 13 Elevator elevator = new Elevator(); 14 elevator.work(); 15 } 16 } 上 述 代 码 的 main 方 法 中, 仅 调 用 了 word 方 法, 是 不 能 完 成 电 梯 的 功 能 的 由 于 调 用 的 地 方 可 能 有 很 多, 如 果 将 开 门 和 关 门 的 方 法 再 调 用, 是 非 常 麻 烦 的 这 时 候 就 可 以 使 用 引 入 间 接 方 法 的 重 构 在 包 资 源 管 理 器 中, 选 中 work 方 法 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Introduce Indirection 命 令, 将 弹 出 进 行 引 入 间 接 方 法 操 作 的 界 面, 如 图 3-25 所 示 图 3-25 引 入 间 接 方 法 其 中 New method name 选 项 表 示 引 入 间 接 方 法 的 方 法 名, 这 里 填 写 workall Delaring type 选 项 表 示 将 引 入 的 间 接 方 法 放 置 在 哪 一 个 类 中, 这 里 我 们 就 选 择 和 原 方 法 在 同 一 个 类 中 Redirect all method invocations 选 项 表 示 是 否 重 定 向 所 有 方 法 的 调 用, 也 就 是 是 否 所 有 的 调 用 都 重 新 调 用 间 接 方 法, 默 认 是 选 中 状 态 单 击 Preview 按 钮 将 看 到 操 作 的 预 览 效 果 单 击 OK 按 钮 就 完 成 引 入 间 接 方 法 的 操 作, 则 Elevator 类 代 码 变 为 : 01 package ref; 02 public class Elevator { 03 public void work(){ 04 System.out.println(" 电 梯 上 下 运 动 "); 05 } 06 public void open(){

33 07 System.out.println(" 开 门 "); 08 } 09 public void close(){ 10 System.out.println(" 关 门 "); 11 } 12 public static void main(string[] args) { 13 Elevator elevator = new Elevator(); 14 Elevator.workAll(elevator); 15 } 16 public static void workall(elevator elevator) { 17 elevator.work(); 18 } 19 } 上 述 代 码 的 第 16 行 生 成 了 一 个 方 法 名 为 workall 的 方 法, 它 就 是 自 动 生 成 的 间 接 方 法, 在 其 中 第 17 行 中 调 用 work 方 法, 从 而 完 成 原 方 法 功 能, 这 里 只 从 而 给 出 当 前 类 类 型 的 参 数, 是 因 为 它 方 法 可 以 定 义 到 其 他 类 中 最 后 就 是 程 序 员 手 动 完 成 重 构 后 的 功 能, 在 workall 方 法 中, 添 加 其 他 功 能, 具 体 代 码 如 下 : 01 package ref; 02 public class Elevator { 03 public void work(){ 04 System.out.println(" 电 梯 上 下 运 动 "); 05 } 06 public void open(){ 07 System.out.println(" 开 门 "); 08 } 09 public void close(){ 10 System.out.println(" 关 门 "); 11 } 12 public static void main(string[] args) { 13 Elevator elevator = new Elevator(); 14 Elevator.workAll(elevator); 15 } 16 public static void workall(elevator elevator) { 17 elevator.open(); 18 elevator.work(); 19 elevator.close(); 20 } 21 } 在 第 16 行 的 间 接 方 法 中, 在 执 行 原 方 法 前 调 用 open 方 法, 在 原 方 法 后 调 用 close

方 法, 从 而 完 善 原 方 法 的 功 能 说 明 : 有 些 读 者 可 能 会 感 觉 到 北 小 节 学 习 的 内 容 和 前 面 学 习 的 代 理 方 法 有 所 类 似 的 如 果 仅 仅 是 完 善 某 一 个 方 法 的 功 能, 建 议 使 用 引 入 间 接 方 法 的 操 作 如 果 是 对 某 一 类 功 能 的 完 善, 则 就 应 该 使 用 代 理 3.4.2 引 入 工 厂 工 厂 模 式 也 是 设 计 模 式 中 非 常 重 要 的 一 种, 其 中 工 厂 类 是 必 不 可 少 的 在 Java Web 项 目 开 发 中, 在 使 用 Spring 框 架 之 前, 通 常 使 用 工 厂 类 来 创 建 对 象 使 用 工 厂 类 创 建 实 现 类 对 象 的 优 势 是 可 以 很 好 的 进 行 分 层, 例 如 在 业 务 逻 辑 层 中 只 需 要 知 道 数 据 访 问 接 口 就 行, 可 不 用 知 道 具 体 是 如 何 实 现 的 在 本 小 节 中, 就 来 学 习 一 下 如 何 在 工 厂 类 中 自 动 生 成 创 建 实 现 类 对 象 的 方 法 这 里 我 们 首 先 要 创 建 一 个 数 据 访 问 层 实 现 类 程 序, 其 代 码 为 : 01 package ref; 02 public class UserDAOImpl { 03 public UserDAOImpl(){ 04 } 05 } 在 进 行 本 小 节 的 操 作 前, 还 要 创 建 一 个 工 厂 类, 其 代 码 为 : 01 package ref; 02 public class UserDAOFactory { 03 } 注 意 : 在 实 现 类 中 只 所 以 要 定 义 无 参 构 造 函 数, 是 因 为 在 工 厂 类 中 创 建 对 象 时 要 知 道 调 用 哪 一 个 构 造 函 数, 本 小 节 操 作 也 是 基 于 该 无 参 构 造 函 数 的 在 MyEclipse 中, 也 不 会 自 动 创 建 工 厂 类, 所 以 在 执 行 操 作 前 一 定 要 首 先 把 工 厂 类 创 建 出 来 在 包 资 源 管 理 器 中, 选 中 UserDAOImpl 的 无 参 构 造 函 数 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 右 键 菜 单 中, 选 择 Refactor Introduce Factory 命 令, 将 弹 出 引 入 工 厂 操 作 界 面, 如 图 3-26 所 示 图 3-26 引 入 工 厂

35 其 中 Factory method name 选 项 表 示 在 工 厂 类 中 定 义 的 创 建 实 现 类 对 象 的 方 法 名, 这 里 就 是 用 默 认 的 createuserdaoimpl Factory class 选 项 表 示 工 厂 类 的 类 名, 这 里 选 择 填 写 UserDAOFactory Make constructor private 选 项 表 示 是 否 改 变 构 造 函 数 的 访 问 级 别, 这 里 采 用 默 认 选 中 状 态 单 击 Preview 按 钮 将 看 到 引 入 工 厂 操 作 的 预 览 单 击 OK 按 钮 将 完 成 引 入 工 厂 操 作, 则 UserDAOImpl 类 程 序 代 码 变 为 : 01 package ref; 02 public class UserDAOImpl { 03 UserDAOImpl(){ 04 } 05 } 可 以 看 到 构 造 函 数 的 访 问 级 别 已 经 发 生 改 变 再 来 看 工 厂 类 的 代 码 : 01 package ref; 02 public class UserDAOFactory { 03 public static UserDAOImpl createuserdaoimpl() { 04 return new UserDAOImpl(); 05 } 06 } 可 以 看 到 在 其 中 第 3 行 创 建 了 方 法 名 为 createuserdaoimpl 的 方 法, 在 其 中 返 回 UserDAOImpl 类 对 象 在 实 际 开 发 中, 经 常 定 义 方 法 的 返 回 类 型 为 接 口 类 型, 所 以 可 以 对 UserDAOImpl 类 执 行 抽 取 接 口 操 作, 具 体 操 作 见 抽 取 接 口 一 节 的 讲 解 3.4.3 引 入 参 数 对 象 在 实 际 开 发 中, 经 常 会 遇 到 这 样 的 现 象, 就 是 一 组 参 数 总 是 同 时 传 递 例 如 在 网 站 中, 用 户 注 册 和 登 录 的 操 作 会 对 应 着 注 册 和 登 录 方 法, 在 这 两 个 方 法 中 都 需 要 传 递 用 户 名 和 密 码 这 两 个 参 数 在 这 种 情 况 下 就 可 以 定 义 一 个 用 户 类, 向 注 册 和 登 录 方 法 中 传 递 用 户 类 类 型 的 参 数, 在 该 参 数 中 包 含 了 用 户 名 和 用 户 密 码 这 里 我 们 通 过 一 个 士 兵 的 程 序 来 更 形 象 的 说 明 该 重 构 操 作, 同 样 也 看 一 下 在 MyEclipse 中, 是 如 何 通 过 命 令 执 行 引 入 参 数 对 象 操 作 的, 士 兵 类 程 序 代 码 为 : 01 package ref; 02 public class Soldier { 03 public void sleep(string grade,string name){ 04 System.out.println(grade+" "+name+" 请 示 睡 觉 "); 05 } 06 public void eat(string grade,string name){ 07 System.out.println(grade+" "+name+" 请 示 吃 饭 "); 08 } 09 } 士 兵 在 执 行 某 件 事 时 都 要 进 行 请 示, 例 如 一 等 兵 张 三 请 示 睡 觉 二 等 兵 李 四 请 示 吃 饭 等 在 sleep 和 eat 方 法 中 都 需 要 士 兵 等 级 和 士 兵 姓 名 两 个 参 数, 这 时 候 就 可 以 使 用 引 入 参 数 对 象 的 重 构 操 作

在 MyEclipse 编 辑 区 中, 选 中 sleep 方 法 名, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Introduce Parameter Object 命 令, 将 弹 出 引 入 参 数 对 象 界 面, 如 图 3-27 所 示 图 3-27 引 入 参 数 对 象 其 中 Class name 选 项 表 示 创 建 参 数 对 象 的 类 型, 这 里 填 写 Parameter Destination 表 示 创 建 的 类 的 位 置, Top level class 选 项 表 示 创 建 顶 级 类, Nested class in Soldier 选 项 表 示 在 士 兵 类 中 创 建 嵌 套 内 部 类, 这 里 选 择 默 认 的 顶 级 类 Select fields for parameter object class 表 示 将 哪 些 参 数 设 置 到 引 入 的 参 数 类 中, 这 里 将 两 个 参 数 都 选 中 Create getters 和 Create setters 选 项 表 示 是 否 为 参 数 设 置 Getter 和 Setter 方 法, 它 们 的 选 择 关 系 到 参 数 的 调 用 方 式, 这 里 将 这 两 个 选 项 选 中 Parameter name 表 示 参 数 名 称, 这 里 保 留 默 认 的 parameterobject 在 界 面 的 最 下 方 会 看 到 简 单 的 预 览, 也 可 以 单 击 Preview 按 钮 查 看 详 细 预 览 单 击 OK 按 钮 将 完 成 引 入 参 数 对 象 的 操 作, 则 士 兵 类 代 码 将 变 为 : 01 package ref; 02 public class Soldier { 03 public void sleep(parameter parameterobject){ 04 System.out.println(parameterObject.getGrade()+" " 05 +parameterobject.getname()+" 请 示 睡 觉 "); 06 } 07 public void eat(string grade,string name){ 08 System.out.println(grade+" "+name+" 请 示 吃 饭 "); 09 } 10 } 从 代 码 中 可 以 看 到, 将 sleep 方 法 中 的 参 数 换 为 Parameter 类 型 的 参 数, 因 为 在 操 作 中 设 置 了 Getter 和 Setter 方 法, 所 以 获 取 参 数 值 时 通 过 它 们 设 置

37 除 了 士 兵 类 的 改 变 为, 在 和 士 兵 类 同 包 下, 还 会 创 建 Parameter 类 程 序, 其 代 码 为 : 01 package ref; 02 public class Parameter { 03 private String grade; 04 private String name; 05 public Parameter(String grade, String name) { 06 this.grade = grade; 07 this.name = name; 08 } 09 public String getgrade() { 10 return grade; 11 } 12 public void setgrade(string grade) { 13 this.grade = grade; 14 } 15 public String getname() { 16 return name; 17 } 18 public void setname(string name) { 19 this.name = name; 20 } 21 } 该 程 序 都 是 自 动 生 成 的, 其 中 生 成 了 grade 和 name 两 个 属 性, 它 们 就 是 操 作 方 法 中 的 原 参 数 第 5 行 中 生 成 了 具 有 上 面 两 个 参 数 的 构 造 函 数, 当 创 建 对 象 时 将 设 置 两 个 属 性 值 从 第 9 行 到 第 20 行 生 成 了 两 个 参 数 的 Getter 和 Setter 方 法, 这 是 在 引 入 参 数 对 象 界 面 中 选 择 的 3.4.4 引 入 参 数 引 入 参 数 和 引 入 参 数 对 象 是 两 种 完 全 不 一 样 的 操 作, 它 们 只 是 名 称 相 似 在 开 发 阶 段 的 方 法 中, 一 些 变 量 通 常 给 出 值 或 者 表 达 式 来 进 行 功 能 的 测 试, 在 测 试 没 有 问 题 后, 通 常 使 用 方 法 参 数 来 代 替 值 或 者 表 达 式 通 过 使 用 引 入 参 数 的 重 构 操 作 就 可 以 自 动 完 成 这 一 点 我 们 在 原 来 士 兵 类 的 基 础 上 定 义 一 个 新 方 法, 它 的 代 码 变 为 : 01 package ref; 02 public class Soldier { 03 // 省 略 其 他 方 法 04 public void sports(){ 05 String mygrade=" 一 等 兵 "; 06 String mygame=" 张 三 "; 07 System.out.println(myGrade+myGame+" 请 示 活 动 "); 08 } 09 }

在 第 4 行 的 sports 方 法 中, 将 通 过 使 用 参 数 给 出 的 士 兵 等 级 和 士 兵 姓 名 以 具 体 局 部 变 量 的 形 式 给 出 选 中 " 一 等 兵 " 内 容, 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Refactor Introduce Parameter 命 令, 将 弹 出 引 入 参 数 的 界 面, 如 图 3-28 所 示 图 3-28 引 入 参 数 其 中 Type 选 项 表 示 引 入 参 数 的 类 型, 它 和 参 数 的 内 容 有 关, 通 常 是 正 确 的 Name 选 项 表 示 引 入 参 数 的 名 称, 这 里 将 它 改 为 grade Keep original method as delegate to changed method 选 项 表 示 是 否 保 留 原 方 法 作 为 更 改 方 法 的 代 理, 默 认 是 不 选 中 的 状 态 在 界 面 的 下 面 可 以 看 到 方 法 的 简 单 预 览, 单 击 Preview 按 钮 可 以 看 到 完 整 预 览 单 击 OK 按 钮 将 完 成 引 入 参 数 的 操 作, 则 士 兵 类 的 代 码 将 变 为 : 01 package ref; 02 public class Soldier { 03 // 省 略 其 他 方 法 04 public void sports(string grade){ 05 String mygrade=grade; 06 String mygame=" 张 三 "; 07 System.out.println(myGrade+myGame+" 请 示 活 动 "); 08 } 09 } 从 代 码 中 可 以 看 到 将 原 局 部 变 量 值 以 参 数 代 替, 在 方 法 中, 给 出 了 一 个 grade 字 符 串 参 数 继 续 对 " 张 三 " 进 行 参 数, 可 以 继 续 为 方 法 添 加 一 个 name 字 符 串 参 数, 这 样 就 和 前 面 两 个 方 法 相 似 了 3.4.5 引 入 方 法 封 装 字 段 封 装 字 段 的 重 构 操 作 和 前 面 学 习 过 的 生 成 Getter Setter 方 法 非 常 类 似 的, 它 们 都 完 成 为 字 段 生 成 Getter 和 Setter 方 法 的 功 能 在 本 小 节 中 就 来 学 习 一 下 在 MyEclipse 中, 如 何 进 行 封 装 字 段 的 重 构 操 作 先 来 开 发 一 个 进 行 操 作 的 User 用 户 类, 其 代 码 为 :

39 01 package ref; 02 public class User { 03 int id; 04 String username; 05 } 在 包 资 源 管 理 中, 选 中 id 变 量 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 选 择 Refactor Encapsulate Field 命 令, 将 弹 出 封 装 字 段 操 作 的 界 面, 如 图 3-29 所 示 图 3-29 封 装 字 段 其 中 Getter name 和 Setter name 选 项 用 于 填 写 生 成 的 Getter 和 Setter 方 法 的 名 称, 默 认 给 出 最 标 准 的 方 法 名 Field access in declaring type 表 示 声 明 类 型 中 的 字 段 访 问, use setter and getter 选 项 表 示 使 用 Setter 和 Getter 方 法, keep field reference 选 项 表 示 保 留 字 段 引 用 Insert new methods agter 选 项 表 示 生 成 的 方 法 放 在 哪 个 方 法 之 后, 如 果 类 中 有 多 个 方 法, 都 会 做 为 选 项 出 现, 默 认 是 As first method, 表 示 做 为 第 一 个 方 法 Access modifier 选 项 表 示 生 成 方 法 的 访 问 修 饰 符, 通 常 选 择 public 单 击 Preview 按 钮 将 看 到 封 装 字 段 后 的 预 览 单 击 OK 按 钮 将 完 成 封 装 字 段 的 操 作, 操 作 后 的 User 用 户 类 的 代 码 将 变 为 : 01 package ref; 02 public class User { 03 private int id; 04 String username; 05 public void setid(int id) { 06 this.id = id; 07 } 08 public int getid() { 09 return id; 10 } 11 } 因 为 进 行 操 作 的 是 id 变 量, 从 而 从 第 5 行 到 第 10 行 生 成 了 它 的 Setter 和 Getter 方 法, 并 且 id 变 量 自 动 变 为 private 私 有 访 问 级 别

说 明 : 如 果 仅 仅 是 想 为 字 段 生 成 Getter 和 Setter 方 法, 就 应 该 使 用 MyEclipse 中 的 Generate Getters and Setters 命 令 因 为 该 命 令 要 比 重 构 中 的 封 装 字 段 更 简 单

北风网讲师原创作品----仅供 www.ibeifeng.com 学员内部交流使用 第4章 管理数据库 数据库在项目开发中是必不可少的 在 MyEclipse 中集成了管理数据库的功能 通 过 MyEclipse 可以对数据库进行操作 使用 MyEclipse 对数据库进行管理 还是后面学 习 Hibernate 等数据访问层框架的基础 在 MyEclipse 中 通过 MyEclipse Database Explorer 进行管理的 它的中文名称被 叫做 MyEclipse 数据库浏览器或者 MyEclipse 数据库管理器 并为它定义了单独的视图 在本章中就主要在 MyEclipse Database Explorer 视图下讲解如何管理数据库 4.1 认识 MyEclipse 中自带的数据库 在 MyEclipse 的默认安装中 会自带一款开源数据库 叫做 Derby Derby 数据库是 一款纯 Java 语言开发的开源免费数据库 在 Java JDK 6.0 版本中也包含该数据库 它已 经是 Java 的一部分 所以也把它称为 Java DB 4.1.1 切换到数据库视图 视图在第 1 章中 已经讲解过了 不同的视图对应着不同的程序开发 例如进行 Java 程序开发时 就可以选择 Java 视图 默认的视图 MyEclipse Java 开发视图 在该视图中 进行 Java 程序开发已经非常方便的 所以在前面的开发中并没有切换视图 但是在管理 数据库中 如果不切换到数据库视图 操作其中是非常不方便的 数据 库视 Explorer 命令 如果在 Open Perspective 下并没有 MyEclipse Database Explorer 图. 在 MyEclipse 的菜单中 选择 Window Open Perspective MyEclipse Database 命令 可以选择 Other 命令 在弹出的界面中 选择 MyEclipse Database Explorer 命令 这时 MyEclipse 中将发生大的改变 其中界面左半部分是数据库浏览器 右上部 分是编辑区 左下部分是控制台区 如图 4-1 所示

图 4-1 数 据 库 视 图 界 面 所 示 在 数 据 库 浏 览 器 中, 会 将 目 前 MyEclipse 中 能 够 管 理 的 数 据 库 显 示 出 来, 如 图 4-2 图 4-2 数 据 库 浏 览 器 因 为 在 MyEclipse 自 带 了 Derby 数 据 库, 所 以 在 这 里 默 认 会 将 这 个 数 据 库 显 示 出 来

3 当 加 入 新 的 外 部 数 据 库 后, 同 样 也 会 显 示 在 这 里 4.1.2 启 动 服 务 器 服 务 在 管 理 数 据 库 操 作 中, 启 动 服 务 器 服 务 并 不 是 必 须 的, 因 为 在 打 开 数 据 库 连 接 时, 会 自 动 执 行 该 操 作 但 是 在 Java 程 序 开 发 中, 如 果 要 进 行 数 据 库 操 作, 就 需 要 启 动 服 务 器 的 服 务 启 动 服 务 器 服 务 并 不 需 要 在 数 据 库 视 图 下 操 作 的, 在 原 视 图 下 就 可 以 完 成 在 控 制 台 区, 有 一 个 Servers 选 项 卡, 选 择 该 选 项 卡 就 可 以 看 到 目 前 有 哪 些 服 务 可 以 启 动, 如 图 4-3 所 示 图 4-3 启 动 服 务 其 中 MyEclipse Derby 就 是 要 启 动 的 Derby 数 据 库 服 务 器 服 务, 选 中 该 服 务, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Run Server 命 令 将 启 动 服 务, 并 进 入 到 控 制 台 中 控 制 台 显 示 内 容 为 : Apache Derby Network Server - 10.2.2.0 - (485682) 已 启 动 并 且 已 准 备 好 2009-11-04 06:59:47.359 GMT 时 在 端 口 1527 上 接 受 连 接 显 示 该 内 容 后, 表 示 Derby 数 据 库 服 务 已 经 启 动, 这 时 候 就 可 以 在 Java 程 序 中 进 行 Derby 数 据 库 的 操 作 4.1.3 打 开 数 据 库 连 接 回 到 数 据 库 视 图 中, 我 们 继 续 来 学 习 如 何 打 开 数 据 库 连 接 在 数 据 库 浏 览 器 中, 选 择 要 打 开 的 数 据 库 当 前 情 况 下 只 有 Derby 数 据 库, 所 以 我 们 选 择 该 数 据 库 单 击 鼠 标 右 键, 在 弹 出 菜 单 中, 选 择 Open connection 命 令 将 打 开 当 前 选 择 的 数 据 库 说 明 : 打 开 数 据 库 连 接, 也 可 以 使 用 数 据 库 浏 览 器 最 上 面 的 按 钮 进 行 操 作, 其 中 第 一 个 按 钮 就 是 打 开 数 据 库 连 接 按 钮 打 开 数 据 库 连 接 后, 将 把 当 前 数 据 库 中 已 经 创 建 的 具 体 数 据 库, 以 及 每 一 个 数 据 库 下 已 经 创 建 的 数 据 表 列 出 来 单 击 Connected to MyEclipse Derby 节 点 前 面 的 加 号, 将 把 所 有 数 据 库 信 息 显 示 出 来 单 击 某 一 数 据 库 节 点 前 的 加 号, 将 把 该 数 据 库 中 的 所 有 表 视 图 等 显 示 出 来 单 击 TABLE 节 点, 将 把 当 前 数 据 库 下 的 所 有 数 据 表 显 示 出 来 如 图 4-4 所 示

图 4-4 打 开 数 据 库 连 接 从 图 中 可 以 看 到 能 够 将 数 据 库 的 信 息 细 分 到 具 体 字 段 上, 并 人 为 地 为 它 们 起 了 相 应 的 名 称, 在 后 面 的 学 习 中 会 经 常 提 到 这 些 名 称 打 开 数 据 库 连 接 后, 我 们 来 看 一 下 如 何 关 闭 数 据 库 连 接 在 数 据 库 浏 览 器 的 最 上 面, 打 开 按 钮 的 后 面, 有 两 个 关 闭 按 钮 第 一 个 按 钮 表 示 关 闭 单 个 连 接, 选 择 某 一 连 接 对 象 后, 可 以 使 用 该 按 钮 第 二 个 按 钮 表 示 关 闭 所 有 数 据 库 连 接 4.1.4 查 看 数 据 库 详 细 信 息 在 上 一 小 节 中 打 开 数 据 库 连 接 后, 可 以 看 到 该 数 据 库 中 具 有 的 库 表 等 信 息 如 果 仅 能 看 到 这 些 信 息, 还 不 能 体 现 MyEclipse 的 强 大 之 处 在 控 制 台 区, 具 体 两 种 查 看 数 据 库 详 细 信 息 的 具 体 视 图, 分 别 是 DB Connection Info 和 Table/Object Info 选 择 DB Connection Info 选 项 卡, 将 显 示 连 接 数 据 库 的 详 细 信 息, 如 图 4-5 所 示

5 图 4-5 连 接 数 据 库 信 息 因 为 其 中 的 内 容 是 非 常 多 的, 在 图 中 并 不 能 完 全 体 现, 读 者 可 以 在 自 己 的 MyEclipse 中 查 看 到 这 里 也 不 能 对 这 些 信 息 完 全 讲 解 到, 我 们 选 择 几 条 重 要 的 信 息 进 行 说 明 其 中 URL 和 Username 就 是 在 JDBC 编 程 中 经 常 用 到 的 信 息, 连 接 MyEclipse 中 默 认 Derby 数 据 库 的 URL 为 jdbc:derby://localhost:1527/myeclipse, username 为 classiccars, 连 接 密 码 这 里 并 没 有 给 出, 密 码 也 是 classiccars 选 择 Table/Object Info 选 项 卡, 可 以 查 看 到 具 体 表 格 信 息, 如 图 4-6 所 示 图 4-6 具 体 表 格 信 息 在 其 中 又 具 有 显 示 更 详 细 信 息 的 选 项 卡 Columns 显 示 表 的 列 信 息, 包 括 列 名 类 型 大 小 等 Indexes 显 示 表 的 索 引 信 息, Primary Key 显 示 表 的 主 键 信 息, Foreign Keys 显 示 表 的 外 键 信 息, Exported Keys 显 示 表 的 导 出 主 键 信 息 Priview 显 示 表 的 具 体 数 据, 在 实 际 开 发 中 经 常 用 来 显 示 表 格 中 已 有 哪 些 数 据 Row Count 表 示 当 前 表 中 具 有 多 少 条 数 据 4.2 对 MySQL 数 据 库 的 管 理 在 上 一 节 中, 主 要 讲 解 了 MyEclipse 中 自 带 的 Derby 数 据 库, 在 目 前 实 际 开 发 中, Derby 数 据 库 使 用 并 不 多 的, 所 以 从 本 节 开 始 主 要 讲 解 如 何 使 用 MyEclipse 管 理 外 部 数 据 库 这 里 我 们 通 过 MySQL 数 据 库 为 例 进 行 讲 解, 在 学 习 本 节 之 前, 一 定 要 首 先 安 装

MySQL 数 据 库 4.2.1 建 立 MySQL 连 接 我 们 首 先 来 学 习 一 下 如 何 建 立 MyEclipse 外 部 的 MySQL 数 据 库 连 接 在 MyEclipse 的 数 据 库 浏 览 器 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New 命 令, 将 弹 出 建 立 数 据 库 连 接 的 界 面, 如 图 4-7 所 示 图 4-7 建 立 外 部 数 据 库 连 接 其 中 Driver template 选 项 表 示 建 立 连 接 的 数 据 库 类 型, 从 该 选 项 中 也 可 以 看 出 在 MyEclipse 中 支 持 非 常 多 的 数 据 库, 这 里 选 择 MySQL Connector/J 选 项, 它 就 表 示 MySQL 数 据 库 Driver name 选 项 表 示 建 立 连 接 后 的 名 称, 也 就 是 显 示 在 数 据 库 浏 览 器 中 的 名 称, 这 里 填 写 MySQL Connection URL 选 项 表 示 建 立 连 接 的 URL, 这 里 填 写 和 MySQL 建 立 连 接 的 URL, 也 就 是 jdbc:mysql://localhost:3306/myeclipse User name 和 Password 选 项 分 别 是 进 行 连 接 用 到 的 用 户 名 和 密 码 注 意 : 这 里 没 有 给 出 具 体 的 用 户 名 和 密 码 的 内 容, 是 因 为 每 个 人 安 装 MySQL 时 设 置 的 密 码 有 所 不 同 的, 要 根 据 本 地 的 设 置 来 填 写 Driver JARS 栏 用 于 导 入 MySQL 的 驱 动 包, 单 击 Add JARS 按 钮, 在 弹 出 的 界 面 中 找 到 本 地 驱 动 包 导 入 驱 动 包 后, 在 Driver calssname 选 项 中 将 自 动 填 写 用 于 连 接 的 驱 动 串 单 击 Test Driver 按 钮, 可 以 对 当 前 连 接 进 行 测 试, 单 击 后 将 弹 出 输 入 密 码 界 面,

7 如 图 4-8 所 示 图 4-8 输 入 连 接 密 码 输 入 安 装 MySQL 数 据 库 时 设 置 的 连 接 数 据 库 的 密 码 后, 单 击 OK 按 钮, 如 图 弹 出 如 图 4-9 所 示 的 界 面, 则 表 示 连 接 数 据 库 的 配 置 正 确 图 4-9 测 试 连 接 成 功 如 果 在 建 立 连 接 界 面 中, 选 中 Save Password 选 项, 再 次 对 连 接 进 行 测 试, 将 不 用 再 输 入 密 码 单 击 Finish 按 钮 将 完 成 建 立 MySQL 连 接 操 作 在 数 据 库 浏 览 器 中, 将 多 出 现 一 个 名 称 为 MySQL 的 数 据 库 连 接, 对 于 它 也 可 以 进 行 上 一 节 学 习 的 打 开 和 查 看 数 据 库 操 作 说 明 : 测 试 在 开 发 中 是 非 常 重 要 的 组 成 部 分, 读 者 在 开 发 中 也 要 养 成 测 试 的 习 惯 通 过 测 试 能 够 保 证 自 己 所 做 的 每 一 步 都 是 正 确 的, 所 以 方 便 后 面 的 使 用 4.2.2 编 辑 和 复 制 数 据 库 连 接 建 立 外 部 数 据 库 连 接 后, 还 可 以 对 该 连 接 进 行 相 应 操 作, 例 如 编 辑 复 制 和 删 除 等 在 数 据 库 浏 览 器 中, 选 中 上 一 小 节 建 立 的 MySQL 连 接, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Edit 命 令, 将 弹 出 对 数 据 库 连 接 进 行 编 辑 操 作 的 界 面, 如 图 4-10 所 示

图 4-10 编 辑 数 据 库 连 接 在 其 中 会 首 先 将 MySQL 连 接 的 信 息 显 示 出 来, 在 该 界 面 中 可 以 对 这 些 进 行 修 改, 修 改 后 单 击 Finish 按 钮 将 完 成 对 数 据 库 连 接 的 编 辑 在 弹 出 的 右 键 菜 单 中, 还 可 以 选 择 Copy 命 令, 将 弹 出 和 编 辑 界 面 类 似 的 界 面, 它 的 操 作 结 果 就 是 另 外 创 建 一 个 数 据 库 连 接 例 如 不 再 连 接 MySQL 数 据 库 中 的 myeclipse 数 据 库, 而 是 连 接 java 数 据 库, 这 时 候 就 可 以 改 动 其 中 的 URL, 变 为 jdbc:mysql://localhost:3306/java, 然 后 改 变 连 接 名 称, 这 样 就 复 制 出 来 另 外 一 个 连 接 除 了 Edit 命 令 和 Copy 命 令 外, 还 有 Delete 命 令, 通 过 它 可 以 将 建 立 的 链 接 删 除 4.2.3 导 出 和 导 入 数 据 库 连 接 在 MyEclipse 中, 可 以 对 Java 项 目 进 行 导 出 和 导 入 操 作, 同 样 对 数 据 库 连 接 也 可 以 进 行 导 出 导 入 操 作 在 数 据 库 浏 览 器 中, 选 中 要 导 入 的 数 据 库 连 接, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Export 命 令, 将 弹 出 导 出 操 作 的 界 面, 如 图 4-11 所 示

9 图 4-11 导 出 数 据 库 连 接 在 其 中 Select the drivers to export 选 项 中 选 择 要 导 入 的 数 据 库, 这 里 我 们 仅 选 择 MySQL File 选 项 表 示 导 出 的 目 标 文 件, 也 就 是 将 信 息 导 出 到 哪 一 个 文 件 中, 这 里 可 以 自 己 填 写, 也 可 以 单 击 Browse 按 钮 选 择 导 出 的 位 置 单 击 Finish 按 钮 将 完 成 导 出 数 据 库 连 接 的 操 作 导 出 数 据 库 连 接 后, 我 们 再 来 看 一 下 如 何 导 入 数 据 库 连 接 首 先 我 们 将 数 据 库 浏 览 器 中 的 MySQL 连 接 删 除, 然 后 在 其 中 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Import 命 令, 将 弹 出 导 入 连 接 的 界 面, 如 图 4-12 所 示

图 4-12 导 入 数 据 库 连 接 其 中 File 选 项 表 示 要 导 入 的 文 件, 这 里 选 择 a.sql 文 件, 它 是 上 面 导 出 操 作 生 成 的 文 件 选 择 该 文 件 后, 在 MyEclipse JDBC Drivers 栏 中 就 会 将 能 够 导 入 的 数 据 库 连 接 显 示 出 来 单 击 Finish 按 钮 就 会 将 该 数 据 库 连 接 导 入, 从 而 将 MySQL 连 接 继 续 显 示 在 数 据 库 浏 览 器 中, 如 图 4-13 所 示 图 4-13 导 入 后 4.3 进 行 数 据 库 操 作 在 前 面 的 讲 解 中, 我 们 主 要 对 数 据 库 连 接 进 行 操 作 在 本 节 中 将 主 要 来 学 习 如 何 在 MyEclipse 中 进 行 数 据 库 的 相 关 操 作, 包 括 创 建 和 删 除 数 据 库 创 建 和 删 除 数 据 表 插 入 数 据 等, 以 及 MyEclipse 中 特 有 的 集 成 功 能

11 4.3.1 创 建 数 据 库 创 建 数 据 库 是 数 据 库 操 作 中 最 基 本 的 操 作 之 一, 在 MyEclipse 中 也 可 以 通 过 SQL 语 句 进 行 创 建, 我 们 这 里 主 要 来 看 如 何 界 面 化 创 建 数 据 库 在 数 据 库 浏 览 器 中, 选 中 Connected to MySQL 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Create Database 命 令, 将 弹 出 创 建 数 据 库 的 界 面, 如 图 4-14 所 示 图 4-14 创 建 数 据 库 其 中 Database name 选 项 用 来 输 入 新 建 数 据 库 的 名 称, 这 里 填 写 mydb Character set 选 项 表 示 创 建 数 据 库 的 字 符 集, 这 里 选 择 表 示 简 体 中 文 的 gb2312 Collation 选 项 表 示 创 建 数 据 库 的 字 符 编 码, 这 里 选 择 和 字 符 集 对 应 的 gb2312_chinese_ci 单 击 Finish 按 钮, 则 完 成 创 建 数 据 库 的 操 作, 从 而 在 MySQL 中 创 建 了 一 个 名 称 为 mydb 的 数 据 库 注 意 : 创 建 数 据 库 时 设 置 字 符 集 和 编 码 是 非 常 重 要 的, 尤 其 是 对 于 中 文 信 息 储 存 时 如 果 选 择 的 字 符 集 和 编 码 不 支 持 中 文, 则 保 存 信 息 后 显 示 的 将 是 乱 码 4.3.2 创 建 数 据 表 创 建 数 据 库 后, 我 们 就 可 以 继 续 在 数 据 库 下 创 建 数 据 表 创 建 数 据 表 也 是 可 以 通 过 SQL 语 句 完 成 的, 但 是 这 里 仍 然 先 来 学 习 如 何 通 过 界 面 进 行 创 建 选 中 mydb 数 据 库 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 new Table 命 令, 将 弹 出 创 建 数 据 表 的 界 面, 如 图 4-15 所 示

图 4-15 创 建 数 据 表 其 中 Catalog 选 项 表 示 新 创 建 的 数 据 表 所 属 哪 个 数 据 库, 这 是 会 自 动 填 写 好 的 Table name 选 项 表 示 新 创 建 数 据 表 的 名 称, 这 里 填 写 user, 表 示 创 建 一 个 用 户 表 下 面 有 两 个 选 项 卡, 在 Table Info 选 项 卡 中, 填 写 数 据 表 的 相 关 信 息, Primary key name 表 示 数 据 表 的 主 键 名 称, Table type 表 示 数 据 表 的 类 型, Description 表 示 数 据 表 的 描 述, 这 些 都 是 可 以 不 填 写 的 在 Columns 选 项 卡 中 完 成 向 数 据 表 中 添 加 字 段 的 功 能, 单 击 Add 按 钮 将 弹 出 创 建 数 据 表 字 段 界 面, 如 图 4-16 所 示

13 图 4-16 创 建 字 段 其 中 Name 选 项 表 示 字 段 的 名 称, 这 里 填 写 id Type 选 项 表 示 字 段 的 类 型, 在 其 中 选 择 INT Size 表 示 字 段 大 小, 对 于 id 而 言, 通 常 填 写 11 Precision 表 示 大 小 精 度, 对 于 INT 类 型 来 说, 是 不 需 要 设 置 它 的 Default value 选 项 表 示 字 段 的 默 认 值, 这 里 可 以 不 填 写 Nullable 选 项 表 示 字 段 内 容 是 否 可 以 为 空, 选 中 表 示 可 以 为 空, 它 也 是 默 认 选 择 Unique 选 项 表 示 字 段 内 容 是 否 是 唯 一 的, 也 就 是 是 否 可 以 重 复 Primary key 选 项 表 示 字 段 是 否 为 主 键 Auto increment 选 项 表 示 是 否 自 动 递 增 在 Description 选 项 中 可 以 给 出 对 该 字 段 的 描 述 单 击 Finish 按 钮, 将 完 成 id 字 段 的 创 建 使 用 同 样 的 创 建 字 段 的 方 法, 再 创 建 一 个 name 字 段 回 到 创 建 数 据 表 的 界 面 中 后, 单 击 Finish 按 钮, 从 而 完 成 数 据 表 的 创 建 这 样 就 在 mydb 数 据 库 下 创 建 了 一 个 user 用 户 表, 其 中 具 有 id 和 name 两 个 字 段 注 意 : 不 同 数 据 库 之 间, 字 段 的 类 型 是 有 所 不 同 的 在 创 建 数 据 表 时, 要 根 据 数 据 库 的 不 同 来 选 择 相 对 应 的 类 型 4.3.3 删 除 数 据 表 删 除 数 据 表 是 和 创 建 数 据 表 相 对 应 的, 它 是 非 常 容 易 操 作 的 选 中 要 删 除 的 数 据 表 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Drop Table 命 令, 将 弹 出 选 择 是 否 删 除 数 据 表 的 对 话 框, 如 图 4-17 所 示

图 4-17 删 除 数 据 表 单 击 OK 按 钮, 将 完 成 删 除 user 数 据 表 的 操 作 4.3.4 进 行 SQL 语 句 编 辑 在 MyEclipse 中 也 可 以 通 过 SQL 语 句 来 进 行 数 据 库 操 作,SQL 语 句 是 数 据 库 操 作 中 最 直 接 的 操 作 方 式 选 中 Connected to MySQL 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New SQL Editor 命 令, 将 在 编 辑 区 中 出 现 用 于 输 入 SQL 语 句 的 编 辑 界 面, 如 图 4-18 所 示 图 4-18 SQL 语 句 编 辑 器 其 中 最 左 端 的 绿 三 角 是 执 行 SQL 语 句 按 钮, Connection 选 项 表 示 对 哪 一 个 连 接 进 行 操 作, 这 里 选 择 MySQL Catalog 选 项 表 示 对 哪 一 个 数 据 库 进 行 操 作, 这 里 选 择 上 一 小 节 创 建 的 mydb 数 据 库 Cmd Sep 选 项 表 示 使 用 什 么 符 号 做 为 分 隔 符 例 如 我 们 在 其 中 输 入 插 入 数 据 的 SQL 语 句, 内 容 如 下 : insert into user values (1,'Tom'); insert into user values (2,'Jerry'); 然 后 单 击 执 行 按 钮, 或 者 使 用 它 的 快 捷 键 Ctrl+F9, 将 会 将 这 两 条 SQL 语 句 执 行, 执 行 后 在 编 辑 区 的 下 面 会 显 示 已 更 多 记 录 数 量 如 果 SQL 语 句 中, 存 在 错 误, 也 会 进 行 报 错 打 开 控 制 台 区 的 Table/Object Info 选 项 卡 下 的 Preview 选 项, 将 看 到 刚 执 行

15 SQL 语 句 插 入 的 两 条 记 录, 如 图 4-19 所 示 图 4-19 插 入 记 录 结 果 在 控 制 台 区 的 SQL History 选 项 卡 中, 会 将 所 有 已 经 执 行 过 的 SQL 语 句 显 示 出 来, 如 图 4-20 所 示 图 4-20 SQL 语 句 历 史 记 录 在 其 中 选 中 某 条 记 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 有 三 个 命 令 使 用 Open in editor 命 令, 将 打 开 编 辑 区, 并 且 将 当 前 选 中 的 SQL 语 句 放 在 编 辑 区 中 使 用 Remove from history 命 令 将 把 该 条 SQL 语 句 从 历 史 记 录 中 删 除 使 用 Copy to Clipboard 命 令 将 对 该 条 SQL 语 句 进 行 复 制, 然 后 可 以 粘 贴 到 编 辑 区, 或 者 其 他 地 方 说 明 : 在 SQL 语 句 编 辑 区 中 可 以 进 行 所 有 的 数 据 库 操 作, 例 如 创 建 数 据 库 创 建 数 据 表, 以 及 增 删 改 查 操 作, 但 是 这 些 操 作 大 部 分 都 是 可 以 通 过 界 面 化 的 操 作 完 成 的, 所 以 在 本 小 节 中 主 要 通 过 插 入 数 据 来 讲 解 它 的 使 用 4.3.5 编 辑 数 据 表 数 据 向 数 据 表 中 插 入 数 据 后, 可 能 还 会 对 已 经 插 入 的 数 据 进 行 修 改, 这 里 我 们 主 要 来 看 一 下 在 MyEclipse 中 如 何 界 面 化 的 进 行 该 操 作

首 先 要 选 中 要 进 行 编 辑 操 作 的 数 据 表 节 点, 这 里 我 们 选 中 user 数 据 表 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Edit Data 命 令, 将 在 控 制 台 区 中 出 现 一 个 新 的 Edit table 选 项 卡, 并 在 其 中 将 该 数 据 表 中 已 有 数 据 显 示 出 来, 如 图 4-21 所 示 图 4-21 编 辑 数 据 在 其 中 就 可 以 选 择 已 有 数 据, 对 这 些 数 据 进 行 修 改 了 例 如 我 们 将 Jerry 改 为 Lucy, 按 下 回 车 键, 将 在 该 界 面 下 显 示 Cell updated successfully 信 息, 表 示 数 据 更 新 成 功 4.3.6 删 除 数 据 表 所 有 数 据 删 除 数 据 表 所 有 数 据 和 删 除 数 据 表 是 不 同 的 两 种 操 作, 删 除 数 据 表 数 据 是 将 表 下 所 有 数 据 删 除, 但 不 删 除 表, 从 而 使 该 表 中 不 再 拥 有 任 何 数 据 选 中 要 进 行 删 除 数 据 操 作 的 数 据 表 节 点, 这 里 仍 然 以 user 表 为 例 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Delete All Rows 命 令, 将 弹 出 删 除 对 话 框, 如 图 4-22 所 示 图 4-22 删 除 数 据 其 中 Delete rows 按 钮 表 示 执 行 删 除 数 据 表 所 有 数 据 操 作 Open command in editor 按 钮 表 示 生 成 删 除 的 SQL 语 句, 并 显 示 在 SQL 语 句 编 辑 区 中, 在 编 辑 区 中 通 过 SQL 语 句 执 行 删 除 操 作 Cancel 按 钮 表 示 取 消 4.3.7 创 建 和 删 除 外 键 外 键 是 用 于 建 立 和 加 强 表 与 表 之 间 关 系 的 数 据 库 重 要 事 物, 例 如 购 物 网 站 中, 用 户

17 会 对 应 一 个 订 单, 但 是 不 可 能 把 订 单 信 息 都 保 存 到 用 户 表 中 通 常 将 它 们 分 别 保 存 在 不 同 的 表 中, 然 后 在 用 户 表 中 创 建 一 个 外 键 来 连 接 订 单 的 主 键, 从 而 使 这 两 个 表 建 立 关 系 为 了 进 行 该 操 作, 我 们 在 mydb 数 据 库 下 再 创 建 一 个 表 示 订 单 的 数 据 表, 表 名 为 order, 其 中 有 两 个 字 段, 分 别 是 id 和 price 创 建 该 表 完 成 后, 就 可 以 进 行 创 建 外 键 的 操 作 了 选 中 user 数 据 表 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Foreign Key 命 令, 将 弹 出 创 建 外 键 操 作 的 界 面, 如 图 4-23 所 示 图 4-23 创 建 外 键 其 中 Foreign key name 选 项 表 示 创 建 外 键 的 列 名, 该 列 名 是 不 能 和 已 有 列 名 重 复 的, 这 里 填 写 orderid Referenced table name 选 项 表 示 外 键 引 入 的 表 名, 这 里 选 择 order Referenced key name 选 项 表 示 外 键 引 入 的 键 名, 通 常 选 择 PRIMARY, 表 示 主 键 选 择 主 键 后, 在 下 面 会 自 动 将 主 键 列 名 显 示 出 来, 在 其 左 面 填 写 id 说 明 : 只 所 以 这 里 有 多 行, 是 因 为 外 键 可 以 是 组 合 外 键, 由 多 个 列 组 成 读 者 可 以 自 己 查 看 数 据 库 相 关 的 资 料 进 行 学 习 在 Advanced Properties 选 项 表 示 对 外 键 的 高 级 设 置, On Delete 和 On update 表 示 进 行 删 除 和 更 新 操 作 时, 另 一 个 表 的 操 作, 其 中 有 四 个 选 项 No action 表 示 不 执 行 任 何 动 作, Cascade 表 示 级 联 操 作, Set null 表 示 将 字 段 设 置 为 null, Restrict 表 示 对 该 操 作 进 行 限 制 这 里 就 选 择 默 认 的 No action 选 项, 单 击 Finish 按 钮 将 完 成 创 建 外 键 的 操 作 在 控 制 台 区 的 Table/Object Info 选 项 卡 下 的 Foreign Keys 选 项 中, 将 可 以 看 到 创 建 的 外 键, 如 图 4-24 所 示

图 4-24 显 示 外 键 可 以 看 到 外 键 已 经 创 建 成 功 选 中 创 建 的 外 键, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 有 四 个 命 令 其 中 Drop Foreign Key 命 令 表 示 删 除 外 键, New Foreign Key 命 令 表 示 创 建 外 键, 选 择 该 命 令 后 同 样 会 弹 出 创 建 外 键 界 面 Generate DDL 命 令 表 示 生 成 执 行 该 结 果 的 SQL 语 句, 例 如 我 们 选 择 该 命 令, 则 在 SQL 语 句 编 辑 区 中 将 显 示 : alter table `mydb`.`user` add index `orderid`(`id`), add constraint `orderid` foreign key (`id`) references `mydb`.`order`(`id`) Copy to Clipboard 命 令 表 示 将 外 键 信 息 复 制 到 剪 切 板 中 说 明 : 有 些 读 者 可 能 会 认 为 使 用 界 面 化 创 建 外 键, 还 没 有 直 接 写 SQL 语 句 方 便 但 是 对 于 初 学 者 和 开 发 中 更 关 注 Java 程 序 开 发 的 人 来 学, 这 种 界 面 化 的 操 作 是 非 常 方 便 的, 能 够 使 他 们 从 SQL 语 句 中 脱 离 出 来 4.3.8 创 建 和 删 除 索 引 在 数 据 库 中, 使 用 索 引 可 以 使 查 询 操 作 不 用 对 整 个 表 进 行 扫 描, 就 可 以 在 其 中 找 到 所 需 的 数 据 对 于 具 有 庞 大 数 据 的 数 据 库 而 言, 索 引 时 必 不 可 少 的 同 样 这 里 我 们 对 索 引 不 进 行 过 多 的 讲 解, 而 是 更 关 心 如 何 使 用 MyEclipse 进 行 索 引 的 创 建 和 删 除 选 中 要 创 建 索 引 的 数 据 表, 例 如 这 里 仍 然 对 user 数 据 表 进 行 操 作 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New Index 命 令, 将 弹 出 创 建 索 引 操 作 界 面, 如 图 4-25 所 示

19 图 4-25 创 建 索 引 其 中 Index name 选 项 表 示 创 建 的 索 引 名 称, 这 里 填 写 user_index Unique 选 项 表 示 创 建 的 索 引 是 否 唯 一 的 接 下 来 就 是 添 加 索 引 列, 单 击 Add 按 钮, 则 在 上 面 将 列 显 示 出 来 其 中 Index columns 表 示 索 引 列 名, 这 里 选 择 name Order 表 示 索 引 顺 序, 其 中 有 两 个 选 项, Ascending 表 示 升 序, Descending 表 示 降 序 最 后 单 击 Finish 按 钮, 则 索 引 创 建 完 成 在 控 制 台 区 的 Table/Object Info 选 项 卡 下 的 Foreign Keys 选 项 中, 将 可 以 看 到 创 建 的 索 引, 如 图 4-26 所 示 图 4-26 显 示 索 引 和 外 键 一 样, 选 中 创 建 的 user_index 索 引, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 有 四 个 命 令 Drop Index 命 令 表 示 删 除 索 引, New Index 表 示 创 建 新 索 引 Generate DDL 表 示 生 成 创 建 索 引 的 SQL 语 句, 则 出 现 在 SQL 语 句 编 辑 区 中 的 内 容 为 : create index `user_index` on `mydb`.`user`(`name`)

Copy to Clipboard 命 令 表 示 将 索 引 信 息 复 制 到 剪 切 板 中 4.3.9 查 询 数 据 表 数 据 查 询 也 是 数 据 库 操 作 中 非 常 重 要 的 一 种, 在 MyEclipse 中 也 集 成 了 该 功 能 在 前 面 的 操 作 中, 可 以 看 到 可 以 查 看 到 数 据 表 中 的 所 有 数 据 但 是 如 果 要 查 询 某 列 数 据, 或 者 按 照 条 件 进 行 查 询, 就 要 借 助 SQL 语 句 来 完 成 选 中 要 进 行 查 询 操 作 的 数 据 表 节 点, 这 里 仍 然 以 user 数 据 表 举 例 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Generate Select Statement 命 令, 将 会 在 SQL 语 句 编 辑 区 中 出 现 查 询 数 据 库 的 语 句, 内 容 为 : select from `id`, `name` `mydb`.`user` 默 认 给 出 的 SQL 语 句 是 进 行 全 部 查 询 的 如 果 想 进 行 部 分 查 询, 可 以 更 改 查 询 的 列, 例 如 将 SQL 语 句 改 为 : select from `name` `mydb`.`user` 则 只 讲 用 户 表 的 所 有 用 户 名 查 询 出 来 在 查 询 SQL 语 句 中 也 可 以 加 入 条 件, 例 如 查 询 姓 名 为 Tom 的 用 户, 则 它 的 SQL 语 句 为 : select from `id`, `name` `mydb`.`user` where name='tom' 说 明 : 在 实 际 开 发 中, 通 常 将 通 过 本 小 节 操 作 得 到 的 SQL 语 句 放 到 程 序 中 所 以 在 生 成 以 后, 一 定 要 运 行 测 试 SQL 语 句 的 正 确 性 4.3.10 生 成 创 建 数 据 表 的 SQL 语 句 在 MyEclipse 中, 可 以 通 过 SQL 语 句 完 成 数 据 库 操 作, 也 可 以 通 过 界 面 化 完 成 后 生 产 完 成 该 操 作 的 SQL 语 句 在 前 面 学 习 创 建 外 键 和 索 引 时, 已 经 见 到 这 种 反 向 操 作 在 前 面 学 习 创 建 数 据 表 时, 是 通 过 界 面 化 的 方 式 创 建 的, 在 本 小 节 中 看 一 下 要 生 成 同 样 的 数 据 表 的 SQL 语 句 选 中 user 数 据 表 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Generate DDL 命 令, 将 会 将 SQL 语 句 显 示 在 编 辑 区 中 其 SQL 语 句 的 内 容 为 : create table `mydb`.`user`( `id` INT not null auto_increment, `name` VARCHAR(20),

21 primary key (`id`) ); 从 生 成 的 SQL 语 句 中 也 可 以 看 到,user 数 据 表 中 有 两 个 字 段, 其 中 id 字 段 是 主 键, 并 且 它 是 不 能 为 空 依 次 递 增 的 4.4 使 用 JDBC 开 发 网 络 商 城 的 数 据 访 问 层 在 前 面 的 学 习 中 已 经 对 基 本 的 数 据 库 操 作 进 行 了 讲 解, 在 本 节 中 我 们 通 过 一 个 实 际 的 项 目 来 学 习 如 何 使 用 MyEclipse 进 行 快 速 开 发, 在 这 里 主 要 来 开 发 网 络 商 城 的 数 据 访 问 层 4.4.1 创 建 项 目 对 应 的 数 据 库 和 数 据 表 在 实 际 开 发 中, 通 常 一 个 项 目 对 应 一 个 数 据 库, 这 里 就 创 建 一 个 新 的 数 据 库 在 MyEclipse 数 据 库 视 图 中, 打 开 连 接 MySQL 数 据 库 的 连 接, 在 连 接 节 点 上, 单 击 鼠 标 右 键, 选 择 Create Database 命 令, 在 弹 出 的 创 建 数 据 库 界 面 中, 输 入 如 下 信 息, 如 图 4-27 所 示 图 4-27 创 建 网 络 商 城 数 据 库 单 击 Finish 按 钮 将 完 成 数 据 库 的 创 建 在 一 个 项 目 中 通 常 由 多 张 数 据 表, 它 们 都 放 在 一 个 数 据 库 中 例 如 网 络 商 城 中 最 少 应 该 具 有 用 户 表 和 商 品 表, 这 里 仅 以 其 中 的 商 品 表 举 例 讲 解 选 中 新 创 建 的 shop 数 据 库 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 new Table 命 令, 将 弹 出 创 建 数 据 表 界 面, 输 入 必 要 信 息 后, 如 图 4-28 所 示

图 4-28 创 建 商 品 数 据 表 在 商 品 数 据 表 中, 定 义 了 商 品 id 商 品 名 称 商 品 价 格 商 品 折 扣 价 等 四 个 字 段, 这 些 都 可 以 根 据 实 际 需 求 进 行 增 加, 例 如 所 属 种 类 等 信 息 单 击 Finish 按 钮, 完 成 商 品 数 据 表 的 创 建 4.4.2 创 建 Java 项 目 并 导 入 驱 动 包 数 据 库 层 的 相 关 数 据 表 创 建 完 成 后, 在 MyEclipse 中, 将 视 图 切 换 为 Java 程 序 开 发 视 图 因 为 我 们 是 开 发 的 项 目 中 的 数 据 访 问 层, 所 以 这 里 创 建 Java 项 目 就 可 以 在 MyEclipse 菜 单 中, 选 择 File New Java Project 命 令, 将 弹 出 创 建 Java 项 目 的 界 面 为 了 让 读 者 更 容 易 在 光 盘 中 找 到 本 项 目, 这 里 将 项 目 名 称 定 义 为 ch4, 在 实 际 开 发 中, 该 名 称 并 不 规 范 的 其 他 设 置 如 图 4-29 所 示

23 MySQL驱动包. 图 4-29 创建网络商城项目 单击 Finish 按钮将完成本项目的创建 因为本项目时要连接数据库的 所以接 下来就是将 MySQL 驱动包导入到项目中 复制 MySQL 驱动包 选择 ch4 项目根目 录 然后执行粘贴操作 从而将 JAR 复制到项目中 选中项目中的 JAR 包 单击鼠标右键 在弹出的菜单中 选择 Build Path Add to Build Path 命令 从而将该 JAR 包导入到 Build Path 中 从而完成驱动包的导入 4.4.3 创建数据库封装类 在进行 JDBC 开发中 有很多重复执行的操作 例如加载驱动 建立数据库连接和 关闭数据库资源等 在实际开发中 通常将这些操作封装到一个类中 每一个操作对应 一个独立方法 当需要使用该操作时 调用相应的方法来完成 在 MyEclipse 中并没有提供创建数据库封装类的快速操作 但是值得庆幸的是该类 重用性非常强 在不同项目中使用该封装类时 几乎不用改动 或者改动非常少的代码 在实际开发中 是不会将所有的类放在同一个包中的 而是按照类的功能不同 将 它们放在不同包中 例如数据库封装类在项目中起到工具的作用 所以通常把它放在 util 包中 在包名中通常还会加入域名信息 例如 com.sanqing.util 包 在部署时 该项 目的域名通常就是 www.sanqing.com 创建包和类是非常简单的 而且在前面的学习中已经多次提到 这里就不再给出它 们的创建方法 接下来我们就来看一下数据库封装类的代码

01 package com.sanqing.util; 02 import java.sql.connection; 03 import java.sql.drivermanager; 04 import java.sql.preparedstatement; 05 import java.sql.resultset; 06 import java.sql.sqlexception; 07 public class DBConnection { 08 private static final String DBDRIVER = "com.mysql.jdbc.driver" ; // 驱 动 串 09 private static final String DBURL = "jdbc:mysql://localhost:3306/shop";// 连 接 URL 10 private static final String DBUSER = "root" ; // 用 户 名 11 private static final String DBPASSWORD = "admin"; // 数 据 库 密 码 12 public static Connection getconnection(){ 13 Connection conn = null; // 声 明 一 个 连 接 对 象 14 try { 15 Class.forName(DBDRIVER); // 注 册 驱 动 16 conn = DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD); 17 } catch (ClassNotFoundException e) { 18 e.printstacktrace(); 19 } catch (SQLException e) { 20 e.printstacktrace(); 21 } 22 return conn; 23 } 24 public static void close(connection conn) { 25 if(conn!= null) { // 如 果 conn 连 接 对 象 不 为 空 26 try { 27 conn.close(); // 关 闭 conn 连 接 对 象 对 象 28 } catch (SQLException e) { 29 e.printstacktrace(); 30 } 31 } 32 } 33 public static void close(preparedstatement pstmt) { 34 if(pstmt!= null) { // 如 果 pstmt 预 处 理 对 象 不 为 空 35 try { 36 pstmt.close(); // 关 闭 pstmt 预 处 理 对 象 37 } catch (SQLException e) { 38 e.printstacktrace(); 39 } 40 } 41 } 42 public static void close(resultset rs) { 43 if(rs!= null) { // 如 果 rs 结 果 集 对 象 不 为 null 44 try { 45 rs.close(); // 关 闭 rs 结 果 集 对 象

25 46 } catch (SQLException e) { 47 e.printstacktrace(); 48 } 49 } 50 } 51 } 其 中 不 同 开 发 环 境 中 需 要 改 动 的 只 有 第 9 行 到 第 11 行, 其 中 第 9 行 是 连 接 数 据 库 的 URL, 根 据 数 据 库 不 同 需 要 进 行 改 动 第 10 行 和 第 11 行 是 连 接 数 据 库 用 到 的 用 户 名 和 密 码, 根 据 本 地 数 据 库 的 设 置 进 行 对 应 修 改 4.4.4 创 建 商 品 实 体 类 通 常 数 据 库 中 的 一 张 数 据 表 就 对 应 着 一 个 实 体 类 例 如 现 在 数 据 库 中 有 商 品 数 据 表, 我 们 就 应 该 创 建 一 个 商 品 实 体 类, 通 过 这 个 类 来 完 成 对 商 品 的 增 删 改 查 等 操 作 在 项 目 中, 通 常 将 实 体 类 放 在 bean 包 下, 如 果 实 体 类 比 较 多, 又 可 以 根 据 实 体 类 的 用 途 分 为 vo po 等 包 实 体 类 中 的 属 性 通 常 是 和 数 据 表 中 的 字 段 相 对 应 的, 则 商 品 实 体 类 的 程 序 代 码 为 : 01 package com.sanqing.bean; 02 public class Commodity { 03 private int id; // 商 品 ID 04 private String name; // 商 品 名 称 05 private double price; // 商 品 价 格 06 private double agio; // 商 品 折 扣 07 } 为 了 获 取 和 设 置 属 性 值, 还 要 为 商 品 实 体 类 中 的 属 性 定 义 Getter 和 Setter 方 法 在 商 品 类 体 中, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中, 选 择 Source Generate Getters and Setters 命 令, 就 会 弹 出 生 成 Getter 和 Setter 方 法 的 界 面, 选 中 所 有 属 性, 如 图 4-30 所 示

图 4-30 创 建 实 体 类 单 击 OK 按 钮 将 完 成 实 体 类 的 创 建, 商 品 实 体 类 的 代 码 变 为 : 01 package com.sanqing.bean; 02 public class Commodity { 03 private int id; // 商 品 ID 04 private String name; // 商 品 名 称 05 private double price; // 商 品 价 格 06 private double agio; // 商 品 折 扣 07 public int getid() { 08 return id; 09 } 10 public void setid(int id) { 11 this.id = id; 12 } 13 public String getname() { 14 return name; 15 } 16 public void setname(string name) { 17 this.name = name; 18 } 19 public double getprice() { 20 return price; 21 } 22 public void setprice(double price) {

27 23 this.price = price; 24 } 25 public double getagio() { 26 return agio; 27 } 28 public void setagio(double agio) { 29 this.agio = agio; 30 31 } } 可以看到 通过 MyEclipse 的命令自动生成很多行代码 并且生成一个标准的实体 类程序 4.4.5 实体类名.DAO.Impl的实体访问类. 创建数据访问层实现类 数据访问层实现类是最直接操作数据库的程序 在其中定义了操作数据库的方法 包括增加 删除 更新和查询操作方法 其中查询通常由两种方法 一种是查询全部 另一种是根据 id 主键查询 数据访问层实现类的命名有通用规范 例如本节创建的 CommodityDAOImpl 类 其中 Commodity 是和实体类类名对应 表示对该商品进行数据库操作 DAO 是 数据访问的缩写 Impl 是实现的缩写 接下来就来看一下 CommodityDAOImpl 类的程序代码 01 package com.sanqing.dao; 02 //省略导入接口和类的代码 03 public class CommodityDAOImpl { 04 //实现添加商品的方法 05 public void addcommodity(commodity commodity) { 06 Connection conn = DBConnection.getConnection(); 07 String addsql = "insert into 08 //获得连接对象 commodity(name,price,agio) values(?,?,?)"; 09 PreparedStatement pstmt = null; 10 try { //声明预处理对象 11 pstmt = conn.preparestatement(addsql); //获得预处理对象并赋值 12 pstmt.setstring(1, commodity.getname()); //设置第一个参数 13 pstmt.setdouble(2, commodity.getprice()); //设置第二个参数 14 pstmt.setdouble(3, commodity.getagio()); //设置第三个参数 15 pstmt.executeupdate(); //执行更新 16 } catch (SQLException e) { 17 e.printstacktrace(); 18 } finally{ 19 20 21 数据库操作中, 需要 关闭预处理对象. DBConnection.close(pstmt); //关闭预处理对象 DBConnection.close(conn); //关闭连接对象 } 22 } 23 //省略其他操作方法

24 } 该 程 序 在 开 发 中, 是 需 要 手 动 完 成 的, 根 据 实 际 需 求 来 定 义 不 同 的 方 法 在 本 小 节 数 据 访 问 层 实 现 类 中 定 义 了 增 加 商 品 删 除 商 品 更 新 商 品 查 询 所 有 商 品 和 按 照 商 品 ID 查 询 商 品 5 种 方 法, 这 里 仅 给 出 增 加 商 品 方 法, 其 他 方 法 代 码 见 光 盘 注 意 : 定 义 数 据 库 操 作 方 法 时, 通 过 将 参 数 定 为 对 应 的 实 体 类 类 型, 如 果 这 里 定 义 了 是 具 体 信 息 参 数, 例 如 商 品 名 称 商 品 价 格 等, 就 可 以 使 用 引 入 参 数 对 象 的 重 构 操 作, 进 行 替 换 4.4.6 创 建 数 据 访 问 层 接 口 数 据 访 问 层 接 口 的 命 名 也 是 遵 循 规 范 的, 通 常 由 实 体 类 名 加 DAO 来 命 名, 例 如 CommodityDAO 数 据 访 问 层 接 口 可 以 和 实 现 类 一 起 放 在 dao 包 中, 也 可 以 将 实 现 类 单 独 放 在 dao 包 的 impl 子 包 下 数 据 访 问 层 接 口 是 可 以 通 过 MyEclipse 的 集 成 功 能 自 动 生 成 的 在 包 资 源 管 理 器 中, 选 中 CommodityDAOImpl 数 据 访 问 层 实 现 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Extract Interface 命 令, 将 弹 出 抽 取 接 口 界 面, 将 其 中 的 方 法 全 部 选 中, 如 图 4-31 所 示 图 4-31 抽 取 数 据 访 问 层 接 口 单 击 OK 按 钮 将 完 成 数 据 访 问 层 接 口 的 抽 取 在 dao 包 下 将 创 建 名 称 为 CommodityDAO 的 数 据 访 问 层 接 口 程 序, 其 代 码 为 : 01 package com.sanqing.dao; 02 import java.util.list; 03 import com.sanqing.bean.commodity; 04 public interface CommodityDAO { 05 public abstract void addcommodity(commodity commodity); 06 public abstract void deletecommodity(int commodityid);

29 07 public abstract List<Commodity> findallcommodity(); 08 public abstract void updatecommodity(commodity commodity); 09 public abstract Commodity findcommoditybyid(int commodityid); 10 } 并且在数据访问层的实现类中实现该接口 4.4.7 创建数据访问层工厂类 工厂类: 什么是工厂类, 其作用是什么?. 在业务访问层中通常借助工厂类来创建数据访问层实现类对象 在本小节中就来看 一下如何快速创建数据访问层的工厂类 在操作前 要完成准备的工作 首先在数据访 问层实现类中定义一个无参构造函数 然后定义工厂类 工厂类通常不和接口和实现类 放在同一包下 而是自定义一个 factory 包 工厂类的代码为 01 package com.sanqing.factory; 02 public class CommodityDAOFactory { 03 04 工厂类: 创建实现类 } 接下来就是定义工厂类中的创建实现类对象的方法 在包资源管理器中 选中 UserDAOImpl 的无参构造函数节点 单击鼠标右键 在弹出的右键菜单中 选择 Refactor Introduce Factory 命令 将弹出引入工厂操作界面 填入如下信息后 如图 4-32 所示 图 4-32 创建工厂方法 单击 OK 按钮 将完成工厂类的创建 则工厂类的代码将变为 01 package com.sanqing.factory; 02 import com.sanqing.dao.commoditydaoimpl; 03 public class CommodityDAOFactory { 04 public static CommodityDAOImpl createcommoditydaoimpl() { 05 return new CommodityDAOImpl(); 06 07 } } 通常该操作生成的工厂方法并不是规范的 其中方法的返回值为实现类类型 这就 失去了工厂类的作用 工厂类的作用就是让业务逻辑层中并不关心数据访问层实现类

只需要关心数据访问层接口 如果想变为规范的方法 还需要经过 尽可能使用超类型 的重构操作 在包资源 管理器中 选中 CommodityDAOImpl 类节点 单击鼠标右键 在弹出的菜单中选择 Refactor Use Supertype Where Possible 命令 将弹出选择超类型的界面 选择 CommodityDAO 接口节点 如图 4-33 所示 图 4-33 选择接口类型 单击 OK 按钮 将完成类型的转换 这是数据访问层工厂类的代码变为 01 package com.sanqing.factory; 02 import com.sanqing.dao.commoditydao; 03 import com.sanqing.dao.commoditydaoimpl; 04 public class CommodityDAOFactory { 05 public static CommodityDAO createcommoditydaoimpl() { 06 return new CommodityDAOImpl(); 07 08 } 很显然工厂类的本质在于: 接口, 实现类. } 这就变为一个规范的工厂类 4.4.8 开发数据访问层测试程序 到目前为止 网络商城的数据访问层应该算开发完成了 但是在实际开发中 通常 开发一部分程序后 要对它进行测试 以验证该部分程序的正确性 测试程序仅用于开发阶段 当进行项目部署时 通常就会将测试程序删除 本节讲 解的网络商城数据访问层的测试程序代码如下 01 package com.sanqing.test; 02 import com.sanqing.bean.commodity; 03 import com.sanqing.dao.commoditydao; 04 import com.sanqing.factory.commoditydaofactory; 05 public class Test { 06 07 08 public static void main(string[] args) { CommodityDAO commoditydaoimpl = CommodityDAOFactory.createCommodityDAOImpl();

31 09 Commodity commodity = new Commodity(); 10 commodity.setid(2); 11 commodity.setname("food"); 12 commodity.setprice(58.50); 13 commodity.setagio(36.00); 14 commoditydaoimpl.addcommodity(commodity); 15 } 16 } 该 程 序 是 需 要 手 动 编 写 的, 当 使 用 到 其 他 包 中 的 接 口 或 者 类 时, 可 以 使 用 导 入 接 口 和 类 命 令 将 它 们 导 入 在 代 码 的 第 7 行 中 调 用 工 厂 类 中 的 创 建 实 现 类 对 象 方 法, 并 使 用 接 口 引 用 指 向 它 在 第 9 行 中 创 建 了 商 品 对 象, 并 依 次 将 id 商 品 名 称 商 品 价 格 商 品 折 扣 价 等 信 息 设 置 到 商 品 对 象 中 在 第 14 行 中 调 用 实 现 类 中 的 addcommodity 方 法, 从 而 完 成 商 品 的 添 加 在 MyEclipse 中 切 换 到 数 据 库 视 图 中, 在 控 制 台 区 的 Table/Object Info 选 项 卡 下 的 Preview 选 项, 将 看 到 执 行 程 序 后 插 入 的 商 品 记 录, 如 图 4-34 所 示 图 4-34 测 试 结 果 从 该 结 果 可 以 看 到, 数 据 访 问 层 开 发 正 确, 可 以 放 到 项 目 中 做 为 项 目 的 一 部 分

北风网讲师原创作品----仅供 www.ibeifeng.com 学员内部交流使用 第5章 管理服务器并进行Web开发 在上一章中已经学习了如何使用 MyEclipse 对数据库进行管理 在本章中将主要学 习如何对服务器进行管理 这里所说的服务器是指用于 Java Web 项目部署的应用服务 器 除了学习服务器的管理外 还会学习最简单的 Web 开发 包括 JSP Servlet 等 Web 程序的开发 5.1 认识 MyEclipse 中的服务器 在配置外部数据库时 我们已经看到在 MyEclipse 中能够管理很多种数据库 同样 在 MyEclipse 中可以管理很多种应用服务器 例如常用的 Tomcat Jboss WebLogic 和 WebSphere 等 注意 在 MyEclipse 中自带了一个 Tomcat 服务器 通过该服务器可以发布常见的 Web 项目 例如 JSP SSH 的项目 但是不能够对 EJB 项目进行发布的 在 MyEclipse 的界面的控制台区中 有一个 Servers 选项卡 在这里可以查看目 前 MyEclipse 中能够使用哪些服务器 在控制台区中 默认是由该选项卡的 如果不存 在 也可以在 MyEclipse 的菜单中 选择 Window Show View Servers 命令 可以显示 如果在 Show View 选项下没有 Servers 命令 可以在 Other 命令的 弹出界面中选择 Servers 界面如图 5-1 所示 图 5-1 Servers 界面 其中 MyEclipse Derby 是 MyEclipse 中内置的数据库 而 MyEclipse Tomcat 是 MyEclipse 中内置的应用服务器 在它们的上面有几个操作按钮 其中使用比较多的 就是其中的第 3 个按钮 表示以运行模式启动服务器 对服务器进行配置. 对应用服务器进行操作 也可以单击鼠标右键 在弹出的菜单中 Configure 命 令表示配置服务器的选择器 Debug Server 命令表示以调试模式启动服务器 Run Server 命令表示以运行模式启动服务器 Restart 命令表示重新启动服务器 Stop

命令表示停止服务器 Add Deployment 命令表示向选中的服务器中发布项目 在后 面的学习中 使用到这些命令后 还会进行详细的讲解 将一个或多个项目发布 到该服务器 5.2 管理外部 Tomcat 服务器 MyEclipse 中的内置服务器是不能完成所有 Java Web 项目的操作的 所以我们有必 要学习一下如何在 MyEclipse 中对外部的应用服务器进行管理 这里通过外部的 Tomcat 服务器讲解该操作 5.2.1 配置 Tomcat 路径 在 MyEclipse 的菜单中 选择 Window Preferences 命令 将打开首选项设置 界面 在常用操作一章已经多次使用到该界面 在首选项设置界面的导航栏中 选择 MyEclipse Enterprise Workbench Servers Tomcat Tomcat 6.x 命令 则当 前首选项界面如图 5-2 所示 图 5-2 配置路径 其中 Tomcat home directory 表示 Tomcat 的主目录 Tomcat base directory 表 示 Tomcat 的基础目录 Tomcat temp directory 表示 Tomcat 的临时参数目录 笔者的 Tomcat 服 务 器 安 装 在 D 盘 下 所 以 Tomcat home directory 选 项 下 选 择 D:\apache-tomcat-6.0.10 读者可以根据本地安装位置进行填写 Optional program arguments 选项表示 Tomcat 的相关参数 通常这一项是不需要填写的 都是采用默认 值 说明 前三个选择 Tomcat 目录的选项是级联关系的 当选择其中一个后 其他的 会自动填写 例如填写 Tomcat 的主目录为 D:\apache-tomcat-6.0.10 后 将自动填写 临时参数目录为 D:\apache-tomcat-6.0.10\temp 只需要设置好Tomcat的 主目录即可.

3 5.2.2 启动 仅配置外部 Tomcat 的路径 单击 OK 按钮后 该服务器并不会出现在服务器界 面中 这是因为还没有启动该配置 在配置路径的上面有两个单选按钮选项 其中 Enable 选项表示启动外部 Tomcat 的配置 Disable 选项表示不启动外部 Tomcat 的配置 默认是不启动的状态 所以 要选择 Enable 选项 这是再单击 OK 按钮 就完成对外部 Tomcat 服务器的配置 技巧 在实际开发中 不同的项目可能需要的服务器不同 这时候就需要将不需 要的服务器停止 从而不影响 MyEclipse 的速度 这种操作主要就是通过 Enable 选项和 Disable 选项完成的 这样的好处就是下次使用时 不需要重新配置服务器 5.2.3 添加 JDK 支持 在实际开发中 要将不需要的服务器停止 对于 Tomcat 6.x 版本的应用服务器来说 经过上面两步的操作就可以在 MyEclipse 中使用了 因为它将使用其中默认的 JRE 但是对于一些低版本的服务器 或者一些特 殊的服务器 还需要为该服务器添加 JDK 支持 例如 Tomcat 4 版本就需要 JDK 1.4 的 支持 这时候就要为它指定 JDK 在首选项设置界面中 单击 Tomcat 6.x 节点前的加号 选择 JDK 命令 将 出现添加 JDK 支持的界面 如图 5-3 所示 指定Tomcat服务器使用的jdk 图 5-3 添加 JDK 支持 在其中 Tomcat JDK name 选项中可以选择需要使用的 JDK 默认是 MyEclipse 6.5 默认安装下 是没有其他 JDK 版本的 需要单击 Add 按钮完成其他 JDK 的添加

这 时 候 将 弹 出 添 加 JDK 的 界 面, 如 图 5-4 所 示 图 5-4 添 加 新 的 JDK 该 界 面 是 和 添 加 外 部 JRE 非 常 类 似 的 单 击 其 中 的 Browse 按 钮, 选 择 JDK 安 装 的 根 目 录, 如 果 是 默 认 安 装, 则 路 径 应 该 为 C:\Program Files\Java\jdk1.6.0_10 选 择 JDK 路 径 后, 则 其 他 选 项 将 自 动 填 写 单 击 OK 按 钮, 将 完 成 外 部 JDK 的 配 置, 从 而 在 添 加 JDK 支 持 界 面 中 将 多 出 一 个 JDK 选 项 注 意 : 在 添 加 新 的 JDK 界 面 中, 设 置 的 路 径 一 定 要 选 择 JDK 的 根 目 录, 而 不 是 JRE 的 根 目 录 这 和 添 加 外 部 JRE 是 不 一 样 的 回 答 首 选 项 设 置 界 面 中, 单 击 OK 按 钮, 将 完 成 外 部 Tomcat 应 用 服 务 器 的 添 加, 这 时 候 再 查 看 Servers 界 面, 如 图 5-5 所 示 图 5-5 添 加 外 部 服 务 器 的 结 果 可 以 看 到 在 其 中 多 出 了 一 个 服 务 器, 正 是 前 面 添 加 操 作 中 添 加 的 外 部 Tomcat 应 用 服 务 器 在 后 面 的 学 习 中 都 是 基 于 该 服 务 器 操 作 的

5 5.3 开发 Web 项目中的 HelloWorld 因为服务器的大部分操作都是对 Java Web 项目进行操作 所以有必要先来学习一 下在 MyEclipse 中如何进行 Java Web 项目的开发 和开发 Java 项目一样 在 MyEclipse 中也集成了大量对 Java Web 项目支持的功能 5.3.1 创建 Web 项目 我们首先来学习一下该如何创建 Web 项目 在 MyEclipse 的菜单中 选择 File New Web Project 命令 将弹出创建 Web 项目界面 如图 5-6 所示 图 5-6 创建 Web 项目 其中 Project Name 选项表示项目的名称 这里填写 FirstWeb Location 选项表示项目文件存放的位置 默认会选中 Use default location 表示保存在当前工 作空间中 也可以取消选中状态 然后在 Directory 中选择保存的目录位置 Source folder 选项表示项目中 Java 源代码文件的保存目录 其中主要包括 Java 包和.java 的文件 通常采用默认的 src 目录 Web root folder 选项表示 Web 相关程序的存放位置 这些文件包括 JSP 程序 HTML 程序等 以及固定的 WEB-INF 目录 通常使用默认的 WebRoot 目录 Context root URL 选项表示发布项目后 使用的访问路径 默认是项目名称 这里会随着项目名称的改变而改变 J2EE Specification Level 选项表示 J2EE 规范版本的选择 这里的版本取决于发 布应用服务器的类型和版本 Add JSTL libraries to WEB-INF/lib folder 选项表示是否 要将 JSTL 相关包加入到项目中 如果选择了 Java EE 5.0 选项 则该选项是不用选 择的 会自动完成该操作 J2EE Specification Level取决于Java Web应用的 Tomcat服务器的类型与版本, 即Tomcat服务器对jdk 的要求.

说明 Tomcat 6.0 等目录主流应用服务器都执行目前最高版本 Java EE 5.0 所 以通常选择该版本 如果选择低版本 后面的学习中会多添加很多操作 所以在后面 的学习中不特殊说明 都是创建的 Java EE 5.0 版本 Java Web 程序 最后单击 Finish 按钮 将完成第一个 Java Web 项目的创建 并且将创建后的项 目显示在包资源管理中 如图 5-7 所示 图 5-7 5.3.2 创建 Web 项目后 浏览生成的项目 经常上一小节的操作 将在包资源管理器中创建一个名称为 FirstWeb 的 Java Web 项目 单击每一层前面的加号 将会将其中的具体文件显示出来 如图 5-8 所示 JSTL, 称为JSP标签库.

7 图 5-8 创 建 项 目 后 目 录 说 明 : 这 是 将 大 部 分 选 项 以 默 认 的 形 式 创 建 的, 所 以 会 有 src 和 WebRoot 目 录, 如 果 创 建 时 进 行 自 定 义 设 置, 这 里 也 会 发 生 改 变, 如 果 没 有 特 别 说 明, 后 面 的 项 目 也 采 用 默 认 的 命 名 其 中 src 目 录 用 于 存 放 Java 源 文 件,JavaBean 和 Servlet 等 程 序 都 会 保 存 在 该 目 录 下 创 建 Java Web 项 目 后, 会 自 动 将 Web 所 需 的 JAR 包 导 入 到 项 目 中, 例 如 其 中 的 jstl-1.2.jar 文 件 就 是 开 发 JSTL 标 签 用 到 的 JAR 包 WebRoot 目 录 是 用 于 放 置 Web 程 序 的 目 录,JSP HTML 等 程 序 都 可 以 直 接 放 在 它 的 根 目 录 下, 在 发 布 和 部 署 Java Web 项 目 时, 就 是 发 布 的 该 目 录 注 意 : 发 布 Java Web 项 目 时, src 目 录 是 不 会 发 布 的, 而 是 仅 将 编 译 后 的.class 文 件 发 布 编 译 后 的.class 文 件 放 在 WebRoot/WEB-INF/classes 目 录 下 讲 解 发 布 时, 还 会 更 详 细 的 看 到 这 一 点 WEB-INF 目 录 是 Java Web 项 目 的 固 定 目 录, 名 称 和 位 置 都 是 固 定 的 在 该 目 录 下, lib 目 录 用 于 保 存 项 目 所 用 到 的 JAR 包, 项 目 中 的 JAR 包 在 发 布 时 都 会 放 在 该 目 录 下 classes 目 录 是 不 会 在 MyEclipse 中 显 示 出 来 的, 只 有 在 发 布 后 才 会 看 到 该 目 录, 在 其 中 编 译 后 的.class 文 件 web.xml 文 件 是 Java Web 项 目 的 描 述 符, 在 其 中 配 置 项 目 的 相 关 内 容, 使 用 最 多 的 就 是 对 Servlet 等 程 序 进 行 必 要 配 置 index.jsp 文 件 是 一 个 JSP 程 序, 它 通 常 也 是 Java Web 项 目 部 署 后 的 访 问 首 页 JSP 等 页 面 显 示 程 序 可 以 直 接 放 在 WebRoot 目 录 下, 也 可 以 在 该 目 录 下 创 建 子 目 录,

将 JSP 程序放在子目录中 5.4 发布项目 在Java EE规范中, java web项目的发布是"打 包发布", 即采用WAR格式文件 在前面对 Tomcat 服务器和 Java Web 项目有所了解后 在本节中就来看一下如何将 Java Web 项目发布到 Tomcat 服务器中 在本节中 主要讲解发布方式 发布操作和如 何运行发布后的项目等内容 5.4.1 发布方式 在MyEclipse进行Java Web项目发布 (1)散包发布(2)打包发布. 在 MyEclipse 中 支持两种发布 Java Web 项目的方式 分别是散包发布和打包发布 这两种发布方式主要是根据项目的不同阶段来选择 散包发布一般用于开发阶段 在 MyEclipse 中使用这种方式发布时 会将项目中的 目录和文件按照 Java EE 规范发布到应用服务器的发布目录下 散包发布的优点就是能 够实时同步 执行一次发布以后 如果在 MyEclipse 中对 JSP 程序进行了修改 会自动 使用修改后的文件替换服务器中的原文件 这时候的项目不用重新发布 只需要刷新页 散包Java Web项目发布的优点 面就能够看到修改后的效果 注意 并不是所有的服务器都支持散包发布的 在 Java EE 规范中规定项目要以 打包的形式进行发布 但是目前主流的服务器 例如 Tomcat Jboss 等都执行散包发 布 所以在开发阶段就可以使用这种方步方式 在本书中也主要采用这种方式 打包发布是一种最规范的发布方式 适用于所有服务器 它主要用于最后项目部署 时 使用打包方式时 会将项目中的文件打包成单个的 ZIP 文件 后缀是比较灵活的 可以使 WAR 或者 JAR 将该文件放到应用服务器的发布目录下 就完成发布操作 打 包发布的缺点也就是散包发布的优点 那就是不能够实时同步 5.4.2 指定项目发布 选择要发布的项目: 执行发布操作 发布项目可以通过多种操作完成 在本书中主要讲解两种最常用的发布操作 一种 是指向项目发布 另一种是指定服务器发布 在本小节中就先来讲解指定项目发布 在包资源管理器中 选中要发布的项目 例如选中 FirstWeb 项目 单击 MyEclipse 工具栏中的 发布按钮 将弹出指定项目发布界面 如图 5-9 所示

9 图 5-9 指 定 项 目 发 布 其 中 Project 选 项 表 示 要 发 布 的 项 目, 默 认 是 前 面 操 作 中 选 中 的 项 目, 也 可 以 在 其 中 选 择, 这 里 会 将 当 前 工 作 空 间 的 Java Web 项 目 都 列 出 来 Delployments 表 示 发 布 到 哪 一 个 应 用 服 务 器 下, 单 击 Add 按 钮, 将 弹 出 选 择 服 务 器 的 界 面, 如 图 5-10 所 示 图 5-10 选 择 服 务 器 其 中 Web Project 表 示 发 布 的 项 目, 它 是 固 定 的 Server 选 项 表 示 选 择 发 布 到 哪 一 个 应 用 服 务 器 中, 这 里 选 择 Tomcat 6.x, 也 就 是 配 置 的 外 部 Tomcat 服 务 器 Deploy type 表 示 发 布 的 方 式, Exploded Archive (development mode) 选 项 表 示 散

包发布 Packaged Archive (production mode) 选项表示打包发布 这里选择散包发布 Deploy Location 选项表示发布的具体目录 选择服务器后 该选项会自动填充 单击 Finish 按钮将完成应用服务器的选择 回到指定项目发布界面 单击 OK 按钮将完成项目的发布 注意 将多个项目部署到一个服务器中是完全没有问题的 只需要进行多次发布 操作 但是在开发阶段 笔者并不建议这样操作 多余的项目会加重服务器的负担 从而使服务器的速度变慢 5.4.3 选择服务器, 给当前服务器 指定服务器发布 添加发布的java web项目 在本小节中继续学习另一种发布操作 就是指定服务器发布 在前面配置外部 Tomcat 服务器后 将在 Servers 界面中多一种 Tomcat 6.x 的服务 选中该服务 单 击鼠标右键 在弹出的菜单中 选择 Add Deployment 命令 将弹出指定服务器发布 界面 如图 5-11 所示 图 5-11 指定服务器发布 其中 Server 选项表示发布到的服务器 采用指定服务器的操作发布 该选项是 固定的 直接显示前面操作的服务器 Project 选项表示要发布的项目 会将当前工 作空间的项目都列在其中 这里选择 FirstWeb 项目 Deploy type 选项表示发布 方式 Deploy Location 选项表示发布的目录 这和前面的讲解时一样的 单击 Finish 按钮将完成指定服务器发布操作 说明 从操作步骤来看 指定服务器发布要比指定项目发布的操作更简单 读者 可以选择自己习惯的发布操作 在后面的学习和操作中 笔者主要采用指定服务器发 布的操作

11 5.4.4 启 动 服 务 器 和 运 行 项 目 不 管 使 用 哪 种 方 式 和 操 作, 发 布 项 目 成 功 后, 就 可 以 运 行 项 目 在 运 行 项 目 之 前 要 首 先 启 动 服 务 器 在 Servers 界 面 中, 选 中 要 启 动 的 服 务 器, 因 为 我 们 的 项 目 是 发 布 到 Tomcat 6.x 服 务 器 下, 所 以 这 里 选 中 Tomcat 6.x 服 务 器 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Run Server 命 令, 将 开 始 启 动 服 务 器 这 时 候 在 控 制 台 中 将 显 示 启 动 服 务 器 的 信 息, 当 其 中 显 示 的 信 息 出 现 如 下 信 息 时, 表 示 启 动 完 成 信 息 : Server startup in 2312 ms 其 中 的 数 字 就 表 示 启 动 所 使 用 的 时 间 启 动 服 务 器 后, 打 开 任 意 一 款 浏 览 器, 这 里 就 以 最 常 用 的 IE 浏 览 器 演 示 打 开 IE 浏 览 器, 输 入 如 下 地 址 : http://localhost:8080/ 其 中 localhost 表 示 本 地 服 务 器, 这 里 也 可 以 使 用 本 地 的 IP 地 址 代 替, 8080 表 示 访 问 的 端 口 号 按 下 回 车 键, 或 者 单 击 浏 览 器 中 的 转 到 按 钮, 显 示 结 果 如 图 5-12 所 示 图 5-12 启 动 服 务 器 页 面 出 现 该 界 面 后, 表 示 在 MyEclipse 中 启 动 外 部 的 Tomcat 服 务 器 成 功 如 果 出 现 的 是 不 可 访 问 页 面, 要 查 看 在 MyEclipse 中 是 否 启 动 了 服 务 器, 或 者 检 查 Tomcat 是 否 安 装 正 确 验 证 Tomcat 服 务 器 启 动 成 功 后, 再 次 输 入 如 下 地 址 : http://localhost:8080/firstweb/ 其 中 FirstWeb 就 是 访 问 项 目 的 URL, 这 是 和 创 建 项 目 时 的 Context root URL 选 项 对 应 的 按 下 回 车 键, 或 者 单 击 浏 览 器 中 的 转 到 按 钮, 显 示 结 果 如 图 5-13 所 示

图 5-13 项 目 运 行 结 果 如 果 读 者 也 出 现 该 结 果, 表 示 项 目 发 布 成 功 因 为 项 目 的 默 认 首 页 是 index.jsp 程 序, 其 中 显 示 This is my JSP page. 信 息 就 是 index.jsp 程 序 的 功 能 这 里 就 不 多 对 该 程 序 进 行 讲 解 对 于 Servers 界 面 中 的 服 务 器 而 言, 除 了 具 有 启 动 命 令 外, 还 有 Restart 命 令 和 Stop 命 令 Restart 命 令 表 示 重 新 启 动 服 务 器, Stop 命 令 表 示 停 止 服 务 器, 它 们 在 开 发 中 也 经 常 用 使 用 到, 操 作 是 比 较 简 单 的, 这 里 就 不 再 详 细 讲 解 5.5 开 发 HTML 页 面 程 序 在 Java Web 项 目 中, 由 多 种 实 现 不 同 功 能 的 程 序 组 成, 例 如 HTML 程 序 JSP 程 序 Servlet 程 序 过 滤 器 等 在 本 节 中 就 来 学 习 一 下 如 何 使 用 MyEclipse 工 具 开 发 这 些 程 序 HTML 页 面 程 序 是 最 直 接 的 显 示 页 面 内 容 程 序, 学 习 过 Web 开 发 的 读 者 对 它 肯 定 是 不 陌 生 的 在 本 小 节 中 主 要 来 看 在 MyEclipse 中 是 如 何 开 发 HTML 页 面 程 序 的 说 明 : 实 际 项 目 的 最 后 的 页 面 效 果 HTML 程 序 通 常 是 不 用 MyEclipse 创 建 开 发 的, 因 为 MyEclipse 做 出 来 的 效 果 远 没 有 DreamWeaver 等 专 业 开 发 HTML 的 工 具 做 出 来 的 好 但 是 Java 程 序 员 一 定 要 做 出 来 一 个 基 本 效 果, 然 后 才 能 提 供 给 美 工 人 员, 让 它 们 再 加 工 所 以 Java 程 序 员 希 望 在 MyEclipse 中 也 能 开 发 HTML 页 面 程 序 5.5.1 创 建 HTML 页 面 程 序 在 MyEclipse 中, 创 建 HTML 等 Web 程 序 的 方 式 有 很 多 种 的, 可 以 通 过 菜 单 或 者 工 具 栏 完 成, 这 里 我 们 主 要 使 用 最 常 用 的 方 式 创 建 在 包 资 源 管 理 器 中, 选 中 Java Web 项 目 中 的 WebRoot 目 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令, 将 弹 出 选 择 要 创 建 程 序 界 面, 如 图 5-14 所 示

13 图 5-14 选 择 要 创 建 的 程 序 在 其 中 选 择 MyEclipse Web 节 点, 可 以 看 到 其 中 有 两 个 创 建 HTML 程 序 的 节 点, 分 别 是 HTML(Advanced Templates) 选 项 和 HTML(Basic Templates) 选 项, 它 们 分 别 对 应 着 高 级 模 板 和 基 础 模 板 5.5.2 使 用 基 础 模 板 创 建 在 选 择 创 建 程 序 界 面 中, 选 择 HTML(Basic Templates) 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 基 础 模 板 的 HTML 程 序 界 面, 如 图 5-15 所 示 图 5-15 创 建 基 础 模 板 HTML 程 序

其 中 Enter or select the parent folder 选 项 表 示 输 入 或 者 选 择 文 件 创 建 的 位 置, 这 里 我 们 就 让 它 创 建 在 WebRoot 目 录 下, 也 就 是 Web 程 序 的 根 目 录 File name 选 项 表 示 新 创 建 程 序 的 文 件 名, 这 里 填 写 HTMLOfBasic.html,HTML 程 序 的 扩 展 名 可 以 是.html, 也 可 以 是.htm 单 击 Next 按 钮 可 以 看 到 创 建 HTML 程 序 的 预 览, 单 击 Finish 按 钮 将 完 成 基 础 模 板 的 HTML 程 序 的 创 建 在 包 资 源 管 理 器 的 FirstWeb 项 目 的 WebRoot 目 录 下 将 创 建 文 件 名 为 HTMLOfBasic.html 的 HTML 程 序, 并 且 在 编 辑 区 中 会 将 该 程 序 显 示 出 来, 如 图 5-16 所 示 图 5-16 基 础 模 板 HTML 程 序 代 码 其 中 编 辑 区 的 下 半 部 分 可 以 看 到 基 础 模 板 HTML 的 程 序 代 码, 在 其 中 给 出 了 HTML 程 序 最 基 本 的 头 标 记 体 标 记 等 基 础 标 记, 并 且 使 用 <meta> 标 记 给 出 当 前 HTML 程 序 的 编 码 规 则 是 UTF-8 该 界 面 具 体 如 何 使 用 在 后 面 的 小 节 中 进 行 详 细 讲 解 5.5.3 使 用 高 级 模 板 创 建 使 用 高 级 模 板 创 建 HTML 程 序 的 创 建 操 作 有 两 种, 第 一 种 就 是 在 图 5-14 的 选 择 创 建 程 序 界 面 中, 选 择 HTML(Advanced Templates) 选 项 第 二 种 就 是 选 中 WebRoot 目 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New HTML(Advanced Templates) 命 令 使 用 这 两 种 操 作 都 将 弹 出 创 建 使 用 高 级 模 板 HTML 程 序 的 界 面, 如 图 5-17 所 示

15 5-17 创 建 高 级 模 板 HTML 程 序 其 中 File Path 表 示 新 创 建 的 HTML 程 序 所 在 目 录, 如 果 使 用 前 面 的 创 建 方 式, 该 目 录 将 会 自 动 填 写 File Name 表 示 创 建 HTML 程 序 的 文 件 名, 这 里 填 写 HTMLOfAdvanced.html Doctype 表 示 新 创 建 HTML 程 序 的 文 档 类 型, 这 里 使 用 默 认 的 选 择 就 可 以 Template to use 表 示 模 板 的 选 择, 其 中 有 两 个 选 项, 默 认 的 Default HTML tempate 选 项 表 示 使 用 默 认 HTML 模 板, HTML tempate with a form 选 项 表 示 创 建 一 个 拥 有 提 交 表 单 的 HTML 程 序 先 选 择 Default HTML tempate 选 项, 单 击 Finish 按 钮, 将 完 成 高 级 模 板 HTML 程 序 的 创 建 在 编 辑 区 中 同 样 会 出 现 上 下 两 部 分, 其 中 上 半 部 分 是 和 基 础 模 板 相 同 的 在 下 半 部 分 中 将 显 示 自 动 生 成 的 代 码, 内 容 为 : 01 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 02 <html> 03 <head> 04 <title>htmlofadvanced.html</title> 05 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 06 <meta http-equiv="description" content="this is my page"> 07 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 08 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 09 </head> 10 <body> 11 This is my HTML page. <br> 12 </body> 13 </html> 其 中 从 第 5 行 到 第 7 行 使 用 <meta> 标 记 给 出 HTML 程 序 的 相 关 信 息, 分 别 是 页 面 关 键 字 页 面 描 述 和 程 序 的 编 码 第 8 行 是 一 行 注 释 代 码, 其 中 给 出 了 CSS 程 序, 将 页 面 需 要 CSS 程 序 时, 可 以 去 掉 该 行 代 码 注 释

如 果 在 创 建 高 级 模 板 程 序 界 面 中, 选 择 HTML tempate with a form 选 项, 则 创 建 的 HTML 程 序 代 码 为 : 01 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 02 <html> 03 <head> 04 <title>htmlofadvanced2.html</title> 05 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 06 <meta http-equiv="description" content="this is my page"> 07 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 08 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 09 </head> 10 <body> 11 <form name="f1" id="f1" action="" method="post"> 12 <table border="0"> 13 <tr> 14 <td>login:</td> 15 <td><input type="text" name="login" id="login"></td> 16 </tr> 17 <tr> 18 <td>password:</td> 19 <td><input type="password" name="password" id="password"></td> 20 </tr> 21 <tr> 22 <td colspan="2" align="center"><input type="submit"></td> 23 </tr> 24 </table> 25 </form> 26 </body> 27 </html> 其 中 从 第 11 行 到 第 25 行 创 建 了 一 个 表 单, 其 中 action 属 性 指 定 的 提 交 目 标 需 要 手 动 填 写 第 15 行 创 建 了 用 于 填 写 用 户 名 的 文 本 框, 第 19 行 创 建 了 用 于 填 写 密 码 的 密 码 框, 第 22 行 创 建 了 提 交 按 钮 当 页 面 中 需 要 提 交 表 单 时, 可 以 使 用 该 模 板 创 建 HTML 程 序 说 明 : 在 实 际 开 发 中, 基 础 模 板 和 高 级 模 板 的 选 择 并 没 有 很 大 区 别 的, 因 为 高 级 模 板 中 自 动 生 成 的 内 容 很 少 被 使 用 到 只 所 以 使 用 高 级 模 板 比 较 多, 是 因 为 在 New 选 项 下 直 接 就 有 创 建 高 级 模 板 HTML 程 序 的 命 令 后 面 学 习 的 JSP 程 序 也 是 这 样 的 5.5.4 编 写 HTML 程 序 当 使 用 编 辑 区 对 HTML 程 序 编 写 时, 通 常 将 编 辑 区 分 为 上 下 两 部 分, 其 中 下 半 部 分 是 HTML 程 序 代 码, 在 其 中 可 以 手 动 编 写 代 码 ; 在 上 半 部 分 中, 可 以 通 过 界 面 的 方 式 创 建 HTML 程 序, 它 是 本 书 讲 解 的 重 点 在 上 下 两 部 分 中 间, 有 两 个 三 角, 单 击 它 们 可 以 使 整 个 编 辑 区 只 显 示 上 半 部 分 或 者 下 半 部 分 在 编 辑 区 的 左 下 角, 有 两 个 选 项,

17 Design 选 项 表 示 设 计 HTML 程 序 ; Preview 选 项 表 示 预 览 设 计 的 效 果, 其 中 给 出 了 IE 浏 览 器 和 Mozilla 浏 览 器 的 预 览 在 以 界 面 方 式 创 建 HTML 程 序 的 部 分 中, 最 上 面 的 工 具 栏 是 对 HTML 中 的 文 件 进 行 操 作 的 这 里 我 们 没 有 必 要 对 它 们 依 次 讲 解, 它 们 都 是 非 常 简 单 的 例 如 我 们 在 界 面 中 输 入 大 家 好, 这 是 我 的 第 一 个 HTML 程 序, 然 后 单 击 加 粗 按 钮, 继 续 单 击 居 中 按 钮 这 时 界 面 中 的 内 容 也 会 发 生 改 变, 并 且 下 半 部 分 的 程 序 也 会 同 时 改 变, 生 成 后 的 代 码 为 : 01 <div align="center"> 02 <strong> 大 家 好, 这 是 我 的 第 一 个 HTML 程 序 03 </strong></div> 其 中 第 1 行 指 定 的 就 是 文 字 居 中,<strong> 标 记 指 定 的 就 是 加 粗 单 击 左 下 角 的 Preview 选 项, 可 以 查 看 到 HTML 程 序 预 览 HTML 程 序 是 并 不 需 要 发 布 项 目 就 可 以 查 看 的, 所 以 直 接 使 用 外 部 的 浏 览 器 也 可 以 查 看 到 它 的 效 果, 如 图 5-17 所 示 图 5-17 HTML 程 序 运 行 效 果 在 以 界 面 方 式 创 建 HTML 程 序 的 部 分 中, 右 边 是 用 于 添 加 HTML 元 素 的 选 项, 如 图 5-18 所 示 图 5-18 创 建 HTML 元 素 其 中 HTML-Basic 栏 中 包 含 用 于 HTML 基 本 元 素 的 创 建, 例 如 超 链 接 图 片

表 格 等 在 HTML-Form 栏 中 包 含 用 于 表 单 创 建 的 元 素, 例 如 表 单 文 本 框 按 钮 等 这 里 我 们 以 表 单 元 素 举 例, 读 者 可 以 自 己 了 解 一 下 其 他 元 素 的 创 建, 都 是 比 较 简 单 的 单 击 HTML-Form 栏 中 的 Form 选 项, 将 弹 出 创 建 表 单 的 界 面, 如 图 5-19 所 示 图 5-19 创 建 表 单 其 中 Name 表 示 创 建 表 单 的 名 称, 这 里 填 写 myform Action 表 示 创 建 表 单 的 提 交 目 标, 这 里 可 以 填 写 HTMLOfAdvanced.html, 也 就 是 高 级 模 板 HTML 程 序 Method 表 示 创 建 表 单 的 提 交 方 法, 可 以 在 get 和 post 两 种 之 间 选 择, 对 于 本 程 序 而 言, 它 们 是 没 有 区 别 的 单 击 Finish 按 钮 将 完 成 表 单 的 创 建, 在 HTML 程 序 将 多 出 如 下 代 码 : <form method="get" action="htmlofadvanced.html" name="myform"> </form> 在 界 面 中, 选 择 表 单 元 素 添 加 的 位 置, 或 者 在 程 序 代 码 中 将 焦 点 定 义 在 <form> 标 记 中 继 续 单 击 HTML-Form 栏 中 的 Text Field 选 项, 将 弹 出 创 建 文 本 框 的 界 面, 如 图 5-20 所 示

19 图 5-20 创 建 文 本 框 其 中 Name 表 示 创 建 文 本 框 的 名 称, 这 里 填 写 mytext Initial Text 表 示 文 本 框 的 初 始 值, 填 写 请 在 这 里 输 入 内 容 Char Width 表 示 文 本 框 的 长 度, Max Chars 表 示 文 本 框 中 能 够 输 入 的 最 大 字 符 数, 当 不 填 写 这 两 项 时 会 给 出 一 个 默 认 值 单 击 Finish 按 钮, 将 完 成 文 本 框 的 创 建, 程 序 代 码 中 将 多 出 如 下 代 码 : <input type="text" value=" 请 在 这 里 输 入 内 容 " name="mytext"> 使 用 外 部 浏 览 器, 打 开 目 前 修 改 后 的 程 序, 运 行 结 果 如 图 5-21 所 示 图 5-21 加 入 表 单 元 素 技 巧 : 使 用 界 面 创 建 的 HTML 程 序 代 码 的 编 写 经 常 是 不 规 范 的 在 编 辑 区 中 可 以 全 部 选 中 这 些 代 码, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Source Format 命 令, 将 把 全 部 代 码 调 整 为 规 范 格 式 5.6 开 发 JSP 程 序 在 本 节 中 继 续 来 学 习 使 用 MyEclipse 开 发 JSP 程 序 JSP 程 序 是 在 HTML 程 序 的 基 础 上 加 入 Java 程 序 组 成 的, 所 以 在 创 建 JSP 程 序 时, 是 和 创 建 HTML 程 序 非 常 类 似 的, 也 分 为 基 础 模 板 和 高 级 模 板 5.6.1 使 用 基 础 模 板 创 建 JSP 程 序 在 包 资 源 管 理 其 中, 选 中 要 创 建 JSP 程 序 的 目 录, 例 如 选 中 WebRoot 目 录 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New Other 命 令, 将 弹 出 选 择 创 建 程 序 的 界 面, 在 其 中 选 择 MyEclipse Web 节 点, 如 图 5-22 所 示

图 5-22 选 择 JSP 程 序 从 界 面 中 可 以 看 到, 创 建 JSP 程 序 中, 也 存 在 高 级 模 板 和 基 础 模 板 在 其 中 选 择 JSP (Basic Templates) 选 项, 单 击 Next 按 钮, 将 进 入 创 建 基 础 模 板 的 JSP 程 序 界 面, 如 图 5-23 所 示 图 5-23 创 建 基 础 模 板 JSP 程 序 可 以 看 到 是 和 创 建 HTML 程 序 非 常 相 似 的 Enter or select the parent folder 选 项 表 示 JSP 程 序 创 建 的 位 置 File name 选 项 表 示 创 建 的 JSP 程 序 的 文 件 名, 这 里 填 写 JSPOfBasic.jsp 单 击 Next 按 钮, 将 看 到 JSP 程 序 的 预 览 单 击 Finish 按 钮

JSF主要简化服 务端的界面开发. 21 后将完成基础模板 JSP 程序的创建 并在编辑区中打开 JSP 程序 如图 5-24 所示 图 5-24 编辑区打开 JSP 程序 可以看到在编辑区中打开 JSP 程序 也是分为上下两部分的 在上半部分中的右边 可以看到不但可以添加 HTML 标记元素 还可以添加 Struts 和 JSF 的标记元素 这些内 容在后面专门讲解对应技术时进行详细讲解 在下半部分中可以看到具体的 JSP 程序代码 和 HTML 程序最大的区别就是在程序 的最开头的部分多出了两行代码 代码内容为 <%@ page language="java" contenttype="text/html; charset=iso-8859-1" pageencoding="iso-8859-1"%> 这两行代码是使用 JSP 技术中的 page 指令指定 JSP 程序的编码规则 5.6.2 使用高级模板创建 JSP 程序 在选择 JSP 程序界面中 选择 JSP Advanced Templates 选项 或者选中要创 建目录 单击鼠标右键 在弹出的菜单中选择 New JSP Advanced Templates 命令 都将弹出使用高级模板创建 JSP 程序的界面 如图 5-25 所示

图 5-25 高 级 模 板 创 建 JSP 程 序 其 中 File Path 表 示 新 创 建 JSP 程 序 所 在 的 目 录 File Name 表 示 创 建 JSP 程 序 的 文 件 名, 这 里 填 写 JSPOfAdvanced.jsp Template to use 表 示 使 用 的 模 板, 通 常 选 择 Default JSP template 选 项, 也 就 是 默 认 JSP 模 板 说 明 : 在 Template to use 中 有 很 多 非 常 好 用 的 模 板, 例 如 Struts 模 板 JSF 模 板 等, 它 们 将 在 后 面 专 门 讲 解 对 应 技 术 时 进 行 讲 解 单 击 Finish 按 钮, 将 完 成 高 级 模 板 JSP 程 序 的 创 建, 这 时 候 会 在 编 辑 区 中 打 开 JSP 程 序 代 码, 其 具 体 代 码 为 : 01 <%@ page language="java" import="java.util.*" pageencoding="iso-8859-1"%> 02 <% 03 String path = request.getcontextpath(); 04 String basepath = request.getscheme()+"://"+request.getservername()+ 05 ":"+request.getserverport()+path+"/"; 06 %> 07 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 08 <html> 09 <head> 10 <base href="<%=basepath%>"> 11 <title>my JSP 'JSPOfAdvanced.jsp' starting page</title> 12 <meta http-equiv="pragma" content="no-cache"> 13 <meta http-equiv="cache-control" content="no-cache"> 14 <meta http-equiv="expires" content="0"> 15 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 16 <meta http-equiv="description" content="this is my page"> 17 <!-- 18 <link rel="stylesheet" type="text/css" href="styles.css">

getcontextpath()用于获取java Web在Tomcat的Webapps的目录. 19 --> 20 </head> 21 <body> 22 23 24 23 This is my JSP page. <br> </body> request.getcontextpath()是在开发web项目时 经常 用到的方法 其作用是获取当前的系统路径 </html> 在其中第 1 行中使用 page 指令指定语言是 Java 导入 util 包和设置 JSP 程序的编码 为 ISO-8859-1 在第 3 行中使用 request 内置对象调用 getcontextpath 方法 从而获 得当前应用的根目录 它在实际开发中经常被用到 通过相对路径的方式 从而避免路 径错误 第 4 行中使用到了三个 request 内置对象中的方法 分别是获取网络协议 主 机名和端口号 然后加入当前应用的根目录 从而得到完整访问路径 后面其他的内容 就和 HTML 程序中的非常相似 这里就不再进行讲解 5.6.3 改变 JSP 程序的编码 在前面讲解 HTML 程序时 我们通过 大家好 这是我的第一个 HTML 程序 这 句话讲解了 HTML 程序的界面化编写 但是如果将这句话复制到当前 JSP 程序中 会发 现是不能够保存的 这是因为当前 JSP 程序的编码规则是 ISO-8859-1 在该编码中 是不支持中文的 如果想在 JSP 页面中显示中文 需要改变 JSP 程序的编码 在 MyEclipse 的菜单中 选择 Window Preferences 命令 将打开首选项设置 界面 在其中左边选择 MyEclipse Enterprise Workbench Files and Editors JSP 节点 界面如图 5-26 所示 图 5-26 改变 JSP 程序的编码

其中 Encoding 就是用于编码的选择 默认的就是 ISO-8859-1 在其中使用 最多的就是选择 ISO 10646/Unicode(UTF-8) 或者 Chinese,National Standard 选项 它们分别对应着 UTF-8 和 GB18030 编码 UTF-8 编码是 Unicode 的一种变长 字符编码 从而它能够对中文进行编码 GB18030 编码是我国定义的汉字编码规则 可以说它专业的中文编码 它和 GBK gb2312 等中文编码类似的 这里我们选择 ISO 10646/Unicode(UTF-8) 选项 也就是定义成 UTF-8 编码 单击 OK 按钮 再次创建高级模板的 JSP 程序 其代码中的 page 指令内容将变 为 <%@ page language="java" import="java.util.*" pageencoding="utf-8"%> 其中使用 pageencoding 属性指定编码规则为 UTF-8 这时候再在其中输入中文 会发现是能够正常保存的 不会出现错误的 注意 编码是 Web 开发中非常重要的一个知识点 一定要对编码有所了解 如果 处理不好 在页面中就会出现乱码 在后面的其他技术的讲解中 还会讲解到编码 5.6.4 在 JSP 程序中使用 EL 表达式 el 读音[el], 表达式的用 途 EL 全名为 Expression Language 它原来是 JSTL1.0 为了方便存取数据所定义的语言 到了 JSP2.0 以后 EL 正式纳入成为标准规划之一 说明 是否能够在 JSP 程序中使用 EL 表达式 这要取决于当前开发环境 要想 在其中能够直接使用 EL 表达式 要在创建 Java Web 项目时选择 J2EE 5.0 版本 EL 表达式使用最多的就是获取保存在某一范围内的属性值 在 EL 表达式中有四个 与存储范围有关的内置对象 分别是 applicationscope sessionscope requestscope pagescope 这些内置对象使用时和 JSP 中的 pagecontext request session application 对象是一样的 但是这四个内置对象只能用来取得某个范围的属性值 即只有 getattribute()方法 不能取得其他的信息 这个是EL表达式 在 EL 表达式中 也可以不指定范围 如直接使用${name} 这时 EL 将默认从 page 范围开始查找 name 属性 如果找不到 再依次到 request session application 范围中 找 如果仍然没有找到就返回 null 在网页中也就没有显示 在 MyEclipse 的包资源管理器中 选中 FirstWeb 项目中的 WebRoot 目录 单击 鼠标右键 在弹出的菜单中选择 New JSP Advanced Templates 命令 在创建 JSP 程序界面中 填写文件名为 JSPOfEL.jsp 创建完成后将在编辑区中打开该代码 在 body 标记中添加如下内容 01 <% 02 request.setattribute("name","tom"); 03 %> 04 欢迎${name}登录本 网站 其中第 2 行使用 request 内置对象保存一个 name 信息 在第 4 行中使用 EL 表达式 获取 name 信息 从而将这些信息显示到页面中 注意 运行 JSP 程序是要首先发布项目 然后启动服务器的

25 启动服务器后 打开浏览器 输入如下地址 http://localhost:8080/firstweb/jspofel.jsp 浏览器如图 5-27 所示 图 5-27 使用 EL 表达式 从运行结果中可以看到 将保存在 request 内置对象中的属性值获取到 如果不运 行项目 而是直接使用浏览器打开 JSP 程序 将会直接将 EL 表达式显示在页面中 读 者可以自己尝试一下 5.6.5 在 JSP 程序中使用 JSTL 标签 使用JSTL的前提, 需要把 JSTL相关的JAR库导入到 当前项目中. JSTL 的全称为 JSP Standard Tag Library 其中文名为 JSP 标准标记库 是一个实现 了 Web 应用程序中常见的通用功能的定制标记库集 这些功能包括迭代和条件判断 数据管理格式化 XML 操作以及数据库访问 如果想在 JSP 程序中使用 JSTL 标签 要首先将 JSTL 标签的相关 JAR 包导入到项 目中 如果创建 Java Web 项目时 选择的是 J2EE 5.0 版本 则会自动将 JSTL 标签 JAR 包导入到项目中 在 FirstWeb 项目的 Java EE 5 Libraries 节点下可以看到有一个 jstl-1.1.jar 文件 它就是 JSTL 标签相关 JAR 包 如果创建 Java Web 项目时 选择的是 J2EE 1.4 版本 那么就需要手动的导入 JSTL 标签 JAR 包 JAR 包可以去官方网站进行下载 然后将下载后的 JAR 包复制到 WebRoot WEB-INF lib 目录下 JSTL 标签库分为五类 分别是 JSTL 核心标签库 数据库标签库 I18N 格式化标 签库 XML 标签库和 JSTL 函数标签库 这里我们以其中的核心标签库中的流程控制相 关标签进行讲解 在 JSP 页面中要使用到核心标签库 必须使用<%@taglib%>指令 指定核心标签库 的前缀以及 uri 代码如下 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 其中 prefix 为 c 表示标签的前缀为 c 这时就必须使用<c:XXX>这种格式

核 心 标 签 通 常 设 置 前 缀 为 c, 也 可 以 直 接 为 其 他 内 容, 但 是 阅 读 性 就 会 降 低 uri 用 来 指 定 核 心 标 签 库 规 范 文 件 (TLD 文 件 ) 地 址 技 巧 :uri 属 性 值 是 比 较 长 的, 有 些 程 序 员 选 择 死 记 硬 背, 这 是 没 有 必 要 的 打 开 jstl-1.1.jar WEB-INF 目 录 下 的 c.tld 文 件, 其 中 <uri>http://java.sun.com/jsp/jstl/core</uri> 指 定 的 就 是 url, 将 其 中 的 http://java.sun.com/jsp/jstl/core 复 制 到 <%@taglib%> 指 令 的 uri 属 性 就 可 以 其 他 的 标 签 库 也 是 这 样 的 使 用 前 面 讲 解 的 创 建 JSP 程 序 的 方 式, 创 建 一 个 文 件 名 为 JSPOfJSTL.jsp 的 JSP 程 序 在 编 辑 区 中, 在 page 指 令 下 加 入 <%@taglib%> 指 令, 引 入 核 心 标 签 库 然 后 在 body 标 记 中 加 入 如 下 代 码 : 01 <% 02 ArrayList list = new ArrayList(); // 创 建 列 表 用 来 存 放 旅 游 地 信 息 03 list.add(" 故 宫 "); // 添 加 故 宫 04 list.add(" 长 城 "); // 添 加 长 城 05 list.add(" 香 山 "); // 添 加 香 山 06 list.add(" 北 海 "); // 添 加 北 海 07 pagecontext.setattribute("list",list);// 将 list 信 息 保 存 在 page 范 围 08 %> 09 <table border="1"> 10 <tr> 11 <td> 序 号 </td> 12 <td> 名 称 </td> 13 </tr> 14 <c:foreach var="lvyou" items="${pagescope.list}" varstatus="stus"> 15 <tr> 16 <td><c:out value="${stus.index + 1}"></c:out></td><%- 列 表 序 号 --%> 17 <c:choose> 18 <c:when test="${(stus.index + 1) % 2 == 0}"><%-- 偶 数 --%> 19 <td bgcolor="#cccccc"><c:out value="${lvyou}"/></td> 20 </c:when> 21 <c:otherwise> 22 <td><c:out value="${lvyou}"/></td> 23 </c:otherwise> 24 </c:choose> 25 </tr> 26 </c:foreach> 27 </table> 其 中 从 第 2 行 到 第 7 行 表 示 创 建 一 个 列 表 集 合, 然 后 将 集 合 信 息 保 存 到 page 范 围 内 在 第 14 行 中 使 用 <c:foreach> 标 签 对 page 范 围 内 的 列 表 进 行 遍 历 在 第 16 行 中 使 用 <c:out> 标 签 进 行 内 容 的 输 入, 这 里 结 合 了 EL 表 达 式 第 17 行 的 <c:choose> 标 签 是 判 断 标 签 的 父 标 签, 在 该 标 签 中, 第 18 行 使 用 <c:when> 标 签 判 断 序 号 是 否 为 偶 数, 它 相 当 于 if 语 句 ; 第 21 行 中 使 用 <c:otherwise> 标 签, 它 相 当 于 else 语 句

27 5.7 开发 JavaBean 程序 Javabeans实际上可称 为实体类程序. 开发 JavaBean 程序并不能算是一个新知识点 因为 JavaBean 其实就是一个简单的 Java 类 在 Java Web 项目中通常将 JavaBean 程序放在 src 目录下 在 Web 的程序中 通常所说的 JavaBean 是指实体类程序 也可以把它称为标准的 JavaBean 程序 标准的 JavaBean 应该具有如下几个特点 1 JavaBean 必须是一个公开的类 也就是说 JavaBean 的类访问权限必须是 public 的 2 JavaBean 必须具有一个无参数的构造方法 如果在 JavaBean 中定义了自定义的 有参构造方法 就必须添加一个无参数构造方法 否则将无法设置属性 如果没有定义 自定义的有参构造方法 则可以利用系统自动生成的无参构造方法 3 JavaBean 一般将属性设置成私有的 通过使用 setxxx()方法和 getxxx()方法来 进行属性的设置和获取 其中构造函数可以通过生成构造函数的操作来自动生成 setxxx()和 getxxx()方法 可以通过生成 Setter 和 Getter 方法的操作自动生成 这些都在第 2 章中详细讲解过 这 里就不再详细讲解 5.8 开发 Servlet 程序 在当前 Java Web 项目的分层思想中 前面两节讲解的 HTML 程序和 JSP 程序主要 是做显示层 而本节将要讲解的 Servlet 主要就是做控制层 在 Servlet 中完成参数的接 收 然后使用参数调用业务逻辑层 接下来根据调用结果的不同跳转到不同的页面 5.8.1 创建 Servlet 程序 在 MyEclipse 中集成了创建 Servlet 程序的功能 会自动生成 Servlet 程序中的固定 代码 并给出配置代码 Servlet 程序将创建在 src 下 并且需要为它定义单独的一个包 例如包名为 com.sanqing.servlet 然后选中包目录 单击鼠标右键 在弹出的菜单中 选择 New Servlet 命令 将弹出创建 Servlet 程序的界面 如图 5-28 所示

图 5-28 创 建 Servlet 程 序 其 中 Source folder 表 示 创 建 Servlet 程 序 的 目 录 位 置 Package 表 示 创 建 Servlet 的 所 在 包 Name 表 示 Servlet 的 名 称, 它 的 名 称 通 常 以 Servlet 结 尾, 例 如 HelloServlet Modifiers 表 示 Servlet 程 序 的 修 饰 符, 通 常 使 用 public 公 共 访 问 修 饰 符, 它 也 是 默 认 选 项 Superclass 表 示 Servlet 程 序 继 承 的 父 类, 当 使 用 这 种 方 式 创 建 Servlet 时 将 自 动 继 承 javax.servlet.http.httpservlet 类 Interfaces 表 示 Servlet 程 序 实 现 的 接 口, 通 常 是 不 需 要 实 现 接 口 的 Template to use 表 示 Servlet 程 序 使 用 的 模 板, 目 前 只 有 默 认 模 板 一 个 选 项 Which method stubs would you like to create 表 示 在 Servlet 程 序 中 将 要 创 建 哪 些 方 法, 其 中 最 重 要 的 就 是 生 命 周 期 方 法 init() and destroy() 选 项 表 示 初 始 化 和 销 毁 方 法, 当 初 始 化 和 销 毁 Servlet 时 执 行 对 应 的 方 法 doget() 选 项 和 dopost() 选 项 都 表 示 Servlet 的 执 行 方 法, 分 别 对 应 GET 和 POST 提 交 方 式 这 里 我 们 先 只 选 择 其 中 的 doget() 选 项 和 dopost(), 单 击 Next 按 钮, 将 进 入 Servlet 配 置 页 面, 如 图 5-29 所 示

29 图 5-29 对 Servlet 进 行 配 置 其 中 Servlet/JSP Class Name 表 示 Servlet 程 序 类 的 类 名, 这 里 一 定 要 是 具 有 包 名 的 完 整 类 名 Servlet/JSP Name 表 示 Servlet 程 序 的 名 称, 理 论 上 这 里 可 以 任 意 取, 但 是 通 常 以 Servlet 的 类 名 来 命 名 Servlet/JSP Mapping URL 表 示 访 问 Servlet 的 URL, 该 URL 出 现 在 提 交 表 单 或 者 浏 览 器 访 问 地 址 中 File Path of web.xml 表 示 在 其 中 进 行 Servlet 配 置 的 web.xml 文 件 所 在 目 录 Display Name 和 Description 都 表 示 描 述 性 的 语 言, 它 们 是 可 以 不 写 的 单 击 Finish 按 钮, 将 完 成 Servlet 程 序 的 创 建 在 编 辑 区 中 将 打 开 HelloServlet.java 和 web.xml 两 个 文 件, 其 中 HelloServlet.java Servlet 程 序 部 分 代 码 如 下 : 01 package com.sanqing.servlet; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class HelloServlet extends HttpServlet { 04 public void doget(httpservletrequest request, HttpServletResponse response) 05 throws ServletException, IOException { 06 response.setcontenttype("text/html"); 07 PrintWriter out = response.getwriter(); 08 out.println("<!doctype HTML PUBLIC \"-//W3C//DTD HTML 09 4.01 Transitional//EN\">"); 10 out.println("<html>"); 11 out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); 12 out.println(" <BODY>"); 13 out.print(" This is "); 14 out.print(this.getclass());

15 out.println(", using the GET method"); 16 out.println(" </BODY>"); 17 out.println("</html>"); 18 out.flush(); 19 out.close(); 20 } 21 // 省 略 dopost 方 法 代 码 22 } 其 中 从 第 8 行 到 第 17 行 的 代 码 都 是 输 出 HTML 标 记, 以 及 其 中 的 内 容, 从 而 组 成 一 个 页 面 再 来 看 在 web.xml 文 件 中 对 Servlet 的 配 置 文 件, 其 配 置 代 码 为 : 01 <servlet> 02 <servlet-name>helloservlet</servlet-name> 03 <servlet-class>com.sanqing.servlet.helloservlet</servlet-class> 04 </servlet> 05 <servlet-mapping> 06 <servlet-name>helloservlet</servlet-name> 07 <url-pattern>/servlet/helloservlet</url-pattern> 08 </servlet-mapping> 其 中 从 第 1 行 到 第 4 行 使 用 <servlet> 标 记 对 Servlet 程 序 进 行 配 置, 第 3 行 中 使 用 <servlet-class> 标 记 配 置 了 Servlet 的 全 称 类 名, 并 为 它 使 用 <servlet-name> 标 记 定 义 了 一 个 名 称 从 第 5 行 到 第 8 行 使 用 <servlet-mapping> 标 记 对 Servlet 程 序 的 映 射 进 行 配 置 其 中 的 Servlet 名 称 一 定 要 有 前 面 配 置 类 时 的 名 称 对 应 上, 然 后 使 用 <url-pattern> 标 记 配 置 访 问 URL 路 径 这 些 内 容 都 是 通 过 配 置 Servlet 界 面 自 动 生 成 的 启 动 或 者 重 启 服 务 器, 启 动 后, 打 开 浏 览 器, 在 其 中 输 入 如 下 地 址 : http://localhost:8080/firstweb/servlet/helloservlet 其 中 /servlet/helloservlet 就 是 在 web.xml 文 件 中 对 Servlet 进 行 的 URL 配 置, 访 问 后 的 页 面 如 图 5-30 所 示 图 5-30 Servlet 程 序 的 运 行 结 果 其 中 的 信 息 就 是 运 行 Servlet 时 输 出 的 内 容, con.sanqing.servlet.helloservlet 就

31 是 this.getclass() 的输出结果 说明 在本小节中主要讲解的是 Servlet 的创建 在实际开发中 Servlet 的功能并 不是输出页面 该功能通常由 JSP 程序来完成 Servlet 的主要功能就是作为控制层 接收参数 调用后台 执行跳转 5.8.2 创建 Filter 过滤器程序 实现filter接口的java类. filter Filter 技术是 Servlet 2.3 新增加的功能 其中文名称为过滤器 Filter 和 Servlet 是非 常类似的 也是一个 Java 类 所以其创建方式和普通的 Java 类完全相同 自定义的 Filter 类必须实现 Filter 接口 还必须实现 Filter 接口中定义的 init()方法 dofilter()方法和 destroy()方法 其中 init()方法和 destroy()方法分别用来初始化和销毁时调用 通常并不 在这两个方法中写任何代码 这里传 递给下 收三个参数 分别是 request response 和 chain 其中 request 和 response 参数用来传递 一个如 给下一个 Filter 如果有多个 Filter 或者 JSP 和 Servlet chain 参数则通过调用其 dofilter 何解释. dofilter()方法用来实现过滤 所有的处理代码都放置在该方法中 dofilter()方法接 方法来调用下一个 Filter 获得调用原始的 JSP 或者 Servlet 等其他内容 在 MyEclipse 中 并没有集成创建 Filter 过滤器的功能 但是也是不难操作的 因 为 Filter 本身就是一个 Java 类 通过创建 Java 类的步骤 在创建 Java 类的界面中 选 择实现 Fileter 接口 如图 5-31 所示 注意:创建filter需要 实现filter接口. 图 5-31 创建过滤器 单击 Finish 按钮 将完成过滤器的创建 在编辑区中打开程序后 在 dofilter

方 法 中 加 入 过 滤 的 功 能 代 码, 例 如 这 里 加 入 对 编 码 进 行 过 滤 的 代 码, 则 过 滤 器 的 完 整 代 码 为 : 01 package com.sanqing.filter; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class EncodeFilter implements Filter { 04 public void destroy() { 05 } 06 public void dofilter(servletrequest req, ServletResponse res, 07 FilterChain chain) throws IOException, ServletException { 08 HttpServletRequest request=(httpservletrequest)req; 09 request.setcharacterencoding("utf-8"); 10 chain.dofilter(req, res); 11 } 12 public void init(filterconfig arg0) throws ServletException { 13 } 14 } 开 发 完 过 滤 器 类 后, 和 Servlet 一 样, 还 需 要 在 web.xml 文 件 中 进 行 配 置, 可 以 直 接 通 过 代 码 进 行 配 置, 也 可 以 通 过 界 面 化 得 操 作 进 行 配 置 在 编 辑 区 中 打 开 web.xml 文 件, 在 左 下 角 中 选 择 Design 选 项, 将 进 入 视 图 化 配 置 的 页 面, 在 其 中 左 边 再 选 择 Filters 节 点, 界 面 如 图 5-32 所 示 图 5-32 视 图 化 配 置 其 中 右 上 角 部 分 是 对 过 滤 器 类 进 行 配 置, 单 击 Add 按 钮, 将 弹 出 过 滤 器 类 配 置 界 面, 如 图 5-33 所 示

33 图 5-33 配 置 过 滤 器 类 其 中 Filter-Name 表 示 配 置 过 滤 器 的 名 称, 这 里 填 写 EncodeFilter Filter-Class 表 示 配 置 过 滤 器 的 类 名, 这 里 要 是 包 括 包 名 的 全 称 类 名, 可 以 输 入, 也 可 以 单 击 Browse 按 钮 选 择 其 他 两 项 可 以 选 择 不 填, 单 击 Finish 按 钮 将 完 成 过 滤 器 类 的 配 置, 并 且 自 动 进 入 更 详 细 的 配 置 界 面, 在 其 中 可 以 对 初 始 化 参 数 等 进 行 配 置, 这 里 就 不 再 讲 解 再 次 选 择 Filters 节 点, 在 视 图 化 配 置 界 面 的 右 下 部 分 中, 单 击 Add 按 钮, 将 弹 出 过 滤 器 映 射 的 配 置 界 面, 如 图 5-34 所 示 图 5-34 对 过 滤 器 映 射 进 行 配 置 其 中 Filter-Name 表 示 配 置 过 滤 器 的 名 称, 这 里 填 写 EncodeFilter, 从 而 和 前 面 的 过 滤 器 类 对 应 URL-Pattern 表 示 过 滤 的 URL 地 址, 也 就 是 对 哪 些 URL 访 问 进 行 过 滤, 这 里 填 写 /*, 它 表 示 对 所 有 请 求 进 行 过 滤 单 击 Finish 按 钮, 将 完 成 过 滤 器 映 射 的 配 置 选 择 编 辑 区 左 下 角 的 Source 选 项, 将 看 到 web.xml 文 件 的 具 体 代 码, 可 以 发

现 其 中 多 出 了 如 下 代 码 : 01 <filter> 02 <filter-name>encodefilter</filter-name> 03 <filter-class>com.sanqing.filter.encodefilter</filter-class> 04 </filter> 05 <filter-mapping> 06 <filter-name>encodefilter</filter-name> 07 <url-pattern>/*</url-pattern> 08 </filter-mapping> 这 就 是 通 过 前 面 界 面 化 操 作 自 动 生 成 的 代 码 说 明 : 在 web.xml 文 件 的 视 图 化 配 置 中, 不 但 能 够 对 过 滤 器 进 行 界 面 化 配 置, 还 能 够 对 Servlet 欢 迎 页 等 其 他 内 容 进 行 界 面 化 配 置 在 后 面 的 学 习 中, 使 用 到 时 进 行 详 细 讲 解 5.9 开 发 网 络 商 城 的 显 示 层 和 控 制 层 在 管 理 数 据 库 一 章 中, 已 经 开 发 了 网 络 商 城 的 数 据 访 问 层, 在 本 章 学 习 完 JSP 和 Servlet 等 Web 程 序 后, 我 们 就 来 开 发 网 络 商 城 的 显 示 层 和 控 制 层 首 先 要 创 建 一 个 名 称 为 store 的 Java Web 项 目, 然 后 将 管 理 数 据 库 一 章 开 发 的 数 据 访 问 层 相 关 包 都 复 制 到 store 项 目 中 因 为 要 连 接 数 据 库, 所 以 需 要 将 数 据 库 驱 动 包 导 入 到 Web 项 目 中, 这 里 只 需 要 复 制 到 WebRoot WEB-INF lib 目 录 下 接 下 来 将 本 章 中 开 发 的 编 码 过 滤 器 程 序 复 制 到 本 项 目 中, 不 要 忘 记 对 它 的 配 置, 从 而 能 够 完 成 对 中 文 信 息 的 处 理 说 明 : 传 输 中 的 信 息 的 编 码 是 和 JSP 程 序 或 者 HTML 程 序 的 编 码 无 关 的, 它 和 HTTP 协 议 有 关, 所 有 通 过 该 协 议 传 输 的 编 码 都 是 ISO-8859-1 ISO-8859-1 编 码 是 不 支 持 中 文 的, 所 以 要 进 行 比 较 的 编 码 处 理 5.9.1 开 发 录 入 商 品 的 HTML 程 序 网 络 商 城 的 主 要 功 能 就 是 让 用 户 来 购 买 商 品, 要 将 商 品 显 示 在 页 面 中, 这 些 商 品 需 要 在 系 统 后 台 进 行 录 入 录 入 商 品 的 页 面 只 需 要 有 一 个 提 交 表 单, 所 以 这 里 开 发 一 个 HTML 程 序 就 可 以 这 里 我 们 选 择 高 级 模 板 来 创 建 HTML 程 序 在 创 建 HTML 程 序 的 界 面 中, 选 择 默 认 模 板, 文 件 名 填 写 AddCommodity.html, 创 建 完 成 后 将 在 编 辑 区 中 将 该 程 序 打 开 删 除 原 body 标 记 对 中 的 内 容, 然 后 在 界 面 化 操 作 部 分 中 创 建 一 个 Form 表 单, 创 建 界 面 如 图 5-35 所 示

35 图 5-35 创 建 录 入 商 品 表 单 创 建 表 单 完 成 后, 在 表 单 中 输 入 商 品 名 称, 然 后 单 击 Text Field 选 项, 弹 出 创 建 用 于 输 入 商 品 的 文 本 框, 填 写 必 要 信 息 后, 界 面 如 图 5-36 所 示 图 5-36 创 建 输 入 商 品 名 称 文 本 框 然 后 使 用 同 样 的 办 法, 创 建 用 于 输 入 商 品 价 格 和 折 扣 价 格 的 文 本 框 最 后 定 义 提 交 按 钮, 单 击 Button 选 项, 将 弹 出 创 建 按 钮 的 界 面, 填 写 必 要 信 息 后, 界 面 如 图 5-37 所 示

图 5-37 创 建 提 交 按 钮 单 击 Finish 按 钮, 从 而 完 成 提 交 按 钮 的 创 建, 从 而 也 完 成 录 入 商 品 表 单 的 创 建 选 择 编 辑 区 左 下 角 的 Preview 选 项, 则 可 以 看 到 IE 浏 览 器 的 预 览, 如 图 5-38 所 示 图 5-39 IE 浏 览 器 预 览 查 看 自 动 生 成 的 HTML 程 序 代 码, 可 以 看 到 代 码 的 编 写 时 不 符 合 规 范 的 选 中 其 中 的 表 单 代 码, 在 右 键 弹 出 菜 单 中, 选 择 Source Format 命 令, 调 整 后 的 代 码 为 : 01 <form method="post" action="addcommodityservlet" name="myform"> 02 <p> 03 商 品 名 称 04 <input type="text" value=" 在 这 里 输 入 商 品 名 称 " name="name"> 05 </p> 06 <p> 07 商 品 价 格 08 <input type="text" value=" 在 这 里 输 入 商 品 价 格 " name="price"> 09 </p> 10 <p> 11 折 扣 价 格 12 <input type="text" value=" 在 这 里 输 入 折 扣 价 格 " name="agio"> 13 </p>

37 14 <p> 15 16 <input type="submit" value=" 录 入 商 品 " name="add"> 17 </p> 18 </form> 注 意 : 使 用 这 种 方 式 创 建 的 HTML 程 序 效 果 并 不 十 分 美 观 的, 这 里 主 要 是 演 示 如 何 快 速 开 发 在 实 际 开 发 中, 具 体 页 面 效 果 由 专 门 的 美 工 人 员 完 成 5.9.2 开 发 录 入 商 品 的 Servlet 程 序 上 一 小 节 开 发 的 录 入 商 品 HTML 程 序 是 项 目 中 的 显 示 层, 单 击 录 入 商 品 按 钮 后 会 将 表 单 中 的 信 息 提 交 到 Servlet 程 序 中 在 本 节 中 就 来 开 发 录 入 商 品 的 Servlet 程 序, 它 主 要 来 做 控 制 层 选 中 项 目 中 的 com.sanqing.servlet 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Servlet 命 令, 在 弹 出 的 创 建 Servlet 界 面 中, 输 入 相 关 信 息 后, 如 图 5-38 所 示 图 5-38 创 建 录 入 商 品 Servlet 示 单 击 Next 按 钮, 将 进 入 配 置 Servlet 的 页 面, 修 改 其 中 的 信 息 后, 如 图 5-39 所

图 5-39 配 置 录 入 商 品 Servlet 技 巧 : 其 中 主 要 是 对 Servlet 的 URL 进 行 修 改, 去 掉 其 中 的 /servlet, 这 样 能 够 保 证 Servlet 的 访 问 也 在 项 目 根 目 录 下 在 编 辑 区 中 打 开 Servlet 程 序 后, 将 代 码 改 为 如 下 内 容 : 01 package com.sanqing.servlet; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class AddCommodityServlet extends HttpServlet { 04 public void doget(httpservletrequest request, HttpServletResponse response) 05 throws ServletException, IOException { 06 dopost(request,response); 07 } 08 public void dopost(httpservletrequest request, HttpServletResponse response) 09 throws ServletException, IOException { 10 String name=request.getparameter("name"); // 接 收 表 单 参 数 11 String price=request.getparameter("price"); 12 String agio=request.getparameter("agio"); 13 Commodity commodity=new Commodity(); // 创 建 商 品 对 象 并 设 置 信 息 14 commodity.setname(name); 15 commodity.setprice(double.parsedouble(price)); 16 commodity.setagio(double.parsedouble(agio)); 17 CommodityDAO commoditydao= 18 CommodityDAOFactory.createCommodityDAOImpl(); 19 commoditydao.addcommodity(commodity); // 调 用 录 入 商 品 方 法 20 request.getrequestdispatcher("addsuccess.html").forward(request, response);

39 21 } 22 } 其 中 只 在 dopost 方 法 中 编 写 了 代 码, 在 doget 方 法 中 调 用 dopost 方 法, 在 实 际 开 发 中 通 常 也 是 这 样 操 作 的 从 第 10 行 到 第 12 行 是 接 收 提 交 表 单 中 的 信 息 在 第 13 行 中 创 建 了 商 品 对 象, 然 后 依 次 将 获 取 到 的 商 品 相 关 信 息 设 置 到 对 象 中 在 第 17 行 通 过 商 品 DAO 工 厂 类 获 取 到 商 品 DAO 实 现 类 后, 在 第 19 行 调 用 addcommodity 方 法, 从 而 将 商 品 的 信 息 保 存 到 数 据 库 中 在 第 20 行 执 行 服 务 器 跳 转, 跳 转 到 录 入 成 功 页 面 因 为 我 们 是 通 过 MyEclipse 中 的 集 成 功 能 创 建 的 Servlet, 所 以 会 自 动 对 它 进 行 配 置, 读 者 可 以 自 己 看 一 下 它 的 配 置 信 息 5.9.3 开 发 录 入 商 品 成 功 页 面 在 录 入 商 品 Servlet 中, 录 入 商 品 成 功 后, 将 进 行 服 务 器 跳 转, 跳 转 到 AddSuccess.html HTML 程 序 在 本 小 节 中 就 来 开 发 该 程 序 这 里 仍 然 采 用 高 级 模 板 来 创 建 HTML 程 序, 首 先 将 原 body 标 记 中 的 内 容 换 为 录 入 商 品 成 功 信 息, 选 中 这 行 文 字, 在 视 图 操 作 的 工 具 栏 中, 依 次 选 择 选 项 单 击 加 粗 按 钮 居 中 按 钮 和 设 置 字 体 颜 色 按 钮, 在 其 中 选 择 自 己 喜 欢 的 颜 色, 这 样 成 功 页 面 的 显 示 信 息 就 开 发 完 成 然 后 开 发 一 个 能 够 进 入 显 示 所 有 商 品 页 面 的 超 链 接 先 在 body 标 记 中 输 入 显 示 所 有 商 品 信 息, 选 中 后 再 在 HTML-Basic 选 项 中 单 击 Hyperlink 节 点, 在 弹 出 的 创 建 超 链 接 界 面, 输 入 相 关 信 息, 如 图 5-40 所 示 图 5-40 创 建 超 链 接 单 击 Finish 按 钮, 将 完 成 超 链 接 的 创 建 对 于 超 链 接 而 言, 也 可 以 像 普 通 文 字 一 样 进 行 操 作, 例 如 单 击 居 中 按 钮 等

所 示 单 击 编 辑 区 左 下 角 的 Preview 选 项, 将 可 以 查 看 到 IE 浏 览 器 的 预 览, 如 图 5-41 图 5-41 录 入 成 功 页 面 预 览 调 整 自 动 生 成 的 HTML 程 序 代 码 格 式, 其 自 动 生 成 的 代 码 内 容 为 : 01 <div align="center"> 02 <h1> 03 <font color="#ff0000"><strong> 录 入 商 品 成 功 </strong> 04 </font> 05 </h1> 06 </div> 07 <div align="center"> 08 <a href="selectcommodityservlet"> 显 示 所 有 商 品 </a> 09 </div> 其 中 显 示 所 有 商 品 超 链 接 指 向 查 询 所 有 商 品 Servlet 的 URL 5.9.4 开 发 查 询 所 有 商 品 Servlet 程 序 单 击 录 入 成 功 页 面 中 的 显 示 所 有 商 品 超 链 接, 将 会 访 问 显 示 所 有 商 品 Servlet, 在 本 小 节 中 就 来 开 发 该 Servlet 程 序 选 中 项 目 中 的 com.sanqing.servlet 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Servlet 命 令, 在 弹 出 的 创 建 Servlet 界 面 中, 输 入 相 关 信 息 后, 如 图 5-42 所 示

41 图 5-42 创 建 查 询 商 品 Servlet 单 击 Next 按 钮, 将 进 入 配 置 查 询 所 有 商 品 Servlet 的 页 面, 修 改 其 中 的 信 息 后, 如 图 5-43 所 示 图 5-43 配 置 查 询 商 品 Servlet

在 编 辑 区 中 打 开 Servlet 程 序 代 码 后, 修 改 其 中 的 代 码, 修 改 后 的 代 码 为 : 01 package com.sanqing.servlet; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class SelectCommodityServlet extends HttpServlet { 04 public void doget(httpservletrequest request, HttpServletResponse response) 05 throws ServletException, IOException { 06 dopost(request,response); 07 } 08 public void dopost(httpservletrequest request, HttpServletResponse response) 09 throws ServletException, IOException { 10 CommodityDAO commoditydao= 11 CommodityDAOFactory.createCommodityDAOImpl(); 12 List<Commodity> commoditylist=commoditydao.findallcommodity(); 13 request.setattribute("commoditylist", commoditylist); 14 request.getrequestdispatcher("allcommodity.jsp") 15.forward(request, response); 16 } 17 } 其 中 第 10 行 通 过 DAO 工 厂 类 得 到 商 品 DAO 实 现 接 口, 然 后 在 第 12 行 调 用 findallcommodity 方 法, 从 而 得 到 目 录 所 有 商 品 组 成 的 集 合 在 第 13 行 中 将 商 品 集 合 保 存 到 request 范 围 中 在 第 14 行 中 进 行 服 务 器 跳 转, 跳 转 到 显 示 所 有 商 品 页 面 5.9.5 开 发 显 示 所 有 商 品 的 JSP 程 序 在 查 询 所 有 商 品 Servlet 中 将 跳 转 到 显 示 所 有 商 品 页 面 中, 在 本 小 节 中 就 来 开 发 该 页 面, 在 这 里 开 发 使 用 JSTL 标 签 的 JSP 程 序 选 中 WebRoot 目 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New JSP(Advanced Templates) 命 令, 将 弹 出 使 用 高 级 模 板 创 建 JSP 程 序 的 界 面, 在 其 中 填 入 文 件 名, 如 图 5-44 所 示

43 图 5-44 创 建 显 示 商 品 JSP 程 序 单 击 Finish 按 钮, 将 完 成 JSP 程 序 的 创 建 因 为 在 其 中 要 使 用 到 JSTL 标 签, 所 以 在 page 指 令 下 给 出 如 下 taglic 指 令 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 然 后 在 body 标 记 中, 加 入 如 下 代 码 : 01 <table border="0" align="center"> 02 <tr> 03 <td> 商 品 名 称 </td> 04 <td> 商 品 原 价 </td> 05 <td> 折 扣 价 格 </td> 06 </tr> 07 <c:foreach var="commodity" items="${requestscope.commoditylist}" 08 varstatus="stus"> 09 <tr> 10 <td><c:out value="${commodity.name}"></c:out></td> 11 <td><del><c:out value="${commodity.price}"></c:out></del></td> 12 <td><font color="red"> 13 <c:out value="${commodity.agio}"></c:out></font></td> 14 </tr> 15 </c:foreach> 16 </table> 技 巧 : 使 用 JSTL 标 签 后, 对 标 签 是 不 能 够 进 行 界 面 化 设 置 的 例 如 第 11 行 的 删 除 线 标 记 不 能 够 直 接 添 加, 但 是 我 们 可 以 在 其 中 先 测 试 文 字, 然 后 进 行 界 面 化 操 作 加 入 相 应 标 记 后, 再 使 用 JSTL 标 签 替 换 测 试 文 字

5.9.6 修 改 项 目 的 首 页 创 建 Java Web 项 目 后, 默 认 的 项 目 首 页 是 WebRoot 根 目 录 下 的 index.jsp JSP 程 序, 但 是 在 该 网 络 商 城 的 项 目 中 并 没 有 使 用 该 文 件, 所 以 要 修 改 项 目 的 首 页 打 开 WebRoot WEB-INF 目 录 下 的 web.xml 文 件, 选 择 编 辑 区 左 下 角 的 Design 选 项, 将 进 入 视 图 化 配 置 的 界 面 在 其 中 左 面, 选 择 welcome-file-list 节 点, 在 右 面 可 以 看 到 原 index.jsp 文 件, 选 中 它, 单 击 Remove 按 钮, 将 它 删 除 再 单 击 Add 按 钮, 将 弹 出 选 择 首 页 界 面, 如 图 5-45 所 示 图 5-45 首 页 设 置 在 其 中 选 择 AddCommodity.html 节 点, 也 就 是 录 入 商 品 页 面, 单 击 Finish 按 钮, 将 完 成 首 页 的 修 改 5.9.7 运 行 网 络 商 城 项 目 到 目 前 为 止, 我 们 的 网 络 商 城 项 目 已 经 开 发 完 成, 它 由 HTML 程 序 JSP 程 序 Servlet 程 序 和 Filter 过 滤 器 程 序 组 成, 完 成 录 入 商 品 和 显 示 所 有 商 品 两 个 功 能 在 本 节 中 就 来 看 一 下 如 何 发 布 和 运 行 该 项 目 在 Servers 界 面 中 选 择 Tomcat 6.x 服 务 器, 单 击 鼠 标 右 键, 选 择 Add Deployment 命 令, 将 弹 出 发 布 项 目 界 面, 填 入 store 项 目 后, 如 图 5-46 所 示

45 图 5-46 发 布 网 络 商 城 项 目 单 击 Finish 按 钮 将 完 成 项 目 的 发 布 再 次 选 中 Tomcat 6.x 服 务 器, 在 右 键 弹 出 菜 单 中, 选 择 Run Server 命 令, 将 开 始 运 行 服 务 器 启 动 服 务 器 完 成 后, 打 开 浏 览 器, 输 入 如 下 地 址 : http://localhost:8080/store/ 将 进 入 网 络 商 城 项 目 首 页, 也 就 是 录 入 商 品 页 面, 在 其 中 填 入 一 件 商 品, 运 行 结 果 如 图 5-47 所 示 图 5-47 录 入 商 品 页 面 单 击 录 入 商 品 按 钮, 将 执 行 录 入 商 品 的 Servlet 程 序, 然 后 自 动 跳 转 到 录 入 商 品 成 功 页 面, 如 图 5-48 所 示

图 5-48 录 入 成 功 页 面 单 击 显 示 所 有 商 品 超 链 接, 将 执 行 查 询 所 有 商 品 的 Servlet 程 序, 然 后 跳 转 到 显 示 所 有 商 品 的 页 面, 如 图 5-49 所 示 图 5-49 显 示 所 有 商 品 因 为 目 前 只 录 入 了 一 件 商 品, 所 以 页 面 中 只 有 计 算 机 书 这 一 件 商 品 信 息

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 6 章 进 行 Struts 开 发 Struts 是 流 行 最 早 和 最 广 的 实 现 Web 层 MVC 架 构 的 开 源 框 架 Struts 是 在 JSP 和 Servlet 技 术 的 基 础 上 开 发 出 来 的 框 架 技 术, 通 过 它 能 够 很 好 的 将 Web 程 序 进 行 分 层 操 作 目 前 Struts 存 在 两 个 版 本, 分 别 是 Struts 1.x 和 Struts 2, 这 两 个 版 本 之 间 有 很 大 的 区 别 在 本 书 中 将 使 用 两 章 来 分 别 讲 解 这 两 个 版 本, 本 章 先 来 讲 解 Struts 1.x 版 本 6.1 开 发 Struts 项 目 由 于 Struts 1.x 版 本 非 常 流 行, 所 以 当 MyEclipse 安 装 完 成 后 就 在 其 中 集 成 了 开 发 Struts 项 目 的 功 能, 而 且 是 非 常 强 大 的 在 本 节 中 就 先 来 看 一 下 在 MyEclipse 中 是 如 何 创 建 Struts 项 目 的 6.1.1 创 建 Web 项 目 Struts 是 一 种 Web 项 目 的 开 发 框 架, 所 以 仅 能 够 在 Java Web 项 目 中 使 用 在 MyEclipse 开 发 Struts 项 目 时, 是 要 基 于 基 本 的 Java Web 项 目 的, 所 以 我 们 要 首 先 创 建 一 个 基 本 的 Web 项 目 在 MyEclipse 的 菜 单 中, 选 择 File New Web Project 命 令, 将 弹 出 创 建 Java Web 项 目 的 界 面, 在 其 中 填 写 项 目 名 等 信 息 后, 如 图 6-1 所 示

图 6-1 创建普通 Web 项目 这里将本节将要创建的 Struts 项目命名为 FirstStruts 单击 Finish 按钮 将 完成基本 Web 项目的创建 6.1.2 加入 Struts 框架支持 给java web项目添加 struts框架支持. 创建基本的 Java Web 项目后 还不能进行 Struts 开发 还需要在其中加入 Struts 框 架支持 在包资源管理器中 选中要加入 Struts 框架支持的项目 这里选中 FirstStruts 项 目 在 MyEclipse 的菜单中 选择 MyEclipse Project Capabilities Add Struts Capabilities 命令 将弹出加入支持操作界面 如图 6-2 所示 图 6-2 加入 Struts 框架支持 其中 Struts config path 表示 Struts 配置文件的名称和所在目录 通常采用默认值 Struts specification 表示要加入 Struts 的版本 有三个版本可以选择 这里选择最 常用的 Struts 1.2 版本 ActionServlet name 表示 Struts 核心控制器配置的名称 通常 就采用默认的 action URL pattern 表示使用中心控制器对哪些请求进行处理 Base package for new classes 表示新建的 Action 和 ActionForm 的根包名 这里 填写 com.sanqing.struts Default application resources 表示用来输入 Struts 1 的默 认的资源文件名 它的位置默认就在 struts 包下 将单击 Finish 按钮将完成 Struts 框 架支持 说明 向普通项目中加入 Struts 支持 主要做的工作就是向项目加入 JAR 包 以 及给出 Struts 的配置文件 在 web.xml 中对核心控制器进行配置 这些操作也是可以 手动完成的 但是要相对复杂的多

3 6.1.3 认 识 Struts 项 目 结 构 创 建 Web 项 目 并 加 入 Struts 框 架 支 持 后, 将 在 包 资 源 管 理 器 中 多 出 一 个 新 项 目, 将 该 项 目 展 开, 如 图 6-3 所 示 图 6-3 Struts 项 目 结 构 其 中 com.sanqing.struts 就 是 Struts 程 序 的 根 包,Action 程 序 通 常 放 在 action 子 包 下,ActionForm 程 序 通 常 放 在 form 子 包 下 在 Struts 1.2 Libraries 节 点 下 有 Struts 框 架 相 关 的 JAR 包, 这 是 在 MyEclipse 中, 在 实 际 项 目 目 录 中, 这 些 JAR 包 都 保 存 在 lib 目 录 下 在 WebRoot WEB-INF 目 录 下, 有 多 个 文 件, 其 中 web.xml 是 Web 项 目 中 的 配 置 文 件, 在 前 面 的 普 通 项 目 中 就 见 过 Struts-config.xml 是 Struts 框 架 的 配 置 文 件, 在 其 中 可 以 对 Action 和 ActionForm 等 程 序 进 行 配 置 首 先 打 开 web.xml 文 件, 其 中 部 分 代 码 如 下 : 01 <servlet> 02 <servlet-name>action</servlet-name> 03 <servlet-class>org.apache.struts.action.actionservlet</servlet-class> 04 <init-param> 05 <param-name>config</param-name> 06 <param-value>/web-inf/struts-config.xml</param-value> 07 </init-param>

08 <init-param> 09 <param-name>debug</param-name> 10 <param-value>3</param-value> 11 </init-param> 12 <init-param> 13 <param-name>detail</param-name> 14 <param-value>3</param-value> 15 </init-param> 16 <load-on-startup>0</load-on-startup> 17 </servlet> 18 <servlet-mapping> 19 <servlet-name>action</servlet-name> 20 <url-pattern>*.do</url-pattern> 21 </servlet-mapping> 其 中 第 3 行 中 的 org.apache.struts.action.actionservlet 就 是 Struts 中 的 核 心 控 制 器 类, 从 名 称 和 配 置 上 可 以 看 出, 它 是 一 个 Servlet 在 其 中 配 置 核 心 控 制 器 的 名 称 为 action, 在 第 20 行 配 置 它 的 URL 为 *.do, 表 示 所 有 以.do 结 尾 的 请 求 都 有 中 心 控 制 器 处 理, 这 些 信 息 都 是 在 加 入 Struts 框 架 支 持 页 面 中 配 置 的 注 意 : 从 这 里 也 可 以 看 出, 不 管 是 什 么 框 架, 都 是 离 不 开 基 本 的 JSP 和 Servlet 程 序 的 在 框 架 中 仅 仅 是 对 操 作 进 行 了 封 装, 使 开 发 更 简 单 从 第 4 行 到 第 16 行 是 对 核 心 控 制 器 中 的 初 始 参 数 进 行 配 置 config 参 数 表 示 以 相 对 路 径 的 方 式 给 出 Struts 配 置 文 件 的 名 称 和 目 录 位 置, 它 的 默 认 值 就 是 /WEB-INF/struts-config.xml, 所 以 这 里 也 可 以 不 配 置 debug 表 示 日 志 记 录 的 详 细 程 度 级 别, 默 认 是 0, 表 示 最 少 记 录 detail 表 示 设 置 Digester 的 记 录 级 别, 默 认 也 是 0 <load-on-startup> 标 记 配 置 的 是 核 心 控 制 器 在 服 务 器 中 的 加 载 次 序, 数 值 越 小, 越 先 加 载 然 后 打 开 Struts-config.xml, 它 是 Struts 的 配 置 文 件, 部 分 代 码 为 : 01 <struts-config> 02 <data-sources /> 03 <form-beans /> 04 <global-exceptions /> 05 <global-forwards /> 06 <action-mappings /> 07 <message-resources parameter="com.sanqing.struts.applicationresources" /> 08 </struts-config> 当 开 发 Struts 相 关 的 程 序 后, 需 要 在 该 配 置 文 件 中 进 行 配 置, 具 体 配 置 方 法 在 后 面 的 讲 解 中 将 会 学 习 到 其 中 第 7 行 中 是 对 Struts 的 资 源 文 件 进 行 配 置, 它 是 加 入 Struts 框 架 支 持 时 自 动 加 入 的

5 6.2 开 发 Struts 项 目 中 的 相 关 程 序 因 为 Struts 是 一 种 MVC 框 架, 所 以 每 一 层 都 有 相 应 的 程 序 构 成 在 一 个 Struts 项 目 中 通 常 由 JSP 页 面 Action ActionForm 和 ActionForward 等 程 序 组 成 在 MyEclipse 中 有 多 种 创 建 这 些 程 序 的 方 法, 我 们 主 要 讲 解 其 中 使 用 最 多 的 方 式, 本 节 先 来 讲 解 通 过 新 建 向 导 的 形 式 创 建 6.2.1 创 建 Struts 项 目 中 的 JSP 页 面 在 Struts 项 目 中, 应 用 于 显 示 层 的 程 序 也 是 JSP 程 序, 而 且 在 其 中 也 可 以 使 用 普 通 的 JSP 程 序 和 JSTL 标 签, 但 是 通 常 不 这 样 做, 而 是 在 JSP 程 序 中 使 用 Struts 自 定 义 的 标 签 在 包 资 源 管 理 器 的 FirstStruts 项 目 中, 选 中 要 创 建 JSP 页 面 的 目 录, 这 里 选 择 WebRoot 目 录 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New JSP(Advanced Templates) 命 令, 将 弹 出 创 建 JSP 程 序 页 面, 在 其 中 输 入 JSP 程 序 名 称 和 选 择 Struts 模 板 后, 如 图 6-4 所 示 图 6-4 创 建 Struts 项 目 中 的 JSP 程 序 在 Templates to use 中 选 择 Standard JSP using Struts 1.2/1.3 选 项, 这 就 是 Struts 项 目 中 JSP 程 序 所 使 用 的 模 板 单 击 Finish 按 钮, 将 完 成 JSP 程 序 的 创 建, 并 且 在 编 辑 区 中 打 开 该 程 序 和 前 面 创 建 普 通 JSP 程 序 所 不 同 的 就 是, 在 page 指 令 加 入 了 4 行 定 义 标 签 的 taglib, 具 体 代 码 如 下 所 示 <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %> <%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>

这 些 就 是 Struts 中 的 标 签 库 其 中 bean 标 签 主 要 用 来 创 建 bean 和 访 问 bean 及 其 属 性, 并 且 也 能 够 根 据 cookies headers 和 parameters 的 值 创 建 相 关 bean html 标 签 主 要 用 来 创 建 页 面 中 的 表 单 及 其 表 单 中 的 元 素 login 标 签 中 主 要 包 括 流 程 控 制 相 关 的 标 签, 这 和 前 面 讲 解 的 JSTL 中 的 流 程 控 制 标 签 非 常 相 似 的 tiles 标 签 主 要 用 来 在 页 面 中 创 建 tiles 样 式 其 中 使 用 最 多 的 就 是 html 标 签 和 login 标 签 在 编 辑 区 的 上 半 部 分 中, 也 就 是 界 面 化 创 建 页 面 的 部 分 中, 其 中 具 有 Struts-Basic 和 Struts-Form 两 个 选 项 其 中 在 Struts-Form 中 包 含 着 创 建 表 单 及 其 元 素 的 节 点, 单 击 Form 节 点, 将 弹 出 创 建 表 单 的 界 面, 输 入 URL 后, 如 图 6-5 所 示 图 6-5 创 建 Struts 表 单 注 意 : 创 建 表 单 时 填 写 的 提 交 URL 为 login.do, 这 和 访 问 Servlet 不 同 的 但 是 在 一 些 程 序 中 提 交 URL 并 没 有 以.do 结 尾, 是 因 为 在 其 中 使 用 的 是 Struts 标 签, 在 框 架 中 会 自 动 给 加 上 如 果 使 用 的 普 通 HTML 标 记, 那 就 必 须 加 上.do 单 击 Finish 按 钮, 将 完 成 表 单 的 创 建 将 鼠 标 放 在 表 单 中, 单 击 Struts-Form 选 项 中 的 Text Field 节 点, 将 弹 出 创 建 文 本 框 的 界 面, 如 图 6-6 所 示

7 图 6-6 创 建 用 户 名 文 本 框 其 中 Attribute name 是 文 本 框 的 名 称, 它 对 应 着 文 本 框 标 签 的 name 属 性 而 Property 也 可 以 说 是 文 本 框 的 名 称, 只 是 它 和 ActionForm 中 的 属 性 相 对 应, 例 如 这 里 我 们 填 写 username, 则 在 ActionForm 应 该 也 有 一 个 名 称 为 username 的 属 性 接 下 来 的 三 个 选 项 分 别 表 示 默 认 值 文 本 框 长 度 和 最 大 输 入 字 符 数 单 击 Finish 按 钮, 则 用 于 输 入 用 户 名 的 文 本 框 已 经 创 建 完 成 然 后 在 Struts-Form 选 项 中 再 单 击 Password 节 点, 将 弹 出 创 建 密 码 框 的 界 面, 它 是 和 创 建 文 本 框 非 常 类 似 的, 这 里 就 不 再 给 出 界 面, 通 过 它 创 建 一 个 用 于 输 入 密 码 的 密 码 框 最 后 Struts-Form 选 项 中 单 击 Button 节 点, 将 弹 出 创 建 按 钮 的 界 面, 在 其 中 输 入 相 关 信 息 后, 如 图 6-7 所 示 图 6-7 创 建 提 交 按 钮 其 中 Label/Value 表 示 提 交 按 钮 上 的 内 容 Button type 表 示 创 建 的 按 钮 类 型, 如 果 在 其 中 选 择 Button 选 择, 则 创 建 的 仅 是 普 通 按 钮 如 果 想 创 建 提 交 按 钮, 需 要

选 择 Submit 选 项 单 击 Finish 按 钮, 将 完 成 提 交 按 钮 的 创 建 通 过 视 图 化 的 形 式 创 建 表 单 后, 查 看 JSP 程 序 的 代 码, 可 以 看 到 多 出 了 如 下 代 码 : 01 <html:form method="post" action="login.do"> 02 用 户 名 <html:text value=" 在 这 里 输 入 用 户 名 " property="username" 03 name="username"></html:text><br> 04 密 码 <html:password redisplay="true" value=" 在 这 里 输 入 密 码 " 05 property="password" name="password"></html:password><br> 06 <html:submit value=" 登 录 " property="form"></html:submit> 07 </html:form> 注 意 : 本 代 码 是 手 动 做 的 代 码 格 式 调 整, 因 为 在 MyEclipse 的 编 辑 区 的 右 键 弹 菜 单 中, 选 择 Source Format 命 令 进 行 的 调 整 并 不 是 规 范 的 6.2.2 开 发 ActionForm 程 序 ActionForm 是 Struts 项 目 中 重 要 的 组 成 程 序 之 一 在 AcitonForm 中 可 以 完 成 对 属 性 的 接 收, 并 且 还 可 以 对 属 性 进 行 验 证 在 本 小 节 中 就 来 看 一 下 在 MyEclipse 中 如 何 创 建 ActionForm 程 序 在 Struts 项 目 中, 通 常 将 actionform 单 独 放 在 一 个 包 中 在 创 建 Struts 项 目 时, 已 经 创 建 了 com.sanqing.struts 根 包 名, 现 在 在 该 包 下 创 建 form 子 包, 这 就 是 用 于 存 放 ActionForm 的 包 选 中 form 子 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令, 将 弹 出 选 择 创 建 程 序 的 界 面, 在 其 中 选 择 MyEclipse Web-Struts Struts 1.2 节 点, 界 面 如 图 6-8 所 示 图 6-8 Struts 项 目 中 可 以 创 建 的 程 序 在 其 中 选 择 Struts 1.2 Form 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 ActionForm 程 序 的 界 面, 填 写 相 应 信 息 后, 如 图 6-9 所 示

9 图 6-9 创 建 ActionForm 程 序 其 中 Config/Module 表 示 在 哪 一 个 文 件 中 对 ActionForm 进 行 配 置 Use case 表 示 ActionForm 的 基 础 用 例, 该 选 项 可 以 不 填, 如 果 填 写, 则 下 面 Name 和 Form type 选 项 将 自 动 填 写 Name 表 示 ActionForm 的 名 称, 对 ActionForm 进 行 配 置 时 将 用 到 该 名 称 Form Impl 表 示 ActionForm 的 类 型, 其 中 New FormBean 选 项 表 示 新 建 该 ActionForm; Existing FormBean 选 项 表 示 使 用 已 经 存 在 的 ActionForm; Dynamic FormBean 选 项 表 示 使 用 动 态 ActionForm 这 里 选 择 New FormBean 选 项 来 创 建 一 个 新 的 ActionForm Superclass 表 示 ActionForm 继 承 的 父 类, 这 里 可 以 采 用 默 认 的 父 类, 也 可 以 在 其 中 选 择 Form type 表 示 ActionForm 的 包 含 包 名 的 完 整 类 名 Form Properties 选 项 卡 表 示 新 创 建 的 ActionForm 中 有 哪 些 属 性, 单 击 Add 按 钮, 将 弹 出 创 建 属 性 的 界 面, 如 图 6-10 所 示

图 6-10 创 建 属 性 其 中 Name 表 示 属 性 的 名 称, 这 里 要 和 表 单 中 元 素 的 property 属 性 相 对 应 上 Type 表 示 属 性 的 类 型, 默 认 是 String 字 符 串 类 型 JSP input type 表 示 JSP 页 面 中 表 单 元 素 的 类 型 通 过 该 界 面 添 加 username 和 password 两 个 属 性 创 建 ActionForm 程 序 界 面 中 的 Methods 选 项 卡 表 示 在 ActionForm 中 创 建 哪 些 方 法, 这 些 方 法 都 是 重 写 父 类 中 的 方 法 默 认 选 中 validate 验 证 方 法 和 reset 重 置 方 法, 其 中 validate 验 证 方 法 用 于 对 表 单 元 素 值 的 验 证, 它 的 使 用 是 比 较 多 的 注 意 : 使 用 validate 方 法 进 行 验 证 属 于 服 务 器 验 证, 该 验 证 可 以 由 页 面 中 的 JavaScript 完 成, 但 是 JavaScript 容 易 被 屏 蔽 掉, 所 以 服 务 器 验 证 是 非 常 必 要 的 JSP 选 项 卡 表 示 是 否 创 建 和 该 ActionForm 相 对 应 的 JSP 页 面, 如 果 选 中 其 中 的 选 项, 将 自 动 在 填 写 的 位 置 中 创 建 JSP 程 序 因 为 我 们 已 经 创 建 了 JSP 程 序, 所 以 这 里 保 持 默 认 不 选 择 的 状 态 对 这 些 信 息 设 置 后, 单 击 创 建 ActionForm 程 序 界 面 中 的 Finish 按 钮, 将 完 成 ActionForm 的 创 建 打 开 位 于 com.sanqing.struts.form 包 下 的 LoginForm 程 序, 可 以 看 到 自 动 生 成 的 ActionForm, 它 的 重 要 代 码 如 下 所 示 : 01 package com.sanqing.struts.form; 02 import javax.servlet.http.httpservletrequest; 03 import org.apache.struts.action.actionerrors; 04 import org.apache.struts.action.actionform; 05 import org.apache.struts.action.actionmapping; 06 public class LoginForm extends ActionForm { 07 private String username; 08 private String password; 09 public ActionErrors validate(actionmapping mapping, 10 HttpServletRequest request) { 11 return null; 12 } 13 public void reset(actionmapping mapping, HttpServletRequest request) { 14 } 15 public String getusername() {

11 16 return username; 17 } 18 public void setusername(string username) { 19 this.username = username; 20 } 21 public String getpassword() { 22 return password; 23 } 24 public void setpassword(string password) { 25 this.password = password; 26 } 27 } 其 中 第 7 行 和 第 8 行 定 义 了 表 示 用 户 名 和 密 码 的 属 性, 从 第 15 行 开 始 依 次 为 这 两 个 属 性 定 义 了 Getter 和 Setter 方 法 第 9 行 定 义 了 validate 验 证 方 法, 在 方 法 中 可 以 输 入 用 于 验 证 的 相 关 代 码 第 13 行 定 义 了 reset 重 置 方 法, 可 以 对 属 性 进 行 重 置 操 作 自 动 生 成 ActionForm 的 同 时, 还 会 在 struts-config.xml 文 件 中 对 ActionForm 进 行 配 置, 配 置 代 码 为 : 01 <form-beans > 02 <form-bean name="loginform" type="com.sanqing.struts.form.loginform" /> 03 </form-beans> 其 中 第 2 行 的 type 属 性 指 定 的 就 是 ActionForm 的 完 整 类 名,name 属 性 就 是 为 ActionForm 起 的 名 称, 它 是 在 创 建 界 面 中 Name 选 项 指 定 的 当 在 Action 中 使 用 ActionForm 时, 将 使 用 到 该 名 称 6.2.3 开 发 Action 程 序 Action 是 Struts 项 目 中 最 核 心 的 程 序 在 Action 程 序 中 调 用 ActionForm, 从 而 获 取 到 通 过 ActionForm 获 取 到 的 属 性 值 然 后 使 用 属 性 值 调 用 业 务 逻 辑 层, 最 后 根 据 业 务 逻 辑 层 的 返 回 值 进 行 跳 转 从 功 能 上 可 以 看 到,Action 程 序 是 和 Servlet 程 序 非 常 相 似 的, 它 们 都 做 控 制 层 在 Struts 项 目 中, 通 常 将 Action 程 序 单 独 放 在 一 个 包 下 在 com.sanqing.struts 根 包 下, 创 建 一 个 名 称 为 action 的 子 包 选 中 action 子 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令, 将 弹 出 选 择 创 建 程 序 的 界 面, 在 其 中 选 择 MyEclipse Web-Struts Struts 1.2 struts 1.2 Action 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 Action 程 序 的 界 面, 如 图 6-11 所 示

图 6-11 创 建 Action 程 序 其 中 Config/Module 和 Use case 两 个 选 项 是 和 创 建 ActionForm 界 面 中 的 选 项 相 同 的, 作 用 也 相 同 Path 表 示 访 问 该 Action 使 用 的 访 问 路 径, 当 前 Action 的 完 整 访 问 路 径 为 http://localhost:8080/ FirstStruts/login.do, 这 里 需 要 注 意 不 要 忘 记.do Action Type 表 示 新 创 建 Action 的 类 型, 通 常 采 用 默 认 的 Type 选 项 在 Action Impl 中 有 两 个 选 项, Create new Action class 选 项 表 示 创 建 新 Action, Use existing Action class 选 项 表 示 使 用 已 经 存 在 的 Action Superclass 表 示 创 建 Action 继 承 的 父 类 Type 表 示 新 创 建 Action 的 全 称 类 名 技 巧 : 根 据 Action 继 承 父 类 不 同, 则 Action 的 种 类 不 同, 最 简 单 的 Action 继 承 的 是 org.apache.struts.action.action 类 除 了 最 基 本 的 Action 外, 还 有 动 态 Action 等 使 用 动 态 Action 可 以 避 免 Action 的 数 量 膨 胀, 从 而 使 多 种 操 作 定 义 在 一 个 Action 中 在 界 面 的 下 半 部 分 中, 有 5 个 选 项 卡 Form 选 项 卡 是 对 Action 中 使 用 的 AtionForm 进 行 设 置, 这 些 都 对 应 配 置 文 件 中 的 属 性, 其 中 Attribute 指 定 ActionForm 的 名 称, Scope 指 定 作 用 范 围, Validate Form 表 示 是 否 使 用 ActionForm 中 的 验 证 方 法, Input Source 表 示 验 证 失 败 后 返 回 的 页 面 在 Parameter 选 项 卡 中 用 来 设 置 Action 的 参 数, 当 使 用 DispatchAction 等 特 殊 Action 时 才 会 使 用 到, 对 于 普 通 的 Action 来 说 是 没 有 作 用 的 在 Methods 选 项 卡 中, 设 置 了 在 Action 中 定 义 哪 些 方 法, 这 里 采 用 默 认 的 execute 方 法 就 可 以, 它 也 是 Action

13 的 主 体 方 法, 功 能 代 码 都 定 义 在 该 方 法 中 在 Forwards 选 项 卡 中 用 来 设 置 Action 中 使 用 的 ActionForward, 也 就 是 执 行 的 页 面 跳 转 单 击 Add 按 钮, 将 弹 出 添 加 ActionForward 的 界 面, 如 图 6-11 所 示 图 6-11 添 加 跳 转 通 过 这 个 界 面 首 先 添 加 登 录 成 功 的 跳 转, 在 其 中 Name 中 输 入 success, 在 Path 中 输 入 /loginsuccess.jsp, 它 表 示 当 返 回 success 字 符 串 时, 跳 转 到 登 录 成 功 页 面 使 用 同 样 的 方 式, 添 加 登 录 失 败 跳 转, 失 败 后 跳 转 回 登 录 页 面 在 Exceptions 选 项 卡 中, 是 对 Action 中 的 异 常 进 行 添 加 单 击 其 中 的 Add 按 钮, 将 弹 出 添 加 异 常 的 界 面, 如 图 6-12 所 示 图 6-12 添 加 异 常 其 中 Exception type 表 示 异 常 的 类 型, 这 里 可 以 是 API 中 已 定 义 的 异 常, 也 可 以 是 自 定 义 异 常 Exception key 表 示 异 常 指 定 的 key 键 值 Exception path 指 定 发 生 该 异 常 后 跳 转 到 的 页 面 在 Action 中, 异 常 是 可 以 不 添 加 的, 具 体 异 常 的 创 建 在 后 面 还 会 讲 解 到 回 到 创 建 Action 程 序 界 面, 单 击 Finish 按 钮 将 完 成 创 建 在 编 辑 区 中 打 开 自 动 创 建 Action 的 程 序, 其 代 码 为 : 01 package com.sanqing.struts.action; 02 import javax.servlet.http.httpservletrequest; 03 import javax.servlet.http.httpservletresponse;

04 import org.apache.struts.action.action; 05 import org.apache.struts.action.actionform; 06 import org.apache.struts.action.actionforward; 07 import org.apache.struts.action.actionmapping; 08 import com.sanqing.struts.form.loginform; 09 public class LoginAction extends Action { 10 public ActionForward execute(actionmapping mapping, ActionForm form, 11 HttpServletRequest request, HttpServletResponse response) { 12 LoginForm loginform = (LoginForm) form; 13 return null; 14 } 15 } 其 中 第 10 行 就 是 Action 的 主 方 法, 所 有 的 功 能 代 码 都 将 放 置 在 该 方 法 中 在 第 12 行 中 使 用 到 了 LoginForm, 它 就 是 我 们 在 上 一 小 节 中 创 建 的 ActionForm 在 LoginForm 中 保 存 了 提 交 表 单 中 的 用 户 名 和 密 码 属 性 值, 获 取 这 些 值 后 就 可 以 调 用 相 应 的 方 法, 然 后 根 据 不 同 的 调 用 结 果, 跳 转 到 不 同 的 页 面 注 意 : 这 里 我 们 只 是 将 自 动 生 成 的 代 码 给 出, 并 没 有 加 入 任 何 操 作 的 代 码 如 果 想 完 成 上 述 功 能 需 要 加 入 相 应 的 代 码 同 时 生 成 Action 的 同 时, 还 会 同 时 在 Struts 配 置 文 件 中 对 该 Action 进 行 配 置, 配 置 代 码 如 下 : 01 <action-mappings > 02 <action 03 attribute="loginform" 04 input="login.jsp" 05 name="loginform" 06 path="/login" 07 scope="request" 08 type="com.sanqing.struts.action.loginaction"> 09 <set-property property="cancellable" value="true" /> 10 <forward name="errer" path="/login.jsp" /> 11 <forward name="success" path="/loginsuccess.jsp" /> 12 </action> 13 </action-mappings> 其 中 使 用 的 属 性 都 是 和 前 面 界 面 操 作 相 对 应 的 例 如 第 3 行 指 定 Action 中 使 用 的 ActionForm, 第 6 行 的 path 属 性 指 定 该 Action 的 访 问 地 址 第 10 行 和 第 11 行 分 别 定 义 了 登 陆 成 功 跳 转 和 登 录 失 败 跳 转 6.2.4 开 发 全 局 ActionForward 跳 转 学 习 上 面 的 三 种 Struts 框 架 中 的 程 序, 对 于 大 部 分 项 目 来 说 已 经 足 够 了, 但 是 它 们 并 不 是 Struts 框 架 的 全 部 程 序 在 本 小 节 中 将 学 习 Struts 框 架 中 的 ActionForward, 在 前 面 学 习 Action 时, 已 经 看 到 它 的 主 方 法 的 返 回 值 就 是 ActionForward, 它 通 常 使 用 ActionMapping 调 用 findforward 方 法 获 取 ActionForward, 这 里 完 全 也 可 以 通 过 new 的

15 方 法 创 建 ActionForward 对 象 然 后 返 回 但 是 这 并 不 是 本 小 节 讲 解 的 重 点, 本 小 节 主 要 讲 解 如 何 创 建 全 局 ActionForward 注 意 :ActionForward 和 前 面 讲 解 的 ActionForm 和 Acton 有 很 大 不 同, 它 并 不 是 一 个 程 序, 而 仅 仅 是 Struts 配 置 文 件 中 的 一 个 配 置 全 局 ActionForward 并 不 是 必 须 的, 但 是 在 某 些 功 能 中, 使 用 全 局 ActionForward 可 以 节 省 很 多 代 码 例 如 在 聊 天 室 网 站 中, 是 要 求 用 户 必 须 登 录 才 能 浏 览 的, 这 时 候 就 应 该 使 用 全 局 ActionForward 跳 转, 不 管 用 户 浏 览 网 站 中 的 哪 一 个 页 面, 判 断 没 有 登 录, 就 会 跳 转 到 登 录 页 面 在 选 择 创 建 Struts 程 序 的 界 面 中, 选 择 MyEclipse Web-Struts Struts 1.2 struts 1.2 ForWard 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 ActionForward 的 界 面, 如 图 6-13 所 示 图 6-13 创 建 ActionForward 其 中 Config/Module 表 示 在 哪 一 个 文 件 中 进 行 配 置 Forward Scope 表 示 ActionForward 的 范 围, 其 中 Global Forward 表 示 全 局 的, 也 就 是 对 所 有 Action 起 作 用 ; Local Avction Forward 表 示 局 部 的, 如 果 选 择 该 项 时, 需 要 指 定 作 用 在 哪 一 个 Action 中 Name 表 示 ActionForward 的 名 称, 它 和 Action 中 返 回 的 字 符 相 对 应 Path 表 示 全 局 跳 转 的 URL 地 址 Redirect 表 示 是 否 重 定 向 操 作, 对 于 全 局 跳 转 而 言, 该 选 项 通 常 是 选 中 的 单 击 Finish 按 钮, 将 完 成 全 局 ActionForward 的 创 建 在 Struts 的 配 置 文 件 中, 将 多 出 一 条 全 局 跳 转 的 配 置, 其 代 码 如 下 : 01 <global-forwards > 02 <forward 03 name="login"

04 path="/login.jsp" 05 redirect="true" /> 06 </global-forwards> 如 果 有 多 条 全 局 跳 转, 都 将 配 置 在 <global-forwards > 标 记 对 中 但 在 Action 中 返 回 login 时, 虽 然 没 有 定 义 局 部 跳 转, 但 是 会 使 用 该 全 局 跳 转, 从 而 跳 转 到 登 录 页 面 6.2.5 开 发 Struts 中 的 异 常 在 Struts 项 目 中, 有 两 种 异 常 处 理 的 方 法, 分 别 是 编 程 式 异 常 和 声 明 式 异 常 在 编 程 式 异 常 处 理 中 是 通 过 手 动 的 编 写 try-catch 语 句, 根 据 获 取 的 不 同 异 常 执 行 不 同 的 跳 转, 它 不 是 Struts 特 有 的 声 明 式 异 常 是 Struts 框 架 特 有 的, 在 代 码 中 使 用 throw 语 句 抛 出 异 常, 该 异 常 将 抛 出 Struts 框 架, 然 后 在 Struts 框 架 中 进 行 处 理 声 明 式 异 常 主 要 是 在 Struts 配 置 文 件 中 进 行 配 置 声 明 在 进 行 声 明 式 异 常 操 作 前, 要 进 行 一 些 准 备 工 作 如 果 项 目 中 需 要 的 异 常 在 API 中 并 不 存 在, 这 时 候 要 进 行 自 定 义 异 常 例 如 这 里 定 义 一 个 密 码 错 误 异 常, 其 代 码 为 : 01 package com.sanqing.struts.exception; 02 public class PasswordErrorException extends Exception { 03 public PasswordErrorException() { 04 super(); 05 } 06 public PasswordErrorException(String message) { 07 super(message); 08 } 09 } 在 该 自 定 义 异 常 中 除 了 无 参 构 造 函 数 外, 还 定 义 了 拥 有 字 符 串 参 数 的 构 造 函 数, 从 而 能 够 传 递 异 常 信 息 声 明 式 异 常 中 的 信 息 并 不 是 手 动 给 出 的, 而 是 定 义 在 一 个 资 源 文 件 中, 通 过 键 值 对 的 方 式 获 取 该 资 源 文 件 就 是 定 义 在 根 包 下 的 ApplicationResources.properties 文 件, 打 开 该 文 件, 在 编 辑 区 中 有 两 种 视 图 方 式, 在 左 下 角 选 择 Properties 选 项, 将 可 以 看 到 界 面 视 图 单 击 Add 按 钮, 将 弹 出 添 加 资 源 信 息 的 界 面, 添 加 后, 界 面 如 图 6-14 所 示

17 图 6-14 添 加 资 源 信 息 单 击 Finish 按 钮, 将 完 成 资 源 信 息 的 添 加 保 存 后, 选 择 编 辑 区 左 下 角 的 Source 选 项, 将 可 以 看 到 多 出 了 如 下 一 行 信 息 password=password is errer 经 过 上 面 两 步 的 操 作, 我 们 就 可 以 继 续 来 进 行 声 明 式 异 常 的 开 发 了 在 选 择 创 建 Struts 程 序 的 界 面 中, 选 择 MyEclipse Web-Struts Struts 1.2 struts 1.2 Exception 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 声 明 式 异 常 的 界 面, 如 图 6-15 所 示 图 6-15 声 明 式 异 常 其 中 Action scope 表 示 异 常 的 处 理 范 围, 单 击 Browse 按 钮 可 以 选 择 作 用 在 哪 一 个 Action 中, 如 果 不 填, 则 定 义 一 个 全 局 异 常, 这 里 我 们 选 择 全 局 Exception key 表 示 异 常 对 应 的 资 源 键, 也 就 是 资 源 文 件 中 等 号 前 面 的 内 容 Exception type 表 示 异

常 类 型, 这 里 选 择 自 定 义 的 密 码 错 误 异 常 Exception path 表 示 当 发 生 异 常 后 跳 转 的 页 面 Scope 表 示 异 常 的 作 用 范 围, 可 以 选 择 request 或 者 session, 默 认 是 request Exception handler 表 示 Struts 框 架 中 进 行 异 常 处 理 的 类, 使 用 界 面 创 建 时 会 自 动 给 出 默 认 值 单 击 Finish 按 钮, 将 完 成 全 局 声 明 异 常 的 创 建 在 Struts 的 配 置 文 件 中, 将 多 出 声 明 式 异 常 的 代 码, 具 体 代 码 如 下 : 01 <global-exceptions > 02 <exception 03 key="password" 04 path="/loginerrer.jsp" 05 type="com.sanqing.struts.exception.passworderrorexception" /> 06 </global-exceptions> 进 行 如 上 配 置 后, 当 Struts 项 目 抛 出 PasswordErrorException 异 常 后, 将 自 动 跳 转 到 loginerrer.jsp, 并 且 在 该 页 面 中 可 以 将 资 源 文 件 中 password 对 应 的 内 容 输 出 说 明 : 在 实 际 开 发 中, 编 程 式 异 常 和 声 明 式 异 常 都 是 会 被 用 到 的 编 程 式 异 常 更 容 易 理 解, 因 为 完 成 时 Java 基 本 语 法 中 的 内 容 而 声 明 式 异 常 在 代 码 量 上 更 少, 更 简 单 6.2.6 同 时 创 建 JSP+ActionForm+Action 程 序 在 Struts 项 目 中, 最 重 要 的 三 种 程 序 就 是 JSP 页 面 程 序 ActionForm 程 序 和 Action 程 序, 它 们 是 紧 密 结 合 在 一 起 的 所 以 在 MyEclipse 中 定 义 了 同 时 创 建 这 三 种 程 序 的 选 项, 在 开 发 中 通 常 使 用 该 选 项 进 行 创 建 只 所 以 把 该 内 容 放 在 最 后 来 讲 解, 是 因 为 它 要 借 助 前 面 很 多 的 内 容 在 选 择 创 建 Struts 程 序 的 界 面 中, 选 择 MyEclipse Web-Struts Struts 1.2 struts 1.2 Form,Action & JSP 选 项, 单 击 Next 按 钮, 将 首 先 弹 出 创 建 ActionForm 的 界 面, 该 界 面 是 和 图 6-9 相 同 的, 这 里 再 创 建 一 个 用 于 注 册 的 ActionForm,, 如 图 6-16 所 示

19 图 6-16 创 建 注 册 ActionForm 选 择 其 中 的 JSP 选 项 卡, 选 中 Create JSP form 选 项, 然 后 输 入 JSP 程 序 地 址, 如 图 6-17 所 示 图 6-17 同 时 创 建 JSP 程 序 所 示 在 创 建 ActionForm 界 面 中 单 击 Next 按 钮 将 进 入 到 创 建 Action 的 界 面, 如 图 6-18

图 6-18 创 建 注 册 Action 该 界 面 中 的 信 息 都 是 自 动 生 成 的, 其 中 会 根 据 ActionForm 的 名 称 生 成 对 应 的 Action 的 名 称 在 Form 选 项 卡 中 会 自 动 对 ActionForm 进 行 配 置 在 Forwards 选 项 卡 中 需 要 添 加 跳 转, 如 图 6-19 所 示 图 6-19 添 加 跳 转 在 创 建 注 册 Aciton 界 面 中, 单 击 Finish 按 钮 将 完 成 三 种 程 序 的 创 建 从 生 成 的 程 序 可 以 看 到, 使 用 这 种 方 式 创 建 的 ActionForm 和 Action 与 单 独 创 建 它 们 是 没 有 差 别 的 它 们 之 间 最 大 的 区 别 就 是 使 用 这 种 方 式 自 动 生 成 了 JSP 页 面, 其 中 重 要 代 码 为 : 01 <html:form action="/register"> 02 username : <html:text property="username"/> 03 <html:errors property="username"/><br/> 04 password : <html:text property="password"/>

21 05 <html:errors property="password"/><br/> 06 <html:submit/><html:cancel/> 07 </html:form> 可 以 看 到 自 动 生 成 的 代 码 是 非 常 规 范 的, 并 且 给 出 了 错 误 处 理 标 签 6.3 通 过 视 图 创 建 Struts 程 序 在 上 一 节 中, 已 经 学 习 了 通 过 界 面 化 的 创 建 方 式 开 发 了 Struts 项 目 最 重 要 的 几 种 程 序 在 MyEclipse 中, 不 但 集 成 了 该 功 能, 而 且 还 集 成 了 一 种 视 图 化 的 创 建 方 式, 这 种 方 式 给 人 的 感 觉 更 直 观, 更 能 看 出 程 序 之 间 的 关 系 6.3.1 认 识 视 图 操 作 界 面 打 开 Struts 的 配 置 文 件, 默 认 是 WebRoot WEB-INF 目 录 下 的 struts-config.xml 文 件 在 编 辑 区 中 如 果 打 开 的 是 代 码 形 式, 选 择 编 辑 区 左 下 角 的 Design 选 项, 将 以 视 图 的 形 式 打 开 该 程 序, 如 图 6-20 所 示 图 6-20 视 图 配 置 其 中 左 半 部 分 是 用 于 创 建 程 序 的 按 钮, 它 们 分 别 对 应 的 创 建 程 序 如 图 6-21 所 示

图 6-21 创 建 按 钮 在 编 辑 区 的 右 边, 是 用 于 显 示 已 有 程 序 的 画 布, 在 其 中 不 但 显 示 出 有 什 么 程 序, 而 且 还 会 显 示 它 们 之 间 的 关 系 在 画 布 中, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中 选 择 New 命 令, 将 出 现 多 个 选 项, 通 过 它 们 可 以 进 入 对 应 创 建 界 面, 从 而 创 建 相 对 应 的 程 序 6.3.2 通 过 视 图 创 建 程 序 这 里 我 们 通 过 Action 和 JSP 程 序 讲 解 如 何 使 用 本 节 中 所 讲 到 的 视 图 首 先 单 击 创 建 Action 的 按 钮, 然 后 进 入 画 布, 选 择 创 建 的 位 置, 再 次 单 击 鼠 标, 将 弹 出 创 建 Action 的 界 面, 在 其 中 输 入 相 应 信 息 后, 单 击 Finish 按 钮, 将 完 成 Action 的 操 作 在 画 布 中 将 出 现 该 Action, 如 图 6-22 所 示 图 6-22 视 图 创 建 Action 在 该 Action 视 图 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Properties 命 令, 将 出 现 弹 出 创 建 Action 界 面, 在 其 中 可 以 对 原 有 信 息 进 行 修 改 双 击 Action 视 图 可 以 打 开 该 Action 的 代 码 创 建 完 Action 后, 再 来 创 建 一 个 JSP 程 序 单 击 创 建 JSP 程 序 的 按 钮, 同 样 进 入 画 布 后 单 击 鼠 标, 将 弹 出 创 建 JSP 程 序 的 界 面, 在 其 中 输 入 文 件 名 为 view.jsp, 单 击 Finish 按 钮 将 完 成 JSP 程 序 的 创 建, 如 图 6-23 所 示

23 图 6-23 视 图 创 建 JSP 对 该 视 图 同 样 能 够 进 行 Action 视 图 的 操 作, 可 以 对 它 进 行 修 改 和 打 开 代 码 6.3.3 建 立 程 序 间 连 接 创 建 Action 和 JSP 程 序 后, 就 可 以 在 这 两 个 程 序 之 间 建 立 连 接 单 击 建 立 连 接 按 钮, 在 画 布 中, 首 先 单 击 Action 视 图, 然 后 单 击 JSP 视 图, 将 弹 出 建 立 ActionForward 的 界 面, 如 图 6-24 所 示 图 6-24 建 立 程 序 间 连 接 其 中 只 需 要 填 写 Name 选 项, 单 击 Finish 按 钮 完 成 程 序 间 的 连 接 在 画 布 中 将 把 两 个 程 序 建 立 连 接, 如 图 6-25 所 示 图 6-25 建 立 连 接 后 其 中 success 就 是 界 面 中 配 置 的, 表 示 当 Action 中 返 回 seccess 时, 跳 转 到 view.jsp 页 面 进 行 该 操 作 后, 会 在 Struts 配 置 文 件 中 进 行 相 应 的 配 置

6.4 快 速 搭 建 论 坛 项 目 后 台 在 实 际 开 发 中, 每 一 个 系 统 项 目 都 要 有 一 个 后 台, 管 理 员 在 后 台 中 进 行 管 理 在 本 节 中 将 开 发 一 个 论 坛 系 统, 管 理 员 将 对 论 坛 中 的 主 题 进 行 管 理, 包 括 发 表 主 题, 查 看 已 有 主 题 删 除 主 题 等 说 明 : 开 发 具 体 程 序 之 前, 要 首 先 创 建 一 个 Java Web 项 目, 我 们 给 它 取 名 为 BBS, 它 就 是 我 们 的 论 坛 项 目, 然 后 为 该 项 目 加 入 Struts 框 架 支 持 6.4.1 开 发 论 坛 数 据 访 问 层 数 据 访 问 层 在 Web 项 目 中 的 主 要 作 用 就 是 操 作 数 据 库, 执 行 增 删 改 查 等 数 据 库 操 作 在 前 面 的 学 习 中 我 们 已 经 学 习 了 使 用 JDBC 技 术 开 发 数 据 访 问 层, 这 里 我 们 仍 然 采 用 它 来 开 发, 从 而 也 就 不 详 细 的 讲 解 注 意 : 只 要 是 开 发 具 有 数 据 访 问 层 的 程 序, 就 需 要 将 数 据 库 的 驱 动 包 导 入 到 Java Web 项 目 中, 不 然 不 能 够 正 常 的 操 作 数 据 库 在 前 面 的 学 习 中 已 经 知 道, 使 用 JDBC 技 术 开 发 的 数 据 访 问 层 主 要 由 数 据 库 封 装 类, DAO 实 现 类 DAO 接 口 DAO 工 厂 类 等 程 序 组 成, 除 此 之 外, 还 要 创 建 相 应 操 作 实 体 类, 例 如 这 里 应 该 创 建 主 题 实 体 类 这 些 代 码 在 我 们 的 项 目 中 都 可 以 查 看 到, 这 里 我 们 只 给 出 DAO 实 现 类 代 码, 如 下 所 示 01 package com.sanqing.dao; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class TopicDAOImpl implements TopicDAO { 04 public TopicDAOImpl(){ 05 } 06 public void addtopic(topic topic) { 07 Connection conn = DBConnection.getConnection(); // 获 得 连 接 对 象 08 String addsql = "insert into topic(title,content,username,date) values(?,?,?,?)"; 09 PreparedStatement pstmt = null; // 声 明 预 处 理 对 象 10 try { 11 pstmt = conn.preparestatement(addsql); // 获 得 预 处 理 对 象 并 赋 值 12 pstmt.setstring(1, topic.gettitle()); // 设 置 第 一 个 参 数 13 pstmt.setstring(2, topic.getcontent()); // 设 置 第 二 个 参 数 14 pstmt.setstring(3, topic.getusername()); // 设 置 第 三 个 参 数 15 pstmt.setdate(4, new java.sql.date(topic.getdate().gettime())); 16 pstmt.executeupdate(); // 执 行 更 新 17 } catch (SQLException e) { 18 e.printstacktrace(); 19 } finally{ 20 DBConnection.close(pstmt); // 关 闭 预 处 理 对 象 21 DBConnection.close(conn); // 关 闭 连 接 对 象 22 }

25 23 } 24 public void deletetopic(int id) { 25 Connection conn = DBConnection.getConnection(); // 获 得 连 接 对 象 26 String updatesql = "delete from topic where id=?"; 27 PreparedStatement pstmt = null; // 声 明 预 处 理 对 象 28 try { 29 pstmt = conn.preparestatement(updatesql);// 获 得 预 处 理 对 象 并 赋 值 30 pstmt.setint(1, id); // 设 置 第 一 个 个 参 数 31 pstmt.executeupdate(); // 执 行 更 新 32 } catch (SQLException e) { 33 e.printstacktrace(); 34 } finally{ 35 DBConnection.close(pstmt); // 关 闭 预 处 理 对 象 36 DBConnection.close(conn); // 关 闭 连 接 对 象 37 } 38 } 39 public List<Topic> findalltopic() { 40 Connection conn = DBConnection.getConnection(); // 获 得 连 接 对 象 41 String updatesql = "select * from topic"; 42 PreparedStatement pstmt = null; // 声 明 预 处 理 对 象 43 List<Topic> topiclist = new ArrayList<Topic>(); 44 try { 45 pstmt = conn.preparestatement(updatesql);// 获 得 预 处 理 对 象 并 赋 值 46 ResultSet rs = pstmt.executequery(); // 执 行 查 询 47 while(rs.next()) { 48 Topic topic = new Topic(); // 实 例 化 49 topic.setid(rs.getint(1)); // 获 得 主 题 ID 50 topic.settitle(rs.getstring(2)); 51 topic.setcontent(rs.getstring(3)); 52 topic.setusername(rs.getstring(4)); 53 topic.setdate(rs.getdate(5)); 54 topiclist.add(topic); 55 } 56 } catch (SQLException e) { 57 e.printstacktrace(); 58 } finally{ 59 DBConnection.close(pstmt); // 关 闭 预 处 理 对 象 60 DBConnection.close(conn); // 关 闭 连 接 对 象 61 } 62 return topiclist; // 返 回 查 询 到 的 所 有 商 品 63 } 64 } 其 中 第 6 行 定 义 了 增 加 主 题 的 方 法, 当 发 表 新 主 题 时, 将 执 行 该 方 法, 从 而 将 主 题 中 的 信 息 保 存 到 数 据 库 中 在 第 24 行 中 定 义 了 删 除 指 定 主 题 的 方 法, 该 方 法 接 收 主 题 id 参 数, 从 而 将 该 主 题 删 除 第 39 行 定 义 了 查 询 所 有 主 题 的 方 法, 通 过 该 方 法 可 以 将

目 前 数 据 库 中 的 所 有 主 题 记 录 查 询 出 来 6.4.2 开 发 发 表 主 题 功 能 在 论 坛 中, 最 主 要 的 功 能 应 该 算 是 发 表 主 题 发 表 主 题 的 用 户 可 以 使 普 通 用 户, 也 可 以 是 后 台 管 理 员 这 里 我 们 主 要 是 通 过 MyEclipse 集 成 的 功 能, 快 速 开 发 完 成 发 表 主 题 功 能 所 需 要 的 JSP ActionForm 和 Action 程 序 在 执 行 创 建 之 前, 要 首 先 在 com.sanqing.struts 包 下 创 建 action 和 form 子 包 然 后 选 中 form 子 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令, 将 弹 出 选 择 创 建 程 序 的 界 面, 在 其 中 选 择 MyEclipse Web-Struts Struts 1.2 节 点, 将 进 入 选 择 创 建 程 序 的 界 面, 在 其 中 选 中 struts 1.2 Form,Action & JSP 选 项, 如 图 6-26 所 示 图 6-26 选 择 同 时 创 建 三 个 程 序 单 击 Next 按 钮, 将 弹 出 创 建 ActionForm 的 界 面, 因 为 这 里 是 表 示 论 坛 中 的 主 题, 所 以 为 它 起 名 为 TopicForm, 其 他 信 息 如 图 6-27 所 示

27 图 6-27 创 建 主 题 ActionForm 其 中 JSP 选 项 卡 中 的 选 择 和 填 写 信 息 如 图 6-28 所 示 图 6-28 生 成 发 表 主 题 JSP 程 序 注 意 : 主 题 ActionForm 中 是 需 要 有 id 属 性 的, 因 为 执 行 删 除 操 作 时 会 对 主 题 id 属 性 值 进 行 接 收 但 是 在 发 表 主 题 页 面 中 主 题 id 是 并 不 需 要 用 户 输 入 的, 所 以 这 里 设 置 主 题 id 对 应 的 表 单 元 素 为 隐 藏 域 在 创 建 主 题 ActionForm 界 面 中, 单 击 Next 按 钮, 将 完 成 主 题 ActionForm 的 创 建, 并 进 入 到 创 建 发 表 主 题 Action 中, 输 入 相 应 信 息 后, 如 图 6-29 所 示

图 6-29 创 建 发 表 主 题 Action 其 中 Path 选 项 中 进 行 修 改, 使 用 /addtopic 更 能 表 达 Action 的 功 能 在 Forwards 选 项 卡 中 还 要 加 入 成 功 和 失 败 跳 转, 如 图 6-30 所 示 图 6-30 发 表 主 题 Action 的 跳 转 当 发 表 成 功 后, 自 动 跳 转 到 查 询 所 有 主 题 Action 中, 从 而 再 执 行 查 询 所 有 主 题 的 功 能 当 发 表 失 败 后, 跳 转 回 发 表 主 题 页 面 在 创 建 发 表 主 题 Action 中, 单 击 Finish 按 钮, 将 完 成 程 序 的 创 建 打 开 发 表 主 题 Action 程 序, 在 其 中 加 入 操 作 数 据 访 问 层 的 代 码, 其 代 码 内 容 为 : 01 package com.sanqing.struts.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class TopicAction extends Action { 04 public ActionForward execute(actionmapping mapping, ActionForm form,

29 05 HttpServletRequest request, HttpServletResponse response) { 06 TopicForm topicform = (TopicForm) form; // 获 取 主 题 ActionForm 07 Topic topic=new Topic(); // 创 建 主 题 对 象 并 设 置 获 取 值 08 topic.settitle(topicform.gettitle()); 09 topic.setcontent(topicform.getcontext()); 10 topic.setusername(topicform.getusername()); 11 topic.setdate(new Date()); 12 try { 13 TopicDAO topicdao = TopicDAOFactory.createTopicDAOImpl(); 14 topicdao.addtopic(topic); // 执 行 发 表 主 题 方 法 15 return mapping.findforward("success"); 16 } catch (Exception e) { 17 e.printstacktrace(); 18 return mapping.findforward("failed"); 19 } 20 } 21 } 在 其 中 第 6 行 中 获 取 主 题 ActionForm 对 象, 在 第 7 行 创 建 主 题 对 象 后, 将 ActionForm 对 象 中 的 属 性 值 设 置 到 主 题 对 象 中 注 意 : 在 主 题 ActionForm 对 象 中 并 没 有 发 表 时 间 属 性 值, 在 第 11 行 中 使 用 当 前 日 期 设 置 到 主 题 对 象 中 在 第 13 行 中 通 过 DAO 工 厂 类 获 取 DAO 实 现 类 对 象, 然 后 调 用 addtopic 发 表 主 题 方 法, 如 果 发 表 成 功, 则 返 回 success 如 果 发 生 异 常, 则 发 表 失 败, 返 回 failed 对 Action 的 代 码 调 整 后, 打 开 发 表 主 题 JSP 程 序, 也 就 是 addtopic.jsp 程 序 可 以 看 到 所 有 的 信 息 都 是 英 文 书 写 的, 将 它 们 修 改 成 中 文, 而 且 id 是 并 不 需 要 显 示 的 调 整 后 的 JSP 重 要 代 码 为 : 01 <html:form action="/addtopic"> 02 <html:hidden property="id"/><html:errors property="id"/><br/> 03 发 表 用 户 : <html:text property="username"/> 04 <html:errors property="username"/><br/> 05 主 题 标 题 : <html:text property="title"/><html:errors property="title"/><br/> 06 主 题 内 容 <html:textarea property="context" cols="20" rows="5"/> 07 <html:errors property="context"/><br/> 08 <html:submit value=" 发 表 "/><html:cancel value=" 重 置 "/> 09 </html:form> 到 这 里, 我 们 的 发 表 主 题 功 能 就 开 发 完 成 了 6.4.3 开 发 查 询 所 有 主 题 功 能 当 发 表 主 题 成 功 后, 将 自 动 跳 转 到 查 询 所 有 主 题 Action 中, 在 本 小 节 中 就 来 开 发 该 Action 因 为 完 成 查 询 所 有 主 题 的 功 能, 并 不 需 要 接 收 参 数, 所 以 在 Action 中 也 并 不 需 要 使 用 到 ActionForm 选 中 action 子 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令,

将 弹 出 选 择 创 建 程 序 的 界 面, 在 其 中 选 择 MyEclipse Web-Struts Struts 1.2 struts 1.2 Action 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 Action 程 序 的 界 面, 输 入 相 关 信 息 后, 如 图 6-31 所 示 图 6-31 创 建 查 询 所 有 主 题 Action 因 为 不 需 要 使 用 任 何 ActionForm, 所 以 其 中 直 接 显 示 Forwards 选 项 卡, 在 其 中 定 义 了 当 查 询 成 功 后, 将 跳 转 到 显 示 所 有 主 题 的 页 面 单 击 Finish 按 钮, 将 完 成 该 Action 的 创 建 打 开 查 询 所 有 主 题 的 Action 程 序, 在 其 中 加 入 相 应 的 功 能 代 码, 其 调 整 后 的 代 码 内 容 为 : 01 package com.sanqing.struts.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class FindAllTopicAction extends Action { 04 public ActionForward execute(actionmapping mapping, ActionForm form, 05 HttpServletRequest request, HttpServletResponse response) { 06 TopicDAO topicdao = TopicDAOFactory.createTopicDAOImpl(); 07 List<Topic> topiclist=topicdao.findalltopic(); 08 request.setattribute("topiclist", topiclist); 09 return mapping.findforward("success"); 10 } 11 } 可 以 看 到 该 程 序 是 非 常 简 单 的, 在 第 8 行 中 将 查 询 到 的 主 题 集 合 保 存 到 request 范

31 围 内, 这 样 在 显 示 页 面 中 就 可 以 对 它 进 行 遍 历, 从 而 得 到 每 一 条 主 题 记 录 接 下 来 就 是 开 发 显 示 所 有 主 题 的 JSP 程 序 选 中 WebRoot 目 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New JSP(Avanced Templates) 命 令, 将 弹 出 创 建 JSP 程 序 的 界 面, 输 入 相 关 信 息 后, 如 图 6-32 所 示 图 6-32 创 建 JSP 程 序 单 击 Finish 按 钮, 将 完 成 显 示 所 有 主 题 JSP 程 序 的 创 建 在 编 辑 区 中 自 动 打 开 生 成 的 JSP 程 序, 在 其 中 加 入 相 应 代 码 后, 其 主 要 代 码 如 下 所 示 : 01 <table border="1"> 02 <tr> 03 <td> 主 题 标 题 </td> 04 <td> 发 表 用 户 </td> 05 <td> 发 表 时 间 </td> 06 <td> 是 否 删 除 </td> 07 </tr> 08 <logic:empty name="topiclist"> 09 <tr> 10 <td colspan="3"> 数 据 库 中 还 没 有 主 题 </td> 11 </tr> 12 </logic:empty> 13 <logic:notempty name="topiclist"> 14 <logic:iterate id="topic" name="topiclist"> 15 <tr> 16 <td> 17 <bean:write name="topic" property="title"/> 18 </td> 19 <td> 20 <bean:write name="topic" property="username"/>

21 </td> 22 <td> 23 <bean:write name="topic" property="date"/> 24 </td> 25 <td> 26 <a href="deletetopic.do?id=<bean:write name='topic' property='id'/>"> 删 除 </a> 27 </td> 28 </tr> 29 </logic:iterate> 30 </logic:notempty> 31 </table> 其 中 在 第 8 行 中 使 用 使 用 <logic:empty> 标 签 判 断 主 题 集 合 是 否 为 空, 如 果 为 空, 则 显 示 目 前 没 有 主 题 在 第 14 行 中 使 用 <logic:iterate> 标 签 对 不 为 空 的 集 合 进 行 循 环 遍 历, 从 而 得 到 主 题 的 具 体 信 息, 包 括 主 题 标 题 发 表 用 户 和 发 表 时 间, 主 题 内 容 通 常 是 比 较 多 的, 并 不 会 显 示 在 这 里 在 第 26 行 中 定 义 了 删 除 超 链 接, 在 其 中 以 当 前 行 主 题 id 为 参 数 调 用 删 除 主 题 Action, 从 而 将 该 行 主 题 删 除 说 明 : 在 删 除 超 链 接 的 路 径 中 可 以 看 到, 在 其 中 也 可 以 使 用 Struts 的 标 签, 将 得 到 的 值 做 为 参 数 值, 也 和 EL 表 达 式 是 一 样 的 6.4.4 开 发 删 除 主 题 功 能 在 显 示 所 有 主 题 页 面 中, 单 击 删 除 超 链 接, 就 会 将 该 行 的 主 题 记 录 删 除 在 本 小 节 中 就 来 完 成 删 除 主 题 的 功 能 在 删 除 主 题 Action 中 要 使 用 主 题 ActionForm 来 接 收 传 递 的 id 属 性 值, 主 题 ActionForm 已 经 存 在 了, 所 以 不 需 要 再 次 创 建 在 选 择 创 建 程 序 界 面 中, 选 择 struts 1.2 Action 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 Action 程 序 的 界 面, 输 入 删 除 Action 的 相 关 信 息 后, 如 图 6-33 所 示

33 图 6-33 创 建 删 除 主 题 Aciton 单 击 Finish 按 钮, 将 完 成 删 除 主 题 Action 的 创 建 打 开 该 程 序, 加 入 相 应 的 功 能 代 码, 其 程 序 代 码 为 : 01 package com.sanqing.struts.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class DeleteTopicAction extends Action { 04 public ActionForward execute(actionmapping mapping, ActionForm form, 05 HttpServletRequest request, HttpServletResponse response) { 06 TopicForm topicform=(topicform)form; 07 int id=topicform.getid(); // 获 取 接 收 到 的 id 08 TopicDAO topicdao = TopicDAOFactory.createTopicDAOImpl(); 09 topicdao.deletetopic(id); // 调 用 删 除 方 法 10 return mapping.findforward("success"); 11 } 12 } 在 其 中 第 7 行 中 首 先 获 取 主 题 id, 然 后 以 主 题 id 为 参 数 在 第 9 行 调 用 deletetopic 方 法, 从 而 将 指 定 的 主 题 删 除 说 明 : 有 些 读 者 可 能 会 认 为 为 发 表 主 题 和 删 除 主 题 分 别 定 义 ActionForm 会 更 好, 这 是 不 对 的, 因 为 如 果 为 每 一 个 Action 都 定 义 一 个 ActionForm, 那 就 不 再 具 有 程 序 的 重 用 性, 同 时 也 会 造 成 程 序 过 分 膨 胀

6.4.5 运 行 论 坛 项 目 经 过 上 面 的 开 发, 该 论 坛 项 目 已 经 能 够 发 布 并 运 行 了, 但 是 这 样 的 项 目 是 不 能 够 处 理 中 文 提 交 的, 要 想 让 该 项 目 支 持 中 文, 还 需 要 将 前 面 学 习 的 编 码 过 滤 器 拷 贝 到 该 项 目 中, 然 后 在 web.xml 文 件 中 进 行 配 置 在 web.xml 文 件 中 同 时 对 项 目 的 首 页 进 行 修 改 成 addtopic.jsp 发 布 Struts 项 目 是 和 发 布 基 本 的 Web 项 目 相 同 的 在 Servers 界 面 中 选 择 Tomcat 6.x 服 务 器, 单 击 鼠 标 右 键, 选 择 Add Deployment 命 令, 将 弹 出 发 布 项 目 界 面, 填 入 BBS 项 目 后, 如 图 6-34 所 示 图 6-34 发 布 论 坛 项 目 单 击 Finish 按 钮 将 完 成 项 目 的 发 布 再 次 选 中 Tomcat 6.x 服 务 器, 在 右 键 弹 出 菜 单 中, 选 择 Run Server 命 令, 将 开 始 运 行 服 务 器 启 动 服 务 器 完 成 后, 打 开 浏 览 器, 输 入 如 下 地 址 : http://localhost:8080/bbs/ 将 进 入 论 坛 项 目 首 页, 也 就 是 发 表 主 题 页 面, 在 其 中 发 表 一 条 主 题, 运 行 结 果 如 图 6-35 所 示

35 图 6-35 发 表 主 题 单 击 发 表 按 钮 后 会 将 这 些 填 写 的 信 息 发 送 到 发 表 主 题 Action 中, 发 表 完 成 后, 将 自 动 进 入 到 查 询 所 有 主 题 Action 中, 然 后 跳 转 到 显 示 所 有 主 题 页 面, 如 图 6-36 所 示 图 6-36 显 示 所 有 主 题 在 页 面 中, 会 将 主 题 的 标 题 发 表 用 户 和 发 表 时 间 显 示 出 来 在 每 一 条 主 题 记 录 后 面 都 有 一 个 删 除 超 链 接, 单 击 该 超 链 接 将 把 该 条 记 录 删 除, 删 除 后 将 再 次 跳 转 到 显 示 所 有 主 题 的 页 面 中, 如 图 6-37 所 示

图 6-37 删 除 主 题 因 为 目 前 我 们 只 有 一 条 主 题, 所 以 删 除 该 主 题 后, 将 在 页 面 中 显 示 数 据 库 中 还 没 有 主 题 的 信 息 6.4.6 使 用 DispatchAction 简 化 开 发 在 本 节 的 论 坛 项 目 中, 可 以 看 到 每 完 成 一 个 功 能, 都 要 定 义 一 个 Action, 这 对 于 一 个 功 能 复 杂 的 项 目 来 说, 就 要 定 义 很 多 个 Action 不 管 是 代 码 量 上, 还 是 配 置 文 件 中 的 配 置 都 是 非 常 多 的 在 Struts 框 架 中, 为 了 解 决 这 个 问 题, 定 义 了 DispatchAction 类, 它 是 Action 类 的 子 类 当 创 建 自 己 的 功 能 Action 时, 可 以 继 承 DispatchAction 类, 从 而 将 每 一 个 功 能 定 义 一 个 方 法, 而 不 是 一 个 Action 在 MyEclipse 中, 也 集 成 了 创 建 这 种 Action 的 功 能 在 选 择 创 建 程 序 的 界 面 中, 选 择 struts 1.2 Action 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 Action 的 界 面, 在 其 中 选 择 Action 继 承 的 父 类 为 DispatchAction, 创 建 界 面 如 图 6-38 所 示 图 6-38 创 建 DispatchAction 在 其 中 Superclass 选 项 中 选 择 org.apache.struts.actions. DispatchAction, 然 后 在 下 面 的 Parameter 选 项 卡 中 填 写 访 问 主 题 Action 时, 使 用 到 的 参 数 单 击 Finish 按 钮, 将 完 成 主 体 Action 的 创 建 打 开 Action 程 序, 加 入 相 应 的 功 能 代 码 后, 具 体 代 码 如 下 所 示 01 package com.sanqing.struts.action;

37 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class TopicAction extends DispatchAction { 04 public ActionForward add(actionmapping mapping, ActionForm form, 05 HttpServletRequest request, HttpServletResponse response) { 06 TopicForm topicform = (TopicForm) form; // 获 取 主 题 ActionForm 07 Topic topic=new Topic(); // 创 建 主 题 对 象 并 设 置 获 取 值 08 topic.settitle(topicform.gettitle()); 09 topic.setcontent(topicform.getcontext()); 10 topic.setusername(topicform.getusername()); 11 topic.setdate(new Date()); 12 try { 13 TopicDAO topicdao = TopicDAOFactory.createTopicDAOImpl(); 14 topicdao.addtopic(topic); // 执 行 发 表 主 题 方 法 15 return mapping.findforward("success"); 16 } catch (Exception e) { 17 e.printstacktrace(); 18 return mapping.findforward("failed"); 19 } 20 } 21 public ActionForward delete(actionmapping mapping, ActionForm form, 22 HttpServletRequest request, HttpServletResponse response) { 23 TopicForm topicform = (TopicForm) form; 24 int id=topicform.getid(); // 获 取 接 收 到 的 id 25 TopicDAO topicdao = TopicDAOFactory.createTopicDAOImpl(); 26 topicdao.deletetopic(id); // 调 用 删 除 方 法 27 return mapping.findforward("success"); 28 } 29 public ActionForward findall(actionmapping mapping, ActionForm form, 30 HttpServletRequest request, HttpServletResponse response) { 31 TopicDAO topicdao = TopicDAOFactory.createTopicDAOImpl(); 32 List<Topic> topiclist=topicdao.findalltopic(); 33 request.setattribute("topiclist", topiclist); 34 return mapping.findforward("success"); 35 } 36 } 从 代 码 上 可 以 看 到, 我 们 将 论 坛 项 目 中 的 发 表 主 题 查 询 所 有 主 题 和 删 除 主 题 的 方 法 都 写 到 了 该 Action 中 当 访 问 该 Action 时, 需 要 给 出 相 应 的 参 数, 例 如 要 访 问 查 询 所 有 主 题 方 法, 则 访 问 地 址 为 : http://localhost:8080/bbs/topic.do? command= findall 其 中 topic.do 就 是 对 Action 进 行 的 路 径, command 是 我 们 在 界 面 中 配 置 的 Action 参 数, findall 指 定 调 用 的 是 哪 一 个 方 法 读 者 可 以 自 己 来 将 本 节 中 开 发 的 论 坛 项 目 修 改 成 DispatchAction 的 形 式 说 明 :DispatchAction 在 实 际 开 发 中 使 用 是 非 常 多 的, 但 是 也 不 是 将 所 有 的 功 能 都 写 到 一 个 Action 中, 而 是 将 一 类 功 能 放 在 一 起, 例 如 对 主 题 的 操 作 功 能 就 都 写 在

TopicAction 中, 而 对 用 户 的 操 作 就 应 该 写 在 UserAction 中

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 7 章 进 行 Hibernate 开 发 在 上 一 章 中 学 习 了 Struts 框 架 的 开 发, 它 是 一 种 MVC 框 架 在 本 章 中 将 学 习 到 Hibernate 框 架, 它 是 一 种 开 发 源 代 码 的 专 注 于 数 据 访 问 层 的 对 象 关 系 映 射 框 架, 仅 使 用 Hibernate 框 架 是 不 能 开 发 项 目 的 在 Hibernatez 中 对 JDBC 进 行 轻 量 级 的 封 装, 将 对 象 模 型 表 示 的 数 据 映 射 到 SQL 表 示 的 关 系 模 型 上, 从 而 使 得 Java 开 发 人 员 能 够 通 过 使 用 对 象 的 变 成 思 维 来 操 作 数 据 库 在 MyEclipse 中, 对 Hibernate 做 了 非 常 好 的 集 成, 通 过 界 面 化 的 操 作 能 够 让 数 据 在 Java 程 序 和 数 据 库 之 间 进 行 转 换 在 本 章 中 将 把 具 体 操 作 做 为 重 点, 从 而 让 读 者 能 够 进 行 Hibernate 相 关 程 序 的 快 速 开 发 7.1 开 发 Hibernate 项 目 Hibernate 框 架 是 一 种 专 注 于 数 据 库 操 作 的 框 架, 所 以 它 并 不 仅 仅 应 用 在 Java Web 的 框 架 中, 同 时 也 可 以 应 用 在 普 通 的 Java 项 目 中 本 本 节 中, 我 们 就 以 简 单 的 Java 项 目 来 看 一 下 在 MyEclipse 中 如 何 开 发 Hibernate 项 目 7.1.1 准 备 工 作 因 为 Hibernate 是 一 种 数 据 库 框 架, 所 以 在 开 发 该 项 目 的 时 候 一 定 要 有 相 应 的 数 据 库 连 接 在 前 面 管 理 数 据 库 一 章 已 经 讲 解 了, 如 何 在 数 据 库 视 图 中 创 建 数 据 库 连 接 其 中 已 经 建 立 了 MySQL 的 数 据 库 连 接, 在 该 Hibernate 项 目 中 就 要 使 用 到 该 连 接 如 果 读 者 的 本 地 计 算 机 中, 不 存 在 该 连 接, 需 要 先 建 立 后, 才 能 够 创 建 Hibernate 连 接 MySQL 数 据 库 的 项 目 在 MyEclipse 开 发 Hibernate 项 目 是 和 开 发 Struts 项 目 类 似 的, 都 需 要 首 先 创 建 一 个 基 本 项 目, 然 后 为 基 本 项 目 加 入 相 应 支 持 在 MyEclipse 的 菜 单 中, 选 择 File New Java Project 命 令, 就 会 弹 出 创 建 Java 项 目 的 界 面, 在 其 中 输 入 项 目 的 名 称 为 FirstHibernate, 如 图 7-1 所 示

图 7-1 创 建 Java 项 目 单 击 Finish 按 钮 将 完 成 普 通 Java 项 目 的 创 建 7.1.2 加 入 Hibernate 框 架 支 持 在 包 资 源 管 理 器 中, 选 中 要 加 入 Hibernate 框 架 支 持 的 项 目, 这 里 选 择 FirstHibernate 项 目 在 MyEclipse 的 菜 单 中, 选 择 MyEclipse Project Capabilities Add Hibernate Capabilities 命 令, 将 弹 出 加 入 支 持 操 作 界 面, 如 图 7-2 所 示

3 图 7-2 加 入 框 架 支 持 其 中 Hibernate Specification 表 示 要 加 入 Hibernate 框 架 的 版 本, 默 认 是 选 中 最 高 版 本, 通 常 也 是 这 样 的 Enable Hibernate Annotations Support 表 示 是 否 让 Hibernate 支 持 注 解 方 式,Hibernate 3 版 本 中 多 出 了 注 解 方 式 的 开 发 方 法, 因 为 后 面 要 进 行 该 操 作, 所 以 这 里 选 中 它 Select the libraries to add to the buildpath 表 示 将 向 项 目 中 加 入 哪 些 类 库, 对 于 基 本 的 Hibernate 项 目 而 言, 采 用 默 认 选 择 就 可 以 其 中 第 1 个 选 项 就 是 注 解 开 发 所 用 到 的 类 库 当 Hibernate 整 合 其 他 技 术 时, 可 能 需 要 更 多 的 类 库 JAR Library Installation 表 示 是 否 将 类 库 复 制 到 项 目 中 其 中 Add checked Libraries to project build-path 选 项 表 示 不 复 制 JAR 文 件 类 库 到 项 目 中, 只 在 发 布 项 目 时 进 行 复 制, 这 是 默 认 的 选 项, 也 是 经 常 采 用 的 选 项 Copy checked Library Jars to project folder and to build-path 选 项 表 示 复 制 JAR 文 件 类 库 到 项 目 中, 选 择 该 选 项 后 还 需 要 填 写 将 这 些 类 库 放 置 的 目 录, 这 种 操 作 的 好 处 是 使 开 发 的 项 目 不 依 赖 于 MyEclipse 单 击 Next 按 钮, 将 完 成 JAR 包 的 加 入, 并 且 弹 出 创 建 文 件 目 录 和 配 置 文 件 的 界 面, 如 图 7-3 所 示

图 7-3 定 义 目 录 和 配 置 文 件 其 中 Hibernate config file 表 示 配 置 文 件 的 选 择, New 选 项 表 示 新 创 建, Existing 选 项 表 示 使 用 已 经 存 在 的 Configuration Folder 表 示 配 置 文 件 的 所 在 目 录, 通 常 将 它 直 接 放 在 src 目 录 下 Configuration File Name 表 示 配 置 文 件 的 名 称, 默 认 名 称 为 hibernate.cfg.xml, 通 常 也 是 采 用 该 名 称 Open configuration file after wizard completion 表 示 创 建 完 成 后 是 否 打 开 该 文 件, 默 认 是 打 开 的 单 击 Next 按 钮, 将 完 成 Hibernate 配 置 文 件 的 创 建, 并 进 入 建 立 数 据 库 连 接 的 界 面, 如 图 7-4 所 示

5 图 7-4 建 立 连 接 其 中 Specify database connection details 表 示 是 否 设 置 数 据 库 连 接 属 性, 如 果 不 选 择, 将 跳 过 该 界 面 的 填 写, 通 常 是 选 择 DataSource 表 示 数 据 源 类 型, Use JDBC Driver 表 示 使 用 JDBC 驱 动, Use JNDI DataSource 表 示 使 用 JNDI 数 据 源, 默 认 是 使 用 JDBC 驱 动, 这 也 是 本 书 中 讲 解 的 DB Driver 表 示 能 够 建 立 的 连 接, 目 前 有 两 个 选 项, MyEclipse Derby 表 示 MyEclipse 中 集 成 的 数 据 库 连 接, MySQL 是 自 己 创 建 的, 这 里 选 择 MySQL 选 择 数 据 库 连 接 后, 将 会 把 下 面 的 选 项 内 容 自 动 填 写 好 注 意 : DB Driver 选 项 是 和 数 据 库 视 图 数 据 库 浏 览 器 中 的 已 有 数 据 库 连 接 相 对 应 的, 如 果 其 中 没 有 MySQL 连 接, 这 里 也 就 没 法 选 择 该 项 其 中 Connect URL 表 示 连 接 数 据 库 的 URL; Driver Class 表 示 驱 动 类 ; Username 和 Password 分 别 表 示 连 接 数 据 库 用 到 的 用 户 名 和 密 码 ; Dialect 表 示 数 据 库 方 言 最 后 的 Enable dynamic DB table creation 表 示 是 否 动 态 生 成 建 表 语 句, 默 认 是 不 选 中 的 单 击 Next 按 钮, 将 完 成 数 据 库 的 连 接, 并 进 入 Hibernate 会 话 工 厂 设 置 界 面, 如 图 7-5 所 示

图 7-5 设 置 会 话 工 厂 其 中 Create SessionFactory class 表 示 是 否 创 建 会 话 工 厂 类, 如 果 取 消 选 中 将 跳 过 该 界 面 的 设 置 Java source folder 表 示 会 话 工 厂 类 创 建 在 哪 一 个 目 录 中 Java package 表 示 会 话 工 厂 类 创 建 在 哪 一 个 包 中, 单 击 Browse 按 钮 可 以 选 择 包, 单 击 New 按 钮 可 以 创 建 一 个 包 说 明 : 在 实 际 开 发 中 通 常 将 它 放 在 hb 包 中, 所 以 这 里 我 们 创 建 com.sanqing.hb 包, 该 包 名 并 不 是 规 范 中 所 固 定 的 Class name 表 示 会 话 工 厂 类 的 类 名, 默 认 是 HibernateSessionFactory, 通 常 也 是 采 用 该 默 认 名 称 Java Complliance Level 表 示 使 用 Java 的 版 本, 这 里 选 择 Java 5 版 本 单 击 Finish 按 钮, 将 完 成 向 项 目 中 加 入 Hibernate 框 架 支 持 的 操 作 7.1.3 认 识 Hibernate 项 目 结 构 加 入 Hibernate 框 架 支 持 后, 在 项 目 中 会 自 动 加 入 Hibernate 的 相 关 JAR 包, 以 及 Hibernate 的 配 置 文 件 和 会 话 工 厂 类 在 包 资 源 管 理 器 中 将 项 目 展 开, 如 图 7-6 所 示

7 图 7-6 Hibernate 项 目 结 构 其 中 在 Referenced Libraries 目 录 下 包 含 着 MySQL 数 据 库 的 驱 动 包, 该 包 来 自 建 立 连 接 时 导 入 的 包, 当 使 用 连 接 建 立 Hibernate 项 目 后 会 自 动 导 入 在 com.sanqing.hb 包 下 会 创 建 会 话 工 厂 类, 该 类 中 的 代 码 都 是 自 动 生 成 的 通 过 会 话 工 厂 类 可 以 很 容 易 获 取 到 Session 对 象 通 过 使 用 Session 对 象 调 用 方 法 才 能 完 成 数 据 库 的 相 关 操 作 注 意 : 这 里 所 指 的 Session 对 象 不 是 JSP 中 的 Session 对 象, 而 是 Hibernate 中 用 来 操 作 数 据 库 的 Hibernate Session 对 象 为 了 更 好 的 了 解 Hibernate 中 的 数 据 库 操 作, 我 们 需 要 对 该 会 话 工 厂 类 有 所 了 解, 它 的 主 要 代 码 为 : 01 public class HibernateSessionFactory { 02 private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";// 配 置 文 件 03 private static final ThreadLocal<Session> threadlocal 04 = new ThreadLocal<Session>();// 定 义 ThreadLocal 对 象 05 private static Configuration configuration 06 = new Configuration();// 定 义 Configuration 对 象 07 private static org.hibernate.sessionfactory sessionfactory;// 定 义 SessionFactory 对 象 08 private static String configfile = CONFIG_FILE_LOCATION; 09 static { 10 try {

11 configuration.configure(configfile);// 读 取 配 置 文 件 12 sessionfactory = 13 configuration.buildsessionfactory();// 根 据 配 置 文 件 创 建 14 } catch (Exception e) { 15 System.err 16.println("%%%% Error Creating SessionFactory %%%%"); 17 e.printstacktrace(); 18 } 19 } 20 private HibernateSessionFactory() { 21 } 22 public static Session getsession() throws HibernateException { 23 Session session = (Session) threadlocal.get();// 从 ThreadLocal 对 象 中 获 得 24 if (session == null!session.isopen()) {// 判 断 Session 对 象 是 否 为 空 者 未 打 开 25 if (sessionfactory == null) { // 如 果 没 有 创 建, 则 首 先 创 建 26 rebuildsessionfactory(); 27 } 28 // 如 果 不 为 空, 则 调 用 其 opensession 方 法 创 建 Session 对 象 29 session = (sessionfactory!= null)? sessionfactory.opensession(): null; 30 threadlocal.set(session);// 在 ThreadLocal 对 象 中 保 存 该 Session 对 象 31 } 32 return session; 33 } 34 public static void rebuildsessionfactory() { 35 try { 36 configuration.configure(configfile);// 读 取 配 置 文 件 37 sessionfactory = 38 configuration.buildsessionfactory();// 根 据 配 置 文 件 创 建 39 } catch (Exception e) { 40 System.err 41.println("%%%% Error Creating SessionFactory %%%%"); 42 e.printstacktrace(); 43 } 44 } 45 public static void closesession() throws HibernateException { 46 Session session = (Session) threadlocal.get();// 从 ThreadLocal 对 象 中 获 得 47 threadlocal.set(null);// 将 当 前 线 程 Session 对 象 从 ThreadLocal 对 象 中 移 除 48 if (session!= null) { 49 session.close(); 50 } 51 } 52 public static org.hibernate.sessionfactory getsessionfactory() {// 取 得 SessionFactory 53 return sessionfactory; 54 } 55 public static void setconfigfile(string configfile) {// 设 置 新 的 配 置 文 件

9 56 HibernateSessionFactory.configFile = configfile; 57 sessionfactory = null; 58 } 59 public static Configuration getconfiguration() {// 获 得 Configuration 对 象 60 return configuration; 61 } 62 } 代 码 第 3 行 定 义 了 一 个 ThreadLocal 对 象, 该 对 象 可 以 用 来 保 存 不 同 线 程 下 的 Session 对 象 ThreadLocal 对 象 的 内 容 结 构 就 是 一 个 Map 对 象, 其 key 值 用 来 保 存 线 程 ID,value 值 用 来 保 存 Session 对 象 这 样 就 能 保 证 每 个 线 程 有 不 同 的 Session 对 象, 同 时 还 可 以 保 证 了 每 一 个 线 程 只 拥 有 一 个 Session 对 象 实 例 代 码 第 9 行 至 第 19 行 定 义 一 个 静 态 代 码 段, 在 该 代 码 段 中 首 先 通 过 configuration 对 象 读 取 配 置 文 件, 然 后 调 用 其 buildsessionfactory 方 法 来 创 建 SessionFactory 对 象 代 码 第 22 行 定 义 了 一 个 getsession 方 法, 在 该 方 法 中 首 先 调 用 ThreadLocal 对 象 来 获 得 当 前 线 程 的 Session 对 象, 然 后 判 断 是 否 存 在 该 Session 对 象 如 果 不 存 在 该 Session 对 象, 或 者 该 Session 对 象 未 打 开, 就 调 用 SessionFactory 对 象 的 opensession 方 法 创 建 Session 对 象 创 建 完 Session 对 象 后, 还 需 要 在 ThreadLocal 对 象 中 保 存 该 Session 对 象, 并 最 终 返 回 该 Session 对 象 代 码 第 45 行 定 义 了 一 个 closesession 方 法, 该 方 法 首 先 从 ThreadLocal 对 象 中 获 得 当 前 线 程 对 象 的 Session 对 象, 然 后 将 当 前 线 程 Session 对 象 从 ThreadLocal 对 象 中 移 除 如 果 该 Session 对 象 不 为 null, 则 调 用 其 close 方 法 将 其 关 闭 说 明 : 从 代 码 量 和 讲 解 上 可 以 看 到, 会 话 工 厂 类 并 不 简 单 的, 但 是 值 得 庆 幸 的 是 该 类 会 由 MyEclipse 自 动 创 建, 不 需 要 自 己 手 动 编 写 这 里 只 需 要 对 它 有 所 了 解, 它 们 会 使 用 会 话 工 厂 类 就 可 以 了 7.1.4 认 识 Hibernate 的 配 置 文 件 Hibernate 配 置 文 件 也 是 Hibernate 项 目 的 重 要 组 成 部 分, 由 于 它 的 内 容 比 较 多, 将 它 单 独 放 在 一 小 节 中 进 行 讲 解 双 击 hibernate.cfg.xml 文 件 在 编 辑 打 开 后, 在 编 辑 区 的 左 下 角 可 以 看 到 有 三 个 选 项, 它 们 对 应 着 三 种 显 示 文 件 的 方 式 Configuration 选 项 表 示 界 面 化 的 显 示 Hibernate 配 置 信 息, 选 择 该 选 项 后, 界 面 如 图 7-7 所 示

图 7-7 界 面 化 显 示 配 置 信 息 在 界 面 的 左 边 是 对 数 据 源 进 行 的 配 置, 和 前 面 加 入 Hibernate 框 架 支 持 操 作 中 的 类 似 的 在 其 中 配 置 了 数 据 库 连 接 URL 驱 动 类 用 户 名 密 码 和 数 据 库 方 言 等 信 息 除 了 这 些 信 息 后, 还 可 以 在 右 边 properties 选 项 中 添 加 其 他 配 置 信 息, 例 如 这 里 添 加 显 示 SQL 语 句 的 配 置 单 击 Add 按 钮, 将 弹 出 添 加 属 性 配 置 界 面, 在 其 中 填 写 相 应 信 息, 如 图 7-8 所 示 图 7-8 添 加 属 性 配 置 说 明 : 在 项 目 开 发 阶 段, 显 示 SQL 语 句 的 配 置 是 经 常 被 使 用 到 的 在 Hibernate 中 执 行 操 作 的 并 不 是 SQL 语 句, 但 是 在 运 行 项 目 时 想 看 到 具 体 的 数 据 库 操 作, 这 时 候 就 可 以 进 行 该 配 置, 从 而 将 Hibernate 框 架 中 执 行 的 SQL 语 句 显 示 在 控 制 台 中 在 Mappings 选 项 中 是 对 实 体 类 映 射 文 件 进 行 配 置, 在 配 置 在 后 面 的 讲 解 中 将 详 细 介 绍 编 辑 区 的 左 下 角 的 第 二 个 选 项 是 Design 选 项, 选 择 该 选 项, 则 会 将 配 置 文 件 中 的 配 置 以 XML 文 件 结 构 的 形 式 显 示 出 来, 如 图 7-9 所 示

11 图 7-9 XML 文 件 形 式 显 示 其 中 每 一 个 property 节 点 就 对 应 着 一 条 属 性 配 置 在 property 节 点 下 又 分 为 两 个 节 点, 分 别 对 应 着 属 性 名 和 属 性 值 例 如 显 示 SQL 语 句 的 配 置, 属 性 名 为 show_sql, 属 性 值 为 true, 表 示 在 控 制 台 中 显 示 SQL 语 句 如 果 设 置 值 为 false, 则 表 示 不 显 示, 它 也 是 默 认 值 编 辑 区 的 第 三 个 Source 选 项 就 是 对 应 着 以 代 码 的 形 式 显 示 Hibernate 的 配 置 文 件, 其 中 的 重 要 代 码 为 : 01 <hibernate-configuration> 02 <session-factory> 03 <property name="dialect"> 04 org.hibernate.dialect.mysqldialect <!-- 数 据 库 方 言 --> 05 </property> 06 <property name="connection.url"> 07 jdbc:mysql://localhost:3306/mydb <!-- 数 据 库 连 接 URL --> 08 </property> 09 <property name="connection.username">root</property><!-- 数 据 库 用 户 名 --> 10 <property name="connection.password">admin</property><!-- 数 据 库 密 码 --> 11 <property name="connection.driver_class"> 12 com.mysql.jdbc.driver <!-- 数 据 库 驱 动 类 --> 13 </property> 14 <property name="show_sql">true</property> <!-- 显 示 SQL 语 句 --> 15 </session-factory> 16 </hibernate-configuration> Hibernate 配 置 文 件 的 根 节 点 为 <hibernate-configuration>,hibernate 的 所 有 配 置 都 必 须 放 置 在 该 节 点 下 代 码 第 2 行 定 义 了 一 个 <session-factory> 标 签, 可 以 在 该 标 签 下 进 行 数 据 源 等 相 关 属 性 的 配 置 代 码 第 3 行 定 义 了 一 个 <property> 标 签, 该 标 签 用 来 指 定 Hibernate 中 需 要 配 置 的 属 性 和 属 性 值

其 中 dialect 属 性 用 来 设 置 数 据 库 方 言, 这 里 使 用 的 是 MySQL 数 据 库, 它 的 值 为 org.hibernate.dialect.mysqldialect 后 面 依 次 对 连 接 URL 用 户 名 密 码 驱 动 类 等 属 性 进 行 了 配 置 show_sql 属 性 是 我 们 自 己 添 加 的, 用 来 设 置 是 否 显 示 SQL 语 句, 当 值 为 true, 表 示 显 示 SQL 语 句, 否 则 不 显 示 说 明 :Hibernate 中 的 数 据 库 方 言 是 非 常 重 要 的, 因 为 不 同 数 据 库 的 数 据 库 操 作 是 有 所 不 同 的 在 Hibernate 框 架 中 通 过 数 据 库 方 言, 来 根 据 不 同 数 据 库 进 行 不 同 的 操 作, 从 而 使 程 序 员 不 用 关 心 数 据 库, 而 只 需 要 关 心 操 作 代 码 7.2 开 发 Hibernate 项 目 中 的 程 序 开 发 完 Hibernate 项 目 后, 就 可 以 在 该 项 目 中 创 建 Hibernate 的 相 关 程 序 Hibernate 程 序 包 括 实 体 类 映 射 文 件 和 DAO 数 据 访 问 类, 在 MyEclipse 中 集 成 了 界 面 化 创 建 这 些 程 序 的 功 能 7.2.1 创 建 数 据 表 界 面 化 创 建 Hibernate 程 序 都 是 基 于 数 据 表 操 作 的, 通 过 数 据 表 可 以 生 成 对 该 表 进 行 操 作 的 相 关 类 所 以 我 们 在 开 发 Hibernate 程 序 之 前, 首 先 要 在 mydb 数 据 库 下 创 建 一 个 数 据 表, 这 里 以 一 个 学 生 表 举 例 说 明 : 数 据 库 相 关 的 操 作 已 经 在 管 理 数 据 库 一 章 进 行 了 详 细 讲 解, 在 本 节 中 只 对 重 要 的 步 骤 进 行 讲 解 在 MyEclipse 中, 首 先 要 切 换 到 数 据 库 操 作 视 图 如 果 前 面 创 建 的 MySQL 已 经 被 删 除, 则 需 要 首 先 创 建 该 连 接 在 数 据 库 浏 览 器 中, 选 中 MySQL 连 接, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Open connection 命 令, 将 打 开 该 连 接 打 开 连 接 后, 选 中 mydb 数 据 库 节 点, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中 选 择 New Table 命 令, 将 弹 出 创 建 数 据 表 的 界 面, 在 其 中 填 写 必 要 信 息 后, 界 面 如 图 7-10 所 示

13 图 7-10 创 建 学 生 表 单 击 Finish 按 钮, 将 完 成 学 生 数 据 表 的 创 建 在 mydb TABLE 节 点 下 将 多 出 一 个 学 生 表 节 点 技 巧 : 如 果 创 建 数 据 表 没 有 发 生 错 误, 但 是 没 有 在 表 格 节 点 下 显 示, 可 以 选 择 TABLE 节 点, 在 右 键 弹 出 菜 单 中 选 择 Refresh 命 令, 执 行 刷 新 操 作, 从 而 显 示 新 创 建 的 数 据 表 7.2.2 创 建 映 射 文 件 程 序 创 建 完 成 学 生 表 后, 我 们 就 可 以 继 续 开 发 操 作 该 数 据 表 的 Hibernate 程 序 选 中 student 数 据 表 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Hibernate Reverse Engineering 命 令, 将 弹 出 创 建 Hibernate 程 序 的 界 面, 如 图 7-10 所 示

图 7-10 创 建 Hibernate 程 序 界 面 其 中 Java src folder 表 示 选 项 创 建 的 Hibernate 程 序 放 在 哪 一 个 项 目 的 src 目 录 下, 单 击 Browse 可 以 选 择, 这 里 选 择 FirstHibernate src 目 录 Java package 表 示 创 建 程 序 所 在 的 包 名, 如 果 在 操 作 前 已 经 创 建 了 包, 则 可 以 单 击 Browse 按 钮 选 择 ; 如 果 没 有 创 建, 则 可 以 自 己 输 入 包 名, 当 创 建 程 序 时 会 将 该 包 同 时 创 建 这 里 输 入 com.sanqing.po, 在 Hibernate 项 目 中 通 常 将 实 体 类 和 映 射 文 件 都 放 在 po 包 下 在 接 下 来 的 界 面 中, 可 以 分 为 三 部 分, 它 们 分 别 创 建 映 射 文 件 实 体 类 和 DAO 类, 它 们 可 以 通 过 该 界 面 同 时 创 建, 这 里 为 了 更 详 细 的 讲 解, 我 们 将 它 们 分 开 创 建 Create POJO<>DB Table mapping information 表 示 是 否 创 建 映 射 文 件, 选 择 该 选 项, 表 示 创 建 在 该 选 项 下, 还 有 具 体 设 置 的 选 项 Create a Hibernate mapping file (*.hbm.xml) for each database table 选 项 表 示 为 每 一 个 数 据 表 创 建 一 个 以.hbm.xml 为 结 尾 的 映 射 文 件 ; Add hibernate mapping annotations to POJO (Hibernate 3.2 only) 选 项 表 示 通 过 注 解 的 方 式 创 建 数 据 表 映 射, 它 只 能 在 3.2 版 本 的 Hibernate 框 架 中 使 用 Update Hibernate configuration with mapping resource location 表 示 是 否 在 Hibernate 的 配 置 文 件 中 对 映 射 文 件 进 行 配 置, 默 认 是 选 择 的, 这 样 就 不 再 需 要 自 己 手 动 配 置 后 面 创 建 其 他 Hibernate 程 序 的 选 项 先 不 进 行 选 择, 单 击 Finish 按 钮, 将 完 成 映 射 文 件 的 创 建, 并 且 弹 出 一 个 询 问 是 否 进 入 Hibernate 操 作 视 图 的 对 话 框 说 明 :Hibernate 操 作 视 图 是 MyEclipse 中 为 了 开 发 Hibernte 项 目 和 程 序 定 义 的 视 图, 由 于 习 惯 问 题, 该 视 图 使 用 的 并 不 多 的 这 里 同 样 不 使 用 该 视 图, 而 是 切 换 到 最 常 用 的 MyEclipse 通 用 开 发 视 图 中

15 切 换 到 MyEclipse 通 用 视 图 中 后, 可 以 在 包 资 源 管 理 器 中 看 到, 在 FirstHibernate src 目 录 下 创 建 了 com.sanqing.po 包, 并 且 在 该 包 下 创 建 了 一 个 名 称 为 student.hbm.xml 的 文 件, 它 就 是 和 数 据 表 对 应 的 映 射 文 件 双 击 打 开 该 文 件, 在 编 辑 区 中 有 两 种 查 看 方 法, 选 择 左 下 角 的 Design 选 项, 将 以 界 面 化 的 形 式 显 示 映 射 信 息, 如 图 7-11 所 示 图 7-11 界 面 化 查 看 映 射 文 件 当 在 映 射 文 件 增 加 更 多 配 置 信 息 时, 可 以 通 过 该 界 面 进 行 添 加 这 里 我 们 主 要 看 一 下 映 射 文 件 的 代 码, 选 择 编 辑 区 左 下 角 的 Source 选 项, 将 可 以 看 到 该 程 序 的 代 码 01 <hibernate-mapping> 02 <class name="com.sanqing.po.student" table="student" catalog="mydb"> 03 <id name="id" type="java.lang.integer"> 04 <column name="id" /> 05 <generator class="identity" /> 06 </id> 07 <property name="name" type="java.lang.string"> 08 <column name="name" length="20" /> 09 </property> 10 <property name="score" type="java.lang.double"> 11 <column name="score" precision="4" /> 12 </property> 13 </class> 14 </hibernate-mapping> 映 射 文 件 的 根 节 点 为 <hibernate-mapping>, 所 有 的 配 置 代 码 都 必 须 放 置 在 该 节 点 之 下 在 第 2 行 定 义 了 一 个 <class> 节 点, 通 过 该 节 点 可 以 让 实 体 类 和 数 据 表 建 立 映 射 关 系, 其 中 table 属 性 指 定 的 就 是 前 面 创 建 的 学 生 数 据 表, catalog 属 性 指 定 的 是 数 据 库 name 属 性 指 定 的 就 是 实 体 类 名 称, 实 体 类 会 在 下 一 小 节 中 讲 解 如 何 创 建

在 第 3 行 定 义 了 一 个 <id> 节 点, 其 中 name 属 性 指 定 主 键 为 实 体 类 中 的 id 属 性,type 属 性 指 定 的 是 id 的 类 型 <column> 节 点 指 定 的 是 数 据 表 中 的 主 键 字 段 名,<generator> 节 点 用 来 指 定 主 键 的 生 成 策 略, 生 成 策 略 的 知 识 会 在 后 面 进 行 讲 解 代 码 第 6 行 至 第 8 行 通 过 <property> 节 点 配 置 了 学 生 表 中 的 其 他 字 段, 分 别 是 姓 名 和 成 绩 字 段 在 创 建 映 射 文 件 界 面 中, 如 果 选 择 了 Update Hibernate configuration with mapping resource location 选 项, 还 会 在 Hibernate.cfg.xml 配 置 文 件 中 对 映 射 文 件 进 行 配 置, 配 置 代 码 为 : <mapping resource="com/sanqing/po/student.hbm.xml" /> 每 有 一 个 映 射 文 件, 就 应 该 多 出 一 条 这 样 的 配 置 注 意 : 对 映 射 文 件 的 配 置 是 可 以 自 动 生 成 的, 如 果 是 手 动 加 入 该 配 置 一 定 要 注 意 其 中 的 resource 属 性 值 的 格 式, 包 名 之 间 不 再 使 用. 连 接, 而 是 使 用 / 连 接 7.2.3 创 建 实 体 类 程 序 创 建 映 射 文 件 后, 继 续 来 看 一 下 如 何 创 建 实 体 类 程 序 使 用 上 一 小 节 同 样 的 操 作 方 式, 打 开 创 建 Hibernate 程 序 的 界 面, 在 其 中 Java src folder 选 项 中 选 择 FirstHibernate src 目 录, 在 Java package 选 项 中 填 写 com.sanqing.po 创 建 Hibernate 程 序 的 界 面 中, Java Data Object (POJO <> DB Table) 选 项 表 示 是 否 创 建 和 数 据 表 相 对 应 的 实 体 类, 选 中 该 选 项, 表 示 创 建 实 体 类 在 该 选 项 中, 还 有 更 详 细 的 创 建 设 置 选 项 Create abstract class 表 示 是 否 创 建 抽 象 类, 通 常 取 消 该 选 项 Base persistent class 表 示 基 本 的 持 久 化 类, 在 普 通 的 Hibernate 项 目 中 也 是 不 需 要 选 择 该 类 的 选 择 后 的 界 面 如 图 7-12 所 示

17 图 7-12 创 建 实 体 类 示 单 击 Finish 按 钮, 将 完 成 实 体 类 的 创 建, 并 且 将 弹 出 一 个 对 话 框, 如 图 7-13 所 图 7-13 确 认 是 否 创 建 对 话 框 注 意 : 弹 出 该 对 话 框 是 因 为 在 选 择 的 包 中 已 经 创 建 了 映 射 文 件, 而 映 射 文 件 是 和 实 体 类 配 对 出 现 的, 所 以 这 时 候 会 提 醒 可 能 覆 盖 原 有 程 序 在 实 际 开 发 中 通 常 将 这 两 个 程 序 同 时 创 建, 也 就 不 会 出 现 该 对 话 框 在 其 中 单 击 OK 按 钮, 跳 过 该 对 话 框 还 会 弹 出 选 择 是 否 更 换 操 作 视 图 的 对 话 框, 这 里 单 击 NO 按 钮, 然 后 手 动 切 换 到 MyEclipse 通 用 视 图 中 在 包 资 源 管 理 中 可 以 看 到, 在 com.sanqing.po 包 下 自 动 生 成 了 名 称 为 Student 的 Java 程 序, 打 开 该 程 序 后, 它 的 代 码 如 下 : 01 package com.sanqing.po; 02 public class Student implements java.io.serializable { 03 private Integer id; 04 private String name; 05 private Double score; 06 public Student() { 07 } 08 public Student(String name, Double score) { 09 this.name = name; 10 this.score = score; 11 } 12 public Integer getid() { 13 return this.id; 14 } 15 public void setid(integer id) { 16 this.id = id; 17 } 18 public String getname() { 19 return this.name; 20 } 21 public void setname(string name) { 22 this.name = name; 23 } 24 public Double getscore() {

25 return this.score; 26 } 27 public void setscore(double score) { 28 this.score = score; 29 } 30 } 其 中 从 第 3 行 到 第 5 行 生 成 了 id 姓 名 和 成 绩 三 个 属 性, 它 们 都 是 根 据 数 据 表 中 的 字 段 自 动 生 成 的 在 第 8 行 中 使 用 非 主 键 属 性 生 成 了 构 造 函 数 从 第 12 行 开 始 为 所 有 的 属 性 生 成 了 Getter 和 Setter 方 法, 这 些 都 是 自 动 生 成 的 说 明 : 在 自 动 生 成 的 实 体 类 中 都 是 使 用 的 基 本 数 据 类 型 的 封 装 类 类 型, 这 和 我 们 手 动 完 成 有 所 不 同 的 但 是 在 功 能 和 调 用 上 它 们 是 没 有 差 别 的, 因 为 在 Java 5.0 版 本 后 有 自 动 装 箱 和 拆 箱 的 特 性 7.2.4 创 建 DAO 程 序 DAO 程 序 中 通 常 不 只 一 个 Java 类 程 序, 在 DAO 程 序 完 成 对 数 据 库 的 增 删 改 查 等 基 本 操 作 在 创 建 Hibernate 创 建 程 序 中, 同 时 也 能 够 完 成 DAO 程 序 的 创 建 在 创 建 Hibernate 程 序 界 面 中, 创 建 DAO 程 序 时, 在 其 中 Java src folder 选 项 中 仍 然 选 择 FirstHibernate src 目 录, 而 在 Java package 选 项 中, 也 就 是 选 择 包 时, 通 常 将 DAO 程 序 放 在 dao 包 中, 所 以 这 里 填 写 com.sanqing.dao 然 后 看 一 下 创 建 DAO 程 序 时 所 用 到 的 选 项 Java Data Access Object (DAO) (Hibernate 3 only) 表 示 是 否 创 建 DAO 程 序, 选 中 表 示 创 建 在 该 选 项 下, 还 有 进 行 更 详 细 设 置 的 选 项 其 中 Generate precise findby methods 表 示 是 否 为 每 一 个 属 性 生 成 findby 方 法, 默 认 是 选 中 的 情 况 如 果 选 中, 例 如 在 学 生 表 中, 就 会 产 生 两 个 分 别 根 据 姓 名 和 成 绩 属 性 查 询 学 生 的 方 法, 具 体 看 后 面 的 代 码 DAO type 表 示 生 成 DAO 程 序 的 类 型, Basic DAO 就 是 最 基 本 的 DAO 程 序, 也 是 这 里 要 创 建 的 Spring DAO 也 是 比 较 常 用 的, 但 是 只 有 Hibernate 和 Spring 整 合 时 才 可 以 创 建 它 JNDI DAO 使 用 的 比 较 少, 在 EJB 开 发 中 可 能 会 用 到 它 Base class 表 示 基 础 DAO 类, 这 里 采 用 默 认 的 类 就 可 以 填 写 好 这 些 信 息 后, 界 面 如 图 7-14 所 示

19 图 7-14 创 建 DAO 程 序 单 击 Finish 按 钮, 将 完 成 Hibernate DAO 程 序 的 创 建 回 到 MyEclipse 通 用 视 图 中, 在 包 资 源 管 理 器 中 可 以 看 到 在 FirstHibernate 项 目 中 创 建 了 com.sanqing.dao 包, 并 且 在 该 包 下 创 建 了 三 个 程 序 首 先 双 击 打 开 IBaseHibernateDAO.java 程 序, 它 的 代 码 为 : 01 package com.sanqing.dao; 02 import org.hibernate.session; 03 public interface IBaseHibernateDAO { 04 public Session getsession(); 05 } 这 是 一 个 非 常 简 单 的 接 口, 在 其 中 定 义 了 获 取 Session 会 话 的 方 法 再 来 双 击 打 开 BaseHibernateDAO.java 程 序, 它 的 代 码 为 : 01 package com.sanqing.dao; 02 import com.sanqing.hb.hibernatesessionfactory; 03 import org.hibernate.session; 04 public class BaseHibernateDAO implements IBaseHibernateDAO { 05 public Session getsession() { 06 return HibernateSessionFactory.getSession(); 07 } 08 } 在 这 个 类 中 首 先 实 现 了 上 面 的 接 口, 在 第 5 行 中 实 现 了 获 取 Session 会 话 的 方 法 在 第 6 行 中 使 用 到 了 HibernateSessionFactory 类, 它 就 是 在 创 建 Hibernate 项 目 时 自 动 创 建 的 会 话 工 厂 类, 在 该 类 中 定 义 了 getsession 获 取 Session 对 象 的 方 法, 从 而 获 取 到 操

作 数 据 库 的 Session 对 象 最 后 来 看 一 下 实 际 操 作 数 据 库 的 StudentDAO.java 程 序, 它 的 代 码 是 由 完 成 不 同 数 据 库 操 作 的 方 法 组 成, 这 里 我 们 只 给 出 其 中 的 常 用 方 法 注 意 : 初 始 创 建 DAO 程 序 后, 程 序 中 是 由 错 误 的, 这 是 因 为 我 们 的 DAO 程 序 和 实 体 类 并 不 在 一 个 包 中, 这 时 候 首 先 要 将 实 体 类 导 入 到 DAO 程 序 中, 快 捷 键 为 Ctrl+Shift+O 01 package com.sanqing.dao; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class StudentDAO extends BaseHibernateDAO { 04 private static final Log log = LogFactory.getLog(StudentDAO.class); 05 public static final String NAME = "name"; 06 public static final String SCORE = "score"; 07 public void save(student transientinstance) {// 增 加 学 生 方 法 08 log.debug("saving Student instance"); 09 try { 10 getsession().save(transientinstance);// 调 用 save 保 存 方 法 11 log.debug("save successful"); 12 } catch (RuntimeException re) { 13 log.error("save failed", re); 14 throw re; 15 } 16 } 17 public void delete(student persistentinstance) {// 删 除 学 生 方 法 18 log.debug("deleting Student instance"); 19 try { 20 getsession().delete(persistentinstance);// 调 用 delete 删 除 方 法 21 log.debug("delete successful"); 22 } catch (RuntimeException re) { 23 log.error("delete failed", re); 24 throw re; 25 } 26 } 27 public Student findbyid(java.lang.integer id) { // 根 据 id 主 键 查 询 28 log.debug("getting Student instance with id: " + id); 29 try { 30 Student instance = (Student) getsession().get( 31 "com.sanqing.dao.student", id); 32 return instance; 33 } catch (RuntimeException re) { 34 log.error("get failed", re); 35 throw re; 36 } 37 } 38 public List findall() { // 查 询 全 部

21 39 log.debug("finding all Student instances"); 40 try { 41 String querystring = "from Student"; 42 Query queryobject = getsession().createquery(querystring); 43 return queryobject.list(); 44 } catch (RuntimeException re) { 45 log.error("find all failed", re); 46 throw re; 47 } 48 } 49 } 其 中 第 7 行 定 义 了 save 保 存 学 生 信 息 方 法, 其 中 重 要 代 码 是 第 10 行 调 用 Session 会 话 对 象 中 的 save 方 法, 从 而 完 成 保 存 功 能 第 17 行 定 义 了 删 除 学 生 学 生 信 息 的 方 法, 其 中 第 20 行 中 调 用 Session 会 话 对 象 中 的 delete 方 法, 从 而 完 成 删 除 功 能 在 第 27 行 定 义 了 findbyid 根 据 id 查 询 学 生 的 方 法, 在 第 30 行 中 调 用 get 方 法 完 成 相 应 功 能 注 意 :get 方 法 中 给 出 的 参 数 并 不 是 数 据 表, 而 是 实 体 类 的 全 称 类 名 后 面 的 id 参 数 也 是 实 体 类 中 对 应 的 属 性 名 在 第 38 行 中 定 义 了 findall 查 询 所 有 学 生 信 息 的 方 法, 在 Session 会 话 中 并 没 有 定 义 相 应 功 能, 而 是 首 先 调 用 createquery 方 法 获 得 Query 对 象, 然 后 使 用 Query 对 象 调 用 list 方 法, 从 而 获 得 由 所 有 查 询 到 的 学 生 对 象 组 成 的 集 合 第 41 行 的 字 符 串 就 是 HQL 语 句, 在 后 面 会 对 它 进 行 详 细 的 讲 解 说 明 : 在 Session 会 话 类 中 对 数 据 库 的 操 作 进 行 了 非 常 好 的 封 装, 从 而 在 我 们 调 用 时 只 需 要 调 用 一 个 方 法 就 可 以 完 成 数 据 库 操 作 在 StudentDAO 中 存 在 大 量 的 日 志 操 作 代 码, 但 是 它 们 是 不 影 响 我 们 调 用 的 注 意 : 在 实 际 开 发 中, 通 常 会 将 StudentDAO 程 序 做 为 超 类, 然 后 自 定 义 一 个 子 类, 对 其 中 必 要 的 方 法 进 行 重 写, 因 为 在 自 动 生 成 的 程 序 的 方 法 中 并 没 有 进 行 事 务 操 作, 这 些 需 要 手 动 完 成 7.3 配 置 映 射 文 件 在 前 面 已 经 讲 解 了 Hibernate 项 目 和 程 序 的 创 建, 它 们 对 于 一 般 功 能 的 项 目 来 说 已 经 足 够 了 但 是 对 于 一 些 功 能 比 较 多, 或 者 数 据 表 关 系 比 较 复 杂 的 项 目 来 说, 就 还 需 要 学 习 更 多 的 内 容 它 们 主 要 体 现 在 映 射 文 件 中, 在 该 文 件 中 进 行 更 详 细 的 配 置 7.3.1 细 节 配 置 细 节 配 置 包 括 映 射 类 主 键 生 成 策 略 多 对 多 一 对 一 等 配 置 在 创 建 Hibernate 创 建 界 面 中, 不 管 是 创 建 映 射 文 件, 还 是 创 建 实 体 类 DAO 程 序 等 都 是 直 接 单 击 Finish 按 钮 完 成 操 作 在 该 界 面 中, 也 可 以 单 击 Next 按 钮, 从 而 进 入 细 节 配 置 的 界 面, 如

图 7-15 所 示 图 7-15 细 节 配 置 对 于 一 般 项 目 来 说, 这 里 的 选 项 都 是 可 以 采 用 默 认 值 的 其 中 Rev-eng settings file 表 示 通 过 一 个 文 件 保 存 配 置 和 选 项, 如 果 不 指 定 这 样 的 一 个 文 件, 系 统 也 会 自 动 创 建 Custom rev-eng strategy 表 示 指 定 自 定 义 的 生 成 策 略 类, 在 该 类 中 定 义 了 创 建 Hibernate 程 序 时 处 理 过 程 的 选 项 Type Mapping 表 示 在 映 射 属 性 中 使 用 的 是 什 么 类 型 Id Generator 表 示 主 键 id 的 生 成 策 略, 如 果 不 进 行 设 置,Hibernate 框 架 会 自 动 指 定 一 个 最 合 适 的 在 下 拉 列 表 中, 有 很 多 个 选 项, 这 里 我 们 对 其 中 几 个 常 用 的 生 成 策 略 进 行 讲 解, 读 者 可 以 根 据 实 际 情 况 和 开 发 要 求 来 选 择 使 用 increment 标 识 生 成 策 略 : 该 生 成 策 略 是 由 Hibernate 在 内 存 中 生 成 主 键, 每 次 增 量 为 1, 不 依 赖 于 底 层 的 数 据 库, 所 以 所 有 的 数 据 库 都 可 以 使 用 UUID 标 识 生 成 策 略 : 该 生 成 策 略 使 用 一 个 128-bit 的 UUID 算 法 生 成 字 符 串 类 型 的 标 识 符,UUID 被 编 码 成 一 个 32 位 16 进 制 数 字 的 字 符 串, 该 id 的 值 将 会 非 常 大 的 identity 标 识 生 成 策 略 : 该 生 成 策 略 使 用 底 层 数 据 库 来 生 成 标 识 符, 适 用 于 MySQL DB2 MS SQL Server 数 据 库 该 生 成 策 略 用 于 为 long short int 类 型 生 成 唯 一 标 识 sequence 标 识 生 成 策 略 : 该 生 成 策 略 使 用 底 层 数 据 库 提 供 的 序 列 来 生 成 标 识 符 适 用 于 DB2 和 Oracle 数 据 库, 该 生 成 策 略 同 样 用 于 为 long short 或 int 生 成 唯 一 标 识

23 hilo 标 识 生 成 策 略 : 该 生 成 策 略 使 用 一 个 高 / 低 位 算 法 生 成 标 识 符, 给 定 一 个 表 和 字 段 做 为 高 位 值 的 来 源 i 该 策 略 将 id 主 键 值 的 产 生 源 分 成 两 部 分, 分 别 是 DB 和 内 存 native 标 识 生 成 策 略 : 该 生 成 策 略 将 根 据 数 据 库 的 支 持 能 力, 来 选 择 使 用 identity, sequence 或 hilo 标 识 生 成 策 略 中 的 一 个 如 果 为 MySQL 或 MS SQL Server 就 选 择 identity 标 识 符 生 成 器 Generate basec typed composite Ids 表 示 是 否 仍 然 使 用 基 本 类 型 来 表 示 复 合 主 键 Generate version and timestamp tags 表 示 名 称 为 version 和 timestamp 的 数 据 表 字 段 是 否 以 <version> 和 <timestamp> 标 记 出 现 Enable many-to-many detection 和 Enable one-to-one detection 选 项 表 示 是 否 能 够 进 行 多 对 多 和 一 对 一 探 测 Customized Type Mappings 表 示 将 指 定 自 定 义 JDBC 类 型 转 换 成 Hibernate 类 型 说 明 : 在 这 些 细 节 配 置 中,id 主 键 生 成 策 略 的 选 择 是 最 重 要 的, 在 实 际 开 发 中 要 灵 活 使 用 这 些 生 成 策 略, 并 能 够 看 懂 项 目 使 用 的 生 成 策 略 7.3.2 数 据 表 和 实 体 类 的 映 射 配 置 在 前 面 自 动 生 成 实 体 类 时, 都 是 根 据 数 据 表 的 表 名 和 字 段 名 自 动 生 成 实 体 类 的 类 名 和 属 性 名 但 是 在 实 际 开 发 中, 开 发 数 据 库 和 开 发 Java 项 目 可 能 并 不 是 一 个 团 队, 这 时 候 可 能 自 动 生 成 的 类 名 和 属 性 名 并 不 符 合 Java 程 序 命 名 规 范 的 例 如 数 据 表 的 名 称 为 db_student, 则 使 用 该 名 称 做 为 实 体 类 的 类 名, 就 会 不 适 合 在 这 种 情 况 下 就 需 要 使 用 到 本 节 讲 解 的 映 射 配 置 在 上 一 小 节 的 细 节 配 置 界 面 中, 单 击 Next 按 钮, 将 进 入 数 据 表 和 实 体 类 映 射 配 置 界 面, 在 其 中 选 中 student 数 据 表 节 点, 界 面 如 图 7-16 所 示

7-16 数 据 表 和 实 体 类 映 射 该 界 面 大 致 可 以 分 为 三 部 分, 左 上 部 分 是 显 示 数 据 表 和 表 中 的 字 段, 右 上 部 分 中 是 进 行 的 实 体 类 映 射, 先 来 看 这 两 部 分 选 中 student 数 据 表 节 点, 在 右 边 将 出 现 对 数 据 表 进 行 映 射 的 配 置 其 中 Name 表 示 数 据 表 名, Catalog 表 示 数 据 表 所 在 的 数 据 库 名, Class name 表 示 映 射 实 体 类 的 包 含 包 名 的 完 整 类 名, Id Generator 表 示 该 表 主 键 的 生 成 策 略, 主 键 生 成 策 略 在 上 一 小 节 中 已 经 详 细 的 讲 解 选 中 id 主 键 节 点, 则 右 半 部 分 将 变 为 对 主 键 进 行 映 射 配 置 的 界 面, 如 图 7-17 所 示

25 图 7-17 对 主 键 进 行 映 射 配 置 其 中 Name 表 示 id 主 键 的 名 称 Exclude column from reverse engineering 表 示 是 否 在 实 体 类 中 忽 略 主 键 对 应 属 性 的 创 建 Property name 表 示 id 主 键 对 应 的 实 体 类 属 性 名 JDBC type 和 Hibernate type 表 示 id 主 键 对 应 的 JDBC 和 Hibernate 的 类 型 选 中 普 通 字 段 节 点, 这 里 以 name 字 段 为 例, 则 右 半 部 分 将 变 为 对 普 通 字 段 进 行 映 射 配 置 的 界 面, 其 中 选 项 是 和 设 置 id 主 键 相 同 的, 这 里 就 不 再 重 复 讲 解 在 具 体 映 射 配 置 界 面 的 下 半 部 分 还 有 几 个 非 常 重 要 的 选 项 其 中 Include referenced tables (A->B) 和 Include referencing tables (A<-B) 表 示 当 数 据 表 中 具 有 外 键 连 接 其 他 数 据 表 时, 是 否 为 连 接 的 数 据 表 也 进 行 映 射 配 置 Generate support for ListedTable(fk)->UnlistedTable 和 Generate support for UnlistedTable(fk)->ListedTable 选 项 表 示 是 否 生 成 关 联 到 当 前 数 据 表 的 数 据 表 对 应 的 实 体 类 7.4 使 用 注 解 方 式 开 发 Hibernate 程 序 在 JDK 5.0 版 本 中 多 出 了 一 种 新 特 性 技 术, 那 就 是 注 解, 它 的 英 文 名 称 为 Annotations 在 Hibernate 3.2 版 本 中 也 增 加 了 通 过 注 解 方 式 开 发 Hibernate 程 序 的 方 式 通 过 使 用 注 解, 能 够 代 替 映 射 文 件, 从 而 也 能 够 让 实 体 类 和 数 据 表 建 立 连 接 注 意 : 注 解 是 一 把 双 刃 剑, 通 过 注 解 可 能 节 省 大 量 的 代 码, 但 是 大 部 分 的 程 序 员 已 经 习 惯 了 通 过 映 射 文 件 的 方 式 开 发, 所 以 在 开 发 中 要 按 照 开 发 要 求 来 进 行 选 择 使 用 7.4.1 创 建 数 据 表 通 过 注 解 方 式 开 发 Hibernate 程 序, 改 变 的 只 是 实 体 类 和 映 射 文 件, 映 射 文 件 将 不

再 需 要, 而 是 在 实 体 类 中 加 入 注 解 对 于 数 据 库 和 DAO 程 序 而 言, 是 没 有 任 何 改 变 的 在 使 用 这 种 方 式 开 发 Hibernate 程 序 时, 同 样 要 首 先 创 建 数 据 表, 这 里 以 老 师 表 为 例, 它 的 创 建 界 面 如 图 7-18 所 示 图 7-18 创 建 老 师 表 在 老 师 表 中 创 建 了 id 主 键, 以 及 name 姓 名 字 段 和 age 年 龄 字 段 7.4.2 使 用 注 解 开 发 在 MyEclipse 的 数 据 库 视 图 中, 选 中 teacher 数 据 表 字 节, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Hibernate Reverse Engineering 命 令, 将 弹 出 创 建 Hibernate 程 序 的 界 面, 在 其 中 选 择 使 用 注 解 选 项, 界 面 如 图 7-19 所 示

27 图 7-19 使 用 注 解 开 发 其 中 选 中 Add hibernate mapping annotations to POJO (Hibernate 3.2 only) 选 项, 就 表 示 通 过 注 解 方 式 建 立 和 数 据 表 的 映 射 配 置 选 中 该 选 项 后, 则 Java Data Object (POJO <> DB Table) 选 项 将 自 动 变 为 选 中 的 状 态, 并 且 不 能 取 消 这 是 因 为 注 解 必 须 配 置 在 实 体 类 中 单 击 Finish 按 钮, 将 完 成 通 过 注 解 方 式 创 建 的 实 体 类 切 换 到 MyEclipse 通 用 视 图 中, 在 com.sanqing.po 包 下 可 以 看 出 多 出 了 一 个 teacher.java 程 序, 它 的 代 码 为 : 01 package com.sanqing.po; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 @Entity // 注 解 该 类 为 Hibernate 实 体 类 04 @Table(name = "teacher", catalog = "mydb") // 注 解 映 射 的 数 据 表 05 public class Teacher implements java.io.serializable { 06 private Integer id; 07 private String name; 08 private Integer age; 09 public Teacher() { 10 } 11 public Teacher(String name, Integer age) { 12 this.name = name; 13 this.age = age; 14 } 15 @Id // 注 解 实 体 类 标 识 16 @GeneratedValue(strategy = IDENTITY) // 注 解 主 键 生 成 策 略

17 @Column(name = "id", unique = true, nullable = false) // 注 解 字 段 18 public Integer getid() { 19 return this.id; 20 } 21 public void setid(integer id) { 22 this.id = id; 23 } 24 @Column(name = "name", length = 20) 25 public String getname() { 26 return this.name; 27 } 28 public void setname(string name) { 29 this.name = name; 30 } 31 @Column(name = "age") 32 public Integer getage() { 33 return this.age; 34 } 35 public void setage(integer age) { 36 this.age = age; 37 } 38 } 其 中 第 3 行 使 用 @Entity 注 解 实 体 类, 从 而 将 一 个 普 通 类 定 义 成 Hibernate 的 实 体 类, 也 就 是 和 数 据 表 相 对 应 的 类 在 该 注 解 中 可 以 有 name 属 性, 用 来 设 置 实 体 名, 默 认 值 是 类 名 在 第 4 行 中 使 用 @Table(name = "teacher", catalog = "mydb") 对 实 体 类 进 行 进 一 步 注 解, 其 中 name 属 性 指 定 的 是 映 射 的 数 据 表,catalog 属 性 指 定 数 据 表 所 在 的 数 据 库 第 15 行 中 使 用 @Id 对 实 体 类 中 的 标 识 进 行 注 解, 它 对 应 数 据 表 中 的 主 键 第 16 行 中 使 用 @GeneratedValue(strategy = IDENTITY) 来 覆 盖 主 键 的 默 认 生 成 策 略, 其 中 strategy 属 性 指 定 主 键 标 识 生 成 策 略,IDENTITY 表 示 由 数 据 库 自 动 设 置 在 第 17 行 24 行 和 31 行 都 是 使 用 到 了 @Column 注 解, 通 过 该 注 解 可 以 让 实 体 类 中 的 属 性 和 数 据 表 中 的 字 段 建 立 映 射 关 系, 其 中 name 属 性 指 定 的 就 是 字 段 名 7.4.3 对 注 解 方 式 的 实 体 类 进 行 配 置 在 使 用 映 射 文 件 的 方 式 开 发 Hibernate 程 序 时, 需 要 在 hibernate.cfg.xml 配 置 文 件 中 对 映 射 文 件 程 序 进 行 配 置 使 用 注 解 方 式 开 发 Hibernate 程 序 时, 并 不 会 产 生 映 射 文 件, 但 是 在 hibernate.cfg.xml 配 置 文 件 仍 然 要 进 行 配 置, 这 里 是 对 实 体 类 进 行 配 置 通 过 上 面 的 自 动 生 成 操 作, 将 自 动 在 hibernate.cfg.xml 配 置 文 件 中 对 实 体 类 进 行 配 置, 自 动 生 成 的 配 置 代 码 为 : <mapping class="com.sanqing.po.teacher" /> 在 这 里 同 样 也 是 使 用 <mapping> 标 记, 然 后 使 用 class 属 性 指 定 实 体 类 的 包 含 包 名 的 全 称 类 名 在 包 名 和 类 名 之 间 使 用. 就 可 以, 而 不 需 要 使 用 /

29 对 于 Hibernate 中 的 DAO 程 序 来 说, 不 管 使 用 映 射 文 件 方 式, 还 是 注 解 方 式, 是 没 有 区 别 的 这 里 就 不 在 讲 解 DAO 程 序 的 创 建 7.5 进 行 HQL 语 句 编 辑 HQL 的 全 称 为 Hibernate Query Language, 直 接 翻 译 就 是 Hibernate 查 询 语 言 HQL 语 句 和 SQL 语 句 非 常 类 似, 不 同 的 是 HQL 是 面 向 对 象 的,HQL 所 操 作 的 都 是 持 久 对 象, 而 不 是 数 据 库 表 在 MyEclipse 中, 集 成 了 用 于 对 HQL 语 句 进 行 编 写 的 编 辑 器, 在 本 节 中 主 要 讲 解 该 编 辑 器 的 使 用 7.5.1 启 动 HQL 编 辑 器 在 包 资 源 管 理 器 中, 选 中 要 进 行 HQL 语 句 编 辑 的 项 目 节 点, 例 如 这 里 选 中 FirstHibernate 项 目 节 点 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 MyEclipse Open HQL Editor 命 令, 将 首 先 弹 出 确 认 是 否 切 换 到 Hibernate 操 作 视 图 的 对 话 框, 如 图 7-20 所 示 图 7-20 是 否 切 换 视 图 在 前 面 的 讲 解 中, 当 弹 出 该 对 话 框 时, 通 常 选 择 不 切 换, 但 是 当 进 行 HQL 语 句 编 辑 时 最 好 选 择 切 换, 因 为 在 原 视 图 中 很 多 界 面 是 看 不 到 的 切 换 后 的 视 图 界 面 如 图 7-21 所 示

图 7-21 Hibernate 开 发 视 图 该 视 图 界 面 是 比 较 复 杂 的, 大 致 可 以 分 为 六 部 分, 位 于 中 间 的 就 是 HQL 语 句 编 辑 器 在 编 辑 器 中, 是 运 行 HQL 语 句 按 钮, 是 刷 新 按 钮, 是 用 于 选 择 操 作 项 目 的 下 拉 列 表, 是 选 择 得 到 最 大 运 行 记 录 数 选 项 而 在 左 部 分 中, 左 上 部 分 是 数 据 库 连 接 浏 览 器 界 面, 坐 下 部 分 是 Java 项 目 的 包 资 源 管 理 器 界 面 其 他 部 分 在 讲 解 知 识 时 进 行 讲 解 7.5.2 执 行 HQL 语 句 在 Hibernate 的 DAO 程 序 中 已 经 看 过 HQL 语 句 的 使 用, 在 其 中 做 为 Session 对 象 调 用 createquery 方 法 时 的 参 数, 从 而 获 取 Query 对 象 然 后 使 用 Query 对 象 调 用 list 方 法 从 而 获 取 查 询 结 果 对 象 组 成 的 集 合 和 编 辑 SQL 语 句 一 样, 编 辑 HQL 语 句 的 作 用 就 是 首 先 验 证 HQL 没 有 问 题 后, 然 后 将 它 加 入 到 DAO 程 序 中 在 执 行 HQL 语 句 之 前, 我 们 首 先 要 向 数 据 库 中 加 入 测 试 使 用 的 数 据, 例 如 这 里 以 学 生 表 为 例 插 入 测 试 数 据 然 后 在 HQL 语 句 编 辑 器 中, 输 入 如 下 代 码 : from Student 其 中 from 是 固 定 的, Student 对 应 的 是 FirstHibernate 项 目 中 的 学 生 实 体 类 类 名 注 意 :HQL 语 句 是 对 持 久 化 对 象 进 行 操 作 的, 而 不 是 对 数 据 表 中 的 记 录 所 以 在 HQL 语 句 中 都 是 和 实 体 类 相 关 的 内 容 在 编 辑 区 中, 单 击 按 钮, 将 运 行 HQL 语 句, 并 在 中 下 部 分 界 面 的 Hibernate

31 Query Result 选 项 卡 中 将 查 询 得 到 学 生 对 象 显 示 出 来, 如 图 7-22 所 示 图 7-22 查 询 得 到 对 象 其 中 com.sanqing.po.student@e24a2 等 信 息 就 是 查 询 出 来 的 学 生 对 象, 选 中 该 对 象 在 右 上 部 分 的 Properties 选 项 卡 中 将 把 该 对 象 的 具 体 属 性 值 显 示 出 来, 如 图 7-23 所 示 图 7-23 查 询 具 体 信 息 其 中 Identifier 表 示 对 象 中 的 标 识 属 性 Properties 表 示 普 通 属 性, 这 里 包 括 name 名 称 和 score 成 绩 两 个 属 性 在 Value 栏 中 将 这 些 属 性 值 显 示 出 来 HQL 语 句 并 不 能 直 接 操 作 数 据 库, 它 需 要 在 Hibernate 框 架 中 被 转 换 为 SQL 语 句 才 能 够 操 作 数 据 库 在 Hibernate 视 图 中 还 会 将 转 换 后 的 SQL 语 句 显 示 出 来 在 右 下 部 分 的 Hibernate Dynamic Query Translator 选 项 卡 中 将 显 示 出 转 换 后 的 SQL 语 句, 如 图 7-24 所 示

图 7-24 转 换 后 SQL 语 句 说 明 : 由 于 是 框 架 自 动 转 换, 所 以 转 换 后 的 SQL 语 句 是 和 程 序 员 写 出 的 SQL 语 句 有 所 不 同 的 在 自 动 生 成 的 SQL 语 句 中, 大 量 使 用 到 别 名, 例 如 student0_ 是 数 据 表 的 别 名, name10_ 是 name 字 段 的 别 名 7.5.3 HQL 语 句 中 的 子 句 设 置 在 上 一 小 节 讲 解 的 是 一 条 最 简 单 的 HQL 语 句, 通 过 该 语 句 讲 解 了 该 如 何 运 行 HQL 语 句 我 们 可 以 在 HQL 语 句 中 加 入 元 素, 从 而 进 行 更 详 细 的 查 询 在 HQL 语 句 中 可 以 加 入 select 子 句, 从 而 查 询 指 定 属 性 的 信 息, 例 如 : 例 如 : select name,score from Student 将 只 查 询 学 生 对 象 中 的 姓 名 和 成 绩 在 HQL 语 句 中, 也 可 以 为 实 体 类 类 名 定 义 别 名, 在 查 询 属 性 时 就 可 以 使 用 该 别 名 select stu.name,stu.score from Student as stu 写 HQL 语 句 时, 和 写 Java 程 序 非 常 类 似 的 当 在 实 体 类 别 名 后 写 入. 后, 会 给 出 可 能 操 作 属 性 的 提 示 在 HQL 语 句 中 也 可 以 使 用 where 子 句, 从 而 给 出 查 询 条 件 例 如 : select name,score from Student where id=1 将 只 查 询 id 值 为 1 的 学 生 对 象, 从 而 将 该 对 象 中 的 姓 名 和 成 绩 属 性 值 查 询 出 来 说 明 : 这 里 只 给 出 常 用 的 几 种 字 句, 在 大 部 分 项 目 中 已 经 足 够 了 如 果 想 了 解 更 多 的 子 句, 例 如 分 组 排 序 等 可 以 查 看 Hibernate 相 关 资 料 7.5.4 为 HQL 语 句 设 置 参 数 在 实 际 开 发 中, 通 过 给 出 的 查 询 条 件 并 不 是 固 定 的, 而 是 通 过 参 数 传 递 条 件 值 例 如 查 询 某 学 生 的 具 体 信 息, 该 学 生 的 名 称 并 不 是 固 定 的 这 时 候 就 需 要 为 HQL 语 句 设 置 参 数 在 SQL 语 句 中 可 以 通 过 位 置 和 属 性 名 两 种 方 式 完 成 参 数 设 置, 但 是 在 HQL 语 句 中 只 支 持 参 数 名 的 方 式 参 数 的 基 本 格 式 为 :name, 例 如 :

33 from Student where id= :idname 在 Hibernate 的 DAO 程 序 中, 就 可 以 通 过 Query 对 象 中 的 setxxx 方 法 来 完 成 参 数 的 赋 值, 其 中 XXX 表 示 为 不 同 的 查 询 参 数 类 型 在 MyEclipse 的 HQL 语 句 编 辑 器 中 也 可 以 对 具 有 参 数 的 HQL 语 句 进 行 测 试, 这 时 候 就 需 要 为 它 定 义 测 试 参 数 值 在 HQL 编 辑 区 中 输 入 上 面 的 HQL 语 句, 然 后 选 择 右 上 部 分 的 Query Parameters 选 项 卡, 如 图 7-25 所 示 图 7-25 设 置 参 数 界 面 在 界 面 的 右 上 角 中 有 三 个 按 钮, 是 添 加 参 数 按 钮, 是 删 除 参 数 按 钮, 是 禁 用 参 数 按 钮 在 其 中 单 击 添 加 参 数 按 钮, 在 其 中 将 自 动 将 Name 栏 和 Type 栏 填 写 好, 在 Value 栏 中 可 以 填 写 用 于 测 试 的 参 数 值, 在 这 里 输 入 1 在 HQL 编 辑 器 中, 单 击 运 行 按 钮, 将 执 行 具 有 参 数 的 HQL 语 句, 运 行 结 果 如 图 7-26 所 示 图 7-26 显 示 运 行 结 果 从 运 行 结 果 中 可 以 看 到 只 将 id 为 1 的 学 生 对 象 查 询 出 来 选 中 该 对 象, 可 以 在 在 右

上 部 分 的 Properties 选 项 卡 中 查 看 到 该 对 象 的 id 值 为 1 7.6 使 用 Hibernate 替 换 论 坛 项 目 的 数 据 访 问 层 在 Struts 一 章 的 最 后 开 发 了 一 个 论 坛 项 目, 其 中 的 数 据 访 问 层 是 使 用 JDBC 开 发 的 在 本 章 中 学 习 完 Hibernate 后, 我 们 就 可 以 将 其 中 的 数 据 访 问 层 替 换 成 Hibernate 技 术 开 发 7.6.1 准 备 工 作 在 执 行 该 操 作 前, 我 们 首 先 复 制 一 下 项 目 在 包 资 源 管 理 器 中, 选 中 BBS 项 目 节 点, 使 用 Ctrl+C 快 捷 键 进 行 复 制, 然 后 在 空 白 处 使 用 Ctrl+V 快 捷 键 粘 贴, 将 弹 出 输 入 复 制 后 项 目 名 称 的 界 面, 如 图 7-27 所 示 图 7-27 复 制 项 目 在 其 中 Project name 选 项 中 输 入 BBSOfHibernate 做 为 新 项 目 的 名 称 单 击 OK 按 钮 后 将 完 成 项 目 的 复 制, 在 包 资 源 管 理 器 中 可 以 看 到 多 出 了 一 个 名 称 为 BBSOfHibernate, 这 里 我 们 就 对 它 进 行 操 作 因 为 我 们 是 替 换 其 中 的 数 据 访 问 层, 所 以 要 将 其 中 的 原 有 JDBC 开 发 的 数 据 访 问 层 删 除 掉 选 项 将 其 中 的 bean dao util 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Delete 命 令, 将 弹 出 确 定 删 除 的 对 话 框, 如 图 7-28 所 示

35 图 7-28 确 定 是 否 删 除 单 击 OK 按 钮, 将 把 选 中 的 包 和 包 下 的 类 全 部 删 除 删 除 后, 项 目 将 会 发 生 错 误, 这 是 以 为 其 中 调 用 的 数 据 访 问 层 类 已 经 消 失 因 为 我 们 这 个 项 目 将 对 MySQL 中 的 bbs 数 据 库 进 行 操 作, 所 以 我 们 需 要 对 数 据 库 视 图 中 的 连 接 进 行 修 改, 选 中 MySQL 连 接, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Edit 命 令, 将 弹 出 的 对 连 接 信 息 修 改 的 操 作 界 面, 修 改 其 中 的 URL, 界 面 如 图 7-29 所 示 图 7-29 修 改 连 接 信 息 注 意 : 修 改 连 接 时, 必 须 要 首 先 关 闭 连 接 当 然 修 改 后, 不 要 忘 记 再 打 开 7.6.2 为 论 坛 项 目 加 入 Hibernate 框 架 支 持 在 前 面 讲 解 Hibernate 项 目 创 建 时, 是 对 Java 项 目 进 行 操 作 的 同 样 对 于 Java Web 项 目 来 说, 也 需 要 加 入 Hibernate 框 架 支 持 选 中 BBSOfHibernate 项 目, 在 MyEclipse 的 菜 单 中, 选 择 MyEclipse Project Capabilities Add Hibernate Capabilities 命 令, 将 弹 出 加 入 支 持 操 作 的 界 面 在 该 项 目 中 我 们 采 用 最 通 用 的 映 射 文 件 方 式 创 建, 所 以 不 选 中 Enable Hibernate Annotations Support 选 项 和 Select the libraries to add to the buildpath 中 的 第 一 个 选 项, 选 择 后 的 界 面 如 图 7-30 所 示

图 7-30 向 论 坛 项 目 中 加 入 类 库 单 击 Next 按 钮, 将 弹 出 创 建 Hibernate 配 置 文 件 的 界 面, 保 持 默 认 选 择, 如 图 7-31 所 示 图 7-31 Hibernate 配 置 文 件 注 意 : 虽 然 Hibernate 配 置 文 件 目 前 在 src 目 录 下, 但 是 当 发 布 Web 项 目 后, 该 文

37 件 将 位 于 WebRoot WEB-INF classes 目 录 下 这 是 由 MyEclipse 中 的 Web 项 目 的 特 性 决 定 的 单 击 Next 按 钮, 将 弹 出 建 立 数 据 库 连 接 的 界 面, 在 其 中 选 择 MySQL 连 接, 如 图 7-32 所 示 图 7-32 建 立 和 论 坛 数 据 库 的 连 接 其 中 Commect URL 选 项 中 将 变 为 和 bbs 数 据 库 连 接 的 URL, 如 果 不 修 改 数 据 库 视 图 中 的 视 图, 这 里 可 能 指 向 其 他 数 据 库 单 击 Next 按 钮, 将 弹 出 创 建 Hibernate 会 话 工 厂 的 程 序 的 界 面, 在 其 中 创 建 它 所 在 的 com.sanqing.hb 包 后, 界 面 如 图 7-33 所 示

图 7-33 创 建 Hibernate 会 话 工 厂 单 击 Finish 按 钮, 将 完 成 Hibernate 框 架 支 持 的 操 作 7.6.3 创 建 Hibernate 数 据 访 问 层 接 下 来 就 是 开 发 最 关 键 的 Hibernate 技 术 的 数 据 访 问 层 将 MyEclipse 的 视 图 切 换 到 数 据 库 视 图, 在 数 据 库 浏 览 器 中, 选 中 MySQL Connected to MySQL bbs TABLE topic 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Hibernate Reverse Engineering 命 令, 将 弹 出 创 建 Hibernate 程 序 的 界 面, 在 其 中 选 择 创 建 映 射 文 件 实 体 类 和 DAO 程 序, 其 界 面 如 图 7-34 所 示

39 图 7-34 创 建 数 据 访 问 层 这 里 并 不 需 要 进 行 更 详 细 的 配 置, 实 体 类 和 数 据 表 的 映 射 也 采 用 默 认 选 择, 所 以 这 里 可 以 直 接 单 击 Finish 按 钮, 完 成 Hibernate 程 序 的 创 建 注 意 : 在 有 些 公 司 和 规 范 中, 规 定 DAO 程 序 和 实 体 类 不 放 在 同 一 个 包 下, 当 有 该 规 定 时, 就 需 要 将 它 们 分 开 创 建, 这 个 在 前 面 已 经 讲 解 7.6.4 为 DAO 程 序 加 入 事 务 操 作 Hibernate 是 对 JDBC 的 轻 量 级 封 装, 它 本 身 不 支 持 事 务 的, 所 以 在 进 行 数 据 库 操 作 时, 要 进 入 事 务 处 理 代 码 在 Hibernate 中, 当 打 开 Session 会 话 后, 将 关 闭 事 务 自 动 提 交, 这 时 候 需 要 自 己 手 动 提 交, 这 样 才 能 够 使 数 据 保 存 到 数 据 库 中 对 于 增 删 改 查 数 据 库 操 作 而 言, 其 中 查 询 时 不 需 要 进 行 事 务 处 理, 但 是 对 于 增 加 删 除 和 修 改 来 说, 就 必 须 进 行 事 务 处 理 在 论 坛 项 目 中 有 发 表 主 题 和 删 除 主 题 两 个 必 须 要 进 行 事 务 处 理 的 方 法 所 以 这 里 定 义 一 个 子 类, 让 它 继 承 自 动 生 成 的 TopicDAO 程 序, 在 其 中 重 写 需 要 事 务 处 理 的 方 法 在 包 资 源 管 理 器 中, 选 中 com.sanqing.dao 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Class 命 令, 将 弹 出 创 建 类 的 界 面, 在 其 中 输 入 类 名 为 TopicDAOImpl, 选 择 继 承 TopicDAO 类, 界 面 如 图 7-35 所 示

图 7-35 创 建 DAO 程 序 子 类 单 击 Finish 按 钮, 将 完 成 TopicDAOImpl 程 序 的 创 建, 在 编 辑 区 中 将 打 开 该 程 序 将 鼠 标 焦 点 放 在 类 体 中, 单 击 鼠 标 右 键, 在 菜 单 中 选 择 Source Override/Implement Methods 命 令, 将 弹 出 重 写 方 法 的 界 面, 在 其 中 选 择 delete 和 save 方 法, 如 图 7-36 所 示 图 7-36 选 择 重 写 的 方 法 单 击 OK 按 钮, 将 完 成 两 个 方 法 的 重 写, 修 改 其 中 的 方 法, 加 入 事 务 操 作 的 代

码, 则 TopicDAOImpl 程 序 的 完 整 代 码 如 下 : 01 package com.sanqing.dao; 02 import org.apache.commons.logging.log; 03 import org.apache.commons.logging.logfactory; 04 public class TopicDAOImpl extends TopicDAO { 05 private static final Log log = LogFactory.getLog(TopicDAO.class); 06 @Override 07 public void save(topic transientinstance) { 08 log.debug("saving Topic instance"); 09 try { 10 getsession().begintransaction(); // 开 启 事 务 11 getsession().save(transientinstance); 12 getsession().gettransaction().commit(); // 提 交 事 务 13 log.debug("save successful"); 14 } catch (RuntimeException re) { 15 log.error("save failed", re); 16 getsession().gettransaction().rollback(); // 回 滚 17 throw re; 18 } 19 } 20 @Override 21 public void delete(topic persistentinstance) { 22 log.debug("deleting Topic instance"); 23 try { 24 getsession().begintransaction(); // 开 启 事 务 25 getsession().delete(persistentinstance); 26 getsession().gettransaction().commit(); // 提 交 事 务 27 log.debug("delete successful"); 28 } catch (RuntimeException re) { 29 log.error("delete failed", re); 30 getsession().gettransaction().rollback(); // 回 滚 31 throw re; 32 } 33 } 34 } 41 其 中 第 10 行 使 用 获 取 到 的 Session 会 话 对 象 调 用 begintransaction 方 法 从 而 开 启 事 务 当 执 行 完 数 据 库 操 作 后, 第 12 行 中 调 用 commit 方 法 进 行 提 交 事 务, 从 而 将 数 据 保 存 到 数 据 库 中 当 中 间 发 生 异 常 后, 将 进 行 异 常 处 理, 将 执 行 第 16 行 的 rollback 方 法, 从 而 进 行 回 滚 操 作 说 明 : 这 时 候 项 目 中 还 是 会 有 错 误 的, 这 是 因 为 原 Topic 主 题 类 和 目 前 的 Topic 实 体 类 并 不 在 同 一 个 包 下 打 开 出 错 的 程 序, 执 行 组 织 导 入 操 作 就 可 以 了, 快 捷 键 是 Ctrl+Shift+O 由 于 原 Topic 类 中 表 示 发 表 时 间 时 使 用 的 是 Date 类 型, 而 Hibernate 自 动 生 成 的 Topic 类 中 使 用 的 Timestamp 类 型 Timestamp 类 是 Date 类 的 子 类, 必 要 的 地 方 进 行 修 改, 具 体 修 改 看 光 盘 代 码

7.6.5 修 改 项 目 的 访 问 URL 因 为 我 们 的 项 目 是 复 制 原 有 项 目 的, 虽 然 项 目 的 名 称 修 改 了, 但 是 当 该 项 目 发 布 到 服 务 器 后, 访 问 的 URL 地 址 是 修 改 的 这 时 候 访 问 BBSOfHibernate 项 目 时, 访 问 地 址 将 是 : http://localhost:8080/bbs 这 并 不 是 我 们 想 要 的, 所 以 接 下 来 将 修 改 该 项 目 的 URL 在 包 资 源 管 理 器 中, 选 中 BBSOfHibernate 项 目 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Properties 命 令, 将 弹 出 对 项 目 设 置 的 界 面, 在 其 中 选 择 MyEclipse Web 节 点, 界 面 如 图 7-37 所 示 图 7-37 修 改 访 问 URL 其 中 Web Context-root 选 项 就 是 访 问 项 目 的 URL, 将 其 中 的 /BBS 修 改 为 /BBSOfHibernate, 单 击 OK 按 钮, 将 完 成 项 目 URL 的 修 改 7.6.6 发 布 和 运 行 项 目 发 布 和 运 行 Java Web 的 项 目 都 是 非 常 类 似 的, 不 管 使 用 什 么 框 架 开 发 首 先 要 将 项 目 部 署 到 应 用 服 务 器 中, 例 如 Tomcat 6.x 运 行 Tomcat 6.x 应 用 服 务 器, 启 动 成 功 后, 打 开 浏 览 器 中, 输 入 如 下 地 址 : http://localhost:8080/bbsofhibernate/ 其 中 BBSOfHibernate/ 就 是 上 一 小 节 修 改 的 项 目 访 问 URL 因 为 开 发 原 BBS 项 目 时 已 经 修 改 了 项 目 首 页, 复 制 后 将 不 会 发 生 改 变 该 地 址 将 直 接 访 问 发 表 主 题 页 面, 浏 览 器 如 图 7-38 所 示

43 图 7-38 发 表 主 题 在 其 中 输 入 发 表 用 户 主 题 标 题 和 主 题 内 容 后, 单 击 发 表 按 钮, 将 进 入 到 显 示 所 有 主 题 的 页 面, 如 图 7-39 所 示 图 7-39 显 示 所 有 主 题 单 击 删 除 超 链 接 后, 将 把 当 前 主 题 删 除, 并 且 再 次 跳 转 会 显 示 所 有 主 题 页 面, 如 图 7-40 所 示

图 7-40 删 除 主 题 说 明 : 该 项 目 开 发 中 有 两 个 需 要 注 意 的 地 方, 首 先 就 是 必 须 重 写 自 动 生 成 的 DAO 程 序, 在 重 写 方 法 中 加 入 事 务 处 理 的 代 码 第 二 点 就 是 不 要 忘 记 修 改 项 目 的 访 问 URL

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 8 章 进 行 Spring 开 发 在 前 面 的 讲 解 中, 已 经 对 Struts 和 Hibernate 框 架 进 行 了 详 细 的 讲 解, 在 本 章 中 继 续 学 习 Spring 框 架 Spring 是 一 种 开 源 框 架, 通 过 使 用 它 可 以 大 大 降 低 企 业 应 用 程 序 的 复 杂 性 Spring 是 一 种 非 常 完 善 的 框 架, 几 乎 涉 及 WEB 开 发 中 的 每 一 层, 但 是 在 开 发 中 通 常 使 用 Spring 开 发 业 务 逻 辑 层 SSH 框 架 是 目 前 最 流 行 的 软 件 开 发 技 术 框 架, 其 中 Spring 的 作 用 就 是 使 Struts 和 Hibernate 建 立 连 接, 使 它 们 更 好 的 分 层 8.1 Spring 概 述 Spring 是 一 种 轻 量 级 框 架, 轻 量 级 是 指 该 框 架 技 术 是 非 入 侵 式 的, 用 Spring 中 开 发 的 系 统 类 不 需 要 依 赖 于 Spring 中 的 类, 它 不 需 要 容 器 支 持 下 面 我 们 主 要 来 讲 解 一 下 在 项 目 中 为 什 么 要 使 用 Spring 框 架, 其 中 最 主 要 的 一 个 原 因 就 是 很 好 的 进 行 分 层 操 作 在 前 面 的 项 目 中, 我 们 都 是 通 过 工 厂 类 的 方 式 进 行 不 同 层 之 间 的 调 用, 例 如 在 Action 中 调 用 DAO 工 厂 类 中 的 方 法, 从 而 获 取 DAO 实 现 类 对 象 这 种 方 式 虽 然 能 够 实 现 了 分 层, 但 是 并 不 彻 底 的 Spring 的 作 用 就 是 更 彻 底 的 进 行 分 层 操 作, 它 采 用 注 入 的 方 式 进 行 对 象 的 引 入 例 如 在 业 务 逻 辑 层 中 调 用 数 据 访 问 层, 在 业 务 逻 辑 层 中 的 代 码 仅 出 现 数 据 访 问 层 的 接 口, 具 体 如 何 使 用, 使 用 哪 一 个 实 现 类 对 象, 这 些 都 是 以 配 置 文 件 注 入 的 方 式 操 作 的, 从 而 使 业 务 逻 辑 层 并 不 需 要 关 心 数 据 访 问 层 是 如 何 实 现 的 Spring 是 一 种 非 常 完 整 的 技 术, 它 涉 及 Web 开 发 中 的 各 个 方 面 但 是 在 实 际 开 发 中, 并 不 会 全 用 到, 用 到 最 多 的 就 是 IoC 技 术 和 AOP 技 术 上 面 所 说 的 就 是 Spring 中 非 常 重 要 的 Ioc 技 术, 也 就 是 控 制 反 转 除 了 该 技 术 外, 还 有 AOP 面 向 切 面 编 程, 在 本 章 的 后 面 将 会 讲 解 它 8.2 开 发 Spring 项 目 Spring 框 架 和 Hibernate 框 架 一 样, 也 是 不 仅 仅 在 Java Web 项 目 中 使 用 的 所 以 这 里 我 们 以 一 个 简 单 的 Java 项 目 讲 解 Spring 的 应 用 在 MyEclipse 中 很 好 的 集 成 了 Spring 项 目 和 程 序 的 开 发, 在 本 节 就 先 来 看 在 其 中 是 如 何 开 发 Spring 项 目 的 8.2.1 开 发 普 通 的 Java 项 目 Spring 的 项 目 是 基 于 普 通 项 目 的, 然 后 在 普 通 项 目 的 基 础 上 加 入 Spring 的 框 架 支 持 在 MyEclipse 的 菜 单 中, 选 择 File New Java Project 命 令, 就 会 弹 出 创 建 Java

项 目 的 界 面, 在 其 中 输 入 项 目 的 名 称 为 FirstSpring, 如 图 8-1 所 示 图 8-1 创 建 普 通 Java 项 目 单 击 Finish 按 钮, 将 完 成 普 通 项 目 的 创 建, 它 的 项 目 名 称 为 FirstSpring 8.2.2 加 入 Spring 框 架 支 持 在 包 资 源 管 理 器 中, 选 中 要 加 入 Spring 框 架 支 持 的 项 目, 这 里 选 择 FirstSpring 项 目 在 MyEclipse 的 菜 单 中, 选 择 MyEclipse Project Capabilities Add Spring Capabilities 命 令, 将 弹 出 加 入 Spring 类 库 支 持 操 作 界 面, 如 图 8-2 所 示

3 图 8-2 加 入 Spring 类 库 其 中 Spring version 表 示 加 入 项 目 的 Spring 框 架 的 版 本, 通 常 选 择 目 前 最 高 的 Spring 2.5 版 本 Select the libraries to add to the buildpath 表 示 将 向 项 目 中 加 入 哪 些 类 库 由 于 Spring 的 技 术 非 常 全 面, 并 且 能 够 整 合 很 多 种 技 术, 所 以 其 中 的 类 库 也 是 非 常 多 的 这 里 我 们 先 采 用 默 认 的 选 择, 也 就 是 仅 选 中 Spring 2.5 Core Libraries 选 项, 它 是 Spring 开 发 的 核 心 类 库, 当 进 行 其 他 操 作, 再 添 加 其 他 的 类 库 JAR Library Installation 表 示 是 否 将 类 库 复 制 到 项 目 中 其 中 Add checked Libraries to project build-path 选 项 表 示 不 复 制 JAR 文 件 类 库 到 项 目 中, 只 在 发 布 项 目 时 进 行 复 制, 这 是 默 认 的 选 项, 也 是 经 常 采 用 的 选 项 Copy checked Library contents to project folder(tlds always copied) 选 项 表 示 复 制 JAR 文 件 类 库 到 项 目 中, 选 择 该 选 项 后 还 需 要 填 写 将 这 些 类 库 放 置 的 目 录, 这 种 操 作 的 好 处 是 使 开 发 的 项 目 不 依 赖 于 MyEclipse Tag Library Folder 选 项 仅 对 Web 项 目 起 作 用, 表 示 指 定 标 签 库 文 件 的 安 装 目 录 单 击 Next 按 钮 将 进 入 到 创 建 Spring 配 置 文 件 的 界 面, 如 图 8-3 所 示

图 8-3 创 建 Spring 配 置 文 件 其 中 Enable AOP Builder 选 项 表 示 是 否 能 够 加 入 AOP 技 术 支 持, 保 持 默 认 的 状 态 就 可 以 Specify new or existing Spring bean configuration file 表 示 是 否 创 建 Spring 配 置 文 件, 这 里 采 用 默 认 的 选 中 状 态 Bean configuration type 表 示 Spring 配 置 文 件 的 类 型, New 表 示 新 建, Existing 表 示 使 用 已 经 存 在 的 Folder 表 示 Spring 配 置 文 件 所 在 的 目 录, 默 认 是 src 目 录, 保 持 默 认 就 可 以 File 表 示 配 置 文 件 的 名 称, 通 常 也 采 用 默 认 的 applicationcontext.xml 名 称 单 击 Finish 按 钮, 将 完 成 加 入 Spring 框 架 支 持 的 操 作 说 明 : 和 前 面 学 习 Hibernate 配 置 文 件 一 样, 在 Java Web 项 目 中, 当 部 署 Web 项 目 时, 当 会 将 该 配 置 文 件 放 到 classes 目 录 下, 而 不 是 在 目 前 的 src 目 录 下 8.2.3 认 识 Spring 的 项 目 结 构 向 普 通 的 Java 项 目 加 入 Spring 框 架 支 持 后, 将 向 项 目 加 入 Spring 核 心 类 库 和 S 的 配 置 文 件, 在 包 资 源 管 理 器 中, 将 项 目 展 开, 如 图 8-4 所 示

5 图 8-4 Spring 项 目 结 构 从 项 目 结 构 上 可 以 看 出,Sring 的 项 目 结 构 要 比 Hibernate 的 项 目 结 构 简 单 的 多 其 中 Spring 2.5 Core Libraties 就 是 加 入 框 架 支 持 时 使 用 的 核 心 类 库 applicationcontext.xml 就 是 Spring 的 配 置 文 件, 双 击 在 编 辑 区 中 打 开 该 文 件 在 编 辑 区 的 左 下 角 有 两 种 显 示 程 序 的 选 项, 选 择 Design 选 项 将 以 XML 的 形 式 显 示 Spring 的 配 置 文 件, 如 图 8-5 所 示 图 8-5 XML 文 件 形 式 显 示 选 择 编 辑 区 左 下 角 的 Source 选 项, 会 将 Spring 配 置 文 件 的 代 码 显 示 出 来, 具 体 代 码 为 : 01 <?xml version="1.0" encoding="utf-8"?> 02 <beans 03 xmlns="http://www.springframework.org/schema/beans" 04 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 05 xmlns:p="http://www.springframework.org/schema/p"

06 xsi:schemalocation="http://www.springframework.org/schema/beans 07 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 08 </beans> 其 中 <beans> 标 记 就 是 Spring 配 置 文 件 的 根 标 记, 在 该 标 记 对 中 可 以 对 Spring 项 目 中 的 Bean 进 行 配 置 说 明 : 这 里 所 说 的 Bean 其 实 就 是 普 通 的 类, 在 Spring 中 通 过 将 这 些 类 称 为 Bean, 它 和 通 常 所 说 的 规 范 JavaBean 是 不 一 样 的 8.3 开 发 控 制 反 转 程 序 控 制 反 转 是 Spring 的 核 心 技 术, 它 是 英 文 名 称 为 Inversion of Control, 所 以 在 很 多 地 方 将 控 制 反 转 缩 写 为 IoC 控 制 反 转 还 有 另 外 一 个 名 称, 叫 做 依 赖 注 入, 它 的 英 文 名 称 为 Dependency Injection, 简 称 是 DI 它 们 指 的 是 一 种 技 术, 就 是 在 框 架 中 将 对 象 创 建 后, 直 接 注 入 到 调 用 的 程 序 中 8.3.1 创 建 Bean 程 序 在 Spring 的 控 制 反 转 项 目 中, 会 自 动 生 成 一 个 IOC 容 器, 在 该 容 器 中 包 含 所 有 创 建 的 Bean, 并 对 这 些 Bean 进 行 管 理 开 发 Bean 程 序 分 为 两 步, 首 先 要 创 建 Bean 程 序 类, 然 后 对 它 进 行 配 置 Bean 程 序 就 是 一 个 普 通 的 类, 但 是 在 该 类 中 要 有 Setter 方 法 或 者 构 造 函 数, 从 而 能 够 将 值 或 者 Bean 对 象 注 入 这 里 我 们 就 以 Web 开 发 中 的 业 务 逻 辑 层 进 行 举 例 在 实 际 开 发 中, 通 常 将 业 务 逻 辑 层 的 程 序 放 在 service 包 中, 所 以 首 先 在 src 目 录 下 创 建 com.sanqing.service 包, 然 后 在 该 包 下 创 建 名 称 为 HelloServiceImpl 的 业 务 逻 辑 实 现 类, 它 的 代 码 为 : 01 package com.sanqing.service; 02 public class HelloServiceImpl { 03 private String message; // 打 招 呼 的 信 息 04 public void setmessage(string message) { // 通 过 Setter 方 法 注 入 05 this.message = message; 06 } 07 public void sayhello(){ // 打 招 呼 方 法 08 System.out.println(" 内 容 为 :"+message); 09 } 10 } 其 中 第 3 行 中 定 义 了 打 招 呼 的 信 息, 在 第 4 行 中 定 义 Setter 方 法 将 值 注 入 第 7 行 是 业 务 方 法, 完 成 打 招 呼 的 功 能 注 意 : 其 中 的 Setter 方 法 是 非 常 重 要 的, 在 后 面 的 讲 解 中 会 了 解 到 有 些 程 序 员 习 惯 也 生 成 Getter 方 法, 但 是 它 对 于 Spring 的 操 作 来 说, 是 没 有 任 何 用 处 的

7 8.3.2 配 置 Bean 程 序 在 上 一 小 节 中 通 过 创 建 类 的 方 式 创 建 了 Bean 程 序, 在 MyEclipse 中 并 没 有 集 成 该 功 能 在 本 节 中 将 继 续 讲 解 如 何 将 Bean 程 序 配 置 到 Spring 的 配 置 文 件 中, 在 MyEclipse 中 很 好 的 集 成 了 该 功 能 双 击 ApplicationContext.xml 文 件, 在 编 辑 区 中 打 开 该 文 件, 将 鼠 标 放 在 <beans> 标 记 对 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Spring New Bean 命 令, 将 弹 出 对 Bean 程 序 进 行 配 置 的 界 面, 如 图 8-6 所 示 图 8-6 配 置 Bean 程 序 其 中 Bean Id 表 示 Bean 程 序 的 id 名 称, 相 当 于 为 程 序 起 一 个 名 称, 在 后 面 的 使 用 Bean 程 序 时 使 用 它, 这 里 填 写 hello Name 选 项 在 普 通 的 Spring 程 序 中 通 常 不 填, 当 和 Struts 框 架 整 合 时, 通 常 才 配 置 它 Creation method 表 示 实 例 化 Bean 的 方 式, Default 选 项 表 示 默 认 的 方 式, 也 就 是 通 过 构 造 函 数 来 实 例 化 ; Factory bean 选 项 表 示 通 过 实 例 工 厂 方 法 方 式 实 例 化 Bean; Static factory method 选 项 表 示 使 用 静 态 工 厂 方 法 实 例 化 Bean 第 一 个 默 认 选 项 只 需 要 给 出 Bean 程 序 的 完 整 类 名 就 可 以, 如 果 使 用 后 两 种 选 项, 还 需 要 给 出 其 他 配 置, 这 里 采 用 最 简 单 的 默 认 方 式 实 例 化 Bean Bean class 表 示 Bean 程 序 的 完 整 类 名, 这 里 选 择 填 写 com.sanqing.service.helloserviceimpl 说 明 : 在 后 面 的 配 置 中, 还 有 一 些 选 项, 它 们 都 对 应 相 应 的 知 识 点, 这 里 我 们 先 采 用 默 认 值, 在 后 面 的 讲 解 中 再 详 细 的 讲 解 它 们 在 界 面 的 最 下 面, 选 择 Properties 选 项 卡, 它 是 对 以 Setter 方 法 方 式 注 入 时 的 设

置 单 击 Add 按 钮, 将 弹 出 设 置 Setter 方 法 属 性 界 面, 如 图 8-7 所 示 图 8-7 设 置 属 性 其 中 Name 就 对 应 Bean 程 序 中 的 属 性 名 称, 这 里 填 写 其 中 的 message 属 性 Spring type 对 应 注 入 类 型, 这 里 选 择 value 选 项, 表 示 进 行 基 本 类 型 注 入 Property format 表 示 注 入 格 式, 使 用 最 多 的 就 是 Element 选 项 Type 表 示 注 入 属 性 的 类 型, Value 表 示 注 入 值 内 容 单 击 Finish 按 钮, 将 完 成 属 性 的 设 置, 并 回 到 配 置 Bean 程 序 界 面, 单 击 Next 按 钮, 将 进 入 注 入 方 法 的 界 面, 如 图 8-8 所 示 图 8-8 方 法 注 入

9 在 该 界 面 中 可 以 完 成 Lookup 方 法 和 自 定 义 方 法 的 注 入, 对 于 普 通 的 Spring 项 目 而 说, 可 以 忽 略 这 一 步 操 作 单 击 Finish 按 钮, 将 完 成 配 置 Bean 程 序 的 操 作 容 为 : 在 ApplicationContext.xml Spring 的 配 置 文 件 中, 将 自 动 添 加 配 置 代 码, 具 体 内 01 <?xml version="1.0" encoding="utf-8"?> 02 <beans 03 xmlns="http://www.springframework.org/schema/beans" 04 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 05 xmlns:p="http://www.springframework.org/schema/p" 06 xsi:schemalocation="http://www.springframework.org/schema/beans 07 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 08 <bean id="hello" class="com.sanqing.service.helloserviceimpl" 09 abstract="false" lazy-init="default" autowire="default" 10 dependency-check="default"> 11 <property name="message"> 12 <value type="java.lang.string">hello everyone</value> 13 </property> 14 </bean> 15 </beans> 其 中 我 们 最 关 心 的 是 第 8 行 和 第 11 行 到 第 13 行 的 代 码 在 第 8 行 中 配 置 Bean 程 序 类, 并 为 它 起 了 一 个 id 名 称 在 第 11 行 中 使 用 <property> 标 记 对 配 置 了 属 性 值, 它 只 对 于 通 过 Setter 方 法 方 式 注 入 起 作 用, 其 中 使 用 name 属 性 指 定 要 配 置 的 属 性 名 称 在 第 12 行 中 给 出 属 性 值, 其 中 type 属 性 指 定 属 性 类 型, 标 记 对 中 位 属 性 值 说 明 : 在 配 置 文 件 中, 有 多 个 属 性 值 是 default, 它 们 都 是 MyEclipse 自 动 生 成 的, 也 可 以 手 动 去 掉 它 们, 是 不 影 响 功 能 的, 在 后 面 的 讲 解 中 会 说 明 它 们 的 作 用 8.3.3 编 写 测 试 类 在 实 际 开 发 中, 测 试 类 并 不 是 必 须 的, 但 是 通 过 都 会 有 该 程 序, 通 过 它 可 以 判 断 开 发 的 局 部 程 序 是 否 正 确 在 本 节 中 就 来 开 发 这 样 的 测 试 类, 通 过 它 来 测 试 是 否 能 够 将 配 置 文 件 中 的 值 注 入 到 Bean 程 序 中 测 试 类 的 具 体 代 码 如 下 : 01 package com.sanqing.test; 02 import org.springframework.beans.factory.beanfactory; 03 import org.springframework.context.support.classpathxmlapplicationcontext; 04 import com.sanqing.service.helloserviceimpl; 05 public class HelloTest { 06 public static void main(string[] args) { 07 BeanFactory factory = 08 new ClassPathXmlApplicationContext("applicationContext.xml"); 09 HelloServiceImpl hello= 10 (HelloServiceImpl)factory.getBean("hello"); // 获 取 Bean 实 例 11 hello.sayhello(); // 调 用 业 务 方 法 12 }

13 } 其 中 第 7 行 是 实 例 化 IoC 容 器 的 代 码, 第 9 行 中 通 过 容 器 实 例 化 指 定 的 Bean, 在 第 11 行 中 调 用 sayhello 业 务 方 法, 从 而 完 成 相 应 功 能 运 行 该 程 序, 运 行 结 果 为 : 内 容 为 :Hello everyone 从 运 行 结 果 中 可 以 看 到, 已 经 将 Spring 配 置 文 件 中 的 值 注 入 到 Bean 程 序 中 说 明 : 从 测 试 类 中 也 可 以 看 到, 我 们 并 没 有 通 过 new 来 创 建 Bean 实 例, 就 可 以 调 用 其 中 的 业 务 方 法, 这 就 是 控 制 反 转 的 作 用 8.4 依 赖 注 入 在 前 面 已 经 讲 解 过, 控 制 反 转 和 依 赖 注 入 指 的 是 同 一 个 技 术 但 是 使 用 名 称 时 又 有 些 小 的 不 同, 当 指 整 个 技 术 时, 通 常 叫 做 控 制 反 转 ; 当 指 注 入 操 作 时, 通 常 叫 做 依 赖 注 入 在 本 节 中, 就 主 要 来 讲 解 一 下 注 入 的 操 作, 包 括 注 入 方 式 和 注 入 类 型 等, 看 一 下 MyEclipse 中 是 如 何 操 作 它 们 的 8.4.1 注 入 方 式 依 赖 注 入 有 两 种 常 用 的 方 式, 分 别 是 Setter 方 法 注 入 和 构 造 函 数 注 入 使 用 不 同 方 式 时,Bean 程 序 中 对 属 性 设 置 的 方 式 不 同, 同 样 对 应 的 配 置 也 是 所 有 不 同 的 在 上 一 节 中, 已 经 见 过 了 Setter 方 法 的 方 式 注 入, 在 本 小 节 中 再 来 看 一 下 如 何 使 用 构 造 函 数 注 入 说 明 : 这 两 种 方 式 中,Setter 方 法 的 方 式 使 用 的 是 比 较 多 的, 这 也 是 Spring 框 架 中 提 倡 的 方 式 当 使 用 构 造 函 数 注 入 属 性 值 时, 需 要 定 义 以 相 应 属 性 为 参 数 的 构 造 函 数 使 用 构 造 函 数 注 入 的 一 个 优 点 就 是 不 需 要 为 每 一 个 属 性 都 定 义 方 法, 只 通 过 一 个 多 参 构 造 函 数 就 可 以 一 次 注 入 同 样 需 要 首 先 创 建 Bean 程 序 代 码, 其 具 体 代 码 为 : 01 package com.sanqing.service; 02 public class Hello2ServiceImpl { 03 private String message; // 打 招 呼 的 信 息 04 public Hello2ServiceImpl(String message) { // 具 有 属 性 参 数 的 构 造 函 数 05 super(); 06 this.message = message; 07 } 08 public void sayhello(){ // 打 招 呼 方 法 09 System.out.println(" 内 容 为 :"+message); 10 } 11 } 接 下 来 就 是 使 用 MyEclipse 中 集 成 的 功 能 在 Spring 的 配 置 文 件 中 对 该 Bean 程 序 进 行 配 置 同 样 将 鼠 标 焦 点 定 义 在 <beans> 标 记 对 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Spring New Bean 命 令, 将 弹 出 对 Bean 程 序 进 行 配 置 的 界 面, 在 其 中 输 入 必 要 信 息 后, 如 图 8-9 所 示

11 图 8-9 配 置 构 造 函 数 注 入 的 Bean 在 其 中 填 写 Bean Id 和 Bean Class 后, 在 最 下 面 选 择 Constructor Args 选 项 卡, 单 击 其 中 的 Add 按 钮, 将 弹 出 配 置 构 造 函 数 属 性 的 界 面, 在 其 中 选 择 配 置 类 型 为 value, 并 输 入 要 注 入 的 值, 如 图 8-10 所 示 图 8-10 设 置 注 入 属 性 其 中 Index 表 示 属 性 对 应 构 造 函 数 中 的 第 几 个 参 数, 它 是 从 0 开 始 的 Java class 表 示 属 性 对 应 构 造 函 数 中 参 数 的 类 型 技 巧 : 上 述 两 种 方 式 选 择 一 种 就 可 以, 建 议 选 择 Index 的 方 式, 从 而 可 以 避 免

参 数 类 型 相 同 情 况 的 麻 烦 这 两 个 选 项 也 可 以 同 时 填 写, 但 是 一 定 要 全 部 和 构 造 函 数 中 的 参 数 对 应 正 确 Spring type 表 示 注 入 类 型, 因 为 这 里 是 注 入 基 本 数 据 类 型, 所 以 选 择 value Type 表 示 注 入 值 的 类 型, 对 于 基 本 数 据 类 型 和 String 类 型 来 说 可 以 不 填, 它 们 是 能 够 根 据 属 性 类 型 自 动 转 换 的 Value 表 示 注 入 基 本 类 型 值 单 击 Finish 按 钮, 将 完 成 属 性 的 设 置 回 到 配 置 Bean 界 面 后, 单 击 Finish 按 钮, 将 完 成 配 置 操 作, 将 自 动 向 Spring 配 置 文 件 中 加 入 配 置 代 码, 其 加 入 的 代 码 为 : 01 <bean id="hello2" class="com.sanqing.service.hello2serviceimpl" 02 abstract="false" lazy-init="default" autowire="default" 03 dependency-check="default"> 04 <constructor-arg index="0"> 05 <value>hello everyone</value> 06 </constructor-arg> 07 </bean> 和 通 过 Setter 方 法 的 方 式 注 入 不 同 的 是 从 第 4 行 到 第 6 行, 构 造 函 数 方 式 注 入 将 采 用 <constructor-arg> 标 记, 其 中 index 属 性 对 应 的 就 是 构 造 函 数 第 几 个 参 数, 在 标 记 对 中 使 用 <value> 标 记, 在 其 中 给 出 具 体 值 开 发 完 通 过 构 造 函 数 注 入 的 Bean 程 序 后, 同 样 要 创 建 测 试 类 程 序, 测 试 程 序 的 正 确 性, 测 试 类 代 码 如 下 : 01 package com.sanqing.test; 02 import org.springframework.beans.factory.beanfactory; 03 import org.springframework.context.support.classpathxmlapplicationcontext; 04 import com.sanqing.service.hello2serviceimpl; 05 public class Hello2Test { 06 public static void main(string[] args) { 07 BeanFactory factory = 08 new ClassPathXmlApplicationContext("applicationContext.xml"); 09 Hello2ServiceImpl hello2= 10 (Hello2ServiceImpl)factory.getBean("hello2"); // 获 取 Bean 实 例 11 hello2.sayhello(); // 调 用 业 务 方 法 12 } 13 } 从 代 码 上 可 以 看 到 在 测 试 类 中 只 需 要 改 动 实 例 化 Bean 的 id, 然 后 转 换 为 相 应 的 Bean 类 就 可 以 运 行 该 程 序, 运 行 结 果 为 : 内 容 为 :Hello everyone 可 以 看 到, 通 过 构 造 函 数 注 入 也 是 正 确 的 8.4.2 注 入 其 他 Bean 在 前 面 的 讲 解 中 都 是 向 Bean 中 注 入 字 符 串 类 型, 对 于 基 本 数 据 类 型 来 说, 是 和 字 符 串 类 型 完 全 一 样 的 在 本 小 节 中 将 继 续 来 讲 解 如 何 向 Bean 中 注 入 其 他 Bean, 在 实 际

13 开 发 中, 使 用 最 多 的 也 是 注 入 其 他 Bean 在 上 一 小 节 中, 已 经 通 过 基 本 类 型 讲 解 了 注 入 的 方 式, 对 于 其 他 类 型 来 说, 都 是 存 在 这 两 种 注 入 方 式 的, 它 们 是 非 常 类 似 的, 这 里 我 们 只 通 过 Setter 方 法 的 方 式 进 行 注 入 讲 解 在 实 际 开 发 中, 使 用 Spring 最 多 的 地 方 就 是 将 数 据 访 问 层 注 入 到 业 务 逻 辑 层 中, 在 其 中 通 过 接 口 操 作, 从 而 达 到 分 层 的 效 果 数 据 访 问 层 一 定 要 有 DAO 接 口 和 DAO 实 现 类, 其 中 DAO 接 口 的 代 码 是 非 常 简 单 的, 这 里 就 不 再 给 出, 读 者 可 以 查 看 光 盘 DAO 实 现 类 代 码 如 下 : 01 package com.sanqing.dao; 02 public class UserDAOImpl implements UserDAO { 03 public boolean finduser(string name, String password) { // 定 义 查 询 数 据 库 方 法 04 if ("Tom".equals(name) && "456123".equals(password)) { // 判 断 是 否 正 确 05 return true; 06 } else { 07 return false; 08 } 09 } 10 } 其 中 第 3 行 定 义 了 查 找 用 户 的 方 法, 这 里 仅 仅 是 演 示 数 据 库 的 操 作, 判 断 参 数 值 是 否 为 指 定 内 容 当 内 容 相 同 时, 表 示 能 够 查 询 到 用 户, 从 而 能 够 正 确 登 录 ; 当 内 容 不 同 时, 表 示 不 能 查 询 到 用 户, 也 就 是 不 能 完 成 登 录 接 下 来 继 续 开 发 业 务 逻 辑 层 的 程 序, 在 其 中 定 义 登 录 业 务 方 法, 在 方 法 中 调 用 数 据 访 问 层 中 的 方 法, 其 代 码 为 : 01 package com.sanqing.service; 02 import com.sanqing.dao.userdao; 03 public class UserServiceImpl { 04 private UserDAO userdao; 05 public void setuserdao(userdao userdao) { 06 this.userdao = userdao; 07 } 08 public boolean Login(String name, String password) { // 定 义 登 录 业 务 方 法 09 boolean b = userdao.finduser(name, password); // 调 用 DAO 方 法 10 return b; 11 } 12 } 开 发 完 数 据 访 问 层 和 业 务 逻 辑 层 的 Bean 程 序 后, 接 下 来 就 是 最 关 键 的 在 Spring 配 置 文 件 中 对 它 们 进 行 配 置 首 先 对 数 据 访 问 层 Bean 程 序 进 行 配 置 将 鼠 标 放 在 <beans> 标 记 对 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Spring New Bean 命 令, 将 弹 出 对 Bean 程 序 进 行 配 置 的 界 面, 在 其 中 输 入 配 置 数 据 访 问 层 程 序 的 信 息, 如 图 8-11 所 示

图 8-11 配 置 数 据 访 问 层 Bean 因 为 在 数 据 访 问 层 中 并 不 需 要 注 入 任 何 属 性 内 容, 所 以 仅 给 出 Bean Id 和 Bean class 选 项 值 就 可 以 单 击 Finish 按 钮, 从 而 完 成 配 置 再 次 进 行 同 样 的 操 作, 弹 出 对 Bean 程 序 进 行 配 置 的 界 面, 在 其 中 输 入 配 置 业 务 逻 辑 层 程 序 的 信 息, 如 图 8-12 所 示

15 图 8-12 配 置 业 务 逻 辑 层 Bean 在 其 中 配 置 Bean Id 和 Bean class 选 项, 选 择 Properties 选 项 卡, 单 击 Add 按 钮, 将 弹 出 配 置 属 性 的 界 面 其 中 最 关 键 的 就 是 配 置 类 型, ref 对 应 的 就 是 注 入 其 他 Bean, 选 择 该 选 项 后, 并 填 写 其 他 信 息, 界 面 如 图 8-13 所 示 图 8-13 配 置 注 入 的 Bean 其 中 Name 选 项 对 应 的 属 性 名 称, 这 和 注 入 基 本 类 型 是 一 样 的 Reference type 表 示 注 入 其 他 Bean 的 形 式, 其 中 包 含 三 种 形 式 Bean 选 项 对 应 最 常 用 的 形 式, 通 过 它 可 以 注 入 同 一 容 器 或 者 父 容 器 中 的 Bean; Local 表 示 只 能 注 入 同 一 文 件 中 的

Bean; Parent 表 示 注 入 父 容 器 中 的 Bean 说 明 : 在 Spring 框 架 中 可 以 定 义 多 个 配 置 文 件, 在 每 一 个 配 置 文 件 中 完 成 一 类 Bean 的 配 置, 这 对 于 大 型 项 目 来 说 是 非 常 必 要 的 在 配 置 文 件 中, 可 以 使 用 <import> 标 记 导 入 其 他 配 置 文 件, 从 而 产 生 父 容 器 和 子 容 器 Reference 表 示 要 注 入 到 当 前 Bean 中 的 Bean, 这 里 填 写 注 入 Bean 的 id 单 击 Finish 按 钮, 将 完 成 注 入 其 他 Bean 的 操 作 回 到 配 置 业 务 逻 辑 层 Bean 的 界 面, 单 击 Finish 按 钮, 将 完 成 所 有 配 置 在 Spring 配 置 文 件 中, 自 动 生 成 的 代 码 为 : 01 <bean id="userdaoimpl" class="com.sanqing.dao.userdaoimpl" 02 abstract="false" lazy-init="default" autowire="default" 03 dependency-check="default"> 04 </bean> 05 <bean id="userserviceimpl" 06 class="com.sanqing.service.userserviceimpl" abstract="false" 07 lazy-init="default" autowire="default" dependency-check="default"> 08 <property name="userdao"> 09 <ref bean="userdaoimpl" /> 10 </property> 11 </bean> 其 中 第 1 行 中 完 成 数 据 访 问 层 实 体 类 的 配 置 从 第 5 行 到 第 11 行 完 成 业 务 逻 辑 层 实 体 类 的 配 置, 其 中 第 8 行 使 用 <property> 标 记 指 定 为 Setter 方 法 的 方 式 注 入, 注 入 的 属 性 是 userdao, 第 9 行 中 定 义 注 入 Bean 的 id, 也 就 是 上 面 配 置 的 数 据 访 问 层 实 体 类 和 前 面 一 样, 最 后 创 建 测 试 类 来 验 证 注 入 其 他 Bean 是 否 正 确, 它 的 代 码 为 : 01 package com.sanqing.test; 02 import org.springframework.beans.factory.beanfactory; 03 import org.springframework.context.support.classpathxmlapplicationcontext; 04 import com.sanqing.service.userserviceimpl; 05 public class OtherBeanClient { 06 public static void main(string[] args) { 07 BeanFactory factory = 08 new ClassPathXmlApplicationContext("applicationContext.xml"); 09 UserServiceImpl userservice= 10 (UserServiceImpl)factory.getBean("userServiceImpl");// 获 取 业 务 实 现 类 11 String name="tom"; // 测 试 使 用 用 户 名 12 String password="456123"; // 测 试 使 用 密 码 13 System.out.println(name+" 是 否 能 够 正 常 登 录 :" 14 +userservice.login(name, password)); // 调 用 业 务 方 法 15 } 16 } 其 中 第 9 行 获 取 业 务 逻 辑 层 实 现 类, 然 后 给 出 测 试 数 据, 在 第 14 行 中 调 用 Login 业 务 方 法 判 断 用 户 是 否 能 够 登 录 在 Login 方 法 中 将 调 用 数 据 访 问 层 实 现 类 中 的 方 法, 如 果 注 入 成 功, 将 能 够 成 功 调 用 运 行 该 程 序, 运 行 结 果 为 :

17 Tom 是 否 能 够 正 常 登 录 :true 从 运 行 结 果 中 可 以 看 到, 向 业 务 逻 辑 层 中 注 入 数 据 访 问 层 成 功 8.4.3 注 入 集 合 在 Java 中, 集 合 包 括 List Set 和 Map 三 种, 在 Spring 除 了 能 够 对 这 三 种 集 合 能 够 注 入 操 作 外, 还 包 括 Properties 映 射 文 件 在 Spring 配 置 文 件 中, 使 用 <list/> <set/> <map/> 及 <props/> 标 记 来 对 应 集 合 进 行 配 置 首 先 创 建 Bean 程 序, 在 其 中 具 有 着 四 种 集 合 属 性, 其 具 体 代 码 为 : 01 package com.sanqing.service; 02 import java.util.list; 03 import java.util.map; 04 import java.util.properties; 05 import java.util.set; 06 public class CollectionBean { 07 private List list; 08 private Set set; 09 private Map map; 10 private Properties props; 11 public void setlist(list list) { 12 this.list = list; 13 } 14 public void setset(set set) { 15 this.set = set; 16 } 17 public void setmap(map map) { 18 this.map = map; 19 } 20 public void setprops(properties props) { 21 this.props = props; 22 } 23 } 然 后 在 Spring 配 置 文 件 中 进 行 注 入 配 置 将 鼠 标 放 在 <beans> 标 记 对 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Spring New Bean 命 令, 将 弹 出 对 Bean 程 序 进 行 配 置 的 界 面, 在 其 中 输 入 id 和 class 后, 如 图 8-14 所 示

图 8-14 注 入 集 合 Bean 在 其 中 选 择 Properties 选 项 卡, 单 击 Add 按 钮, 将 弹 出 配 置 属 性 界 面, 通 过 该 操 作 依 次 配 置 四 种 属 性 首 先 来 看 配 置 List 的 界 面, 如 图 8-15 所 示 图 8-15 配 置 List 属 性 其 中 单 击 Add 按 钮 将 弹 出 向 List 中 加 入 元 素 的 界 面, 在 其 中 可 以 添 加 基 本 类 型 的 value 值, 也 可 以 添 加 其 他 Bean, 具 体 操 作 界 面 是 和 前 面 注 入 方 式 是 相 同 的 这 里 为 了 简 单, 就 采 用 基 本 类 型 演 示 选 中 集 合 元 素 后, 还 可 以 通 过 右 边 的 按 钮 进 行 操 作, 通 过 Up 和 Down 按 钮 可 以 调 整 元 素 顺 序 单 击 Finish 按 钮, 将 完 成 List 的 配 置

所 示 19 继 续 单 击 注 入 集 合 Bean 界 面 中 的 Add 按 钮, 对 Set 进 行 配 置, 界 面 如 图 8-16 图 8-16 配 置 Set 属 性 向 Set 中 添 加 元 素 的 操 作 是 和 向 List 添 加 元 素 操 作 相 同 的, 这 里 就 不 再 重 复 讲 解 继 续 单 击 注 入 集 合 Bean 界 面 中 的 Add 按 钮, 对 Map 进 行 配 置, 界 面 如 图 8-17 所 示 图 8-17 配 置 Map 属 性 在 其 中 单 击 Add 按 钮, 将 弹 出 添 加 Map 属 性 的 界 面, 因 为 Map 是 以 键 值 对 存 在 的, 所 以 要 填 写 键 和 值 在 配 置 Map 属 性 界 面 中, 单 击 Finish 按 钮, 将 完 成 配 置 操 作 继 续 单 击 注 入 集 合 Bean 界 面 中 的 Add 按 钮, 对 Properties 进 行 配 置, 界 面 如 图 8-18 所 示

图 8-18 配 置 映 射 文 件 属 性 配 置 映 射 文 件 属 性 和 配 置 Map 属 性 非 常 类 似 的, 它 也 是 键 值 对 的 形 式 单 击 Finish 按 钮, 完 成 映 射 文 件 的 配 置 回 到 注 入 集 合 Bean 的 界 面, 单 击 Finish 按 钮, 完 成 注 入 操 作 在 配 置 文 件 中 将 自 动 添 加 如 下 代 码 : 01 <bean id="collection" class="com.sanqing.service.collectionbean" 02 abstract="false" lazy-init="default" autowire="default" 03 dependency-check="default"> 04 <property name="list"> 05 <list> 06 <value>listone</value> 07 <value>listtwo</value> 08 </list> 09 </property> 10 <property name="set"> 11 <set> 12 <value>setone</value> 13 <value>settwo</value> 14 </set> 15 </property> 16 <property name="map"> 17 <map> 18 <entry key="one" value="mapone"></entry> 19 <entry key="two" value="maptwo"></entry> 20 </map> 21 </property> 22 <property name="props"> 23 <props> 24 <prop key="one">propsone</prop> 25 <prop key="two">propstwo</prop> 26 </props>

21 27 </property> 28 </bean> 注 意 : 不 同 的 集 合 之 间 使 用 的 标 记 对 是 不 一 样 的, 包 括 标 记 对 中 使 用 的 元 素 标 记 所 以 使 用 MyEclipse 集 成 的 功 能, 要 比 手 动 写 容 易 的 多 在 测 试 类 中, 首 先 获 取 Bean, 然 后 通 过 Bean 获 取 集 合 属 性 后, 可 以 通 过 循 环 对 它 们 进 行 遍 历, 从 而 得 到 每 一 个 元 素 值, 读 者 可 以 自 己 来 完 成 测 试 类 的 编 写 8.4.4 不 完 全 依 赖 在 前 面 学 习 注 入 其 他 Bean 时, 当 Bean 甲 被 依 赖 注 入 到 Bean 乙 中 时, 在 Bean 乙 中 就 可 以 使 用 Bean 甲 进 行 调 用 方 法 在 其 中 Bean 甲 是 要 在 Bean 乙 之 前 实 例 化 的 但 是 实 际 开 发 中 有 这 样 一 种 情 况, 需 要 Bean 甲 在 Bean 乙 之 前 实 例 化, 但 是 在 Bean 乙 中 是 不 需 要 使 用 Bean 甲 的, 这 种 情 况 下 就 可 以 使 用 不 完 全 依 赖 注 入 在 MyEclipse 中 也 集 成 了 进 行 不 完 全 依 赖 的 功 能 例 如 这 里 完 成 这 样 一 个 功 能, 在 执 行 登 录 前, 要 先 执 行 打 招 呼 的 功 能, 这 时 候 就 需 要 在 用 户 业 务 逻 辑 层 中 配 置 完 成 打 招 呼 功 能 的 Bean 将 鼠 标 放 在 <beans> 标 记 对 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Spring New Bean 命 令, 将 弹 出 对 Bean 程 序 进 行 配 置 的 界 面, 在 其 中 选 择 Dependencies 选 项 卡, 如 图 8-19 所 示 图 8-19 不 完 全 依 赖 配 置

在 Dependencies 选 项 卡 中, Depends on Bean Ids 选 项 就 表 示 不 完 全 依 赖 Bean 的 id 这 里 可 以 自 己 填 写, 也 可 以 单 击 Add 方 法 添 加, 如 图 8-20 所 示 图 8-20 选 择 不 完 全 依 赖 id 在 界 面 的 下 拉 列 表 中, 将 出 现 目 前 Spring 配 置 文 件 中 所 有 的 id 值, 选 择 Hello 后, 单 击 OK 按 钮, 将 完 成 id 的 选 择, 并 将 它 添 加 到 配 置 界 面 的 Depends on Bean Ids 选 项 中 id 操 作 可 以 添 加 多 次, 例 如 再 添 加 hello2,id 之 间 将 以 逗 号 分 隔 单 击 Finish 按 钮, 将 完 成 不 完 全 依 赖 的 配 置 在 Spring 中, 自 动 生 成 的 代 码 为 : 01 <bean id="user" class="com.sanqing.service.userserviceimpl" 02 abstract="false" lazy-init="default" autowire="default" 03 dependency-check="default" depends-on="hello,hello2"> 04 </bean> 其 中 depends-on 属 性 配 置 的 就 是 不 完 全 依 赖 Bean 的 id 值 说 明 : 不 完 全 依 赖 的 情 况 在 数 据 库 开 发 中 比 较 常 见, 例 如 注 册 数 据 驱 动 必 须 在 所 有 操 作 之 前 完 成, 但 是 在 操 作 中 是 不 会 调 用 驱 动 的 8.4.5 延 迟 初 始 化 Bean 在 Spring 框 架 中, 默 认 情 况 下 当 启 动 项 目 后, 会 将 所 有 已 经 配 置 的 单 例 Bean 全 部 实 例 化, 其 中 包 括 配 置 的 和 注 入 的 这 样 做 的 好 处 就 是 在 启 动 时, 如 果 配 置 文 件 中 有 什 么 错 误, 将 会 立 刻 发 现 但 是 这 样 做, 并 不 是 适 合 所 有 情 况 的, 在 特 殊 情 况 下, 我 们 并 不 想 让 Bean 在 启 动 的 时 候 就 马 上 实 例 化 这 时 候 也 可 以 通 过 配 置, 将 它 设 置 为 延 迟 初 始 化 在 MyEclipse 的 配 置 界 面 中, 集 成 了 该 功 能, 例 如 我 们 将 Hello 程 序 设 置 为 延 迟 初 始 化 Bean, 它 的 配 置 界 面 如 图 8-21 所 示

23 图 8-21 延 迟 初 始 化 Bean 其 中 Lazy init 选 项 表 示 是 否 延 迟 初 始 化 Bean, 默 认 选 项 是 default, 表 示 根 据 实 际 Bean 类 型 决 定 在 其 中 选 择 true 表 示 延 迟 初 始 化, 选 择 false 表 示 提 前 初 始 化 为 : 单 击 Finish 按 钮, 将 完 成 初 始 化 的 设 置, 在 Spring 配 置 文 件 中 自 动 生 成 的 代 码 01 <bean id="hello3" class="com.sanqing.service.helloserviceimpl" 02 abstract="false" lazy-init="true" autowire="default" 03 dependency-check="default"> 04 </bean> 其 中 lazy-init 属 性 就 表 示 是 否 延 迟 初 始 化, 设 置 为 true, 就 表 示 延 迟 初 始 化 注 意 : 延 迟 初 始 化 的 设 置 有 时 可 能 会 失 效 当 Bean 甲 设 置 为 延 迟 初 始 化 时, 但 是 非 延 迟 初 始 化 的 Bean 乙 依 赖 于 Bean 甲, 那 Bean 甲 的 延 迟 初 始 化 的 设 置 就 会 失 效 8.4.6 自 动 装 配 在 前 面 讲 解 注 入 其 他 Bean 时, 都 是 通 过 直 接 配 置 的 方 式 注 入 的 在 Spring 框 架 的 容 器 中, 还 可 以 通 过 自 动 装 配 的 方 式, 让 容 器 自 动 进 行 注 入 其 他 Bean 的 操 作 在 MyEclipse 中, 也 集 成 了 自 动 装 配 的 功 能 我 们 再 次 以 用 户 业 务 逻 辑 实 现 类 为 例, 在 配 置 它 的 弹 出 界 面, 选 择 自 动 装 配, 界 面 如 图 8-22 所 示

图 8-22 自 动 装 配 其 中 Autowire 表 示 的 就 是 自 动 装 配 的 方 式 其 中 包 括 5 个 选 项, no 选 项 表 示 不 使 用 自 动 装 配, 它 是 默 认 方 式, 当 选 择 该 方 式 时, 必 须 对 Bean 进 行 配 置 除 此 之 外, 还 有 四 个 选 项, 它 们 分 别 表 示 内 容 如 下 : byname: 根 据 属 性 名 自 动 装 配 此 选 项 将 检 查 容 器 并 根 据 名 字 查 找 与 属 性 完 全 一 致 的 bean, 并 将 其 与 属 性 自 动 装 配 bytype: 如 果 容 器 中 存 在 一 个 与 指 定 属 性 类 型 相 同 的 bean, 那 么 将 与 该 属 性 自 动 装 配 如 果 存 在 多 个 该 类 型 的 bean, 那 么 将 会 抛 出 异 常, 并 指 出 不 能 使 用 bytype 方 式 进 行 自 动 装 配 若 没 有 找 到 相 匹 配 的 bean, 则 什 么 事 都 不 发 生, 属 性 也 不 会 被 设 置 constructor: 与 bytype 的 方 式 类 似, 不 同 之 处 在 于 它 应 用 于 构 造 器 参 数 如 果 在 容 器 中 没 有 找 到 与 构 造 器 参 数 类 型 一 致 的 bean, 那 么 将 会 抛 出 异 常 autodetect: 通 过 bean 类 的 自 省 机 制 (introspection) 来 决 定 是 使 用 constructor 还 是 bytype 方 式 进 行 自 动 装 配 如 果 发 现 默 认 的 构 造 器, 那 么 将 使 用 bytype 方 式 这 里 先 选 择 no 选 项, 单 击 Finish 按 钮, 将 完 成 自 动 装 配 的 配 置, 在 Spring 配 置 文 件 中 将 自 动 生 成 如 下 代 码 : 01 <bean id="userservice" class="com.sanqing.service.userserviceimpl" 02 abstract="false" lazy-init="default" autowire="no" 03 dependency-check="default"> 04 <property name="userdao"> 05 <ref bean="userdaoimpl" />

25 06 </property> 07 </bean> 其 中 第 2 行 的 autowire 属 性 配 置 的 就 是 自 动 装 配 的 方 式 注 意 : 目 前 自 动 装 配 仅 对 于 注 入 其 他 Bean 的 操 作 有 效, 对 于 基 本 类 型 是 没 有 任 何 作 用 的 说 明 : 自 动 装 配 既 有 优 点 又 有 缺 点 优 点 是 能 够 减 少 配 置 数 量, 缺 点 是 使 配 置 文 件 不 再 能 够 明 显 Bean 之 间 的 注 入 关 系 8.4.7 依 赖 注 入 检 查 通 过 依 赖 注 入 检 查 可 以, 可 以 对 Spring 配 置 文 件 中 的 注 入 配 置 进 行 检 查, 当 需 要 确 保 所 有 属 性 值 或 者 属 性 类 型 正 确 配 置 时, 使 用 该 操 作 是 非 常 必 要 的 和 它 相 对 的, 在 Bean 中 一 些 属 性 具 有 默 认 值, 或 者 该 属 性 并 不 在 所 有 环 境 下 都 被 调 用, 这 时 候 就 不 需 要 进 行 依 赖 注 入 检 查 所 以 就 需 要 对 每 一 个 Bean 进 行 各 自 特 有 的 依 赖 注 入 检 查 设 置 在 MyEclipse 中, 也 集 成 了 对 依 赖 注 入 检 查 设 置 的 功 能 在 弹 出 的 配 置 Bean 程 序 的 界 面 中, 选 择 Dependencies 选 项 卡, 如 图 8-23 所 示 图 8-23 依 赖 注 入 检 查 其 中 Check Dependency 表 示 的 就 是 依 赖 注 入 检 查 设 置, 其 中 包 括 4 个 选 项 它 们 分 别 表 示 的 含 义 如 下 : none: 不 进 行 依 赖 注 入 检 查

simple: 对 基 本 类 型 和 集 合 进 行 依 赖 注 入 检 查 object: 当 注 入 其 他 Bean 时, 进 行 依 赖 注 入 检 查 all: 对 所 有 类 型 都 进 行 依 赖 注 入 检 查 在 Spring 的 配 置 文 件 中, 将 采 用 dependency-check 属 性 对 依 赖 注 入 检 查 进 行 配 置 8.4.8 Bean 作 用 域 设 置 在 Spring 配 置 文 件 中 创 建 Bean 时, 有 时 候 还 要 设 置 Bean 的 作 用 域 Bean 的 作 用 域 就 是 指 一 个 Bean 对 象 的 使 用 方 式 和 使 用 范 围 Spring 中 的 这 种 设 计 使 定 义 Bean 的 作 用 域 不 用 在 类 程 序 中 进 行, 而 是 在 配 置 文 件 中 进 行, 大 大 提 高 了 灵 活 性 在 MyEclipse 中, 也 集 成 了 对 Bean 作 用 域 进 行 设 置 的 功 能 在 配 置 Bean 的 界 面 中, Scope 选 项 就 是 用 来 对 Bean 作 用 域 进 行 设 置, 如 图 8-24 所 示 图 8-24 设 置 Bean 作 用 域 在 Scope 的 下 拉 列 表 中, 有 5 个 选 项, 它 们 分 别 表 示 的 含 义 如 下 : singleton: 它 是 Bean 的 默 认 作 用 域, 使 用 该 作 用 域 时, 在 Spring IoC 容 器 中 将 只 会 存 在 一 个 共 享 的 Bean 实 例, 所 有 的 请 求 都 只 返 回 这 个 Bean 实 例 prototype: 它 和 singleton 作 用 域 相 对 应, 将 为 每 一 个 请 求 返 回 不 同 的 Bean 实 例 request: 在 一 次 HTTP 请 求 中, 一 个 bean 定 义 对 应 一 个 实 例 ; 即 每 次 HTTP 请 求 将 会 有 各 自 的 bean 实 例, 它 们 依 据 某 个 bean 定 义 创 建 而 成 session: 在 一 个 HTTP Session 中, 一 个 bean 定 义 对 应 一 个 实 例 global session: 在 一 个 全 局 的 HTTP Session 中, 一 个 bean 定 义 对 应 一 个 实 例

27 典 型 情 况 下, 仅 在 使 用 portlet context 的 时 候 有 效 注 意 : 其 中 request session 和 global session 的 作 用 域 只 在 WEB 的 项 目 中 有 效 注 意 : 单 例 Bean 和 设 计 模 式 中 的 单 例 模 式 是 完 全 不 同 的 单 例 模 式 是 指 类 只 能 创 建 一 个 对 象 单 例 Bean 是 指 在 一 个 IoC 容 器 中, 创 建 一 个 Bean 对 象 放 在 缓 存 中, 所 有 的 请 求 就 是 访 问 这 一 个 对 象 不 同 容 器 之 间 的 对 象 是 不 同 的 这 里 以 对 Hello Bean 的 设 置 为 例, 将 它 设 置 为 prototype 作 用 域, 在 Spring 的 配 置 文 件 中 自 动 生 成 的 配 置 代 码 为 : 01 <bean id="hello4" class="com.sanqing.service.helloserviceimpl" 02 abstract="false" scope="prototype" lazy-init="default" 03 autowire="default" dependency-check="default"> 04 </bean> 其 中 第 2 行 的 scope 属 性 设 置 的 就 是 Bean 程 序 的 作 用 域 说 明 : 如 果 配 置 不 是 在 Web 项 目 中, 也 可 以 使 用 singleton 属 性 进 行 配 置 当 属 性 值 为 true 时, 表 示 使 用 singleton 作 用 域 ; 当 属 性 值 为 false 时, 表 示 使 用 prototype 作 用 域 8.4.9 方 法 注 入 在 上 一 小 节 中, 已 经 学 习 了 Bean 作 用 域 的 知 识 在 默 认 情 况 下,Ioc 容 器 中 的 所 有 Bean 的 作 用 域 都 是 singleton, 我 们 也 可 以 手 动 改 变 作 用 域 当 改 变 Bean 的 作 用 域 后, 进 行 注 入 其 他 Bean 操 作 时 就 可 以 产 生 问 题, 例 如 向 一 个 作 用 域 为 singleton 的 Bean 甲 中 注 入 作 用 域 为 prototype 的 Bean 乙 对 于 Bean 甲 来 说, 容 器 只 会 创 建 一 个 Bean 甲 实 例, 这 样 就 没 法 让 容 器 提 供 不 同 的 Bean 乙 实 例 为 了 解 决 这 个 问 题, 就 需 要 放 弃 控 制 反 转, 而 是 采 用 方 法 注 入 的 方 式 方 法 注 入 分 为 两 种, 分 别 是 Lookup 方 法 注 入 和 自 定 义 方 法 注 入 在 MyEclipse 中 也 集 成 了 方 法 注 入 的 操 作, 在 配 置 Bean 界 面 中, 单 击 Next 按 钮, 将 进 入 方 法 注 入 界 面, 如 图 8-25 所 示

图 8-25 方 法 注 入 其 中 Lookup methods 栏 表 示 的 就 是 Lookup 方 法 注 入, 而 Replaced methods 栏 表 示 的 就 是 自 定 义 方 法 注 入 单 击 Lookup methods 栏 中 的 Add 按 钮, 将 弹 出 添 加 Lookup 方 法 的 界 面, 如 图 8-26 所 示 图 8-26 添 加 Lookup 方 法 其 中 Method 表 示 获 取 Bean 的 方 法 名 称, Bean 表 示 要 注 入 Bean 的 id, 也 就 是 前 面 举 例 中 的 Bean 乙 的 id 说 明 : 在 实 际 开 发 中, 方 法 注 入 使 用 的 并 不 多 并 且 自 定 义 方 法 注 入 使 用 的 比 Lookup 方 法 注 入 更 少, 所 以 这 里 就 不 在 讲 解 自 定 义 方 法 注 入, 有 兴 趣 的 读 者 可 以 自 己 参 考 相 应 资 料

29 8.4.10 定 义 Bean 的 生 命 周 期 方 法 在 Spring 框 架 中 的 Bean 程 序 和 普 通 的 Java 类 一 样, 也 是 具 有 生 命 周 期 的, 包 括 初 始 化 和 销 毁 在 Spring 框 架 中 定 义 了 相 关 生 命 周 期 接 口, 在 定 义 Bean 时 可 以 实 现 这 些 接 口, 然 后 实 现 其 中 的 生 命 周 期 方 法, 从 而 可 以 完 成 相 应 功 能 但 是 这 并 不 是 建 议 使 用 的, 因 为 这 样 就 使 程 序 和 框 架 耦 合 在 一 起 为 了 不 让 程 序 和 框 架 耦 合 在 一 起, 可 以 通 过 配 置 的 方 式 定 义 自 己 的 初 始 化 和 销 毁 等 生 命 周 期 方 法 在 MyEclipse 中, 也 集 成 了 该 功 能 首 先 开 发 一 个 Bean 程 序, 它 的 具 体 代 码 为 : 01 package com.sanqing.service; 02 public class LifeBean { 03 private String message; // 打 招 呼 的 信 息 04 public void setmessage(string message) { // 通 过 Setter 方 法 注 入 05 this.message = message; 06 } 07 public void sayhello(){ // 打 招 呼 方 法 08 System.out.println(" 内 容 为 :"+message); 09 } 10 public void init(){ // 初 始 化 方 法 11 System.out.println(" 进 行 Bean 初 始 化 操 作 "); 12 } 13 public void destroy(){ // 销 毁 方 法 14 System.out.println(" 进 行 Bean 销 毁 操 作 "); 15 } 16 } 其 中 第 10 行 的 init 方 法 就 是 自 定 义 的 初 始 化 方 法, 第 13 行 的 destrory 方 法 就 是 自 定 义 的 销 魂 方 法 开 发 完 Bean 程 序 后, 在 Spring 的 配 置 文 件 中 对 生 命 周 期 方 法 进 行 配 置, 在 配 置 界 面 中, 选 择 Life-cycle 选 项 卡, 在 其 中 填 入 相 应 的 方 法 名, 如 图 8-27 所 示

图 8-27 定 义 Bean 生 命 周 期 方 法 在 Life-cycle 选 项 卡 中, Init method 对 应 的 就 是 初 始 化 方 法, 这 里 选 择 定 义 在 Bean 程 序 中 的 init 方 法 Destroy method 对 应 的 就 是 销 毁 方 法, 这 里 选 择 同 样 定 义 在 Bean 程 序 中 的 destroy 方 法 单 击 Finish 按 钮, 将 完 成 Bean 程 序 的 配 置, 自 动 生 成 的 代 码 为 : 01 <bean id="life" class="com.sanqing.service.lifebean" 02 abstract="false" lazy-init="default" autowire="default" 03 dependency-check="default" init-method="init" 04 destroy-method="destroy"> 05 <property name="message"> 06 <value>hello everyone</value> 07 </property> 08 </bean> 其 中 第 3 行 的 init-method 属 性 配 置 的 就 是 初 始 化 方 法 名 第 4 行 中 的 destroy-method 属 性 配 置 的 就 是 销 毁 方 法 名 最 后 就 是 开 发 测 试 类, 来 看 一 下 开 发 的 Bean 程 序 和 对 它 的 配 置 是 否 正 确, 测 试 类 代 码 为 : 01 package com.sanqing.test; 02 import org.springframework.beans.factory.beanfactory; 03 import org.springframework.context.support.classpathxmlapplicationcontext; 04 import com.sanqing.service.lifebean; 05 public class LifeTest { 06 public static void main(string[] args) {

31 07 BeanFactory factory = 08 new ClassPathXmlApplicationContext("applicationContext.xml"); 09 LifeBean life=(lifebean)factory.getbean("life"); // 获 取 Bean 实 例 10 life.sayhello(); // 调 用 业 务 方 法 11 } 12 } 运 行 该 程 序, 运 行 结 果 为 : 进 行 Bean 初 始 化 操 作 内 容 为 :Hello everyone 可 以 看 到, 当 执 行 Bean 程 序 中 的 业 务 方 法 前, 首 先 执 行 了 init 方 法, 从 而 可 以 得 知 已 经 将 该 方 法 定 义 成 初 始 化 方 法 当 Bean 被 销 毁 时, 还 会 执 行 destroy 方 法 说 明 : 在 实 际 开 发 中 在 某 些 情 况 下, 初 始 化 和 销 毁 方 法 是 必 须 的, 例 如 在 非 Web 项 目 中 关 闭 IoC 容 器 操 作, 就 需 要 在 销 毁 方 法 中 完 成 8.4.11 Bean 中 的 继 承 继 承 是 Java 编 程 语 言 的 三 大 特 性 之 一, 继 承 的 类 称 为 子 类, 被 继 承 的 类 称 为 父 类 在 Spring 的 配 置 文 件 中, 对 Bean 程 序 的 配 置 也 存 在 父 子 关 系 在 配 置 Bean 时 可 以 通 过 操 作 让 它 继 承 已 有 的 配 置 Bean 信 息, 它 们 分 别 被 称 为 子 Bean 配 置 和 父 Bean 配 置 在 子 Bean 配 置 中 可 以 继 承 父 Bean 配 置 的 数 据, 也 可 以 覆 盖 原 有 数 据 或 者 添 加 新 配 置 在 MyEclipse 中, 也 集 成 了 进 行 集 成 配 置 的 功 能 在 配 置 Bean 界 面 中, Parent bean Id 选 项 就 是 用 来 选 择 父 Bean 配 置 的 id, 如 图 8-28 所 示 图 8-28 继 承 配 置

单 击 Finish 按 钮, 将 完 成 继 承 配 置 的 操 作 在 Spring 的 配 置 文 件 中, 将 自 动 生 成 如 下 代 码 : 01 <bean id="hello5" class="com.sanqing.service.helloserviceimpl" 02 parent="hello" abstract="false" lazy-init="default" autowire="default" 03 dependency-check="default"> 04 </bean> 其 中 第 2 行 的 parent 属 性 就 是 进 行 的 父 Bean 配 置 使 用 该 配 置 后, 就 不 需 要 在 其 中 对 message 属 性 进 行 配 置, 它 会 自 动 集 成 hello Bean 中 对 message 属 性 的 配 置 注 意 : 本 节 中 所 说 的 继 承, 并 不 是 指 Bean 类 之 间 的 继 承 关 系, 而 是 仅 仅 只 配 置 文 件 中 配 置 之 间 的 继 承 关 系 在 对 Bean 程 序 进 行 配 置 时, 还 可 以 选 择 其 中 的 Abstract 选 项, 当 把 该 选 项 选 中 时, 表 示 它 的 配 置 是 抽 象 的 则 该 Bean 将 做 为 模 板, 被 其 他 Bean 配 置 继 承 注 意 : 标 识 为 abstract 的 Bean 配 置 是 不 能 够 进 行 实 例 化 的, 当 调 用 getbean 方 法 时 将 发 生 错 误 这 种 Bean 的 唯 一 作 用 就 是 让 其 他 Bean 配 置 继 承 8.5 面 向 切 面 编 程 面 向 切 面 编 程 是 Spring 中 的 第 二 大 功 能, 它 的 英 文 名 称 缩 写 是 AOP 使 用 面 向 对 象 编 程, 在 指 定 方 法 的 前 面 执 行 另 一 个 方 法 是 不 难 实 现 的, 但 是 如 果 要 求 在 同 一 个 包 下 的 所 有 类 的 方 法 前 面 都 执 行 同 一 方 法, 就 是 一 件 比 较 复 杂 的 工 作 在 这 种 情 况 下, 如 果 使 用 面 向 切 面 编 程 就 很 容 易 实 现 在 目 前 最 新 版 本 的 MyEclipse 中, 并 没 有 集 成 开 发 AOP 项 目 的 功 能, 所 以 在 本 节 中 主 要 通 过 手 动 编 程 程 序 的 方 式 进 行 讲 解 8.5.1 准 备 工 作 在 FirstSpring 项 目 中 是 不 能 够 继 续 开 发 AOP 项 目 的, 因 为 在 其 中 并 没 有 加 入 AOP 开 发 所 需 要 的 类 库, 所 以 这 里 单 独 再 创 建 一 个 名 称 为 SpringAOP 的 项 目 开 发 完 普 通 的 Java 项 目 后, 将 执 行 加 入 Spring 框 架 支 持 的 操 作, 在 添 加 类 库 界 面 中, 不 但 要 加 入 Spring 核 心 类 库, 还 要 加 入 AOP 开 发 的 类 库, 如 图 8-29 所 示

33 图 8-29 加 入 AOP 类 库 其 中 Spring 2.5 AOP Libraries 选 项 就 是 AOP 开 发 类 库 因 为 并 不 需 要 对 配 置 文 件 进 行 特 殊 设 置, 所 以 直 接 采 用 默 认 值 在 该 界 面 中 单 击 Finish 按 钮, 将 完 成 加 入 Spring 框 架 支 持 的 操 作 在 包 资 源 管 理 中 展 开 SpringAOP 项 目, 可 以 看 到 其 中 多 出 了 AOP 类 库 双 击 打 开 ApplicationContext.xml 文 件, 也 就 是 Spring 的 配 置 文 件, 在 其 中 要 加 入 AOP 相 关 的 schemalocation, 加 入 后 的 完 整 代 码 为 : 01 <?xml version="1.0" encoding="utf-8"?> 02 <beans 03 xmlns="http://www.springframework.org/schema/beans" 04 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 05 xmlns:p="http://www.springframework.org/schema/p" 06 xmlns:aop="http://www.springframework.org/schema/aop" 07 xsi:schemalocation="http://www.springframework.org/schema/beans 08 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 09 http://www.springframework.org/schema/aop 10 http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> 11 </beans> 其 中 新 加 入 的 是 第 6 行 第 9 行 和 第 10 行 这 些 代 码 可 以 通 过 Spring 的 下 载 安 装 包 中 找 到 对 应 文 件, 不 过 为 了 方 便, 读 者 只 需 要 复 制 本 书 光 盘 中 的 该 文 件 就 可 以 进 行 开 发 了 8.5.2 通 过 配 置 方 式 开 发 AOP 项 目 开 发 AOP 项 目 由 两 种 方 式, 分 别 是 通 过 配 置 方 式 和 通 过 注 解 方 式, 注 解 方 式 是 Java

5.0 版 本 以 后 增 加 的, 它 在 下 一 小 节 中 进 行 讲 解 面 向 切 面 编 程 的 作 用 就 是 在 某 一 类 方 法 的 特 定 位 置, 执 行 相 同 的 功 能 例 如 执 行 数 据 库 时, 不 管 执 行 什 么 操 作 都 要 执 行 关 闭 数 据 库 的 操 作 首 先 来 开 发 执 行 数 据 库 操 作 的 数 据 访 问 层 程 序, 它 的 程 序 代 码 如 下 : 01 package com.sanqing.dao; 02 public class BookDAOImpl implements BookDAO { 03 public void addbook(string name, double price) { // 增 加 图 书 04 System.out.println(" 执 行 增 加 图 书 操 作 "); 05 } 06 public void deletebook(int id) { // 删 除 图 书 07 System.out.println(" 执 行 删 除 图 书 操 作 "); 08 } 09 public void updatebook(int id, String name, double price) { // 更 新 图 书 10 System.out.println(" 执 行 更 新 图 书 操 作 "); 11 } 12 public void findbookbybook(string name, double price) { // 根 据 ID 查 找 图 书 13 System.out.println(" 执 行 根 据 用 户 信 息 查 询 图 书 操 作 "); 14 } 15 public void findbookbyid(int id) { // 根 据 信 息 查 找 图 书 16 System.out.println(" 执 行 根 据 用 户 ID 查 询 图 书 操 作 "); 17 } 18 } 在 其 中 并 没 有 写 具 体 的 数 据 库 操 作, 而 是 通 过 显 示 信 息 来 演 示, 这 是 不 难 理 解 的 继 续 开 发 面 向 切 面 编 程 类, 它 的 代 码 为 : 01 package com.sanqing.service; 02 public class AspectJXML { 03 public void myaftermethod(){ // 定 义 通 知 方 法 04 System.out.println(" 数 据 库 操 作 后, 释 放 数 据 库 资 源 "); 05 } 06 } 在 该 类 中 第 3 行 定 义 了 通 知 方 法, 不 管 执 行 什 么 数 据 库 操 作 方 法 时, 都 执 行 该 方 法 为 了 实 现 该 功 能, 还 要 进 行 必 要 的 配 置, 它 是 面 向 切 面 编 程 的 核 心, 其 中 的 配 置 代 码 为 : 01 <bean id="bookdaoimpl" class="com.sanqing.dao.bookdaoimpl" 02 abstract="false" lazy-init="default" autowire="default" 03 dependency-check="default"> 04 </bean> 05 <bean id="aspectjxml" class="com.sanqing.service.aspectjxml" 06 abstract="false" lazy-init="default" autowire="default" 07 dependency-check="default"> 08 </bean> 09 <aop:config> 10 <aop:aspect id="myaspect" ref="aspectjxml"> 11 <aop:pointcut id="allmothod" expression="execution(* com.sanqing.dao.*.*(..))" /> 12 <aop:after pointcut-ref="allmothod" method="myaftermethod" />

35 13 </aop:aspect> 14 </aop:config> 在 其 中 第 1 行 对 数 据 访 问 层 Bean 进 行 配 置, 第 5 行 对 面 向 切 面 编 程 Bean 进 行 配 置, 这 些 配 置 在 前 面 讲 解 过 从 第 9 行 开 发 就 是 对 面 向 切 面 编 程 进 行 配 置, 使 用 <aop:config> 标 记 对 包 含 相 关 配 置 在 第 10 行 中 使 用 <aop:aspect> 标 记 对 声 明 上 面 开 发 的 面 向 切 面 编 程 类 为 切 面 在 第 11 行 中 声 明 了 对 哪 些 方 法 执 行 操 作, 这 里 指 定 对 dao 包 下 的 所 有 方 法 执 行 第 12 行 中 使 用 <aop:after> 标 记 指 定 后 置 通 知 方 法 最 后 我 们 通 过 一 个 测 试 类, 来 验 证 通 过 配 置 方 式 是 否 达 到 我 们 想 要 的 结 果, 测 试 类 代 码 如 下 : 01 package com.sanqing.test; 02 import org.springframework.beans.factory.beanfactory; 03 import org.springframework.context.support.classpathxmlapplicationcontext; 04 import com.sanqing.dao.bookdao; 05 public class BookTest { 06 public static void main(string[] args) { 07 BeanFactory factory = 08 new ClassPathXmlApplicationContext("applicationContext.xml"); 09 BookDAO bookdao= 10 (BookDAO)factory.getBean("bookDAOImpl"); // 获 取 DAO 11 bookdao.updatebook(3,"java", 58.5); // 执 行 更 新 图 书 操 作 12 bookdao.findbookbybook("linux",68.5); // 执 行 根 据 信 息 查 询 图 书 操 作 13 } 14 } 在 代 码 中 第 11 行 执 行 了 更 新 方 法, 在 第 12 行 中 执 行 了 查 询 方 法, 都 是 非 常 简 单 的 重 要 看 一 下 执 行 结 果, 它 的 运 行 结 果 为 : 执 行 更 新 图 书 操 作 数 据 库 操 作 后, 释 放 数 据 库 资 源 执 行 根 据 用 户 信 息 查 询 图 书 操 作 数 据 库 操 作 后, 释 放 数 据 库 资 源 可 以 看 到, 不 管 什 么 操 作, 在 后 面 都 会 显 示 数 据 库 操 作 后, 释 放 数 据 库 资 源, 它 就 是 面 向 切 面 编 程 类 中 方 法 的 执 行 结 果, 从 这 里 可 以 看 出 通 过 配 置 方 式 开 发 AOP 项 目 运 行 正 确 8.5.3 通 过 注 解 方 式 开 发 AOP 项 目 注 解 是 Java 5.0 版 本 中 提 出 的 新 特 性 技 术, 通 过 注 解 可 以 是 一 个 普 通 的 Java 程 序 完 成 特 定 的 功 能 也 就 是 说 当 需 要 完 成 一 个 特 定 功 能 时, 只 需 要 对 普 通 Java 程 序 进 行 相 应 注 解 就 可 以 完 成 当 使 用 注 解 方 法 开 发 时, 要 首 先 在 配 置 文 件 中, 加 入 如 下 配 置 代 码 : <aop:aspectj-autoproxy/> 通 过 它 可 以 启 动 AspectJ 组 件 技 术 在 Spring 的 开 发 中 要 结 合 它 来 进 行 操 作 使 用 注 解 方 式 开 发 和 使 用 配 置 方 法 开 发 最 大 的 不 同 就 是 面 向 切 面 编 程 类, 在 该 类 中 进 行 了 面 向 切 面 中 每 一 部 分 的 注 解, 从 而 不 再 需 要 在 配 置 文 件 中 进 行 配 置 这 里 我 们 来

看 一 个 简 单 的 面 向 切 面 编 程 类, 它 的 代 码 为 : 01 package com.sanqing.service; 02 import org.aspectj.lang.annotation.aspect; 03 import org.aspectj.lang.annotation.before; 04 import org.aspectj.lang.annotation.pointcut; 05 @Aspect // 声 明 切 面 06 public class AspectJAnnotation { 07 @Pointcut("execution(* com.sanqing.dao.*.*(..))") // 声 明 切 入 点 08 public void allmothod(){} // 定 义 切 入 点 名 称 09 @Before("allMothod()") // 声 明 通 知 10 public void mybeforemethod(){ // 定 义 通 知 方 法 11 System.out.println(" 开 始 进 行 数 据 库 操 作 "); 12 } 13 } 在 该 程 序 第 5 行 中 使 用 @Aspect 注 解 声 明 该 程 序 是 一 个 切 面 在 第 7 行 中 使 用 @Pointcut 声 明 了 切 入 点, 也 就 是 对 哪 些 方 法 进 行 操 作, 下 面 的 第 8 行 并 不 是 一 个 类 方 法, 而 是 切 入 点 的 名 称, 在 通 知 中 使 用 第 9 行 中 使 用 @Before 声 明 了 前 置 通 知, 在 其 中 指 定 切 入 点 的 名 称, 从 而 表 明 当 执 行 该 切 入 点 中 的 方 法 时, 执 行 第 10 行 的 通 知 方 法 通 过 这 种 方 式 完 成 面 向 切 面 的 功 能 其 他 程 序 是 和 前 面 配 置 方 式 的 方 法 相 似 的, 这 里 就 不 再 详 细 讲 解 技 巧 : 对 于 普 通 的 AOP 项 目 来 说, 最 好 使 用 注 解 的 方 式 开 发, 它 能 够 节 省 大 量 大 量 但 是 当 Spring 需 要 整 合 其 他 技 术 时, 所 必 须 的 AOP 操 作, 习 惯 于 使 用 配 置 文 件 的 方 式

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 9 章 SSH 框 架 整 合 开 发 SSH 框 架 整 合 指 的 就 是 前 面 所 学 的 Struts Spring 和 Hibernate 框 架 的 整 合, 它 们 每 两 种 框 架 之 间 都 可 以 整 合 进 行 开 发, 在 Hibernate 一 章 中 已 经 讲 解 了 Struts +Hibernate 的 整 合 在 本 章 中 将 继 续 来 讲 解 在 MyEclipse 中 是 如 何 集 成 整 合 开 发 功 能 的 9.1 Spring+Hibernate 整 合 开 发 Spring 框 架 和 Hibernate 框 架 在 前 面 都 已 经 讲 解 过 了, 它 们 都 不 局 限 在 Web 项 目 中 在 Hibernate 技 术 中, 自 动 生 成 的 DAO 是 不 具 有 事 务 能 力 的, 通 过 和 Spring 整 合 可 以 提 供 事 务 操 作 在 Spring 中 还 定 义 了 用 于 简 化 Hibernate 操 作 的 封 装 类, 在 本 节 中 就 对 它 们 进 行 讲 解 9.1.1 创 建 整 合 项 目 因 为 Spring 和 Hibernate 技 术 都 不 局 限 于 Web 项 目, 所 以 这 里 我 们 通 过 一 个 简 单 的 Java 项 目 来 演 示 它 们 之 间 的 整 合 首 先 创 建 一 个 名 称 为 SpringAndHibernate 的 Java 项 目, 然 后 就 是 向 该 项 目 中 加 入 两 种 框 架 的 技 术 支 持 如 果 想 让 Spring 来 管 理 Hibernate, 它 们 的 加 入 顺 序 是 有 严 格 规 定 的, 必 须 先 加 入 Spring 框 架 支 持, 再 加 入 Hibernate 框 架 支 持 在 包 资 源 管 理 器 中, 选 中 SpringAndHibernate 项 目 节 点 在 MyEclipse 的 菜 单 中, 选 择 MyEclipse Project Capabilities Add Spring Capabilities 命 令, 将 弹 出 加 入 Spring 类 库 支 持 操 作 界 面, 在 其 中 选 择 Spring 核 心 类 库, 如 图 9-1 所 示

图 9-1 加 入 Spring 类 库 单 击 Next 按 钮, 将 进 入 对 Spring 配 置 文 件 进 行 设 置 的 界 面, 如 图 9-2 所 示 图 9-2 设 置 Spring 配 置 文 件 单 击 Finish 按 钮, 完 成 Spring 框 架 的 技 术 支 持 在 包 资 源 管 理 器 中, 再 次 选 择 SpringAndHibernate 项 目 节 点 在 MyEclipse 的 菜 单 中, 选 择 MyEclipse Project

3 Capabilities Add Hibernate Capabilities 命 令, 将 弹 出 加 入 Hibernate 类 库 支 持 的 界 面 在 其 中 不 但 要 加 入 Hibernate 的 核 心 类 库, 因 为 要 整 合 Spring, 所 以 还 要 加 入 Spring 的 相 关 类 库, 如 图 9-3 所 示 图 9-3 加 入 Hibernate 相 关 类 库 单 击 Next 按 钮, 将 进 入 对 Hibernate 相 关 信 息 进 行 管 理 的 界 面, 如 图 9-4 所 示 图 9-4 管 理 Hibernate

其 中 Hibernate configuration file (hibernate.cfg.xml) 选 项 表 示 创 建 Hibernate 的 配 置 文 件, 将 Hibernate 的 相 关 配 置 内 容 放 在 其 中 Spring configuration file (applicationcontext.xml) 选 项 表 示 将 Hibernate 的 相 关 配 置 放 到 Spring 配 置 文 件 中 这 两 个 选 项 的 不 同 选 择, 将 造 成 后 面 的 配 置 和 生 成 的 项 目 结 构 有 很 大 不 同 在 实 际 开 发 中, 如 果 让 Hibernate 和 Spring 整 合, 通 常 让 Spring 管 理 Hibernate 配 置 信 息, 所 以 选 择 第 二 个 选 项 单 击 Next 按 钮, 将 进 入 配 置 会 话 工 厂 类 的 界 面, 如 图 9-5 所 示 图 9-5 配 置 会 话 工 厂 类 界 面 最 上 面 是 两 个 单 选 按 钮, New Spring configuration file 表 示 新 创 建 Spring 的 配 置 文 件 Existing Spring configuration file 表 示 使 用 已 经 存 在 的 Spring 配 置 文 件, 因 为 在 前 面 已 经 加 入 过 Spring 的 框 架 支 持, 所 以 选 择 该 选 项, 并 选 择 该 文 件 的 位 置 SessionFactory Id 表 示 在 Spring 配 置 文 件 中 为 Hibernate 中 的 会 话 工 厂 类 配 置 的 Bean 程 序 id, 默 认 是 sessionfactory, 采 用 这 个 默 认 值 就 可 以 单 击 Next 按 钮, 将 进 入 配 置 数 据 源 的 界 面, 选 择 数 据 库 连 接 后, 如 图 9-6 所 示

5 图 9-6 配 置 数 据 源 其 中 Bean Id 表 示 数 据 源 的 id 名, 采 用 默 认 的 datasource 就 可 以 DataSource 表 示 数 据 源 类 型, 这 里 选 择 最 常 用 的 Use JDBC Driver JDBC 驱 动 DB Driver 表 示 数 据 库 连 接 选 择, 它 是 和 数 据 库 视 图 中 数 据 库 浏 览 器 中 的 连 接 相 对 应 的, 这 里 选 择 MySQL 连 接 选 择 后, 会 自 动 将 下 面 的 URL 驱 动 串 用 户 名 密 码 和 方 言 填 写 好 单 击 Next 按 钮, 将 进 入 创 建 会 话 工 厂 类 的 界 面, 如 图 9-7 所 示

图 9-7 创 建 会 话 工 厂 类 该 创 建 界 面 是 和 Hibernate 项 目 中 创 建 界 面 相 同 的 在 其 中 需 要 为 会 话 工 厂 类 定 义 新 创 建 一 个 包, 这 里 仍 然 采 用 hb 的 包 名 单 击 Finish 按 钮, 将 完 成 加 入 Hibernate 框 架 支 持 的 操 作 9.1.2 认 识 整 合 后 的 项 目 向 SpringAndHibernate 项 目 中, 依 次 加 入 Spring 框 架 支 持 和 Hibernate 框 架 支 持 后, 则 Spring+Hibernate 整 合 的 项 目 就 创 建 完 成 了 在 包 资 源 管 理 器 中 展 开 该 项 目, 结 构 如 图 9-8 所 示 图 9-8 整 合 项 目 结 构 在 项 目 结 构 中 可 以 看 出, 在 其 中 导 入 了 多 个 类 库, 这 些 都 是 前 面 操 作 中 加 入 的 在 src 目 录 下, 仅 有 Spring 的 配 置 文 件, 而 没 有 Hibernate 的 配 置 文 件, 这 是 因 为 在 加 入 框 架 支 持 操 作 中 选 择 使 用 Spring 配 置 文 件 对 Hibernate 进 行 管 理 其 中 的 HibernateSessionFactory 文 件 是 会 话 工 厂 类, 在 Hibernate 一 章 中 已 经 对 它 进 行 了 了 解, 这 里 就 不 再 进 行 讲 解 双 击 在 编 辑 区 中 打 开 applicationcontext.xml 文 件, 它 的 具 体 代 码 如 下 : 01 <?xml version="1.0" encoding="utf-8"?> 02 <beans 03 xmlns="http://www.springframework.org/schema/beans" 04 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 05 xmlns:p="http://www.springframework.org/schema/p" 06 xsi:schemalocation="http://www.springframework.org/schema/beans

7 07 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 08 <bean id="datasource" 09 class="org.apache.commons.dbcp.basicdatasource"> 10 <property name="driverclassname" 11 value="com.mysql.jdbc.driver"> 12 </property> 13 <property name="url" value="jdbc:mysql://localhost:3306/mydb"></property> 14 <property name="username" value="root"></property> 15 <property name="password" value="admin"></property> 16 </bean> 17 <bean id="sessionfactory" 18 class="org.springframework.orm.hibernate3.localsessionfactorybean"> 19 <property name="datasource"> 20 <ref bean="datasource" /> 21 </property> 22 <property name="hibernateproperties"> 23 <props> 24 <prop key="hibernate.dialect"> 25 org.hibernate.dialect.mysqldialect 26 </prop> 27 </props> 28 </property> 29 </bean> 30 </beans> 其 中 的 配 置 信 息 都 是 创 建 整 合 项 目 后 自 动 生 成 的 从 第 8 行 到 第 16 行 是 配 置 了 数 据 源, 向 org.apache.commons.dbcp.basicdatasource 类 中 通 过 Setter 方 法 的 方 式 注 入 驱 动 类 URL 用 户 名 和 密 码 的 信 息 值, 这 样 在 Sprnig 的 IoC 容 器 中 就 可 以 创 建 数 据 源 对 象 从 第 17 行 到 第 29 行 配 置 了 会 话 工 厂, 向 org.springframework.orm.hibernate3. LocalSessionFactoryBean 类 中 通 过 Setter 方 法 的 方 式 注 入 数 据 源 Bean 和 Hibernate 属 性 信 息 数 据 源 Bean 在 上 面 已 经 配 置 了,Hibernate 属 性 的 类 型 是 映 射 文 件 集 合, 目 前 只 有 一 个 值, 那 就 是 数 据 库 方 言 当 有 其 他 属 性 配 置 时, 可 以 以 元 素 的 形 式 加 到 该 集 合 中 9.1.3 开 发 整 合 的 DAO 程 序 当 Spring 和 Hibernate 整 合 后, 再 来 开 发 DAO 程 序, 则 生 成 的 代 码 是 和 原 只 有 Hibernate 时 生 成 的 不 一 样 的 同 样 要 首 先 进 入 MyEclipse 的 数 据 库 视 图 中, 打 开 MySQL 连 接, 在 其 中 选 择 操 作 的 数 据 表 节 点 例 如 这 里 仍 然 选 择 mydb 数 据 库 下 的 student 数 据 表 单 击 鼠 标 右 键, 在 其 中 选 择 Hibernate Reverse Engineering 命 令, 将 弹 出 创 建 Hibernate 程 序 的 界 面, 填 写 必 要 信 息 后, 如 图 9-9 所 示

图 9-9 创 建 整 合 DAO 程 序 界 面 中 的 上 半 部 分 是 和 普 通 的 Hibernate DAO 程 序 没 有 区 别 的, 这 样 就 不 再 重 复 讲 解 在 Java Data Access Object (DAO) (Hibernate 3 only) 选 项 中, 在 其 中 的 DAO 程 序 类 型 中, 可 以 看 到 原 来 不 能 选 择 的 Spring DAO 选 项, 现 在 已 经 可 以 选 择 了 Spring config file 表 示 在 哪 个 文 件 中 对 该 DAO 程 序 进 行 配 置, 默 认 的 就 是 在 src 目 录 下 的 Spring 配 置 文 件 SessionFactory Id 表 示 在 DAO 程 序 中 注 入 的 会 话 工 厂 类 id 值, 并 标 明 是 在 哪 一 个 配 置 文 件 中 单 击 Finish 按 钮, 将 完 成 Hibernate 程 序 的 创 建 创 建 完 成 后, 将 在 SpringAndHibernate 项 目 中, 创 建 一 个 名 称 为 com.sanqing.dao 的 包, 在 该 包 下 包 括 刚 创 建 的 实 体 类 映 射 文 件 和 DAO 程 序 实 体 类 和 映 射 文 件 是 没 有 变 化 的, 我 们 主 要 来 看 一 下 DAO 程 序, 它 的 部 分 代 码 为 : 01 package com.sanqing.dao; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class StudentDAO extends HibernateDaoSupport { 04 private static final Log log = LogFactory.getLog(StudentDAO.class); 05 public static final String NAME = "name"; 06 public static final String SCORE = "score"; 07 protected void initdao() { 08 // do nothing 09 } 10 public void save(student transientinstance) { // 保 存 方 法 11 log.debug("saving Student instance"); 12 try {

9 13 gethibernatetemplate().save(transientinstance); 14 log.debug("save successful"); 15 } catch (RuntimeException re) { 16 log.error("save failed", re); 17 throw re; 18 } 19 } 20 public void delete(student persistentinstance) { // 删 除 21 log.debug("deleting Student instance"); 22 try { 23 gethibernatetemplate().delete(persistentinstance); 24 log.debug("delete successful"); 25 } catch (RuntimeException re) { 26 log.error("delete failed", re); 27 throw re; 28 } 29 } 30 public Student findbyid(java.lang.integer id) { // 根 据 ID 查 询 31 log.debug("getting Student instance with id: " + id); 32 try { 33 Student instance = (Student) gethibernatetemplate().get( 34 "com.sanqing.dao.student", id); 35 return instance; 36 } catch (RuntimeException re) { 37 log.error("get failed", re); 38 throw re; 39 } 40 } 41 public List findall() { // 查 询 全 部 42 log.debug("finding all Student instances"); 43 try { 44 String querystring = "from Student"; 45 return gethibernatetemplate().find(querystring); 46 } catch (RuntimeException re) { 47 log.error("find all failed", re); 48 throw re; 49 } 50 } 51 public static StudentDAO getfromapplicationcontext(applicationcontext ctx) { 52 return (StudentDAO) ctx.getbean("studentdao"); 53 } 54 } 其 中 在 第 3 行 中 自 动 生 成 的 DAO 程 序 将 继 承 HibernateDaoSupport 类, 它 是 Spring 框 架 中 用 于 操 作 Hibernate 的 类 在 该 类 中 提 供 了 一 个 setsessionfactory 方 法 来 接 收 一 个 SessionFactory 对 象, 从 而 完 成 SessionFactory 的 注 入 在 setsessionfactory 方 法 中, 通

过 SessionFactory 对 象 创 建 了 HibernateTemplate 对 象 HibernateTemplate 类 中 提 供 了 那 些 简 单 的 诸 如 find load saveorupdate 或 者 delete 操 作 的 方 法, 还 提 供 了 可 选 择 的 快 捷 函 数 来 替 换 回 调 的 实 现 在 HibernateDaoSupport 类 中 还 提 供 了 gethibernatetemplate 方 法, 所 以 在 DAO 程 序 的 操 作 数 据 库 的 方 法 中, 都 会 调 用 继 承 而 来 的 gethibernatetemplate 方 法 首 先 获 取 HibernateTemplate 对 象, 然 后 调 用 相 应 的 方 法 完 成 数 据 库 操 作 自 动 生 成 Hibernate 程 序 的 同 时, 还 会 自 动 完 成 在 Spring 配 置 文 件 中 的 配 置, 配 置 代 码 如 下 : 01 <bean id="sessionfactory" 02 class="org.springframework.orm.hibernate3.localsessionfactorybean"> 03 <property name="datasource"> 04 <ref bean="datasource" /> 05 </property> 06 <property name="hibernateproperties"> 07 <props> 08 <prop key="hibernate.dialect"> 09 org.hibernate.dialect.mysqldialect 10 </prop> 11 </props> 12 </property> 13 <property name="mappingresources"> 14 <list> 15 <value>com/sanqing/dao/student.hbm.xml</value> 16 </list> 17 </property> 18 </bean> 19 <bean id="studentdao" class="com.sanqing.dao.studentdao"> 20 <property name="sessionfactory"> 21 <ref bean="sessionfactory" /> 22 </property> 23 </bean> 其 中 第 15 行 配 置 了 映 射 文 件, 可 以 看 到 它 做 为 集 合 中 的 一 个 元 素 注 入 到 会 话 工 厂 类 中 当 有 多 个 配 置 文 件 时, 都 会 做 为 该 集 合 的 元 素 在 第 19 行 中 对 生 成 的 DAO 程 序 Bean 进 行 了 配 置, 向 其 中 注 入 了 会 话 工 厂 Bean, 从 而 能 够 获 得 HibernateTemplate 对 象 进 行 数 据 库 操 作 9.1.4 事 务 管 理 自 动 生 成 的 DAO 程 序 中 是 没 有 事 务 操 作 的, 以 前 的 做 法 是 继 承 自 动 生 成 的 DAO 程 序, 在 重 写 方 法 中 加 入 事 务 操 作 当 整 合 Spring 技 术 后, 完 全 没 有 必 要 这 样 操 作, 我 们 可 以 通 过 Spring 来 对 事 务 进 行 管 理 在 Spring 中 进 行 事 务 管 理 有 两 种 方 式, 分 别 是 编 程 式 事 务 管 理 和 声 明 式 事 务 管 理, 这 里 我 们 主 要 讲 解 最 常 用 的 声 明 式 事 务 管 理 使 用 声 明 式 事 务 管 理, 可 以 无 需 修 改 项 目

11 中 的 原 代 码, 只 需 要 在 Spring 配 置 文 件 中 进 行 相 应 配 置 就 可 以 声 明 式 事 务 管 理 的 配 置 代 码 如 下 所 示 01 <?xml version="1.0" encoding="utf-8"?> 02 <beans 03 xmlns="http://www.springframework.org/schema/beans" 04 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 05 xmlns:p="http://www.springframework.org/schema/p" 06 xmlns:aop="http://www.springframework.org/schema/aop" 07 xmlns:tx="http://www.springframework.org/schema/tx" 08 xsi:schemalocation="http://www.springframework.org/schema/beans 09 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 10 http://www.springframework.org/schema/aop 11 http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 12 http://www.springframework.org/schema/tx 13 http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 14 <bean id="transactionmanager" 15 class="org.springframework.orm.hibernate3.hibernatetransactionmanager"> 16 <property name="sessionfactory"> 17 <ref bean="sessionfactory"/> 18 </property> 19 </bean> 20 <tx:advice id="txadvice" transaction-manager="transactionmanager"> 21 <tx:attributes> 22 <tx:method name="*" propagation="required"/> 23 </tx:attributes> 24 </tx:advice> 25 <aop:config> 26 <aop:pointcut id="alldaomethod" 27 expression="execution(* com.sanqing.dao.*.*(..))"/> 28 <aop:advisor pointcut-ref="alldaomethod" advice-ref="txadvice"/> 29 </aop:config> 30 </beans> 在 进 行 声 明 式 事 务 配 置 之 前, 首 先 要 在 XML 文 件 头 中 加 入 相 关 的 配 置, 不 然 下 面 的 配 置 是 会 发 生 错 误 的 从 第 14 行 到 第 19 行 对 Hibernate 中 的 事 物 管 理 器 进 行 配 置 从 第 20 行 到 第 24 行 配 置 了 对 哪 些 方 法 进 行 事 务 管 理, 在 其 中 第 22 行 使 用 * 表 示 所 有 方 法 说 明 : 如 果 在 DAO 程 序 中 有 严 格 的 方 法 命 名 规 则, 可 以 分 别 对 增 加 删 除 和 修 改 方 法 进 行 事 务 管 理, 例 如 填 写 delete* 就 表 示 所 有 删 除 方 法 对 于 查 询 方 法 来 说 是 不 需 要 进 行 事 务 管 理 的 从 第 25 行 到 第 29 行 使 用 AOP 配 置 方 式 配 置 了 对 哪 一 个 包 下 的 所 有 方 法 进 行 事 务 管 理, 这 里 填 写 的 是 dao 包 下 这 一 段 配 置 在 开 发 中 可 以 复 制 使 用, 其 中 可 能 改 变 的 只 有 第 27 行 定 义 的 需 要 事 务 处 理 的 方 法

9.1.5 测 试 Spring+Hibernate 整 合 项 目 因 为 在 Spring 中 大 量 使 用 到 的 代 理 模 式, 所 以 当 获 取 实 体 类 Bean 对 象 时 获 取 的 是 该 类 的 代 理 对 象, 所 以 在 测 试 前 要 首 先 进 行 抽 取 接 口 的 操 作 在 包 资 源 管 理 器 中, 选 中 StudentDAO 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Extract Interface 命 令, 将 弹 出 抽 取 接 口 界 面, 在 其 中 输 入 接 口 名 为 IStudentDAO, 然 后 将 其 中 的 所 有 方 法 选 中, 界 面 如 图 9-10 所 示 图 9-10 抽 取 接 口 单 击 OK 按 钮, 将 完 成 抽 取 接 口 的 操 作 接 下 来 就 可 以 开 发 测 试 类 了, 它 的 代 码 为 : 01 package com.sanqing.test; 02 import org.springframework.beans.factory.beanfactory; 03 import org.springframework.context.support.classpathxmlapplicationcontext; 04 import com.sanqing.dao.istudentdao; 05 import com.sanqing.dao.student; 06 public class SHTest { 07 public static void main(string[] args) { 08 BeanFactory factory = 09 new ClassPathXmlApplicationContext("applicationContext.xml"); 10 IStudentDAO studentdao=(istudentdao)factory.getbean("studentdao"); 11 Student student=new Student(); // 创 建 学 生 12 student.setname("tom"); // 设 置 学 生 姓 名 13 student.setscore(85.5); // 设 置 学 生 成 绩

13 14 studentdao.save(student); // 保 存 学 生 15 } 16 } 上 述 代 码 中 第 10 行 获 取 学 生 DAO 程 序 对 象 在 第 11 行 中 创 建 了 学 生 对 象, 并 依 次 将 姓 名 和 成 绩 设 置 到 对 象 中 在 第 14 行 中 调 用 DAO 程 序 中 的 save 方 法, 从 而 将 学 生 对 象 信 息 保 存 到 数 据 库 中 切 换 到 MyEclipse 中 的 数 据 库 视 图 中, 查 看 学 生 数 据 表 可 以 发 现 多 出 了 一 条 学 生 记 录, 字 段 内 容 就 是 测 试 类 中 设 置 的, 从 而 表 明 Spring 和 Hibernate 整 合 的 项 目 开 发 完 成 9.1.6 通 过 注 解 方 式 进 行 事 务 管 理 在 学 习 Spring 的 面 向 切 面 编 程 时, 已 经 知 道 可 以 通 过 注 解 的 方 式 进 行 开 发 在 进 行 事 务 管 理 中, 也 可 以 通 过 注 解 的 方 式 完 成 该 功 能, 而 且 要 比 配 置 的 方 式 简 单 很 多 在 MyEclipse 的 数 据 库 视 图 中, 再 以 teacher 老 师 数 据 表 为 例 进 行 操 作, 从 而 生 成 Hibernate 的 程 序, 包 括 实 体 类 映 射 文 件 和 DAO 程 序 打 开 自 动 生 成 的 DAO 程 序, 在 类 名 上 加 入 如 下 注 解 代 码 : @Transactional 通 过 该 代 码, 标 注 对 该 类 中 的 方 法 进 行 事 务 管 理 然 后 在 Spring 的 配 置 文 件 中 加 入 如 下 配 置 代 码 : 01 <tx:annotation-driven transaction-manager="transactionmanager" 02 proxy-target-class="true"/> 在 其 中 使 用 transaction-manager 属 性 指 定 事 务 管 理 器 这 样 对 事 务 管 理 配 置 就 已 经 完 成 了 最 后 进 行 通 过 测 试 类 进 行 测 试, 它 的 代 码 为 : 01 package com.sanqing.test; 02 import org.springframework.beans.factory.beanfactory; 03 import org.springframework.context.support.classpathxmlapplicationcontext; 04 import com.sanqing.dao.teacher; 05 import com.sanqing.dao.teacherdao; 06 public class TeacherTest { 07 public static void main(string[] args) { 08 BeanFactory factory = 09 new ClassPathXmlApplicationContext("applicationContext.xml"); 10 TeacherDAO teacherdao=(teacherdao)factory.getbean("teacherdao"); 11 Teacher teacher=new Teacher(); // 创 建 老 师 对 象 12 teacher.setname("tom"); // 设 置 老 师 姓 名 13 teacher.setage(36); // 设 置 老 师 年 龄 14 teacherdao.save(teacher); // 保 存 老 师 15 } 16 } 运 行 该 程 序, 是 不 会 发 生 错 误 的 在 数 据 库 视 图 中 查 看 数 据 库 数 据, 可 以 看 到 测 试 类 中 的 测 试 数 据 已 经 保 存 到 数 据 库 中, 表 明 事 务 处 理 成 功 说 明 : 通 过 本 节 的 程 序, 可 以 看 到 使 用 注 解 方 式 进 行 事 务 管 理 要 比 配 置 方 式 简 单 很 多, 但 是 目 前 开 发 中 使 用 最 多 的 还 是 配 置 方 式, 所 以 读 者 要 将 这 两 种 方 式 都 掌 握

9.2 Struts+Spring 整 合 开 发 Struts 和 Spring 整 合 主 要 的 目 的 就 是 让 Spring 管 理 Struts 中 的 Action, 并 且 将 业 务 逻 辑 层 注 入 到 Action 中 Struts 和 Spring 的 整 合 有 多 种 方 式, 这 里 选 择 一 种 最 通 用 最 优 秀 的 整 合 方 式 进 行 讲 解 9.2.1 创 建 Struts+Spring 的 整 合 项 目 因 为 Struts 技 术 时 仅 仅 使 用 在 Java Web 项 目 中 的, 所 以 我 们 首 先 要 开 发 一 个 基 本 的 Java Web 项 目, 项 目 的 名 称 叫 做 StrutsAndSpring 在 加 入 框 架 支 持 时,Struts 和 Spring 的 前 后 顺 序 是 没 有 关 系 的, 我 们 先 来 加 入 Struts 框 架 支 持 在 包 资 源 管 理 器 中, 选 中 SpringAndHibernate 项 目 节 点 在 MyEclipse 的 菜 单 中, 选 择 MyEclipse Project Capabilities Add Struts Capabilities 命 令, 将 弹 出 加 入 Struts 框 架 支 持 的 界 面, 修 改 其 中 的 包 名 后 界 面 如 图 9-11 所 示 图 9-11 加 入 Struts 支 持 单 击 Finish 按 钮, 将 完 成 Struts 框 架 的 支 持 再 次 在 MyEclipse 的 菜 单 中, 选 择 MyEclipse Project Capabilities Add Spring Capabilities 命 令, 将 弹 出 加 入 Spring 类 库 的 界 面, 在 其 中 不 但 要 选 择 Spring 的 核 心 类 库, 还 要 选 择 用 于 Web 项 目 开 发 的 Web 类 库, 如 图 9-12 所 示

15 图 9-12 加 入 Spring 类 库 单 击 Next 按 钮, 将 完 成 Spring 类 库 的 添 加 单 击 Next 按 钮, 将 进 入 对 Spring 配 置 文 件 进 行 设 置 的 界 面, 默 认 情 况 下 是 将 它 创 建 在 src 目 录 下, 但 是 在 Web 项 目 中, 通 常 将 它 放 在 WebRoot WEB-INF 目 录 下, 选 择 该 目 录 后, 界 面 如 图 9-13 所 示 图 9-13 设 置 Spring 配 置 文 件

单 击 Finish 按 钮, 将 完 成 加 入 Spring 框 架 支 持 的 操 作 9.2.2 认 识 Struts+Spring 的 整 合 项 目 依 次 加 入 Struts 和 Spring 的 框 架 支 持 后, 在 MyEclipse 的 包 资 源 管 理 器 中 展 开 StrutsAndSpring 项 目, 项 目 结 构 如 图 9-14 所 示 图 9-14 整 合 项 目 结 构 整 合 后 的 项 目 结 构 是 和 Struts 项 目 结 构 相 差 不 大 的, 只 是 在 其 中 加 入 了 Spring 的 两 个 类 库, 并 且 Spring 的 配 置 文 件 并 不 直 接 放 在 src 目 录 下, 而 是 放 在 了 WebRoot WEB-INF 目 录 下 注 意 : 将 Spring 的 配 置 文 件 放 在 src 目 录 下 也 是 可 以 的, 当 部 署 项 目 后, 它 会 自 动 放 在 WebRoot WEB-INF classes 目 录 下 这 两 种 放 置 方 式 可 能 造 成 后 面 的 配 置 有 所 不 同 9.2.3 整 合 插 件 配 置 在 Spring 的 web 开 发 类 库 中 定 义 了 ContextLoaderPlugIn 类, 通 过 对 该 类 的 配 置 可 以 让 Struts 框 架 找 到 Spring 框 架 的 支 持 这 里 是 通 过 Struts 插 件 的 形 式 加 入 的, 它 的 配 置 代 码 如 下 所 示 : 01 <plug-in classname="org.springframework.web.struts.contextloaderplugin"> 02 <set-property property="contextconfiglocation" 03 value="/web-inf/applicationcontext.xml" /> 04 </plug-in> 该 配 置 代 码 要 放 在 Struts 的 配 置 文 件 的 <struts-config> 标 记 对 中 在 该 配 置 代 码 中, 通 过 ContextLoaderPlugIn 类 可 以 指 定 哪 些 配 置 文 件 需 要 加 载, 从 而 可 以 在 Struts 其 中 时 就 创 建 Spring 的 IoC 容 器

17 注 意 :Spring 的 配 置 文 件 也 可 以 有 多 个, 在 配 置 时 只 需 要 将 这 些 配 置 文 件 到 放 在 第 3 行 的 value 属 性 中 就 可 以, 之 间 使 用 逗 号 分 隔 这 里 也 可 以 使 用 通 配 符, 例 如 /WEB-INF/applicationContext-*.xml 就 表 示 所 有 以 applicationcontext 开 头 的 配 置 文 件 注 意 : 当 项 目 中 的 Spring 配 置 文 件 不 在 WEB-INF 目 录 下 时, 这 里 也 需 要 改 动 这 里 的 配 置 例 如 直 接 放 在 src 目 录 下, 则 value 的 值 应 该 为 /WEB-INF/classes/applicationContext.xml 9.2.4 开 发 业 务 逻 辑 层 并 配 置 这 里 就 通 过 一 个 简 单 的 登 录 程 序 来 举 例, 在 其 中 定 义 完 成 登 录 功 能 的 业 务 方 法 业 务 逻 辑 层 实 现 类 的 代 码 如 下 所 示 01 package com.sanqing.service; 02 public class UserServiceImpl { 03 public boolean login(string username,string password){ 04 if("tom".equals(username)&&"456123".equals(password)){ 05 return true; 06 }else{ 07 return false; 08 } 09 } 10 } 在 其 中 第 3 行 中 定 义 了 登 录 业 务 方 法, 这 里 只 是 简 单 的 通 过 固 定 字 符 来 判 断 用 户 输 入 的 是 否 为 指 定 内 容 在 包 资 源 管 理 中, 选 中 UserServiceImpl 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Refector Extract Interface 命 令, 将 弹 出 抽 取 接 口 的 界 面, 填 写 接 口 名 和 抽 取 的 方 法 后, 界 面 如 图 9-15 所 示

图 9-15 抽 取 接 口 单 击 OK 按 钮, 完 成 业 务 逻 辑 接 口 的 抽 取 接 下 来 就 需 要 在 Spring 的 配 置 文 件 中, 对 业 务 逻 辑 层 实 现 类 进 行 配 置 双 击 ApplicationContext.xml 文 件, 在 编 辑 区 中 打 开 该 文 件, 将 鼠 标 放 在 <beans> 标 记 对 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Spring New Bean 命 令, 将 弹 出 对 Bean 程 序 进 行 配 置 的 界 面, 填 写 配 置 信 息 后, 界 面 如 图 9-16 所 示 图 9-16 配 置 业 务 逻 辑 层 单 击 Finish 按 钮, 将 完 成 对 业 务 逻 辑 层 的 配 置, 并 在 Spring 的 配 置 文 件 中 自 动 生 成 配 置 代 码 9.2.5 开 发 Struts 相 关 程 序 开 发 完 业 务 逻 辑 层 后, 我 们 就 继 续 来 开 发 控 制 层 和 显 示 层, 它 们 都 是 通 过 Struts 技 术 完 成 的 在 MyEclipse 的 包 资 源 管 理 器 中, 选 中 com.sanqing.struts 包 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令, 将 弹 出 选 择 创 建 程 序 的 界 面, 在 其 中 选 择 MyEclipse Web-Struts struts 1.2 Form,Action & JSP 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 ActionForm 的 界 面, 在 其 中 输 入 信 息 后, 界 面 如 图 9-17 所 示

19 图 9-17 创 建 ActionForm 除 了 界 面 中 的 配 置 外, 还 要 选 择 JSP 选 项 卡, 其 中 的 配 置 如 图 9-18 所 示 图 9-18 创 建 JSP 页 面 所 示 单 击 Next 按 钮, 将 进 入 创 建 Action 的 界 面, 在 其 中 填 写 创 建 信 息 后, 如 图 9-19

图 9-19 创 建 Action 单 击 Finish 按 钮, 将 完 成 Action 的 创 建, 也 就 完 成 全 部 Struts 程 序 的 创 建 并 且 同 时 在 Struts 配 置 文 件 中 完 成 对 ActionForm 和 Action 的 创 建 9.2.6 开 发 Action 程 序 代 码 通 过 上 一 小 节 的 创 建, 是 不 会 在 Action 中 加 入 任 何 功 能 代 码 的 在 登 录 Action 中 要 通 过 ActionForm 获 取 登 录 页 面 的 信 息, 并 且 调 用 业 务 逻 辑 层 因 为 本 项 目 采 用 到 了 和 Spring 的 整 合, 所 以 可 以 以 注 入 的 方 式, 将 业 务 逻 辑 层 实 现 类 对 象 注 入 到 Action 中 登 录 Action 的 具 体 代 码 为 : 01 package com.sanqing.struts.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class LoginAction extends Action { 04 private UserService userservice; 05 public void setuserservice(userservice userservice) { 06 this.userservice = userservice; 07 } 08 public ActionForward execute(actionmapping mapping, ActionForm form, 09 HttpServletRequest request, HttpServletResponse response) { 10 LoginForm loginform = (LoginForm) form; 11 String username=loginform.getusername(); // 获 取 用 户 名 12 String password=loginform.getpassword(); // 获 取 密 码 13 try {

21 14 boolean b=userservice.login(username, password); // 调 用 业 务 方 法 15 if(b==true){ 16 return mapping.findforward("success"); 17 }else{ 18 return mapping.findforward("errer"); 19 } 20 } catch (Exception e) { 21 return mapping.findforward("errer"); 22 } 23 } 24 } 在 上 述 代 码 中 第 4 行 定 义 了 业 务 逻 辑 层 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 个 方 式 将 业 务 逻 辑 实 现 类 对 象 注 入 在 第 14 行 中 调 用 login 登 录 方 法, 当 正 确 登 录 时, 将 返 回 success, 从 而 跳 转 到 登 录 成 功 页 面, 这 是 在 配 置 文 件 中 配 置 的 所 以 在 项 目 中 还 要 创 建 登 录 成 功 页 面, 该 页 面 是 非 常 简 单 的, 读 者 可 以 自 己 查 看 光 盘 当 登 录 失 败, 或 者 发 生 异 常 时, 将 重 新 回 答 登 录 页 面 9.2.7 对 Action 进 行 配 置 要 想 要 Spring 框 架 来 管 理 Action 程 序, 不 但 要 在 Spring 的 配 置 文 件 中 进 行 配 置, 还 要 修 改 原 有 的 Struts 配 置 在 Struts 配 置 文 件 中, 要 修 改 原 Action 配 置 的 type 属 性 值 为 org.springframework.web.struts.delegatingactionproxy, 该 类 定 义 在 Spring 框 架 中, 它 是 org.apache.struts.action.action 的 子 类, 通 过 它 可 以 将 请 求 转 发 给 真 正 的 Action 来 进 行 处 理 除 此 之 外, 还 要 在 Spring 配 置 文 件 中 对 Action 进 行 配 置, 从 而 可 以 将 Action 看 成 普 通 的 Bean 来 进 行 管 理 将 鼠 标 放 在 <beans> 标 记 对 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Spring New Bean 命 令, 将 弹 出 对 Action 这 种 特 殊 Bean 程 序 进 行 配 置 的 界 面 因 为 Action 并 不 会 注 入 到 其 他 Bean 中, 而 仅 仅 是 注 入 给 Struts 框 架 所 以 这 里 可 以 只 填 写 name 选 项, 不 填 写 id 选 项 在 name 选 项 中 要 填 写 Action 的 请 求 路 径, 也 就 是 和 Struts 配 置 中 的 path 属 性 相 同 这 样 当 调 用 DelegatingActionProxy 类 时, 根 据 path 属 性 值 查 找 指 定 的 Spring 中 的 Bean 配 置 界 面 如 图 9-20 所 示

图 9-20 配 置 Action 在 其 中 还 要 将 业 务 逻 辑 层 注 入 到 Aciton 中, 因 为 是 通 过 Setter 方 法 的 方 式 注 入 的, 所 以 选 择 Properties 选 项 卡 单 击 Finish 按 钮, 将 完 成 对 登 录 Action 的 配 置 9.2.8 运 行 项 目 到 目 前 为 止, 我 们 的 Struts+Spring 整 合 项 目 就 已 经 开 发 完 成 了, 现 在 就 来 看 一 下 开 发 的 项 目 是 否 正 确 将 项 目 发 布 到 Tomcat 6.x 服 务 器 中, 启 动 该 服 务 器, 打 开 浏 览 器, 在 其 中 输 入 如 下 地 址 : http://localhost:8080/strutsandspring/login.jsp 页 面 显 示 界 面 如 图 9-21 所 示 图 9-21 登 录 页 面 这 是 自 动 生 成 的 页 面, 所 以 其 中 都 是 以 英 文 出 现 的, 如 何 修 改 该 页 面, 在 Struts 一

23 章 已 经 讲 解 过, 这 里 就 不 再 重 复 讲 解 在 用 户 文 本 框 中 输 入 Tom, 在 密 码 框 中 输 入 456123, 单 击 Submit 按 钮, 将 进 入 到 登 录 成 功 页 面, 如 图 9-22 所 示 图 9-22 登 录 成 功 如 果 在 登 录 页 面 中, 输 入 的 是 错 误 信 息, 则 会 执 行 Action, 并 且 再 次 跳 回 到 登 录 页 面, 从 而 表 明 该 Struts 和 Spring 整 合 的 项 目 开 发 成 功 9.3 SSH 框 架 整 合 开 发 博 客 网 站 在 前 面 的 学 习 中 已 经 分 别 讲 解 了 Struts Hibernate 和 Spring 技 术, 并 且 还 讲 解 了 它 们 两 两 之 间 的 整 合, 在 本 节 中 将 通 过 一 个 博 客 网 站 项 目 来 演 示 如 何 将 这 三 种 框 架 技 术 整 合 在 一 起 进 行 开 发 9.3.1 博 客 网 站 项 目 功 能 分 析 在 进 行 大 型 项 目 开 发 之 前, 一 定 要 对 项 目 的 功 能 进 行 分 析, 从 而 进 行 系 统 分 析 用 户 进 入 博 客 网 站 后, 可 以 通 过 注 册 可 以 拥 有 自 己 的 博 客 ; 登 录 后 将 进 入 自 己 的 博 客 在 个 人 博 客 中, 可 以 查 看 自 己 发 表 的 所 有 文 章, 发 表 文 章, 修 改 已 发 表 文 件 和 删 除 文 章 如 果 用 户 不 注 册, 将 以 游 客 的 身 份 出 现 不 管 游 客 还 是 注 册 用 户, 都 可 以 查 看 所 用 用 户 的 文 章, 并 能 够 对 文 件 进 行 评 论 9.3.2 创 建 数 据 表 从 系 统 功 能 上 可 以 看 出, 博 客 网 站 有 三 种 主 体 对 象, 分 别 是 用 户 文 章 和 评 论, 所 以 要 为 它 们 分 别 定 义 三 张 数 据 表, 我 们 将 这 些 数 据 表 都 放 在 blog 数 据 库 中 在 MyEclipse 的 数 据 库 视 图 中, 打 开 MySQL 连 接, 在 Connected to MySQL 节 点 上, 单 击 鼠 标 右 键, 在 菜 单 中 选 择 Create database 命 令, 在 弹 出 的 创 建 数 据 库 界 面 中 填 写 相 关 信 息 后, 如 图 9-23 所 示

图 9-23 创 建 博 客 数 据 库 单 击 Finish 按 钮, 将 完 成 数 据 库 的 创 建 选 中 blog 数 据 库 节 点, 单 击 鼠 标 右 键, 选 择 New Table 命 令, 将 弹 出 创 建 数 据 表 界 面 通 过 该 界 面, 依 次 创 建 用 户 文 章 和 评 论 三 张 数 据 表 首 先 来 创 建 用 户 数 据 表, 它 的 创 建 界 面 如 图 9-24 所 示 图 9-24 创 建 用 户 表 在 用 户 表 中 创 建 id 主 键 用 户 名 和 密 码 两 个 字 段 如 果 网 站 中 可 以 设 置 用 户 昵 称, 或 者 需 要 设 置 验 证 问 题 和 答 案, 都 可 以 添 加 这 些 字 段, 这 里 为 了 简 单 只 填 写 这 两 个 字 段 再 来 创 建 文 章 数 据 表, 创 建 界 面 如 图 9-24 所 示

25 图 9-25 创 建 文 章 表 在 文 章 表 中, 除 了 定 义 了 id 主 键 外, 还 定 义 了 标 题 内 容 发 表 用 户 和 发 表 时 间 等 四 个 字 段 其 中 文 章 内 容 不 应 该 使 用 VARCHAR 类 型, 而 应 该 使 用 TEXT 类 型, 从 而 保 存 大 文 本 内 容 最 后 创 建 评 论 数 据 表, 创 建 界 面 如 图 9-26 所 示 图 9-26 创 建 评 论 表 其 中 id 是 评 论 表 的 主 键 并 且 并 且 定 义 了 Aid 字 段, 用 来 表 示 所 属 文 章 id, 也 就 是 该 评 论 是 发 表 在 哪 一 个 文 章 下 的 除 此 之 外 还 有 发 表 内 容 和 发 表 用 户 两 个 字 段 创 建 数 据 库 和 数 据 表 完 成 后 修 改 MySQL 数 据 库 连 接, 让 其 中 的 URL 指 向 blog

数 据 库 9.3.3 创 建 博 客 项 目 首 先 创 建 一 个 普 通 的 Java Web 项 目, 项 目 名 称 为 BLOG, 然 后 就 是 向 其 中 加 入 框 架 支 持 如 果 想 让 Spring 对 Hibernate 进 行 管 理, 就 一 定 要 先 加 入 Spring 框 架 支 持, 其 他 顺 序 是 没 有 要 求 的 技 巧 : 通 常 情 况 下, 加 入 顺 序 是 Struts Spring 和 Hibernate, 这 也 是 SSH 框 架 整 合 缩 写 的 由 来 先 向 BLOG 项 目 中 加 入 Struts 框 架 支 持, 加 入 界 面, 如 图 9-27 所 示 图 9-27 加 入 Struts 支 持 所 示 然 后 加 入 Spring 框 架 支 持, 其 中 不 要 忘 记 加 入 web 开 发 所 用 到 的 类 库, 如 图 9-28

27 图 9-28 加 入 Spring 类 库 支 持 单 击 Next 按 钮, 将 进 入 对 Spring 配 置 文 件 的 设 置, 将 该 配 置 文 件 放 在 WEB-INF 目 录 下, 如 图 9-29 所 示 图 9-29 设 置 Spring 配 置 文 件 单 击 Finish 按 钮, 将 完 成 Spring 框 架 的 加 入 支 持 操 作 最 后 加 入 Hibernate 的 框 架 支 持, 在 其 中 不 要 忘 记 Spring 整 合 Hibernate 时 所 用 到 的 类 库, 如 图 9-30 所 示 图 9-30 加 入 Hibernate 类 库 支 持

单 击 Next 按 钮, 将 进 入 选 择 Hiibernate 配 置 信 息 支 持 的 界 面, 在 其 中 选 择 第 2 个 选 项, 让 Spring 的 配 置 文 件 对 数 据 库 的 相 关 信 息 管 理 单 击 Next 按 钮, 将 进 入 配 置 会 话 工 厂 类 的 界 面, 选 择 使 用 已 有 Spring 配 置 文 件, 其 他 采 用 默 认 值 单 击 Next 按 钮, 将 进 入 配 置 数 据 库 连 接 的 界 面, 在 其 中 选 择 MySQL, 如 图 9-31 所 示 图 9-31 建 立 数 据 库 连 接 单 击 Next 按 钮, 将 进 入 创 建 会 话 工 厂 类 的 界 面, 将 它 定 义 在 com.sanqing.hb 包 中, 单 击 Finish 按 钮, 将 完 成 加 入 Hibernate 框 架 支 持 的 操 作 加 入 三 种 框 架 支 持 后, 读 者 可 以 自 己 简 单 的 了 解 一 下 项 目 结 构, 这 里 就 不 在 抓 图 讲 解 了 注 意 : 加 入 三 种 框 架 后, 经 常 会 出 现 相 同 包 之 间 重 复 的 错 误, 这 是 因 为 有 可 能 三 个 框 架 中 都 引 入 了 用 一 个 JAR 包, 这 时 候 只 需 要 将 重 复 的 JAR 包 去 掉 就 可 以 最 常 见 的 就 是 asm.jar 包 重 复 9.3.4 进 行 整 合 配 置 仅 仅 加 入 框 架 支 持 后, 是 还 不 能 进 行 整 合 开 发 的, 还 需 要 进 行 必 要 的 配 置 首 先 是 在 Struts 配 置 文 件 中 加 入 Struts 和 Spring 整 合 所 需 要 的 插 件 配 置 代 码, 具 体 代 码 为 : 01 <plug-in classname="org.springframework.web.struts.contextloaderplugin"> 02 <set-property property="contextconfiglocation" 03 value="/web-inf/applicationcontext.xml" /> 04 </plug-in> 当 Spring 和 Hibernate 整 合 时, 通 常 将 事 务 将 给 Spring 进 行 管 理, 所 以 要 在 Spring 配 置 文 件 中 对 事 务 进 行 配 置, 配 置 代 码 如 下 所 示 01 <bean id="transactionmanager" 02 class="org.springframework.orm.hibernate3.hibernatetransactionmanager"> 03 <property name="sessionfactory">

29 04 <ref bean="sessionfactory"/> 05 </property> 06 </bean> 07 <tx:advice id="txadvice" transaction-manager="transactionmanager"> 08 <tx:attributes> 09 <tx:method name="*" propagation="required"/> 10 </tx:attributes> 11 </tx:advice> 12 <aop:config> 13 <aop:pointcut id="alldaomethod" 14 expression="execution(* com.sanqing.dao.*.*(..))"/> 15 <aop:advisor pointcut-ref="alldaomethod" advice-ref="txadvice"/> 16 </aop:config> 在 其 中 不 要 忘 记 加 入 XML 文 件 头 信 息 9.3.5 开 发 数 据 访 问 层 在 实 际 开 发 中,Java 项 目 的 开 发 顺 序 通 常 是 固 定 的, 从 数 据 访 问 层 开 始, 然 后 是 业 务 逻 辑 层, 最 后 是 控 制 层 和 显 示 层 在 SSH 框 架 整 合 项 目 也 是 按 照 这 个 顺 序 的, 我 们 先 来 开 发 数 据 访 问 层, 通 过 它 可 以 进 行 基 本 的 数 据 库 操 作 在 MyEclipse 的 数 据 库 视 图 中, 选 中 要 操 作 的 数 据 表 节 点, 例 如 这 里 选 中 MySQL Connection to MySQL blog TABLE user 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Hibernate Reverse Engineering 命 令, 将 弹 出 创 建 Hibernate 程 序 的 界 面, 在 其 中 选 择 创 建 实 体 类 映 射 文 件 和 DAO 程 序, 如 图 9-32 所 示

图 9-32 创 建 Hibernate 程 序 单 击 Finish 按 钮, 将 完 成 用 户 数 据 访 问 层 程 序 这 里 只 生 成 了 DAO 实 现 类 程 序, 为 了 使 用 Spring 的 注 入 技 术, 所 以 还 需 要 为 它 抽 取 接 口 在 包 资 源 管 理 器 中, 选 中 UserDAO 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Extract Interface 命 令, 将 弹 出 抽 取 接 口 界 面, 在 其 中 输 入 接 口 名 为 IUserDAO, 然 后 将 其 中 的 所 有 方 法 选 中, 界 面 如 图 9-33 所 示 图 9-33 抽 取 用 户 DAO 接 口 抽 取 接 口 后, 就 可 以 使 用 该 接 口 来 引 用 实 现 类 对 象 通 过 上 述 方 法, 依 次 再 对 article 文 章 数 据 表 和 critique 评 论 数 据 表 进 行 操 作, 从 而 生 成 它 们 的 DAO 程 序, 并 也 进 行 抽 取 方 法 操 作 操 作 后 的 具 体 代 码 这 里 就 不 再 给 出, 读 者 可 以 自 己 查 看 光 盘 中 的 代 码 说 明 : 使 用 Spring DAO 类 型 创 建 的 数 据 访 问 层 程 序, 在 创 建 完 成 后, 也 会 在 Spring 配 置 文 件 中 自 动 进 行 配 置, 是 不 需 要 手 动 配 置 的 9.3.6 开 发 用 户 业 务 逻 辑 层 业 务 逻 辑 层 的 主 要 作 用 就 是 定 义 相 应 的 功 能 方 法, 从 而 完 成 项 目 中 的 功 能 需 求 在 项 目 中, 业 务 逻 辑 层 将 被 控 制 层 调 用, 在 业 务 逻 辑 层 的 方 法 中 又 将 调 用 数 据 访 问 层, 从 而 进 行 数 据 库 操 作 业 务 逻 辑 层 也 是 按 照 项 目 操 作 主 体 来 划 分 的, 所 以 本 博 客 项 目 中, 将 分 为 用 户 业 务 逻 辑 实 现 类 文 章 业 务 逻 辑 实 现 类 和 评 论 业 务 逻 辑 实 现 类 在 业 务 逻 辑 实 现 类 中 开 发 哪 些 方 法 是 由 项 目 开 始 之 前 的 功 能 分 析 得 到 的, 例 如 用 户 业 务 逻 辑 实 现 类 中 就 应 该 定 义 注 册 和 登 录 方 法 因 为 在 项 目 中 使 用 到 了 Spring 的 控 制 反 转 技 术, 所 以 要 在 业 务 逻 辑 层 中 定 义 数 据 访 问 层 的 引 用, 并 为 它 定 义 Setter 方 法, 通 过 这 种 方 式 注 入 用 户 业 务 逻 辑 层 的 具 体 代 码 如 下 : 01 package com.sanqing.service;

31 02 import java.util.list; 03 import com.sanqing.dao.iuserdao; 04 import com.sanqing.dao.user; 05 public class UserServiceImpl implements UserService { 06 private IUserDAO userdao; 07 public void setuserdao(iuserdao userdao) { 08 this.userdao = userdao; 09 } 10 public boolean register(user user){ // 注 册 方 法 11 if(userdao.findbyusername(user.getusername()).size()>0){ 12 return false; 13 }else{ 14 userdao.save(user); 15 return true; 16 } 17 } 18 public boolean login(user user){ // 登 录 方 法 19 if(userdao.findbyusername(user.getusername()).size()==0){ 20 return false; 21 }else{ 22 User finduser= 23 (User)userDAO.findByUsername(user.getUsername()).get(0); 24 if(finduser.getpassword().equals(user.getpassword())){ 25 return true; 26 }else{ 27 return false; 28 } 29 } 30 } 31 public List<User> showalluser(){ 32 return userdao.findall(); 33 } 34 } 其 中 第 5 行 中 定 义 了 用 户 数 据 访 问 接 口 引 用, 并 它 定 义 了 Setter 方 法, 从 而 能 够 将 数 据 访 问 实 现 类 对 象 注 入 在 第 9 行 中 定 义 了 注 册 方 法, 在 其 中 要 首 先 判 断 该 用 户 名 是 否 已 经 被 注 册, 如 果 没 有 则 可 以 执 行 保 存 操 作 第 17 行 中 定 义 了 登 录 方 法, 在 其 中 同 样 要 判 断 用 户 名 是 否 存 在, 如 果 不 存 在 时 肯 定 不 能 够 登 录 的 当 存 在 时, 并 且 密 码 也 相 同 的 话, 就 可 以 进 行 登 录 在 第 31 行 中 还 定 义 了 获 取 所 有 用 户 的 方 法, 从 而 可 以 将 所 有 用 户 显 示 在 首 页 中 开 发 完 业 务 逻 辑 实 现 类 后, 执 行 抽 取 接 口 操 作 抽 取 接 口 的 具 体 操 作 就 不 介 绍 了, 它 的 操 作 界 面 如 图 9-34 所 示

图 9-34 抽 取 业 务 逻 辑 接 口 其 中 的 数 据 访 问 接 口 的 Setter 方 法 不 需 要 抽 取 单 击 OK 按 钮, 完 成 用 户 业 务 逻 辑 接 口 的 抽 取 由 于 业 务 逻 辑 层 程 序 是 手 动 开 发 的, 是 不 会 在 Spring 配 置 文 件 中 自 动 配 置 的, 所 以 要 进 行 手 动 配 置 配 置 界 面 如 图 9-35 所 示 图 9-35 配 置 用 户 业 务 实 现 类 完 成 单 击 Finish 按 钮, 完 成 用 户 业 务 实 现 类 的 配 置, 到 这 里 用 户 业 务 逻 辑 层 就 开 发

33 9.3.7 开 发 文 章 业 务 逻 辑 层 在 文 章 业 务 逻 辑 层 中 要 完 成 对 文 章 进 行 操 作 的 功 能, 包 括 显 示 网 站 所 有 文 章 显 示 某 用 户 所 有 文 章 显 示 某 一 文 章 详 细 内 容 发 表 文 章 删 除 文 章 和 对 文 章 进 行 修 改 等 功 能 同 样 在 文 章 业 务 逻 辑 实 现 类 中 定 义 数 据 访 问 接 口 引 用, 并 为 它 定 义 Setter 方 法 文 章 业 务 实 现 类 的 具 体 代 码 如 下 : 01 package com.sanqing.service; 02 import java.util.list; 03 import com.sanqing.dao.article; 04 import com.sanqing.dao.iarticledao; 05 public class ArticleServiceImpl { 06 private IArticleDAO articledao; 07 public void setarticledao(iarticledao articledao) { 08 this.articledao = articledao; 09 } 10 public List<Article> showallarticle(){ // 显 示 所 有 文 章 11 return articledao.findall(); 12 } 13 public List<Article> showuserarticle(string username){// 显 示 指 定 用 户 文 章 14 return articledao.findbyusername(username); 15 } 16 public Article showarticle(int id){ // 显 示 文 章 具 体 内 容 17 return articledao.findbyid(id); 18 } 19 public void addarticle(article article){ // 发 表 文 章 20 articledao.save(article); 21 } 22 public void deletearticle(article article){ // 删 除 文 章 23 articledao.delete(article); 24 } 25 public void updatearticle(article article){ // 更 新 文 章 26 articledao.attachdirty(article); 27 } 28 } 其 中 第 6 行 定 义 了 文 章 数 据 访 问 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 数 据 访 问 实 现 类 对 象 注 入 并 且 在 后 面 依 次 定 义 了 显 示 所 有 文 章 显 示 指 定 用 户 发 表 的 文 章 显 示 文 章 具 体 信 息 发 表 文 章 删 除 文 章 和 更 新 文 章 等 功 能 方 法 开 发 完 文 章 业 务 逻 辑 实 现 类 后, 为 它 抽 取 接 口, 抽 取 接 口 操 作 界 面 如 图 9-36 所 示

图 9-36 抽 取 文 章 业 务 逻 辑 接 口 单 击 OK 按 钮, 完 成 抽 取 文 章 业 务 逻 辑 接 口 操 作 最 后 就 是 在 Spring 配 置 文 件 中 对 文 章 业 务 实 现 类 进 行 配 置, 配 置 界 面 如 图 9-37 所 示 图 9-37 配 置 文 章 业 务 逻 辑 实 现 类 单 击 Finish 按 钮, 完 成 文 章 业 务 逻 辑 实 现 类 的 配 置

35 9.3.8 开 发 评 论 业 务 逻 辑 层 在 评 论 业 务 逻 辑 层 中 要 完 成 对 评 论 进 行 操 作 的 功 能, 包 括 发 表 评 论, 显 示 文 章 所 有 评 论 和 获 取 文 章 评 论 数 量 等 功 能 在 评 论 业 务 逻 辑 实 现 类 中 要 定 义 评 论 数 据 访 问 接 口 引 用, 并 为 它 定 义 Setter 方 法, 通 过 这 种 方 式 注 入 评 论 业 务 逻 辑 实 现 类 的 具 体 代 码 如 下 所 示 01 package com.sanqing.service; 02 import java.util.list; 03 import com.sanqing.dao.critique; 04 import com.sanqing.dao.icritiquedao; 05 public class CritiqueServiceImpl { 06 private ICritiqueDAO critiquedao; 07 public void setcritiquedao(icritiquedao critiquedao) { 08 this.critiquedao = critiquedao; 09 } 10 public void addcritique(critique critique){ // 发 表 评 论 11 critiquedao.save(critique); 12 } 13 public List<Critique> showallcritique (int aid){ // 显 示 文 章 所 有 评 论 14 return critiquedao.findbyaid(aid); 15 } 16 public int getcritiquecount(int aid){ // 获 取 文 章 评 论 数 量 17 return showallcritique (aid).size(); 18 } 19 } 上 述 代 码 中 第 6 行 定 义 了 评 论 数 据 访 问 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 从 而 将 评 论 数 据 访 问 实 现 类 对 象 注 入 在 后 面 依 次 定 义 了 发 表 评 论 显 示 文 章 所 有 评 论 和 获 取 文 章 评 论 数 量 等 方 法 同 样, 开 发 完 评 论 业 务 逻 辑 实 现 类 后, 要 对 它 进 行 抽 取 接 口 的 操 作, 抽 取 接 口 操 作 界 面 如 图 9-38 所 示

图 9-38 抽 取 评 论 业 务 逻 辑 接 口 单 击 OK 按 钮, 将 完 成 抽 取 评 论 业 务 逻 辑 接 口 的 操 作 同 样 开 发 完 评 论 业 务 逻 辑 实 现 类 后, 要 在 Spring 配 置 文 件 中 对 它 进 行 配 置, 配 置 界 面 如 图 9-39 所 示 图 9-39 配 置 评 论 业 务 逻 辑 实 现 类 单 击 Finish 按 钮, 完 成 对 评 论 业 务 逻 辑 实 现 类 的 配 置

37 9.3.9 开 发 首 页 控 制 层 因 为 本 节 中 讲 解 的 博 客 显 示 是 SSH 框 架 整 合 开 发 的, 所 以 项 目 中 的 控 制 层 将 由 Struts 中 的 Action 完 成 在 博 客 网 站 的 首 页 中 将 把 网 站 中 所 有 的 文 章 和 用 户 显 示 出 来, 这 些 都 不 是 固 定 的, 所 以 可 以 定 义 一 个 首 页 控 制 层, 在 其 中 获 取 显 示 数 据 后 跳 转 到 首 页 中 因 为 在 首 页 控 制 层 中, 并 不 需 要 接 收 任 何 参 数, 所 以 是 不 需 要 定 义 相 应 的 ActionForm 的 在 创 建 博 客 项 目 后, 会 在 项 目 中 自 动 创 建 com.sanqing.struts 包 选 中 该 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令, 将 弹 出 选 择 创 建 程 序 的 界 面, 在 其 中 选 择 MyEclipse Web-Struts Struts 1.2 struts 1.2 Action 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 Action 程 序 的 界 面, 在 其 中 输 入 必 须 信 息, 如 图 9-40 所 示 图 9-40 创 建 首 页 控 制 层 单 击 Finish 按 钮, 将 完 成 首 页 控 制 层 的 创 建 因 为 本 项 目 中 将 采 用 SSH 框 架 整 合 开 发, 所 以 在 Action 中 调 用 业 务 逻 辑 层 时 采 用 注 入 的 方 式 在 首 页 Action 中 将 定 义 所 需 要 的 业 务 逻 辑 接 口 引 用, 并 为 它 们 定 义 Setter 方 法, 使 用 这 种 方 式 将 业 务 逻 辑 实 现 类 对 象 注 入 首 页 Action 的 具 体 代 码 如 下 所 示 01 package com.sanqing.struts.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class GoIndexAction extends Action { 04 private UserService userservice; 05 private ArticleService articleservice; 06 private CritiqueService critiqueservice; 07 public void setuserservice(userservice userservice) {

08 this.userservice = userservice; 09 } 10 public void setarticleservice(articleservice articleservice) { 11 this.articleservice = articleservice; 12 } 13 public void setcritiqueservice(critiqueservice critiqueservice) { 14 this.critiqueservice = critiqueservice; 15 } 16 17 public ActionForward execute(actionmapping mapping, ActionForm form, 18 HttpServletRequest request, HttpServletResponse response) { 19 List<User> userlist=userservice.showalluser(); 20 List<Article> articlelist=articleservice.showallarticle(); 21 List<Integer> countlist=new ArrayList<Integer>(); 22 for(int i=0;i<articlelist.size();i++){ 23 Article article=articlelist.get(i); 24 int count=critiqueservice.getcritiquecount(article.getid()); 25 countlist.add(count); 26 } 27 request.setattribute("userlist", userlist); 28 request.setattribute("articlelist", articlelist); 29 request.setattribute("countlist", countlist); 30 return mapping.findforward("success"); 31 } 32 } 因 为 在 首 页 中 将 显 示 所 有 用 户 所 有 文 章 和 每 一 个 文 章 的 评 论 数, 所 以 定 义 用 户 业 务 逻 辑 接 口 文 章 业 务 逻 辑 接 口 和 评 论 业 务 逻 辑 接 口, 并 为 它 们 定 义 Setter 方 法, 从 而 通 过 这 种 方 式 将 相 应 的 实 现 类 对 象 注 入 在 第 19 行 中 调 用 用 户 业 务 逻 辑 实 现 类 中 的 showalluser 方 法, 从 而 获 取 目 前 网 站 中 所 有 的 用 户, 在 第 27 行 中 将 获 取 的 用 户 集 合 保 存 到 request 范 围 内 在 第 20 行 中 调 用 文 章 业 务 逻 辑 实 现 类 中 的 showallarticle 方 法, 从 而 获 取 已 发 表 的 所 有 文 章 组 成 的 集 合, 在 第 28 行 中 同 样 将 它 保 存 到 request 范 围 内 在 第 24 行 中 调 用 评 论 业 务 逻 辑 实 现 类 中 的 getcritiquecount 方 法, 从 而 获 取 每 一 文 章 的 评 论 数, 并 依 次 保 存 到 集 合 中, 在 显 示 时 可 以 按 照 顺 序 依 次 得 到 每 一 文 章 评 论 数 开 发 完 首 页 Action 后, 要 对 它 进 行 配 置 首 先 要 修 改 Struts 配 置 文 件 中 的 配 置, 将 type 属 性 值 修 改 为 org.springframework.web.struts.delegatingactionproxy, 从 而 将 Action 交 给 Spring 进 行 管 理 然 后 再 在 Spring 的 配 置 文 件 中 对 Action 进 行 配 置, 配 置 界 面 如 图 9-41 所 示

39 图 9-41 配 置 首 页 Action 单 击 Finish 按 钮, 将 完 成 对 指 向 首 页 Action 的 Spring 配 置 在 其 中 将 所 需 要 的 业 务 逻 辑 实 现 类 对 象 注 入 9.3.10 开 发 用 户 控 制 层 在 Struts 框 架 中, 通 常 将 对 某 一 主 体 进 行 操 作 的 Action 放 在 一 个 DispatchAction 中, 在 Struts 一 章 中 已 经 讲 解 过 对 于 注 册 和 登 录 来 说, 都 是 对 用 户 进 行 操 作, 所 以 就 可 以 定 义 一 个 DispatchAction, 在 其 中 定 义 分 别 执 行 注 册 和 登 录 的 方 法 因 为 在 注 册 和 登 录 Action 中 都 需 要 接 收 来 自 页 面 的 信 息, 所 以 要 定 义 用 户 ActionForm, 所 以 这 里 选 择 同 时 创 建 JSP 页 面 ActionForm 程 序 和 Action 程 序 的 命 令 在 选 择 创 建 Struts 程 序 的 界 面 中, 选 择 MyEclipse Web-Struts Struts 1.2 struts 1.2 Form,Action & JSP 选 项, 单 击 Next 按 钮, 将 首 先 弹 出 创 建 ActionForm 的 界 面, 填 写 用 户 ActionForm 后, 界 面 如 图 9-41 所 示

图 9-41 创 建 用 户 ActionForm 除 了 界 面 中 的 配 置 信 息 外, 在 Methods 选 项 卡 中 取 消 验 证 和 重 置 两 个 方 法 选 中 状 态, 在 JSP 选 项 卡 中 选 择 创 建 JSP 程 序,JSP 程 序 的 名 称 为 /register.jsp 单 击 Next 按 钮 完 成 用 户 AtionForm 的 创 建, 并 进 入 到 创 建 用 户 Action 的 界 面, 在 其 中 填 写 相 关 信 息 后, 如 图 9-42 所 示

41 图 9-42 创 建 用 户 Action 除 了 界 面 中 的 配 置 外, 在 Form 选 项 卡 中 自 动 配 置 了 用 户 ActionForm, 在 Parameter 选 项 卡 中 还 将 配 置 所 必 须 的 参 数, 这 里 设 置 参 数 名 为 command 单 击 Finish 按 钮, 将 完 成 用 户 Action 的 创 建 打 开 创 建 的 用 户 Action, 在 其 中 分 别 定 义 完 成 注 册 和 登 录 的 控 制 方 法, 其 具 体 代 码 如 下 所 示 01 package com.sanqing.struts.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class UserAction extends DispatchAction { 04 private UserService userservice; 05 public void setuserservice(userservice userservice) { 06 this.userservice = userservice; 07 } 08 public ActionForward register(actionmapping mapping, ActionForm form, 09 HttpServletRequest request, HttpServletResponse response) { 10 UserForm userform = (UserForm) form;// TODO Auto-generated method stub 11 User user=new User(); 12 user.setusername(userform.getusername()); 13 user.setpassword(userform.getpassword()); 14 try { 15 if(userservice.register(user)){ 16 request.getsession().setattribute("username", userform.getusername()); 17 return mapping.findforward("register_success"); 18 }else{ 19 return mapping.findforward("register_fail"); 20 } 21 } catch (Exception e) { 22 return mapping.findforward("register_fail"); 23 } 24 } 25 public ActionForward login(actionmapping mapping, ActionForm form, 26 HttpServletRequest request, HttpServletResponse response) { 27 UserForm userform = (UserForm) form;// TODO Auto-generated method stub 28 User user=new User(); 29 user.setusername(userform.getusername()); 30 user.setpassword(userform.getpassword()); 31 try { 32 if(userservice.login(user)){ 33 request.getsession().setattribute("username", userform.getusername()); 34 return mapping.findforward("login_success"); 35 }else{ 36 return mapping.findforward("login_fail"); 37 } 38 } catch (Exception e) {

39 return mapping.findforward("login_fail"); 40 } 41 } 42 } 上 述 代 码 中 第 4 行 定 义 了 用 户 业 务 逻 辑 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 用 户 业 务 逻 辑 实 现 类 对 象 注 入 在 第 8 行 中 定 义 了 注 册 方 法, 在 其 中 调 用 用 户 业 务 逻 辑 实 现 类 中 的 register 方 法, 当 返 回 结 果 为 true 时, 表 示 能 够 注 册 当 返 回 结 果 为 false, 或 者 操 作 发 生 异 常, 将 不 能 够 进 行 注 册, 返 回 注 册 页 面 登 录 方 法 也 是 类 似 的 开 发 完 代 码 程 序 后, 就 要 对 用 户 Action 进 行 配 置 首 先 将 Struts 配 置 文 件 中 对 用 户 Action 配 置 的 type 属 性 修 改 为 org.springframework.web.struts.delegatingactionproxy 然 后 在 Spring 配 置 文 件 中 对 Action 进 行 配 置, 配 置 界 面 如 图 9-43 所 示 图 9-43 配 置 用 户 Action 单 击 Finish 按 钮, 将 完 成 对 用 户 Action 的 配 置 9.3.11 开 发 个 人 博 客 控 制 层 在 博 客 网 站 中 成 功 注 册 后, 就 会 拥 有 属 于 自 己 的 个 人 博 客 注 册 和 登 录 成 功 后, 就 会 自 动 进 入 自 己 的 博 客 在 首 页 中 的 用 户 栏 中, 单 击 用 户 超 链 接, 或 者 在 文 章 标 题 后 单 击 用 户 超 链 接 都 会 进 入 该 用 户 的 个 人 博 客 在 本 小 节 中 就 来 开 发 完 成 该 功 能 的 个 人 博 客 控 制 层 在 创 建 Ation 的 界 面 中, 输 入 进 入 个 人 博 客 的 必 要 信 息, 如 图 9-44 所 示

43 图 9-44 创 建 个 人 博 客 Action 单 击 Finish 按 钮, 将 完 成 进 入 个 人 博 客 Acton 的 创 建 在 进 入 个 人 博 客 Action 将 完 成 获 取 指 定 用 户 所 发 表 文 章 的 集 合, 并 且 同 样 也 会 将 文 章 的 评 论 数 获 取 出 来, 它 的 具 体 代 码 如 下 所 示 01 package com.sanqing.struts.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class UserBlogAction extends Action { 04 private ArticleService articleservice; 05 private CritiqueService critiqueservice; 06 public void setarticleservice(articleservice articleservice) { 07 this.articleservice = articleservice; 08 } 09 public void setcritiqueservice(critiqueservice critiqueservice) { 10 this.critiqueservice = critiqueservice; 11 } 12 public ActionForward execute(actionmapping mapping, ActionForm form, 13 HttpServletRequest request, HttpServletResponse response) { 14 UserForm userform = (UserForm) form; 15 String username=null; 16 if(userform.getusername()==null){ // 判 断 是 否 接 收 到 参 数 17 username=(string)request.getsession().getattribute("username"); 18 request.getsession().setattribute("self", new Boolean(true)); 19 }else{

20 username=userform.getusername(); 21 request.getsession().setattribute("self", new Boolean(false)); 22 } 23 List<Article> articlelist=articleservice.showuserarticle(username); 24 List<Integer> countlist=new ArrayList<Integer>(); 25 for(int i=0;i<articlelist.size();i++){ 26 Article article=articlelist.get(i); 27 int count=critiqueservice.getcritiquecount(article.getid()); 28 countlist.add(count); 29 } 30 request.setattribute("articlelist", articlelist); 31 request.setattribute("countlist", countlist); 32 return mapping.findforward("success"); 33 } 34 } 上 述 代 码 中 第 4 行 和 第 5 行 中 定 义 了 文 章 和 评 论 业 务 逻 辑 接 口 引 用, 并 为 它 们 定 义 了 Setter 方 法, 从 而 将 对 象 的 业 务 逻 辑 实 现 类 对 象 注 入 因 为 进 入 个 人 博 客 的 方 式 不 同, 可 以 是 通 过 注 册 和 登 录 后 进 入 自 己 的 博 客, 也 可 能 是 进 入 别 人 的 博 客, 在 其 中 要 进 行 时 哪 一 种 方 式 进 入 的 当 进 入 别 人 博 客 时 会 提 交 对 应 用 户 的 用 户 名, 从 而 可 以 通 过 获 取 用 户 名 参 数 得 到 当 进 入 的 是 自 己 博 客 时, 是 不 会 提 交 用 户 名 参 数 的, 可 以 在 session 中 获 取 用 户 名 在 第 23 行 中 通 过 获 取 的 用 户 名 调 用 文 章 业 务 实 现 类 中 的 showuserarticle 方 法, 从 而 获 取 该 用 户 所 发 表 的 所 有 文 章 使 用 首 页 Action 中 同 样 的 方 法 可 以 获 取 每 一 个 文 章 的 评 论 数 量 开 发 完 进 入 个 人 博 客 Action 后, 要 对 它 进 行 配 置 同 样 还 是 首 先 修 改 Struts 配 置 文 件 中 的 type 属 性 值 为 org.springframework.web.struts.delegatingactionproxy, 然 后 在 Spring 的 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 9-45 所 示

45 图 9-45 配 置 个 人 博 客 Action 单 击 Finish 按 钮, 将 完 成 对 进 入 个 人 博 客 Action 的 配 置, 向 其 中 注 入 了 文 章 业 务 逻 辑 实 现 类 对 象 和 评 论 业 务 逻 辑 实 现 类 对 象 9.3.12 开 发 文 章 控 制 层 在 博 客 系 统 中, 对 文 章 的 操 作 是 比 较 多 的, 所 以 我 们 将 所 有 的 文 章 操 作 放 在 一 个 DispatchAction 中 对 文 章 的 操 作 包 括 发 表 文 章 查 看 指 定 文 章 修 改 文 章 和 删 除 文 章, 在 执 行 这 些 操 作 时, 都 要 进 行 接 收 文 章 相 关 参 数 信 息 所 以 在 开 发 文 章 Action 之 前, 要 首 先 创 建 文 章 ActionForm 这 里 我 们 选 择 同 时 创 建 JSP 页 面 ActionForm 和 Action, 首 先 进 入 创 建 ActionForm 界 面, 在 其 中 输 入 相 关 信 息 后, 界 面 如 图 9-46 所 示

图 9-46 创 建 文 章 ActionForm 单 击 Next 按 钮, 将 完 成 文 章 ActionForm 的 创 建, 并 进 入 创 建 文 章 Action 的 界 面, 填 写 相 关 信 息 后, 界 面 如 图 9-47 所 示

47 图 9-47 创 建 文 章 Action 单 击 Finish 按 钮, 将 完 成 文 章 Action 的 创 建 然 后 在 文 章 Action 中 依 次 定 义 完 成 发 表 文 章 查 看 指 定 文 章 修 改 文 章 和 删 除 文 章 的 操 作 方 法, 其 具 体 代 码 如 下 所 示 01 package com.sanqing.struts.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class ArticleAction extends DispatchAction { 04 private ArticleService articleservice; 05 public void setarticleservice(articleservice articleservice) { 06 this.articleservice = articleservice; 07 } 08 public ActionForward showarticle(actionmapping mapping, ActionForm form, 09 HttpServletRequest request, HttpServletResponse response) {// 显 示 文 章 10 ArticleForm articleform = (ArticleForm) form; 11 Article article=articleservice.showarticle(articleform.getid()); 12 request.setattribute("article", article); 13 return mapping.findforward("show_success"); 14 } 15 public ActionForward addarticle(actionmapping mapping, ActionForm form, 16 HttpServletRequest request, HttpServletResponse response) {// 发 表 文 章 17 ArticleForm articleform = (ArticleForm) form; 18 Article article=new Article(); 19 article.settitle(articleform.gettitle()); 20 article.setcontent(articleform.getcontent());

21 article.setusername((string)request.getsession().getattribute("username")); 22 article.setdate(new Timestamp(new Date().getTime())); 23 articleservice.addarticle(article); 24 return mapping.findforward("add_success"); 25 } 26 public ActionForward deletearticle(actionmapping mapping, ActionForm form, 27 HttpServletRequest request, HttpServletResponse response) {// 删 除 文 章 28 ArticleForm articleform = (ArticleForm) form; 29 Article article=articleservice.showarticle(articleform.getid()); 30 articleservice.deletearticle(article); 31 return mapping.findforward("delete_success"); 32 } 33 public ActionForward updatebefore(actionmapping mapping, ActionForm form, 34 HttpServletRequest request, HttpServletResponse response) {// 更 新 前 35 ArticleForm articleform = (ArticleForm) form; 36 Article article=articleservice.showarticle(articleform.getid()); 37 request.setattribute("article", article); 38 return mapping.findforward("update_before"); 39 } 40 public ActionForward updatearticle(actionmapping mapping, ActionForm form, 41 HttpServletRequest request, HttpServletResponse response) {// 更 新 文 章 42 ArticleForm articleform = (ArticleForm) form;/ 43 Article article=new Article(); 44 article.settitle(articleform.gettitle()); 45 article.setcontent(articleform.getcontent()); 46 articleservice.updatearticle(article); 47 return mapping.findforward("update_success"); 48 } 49 } 上 述 代 码 中 第 4 行 定 义 了 文 章 业 务 逻 辑 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 文 章 业 务 逻 辑 实 现 类 对 象 注 入 在 后 面 操 作 代 码 中, 依 次 定 义 了 显 示 文 章 发 表 文 章 删 除 文 章 和 更 新 文 章 方 法, 在 更 新 操 作 中, 要 首 先 将 原 信 息 显 示 在 页 面 中, 然 后 执 行 更 新, 所 以 这 里 有 两 个 方 法 开 发 完 文 章 控 制 层 后, 首 先 要 修 改 Struts 配 置 文 件 中 的 type 属 性 配 置, 将 它 的 值 修 改 为 org.springframework.web.struts.delegatingactionproxy, 然 后 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 9-48 所 示

49 图 9-48 配 置 文 章 Action 单 击 Finish 按 钮, 将 完 成 对 文 章 Action 的 配 置, 向 其 中 注 入 了 文 章 业 务 逻 辑 实 现 类 对 象 9.3.13 开 发 评 论 控 制 层 对 评 论 的 操 作 要 比 文 章 的 操 作 少 很 多, 在 其 中 只 需 要 定 义 显 示 文 章 所 有 评 论 和 发 表 新 评 论 两 个 操 作, 所 以 这 里 也 为 评 论 控 制 层 开 发 一 个 DispatchAction 在 发 表 评 论 时, 也 是 需 要 需 要 接 收 参 数 的, 所 以 也 要 定 义 评 论 ActionForm 这 里 我 们 选 择 同 时 创 建 JSP 页 面 ActionForm 和 Action, 首 先 进 入 创 建 ActionForm 界 面, 在 其 中 输 入 相 关 信 息 后, 界 面 如 图 9-49 所 示

图 9-49 创 建 评 论 ActionForm 单 击 Next 按 钮, 将 完 成 评 论 ActionForm 的 创 建, 并 且 进 入 创 建 评 论 Aciton 的 界 面, 在 其 中 输 入 相 关 信 息 后, 如 图 9-50 所 示

51 图 9-50 创 建 评 论 Action 单 击 Finish 按 钮, 将 完 成 评 论 Action 的 创 建 然 后 在 Action 程 序 中 加 入 显 示 文 章 所 有 评 论 和 发 表 新 评 论 操 作 方 法, 其 具 体 代 码 如 下 所 示 01 package com.sanqing.struts.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class CritiqueAction extends DispatchAction { 04 private CritiqueService critiqueservice; 05 public void setcritiqueservice(critiqueservice critiqueservice) { 06 this.critiqueservice = critiqueservice; 07 } 08 public ActionForward showcritique(actionmapping mapping, ActionForm form, 09 HttpServletRequest request, HttpServletResponse response) {// 显 示 评 论 10 CritiqueForm critiqueform = (CritiqueForm) form; 11 List<Critique> critiquelist= 12 critiqueservice.showallcritique(critiqueform.getaid()); 13 request.setattribute("critiquelist", critiquelist); 14 return mapping.findforward("show_success"); 15 } 16 public ActionForward addcritique(actionmapping mapping, ActionForm form, 17 HttpServletRequest request, HttpServletResponse response) {// 发 表 评 论 18 CritiqueForm critiqueform = (CritiqueForm) form; 19 Critique critique=new Critique(); 20 critique.setcontent(critiqueform.getcontext());

21 critique.setaid(critiqueform.getaid()); 22 String username=" 匿 名 "; 23 if(request.getsession().getattribute("username")!=null){ 24 username=(string)request.getsession().getattribute("username"); 25 } 26 critique.setusername(username); 27 critiqueservice.addcritique(critique); 28 return mapping.findforward("add_success"); 29 } 30 } 上 述 代 码 中 第 4 行 定 义 了 评 论 业 务 逻 辑 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 评 论 业 务 逻 辑 实 现 类 对 象 注 入 在 后 面 的 操 作 中, 依 次 定 义 了 显 示 文 章 所 有 评 论 和 发 表 评 论 的 操 作 方 法 开 发 完 评 论 Action 代 码 后, 就 是 对 评 论 Action 进 行 配 置 首 先 修 改 Struts 配 置 文 件 中 的 type 属 性 值 为 org.springframework.web.struts.delegatingactionproxy 然 后 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 9-51 所 示 图 9-51 配 置 评 论 Action 单 击 Finish 按 钮, 完 成 对 评 论 Action 的 配 置, 向 其 中 注 入 了 评 论 业 务 逻 辑 实 现 类 对 象 到 这 里 为 止, 该 博 客 网 站 项 目 就 已 经 开 发 完 成 了, 读 者 可 以 自 己 开 发 显 示 层 程 序, 也 就 是 JSP 程 序 显 示 层 的 开 发 是 非 常 简 单 的, 这 里 就 不 再 详 细 讲 解

53

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 10 章 进 行 Struts 2 开 发 Struts 2 框 架 和 前 面 讲 解 的 Struts 框 架 有 很 大 的 差 别 Struts 2 是 以 WebWork 为 核 心, 采 用 拦 截 器 的 机 制 来 处 理 用 户 的 请 求, 这 样 的 设 计 也 是 可 以 使 得 业 务 逻 辑 控 制 器 能 够 与 Selvet API 完 全 的 脱 离 开, 所 以 Struts 2 可 以 理 解 为 是 WebWork 的 更 新 产 品 但 是 由 于 Struts 的 名 气, 从 而 使 新 框 架 延 续 该 名 称 随 着 Struts 2 的 发 展, 以 及 慢 慢 取 代 了 Struts 1 的 霸 主 地 位, 越 来 越 多 的 项 目 都 在 向 Struts 2 迁 移, 在 本 节 中 就 来 学 习 一 下 如 何 在 MyEclipse 中 进 行 Struts 2 的 项 目 开 发 说 明 : 在 本 书 讲 解 中, 使 用 Struts 2 就 表 示 的 是 Struts 2 框 架, 如 果 没 有 特 别 说 明, 就 是 指 原 Struts 框 架 10.1 使 用 插 件 开 发 Struts 2 项 目 Struts 2 是 目 前 最 流 行 的 MVC 框 架, 基 于 Struts 2 来 进 行 开 发 可 以 大 大 减 少 开 发 时 间, 提 高 开 发 效 率, 并 降 低 后 期 维 护 时 间 和 精 力 安 装 MyEclipse 后 并 没 有 集 成 开 发 Struts 2 项 目 的 功 能, 对 于 低 版 本 的 MyEclipse 而 言, 只 能 够 手 动 搭 建 Struts 2 项 目 开 发 环 境 但 是 在 MyEclipse 7.5 版 本 中, 可 以 在 线 安 装 Struts 2 项 目 开 发 插 件 10.1.1 安 装 Struts 2 插 件 在 MyEclipse 中, 所 有 的 功 能 都 是 通 过 插 件 完 成 的 只 是 有 些 插 件 在 安 装 MyEclipse 时 就 已 经 默 认 安 装 了, 例 如 前 面 介 绍 的 Hibernate 和 Spring 开 发 但 是 对 于 Struts 2 来 说, 默 认 安 装 MyEclipse 时, 是 不 会 自 动 安 装 它 的 插 件 的, 所 以 需 要 手 动 安 装 安 装 插 件 有 两 种 方 式, 分 别 是 在 线 安 装 和 本 地 安 装, 这 里 我 们 选 择 比 较 容 易 的 在 线 安 装 在 MyEclipse 的 菜 单 中, 选 择 Help Software update Add/Remove Software 命 令, 经 过 一 段 时 间 后, 将 弹 出 如 图 10-1 所 示 的 界 面

图 10-1 选 择 安 装 插 件 目 前 是 没 有 Struts 2 插 件 的, 单 击 Add 按 钮, 将 弹 出 增 加 或 者 删 除 插 件 的 界 面, 如 图 10-2 所 示 图 10-2 增 加 和 删 除 插 件 单 击 Add Site 按 钮, 将 弹 出 连 接 下 载 地 址 的 操 作 界 面, 如 图 10-3 所 示 图 10-3 连 接 插 件 下 载 地 址

3 在 界 面 中 Name 文 本 框 中 输 入 Struts 2, URL 文 本 框 中 输 入 http://mvcwebproject.sourceforge.net, 单 击 OK 按 钮, 回 到 增 加 插 件 界 面, 将 其 中 的 Personal Sites 节 点 展 开, 如 图 10-4 所 示 图 10-4 查 找 到 Struts 2 插 件 单 击 Next 按 钮, 将 进 入 选 择 安 装 Struts 2 插 件 的 界 面, 如 图 10-5 所 示 图 10-5 选 择 安 装 插 件 在 其 中 选 中 Alveole Studio Struts 2 Editor Feature 节 点, 单 击 Apply 按 钮 将 进 入 更 新 MyEclipse 的 界 面, 也 就 是 安 装 Struts 2 插 件 的 界 面, 如 图 10-6 所 示

图 10-6 更 新 MyEclipse 单 击 Update 按 钮, 将 开 始 更 新 MyEclipse, 主 要 是 安 装 Struts 2 插 件 该 步 骤 根 据 本 地 的 网 速 不 同, 花 费 的 时 间 也 不 同 更 新 完 成 后, 将 出 现 一 个 选 择 是 否 重 启 MyEclipse 的 对 话 框, 在 其 中 单 击 Yes 按 钮, 重 启 MyEclipse, 重 启 后 Struts 2 插 件 就 安 装 完 成 说 明 : 所 有 的 在 线 安 装 操 作 都 是 非 常 类 似 的, 在 后 面 的 学 习 中 还 会 使 用 到 其 他 插 件 如 果 本 地 网 速 并 不 好, 笔 者 建 议 采 用 本 地 安 装 的 方 式, 将 插 件 文 件 先 放 置 在 MyEclipse 文 件 中, 然 后 重 启 MyEclipse 具 体 操 作 读 者 可 以 在 网 络 上 搜 索 一 下, 是 不 难 操 作 的 10.1.2 开 发 Struts 2 项 目 Struts 2 框 架 也 是 只 使 用 在 Web 项 目 中 的, 所 以 要 首 先 创 建 一 个 普 通 的 Java Web 项 目 在 MyEclipse 的 菜 单 中, 选 择 File New Project 命 令, 将 弹 出 选 择 创 建 程 序 界 面 选 中 Show all Wizards 选 项, 在 其 中 选 择 Web Dynamic Web Project 节 点, 界 面 如 图 10-7 所 示

5 图 10-7 选 择 创 建 程 序 单 击 Next 按 钮, 将 弹 出 创 建 动 态 Web 项 目 的 界 面, 在 其 中 输 入 项 目 的 名 称 为 FirstStruts 2, 界 面 如 图 10-8 所 示 图 10-8 创 建 动 态 Web 项 目 单 击 Finish 按 钮, 将 完 成 动 态 Web 项 目 的 创 建 在 包 资 源 管 理 器 中, 选 中 FirstStruts 2 项 目 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令, 将 再 次 弹 出 选 择 创 建 程 序 界 面, 在 其 中 选 择 Web Alveole Studio MVC Web Project 节 点,

界 面 如 图 10-9 所 示 图 10-9 创 建 Struts 2 项 目 单 击 Next 按 钮, 将 进 入 创 建 Struts 2 项 目 工 厂 文 件 的 界 面, 如 图 10-10 所 示 图 10-10 创 建 工 程 文 件 在 其 中 选 择 FirstStruts2 项 目, 然 后 在 File name 文 本 框 中 输 入 工 厂 文 件 名 称, 这 里 输 入 project.aswp 单 击 Next 按 钮, 将 进 入 填 写 项 目 描 述 信 息 的 界 面, 如 图 10-11 所 示

7 图 10-11 项 目 描 述 这 里 保 持 默 认 的 不 填 写 任 何 内 容, 单 击 Next 按 钮, 进 入 到 添 加 Struts 2 相 关 类 库 的 界 面, 如 图 10-12 所 示 图 10-12 添 加 Struts 2 类 库 其 中 Target dir 表 示 向 哪 一 个 目 录 中 添 加 类 库, 在 默 认 情 况 下 会 指 定 放 置 目 录 的, 默 认 值 是 /FirstStruts2/WebContent/WEB-INF/lib/ 单 击 Finish 按 钮, 将 完 成 Struts 项 目 的 创 建

10.1.3 认 识 Struts 2 项 目 开 发 完 Struts 2 项 目 后, 我 们 来 简 单 的 认 识 一 下 Struts 2 项 目 结 构 在 包 资 源 管 理 器 中, 将 它 展 开, 如 图 10-13 所 示 图 10-13 Struts 2 项 目 结 构 其 中 Web App Libraries 中 包 含 了 Struts 2 开 发 中 所 用 到 的 所 有 JAR 包, 其 中 是 比 较 多 了, 如 果 仅 进 行 基 本 的 Struts 2 项 目 开 发, 将 只 使 用 到 其 中 的 Struts 核 心 包 web.xml 文 件 是 Web 项 目 中 都 会 有 的, 双 击 打 开 该 文 件, 可 以 发 现 其 中 对 Struts 2 的 核 心 控 制 器 进 行 了 配 置, 具 体 配 置 代 码 如 下 所 示 01 <filter> 02 <filter-name>org.apache.struts2.dispatcher.filterdispatcher</filter-name> 03 <filter-class>org.apache.struts2.dispatcher.filterdispatcher</filter-class> 04 </filter> 05 <filter-mapping> 06 <filter-name>org.apache.struts2.dispatcher.filterdispatcher</filter-name> 07 <url-pattern>*.action</url-pattern> 08 </filter-mapping> 在 其 中 第 7 行 中 配 置 了 当 所 有 以 action 结 尾 的 请 求 都 由 和 核 心 控 制 器 进 行 处 理 注 意 : 当 自 己 手 动 搭 建 Struts 2 开 发 环 境 时, 经 常 在 第 7 行 中 写 入 /*, 表 示 处 理 所 有 请 求, 它 们 两 种 都 是 可 以 的 但 是 不 要 写 入 /*.action, 它 只 表 示 根 目 录 下 的 以 action 结 尾 的 请 求 struts.xml 是 Struts 2 项 目 中 的 核 心 配 置 文 件, 在 后 面 开 发 Action 程 序 时, 都 要 在 该 文 件 中 进 行 配 置 project.aswp 文 件 就 是 在 使 用 Struts 2 插 件 开 发 Struts 2 项 目 时 创 建 的 工 程 文 件, 通 过 该 文 件 可 以 进 行 视 图 化 的 创 建 Struts 2 程 序 双 击 打 开 该 文 件,

9 它 有 多 种 视 图 选 项, 主 要 使 用 其 中 的 Tree 选 项, 选 择 它, 操 作 界 面 如 图 10-14 所 示 图 10-14 视 图 创 建 Struts 2 程 序 在 后 面 的 操 作 中, 我 们 主 要 通 过 该 界 面 进 行 各 种 程 序 的 开 发 10.2 使 用 插 件 开 发 Struts 2 程 序 开 发 完 Struts 2 项 目 后, 就 继 续 来 学 习 如 何 通 过 插 件 开 发 Struts 2 项 目 中 的 程 序 Struts 2 中 最 重 要 的 程 序 那 就 是 Action, 它 是 Struts 2 项 目 的 核 心, 它 从 JSP 页 面 程 序 中 接 收 参 数, 然 后 处 理 后 跳 转 到 其 他 页 面 10.2.1 创 建 Action 程 序 双 击 打 开 project.aswp 文 件, 选 择 编 辑 区 左 下 角 的 Tree 选 项, 将 以 界 面 的 形 式 打 开 该 文 件 在 界 面 的 最 上 面 是 用 于 创 建 Struts 2 程 序 的 功 能 按 钮, 其 中 就 是 用 来 创 建 Action 的 按 钮 单 击 Action 按 钮, 将 打 开 用 于 创 建 Action 的 视 图 界 面, 如 图 10-15 所 示

图 10-15 创 建 Action 视 图 界 面 其 中 Node label 表 示 节 点 标 签, 也 就 是 在 界 面 中 显 示 的 内 容, 这 里 填 写 register action Action name 表 示 访 问 创 建 的 Action 时 所 使 用 的 URL, 这 里 填 写 register 注 意 : 请 求 URL 中, 既 没 有 前 面 的 /, 也 没 有 后 面 的.action, 只 需 要 给 出 名 称 就 可 以 Package 表 示 创 建 Action 所 在 的 配 置 包, 不 填 写 表 示 使 用 默 认 内 容 Action class 表 示 创 建 Action 的 类 名, 这 里 一 定 要 填 写 包 括 包 名 的 完 整 类 名, 如 com.sanqing.action.registeraction Action method 表 示 Action 中 创 建 的 控 制 方 法, 这 里 填 写 register 单 击 OK 按 钮, 将 完 成 注 册 Action 的 创 建, 并 将 其 显 示 在 创 建 操 作 界 面 中, 如 图 10-16 所 示 图 10-16 显 示 Action 双 击 其 中 的 图 标 将 弹 出 创 建 Action 类 的 界 面, 如 图 10-17 所 示

11 图 10-18 创 建 Action 类 从 界 面 中 可 以 看 到, 创 建 Action 程 序 是 和 创 建 普 通 的 Java 类 是 没 有 区 别 的, 只 是 其 中 让 创 建 的 Action 继 承 com.opensymphony.xwork2.actionsupport 类 单 击 Finish 按 钮, 将 完 成 注 册 Action 的 创 建 创 建 Action 程 序 后, 将 自 动 在 编 辑 区 中 打 开 相 应 的 程 序, 自 动 创 建 的 程 序 代 码 为 : 01 package com.sanqing.action; 02 import com.opensymphony.xwork2.actionsupport; 03 public class RegisterAction extends ActionSupport { 04 public String register() { 05 return "success"; 06 } 07 } 在 这 些 代 码 的 基 础 上 可 以 加 入 必 要 的 功 能 代 码, 这 里 我 们 就 仅 让 Action 执 行 跳 转 这 一 简 单 操 作 10.2.2 创 建 JSP 显 示 程 序 在 Struts 2 插 件 中 也 集 成 了 创 建 JSP 显 示 程 序 的 功 能, 单 击 功 能 按 钮 工 具 栏 中 的 按 钮, 将 打 开 用 于 创 建 JSP 程 序 的 视 图 界 面, 如 图 10-19 所 示

图 10-19 创 建 JSP 程 序 其 中 Label 就 是 用 于 在 界 面 中 显 示 的 内 容, 填 写 register success JSP Jsp Path 表 示 JSP 程 序 的 访 问 URL, 这 里 填 写 registersuccess.jsp 单 击 OK 按 钮, 将 完 成 JSP 程 序 的 创 建, 从 而 也 会 将 它 的 图 标 显 示 在 界 面 中, 如 图 10-20 所 示 图 10-20 显 示 JSP 程 序 双 击 JSP 程 序 图 标, 将 打 开 创 建 JSP 程 序 的 界 面, 如 图 10-21 所 示

13 图 10-21 创 建 JSP 程 序 文 件 单 击 Finish 按 钮, 将 完 成 注 册 成 功 页 面 程 序 的 创 建 JSP 程 序 的 编 写 时 非 常 简 单 的, 只 需 要 让 它 输 出 注 册 成 功 信 息 就 可 以 10.2.3 创 建 链 接 当 正 确 执 行 注 册 Action 后 将 跳 转 到 注 册 成 功 页 面, 在 本 节 中 就 来 通 过 插 件 创 建 Action 和 JSP 页 面 的 链 接 在 功 能 工 具 栏 中, 单 击 按 钮, 然 后 先 选 择 Action 图 标, 一 直 拖 动 到 JSP 图 标, 这 时 候 将 打 开 创 建 连 接 的 视 图 界 面, 如 图 10-22 所 示 图 10-22 创 建 链 接 视 图 界 面

其 中 Link Name 表 示 链 接 的 名 称, 也 就 是 Action 中 的 返 回 值, 这 里 填 写 success Fwd type 表 示 跳 转 类 型, 采 用 默 认 的 dispatcher 就 可 以 Params 表 示 跳 转 时 传 递 的 参 数, 不 填 写 表 示 不 传 递 参 数 单 击 OK 按 钮, 将 完 成 链 接 的 创 建 创 建 链 接 后, 显 示 界 面 如 图 10-23 所 示 图 10-23 创 建 链 接 后 界 面 保 存 工 程 文 件, 将 完 成 Struts 2 程 序 的 创 建, 并 完 成 对 它 们 的 配 置 打 开 其 中 的 alveole-struts.xml 文 件, 可 以 看 到 配 置 代 码, 如 下 所 示 01 <package extends="alveole-defaults" name="alveole" namespace="/"> 02 <action class="com.sanqing.action.registeraction" 03 method="register" name="register"> 04 <result name="success" type="dispatcher"> 05 /registersuccess.jsp 06 </result> 07 </action> 08 </package> 其 中 第 2 行 对 注 册 Action 进 行 了 配 置, 第 4 行 中 配 置 了 当 返 回 值 为 success 是 跳 转 到 第 5 行 的 注 册 页 面 10.2.4 运 行 Struts 2 项 目 因 为 使 用 Struts 2 插 件 使 用 的 并 不 是 前 面 Web 一 章 中 介 绍 的 Java Web 项 目, 所 以 它 的 部 署 和 运 行 也 是 有 所 不 同 的 在 包 资 源 管 理 器 中, 选 中 FirstStruts2 项 目 节 点, 单 击 鼠 标 右 键, 选 择 Run Ads Run on Server 命 令, 将 弹 出 发 布 界 面, 在 其 中 选 择 Tomcat 服 务 器, 如 图 10-24 所 示

15 图 10-24 发 布 Struts 2 项 目 单 击 Finish 按 钮, 将 完 成 Struts 2 项 目 的 发 布, 并 且 在 编 辑 区 中 将 打 开 一 个 虚 拟 浏 览 器, 在 其 中 输 入 如 下 地 址 : http://localhost:8080/firststruts2/register.action 则 界 面 如 图 10-25 所 示 图 10-25 显 示 结 果 当 方 法 注 册 Action 后, 返 回 值 为 success, 将 执 行 跳 转, 从 而 跳 转 到 注 册 成 功 JSP 程 序, 从 而 出 现 该 界 面 到 这 里 我 们 就 通 过 插 件 开 发 了 一 个 非 常 简 单 的 Struts 2 项 目, 并 且 运 行 成 功

10.3 手 动 搭 建 Struts 2 开 发 环 境 使 用 Struts 2 插 件 虽 然 能 够 视 图 化 的 创 建 Struts 2 项 目 和 程 序, 但 是 操 作 起 来 远 比 前 面 三 种 框 架 的 复 杂 而 且 该 插 件 和 MyEclipse 集 成 并 不 好, 它 更 倾 向 于 和 Eclipse 集 成 所 以 在 本 节 中 将 来 学 习 一 下 如 何 手 动 的 搭 建 Struts 2 开 发 环 境, 它 也 是 不 难 操 作 的 10.3.1 下 载 和 安 装 Struts 2 类 库 Struts 2 框 架 是 由 Apache 开 源 组 织 开 发 并 负 责 维 护 的, 它 的 官 方 网 站 为 http://struts.apache.org 目 前 Struts 2 最 新 版 本 是 2.1.8, 它 的 下 载 地 址 是 http://struts.apache.org/download.cgi#struts2181 其 中 有 多 个 版 本 的 下 载 链 接, 如 图 10-26 所 示 图 10-26 下 载 版 本 在 页 面 包 括 如 下 下 载 链 接 Full Distribution: 为 完 整 版 的 下 载, 包 括 了 下 面 所 有 的 文 件, 建 议 下 载 这 个 Example Applications: 为 Struts 2 的 示 例 程 序, 这 些 示 例 程 序 在 以 后 的 学 习 中 会 有 很 大 的 帮 助 Essential Dependencies Only: 为 Struts 2 的 核 心 库 Documentation: 为 Struts 2 的 相 关 文 档, 包 含 Struts 2 的 使 用 文 档 参 考 手 册 和 API 文 档 等 有 很 好 的 参 考 价 值 Source: 为 Struts 2 的 源 代 码 因 为 Struts 2 也 是 开 源 框 架, 提 供 源 代 码 以 供 参 考 这 里 我 们 现 在 完 整 版 本, 单 击 Full Distribution 下 面 的 文 件 链 接, 将 开 始 下 载 下 载 完 成 后, 对 下 载 文 件 进 行 解 压, 其 中 包 括 如 下 几 个 文 件 夹 apps: 该 文 件 夹 中 存 放 Struts 2 的 示 例 程 序 doc: 该 文 件 夹 中 存 放 Struts 2 的 相 关 文 档 lib: 该 文 件 夹 中 存 放 Struts 2 的 核 心 类 库, 以 及 第 三 方 的 JAR 文 件 src: 该 文 件 夹 中 存 放 Struts 2 框 架 的 全 部 源 代 码

17 在 lib 下 包 含 了 Struts 2 开 发 的 核 心 JAR 包, 其 中 最 重 要 的 就 是 common-logging-1.0.4.jar commons-fileupload-1.2.1.jar freemarker-2.3.15.jar struts2-core-2.1.8.1.jar xwork-2.1.6.jar 和 ognl-2.7.3.jar 这 几 个 JAR 包, 将 它 们 复 制 到 项 目 中 例 如 我 们 这 里 创 建 一 个 SecondStruts2 目 录, 将 核 心 JAR 包 复 制 到 WebRoot WEB-INF lib 目 录 下, 这 样 就 搭 建 了 Struts 2 项 目 的 开 发 环 境 说 明 : 上 述 导 入 的 JAR 包 只 是 核 心 JAR 包, 如 果 需 要 进 行 更 多 的 功 能, 还 要 导 入 其 他 的 JAR 包, 这 些 都 在 lib 目 录 下 10.3.2 配 置 Web 描 述 符 在 Web 项 目 中, web.xml 文 件 是 必 不 可 少 的, 当 进 行 Struts 2 项 目 开 发 时, 在 该 文 件 中 需 要 对 Struts 2 的 核 心 控 制 器 进 行 配 置 配 置 代 码 如 下 所 示 01 <?xml version="1.0" encoding="utf-8"?> 02 <web-app version="2.5" 03 xmlns="http://java.sun.com/xml/ns/javaee" 04 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 05 xsi:schemalocation="http://java.sun.com/xml/ns/javaee 06 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 07 <filter> 08 <filter-name>struts2</filter-name> 09 <filter-class> 10 org.apache.struts2.dispatcher.ng.filter.strutsprepareandexecutefilter 11 </filter-class> 12 </filter> 13 <filter-mapping> 14 <filter-name>struts2</filter-name> 15 <url-pattern>/*</url-pattern> 16 </filter-mapping> 17 <welcome-file-list> 18 <welcome-file>index.jsp</welcome-file> 19 </welcome-file-list> 20 </web-app> 从 配 置 所 使 用 的 标 记 可 以 看 到, 是 对 过 滤 器 进 行 配 置 在 第 10 行 中 配 置 的 过 滤 器 类 是 org.apache.struts2.dispatcher.ng.filter.strutsprepareandexecutefilter, 它 是 Struts 2 框 架 的 核 心 控 制 器 类 第 15 行 中 使 用 /* 表 示 对 所 有 请 求 进 行 过 滤 由 Struts 2 核 心 控 制 器 进 行 处 理 说 明 : 控 制 层 的 框 架 都 有 有 一 个 核 心 控 制 器 来 处 理 请 求, 它 们 的 作 用 都 是 在 其 中 分 析 请 求, 然 后 调 用 不 同 的 处 理 类, 在 Struts 2 中 就 是 调 用 Action 10.3.3 创 建 Struts 2 配 置 文 件 和 其 他 框 架 一 样,Struts 2 框 架 也 有 自 己 的 配 置 文 件, 在 其 中 完 成 对 Action 的 配 置

Struts 2 的 配 置 文 件 通 常 命 名 为 struts.xml, 它 和 Struts 配 置 文 件 的 名 称 是 不 同 的 Struts 2 配 置 文 件 要 放 置 在 项 目 的 WebRoot WEB-INF classes 目 录 下, 对 于 MyEclipse 中 的 Web 项 目 来 说, 只 需 要 放 在 src 目 录 下 就 可 以, 当 发 布 项 目 后, 将 自 动 放 置 到 WebRoot WEB-INF classes 目 录 下 Struts 2 配 置 文 件 的 基 础 模 板 可 以 参 考 Struts 2 下 载 包 中 的 实 例 中 的 配 置 文 件 在 包 资 源 管 理 器 中, 选 中 SecondStruts2 项 目 中 的 src 目 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New XML(Basic Templates) 命 令, 将 弹 出 创 建 XML 文 件 的 界 面, 如 图 10-27 所 示 图 10-27 创 建 Struts 2 配 置 文 件 单 击 Finish 按 钮, 将 完 成 Struts 2 配 置 文 件 的 创 建 在 编 辑 区 中 打 开 该 文 件, 复 制 如 下 代 码 到 文 件 中 01 <?xml version="1.0" encoding="utf-8"?> 02 <!DOCTYPE struts PUBLIC 03 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 04 "http://struts.apache.org/dtds/struts-2.0.dtd"> 05 <struts> 06 <package name="default" extends="struts-default"> 07 08 </package> 09 </struts> 其 中 第 5 行 的 <struts> 标 记 是 Struts 2 配 置 文 件 的 根 标 记, 对 于 不 同 类 的 Action 来 说 可 以 定 义 不 同 的 package 在 根 标 记 下 创 建 <package> 标 记 来 包 含 一 类 Action

19 10.4 手 动 开 发 Struts 2 程 序 在 前 面 已 经 讲 解 了 通 过 Struts 2 插 件 的 方 式 开 发 Struts 2 程 序, 在 本 节 中 将 讲 解 通 过 手 动 的 方 法 开 发 Struts 2 程 序, 这 也 不 是 困 难 的 在 本 节 中 通 过 一 个 简 单 的 登 录 功 能 来 进 行 讲 解, 其 中 包 括 填 写 登 录 的 表 单 页 面 程 序 进 行 处 理 的 登 录 Action 程 序 和 显 示 登 录 结 果 的 页 面 程 序 10.4.1 开 发 登 录 页 面 程 序 Struts 2 框 架 也 是 拥 有 自 己 独 立 的 一 套 标 签 库 的, 而 且 和 Struts 框 架 中 的 标 签 完 全 不 同 但 是 这 里 为 了 简 单, 只 使 用 HTML 中 的 表 单 标 记 来 定 义 一 个 用 于 登 录 的 表 单 如 何 创 建 HTML 程 序 这 里 就 不 在 详 细 讲 解 了, 表 单 代 码 如 下 所 示 01 <body> 02 <form action="login.action" method="post"> 03 用 户 名 称 :<input type="text" name="username"><br> 04 用 户 密 码 :<input type="password" name="password"><br> 05 <input type="submit" value=" 登 录 "> 06 </form> 07 </body> 在 该 表 单 中 创 建 了 用 于 输 入 用 户 名 的 文 本 框 和 用 于 输 入 密 码 的 密 码 框 执 行 登 录 处 理 后, 如 果 登 录 成 功, 将 跳 转 到 登 录 成 功 页 面 ; 如 果 登 录 失 败, 将 跳 转 到 登 录 失 败 页 面 在 该 登 录 项 目 中, 在 结 果 页 面 中 只 显 示 结 果 信 息, 具 体 代 码 读 者 可 以 查 看 光 盘 注 意 : 在 提 交 表 单 的 action 属 性 指 定 的 提 交 URL 中, 一 定 要 以.action 结 尾, 并 且 前 面 没 有 / 10.4.2 开 发 处 理 登 录 Action 在 Struts 2 项 目 中, 也 通 过 Action 程 序 来 处 理 功 能, 但 是 Struts 2 中 的 Action 程 序 是 和 Struts 项 目 中 的 有 很 大 不 同 的 在 Struts 2 项 目 的 Action 中 并 不 借 助 ActionForm 来 接 收 参 数 值, 而 是 通 过 自 身 来 接 收, 所 以 在 Action 程 序 中 要 定 义 和 表 单 对 应 的 属 性, 并 需 要 为 这 些 属 性 定 义 相 应 的 Setter 和 Getter 方 法 Struts 2 项 目 中 的 Action 中 的 处 理 方 法 名 称 可 以 是 execute, 也 可 以 是 其 他 的 名 称 Struts 2 中 的 Action 是 可 以 和 框 架 相 分 离 的, 也 就 是 不 需 要 继 承 框 架 中 的 类, 但 是 在 开 发 中 通 常 让 它 继 承 com.opensymphony.xwork2.actionsupport, 是 否 继 承 都 是 能 够 完 成 处 理 功 能 的 Struts 2 中 的 Action 程 序 通 常 也 是 放 在 action 包 下 的, 选 中 该 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Class 命 令, 将 弹 出 创 建 Java 类 的 界 面, 在 其 中 输 入 Action 的 相 关 信 息 后, 如 图 10-28 所 示

图 10-28 创 建 登 录 Action 单 击 Finish 按 钮, 将 完 成 登 录 Action 的 创 建 在 编 辑 区 打 开 程 序 后, 加 入 必 要 的 功 能 代 码, 具 体 代 码 如 下 所 示 01 package com.sanqing.action; 02 import com.opensymphony.xwork2.actionsupport; 03 public class LoginAction extends ActionSupport { 04 private String username; // 用 户 名 05 private String password; // 密 码 06 public String getusername() { 07 return username; 08 } 09 public void setusername(string username) { 10 this.username = username; 11 } 12 public String getpassword() { 13 return password; 14 } 15 public void setpassword(string password) { 16 this.password = password; 17 } 18 public String execute() throws Exception { 19 if("tom".equals(username)&&"456123".equals(password)){// 判 断 是 否 登 录 20 return "success"; // 返 回 成 功 字 符 串 21 }else{ 22 return "fail"; // 返 回 失 败 字 符 串 23 } 24 } 25 }

21 上 述 代 码 中 第 4 行 和 第 5 行 分 别 定 义 了 用 户 名 和 密 码 属 性, 并 为 它 们 定 义 了 Getter 和 Setter 方 法, 从 而 能 够 获 取 提 交 表 单 中 的 内 容 在 第 18 行 中 的 处 理 方 法 中, 判 断 用 户 名 和 密 码 是 否 为 指 定 内 容, 从 而 返 回 不 同 的 字 符 串 10.4.3 对 登 录 Action 进 行 配 置 使 用 插 件 开 发 Action 程 序 时, 并 不 需 要 进 行 手 动 配 置, 在 其 中 会 自 动 完 成 配 置 当 手 动 开 发 登 录 Action 后, 是 要 自 己 手 动 配 置 的 配 置 代 码 就 是 放 在 Struts 2 配 置 文 件 中, 具 体 配 置 代 码 如 下 所 示 01 <struts> 02 <package name="default" extends="struts-default"> 03 <action name="login" class="com.sanqing.action.loginaction"> 04 <result name="success">/login_success.jsp</result> 05 <result name="fail">/login_fail.jsp</result> 06 </action> 07 </package> 08 </struts> 其 中 第 3 行 对 登 录 Action 进 行 配 置,class 属 性 指 定 Action 类 的 完 整 类 名,name 属 性 指 定 访 问 该 Action 使 用 的 名 称 第 4 行 中 配 置 了 当 返 回 结 果 为 success 时, 跳 转 到 /login_success.jsp 程 序, 也 就 是 登 录 成 功 页 面 第 5 行 是 配 置 了 登 录 失 败 页 面, 和 配 置 成 功 页 面 相 似 的 10.4.4 发 布 并 运 行 登 录 项 目 在 前 面 学 习 通 过 插 件 方 式 开 发 Struts 2 项 目 时, 发 布 项 目 是 和 本 书 前 面 讲 到 的 发 布 方 式 有 很 大 不 同 的 但 是 如 果 通 过 手 动 开 发 Struts 2 项 目, 那 么 和 发 布 普 通 Web 项 目 没 有 区 别 的 在 Servers 界 面 中 选 中 Tomcat 6.x 服 务 器, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Add Deployment 命 令, 将 弹 出 指 定 服 务 器 发 布 界 面, 在 其 中 选 择 SecondStruts2 项 目 进 行 发 布 然 后 选 中 Tomcat 6.x 服 务 器, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Run Server 命 令, 将 开 始 启 动 服 务 器 启 动 服 务 器 成 功 后, 打 开 浏 览 器 中, 在 其 中 输 入 如 下 地 址 : http://localhost:8080/secondstruts2/login.html 运 行 结 果 如 图 10-29 所 示

图 10-29 登 录 页 面 在 其 中 用 户 名 称 文 本 框 中 输 入 Tom, 在 用 户 密 码 框 中 输 入 456123, 单 击 登 录 按 钮, 运 行 结 果 页 面 如 图 10-30 所 示 图 10-30 登 录 成 功 页 面 如 果 输 入 的 内 容 不 是 上 述 内 容, 将 跳 转 到 登 录 失 败 页 面 从 运 行 结 果 中 可 以 看 到 登 录 项 目 开 发 成 功 10.4.5 Struts 2 程 序 执 行 流 程 开 发 完 Struts 2 的 项 目 后, 我 们 简 单 的 来 看 一 下 Struts 程 序 的 执 行 流 程 在 表 单 中 进 行 提 交 操 作 后, 将 经 过 Web 描 述 符 中 配 置 的 核 心 控 制 器 进 行 过 滤 操 作, 在 其 中 分 析 提 交 地 址, 截 取 后 的 字 符 为 login 然 后 进 入 Struts 2 的 配 置 文 件 中 查 找 以 login 为 名 称 的 Action 配 置, 从 而 找 到 Action 程 序 类 执 行 执 行 返 回 结 果 后, 再 访 问 Struts2 配 置 文 件, 查 找 通 过 <request> 标 记 配 置 的 该 字 符 串 指 定 的 返 回 结 果, 从 而 得 到 相 应 的 页 面

23

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 11 章 SSH2 框 架 整 合 开 发 Struts 2 框 架 在 实 际 开 发 中 主 要 做 控 制 层, 所 以 它 也 可 以 和 Spring Hibernate 进 行 整 合 开 发, 通 常 将 它 们 整 合 后 的 框 架 称 为 SSH2 框 架 Struts2 框 架 只 和 Hibernate 框 架 整 合 是 比 较 少 见 的, 它 并 不 符 合 当 前 Web 项 目 的 分 层 思 想, 所 以 这 里 就 不 对 它 进 行 详 细 讲 解 在 本 章 中 将 先 来 讲 解 Struts2 和 Spring 整 合, 再 来 讲 解 如 何 将 三 种 框 架 整 合 在 一 起 开 发 11.1 Struts 2+Spring 整 合 开 发 在 Struts 和 Spring 整 合 一 节 中, 可 以 发 现 修 改 的 地 方 是 非 常 多 的 Struts2 和 Spring 整 合 是 比 较 方 便 的, 在 Struts 2 框 架 中 专 门 开 发 了 用 于 Spring 整 合 的 插 件 JAR 包, 在 本 节 中 将 主 要 讲 解 它 们 之 间 的 整 合 操 作 11.1.1 创 建 整 合 项 目 因 为 在 MyEclipse 中 并 没 有 集 成 开 发 Struts 2 项 目 的 功 能, 所 以 要 首 先 手 动 创 建 一 个 Struts 2 项 目 在 普 通 的 Web 项 目 中 执 行 加 入 Struts 2 类 库 和 加 入 修 改 配 置 文 件 等 操 作, 这 些 操 作 可 以 参 考 Struts 2 一 章 进 行 学 习 在 Struts 2 项 目 的 基 础 上, 加 入 Spring 框 架 的 支 持 在 MyEclipse 的 菜 单 中, 选 择 MyEclipse Project Capabilities Add Spring Capabilities 命 令, 将 弹 出 加 入 Spring 类 库 支 持 操 作 界 面, 在 其 中 选 择 Spring 核 心 类 库 和 Web 类 库, 如 图 11-1 所 示

图 11-1 加 入 Spring 类 库 单 击 Next 按 钮, 将 进 入 对 Spring 配 置 文 件 进 行 设 置 的 界 面, 如 图 11-2 所 示 说 明 : 在 和 Struts 2 整 合 的 项 目 中, 当 启 动 项 目 时 将 会 首 先 查 找 WEB-INF 目 录 下 的 Spring 配 置 文 件, 如 果 该 根 目 录 下 没 有, 则 会 自 动 查 找 子 目 录 所 以 通 常 直 接 放 在 WEB-INF 目 录 下, 放 在 sec 目 录 下 也 是 可 以 的, 它 将 自 动 放 置 在 WEB-INF classes 目 录 下 图 11-2 设 置 Spring 配 置 文 件 单 击 Finish 按 钮, 完 成 Spring 框 架 的 技 术 支 持 向 普 通 的 Web 项 目 中 Struts 2 框 架 和 Spring 框 架 支 持 后, 是 还 不 能 够 进 行 整 合 开 发 的, 还 要 进 行 必 要 的 配 置 首 先 就 是 要 安 装 Struts 2 框 架 中 的 Spring 插 件, 该 Spring 插 件 是 一 个 JAR 包, 名 称 为 struts2-spring-plugin-2.1.8.1.jar, 在 Struts 2 框 架 的 下 载 包 中 可 以 找 到 它 只 需 要 将 它 复 制 到 WebRoot WEB-INF lib 目 录 下 就 可 以 为 了 让 Web 项 目 启 动 时, 就 能 够 查 找 到 Spring 的 配 置 文 件, 还 需 要 在 Web 描 述 符 中 添 加 一 个 Spring 框 架 中 的 监 听 器 类, 配 置 代 码 如 下 所 示 01 <listener> 02 <listener-class>org.springframework.web.context.contextloaderlistener 03 </listener-class> 04 </listener> 通 过 添 加 该 监 听 器, 使 得 Web 应 用 启 动 时 会 自 动 查 找 WEB-INF 目 录 下 的 applicationcontext.xml 配 置 文 件, 并 根 据 该 配 置 文 件 来 创 建 Spring 容 器 11.1.2 开 发 业 务 逻 辑 层 并 配 置 在 Struts 2 一 章 中 是 以 登 录 程 序 来 讲 解 了 如 何 开 发 Struts 2 程 序 这 里 我 们 通 过 通 过

3 登 录 来 讲 解 Struts 2 和 Spring 整 合 开 发 首 先 是 开 发 业 务 逻 辑 层, 在 其 中 定 义 了 处 理 登 录 的 业 务 方 法, 它 的 代 码 为 : 01 package com.sanqing.service; 02 public class UserServiceImpl { 03 public boolean login(string username,string password){ 04 if("tom".equals(username)&&"456123".equals(password)){ 05 return true; 06 }else{ 07 return false; 08 } 09 } 10 } 在 包 资 源 管 理 中, 选 中 UserServiceImpl 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Refector Extract Interface 命 令, 将 弹 出 抽 取 接 口 的 界 面, 填 写 接 口 名 和 抽 取 的 方 法 后, 界 面 如 图 11-3 所 示 图 11-3 抽 取 接 口 单 击 OK 按 钮, 完 成 业 务 逻 辑 接 口 的 抽 取 接 下 来 就 需 要 在 Spring 的 配 置 文 件 中, 对 业 务 逻 辑 层 实 现 类 进 行 配 置, 配 置 界 面 如 图 11-4 所 示

图 11-4 配 置 业 务 逻 辑 层 单 击 Finish 按 钮, 将 完 成 对 业 务 逻 辑 层 的 配 置, 并 在 Spring 的 配 置 文 件 中 自 动 生 成 配 置 代 码 11.1.3 开 发 控 制 层 的 Action 这 里 我 们 采 用 手 动 创 建 的 方 式 创 建 Action 程 序, 因 为 该 项 目 整 合 了 Spring 框 架, 所 以 在 其 中 可 以 将 业 务 逻 辑 实 现 类 对 象 注 入, 从 而 需 要 在 Action 程 序 中 定 义 相 应 的 Setter 方 法 登 录 Action 的 具 体 代 码 如 下 所 示 01 package com.sanqing.action; 02 import com.opensymphony.xwork2.actionsupport; 03 import com.sanqing.service.userservice; 04 public class LoginAction extends ActionSupport { 05 private String username; // 用 户 名 06 private String password; // 密 码 07 private UserService userservice; 08 public String getusername() { 09 return username; 10 } 11 public void setusername(string username) { 12 this.username = username; 13 } 14 public String getpassword() { 15 return password; 16 } 17 public void setpassword(string password) { 18 this.password = password;

5 19 } 20 public void setuserservice(userservice userservice) { 21 this.userservice = userservice; 22 } 23 public String execute() throws Exception { 24 if(userservice.login(username, password)){ // 判 断 是 否 登 录 25 return "success"; // 返 回 成 功 字 符 串 26 }else{ 27 return "fail"; // 返 回 失 败 字 符 串 28 } 29 } 30 } 在 其 中 第 7 行 中 定 义 了 业 务 逻 辑 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 业 务 逻 辑 实 现 类 对 象 注 入 在 第 24 行 中 调 用 业 务 逻 辑 实 现 类 中 的 login 登 录 方 法, 从 而 判 断 是 否 能 够 登 录 开 发 完 Action 程 序 后, 需 要 进 行 两 个 配 置, 分 别 是 Struts 配 置 和 Spring 配 置 首 先 进 行 Spring 的 配 置, 配 置 界 面 如 图 11-5 所 示 图 11-5 Spring 配 置 登 录 Action 单 击 Finish 按 钮, 从 而 完 成 对 登 录 Action 的 Spring 配 置, 也 从 而 将 业 务 逻 辑 实 现 类 对 象 注 入 到 Action 中 然 后 进 行 Struts 2 配 置, 在 Struts 2 配 置 文 件 中 的 配 置 代 码 如 下 所 示 01 <struts> 02 <package name="default" extends="struts-default"> 03 <action name="login" class="loginaction"> 04 <result name="success">/login_success.jsp</result>

05 <result name="fail">/login_fail.jsp</result> 06 </action> 07 </package> 08 </struts> 在 该 代 码 中 主 要 修 改 了 <action> 节 点 中 的 class 属 性, 因 为 这 时 业 务 控 制 器 不 再 由 Struts 2 来 创 建, 而 是 需 要 从 Spring 的 IoC 容 器 中 取 得 class 属 性 的 属 性 值 为 进 行 Spring 配 置 时 指 定 的 id 值, 也 就 是 <bean> 节 点 的 id 属 性 值 技 巧 : 对 Action 进 行 配 置 时, 通 常 先 进 行 Spring 配 置, 再 进 行 Struts 2 配 置 因 为 在 Struts 2 配 置 中 需 要 使 用 到 Spring 配 置 中 的 id 11.1.4 运 行 整 合 项 目 开 发 Struts 2+Spring 的 项 目 后, 我 们 就 可 以 来 运 行 该 项 目, 从 而 验 证 项 目 开 发 的 是 否 正 确 将 Struts2AndSpring 项 目 发 布 到 Tomcat 服 务 器 中 后, 启 动 Tomcat 服 务 器 打 开 浏 览 器, 在 其 中 输 入 如 下 地 址 : http://localhost:8080/struts2andspring/login.html 运 行 页 面 如 图 11-6 所 示 图 11-6 登 录 页 面 这 里 我 们 输 入 一 个 错 误 的 密 码, 单 击 登 录 按 钮, 运 行 结 果 如 图 11-7 所 示

7 图 11-7 登 录 失 败 从 运 行 结 果 中 可 以 看 到,Struts 2 框 架 成 功 整 合 了 Spring 框 架, 项 目 开 发 正 确 11.2 SSH2 框 架 整 合 开 发 考 试 系 统 SSH2 框 架 整 合 开 发 是 目 前 最 流 行 的 开 发 技 术, 在 前 面 的 学 习 中 已 经 学 习 了 它 们 之 间 两 两 之 间 的 整 合 在 本 节 中 通 过 一 个 考 试 系 统 来 学 习 一 下 如 何 将 三 种 框 架 技 术 整 合 在 一 起 进 行 开 发 11.2.1 考 试 系 统 功 能 分 析 在 一 个 完 成 的 考 试 系 统 中, 应 该 具 有 后 台 的 录 入 试 题 查 看 考 生 考 试 信 息 功 能, 在 前 台 中, 应 该 具 有 考 生 登 录 获 取 考 试 试 卷 提 交 考 试 试 卷 获 取 考 试 成 绩 显 示 试 卷 解 析 等 功 能 后 台 的 功 能 实 现 起 来 是 比 较 容 易 的, 在 本 节 中 主 要 来 完 成 系 统 前 台 考 生 操 作 的 功 能 目 前 的 考 试 形 式 有 两 种, 一 种 是 所 有 考 生 答 同 样 的 试 卷, 这 种 适 合 考 试 一 起 考 试 另 一 种 是 随 机 从 题 库 中 获 取 试 卷, 计 算 机 方 面 的 考 虑 一 般 都 采 用 这 种 方 式, 在 本 系 统 中 也 开 发 这 样 的 功 能 11.2.2 创 建 数 据 库 在 创 建 数 据 库 和 数 据 表 之 前, 首 先 要 分 析 系 统 中 有 哪 些 主 体, 由 于 这 里 我 们 只 开 始 考 试 系 统 的 前 台, 所 以 主 体 包 括 考 生 和 科 目 考 试 试 题, 所 以 要 为 它 们 分 别 定 义 考 生 数 据 表 和 试 题 数 据 表 在 创 建 这 些 数 据 表 之 前, 我 们 为 该 项 目 单 独 创 建 一 个 数 据 库 在 MyEclipse 的 数 据 库 视 图 中, 打 开 MySQL 连 接, 在 Connected to MySQL 节 点 上, 单 击 鼠 标 右 键, 在 菜 单 中 选 择 Create database 命 令, 在 弹 出 的 创 建 数 据 库 界 面 中 填 写 数 据 库 的 名 称 是 exam, 如 图 11-8 所 示 图 11-8 创 建 考 试 数 据 库 单 击 Finish 按 钮, 将 完 成 数 据 库 的 创 建 选 中 exam 数 据 库 节 点, 单 击 鼠 标

右 键, 选 择 New Table 命 令, 将 弹 出 创 建 数 据 表 界 面 通 过 该 界 面, 依 次 创 建 考 生 和 试 题 数 据 表 先 来 创 建 考 生 数 据 表, 创 建 界 面 如 图 11-9 所 示 图 11-9 创 建 考 生 数 据 表 其 中 id 是 考 生 数 据 表 的 主 键, 它 也 是 考 生 的 学 生 证 号 password 是 考 生 进 入 考 试 系 统 的 密 码 name 是 考 生 的 真 实 姓 名, 因 为 姓 名 可 以 重 复, 所 以 不 能 让 它 做 为 主 键 result 是 考 生 的 考 试 成 绩, 设 置 默 认 值 是 0 分 sclass 是 考 生 所 在 的 班 级, 通 过 该 字 段 就 可 以 得 到 某 一 个 班 的 所 有 学 生 成 绩 单 击 Finish 按 钮, 将 完 成 考 生 数 据 表 的 创 建 再 执 行 创 建 数 据 表 操 作, 在 界 面 中 填 写 试 题 信 息, 界 面 如 图 11-10 所 示

9 图 11-10 创 建 试 题 数 据 表 其 中 id 是 试 题 数 据 表 的 主 键,title 是 实 体 的 题 目 optiona optionb optionc 和 optiond 分 别 是 试 题 的 四 个 选 项 answer 是 试 题 的 正 确 答 案, 目 前 系 统 中 只 支 持 选 择 题 parse 是 试 题 的 解 析, 考 生 考 试 完 成 后, 可 以 查 看 单 击 Finish 按 钮, 将 完 成 试 题 数 据 表 的 创 建, 向 其 中 插 入 一 些 测 试 数 据, 这 里 就 不 演 示 了, 读 者 可 以 参 考 数 据 库 管 理 一 章 进 行 学 习 开 发 完 成 后 不 要 忘 记 修 改 数 据 库 连 接 指 向 exam 数 据 库 11.2.3 创 建 考 试 系 统 项 目 首 先 创 建 一 个 普 通 的 Java Web 项 目, 项 目 的 名 称 是 EXAM, 然 后 依 次 向 其 中 加 入 Struts 2 框 架 Spring 框 架 和 Hibernate 框 架 的 支 持 想 项 目 中 加 入 Struts 2 框 架 支 持 时, 首 先 要 将 必 要 的 开 发 包 复 制 到 WebRoot WEB-INF lib 目 录 下, 其 中 包 括 6 个 基 础 包 和 Spring 插 件 包 然 后 在 web.xml 文 件 中 加 入 对 Struts 2 核 心 控 制 器 配 置 的 代 码, 代 码 如 下 : 01 <filter> 02 <filter-name>struts2</filter-name> 03 <filter-class> 04 org.apache.struts2.dispatcher.ng.filter.strutsprepareandexecutefilter</filter-class> 05 </filter> 06 <filter-mapping> 07 <filter-name>struts2</filter-name> 08 <url-pattern>/*</url-pattern> 09 </filter-mapping> 接 下 来 在 src 目 录 下 创 建 Struts 2 的 配 置 文 件, 文 件 名 称 为 struts.xml, 基 础 配 置 代 码 为 :

01 <?xml version="1.0" encoding="utf-8"?> 02 <!DOCTYPE struts PUBLIC 03 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 04 "http://struts.apache.org/dtds/struts-2.0.dtd"> 05 <struts> 06 <package name="default" extends="struts-default"> 07 08 </package> 09 </struts> 加 入 Struts 2 框 架 支 持 后, 依 次 再 加 入 Spring 的 框 架 支 持 选 中 EXAM 项 目 后, 在 MyEclipse 的 菜 单 中, 选 择 MyEclipse Project Capabilities Add Spring Capabilities 命 令, 将 弹 出 加 入 Spring 类 库 支 持 操 作 界 面, 在 其 中 选 择 Spring 核 心 类 库 和 Web 类 库, 如 图 11-11 所 示 图 11-11 加 入 Spring 类 库 单 击 Next 按 钮, 将 进 入 对 Spring 配 置 文 件 进 行 设 置 的 界 面, 在 其 中 将 Spring 的 配 置 文 件 放 置 在 WebRoot WEB-INF 目 录 下, 如 图 11-12 所 示

11 图 11-12 设 置 Spring 配 置 文 件 单 击 Finish 按 钮, 将 完 成 加 入 Spring 框 架 的 支 持 操 作 最 后 是 向 项 目 中 加 入 Hibernate 框 架 支 持 在 加 入 Hibernate 类 库 操 作 界 面 中, 不 要 忘 记 Spring 整 合 Hibernate 时 所 用 到 的 类 库, 如 图 11-13 所 示 图 11-13 加 入 Hibernate 类 库 支 持 单 击 Next 按 钮, 将 进 入 选 择 Hiibernate 配 置 信 息 支 持 的 界 面, 在 其 中 选 择 第 2 个 选 项, 让 Spring 的 配 置 文 件 对 数 据 库 的 相 关 信 息 管 理 单 击 Next 按 钮, 将 进 入 配 置 会 话 工 厂 类 的 界 面, 选 择 使 用 已 有 Spring 配 置 文 件, 其 他 采 用 默 认 值 单 击 Next 按 钮, 将 进 入 配 置 数 据 库 连 接 的 界 面, 在 其 中 选 择 MySQL, 如 图 11-14 所 示

图 11-14 建 立 数 据 库 连 接 单 击 Next 按 钮, 将 进 入 创 建 会 话 工 厂 类 的 界 面, 将 它 定 义 在 com.sanqing.hb 包 中, 单 击 Finish 按 钮, 将 完 成 加 入 Hibernate 框 架 支 持 的 操 作 向 项 目 中 加 入 三 种 框 架 支 持 后, 要 想 进 行 项 目 程 序 开 发, 还 要 进 行 必 要 的 配 置 首 先 是 Struts 2 和 Spring 整 合 时 需 要 配 置 的 Spring 监 听 器, 在 web.xml 文 件 中 添 加 一 个 Spring 框 架 中 的 监 听 器 类, 配 置 代 码 如 下 所 示 01 <listener> 02 <listener-class>org.springframework.web.context.contextloaderlistener 03 </listener-class> 04 </listener> 通 过 添 加 该 监 听 器, 可 以 在 Web 项 目 启 动 时 会 查 找 WEB-INF 目 录 下 的 applicationcontext.xml 配 置 文 件, 通 过 该 配 置 文 件 来 创 建 Spring 容 器 Spring 和 Hibernate 整 合 时, 通 常 将 事 务 交 给 Spring 进 行 管 理, 从 而 要 在 Spring 的 配 置 文 件 中 对 事 务 进 行 配 置, 配 置 代 码 为 : 01 <bean id="transactionmanager" 02 class="org.springframework.orm.hibernate3.hibernatetransactionmanager"> 03 <property name="sessionfactory"> 04 <ref bean="sessionfactory"/> 05 </property> 06 </bean> 07 <tx:advice id="txadvice" transaction-manager="transactionmanager"> 08 <tx:attributes> 09 <tx:method name="*" propagation="required"/> 10 </tx:attributes> 11 </tx:advice> 12 <aop:config> 13 <aop:pointcut id="alldaomethod" 14 expression="execution(* com.sanqing.dao.*.*(..))"/>

13 15 <aop:advisor pointcut-ref="alldaomethod" advice-ref="txadvice"/> 16 </aop:config> 到 此 为 止, 我 们 的 SSH2 框 架 整 合 开 发 的 环 境 就 已 经 创 建 完 成 技 巧 : 如 果 经 常 使 用 同 一 种 框 架 整 合 技 术 进 行 开 发, 可 以 创 建 一 个 空 的 模 板 项 目, 在 该 模 板 项 目 加 入 必 要 的 框 架 支 持 和 进 行 必 要 配 置 当 创 建 某 一 项 目 时, 直 接 复 制 模 板 项 目, 然 后 在 其 中 开 发 项 目 程 序 通 过 这 种 方 式, 可 以 节 省 创 建 项 目 所 花 费 的 时 间 11.2.4 开 发 数 据 访 问 层 对 于 Hibernate 技 术 开 发 的 数 据 访 问 层 来 说, 是 不 受 控 制 层 使 用 什 么 框 架 影 响 的 在 MyEclipse 的 数 据 访 问 层 中, 对 数 据 表 进 行 操 作 自 动 生 成 数 据 访 问 层 程 序 在 考 试 系 统 中 存 在 两 个 数 据 表, 依 次 对 它 们 进 行 生 成 数 据 访 问 层 程 序 的 操 作, 这 里 以 试 题 数 据 表 为 例 在 MyEclipse 的 数 据 库 视 图 中, 选 中 MySQL Connection to MySQL exam TABLE subject 试 题 数 据 表 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Hibernate Reverse Engineering 命 令, 将 弹 出 创 建 Hibernate 程 序 的 界 面, 在 其 中 选 择 创 建 实 体 类 映 射 文 件 和 DAO 程 序, 如 图 11-15 所 示 图 11-15 创 建 试 题 数 据 访 问 层 单 击 Finish 按 钮, 将 完 成 试 题 相 关 的 实 体 类 映 射 文 件 和 DAO 实 体 类 程 序 的 创 建 在 自 动 生 成 的 DAO 程 序 中, 虽 然 自 动 生 成 很 多 操 作 数 据 库 的 方 法, 但 是 并 不 能 完 成 所 有 功 能, 例 如 从 数 据 库 中 随 机 获 取 记 录 这 时 候 就 需 要 手 动 的 完 成 这 类 功 能 随 机 获 取 试 题 记 录 的 方 法 代 码 如 下 所 示 : 01 public List<Subject> randomfindsubject(int number) { 02 Query query = getsession().createquery("from Subject as sub order by rand()");

03 query.setmaxresults(number);// 设 置 查 询 记 录 数 04 List list = query.list(); // 查 询 结 果 保 存 到 list 中 05 return list; 06 } 其 中 使 用 到 了 HQL 语 句, 在 第 2 行 中 调 用 了 rand 函 数, 从 而 获 取 随 机 记 录 说 明 : 在 HQL 语 句 中 有 很 多 非 常 有 用 的 函 数, 出 了 本 节 中 介 绍 的 随 机 函 数 外, 还 有 获 取 前 几 条 记 录, 获 取 从 多 少 条 到 多 少 条 的 记 录 等 函 数 在 本 书 中 是 不 可 能 全 部 讲 到 的, 有 兴 趣 的 读 者 可 以 查 看 相 关 资 料 创 建 DAO 程 序 后, 要 进 行 抽 取 接 口 的 操 作 在 包 资 源 管 理 器 中, 选 中 SubjectDAO 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Extract Interface 命 令, 将 弹 出 抽 取 接 口 界 面, 在 其 中 输 入 接 口 名 为 ISubjectDAO, 然 后 将 其 中 的 所 有 方 法 选 中, 界 面 如 图 11-16 所 示 图 11-16 抽 取 试 题 DAO 接 口 单 击 OK 按 钮, 将 完 成 试 题 DAO 接 口 的 抽 取 操 作 对 试 题 数 据 表 操 作 后, 依 次 再 对 考 生 数 据 表 进 行 操 作, 操 作 步 骤 是 非 常 类 似 的, 只 是 考 生 DAO 程 序 中 并 不 需 要 手 动 加 入 代 码 11.2.5 开 发 考 生 业 务 逻 辑 层 从 前 面 的 功 能 分 析 中 可 以 知 道, 关 于 考 生 的 操 作 功 能 包 括 登 录 考 试 系 统 获 取 考 生 信 息 和 设 置 考 生 成 绩 等 功 能, 在 本 节 中 就 来 开 发 具 有 这 些 功 能 的 考 生 业 务 逻 辑 实 现 类 因 为 该 系 统 使 用 了 Spring 框 架 技 术, 所 以 在 业 务 逻 辑 实 现 类 中 调 用 数 据 访 问 层 时, 采 用 的 是 Setter 方 法 注 入 的 方 式 考 生 业 务 逻 辑 层 的 具 体 代 码 如 下 所 示 : 01 package com.sanqing.service; 02 import com.sanqing.dao.istudentdao; 03 import com.sanqing.dao.student;

15 04 public class StudentServiceImpl { 05 private IStudentDAO studentdao; 06 public void setstudentdao(istudentdao studentdao) { 07 this.studentdao = studentdao; 08 } 09 public boolean login(student student) { // 登 录 10 if(studentdao.findbyid(student.getid())==null){ // 判 断 是 否 有 该 考 生 11 return false; 12 }else{ 13 Student findstudent=studentdao.findbyid(student.getid()); 14 if(student.getpassword().equals(findstudent.getpassword())){ 15 return true; 16 }else{ 17 return false; 18 } 19 } 20 } 21 public Student getstudent(int id) { // 获 取 考 生 信 息 22 return studentdao.findbyid(id); 23 } 24 public void setstudentresult(int id, double result) { 25 Student student = studentdao.findbyid(id);// 根 据 ID 查 找 到 该 学 生 26 student.setresult(result); // 设 置 其 成 绩 27 studentdao.attachdirty(student); // 更 新 学 生 信 息 28 } 29 } 上 述 代 码 中 第 5 行 定 义 了 考 生 数 据 访 问 层 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 考 生 数 据 访 问 层 实 现 类 对 象 注 入 在 后 面 的 代 码 中 依 次 定 义 了 登 录 方 法 获 取 考 生 信 息 方 法 和 设 置 考 生 成 绩 方 法 开 发 完 考 生 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 考 生 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 11-17 所 示

图 11-17 抽 取 考 生 业 务 逻 辑 接 口 单 击 OK 按 钮, 将 完 成 考 生 业 务 逻 辑 接 口 的 抽 取 开 发 完 考 生 业 务 逻 辑 实 现 类 后, 要 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 11-18 所 示 图 11-18 配 置 考 生 业 务 逻 辑 实 现 类 单 击 Finish 按 钮, 将 完 成 考 生 业 务 逻 辑 实 现 类 的 Spring 配 置, 将 考 生 数 据 访 问 层 实 现 类 对 象 注 入 到 其 中 11.2.6 开 发 试 题 业 务 逻 辑 层 在 试 题 业 务 逻 辑 实 现 类 中, 要 完 成 对 试 题 进 行 操 作 的 功 能 方 法, 包 括 获 取 试 题 信 息 随 机 获 取 一 张 试 卷 和 计 算 考 生 考 试 成 绩 等 功 能 试 题 业 务 逻 辑 实 现 类 的 具 体 代 码 为 : 01 package com.sanqing.service; 02 import java.util.list; 03 import com.sanqing.dao.isubjectdao; 04 import com.sanqing.dao.subject; 05 public class SubjectServiceImpl { 06 private ISubjectDAO subjectdao; 07 public void setsubjectdao(isubjectdao subjectdao) { 08 this.subjectdao = subjectdao; 09 } 10 public Subject getsubject(int id){ // 获 取 试 题 信 息 11 return subjectdao.findbyid(id); 12 } 13 public List<Subject> randomfindsubject(int number) { // 随 机 获 取 试 卷 14 return subjectdao.randomfindsubject(number);

17 15 } 16 public int accountresult(list<integer> subjectids, 17 List<String> studentanswers) { // 计 算 考 试 成 绩 18 int GeneralPoint = 0;// 总 分 19 for(int i = 0; i < subjectids.size(); i++) { 20 String rightanswer = subjectdao.findbyid(subjectids.get(i)). 21 getanswer(); // 得 到 正 确 答 案, 通 过 试 题 ID 22 if(rightanswer.equals(studentanswers.get(i))) { 23 GeneralPoint += 20; // 加 20 分 24 } 25 } 26 return GeneralPoint; 27 } 28 } 上 述 代 码 中 第 6 行 定 义 了 试 题 数 据 访 问 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 试 题 数 据 访 问 实 现 类 对 象 注 入 在 后 面 的 代 码 中, 依 次 定 义 了 获 取 试 题 信 息 随 机 获 取 试 卷 和 计 算 考 试 成 绩 的 方 法 技 巧 : 我 们 的 系 统 中 是 固 定 每 一 道 题 分 值 是 相 同 的, 如 果 不 同, 可 以 在 试 题 数 据 表 中 定 义 分 值 字 段 在 计 算 结 果 业 务 方 法 中 还 要 求 每 一 道 题 的 分 值, 从 而 完 成 累 加 开 发 完 试 题 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 试 题 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 11-19 所 示 图 11-19 抽 取 试 题 业 务 逻 辑 接 口 单 击 OK 按 钮, 完 成 试 题 业 务 逻 辑 接 口 的 抽 取 最 后 同 样 还 是 在 Spring 配 置 文 件 中 对 试 题 业 务 实 现 类 进 行 配 置, 配 置 界 面 如 图 11-20 所 示

图 11-20 配 置 试 题 业 务 逻 辑 实 现 类 单 击 Finish 按 钮, 将 完 成 对 试 题 业 务 逻 辑 实 现 类 的 配 置, 并 将 试 题 数 据 访 问 实 现 类 对 象 注 入 11.2.7 开 发 登 录 系 统 Action 考 生 进 入 考 试 系 统 以 后, 首 先 看 到 的 就 是 登 录 页 面, 在 其 中 通 过 输 入 自 己 的 考 试 号 和 密 码 就 可 以 进 入 系 统 登 录 页 面 程 序 就 不 再 给 出 了, 读 者 可 以 查 看 光 盘, 这 里 主 要 来 讲 处 理 登 录 的 Action, 它 在 系 统 中 主 要 作 为 控 制 层 登 录 Action 的 主 要 功 能 就 是 接 收 登 录 页 面 中 的 考 试 号 和 密 码 信 息, 然 后 调 用 业 务 逻 辑 层 中 的 登 录 业 务 方 法, 最 后 根 据 返 回 结 果 跳 转 到 不 同 页 面 下 面 来 看 登 录 Action 的 具 体 代 码 01 package com.sanqing.action; 02 import com.opensymphony.xwork2.actionsupport; 03 import com.sanqing.dao.student; 04 import com.sanqing.service.studentservice; 05 public class LoginAction extends ActionSupport { 06 private int id; 07 private String password; 08 private StudentService studentservice; 09 public int getid() { 10 return id; 11 } 12 public void setid(int id) {

19 13 this.id = id; 14 } 15 public String getpassword() { 16 return password; 17 } 18 public void setpassword(string password) { 19 this.password = password; 20 } 21 public void setstudentservice(studentservice studentservice) { 22 this.studentservice = studentservice; 23 } 24 public String execute() throws Exception { 25 Student student=new Student(); // 创 建 考 生 对 象 26 student.setid(id); // 设 置 考 生 编 号 27 student.setpassword(password); // 设 置 考 生 密 码 28 if(studentservice.login(student)){ // 判 断 是 否 正 确 29 Map session = ActionContext.getContext().getSession(); 30 session.put("student", student); 31 return "success"; 32 }else{ 33 return "fail"; 34 } 35 } 36 } 上 述 代 码 中 第 6 行 和 第 7 行 分 别 定 义 了 考 试 的 考 号 和 密 码 属 性, 并 为 它 们 定 义 了 Setter 方 法, 从 而 获 取 登 录 页 面 中 的 信 息 在 第 8 行 定 义 了 考 生 业 务 逻 辑 接 口 引 用, 为 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 考 生 业 务 逻 辑 实 现 类 对 象 注 入 在 处 理 方 法 中, 第 25 行 创 建 考 生 对 象, 并 依 次 将 获 取 的 考 号 和 密 码 信 息 设 置 到 对 象 中 第 28 行 中 调 用 考 生 业 务 实 现 类 中 的 登 录 业 务 方 法, 从 而 判 断 是 否 能 够 登 录 开 发 完 Action 程 序 后, 要 在 Spring 和 Struts 2 配 置 文 件 中 进 行 配 置, 通 常 是 先 在 Spring 配 置 文 件 中 进 行 配 置 它 的 配 置 界 面 如 图 11-21 所 示

图 11-21 Spring 配 置 登 录 Action 单 击 Finish 按 钮, 将 完 成 登 录 Action 的 配 置, 并 将 考 生 业 务 逻 辑 实 现 类 对 象 注 入 进 去 完 成 Spring 配 置 后, 要 在 Struts 2 配 置 文 件 中 进 行 配 置, 它 的 配 置 代 码 为 : 01 <action name="login" class="loginaction"> 02 <result name="success" type="chain" >getrandomsubject</result> 03 <result name="fail">/login.jsp</result> 04 </action> 其 中 第 1 行 的 class 属 性 指 定 Spring 配 置 文 件 中 的 id 属 性 第 2 行 配 置 了 当 考 生 登 录 成 功 后, 将 执 行 获 取 随 机 试 题 Action, 该 Action 将 在 下 一 小 节 中 开 发 11.2.8 开 发 获 取 随 机 试 题 Action 考 生 登 录 成 功 后, 进 入 考 试 系 统 后, 将 自 动 获 取 一 张 试 卷, 该 试 卷 中 的 试 题 是 从 题 库 中 随 机 获 取 的 在 本 小 节 中 就 来 开 发 完 成 该 功 能 的 Action 程 序 在 获 取 随 机 试 题 Action 中, 并 不 会 接 收 任 何 参 数, 在 其 中 将 调 用 试 题 业 务 逻 辑 实 现 类 中 的 随 机 获 取 试 题 业 务 方 法, 它 的 具 体 代 码 如 下 所 示 01 package com.sanqing.action; 02 import java.util.list; 03 import javax.servlet.http.httpservletrequest; 04 import org.apache.struts2.servletactioncontext; 05 import com.opensymphony.xwork2.actionsupport; 06 import com.sanqing.dao.subject; 07 import com.sanqing.service.subjectservice; 08 public class GetRandomSubjectAction extends ActionSupport { 09 private SubjectService subjectservice; 10 public void setsubjectservice(subjectservice subjectservice) {

21 11 this.subjectservice = subjectservice; 12 } 13 public String execute() throws Exception { 14 List<Subject> subjectlist=subjectservice.randomfindsubject(5); // 随 机 5 道 15 HttpServletRequest request = ServletActionContext.getRequest(); 16 request.setattribute("subjectlist", subjectlist); // 保 存 到 request 中 17 return "success"; 18 } 19 } 上 述 代 码 中 第 9 行 定 义 了 试 题 业 务 逻 辑 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 试 题 业 务 逻 辑 实 现 类 对 象 注 入 在 操 作 方 法 中, 第 14 行 调 用 试 题 业 务 逻 辑 实 现 类 中 的 randomfindsubject 随 机 获 取 试 题 方 法, 从 而 获 取 由 试 题 对 象 组 成 的 集 合 并 在 第 16 行 中 将 试 题 对 象 集 合 保 存 到 request 中 说 明 : 从 获 取 随 机 试 题 Action 中 也 可 以 更 好 的 体 会 到 Action 的 作 用,Action 就 是 接 收 参 数, 调 用 业 务 方 法, 然 后 根 据 结 果 跳 转 具 体 功 能 的 实 现 由 业 务 逻 辑 层 来 完 成, 例 如 获 取 随 机 试 题 开 发 完 获 取 随 机 试 题 Action 后, 首 先 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 11-22 所 示 图 11-22 配 置 获 取 随 机 试 题 Ation 单 击 Finish 按 钮, 将 完 成 在 Spring 配 置 文 件 中 对 获 取 随 机 试 题 Action 的 配 置, 从 而 将 试 题 业 务 逻 辑 实 现 类 对 象 注 入 接 下 来 就 是 在 Struts 2 配 置 文 件 中 进 行 配 置, 配 置 代 码 如 下 所 示 01 <action name="getrandomsubject" class="getrandomsubjectaction">

02 <result name="success">/showsubject.jsp</result> 03 </action> 当 执 行 完 获 取 随 机 试 题 Action 后, 将 跳 转 到 显 示 所 有 试 题 的 页 面, 在 其 中 对 保 存 在 request 中 的 试 题 对 象 集 合 遍 历, 从 而 得 到 一 张 试 卷 显 示 获 取 试 题 的 页 面 程 序 读 者 可 以 自 己 查 看 光 盘 代 码 技 巧 : 在 显 示 所 有 试 题 的 页 面 程 序 中, 使 用 到 了 隐 藏 域 来 获 取 试 题 id 值, 从 而 在 计 算 考 试 成 绩 时 可 以 获 取 这 些 值, 从 而 能 够 调 用 后 台 获 取 它 的 正 确 答 案 11.2.9 开 发 获 取 考 试 成 绩 Action 在 显 示 试 题 的 试 卷 中, 单 击 提 交 答 卷 按 钮, 将 执 行 获 取 考 试 成 绩 Action 在 获 取 考 试 成 绩 Action 中, 不 但 获 取 考 生 提 交 的 答 案, 还 会 获 取 所 有 试 题 的 id 属 性 值 在 Action 的 操 作 功 能 中 计 算 考 生 的 成 绩, 并 将 所 得 成 绩 保 存 到 考 生 数 据 表 中 获 取 考 试 成 绩 Acton 的 具 体 代 码 为 : 01 package com.sanqing.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class SubmitExamAction extends ActionSupport{ 04 private List<Integer> subjectid; // 考 试 考 试 试 题 id 05 private SubjectService subjectservice; 06 private StudentService studentservice; 07 public List<Integer> getsubjectid() { 08 return subjectid; 09 } 10 public void setsubjectid(list<integer> subjectid) { 11 this.subjectid = subjectid; 12 } 13 public void setsubjectservice(subjectservice subjectservice) { 14 this.subjectservice = subjectservice; 15 } 16 public void setstudentservice(studentservice studentservice) { 17 this.studentservice = studentservice; 18 } 19 public String execute() throws Exception { 20 HttpServletRequest request = ServletActionContext.getRequest(); 21 List<String> studentanswers = new ArrayList<String>(); 22 for(int i = 0; i < 5; i++) { 23 String answer = request.getparameter("subjectanswer"+i); 24 studentanswers.add(answer); // 将 每 一 题 的 答 案 保 存 到 答 案 集 合 中 25 } 26 int GeneralPoint = subjectservice.accountresult(subjectid, studentanswers); 27 Map session = ActionContext.getContext().getSession(); 28 Student student = (Student)session.get("student"); 29 int studentid = student.getid(); 30 Student student2=studentservice.getstudent(studentid);

23 31 studentservice.setstudentresult(studentid, GeneralPoint); 32 request.setattribute("studentname", student2.getname());// 保 存 学 生 姓 名 33 request.setattribute("generalpoint", GeneralPoint); 34 session.put("subjectids", subjectid);// 将 考 试 题 目 保 存 到 session 35 return SUCCESS; 36 } 37 } 上 述 代 码 中 第 4 行 定 义 了 试 题 id 属 性 集 合, 并 为 它 定 义 了 Setter 和 Getter 方 法, 从 而 获 取 考 生 试 卷 中 所 有 的 试 题 id 在 第 5 行 和 第 6 行 分 别 定 义 了 试 题 和 考 生 的 业 务 逻 辑 接 口 引 用, 并 为 它 们 定 义 了 Setter 方 法, 从 而 将 相 应 的 实 现 类 对 象 注 入 在 操 作 方 法 中, 首 先 依 次 将 用 户 提 交 的 答 案 获 取 出 来, 并 且 将 它 们 保 存 到 集 合 中 在 第 26 行 中 调 用 试 题 业 务 逻 辑 实 现 类 中 的 accountresult 获 取 考 试 成 绩 业 务 方 法 在 第 31 行 中 调 用 考 生 业 务 逻 辑 实 现 类 中 的 setstudentresult 设 置 成 绩 业 务 方 法, 从 而 将 考 生 的 成 绩 保 存 到 数 据 库 中 在 第 34 行 中 将 所 有 的 考 试 题 目 保 存 到 session 中, 因 为 显 示 试 卷 正 确 答 案 和 解 析 时 将 会 使 用 到 开 发 完 获 取 考 试 成 绩 Action 后, 首 先 要 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 11-23 所 示 图 11-23 配 置 获 取 考 试 成 绩 Action 单 击 Finish 按 钮, 将 完 成 获 取 考 试 成 绩 Action 在 Spring 配 置 文 件 中 的 配 置 接 下 来 就 是 在 Struts 2 配 置 文 件 中 进 行 配 置, 配 置 代 码 如 下 所 示 01 <action name="submitexam" class="submitexamaction"> 02 <result name="success">/examresult.jsp</result> 03 </action> 当 执 行 完 获 取 考 试 成 绩 Action 后, 将 跳 转 到 第 2 行 配 置 的 显 示 考 试 结 果 的 页 面 中,

在 其 中 将 把 考 生 姓 名 和 对 应 的 成 绩 显 示 出 来 在 该 页 面 中 还 会 定 义 一 个 查 看 答 案 超 链 接, 从 而 将 考 生 所 做 试 卷 的 正 确 答 案 显 示 出 来 11.2.10 开 发 显 示 试 题 答 案 Action 在 显 示 考 试 成 绩 页 面 中, 单 击 查 看 答 案 超 链 接 将 执 行 显 示 试 题 答 案 Action 在 显 示 试 题 答 案 Action 中 并 不 会 接 收 任 何 参 数, 只 是 获 取 保 存 在 session 中 的 试 题 id 集 合, 从 而 获 取 对 应 的 每 一 个 试 题 对 象 显 示 试 题 答 案 Action 的 具 体 代 码 如 下 所 示 01 package com.sanqing.action; 02 // 省 略 导 入 接 口 和 类 的 代 码 03 public class ShowSubjectAnswer extends ActionSupport{ 04 private SubjectService subjectservice; 05 public void setsubjectservice(subjectservice subjectservice) { 06 this.subjectservice = subjectservice; 07 } 08 public String execute() throws Exception { 09 List<Subject> subjects = new ArrayList<Subject>();// 保 存 学 生 考 过 的 题 目 10 HttpServletRequest request = ServletActionContext.getRequest(); 11 Map session = ActionContext.getContext().getSession(); 12 List<Integer> subjectids = (List<Integer>) session.get("subjectids"); 13 for(integer subjectid : subjectids) { 14 Subject subject = subjectservice.getsubject(subjectid);// 通 过 id 查 找 15 subjects.add(subject); 16 } 17 request.setattribute("subjects", subjects); 18 return SUCCESS; 19 } 20 } 上 述 代 码 第 12 行 中 获 取 保 存 在 session 中 的 试 题 id 组 成 的 集 成, 第 13 行 中 对 它 进 行 遍 历 在 第 14 行 中 调 用 试 题 业 务 逻 辑 实 现 类 中 的 getsubject 获 取 试 题 方 法, 从 而 获 取 考 生 试 卷 中 所 有 试 题 对 象, 并 在 第 15 行 中 将 它 们 保 存 到 集 合 中 开 发 完 显 示 试 题 答 案 Action 后, 首 先 在 Spring 配 置 文 件 中 对 该 Action 进 行 配 置, 配 置 界 面 如 图 11-24 所 示

25 图 11-24 配 置 显 示 试 题 答 案 Action 单 击 Finish 按 钮, 将 完 成 对 显 示 试 题 答 案 Action 的 配 置, 在 其 中 将 试 题 业 务 逻 辑 实 现 类 对 象 注 入 接 下 来 在 Struts 2 配 置 文 件 中 对 该 Action 进 行 配 置, 配 置 代 码 如 下 所 示 01 <action name="showsubjectanswer" class="showsubjectanswer"> 02 <result name="success">/showanswer.jsp</result> 03 </action> 执 行 完 显 示 试 题 答 案 Action 后, 将 跳 转 到 显 示 答 案 页 面 程 序, 从 而 将 试 题 的 答 案 和 解 析 显 示 在 页 面 中 11.2.11 运 行 考 试 系 统 将 项 目 部 署 到 Tomcat 服 务 器 中 后, 启 动 服 务 器 如 果 启 动 时 发 生 错 误, 将 项 目 中 的 asm-x.jar JAR 包 删 除, 因 为 其 中 该 包 重 复 启 动 成 功 后, 打 开 浏 览 器, 在 其 中 输 入 如 下 地 址 : http://localhost:8080/exam/login.jsp 运 行 结 果 如 图 11-25 所 示

图 11-25 登 录 页 面 注 意 : 在 执 行 登 录 操 作 之 前, 一 定 要 向 数 据 库 中 加 入 测 试 的 考 生 信 息 在 实 际 开 发 中, 考 生 的 信 息 也 是 事 前 录 入 的 在 其 中 编 号 文 本 框 中 输 入 20090001, 在 密 码 框 中 输 入 456123, 单 击 登 录 按 钮, 运 行 结 果 如 图 11-26 所 示 图 11-26 试 卷 页 面 在 试 卷 页 面 中 将 随 机 得 到 5 道 题, 考 生 可 以 对 这 些 试 题 进 行 作 答 当 考 试 时 间 结 束, 或 者 考 试 单 击 提 交 答 卷 按 钮 后 将 完 成 试 题 答 案 的 提 交, 并 进 入 到 显 示 考 试 成 绩 页 面, 如 图 11-27 所 示

27 图 11-27 显 示 考 试 成 绩 在 显 示 考 试 成 绩 页 面 中 会 将 学 生 姓 名 和 它 的 考 试 成 绩 显 示 出 来, 单 击 其 中 的 查 看 答 案 超 链 接, 将 进 入 显 示 答 案 页 面, 如 图 11-28 所 示 图 11-28 显 示 试 题 答 案 该 页 面 中 的 试 题 答 案 是 和 考 生 的 考 试 试 卷 相 对 应 的 在 显 示 试 题 答 案 页 面 中, 将 把 试 题 的 答 案 显 示 出 来, 如 果 试 题 有 参 考 解 析, 也 会 将 解 析 内 容 显 示 出 来

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 12 章 调 试 和 测 试 调 试 和 测 试 在 项 目 开 发 中 是 必 不 可 少 的 通 过 测 试 可 以 检 测 程 序 中 是 否 有 错 误, 通 过 调 试 可 以 查 找 到 具 体 错 误, 并 进 行 排 错 操 作 在 MyEclipse 中, 集 成 了 对 程 序 进 行 调 试 和 测 试 的 功 能 在 MyEclipse 中, 说 测 试 时 一 般 是 指 单 元 测 试, 也 就 是 对 某 一 小 段 代 码 进 行 测 试, 而 不 是 对 整 个 项 目 进 行 测 试 12.1 调 试 不 管 程 序 员 的 技 术 多 么 精 通, 工 作 经 验 多 么 丰 富, 都 不 能 保 证 所 写 程 序 中 不 存 在 BUG 在 这 种 情 况 下, 通 过 人 为 查 错 是 非 常 复 杂 的, 这 时 候 就 需 要 调 试 工 具 来 对 程 序 进 行 查 错, 最 后 人 为 的 修 改 这 些 错 误 在 MyEclipse 中, 就 集 成 了 对 程 序 进 行 调 试 的 工 具 12.1.1 认 识 调 试 透 视 图 在 MyEclipse 的 默 认 透 视 图 下, 是 不 能 很 好 的 看 到 调 试 效 果 的, 所 以 需 要 切 换 到 调 试 透 视 图 下 在 MyEclipse 的 菜 单 中, 选 择 Window Open Perspective Other 命 令, 将 弹 出 选 择 切 换 透 视 图 的 界 面, 如 图 12-1 所 示 图 12-1 选 择 切 换 透 视 图 在 其 中 选 择 Debug 节 点, 单 击 OK 按 钮,MyEclipse 的 视 图 将 会 发 生 变 化, 界 面 将 变 为 如 图 12-2 所 示

图 12-2 调 试 透 视 图 界 面 其 中 上 面 的 四 个 视 图 界 面 是 重 要 的 左 上 角 是 调 试 视 图 界 面, 在 其 中 可 以 控 制 程 序 的 运 行, 让 程 序 按 照 程 序 员 的 意 愿 进 行 运 行, 从 而 不 会 一 次 运 行 结 束 右 上 角 是 变 量 和 断 点 视 图 界 面, 在 变 量 视 图 中 可 以 看 到 程 序 中 变 量 值 的 变 化 ; 断 点 是 调 试 中 重 要 的 部 分, 在 后 面 将 详 细 讲 解 左 下 角 是 编 辑 区 视 图 界 面, 在 其 中 将 显 示 要 调 试 的 代 码 内 容, 如 果 想 创 建 和 修 改 程 序, 最 好 回 到 默 认 透 视 图 中 右 下 角 是 大 纲 视 图 界 面, 会 将 Java 的 文 件 结 构 显 示 在 其 中, 它 是 比 较 少 用 的 说 明 : 这 里 只 是 简 单 的 认 识 各 个 部 分, 在 后 面 的 讲 解 中 还 会 讲 解 它 们 的 具 体 使 用 和 操 作 在 后 面 的 讲 解 中 将 直 接 使 用 每 一 部 分 的 名 称 12.1.2 启 动 调 试 配 置 在 正 式 开 始 调 试 操 作 之 前, 我 们 先 来 开 发 一 个 项 目, 并 在 项 目 中 开 发 一 个 简 单 的 Java 程 序, 该 程 序 的 具 体 代 码 为 : 01 public class DoubleFor { 02 public static void main(string args[]){ 03 for(int i=0;i<5;i++){ 04 for(int j=0;j<5;j++){ 05 System.out.println(" 当 前 i="+i+";j="+j); 06 } 07 System.out.println(" 内 部 循 环 执 行 结 束 "); 08 } 09 } 10 } 该 程 序 是 非 常 简 单 的, 例 如 定 义 了 双 重 for 循 环 语 句, 从 而 该 程 序 来 查 看 其 中 变 量 值 的 变 化 开 发 完 Java 程 序 后, 就 可 以 对 其 进 行 调 试

3 说 明 : 启 动 调 试 有 多 种 方 式, 包 括 启 动 菜 单 启 动 工 具 按 钮 和 编 辑 区 右 键 弹 出 菜 单 笔 者 更 倾 向 于 使 用 右 键 弹 出 菜 单 来 启 动 调 试 有 时 候 在 执 行 调 试 之 前, 需 要 进 行 必 要 的 调 试 配 置 在 编 辑 区 中, 单 数 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Debug As Debug Configurations 命 令, 将 弹 出 进 行 调 试 配 置 的 界 面 在 其 中 左 面 选 择 Java Application 节 点, 然 后 选 择 要 进 行 调 试 的 程 序 节 点, 如 图 12-3 所 示 图 12-3 调 试 配 置 界 面 其 中 Name 表 示 进 行 调 试 的 类 的 名 称, 下 面 有 多 个 选 项 卡 用 来 对 该 类 进 行 必 要 的 配 置 Main 选 项 卡 是 我 们 主 要 配 置 的, 其 中 Project 表 示 要 调 试 程 序 所 在 的 项 目, Main class 表 示 类 名, 单 击 Search 按 钮 可 以 对 类 进 行 搜 索 单 击 Apply 按 钮, 将 完 成 调 试 配 置 操 作 单 击 Debug 按 钮, 将 开 始 对 配 置 的 类 进 行 调 试 12.1.3 断 点 断 点 是 调 试 中 的 重 要 组 成 部 分 如 果 不 使 用 断 点, 进 行 调 试 时, 程 序 在 不 发 生 异 常 的 情 况 下 会 执 行 到 最 后, 但 是 如 果 使 用 断 点 后, 当 程 序 运 行 到 该 断 点, 就 会 将 当 前 执 行 线 程 挂 起, 从 而 能 够 人 为 的 控 制 程 序 执 行 在 程 序 中 加 入 断 点 是 非 常 简 单 的 在 编 辑 区 中, 在 行 号 的 左 边 的 标 记 栏 中, 双 击 鼠 标 就 会 为 所 在 行 的 代 码 加 入 一 个 断 点, 如 图 12-4 所 示

图 12-4 添 加 断 点 所 示 添 加 断 点 后, 在 调 试 透 视 图 的 断 点 视 图 界 面 中 也 将 显 示 该 断 点 的 信 息, 如 图 12-5 图 12-5 断 点 视 图 在 断 电 视 图 中, 将 把 断 点 所 在 的 类 行 号 和 所 在 方 法 等 信 息 显 示 出 来 在 一 个 程 序 中, 使 用 同 样 的 方 法, 可 以 同 时 添 加 多 个 断 点, 从 而 在 断 电 视 图 中 会 将 这 些 断 点 信 息 都 显 示 出 来 当 断 点 完 成 调 试 需 求 后, 将 需 要 将 段 断 点 删 除 删 除 断 点 是 非 常 容 易 的, 在 断 点 上 双 击 鼠 标, 就 可 以 将 断 点 删 除 在 断 点 视 图 界 面 中, 还 可 以 对 断 点 进 行 操 作 例 如 不 想 对 断 点 进 行 频 繁 的 添 加 和 删 除, 就 可 以 对 断 点 进 行 启 用 和 禁 用 在 断 点 视 图 界 面 中, 选 中 断 点 信 息, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中 选 择 Disable 命 令, 将 禁 用 该 断 点, 是 和 删 除 断 点 一 样 的 禁 用 的 断 点 将 以 空 心 的 形 式 出 现, 如 图 12-6 所 示 图 12-6 禁 用 断 点 在 断 点 视 图 中, 选 中 禁 用 的 断 点 信 息, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Enable 命 令, 将 启 用 被 禁 用 的 断 点 12.1.4 开 始 调 试 设 置 断 点 后, 就 可 以 进 行 调 试 开 启 调 试 的 方 式 有 很 多, 除 了 能 够 在 调 试 配 置 界 面 中 单 击 Debug 按 钮 外, 还 可 以 在 编 辑 区 中 的 右 键 弹 出 菜 单 中 选 择 Debug As Java

5 Application 命 令 启 动 启 动 调 试 后, 开 始 运 行 程 序, 当 运 行 到 断 点 处 后, 将 会 把 当 前 线 程 挂 起, 调 试 视 图 界 面 如 图 12-7 所 示 图 12-7 断 点 处 挂 起 其 中 三 条 蓝 色 线 就 表 示 在 当 前 位 置 挂 起, 并 给 出 位 置 是 第 3 行 通 过 调 试 视 图 可 以 对 程 序 进 行 多 种 调 试 操 作, 其 中 使 用 最 多 的 就 是 单 步 跳 过 其 中 就 是 单 步 跳 过 按 钮, 它 的 快 捷 键 是 F6 单 击 单 步 跳 过 按 钮, 在 编 辑 区 中 将 高 亮 显 示 当 前 运 行 的 行, 如 图 12-8 所 示 图 12-8 编 辑 区 的 变 化 在 变 量 视 图 界 面 中, 还 会 将 当 前 程 序 中 的 变 量 值 显 示 出 来, 如 图 12-9 所 示 图 12-9 变 量 视 图 多 次 单 击 单 步 跳 过 按 钮, 变 量 视 图 中 的 变 量 将 随 着 变 化, 通 过 它 就 可 以 观 察 变 化 是 否 是 我 们 想 要 的 结 果 如 果 发 生 异 常, 或 者 变 量 结 果 和 期 望 结 果 不 同, 就 需 要 及 时 排 错, 从 而 保 证 程 序 正 常 运 行

12.1.5 断 点 命 中 计 数 在 调 试 程 序 时, 当 运 行 到 断 点 时, 将 自 动 会 将 程 序 挂 起 但 是 有 些 时 候, 我 们 并 不 想 每 一 次 运 行 到 断 点 时 都 将 程 序 挂 起, 这 时 候 就 需 要 使 用 到 断 点 命 中 计 数 在 对 循 环 语 句 进 行 调 试 时, 该 操 作 是 非 常 重 要 的 例 如 我 们 将 断 点 设 置 在 DoubleFor 程 序 的 内 存 循 环 语 句 中, 如 图 12-10 所 示 图 12-10 将 断 点 设 置 在 循 环 中 然 后 在 断 点 视 图 中, 选 中 当 前 断 点 信 息, 在 右 键 菜 单 中 选 择 Hit Count 命 令, 将 弹 出 设 置 命 中 计 数 的 界 面, 如 图 12-11 所 示 图 12-11 设 置 命 中 计 数 在 其 中 设 置 断 点 的 命 中 计 数 为 3, 单 击 OK 按 钮, 将 完 成 设 置 再 次 启 动 调 试, 观 看 控 制 台 中 的 输 出, 输 出 结 果 为 : 当 前 i=0;j=0 当 前 i=0;j=1 当 第 3 次 要 运 行 断 点 所 在 的 代 码 时, 将 把 当 前 线 程 挂 起, 从 而 只 输 出 了 两 条 语 句 注 意 : 在 启 动 下 一 个 调 试 之 前, 一 定 要 将 上 一 次 的 调 试 结 束 掉, 在 调 试 视 图 界 面 中 单 击 停 止 按 钮 可 以 完 成 该 操 作 12.1.6 断 点 条 件 断 点 条 件 也 是 一 种 对 断 点 的 限 制, 是 指 当 断 点 满 足 某 一 条 件 时, 才 会 将 当 前 线 程 挂 起 设 置 断 点 条 件 也 是 在 断 点 视 图 界 面 中 完 成, 选 中 断 点 信 息, 在 右 键 弹 出 菜 单 中, 选 择 Breakpoint Properties 命 令, 将 它 们 对 断 点 进 行 属 性 设 置 的 界 面, 如 图 12-12 所 示

7 图 12-12 设 置 断 点 条 件 从 属 性 设 置 界 面 中 可 以 看 到, 也 可 以 在 该 界 面 中 进 行 启 用 断 点 和 设 置 断 点 命 中 计 数 设 置 其 中 Enable Condition (Alt+/ for code assist) 选 项 就 是 选 择 是 否 启 用 断 点 条 件, 这 里 选 中 它, 然 后 在 下 面 的 文 本 域 中 输 入 断 点 条 件, 这 里 输 入 j==2 其 他 选 项 采 用 默 认 值, 单 击 OK 按 钮, 将 完 成 断 点 条 件 的 设 置 注 意 : 将 要 其 中 的 Hit Count 选 项 修 改 为 未 选 中 状 态, 从 而 使 断 点 只 按 照 断 点 条 件 执 行 再 次 启 动 调 试, 可 以 看 到 控 制 台 的 运 行 结 果 为 : 当 前 i=0;j=0 当 前 i=0;j=1 可 以 看 到 当 j 等 于 2 的 结 果 并 没 有 输 出, 这 是 因 为 设 置 了 断 点 的 条 件 时 j==2, 这 时 候 程 序 中 的 线 程 被 挂 起 了 12.2 测 试 软 件 测 试 和 软 件 开 发 一 样, 都 是 一 种 非 常 宽 泛 的 概 念 随 着 软 件 项 目 的 规 范 越 来 越 大, 软 件 测 试 已 经 变 的 非 常 重 要 测 试 分 为 多 种, 分 别 是 综 合 测 试 单 元 测 试 和 用 户 测 试 等 在 本 书 中 主 要 讲 解 的 是 单 元 测 试, 它 是 和 开 发 人 员 联 系 非 常 紧 密 的 通 过 单 元 测 试 可 以 确 定 某 一 段 代 码 或 者 某 一 个 方 法 是 否 正 确 JUnit 是 一 种 开 发 开 源 的 用 于 Java 程 序 测 试 的 框 架, 在 实 际 开 发 中 通 常 使 用 它 来 进 行 单 元 测 试 在 MyEclipse 中, 也 集 成 了 JUnit 框 架, 在 本 节 中 主 要 来 讲 解 MyEclipse 中 JUnit 的 使 用

12.2.1 创 建 测 试 程 序 单 元 测 试 主 要 是 对 某 一 方 法 进 行 测 试, 所 以 这 里 我 们 首 先 来 开 发 一 个 功 能 方 法 被 测 试 的 程 序 代 码 如 下 所 示 01 package com.sanqing.junit; 02 public class HelloWorld { 03 public String connection(string s1,string s2){ 04 return s1+s2; 05 } 06 } 上 述 代 码 第 3 行 定 义 了 连 接 字 符 串 的 方 法, 通 过 该 方 法 可 以 让 两 个 字 符 串 连 接 在 一 起, 从 而 组 成 一 个 新 字 符 串, 并 返 回 接 下 来 就 是 开 发 用 于 测 试 连 接 字 符 串 方 法 的 JUnit 程 序 说 明 :JUnit 的 测 试 程 序 类 通 常 不 和 被 测 试 程 序 放 在 同 一 个 包 下, 而 是 在 原 包 的 基 础 上 创 建 名 称 为 test 的 子 包, 将 所 有 的 测 试 程 序 都 放 在 test 包 下 在 包 资 源 管 理 器 中, 选 中 test 包, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中 选 择 New Other 命 令, 将 弹 出 选 择 创 建 程 序 界 面, 选 中 Show All Wizards 选 项, 界 面 如 图 12-13 所 示 图 12-13 选 择 创 建 程 序 在 其 中 选 中 Java JUnit JUnit Test Case 节 点, 单 击 Next 按 钮, 将 弹 出 创 建 JUnit 程 序 的 界 面, 如 图 12-14 所 示

9 图 12-14 创 建 JUnit 程 序 界 面 最 开 始 就 是 选 择 创 建 哪 一 个 版 本 的 JUnit 程 序, 其 中 JUnit 3 版 本 流 行 了 很 长 时 间,JUnit 4 版 本 是 JDK 5.0 以 后 出 现 的, 和 原 版 本 相 比 变 化 时 比 较 大 的, 这 里 我 们 直 接 学 习 最 新 版 本 的 JUnit 4 版 本 其 中 Source folder 表 示 JUnit 测 试 程 序 所 在 的 目 录, Package 表 示 JUnit 测 试 程 序 所 在 的 包 Name 表 示 测 试 程 序 类 的 名 称 注 意 : 测 试 程 序 类 的 类 名 通 常 是 固 定 格 式 的, 为 XXXTest 形 式, 其 中 XXX 就 是 被 测 试 程 序 的 类 名 Superclass 表 示 测 试 类 将 要 继 承 的 父 类, 对 于 JUnit 3 版 本 来 说 需 要 继 承 junit.framework.testcase 类, 但 是 对 于 JUnit 4 版 本 来 说 是 并 不 需 要 的, 直 接 使 用 注 解 标 识 就 可 以, 在 后 面 的 代 码 中 可 以 看 到 这 一 点 Which method stubs would you like to create 表 示 在 测 试 程 序 中 创 建 哪 些 方 法, 这 里 保 持 默 认 的 不 选 中 状 态 Class under test 表 示 对 哪 一 个 类 进 行 测 试, 单 击 Browse 按 钮 可 以 选 择, 这 里 填 写 本 节 开 始 创 建 的 HelloWorld 程 序 单 击 Next 按 钮, 将 进 入 选 择 测 试 方 法 的 界 面 如 图 12-15 所 示

图 12-15 选 择 测 试 方 法 其 中 不 但 将 被 测 试 类 本 身 的 方 法 列 出 来, 还 会 将 它 的 父 类 中 的 方 法 同 样 给 出 这 里 我 们 只 对 其 中 的 连 接 字 符 串 方 法 进 行 测 试, 选 择 connection 方 法, 单 击 Finish 按 钮, 将 弹 出 导 入 JAR 包 的 界 面, 如 图 12-16 所 示 图 12-16 选 择 导 入 JAR 包 其 中 有 三 个 选 项, Not now 表 示 不 加 入 JAR 包 ; Open the build path property page 表 示 打 开 构 建 路 径 界 面, 手 动 导 入 JAR 包 ; Paerform the following action 表 示 使 用 MyEclipse 中 自 带 的 JUnit 相 关 JAR 包 这 里 采 用 默 认 的 使 用 自 带 包, 单 击 OK 按 钮, 将 完 成 测 试 程 序 的 创 建 说 明 :MyEclipse 中 自 带 的 JUnit 包 并 不 是 十 分 优 秀 的, 当 进 行 某 些 操 作 时, 需 要 手 动 导 入 最 新 的 JAR 包 在 后 面 使 用 到 时 进 行 讲 解

11 完 成 上 述 操 作 后, 会 在 编 辑 区 中 自 动 打 开 创 建 的 测 试 程 序, 自 动 生 成 的 代 码 为 : 01 package com.sanqing.junit.test; 02 import static org.junit.assert.*; 03 import org.junit.test; 04 public class HelloWorldTest { 05 @Test 06 public void testconnection() { 07 fail("not yet implemented"); 08 } 09 } 注 意 : 第 2 行 中 使 用 的 是 静 态 导 入 方 法, 并 不 是 通 常 用 的 导 入 接 口 或 者 类, 它 是 JDK 5.0 以 后 加 入 的, 通 过 它 可 以 在 程 序 中 直 接 使 用 指 定 类 的 静 态 方 法, 例 如 Assert 类 中 的 静 态 方 法 其 中 第 5 行 使 用 到 了 @Test 注 解, 通 过 它 可 以 标 明 下 面 第 6 行 的 testconnection 是 一 个 测 试 方 法 注 意 : 测 试 方 法 的 名 称 是 有 固 定 格 式 的, 通 常 为 testxxx, 其 中 XXX 就 是 被 测 试 方 法 的 名 称 虽 然 在 JUnit 4 版 本 中 并 没 有 严 格 规 定, 但 是 最 好 采 用 同 样 规 范 12.2.2 开 发 测 试 代 码 创 建 测 试 程 序 后, 将 自 动 生 成 测 试 代 码, 但 是 这 并 不 是 我 们 想 要 的 我 们 测 试 方 法 是 为 了 验 证 它 是 否 能 够 完 成 某 一 个 功 能 例 如 连 接 字 符 串 方 法, 我 们 就 来 验 证 是 否 能 够 达 到 连 接 字 符 串 的 效 果 将 自 动 生 成 的 代 码 修 改 成 如 下 代 码 : 01 package com.sanqing.junit.test; 02 import static org.junit.assert.*; 03 import org.junit.test; 04 import com.sanqing.junit.helloworld; 05 public class HelloWorldTest { 06 @Test 07 public void testconnection() { 08 String s=new HelloWorld().connection("Hello", "World"); 09 assertequals("helloworld", s); // 判 断 是 否 和 期 望 值 相 等 10 } 11 } 其 中 第 8 行 中 调 用 了 被 测 试 程 序 中 的 被 测 试 方 法, 得 到 一 个 返 回 的 字 符 串 变 量 在 第 9 行 中 调 用 了 Assert 类 中 的 assertequals 静 态 方 法, 该 方 法 中 具 有 两 个 Object 类 型 的 参 数, 其 中 第 1 个 参 数 表 示 期 望 值, 第 2 个 参 数 表 示 真 实 值, 它 的 作 用 就 是 判 断 真 实 值 和 期 望 值 是 否 相 等 在 Assert 类 中 除 了 assertequals 静 态 方 法 外, 还 有 其 他 一 些 判 断 方 法, 在 后 面 的 学 习 中 将 会 学 习 到

12.2.3 运 行 测 试 程 序 当 运 行 普 通 Java 程 序 时, 如 果 有 输 出 结 果, 将 把 输 出 结 果 输 出 到 控 制 台 中 运 行 测 试 程 序 是 和 运 行 普 通 程 序 有 很 大 不 同 的, 在 本 小 节 中 就 来 看 一 下 如 何 运 行 测 试 程 序 和 查 看 运 行 结 果 在 运 行 测 试 程 序 之 前, 我 们 首 先 将 MyEclipse 切 换 到 Java 透 视 图 在 MyEclipse 菜 单 中, 选 择 Window Open Perspective Other 命 令, 在 弹 出 界 面 中 选 择 Java 节 点, 单 击 OK 按 钮, 将 完 成 MyEclipse 视 图 的 切 换, 切 换 到 Java 透 视 图 下 运 行 测 试 程 序 和 运 行 普 通 程 序 一 样, 也 是 有 多 种 操 作 方 式, 这 里 采 用 右 键 菜 单 的 方 式 在 测 试 程 序 编 辑 区 中, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中 选 择 Run JUnit Test 命 令, 将 出 现 一 个 JUnit 视 图 界 面, 界 面 如 图 12-17 所 示 图 12-17 测 试 正 确 结 果 界 面 中 最 明 显 的 就 是 最 上 方 的 绿 条, 出 现 该 绿 条 后 就 表 示 测 试 通 过, 功 能 代 码 是 正 确 可 用 的 在 该 界 面 中 的 按 钮 是 启 动 按 钮, 如 果 测 试 程 序 发 生 改 变, 需 要 再 次 执 行 测 试, 就 可 以 单 击 该 按 钮 例 如 将 测 试 程 序 中 第 9 行 的 HelloWorld 改 为 NOHelloWorld, 单 击 启 动 按 钮, JUnit 视 图 界 面 将 变 为 如 图 12-18 所 示 的 结 果

13 图 12-18 测 试 错 误 结 果 因 为 我 们 将 测 试 中 的 期 望 值 改 变 了, 所 以 将 和 输 出 值 是 不 同 的, 从 而 将 测 试 得 到 错 误 结 果 在 JUnit 视 图 界 面 中 将 显 示 红 条, 表 示 测 试 不 通 过 在 最 下 方 的 Failure Trace 栏 中 将 把 测 试 不 通 过 的 原 因 显 示 出 来 12.3 测 试 方 法 在 上 一 节 中 已 经 讲 解 了 一 种 测 试 方 法, 比 较 方 法 输 出 是 否 和 期 望 值 相 等 除 了 该 方 法 外, 还 有 其 他 比 较 的 方 法, 例 如 比 较 结 果 是 否 为 false 或 者 true, 比 较 结 果 是 否 为 null, 比 较 结 果 是 否 相 同 等 这 些 都 是 JUnit 3 版 本 中 已 经 有 的, 在 JUnit 4 版 本 中 又 增 加 了 assertthat 方 法, 在 本 节 中 将 对 这 些 内 容 进 行 讲 解 12.3.1 输 出 测 试 错 误 信 息 在 每 一 种 测 试 方 法 中, 都 有 一 个 对 应 的 多 出 一 个 字 符 串 类 型 参 数 的 重 载 方 法, 该 字 符 串 的 值 就 是 测 试 失 败 后, 输 出 的 错 误 信 息 修 改 上 一 节 的 测 试 程 序, 在 该 程 序 中 再 加 入 一 个 测 试 方 法, 该 方 法 的 代 码 为 : 01 @Test 02 public void testconnection2() { 03 String s=new HelloWorld().connection("Hello", "World"); 04 assertequals(" 输 出 结 果 和 期 望 值 不 同 ","NOHelloWorld", s); // 判 断 是 否 相 等 05 } 如 果 这 时 候 再 在 编 辑 区 中 的 右 键 弹 出 菜 单 中, 选 择 命 令 进 行 测 试, 将 同 时 测 试 其 中 的 两 个 方 法 如 果 只 想 测 试 这 一 个 方 法, 可 以 在 包 资 源 管 理 中, 选 中 testconnection2 方 法 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Run As JUnit Test 命 令, 这 时 候 将 只 测 试 指 定 的 方 法 测 试 结 果 如 图 12-19 所 示

图 12-19 输 出 错 误 信 息 其 中 上 半 部 分 是 和 前 面 相 同 的, 在 Failure Trace 栏 中 将 把 方 法 中 定 义 的 信 息 显 示 在 其 中 该 信 息 只 有 测 试 失 败 时 才 会 出 现, 当 测 试 成 功 后 将 被 忽 略 掉, 通 过 它 能 够 更 好 的 检 查 到 哪 一 个 方 法 测 试 没 有 通 过 12.3.2 测 试 结 果 true 和 false 在 org.junit.assert 类 中 定 义 了 asserttrue 和 assertfalse 方 法, 通 过 这 两 个 方 法 可 以 测 试 参 数 是 否 为 true 或 者 false 对 于 返 回 值 为 booean 类 型 的 方 法 来 说, 一 般 采 用 这 两 种 方 法 进 行 测 试 首 先 我 们 先 来 开 发 一 个 被 测 试 的 方 法, 这 里 以 登 录 举 例 说 明, 它 的 程 序 代 码 为 : 01 package com.sanqing.junit; 02 public class UserServiceImpl { 03 public boolean login(string username,string password){ 04 if("tom".equals(username)&&"456123".equals(password)){ 05 return true; 06 }else{ 07 return false; 08 } 09 } 10 } 其 中 定 义 了 一 个 登 录 业 务 方 法, 接 下 来 就 是 对 该 方 法 进 行 测 试 开 发 测 试 程 序 的 步 骤 在 前 面 已 经 讲 解 了, 这 里 就 不 再 重 复 介 绍 测 试 程 序 的 代 码 为 : 01 package com.sanqing.junit.test; 02 import static org.junit.assert.*; 03 import org.junit.test; 04 import com.sanqing.junit.userserviceimpl; 05 public class UserServiceImplTest {

15 06 @Test 07 public void testlogin() { 08 boolean b=new UserServiceImpl().login("Tom", "456123"); 09 asserttrue(b); 10 } 11 } 启 动 运 行 测 试, JUnit 视 图 界 面 如 图 12-20 所 示 图 12-20 true 测 试 上 面 代 码 第 8 行 中 使 用 测 试 数 据 调 用 登 录 测 试 方 法, 从 而 得 到 表 示 是 否 能 够 登 录 的 boolean 类 型 返 回 值 在 第 9 行 中 使 用 asserttrue 方 法 判 断 返 回 值 是 否 为 true, 如 果 是 true, 则 测 试 通 过, 得 到 上 面 的 结 果 说 明 : assertfalse 方 法 和 asserttrue 方 法 非 常 类 似 的, 它 是 用 来 判 断 结 果 是 否 为 false 如 果 是, 则 测 试 成 功, 如 果 不 是, 则 测 试 失 败 12.3.3 测 试 结 果 是 否 为 null 在 实 际 开 发 中, 测 试 方 法 的 返 回 结 果 是 否 为 null 是 非 常 重 要 的, 因 为 该 返 回 结 果 可 能 会 被 使 用 来 调 用 其 他 方 法 例 如 在 Web 开 发 中, 在 业 务 逻 辑 层 中 要 使 用 数 据 访 问 层 的 对 象 来 调 用 数 据 访 问 层 中 的 方 法, 在 使 用 之 前, 通 常 就 应 该 对 数 据 访 问 层 对 象 进 行 是 否 为 null 测 试 接 下 来 就 来 演 示 测 试 数 据 访 问 层 对 象 是 否 null, 先 来 开 发 业 务 逻 辑 层 程 序, 程 序 代 码 为 : 01 package com.sanqing.junit; 02 public class UserServiceImpl { 03 private UserDAO userdao; 04 public UserDAO getuserdao() { 05 return userdao;

06 } 07 public void setuserdao(userdao userdao) { 08 this.userdao = userdao; 09 } 10 } 如 果 学 习 过 本 书 前 面 的 内 容, 是 不 难 理 解 该 代 码 的 上 述 代 码 第 3 行 中 定 义 了 数 据 访 问 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 从 而 如 果 使 用 Spring, 将 把 数 据 访 问 实 现 类 对 象 注 入 使 用 其 中 第 4 行 的 获 取 对 象 方 法, 就 可 以 获 取 该 对 象, 接 下 来 就 对 该 获 取 对 象 方 法 进 行 测 试, 判 断 是 否 将 对 象 注 入 进 来 测 试 程 序 中 的 测 试 方 法 代 码 为 : 01 @Test 02 public void testgetuserdao() { 03 UserDAO userdao=new UserServiceImpl().getUserDAO(); 04 assertnull(userdao); 05 } 启 动 运 行 测 试, JUnit 视 图 界 面 如 图 12-21 所 示 图 12-21 是 否 为 null 测 试 因 为 在 程 序 中 并 没 有 使 用 到 Spring, 所 以 调 用 getuserdao 方 法 是 不 会 获 取 到 对 象 的, 从 而 userdao 引 用 的 值 就 是 null 在 第 4 行 中 调 用 assertnull 方 法 测 试 值 是 否 为 null, 从 而 测 试 通 过, 出 现 上 面 的 结 果 说 明 : 和 assertnull 方 法 类 似 的 还 有 一 个 assertnotnull 方 法, 当 测 试 值 不 为 nul 时, 使 用 该 方 法 通 过 测 试 12.3.4 测 试 是 否 引 用 同 一 个 对 象 在 前 面 使 用 assertequals 方 法 时, 是 用 来 判 断 两 个 参 数 的 值 是 否 相 等 和 它 相 似 的 还 有 一 个 assertsame 方 法, 通 过 该 方 法 可 以 判 断 两 个 参 数 是 否 引 用 同 一 个 对 象, 也 从 而 定 义 该 方 法 的 参 数 类 型 必 须 是 对 象 类 型

17 多 个 引 用 指 向 一 个 对 象 的 情 况 最 多 的 就 是 出 现 在 单 例 模 式 中, 我 们 首 先 创 建 一 个 单 例 模 式 程 序, 它 的 代 码 为 : 01 package com.sanqing.junit; 02 public class MyBean { 03 private static MyBean instance =null; 04 private MyBean(){ 05 } 06 public static MyBean getinstance(){ 07 if(instance==null){ 08 instance=new MyBean(); 09 } 10 return instance; 11 } 12 } 上 述 代 码 是 一 个 标 准 的 单 例 模 式 程 序, 其 中 最 关 键 的 就 是 第 4 行 定 义 了 私 有 的 构 造 函 数, 从 而 不 能 在 类 外 部 创 建 对 象, 只 能 够 通 过 第 6 行 中 的 方 法 获 取 接 下 来 就 是 对 其 中 第 6 行 的 方 法 进 行 测 试, 判 断 是 否 返 回 的 都 是 同 一 对 象 创 建 测 试 程 序, 然 后 在 其 中 加 入 测 试 代 码, 其 具 体 代 码 为 : 01 package com.sanqing.junit.test; 02 import static org.junit.assert.*; 03 import org.junit.test; 04 import com.sanqing.junit.mybean; 05 public class MyBeanTest { 06 @Test 07 public void testgetinstance() { 08 MyBean mybean1=mybean.getinstance(); 09 MyBean mybean2=mybean.getinstance(); 10 assertsame(mybean1, mybean2); 11 } 12 } 启 动 运 行 测 试, JUnit 视 图 界 面 如 图 12-22 所 示

图 12-22 测 试 是 否 为 一 个 对 象 在 代 码 中 第 8 行 和 第 9 行 都 调 用 了 单 例 默 认 程 序 中 获 取 对 象 的 方 法, 然 后 在 第 10 行 中 调 用 assertsame 方 法 判 断 获 取 的 对 象 是 否 为 同 一 个 对 象 注 意 : 和 前 面 几 种 方 法 一 样, 也 有 和 assertsame 功 能 相 反 的 assertnotsame 方 法, 使 用 它 时, 当 两 个 引 用 指 向 不 同 对 象 时 测 试 通 过 12.3.5 新 版 本 新 增 方 法 在 JUnit 4 版 本 中 新 增 了 一 个 方 法, 那 就 是 assertthat 方 法, 使 用 该 方 法 可 以 完 成 上 面 所 讲 的 所 有 方 法 的 功 能 assertthat 方 法 的 基 本 语 法 结 构 为 : public static void assertthat( [value], [matcher statement] ); 其 中 value 表 示 想 要 测 试 的 变 量 值 matcher statement 是 使 用 Hamcrest 匹 配 符 来 表 达 的 对 前 面 变 量 所 期 望 的 值 的 声 明, 如 果 value 值 与 matcher statement 所 表 达 的 期 望 值 相 符, 则 测 试 成 功, 否 则 测 试 失 败 在 JUnit 框 架 中 自 带 了 有 限 的 几 个 Hamcrest 匹 配 符, 如 果 想 使 用 更 多 的, 可 以 去 下 载 Hamcrest 匹 配 符 的 相 关 JAR 包, 然 后 将 它 们 导 入 到 测 试 项 目 中 Hamcrest 匹 配 符 的 官 方 网 站 为 http://code.google.com/p/hamcrest/, 在 其 中 选 择 下 载 栏 目 就 可 以 下 载 到 最 新 版 本 的 Hamcrest 匹 配 符 下 载 包 将 下 载 包 解 压 缩 后, 将 根 目 录 下 的 hamcrest-library-1.2.jar 和 hamcrest-core-1.2.jar 两 个 文 件 导 入 到 项 目 就 可 以 在 项 目 中 使 用 所 有 Hamcrest 匹 配 符 注 意 :MyEclipse 中 自 带 JUnit 的 JAR 包 是 和 下 载 的 Hamcrest 匹 配 符 JAR 包 相 冲 突 的, 所 以 要 去 JUnit 官 方 网 站 下 载 最 新 包, 官 方 网 站 地 址 为 www.junit.org/ 下 面 我 们 就 通 过 assertthat 方 法 使 用 Hamcrest 匹 配 符 的 方 式 来 测 试 最 开 始 的 连 接 字 符 串 方 法, 测 试 方 法 的 代 码 如 下 所 示 01 @Test 02 public void testconnection3() {

19 03 String s=new HelloWorld().connection("Hello", "World"); 04 assertthat ("HelloWorld", is(s)); // 判 断 是 否 和 期 望 值 相 等 05 } 其 中 第 4 行 中 使 用 了 assertthat 方 法, 方 法 中 的 第 二 个 参 数 is(s) 就 是 一 个 Hamcrest 匹 配 符, 判 断 值 是 否 等 于 前 面 的 值, 它 的 作 用 是 和 assertequals 方 法 相 同 的 从 上 面 这 一 个 简 单 程 序, 就 应 该 能 够 体 现 出 assertthat 方 法 的 优 点 首 先 在 测 试 程 序 中 不 在 需 要 多 种 方 法, 通 过 assertthat 方 法 就 可 以 代 替 以 前 所 有 的 老 方 法, 使 得 编 写 测 试 用 例 变 得 简 单, 代 码 风 格 变 得 统 一, 测 试 代 码 也 更 容 易 维 护 其 次 使 用 assertthat 方 法 更 适 合 代 码 阅 读, 因 为 在 Hamcrest 匹 配 符 中 使 用 了 大 量 的 符 合 英 文 的 格 式, 例 如 is allof anyof 等 这 里 我 们 就 不 为 每 一 个 匹 配 符 进 行 代 码 举 例, 下 面 给 出 部 分 重 要 通 配 符 的 使 用 格 式, 这 里 按 照 它 们 的 作 用 不 同 分 为 几 类 1. 一 般 通 配 符 (1)allOf 匹 配 符 表 明 当 后 面 的 所 有 条 件 都 成 立 时, 测 试 才 能 通 过, 相 当 于 运 算 符 中 的 与 (&&) 例 如 : assertthat( testednumber, allof( greaterthan(3), lessthan(10) ) ); 表 示 testednumber 的 值 必 须 大 于 3, 并 且 小 于 10, 则 测 试 通 过 (2)anyOf 匹 配 符 表 明 后 面 的 所 有 条 件 中 只 要 有 一 个 成 立 就 测 试 通 过, 相 当 于 运 算 符 中 的 或 ( ) 例 如 assertthat( testednumber, anyof( greaterthan(10), lessthan(3) ) ); 表 示 testednumber 的 值 大 于 10, 或 者 小 于 3, 则 测 试 通 过 (3)not 匹 配 符 和 is 匹 配 符 正 好 相 反, 表 明 如 果 前 面 测 试 的 object 不 等 于 后 面 给 出 的 object, 则 测 试 通 过 例 如 : assertthat( testedstring, not( "developerworks" ) ); 2. 字 符 串 相 关 匹 配 符 ( 1 ) containsstring 匹 配 符 表 明 如 果 测 试 的 字 符 串 testedstring 包 含 子 字 符 串 "developerworks" 则 测 试 通 过 例 如 assertthat( testedstring, containsstring( "developerworks" ) ); (2)endsWith 匹 配 符 表 明 如 果 测 试 的 字 符 串 testedstring 以 字 符 串 "developerworks" 结 尾 则 测 试 通 过 例 如 assertthat( testedstring, endswith( "developerworks" ) ); (3)startsWith 匹 配 符 表 明 如 果 测 试 的 字 符 串 testedstring 以 字 符 串 "developerworks" 开 始 则 测 试 通 过 例 如 assertthat( testedstring, startswith( "developerworks" ) ); (4)equalTo 匹 配 符 表 明 如 果 测 试 的 testedvalue 等 于 expectedvalue 则 测 试 通 过 例 如 assertthat( testedvalue, equalto( expectedvalue ) ); (5)equalToIgnoringCase 匹 配 符 表 明 如 果 测 试 的 字 符 串 testedstring 在 忽 略 大 小 写 的 情 况 下 等 于 "developerworks" 则 测 试 通 过 例 如

assertthat( testedstring, equaltoignoringcase("developerworks" ) ); (6)qualToIgnoringWhiteSpace 匹 配 符 表 明 如 果 测 试 的 字 符 串 testedstring 在 去 除 收 尾 的 空 格 后 等 于 "developerworks" 字 符 串, 则 测 试 通 过 例 如 assertthat( testedstring, equaltoignoringwhitespace( "developerworks" ) ); 3. 数 值 相 关 匹 配 符 (1)closeTo 匹 配 符 表 明 如 果 所 测 试 的 浮 点 型 数 testeddouble 在 20.0±0.5 范 围 之 内 则 测 试 通 过 例 如 例 如 例 如 assertthat( testeddouble, closeto( 20.0, 0.5 ) ); (2)greaterThan 匹 配 符 表 明 如 果 所 测 试 的 数 值 testednumber 大 于 16.0 则 测 试 通 过 assertthat( testednumber, greaterthan(16.0) ); (3)lessThan 匹 配 符 表 明 如 果 所 测 试 的 数 值 testednumber 小 于 16.0 则 测 试 通 过 assertthat( testednumber, lessthan (16.0) ); (4)greaterThanOrEqualTo 匹 配 符 表 明 如 果 所 测 试 的 数 值 testednumber 大 于 等 于 16.0 则 测 试 通 过 例 如 assertthat( testednumber, greaterthanorequalto (16.0) ); (5)lessThanOrEqualTo 匹 配 符 表 明 如 果 所 测 试 的 数 值 testednumber 小 于 等 于 16.0 则 测 试 通 过 例 如 assertthat( testednumber, lessthanorequalto (16.0) ); 4.collection 相 关 匹 配 符 (1)hasEntry 匹 配 符 表 明 如 果 测 试 的 Map 对 象 mapobject 中, 含 有 一 个 键 值 为 "key" 对 应 值 为 "value" 的 键 值 对 组 成, 则 测 试 通 过 它 的 语 法 格 式 为 : assertthat( mapobject, hasentry( "key", "value" ) ); (2)hasItem 匹 配 符 表 明 如 果 测 试 的 迭 代 对 象 iterableobject, 它 可 以 使 Set List 或 者 数 组, 其 中 含 有 element 元 素, 则 测 试 通 过 它 的 语 法 格 式 为 : assertthat( iterableobject, hasitem ( "element" ) ); (3)hasKey 匹 配 符 表 明 如 果 测 试 的 Map 对 象 mapobject 中 含 有 key 键, 则 测 试 通 过 它 的 语 法 格 式 为 : assertthat( mapobject, haskey ( "key" ) ); (4)hasValue 匹 配 符 表 明 如 果 测 试 的 Map 对 象 mapobject 中 含 有 value 值, 则 测 试 通 过 它 的 语 法 格 式 为 : assertthat( mapobject, hasvalue ( "key" ) ); 说 明 :Hamcrest 匹 配 符 并 不 是 我 们 的 学 习 重 点, 在 其 中 读 者 只 需 要 知 道 assertthat 方 法 的 使 用 方 式 就 可 以, 如 果 对 它 感 兴 趣, 可 以 看 一 下 官 方 文 档, 它 是 非 常 容 易 学 习 的

21 12.4 注 解 在 测 试 中 的 使 用 注 解 是 JDK 5.0 版 本 以 后 添 加 的 新 特 性 技 术, 通 过 使 用 它 可 以 在 程 序 中 节 省 大 量 代 码 在 JUnit 4 版 本 中 也 引 入 的 注 解, 例 如 前 面 见 过 多 次 的 @Test 注 解, 通 过 它 就 可 以 标 明 下 面 的 方 法 是 一 个 测 试 方 法, 从 而 就 不 需 要 让 测 试 类 继 承 其 他 类 除 了 @Test 注 解 外, 还 有 其 他 几 种 常 用 的 注 解, 在 本 节 中 就 来 对 它 们 进 行 讲 解 12.4.1 测 试 程 序 是 否 发 生 异 常 在 前 面 使 用 @Test 注 解 时 只 是 标 明 下 面 的 方 法 是 测 试 方 法, 在 该 注 解 中 还 可 以 添 加 属 性 来 进 行 更 详 细 的 测 试, 例 如 expected 属 性, 通 过 它 可 以 测 试 程 序 中 是 否 发 生 指 定 的 异 常 例 如 在 程 序 中 定 义 了 一 个 执 行 除 法 运 算 的 业 务 方 法, 它 的 代 码 为 : 01 package com.sanqing.junit; 02 public class DivideMath { 03 public double divide(int a,int b){ 04 return a/b; 05 } 06 } 其 中 第 3 行 定 义 了 执 行 除 法 运 算 的 业 务 方 法, 当 执 行 该 方 法 时, 就 可 以 发 生 除 数 为 0 的 异 常 现 在 我 们 就 来 测 试 使 用 两 个 数 调 用 该 方 法 是 否 发 生 除 数 为 0 的 异 常 测 试 代 码 如 下 所 示 : 01 package com.sanqing.junit.test; 02 import org.junit.test; 03 import com.sanqing.junit.dividemath; 04 public class DivideMathTest { 05 @Test(expected=java.lang.ArithmeticException.class) 06 public void testdivide() { 07 double d=new DivideMath().divide(3, 0); 08 } 09 } 启 动 运 行 测 试, JUnit 视 图 界 面 如 图 12-23 所 示

图 12-23 测 试 异 常 在 代 码 中 的 第 7 行 是 测 试 除 法 方 法, 设 置 其 中 的 除 数 为 0, 执 行 该 方 法 是 会 发 生 异 常 的 在 测 试 方 法 的 上 面 使 用 @Test 注 解 中 的 expected 属 性 来 测 试 程 序 中 是 否 会 发 生 java.lang.arithmeticexception 当 发 生 该 异 常 时, 则 测 试 通 过, 从 而 出 现 上 面 的 结 果 如 果 在 测 试 方 法 上 的 @Test 注 解 中 不 使 用 expected 属 性, 也 就 是 将 测 试 代 码 该 为 如 下 代 码 : 01 @Test 02 public void testdivide2() { 03 double d=new DivideMath().divide(3, 0); 04 } 启 动 运 行 测 试 该 方 法, JUnit 视 图 界 面 如 图 12-24 所 示

23 图 12-24 测 试 异 常 失 败 从 界 面 中 可 以 看 到 测 试 没 有 通 过 注 意 : 测 试 没 有 通 过 可 能 有 两 种 原 因 一 种 就 是 最 常 见 的 程 序 功 能 有 问 题, 另 一 种 就 是 测 试 程 序 中 发 生 异 常, 该 程 序 就 是 该 原 因 在 界 面 中 也 会 进 行 信 息 提 示, 在 红 条 的 上 面, Error 提 示 的 就 是 错 误 或 者 异 常 数 量, Failures 就 是 测 试 不 同 的 数 量 12.4.2 测 试 程 序 运 行 时 间 在 前 面 的 学 习 中 都 是 测 试 程 序 是 否 正 确, 但 是 对 于 项 目 而 言, 除 了 正 确 以 外, 效 率 也 是 非 常 重 要 的 在 测 试 中, 也 可 以 对 执 行 效 率 进 行 测 试, 它 是 通 过 @Test 注 解 中 的 timeout 属 性 完 成 的 测 试 程 序 运 行 时 间 的 代 码 如 下 所 示 01 @Test(expected=java.lang.ArithmeticException.class,timeout=100) 02 public void testdivide3() { 03 double d=new DivideMath().divide(3, 0); 04 } 其 中 第 1 行 中 使 用 timeout 属 性 指 定 程 序 所 花 费 的 时 间, 当 执 行 被 测 试 方 法 时, 花 费 的 时 间 超 过 timeout 属 性 值, 则 测 试 失 败 反 之 则 测 试 成 功 启 动 运 行 测 试, JUnit 视 图 界 面 如 图 12-25 所 示 图 12-25 测 试 时 间 出 现 绿 条, 表 示 测 试 成 功, 也 就 是 执 行 除 法 运 算 方 法 所 花 费 的 时 间 不 会 超 过 100 毫 秒 说 明 : 对 于 本 地 方 法 调 用 来 说, 是 通 过 不 需 要 进 行 时 间 测 试 的 但 是 对 于 Web 程 序 或 者 执 行 大 量 查 询 的 数 据 库 程 序, 测 试 程 序 的 运 行 时 间 是 非 常 重 要 的 如 果 时 间 不 符 合 要 求, 那 就 需 要 调 整 开 发 方 式

12.4.3 测 试 方 法 的 初 始 化 和 销 毁 在 讲 解 知 识 之 前, 我 们 来 分 析 几 个 情 况 例 如 在 Web 项 目 中, 我 们 要 对 Spring 管 理 的 所 有 业 务 方 法 进 行 测 试, 在 其 中 都 要 执 行 实 例 化 IoC 容 器 等 操 作 再 例 如 对 数 据 访 问 层 的 方 法 进 行 测 试, 执 行 完 测 试 后, 都 要 关 闭 数 据 库 资 源 这 些 情 况 下, 每 一 个 测 试 方 法 中 都 要 写 相 同 的 代 码 在 这 种 情 况 下 就 可 以 考 虑 使 用 @Before 注 解 和 @After 注 解, 通 过 这 两 种 注 解 标 明 的 方 法 就 会 在 测 试 方 法 之 前 和 之 后 执 行 相 同 的 代 码 例 如 在 DivideMathTest 测 试 类 程 序 中 加 入 下 面 的 代 码 : 01 @Before 02 public void before() { 03 System.out.println(" 进 行 Spring 中 IoC 容 器 的 实 例 化 "); 04 } 05 @After 06 public void after() { 07 System.out.println(" 释 放 数 据 库 资 源 "); 08 } 加 入 这 些 代 码 后, 启 动 运 行 测 试, 这 里 我 们 不 关 心 测 试 的 结 果, 直 接 看 控 制 台 中, 程 序 的 输 出 结 果 为 : 进 行 Spring 中 IoC 容 器 的 实 例 化 释 放 数 据 库 资 源 进 行 Spring 中 IoC 容 器 的 实 例 化 释 放 数 据 库 资 源 在 程 序 中 进 行 了 两 个 方 法 的 测 试, 从 运 行 结 果 中 可 以 看 到 各 执 行 了 两 次 上 面 的 方 法 其 中 @Before 注 解 的 方 法 将 在 每 一 个 测 试 方 法 之 前 执 行, @After 注 解 的 方 法 将 在 每 一 个 测 试 方 法 之 后 执 行 12.4.4 测 试 类 的 初 始 化 和 销 毁 不 但 可 以 为 每 一 个 方 法 定 义 初 始 化 和 销 毁 方 法, 还 可 以 直 接 为 测 试 类 定 义 这 样 的 方 法 @BeforeClass 注 解 标 明 的 方 法 就 是 一 个 测 试 类 初 始 化 方 法, 当 执 行 该 测 试 类 时 将 首 先 执 行 该 方 法 @AfterClass 注 解 标 明 的 方 法 就 是 测 试 类 的 销 毁 方 法, 当 执 行 完 测 试 类 中 的 所 有 测 试 方 法 后, 将 执 行 该 方 法 我 们 在 继 续 在 DivideMathTest 测 试 类 程 序 中 加 入 下 面 的 代 码 : @BeforeClass public static void beforeclass() { System.out.println(" 开 始 执 行 用 户 业 务 逻 辑 层 测 试 "); } @AfterClass public static void afterclass() { System.out.println(" 结 束 执 行 用 户 业 务 逻 辑 层 测 试 "); } 加 入 代 码 后, 再 次 启 动 测 试, 则 控 制 台 的 输 出 结 果 如 下 所 示 :

25 开 始 执 行 用 户 业 务 逻 辑 层 测 试 进 行 Spring 中 IoC 容 器 的 实 例 化 释 放 数 据 库 资 源 进 行 Spring 中 IoC 容 器 的 实 例 化 释 放 数 据 库 资 源 结 束 执 行 用 户 业 务 逻 辑 层 测 试 从 运 行 结 果 中 可 以 看 到, 在 执 行 所 有 测 试 方 法 之 前, 执 行 了 @BeforeClass 注 解 标 明 的 方 法 当 执 行 完 所 有 测 试 方 法 后, 将 执 行 @AfterClass 注 解 标 明 的 方 法 注 意 : @BeforeClass 注 解 和 @AfterClass 注 解 标 明 的 方 法 一 定 要 是 static 修 饰 的 静 态 方 法, 这 样 才 能 保 证 在 类 实 例 化 之 前 就 能 够 执 行 方 法 12.5 运 行 多 个 测 试 在 前 面 的 学 习 中, 学 习 了 如 何 运 行 单 个 测 试 方 法, 也 学 习 了 如 何 运 行 一 个 测 试 类 中 的 所 有 测 试 方 法 如 果 仅 仅 能 够 这 样, 测 试 效 率 是 非 常 低 的, 对 于 一 个 大 型 项 目 而 言, 运 行 测 试 的 时 间 就 是 非 常 多 的 在 JUnit 测 试 中, 还 可 以 对 整 个 包 中 的 测 试 方 法 同 时 运 行 因 为 项 目 中 的 所 有 测 试 程 序 通 常 放 在 同 一 包 下, 经 过 该 操 作 后 就 可 以 同 时 运 行 一 个 项 目 中 的 测 试 在 MyEclipse 的 包 资 源 管 理 器 中 选 中 测 试 程 序 所 在 的 包, 这 里 选 择 com.sanqing.junit.test 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Run As JUnit Test 命 令, 就 会 执 行 整 个 包 的 所 有 测 试 方 法 执 行 完 成 后, JUnit 视 图 界 面 如 图 12-26 所 示 图 12-26 运 行 多 个 测 试 当 执 行 多 个 测 试 时, 只 要 其 中 有 一 个 不 能 通 过 测 试, 都 会 出 现 红 条 在 红 条 上 面, 在 Error 后 会 显 示 有 多 少 个 测 试 方 法 发 生 异 常, 在 Failures 后 会 显 示 有 多 少 个 测

试 方 法 测 试 失 败 在 下 面 选 中 没 有 通 过 测 试 的 方 法, 将 在 Failure Trace 栏 中 显 示 出 它 的 具 体 信 息 然 后 依 次 对 没 有 通 过 测 试 的 方 法 进 行 排 错 处 理, 直 到 在 界 面 中 出 现 绿 条, 所 有 方 法 通 过 测 试 说 明 : 测 试 是 一 个 反 复 的 过 程, 没 有 程 序 员 能 够 保 证 写 的 程 序 都 能 通 过 测 试, 也 不 能 保 证 每 一 次 排 错 后 都 不 会 在 出 错 测 试 的 方 法 可 以 学 会, 但 是 测 试 的 经 验 需 要 每 一 个 读 者 自 己 总 结

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 13 章 CVS 和 SVN 版 本 控 制 在 开 发 小 型 项 目 中, 通 常 只 保 留 最 新 的 版 本 对 于 大 型 项 目 而 言, 这 种 做 法 就 会 有 一 定 的 问 题 因 为 在 大 型 项 目 改 动 是 比 较 多 的, 而 且 不 能 保 证 最 新 修 改 的 版 本 就 是 最 好 的 版 本, 所 以 经 常 要 反 复 操 作, 这 时 候 就 要 用 到 版 本 管 理 的 概 念 当 工 作 到 一 个 阶 段, 就 要 进 行 版 本 保 存, 在 后 面 的 工 作 中 或 者 其 他 开 发 人 员 可 以 使 用 指 定 的 某 一 个 版 本 随 着 项 目 的 发 展, 版 本 管 理 越 来 越 重 要, 它 在 当 前 软 件 开 发 中 是 必 不 可 少 的 版 本 管 理 是 一 种 功 能, 目 前 实 现 该 功 能 的 技 术 有 很 多, 在 MyEclipse 中 本 身 集 成 了 标 准 的 版 本 管 理 系 统 CVS, 该 技 术 已 经 流 行 了 很 长 时 间 除 了 CVS 外,SVN 也 是 最 近 流 行 起 来 的 版 本 管 理 工 具, 它 包 含 CVS 的 所 有 功 能, 并 且 修 复 了 CVS 的 一 些 缺 陷 在 本 章 中 将 重 点 讲 解 在 MyEclipse 中 如 何 操 作 CVS 和 SVN 这 两 个 版 本 管 理 工 具 13.1 本 地 版 本 控 制 CVS 和 SVN 是 在 大 型 项 目 中 团 队 开 发 和 阶 段 性 开 发 起 到 非 常 重 要 的 作 用, 但 是 如 果 是 对 于 一 个 人 来 说, 或 者 对 于 某 一 个 程 序 文 件 来 说, 完 全 没 有 必 要 使 用 这 些 工 具, 只 使 用 MyEclipse 自 带 的 版 本 管 理 功 能 就 可 以 13.1.1 比 较 在 讲 解 操 作 之 前, 我 们 先 来 看 一 下 MyEclipse 的 保 存 机 制 在 MyEclipse 中 开 发 程 序, 每 保 存 一 次 都 会 在 其 中 保 存 一 个 历 史 文 件 副 本 本 地 的 版 本 管 理 就 是 对 这 些 历 史 副 本 进 行 操 作 先 来 学 习 一 下 如 何 比 较 两 个 历 史 副 本 我 们 首 先 创 建 一 个 程 序, 程 序 的 代 码 为 : 01 public class HelloWorld { 02 public static void main(string[] args) { 03 System.out.println("HelloWorld 第 1 个 版 本 AAA"); 04 } 05 } 保 存 该 程 序 后, 然 后 将 其 中 的 第 3 行 代 码 换 为 如 下 代 码 : System.out.println("HelloWorld 第 2 个 版 本 BBB"); 然 后 再 次 保 存 程 序, 这 时 候 就 会 在 MyEclipse 中 产 生 两 种 历 史 文 件 副 本 在 编 辑 区 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Compare With Local History 命 令, 将 弹 出 文 件 历 史 视 图 界 面, 如 图 13-1 所 示

图 13-1 程 序 历 史 记 录 然 后 在 其 中 双 击 某 一 历 史 记 录, 例 如 选 择 09-11-29 上 午 10:09 记 录, 在 编 辑 区 中 将 弹 出 比 较 的 界 面, 如 图 13-2 所 示 图 13-2 比 较 界 面 界 面 中 上 部 分 是 显 示 当 前 程 序 的 程 序 结 构 在 左 下 部 分 中 显 示 了 当 前 程 序 的 代 码, 右 下 部 分 中 显 示 指 定 历 史 记 录 的 代 码, 在 其 中 将 两 个 代 码 不 同 的 地 方 标 明 在 历 史 记 录 代 码 的 上 面 有 几 个 操 作 按 钮, 其 中 和 按 钮 表 示 查 找 下 一 个 不 同 处 和 上 一 个 不 同 处 按 钮 表 示 使 用 所 有 不 同 的 地 方 替 换 左 边 的 内 容, 按 钮 表 示 将 当 前 指 定 的 不 同 处 替 换 成 左 边 的 内 容 注 意 : 不 但 可 以 让 当 前 程 序 和 某 一 历 史 记 录 进 行 比 较, 还 可 以 让 两 个 历 史 记 录 之

3 间 进 行 比 较 在 历 史 记 录 视 图 界 面 中, 选 中 两 个 历 史 记 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Copare with Each Other 命 令, 将 弹 出 对 这 两 个 历 史 记 录 进 行 比 较 的 界 面 和 前 面 的 比 较 界 面 非 常 相 似 的 13.1.2 替 换 在 上 一 小 节 中 讲 解 了 如 何 比 较 两 个 历 史 记 录, 所 以 对 不 同 处 进 行 替 换 操 作 在 MyEclipse 中, 也 可 以 直 接 进 行 替 换 操 作, 将 当 前 程 序 替 换 成 指 定 历 史 记 录 的 副 本 在 编 辑 区 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 中 选 择 Relace With Local History 命 令, 将 弹 出 替 换 界 面, 在 其 中 双 击 要 替 换 的 历 史 记 录, 替 换 界 面 将 变 为 如 图 13-3 所 示 图 13-3 替 换 界 面 在 界 面 中 将 把 当 前 代 码 和 指 定 历 史 记 录 的 代 码 都 显 示 出 来, 并 将 其 中 的 不 同 处 也 显 示 出 来 单 击 Replace 按 钮, 将 使 用 右 边 指 定 历 史 记 录 的 代 码 完 全 替 换 左 边 的 当 前 代 码 技 巧 : 在 实 际 开 发 中, 使 用 最 多 的 就 是 替 换 功 能, 但 是 并 不 是 上 面 的 替 换 操 作, 而 是 替 换 成 上 一 次 的 历 史 记 录 在 编 辑 区 中, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Relace With Previous from Local History 命 令, 并 不 会 弹 出 任 何 界 面, 而 是 直 接 替 换 成 上 一 次 保 存 时 的 历 史 记 录 使 用 该 操 作, 要 比 使 用 Ctrl+Z 撤 销 更 快 捷 13.2 CVS 版 本 控 制 使 用 MyEclipse 中 自 带 的 版 本 管 理 功 能 只 能 对 一 台 代 码 中 的 指 定 程 序 进 行 操 作 如

果 在 团 队 开 发 中, 该 功 能 就 不 能 达 到 需 求 CVS 是 一 种 控 制 系 统, 它 是 C/S 结 构 的 对 于 每 一 个 程 序 员 来 说 都 是 一 个 客 户 端, 程 序 员 可 以 上 传 自 己 的 程 序, 每 次 上 传 CVS 都 会 提 供 一 个 依 次 增 加 的 版 本 号 程 序 员 也 可 以 下 载 其 他 程 序 员 开 发 完 成 的 程 序, 在 其 中 可 以 选 择 最 新 版 本 或 者 某 一 版 本 在 CVS 的 服 务 器 端 中, 可 以 接 收 程 序 员 的 上 传 程 序, 也 可 以 让 程 序 员 下 载 服 务 器 端 通 常 是 由 项 目 经 理 管 理 的, 在 MyEclipse 中 只 集 成 了 CVS 客 户 端 的 功 能, 想 对 服 务 器 端 进 行 操 作, 还 可 以 安 装 CVS 服 务 器 13.2.1 下 载 和 安 装 CVS 服 务 器 CVS 可 以 使 用 在 多 个 操 作 系 统 下, 对 于 每 一 个 系 统 的 软 件 名 称 是 不 同 的 使 用 在 Windows 系 统 下 的 CVS 服 务 器 的 软 件 名 称 为 CVSNT, 它 的 官 方 网 站 为 www.cvsnt.org, 在 其 中 下 载 最 新 版 本 的 CVS 服 务 器 进 入 官 方 网 站 后, 如 图 13-4 所 示 图 13-4 CVS 服 务 器 官 方 网 站 单 击 CVSNT 图 标 下 的 download 按 钮, 将 显 示 下 载 CVS 服 务 器 的 页 面, 如 图 13-5 所 示

5 图 13-5 服 务 器 选 择 页 面 在 其 中 选 择 Server Windows 选 项, 单 击 Free Download Now 按 钮, 将 弹 出 下 载 窗 口, 或 者 在 下 载 工 具 中 进 行 下 载 注 意 : 浏 览 器 可 能 会 阻 止 下 载 窗 口 的 出 现, 如 果 出 现 该 结 果, 手 动 在 阻 止 工 具 条 中 单 击 鼠 标 右 键, 选 择 下 载 文 件 命 令 将 CVS 服 务 器 端 文 件 下 载 到 本 地 后, 就 可 以 安 装 它, 其 中 大 部 分 操 作 只 需 要 单 击 Next 按 钮 就 可 以, 在 其 中 要 选 择 同 意 协 议 进 入 到 安 装 方 式 选 择 界 面 中 后, 如 图 13-6 所 示 图 13-6 安 装 方 式 选 择 其 中 第 一 个 选 项 Typical 表 示 典 型 安 装, 选 择 该 选 项 就 可 以 然 后 在 下 一 个 界 面 中 单 击 Install 按 钮 将 开 始 安 装 稍 等 一 会 后, 将 弹 出 安 装 完 成 界 面, 单 击 Finish 按 钮, 将 完 成 安 装

13.2.2 配 置 CVS 服 务 器 下 载 和 安 装 CVS 服 务 器 后, 还 需 要 对 CVS 服 务 器 进 行 配 置 在 系 统 开 始 菜 单 中, 选 择 程 序 CVSNT CVSNT Control Panel 命 令, 将 弹 出 配 置 CVS 服 务 器 的 界 面, 如 图 13-7 所 示 图 13-7 配 置 界 面 所 示 在 其 中 选 择 Repository configuration 选 项 卡, 将 进 入 到 服 务 器 库 的 界 面, 如 图 13-8 图 13-8 服 务 器 库 界 面 单 击 Add 按 钮, 将 进 入 到 服 务 配 置 界 面, 如 图 13-9 所 示

7 图 13-9 服 务 配 置 界 面 其 中 Location 表 示 资 源 库 所 在 的 路 径, 例 如 我 们 在 D 盘 下 创 建 了 一 个 名 称 为 CVSNT 的 文 件 夹, 在 这 里 就 可 以 单 击 按 钮, 选 择 该 文 件 夹 这 样 我 们 就 为 资 源 库 创 建 了 一 个 存 储 空 间 单 击 OK 按 钮, 将 完 成 服 务 器 配 置 中 资 源 库 的 配 置 并 且 回 到 服 务 器 库 界 面, 并 将 新 增 加 的 库 显 示 在 其 中 在 配 置 界 面 中 再 次 选 择 Server Settings 选 项 卡, 界 面 如 图 13-10 所 示 图 13-10 配 置 管 理 员 其 中 Run as 用 来 选 择 管 理 员, 这 里 选 择 Administrator Temporary 表 示 出 错 信 息 的 存 储 目 录, 保 持 默 认 的 目 录 就 可 以 单 击 确 定 按 钮, 将 完 成 CVS 服 务 器 的 配 置

13.2.3 建 立 CVS 服 务 器 端 连 接 安 装 和 配 置 CVS 服 务 器 后, 我 们 就 可 以 继 续 来 开 发 CVS 的 客 户 端 在 MyEclipse 中 集 成 了 CVS 客 户 端 的 功 能, 并 且 定 义 了 CVS 操 作 透 视 图, 我 们 通 常 是 在 该 透 视 图 下 操 作 的 在 选 择 透 视 图 界 面 中, 选 择 CVS Repository Exploring 选 项, 就 会 将 MyEclipse 切 换 到 CVS 服 务 器 操 作 的 视 图, 如 图 13-11 所 示 图 13-11 CVS 操 作 透 视 图 在 该 透 视 图 中, 我 们 就 可 以 进 行 CVS 客 户 端 的 操 作 在 客 户 端 进 行 程 序 的 操 作 之 前, 要 首 先 和 CVS 服 务 器 端 建 立 连 接 在 CVS Repositories 视 图 界 面 的 空 白 处, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Repository Location 命 令, 将 弹 出 添 加 CVS 资 源 库 的 界 面, 如 图 13-12 所 示

9 图 13-12 添 加 CVS 资 源 库 其 中 Host 表 示 指 定 安 装 CVS 服 务 器 的 主 机 IP 地 址, 因 为 这 里 我 们 做 实 验 在 一 台 计 算 机 上, 所 以 可 以 填 写 LocalHost Repository path 表 示 资 源 库 的 路 径, 也 就 是 我 们 在 配 置 CVS 服 务 器 时 配 置 的, 这 里 填 写 /CVSNT User 和 Password 分 别 表 示 系 统 的 用 户 名 和 密 码, 这 里 可 以 是 Administrator 超 级 用 户, 也 可 以 是 自 己 创 建 的 普 通 用 户 其 他 选 项 采 用 默 认 值 就 可 以, 单 击 Finish 按 钮, 将 完 成 CVS 服 务 器 的 连 接, 从 而 在 CVS Repositories 视 图 界 面 多 出 一 个 资 源 库, 如 图 13-13 所 示 图 13-13 建 立 CVS 服 务 器 连 接 13.2.4 创 建 共 享 项 目 和 CVS 服 务 器 端 建 立 连 接 后, 我 们 就 可 以 进 行 客 户 端 的 操 作, 首 先 是 学 习 如 何 在 CVS 服 务 器 端 创 建 项 目 这 里 我 们 就 以 本 章 的 项 目 为 例 进 行 操 作 在 MyEclipse 中, 切 换 到 普 通 透 视 图 后, 在 包 资 源 管 理 器 中 选 中 要 提 交 的 项 目 单 击 鼠 标 右 键, 在 弹 出 菜 单 中 选 择 Team Share Project 命 令, 将 弹 出 选 择 资 源 库 的 界 面, 如 图 13-14 所 示

图 13-14 选 择 资 源 库 在 界 面 中 有 两 个 选 项, 其 中 Create a new repository location 表 示 创 建 一 个 新 的 资 源 库, Use existing repository location 表 示 使 用 已 经 创 建 的 资 源 库 因 为 我 们 在 前 面 的 操 作 中, 已 经 创 建 了 资 源 库, 所 以 这 里 选 择 第 2 个 选 项, 然 后 在 现 在 选 择.CVSNT 资 源 库 单 击 Next 按 钮, 将 弹 出 设 置 提 交 后 名 称 的 界 面, 如 图 13-15 所 示 图 13-15 设 置 名 称 其 中 Use project name module name 表 示 使 用 项 目 的 名 称 做 为 提 交 后 名 称 ; Use specified module name 表 示 自 己 指 定 提 交 后 的 名 称, 选 择 该 选 项 后, 需 要 在 后 面 填 写 名 称 ; Use an existing module 表 示 使 用 已 经 存 在 的 名 称 通 常 情 况 就 是 选 择 Use project

11 name module name 选 项, 单 击 Next 按 钮, 将 弹 出 共 享 项 目 资 源 界 面, 如 图 13-15 所 示 图 13-15 共 享 项 目 资 源 如 果 在 其 中 选 中 了 Launch the Commit wizard 复 选 框, 共 享 后, 会 启 动 提 交 选 项, 从 而 完 成 第 1 次 提 交 单 击 Finish 按 钮, 将 完 成 共 享 操 作, 并 弹 出 提 交 项 目 界 面, 如 图 13-16 所 示 图 13-16 第 1 次 提 交 项 目

在 界 面 的 上 半 部 分 的 文 本 域 中, 是 用 来 输 入 关 于 提 交 操 作 的 注 释 和 描 述 注 意 : 在 实 际 开 发 中, 它 是 非 常 重 要 的 通 过 描 述, 项 目 经 理 可 以 了 解 程 序 员 的 开 发 速 度, 其 他 程 序 员 使 用 你 的 项 目 时, 也 可 以 得 到 必 要 信 息 具 体 到 描 述 的 书 写 格 式, 每 一 个 公 司 都 是 不 同 的, 读 者 需 要 遵 守 所 在 公 司 的 规 范 单 击 Finish 按 钮, 将 完 成 项 目 的 第 一 次 提 交 切 换 到 CVS 操 作 透 视 图 中, 刷 新 其 中 的 CVS 服 务 器, 然 后 将 它 展 开, 如 图 13-17 所 示 图 13-17 第 一 次 提 交 结 果 从 结 果 中 可 以 看 到, 已 经 将 ch13 项 目 提 交 到 CVS 服 务 器 中, 并 且 在 程 序 文 件 后 面 多 出 了 1.1 的 内 容, 这 就 是 提 交 的 版 本 我 们 继 续 再 来 看 一 下 普 通 透 视 图 中 包 资 源 管 理 器 的 视 图 界 面, 如 图 13-18 所 示 图 13-18 提 交 后 包 资 源 管 理 器 在 包 资 源 管 理 器 中, 项 目 名 后 会 显 示 该 项 目 提 交 的 服 务 器, 在 每 一 个 文 件 后 都 会 显

13 示 该 文 件 在 CVS 服 务 器 中 的 版 本 号 13.2.5 提 交 文 件 在 上 一 小 节 中 已 经 完 成 了 共 享 项 目 的 操 作, 并 且 已 经 完 成 了 第 1 次 提 交 当 项 目 或 者 某 一 个 文 件 发 生 变 化 后, 我 们 需 要 将 新 版 本 的 程 序 提 交 到 CVS 服 务 器 中, 从 而 供 其 他 程 序 员 使 用 在 本 小 节 中 就 来 学 习 一 下 如 何 在 MyEclipse 中 完 成 提 交 程 序 的 操 作 首 先 我 们 将 HelloWorld 程 序 的 代 码 修 改 成 如 下 内 容 : 01 public class HelloWorld { 02 public static void main(string[] args) { 03 System.out.println("HelloWorld 第 3 个 版 本 CCC"); 04 } 05 } 然 后 在 包 资 源 管 理 器 中, 选 中 HelloWorld.java 程 序 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Team Commit 命 令, 将 弹 出 提 交 文 件 界 面, 在 其 中 输 入 提 交 描 述 后, 界 面 如 图 13-19 所 示 图 13-19 提 交 文 件 单 击 Finish 按 钮, 将 完 成 提 交 文 件 的 操 作 再 次 展 开 包 资 源 管 理 器 中 的 项 目, 如 图 13-20 所 示

图 13-20 提 交 后 界 面 从 包 资 源 管 理 器 中 可 以 看 到, 提 交 程 序 后 的 版 本 已 经 变 为 1.2 技 巧 : 不 但 可 以 提 交 某 一 个 文 件, 也 可 以 提 交 整 个 项 目, 操 作 是 一 样 的 通 过 这 种 方 式 可 以 将 整 个 项 目 提 交, 其 中 所 有 发 生 改 变 的 文 件 都 会 版 本 增 加, 没 有 改 变 的 文 件 不 会 版 本 增 加 在 实 际 开 发 中, 这 种 操 作 使 用 时 最 多 的 13.2.6 更 新 文 件 当 对 程 序 修 改 后, 发 现 修 改 的 并 不 正 确, 需 要 回 到 原 来 的 样 子, 这 时 候 就 要 在 CVS 服 务 器 中 更 新 文 件 例 如 我 们 将 HelloWorld 程 序 的 代 码 修 改 为 : 01 public class HelloWorld { 02 public static void main(string[] args) { 03 System.out.println("HelloWorld 第 4 个 版 本 DDD"); 04 } 05 } 修 改 后, 发 现 并 不 是 我 们 想 要 的, 需 要 切 换 到 原 来 版 本 这 时 候 就 要 执 行 更 新 文 件 的 操 作, 在 包 资 源 管 理 器 中 选 择 Team Synchronize with Repository 命 令, 将 弹 出 比 较 不 同 的 界 面, 如 图 13-21 所 示

15 图 13-21 和 原 版 本 比 较 通 过 该 文 件 就 可 以 使 用 当 前 程 序 内 容 和 提 交 到 CVS 服 务 器 的 程 序 相 比 较, 从 而 得 到 所 有 的 不 同 点 单 击 其 中 的 按 钮 和 按 钮 可 以 完 成 更 新 操 作 13.2.7 检 出 CVS 服 务 器 中 的 项 目 程 序 员 不 但 可 以 将 自 己 的 项 目 提 交 到 CVS 服 务 器 中, 还 可 以 在 CVS 服 务 器 中 检 出 其 他 程 序 员 的 项 目 在 MyEclipse 中, 切 换 到 CVS 操 作 透 视 图 中 后, 在 CVS Repositories 视 图 界 面 中 选 中 要 检 出 的 项 目, 例 如 这 里 选 择 前 面 操 作 上 传 的 ch13 项 目 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 有 两 个 检 出 命 令, 分 别 是 Check Out 命 令 和 Check Out As 命 令 说 明 : Check Out 命 令 表 示 检 出 到 本 地 当 前 工 作 空 间 内, 在 实 际 开 发 中, 通 常 使 用 该 命 令, 因 为 上 传 者 和 下 载 者 通 常 不 是 一 个 程 序 员, 也 就 是 不 在 同 一 电 脑 上 但 是 现 在 我 们 是 在 本 地 做 实 验, 所 以 我 们 这 里 选 择 Check Out As 命 令, 它 的 操 作 界 面 是 和 Check Out 命 令 的 操 作 界 面 非 常 相 似 的 选 择 Check Out As 命 令 后, 将 弹 出 修 改 检 出 项 目 名 称 的 界 面, 如 图 13-22 所 示

图 13-22 修 改 项 目 名 称 其 中 Check out as a project in the wordspace 选 项 表 示 做 为 工 作 空 间 中 的 项 目 检 出, 下 面 的 Project Name 表 示 检 出 项 目 的 名 称, 这 里 将 它 修 改 为 ch13_2 Check out into an existing project 表 示 检 出 到 一 个 已 经 存 在 的 项 目 中, 对 于 检 出 文 件 的 操 作, 通 常 选 中 该 选 项 Checkout subfolders 表 示 检 出 子 文 件 夹, 通 常 保 持 选 中 的 状 态 单 击 Next 按 钮, 将 弹 出 选 择 工 作 空 间 的 界 面, 如 图 13-23 所 示 图 13-23 选 择 检 出 项 目 工 作 空 间 其 中 Use default workspace location 表 示 是 否 使 用 默 认 的 工 作 空 间, 默 认 是 选 中 的 状 态 取 消 选 中 状 态 后, 可 以 在 Location 中 选 择 其 他 工 作 空 间 采 用 默 认 值, 单 击 Next 按 钮, 将 弹 出 对 检 出 项 目 进 行 描 述 的 界 面, 如 图 13-24 所 示

17 图 13-24 配 置 检 出 项 目 其 中 Refresh Tags 表 示 刷 新 标 记, Configure Tags 表 示 配 置 标 记, Add Date 表 示 为 检 出 项 目 添 加 一 个 日 期 单 击 这 些 按 钮, 都 会 进 入 相 应 设 置 的 界 面, 这 里 就 不 详 细 讲 解 了 可 以 采 用 默 认 值, 单 击 Finish 按 钮, 将 完 成 项 目 的 检 出 在 MyEclipse 中 切 换 到 默 认 视 图 中 后, 在 包 资 源 管 理 器 中 可 以 看 到 多 出 了 一 个 项 目, 如 图 13-25 所 示 图 13-25 检 出 项 目 结 果 从 包 资 源 管 理 器 可 以 看 到, 多 出 了 一 个 名 称 为 ch13_2 的 项 目, 这 就 是 从 CVS 服 务 器 中 检 出 的 项 目 在 该 项 目 中 也 会 保 留 程 序 的 版 本, 例 如 HelloWorld 程 序 是 以 1.2 版 本 提 交 的, 从 而 也 以 该 版 本 显 示 出 来

13.3 SVN 版 本 控 制 SVN 可 以 说 是 CVS 的 接 班 人, 它 是 比 CVS 更 强 大 的 版 本 控 制 工 具 在 SVN 中 实 现 了 CVS 的 全 部 功 能, 并 且 修 正 了 CVS 的 缺 陷 和 增 加 了 更 强 大 的 功 能 但 是 在 MyEclipse 中 并 没 有 集 合 SVN 的 操 作 功 能, 所 以 如 果 想 在 MyEclipse 中 进 行 SVN 操 作, 需 要 安 装 相 应 的 插 件 13.3.1 下 载 和 安 装 SVN 服 务 器 SVN 和 CVS 类 似, 也 是 由 服 务 器 端 和 客 户 端 组 成 的, 服 务 器 端 需 要 在 官 方 网 站 下 载 如 果 不 采 用 MyEclipse 等 开 发 工 具, 客 户 端 也 是 需 要 下 载 的, 但 是 这 里 我 们 采 用 MyEclipse 的 插 件 进 行 客 户 端 操 作 在 本 节 中 先 来 学 习 下 载 和 安 装 SVN 服 务 器 SVN 的 服 务 器 端 的 官 方 网 站 为 http://subversion.tigris.org, 它 的 下 载 链 接 为 http://subversion.tigris.org/project_packages.html, 打 开 该 链 接 后, 页 面 如 图 13-26 所 示 图 13-26 下 载 页 面 在 该 页 面 中, 会 显 示 SVN 服 务 器 在 不 同 操 作 系 统 下 的 版 本, 这 里 选 择 Windows 操 作 系 统 的 版 本, 单 击 后 面 的 here 超 链 接, 将 进 入 Windows 版 本 下 载 的 页 面, 在 其 中 选 择 Tigris.org 超 链 接, 就 会 进 入 对 应 选 择 版 本 的 下 载 页 面 在 其 中 选 择 最 新 的 版 本, 目 前 最 新 版 本 为 1.6.5 版 本, 单 击 它 对 应 的 超 链 接, 就 会 开 始 下 载 下 载 完 成 后, 就 可 以 进 行 双 击 安 装 SVN 服 务 器 的 安 装 时 非 常 简 单 的, 几 乎 都 是 单 击 Next 按 钮, 中 间 有 一 步 时 选 择 安 装 位 置, 可 以 采 用 默 认 地 址, 也 可 以 自 己 指 定, 选 择 位 置 后, 单 击 Next 按 钮, 将 弹 出 如 图 13-27 所 示 的 界 面

19 图 13-27 安 装 SVN 服 务 器 单 击 Install 按 钮, 将 开 始 安 装 SVN 服 务 器 稍 等 片 刻 后, 弹 出 完 成 界 面, 如 图 13-28 所 示 图 13-28 安 装 完 成 单 击 Finish 按 钮, 将 完 成 SVN 服 务 器 的 安 装 13.3.2 安 装 SVN 插 件 在 前 面 学 习 Struts 2 开 发 时, 已 经 学 习 了 如 何 安 装 Struts 2 插 件 在 MyEclipse 中, 所 有 的 插 件 的 安 装 都 是 非 常 类 似 的 在 MyEclipse 的 菜 单 中, 选 择 Help Software update Add/Remove Software 命 令, 将 弹 出 选 择 安 装 插 件 的 界 面, 在 其 中 Add 按 钮, 将 弹 出 增 加 插 件 的 界 面 在 增 加 插 件 界 面 中, 单 击 Add Site 按 钮, 将 弹 出 连 接 下 载 地 址 的 操 作 界 面, 在 其 中 输 入 下 载 SVN 插 件 的 URL, 如 图 13-29 所 示

图 13-29 连 接 SVN 插 件 URL SVN 插 件 的 安 装 URL 为 http://subclipse.tigris.org/update_1.6.x, 输 入 该 URL 后, 单 击 OK 按 钮, 将 完 成 SVN 插 件 的 连 接, 然 后 在 增 加 和 删 除 插 件 的 界 面 中 展 开 下 载 的 插 件, 如 图 13-30 所 示 图 13-30 查 找 到 SVN 插 件 选 择 SVN 下 的 三 个 选 项, 单 击 Next 按 钮, 将 进 入 安 装 SVN 插 件 的 界 面, 在 其 中 单 击 Apply 按 钮 将 开 始 安 装 这 些 插 件 后 面 的 操 作 就 是 和 安 装 Struts 2 插 件 完 成 相 同 的, 这 里 就 不 再 详 细 讲 解 13.3.3 创 建 服 务 器 资 源 库 安 装 SVN 服 务 器 后, 就 可 以 创 建 服 务 器 资 源 库 该 操 作 一 定 要 在 系 统 中 完 成, 然 后 在 MyEclipse 中 引 用, 在 MyEclipse 是 不 能 够 直 接 完 成 了, 因 为 其 他 并 没 有 集 成 服 务 器 的 功 能 在 创 建 服 务 器 资 源 库 之 前, 同 样 需 要 在 系 统 中 首 先 创 建 一 个 空 文 件 夹, 例 如 在 D 盘 下 创 建 SVN 文 件 夹 然 后 在 系 统 开 始 菜 单 中, 选 择 命 令, 输 入 cmd 命 令, 将 进

21 入 命 令 操 作 界 面, 在 其 中 输 入 svnadmin create d:\svn 命 令, 如 图 13-31 所 示 图 13-31 创 建 资 源 库 按 下 Enter 回 车 键 后, 将 完 成 该 命 令 的 执 行 打 开 D 盘 下 的 SVN 文 件 夹 可 以 发 现 里 面 初 始 化 了 一 些 文 件, 这 就 是 资 源 库 的 相 关 文 件 创 建 服 务 器 资 源 库 后, 通 常 还 需 要 对 它 进 行 比 较 的 配 置 在 默 认 情 况 下, 登 录 SVN 服 务 器 是 匿 名 的 形 式 登 录 的, 这 对 于 服 务 器 而 言 是 非 常 不 安 全 的, 所 以 我 们 要 定 义 登 录 用 户 名 和 密 码 首 先 打 开 资 源 库 文 件 夹 下 的 conf\svnserve.conf 文 件, 因 为 我 们 将 资 源 库 放 在 D 盘 的 SVN 文 件 夹 下, 所 以 完 整 路 径 为 D:\SVN\conf\svnserve.conf 打 开 文 件 后, 如 果 其 中 anon-access = read 和 auth-access = write 行 前 面 没 有 加 # 注 释, 就 为 它 们 加 上 # 注 释 然 后 将 其 中 的 password-db = passwd 行 前 面 的 # 注 释 去 掉, 通 过 该 操 作 可 以 时 同 目 录 下 的 密 码 文 件 生 效 接 下 来 使 用 记 事 本 等 文 本 工 具 打 开 同 目 录 下 的 passwd 文 件, 笔 者 计 算 机 上 它 的 完 整 路 径 为 D:\SVN\conf\passwd 在 该 文 件 的 最 后 加 入 如 下 内 容 : Tom = 456123 其 中 等 号 左 边 的 Tom 就 表 示 用 户 名, 等 号 右 边 的 456123 就 表 示 密 码 注 意 : 创 建 服 务 器 资 源 库 后, 要 在 命 令 控 制 台 中 输 入 svnserve d r d:/svn 命 令, 并 且 不 要 关 闭 窗 口, 这 样 才 能 够 保 证 SVN 服 务 器 启 动 状 态 13.3.4 在 MyEclipse 中 引 入 服 务 器 资 源 库 在 MyEclipse 中 安 装 SVN 插 件 成 功 后, 将 在 其 中 出 现 SVN 透 视 图 在 MyEclipse 菜 单 中, 选 择 Window Open Perspective Other 命 令, 将 弹 出 选 择 透 视 图 的 界 面, 如 图 13-32 所 示

图 13-32 选 择 SVN 透 视 图 可 以 看 到, 其 中 多 出 了 一 个 SVN 资 源 库 研 究 的 透 视 图, 选 择 该 透 视 图, 单 击 OK 按 钮, 将 切 换 到 该 透 视 图 中, 如 图 13-33 所 示 说 明 : 自 动 安 装 SVN 插 件 时, 会 自 动 安 装 对 应 语 言 的 版 本, 例 如 这 里 显 示 的 是 中 文, 在 后 面 的 操 作 步 骤 中, 大 部 分 也 是 中 文 这 和 其 他 功 能 是 有 很 大 区 别 的 图 13-33 SVN 透 视 图 效 果 其 中 最 重 要 的 就 是 SVN 资 源 库 视 图 界 面, 在 其 中 空 白 处, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 新 建 资 源 库 位 置 命 令, 将 弹 出 添 加 SVN 资 源 库 的 界 面, 如 图 13-34 所 示

23 图 13-34 添 加 SVN 资 源 库 其 中 URL 表 示 的 就 是 SVN 资 源 库 所 在 的 地 址, 因 为 我 们 在 本 地 做 实 验, 所 以 这 里 可 以 填 写 svn://localhost, 最 后 单 击 Finish 按 钮, 将 完 成 引 入 操 作, 从 而 在 SVN 资 源 库 视 图 界 面 中 多 出 一 个 SVN 资 源 库 13.3.5 向 SVN 服 务 器 中 提 交 创 建 SVN 服 务 器 资 源 库 后, 我 们 就 可 以 向 资 源 库 中 提 交 项 目 或 者 程 序 文 件 切 换 到 MyEclipse 的 默 认 透 视 图 下, 在 包 资 源 管 理 器 中 创 建 一 个 新 项 目, 项 目 的 名 称 为 ch13_svn, 然 后 在 该 项 目 中 创 建 Java 程 序, 其 代 码 内 容 为 : 01 public class HelloWorld { 02 public static void main(string[] args) { 03 System.out.println("SVN 服 务 器 第 1 次 提 交 AAA"); 04 } 05 } 在 讲 解 CVS 时, 主 要 是 进 行 的 程 序 文 件 操 作, 这 里 讲 解 SVN 时 就 主 要 以 项 目 进 行 操 作, 它 们 的 操 作 都 是 一 样 的 在 包 资 源 管 理 器 中, 选 中 ch13_svn 项 目, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Team Share Project 命 令, 将 弹 出 选 择 版 本 控 制 工 具 的 界 面, 如 图 13-35 所 示

图 13-35 选 择 版 本 控 制 工 具 因 为 目 前 MyEclipse 中 并 不 只 CVS 这 一 种 版 本 控 制 工 具, 所 以 会 出 现 该 选 择 工 具 的 界 面 在 其 中 选 择 SVN 选 项, 单 击 Next 按 钮, 将 进 入 选 择 资 源 库 的 界 面, 如 图 13-36 所 示 图 13-36 选 择 资 源 库 在 该 界 面 中, 可 以 选 择 创 建 新 的 资 源 库, 也 可 以 选 择 使 用 已 有 的 资 源 库 当 选 择 第 2 个 使 用 已 有 资 源 库 的 选 项 后, 还 可 以 在 下 面 选 择 具 体 的 哪 一 个 资 源 库 选 中 后, 单 击 Next 按 钮, 将 弹 出 设 置 文 件 夹 名 的 界 面, 如 图 13-37 所 示

25 图 13-37 设 置 文 件 夹 名 在 该 界 面 中, 我 们 通 常 选 择 使 用 项 目 名 作 为 文 件 夹 的 名 称, 在 URL 的 文 本 框 中 海 会 显 示 该 项 目 在 SVN 服 务 器 中 的 访 问 地 址 单 击 Next 按 钮, 将 弹 出 输 入 提 交 注 释 的 界 面, 如 图 13-38 所 示 图 13-38 输 入 提 交 注 释 每 一 种 版 本 控 制 工 具 中 都 会 有 这 一 步 的, 这 里 我 们 输 入 这 是 向 SVN 服 务 器 中 第 1 次 提 交 单 击 Finish 按 钮, 将 完 成 向 SVN 服 务 器 的 第 1 次 提 交 提 交 后, 在 MyEclipse 菜 单 中, 选 择 Show View Other 命 令, 将 弹 出 选 择 视 图 界 面 的 窗 口, 如 图 13-39 所 示

图 13-39 选 择 视 图 界 面 在 其 中 选 择 Team Synchronize 选 项, 单 击 OK 按 钮, 将 打 开 该 视 图 界 面, 如 图 13-40 所 示 图 13-40 提 交 项 目 后 结 果 该 视 图 界 面 就 是 用 于 显 示 SVN 服 务 器 中 保 存 的 项 目, 从 其 中 可 以 看 到 前 面 创 建 ch13_svn 项 目 已 经 被 提 交 到 SVN 服 务 器 中, 从 而 可 以 供 其 他 程 序 员 下 载 说 明 : 第 1 次 提 交 项 目 是 比 较 复 杂 的, 需 要 首 先 在 SVN 服 务 器 中 创 建 对 应 的 文 件 夹 在 以 后 的 提 交 后, 就 比 较 简 单, 只 要 在 右 键 弹 出 菜 单 中 选 择 Team 提 交 命 令 就 可 以 完 成 新 版 本 的 提 交 13.3.6 从 SVN 服 务 器 中 检 出 向 SVN 服 务 器 中 提 交 项 目 后, 其 他 程 序 员 就 可 以 将 该 项 目 检 出 这 里 我 们 重 新 启 动 一 个 MyEclipse, 并 切 换 到 不 同 的 工 作 空 间 下, 这 样 来 模 拟 另 一 个 程 序 员

27 在 MyEclipse 中, 首 先 切 换 到 SVN 资 源 库 研 究 透 视 图 下, 同 样 需 要 在 其 中 引 入 服 务 器 资 源 库 打 开 该 服 务 器 资 源 库, 可 以 发 现 其 中 多 出 了 一 个 名 称 为 ch13_svn 的 项 目, 选 中 该 项 目, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 检 出 为 命 令, 将 弹 出 检 出 操 作 的 界 面, 如 图 13-41 所 示 图 13-41 从 SVN 检 出 在 其 中 选 中 做 为 工 作 空 间 中 的 项 目 检 出 的 选 项, 保 持 项 目 的 名 称 为 ch13_svn, 单 击 Next 按 钮, 将 弹 出 选 择 项 目 位 置 的 界 面, 如 图 13-42 所 示 图 13-42 选 择 项 目 位 置 通 过 该 界 面 可 以 设 置 是 否 将 检 出 的 项 目 放 置 在 默 认 工 作 空 间 内, 通 常 是 保 持 默 认 的 选 中 状 态 的 单 击 Finish 按 钮, 将 把 SVN 服 务 器 中 的 项 目 检 出 到 当 前 工 作 空 间 中 将 MyEclipse 切 换 到 默 认 透 视 图 中, 在 包 资 源 管 理 器 中 展 开 ch13_svn 项 目, 如

图 13-43 所 示 图 13-43 检 出 结 果 在 其 中 可 以 看 到 在 项 目 名 后 将 出 现 对 应 SVN 服 务 器 中 的 文 件 夹 名 称 在 其 中 的 程 序 文 件 后, 将 出 现 该 文 件 的 SVN 版 本 提 交 时 间 和 提 交 用 户

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 14 章 UML 建 模 UML 的 中 文 名 称 叫 统 一 建 模 语 言, 它 是 一 种 对 软 件 密 集 系 统 进 行 可 视 化 建 模 的 编 程 语 言 随 着 软 件 的 发 展,UML 越 来 越 重 要 目 前 UML 的 开 发 工 具 有 很 多, 例 如 Rational Rose Borland Together 等, 它 们 大 部 分 都 是 商 业 软 件, 也 就 是 收 费 的 开 源 的 UML 开 发 工 具 比 较 少, 最 有 名 的 是 ArgoUML, MyEclipse 中 集 成 的 UML 建 模 工 具 就 是 基 于 ArgoUML 工 具 开 发 的 在 本 章 中 将 重 要 来 讲 解 MyEclipse 中 进 行 UML 建 模 操 作 14.1 创 建 UML 模 型 仓 库 在 本 节 中 通 过 一 个 最 简 单 的 例 子 来 演 示 在 MyEclipse 中 如 何 创 建 UML 模 型 在 MyEclipse 中,UML 模 型 也 是 被 看 做 是 一 般 的 程 序 文 件 的, 所 以 它 也 要 放 在 某 一 项 目 下 首 先 在 开 发 之 前 首 先 创 建 一 个 名 称 为 ch14 的 项 目, 然 后 在 该 项 目 下 创 建 uml 包 在 MyEclipse 中 进 行 UML 开 发, 第 一 步 并 不 是 直 接 创 建 UML 模 型, 而 是 首 先 要 创 建 一 个 UML 模 型 仓 库, 所 有 的 UML 模 型 将 放 在 该 模 型 仓 库 中 在 包 资 源 管 理 器 中, 选 中 uml 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New UML1 Model 命 令, 将 弹 出 创 建 UML 模 型 仓 库 的 界 面, 如 图 14-1 所 示 图 14-1 创 建 UML 模 型 仓 库

其 中 UML1 model file 表 示 模 型 仓 库 的 名 称, 这 里 输 入 firstuml, 其 他 保 持 默 认 值, 单 击 Finish 按 钮, 将 完 成 UML 模 型 仓 库 文 件 的 创 建 并 且 弹 出 一 个 是 否 切 换 透 视 图 的 对 象 化, 这 里 单 击 Yes 按 钮, 将 切 换 到 UML 透 视 图 中 并 且 在 编 辑 区 中 还 会 打 开 firstuml 模 型 仓 库 文 件, 界 面 如 图 14-2 所 示 图 14-2 开 发 界 面 在 该 文 件 界 面 中, 就 可 以 创 建 UML 模 型, 主 要 通 过 上 面 的 工 具 按 钮 来 完 成, 在 后 面 操 作 中 将 详 细 讲 解 它 们 注 意 : 在 MyEclipse 中 虽 然 显 示 UML 模 型 仓 库 的 扩 展 名 为.umr, 其 实 它 是 一 个 包 文 件, 完 全 可 以 使 用 WinRAR 等 软 件 打 开 14.2 用 例 图 开 发 完 UML 模 型 仓 库 后, 也 就 是 创 建 模 型 仓 库 文 件 后, 就 可 以 在 该 文 件 中 创 建 UML 模 型 图 形 UML 中 的 模 型 图 形 有 很 多 种, 包 括 用 例 图 类 图 状 态 图 时 序 图 等 很 多 种, 在 本 节 中 将 对 其 中 开 发 中 经 常 用 到 的 图 进 行 操 作 学 习 用 例 图 是 在 系 统 分 析 阶 段 经 常 要 绘 制 的 UML 图, 在 其 中 通 常 标 出 系 统 中 有 哪 些 用 户, 这 些 用 户 能 够 完 成 哪 些 功 能 在 用 例 图 中 可 以 包 含 6 个 元 素, 分 别 是 参 与 者 用 例 关 联 关 系 包 含 关 系 扩 展 关 系 和 泛 化 关 系, 在 一 个 用 例 图 中 是 不 必 须 全 部 包 含 这 六 种 元 素 14.2.1 参 与 者 在 MyEclipse 的 模 型 仓 库 界 面 中, 选 择 工 具 栏 第 一 个 下 三 角 菜 单 中 的 New Use Case Diagram 选 项, 则 当 前 工 具 栏 将 变 为 进 行 用 例 图 创 建 的 形 式 在 其 中 单 击 按 钮, 然 后 在 画 布 中 单 击, 将 创 建 一 个 用 例 图 中 的 参 与 者, 并 在 界 面 中 显 示 一 个 参 与 者 图 标 双 击 参 与 者 图 标 下 空 白 处, 可 以 添 加 参 与 者 的 名 称, 这 里 添 加 游 客 如 图 14-3 所 示 说 明 : 为 UML 图 添 加 例 如 名 称 这 样 的 信 息, 通 常 是 双 击 添 加, 也 可 以 在

3 Properties 视 图 界 面 中 添 加 图 14-3 创 建 参 与 者 14.2.2 用 例 开 发 完 参 与 者 后, 就 可 以 开 发 用 例, 用 例 就 表 示 在 系 统 中 能 够 完 成 哪 些 功 能 单 击 工 具 栏 中 的 按 钮, 然 后 在 画 布 中 再 次 单 击, 将 创 建 一 个 用 例, 双 击 图 标 可 以 添 加 用 例 的 内 容 使 用 这 种 方 式, 这 里 添 加 两 个 用 例, 如 图 14-4 所 示 图 14-4 创 建 用 例 14.2.3 关 联 关 系 参 与 者 和 用 例 之 间 的 关 系 称 之 为 关 联 关 系 在 工 具 栏 中 单 击 按 钮 后 的 下 三 角 选 择 uni Association 选 项, 然 后 在 下 面 的 界 面 中 首 先 选 中 参 与 者, 然 后 拖 动 鼠 标 在 选 中 用 例, 这 样 就 添 加 了 一 条 关 联 关 系 为 两 个 用 例 都 建 立 关 联 关 系 后, 如 图 14-5 所 示

图 14-5 创 建 关 联 关 系 建 立 关 联 关 系 后, 一 个 基 本 的 用 例 图 就 开 发 完 成 了 从 用 例 图 中 可 以 知 道 目 前 系 统 中 有 一 种 用 户 是 游 客, 它 能 够 完 成 注 册 和 登 录 的 功 能 说 明 : 用 例 图 除 了 上 面 三 种 元 素 外, 包 括 包 含 关 系 扩 展 关 系 和 泛 化 关 系 包 含 关 系 用 于 用 例 和 用 例 之 间, 表 示 一 个 用 例 包 含 另 一 个 用 例 的 全 部 功 能, 例 如 用 户 用 例 包 含 游 客 用 例 扩 展 关 系 也 是 用 在 用 例 之 间, 表 示 对 用 例 的 扩 展, 例 如 发 表 主 题 时, 用 户 积 分 会 增 加, 则 积 分 增 加 用 例 和 发 表 主 题 用 例 之 间 就 是 扩 展 关 系 返 回 关 系 表 示 将 用 例 功 能 更 详 细 化, 例 如 查 看 文 章 用 例, 就 可 以 泛 化 为 在 首 页 查 看 文 章 和 个 人 博 客 中 查 看 文 章 两 个 范 例 14.3 类 图 类 图 是 用 来 描 述 类 相 关 的 信 息, 例 如 类 中 的 变 量 和 方 法 类 与 类 之 间 的 关 系, 通 过 它 可 以 显 示 类 的 静 态 结 构 类 图 中 包 含 多 种 元 素, 分 别 是 类 接 口 协 作 依 赖 关 系 泛 化 关 系 和 关 联 关 系 等 注 意 : 在 不 同 的 UML 图 中 经 常 会 出 现 相 同 的 元 素 名 称, 例 如 泛 化 关 系, 需 要 注 意 的 是 它 们 表 示 的 含 义 是 完 全 不 同 的, 一 定 要 注 意 区 分 14.3.1 类 在 工 具 栏 中 选 择 New Class Diagram 选 项, 当 前 工 具 栏 将 变 为 创 建 类 图 的 工 具 栏 单 击 其 中 的 按 钮, 然 后 在 画 布 中 再 次 单 击, 将 创 建 一 个 表 示 UML 图 中 类 的 图 标 类 图 标 分 为 三 层, 依 次 可 以 向 其 中 输 入 类 名 属 性 名 和 方 法 名 通 过 双 击 可 以 填 写 相 关 名 称, 属 性 和 方 法 名 可 以 填 写 多 个 例 如 这 里 创 建 一 个 学 生 类, 如 图 14-6 所 示

5 图 14-6 类 通 过 该 类 图 标, 程 序 员 就 可 以 知 道 在 项 目 中 要 创 建 一 个 Student 学 生 类, 在 该 类 中 定 义 name 姓 名 和 age 年 龄 属 性, 以 及 sleep 睡 觉 和 eat 吃 饭 方 法 14.3.2 接 口 接 口 也 是 类 图 中 必 不 可 少 的 一 种 元 素 在 接 口 中 规 定 了 一 类 对 象 行 为 的 描 述, 但 是 并 没 有 给 出 具 体 的 实 现 在 接 口 中 只 包 含 操 作, 并 不 包 含 属 性 在 类 图 工 具 栏 中 单 击 按 钮, 然 后 在 画 布 中 再 次 单 击, 将 创 建 一 个 UML 图 中 的 接 口 图 标 接 口 图 标 分 为 两 层, 上 层 是 用 来 填 写 接 口 名, 下 层 用 来 定 义 接 口 中 有 哪 些 方 法 通 过 双 击 操 作 同 样 能 够 输 入 内 容, 例 如 这 里 创 建 一 个 表 示 人 的 接 口, 如 图 14-7 所 示 图 14-7 接 口 这 样 就 创 建 了 一 个 表 示 人 的 接 口, 其 中 定 义 了 睡 觉 和 吃 饭 两 个 抽 象 方 法 类 与 接 口 之 间 最 常 见 的 关 系 就 是 实 现, 单 击 工 具 栏 中 的 按 钮, 然 后 从 类 拖 动 到 接 口, 就 建 立 了 它 们 之 间 的 实 现 关 系, 如 图 14-8 所 示 图 14-8 类 实 现 接 口 通 过 这 种 虚 线 闭 合 箭 头 的 形 式, 就 可 以 知 道 Student 学 生 类 将 实 现 Person 接 口 技 巧 : 实 现 关 系 还 有 简 略 的 方 式, 就 是 将 接 口 使 用 圆 圈 图 标, 然 后 使 用 线 段 连 接

类 和 接 口 就 表 示 实 现 关 系 但 是 目 前 这 种 UML 图 已 经 很 少 见 了 14.3.3 类 之 间 的 依 赖 关 系 依 赖 关 系 是 指 类 模 型 之 间 语 义 上 的 关 系, 其 中 包 含 四 种 依 赖 类 型, 分 别 是 使 用 依 赖 抽 象 依 赖 授 权 依 赖 和 绑 定 依 赖 依 赖 关 系 通 过 虚 线 非 闭 合 箭 头 表 示, 单 击 工 具 栏 中 的 按 钮 中 的 倒 三 角 可 以 完 成, 如 图 14-9 所 示 图 14-9 依 赖 关 系 该 依 赖 关 系 UML 图 就 表 示 在 Car 汽 车 类 中 将 使 用 依 赖 于 Tyre 轮 胎 类 具 体 其 他 依 赖 关 系, 读 者 可 以 参 考 UML 相 关 资 料 学 习, 这 里 就 不 再 一 一 讲 解 14.3.4 类 之 间 泛 化 关 系 UML 中 的 类 之 间 泛 化 关 系 对 应 的 就 是 程 序 中 的 继 承, 它 表 示 父 类 和 子 类 之 间 的 关 系 在 UML 图 中, 使 用 实 线 闭 合 箭 头 从 子 类 指 向 父 类, 从 而 表 示 他 们 之 间 的 泛 化 关 系, 单 击 按 钮 可 以 完 成, 如 图 14-10 所 示 图 14-10 泛 化 关 系 通 过 该 UML 图 就 可 以 表 示 Car 汽 车 类 将 继 承 Vehicle 交 通 工 具 类 说 明 : 一 个 类 的 图 标 可 以 被 多 个 类 图 标 泛 化, 也 是 Java 程 序 中 的 一 个 父 类 拥 有 多 个 子 类, 例 如 飞 机 类 也 可 以 和 交 通 工 具 类 建 立 泛 化 关 系 因 为 UML 不 只 能 表 示 Java 程 序, 当 表 示 其 他 编 程 语 言 时, 还 可 能 出 现 一 个 类 泛 化 多 个 类 的 情 况 14.3.5 类 之 间 关 联 关 系 严 格 的 来 说, 关 联 关 系 并 不 是 类 之 间 的 关 系, 而 是 类 实 例 或 者 对 象 之 间 的 关 系, 但 是 因 为 UML 图 中 通 过 使 用 类 的 图 标 建 立 关 系, 所 以 也 可 以 称 之 为 类 之 间 的 关 联 关 系 关 联 关 系 是 通 过 一 个 线 段 表 示 的, 但 是 如 果 仅 仅 使 用 它 是 不 能 具 体 看 出 之 间 的 关 系 的, 所 以 需 要 为 它 加 入 一 些 修 饰, 包 括 名 称 角 色 多 重 性 聚 合 组 合 和 导 航 性 单

7 击 工 具 栏 中 的 按 钮, 可 以 完 成 关 联 关 系 的 创 建, 通 过 Properties 视 图 界 面 可 以 为 关 联 关 系 加 入 修 饰, 如 图 14-11 所 示 图 14-11 关 联 关 系 该 UML 图 中 为 Teacher 老 师 类 和 Student 学 生 类 建 立 了 关 联 关 系, 它 们 之 间 是 teach 教 学 的 关 系 类 图 标 旁 边 的 数 字 表 示 类 的 多 重 性, 这 里 表 示 一 个 老 师 可 以 教 多 个 学 生, 一 个 学 生 可 以 被 多 个 老 师 教 14.4 UML 和 Java 程 序 之 间 的 转 换 如 果 仅 仅 是 通 过 UML 图 来 表 示 程 序 的 结 构 或 者 程 序 之 间 的 关 系, 那 UML 也 不 会 这 种 重 要 UML 强 大 之 处 在 于 它 能 够 和 Java 程 序 进 行 相 互 转 换, 也 就 是 我 们 绘 制 完 UML 类 图 后, 能 够 自 动 生 成 Java 程 序 从 UML 类 图 到 Java 程 序 被 称 为 正 向 工 程, 从 Java 程 序 到 UML 类 图 被 称 为 反 向 工 程 14.4.1 正 向 工 程 正 向 工 程 就 是 建 立 UML 类 图 后, 自 动 生 成 和 它 对 应 的 Java 程 序, 在 该 Java 程 序 中 就 会 具 有 UML 类 图 中 定 义 了 属 性 方 法 等 信 息 注 意 : 自 动 生 成 是 有 前 提 条 件 的, 必 须 在 绘 制 UML 类 图 时 就 要 使 用 规 范 的 形 式 因 为 在 绘 制 UML 时 并 没 有 严 格 的 规 范, 例 如 定 义 方 法 时 不 填 写 返 回 值 也 是 没 有 问 题 的, 但 是 当 转 换 Java 程 序 时 就 会 出 现 问 题 这 里 我 们 先 创 建 一 个 UML 模 型 仓 库, 然 后 在 该 模 型 仓 库 中 定 义 表 示 Student 学 生 类 的 图 标, 如 图 14-12 所 示 图 14-12 创 建 示 例 类 创 建 UML 模 型 后, 不 要 忘 记 保 存 模 型 仓 库 文 件 然 后 就 是 执 行 正 向 工 程 的 操 作, 在 MyEclipse 中 选 择 UML Generate Java 命 令, 将 弹 出 创 建 Java 程 序 的 界 面, 如

图 14-13 所 示 图 14-13 正 向 工 程 其 中 Java Output Folder 表 示 Java 程 序 的 输 出 目 录, 这 里 要 选 择 在 src 目 录 下 在 下 面 的 文 本 域 中 将 列 出 可 以 创 建 哪 些 Java 程 序, 如 果 UML 图 中 有 多 个 类 或 者 接 口, 都 将 列 在 这 里 由 于 目 前 只 创 建 了 一 个 Student 学 生 类 的 图 标, 所 以 这 里 只 有 一 个 Student 节 点, 选 中 它, 单 击 Finish 按 钮, 将 完 成 Java 程 序 的 创 建 双 击 打 开 自 动 生 成 的 Student.java 程 序, 在 编 辑 区 中 将 显 示 它 的 代 码, 如 下 所 示 01 import java.lang.string; 02 public class Student { 03 public int age; 04 public String name; 05 public void study() { 06 } 07 } 从 代 码 中 可 以 看 到 自 动 生 成 了 age 年 龄 和 name 姓 名 属 性, 并 且 也 生 成 了 表 示 study 学 习 的 空 方 法, 需 要 手 动 在 方 法 中 加 入 功 能 代 码 自 动 生 成 的 代 码 也 是 有 不 合 适 的 地 方 的, 例 如 第 1 行 的 代 码, 对 于 java.lang.* 包 的 类 是 不 需 要 导 入 的, 但 是 自 动 生 成 时 会 加 上 14.4.2 反 向 工 程 有 些 读 者 可 能 有 这 样 的 疑 问 :UML 模 型 的 作 用 就 是 让 程 序 员 参 考 进 行 开 发, 那 为 什 么 开 发 完 Java 程 序 后, 还 需 要 生 成 UML 模 型 呢? 这 是 因 为 通 过 UML 模 型 能 够 很 清 楚 的 看 到 程 序 之 间 的 关 系, 这 在 大 型 项 目 中 是 非 常 重 要 的 当 项 目 中 有 很 多 个 程 序 时, 并 且 程 序 之 间 关 系 复 杂, 通 过 读 程 序 代 码 是 非 常 麻 烦 的, 这 时 候 就 可 以 将 它 们 生 成 UML 模 型, 通 过 它 们 来 看 程 序 之 间 的 关 系 这 里 我 们 首 先 创 建 一 个 非 常 简 单 的 Java 类 程 序, 通 过 它 可 以 演 示 如 何 生 成 UML 类 图, 它 的 代 码 为 :

9 01 package com; 02 public class Teacher { 03 private String name; 04 private int age; 05 public String getname() { 06 return name; 07 } 08 public void setname(string name) { 09 this.name = name; 10 } 11 public int getage() { 12 return age; 13 } 14 public void setage(int age) { 15 this.age = age; 16 } 17 } 开 发 完 程 序 后, 然 后 回 到 UML 模 型 仓 库 文 件 中 在 MyEclipse 的 菜 单 中, 选 择 UML Reverse Engineer UML from Java 命 令, 将 弹 出 选 择 Java 程 序 的 界 面, 如 图 14-14 所 示 图 14-14 选 择 Java 程 序 这 里 在 其 中 只 选 择 Teacher.java 程 序 节 点, 单 击 Next 按 钮, 将 弹 出 设 置 UML 类 图 的 界 面, 如 图 14-15 所 示

图 14-15 设 置 UML 类 图 界 面 中 Java Processing 表 示 Java 处 理 的 设 置 栏, 其 中 Creat class diagrams 表 示 是 否 生 成 类 图, 保 持 默 认 选 中 状 态 ; Hide class/interface details 表 示 是 否 隐 藏 类 或 者 接 口 详 细 内 容, 通 常 取 消 该 选 项 选 中 状 态, 显 示 详 细 内 容 在 生 成 UML 设 置 的 Java UML Generation 栏 中, UML attributes 选 项 表 示 将 Java 属 性 建 模 为 UML 属 性, UML associations 选 项 表 示 将 Java 属 性 建 模 为 UML 关 联 UML datatype 表 示 将 Java 数 组 建 模 为 UML 数 据 类 型, UML multiplicity 1..n 表 示 将 Java 数 组 建 模 为 UML 一 对 多 关 系 这 些 选 项 通 常 采 用 默 认 的 选 项 就 可 以, 单 击 Finish 按 钮, 将 完 成 反 向 工 程 操 作, 片 刻 后 将 弹 出 对 话 框, 如 图 14-16 所 示 图 14-16 确 定 对 话 框 保 持 该 对 话 框 中 选 项 默 认 的 选 中 状 态, 单 击 OK 按 钮, 将 完 成 所 有 操 作, 在 UML 模 型 仓 库 界 面 中 将 显 示 创 建 的 Teacher 老 师 类 图, 如 图 14-17 所 示

11 图 14-17 反 向 工 程 生 成 UML 模 型 从 类 图 中 可 以 看 到, 将 程 序 中 的 类 名 属 性 和 方 法 都 定 义 到 了 Teacher 类 图 中 如 果 在 设 置 UML 类 图 界 面 中, 保 持 默 认 的 Hide class/interface details 选 项 选 中 状 态, 这 时 候 将 只 显 示 类 名 技 巧 : 本 小 节 中 讲 解 的 方 式 最 实 用 与 对 多 个 程 序 同 时 生 成 UML 模 型 的 情 况, 如 果 仅 仅 对 数 量 有 限 的 程 序 生 成, 还 有 一 个 更 简 单 的 方 式, 那 就 是 直 接 将 程 序 拖 动 到 UML 模 型 仓 库 画 布 中, 将 执 行 弹 出 设 置 UML 类 图 的 界 面 14.5 状 态 图 状 态 图 是 一 种 系 统 分 析 时 经 常 用 到 的 UML 图, 通 过 它 可 以 跟 踪 某 一 对 象 变 化 的 动 态 行 为 例 如 网 上 商 店 中 的 订 单 对 象, 当 用 户 购 买 后, 就 生 产 订 单, 然 后 该 订 单 就 会 经 过 销 售 部 门 仓 库 部 门 财 务 部 门 等, 在 每 一 个 部 门 中 都 会 产 生 一 个 新 状 态, 例 如 已 确 定 已 发 货 已 收 钱 等 14.5.1 开 始 状 态 和 终 止 状 态 在 MyEclipse 的 UML 模 型 仓 库 界 面 中, 单 击 工 具 栏 中 第 一 个 按 钮 后 的 倒 三 角, 在 其 中 选 择 New Statechart Diagram 选 项, 就 会 切 换 到 状 态 图 开 发 的 工 具 栏 状 态 图 中 最 固 定 的 状 态, 那 就 是 开 始 状 态 和 终 止 状 态 在 工 具 栏 中 使 用 按 钮 可 以 创 建 开 始 状 态, 使 用 按 钮 可 以 创 建 终 止 状 态, 创 建 的 图 标 如 图 14-18 所 示 图 14-18 开 始 和 终 止 状 态 其 中 实 心 黑 点 就 是 开 始 状 态, 圆 环 黑 点 就 是 终 止 状 态, 这 两 个 状 态 是 固 定 的, 在 这

两 个 状 态 之 间 可 以 加 入 其 它 自 定 义 的 状 态 14.5.2 增 加 状 态 开 发 完 开 始 状 态 和 终 止 状 态 后, 就 可 以 在 其 中 增 加 自 定 义 的 状 态 在 工 具 栏 中 使 用 按 钮, 可 以 增 加 一 个 状 态, 单 击 上 面 的 空 白 处 可 以 添 加 状 态 的 内 容 例 如 这 里 我 们 增 加 确 认 发 货 和 回 款 三 种 状 态, 如 图 14-19 所 示 图 14-19 增 加 状 态 14.5.3 连 接 状 态 在 状 态 图 中 创 建 状 态 后, 需 要 将 所 有 的 状 态 连 接 起 来, 从 而 知 道 状 态 的 执 行 顺 序 在 工 具 栏 中 使 用 按 钮, 可 以 连 接 两 个 状 态, 在 该 图 标 的 上 面 还 可 以 给 出 状 态 转 换 的 条 件, 如 图 14-20 所 示 图 14-20 连 接 状 态 当 销 售 部 门 确 认 订 单 后, 就 可 以 将 订 单 提 交 给 仓 库 部 分, 如 果 仓 库 中 有 货, 则 订 单 就 进 入 发 货 状 态 用 户 收 到 商 品 后, 支 付 商 品 所 用 的 钱, 则 订 单 就 进 入 回 款 状 态 14.6 活 动 图 活 动 图 是 UML 技 术 中 的 一 个 概 念, 它 和 开 发 中 经 常 说 的 流 程 图 是 非 常 类 似 的 当 接 触 UML 的 读 者 经 常 会 混 淆 状 态 图 和 活 动 图 的 活 动 图 是 指 活 动 间 的 控 制 流, 是 内 部 处 理 驱 动 的 流 程, 而 状 态 图 是 指 某 一 对 象 不 同 状 态 间 的 控 制 流, 主 要 是 由 于 外 部 事 件 驱 动 的 流 程 14.6.1 增 加 动 作 状 态 在 MyEclipse 的 UML 模 型 仓 库 界 面 中, 单 击 工 具 栏 中 第 一 个 按 钮 后 的 倒 三 角, 在 其 中 选 择 New Activity Diagram 选 项, 就 会 切 换 到 状 态 图 开 发 的 工 具 栏

13 在 活 动 图 中 最 基 本 的 就 是 初 态 和 终 态, 它 们 是 和 状 态 图 中 的 开 始 状 态 和 终 止 状 态 非 常 相 似 的, 这 里 就 不 多 介 绍, 我 们 直 接 学 习 如 何 增 加 动 作 状 态 在 活 动 图 工 具 栏 中, 使 用 按 钮 可 以 增 加 一 个 动 作 状 态, 双 击 其 中 的 空 白 处 可 以 填 写 状 态 内 容, 这 里 以 登 录 为 例, 如 图 14-21 所 示 图 14-21 增 加 动 作 状 态 这 里 增 加 了 两 个 动 作 状 态, 首 先 进 入 输 入 信 息 页 面, 执 行 该 动 作 输 入 信 息 正 确, 就 会 执 行 登 录 成 功 的 动 作 14.6.2 增 加 分 支 结 构 通 常 活 动 图 中 动 作 状 态 的 切 换 并 不 是 一 帆 风 顺 的, 例 如 输 入 登 录 所 用 的 信 息, 当 输 入 正 确 时 将 进 入 登 录 成 功 动 作 状 态 ; 但 是 当 输 入 不 正 确 时, 就 不 能 继 续 下 面 的 状 态, 这 种 情 况 下 就 需 要 增 加 一 个 分 支 结 构 在 活 动 图 工 具 栏 中, 使 用 按 钮, 可 以 创 建 增 加 一 个 分 支 结 构, 例 如 这 里 我 们 增 加 一 个 对 输 入 信 息 进 行 判 断 的 分 值 结 构, 如 图 14-22 所 示

图 14-22 增 加 分 支 其 中 菱 形 就 表 示 分 支 结 构, 通 常 并 不 在 其 中 输 入 任 何 内 容 在 分 支 结 构 上 最 少 定 义 两 个 继 续 的 动 作 状 态, 根 据 不 同 的 结 果, 进 入 不 同 的 动 作 状 态 在 上 图 中, 不 但 定 义 了 分 支 结 构, 还 将 动 作 状 态 和 分 支 结 构 之 间 使 用 实 线 箭 头 连 接 起 来, 从 而 组 成 一 个 简 单 的 活 动 图 14.7 时 序 图 时 序 图 在 有 些 地 方 也 被 称 为 序 列 图, 它 是 一 种 以 时 间 为 序 来 描 述 对 象 之 间 传 递 消 息 在 开 发 中, 通 过 时 序 图 能 够 很 好 的 描 述 程 序 的 执 行, 在 框 架 开 发 中 尤 其 重 要 时 序 图 中 包 含 4 个 元 素, 分 别 是 对 象 生 命 线 消 息 和 激 活 14.7.1 创 建 时 序 图 对 象 在 MyEclipse 的 UML 模 型 仓 库 界 面 中, 单 击 工 具 栏 中 第 一 个 按 钮 后 的 倒 三 角, 在 其 中 选 择 New Sequence Diagram 选 项, 就 会 切 换 到 时 序 图 开 发 的 工 具 栏 时 序 图 对 象 时 时 序 图 中 最 重 要 的 组 成 部 分 在 其 中 使 用 按 钮, 可 以 创 建 时 序 图 对 象, 单 击 矩 形 其 中 的 空 白 处 就 可 以 添 加 对 象 名 称, 例 如 这 里 我 们 创 建 用 户 和 评 论 两 个 对 象, 如 图 14-23 所 示

15 图 14-23 创 建 对 象 从 图 中 可 以 看 到 创 建 了 两 个 对 象, 在 这 两 个 对 象 之 间 就 可 以 完 成 一 些 操 作, 例 如 发 表 评 论, 查 看 评 论 等 14.7.2 添 加 消 息 时 序 图 中 的 消 息 就 是 对 象 间 的 通 信, 一 个 对 象 可 以 请 求 另 一 个 对 象 做 某 操 作 在 工 具 栏 中, 使 用 按 钮 可 以 创 建 时 序 图 中 的 消 息, 这 里 我 们 就 添 加 一 个 发 表 评 论 的 消 息, 如 图 14-24 所 示 图 14-24 添 加 消 息 添 加 消 息 后, 则 对 象 下 面 的 生 命 线 将 被 激 活 在 消 息 实 现 箭 头 上 可 以 添 加 具 体 消 息 的 内 容, 也 就 是 具 体 的 两 个 对 象 间 的 操 作

北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 第 15 章 团 队 开 发 新 闻 发 布 系 统 在 前 面 的 讲 解 中, 我 们 已 经 了 解 了 MyEclipse 在 开 发 中 的 重 要 功 能, 在 本 章 中 将 通 过 一 个 综 合 案 例, 再 来 全 面 的 认 识 MyEclipse 这 一 款 开 发 工 具 在 当 前 项 目 开 发 中, 通 常 都 是 采 用 团 队 开 发 的 方 式, 让 每 一 组 或 者 一 位 开 发 人 员 完 成 某 一 模 块 或 者 层 的 开 发 在 本 章 的 讲 解 中 就 来 模 拟 一 下 如 何 在 MyEclipse 开 发 工 具 中 使 用 Struts2+Spring+Hibernate 框 架 技 术 进 行 模 拟 开 发 15.1 系 统 分 析 和 设 计 在 本 章 中 将 开 发 一 个 新 闻 发 布 系 统, 在 进 行 开 发 之 前, 要 首 先 确 定 在 该 系 统 中 应 该 开 发 哪 些 功 能, 以 及 系 统 的 性 能 效 率 等 问 题 15.1.1 需 求 分 析 一 个 新 闻 发 布 系 统, 必 须 由 两 部 分 组 成, 分 别 是 系 统 前 台 和 系 统 后 台 其 中 系 统 后 台 供 新 闻 工 作 者 使 用, 用 来 管 理 版 面 和 新 闻, 其 中 管 理 板 块 包 括 新 增 版 面 对 已 经 板 块 进 行 修 改 以 及 删 除 指 定 板 块 ; 管 理 新 闻 包 括 发 布 新 闻 浏 览 当 前 所 有 新 闻 和 删 除 新 闻 系 统 前 台 供 所 有 网 友 使 用, 由 用 户 自 行 选 择 感 兴 趣 的 版 面, 然 后 选 择 感 兴 趣 的 新 闻 15.1.2 功 能 分 析 新 闻 发 布 系 统 分 为 前 台 和 后 台 两 个 部 分, 其 中 前 台 是 一 个 公 共 的 平 台, 所 有 的 系 统 访 问 者 都 可 以 使 用 不 过 对 于 新 闻 发 布 系 统 的 后 台, 则 只 提 供 给 特 定 的 用 户, 这 里 主 要 指 新 闻 工 作 者 和 管 理 员 在 该 系 统 中 根 据 权 限 将 用 户 分 成 三 种 角 色, 分 别 为 普 通 用 户 新 闻 工 作 者 和 管 理 员 对 于 普 通 用 户, 只 能 进 入 新 闻 发 布 系 统 的 前 台, 可 以 选 择 自 己 感 兴 趣 的 新 闻 版 面 和 新 闻, 并 翻 阅 先 问 内 容 对 于 新 闻 工 作 者, 除 了 具 有 普 通 用 户 的 所 有 功 能 外, 还 可 以 进 入 新 闻 发 布 系 统 的 后 台 并 对 系 统 的 版 面 进 行 管 理, 包 括 新 增 版 面 查 看 已 有 版 面 编 辑 版 面 和 删 除 版 面 还 可 以 对 新 闻 进 行 管 理, 包 括 发 布 新 闻 浏 览 新 闻 和 删 除 新 闻 对 于 管 理 员, 除 了 拥 有 新 闻 工 作 者 的 所 有 功 能 外, 还 可 以 对 系 统 用 户 进 行 管 理, 包 括 新 增 用 户 更 新 用 户 浏 览 所 有 用 户 和 删 除 指 定 用 户 15.1.3 绘 制 UML 用 例 图 确 定 系 统 功 能 从 前 面 的 系 统 分 析 中 知 道 论 坛 系 统 一 共 包 含 三 种 用 户 角 色, 分 别 普 通 用 户 新 闻 工 作 者 和 系 统 管 理 员 下 面 就 来 分 析 这 三 个 角 色 所 对 应 的 用 例 图

普 通 用 户 仅 仅 能 选 择 指 定 版 面 和 查 看 指 定 新 闻, 其 用 例 图 如 图 20-1 所 示 图 15-1 普 通 用 户 用 例 图 新 闻 工 作 者 除 了 拥 有 普 通 用 户 的 所 有 功 能 外, 还 可 以 对 版 面 和 新 闻 进 行 管 理, 其 用 例 图 如 图 20-2 所 示 图 15-2 新 闻 工 作 者 用 例 图 管 理 员 拥 有 了 新 闻 工 作 者 的 全 部 功 能, 还 可 以 对 所 有 的 用 户 进 行 统 一 管 理, 包 括 新 增 用 户 修 改 用 户 删 除 用 户 以 及 查 看 所 有 用 户 其 用 例 图 如 图 20-3 所 示 图 15-3 管 理 员 用 例 图 15.1.4 绘 制 系 统 流 程 图 普 通 用 户 进 入 本 系 统 后, 将 首 先 打 开 系 统 首 页 在 系 统 首 页 中, 用 户 可 以 选 择 自 己 喜 欢 的 版 块, 选 择 指 定 板 块 后 将 显 示 该 板 块 的 所 有 新 闻 对 于 新 闻 工 作 者 和 管 理 员 可 以 进 入 系 统 后 台, 在 系 统 后 台 中 可 以 对 用 户 版 面 新 闻 进 行 管 理 系 统 流 程 图 如 图 20-4

3 所 示 系 统 首 页 浏 览 版 面 查 看 新 闻 进 入 后 台 管 理 否 是 否 合 法 是 是 否 为 管 理 员 是 不 是 管 理 员 新 闻 工 作 者 用 户 管 理 版 面 管 理 新 闻 管 理 图 15-4 系 统 流 程 图 15.2 DBA 团 队 分 析 和 设 计 数 据 库 DBA 是 数 据 库 管 理 员 的 英 文 缩 写 当 开 发 人 员 完 成 系 统 的 设 计 后, 就 需 要 DBA 来 创 建 数 据 库 存 储 结 构 和 数 据 库 对 象 DBA 将 根 据 系 统 设 计 分 析 采 用 何 种 数 据 库 和 创 建 什 么 数 据 表 在 本 书 中,DBA 就 采 用 MySQL 数 据 库 和 MyEclipse 来 开 发 数 据 库 15.2.1 数 据 库 逻 辑 结 构 设 计 在 前 面 的 需 求 和 功 能 分 析 中, 我 们 可 以 分 析 出 在 数 据 库 中 应 该 创 建 用 户 数 据 表 版 面 数 据 表 和 新 闻 数 据 表 接 下 来 就 是 确 定 每 一 个 数 据 表 的 逻 辑 结 构 用 户 数 据 表 用 来 保 存 用 户 的 信 息, 包 括 用 户 编 号 用 户 名 密 码 该 表 的 逻 辑 结 果 如 表 15.1 所 示 表 15.1 用 户 数 据 表 字 段 名 数 据 类 型 是 否 主 键 描 述 userid 整 数 (int) 是 用 户 编 号 username 文 本 (varchar) 否 用 户 名 password 文 本 (varchar) 否 登 录 密 码 版 面 表 用 来 保 存 版 面 信 息, 包 括 版 面 编 号 版 面 名 称 版 面 描 述 版 面 是 否 审 核 该 表 的 逻 辑 结 果 如 表 15.2 所 示 表 15.2 版 面 数 据 表 字 段 名 数 据 类 型 是 否 主 键 描 述 moduleid 整 数 (int) 是 版 面 编 号 modulename 文 本 (varchar) 否 版 面 名 称

moduledescription 文 本 (varchar) 否 版 面 描 述 auditing 整 数 (binary) 否 是 否 审 核 新 闻 表 用 来 保 存 新 闻 信 息, 包 括 新 闻 编 号 新 闻 标 题 新 闻 内 容 新 闻 作 者 新 闻 发 表 时 间 新 闻 关 键 字 新 闻 来 源, 所 属 版 面 编 号, 该 表 的 逻 辑 结 果 如 表 15.3 所 示 表 15.3 新 闻 数 据 表 字 段 名 数 据 类 型 是 否 主 键 描 述 newsid 整 数 (int) 是 新 闻 编 号 newstitle 文 本 (varchar) 否 新 闻 标 题 newscontent 文 本 (text) 否 新 闻 内 容 newsauthor 文 本 (varchar) 否 新 闻 作 者 publishddate 日 期 否 新 闻 发 表 时 间 newskey 文 本 (varchar) 否 新 闻 关 键 字 origin 文 本 (varchar) 否 新 闻 来 源 module 整 数 (int) 外 键 所 属 版 面 编 号 15.2.2 创 建 数 据 库 和 数 据 表 确 定 使 用 MySQL 数 据 库 和 分 析 确 定 每 一 数 据 表 的 逻 辑 结 构 后, 就 可 以 进 入 MyEclipse 的 数 据 库 视 图 进 行 数 据 库 的 开 发 打 开 MySQL 连 接, 在 Connected to MySQL 节 点 上, 单 击 鼠 标 右 键, 在 菜 单 中 选 择 Create database 命 令, 在 弹 出 的 创 建 数 据 库 界 面 中 填 写 相 关 信 息 后, 如 图 15-5 所 示 图 15-5 创 建 数 据 库 单 击 Finish 按 钮, 将 完 成 数 据 库 的 创 建 选 中 db_myeclipse_news 数 据 库 节 点, 单 击 鼠 标 右 键, 选 择 New Table 命 令, 将 弹 出 创 建 数 据 表 界 面 通 过 该 界 面, 依 次 创 建 用 户 版 面 和 新 闻 数 据 表 先 来 创 建 用 户 数 据 表, 它 的 创 建 数 据 表 界 面 如 图 15-6 所 示

5 图 15-6 创 建 用 户 数 据 表 单 击 Finish 按 钮, 将 完 成 用 户 数 据 表 的 创 建 使 用 同 样 的 创 建 方 法, 继 续 创 建 版 面 数 据 表, 它 的 创 建 数 据 表 界 面 如 图 15-7 所 示 图 15-7 创 建 版 面 数 据 表 单 击 Finish 按 钮, 将 完 成 版 面 数 据 表 的 创 建 在 每 一 版 面 下 面 都 将 有 多 条 新 闻 信 息, 新 闻 实 体 也 是 本 章 新 闻 发 布 系 统 的 核 心, 所 以 新 闻 数 据 表 的 创 建 也 是 相 对 复 杂 的, 它 的 创 建 数 据 表 界 面 如 图 15-8 所 示

图 15-8 创 建 新 闻 数 据 表 单 击 Finish 按 钮, 将 完 成 新 闻 数 据 表 的 创 建 到 这 里 DBA 将 完 成 数 据 库 的 分 析 和 设 计, 从 而 将 创 建 后 的 数 据 库 将 给 开 发 人 员 开 发 人 员 将 根 据 系 统 设 计 和 数 据 库 进 行 程 序 的 开 发 15.3 项 目 经 理 配 置 版 本 控 制 服 务 器 因 为 我 们 采 用 的 是 团 队 开 发 的 形 式 进 行 开 发, 所 以 所 有 的 程 序 并 不 是 开 发 在 一 台 计 算 机 中, 这 时 候 就 需 要 使 用 到 版 本 控 制 服 务 器 在 前 面 的 讲 解 中, 我 们 了 解 了 CVS 和 SVN 这 两 种 版 本 控 制 服 务 器, 它 们 的 操 作 是 类 似 的, 这 里 我 们 就 采 用 MyEclipse 中 集 成 的 CVS 版 本 控 制 服 务 器 使 用 CVS 版 本 控 制 服 务 器 时, 首 先 就 需 要 由 项 目 经 理 在 公 司 的 主 机 上 建 立 和 配 置 版 本 控 制 服 务 器, 团 队 中 开 发 的 所 有 程 序 都 将 提 交 到 该 服 务 器 在 前 面 章 节 中 已 经 学 习 了 如 何 下 载 和 安 装 CVS 服 务 器, 这 里 我 们 就 不 再 重 复, 重 点 讲 解 如 何 配 置 版 本 控 制 服 务 器 安 装 后, 在 系 统 开 始 菜 单 中, 选 择 程 序 CVSNT CVSNT Control Panel 命 令, 将 弹 出 配 置 CVS 服 务 器 的 界 面 在 其 中 选 择 Repository configuration 选 项 卡, 将 进 入 到 服 务 器 库 的 界 面 单 击 Add 按 钮, 将 进 入 到 服 务 配 置 界 面, 在 其 中 输 入 相 关 信 息 后, 界 面 如 图 15-9 所 示

7 图 15-9 服 务 配 置 界 面 在 其 中 Location 选 项 中 选 择 的 是 E 盘 下 的 NEWS 目 录, 从 而 团 队 中 开 发 的 所 有 程 序 都 可 以 提 交 到 该 目 录 中 配 置 版 本 控 制 服 务 器 还 有 其 他 一 些 选 项, 读 者 可 以 自 己 参 考 前 面 的 章 节 进 行 学 习 15.4 开 发 数 据 访 问 层 在 前 面 的 讲 解 中, 我 们 已 经 多 次 提 到 Web 项 目 开 发 的 分 层 思 想, 通 常 将 整 个 项 目 分 为 表 现 层 控 制 层 业 务 逻 辑 层 和 数 据 访 问 层 每 一 层 完 成 特 定 的 工 作, 在 开 发 中, 可 能 一 位 开 发 人 员 完 成 其 中 一 层 的 开 发, 从 而 就 需 要 每 一 位 开 发 人 员 创 建 一 个 项 目 具 体 项 目 开 发 环 境 的 搭 建, 这 里 就 不 再 重 复, 可 以 前 面 知 识 点 的 讲 解 全 部 开 发 完 成 后 将 它 们 整 合 在 一 起, 从 而 完 成 项 目 的 开 发 我 们 首 先 在 本 节 中 开 发 数 据 访 问 层, 创 建 一 个 项 目 名 称 为 NEWS_dao 的 项 目 15.4.1 生 成 数 据 访 问 层 程 序 使 用 MyEclipse 开 发 工 具 中 集 成 的 Hibernate 框 架 技 术 能 够 非 常 方 便 的 开 发 数 据 访 问 层 程 序 并 且 在 本 章 中 采 用 Spring+Hibernate 框 架 整 合 的 技 术 开 发, 所 以 应 该 选 择 Spring DAO 选 项 当 然 在 MyEclipse 的 数 据 库 视 图 中, 选 中 MySQL Connection to MySQL db_myeclipse_news TABLE user 试 题 数 据 表 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Hibernate Reverse Engineering 命 令, 将 弹 出 创 建 Hibernate 程 序 的 界 面, 在 其 中 选 择 创 建 实 体 类 映 射 文 件 和 DAO 程 序, 如 图 15-9 所 示

图 15-9 创 建 用 户 数 据 访 问 层 单 击 Finish 按 钮, 将 完 成 用 户 相 关 的 实 体 类 映 射 文 件 和 DAO 实 体 类 程 序 的 创 建 创 建 DAO 程 序 后, 要 进 行 抽 取 接 口 的 操 作 在 包 资 源 管 理 器 中, 选 中 UserDAO 类 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Refactor Extract Interface 命 令, 将 弹 出 抽 取 接 口 界 面, 在 其 中 输 入 接 口 名 为 IUserDAO, 然 后 将 其 中 的 所 有 方 法 选 中, 界 面 如 图 15-10 所 示 图 15-10 抽 取 接 口 单 击 OK 按 钮, 将 完 成 用 户 DAO 接 口 的 抽 取 操 作 使 用 同 样 的 操 作 步 骤, 依 次 完 成 版 面 DAO 接 口 和 新 闻 DAO 接 口 的 抽 取 操 作

9 15.4.2 提 交 到 版 本 控 制 服 务 器 开 发 完 程 序 后, 通 常 需 要 程 序 员 自 己 完 成 单 元 测 试, 但 是 由 于 数 据 访 问 层 程 序 完 全 是 由 MyEclipse 自 动 生 成 的, 从 而 可 以 省 略 该 操 作 为 了 让 团 队 中 其 他 程 序 员 使 用 开 发 的 数 据 访 问 层, 需 要 将 这 些 程 序 提 交 到 CVS 版 本 控 制 服 务 器 中 提 交 程 序 到 版 本 控 制 服 务 器 中, 首 先 第 一 步 就 需 要 和 服 务 器 建 立 连 接 将 MyEclipse 的 透 视 图 切 换 到 CVS Repository Exploring CVS 服 务 器 视 图 中, 然 后 在 CVS Repositories 视 图 界 面 的 空 白 处, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Repository Location 命 令, 将 弹 出 添 加 CVS 资 源 库 的 界 面, 在 其 中 输 入 相 关 信 息 后, 界 面 如 图 15-11 所 示 图 15-11 建 立 服 务 器 连 接 其 中 Host 选 项 就 是 填 写 的 公 司 主 机 的 IP 地 址, Repository path 表 示 资 源 库 的 路 径, 也 就 是 我 们 在 配 置 CVS 服 务 器 时 配 置 的, 这 里 填 写 /NEWS 单 击 Finish 按 钮, 将 完 成 CVS 服 务 器 的 连 接, 从 而 在 CVS Repositories 视 图 界 面 多 出 一 个 资 源 库 和 服 务 器 建 立 连 接 后, 就 可 以 将 开 发 的 程 序 提 交 到 服 务 器 中 第 一 次 提 交 是 比 较 复 杂 的, 需 要 向 进 行 共 享 操 作 在 MyEclipse 中, 切 换 到 普 通 透 视 图 后, 在 包 资 源 管 理 器 中 选 中 要 提 交 的 项 目 单 击 鼠 标 右 键, 在 弹 出 菜 单 中 选 择 Team Share Project 命 令, 将 弹 出 选 择 资 源 库 的 界 面, 如 图 15-12 所 示

图 15-12 选 择 资 源 库 在 其 中 选 择 /NEWS 资 源 库 单 击 Next 按 钮, 将 弹 出 设 置 提 交 后 名 称 的 界 面, 如 图 15-13 所 示 图 15-13 设 置 名 称 在 其 中 选 择 Use project name module name 选 项, 它 表 示 使 用 项 目 的 名 称 做 为 提 交 后 名 称 单 击 Next 按 钮, 将 弹 出 共 享 项 目 资 源 界 面, 在 其 中 选 中 了 Launch the Commit wizard 复 选 框 后 单 击 Finish 按 钮, 将 完 成 共 享 操 作, 并 弹 出 提 交 项 目 界 面

11 在 该 界 面 中 输 入 输 入 注 释 和 描 述 后, 界 面 如 图 15-14 所 示 图 15-14 添 加 注 释 和 描 述 单 击 Finish 按 钮, 将 完 成 项 目 的 第 一 次 提 交 当 程 序 发 生 改 变 后, 再 次 提 交 将 变 的 容 易 在 包 资 源 管 理 器 中, 选 中 被 修 改 的 程 序 节 点 或 者 选 中 项 目 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Team Commit 命 令, 将 弹 出 提 交 文 件 界 面, 在 其 中 再 次 输 入 提 交 描 述 后, 单 击 Finish 按 钮, 将 完 成 提 交 文 件 的 操 作 15.5 开 发 业 务 逻 辑 层 当 不 是 团 队 开 发 时, 业 务 逻 辑 层 通 常 放 在 数 据 访 问 层 后 开 发 但 是 在 团 队 开 发 中, 这 两 层 可 能 同 时 进 行, 也 可 能 是 按 照 前 面 的 顺 序 业 务 逻 辑 层 开 发 人 员, 从 版 本 控 制 服 务 器 中 检 出 数 据 访 问 层 程 序 后, 进 行 开 发 不 过 业 务 逻 辑 层 开 发 人 员 也 可 以 自 己 先 开 发 一 个 空 的 数 据 访 问 层 程 序, 等 到 数 据 访 问 层 开 发 完 成 后, 直 接 进 行 替 换 15.5.1 检 出 数 据 访 问 层 程 序 同 时 开 发 两 层 并 没 有 什 么 难 点 的, 只 要 两 组 人 员 间 将 程 序 和 方 法 的 名 称 统 一 好 就 可 以 在 本 章 中 我 们 重 点 来 看 一 下 相 继 开 发 的 方 式, 该 方 式 是 建 立 在 检 出 版 本 控 制 服 务 器 中 的 程 序 为 基 础 的 在 MyEclipse 中, 切 换 到 CVS 操 作 透 视 图 中 后, 在 CVS Repositories 视 图 界 面 中 选 中 要 检 出 的 项 目, 例 如 这 里 选 择 前 面 操 作 上 传 的 NEWS_dao 项 目 单 击 鼠 标 右

键, 在 弹 出 的 菜 单 中 选 择 Check Out As 命 令, 将 弹 出 修 改 检 出 项 目 名 称 的 界 面, 在 其 中 修 改 项 目 的 名 称 为 NEWS_service 其 他 检 出 操 作 见 前 面 知 识 点 章 节, 这 里 就 不 再 重 复 给 出 15.5.2 开 发 用 户 业 务 逻 辑 层 在 新 闻 发 布 系 统 中, 用 户 的 主 要 作 用 是 发 布 新 闻, 而 这 部 分 用 户 不 是 通 过 注 册 定 义 了, 这 是 由 后 台 管 理 人 员 进 行 分 配 所 以 在 后 台 管 理 中, 要 有 对 系 统 用 户 的 管 理, 这 也 是 本 节 将 要 讲 解 的 系 统 用 户 管 理 模 块 在 新 闻 发 布 系 统 中, 系 统 用 户 管 理 模 块 中 包 括 新 增 用 户 浏 览 用 户 修 改 用 户 和 删 除 用 户 等 功 能, 这 些 功 能 也 就 是 需 要 在 用 户 业 务 逻 辑 层 中 开 发 的 方 法 因 为 在 本 章 的 新 闻 发 布 系 统 中 将 使 用 到 Spring 框 架, 所 以 我 们 将 在 业 务 逻 辑 层 中 将 数 据 访 问 层 对 象 注 入, 其 具 体 代 码 如 下 所 示 : 01 package com.news.service; 02 import com.news.dao.iuserdao; 03 import com.news.dao.user; 04 import com.news.util.page; 05 import com.news.util.pageutil; 06 import com.news.util.result; 07 public class UserServiceImpl{ 08 private IUserDAO userdao; 09 public void setiuserdao(iuserdao userdao) { 10 this.userdao = userdao; 11 } 12 public boolean adduser(user user) { 13 String username = user.getusername();// 获 得 用 户 名 14 if(userdao.findbyusername(username) == null) {// 用 户 名 没 有 被 占 用 15 userdao.save(user);// 保 存 用 户 16 return true; // 保 存 成 功 17 }else{ 18 return false; // 保 存 失 败 19 } 20 } 21 public Result findalluser(page page) { 22 page = PageUtil.createPage(page, userdao.findall().size()); 23 Result result = new Result(); 24 result.setlist(userdao.findall()); 25 result.setpage(page); 26 return result; 27 } 28 public boolean deleteuser(string username) { 29 User user = (User)userDAO.findByUsername(username).get(0); 30 if(user == null) {// 不 存 在 该 用 户 31 return false; // 删 除 失 败

13 32 }else{ 33 userdao.delete(user); 34 return true; // 删 除 成 功 35 } 36 } 37 public boolean updateuser(user user) { 38 User queryuser 39 =(User)userDAO.findByUsername(user.getUsername()).get(0); 40 if(queryuser == null) {// 不 存 在 该 用 户 41 return false; // 更 新 失 败 42 }else{ 43 user.setuserid(queryuser.getuserid());// 设 置 用 户 ID 44 userdao.attachdirty(user); 45 return true; // 更 新 成 功 46 } 47 } 48 } 上 述 代 码 中 第 8 行 定 义 了 用 户 数 据 访 问 层 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 通 过 这 种 方 式 将 用 户 数 据 访 问 层 实 现 类 对 象 注 入 在 后 面 的 代 码 中 依 次 定 义 了 新 增 用 户 浏 览 用 户 删 除 用 户 和 更 新 用 户 的 业 务 方 法 开 发 完 用 户 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 用 户 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 15-15 所 示 图 15-15 抽 取 用 户 业 务 逻 辑 接 口 单 击 OK 按 钮, 将 完 成 用 户 业 务 逻 辑 接 口 的 抽 取 开 发 完 用 户 业 务 逻 辑 实 现 类 后, 要 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 15-16 所 示

图 15-16 配 置 用 户 业 务 逻 辑 类 单 击 Finish 按 钮, 将 完 成 用 户 业 务 逻 辑 实 现 类 的 Spring 配 置, 将 用 户 数 据 访 问 层 实 现 类 对 象 注 入 到 其 中 15.5.3 对 用 户 业 务 逻 辑 类 进 行 单 元 测 试 开 发 完 用 户 业 务 逻 辑 层 程 序 后, 是 不 能 直 接 运 行 项 目 的, 但 是 为 了 保 证 控 制 层 开 发 的 正 确 性, 业 务 逻 辑 层 程 序 开 发 人 员 需 要 完 成 对 程 序 的 单 元 测 试, 从 而 保 证 程 序 的 正 确 性 首 先 我 们 需 要 将 JUnit 单 元 测 试 所 需 要 的 JAR 包 导 入 到 项 目 中, 然 后 创 建 一 个 用 户 业 务 逻 辑 层 的 测 试 程 序, 创 建 JUnit 程 序 的 界 面 如 图 15-17 所 示

15 图 15-17 创 建 JUnit 程 序 单 击 Next 按 钮, 将 进 入 选 择 测 试 方 法 的 界 面, 在 其 中 选 择 用 户 业 务 逻 辑 类 中 的 业 务 方 法, 如 图 15-18 所 示 图 15-18 选 择 业 务 方 法 单 击 Finish 按 钮, 将 自 动 生 成 代 码 这 是 在 提 前 导 入 JUnit 单 元 测 试 JAR 包 的

前 提 下, 如 果 没 有 导 入, 将 进 入 添 加 JAR 包 的 界 面 在 生 成 的 代 码 中 加 入 测 试 的 程 序, 代 码 如 下 所 示 : 01 package com.news.service.test; 02 import static org.junit.assert.*; 03 import org.junit.test; 04 import org.springframework.beans.factory.beanfactory; 05 import org.springframework.context.support.classpathxmlapplicationcontext; 06 import com.news.dao.user; 07 import com.news.service.userserviceimpl; 08 public class UserServiceImplTest { 09 @Test 10 public void testadduser() { 11 User user=new User(); 12 user.setuserid(1); 13 user.setusername("admin"); 14 user.setpassword("admin"); 15 BeanFactory factory = 16 new ClassPathXmlApplicationContext("applicationContext.xml"); 17 UserServiceImpl userserviceimpl=(userserviceimpl) 18 factory.getbean("userserviceimpl"); // 获 取 数 据 访 问 接 口 19 boolean b=userserviceimpl.adduser(user); 20 asserttrue(b); 21 } 22 @Test 23 public void testfindalluser() { 24 } 25 @Test 26 public void testdeleteuser() { 27 User user=new User(); 28 user.setuserid(1); 29 user.setusername("admin"); 30 user.setpassword("admin"); 31 BeanFactory factory = 32 new ClassPathXmlApplicationContext("applicationContext.xml"); 33 UserServiceImpl userserviceimpl=(userserviceimpl) 34 factory.getbean("userserviceimpl"); // 获 取 数 据 访 问 接 口 35 boolean b=userserviceimpl.deleteuser(user.getusername()); 36 asserttrue(b); 37 } 38 @Test 39 public void testupdateuser() { 40 User user=new User(); 41 user.setuserid(1); 42 user.setusername("admin"); 43 user.setpassword("admin");

17 44 BeanFactory factory = 45 new ClassPathXmlApplicationContext("applicationContext.xml"); 46 UserServiceImpl userserviceimpl=(userserviceimpl) 47 factory.getbean("userserviceimpl"); // 获 取 数 据 访 问 接 口 48 boolean b=userserviceimpl.updateuser(user); 49 asserttrue(b); 50 } 51 } 上 述 代 码 中 分 别 对 新 增 用 户 删 除 用 户 和 更 新 用 户 进 行 了 测 试, 对 于 查 询 所 有 用 户 来 说 是 没 有 测 试 的 必 要 的 在 测 试 方 法 中 是 不 能 够 直 接 通 过 new 来 创 建 业 务 逻 辑 对 象 的, 这 是 因 为 在 其 中 使 用 Spring 框 架 将 数 据 访 问 对 象 注 入, 需 要 通 过 实 例 化 Bean 容 器 创 建 对 象 注 意 : 在 实 例 化 Bean 容 器 时, 需 要 使 用 到 Spring 的 配 置 文 件, 也 就 是 applicationcontext.xml 采 用 这 种 方 式 实 例, 必 须 将 它 拷 贝 到 src 目 录 下 一 份, 不 然 是 不 能 够 实 例 成 功 的 15.5.4 开 发 版 面 业 务 逻 辑 层 在 新 闻 发 布 系 统 中, 很 重 要 的 一 个 组 成 元 素 就 是 版 面, 通 过 使 用 版 面 可 以 将 新 闻 进 行 分 类 例 如 娱 乐 新 闻 体 育 新 闻 等 在 版 面 管 理 中, 包 括 创 建 新 版 面 浏 览 目 前 所 有 版 面 更 新 版 面 和 删 除 版 面 等 操 作, 所 以 在 版 面 业 务 逻 辑 层 中 需 要 创 建 对 应 的 业 务 方 法, 其 程 序 代 码 如 下 所 示 : 01 package com.news.service; 02 import java.util.list; 03 import com.news.dao.imoduledao; 04 import com.news.dao.module; 05 import com.news.util.page; 06 import com.news.util.pageutil; 07 import com.news.util.result; 08 public class ModuleServiceImpl{ 09 private IModuleDAO moduledao; 10 public void setmoduledao(imoduledao moduledao) { 11 this.moduledao = moduledao; 12 } 13 public boolean addmodule(module module) { 14 String modulename = module.getmodulename();// 获 得 版 面 名 称 15 if(moduledao.findbymodulename(modulename).size() == 0) {// 没 有 被 占 用 16 moduledao.save(module);// 保 存 版 面 17 return true; // 保 存 成 功 18 }else{ 19 return false; // 保 存 失 败 20 } 21 }

22 public boolean deleteitembymoduleid(int moduleid) { 23 Module module = moduledao.findbyid(moduleid); 24 if(module == null) {// 不 存 在 该 版 面 25 return false; // 删 除 失 败 26 }else{ 27 moduledao.delete(module); 28 return true; // 删 除 成 功 29 } 30 } 31 public Result findallmodule(page page) { 32 page = PageUtil.createPage(page, moduledao.findall().size()); 33 Result result = new Result(); 34 result.setlist(moduledao.findall()); 35 result.setpage(page); 36 return result; 37 } 38 public boolean updatemodule(module module) { 39 Module querymodule = moduledao.findbyid(module.getmoduleid()); 40 if(querymodule == null) {// 不 存 在 该 版 面 41 return false; // 更 新 失 败 42 }else{ 43 moduledao.attachdirty(module); 44 return true; // 更 新 成 功 45 } 46 } 47 public Module findmodule(int moduleid) { 48 return moduledao.findbyid(moduleid); 49 } 50 public List<Module> findallmodule() { 51 return moduledao.findall(); 52 } 53 } 上 述 代 码 中 第 9 行 定 义 了 版 面 数 据 访 问 接 口 引 用, 并 为 它 定 义 了 Setter 方 法, 从 而 将 版 面 数 据 访 问 类 对 象 注 入 在 后 面 的 程 序 中, 依 次 定 义 了 新 增 版 面 删 除 版 面 查 询 所 有 版 面 更 新 版 面 和 查 找 指 定 版 面 的 业 务 方 法 开 发 完 版 面 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 版 面 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 15-19 所 示

19 图 15-19 抽 取 版 面 业 务 逻 辑 接 口 单 击 OK 按 钮, 将 完 成 版 面 业 务 逻 辑 接 口 的 抽 取 开 发 完 版 面 业 务 逻 辑 实 现 类 后, 要 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 15-20 所 示 图 15-20 配 置 版 面 业 务 逻 辑 类 单 击 Finish 按 钮, 将 完 成 版 面 业 务 逻 辑 实 现 类 的 Spring 配 置, 将 版 面 数 据 访 问 层 实 现 类 对 象 注 入 到 其 中

15.5.5 对 版 面 业 务 逻 辑 类 进 行 单 元 测 试 开 发 完 版 面 业 务 逻 辑 层 程 序 后, 同 样 也 需 要 对 它 进 行 测 试 创 建 测 试 程 序 的 步 骤 这 里 就 不 再 给 出, 它 的 具 体 代 码 如 下 所 示 : 01 package com.news.service.test; 02 import static org.junit.assert.*; 03 import org.junit.beforeclass; 04 import org.junit.test; 05 import org.springframework.beans.factory.beanfactory; 06 import org.springframework.context.support.classpathxmlapplicationcontext; 07 import com.news.dao.module; 08 import com.news.service.moduleserviceimpl; 09 public class ModuleServiceImplTest { 10 static ModuleServiceImpl moduleserviceimpl=null; 11 @BeforeClass 12 public static void beforeclass() { 13 BeanFactory factory = 14 new ClassPathXmlApplicationContext("applicationContext.xml"); 15 moduleserviceimpl=(moduleserviceimpl) 16 factory.getbean("moduleserviceimpl"); 17 } 18 @Test 19 public void testaddmodule() { 20 Module module=new Module(); 21 module.setmoduleid(1); 22 module.setmodulename(" 国 内 新 闻 "); 23 module.setmoduledescription(" 该 栏 目 刊 登 国 内 新 闻 "); 24 module.setauditing("1"); 25 boolean b=moduleserviceimpl.addmodule(module); 26 asserttrue(b); 27 } 28 @Test 29 public void testdeleteitembymoduleid() { 30 boolean b=moduleserviceimpl.deleteitembymoduleid(1); 31 asserttrue(b); 32 } 33 @Test 34 public void testupdatemodule() { 35 Module module=new Module(); 36 module.setmoduleid(1); 37 module.setmodulename(" 国 内 新 闻 "); 38 module.setmoduledescription(" 该 栏 目 刊 登 国 内 新 闻 "); 39 module.setauditing("0"); 40 boolean b=moduleserviceimpl.updatemodule(module); 41 asserttrue(b);

21 42 } 43 @Test 44 public void testfindmodule() { 45 Module m=moduleserviceimpl.findmodule(1); 46 assertnotnull(m); 47 } 48 } 上 述 对 版 面 业 务 逻 辑 层 进 行 测 试 的 程 序 和 前 面 对 用 户 业 务 逻 辑 类 进 行 测 试 的 程 序 有 所 不 同, 在 其 中 第 12 行 中 定 义 了 类 初 始 化 方 法, 在 该 方 法 中 定 义 了 实 例 化 Spring 的 Bean 容 器 的 代 码, 从 而 完 成 创 建 业 务 逻 辑 类 对 象 的 工 作 在 后 面 的 具 体 测 试 方 法 中, 将 不 用 在 进 行 实 例 化 Bean 容 器 的 工 作, 只 需 要 写 具 体 的 测 试 方 法, 分 别 定 义 了 新 增 版 面 删 除 版 面 更 新 版 面 和 查 找 版 面 方 法 的 测 试 方 法 15.5.6 开 发 新 闻 业 务 逻 辑 层 新 闻 业 务 可 以 说 是 新 闻 发 布 系 统 的 核 心 功 能, 在 新 闻 业 务 逻 辑 层 程 序 中 定 义 了 完 成 发 布 新 闻 浏 览 所 有 新 闻 和 删 除 新 闻 等 功 能, 所 以 要 在 新 闻 业 务 逻 辑 类 中 定 义 相 对 应 的 方 法, 该 程 序 的 具 体 代 码 如 下 所 示 : 01 package com.news.service; 02 import com.news.dao.imoduledao; 03 import com.news.dao.inewsdao; 04 import com.news.dao.module; 05 import com.news.dao.news; 06 import com.news.util.page; 07 import com.news.util.pageutil; 08 import com.news.util.result; 09 public class NewsServiceImpl{ 10 private INewsDAO newsdao; 11 private IModuleDAO moduledao; 12 public void setnewsdao(inewsdao newsdao) { 13 this.newsdao = newsdao; 14 } 15 public void setmoduledao(imoduledao moduledao) { 16 this.moduledao = moduledao; 17 } 18 public boolean addnews(news news) { 19 String newstitle = news.getnewstitle();// 获 得 新 闻 标 题 20 if(newsdao.findbynewstitle(newstitle).size() == 0) {// 没 有 被 占 用 21 Module module = moduledao.findbyid(news.getmodule()); 22 news.setmodule(module.getmoduleid()); 23 newsdao.save(news); // 保 存 新 闻 24 return true; // 保 存 成 功 25 }else{ 26 return false; // 保 存 失 败

27 } 28 } 29 public boolean deleteitembynewsid(int newsid) { 30 News news = newsdao.findbyid(newsid); 31 if(news == null) {// 不 存 在 该 版 面 32 return false; // 删 除 失 败 33 }else{ 34 newsdao.delete(news); 35 return true; // 删 除 成 功 36 } 37 } 38 public Result findallnews(page page) { 39 page = PageUtil.createPage(page, newsdao.findall().size()); 40 Result result = new Result(); 41 result.setlist(newsdao.findall()); 42 result.setpage(page); 43 return result; 44 } 45 public News findnews(int newsid) { 46 return newsdao.findbyid(newsid); 47 } 48 public boolean updatenews(news news) { 49 News querynews = newsdao.findbyid(news.getnewsid()); 50 if(querynews == null) {// 不 存 在 该 版 面 51 return false; // 更 新 失 败 52 }else{ 53 newsdao.attachdirty(news); 54 return true; // 更 新 成 功 55 } 56 } 57 } 上 述 代 码 中 第 10 行 和 第 11 行 分 别 定 义 了 新 闻 数 据 访 问 接 口 引 用 和 版 面 数 据 访 问 接 口 引 用, 并 为 它 们 定 义 了 Setter 方 法, 从 而 将 对 应 的 数 据 访 问 对 象 注 入 然 后 依 次 定 义 了 新 增 新 闻 删 除 新 闻 查 询 所 有 新 闻 查 询 单 个 新 闻 和 更 新 新 闻 的 业 务 方 法, 从 而 完 成 对 应 的 功 能 开 发 完 新 闻 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 新 闻 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 15-20 所 示

23 图 15-20 抽 取 新 闻 业 务 逻 辑 接 口 单 击 OK 按 钮, 将 完 成 新 闻 业 务 逻 辑 接 口 的 抽 取 开 发 完 新 闻 业 务 逻 辑 实 现 类 后, 要 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 15-21 所 示 图 15-21 配 置 版 面 业 务 逻 辑 类 单 击 Finish 按 钮, 将 完 成 新 闻 业 务 逻 辑 实 现 类 的 Spring 配 置, 将 新 闻 数 据 访 问 层 实 现 类 对 象 注 入 到 其 中

15.5.7 对 新 闻 业 务 罗 逻 辑 类 进 行 单 元 测 试 和 前 面 的 两 个 业 务 逻 辑 类 一 样, 开 发 完 程 序 后 都 需 要 编 写 对 应 的 单 元 测 试 程 序, 通 过 该 程 序 完 成 对 程 序 功 能 的 测 试 具 体 测 试 程 序 的 开 发 步 骤 同 样 还 是 不 再 给 出, 主 要 来 看 它 的 具 体 程 序, 代 码 如 下 所 示 : 01 package com.news.service.test; 02 import static org.junit.assert.*; 03 import java.sql.timestamp; 04 import org.junit.beforeclass; 05 import org.junit.test; 06 import org.springframework.beans.factory.beanfactory; 07 import org.springframework.context.support.classpathxmlapplicationcontext; 08 import com.news.dao.news; 09 import com.news.service.newsserviceimpl; 10 public class NewsServiceImplTest { 11 static NewsServiceImpl newsserviceimpl=null; 12 @BeforeClass 13 public static void beforeclass() { 14 BeanFactory factory = 15 new ClassPathXmlApplicationContext("applicationContext.xml"); 16 newsserviceimpl=(newsserviceimpl)factory.getbean("newsserviceimpl"); 17 } 18 @Test 19 public void testaddnews() { 20 News news=new News(); 21 news.setnewsid(1); 22 news.setnewstitle(" 一 年 一 度 的 两 会 召 开 "); 23 news.setnewscontent(" 一 年 一 度 的 两 会 在 北 京 召 开 "); 24 news.setnewsauthor(" 李 磊 "); 25 news.setnewskey(" 两 会 "); 26 news.setorigin(""); 27 news.setpublishddate(new Timestamp(55555)); 28 boolean b=newsserviceimpl.addnews(news); 29 asserttrue(b); 30 } 31 @Test 32 public void testdeleteitembynewsid() { 33 boolean b=newsserviceimpl.deleteitembynewsid(1); 34 asserttrue(b); 35 } 36 @Test 37 public void testfindnews() { 38 News news=newsserviceimpl.findnews(1); 39 assertnotnull(news); 40 }

25 41 @Test 42 public void testupdatenews() { 43 News news=new News(); 44 news.setnewsid(1); 45 news.setnewstitle(" 一 年 一 度 的 两 会 召 开 "); 46 news.setnewscontent(" 一 年 一 度 的 两 会 在 北 京 召 开 "); 47 news.setnewsauthor(" 李 磊 "); 48 news.setnewskey(" 两 会 "); 49 news.setorigin(""); 50 news.setpublishddate(new Timestamp(55555)); 51 boolean b=newsserviceimpl.updatenews(news); 52 asserttrue(b); 53 } 54 } 上 述 代 码 中 同 样 在 第 13 行 定 义 了 类 初 始 化 方 法, 在 该 方 法 中 定 义 了 实 例 化 Spring 的 Bean 容 器 的 代 码, 从 而 完 成 创 建 业 务 逻 辑 类 对 象 的 工 作 在 后 面 的 具 体 测 试 方 法 中, 将 不 用 在 进 行 实 例 化 Bean 容 器 的 工 作, 只 需 要 写 具 体 的 测 试 方 法, 分 别 定 义 了 新 增 新 闻 删 除 新 闻 更 新 新 闻 和 查 找 新 闻 方 法 的 测 试 方 法 15.6 开 发 控 制 层 开 发 完 业 务 逻 辑 层 后, 同 样 也 需 要 将 程 序 提 交 到 版 本 控 制 服 务 器 中, 从 而 共 享 给 其 他 开 发 团 队, 主 要 是 提 供 给 控 制 层 开 发 团 队 在 控 制 层 开 发 团 队 开 发 对 应 程 序 时, 如 果 业 务 逻 辑 层 程 序 已 经 开 发 完 成, 将 从 版 本 控 制 服 务 器 中 检 出 相 应 的 程 序 这 些 操 作 读 者 可 以 参 考 前 面 的 讲 解 学 习, 这 里 就 不 再 给 出 15.6.1 开 发 发 布 新 闻 Action 由 于 本 章 开 发 的 新 闻 发 布 系 统 中 的 功 能 相 对 是 比 较 多 的, 所 以 对 应 处 理 这 里 功 能 的 Action 程 序 也 就 比 较 多 这 里 就 采 用 其 中 最 核 心 的 发 布 新 闻 功 能 来 讲 解 Action 程 序 的 开 发 在 MyEclipse 的 原 始 安 装 中, 并 没 有 集 成 Struts2 框 架, 从 而 也 就 不 存 在 直 接 创 建 Action 的 功 能 在 前 面 的 学 习 中, 已 经 讲 解 了 如 何 通 过 创 建 类 的 方 式 来 创 建 Action 程 序, 这 里 就 不 再 讲 解, 直 接 来 看 它 的 程 序, 其 代 码 如 下 所 示 : 01 package com.news.action; 02 import java.sql.timestamp; 03 import com.news.dao.module; 04 import com.news.dao.news; 05 import com.news.service.newsservice; 06 import com.opensymphony.xwork2.actionsupport; 07 public class NewsAddAction extends ActionSupport { 08 private NewsService newsservice; 09 private String newstitle; // 新 闻 标 题 10 private String newscontent; // 新 闻 内 容

11 private String newsauthor; // 新 闻 作 者 12 private String newskey; // 关 键 字 13 private String origin; // 新 闻 来 源 14 private int module; // 所 属 板 块 15 public void setnewsservice(newsservice newsservice) { 16 this.newsservice = newsservice; 17 } 18 public String getnewstitle() { 19 return newstitle; 20 } 21 public void setnewstitle(string newstitle) { 22 this.newstitle = newstitle; 23 } 24 public String getnewscontent() { 25 return newscontent; 26 } 27 public void setnewscontent(string newscontent) { 28 this.newscontent = newscontent; 29 } 30 public String getnewsauthor() { 31 return newsauthor; 32 } 33 public void setnewsauthor(string newsauthor) { 34 this.newsauthor = newsauthor; 35 } 36 public String getnewskey() { 37 return newskey; 38 } 39 public void setnewskey(string newskey) { 40 this.newskey = newskey; 41 } 42 public String getorigin() { 43 return origin; 44 } 45 public void setorigin(string origin) { 46 this.origin = origin; 47 } 48 public int getmodule() { 49 return module; 50 } 51 public void setmodule(int module) { 52 this.module = module; 53 } 54 public String execute() throws Exception { 55 // 将 所 有 的 参 数 组 合 成 一 个 News 对 象

27 56 News news = new News(); 57 news.setnewsauthor(newsauthor); 58 news.setnewscontent(newscontent); 59 news.setnewskey(newskey); 60 news.setnewstitle(newstitle); 61 news.setorigin(origin); 62 news.setpublishddate(new Timestamp(5555)); 63 Module newmodule = new Module(); 64 newmodule.setmoduleid(module); 65 news.setmodule(module); 66 if(newsservice.addnews(news)){// 保 存 成 功 67 this.addactionmessage(" 添 加 新 闻 成 功!"); 68 }else{ 69 this.addactionmessage(" 新 闻 标 题 已 经 被 占 用, 请 重 新 输 入 "); 70 } 71 return SUCCESS; 72 } 73 } 上 述 代 码 中 第 8 行 定 义 了 新 闻 业 务 逻 辑 接 口 引 用, 并 为 它 在 第 15 行 定 义 了 Setter 方 法, 从 而 将 新 闻 业 务 逻 辑 对 象 注 入 从 第 9 行 到 第 14 行 依 次 定 义 了 新 闻 的 标 题 内 容 作 者 关 键 字 发 表 时 间 和 所 属 版 面 等 属 性, 并 为 这 些 属 性 定 义 了 Setter 和 Getter 方 法, 从 而 能 够 获 取 发 布 新 闻 网 页 中 的 提 交 信 息 在 Action 程 序 中 的 处 理 方 法 中, 首 先 创 建 了 新 闻 对 象, 然 后 将 获 取 到 的 属 性 值 设 置 到 该 对 象 中, 在 第 66 行 中 调 用 新 闻 业 务 接 口 中 的 添 加 新 闻 的 业 务 方 法, 从 而 将 保 存 在 新 闻 对 象 中 的 信 息 提 交 给 后 台 程 序 15.6.2 配 置 Action 程 序 当 使 用 Struts 2+Spring 框 架 开 发 时, 配 置 Action 程 序 是 比 较 繁 琐 的, 不 但 要 在 Spring 的 配 置 文 件 中 进 行 配 置, 还 要 在 Struts 2 的 配 置 文 件 中 进 行 配 置 通 常 首 先 在 Spring 的 配 置 文 件 中 进 行 配 置, 它 的 配 置 界 面 如 图 15-22 所 示

图 15-22 在 Spring 中 配 置 Action 单 击 Finish 按 钮, 将 发 布 新 闻 Action 的 配 置, 并 将 新 闻 业 务 逻 辑 实 现 类 对 象 注 入 进 去 完 成 Spring 配 置 后, 要 在 Struts 2 配 置 文 件 中 进 行 配 置, 它 的 配 置 代 码 为 : 01 <action name="newsadd" class="newsaddaction"> 02 <result name="success" type="chain">publishnewsbefore</result> 03 </action> 其 中 第 1 行 的 class 属 性 指 定 Spring 配 置 文 件 中 的 id 属 性 第 2 行 配 置 了 当 发 布 新 闻 后 跳 转 到 显 示 所 有 新 闻 的 Action 程 序, 该 Action 程 序 以 及 其 他 Action 读 者 可 以 在 光 盘 源 代 码 中 看 到, 这 里 就 不 再 一 一 讲 解 15.7 开 发 表 现 层 并 运 行 系 统 15.7.1 开 发 前 台 表 现 层 除 了 前 面 开 发 的 数 据 访 问 层 业 务 逻 辑 层 和 控 制 层, 一 个 项 目 中 还 应 该 具 有 表 现 层, 也 就 是 前 台 显 示 程 序 这 部 分 程 序 通 常 是 由 专 门 的 前 台 美 工 来 完 成, 在 MyEclipse 中 虽 然 也 集 成 了 前 台 程 序 的 开 发 功 能, 但 是 并 不 优 秀 的, 所 以 这 部 分 程 序 我 们 在 光 盘 中 直 接 给 出, 这 里 就 不 再 详 细 讲 解 15.7.2 运 行 系 统 给 出 表 现 层 程 序 后, 我 们 就 可 以 访 问 我 们 开 发 的 整 个 系 统 了 将 项 目 部 署 到 Tomcat

29 服 务 器 中 后, 启 动 服 务 器 如 果 启 动 时 发 生 错 误, 将 项 目 中 的 asm-x.jar JAR 包 删 除, 因 为 其 中 该 包 重 复 启 动 成 功 后, 打 开 浏 览 器, 在 其 中 输 入 如 下 地 址 : http://localhost:8080/news/goindex.action 运 行 结 果 如 图 15-23 所 示 图 15-23 新 闻 系 统 前 台 首 页 在 该 页 面 中, 单 击 版 面 超 链 接, 将 查 看 该 版 面 中 的 所 有 新 闻 单 击 新 闻 标 题 超 链 接, 可 以 查 看 该 新 闻 的 详 细 信 息 再 次 在 地 址 栏 中 输 入 如 下 地 址 : http://localhost:8080/news/admin/index.jsp 运 行 结 果 如 图 15-24 所 示 图 15-24 新 闻 系 统 后 台 首 页 该 页 面 是 对 新 闻 系 统 进 行 管 理 的 页 面, 其 中 包 括 用 户 管 理 版 面 管 理 和 新 闻 管 理, 通 过 它 们 可 以 完 成 发 布 新 闻 等 日 常 操 作 发 布 新 闻 后, 在 前 台 页 面 中 就 会 看 到 发 布 的 内 容 这 些 操 作 读 者 可 以 自 己 运 行 进 行 演 示