Spring +MyBatis企业应用实战(一)

第1章 Java EE 应用

本章要点

  • Java EE 应用的基础知识
  • Java EE 应用的模型和相关组件
  • Java EE 应用的结构和优势
  • 轻量级 Java EE 应用的相关技术

时至今日, 轻量级Java EE 平台在企业开发中占有绝对的优势, Java EE 应用以其稳定的性能、良好的开放性以及严格的安全性,深受企业应用开发者的青睐。实际上,对于信息化要求较高的行业,如银行、电信、证券以及电子商务等,都不约而同地选择了Java EE 作为开发平台。

对于一个企业而言,选择Java EE 构建信息化平台,更体现了一种长远的规划:企业的信息化是不断整合的过程,在未来的日子里,经常会有不同的平台、不同的异构系统需要整合。Java EE 应用提供的跨平台、开放性以及各种远程访问技术,为异构系统的良好整合提供了保证。

一些有高并发、高稳定要求的电商网站(如淘宝、京东等),公司创立之初并没有采用Java EE技术架构(淘宝早期用PHP,京东早期用 .NET),但当公司的业务一旦真正开始,他们马上就发现PHP、.NET无法支撑公司业务运营,后来全部改为使用Java EE技术架构。就目前的局面来看,Java EE 已经成为真正企业级应用的不二之选。

spring boot.jpg

1.1 Java EE 应用概述

今天所说的Java EE应用,超出了Sun所提出的经典Java EE应用规范,而是一种更广泛的开发规范。经典Java EE往往以EJB(企业级Java Bean)为核心,以应用服务器为运行环境,所以开发、运行成本较高。本书所介绍的Spring MVC + MyBatis作为轻量级Java EE应用不仅具备Java EE规范的种种特征,例如面向对象建模的思维方式、优秀的应用分层及良好的可扩展性、可维护性,而且保留了经典Java EE 应用的架构,但其开发、运行成本更低。

1.1.1 Java EE 应用的分层模型

不管是经典的Java EE架构,还是本书介绍的轻量级Java EE架构,大致上都可分为如下几层:

  • Domain Object(领域对象)层。 此层由一系列的POJO(Plain Old Java Object,普通的、传统的Java对象)组成,这些对象是该系统的Domain Object(领域对象),往往包含了各自所需实现的业务逻辑方法。
  • DAO(Data Access Object,数据访问对象)层。 此层由一系列的DAO组件组成,这些DAO实现了对数据库的创建、查询、更新和删除(CRUD)等原子操作。
  • Service(业务逻辑)层。 此层由一系列的业务逻辑对象组成,这些业务逻辑对象实现了系统所需的业务逻辑方法。这些业务逻辑方法可能仅仅用于暴露Domain Object对象所实现的业务逻辑方法,也可能是依赖DAO组件实现的业务逻辑方法。
  • Controller(控制器)层。 此层由一系列控制器组成,这些控制器用于拦截用户请求,并调用业务逻辑组件的业务逻辑方法,处理用户请求,并根据处理结果向不同的表现层组件转发。
  • View(表现)层。 此层由一系列的JSP页面、Velocity页面、PDF文档视图组件组成,负责收集用户请求,并显示处理结果。

注意:
在经典Java EE 应用中,DAO层也被成为EAO层,EAO层组件的作用与DAO层组件的作用基本相似。只是EAO层主要完成对实体(Entity)的CRUD操作,因此成为EAO层。
DAO层在MyBatis中也被成为Mapper层,其通过SQL语句的映射完成CRUD操作。

各层的Java EE 组件之间以松耦合的方式耦合在一起,各组件并不以硬编码方式耦合,这种方式是为了应用以后的扩展性。从上向下,上面组件的实现依赖于下面组件的功能;从下向上,下面组件支持上面组件的实现。

1.1.2 Java EE 应用的组件

通过上一节的介绍,我们可以看到Java EE 应用提供了系统架构上的飞跃。Java EE架构提供了良好的分离,隔离了各组件之间的代码依赖。

