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

Size: px
Start display at page:

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

Transcription

1

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

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

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

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

6 图 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 超 链 接 上 单 击 右 键, 也 可 以 在 弹 出 菜 单 中 选 择 下 载 工 具 进 行 下 载 安 装 JDK 下 载 完 成 后, 就 可 以 安 装 JDK,Windows 操 作 系 统 中 的 JDK 安 装 是 非 常 简 单 的 双 击 下 载 的 jdk-6u17-windows-i586.exe 文 件, 将 首 先 打 开 许 可 证 协 议 确 认 界 面, 在 其 中 单 击 接 受 按 钮, 将 弹 出 自 定 义 安 装 界 面, 如 图 1-4 所 示

7 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 数 据 库 为 例 进 行 讲 解, 其 他 数 据 库 的 操 作 也 是 类 似 的 下 载 MySQL 数 据 库 MySQL 数 据 库 的 官 方 网 站 地 址 为 在 其 中 可 以 单 击 导 航 栏 中 的 Downloads 选 项, 将 进 入 版 本 选 择 页 面 目 前 MySQL 数 据 库 的 最 新 版 本 为 5.4 版 本, 但 是 还 是 测 试 版 本, 所 以 这 里 我 们 选 择 5.1 版 本 单 击 对 应 的 超 链 接, 将 进 入 MySQL 5.1 下 载 页 面, 然 后 在 其 中 单 击 MySQL Community Server 下 的 Download

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

9 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 开 源 组 织 的 官 方 网 站 进 行 下 载, 它 的 地 址 为 在 该 网 站 主 页 右 侧 导 航 栏 中 有 很 多 该 开 源 组 织 开 发 的 项 目, 在 其 中 单 击 Tomcat 超 链 接, 将 进 入 Tomcat 项 目 的 首 页 在 Tomcat 项 目 首 页 的 左 侧 Download 列 表 中, 单 击 Tomcat 6.x 超 链 接, 将 进 入 该 版 本 的 下 载 页 面, 如 图 1-8 所 示

10 图 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 进 行 学 习, 它 们 的 差 别 是 不 大 的

11 下 载 和 安 装 MyEclipse MyEclipse 的 官 方 网 站 为 因 为 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 的 安 装 运 行 MyEclipse 安 装 MyEclipse 后, 在 桌 面 上 就 出 现 一 个 启 动 MyEclipse 的 快 捷 方 式, 它 的 图 标 为 双 击 该 快 捷 方 式, 将 开 始 运 行 MyEclipse, 首 先 出 现 的 将 是 定 义 工 作 空 间 的 界 面, 如 图 1-10 所 示

12 图 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 中, 除 了 视 图 界 面 外, 最 上 部 还 有 菜 单 和 工 具 栏, 在 后 面 的 学 习 中,

13 9 主 要 是 通 过 它 们 进 行 MyEclipse 的 操 作 当 讲 解 具 体 操 作 时, 我 们 再 对 它 们 进 行 详 细 的 功 能 讲 解 1.5 开 发 HelloWorld 程 序 在 前 面 的 讲 解 中, 已 经 将 开 发 环 境 搭 建 成 功 了, 并 且 已 经 对 MyEclipse 的 每 一 部 分 有 所 了 解 在 本 节 中, 就 来 看 一 下 如 何 使 用 MyEclipse 进 行 项 目 开 发 在 这 里 将 要 开 发 一 个 非 常 简 单 的 HelloWorld 的 Java SE 项 目 创 建 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 除 此 之 外, 还 有 对 新 建 项 目 进 行 设 置 的 选 项,

14 依 次 是 创 建 项 目 的 位 置 项 目 使 用 的 JRE 项 目 布 局 和 工 作 集 下 面 我 们 对 每 一 个 选 项 进 行 简 单 讲 解 Creat new project in workspace: 在 工 作 空 间 内 创 建 项 目, 这 是 推 荐 使 用 的 Creat project from existing source: 在 现 有 位 置 中 创 建 项 目, 如 果 选 择 该 选 项, 则 需 要 单 击 Browse 按 钮, 然 后 选 择 项 目 放 置 的 位 置 Use default JRE(Currently com.sun.java.jdk.win32.x86_ ): 使 用 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 所 示

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

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

17 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 类 程 序 后, 包 资 源 管 理 器 和 编 辑 区 都 会 发 生 改 变,

