Skip to content

22. 结论

让我们回顾一下本文中我们所做的工作。我们研究了两个具有以下两种架构之一层:

[DAO1] 层采用 Spring JDBC 实现,而 [DAO2] 层则采用 Spring JPA 实现 [DAO1] 和 [DAO2] 层实现了相同的 [IDAO] 接口,这使得编写单个测试用例 [JUnitTestDao] 来测试这两个 [DAO] 层;

完成上述工作后,我们通过以下方式在 Web 上公开了 [IDAO] 接口:

  • 在 [1] 中,[IDAO] 层是通过由 Spring MVC 实现的 [2] Web 层在 Web 上暴露的。 确实是 [IDAO] 接口被公开,我们根据该接口采用 [DAO-JDBC] 或 [DAO-JPA-JDBC] 架构进行实现,构建了两个版本的 Web 服务;
  • 在 [B] 架构中,远程客户端使用 Web 服务暴露的 URL 接口,从而访问 [IDAO-serveur] 层的方法。 我们确保 [DAO-Client] 和 [3] 层实现了 [IDAO-serveur] 和 [1] 接口。 这使我们能够复用已使用过两次的同一测试 [JUnitTestDao];
  • 在 [3] 中,[DAO-client] 层已通过 Spring RestTemplate 实现;

完成上述操作后,我们已对Web服务访问进行了安全加固:

  • 在 [5] 中,客户端的 HTTP 请求通过了使用 Spring Security 实现的身份验证层;

至此,我们已将之前的架构演进为以下架构:

  • 在 [3] 中,客户端应用程序本身是由 Web 服务器 [4] 提供的 Web 应用程序。 客户端应用程序在浏览器中呈现一个表单 [5],用于向安全 Web 服务的 URL 发起查询。 对安全 Web 服务的 HTTP 访问是通过用 JavaScript 实现的 [jS] 层完成的。该架构实现了所谓的跨域请求:
    • Web服务提供形式为URL的[http://machine1:port1/];
    • 客户端Web应用程序从URL下载[http://machine2:port2/]。 如果 [http://machine2:port2/] 与 [http://machine1:port1/] 不完全一致(即使在同一台机器、同一端口上),则客户端浏览器将阻止 HTTP 层发出的 [DAO-client-js] 调用。 为解决此问题,Web 服务必须允许跨域请求;

所展示的项目已在以下六种数据库上进行了测试:

  • MySQL 5 Community Edition;
  • SQL Server 2014 Express;
  • PostgreSQL 9.4;
  • Oracle Express 11g 版本 2;
  • IBM DB2 Express-C 10.5;
  • Firebird 2.5.4;

针对上述每个 SGBD,我们开发了四种不同的 [DAO] 层:

  • 一个基于 Spring 实现的层 JDBC;
  • 一个基于 Spring JPA 并使用 Hibernate 提供程序 JPA 实现的层;
  • 一个基于 Spring JPA 并使用 JPA EclipseLink 提供商的层;
  • 一个基于 Spring 实现的层 JPA 及其提供者 JPA OpenJPA;

因此,本次共展示了二十四种不同的配置方案。我们进行了大量的代码重构:

  • 大部分代码仅编写一次。该方案基于两个Maven配置项目:
    • 一个用于配置 JDBC 层;
    • 另一个负责配置 JPA 层;

针对特定 SGBD 的 JDBC [1] 配置 Maven 项目可实现:

  • 导入驱动程序存档 JDBC;
  • 定义所用数据库的访问凭据,以及 SQL 层将向 JDBC 驱动程序发送的各类 [DAO1] 命令。 尽管SQL已标准化,但仍遇到了可移植性问题,这主要是因为查询中包含的表名/列名在某些SGBD中被证明是禁止使用的关键字 (例如 ROLES 表对应 DB2,PASSWORD 列对应 Firebird)。 此外,尽管列名通常不区分大小写,但在 PostgreSQL 中,表的主键列 ID 却出现了问题。 它要求该列命名为全小写的 id

针对特定 SGBD 的 JPA、[2] 配置层这三个 Maven 项目,允许:

  • 导入 JPA 实现的归档文件;
  • 配置用于连接特定 SGBD 的 JPA 实现。 实际上,正是 JPA 层向 JDBC 层发送 SQL 命令。 为了有效运作,它必须知道 SGBD,以便向其发送 SQL 命令,而该层会识别这些命令。 这些命令可利用作为该 SGBD 所有者的 SQL,以及后者的特定特性(数据类型、序列、触发器、存储过程、主键自动生成等);

由此创建了二十四个 Maven 配置项目(4 种配置 × 6 个 SGBD),所有其他数据库操作项目均基于这些配置项目。 在上述架构中,由于 [DAO1] 和 [DAO2] 层提供相同的接口,因此上述两个架构的 24 种配置均使用唯一的测试类 [JUnitTestDao] 进行了测试。 在验证了这些架构后,便不再存在困难:

  • 将数据库发布到 Web 上的 Maven 项目基于这两种架构。因此,这里同样有 24 种可能的配置;
  • 用于保障Web服务访问安全的Maven项目基于前一个项目,同样拥有24种可能的配置;
  • 最后,支持向安全Web服务发起跨域请求的Maven项目基于前一个项目,同样拥有24种可能的配置;

尽管本文档并未涵盖 Java 语言的所有功能及其所有应用领域,但仍可作为该语言的学习资料。掌握本课程内容的读者,无论在语言使用还是 Spring 框架应用方面,都将达到“Java 高级”水平。届时,读者可通过以下书籍继续深造:

  • [Spring MVC et Thymeleaf par l'exemple] [http://tahe.developpez.com/java/springmvc-thymeleaf] 该书延续了对Spring生态系统的学习,重点介绍了其“Web编程”分支 MVC。书中使用的数据库比本文所探讨的更为复杂;
  • [Tutoriel AngularJS / Spring MVC] [http://tahe.developpez.com/angularjs-spring4] 采用客户端/服务器架构,其中客户端基于 [AngularJS] 框架实现,服务器基于 [Spring MVC] 实现;
  • [Introduction à Java EE] [http://tahe.developpez.com/java/javaee] 该方案摒弃了 Spring 框架,转而采用基于 JSF(Java Server Faces)和 EJB(Enterprise Java Bean)的 Web 架构;
  • [Introduction à la programmation des tablettes Android] [http://tahe.developpez.com/android/exemples-intellij-aa] 描述了一种客户端/服务器架构,其中客户端是使用 Java 编程的 Android 平板电脑,服务器是由 Spring 实现的 Web 服务 MVC;