总体而言,Java EE 应用大致包括如下几类组件:

  • 表现层组件。 主要负责收集用户输入数据,或者先客户显示系统状态。最常用的表现层技术是JSP,但JSP并不是唯一的表现层技术。表现层还可有Velocity、FreeMarker和Tapestry等技术完成,或者使用普通的应用程序充当表现层组件,甚至可以是小心智能设备。
  • 控制器组件。 对于Java EE的MVC框架,其提供一个前端核心控制器,核心控制器负责拦截用户请求,并将请求转发给用户实现的控制器组件。这些用户实现的控制器组件则负责调用业务逻辑方法,处理用户请求。
  • 业务逻辑组件。 这是系统的核心组件,实现系统的业务逻辑。通常,一个业务逻辑方法对应一次用户操作。一个业务逻辑方法应该是一个整体,因此要求对业务逻辑方法增加事务性。业务逻辑方法仅仅负责实现业务逻辑,不应该进行数据库访问。因此,业务逻辑组件中不应该出现原始的MyBatis、Hibernate和JDBC等API。
  • DAO组件。 这个类型的对象比较缺乏变化,每个DAO组件都提供Domain Object对象基本的创建、查询、更新和删除等操作,这些操作对应于数据库的CRUD(创建、查询、更新和删除)等原子操作。当然,如果采用不同的持久层访问技术,DAO组件的实现会完全不同。为了业务逻辑组件的实现与DAO组件的实现分离,程序应该为每个DAO组件都提供接口,业务逻辑组件面向DAO接口编程,这样才能提供更好地解耦。
  • 领域对象组件。 领域对象(Domain Object)抽象了系统的对象模型。通常而言,这些领域对象的状态都必须保存在数据库里。因此,每个领域对象通常对应一个或多个数据表,领域对象通常需要提供对数据记录的访问方式。

提示:

保证业务逻辑组件之间不出现MyBatis、Hibernate和JDB等API,有一个更重要的原因:为保证业务逻辑方法的实现,与具体的持久层访问技术分离。当系统需要在不同持久层技术之间切换时,系统的业务逻辑组件无须任何修改。有时会见到一些所谓的Java EE应用,居然在JSP页面里面调用SqlSessionFactory、SqlSession等API,这无疑是非常荒唐的,这种应用仅仅是使用MyBatis,完成没有脱离Model 1的JSP开发模式,这是相当失败的结构。实际上,不仅JSP,Servlet中也不应出现持久层API,包括JDBC、MyBatis、Hibernate API。最理性的情况是,业务逻辑组件中都不应出现持久层API。

1.1.3 Java EE 应用的结构和优势

作为Java EE的初学者,常常有一个问题:明明可以使用JSP完成这个系统,为什么还要使用MyBatis和Hibernate等技术?难道仅仅是为了听起来高深一些?明明可以使用纯粹的JSP完成整个系统,为什么还要将系统分层?

要回答这些问题,就不能仅仅考虑系统开发过程,还需要考虑系统后期的维护、扩展;而且不能仅仅考虑小型系统,还要考虑大型系统的协同开发。如果是用于个人学习、娱乐的个人站点,的确没有必要使用复杂的Java EE应用框架,采用纯粹的JSP就可以实现整个系统。

但对于大型信息化系统,采用Java EE 应用架构则有很大的优势。

对于信息化系统,前期开发工作对整个系统工作量而言,仅仅是小部分,而后期的维护、升级往往占更大的比重。更极端的情况是,可能在前期开发期间,企业需求已经发生变化,而这种改变是客观的,软件系统必须适应这种改变,这要求软件系统具有良好的伸缩性。

这种框架结构其目的是让应用的各种组件以松耦合的方式组织在一起,让应用之间的耦合停留在接口层次,而不是代码层次。

1.2 轻量级Java EE应用相关技术

轻量级Java EE应用以传统的JSP作为表现层技术,以一系列开源框架作为MVC层、中间层、持久层解决方案,并将这些开源框架有机地组合在一起,使得Java EE应用具有高度的可扩展性、可维护性。

1.2.1 JSP、Servlet和JavaBean及替代技术

JSP是最早的Java EE规范之一,也是最经典的Java EE技术之一。直到今天,JSP依然广泛地应用于各种Java EE应用中,充当Java EE应用的表现层角色。

JSP具有简单、易用的特点,JSP的学习路线平坦,而且国内有大量JSP学习资料,所以大部分Java学习者学习Java EE开发都会选择从JSP开始。

Servlet和JSP其实完全统一的,二者底层的运行原理是完全易用的。实际上,JSP必须被Web服务器编译成Servlet,真正在Web服务器内运行的是Servlet。从这个意义上来看,JSP相当于一个”草稿“文件,Web服务器根据该”草稿“文件生成Servlet,真正提供HTTP服务的是Servlet,因此广义的Servlet包含了JSP和Servlet。

就目前的Java EE应用来看,纯粹的Servlet已经很少使用了,毕竟Servlet的开发成本太高,而且使用Servlet充当表现层将导致表现层页面难以维护,不利于美工人员参与Servlet开发,所以在实际开发中大都使用JSP充当表现层技术。

Servlet 3.x 规范的出现,再次为Java Web 开发带来了巨大的便捷。Servlet 3.x 提供了异步请求、注解、增强的Servlet API 、非阻塞IO功能,这些功能都极大地简化了Java Web 开发。