18 如 图 1-17 是 包 资 源 管 理 器 的 变 化 图 1-17 包 资 源 管 理 器 的 变 化 从 图 中 可 以 看 到 在 src 下 创 建 了 一 个 Hello.java 文 件, 其 中 default package 并 不 是 包 名, 而 是 只 默 认 包, 也 就 是 没 有 使 用 包 创 建 Java 类 程 序 后, 同 时 会 在 编 辑 区 中 将 创 建 的 Java 类 程 序 的 代 码 显 示 出 来, 代 码 内 容 如 下 : 01 public class Hello { 02 /** 03 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 命 令 这 种 方 式 的 好 处 是 直 接 指 定 程 序 的 位 置, 如 果 采 用 菜 单 的 方 式 创 建, 经 常 还 需

19 15 要 指 定 程 序 位 置 运 行 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 所 示

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

21 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 分 层 方 式 显 示 包

22 从 结 果 中 可 以 看 到 将 两 个 包 重 叠 在 一 起, 这 是 因 为 目 前 包 中 并 没 有 任 何 Java 程 序 造 成 的 结 果 在 后 面 创 建 Java 程 序 后, 读 者 可 以 再 来 进 行 切 换 包 显 示 方 式 操 作 创 建 接 口 接 口 也 是 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;

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

24 图 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 行 是 自 动 实 现 接 口 中 的 抽 象 方 法, 程 序 员 可 以 在 其 中 添 加 自 己 的 业 务 操 作

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

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

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

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

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

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

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

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

33 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, 还 可 以 通 过 右 边 的 按 钮, 对 它 进 行 编 辑 删 除 等 操 作, 读 者 可 以 自 己 操 作 一 下 导 入 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 所 示

34 图 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 命 令 下 的 所 有 选 项

35 添 加 和 删 除 注 释 在 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 调 整 代 码 格 式 在 调 整 代 码 中, 有 两 种 操 作, 一 种 是 调 整 行 缩 进, 另 外 一 种 就 是 调 整 格 式 我 们 通 过 下 面 打 乱 后 的 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 行 的 花 括 号 的 缩 进 已 经 符 合 规 范 从 代 码 的 变 化 可 以 看

36 到 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!!!"); } } 从代码的变化可以看到 不但缩进符合的了规范 而且换行也符合了规范 Format 命令的作用就是调整所有选中行的格式 记忆 调整格式的快捷键为 Ctrl+Shift+F 调整格式是包含调整缩进的功能的 所以在开发中完全可以只使用 Format 命令 在当前类中 要实现的接口和类与其 添加和组织导入接口和类 不在同一个包中, 就需要将该接口和 类导入到当前程序中. 当程序中使用的接口或者类和当前程序类不在同一包下 并且接口或者类并不是在 选中"要 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 所示

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

38 图 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 } 09 public String tostring() { 10 // TODO Auto-generated method stub 11 return super.tostring(); 12 } 13 } 在 其 中 第 8 行 使 注 解 标 明 下 面 的 tostring 方 法 是 重 写 的 方 法 生 成 Getter 和 Setter 方 法 在 进 行 Java Web 项 目 开 发 中,JavaBean 是 不 可 缺 少 的 一 部 分 在 标 准 的 JavaBean 中, 应 该 具 有 属 性, 以 及 这 些 属 性 的 Getter 和 Setter 方 法 在 本 小 节 中, 就 来 学 习 一 下 如 何 自 动 生 成 Getter 和 Setter 方 法 在 HelloWorld 项 目 中, 创 建 名 称 为 po 的 包, 然 后 在 该 包 下 创 建 Student 学 生 类, 并 为 该 类 定 义 了 姓 名 年 龄 和 性 别 三 个 属 性, 它 的 程 序 代 码 为 :

39 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

40 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 方 法 自 动 被 生 成

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

42 图 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();

43 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 技 术 这 里 我 们 在 后 面 的 学 习 中 都 会 学 习 到 生 成 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; } 在 第 5 行 中, 在 编 辑 区 右 键 弹 出 菜 单 中, 选 择 Source Generate hashcode() and equals() 命 令, 将 弹 出 生 成 hashcode 和 equals 方 法 的 界 面, 如 图 2-18 所 示

44 图 2-18 生 成 hashcode 和 equals 方 法 在 生 成 hashcode 和 equals 方 法 界 面 的 文 本 域 中, 选 择 对 哪 些 属 性 操 作, 也 就 是 说 当 哪 些 属 性 相 同 时, 认 为 两 个 对 象 是 相 等 的 在 Insertion point 选 项 是 选 择 生 成 的 方 法 插 入 的 位 置, 和 前 面 两 小 节 中 讲 解 是 相 同 的 最 后 单 击 OK 按 钮, 则 Student 学 生 类 程 序 代 码 变 为 : 01 package hashcodeequals; 02 public class Student { 03 String name; 04 int age; 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 } 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;

45 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 等 集 合 时 生 成 构 造 函 数 构 造 函 数 是 Java 程 序 中 非 常 重 要 的 组 成 部 分, 如 果 没 有 人 为 的 定 义 构 造 函 数, 系 统 会 自 动 给 出 一 个 无 参 构 造 函 数 在 MyEclipse 中, 生 成 构 造 函 数 有 两 种 方 式, 一 种 是 使 用 属 性 生 成, 另 一 种 是 从 父 类 中 生 成 1. 使 用 属 性 生 成 使 用 属 性 生 成 构 造 函 数, 是 通 过 使 用 已 有 属 性 做 为 构 造 函 数 参 数 来 生 成 构 造 函 数 在 本 章 项 目 中, 在 创 建 一 个 constructor 包, 在 其 中 创 建 Student 学 生 类 程 序, 并 在 其 中 定 义 姓 名 和 年 龄 两 个 属 性, 代 码 为 : 01 package hashcodeequals; 02 public class Student { 03 String name; 04 int age; } 将 鼠 标 放 在 第 5 行, 在 右 键 弹 出 菜 单 中, 选 择 Source Generate Constructor using Fields 命 令, 从 而 弹 出 使 用 属 性 生 成 构 造 函 数 界 面, 如 图 2-19 所 示

46 图 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) {

47 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; } 将 鼠 标 放 在 第 5 行 中, 在 右 键 弹 出 菜 单 中, 选 择 Source Generate Constructor from Superclass 命 令, 会 弹 出 从 超 类 中 生 成 构 造 函 数 的 界 面, 如 图 2-20 所 示

48 图 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, 则 在 子 类 中 同 样 也 是 这 样 的 顺 序

49 25 注 意 : 我 们 完 全 可 以 在 Teacher 老 师 类 中 不 定 义 姓 名 和 年 龄 属 性, 也 能 生 成 这 三 种 构 造 函 数 这 是 因 为 这 两 个 属 性 会 从 父 类 中 继 承 下 来, 这 里 我 们 给 出 了 这 两 个 属 性, 是 因 为 可 以 让 构 造 函 数 看 的 更 明 白 2.3 包 围 方 式 在 Java 语 言 的 流 程 控 制 语 句 中, 大 部 分 语 句 都 是 具 有 固 定 格 式 的 在 控 制 语 句 中, 包 括 条 件 语 句 循 环 语 句 和 异 常 处 理 语 句 等 在 MyEclipse 中, 通 过 命 令 操 作 可 以 自 动 生 成 这 些 语 句, 从 而 减 轻 程 序 员 的 操 作 在 菜 单 中, 选 择 Source Surround With 命 令, 可 以 看 到 包 围 方 式 选 项 在 编 辑 区 的 右 键 弹 出 菜 单 中, 选 择 Surround With 命 令 也 可 以 得 到 包 围 方 式 选 项 记 忆 : 在 进 行 包 围 操 作 时, 一 定 首 先 选 择 被 包 围 的 代 码 包 围 方 式 的 快 捷 键 为 Alt+Shift+Z 条 件 语 句 包 围 在 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 条 件 语 句 的 包 围

50 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

51 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 循 环 语 句 完 成 异 常 处 理 语 句 包 围 异 常 处 理 语 句 也 是 流 程 控 制 语 句 的 一 种, 在 很 多 书 上 之 所 以 把 它 放 在 后 面 讲 解 是 因 为 异 常 的 概 念 要 放 在 后 面 讲 解 在 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;

52 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 语 句 处 理 多 线 程 语 句 包 围 在 多 线 程 的 操 作 中, 线 程 方 法 和 同 步 块 都 是 经 常 使 用 到 的, 线 程 方 法 就 是 run 方 法, 同 步 块 是 使 用 synchronized 关 键 字 定 义, 这 些 都 是 有 固 定 格 式 的 在 MyEclipse 中, 也 定 义 了 相 关 命 令 生 成 这 些 内 容

53 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 方 法, 从 而 启 动 线 程 注 意 : 在 实 际 开 发 中, 多 线 程 语 句 包 围 使 用 的 是 比 较 少 的 不 是 因 为 功 能 不 强 大,

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

55 北风网讲师原创作品----仅供 学员内部交流使用 第3章 重构 也就是在MyEclipse中的 Refactor菜单功能. 重构是对软件程序的一种调整 使用重构的目的就是在不改变软件可察行为的前提 下 调整软件结构 从而降低修改成本 重构是软件工程中非常重要的一个概念 只讲 重构的知识点 500 页的书都不能全部包括 在本书中主要来学习 MyEclipse 中支持的 对重构的操作 由于重构的内容比较多 我们按照重构的对象不同 将重构分为物理结构重构 类 内部重构 类层次上重构和引入重构 记忆 在 MyEclipse 的菜单中 Refactor 菜单中包含了所有重构操作 在编辑 区右键弹出菜单中 重构的快捷键为 Alt+Shift+T 这两种方式都可以进行重构操作 但是本书中的重构主要通过常用的包资源管理器节点的方式进行操作 3.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) {

56 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 所 示

57 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 栏 中 会 出 现 有 哪 些 程 序 发 生 了 改 变 在 其 中 进 行 选 择, 会 将 改 变 的 细 节 显 示 在 界 面 的 下 半 部 分, 包 括 原 代 码 内 容 查 看

58 重 命 名 的 预 览 没 有 问 题 后, 单 击 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, 使 用 该 快 捷 键 可 以 直 接 进 入 重 命 名 操 作 页 面 移 动 在 Windows 操 作 系 统 中, 可 以 对 文 件 进 行 剪 切 操 作 在 文 字 编 辑 工 具 中, 也 可 以 对 文 字 等 信 息 进 行 剪 切 操 作 在 MyEclipse 的 重 构 操 作 中, 也 有 类 似 的 操 作, 通 常 将 它 称 为 移 动 说 明 : 和 移 动 类 似 的 操 作, 那 就 是 复 制 粘 贴 例 如 在 A 包 下 复 制 一 个 Java 程 序, 然 后 选 中 B 包 后 粘 贴, 这 样 就 把 这 个 Java 程 序 复 制 了 一 份 放 到 B 包 中 这 是 比 较 简 单 的, 这 里 就 不 再 进 行 讲 解

59 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 所 示

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

61 钮, 完 成 预 览 的 观 看, 并 完 成 移 动 操 作 这 时 候,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, 使 用 该 快 捷 键 可 以 直 接 进 入 移 动 操 作 界 面 中 更 改 方 法 签 名 在 Java 程 序 中, 方 法 中 的 元 素 是 比 较 多 的, 例 如 修 饰 符 返 回 类 型 方 法 名 参 数 和 抛 出 异 常 等 在 MyEclipse 中, 可 以 通 过 界 面 化 的 操 作, 对 这 些 元 素 进 行 更 改

62 在 包 资 源 管 理 器 中, 选 中 要 更 改 的 方 法 节 点, 例 如 这 里 我 们 更 改 移 动 后 的 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 所 示

63 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[]){

64 04 Teacher.sayHello("Tom"); 05 } 06 } 可 以 看 到 调 用 该 更 改 方 法 的 代 码 也 发 生 的 改 变, 给 出 了 一 个 字 符 串 类 型 的 参 数 有 些 读 者 可 能 有 这 样 的 疑 问, Tom 参 数 值 是 什 么 地 方 来 的 呢? 它 是 在 更 改 方 法 签 名 界 面 中 设 置 参 数 时, 其 中 的 第 3 项 Default value, 就 是 用 来 设 置 调 用 该 方 法 时, 使 用 的 默 认 值 注 意 : 更 改 方 法 签 名 时, 可 能 会 造 成 程 序 的 错 误 例 如 我 们 将 sayhello 方 法 的 访 问 修 饰 符 该 为 private 私 有 级 别, 这 样 在 其 他 程 序 中 调 用 该 方 法 将 发 生 错 误 记 忆 : 更 改 方 法 签 名 的 快 捷 键 为 Alt+Shift+C, 使 用 该 快 捷 键 将 直 接 进 入 更 改 方 法 签 名 界 面 3.2 类 内 部 重 构 类 内 部 重 构 是 指 在 当 前 操 作 类 类 体 中 进 行 重 构 操 作, 其 中 包 括 抽 取 内 联 和 职 能 转 换 等 操 作 在 抽 取 操 作 中, 又 可 以 分 为 抽 取 方 法 抽 取 局 部 变 量 和 抽 取 常 量 等 具 体 操 作 在 职 能 转 换 操 作 中, 包 括 两 种 内 部 类 的 转 换 和 变 量 间 的 转 换 抽 取 方 法 在 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 所 示

65 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 }

66 从 代 码 中 可 以 看 到, 从 第 7 行 到 第 11 行 定 义 了 一 个 名 称 为 formethod 的 方 法, 将 for 循 环 放 在 该 方 法 中 而 在 原 来 的 方 法 中 for 循 环 代 码 换 为 了 调 用 formethod 方 法 注 意 : 如 果 被 抽 取 的 代 码 在 静 态 方 法 中, 则 抽 取 后 的 方 法 就 是 静 态 方 法 同 理 如 果 被 抽 取 的 代 码 在 非 静 态 方 法 中, 则 抽 取 后 的 方 法 就 是 非 静 态 方 法 这 样 就 会 产 生 这 样 一 个 问 题, 如 果 被 抽 取 代 码 既 出 现 在 静 态 方 法 中, 又 出 现 在 非 静 态 方 法 中, 抽 取 得 到 非 静 态 方 法 后, 程 序 就 发 生 错 误, 需 要 手 动 修 改 记 忆 : 抽 取 方 法 操 作 的 快 捷 键 为 Alt Shift+M, 在 编 辑 区 中, 选 中 被 抽 取 的 代 码, 使 用 该 快 捷 键 将 自 动 进 入 抽 取 方 法 的 界 面 抽 取 局 部 变 量 在 上 一 小 节 中, 我 们 学 习 了 如 何 将 一 段 功 能 代 码 抽 取 成 一 个 方 法, 在 本 小 节 中 就 继 续 来 学 习 如 何 将 一 个 表 达 式 抽 取 成 局 部 变 量 如 果 在 一 个 程 序 中, 一 个 表 达 式 被 使 用 多 次, 就 可 以 将 该 表 达 式 抽 取 成 一 个 局 部 变 量, 将 使 用 该 表 达 式 的 地 方 都 替 换 为 该 局 部 变 量 首 先 定 义 了 一 个 类 名 为 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

67 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, 使 用 该 快 捷 键 可 以 直 接 进 入 抽 取 局 部 变 量 的 界 面 抽 取 常 量 抽 取 常 量 是 和 抽 取 局 部 变 量 非 常 类 似 的, 但 是 它 的 限 制 要 求 更 多 因 为 常 量 的 修 饰 符 中 有 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 所 示

68 图 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 表 达 式 替 换 成 了 常 量, 并 把 表 达 式 赋 值 给 该 常 量 内 联 内 联 是 上 述 三 种 抽 取 操 作 的 反 向 操 作, 它 的 操 作 对 象 是 方 法 局 部 变 量 和 常 量 通 过 内 联 操 作, 可 以 使 用 代 码 代 替 调 用 方 法 或 者 使 用 局 部 变 量 和 常 量 的 地 方 这 里 我 们 通 过 方 法 的 形 式 来 讲 解 内 联 操 作 我 们 先 来 创 建 一 个 类 名 为 InlineTest 的 程 序, 它 的 代 码 为 : 01 package refactor; 02 public class InlineTest { 03 public void method1(){ 04 System.out.println(" 这 是 第 一 个 方 法 ");

69 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(" 这 是 第 二 个 方 法 ");

70 11 for(int i=0;i<10;i++){ 12 System.out.println(i); 13 } 14 } 15 } 从 代 码 的 变 化 可 以 看 到, 将 所 有 调 用 选 中 方 法 的 地 方 都 换 为 了 方 法 中 的 代 码, 而 且 定 义 的 方 法 被 删 除, 这 就 是 内 联 操 作 的 作 用 记 忆 : 内 联 操 作 的 快 捷 键 为 Alt+Shift+I, 使 用 该 快 捷 键 可 以 直 接 进 入 内 联 操 作 界 面, 但 是 要 在 前 面 先 进 行 选 择 对 什 么 对 象 进 行 操 作 将 匿 名 内 部 类 转 换 为 嵌 套 内 部 类 学 习 本 小 节 的 操 作 前, 读 者 一 定 要 先 了 解 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 所 示

71 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 行 中 创 建 了 该 嵌 套 内 部 类 对 象 注 意 : 在 进 行 从 匿 名 内 部 类 向 嵌 套 内 部 类 转 换 时, 一 定 要 仅 仅 选 择 匿 名 内 部 类 的 代 码, 不 要 多 选 了 任 何 内 容, 包 括 最 后 的 分 号, 甚 至 是 前 后 空 格 将 成 员 类 型 内 部 类 转 换 为 顶 级 类 在 上 一 小 节 中, 我 们 学 习 了 如 何 将 匿 名 内 部 类 转 换 成 嵌 套 内 部 类, 在 本 小 节 中 将 继 续 来 学 习 如 何 将 嵌 套 内 部 类 转 换 为 普 通 类 对 于 内 部 类 中 的 成 员 内 部 类 来 说 该 操 作 也 是 适 用 的, 我 们 这 里 仅 使 用 静 态 内 部 类 举 例

72 这 里 我 们 就 不 再 开 发 举 例 程 序, 而 是 在 变 化 后 的 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 中, 并 没 有 定 义 将 匿 名 内 部 类 转 换 为 顶 级 类 的 命 令, 但 是 我

73 19 们 可 以 将 匿 名 内 部 类 首 先 转 换 为 嵌 套 内 部 类, 再 将 潜 逃 内 部 类 转 换 为 顶 级 类 将 局 部 变 量 转 换 为 成 员 变 量 在 实 际 开 发 中, 定 义 完 局 部 变 量 后, 发 现 该 变 量 将 在 多 个 语 句 块 中 使 用, 这 时 候 就 要 将 该 局 部 变 量 提 升 为 成 员 变 量, 这 在 数 据 库 操 作 中 经 常 出 现 在 本 小 节 中, 就 来 看 一 下 在 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 类 程 序 代 码 为 :

74 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 类 层 次 重 构 类 层 次 重 构 泛 指 父 类 与 子 类 之 间 的 重 构, 也 可 以 是 接 口 和 实 现 类 之 间 的 重 构 其 中 包 括 抽 取 超 类 抽 取 接 口 等 抽 取 操 作, 尽 可 能 使 用 超 类 型 的 操 作, 以 及 对 成 员 进 行 的 下 推 和 上 拉 操 作 抽 取 超 类 抽 取 超 类 就 是 为 当 前 操 作 类 生 成 一 个 超 类, 生 成 的 超 类 可 以 是 非 抽 象 类, 也 可 以 是 抽 象 类 在 抽 取 超 类 中, 可 以 选 择 是 否 抽 取 子 类 中 的 方 法, 如 果 抽 取, 这 些 方 法 将 移 动 到 生 成 的 超 类 中 先 来 看 进 行 操 作 的 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 所 示

75 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 选 项 将 抽 取 的 方 法 声 明 为 抽 象 方 法, 如 果 选 择 该 操 作, 则 抽 取 的 超 类 也 就

76 为 抽 象 类, 这 里 我 们 选 择 该 选 项 最 后 单 击 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 { 04 public void firstmethod(){ 05 System.out.println(" 这 是 第 一 个 方 法 "); 06 } 07 public void secondmethod(){

77 23 08 System.out.println(" 这 是 第 二 个 方 法 "); 09 } 10 } 其 中 firstmethod 方 法 是 实 现 的 超 类 中 的 抽 象 方 法 如 果 在 抽 取 超 类 界 面 中, 将 secondmethod 方 法 也 选 中, 并 设 置 操 作 是 抽 取, 则 该 方 法 将 出 现 在 SuperClass 类 程 序 中, 在 ExtractSuperclassTest 类 中 也 就 不 会 再 出 现 注 意 : 如 果 一 个 类 中 有 抽 象 方 法, 则 这 个 类 一 定 是 抽 象 类 但 是 在 抽 象 类 中, 不 一 定 有 抽 象 方 法 在 MyEclipse 中, 正 是 遵 守 该 语 法, 当 抽 取 方 法 是 设 置 操 作 为 抽 象 抽 取, 则 超 类 将 自 动 变 为 抽 象 类 抽 取 接 口 抽 取 接 口 是 和 抽 取 超 类 非 常 类 似 的, 使 用 该 操 作 可 以 从 当 前 操 作 类 抽 取 出 该 类 所 实 现 的 接 口, 在 其 中 也 可 以 将 方 法 抽 取 成 抽 象 方 法 同 样 还 是 开 发 一 个 操 作 类, 类 名 为 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 所 示

78 图 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)

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

80 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 refactor.myinterface#firstmethod() 05 */ 06 public void firstmethod(){ 07 System.out.println(" 这 是 第 一 个 方 法 "); 08 } 09 /* (non-javadoc) 10 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 }

81 27 20 } 上 述 代 码 中 第 16 行 的 ExtractInterfaceTest 类 引 用 已 经 变 为 了 MyInterface 接 口 引 用, 从 而 就 变 为 使 用 接 口 引 用 指 向 实 现 类 对 象 如 果 代 码 中 有 多 种 同 样 情 况 都 会 使 用 同 种 操 作 更 改 说 明 : 在 JavaWeb 的 分 层 开 发 中, 本 小 节 的 操 作 也 经 常 被 用 到 例 如 在 Spring 框 架 的 开 发 中, 使 用 最 多 的 就 是 使 用 接 口 引 用 指 向 子 类 对 象, 但 是 这 里 的 对 象 是 通 过 系 统 创 建 后 注 入 的, 该 知 识 点 要 到 后 面 的 讲 解 中 才 会 学 到 下 推 下 推 和 上 拉 是 重 构 中 非 常 重 要 的 两 个 概 念, 它 们 的 操 作 对 象 就 是 父 类 和 子 类, 在 本 小 节 中 先 来 学 习 一 下 下 推 使 用 下 推 操 作, 可 以 将 父 类 中 的 成 员 ( 包 括 方 法 和 变 量 ) 移 动 到 它 的 直 接 子 类 中 如 果 操 作 的 是 方 法, 在 父 类 中 可 以 不 保 留 或 者 保 留 该 方 法 的 抽 象 方 法 同 样 还 是 先 来 开 发 进 行 操 作 的 程 序, 这 里 我 们 通 过 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 所 示

82 图 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 }

83 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 类 中 上 拉 上 拉 和 下 推 正 好 相 反, 它 是 将 子 类 中 的 成 员 移 动 到 它 的 父 类 中 在 操 作 中 也 可 以 选 择 是 整 体 移 动, 还 是 在 父 类 中 保 留 抽 象 方 法 这 里 我 们 开 发 一 个 继 承 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 所 示

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

85 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 引 入 重 构 引 入 重 构 是 指 在 原 事 物 的 基 础 上, 引 入 新 事 物, 从 而 进 行 封 装 操 作 其 中 包 括 引 入 间 接 方 法 引 入 工 厂 引 入 参 数 对 象 引 入 参 数 引 入 方 法 封 装 字 段 等 操 作 在 实 际 开 发 中 灵 活 使 用 这 些 引 入 操 作, 能 够 大 大 加 快 开 发 速 度 引 入 间 接 方 法 在 Java 程 序 中, 每 一 个 方 法 完 成 一 个 功 能, 项 目 的 实 现 就 是 通 过 调 用 这 些 方 法 完 成 的 在 项 目 开 发 中 期, 有 可 能 会 发 现 一 些 方 法 的 功 能 并 不 完 善, 但 是 通 常 不 改 变 已 经 测 试 通 过 的 方 法, 而 是 对 这 些 方 法 进 行 重 构, 产 生 间 接 方 法 在 间 接 方 法 中 调 用 原 方 法, 然 后 进 行 功 能 补 充, 让 调 用 原 方 法 的 地 方 调 用 这 个 间 接 方 法 在 本 小 节 中 就 来 学 习 一 下 在 MyEclipse 中, 如 何 使 用 命 令 完 成 该 引 入 间 接 方 法 的 重 构 操 作 这 里 我 们 通 过 电 梯 来 模 拟 该 操 作, 电 梯 最 基 本 的 功 能 就 是 上 下 运 动, 除 此 之 外 还 应 该 有 开 门 和 关 门 的 功 能 来 看 模 拟 电 梯 的 代 码 : 01 package ref; 02 public class Elevator { 03 public void work(){ 04 System.out.println(" 电 梯 上 下 运 动 "); 05 }

86 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(){

87 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

88 方 法, 从 而 完 善 原 方 法 的 功 能 说 明 : 有 些 读 者 可 能 会 感 觉 到 北 小 节 学 习 的 内 容 和 前 面 学 习 的 代 理 方 法 有 所 类 似 的 如 果 仅 仅 是 完 善 某 一 个 方 法 的 功 能, 建 议 使 用 引 入 间 接 方 法 的 操 作 如 果 是 对 某 一 类 功 能 的 完 善, 则 就 应 该 使 用 代 理 引 入 工 厂 工 厂 模 式 也 是 设 计 模 式 中 非 常 重 要 的 一 种, 其 中 工 厂 类 是 必 不 可 少 的 在 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 引 入 工 厂

89 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 类 执 行 抽 取 接 口 操 作, 具 体 操 作 见 抽 取 接 口 一 节 的 讲 解 引 入 参 数 对 象 在 实 际 开 发 中, 经 常 会 遇 到 这 样 的 现 象, 就 是 一 组 参 数 总 是 同 时 传 递 例 如 在 网 站 中, 用 户 注 册 和 登 录 的 操 作 会 对 应 着 注 册 和 登 录 方 法, 在 这 两 个 方 法 中 都 需 要 传 递 用 户 名 和 密 码 这 两 个 参 数 在 这 种 情 况 下 就 可 以 定 义 一 个 用 户 类, 向 注 册 和 登 录 方 法 中 传 递 用 户 类 类 型 的 参 数, 在 该 参 数 中 包 含 了 用 户 名 和 用 户 密 码 这 里 我 们 通 过 一 个 士 兵 的 程 序 来 更 形 象 的 说 明 该 重 构 操 作, 同 样 也 看 一 下 在 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 方 法 中 都 需 要 士 兵 等 级 和 士 兵 姓 名 两 个 参 数, 这 时 候 就 可 以 使 用 引 入 参 数 对 象 的 重 构 操 作

90 在 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 方 法, 所 以 获 取 参 数 值 时 通 过 它 们 设 置

91 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 方 法, 这 是 在 引 入 参 数 对 象 界 面 中 选 择 的 引 入 参 数 引 入 参 数 和 引 入 参 数 对 象 是 两 种 完 全 不 一 样 的 操 作, 它 们 只 是 名 称 相 似 在 开 发 阶 段 的 方 法 中, 一 些 变 量 通 常 给 出 值 或 者 表 达 式 来 进 行 功 能 的 测 试, 在 测 试 没 有 问 题 后, 通 常 使 用 方 法 参 数 来 代 替 值 或 者 表 达 式 通 过 使 用 引 入 参 数 的 重 构 操 作 就 可 以 自 动 完 成 这 一 点 我 们 在 原 来 士 兵 类 的 基 础 上 定 义 一 个 新 方 法, 它 的 代 码 变 为 : 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 }

92 在 第 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 字 符 串 参 数, 这 样 就 和 前 面 两 个 方 法 相 似 了 引 入 方 法 封 装 字 段 封 装 字 段 的 重 构 操 作 和 前 面 学 习 过 的 生 成 Getter Setter 方 法 非 常 类 似 的, 它 们 都 完 成 为 字 段 生 成 Getter 和 Setter 方 法 的 功 能 在 本 小 节 中 就 来 学 习 一 下 在 MyEclipse 中, 如 何 进 行 封 装 字 段 的 重 构 操 作 先 来 开 发 一 个 进 行 操 作 的 User 用 户 类, 其 代 码 为 :

93 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 私 有 访 问 级 别

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

95 北风网讲师原创作品----仅供 学员内部交流使用 第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 切换到数据库视图 视图在第 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 所示

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

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

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

99 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 数 据 库 为 例 进 行 讲 解, 在 学 习 本 节 之 前, 一 定 要 首 先 安 装

100 MySQL 数 据 库 建 立 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 按 钮, 可 以 对 当 前 连 接 进 行 测 试, 单 击 后 将 弹 出 输 入 密 码 界 面,

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

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

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

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

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

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

107 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 两 个 字 段 注 意 : 不 同 数 据 库 之 间, 字 段 的 类 型 是 有 所 不 同 的 在 创 建 数 据 表 时, 要 根 据 数 据 库 的 不 同 来 选 择 相 对 应 的 类 型 删 除 数 据 表 删 除 数 据 表 是 和 创 建 数 据 表 相 对 应 的, 它 是 非 常 容 易 操 作 的 选 中 要 删 除 的 数 据 表 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Drop Table 命 令, 将 弹 出 选 择 是 否 删 除 数 据 表 的 对 话 框, 如 图 4-17 所 示

108 图 4-17 删 除 数 据 表 单 击 OK 按 钮, 将 完 成 删 除 user 数 据 表 的 操 作 进 行 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 选 项, 将 看 到 刚 执 行

109 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 语 句 编 辑 区 中 可 以 进 行 所 有 的 数 据 库 操 作, 例 如 创 建 数 据 库 创 建 数 据 表, 以 及 增 删 改 查 操 作, 但 是 这 些 操 作 大 部 分 都 是 可 以 通 过 界 面 化 的 操 作 完 成 的, 所 以 在 本 小 节 中 主 要 通 过 插 入 数 据 来 讲 解 它 的 使 用 编 辑 数 据 表 数 据 向 数 据 表 中 插 入 数 据 后, 可 能 还 会 对 已 经 插 入 的 数 据 进 行 修 改, 这 里 我 们 主 要 来 看 一 下 在 MyEclipse 中 如 何 界 面 化 的 进 行 该 操 作

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

111 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 所 示

112 图 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 语 句 中 脱 离 出 来 创 建 和 删 除 索 引 在 数 据 库 中, 使 用 索 引 可 以 使 查 询 操 作 不 用 对 整 个 表 进 行 扫 描, 就 可 以 在 其 中 找 到 所 需 的 数 据 对 于 具 有 庞 大 数 据 的 数 据 库 而 言, 索 引 时 必 不 可 少 的 同 样 这 里 我 们 对 索 引 不 进 行 过 多 的 讲 解, 而 是 更 关 心 如 何 使 用 MyEclipse 进 行 索 引 的 创 建 和 删 除 选 中 要 创 建 索 引 的 数 据 表, 例 如 这 里 仍 然 对 user 数 据 表 进 行 操 作 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New Index 命 令, 将 弹 出 创 建 索 引 操 作 界 面, 如 图 4-25 所 示

113 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`)

114 Copy to Clipboard 命 令 表 示 将 索 引 信 息 复 制 到 剪 切 板 中 查 询 数 据 表 数 据 查 询 也 是 数 据 库 操 作 中 非 常 重 要 的 一 种, 在 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 语 句 的 正 确 性 生 成 创 建 数 据 表 的 SQL 语 句 在 MyEclipse 中, 可 以 通 过 SQL 语 句 完 成 数 据 库 操 作, 也 可 以 通 过 界 面 化 完 成 后 生 产 完 成 该 操 作 的 SQL 语 句 在 前 面 学 习 创 建 外 键 和 索 引 时, 已 经 见 到 这 种 反 向 操 作 在 前 面 学 习 创 建 数 据 表 时, 是 通 过 界 面 化 的 方 式 创 建 的, 在 本 小 节 中 看 一 下 要 生 成 同 样 的 数 据 表 的 SQL 语 句 选 中 user 数 据 表 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Generate DDL 命 令, 将 会 将 SQL 语 句 显 示 在 编 辑 区 中 其 SQL 语 句 的 内 容 为 : create table `mydb`.`user`( `id` INT not null auto_increment, `name` VARCHAR(20),

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

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

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

118 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 结 果 集 对 象

119 25 46 } catch (SQLException e) { 47 e.printstacktrace(); 48 } 49 } 50 } 51 } 其 中 不 同 开 发 环 境 中 需 要 改 动 的 只 有 第 9 行 到 第 11 行, 其 中 第 9 行 是 连 接 数 据 库 的 URL, 根 据 数 据 库 不 同 需 要 进 行 改 动 第 10 行 和 第 11 行 是 连 接 数 据 库 用 到 的 用 户 名 和 密 码, 根 据 本 地 数 据 库 的 设 置 进 行 对 应 修 改 创 建 商 品 实 体 类 通 常 数 据 库 中 的 一 张 数 据 表 就 对 应 着 一 个 实 体 类 例 如 现 在 数 据 库 中 有 商 品 数 据 表, 我 们 就 应 该 创 建 一 个 商 品 实 体 类, 通 过 这 个 类 来 完 成 对 商 品 的 增 删 改 查 等 操 作 在 项 目 中, 通 常 将 实 体 类 放 在 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 所 示

120 图 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) {

121 27 23 this.price = price; 24 } 25 public double getagio() { 26 return agio; 27 } 28 public void setagio(double agio) { 29 this.agio = agio; } } 可以看到 通过 MyEclipse 的命令自动生成很多行代码 并且生成一个标准的实体 类程序 实体类名.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{ 数据库操作中, 需要 关闭预处理对象. DBConnection.close(pstmt); //关闭预处理对象 DBConnection.close(conn); //关闭连接对象 } 22 } 23 //省略其他操作方法

122 24 } 该 程 序 在 开 发 中, 是 需 要 手 动 完 成 的, 根 据 实 际 需 求 来 定 义 不 同 的 方 法 在 本 小 节 数 据 访 问 层 实 现 类 中 定 义 了 增 加 商 品 删 除 商 品 更 新 商 品 查 询 所 有 商 品 和 按 照 商 品 ID 查 询 商 品 5 种 方 法, 这 里 仅 给 出 增 加 商 品 方 法, 其 他 方 法 代 码 见 光 盘 注 意 : 定 义 数 据 库 操 作 方 法 时, 通 过 将 参 数 定 为 对 应 的 实 体 类 类 型, 如 果 这 里 定 义 了 是 具 体 信 息 参 数, 例 如 商 品 名 称 商 品 价 格 等, 就 可 以 使 用 引 入 参 数 对 象 的 重 构 操 作, 进 行 替 换 创 建 数 据 访 问 层 接 口 数 据 访 问 层 接 口 的 命 名 也 是 遵 循 规 范 的, 通 常 由 实 体 类 名 加 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);

123 29 07 public abstract List<Commodity> findallcommodity(); 08 public abstract void updatecommodity(commodity commodity); 09 public abstract Commodity findcommoditybyid(int commodityid); 10 } 并且在数据访问层的实现类中实现该接口 创建数据访问层工厂类 工厂类: 什么是工厂类, 其作用是什么?. 在业务访问层中通常借助工厂类来创建数据访问层实现类对象 在本小节中就来看 一下如何快速创建数据访问层的工厂类 在操作前 要完成准备的工作 首先在数据访 问层实现类中定义一个无参构造函数 然后定义工厂类 工厂类通常不和接口和实现类 放在同一包下 而是自定义一个 factory 包 工厂类的代码为 01 package com.sanqing.factory; 02 public class CommodityDAOFactory { 工厂类: 创建实现类 } 接下来就是定义工厂类中的创建实现类对象的方法 在包资源管理器中 选中 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(); } } 通常该操作生成的工厂方法并不是规范的 其中方法的返回值为实现类类型 这就 失去了工厂类的作用 工厂类的作用就是让业务逻辑层中并不关心数据访问层实现类

124 只需要关心数据访问层接口 如果想变为规范的方法 还需要经过 尽可能使用超类型 的重构操作 在包资源 管理器中 选中 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(); } 很显然工厂类的本质在于: 接口, 实现类. } 这就变为一个规范的工厂类 开发数据访问层测试程序 到目前为止 网络商城的数据访问层应该算开发完成了 但是在实际开发中 通常 开发一部分程序后 要对它进行测试 以验证该部分程序的正确性 测试程序仅用于开发阶段 当进行项目部署时 通常就会将测试程序删除 本节讲 解的网络商城数据访问层的测试程序代码如下 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 { public static void main(string[] args) { CommodityDAO commoditydaoimpl = CommodityDAOFactory.createCommodityDAOImpl();

125 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 测 试 结 果 从 该 结 果 可 以 看 到, 数 据 访 问 层 开 发 正 确, 可 以 放 到 项 目 中 做 为 项 目 的 一 部 分

126 北风网讲师原创作品----仅供 学员内部交流使用 第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

127 命令表示停止服务器 Add Deployment 命令表示向选中的服务器中发布项目 在后 面的学习中 使用到这些命令后 还会进行详细的讲解 将一个或多个项目发布 到该服务器 5.2 管理外部 Tomcat 服务器 MyEclipse 中的内置服务器是不能完成所有 Java Web 项目的操作的 所以我们有必 要学习一下如何在 MyEclipse 中对外部的应用服务器进行管理 这里通过外部的 Tomcat 服务器讲解该操作 配置 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 读者可以根据本地安装位置进行填写 Optional program arguments 选项表示 Tomcat 的相关参数 通常这一项是不需要填写的 都是采用默认 值 说明 前三个选择 Tomcat 目录的选项是级联关系的 当选择其中一个后 其他的 会自动填写 例如填写 Tomcat 的主目录为 D:\apache-tomcat 后 将自动填写 临时参数目录为 D:\apache-tomcat \temp 只需要设置好Tomcat的 主目录即可.

128 启动 仅配置外部 Tomcat 的路径 单击 OK 按钮后 该服务器并不会出现在服务器界 面中 这是因为还没有启动该配置 在配置路径的上面有两个单选按钮选项 其中 Enable 选项表示启动外部 Tomcat 的配置 Disable 选项表示不启动外部 Tomcat 的配置 默认是不启动的状态 所以 要选择 Enable 选项 这是再单击 OK 按钮 就完成对外部 Tomcat 服务器的配置 技巧 在实际开发中 不同的项目可能需要的服务器不同 这时候就需要将不需 要的服务器停止 从而不影响 MyEclipse 的速度 这种操作主要就是通过 Enable 选项和 Disable 选项完成的 这样的好处就是下次使用时 不需要重新配置服务器 添加 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 的添加

129 这 时 候 将 弹 出 添 加 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 应 用 服 务 器 在 后 面 的 学 习 中 都 是 基 于 该 服 务 器 操 作 的

130 5 5.3 开发 Web 项目中的 HelloWorld 因为服务器的大部分操作都是对 Java Web 项目进行操作 所以有必要先来学习一 下在 MyEclipse 中如何进行 Java Web 项目的开发 和开发 Java 项目一样 在 MyEclipse 中也集成了大量对 Java Web 项目支持的功能 创建 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 的要求.

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

132 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 目 录 下, 也 可 以 在 该 目 录 下 创 建 子 目 录,

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

134 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) 选 项 表 示 散

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

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

137 图 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 页 面 程 序 创 建 HTML 页 面 程 序 在 MyEclipse 中, 创 建 HTML 等 Web 程 序 的 方 式 有 很 多 种 的, 可 以 通 过 菜 单 或 者 工 具 栏 完 成, 这 里 我 们 主 要 使 用 最 常 用 的 方 式 创 建 在 包 资 源 管 理 器 中, 选 中 Java Web 项 目 中 的 WebRoot 目 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令, 将 弹 出 选 择 要 创 建 程 序 界 面, 如 图 5-14 所 示

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

139 其 中 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 该 界 面 具 体 如 何 使 用 在 后 面 的 小 节 中 进 行 详 细 讲 解 使 用 高 级 模 板 创 建 使 用 高 级 模 板 创 建 HTML 程 序 的 创 建 操 作 有 两 种, 第 一 种 就 是 在 图 5-14 的 选 择 创 建 程 序 界 面 中, 选 择 HTML(Advanced Templates) 选 项 第 二 种 就 是 选 中 WebRoot 目 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New HTML(Advanced Templates) 命 令 使 用 这 两 种 操 作 都 将 弹 出 创 建 使 用 高 级 模 板 HTML 程 序 的 界 面, 如 图 5-17 所 示

140 创 建 高 级 模 板 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 程 序 时, 可 以 去 掉 该 行 代 码 注 释

141 如 果 在 创 建 高 级 模 板 程 序 界 面 中, 选 择 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 程 序 也 是 这 样 的 编 写 HTML 程 序 当 使 用 编 辑 区 对 HTML 程 序 编 写 时, 通 常 将 编 辑 区 分 为 上 下 两 部 分, 其 中 下 半 部 分 是 HTML 程 序 代 码, 在 其 中 可 以 手 动 编 写 代 码 ; 在 上 半 部 分 中, 可 以 通 过 界 面 的 方 式 创 建 HTML 程 序, 它 是 本 书 讲 解 的 重 点 在 上 下 两 部 分 中 间, 有 两 个 三 角, 单 击 它 们 可 以 使 整 个 编 辑 区 只 显 示 上 半 部 分 或 者 下 半 部 分 在 编 辑 区 的 左 下 角, 有 两 个 选 项,

142 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 基 本 元 素 的 创 建, 例 如 超 链 接 图 片

143 表 格 等 在 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 所 示

144 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 程 序 非 常 类 似 的, 也 分 为 基 础 模 板 和 高 级 模 板 使 用 基 础 模 板 创 建 JSP 程 序 在 包 资 源 管 理 其 中, 选 中 要 创 建 JSP 程 序 的 目 录, 例 如 选 中 WebRoot 目 录 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 New Other 命 令, 将 弹 出 选 择 创 建 程 序 的 界 面, 在 其 中 选 择 MyEclipse Web 节 点, 如 图 5-22 所 示

145 图 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 按 钮

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

147 图 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 "%> 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">

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

149 其中 Encoding 就是用于编码的选择 默认的就是 ISO 在其中使用 最多的就是选择 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 开发中非常重要的一个知识点 一定要对编码有所了解 如果 处理不好 在页面中就会出现乱码 在后面的其他技术的讲解中 还会讲解到编码 在 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 程序是要首先发布项目 然后启动服务器的

150 25 启动服务器后 打开浏览器 输入如下地址 浏览器如图 5-27 所示 图 5-27 使用 EL 表达式 从运行结果中可以看到 将保存在 request 内置对象中的属性值获取到 如果不运 行项目 而是直接使用浏览器打开 JSP 程序 将会直接将 EL 表达式显示在页面中 读 者可以自己尝试一下 在 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=" 其中 prefix 为 c 表示标签的前缀为 c 这时就必须使用<c:XXX>这种格式

151 核 心 标 签 通 常 设 置 前 缀 为 c, 也 可 以 直 接 为 其 他 内 容, 但 是 阅 读 性 就 会 降 低 uri 用 来 指 定 核 心 标 签 库 规 范 文 件 (TLD 文 件 ) 地 址 技 巧 :uri 属 性 值 是 比 较 长 的, 有 些 程 序 员 选 择 死 记 硬 背, 这 是 没 有 必 要 的 打 开 jstl-1.1.jar WEB-INF 目 录 下 的 c.tld 文 件, 其 中 <uri> 指 定 的 就 是 url, 将 其 中 的 复 制 到 <%@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 语 句

152 开发 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 中完成参数的接 收 然后使用参数调用业务逻辑层 接下来根据调用结果的不同跳转到不同的页面 创建 Servlet 程序 在 MyEclipse 中集成了创建 Servlet 程序的功能 会自动生成 Servlet 程序中的固定 代码 并给出配置代码 Servlet 程序将创建在 src 下 并且需要为它定义单独的一个包 例如包名为 com.sanqing.servlet 然后选中包目录 单击鼠标右键 在弹出的菜单中 选择 New Servlet 命令 将弹出创建 Servlet 程序的界面 如图 5-28 所示

153 图 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 所 示

154 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 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());

155 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 界 面 自 动 生 成 的 启 动 或 者 重 启 服 务 器, 启 动 后, 打 开 浏 览 器, 在 其 中 输 入 如 下 地 址 : 其 中 /servlet/helloservlet 就 是 在 web.xml 文 件 中 对 Servlet 进 行 的 URL 配 置, 访 问 后 的 页 面 如 图 5-30 所 示 图 5-30 Servlet 程 序 的 运 行 结 果 其 中 的 信 息 就 是 运 行 Servlet 时 输 出 的 内 容, con.sanqing.servlet.helloservlet 就

156 31 是 this.getclass() 的输出结果 说明 在本小节中主要讲解的是 Servlet 的创建 在实际开发中 Servlet 的功能并 不是输出页面 该功能通常由 JSP 程序来完成 Servlet 的主要功能就是作为控制层 接收参数 调用后台 执行跳转 创建 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

157 方 法 中 加 入 过 滤 的 功 能 代 码, 例 如 这 里 加 入 对 编 码 进 行 过 滤 的 代 码, 则 过 滤 器 的 完 整 代 码 为 : 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 所 示

158 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 文 件 的 具 体 代 码, 可 以 发

159 现 其 中 多 出 了 如 下 代 码 : 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 ISO 编 码 是 不 支 持 中 文 的, 所 以 要 进 行 比 较 的 编 码 处 理 开 发 录 入 商 品 的 HTML 程 序 网 络 商 城 的 主 要 功 能 就 是 让 用 户 来 购 买 商 品, 要 将 商 品 显 示 在 页 面 中, 这 些 商 品 需 要 在 系 统 后 台 进 行 录 入 录 入 商 品 的 页 面 只 需 要 有 一 个 提 交 表 单, 所 以 这 里 开 发 一 个 HTML 程 序 就 可 以 这 里 我 们 选 择 高 级 模 板 来 创 建 HTML 程 序 在 创 建 HTML 程 序 的 界 面 中, 选 择 默 认 模 板, 文 件 名 填 写 AddCommodity.html, 创 建 完 成 后 将 在 编 辑 区 中 将 该 程 序 打 开 删 除 原 body 标 记 对 中 的 内 容, 然 后 在 界 面 化 操 作 部 分 中 创 建 一 个 Form 表 单, 创 建 界 面 如 图 5-35 所 示

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

161 图 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>

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

163 图 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);

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

165 所 示 单 击 编 辑 区 左 下 角 的 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 开 发 查 询 所 有 商 品 Servlet 程 序 单 击 录 入 成 功 页 面 中 的 显 示 所 有 商 品 超 链 接, 将 会 访 问 显 示 所 有 商 品 Servlet, 在 本 小 节 中 就 来 开 发 该 Servlet 程 序 选 中 项 目 中 的 com.sanqing.servlet 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Servlet 命 令, 在 弹 出 的 创 建 Servlet 界 面 中, 输 入 相 关 信 息 后, 如 图 5-42 所 示

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

167 在 编 辑 区 中 打 开 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 行 中 进 行 服 务 器 跳 转, 跳 转 到 显 示 所 有 商 品 页 面 开 发 显 示 所 有 商 品 的 JSP 程 序 在 查 询 所 有 商 品 Servlet 中 将 跳 转 到 显 示 所 有 商 品 页 面 中, 在 本 小 节 中 就 来 开 发 该 页 面, 在 这 里 开 发 使 用 JSTL 标 签 的 JSP 程 序 选 中 WebRoot 目 录, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New JSP(Advanced Templates) 命 令, 将 弹 出 使 用 高 级 模 板 创 建 JSP 程 序 的 界 面, 在 其 中 填 入 文 件 名, 如 图 5-44 所 示

168 43 图 5-44 创 建 显 示 商 品 JSP 程 序 单 击 Finish 按 钮, 将 完 成 JSP 程 序 的 创 建 因 为 在 其 中 要 使 用 到 JSTL 标 签, 所 以 在 page 指 令 下 给 出 如 下 taglic 指 令 taglib prefix="c" uri=" 然 后 在 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 标 签 替 换 测 试 文 字

169 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 按 钮, 将 完 成 首 页 的 修 改 运 行 网 络 商 城 项 目 到 目 前 为 止, 我 们 的 网 络 商 城 项 目 已 经 开 发 完 成, 它 由 HTML 程 序 JSP 程 序 Servlet 程 序 和 Filter 过 滤 器 程 序 组 成, 完 成 录 入 商 品 和 显 示 所 有 商 品 两 个 功 能 在 本 节 中 就 来 看 一 下 如 何 发 布 和 运 行 该 项 目 在 Servers 界 面 中 选 择 Tomcat 6.x 服 务 器, 单 击 鼠 标 右 键, 选 择 Add Deployment 命 令, 将 弹 出 发 布 项 目 界 面, 填 入 store 项 目 后, 如 图 5-46 所 示

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

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

172 北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 第 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 项 目 的 创 建 Web 项 目 Struts 是 一 种 Web 项 目 的 开 发 框 架, 所 以 仅 能 够 在 Java Web 项 目 中 使 用 在 MyEclipse 开 发 Struts 项 目 时, 是 要 基 于 基 本 的 Java Web 项 目 的, 所 以 我 们 要 首 先 创 建 一 个 基 本 的 Web 项 目 在 MyEclipse 的 菜 单 中, 选 择 File New Web Project 命 令, 将 弹 出 创 建 Java Web 项 目 的 界 面, 在 其 中 填 写 项 目 名 等 信 息 后, 如 图 6-1 所 示

173 图 6-1 创建普通 Web 项目 这里将本节将要创建的 Struts 项目命名为 FirstStruts 单击 Finish 按钮 将 完成基本 Web 项目的创建 加入 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 中对核心控制器进行配置 这些操作也是可以 手动完成的 但是要相对复杂的多

174 认 识 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>

175 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 框 架 支 持 时 自 动 加 入 的

176 5 6.2 开 发 Struts 项 目 中 的 相 关 程 序 因 为 Struts 是 一 种 MVC 框 架, 所 以 每 一 层 都 有 相 应 的 程 序 构 成 在 一 个 Struts 项 目 中 通 常 由 JSP 页 面 Action ActionForm 和 ActionForward 等 程 序 组 成 在 MyEclipse 中 有 多 种 创 建 这 些 程 序 的 方 法, 我 们 主 要 讲 解 其 中 使 用 最 多 的 方 式, 本 节 先 来 讲 解 通 过 新 建 向 导 的 形 式 创 建 创 建 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=" prefix="bean" %> <%@ taglib uri=" prefix="html" %> <%@ taglib uri=" prefix="logic" %> <%@ taglib uri=" prefix="tiles" %>

177 这 些 就 是 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 所 示

178 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 选 择, 则 创 建 的 仅 是 普 通 按 钮 如 果 想 创 建 提 交 按 钮, 需 要

179 选 择 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 命 令 进 行 的 调 整 并 不 是 规 范 的 开 发 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 所 示

180 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 所 示

181 图 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() {

182 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 时, 将 使 用 到 该 名 称 开 发 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 所 示

183 图 6-11 创 建 Action 程 序 其 中 Config/Module 和 Use case 两 个 选 项 是 和 创 建 ActionForm 界 面 中 的 选 项 相 同 的, 作 用 也 相 同 Path 表 示 访 问 该 Action 使 用 的 访 问 路 径, 当 前 Action 的 完 整 访 问 路 径 为 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

184 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;

185 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 行 分 别 定 义 了 登 陆 成 功 跳 转 和 登 录 失 败 跳 转 开 发 全 局 ActionForward 跳 转 学 习 上 面 的 三 种 Struts 框 架 中 的 程 序, 对 于 大 部 分 项 目 来 说 已 经 足 够 了, 但 是 它 们 并 不 是 Struts 框 架 的 全 部 程 序 在 本 小 节 中 将 学 习 Struts 框 架 中 的 ActionForward, 在 前 面 学 习 Action 时, 已 经 看 到 它 的 主 方 法 的 返 回 值 就 是 ActionForward, 它 通 常 使 用 ActionMapping 调 用 findforward 方 法 获 取 ActionForward, 这 里 完 全 也 可 以 通 过 new 的

186 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"

187 04 path="/login.jsp" 05 redirect="true" /> 06 </global-forwards> 如 果 有 多 条 全 局 跳 转, 都 将 配 置 在 <global-forwards > 标 记 对 中 但 在 Action 中 返 回 login 时, 虽 然 没 有 定 义 局 部 跳 转, 但 是 会 使 用 该 全 局 跳 转, 从 而 跳 转 到 登 录 页 面 开 发 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 所 示

188 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 表 示 异

189 常 类 型, 这 里 选 择 自 定 义 的 密 码 错 误 异 常 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 基 本 语 法 中 的 内 容 而 声 明 式 异 常 在 代 码 量 上 更 少, 更 简 单 同 时 创 建 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 所 示

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

191 图 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"/>

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

193 图 6-21 创 建 按 钮 在 编 辑 区 的 右 边, 是 用 于 显 示 已 有 程 序 的 画 布, 在 其 中 不 但 显 示 出 有 什 么 程 序, 而 且 还 会 显 示 它 们 之 间 的 关 系 在 画 布 中, 单 击 鼠 标 右 键, 在 弹 出 菜 单 中 选 择 New 命 令, 将 出 现 多 个 选 项, 通 过 它 们 可 以 进 入 对 应 创 建 界 面, 从 而 创 建 相 对 应 的 程 序 通 过 视 图 创 建 程 序 这 里 我 们 通 过 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 所 示

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

195 6.4 快 速 搭 建 论 坛 项 目 后 台 在 实 际 开 发 中, 每 一 个 系 统 项 目 都 要 有 一 个 后 台, 管 理 员 在 后 台 中 进 行 管 理 在 本 节 中 将 开 发 一 个 论 坛 系 统, 管 理 员 将 对 论 坛 中 的 主 题 进 行 管 理, 包 括 发 表 主 题, 查 看 已 有 主 题 删 除 主 题 等 说 明 : 开 发 具 体 程 序 之 前, 要 首 先 创 建 一 个 Java Web 项 目, 我 们 给 它 取 名 为 BBS, 它 就 是 我 们 的 论 坛 项 目, 然 后 为 该 项 目 加 入 Struts 框 架 支 持 开 发 论 坛 数 据 访 问 层 数 据 访 问 层 在 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 }

196 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 行 定 义 了 查 询 所 有 主 题 的 方 法, 通 过 该 方 法 可 以 将

197 目 前 数 据 库 中 的 所 有 主 题 记 录 查 询 出 来 开 发 发 表 主 题 功 能 在 论 坛 中, 最 主 要 的 功 能 应 该 算 是 发 表 主 题 发 表 主 题 的 用 户 可 以 使 普 通 用 户, 也 可 以 是 后 台 管 理 员 这 里 我 们 主 要 是 通 过 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 所 示

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

199 图 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,

200 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> 到 这 里, 我 们 的 发 表 主 题 功 能 就 开 发 完 成 了 开 发 查 询 所 有 主 题 功 能 当 发 表 主 题 成 功 后, 将 自 动 跳 转 到 查 询 所 有 主 题 Action 中, 在 本 小 节 中 就 来 开 发 该 Action 因 为 完 成 查 询 所 有 主 题 的 功 能, 并 不 需 要 接 收 参 数, 所 以 在 Action 中 也 并 不 需 要 使 用 到 ActionForm 选 中 action 子 包, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 New Other 命 令,

201 将 弹 出 选 择 创 建 程 序 的 界 面, 在 其 中 选 择 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 范

202 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"/>

203 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 表 达 式 是 一 样 的 开 发 删 除 主 题 功 能 在 显 示 所 有 主 题 页 面 中, 单 击 删 除 超 链 接, 就 会 将 该 行 的 主 题 记 录 删 除 在 本 小 节 中 就 来 完 成 删 除 主 题 的 功 能 在 删 除 主 题 Action 中 要 使 用 主 题 ActionForm 来 接 收 传 递 的 id 属 性 值, 主 题 ActionForm 已 经 存 在 了, 所 以 不 需 要 再 次 创 建 在 选 择 创 建 程 序 界 面 中, 选 择 struts 1.2 Action 选 项, 单 击 Next 按 钮, 将 弹 出 创 建 Action 程 序 的 界 面, 输 入 删 除 Action 的 相 关 信 息 后, 如 图 6-33 所 示

204 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, 那 就 不 再 具 有 程 序 的 重 用 性, 同 时 也 会 造 成 程 序 过 分 膨 胀

205 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 命 令, 将 开 始 运 行 服 务 器 启 动 服 务 器 完 成 后, 打 开 浏 览 器, 输 入 如 下 地 址 : 将 进 入 论 坛 项 目 首 页, 也 就 是 发 表 主 题 页 面, 在 其 中 发 表 一 条 主 题, 运 行 结 果 如 图 6-35 所 示

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

207 图 6-37 删 除 主 题 因 为 目 前 我 们 只 有 一 条 主 题, 所 以 删 除 该 主 题 后, 将 在 页 面 中 显 示 数 据 库 中 还 没 有 主 题 的 信 息 使 用 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;

208 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 时, 需 要 给 出 相 应 的 参 数, 例 如 要 访 问 查 询 所 有 主 题 方 法, 则 访 问 地 址 为 : command= findall 其 中 topic.do 就 是 对 Action 进 行 的 路 径, command 是 我 们 在 界 面 中 配 置 的 Action 参 数, findall 指 定 调 用 的 是 哪 一 个 方 法 读 者 可 以 自 己 来 将 本 节 中 开 发 的 论 坛 项 目 修 改 成 DispatchAction 的 形 式 说 明 :DispatchAction 在 实 际 开 发 中 使 用 是 非 常 多 的, 但 是 也 不 是 将 所 有 的 功 能 都 写 到 一 个 Action 中, 而 是 将 一 类 功 能 放 在 一 起, 例 如 对 主 题 的 操 作 功 能 就 都 写 在

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

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

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

212 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 所 示

213 图 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 所 示

214 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 所 示

215 图 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 框 架 支 持 的 操 作 认 识 Hibernate 项 目 结 构 加 入 Hibernate 框 架 支 持 后, 在 项 目 中 会 自 动 加 入 Hibernate 的 相 关 JAR 包, 以 及 Hibernate 的 配 置 文 件 和 会 话 工 厂 类 在 包 资 源 管 理 器 中 将 项 目 展 开, 如 图 7-6 所 示

216 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 {

217 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) {// 设 置 新 的 配 置 文 件

218 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 自 动 创 建, 不 需 要 自 己 手 动 编 写 这 里 只 需 要 对 它 有 所 了 解, 它 们 会 使 用 会 话 工 厂 类 就 可 以 了 认 识 Hibernate 的 配 置 文 件 Hibernate 配 置 文 件 也 是 Hibernate 项 目 的 重 要 组 成 部 分, 由 于 它 的 内 容 比 较 多, 将 它 单 独 放 在 一 小 节 中 进 行 讲 解 双 击 hibernate.cfg.xml 文 件 在 编 辑 打 开 后, 在 编 辑 区 的 左 下 角 可 以 看 到 有 三 个 选 项, 它 们 对 应 着 三 种 显 示 文 件 的 方 式 Configuration 选 项 表 示 界 面 化 的 显 示 Hibernate 配 置 信 息, 选 择 该 选 项 后, 界 面 如 图 7-7 所 示

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

220 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 中 需 要 配 置 的 属 性 和 属 性 值

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

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

223 图 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 通 用 开 发 视 图 中

224 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 属 性 指 定 的 就 是 实 体 类 名 称, 实 体 类 会 在 下 一 小 节 中 讲 解 如 何 创 建

225 在 第 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 属 性 值 的 格 式, 包 名 之 间 不 再 使 用. 连 接, 而 是 使 用 / 连 接 创 建 实 体 类 程 序 创 建 映 射 文 件 后, 继 续 来 看 一 下 如 何 创 建 实 体 类 程 序 使 用 上 一 小 节 同 样 的 操 作 方 式, 打 开 创 建 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 所 示

226 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() {

227 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 版 本 后 有 自 动 装 箱 和 拆 箱 的 特 性 创 建 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 所 示

228 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 对 象 的 方 法, 从 而 获 取 到 操

229 作 数 据 库 的 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() { // 查 询 全 部

230 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 项 目 和 程 序 的 创 建, 它 们 对 于 一 般 功 能 的 项 目 来 说 已 经 足 够 了 但 是 对 于 一 些 功 能 比 较 多, 或 者 数 据 表 关 系 比 较 复 杂 的 项 目 来 说, 就 还 需 要 学 习 更 多 的 内 容 它 们 主 要 体 现 在 映 射 文 件 中, 在 该 文 件 中 进 行 更 详 细 的 配 置 细 节 配 置 细 节 配 置 包 括 映 射 类 主 键 生 成 策 略 多 对 多 一 对 一 等 配 置 在 创 建 Hibernate 创 建 界 面 中, 不 管 是 创 建 映 射 文 件, 还 是 创 建 实 体 类 DAO 程 序 等 都 是 直 接 单 击 Finish 按 钮 完 成 操 作 在 该 界 面 中, 也 可 以 单 击 Next 按 钮, 从 而 进 入 细 节 配 置 的 界 面, 如

231 图 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 生 成 唯 一 标 识

232 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 主 键 生 成 策 略 的 选 择 是 最 重 要 的, 在 实 际 开 发 中 要 灵 活 使 用 这 些 生 成 策 略, 并 能 够 看 懂 项 目 使 用 的 生 成 策 略 数 据 表 和 实 体 类 的 映 射 配 置 在 前 面 自 动 生 成 实 体 类 时, 都 是 根 据 数 据 表 的 表 名 和 字 段 名 自 动 生 成 实 体 类 的 类 名 和 属 性 名 但 是 在 实 际 开 发 中, 开 发 数 据 库 和 开 发 Java 项 目 可 能 并 不 是 一 个 团 队, 这 时 候 可 能 自 动 生 成 的 类 名 和 属 性 名 并 不 符 合 Java 程 序 命 名 规 范 的 例 如 数 据 表 的 名 称 为 db_student, 则 使 用 该 名 称 做 为 实 体 类 的 类 名, 就 会 不 适 合 在 这 种 情 况 下 就 需 要 使 用 到 本 节 讲 解 的 映 射 配 置 在 上 一 小 节 的 细 节 配 置 界 面 中, 单 击 Next 按 钮, 将 进 入 数 据 表 和 实 体 类 映 射 配 置 界 面, 在 其 中 选 中 student 数 据 表 节 点, 界 面 如 图 7-16 所 示

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

234 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 程 序 的 方 式 通 过 使 用 注 解, 能 够 代 替 映 射 文 件, 从 而 也 能 够 让 实 体 类 和 数 据 表 建 立 连 接 注 意 : 注 解 是 一 把 双 刃 剑, 通 过 注 解 可 能 节 省 大 量 的 代 码, 但 是 大 部 分 的 程 序 员 已 经 习 惯 了 通 过 映 射 文 件 的 方 式 开 发, 所 以 在 开 发 中 要 按 照 开 发 要 求 来 进 行 选 择 使 用 创 建 数 据 表 通 过 注 解 方 式 开 发 Hibernate 程 序, 改 变 的 只 是 实 体 类 和 映 射 文 件, 映 射 文 件 将 不

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

236 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 // 省 略 导 入 接 口 和 类 的 代 码 // 注 解 该 类 为 Hibernate 实 体 类 = "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 } // 注 解 实 体 类 标 识 = IDENTITY) // 注 解 主 键 生 成 策 略

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

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

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

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

241 图 7-24 转 换 后 SQL 语 句 说 明 : 由 于 是 框 架 自 动 转 换, 所 以 转 换 后 的 SQL 语 句 是 和 程 序 员 写 出 的 SQL 语 句 有 所 不 同 的 在 自 动 生 成 的 SQL 语 句 中, 大 量 使 用 到 别 名, 例 如 student0_ 是 数 据 表 的 别 名, name10_ 是 name 字 段 的 别 名 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 相 关 资 料 为 HQL 语 句 设 置 参 数 在 实 际 开 发 中, 通 过 给 出 的 查 询 条 件 并 不 是 固 定 的, 而 是 通 过 参 数 传 递 条 件 值 例 如 查 询 某 学 生 的 具 体 信 息, 该 学 生 的 名 称 并 不 是 固 定 的 这 时 候 就 需 要 为 HQL 语 句 设 置 参 数 在 SQL 语 句 中 可 以 通 过 位 置 和 属 性 名 两 种 方 式 完 成 参 数 设 置, 但 是 在 HQL 语 句 中 只 支 持 参 数 名 的 方 式 参 数 的 基 本 格 式 为 :name, 例 如 :

242 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 的 学 生 对 象 查 询 出 来 选 中 该 对 象, 可 以 在 在 右

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

244 35 图 7-28 确 定 是 否 删 除 单 击 OK 按 钮, 将 把 选 中 的 包 和 包 下 的 类 全 部 删 除 删 除 后, 项 目 将 会 发 生 错 误, 这 是 以 为 其 中 调 用 的 数 据 访 问 层 类 已 经 消 失 因 为 我 们 这 个 项 目 将 对 MySQL 中 的 bbs 数 据 库 进 行 操 作, 所 以 我 们 需 要 对 数 据 库 视 图 中 的 连 接 进 行 修 改, 选 中 MySQL 连 接, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Edit 命 令, 将 弹 出 的 对 连 接 信 息 修 改 的 操 作 界 面, 修 改 其 中 的 URL, 界 面 如 图 7-29 所 示 图 7-29 修 改 连 接 信 息 注 意 : 修 改 连 接 时, 必 须 要 首 先 关 闭 连 接 当 然 修 改 后, 不 要 忘 记 再 打 开 为 论 坛 项 目 加 入 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 所 示

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

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

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

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

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

250 码, 则 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); 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 } 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 类 的 子 类, 必 要 的 地 方 进 行 修 改, 具 体 修 改 看 光 盘 代 码

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

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

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

254 北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 第 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 项 目 的 开 发 普 通 的 Java 项 目 Spring 的 项 目 是 基 于 普 通 项 目 的, 然 后 在 普 通 项 目 的 基 础 上 加 入 Spring 的 框 架 支 持 在 MyEclipse 的 菜 单 中, 选 择 File New Java Project 命 令, 就 会 弹 出 创 建 Java

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

256 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 所 示

257 图 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 目 录 下 认 识 Spring 的 项 目 结 构 向 普 通 的 Java 项 目 加 入 Spring 框 架 支 持 后, 将 向 项 目 加 入 Spring 核 心 类 库 和 S 的 配 置 文 件, 在 包 资 源 管 理 器 中, 将 项 目 展 开, 如 图 8-4 所 示

258 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=" 04 xmlns:xsi=" 05 xmlns:p="

259 06 xsi:schemalocation=" </beans> 其 中 <beans> 标 记 就 是 Spring 配 置 文 件 的 根 标 记, 在 该 标 记 对 中 可 以 对 Spring 项 目 中 的 Bean 进 行 配 置 说 明 : 这 里 所 说 的 Bean 其 实 就 是 普 通 的 类, 在 Spring 中 通 过 将 这 些 类 称 为 Bean, 它 和 通 常 所 说 的 规 范 JavaBean 是 不 一 样 的 8.3 开 发 控 制 反 转 程 序 控 制 反 转 是 Spring 的 核 心 技 术, 它 是 英 文 名 称 为 Inversion of Control, 所 以 在 很 多 地 方 将 控 制 反 转 缩 写 为 IoC 控 制 反 转 还 有 另 外 一 个 名 称, 叫 做 依 赖 注 入, 它 的 英 文 名 称 为 Dependency Injection, 简 称 是 DI 它 们 指 的 是 一 种 技 术, 就 是 在 框 架 中 将 对 象 创 建 后, 直 接 注 入 到 调 用 的 程 序 中 创 建 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 的 操 作 来 说, 是 没 有 任 何 用 处 的

260 配 置 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 方 法 方 式 注 入 时 的 设

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

262 9 在 该 界 面 中 可 以 完 成 Lookup 方 法 和 自 定 义 方 法 的 注 入, 对 于 普 通 的 Spring 项 目 而 说, 可 以 忽 略 这 一 步 操 作 单 击 Finish 按 钮, 将 完 成 配 置 Bean 程 序 的 操 作 容 为 : 在 ApplicationContext.xml Spring 的 配 置 文 件 中, 将 自 动 添 加 配 置 代 码, 具 体 内 01 <?xml version="1.0" encoding="utf-8"?> 02 <beans 03 xmlns=" 04 xmlns:xsi=" 05 xmlns:p=" 06 xsi:schemalocation=" <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 自 动 生 成 的, 也 可 以 手 动 去 掉 它 们, 是 不 影 响 功 能 的, 在 后 面 的 讲 解 中 会 说 明 它 们 的 作 用 编 写 测 试 类 在 实 际 开 发 中, 测 试 类 并 不 是 必 须 的, 但 是 通 过 都 会 有 该 程 序, 通 过 它 可 以 判 断 开 发 的 局 部 程 序 是 否 正 确 在 本 节 中 就 来 开 发 这 样 的 测 试 类, 通 过 它 来 测 试 是 否 能 够 将 配 置 文 件 中 的 值 注 入 到 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 }

263 13 } 其 中 第 7 行 是 实 例 化 IoC 容 器 的 代 码, 第 9 行 中 通 过 容 器 实 例 化 指 定 的 Bean, 在 第 11 行 中 调 用 sayhello 业 务 方 法, 从 而 完 成 相 应 功 能 运 行 该 程 序, 运 行 结 果 为 : 内 容 为 :Hello everyone 从 运 行 结 果 中 可 以 看 到, 已 经 将 Spring 配 置 文 件 中 的 值 注 入 到 Bean 程 序 中 说 明 : 从 测 试 类 中 也 可 以 看 到, 我 们 并 没 有 通 过 new 来 创 建 Bean 实 例, 就 可 以 调 用 其 中 的 业 务 方 法, 这 就 是 控 制 反 转 的 作 用 8.4 依 赖 注 入 在 前 面 已 经 讲 解 过, 控 制 反 转 和 依 赖 注 入 指 的 是 同 一 个 技 术 但 是 使 用 名 称 时 又 有 些 小 的 不 同, 当 指 整 个 技 术 时, 通 常 叫 做 控 制 反 转 ; 当 指 注 入 操 作 时, 通 常 叫 做 依 赖 注 入 在 本 节 中, 就 主 要 来 讲 解 一 下 注 入 的 操 作, 包 括 注 入 方 式 和 注 入 类 型 等, 看 一 下 MyEclipse 中 是 如 何 操 作 它 们 的 注 入 方 式 依 赖 注 入 有 两 种 常 用 的 方 式, 分 别 是 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 所 示

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

265 参 数 类 型 相 同 情 况 的 麻 烦 这 两 个 选 项 也 可 以 同 时 填 写, 但 是 一 定 要 全 部 和 构 造 函 数 中 的 参 数 对 应 正 确 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 可 以 看 到, 通 过 构 造 函 数 注 入 也 是 正 确 的 注 入 其 他 Bean 在 前 面 的 讲 解 中 都 是 向 Bean 中 注 入 字 符 串 类 型, 对 于 基 本 数 据 类 型 来 说, 是 和 字 符 串 类 型 完 全 一 样 的 在 本 小 节 中 将 继 续 来 讲 解 如 何 向 Bean 中 注 入 其 他 Bean, 在 实 际

266 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 所 示

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

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

269 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 方 法 中 将 调 用 数 据 访 问 层 实 现 类 中 的 方 法, 如 果 注 入 成 功, 将 能 够 成 功 调 用 运 行 该 程 序, 运 行 结 果 为 :

270 17 Tom 是 否 能 够 正 常 登 录 :true 从 运 行 结 果 中 可 以 看 到, 向 业 务 逻 辑 层 中 注 入 数 据 访 问 层 成 功 注 入 集 合 在 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 所 示

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

272 所 示 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 所 示

273 图 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>

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

275 在 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 值 说 明 : 不 完 全 依 赖 的 情 况 在 数 据 库 开 发 中 比 较 常 见, 例 如 注 册 数 据 驱 动 必 须 在 所 有 操 作 之 前 完 成, 但 是 在 操 作 中 是 不 会 调 用 驱 动 的 延 迟 初 始 化 Bean 在 Spring 框 架 中, 默 认 情 况 下 当 启 动 项 目 后, 会 将 所 有 已 经 配 置 的 单 例 Bean 全 部 实 例 化, 其 中 包 括 配 置 的 和 注 入 的 这 样 做 的 好 处 就 是 在 启 动 时, 如 果 配 置 文 件 中 有 什 么 错 误, 将 会 立 刻 发 现 但 是 这 样 做, 并 不 是 适 合 所 有 情 况 的, 在 特 殊 情 况 下, 我 们 并 不 想 让 Bean 在 启 动 的 时 候 就 马 上 实 例 化 这 时 候 也 可 以 通 过 配 置, 将 它 设 置 为 延 迟 初 始 化 在 MyEclipse 的 配 置 界 面 中, 集 成 了 该 功 能, 例 如 我 们 将 Hello 程 序 设 置 为 延 迟 初 始 化 Bean, 它 的 配 置 界 面 如 图 8-21 所 示

276 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 甲 的 延 迟 初 始 化 的 设 置 就 会 失 效 自 动 装 配 在 前 面 讲 解 注 入 其 他 Bean 时, 都 是 通 过 直 接 配 置 的 方 式 注 入 的 在 Spring 框 架 的 容 器 中, 还 可 以 通 过 自 动 装 配 的 方 式, 让 容 器 自 动 进 行 注 入 其 他 Bean 的 操 作 在 MyEclipse 中, 也 集 成 了 自 动 装 配 的 功 能 我 们 再 次 以 用 户 业 务 逻 辑 实 现 类 为 例, 在 配 置 它 的 弹 出 界 面, 选 择 自 动 装 配, 界 面 如 图 8-22 所 示

277 图 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" />

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

279 simple: 对 基 本 类 型 和 集 合 进 行 依 赖 注 入 检 查 object: 当 注 入 其 他 Bean 时, 进 行 依 赖 注 入 检 查 all: 对 所 有 类 型 都 进 行 依 赖 注 入 检 查 在 Spring 的 配 置 文 件 中, 将 采 用 dependency-check 属 性 对 依 赖 注 入 检 查 进 行 配 置 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 定 义 对 应 一 个 实 例

280 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 作 用 域 方 法 注 入 在 上 一 小 节 中, 已 经 学 习 了 Bean 作 用 域 的 知 识 在 默 认 情 况 下,Ioc 容 器 中 的 所 有 Bean 的 作 用 域 都 是 singleton, 我 们 也 可 以 手 动 改 变 作 用 域 当 改 变 Bean 的 作 用 域 后, 进 行 注 入 其 他 Bean 操 作 时 就 可 以 产 生 问 题, 例 如 向 一 个 作 用 域 为 singleton 的 Bean 甲 中 注 入 作 用 域 为 prototype 的 Bean 乙 对 于 Bean 甲 来 说, 容 器 只 会 创 建 一 个 Bean 甲 实 例, 这 样 就 没 法 让 容 器 提 供 不 同 的 Bean 乙 实 例 为 了 解 决 这 个 问 题, 就 需 要 放 弃 控 制 反 转, 而 是 采 用 方 法 注 入 的 方 式 方 法 注 入 分 为 两 种, 分 别 是 Lookup 方 法 注 入 和 自 定 义 方 法 注 入 在 MyEclipse 中 也 集 成 了 方 法 注 入 的 操 作, 在 配 置 Bean 界 面 中, 单 击 Next 按 钮, 将 进 入 方 法 注 入 界 面, 如 图 8-25 所 示

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

282 定 义 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 所 示

283 图 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) {

284 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 容 器 操 作, 就 需 要 在 销 毁 方 法 中 完 成 Bean 中 的 继 承 继 承 是 Java 编 程 语 言 的 三 大 特 性 之 一, 继 承 的 类 称 为 子 类, 被 继 承 的 类 称 为 父 类 在 Spring 的 配 置 文 件 中, 对 Bean 程 序 的 配 置 也 存 在 父 子 关 系 在 配 置 Bean 时 可 以 通 过 操 作 让 它 继 承 已 有 的 配 置 Bean 信 息, 它 们 分 别 被 称 为 子 Bean 配 置 和 父 Bean 配 置 在 子 Bean 配 置 中 可 以 继 承 父 Bean 配 置 的 数 据, 也 可 以 覆 盖 原 有 数 据 或 者 添 加 新 配 置 在 MyEclipse 中, 也 集 成 了 进 行 集 成 配 置 的 功 能 在 配 置 Bean 界 面 中, Parent bean Id 选 项 就 是 用 来 选 择 父 Bean 配 置 的 id, 如 图 8-28 所 示 图 8-28 继 承 配 置

285 单 击 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 项 目 的 功 能, 所 以 在 本 节 中 主 要 通 过 手 动 编 程 程 序 的 方 式 进 行 讲 解 准 备 工 作 在 FirstSpring 项 目 中 是 不 能 够 继 续 开 发 AOP 项 目 的, 因 为 在 其 中 并 没 有 加 入 AOP 开 发 所 需 要 的 类 库, 所 以 这 里 单 独 再 创 建 一 个 名 称 为 SpringAOP 的 项 目 开 发 完 普 通 的 Java 项 目 后, 将 执 行 加 入 Spring 框 架 支 持 的 操 作, 在 添 加 类 库 界 面 中, 不 但 要 加 入 Spring 核 心 类 库, 还 要 加 入 AOP 开 发 的 类 库, 如 图 8-29 所 示

286 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=" 04 xmlns:xsi=" 05 xmlns:p=" 06 xmlns:aop=" 07 xsi:schemalocation=" </beans> 其 中 新 加 入 的 是 第 6 行 第 9 行 和 第 10 行 这 些 代 码 可 以 通 过 Spring 的 下 载 安 装 包 中 找 到 对 应 文 件, 不 过 为 了 方 便, 读 者 只 需 要 复 制 本 书 光 盘 中 的 该 文 件 就 可 以 进 行 开 发 了 通 过 配 置 方 式 开 发 AOP 项 目 开 发 AOP 项 目 由 两 种 方 式, 分 别 是 通 过 配 置 方 式 和 通 过 注 解 方 式, 注 解 方 式 是 Java

287 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" />

288 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 项 目 运 行 正 确 通 过 注 解 方 式 开 发 AOP 项 目 注 解 是 Java 5.0 版 本 中 提 出 的 新 特 性 技 术, 通 过 注 解 可 以 是 一 个 普 通 的 Java 程 序 完 成 特 定 的 功 能 也 就 是 说 当 需 要 完 成 一 个 特 定 功 能 时, 只 需 要 对 普 通 Java 程 序 进 行 相 应 注 解 就 可 以 完 成 当 使 用 注 解 方 法 开 发 时, 要 首 先 在 配 置 文 件 中, 加 入 如 下 配 置 代 码 : <aop:aspectj-autoproxy/> 通 过 它 可 以 启 动 AspectJ 组 件 技 术 在 Spring 的 开 发 中 要 结 合 它 来 进 行 操 作 使 用 注 解 方 式 开 发 和 使 用 配 置 方 法 开 发 最 大 的 不 同 就 是 面 向 切 面 编 程 类, 在 该 类 中 进 行 了 面 向 切 面 中 每 一 部 分 的 注 解, 从 而 不 再 需 要 在 配 置 文 件 中 进 行 配 置 这 里 我 们 来

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

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

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

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

293 其 中 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 所 示

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

295 图 9-7 创 建 会 话 工 厂 类 该 创 建 界 面 是 和 Hibernate 项 目 中 创 建 界 面 相 同 的 在 其 中 需 要 为 会 话 工 厂 类 定 义 新 创 建 一 个 包, 这 里 仍 然 采 用 hb 的 包 名 单 击 Finish 按 钮, 将 完 成 加 入 Hibernate 框 架 支 持 的 操 作 认 识 整 合 后 的 项 目 向 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=" 04 xmlns:xsi=" 05 xmlns:p=" 06 xsi:schemalocation="

296 <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 属 性 的 类 型 是 映 射 文 件 集 合, 目 前 只 有 一 个 值, 那 就 是 数 据 库 方 言 当 有 其 他 属 性 配 置 时, 可 以 以 元 素 的 形 式 加 到 该 集 合 中 开 发 整 合 的 DAO 程 序 当 Spring 和 Hibernate 整 合 后, 再 来 开 发 DAO 程 序, 则 生 成 的 代 码 是 和 原 只 有 Hibernate 时 生 成 的 不 一 样 的 同 样 要 首 先 进 入 MyEclipse 的 数 据 库 视 图 中, 打 开 MySQL 连 接, 在 其 中 选 择 操 作 的 数 据 表 节 点 例 如 这 里 仍 然 选 择 mydb 数 据 库 下 的 student 数 据 表 单 击 鼠 标 右 键, 在 其 中 选 择 Hibernate Reverse Engineering 命 令, 将 弹 出 创 建 Hibernate 程 序 的 界 面, 填 写 必 要 信 息 后, 如 图 9-9 所 示

297 图 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 {

298 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 方 法 中, 通

299 过 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 对 象 进 行 数 据 库 操 作 事 务 管 理 自 动 生 成 的 DAO 程 序 中 是 没 有 事 务 操 作 的, 以 前 的 做 法 是 继 承 自 动 生 成 的 DAO 程 序, 在 重 写 方 法 中 加 入 事 务 操 作 当 整 合 Spring 技 术 后, 完 全 没 有 必 要 这 样 操 作, 我 们 可 以 通 过 Spring 来 对 事 务 进 行 管 理 在 Spring 中 进 行 事 务 管 理 有 两 种 方 式, 分 别 是 编 程 式 事 务 管 理 和 声 明 式 事 务 管 理, 这 里 我 们 主 要 讲 解 最 常 用 的 声 明 式 事 务 管 理 使 用 声 明 式 事 务 管 理, 可 以 无 需 修 改 项 目

300 11 中 的 原 代 码, 只 需 要 在 Spring 配 置 文 件 中 进 行 相 应 配 置 就 可 以 声 明 式 事 务 管 理 的 配 置 代 码 如 下 所 示 01 <?xml version="1.0" encoding="utf-8"?> 02 <beans 03 xmlns=" 04 xmlns:xsi=" 05 xmlns:p=" 06 xmlns:aop=" 07 xmlns:tx=" 08 xsi:schemalocation=" <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 行 定 义 的 需 要 事 务 处 理 的 方 法

301 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); // 设 置 学 生 成 绩

302 13 14 studentdao.save(student); // 保 存 学 生 15 } 16 } 上 述 代 码 中 第 10 行 获 取 学 生 DAO 程 序 对 象 在 第 11 行 中 创 建 了 学 生 对 象, 并 依 次 将 姓 名 和 成 绩 设 置 到 对 象 中 在 第 14 行 中 调 用 DAO 程 序 中 的 save 方 法, 从 而 将 学 生 对 象 信 息 保 存 到 数 据 库 中 切 换 到 MyEclipse 中 的 数 据 库 视 图 中, 查 看 学 生 数 据 表 可 以 发 现 多 出 了 一 条 学 生 记 录, 字 段 内 容 就 是 测 试 类 中 设 置 的, 从 而 表 明 Spring 和 Hibernate 整 合 的 项 目 开 发 完 成 通 过 注 解 方 式 进 行 事 务 管 理 在 学 习 Spring 的 面 向 切 面 编 程 时, 已 经 知 道 可 以 通 过 注 解 的 方 式 进 行 开 发 在 进 行 事 务 管 理 中, 也 可 以 通 过 注 解 的 方 式 完 成 该 功 能, 而 且 要 比 配 置 的 方 式 简 单 很 多 在 MyEclipse 的 数 据 库 视 图 中, 再 以 teacher 老 师 数 据 表 为 例 进 行 操 作, 从 而 生 成 Hibernate 的 程 序, 包 括 实 体 类 映 射 文 件 和 DAO 程 序 打 开 自 动 生 成 的 DAO 程 序, 在 类 名 上 加 入 如 下 注 解 代 码 通 过 该 代 码, 标 注 对 该 类 中 的 方 法 进 行 事 务 管 理 然 后 在 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 } 运 行 该 程 序, 是 不 会 发 生 错 误 的 在 数 据 库 视 图 中 查 看 数 据 库 数 据, 可 以 看 到 测 试 类 中 的 测 试 数 据 已 经 保 存 到 数 据 库 中, 表 明 事 务 处 理 成 功 说 明 : 通 过 本 节 的 程 序, 可 以 看 到 使 用 注 解 方 式 进 行 事 务 管 理 要 比 配 置 方 式 简 单 很 多, 但 是 目 前 开 发 中 使 用 最 多 的 还 是 配 置 方 式, 所 以 读 者 要 将 这 两 种 方 式 都 掌 握

303 9.2 Struts+Spring 整 合 开 发 Struts 和 Spring 整 合 主 要 的 目 的 就 是 让 Spring 管 理 Struts 中 的 Action, 并 且 将 业 务 逻 辑 层 注 入 到 Action 中 Struts 和 Spring 的 整 合 有 多 种 方 式, 这 里 选 择 一 种 最 通 用 最 优 秀 的 整 合 方 式 进 行 讲 解 创 建 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 所 示

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

305 单 击 Finish 按 钮, 将 完 成 加 入 Spring 框 架 支 持 的 操 作 认 识 Struts+Spring 的 整 合 项 目 依 次 加 入 Struts 和 Spring 的 框 架 支 持 后, 在 MyEclipse 的 包 资 源 管 理 器 中 展 开 StrutsAndSpring 项 目, 项 目 结 构 如 图 9-14 所 示 图 9-14 整 合 项 目 结 构 整 合 后 的 项 目 结 构 是 和 Struts 项 目 结 构 相 差 不 大 的, 只 是 在 其 中 加 入 了 Spring 的 两 个 类 库, 并 且 Spring 的 配 置 文 件 并 不 直 接 放 在 src 目 录 下, 而 是 放 在 了 WebRoot WEB-INF 目 录 下 注 意 : 将 Spring 的 配 置 文 件 放 在 src 目 录 下 也 是 可 以 的, 当 部 署 项 目 后, 它 会 自 动 放 在 WebRoot WEB-INF classes 目 录 下 这 两 种 放 置 方 式 可 能 造 成 后 面 的 配 置 有 所 不 同 整 合 插 件 配 置 在 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 容 器

306 17 注 意 :Spring 的 配 置 文 件 也 可 以 有 多 个, 在 配 置 时 只 需 要 将 这 些 配 置 文 件 到 放 在 第 3 行 的 value 属 性 中 就 可 以, 之 间 使 用 逗 号 分 隔 这 里 也 可 以 使 用 通 配 符, 例 如 /WEB-INF/applicationContext-*.xml 就 表 示 所 有 以 applicationcontext 开 头 的 配 置 文 件 注 意 : 当 项 目 中 的 Spring 配 置 文 件 不 在 WEB-INF 目 录 下 时, 这 里 也 需 要 改 动 这 里 的 配 置 例 如 直 接 放 在 src 目 录 下, 则 value 的 值 应 该 为 /WEB-INF/classes/applicationContext.xml 开 发 业 务 逻 辑 层 并 配 置 这 里 就 通 过 一 个 简 单 的 登 录 程 序 来 举 例, 在 其 中 定 义 完 成 登 录 功 能 的 业 务 方 法 业 务 逻 辑 层 实 现 类 的 代 码 如 下 所 示 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 所 示

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

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

309 图 9-19 创 建 Action 单 击 Finish 按 钮, 将 完 成 Action 的 创 建, 也 就 完 成 全 部 Struts 程 序 的 创 建 并 且 同 时 在 Struts 配 置 文 件 中 完 成 对 ActionForm 和 Action 的 创 建 开 发 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 {

310 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, 从 而 跳 转 到 登 录 成 功 页 面, 这 是 在 配 置 文 件 中 配 置 的 所 以 在 项 目 中 还 要 创 建 登 录 成 功 页 面, 该 页 面 是 非 常 简 单 的, 读 者 可 以 自 己 查 看 光 盘 当 登 录 失 败, 或 者 发 生 异 常 时, 将 重 新 回 答 登 录 页 面 对 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 所 示

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

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

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

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

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

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

317 单 击 Next 按 钮, 将 进 入 选 择 Hiibernate 配 置 信 息 支 持 的 界 面, 在 其 中 选 择 第 2 个 选 项, 让 Spring 的 配 置 文 件 对 数 据 库 的 相 关 信 息 管 理 单 击 Next 按 钮, 将 进 入 配 置 会 话 工 厂 类 的 界 面, 选 择 使 用 已 有 Spring 配 置 文 件, 其 他 采 用 默 认 值 单 击 Next 按 钮, 将 进 入 配 置 数 据 库 连 接 的 界 面, 在 其 中 选 择 MySQL, 如 图 9-31 所 示 图 9-31 建 立 数 据 库 连 接 单 击 Next 按 钮, 将 进 入 创 建 会 话 工 厂 类 的 界 面, 将 它 定 义 在 com.sanqing.hb 包 中, 单 击 Finish 按 钮, 将 完 成 加 入 Hibernate 框 架 支 持 的 操 作 加 入 三 种 框 架 支 持 后, 读 者 可 以 自 己 简 单 的 了 解 一 下 项 目 结 构, 这 里 就 不 在 抓 图 讲 解 了 注 意 : 加 入 三 种 框 架 后, 经 常 会 出 现 相 同 包 之 间 重 复 的 错 误, 这 是 因 为 有 可 能 三 个 框 架 中 都 引 入 了 用 一 个 JAR 包, 这 时 候 只 需 要 将 重 复 的 JAR 包 去 掉 就 可 以 最 常 见 的 就 是 asm.jar 包 重 复 进 行 整 合 配 置 仅 仅 加 入 框 架 支 持 后, 是 还 不 能 进 行 整 合 开 发 的, 还 需 要 进 行 必 要 的 配 置 首 先 是 在 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">

318 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 文 件 头 信 息 开 发 数 据 访 问 层 在 实 际 开 发 中,Java 项 目 的 开 发 顺 序 通 常 是 固 定 的, 从 数 据 访 问 层 开 始, 然 后 是 业 务 逻 辑 层, 最 后 是 控 制 层 和 显 示 层 在 SSH 框 架 整 合 项 目 也 是 按 照 这 个 顺 序 的, 我 们 先 来 开 发 数 据 访 问 层, 通 过 它 可 以 进 行 基 本 的 数 据 库 操 作 在 MyEclipse 的 数 据 库 视 图 中, 选 中 要 操 作 的 数 据 表 节 点, 例 如 这 里 选 中 MySQL Connection to MySQL blog TABLE user 节 点, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中 选 择 Hibernate Reverse Engineering 命 令, 将 弹 出 创 建 Hibernate 程 序 的 界 面, 在 其 中 选 择 创 建 实 体 类 映 射 文 件 和 DAO 程 序, 如 图 9-32 所 示

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

320 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 所 示

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

322 开 发 文 章 业 务 逻 辑 层 在 文 章 业 务 逻 辑 层 中 要 完 成 对 文 章 进 行 操 作 的 功 能, 包 括 显 示 网 站 所 有 文 章 显 示 某 用 户 所 有 文 章 显 示 某 一 文 章 详 细 内 容 发 表 文 章 删 除 文 章 和 对 文 章 进 行 修 改 等 功 能 同 样 在 文 章 业 务 逻 辑 实 现 类 中 定 义 数 据 访 问 接 口 引 用, 并 为 它 定 义 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 所 示

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

324 开 发 评 论 业 务 逻 辑 层 在 评 论 业 务 逻 辑 层 中 要 完 成 对 评 论 进 行 操 作 的 功 能, 包 括 发 表 评 论, 显 示 文 章 所 有 评 论 和 获 取 文 章 评 论 数 量 等 功 能 在 评 论 业 务 逻 辑 实 现 类 中 要 定 义 评 论 数 据 访 问 接 口 引 用, 并 为 它 定 义 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 所 示

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

326 开 发 首 页 控 制 层 因 为 本 节 中 讲 解 的 博 客 显 示 是 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) {

327 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 } 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 所 示

328 39 图 9-41 配 置 首 页 Action 单 击 Finish 按 钮, 将 完 成 对 指 向 首 页 Action 的 Spring 配 置 在 其 中 将 所 需 要 的 业 务 逻 辑 实 现 类 对 象 注 入 开 发 用 户 控 制 层 在 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 所 示

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

330 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) {

331 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 的 配 置 开 发 个 人 博 客 控 制 层 在 博 客 网 站 中 成 功 注 册 后, 就 会 拥 有 属 于 自 己 的 个 人 博 客 注 册 和 登 录 成 功 后, 就 会 自 动 进 入 自 己 的 博 客 在 首 页 中 的 用 户 栏 中, 单 击 用 户 超 链 接, 或 者 在 文 章 标 题 后 单 击 用 户 超 链 接 都 会 进 入 该 用 户 的 个 人 博 客 在 本 小 节 中 就 来 开 发 完 成 该 功 能 的 个 人 博 客 控 制 层 在 创 建 Ation 的 界 面 中, 输 入 进 入 个 人 博 客 的 必 要 信 息, 如 图 9-44 所 示

332 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{

333 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 所 示

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

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

336 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());

337 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 所 示

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

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

340 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());

341 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 程 序 显 示 层 的 开 发 是 非 常 简 单 的, 这 里 就 不 再 详 细 讲 解

342 53

343 北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 第 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 项 目 开 发 插 件 安 装 Struts 2 插 件 在 MyEclipse 中, 所 有 的 功 能 都 是 通 过 插 件 完 成 的 只 是 有 些 插 件 在 安 装 MyEclipse 时 就 已 经 默 认 安 装 了, 例 如 前 面 介 绍 的 Hibernate 和 Spring 开 发 但 是 对 于 Struts 2 来 说, 默 认 安 装 MyEclipse 时, 是 不 会 自 动 安 装 它 的 插 件 的, 所 以 需 要 手 动 安 装 安 装 插 件 有 两 种 方 式, 分 别 是 在 线 安 装 和 本 地 安 装, 这 里 我 们 选 择 比 较 容 易 的 在 线 安 装 在 MyEclipse 的 菜 单 中, 选 择 Help Software update Add/Remove Software 命 令, 经 过 一 段 时 间 后, 将 弹 出 如 图 10-1 所 示 的 界 面

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

345 3 在 界 面 中 Name 文 本 框 中 输 入 Struts 2, URL 文 本 框 中 输 入 单 击 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 所 示

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

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

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

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

350 认 识 Struts 2 项 目 开 发 完 Struts 2 项 目 后, 我 们 来 简 单 的 认 识 一 下 Struts 2 项 目 结 构 在 包 资 源 管 理 器 中, 将 它 展 开, 如 图 所 示 图 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 程 序 双 击 打 开 该 文 件,

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

352 图 创 建 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 的 创 建, 并 将 其 显 示 在 创 建 操 作 界 面 中, 如 图 所 示 图 显 示 Action 双 击 其 中 的 图 标 将 弹 出 创 建 Action 类 的 界 面, 如 图 所 示

353 11 图 创 建 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 执 行 跳 转 这 一 简 单 操 作 创 建 JSP 显 示 程 序 在 Struts 2 插 件 中 也 集 成 了 创 建 JSP 显 示 程 序 的 功 能, 单 击 功 能 按 钮 工 具 栏 中 的 按 钮, 将 打 开 用 于 创 建 JSP 程 序 的 视 图 界 面, 如 图 所 示

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

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

356 其 中 Link Name 表 示 链 接 的 名 称, 也 就 是 Action 中 的 返 回 值, 这 里 填 写 success Fwd type 表 示 跳 转 类 型, 采 用 默 认 的 dispatcher 就 可 以 Params 表 示 跳 转 时 传 递 的 参 数, 不 填 写 表 示 不 传 递 参 数 单 击 OK 按 钮, 将 完 成 链 接 的 创 建 创 建 链 接 后, 显 示 界 面 如 图 所 示 图 创 建 链 接 后 界 面 保 存 工 程 文 件, 将 完 成 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 行 的 注 册 页 面 运 行 Struts 2 项 目 因 为 使 用 Struts 2 插 件 使 用 的 并 不 是 前 面 Web 一 章 中 介 绍 的 Java Web 项 目, 所 以 它 的 部 署 和 运 行 也 是 有 所 不 同 的 在 包 资 源 管 理 器 中, 选 中 FirstStruts2 项 目 节 点, 单 击 鼠 标 右 键, 选 择 Run Ads Run on Server 命 令, 将 弹 出 发 布 界 面, 在 其 中 选 择 Tomcat 服 务 器, 如 图 所 示

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

358 10.3 手 动 搭 建 Struts 2 开 发 环 境 使 用 Struts 2 插 件 虽 然 能 够 视 图 化 的 创 建 Struts 2 项 目 和 程 序, 但 是 操 作 起 来 远 比 前 面 三 种 框 架 的 复 杂 而 且 该 插 件 和 MyEclipse 集 成 并 不 好, 它 更 倾 向 于 和 Eclipse 集 成 所 以 在 本 节 中 将 来 学 习 一 下 如 何 手 动 的 搭 建 Struts 2 开 发 环 境, 它 也 是 不 难 操 作 的 下 载 和 安 装 Struts 2 类 库 Struts 2 框 架 是 由 Apache 开 源 组 织 开 发 并 负 责 维 护 的, 它 的 官 方 网 站 为 目 前 Struts 2 最 新 版 本 是 2.1.8, 它 的 下 载 地 址 是 其 中 有 多 个 版 本 的 下 载 链 接, 如 图 所 示 图 下 载 版 本 在 页 面 包 括 如 下 下 载 链 接 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 框 架 的 全 部 源 代 码

359 17 在 lib 下 包 含 了 Struts 2 开 发 的 核 心 JAR 包, 其 中 最 重 要 的 就 是 common-logging jar commons-fileupload jar freemarker jar struts2-core jar xwork jar 和 ognl jar 这 几 个 JAR 包, 将 它 们 复 制 到 项 目 中 例 如 我 们 这 里 创 建 一 个 SecondStruts2 目 录, 将 核 心 JAR 包 复 制 到 WebRoot WEB-INF lib 目 录 下, 这 样 就 搭 建 了 Struts 2 项 目 的 开 发 环 境 说 明 : 上 述 导 入 的 JAR 包 只 是 核 心 JAR 包, 如 果 需 要 进 行 更 多 的 功 能, 还 要 导 入 其 他 的 JAR 包, 这 些 都 在 lib 目 录 下 配 置 Web 描 述 符 在 Web 项 目 中, web.xml 文 件 是 必 不 可 少 的, 当 进 行 Struts 2 项 目 开 发 时, 在 该 文 件 中 需 要 对 Struts 2 的 核 心 控 制 器 进 行 配 置 配 置 代 码 如 下 所 示 01 <?xml version="1.0" encoding="utf-8"?> 02 <web-app version="2.5" 03 xmlns=" 04 xmlns:xsi=" 05 xsi:schemalocation=" <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 创 建 Struts 2 配 置 文 件 和 其 他 框 架 一 样,Struts 2 框 架 也 有 自 己 的 配 置 文 件, 在 其 中 完 成 对 Action 的 配 置

360 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 文 件 的 界 面, 如 图 所 示 图 创 建 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 " 05 <struts> 06 <package name="default" extends="struts-default"> </package> 09 </struts> 其 中 第 5 行 的 <struts> 标 记 是 Struts 2 配 置 文 件 的 根 标 记, 对 于 不 同 类 的 Action 来 说 可 以 定 义 不 同 的 package 在 根 标 记 下 创 建 <package> 标 记 来 包 含 一 类 Action

361 手 动 开 发 Struts 2 程 序 在 前 面 已 经 讲 解 了 通 过 Struts 2 插 件 的 方 式 开 发 Struts 2 程 序, 在 本 节 中 将 讲 解 通 过 手 动 的 方 法 开 发 Struts 2 程 序, 这 也 不 是 困 难 的 在 本 节 中 通 过 一 个 简 单 的 登 录 功 能 来 进 行 讲 解, 其 中 包 括 填 写 登 录 的 表 单 页 面 程 序 进 行 处 理 的 登 录 Action 程 序 和 显 示 登 录 结 果 的 页 面 程 序 开 发 登 录 页 面 程 序 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 结 尾, 并 且 前 面 没 有 / 开 发 处 理 登 录 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 的 相 关 信 息 后, 如 图 所 示

362 图 创 建 登 录 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 }

363 21 上 述 代 码 中 第 4 行 和 第 5 行 分 别 定 义 了 用 户 名 和 密 码 属 性, 并 为 它 们 定 义 了 Getter 和 Setter 方 法, 从 而 能 够 获 取 提 交 表 单 中 的 内 容 在 第 18 行 中 的 处 理 方 法 中, 判 断 用 户 名 和 密 码 是 否 为 指 定 内 容, 从 而 返 回 不 同 的 字 符 串 对 登 录 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 行 是 配 置 了 登 录 失 败 页 面, 和 配 置 成 功 页 面 相 似 的 发 布 并 运 行 登 录 项 目 在 前 面 学 习 通 过 插 件 方 式 开 发 Struts 2 项 目 时, 发 布 项 目 是 和 本 书 前 面 讲 到 的 发 布 方 式 有 很 大 不 同 的 但 是 如 果 通 过 手 动 开 发 Struts 2 项 目, 那 么 和 发 布 普 通 Web 项 目 没 有 区 别 的 在 Servers 界 面 中 选 中 Tomcat 6.x 服 务 器, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Add Deployment 命 令, 将 弹 出 指 定 服 务 器 发 布 界 面, 在 其 中 选 择 SecondStruts2 项 目 进 行 发 布 然 后 选 中 Tomcat 6.x 服 务 器, 单 击 鼠 标 右 键, 在 弹 出 的 菜 单 中, 选 择 Run Server 命 令, 将 开 始 启 动 服 务 器 启 动 服 务 器 成 功 后, 打 开 浏 览 器 中, 在 其 中 输 入 如 下 地 址 : 运 行 结 果 如 图 所 示

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

365 23

366 北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 第 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 包, 在 本 节 中 将 主 要 讲 解 它 们 之 间 的 整 合 操 作 创 建 整 合 项 目 因 为 在 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 所 示

367 图 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 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 容 器 开 发 业 务 逻 辑 层 并 配 置 在 Struts 2 一 章 中 是 以 登 录 程 序 来 讲 解 了 如 何 开 发 Struts 2 程 序 这 里 我 们 通 过 通 过

368 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 所 示

369 图 11-4 配 置 业 务 逻 辑 层 单 击 Finish 按 钮, 将 完 成 对 业 务 逻 辑 层 的 配 置, 并 在 Spring 的 配 置 文 件 中 自 动 生 成 配 置 代 码 开 发 控 制 层 的 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;

370 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>

371 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 运 行 整 合 项 目 开 发 Struts 2+Spring 的 项 目 后, 我 们 就 可 以 来 运 行 该 项 目, 从 而 验 证 项 目 开 发 的 是 否 正 确 将 Struts2AndSpring 项 目 发 布 到 Tomcat 服 务 器 中 后, 启 动 Tomcat 服 务 器 打 开 浏 览 器, 在 其 中 输 入 如 下 地 址 : 运 行 页 面 如 图 11-6 所 示 图 11-6 登 录 页 面 这 里 我 们 输 入 一 个 错 误 的 密 码, 单 击 登 录 按 钮, 运 行 结 果 如 图 11-7 所 示

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

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

374 9 图 创 建 试 题 数 据 表 其 中 id 是 试 题 数 据 表 的 主 键,title 是 实 体 的 题 目 optiona optionb optionc 和 optiond 分 别 是 试 题 的 四 个 选 项 answer 是 试 题 的 正 确 答 案, 目 前 系 统 中 只 支 持 选 择 题 parse 是 试 题 的 解 析, 考 生 考 试 完 成 后, 可 以 查 看 单 击 Finish 按 钮, 将 完 成 试 题 数 据 表 的 创 建, 向 其 中 插 入 一 些 测 试 数 据, 这 里 就 不 演 示 了, 读 者 可 以 参 考 数 据 库 管 理 一 章 进 行 学 习 开 发 完 成 后 不 要 忘 记 修 改 数 据 库 连 接 指 向 exam 数 据 库 创 建 考 试 系 统 项 目 首 先 创 建 一 个 普 通 的 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, 基 础 配 置 代 码 为 :

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

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

377 图 建 立 数 据 库 连 接 单 击 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.*.*(..))"/>

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

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

380 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 方 法, 通 过 这 种 方 式 将 考 生 数 据 访 问 层 实 现 类 对 象 注 入 在 后 面 的 代 码 中 依 次 定 义 了 登 录 方 法 获 取 考 生 信 息 方 法 和 设 置 考 生 成 绩 方 法 开 发 完 考 生 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 考 生 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 所 示

381 图 抽 取 考 生 业 务 逻 辑 接 口 单 击 OK 按 钮, 将 完 成 考 生 业 务 逻 辑 接 口 的 抽 取 开 发 完 考 生 业 务 逻 辑 实 现 类 后, 要 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 所 示 图 配 置 考 生 业 务 逻 辑 实 现 类 单 击 Finish 按 钮, 将 完 成 考 生 业 务 逻 辑 实 现 类 的 Spring 配 置, 将 考 生 数 据 访 问 层 实 现 类 对 象 注 入 到 其 中 开 发 试 题 业 务 逻 辑 层 在 试 题 业 务 逻 辑 实 现 类 中, 要 完 成 对 试 题 进 行 操 作 的 功 能 方 法, 包 括 获 取 试 题 信 息 随 机 获 取 一 张 试 卷 和 计 算 考 生 考 试 成 绩 等 功 能 试 题 业 务 逻 辑 实 现 类 的 具 体 代 码 为 : 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);

382 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 方 法, 通 过 这 种 方 式 将 试 题 数 据 访 问 实 现 类 对 象 注 入 在 后 面 的 代 码 中, 依 次 定 义 了 获 取 试 题 信 息 随 机 获 取 试 卷 和 计 算 考 试 成 绩 的 方 法 技 巧 : 我 们 的 系 统 中 是 固 定 每 一 道 题 分 值 是 相 同 的, 如 果 不 同, 可 以 在 试 题 数 据 表 中 定 义 分 值 字 段 在 计 算 结 果 业 务 方 法 中 还 要 求 每 一 道 题 的 分 值, 从 而 完 成 累 加 开 发 完 试 题 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 试 题 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 所 示 图 抽 取 试 题 业 务 逻 辑 接 口 单 击 OK 按 钮, 完 成 试 题 业 务 逻 辑 接 口 的 抽 取 最 后 同 样 还 是 在 Spring 配 置 文 件 中 对 试 题 业 务 实 现 类 进 行 配 置, 配 置 界 面 如 图 所 示

383 图 配 置 试 题 业 务 逻 辑 实 现 类 单 击 Finish 按 钮, 将 完 成 对 试 题 业 务 逻 辑 实 现 类 的 配 置, 并 将 试 题 数 据 访 问 实 现 类 对 象 注 入 开 发 登 录 系 统 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) {

384 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 配 置 文 件 中 进 行 配 置 它 的 配 置 界 面 如 图 所 示

385 图 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 将 在 下 一 小 节 中 开 发 开 发 获 取 随 机 试 题 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) {

386 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 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 所 示 图 配 置 获 取 随 机 试 题 Ation 单 击 Finish 按 钮, 将 完 成 在 Spring 配 置 文 件 中 对 获 取 随 机 试 题 Action 的 配 置, 从 而 将 试 题 业 务 逻 辑 实 现 类 对 象 注 入 接 下 来 就 是 在 Struts 2 配 置 文 件 中 进 行 配 置, 配 置 代 码 如 下 所 示 01 <action name="getrandomsubject" class="getrandomsubjectaction">

387 02 <result name="success">/showsubject.jsp</result> 03 </action> 当 执 行 完 获 取 随 机 试 题 Action 后, 将 跳 转 到 显 示 所 有 试 题 的 页 面, 在 其 中 对 保 存 在 request 中 的 试 题 对 象 集 合 遍 历, 从 而 得 到 一 张 试 卷 显 示 获 取 试 题 的 页 面 程 序 读 者 可 以 自 己 查 看 光 盘 代 码 技 巧 : 在 显 示 所 有 试 题 的 页 面 程 序 中, 使 用 到 了 隐 藏 域 来 获 取 试 题 id 值, 从 而 在 计 算 考 试 成 绩 时 可 以 获 取 这 些 值, 从 而 能 够 调 用 后 台 获 取 它 的 正 确 答 案 开 发 获 取 考 试 成 绩 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);

388 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 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 所 示 图 配 置 获 取 考 试 成 绩 Action 单 击 Finish 按 钮, 将 完 成 获 取 考 试 成 绩 Action 在 Spring 配 置 文 件 中 的 配 置 接 下 来 就 是 在 Struts 2 配 置 文 件 中 进 行 配 置, 配 置 代 码 如 下 所 示 01 <action name="submitexam" class="submitexamaction"> 02 <result name="success">/examresult.jsp</result> 03 </action> 当 执 行 完 获 取 考 试 成 绩 Action 后, 将 跳 转 到 第 2 行 配 置 的 显 示 考 试 结 果 的 页 面 中,

389 在 其 中 将 把 考 生 姓 名 和 对 应 的 成 绩 显 示 出 来 在 该 页 面 中 还 会 定 义 一 个 查 看 答 案 超 链 接, 从 而 将 考 生 所 做 试 卷 的 正 确 答 案 显 示 出 来 开 发 显 示 试 题 答 案 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 进 行 配 置, 配 置 界 面 如 图 所 示

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

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

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

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

394 图 12-2 调 试 透 视 图 界 面 其 中 上 面 的 四 个 视 图 界 面 是 重 要 的 左 上 角 是 调 试 视 图 界 面, 在 其 中 可 以 控 制 程 序 的 运 行, 让 程 序 按 照 程 序 员 的 意 愿 进 行 运 行, 从 而 不 会 一 次 运 行 结 束 右 上 角 是 变 量 和 断 点 视 图 界 面, 在 变 量 视 图 中 可 以 看 到 程 序 中 变 量 值 的 变 化 ; 断 点 是 调 试 中 重 要 的 部 分, 在 后 面 将 详 细 讲 解 左 下 角 是 编 辑 区 视 图 界 面, 在 其 中 将 显 示 要 调 试 的 代 码 内 容, 如 果 想 创 建 和 修 改 程 序, 最 好 回 到 默 认 透 视 图 中 右 下 角 是 大 纲 视 图 界 面, 会 将 Java 的 文 件 结 构 显 示 在 其 中, 它 是 比 较 少 用 的 说 明 : 这 里 只 是 简 单 的 认 识 各 个 部 分, 在 后 面 的 讲 解 中 还 会 讲 解 它 们 的 具 体 使 用 和 操 作 在 后 面 的 讲 解 中 将 直 接 使 用 每 一 部 分 的 名 称 启 动 调 试 配 置 在 正 式 开 始 调 试 操 作 之 前, 我 们 先 来 开 发 一 个 项 目, 并 在 项 目 中 开 发 一 个 简 单 的 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 程 序 后, 就 可 以 对 其 进 行 调 试

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

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

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

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

399 7 图 设 置 断 点 条 件 从 属 性 设 置 界 面 中 可 以 看 到, 也 可 以 在 该 界 面 中 进 行 启 用 断 点 和 设 置 断 点 命 中 计 数 设 置 其 中 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 的 使 用

400 创 建 测 试 程 序 单 元 测 试 主 要 是 对 某 一 方 法 进 行 测 试, 所 以 这 里 我 们 首 先 来 开 发 一 个 功 能 方 法 被 测 试 的 程 序 代 码 如 下 所 示 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 选 项, 界 面 如 图 所 示 图 选 择 创 建 程 序 在 其 中 选 中 Java JUnit JUnit Test Case 节 点, 单 击 Next 按 钮, 将 弹 出 创 建 JUnit 程 序 的 界 面, 如 图 所 示

401 9 图 创 建 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 按 钮, 将 进 入 选 择 测 试 方 法 的 界 面 如 图 所 示

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

403 11 完 成 上 述 操 作 后, 会 在 编 辑 区 中 自 动 打 开 创 建 的 测 试 程 序, 自 动 生 成 的 代 码 为 : 01 package com.sanqing.junit.test; 02 import static org.junit.assert.*; 03 import org.junit.test; 04 public class HelloWorldTest { 06 public void testconnection() { 07 fail("not yet implemented"); 08 } 09 } 注 意 : 第 2 行 中 使 用 的 是 静 态 导 入 方 法, 并 不 是 通 常 用 的 导 入 接 口 或 者 类, 它 是 JDK 5.0 以 后 加 入 的, 通 过 它 可 以 在 程 序 中 直 接 使 用 指 定 类 的 静 态 方 法, 例 如 Assert 类 中 的 静 态 方 法 其 中 第 5 行 使 用 到 注 解, 通 过 它 可 以 标 明 下 面 第 6 行 的 testconnection 是 一 个 测 试 方 法 注 意 : 测 试 方 法 的 名 称 是 有 固 定 格 式 的, 通 常 为 testxxx, 其 中 XXX 就 是 被 测 试 方 法 的 名 称 虽 然 在 JUnit 4 版 本 中 并 没 有 严 格 规 定, 但 是 最 好 采 用 同 样 规 范 开 发 测 试 代 码 创 建 测 试 程 序 后, 将 自 动 生 成 测 试 代 码, 但 是 这 并 不 是 我 们 想 要 的 我 们 测 试 方 法 是 为 了 验 证 它 是 否 能 够 完 成 某 一 个 功 能 例 如 连 接 字 符 串 方 法, 我 们 就 来 验 证 是 否 能 够 达 到 连 接 字 符 串 的 效 果 将 自 动 生 成 的 代 码 修 改 成 如 下 代 码 : 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 { 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 静 态 方 法 外, 还 有 其 他 一 些 判 断 方 法, 在 后 面 的 学 习 中 将 会 学 习 到

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

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

406 图 输 出 错 误 信 息 其 中 上 半 部 分 是 和 前 面 相 同 的, 在 Failure Trace 栏 中 将 把 方 法 中 定 义 的 信 息 显 示 在 其 中 该 信 息 只 有 测 试 失 败 时 才 会 出 现, 当 测 试 成 功 后 将 被 忽 略 掉, 通 过 它 能 够 更 好 的 检 查 到 哪 一 个 方 法 测 试 没 有 通 过 测 试 结 果 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 {

407 15 07 public void testlogin() { 08 boolean b=new UserServiceImpl().login("Tom", "456123"); 09 asserttrue(b); 10 } 11 } 启 动 运 行 测 试, JUnit 视 图 界 面 如 图 所 示 图 true 测 试 上 面 代 码 第 8 行 中 使 用 测 试 数 据 调 用 登 录 测 试 方 法, 从 而 得 到 表 示 是 否 能 够 登 录 的 boolean 类 型 返 回 值 在 第 9 行 中 使 用 asserttrue 方 法 判 断 返 回 值 是 否 为 true, 如 果 是 true, 则 测 试 通 过, 得 到 上 面 的 结 果 说 明 : assertfalse 方 法 和 asserttrue 方 法 非 常 类 似 的, 它 是 用 来 判 断 结 果 是 否 为 false 如 果 是, 则 测 试 成 功, 如 果 不 是, 则 测 试 失 败 测 试 结 果 是 否 为 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;

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

409 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 { 07 public void testgetinstance() { 08 MyBean mybean1=mybean.getinstance(); 09 MyBean mybean2=mybean.getinstance(); 10 assertsame(mybean1, mybean2); 11 } 12 } 启 动 运 行 测 试, JUnit 视 图 界 面 如 图 所 示

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

411 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" 则 测 试 通 过 例 如

412 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 方 法 的 使 用 方 式 就 可 以, 如 果 对 它 感 兴 趣, 可 以 看 一 下 官 方 文 档, 它 是 非 常 容 易 学 习 的

413 注 解 在 测 试 中 的 使 用 注 解 是 JDK 5.0 版 本 以 后 添 加 的 新 特 性 技 术, 通 过 使 用 它 可 以 在 程 序 中 节 省 大 量 代 码 在 JUnit 4 版 本 中 也 引 入 的 注 解, 例 如 前 面 见 过 多 次 注 解, 通 过 它 就 可 以 标 明 下 面 的 方 法 是 一 个 测 试 方 法, 从 而 就 不 需 要 让 测 试 类 继 承 其 他 类 除 注 解 外, 还 有 其 他 几 种 常 用 的 注 解, 在 本 节 中 就 来 对 它 们 进 行 讲 解 测 试 程 序 是 否 发 生 异 常 在 前 面 使 注 解 时 只 是 标 明 下 面 的 方 法 是 测 试 方 法, 在 该 注 解 中 还 可 以 添 加 属 性 来 进 行 更 详 细 的 测 试, 例 如 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 { 06 public void testdivide() { 07 double d=new DivideMath().divide(3, 0); 08 } 09 } 启 动 运 行 测 试, JUnit 视 图 界 面 如 图 所 示

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

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

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

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

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

419 北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 第 13 章 CVS 和 SVN 版 本 控 制 在 开 发 小 型 项 目 中, 通 常 只 保 留 最 新 的 版 本 对 于 大 型 项 目 而 言, 这 种 做 法 就 会 有 一 定 的 问 题 因 为 在 大 型 项 目 改 动 是 比 较 多 的, 而 且 不 能 保 证 最 新 修 改 的 版 本 就 是 最 好 的 版 本, 所 以 经 常 要 反 复 操 作, 这 时 候 就 要 用 到 版 本 管 理 的 概 念 当 工 作 到 一 个 阶 段, 就 要 进 行 版 本 保 存, 在 后 面 的 工 作 中 或 者 其 他 开 发 人 员 可 以 使 用 指 定 的 某 一 个 版 本 随 着 项 目 的 发 展, 版 本 管 理 越 来 越 重 要, 它 在 当 前 软 件 开 发 中 是 必 不 可 少 的 版 本 管 理 是 一 种 功 能, 目 前 实 现 该 功 能 的 技 术 有 很 多, 在 MyEclipse 中 本 身 集 成 了 标 准 的 版 本 管 理 系 统 CVS, 该 技 术 已 经 流 行 了 很 长 时 间 除 了 CVS 外,SVN 也 是 最 近 流 行 起 来 的 版 本 管 理 工 具, 它 包 含 CVS 的 所 有 功 能, 并 且 修 复 了 CVS 的 一 些 缺 陷 在 本 章 中 将 重 点 讲 解 在 MyEclipse 中 如 何 操 作 CVS 和 SVN 这 两 个 版 本 管 理 工 具 13.1 本 地 版 本 控 制 CVS 和 SVN 是 在 大 型 项 目 中 团 队 开 发 和 阶 段 性 开 发 起 到 非 常 重 要 的 作 用, 但 是 如 果 是 对 于 一 个 人 来 说, 或 者 对 于 某 一 个 程 序 文 件 来 说, 完 全 没 有 必 要 使 用 这 些 工 具, 只 使 用 MyEclipse 自 带 的 版 本 管 理 功 能 就 可 以 比 较 在 讲 解 操 作 之 前, 我 们 先 来 看 一 下 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 所 示

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

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

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

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

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

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

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

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

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

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

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

431 13 示 该 文 件 在 CVS 服 务 器 中 的 版 本 号 提 交 文 件 在 上 一 小 节 中 已 经 完 成 了 共 享 项 目 的 操 作, 并 且 已 经 完 成 了 第 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 命 令, 将 弹 出 提 交 文 件 界 面, 在 其 中 输 入 提 交 描 述 后, 界 面 如 图 所 示 图 提 交 文 件 单 击 Finish 按 钮, 将 完 成 提 交 文 件 的 操 作 再 次 展 开 包 资 源 管 理 器 中 的 项 目, 如 图 所 示

432 图 提 交 后 界 面 从 包 资 源 管 理 器 中 可 以 看 到, 提 交 程 序 后 的 版 本 已 经 变 为 1.2 技 巧 : 不 但 可 以 提 交 某 一 个 文 件, 也 可 以 提 交 整 个 项 目, 操 作 是 一 样 的 通 过 这 种 方 式 可 以 将 整 个 项 目 提 交, 其 中 所 有 发 生 改 变 的 文 件 都 会 版 本 增 加, 没 有 改 变 的 文 件 不 会 版 本 增 加 在 实 际 开 发 中, 这 种 操 作 使 用 时 最 多 的 更 新 文 件 当 对 程 序 修 改 后, 发 现 修 改 的 并 不 正 确, 需 要 回 到 原 来 的 样 子, 这 时 候 就 要 在 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 命 令, 将 弹 出 比 较 不 同 的 界 面, 如 图 所 示

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

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

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

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

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

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

439 21 入 命 令 操 作 界 面, 在 其 中 输 入 svnadmin create d:\svn 命 令, 如 图 所 示 图 创 建 资 源 库 按 下 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 = 其 中 等 号 左 边 的 Tom 就 表 示 用 户 名, 等 号 右 边 的 就 表 示 密 码 注 意 : 创 建 服 务 器 资 源 库 后, 要 在 命 令 控 制 台 中 输 入 svnserve d r d:/svn 命 令, 并 且 不 要 关 闭 窗 口, 这 样 才 能 够 保 证 SVN 服 务 器 启 动 状 态 在 MyEclipse 中 引 入 服 务 器 资 源 库 在 MyEclipse 中 安 装 SVN 插 件 成 功 后, 将 在 其 中 出 现 SVN 透 视 图 在 MyEclipse 菜 单 中, 选 择 Window Open Perspective Other 命 令, 将 弹 出 选 择 透 视 图 的 界 面, 如 图 所 示

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

441 23 图 添 加 SVN 资 源 库 其 中 URL 表 示 的 就 是 SVN 资 源 库 所 在 的 地 址, 因 为 我 们 在 本 地 做 实 验, 所 以 这 里 可 以 填 写 svn://localhost, 最 后 单 击 Finish 按 钮, 将 完 成 引 入 操 作, 从 而 在 SVN 资 源 库 视 图 界 面 中 多 出 一 个 SVN 资 源 库 向 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 命 令, 将 弹 出 选 择 版 本 控 制 工 具 的 界 面, 如 图 所 示

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

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

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

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

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

447 北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 第 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 模 型 仓 库

448 其 中 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 个 元 素, 分 别 是 参 与 者 用 例 关 联 关 系 包 含 关 系 扩 展 关 系 和 泛 化 关 系, 在 一 个 用 例 图 中 是 不 必 须 全 部 包 含 这 六 种 元 素 参 与 者 在 MyEclipse 的 模 型 仓 库 界 面 中, 选 择 工 具 栏 第 一 个 下 三 角 菜 单 中 的 New Use Case Diagram 选 项, 则 当 前 工 具 栏 将 变 为 进 行 用 例 图 创 建 的 形 式 在 其 中 单 击 按 钮, 然 后 在 画 布 中 单 击, 将 创 建 一 个 用 例 图 中 的 参 与 者, 并 在 界 面 中 显 示 一 个 参 与 者 图 标 双 击 参 与 者 图 标 下 空 白 处, 可 以 添 加 参 与 者 的 名 称, 这 里 添 加 游 客 如 图 14-3 所 示 说 明 : 为 UML 图 添 加 例 如 名 称 这 样 的 信 息, 通 常 是 双 击 添 加, 也 可 以 在

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

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

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

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

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

454 图 所 示 图 正 向 工 程 其 中 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.* 包 的 类 是 不 需 要 导 入 的, 但 是 自 动 生 成 时 会 加 上 反 向 工 程 有 些 读 者 可 能 有 这 样 的 疑 问 :UML 模 型 的 作 用 就 是 让 程 序 员 参 考 进 行 开 发, 那 为 什 么 开 发 完 Java 程 序 后, 还 需 要 生 成 UML 模 型 呢? 这 是 因 为 通 过 UML 模 型 能 够 很 清 楚 的 看 到 程 序 之 间 的 关 系, 这 在 大 型 项 目 中 是 非 常 重 要 的 当 项 目 中 有 很 多 个 程 序 时, 并 且 程 序 之 间 关 系 复 杂, 通 过 读 程 序 代 码 是 非 常 麻 烦 的, 这 时 候 就 可 以 将 它 们 生 成 UML 模 型, 通 过 它 们 来 看 程 序 之 间 的 关 系 这 里 我 们 首 先 创 建 一 个 非 常 简 单 的 Java 类 程 序, 通 过 它 可 以 演 示 如 何 生 成 UML 类 图, 它 的 代 码 为 :

455 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 程 序 的 界 面, 如 图 所 示 图 选 择 Java 程 序 这 里 在 其 中 只 选 择 Teacher.java 程 序 节 点, 单 击 Next 按 钮, 将 弹 出 设 置 UML 类 图 的 界 面, 如 图 所 示

456 图 设 置 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 按 钮, 将 完 成 反 向 工 程 操 作, 片 刻 后 将 弹 出 对 话 框, 如 图 所 示 图 确 定 对 话 框 保 持 该 对 话 框 中 选 项 默 认 的 选 中 状 态, 单 击 OK 按 钮, 将 完 成 所 有 操 作, 在 UML 模 型 仓 库 界 面 中 将 显 示 创 建 的 Teacher 老 师 类 图, 如 图 所 示

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

473 键, 在 弹 出 的 菜 单 中 选 择 Check Out As 命 令, 将 弹 出 修 改 检 出 项 目 名 称 的 界 面, 在 其 中 修 改 项 目 的 名 称 为 NEWS_service 其 他 检 出 操 作 见 前 面 知 识 点 章 节, 这 里 就 不 再 重 复 给 出 开 发 用 户 业 务 逻 辑 层 在 新 闻 发 布 系 统 中, 用 户 的 主 要 作 用 是 发 布 新 闻, 而 这 部 分 用 户 不 是 通 过 注 册 定 义 了, 这 是 由 后 台 管 理 人 员 进 行 分 配 所 以 在 后 台 管 理 中, 要 有 对 系 统 用 户 的 管 理, 这 也 是 本 节 将 要 讲 解 的 系 统 用 户 管 理 模 块 在 新 闻 发 布 系 统 中, 系 统 用 户 管 理 模 块 中 包 括 新 增 用 户 浏 览 用 户 修 改 用 户 和 删 除 用 户 等 功 能, 这 些 功 能 也 就 是 需 要 在 用 户 业 务 逻 辑 层 中 开 发 的 方 法 因 为 在 本 章 的 新 闻 发 布 系 统 中 将 使 用 到 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; // 删 除 失 败

474 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 方 法, 通 过 这 种 方 式 将 用 户 数 据 访 问 层 实 现 类 对 象 注 入 在 后 面 的 代 码 中 依 次 定 义 了 新 增 用 户 浏 览 用 户 删 除 用 户 和 更 新 用 户 的 业 务 方 法 开 发 完 用 户 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 用 户 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 所 示 图 抽 取 用 户 业 务 逻 辑 接 口 单 击 OK 按 钮, 将 完 成 用 户 业 务 逻 辑 接 口 的 抽 取 开 发 完 用 户 业 务 逻 辑 实 现 类 后, 要 在 Spring 配 置 文 件 中 进 行 配 置, 配 置 界 面 如 图 所 示

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

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

477 前 提 下, 如 果 没 有 导 入, 将 进 入 添 加 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 { 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 } 23 public void testfindalluser() { 24 } 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 } 39 public void testupdateuser() { 40 User user=new User(); 41 user.setuserid(1); 42 user.setusername("admin"); 43 user.setpassword("admin");

478 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 目 录 下 一 份, 不 然 是 不 能 够 实 例 成 功 的 开 发 版 面 业 务 逻 辑 层 在 新 闻 发 布 系 统 中, 很 重 要 的 一 个 组 成 元 素 就 是 版 面, 通 过 使 用 版 面 可 以 将 新 闻 进 行 分 类 例 如 娱 乐 新 闻 体 育 新 闻 等 在 版 面 管 理 中, 包 括 创 建 新 版 面 浏 览 目 前 所 有 版 面 更 新 版 面 和 删 除 版 面 等 操 作, 所 以 在 版 面 业 务 逻 辑 层 中 需 要 创 建 对 应 的 业 务 方 法, 其 程 序 代 码 如 下 所 示 : 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 }

479 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 方 法, 从 而 将 版 面 数 据 访 问 类 对 象 注 入 在 后 面 的 程 序 中, 依 次 定 义 了 新 增 版 面 删 除 版 面 查 询 所 有 版 面 更 新 版 面 和 查 找 指 定 版 面 的 业 务 方 法 开 发 完 版 面 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 版 面 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 所 示

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

481 对 版 面 业 务 逻 辑 类 进 行 单 元 测 试 开 发 完 版 面 业 务 逻 辑 层 程 序 后, 同 样 也 需 要 对 它 进 行 测 试 创 建 测 试 程 序 的 步 骤 这 里 就 不 再 给 出, 它 的 具 体 代 码 如 下 所 示 : 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; 12 public static void beforeclass() { 13 BeanFactory factory = 14 new ClassPathXmlApplicationContext("applicationContext.xml"); 15 moduleserviceimpl=(moduleserviceimpl) 16 factory.getbean("moduleserviceimpl"); 17 } 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 } 29 public void testdeleteitembymoduleid() { 30 boolean b=moduleserviceimpl.deleteitembymoduleid(1); 31 asserttrue(b); 32 } 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);

482 21 42 } 44 public void testfindmodule() { 45 Module m=moduleserviceimpl.findmodule(1); 46 assertnotnull(m); 47 } 48 } 上 述 对 版 面 业 务 逻 辑 层 进 行 测 试 的 程 序 和 前 面 对 用 户 业 务 逻 辑 类 进 行 测 试 的 程 序 有 所 不 同, 在 其 中 第 12 行 中 定 义 了 类 初 始 化 方 法, 在 该 方 法 中 定 义 了 实 例 化 Spring 的 Bean 容 器 的 代 码, 从 而 完 成 创 建 业 务 逻 辑 类 对 象 的 工 作 在 后 面 的 具 体 测 试 方 法 中, 将 不 用 在 进 行 实 例 化 Bean 容 器 的 工 作, 只 需 要 写 具 体 的 测 试 方 法, 分 别 定 义 了 新 增 版 面 删 除 版 面 更 新 版 面 和 查 找 版 面 方 法 的 测 试 方 法 开 发 新 闻 业 务 逻 辑 层 新 闻 业 务 可 以 说 是 新 闻 发 布 系 统 的 核 心 功 能, 在 新 闻 业 务 逻 辑 层 程 序 中 定 义 了 完 成 发 布 新 闻 浏 览 所 有 新 闻 和 删 除 新 闻 等 功 能, 所 以 要 在 新 闻 业 务 逻 辑 类 中 定 义 相 对 应 的 方 法, 该 程 序 的 具 体 代 码 如 下 所 示 : 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; // 保 存 失 败

483 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 方 法, 从 而 将 对 应 的 数 据 访 问 对 象 注 入 然 后 依 次 定 义 了 新 增 新 闻 删 除 新 闻 查 询 所 有 新 闻 查 询 单 个 新 闻 和 更 新 新 闻 的 业 务 方 法, 从 而 完 成 对 应 的 功 能 开 发 完 新 闻 业 务 逻 辑 实 现 类 后, 要 进 行 抽 取 接 口 操 作, 抽 取 出 一 个 新 闻 业 务 逻 辑 接 口 抽 取 操 作 界 面 如 图 所 示

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

485 对 新 闻 业 务 罗 逻 辑 类 进 行 单 元 测 试 和 前 面 的 两 个 业 务 逻 辑 类 一 样, 开 发 完 程 序 后 都 需 要 编 写 对 应 的 单 元 测 试 程 序, 通 过 该 程 序 完 成 对 程 序 功 能 的 测 试 具 体 测 试 程 序 的 开 发 步 骤 同 样 还 是 不 再 给 出, 主 要 来 看 它 的 具 体 程 序, 代 码 如 下 所 示 : 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; 13 public static void beforeclass() { 14 BeanFactory factory = 15 new ClassPathXmlApplicationContext("applicationContext.xml"); 16 newsserviceimpl=(newsserviceimpl)factory.getbean("newsserviceimpl"); 17 } 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 } 32 public void testdeleteitembynewsid() { 33 boolean b=newsserviceimpl.deleteitembynewsid(1); 34 asserttrue(b); 35 } 37 public void testfindnews() { 38 News news=newsserviceimpl.findnews(1); 39 assertnotnull(news); 40 }

486 25 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 开 发 控 制 层 开 发 完 业 务 逻 辑 层 后, 同 样 也 需 要 将 程 序 提 交 到 版 本 控 制 服 务 器 中, 从 而 共 享 给 其 他 开 发 团 队, 主 要 是 提 供 给 控 制 层 开 发 团 队 在 控 制 层 开 发 团 队 开 发 对 应 程 序 时, 如 果 业 务 逻 辑 层 程 序 已 经 开 发 完 成, 将 从 版 本 控 制 服 务 器 中 检 出 相 应 的 程 序 这 些 操 作 读 者 可 以 参 考 前 面 的 讲 解 学 习, 这 里 就 不 再 给 出 开 发 发 布 新 闻 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; // 新 闻 内 容

487 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 对 象

488 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 行 中 调 用 新 闻 业 务 接 口 中 的 添 加 新 闻 的 业 务 方 法, 从 而 将 保 存 在 新 闻 对 象 中 的 信 息 提 交 给 后 台 程 序 配 置 Action 程 序 当 使 用 Struts 2+Spring 框 架 开 发 时, 配 置 Action 程 序 是 比 较 繁 琐 的, 不 但 要 在 Spring 的 配 置 文 件 中 进 行 配 置, 还 要 在 Struts 2 的 配 置 文 件 中 进 行 配 置 通 常 首 先 在 Spring 的 配 置 文 件 中 进 行 配 置, 它 的 配 置 界 面 如 图 所 示

489 图 在 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 开 发 表 现 层 并 运 行 系 统 开 发 前 台 表 现 层 除 了 前 面 开 发 的 数 据 访 问 层 业 务 逻 辑 层 和 控 制 层, 一 个 项 目 中 还 应 该 具 有 表 现 层, 也 就 是 前 台 显 示 程 序 这 部 分 程 序 通 常 是 由 专 门 的 前 台 美 工 来 完 成, 在 MyEclipse 中 虽 然 也 集 成 了 前 台 程 序 的 开 发 功 能, 但 是 并 不 优 秀 的, 所 以 这 部 分 程 序 我 们 在 光 盘 中 直 接 给 出, 这 里 就 不 再 详 细 讲 解 运 行 系 统 给 出 表 现 层 程 序 后, 我 们 就 可 以 访 问 我 们 开 发 的 整 个 系 统 了 将 项 目 部 署 到 Tomcat

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

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

内 容 提 要 将 JAVA 开 发 环 境 迁 移 到 Linux 系 统 上 是 现 在 很 多 公 司 的 现 实 想 法, 而 在 Linux 上 配 置 JAVA 开 发 环 境 是 步 入 Linux 下 JAVA 程 序 开 发 的 第 一 步, 本 文 图 文 并 茂 地 全 程 指 内 容 提 要 将 JAVA 开 发 环 境 迁 移 到 Linux 系 统 上 是 现 在 很 多 公 司 的 现 实 想 法, 而 在 Linux 上 配 置 JAVA 开 发 环 境 是 步 入 Linux 下 JAVA 程 序 开 发 的 第 一 步, 本 文 图 文 并 茂 地 全 程 指 导 你 搭 建 Linux 平 台 下 的 JAVA 开 发 环 境, 包 括 JDK 以 及 集

More information

Java 1 Java String Date

Java 1 Java String Date JAVA SCJP Java 1 Java String Date 1Java 01 Java Java 1995 Java Java 21 Java Java 5 1-1 Java Java 1990 12 Patrick Naughton C++ C (Application Programming Interface API Library) Patrick Naughton NeXT Stealth

More information

附录J:Eclipse教程

附录J:Eclipse教程 附 录 J:Eclipse 教 程 By Y.Daniel Liang 该 帮 助 文 档 包 括 以 下 内 容 : Eclipse 入 门 选 择 透 视 图 创 建 项 目 创 建 Java 程 序 编 译 和 运 行 Java 程 序 从 命 令 行 运 行 Java Application 在 Eclipse 中 调 试 提 示 : 在 学 习 完 第 一 章 后 使 用 本 教 程 第

More information

新・解きながら学ぶJava

新・解きながら学ぶJava 481! 41, 74!= 40, 270 " 4 % 23, 25 %% 121 %c 425 %d 121 %o 121 %x 121 & 199 && 48 ' 81, 425 ( ) 14, 17 ( ) 128 ( ) 183 * 23 */ 3, 390 ++ 79 ++ 80 += 93 + 22 + 23 + 279 + 14 + 124 + 7, 148, 16 -- 79 --

More information

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

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit Tomcat Web JUnit Cactus JUnit Java Cactus JUnit 26.1 JUnit Java JUnit JUnit Java JSP Servlet JUnit Java Erich Gamma Kent Beck xunit JUnit boolean JUnit Java JUnit Java JUnit Java 26.1.1 JUnit JUnit How

More information

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

基于CDIO一体化理念的课程教学大纲设计 Java 语 言 程 序 设 计 课 程 教 学 大 纲 Java 语 言 程 序 设 计 课 程 教 学 大 纲 一 课 程 基 本 信 息 1. 课 程 代 码 :52001CC022 2. 课 程 名 称 :Java 语 言 程 序 设 计 3. 课 程 英 文 名 称 :Java Programming 4. 课 程 类 别 : 理 论 课 ( 含 实 验 上 机 或 实 践 ) 5. 授

More information

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 Java V1.0.1 2007 4 10 1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 6.2.10 6.3..10 6.4 11 7.12 7.1

More information

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

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6 www.brainysoft.net 1.JasperReport ireport...4 1.1 JasperReport...4 1.2 ireport...4 2....4 2.1 JDK...4 2.1.1 JDK...4 2.1.2 JDK...5 2.1.3 JDK...5 2.2 ant...6 2.2.1 ant...6 2.2.2 ant...6 2.3 JasperReport...7

More information

Eclipse C C++, or

Eclipse C C++,  or Eclipse C C++, Emailctchen@pl.csie.ntut.edu.tw or s1669021@ntut.edu.tw, s2598003@ntut.edu.tw http://pl.csie.ntut.edu.tw/~ctchen, http://www.ntut.edu.tw/~s2598003/ 2004/9/10 (0.02 ) Eclipse http://www.eclipse.org

More information

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

2 Java 语 言 程 序 设 计 教 程 1.2.1 简 单 性 Java 语 言 的 语 法 与 C 语 言 和 C++ 语 言 很 接 近, 使 得 大 多 数 程 序 员 很 容 易 学 习 和 使 用 Java 另 一 方 面,Java 丢 弃 了 C++ 中 很 少 使 用 的 很 难 第 1 章 Java 概 述 Java 的 诞 生 Java 的 特 点 Java 开 发 环 境 安 装 与 配 置 创 建 并 运 行 一 个 简 单 的 Java 程 序 Java 语 言 是 当 今 计 算 机 软 件 行 业 中 最 热 门 的 网 络 编 程 语 言, 以 Java 为 核 心 的 芯 片 技 术 编 译 技 术 数 据 库 连 接 技 术, 以 及 基 于 企 业 级

More information

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

WebSphere Studio Application Developer IBM Portal Toolkit... 2/21 1. WebSphere Portal Portal WebSphere Application Server stopserver.bat -configfile.. WebSphere Studio Application Developer IBM Portal Toolkit... 1/21 WebSphere Studio Application Developer IBM Portal Toolkit Portlet Doug Phillips (dougep@us.ibm.com),, IBM Developer Technical Support Center

More information

Microsoft PowerPoint - ch6 [相容模式]

Microsoft PowerPoint - ch6 [相容模式] UiBinder wzyang@asia.edu.tw UiBinder Java GWT UiBinder XML UI i18n (widget) 1 2 UiBinder HelloWidget.ui.xml: UI HelloWidgetBinder HelloWidget.java XML UI Owner class ( Composite ) UI XML UiBinder: Owner

More information

epub83-1

epub83-1 C++Builder 1 C + + B u i l d e r C + + B u i l d e r C + + B u i l d e r C + + B u i l d e r 1.1 1.1.1 1-1 1. 1-1 1 2. 1-1 2 A c c e s s P a r a d o x Visual FoxPro 3. / C / S 2 C + + B u i l d e r / C

More information

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

目 錄 版 次 變 更 記 錄... 2 原 始 程 式 碼 類 型 之 使 用 手 冊... 3 一 安 裝 軟 體 套 件 事 前 準 備... 3 二 編 譯 流 程 說 明... 25 1 科 技 部 自 由 軟 體 專 案 原 始 程 式 碼 使 用 手 冊 Source Code Manual of NSC Open Source Project 可 信 賴 的 App 安 全 應 用 框 架 -App 應 用 服 務 可 移 轉 性 驗 證 Trusted App Framework -Transferability Verification on App MOST 102-2218-E-011-012

More information

EJB-Programming-4-cn.doc

EJB-Programming-4-cn.doc EJB (4) : (Entity Bean Value Object ) JBuilder EJB 2.x CMP EJB Relationships JBuilder EJB Test Client EJB EJB Seminar CMP Entity Beans Session Bean J2EE Session Façade Design Pattern Session Bean Session

More information

untitled

untitled JavaEE+Android - 6 1.5-2 JavaEE web MIS OA ERP BOSS Android Android Google Map office HTML CSS,java Android + SQL Sever JavaWeb JavaScript/AJAX jquery Java Oracle SSH SSH EJB+JBOSS Android + 1. 2. IDE

More information

前言 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

前言 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 前言 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 C# 7 More Effective C# C# C# C# C# C# Common Language Runtime CLR just-in-time

More information

untitled

untitled MySQL DBMS under Win32 Editor: Jung Yi Lin, Database Lab, CS, NCTU, 2005/09/16 MySQL 料 理 MySQL 兩 Commercial License 利 GPL MySQL http://www.mysql.com Developer Zone http://www.mysql.com Download 連 連 MySQL

More information

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

KillTest 质量更高 服务更好 学习资料   半年免费更新服务 KillTest 质量更高 服务更好 学习资料 http://www.killtest.cn 半年免费更新服务 Exam : 310-065Big5 Title : Sun Certified Programmer for the Java 2 Platform, SE 6.0 Version : Demo 1 / 14 1. 35. String #name = "Jane Doe"; 36. int

More information

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

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌 语 言 程 序 设 计 郑 莉 胡 家 威 编 著 清 华 大 学 逸 夫 图 书 馆 北 京 内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌 握 语

More information

chp6.ppt

chp6.ppt Java 软 件 设 计 基 础 6. 异 常 处 理 编 程 时 会 遇 到 如 下 三 种 错 误 : 语 法 错 误 (syntax error) 没 有 遵 循 语 言 的 规 则, 出 现 语 法 格 式 上 的 错 误, 可 被 编 译 器 发 现 并 易 于 纠 正 ; 逻 辑 错 误 (logic error) 即 我 们 常 说 的 bug, 意 指 编 写 的 代 码 在 执 行

More information

untitled

untitled 1 Outline 數 料 數 數 列 亂數 練 數 數 數 來 數 數 來 數 料 利 料 來 數 A-Z a-z _ () 不 數 0-9 數 不 數 SCHOOL School school 數 讀 school_name schoolname 易 不 C# my name 7_eleven B&Q new C# (1) public protected private params override

More information

untitled

untitled 1 Outline 料 類 說 Tang, Shih-Hsuan 2006/07/26 ~ 2006/09/02 六 PM 7:00 ~ 9:30 聯 ives.net@gmail.com www.csie.ntu.edu.tw/~r93057/aspnet134 度 C# 力 度 C# Web SQL 料 DataGrid DataList 參 ASP.NET 1.0 C# 例 ASP.NET 立

More information

Microsoft Word - 01.DOC

Microsoft Word - 01.DOC 第 1 章 JavaScript 简 介 JavaScript 是 NetScape 公 司 为 Navigator 浏 览 器 开 发 的, 是 写 在 HTML 文 件 中 的 一 种 脚 本 语 言, 能 实 现 网 页 内 容 的 交 互 显 示 当 用 户 在 客 户 端 显 示 该 网 页 时, 浏 览 器 就 会 执 行 JavaScript 程 序, 用 户 通 过 交 互 式 的

More information

EJB-Programming-3.PDF

EJB-Programming-3.PDF :, JBuilder EJB 2.x CMP EJB Relationships JBuilder EJB Test Client EJB EJB Seminar CMP Entity Beans Value Object Design Pattern J2EE Design Patterns Value Object Value Object Factory J2EE EJB Test Client

More information

untitled

untitled 4.1AOP AOP Aspect-oriented programming AOP 來說 AOP 令 理 Cross-cutting concerns Aspect Weave 理 Spring AOP 來 AOP 念 4.1.1 理 AOP AOP 見 例 來 例 錄 Logging 錄 便 來 例 行 留 錄 import java.util.logging.*; public class HelloSpeaker

More information

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

Oracle Solaris Studio makefile C C++ Fortran IDE Solaris Linux C/C++/Fortran IDE Project Properties IDE makefile 1. Oracle Solaris Studio 12.2 IDE 2010 9 2 8 9 10 11 13 20 26 28 30 32 33 Oracle Solaris Studio makefile C C++ Fortran IDE Solaris Linux C/C++/Fortran IDE "Project Properties" IDE makefile 1. "File" > "New

More information

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

Oracle Oracle Solaris Studio IDE makefile C C++ Fortran makefile IDE Solaris Linux C/C++/Fortran Oracle IDE P Oracle Solaris Studio 12.3 IDE 2011 12 E26461-01 2 7 8 9 9 Oracle 10 12 14 21 26 27 29 31 32 33 Oracle Solaris Studio IDE makefile C C++ Fortran makefile IDE Solaris Linux C/C++/Fortran Oracle IDE "Project

More information

Chapter 9: Objects and Classes

Chapter 9: Objects and Classes Java application Java main applet Web applet Runnable Thread CPU Thread 1 Thread 2 Thread 3 CUP Thread 1 Thread 2 Thread 3 ,,. (new) Thread (runnable) start( ) CPU (running) run ( ) blocked CPU sleep(

More information

Learning Java

Learning Java Java Introduction to Java Programming (Third Edition) Prentice-Hall,Inc. Y.Daniel Liang 2001 Java 2002.2 Java2 2001.10 Java2 Philip Heller & Simon Roberts 1999.4 Java2 2001.3 Java2 21 2002.4 Java UML 2002.10

More information

RunPC2_.doc

RunPC2_.doc PowerBuilder 8 (5) PowerBuilder Client/Server Jaguar Server Jaguar Server Connection Cache Thin Client Internet Connection Pooling EAServer Connection Cache Connection Cache Connection Cache Connection

More information

AL-M200 Series

AL-M200 Series NPD4754-00 TC ( ) Windows 7 1. [Start ( )] [Control Panel ()] [Network and Internet ( )] 2. [Network and Sharing Center ( )] 3. [Change adapter settings ( )] 4. 3 Windows XP 1. [Start ( )] [Control Panel

More information

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

没 有 多 余 的 Contruol 或 Action 了 原 来 Domain 层 被 服 务 层 Service layer 遮 挡, 在 右 边 图 中, 则 Domain 层 直 接 暴 露 给 前 台 了, 没 有 被 遮 挡, 裸 露 了 这 样 一 步 到 位 实 现 领 域 模 型 文 章 编 号 :1007-757X(2012)1-0036-04 领 域 驱 动 模 型 的 WEB 软 件 系 统 设 计 研 究 摘 要 : J2EE 3 JDK1.7 Tomcat WEB 关 键 词 : 中 图 分 类 号 :TP311 文 献 标 志 码 :A 0 引 言 Web 软 件 系 统 的 分 层 结 构 典 型 的 J2EE 软 件 系 统 开 发 方 法 分 为 三 层 结

More information

Microsoft Word - ch04三校.doc

Microsoft Word - ch04三校.doc 4-1 4-1-1 (Object) (State) (Behavior) ( ) ( ) ( method) ( properties) ( functions) 4-2 4-1-2 (Message) ( ) ( ) ( ) A B A ( ) ( ) ( YourCar) ( changegear) ( lowergear) 4-1-3 (Class) (Blueprint) 4-3 changegear

More information

Microsoft Word zw

Microsoft Word zw 第 1 章 Android 概述 学习目标 : Android Android Android Studio Android Android APK 1.1 1. 智能手机的定义 Smartphone 2. 智能手机的发展 1973 4 3 PC IBM 1994 IBM Simon PDA PDA Zaurus OS 1996 Nokia 9000 Communicator Nokia 9000

More information

Microsoft Word - 第3章.doc

Microsoft Word - 第3章.doc Java C++ Pascal C# C# if if if for while do while foreach while do while C# 3.1.1 ; 3-1 ischeck Test() While ischeck while static bool ischeck = true; public static void Test() while (ischeck) ; ischeck

More information

Chapter 9: Objects and Classes

Chapter 9: Objects and Classes Fortran Algol Pascal Modula-2 BCPL C Simula SmallTalk C++ Ada Java C# C Fortran 5.1 message A B 5.2 1 class Vehicle subclass Car object mycar public class Vehicle extends Object{ public int WheelNum

More information

《大话设计模式》第一章

《大话设计模式》第一章 第 1 章 代 码 无 错 就 是 优? 简 单 工 厂 模 式 1.1 面 试 受 挫 小 菜 今 年 计 算 机 专 业 大 四 了, 学 了 不 少 软 件 开 发 方 面 的 东 西, 也 学 着 编 了 些 小 程 序, 踌 躇 满 志, 一 心 要 找 一 个 好 单 位 当 投 递 了 无 数 份 简 历 后, 终 于 收 到 了 一 个 单 位 的 面 试 通 知, 小 菜 欣 喜

More information

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

IBM Rational ClearQuest Client for Eclipse   1/ IBM Rational ClearQuest Client for Ecl 1/39 Balaji Krish,, IBM Nam LeIBM 2005 4 15 IBM Rational ClearQuest ClearQuest Eclipse Rational ClearQuest / Eclipse Clien Rational ClearQuest Rational ClearQuest Windows Web Rational ClearQuest Client

More information

ebook

ebook 26 JBuilder RMI Java Remote Method Invocation R M I J a v a - - J a v a J a v J a v a J a v a J a v a R M I R M I ( m a r s h a l ) ( u n m a r c h a l ) C a ff e i n e J a v a j a v a 2 i i o p J a v

More information

优迈科技教学大纲2009版本

优迈科技教学大纲2009版本 java 软 件 工 程 师 培 训 教 学 大 纲 1 JAVA 软 件 工 程 师 培 训 教 学 大 纲 深 圳 软 件 园 人 才 实 训 基 地 2009 年 3 月 目 录 java 软 件 工 程 师 培 训 教 学 大 纲 2 教 学 阶 段...3 第 一 章 JAVA 起 步...3 第 二 章 面 向 对 象 的 编 程...4 第 三 章 数 据 结 构 IO 线 程 网 络...5

More information

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

KillTest 质量更高 服务更好 学习资料   半年免费更新服务 KillTest 质量更高 服务更好 学习资料 http://www.killtest.cn 半年免费更新服务 Exam : 1Z0-854 Title : Java Standard Edition 5 Programmer Certified Professional Upgrade Exam Version : Demo 1 / 12 1.Given: 20. public class CreditCard

More information

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

Symantec™ Sygate Enterprise Protection 防护代理安装使用指南 Symantec Sygate Enterprise Protection 防 护 代 理 安 装 使 用 指 南 5.1 版 版 权 信 息 Copyright 2005 Symantec Corporation. 2005 年 Symantec Corporation 版 权 所 有 All rights reserved. 保 留 所 有 权 利 Symantec Symantec 徽 标 Sygate

More information

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

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入 100 年 特 種 考 試 地 方 政 府 公 務 人 員 考 試 試 題 等 別 : 三 等 考 試 類 科 : 資 訊 處 理 科 目 : 系 統 分 析 與 設 計 一 請 參 考 下 列 旅 館 管 理 系 統 的 使 用 案 例 圖 (Use Case Diagram) 撰 寫 預 約 房 間 的 使 用 案 例 規 格 書 (Use Case Specification), 繪 出 入

More information

untitled

untitled -JAVA 1. Java IDC 20 20% 5 2005 42.5 JAVA IDC JAVA 60% 70% JAVA 3 5 10 JAVA JAVA JAVA J2EE J2SE J2ME 70% JAVA JAVA 20 1 51 2. JAVA SUN JAVA J2EE J2EE 3. 1. CSTP CSTP 2 51 2. 3. CSTP IT CSTP IT IT CSTP

More information

javaexample-02.pdf

javaexample-02.pdf n e w. s t a t i c s t a t i c 3 1 3 2 p u b l i c p r i v a t e p r o t e c t e d j a v a. l a n g. O b j e c t O b j e c t Rect R e c t x 1 y 1 x 2 y 2 R e c t t o S t r i n g ( ) j a v a. l a n g. O

More information

D C 93 2

D C 93 2 D9223468 3C 93 2 Java Java -- Java UML Java API UML MVC Eclipse API JavadocUML Omendo PSPPersonal Software Programming [6] 56 8 2587 56% Java 1 epaper(2005 ) Java C C (function) C (reusability) eat(chess1,

More information

FileMaker 16 ODBC 和 JDBC 指南

FileMaker 16 ODBC 和 JDBC 指南 FileMaker 16 ODBC JDBC 2004-2017 FileMaker, Inc. FileMaker, Inc. 5201 Patrick Henry Drive Santa Clara, California 95054 FileMaker FileMaker Go FileMaker, Inc. FileMaker WebDirect FileMaker Cloud FileMaker,

More information

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

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 1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET 2.0 2.0.NET Framework.NET Framework 2.0 ( 3).NET Framework 2.0.NET Framework ( System ) o o o o o o Boxing UnBoxing() o

More information

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

KillTest 质量更高 服务更好 学习资料   半年免费更新服务 KillTest 质量更高 服务更好 学习资料 http://www.killtest.cn 半年免费更新服务 Exam : 310-055Big5 Title : Sun Certified Programmer for the Java 2 Platform.SE 5.0 Version : Demo 1 / 22 1. 11. public static void parse(string str)

More information

untitled

untitled How to using M-Power Report API M-Power Report API 力 了 M-Power Report -- Java (Library) M-Power Report API 行 Java M-Power Report M-Power Report API ( 30 ) PDF/HTML/CSV/XLS JPEG/PNG/SVG 料 料 OutputStream

More information

AL-MX200 Series

AL-MX200 Series PostScript Level3 Compatible NPD4760-00 TC Seiko Epson Corporation Seiko Epson Corporation ( ) Seiko Epson Corporation Seiko Epson Corporation Epson Seiko Epson Corporation Apple Bonjour ColorSync Macintosh

More information

WinMDI 28

WinMDI 28 WinMDI WinMDI 2 Region Gate Marker Quadrant Excel FACScan IBM-PC MO WinMDI WinMDI IBM-PC Dr. Joseph Trotter the Scripps Research Institute WinMDI HP PC WinMDI WinMDI PC MS WORD, PowerPoint, Excel, LOTUS

More information

Chapter 2

Chapter 2 2 (Setup) ETAP PowerStation ETAP ETAP PowerStation PowerStation PowerPlot ODBC SQL Server Oracle SQL Server Oracle Windows SQL Server Oracle PowerStation PowerStation PowerStation PowerStation ETAP PowerStation

More information

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

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6: Chapter 15. Suppressed Exception CH14 Finally Block Java SE 7 try-with-resources JVM cleanup try-with-resources JVM cleanup cleanup Java SE 7 Throwable getsuppressed Throwable[] getsuppressed() Suppressed

More information

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

序 言 本 专 业 人 才 培 养 方 案 以 适 应 市 场 需 求 为 目 标, 根 据 学 校 校 企 双 主 体 人 才 培 养 的 要 求 和 移 动 应 用 开 发 专 业 的 特 点 设 置 课 程 体 系, 体 现 了 课 程 为 市 场 服 务 的 特 点 本 专 业 要 求 学 广 东 新 安 职 业 技 术 学 院 计 算 机 移 动 应 用 开 发 专 业 2016 级 人 才 培 养 方 案 专 业 方 向 负 责 人 : 梅 红 系 主 任 : 毛 立 冰 计 算 机 系 二 一 五 年 六 月 序 言 本 专 业 人 才 培 养 方 案 以 适 应 市 场 需 求 为 目 标, 根 据 学 校 校 企 双 主 体 人 才 培 养 的 要 求 和 移 动 应 用 开

More information

FileMaker 15 ODBC 和 JDBC 指南

FileMaker 15 ODBC 和 JDBC 指南 FileMaker 15 ODBC JDBC 2004-2016 FileMaker, Inc. FileMaker, Inc. 5201 Patrick Henry Drive Santa Clara, California 95054 FileMaker FileMaker Go FileMaker, Inc. / FileMaker WebDirect FileMaker, Inc. FileMaker

More information

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

使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款 JAVA 程 序 设 计 ( 肆 ) 徐 东 / 数 学 系 使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款 使 用 Java class 代 表 保 险 箱 public class SaveBox 类 名 类 类 体 实 现 封 装 性 使 用 class SaveBox 代 表 保

More information

<4D6963726F736F667420576F7264202D20BBF9D3DA416E64726F6964C6BDCCA8B5C4B5E7D7D3C5C4C2F4CFB5CDB32E646F63>

<4D6963726F736F667420576F7264202D20BBF9D3DA416E64726F6964C6BDCCA8B5C4B5E7D7D3C5C4C2F4CFB5CDB32E646F63> 基 于 Android 平 台 的 电 子 拍 卖 系 统 摘 要 本 电 子 拍 卖 系 统 其 实 就 是 一 个 电 子 商 务 平 台, 只 要 将 该 系 统 部 署 到 互 联 网 上, 客 户 都 可 以 在 该 系 统 上 发 布 想 出 售 的 商 品, 也 可 以 对 拍 卖 中 的 商 品 参 与 竞 价 整 个 过 程 无 须 人 工 干 预, 由 系 统 自 动 完 成 本

More information

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

软 件 工 程 专 业 习 指 南 目 录 一 软 件 工 程 专 业 设 置 背 景 与 发 展 前 景... 3 二 软 件 工 程 专 业 实 践 教 条 件... 4 三 软 件 工 程 专 业 课 程 类 型 及 核 方 式... 6 1. 软 件 工 程 专 业 课 程 类 型...7 计 算 机 系 软 件 工 程 专 业 习 指 南 广 东 科 技 院 计 算 机 系 2015-9-1 软 件 工 程 专 业 习 指 南 目 录 一 软 件 工 程 专 业 设 置 背 景 与 发 展 前 景... 3 二 软 件 工 程 专 业 实 践 教 条 件... 4 三 软 件 工 程 专 业 课 程 类 型 及 核 方 式... 6 1. 软 件 工 程 专 业 课 程 类 型...7

More information

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

计算机软件技术专业教学计划 计 算 机 软 件 技 术 专 业 人 才 培 养 方 案 ( 服 务 外 包 方 向 ) 专 业 大 类 名 称 ( 代 码 ):++(++) 专 业 类 名 称 ( 代 码 ):++++++(++++) 专 业 名 称 ( 代 码 ):+++++++(++++++) 修 业 年 限 : 三 年, 全 日 制 招 生 对 象 : 三 年 制 普 通 高 中 及 对 口 中 职 专 业 毕 业 生

More information

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

Microsoft Word - 王彬_已修改_.doc 第 39 卷 第 1 期 应 用 科 技 Vol.39, No.1 2012 年 2 月 Applied Science and Technology Feb. 2012 doi:10.3969/j.issn.1009-671x.201110009 基 于 J2EE 网 络 教 学 系 统 的 设 计 与 实 现 李 静 梅, 王 彬, 彭 晴 晴 哈 尔 滨 工 程 大 学 计 算 机 科 学 与

More information

epub 61-2

epub 61-2 2 Web Dreamweaver UltraDev Dreamweaver 3 We b We b We Dreamweaver UltraDev We b Dreamweaver UltraDev We b We b 2.1 Web We b We b D r e a m w e a v e r J a v a S c r i p t We b We b 2.1.1 Web We b C C +

More information

Windows 2000 Server for T100

Windows 2000 Server for T100 2 1 Windows 95/98 Windows 2000 3.5 Windows NT Server 4.0 2 Windows DOS 3.5 T200 2002 RAID RAID RAID 5.1 Windows 2000 Server T200 2002 Windows 2000 Server Windows 2000 Server Windows 2000 Server 3.5 for

More information

untitled

untitled PowerBuilder Tips 利 PB11 Web Service 年度 2 PB Tips PB9 EAServer 5 web service PB9 EAServer 5 了 便 web service 來說 PB9 web service 力 9 PB11 release PB11 web service 力更 令.NET web service PB NVO 論 不 PB 來說 說

More information

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

基于ECO的UML模型驱动的数据库应用开发1.doc ECO UML () Object RDBMS Mapping.Net Framework Java C# RAD DataSetOleDbConnection DataGrod RAD Client/Server RAD RAD DataReader["Spell"].ToString() AObj.XXX bug sql UML OR Mapping RAD Lazy load round trip

More information

RUN_PC連載_12_.doc

RUN_PC連載_12_.doc PowerBuilder 8 (12) PowerBuilder 8.0 PowerBuilder PowerBuilder 8 PowerBuilder 8 / IDE PowerBuilder PowerBuilder 8.0 PowerBuilder PowerBuilder PowerBuilder PowerBuilder 8.0 PowerBuilder 6 PowerBuilder 7

More information

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

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP:  ******************* * 关于 Java 测试试题 ****** ******************* * 关于 Java 测试试题 ******************* 問 1 运行下面的程序, 选出一个正确的运行结果 public class Sample { public static void main(string[] args) { int[] test = { 1, 2, 3, 4, 5 ; for(int i = 1 ; i System.out.print(test[i]);

More information

目 录 目 录... 2 1 平 台 概 述... 3 2 技 术 架 构... 4 3 技 术 特 点... 7 3.1 基 于 统 一 平 台 的 多 产 品 线 支 撑... 7 3.2 先 进 性... 7 3.3 安 全 性... 7 3.4 开 放 性... 8 3.5 高 性 能 和

目 录 目 录... 2 1 平 台 概 述... 3 2 技 术 架 构... 4 3 技 术 特 点... 7 3.1 基 于 统 一 平 台 的 多 产 品 线 支 撑... 7 3.2 先 进 性... 7 3.3 安 全 性... 7 3.4 开 放 性... 8 3.5 高 性 能 和 致 远 协 同 管 理 软 件 V5 平 台 白 皮 书 北 京 致 远 协 创 软 件 有 限 公 司 2014 年 6 月 1 / 20 目 录 目 录... 2 1 平 台 概 述... 3 2 技 术 架 构... 4 3 技 术 特 点... 7 3.1 基 于 统 一 平 台 的 多 产 品 线 支 撑... 7 3.2 先 进 性... 7 3.3 安 全 性... 7 3.4 开 放

More information

IoC容器和Dependency Injection模式.doc

IoC容器和Dependency Injection模式.doc IoC Dependency Injection /Martin Fowler / Java Inversion of Control IoC Dependency Injection Service Locator Java J2EE open source J2EE J2EE web PicoContainer Spring Java Java OO.NET service component

More information

雲端 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

雲端 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 CHAPTER 使用 Hadoop 打造自己的雲 8 8.3 測試 Hadoop 雲端系統 4 Nodes Hadoop Map Reduce Hadoop WordCount 4 Nodes Hadoop Map/Reduce $HADOOP_HOME /home/ hadoop/hadoop-0.20.2 wordcount echo $ mkdir wordcount $ cd wordcount

More information

ebook140-9

ebook140-9 9 VPN VPN Novell BorderManager Windows NT PPTP V P N L A V P N V N P I n t e r n e t V P N 9.1 V P N Windows 98 Windows PPTP VPN Novell BorderManager T M I P s e c Wi n d o w s I n t e r n e t I S P I

More information

Microsoft Word - Learn Objective-C.doc

Microsoft Word - Learn Objective-C.doc Learn Objective C http://cocoadevcentral.com/d/learn_objectivec/ Objective C Objective C Mac C Objective CC C Scott Stevenson [object method]; [object methodwithinput:input]; output = [object methodwithoutput];

More information

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

中 文 摘 要 智 慧 型 手 機 由 於 有 強 大 的 功 能, 以 及 優 渥 的 便 利 性, 還 能 與 網 路 保 持 隨 時 的 鏈 結 與 同 步 更 新, 因 此 深 受 廣 大 消 費 者 喜 愛, 當 然, 手 機 遊 戲 也 成 為 現 代 人 不 可 或 缺 的 娛 樂 之 臺 北 市 大 安 高 級 工 業 職 業 學 校 資 訊 科 一 百 零 一 學 年 度 專 題 製 作 報 告 ------ 以 Android 製 作 ------ ----- 連 線 塔 防 遊 戲 ------ Tower defense game using Internet technology 班 級 : 資 訊 三 甲 組 別 : A9 組 組 員 : 葉 冠 麟 (9906129)

More information

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)

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) 1/14 IBM Rational Test RealTime IBM, 2004 7 01 50% IBM Rational Test RealTime IBM Rational Test RealTime 1. 50% IBM Rational Test RealTime IBM Rational Test RealTime 2. IBM Rational Test RealTime Test

More information

Microsoft Word - PS2_linux_guide_cn.doc

Microsoft Word - PS2_linux_guide_cn.doc Linux For $ONY PlayStatioin2 Unofficall General Guide Language: Simplified Chinese First Write By Beter Hans v0.1 Mail: hansb@citiz.net Version: 0.1 本 人 是 菜 鸟 + 小 白 欢 迎 指 正 错 误 之 处, 如 果 您 有 其 他 使 用 心 得

More information

JavaIO.PDF

JavaIO.PDF O u t p u t S t ream j a v a. i o. O u t p u t S t r e a m w r i t e () f l u s h () c l o s e () public abstract void write(int b) throws IOException public void write(byte[] data) throws IOException

More information

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

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

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

1. 访 问 最 新 发 行 公 告 信 息 jconnect for JDBC 7.0 1. 访 问 最 新 发 行 公 告 信 息 最 新 版 本 的 发 行 公 告 可 以 从 网 上 获 得 若 要 查 找 在 本 产 品 发 布 后 增 加 的 重 要 产 品 或 文 档 信 息, 请 访 发 行 公 告 jconnect for JDBC 7.0 文 档 ID:DC74874-01-0700-01 最 后 修 订 日 期 :2010 年 3 月 2 日 主 题 页 码 1. 访 问 最 新 发 行 公 告 信 息 2 2. 产 品 摘 要 2 3. 特 殊 安 装 说 明 2 3.1 查 看 您 的 jconnect 版 本 3 4. 特 殊 升 级 指 导 3 4.1 迁 移 3

More information

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

职 位 类 别 : 测 试 工 程 师 工 作 经 验 或 实 习 经 历 : 不 限 岗 位 要 求 : 1. 本 科 及 其 以 上 学 历, 计 算 机 相 关 专 业 2014 届 毕 业 生 ; 2. 实 习 时 间 要 求, 尽 量 一 周 五 个 工 作 日 ; 3. 熟 悉 Wind 企 业 信 息 表 公 司 名 称 : 中 铁 信 安 ( 北 京 ) 信 息 安 全 技 术 有 限 公 司 公 司 性 质 : 国 企 控 股 公 司 规 模 : 100 人 左 右 所 属 行 业 : 互 联 网 计 算 机 软 件 招 聘 人 数 :12 工 作 地 点 : 北 京 市 海 淀 区 公 司 能 够 提 供 的 福 利 : 五 险 一 金 晋 升 旅 游 节 假 日 礼 物 加

More information

<4D6963726F736F667420576F7264202D20C8EDBCFEA1B232303130A1B33136BAC5A3BAB9D8D3DAB7A2B2BC32303130C4EAC8EDBCFEB9A4B3CCCAB5D1B5D6AED0A3C4DABFC6D1D0CFEEC4BFB5C4CDA8D6AA2E646F63>

<4D6963726F736F667420576F7264202D20C8EDBCFEA1B232303130A1B33136BAC5A3BAB9D8D3DAB7A2B2BC32303130C4EAC8EDBCFEB9A4B3CCCAB5D1B5D6AED0A3C4DABFC6D1D0CFEEC4BFB5C4CDA8D6AA2E646F63> 附 件 4 软 件 学 院 第 六 届 软 件 创 新 设 计 大 赛 专 题 项 目 项 目 1 指 导 老 师 : 林 倞 潘 炎 曾 坤 项 目 ( 课 题 ) 名 称 : 基 于 GraphCut 算 法 的 快 速 图 像 分 割 技 术 图 像 分 割 是 图 像 处 理 的 基 本 技 术 之 一, 也 是 图 像 分 析 的 最 基 本 的 步 骤, 作 为 计 算 机 视 觉 的

More information

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

KillTest 质量更高 服务更好 学习资料   半年免费更新服务 KillTest 质量更高 服务更好 学习资料 http://www.killtest.cn 半年免费更新服务 Exam : 70-536Chinese(C++) Title : TS:MS.NET Framework 2.0-Application Develop Foundation Version : DEMO 1 / 10 1. Exception A. Data B. Message C.

More information

(京)新登字063号

(京)新登字063号 教 育 部 职 业 教 育 与 成 人 教 育 司 推 荐 教 材 Java 程 序 设 计 教 程 ( 第 二 版 ) 沈 大 林 主 编 沈 昕 肖 柠 朴 曾 昊 等 编 著 内 容 简 介 Java 是 由 美 国 SUN 公 司 开 发 的 一 种 功 能 强 大 的, 具 有 简 单 面 向 对 象 分 布 式 可 移 植 等 性 能 的 多 线 程 动 态 计 算 机 编 程 语 言

More information

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

第 15 章 程 式 編 写 語 言 15.1 程 式 編 写 語 言 的 角 色 程 式 編 寫 語 言 是 程 式 編 寫 員 與 電 腦 溝 通 的 界 面 語 法 是 一 組 規 則 讓 程 式 編 寫 員 將 字 詞 集 合 起 來 電 腦 是 處 理 位 元 和 字 節 的 機 器, 與 程 式 編 写 語 言 在 完 成 這 章 後, 你 將 能 夠 了 解 程 式 編 写 語 言 的 功 能 了 解 高 階 語 言 和 低 階 語 言 之 間 的 分 別 知 道 翻 譯 程 式 的 意 義 和 能 夠 把 翻 譯 程 式 分 類 為 : 匯 編 程 式 編 譯 程 式 和 解 譯 程 式 認 識 不 同 翻 譯 程 式 的 優 點 和 缺 點 程 式 是 指 揮 電 腦 的 指

More information

Guide to Install SATA Hard Disks

Guide to Install SATA Hard Disks SATA RAID 1. SATA. 2 1.1 SATA. 2 1.2 SATA 2 2. RAID (RAID 0 / RAID 1 / JBOD).. 4 2.1 RAID. 4 2.2 RAID 5 2.3 RAID 0 6 2.4 RAID 1.. 10 2.5 JBOD.. 16 3. Windows 2000 / Windows XP 20 1. SATA 1.1 SATA Serial

More information

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

NEXT SDT2.51 C:\ARM251 SDT2.51 ARM SDT 2.51 ARM PROJECT MANAGER SDT 2 S3C44B0 SDT DRAGNBOY MICROSTAR ARM 51 ARM S3C44B0 ARM SDT2.51 IAR ADS SDT2.51 S3C44B0 LEDTEST SDT ARM 1 2 SDT embed.8800.org SDT2.51 SDT2.51 ARM ARM CPU ARM SDT ADS ADS MULTI-ICE SDT JTAG JTAG SDT SDT2.51

More information

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

Java Access 5-1 Server Client Client Server Server Client 5-2 DataInputStream Class java.io.datainptstream (extends) FilterInputStream InputStream Obj Message Transition 5-1 5-2 DataInputStream Class 5-3 DataOutputStream Class 5-4 PrintStream Class 5-5 (Message Transition) (Exercises) Java Access 5-1 Server Client Client Server Server Client 5-2 DataInputStream

More information

PowerPoint Presentation

PowerPoint Presentation 数 字 化 校 园 信 息 平 台 解 决 方 案 杭 州 正 方 电 子 工 程 有 限 公 司 2007.10 杭 州 正 方 电 子 工 程 有 限 公 司 简 介 正 方 公 司 成 立 于 1999 年 1 月 份, 现 有 员 工 170 多 名, 是 经 相 关 机 构 认 定 的 高 新 技 术 企 业 软 杭 件 企 州 业 正, 取 方 得 电 计 算 子 机 工 软 件 程 著

More information

序号:001

序号:001 第 一 组 选 题 简 介 序 号 :001 题 目 : 基 于 BPEL 的 网 上 订 餐 系 统 的 设 计 与 实 现 网 上 订 餐 系 统 是 在 互 联 网 上 进 行 菜 单 信 息 发 布 网 上 订 餐 以 及 维 护 客 户 关 系 的 电 子 商 务 系 统, 餐 饮 企 业 可 以 通 过 这 个 电 子 商 务 系 统 发 布 自 己 的 菜 单 信 息 以 供 客 户

More information

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

基于UML建模的管理管理信息系统项目案例导航——VB篇 PowerBuilder 8.0 PowerBuilder 8.0 12 PowerBuilder 8.0 PowerScript PowerBuilder CIP PowerBuilder 8.0 /. 2004 21 ISBN 7-03-014600-X.P.. -,PowerBuilder 8.0 - -.TP311.56 CIP 2004 117494 / / 16 100717 http://www.sciencep.com

More information

ebook8-30

ebook8-30 3 0 C C C C C C++ C + + C++ GNU C/C++ GNU egcs UNIX shell s h e l l g a w k P e r l U N I X I / O UNIX shell awk P e r l U N I X C C C C C C U N I X 30.1 C C U N I X 70 C C U N I X U N I X U N I X C Dennis

More information

Mac Java import com.apple.mrj.*;... public class MyFirstApp extends JFrame implements ActionListener, MRJAboutHandler, MRJQuitHandler {... public MyFirstApp() {... MRJApplicationUtils.registerAboutHandler(this);

More information

<4D6963726F736F667420506F776572506F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

<4D6963726F736F667420506F776572506F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074> 程 序 设 计 实 习 INFO130048 3-2.C++ 面 向 对 象 程 序 设 计 重 载 继 承 多 态 和 聚 合 复 旦 大 学 计 算 机 科 学 与 工 程 系 彭 鑫 pengxin@fudan.edu.cn 内 容 摘 要 方 法 重 载 类 的 继 承 对 象 引 用 和 拷 贝 构 造 函 数 虚 函 数 和 多 态 性 类 的 聚 集 复 旦 大 学 计 算 机 科 学

More information

XXXXXXXX http://cdls.nstl.gov.cn 2 26

XXXXXXXX http://cdls.nstl.gov.cn 2 26 [ ] [ ] 2003-7-18 1 26 XXXXXXXX http://cdls.nstl.gov.cn 2 26 (2003-7-18) 1...5 1.1...5 1.2...5 1.3...5 2...6 2.1...6 2.2...6 2.3...6 3...7 3.1...7 3.1.1...7 3.1.2...7 3.1.2.1...7 3.1.2.1.1...8 3.1.2.1.2...10

More information

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

填 写 要 求 1. 以 word 文 档 格 式 如 实 填 写 各 项 2. 表 格 文 本 中 外 文 名 词 第 一 次 出 现 时, 要 写 清 全 称 和 缩 写, 再 次 出 现 时 可 以 使 用 缩 写 3. 本 表 栏 目 未 涵 盖 的 内 容, 需 要 说 明 的, 请 在 附 件 4 精 品 在 线 开 放 课 程 申 报 书 学 校 名 称 课 程 名 称 广 东 科 学 技 术 职 业 学 院 Java 面 向 对 象 程 序 设 计 课 程 类 别 专 业 基 础 课 专 业 核 心 课 所 属 专 业 课 程 负 责 人 申 报 日 期 推 荐 单 位 软 件 技 术 刘 晓 英 2016 年 6 月 1 日 计 算 机 工 程 技 术 学 院 广 东 省 教

More information

EK-STM32F

EK-STM32F STMEVKIT-STM32F10xx8 软 件 开 发 入 门 指 南 目 录 1 EWARM 安 装... 1 1.1 第 一 步 : 在 线 注 册... 1 1.2 第 二 步 : 下 载 软 件... 2 1.3 第 三 步 : 安 装 EWARM... 3 2 基 于 STMEVKIT-STM32F10xx8 的 示 例 代 码 运 行... 6 2.1 GPIO Demo... 6 2.2

More information

Microsoft Word - template.doc

Microsoft Word - template.doc HGC efax Service User Guide I. Getting Started Page 1 II. Fax Forward Page 2 4 III. Web Viewing Page 5 7 IV. General Management Page 8 12 V. Help Desk Page 13 VI. Logout Page 13 Page 0 I. Getting Started

More information

untitled

untitled 653 JAVA 2008 11 Institution of Software Engineer... 2... 4... 4... 5... 5... 8... 8... 8... 8... 8... 9... 9... 9... 11... 13... 13... 13... 13... 15... 15... 15... 15... 16... 16... 17... 17... 17...

More information

LiveBOS产品白皮书

LiveBOS产品白皮书 面 向 对 象 的 业 务 支 撑 平 台 与 建 模 工 具 * 实 现 应 您 所 需, 随 时 而 变 的 应 用 * 业 务 管 理 应 用 软 件 最 佳 选 择 * LiveBOS 产 品 白 皮 书 LiveBOS 产 品 白 皮 书 福 建 顶 点 软 件 股 份 有 限 公 司 www.livebos.com Copyright c 1996-2009 版 权 所 有 福 建 顶

More information