由于JSP只负责简单地显示逻辑,因此JSP无法直接访问应用的底层状态,Java EE 应用会选择使用JavaBean来传输数据。在严格的Java EE 应用中,中间层的组件会将引用底层的状态信息封装成JavaBean 集,这些JavaBean也被成为DTO(Data Transfer Object,数据传输对象),并将这些DTO集传到JSP页面,从而让JSP可以显示应用的底层状态。

在目前阶段,Java EE应用除了可以使用JSP作为表现层技术之外,还可以使用FreeMarker或Velocity作为表现层技术,这些表现层技术更加纯粹,使用起来更加便捷,完全可以作为JSP的替代。

1.2.2 MyBatis3及替代技术

传统的Java应用都是采用JDBC来访问数据库的,但传统的JDBC采用的是一种基于SQL的操作方式,这种操作方式与Java语言的面向对象特性不太一致,所以Java EE应用需要一种技术,通过这种技术能让Java 以面向对象的方式操作关系数据库。

这种特殊的技术就是ORM(Object Relation Mapping),最早的ORM是Entity EJ(Enterprise JavaBean),EJB就是经典Java EE应用的核心,从EJB 1.0 到EJB 2.x,许多人会觉得EJB非常烦琐,所以导致EJB备受诟病。

在这种背景下,Hibernate框架应运而生。Hibernate框架是一种开源的、轻量级的ORM框架,它允许将简单的、传统的Java对象(POJO)映射成持久化类,允许应用程序已面向对象的方式来操作POJO,而Hibernate框架则负责将这种操作转换成底层的SQL操作。

大多数情况下(特别是对新项目、新系统的开发而言),Hibernate这样的机制无往不利,大有一统天下的势头。但是,在一些特定的环境下,Hibernate这种一站式的解决方案却未必适合。如:

  • 系统的部分或全部数据来自现有的数据库,出于安全考虑,只对开发团队提供几条Select SQL(或存储过程)以获取所需数据,具体的表结构不予公开。
  • 开发规范中要求,所有牵涉到业务逻辑部分的数据库操作,必须在数据库层由存储过程实现(就金融行业而言,工商银行、中国银行、交通银行等商业银行都曾在开发规范中严格规定)。
  • 系统数据处理量巨大,性能要求极为苛刻,这往往意味着我们必须通过经过高度优化的SQL语句(或存储过程)才能达到系统性能设计指标。

面对这样的需求,Hibernate不再适合,甚至无法使用。此时,直接使用JDBC进行数据库操作实际上也是不错的选择,只是拖沓的数据库访问代码、乏味的字段读取操作令人烦烦,而“半自动化”的MyBatis,却正好解决了这个问题。

这里的“半自动化”,是相对Hibernate等提供了全面地数据库封装机制的“全自动化”ORM实现而言的,“全自动”ORM实现了POJO和数据库表之间的映射,以及SQL的自动生成和执行。而MyBatis的着力点,则在于POJO与SQL之间的映射关系。也就是说,使用MyBatis提供的ORM机制,对业务逻辑实现人员而言,面对的是纯粹的Java对象,这一层与通过Hibernate实现ORM而言基本一致,而对于具体的数据操作,Hibernate会自动生成SQL语句,但MyBatis则并不会为程序员在运行期自动生成SQL语句。具体的SQL需要程序员编写,然后通过映射配置文件,将SQL所需的参数以及返回的结果字段映射到指定的POJO。

相对Hibernate等“自动化”ORM机制而言,MyBatis以SQL开发的工作量和数据库移植性上的让步,为系统设计提供了更大的自由空间。作为“全自动”ORM实现的一种有益补充,MyBatis的存在具有特别的意义。

MyBatis是Apache组织提供的一个轻量级持久层框架,是一个支持普通SQL查询、存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置过程以及结果集的检索封装。MyBatis可以使用简单的XML或注解来进行配置和原始映射,将接口和Java的POJO映射成数据库中的记录。

MyBatis作为持久层框架,其主要思想是将程序中的大量SQL语句剥离出来,配置在配置文件中,实现SQL的灵活配置。这样做的好处是将SQL与程序代码分离,可以在不修改程序代码的情况下,直接在配置文件中修改SQL。

MyBatis最新版本是3.4.1,这也是本书所使用的MyBatis版本。

除此之外,Oracle的TopLink、Apache的OJB都可以作为替代方案。但由于种种原因,它们并未得到广泛的市场支持,所以这两个框架的资料、文档相对比较少,选择它们需要一定的勇气和技术功底。

1.2.3 Spring 4 及替代技术

如果你有5年以上的Java EE 开发经验,并主持过一些大型项目的设计,你会发现Spring 框架似曾相识。Spring甚至没有太多的新东西,它只是抽象了大量Java EE应用中的常用代码,将它们抽象成一个框架。通过使用Spring可以大幅度地提高开发效率,并可以保证整个应用具有良好的设计。

Spring框架里充满了各种设计模式的应用,如单例模式、工厂模式、抽象工厂模式、命令模式、职责链模式、代理模式等,Spring框架的用法、源码则更是一道丰富的Java大餐。

Spring框架号称Java EE应用的一站式解决方案,Spring本身提供了一个设计优良的MVC框架:Spring MVC。使用Spring框架可以直接使用该MVC框架。由于Spring框架拥有极高的市场占有率,因此越来越多的Spring框架的使用者使用Spring MVC替代曾经的MVC框架的王者Struts2。当然,Spring也可以无缝地整合Struts2、JSF等优秀的MVC框架。

Spring框架并未提供完整的持久层框架,可以将其理解成一种“空”,但这种“空”正是Spring框架的魅力所在。Spring能与大部分持久层框架无缝整合:MyBatis、Hibernate、JPA、TopLikn,更甚至直接使用JDBC,随便你喜欢,无论选择哪种持久层框架,Spring都会为你提供无缝的整合及极好的简化。

从这个意义上来看,Spring更像一种中间层容器,Spring向上可以与MVC框架无缝整合,向下可以与各种持久层框架无缝整合,其的确具有强大的生命力。由于Spring框架的特殊地位,因而轻量级Java EE 应用通常都不会拒绝使用Spring。实际上,轻量级Java EE 这个概念也是由Spring框架衍生出来的。Spring框架暂时没有较好的替代框架。

Spring的最新版本是4.2.0,本书所介绍的Spring也是基于该版本。

1.2.4 使用开源框架的好处

以上提到的Struts2、MyBatis3、Hibernate4、Spring4等都是Java领域最常见的框架,这些框架得到广泛的开发者支持,它们能极大地提高Java EE应用的开发效率,并能保证应用具有稳定的性能。

越来越多的企业开始选择Spring MVC +MyBatis来构建系统架构,在电商热门的今天,Spring MVC+MyBatis已成为电商项目架构的最佳搭配。本书将重点讲解Spring MVC +MyBatis如何无缝整合开发Java EE项目。

常常有些初学者,甚至包括一些所谓的企业开发人士提出:为什么需要使用框架?用JSP和Servlet已经足够了。

提出这些疑问的人通常还未真正进入企业开发,或者从未开发一个真正的项目。因为真实的企业应用开发有两个重要的关注点:可维护性和复用。

先从软件的可维护性来考虑这种说法。全部采用JSP和Servlet的应用,因为分层不够清晰,业务逻辑的实现没有单独分离出来,从而造成系统后期维护困难。

从软件复用角度来考虑。这是一个企业开发的生命,企业以追求利润为最大目标,企业希望以最快的速度,开发出最稳定、最实用的软件。因为系统没有使用任何框架,每次开发系统都需要重新开发,重新开发的代码具有更多的漏洞,这就增加了系统出错的风险;另外,每次开发新代码都需要投入更多的人力和物力。

以笔者多年的实际开发经验来看,每个公司都有自己的基础类库,这就是软件的复用,这些基础类库将在后续开发中多次被重复使用。例如,信息化系统,其中总有一些开发过程是重复的,为什么不将这些重复开发工作抽象成基础类库呢?这种抽象既提高了开发效率,而且因为重复使用,也降低了引入错误的风险。

因此只要是一个有实际开发经验的软件公司,就一定有自己的一套基础类库,这就是需要使用框架的原因。从某个角度来看,框架也是一种基础类库,它抽象了软件开发的通用步骤,让实际开发人员可以直接利用这部分实现。当然,即使使用JSP和Servlet开发的公司,也可以抽象出自己的一套基础类库,那么这也是框架!一个从事实际开发的软件公司,不管它是否意识到,它已经在使用框架。区别只有:使用的框架到底是别人提供的,还是自己抽象出来的。

到底是使用第三方提供的框架更好,还是使用自己抽象的框架更好?这个问题就见仁见智了。通常而言,第三提供的框架更稳定,更有保证,因为第三方提供的框架往往经过了更多人的测试。而使用自己抽象的框架,则更加熟悉底层运行原理,在处理问题上更有方向性。如果不是有非常特殊的理由,还是推荐使用第三方框架,特别是那些流行的、广泛使用的、开源的框架。

1.3 本章小结

本章主要介绍了Java EE应用的相关基础知识,其中,简要介绍了Java EE应用应该遵循怎样的架构模型,通常应该具有哪些组件,以及这些组件通常使用什么样的技术来实现。本章还简单归纳了Java EE应用所具有的优势和吸引力。

本书使用的是Apache Tomcat Web服务器,使用的开发工具是Eclipse。

第2章将重点介绍Spring MVC。

发表评论

电子邮件地址不会被公开。