Java EE的轻量级开发利剑:Spring Boot实战

978-7-115-57765-8
作者: 王波
译者:
编辑: 刘雅思
分类: Java

图书目录:

详情

本书以Java EE的最佳实践为主题,全面阐述Spring Boot、Spring MVC、Spring Cloud等企业级领域内的热门技术。本书讲解相关技术框架的核心知识,并结合汽车管理系统等实战项目,把Java EE领域内流行的SSH、SSM、Spring Boot、Spring Cloud、MyBatis和JPA等框架整合起来,再从代码层面讲述Activiti、Kafka、Redis、Docker、Maven、WebService和POI等经典技术。通过本书深入浅出的讲解,读者在学习Java架构师必备专业技能的同时,还可以学习项目开发的整个过程,真正意义上做到Spring Boot从入门到精通。 本书适合Java EE领域的开发人员阅读。阅读本书,读者可以学习目前流行的Java开发技术,力争在短时间内掌握Spring Boot核心技术,成为Java架构师,走向自己职业生涯的辉煌。

图书摘要

版权信息

书名:Java EE的轻量级开发利剑:Spring Boot实战

ISBN:978-7-115-57765-8

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

著    王 波

责任编辑 刘雅思

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


本书以Java EE的最佳实践为主题,全面阐述Spring Boot、Spring MVC、Spring Cloud等企业级领域内的热门技术。本书讲解相关技术框架的核心知识,并结合汽车管理系统等实战项目,把Java EE领域内流行的SSH、SSM、Spring Boot、Spring Cloud、MyBatis和JPA等框架整合起来,再从代码层面讲述Activiti、Kafka、Redis、Docker、Maven、WebService和POI等经典技术。通过本书深入浅出的讲解,读者在学习Java架构师必备专业技能的同时,还可以学习项目开发的整个过程,真正意义上做到Spring Boot从入门到精通。

本书适合Java EE领域的开发人员阅读。阅读本书,读者可以学习目前流行的Java开发技术,力争在短时间内掌握Spring Boot核心技术,成为Java架构师,走向自己职业生涯的辉煌。


Java语言的发展非常迅速,伴随Java语言发展起来的各类框架技术也推陈出新。从最初的Servlet到Struts,再到Spring MVC,直至今天异常火爆的Spring Boot,一转眼技术的发展就已经过去了二十多年。在这段漫长的时间里,Servlet从最初的1.0版本发展到了如今的4.0版本,Struts从1.0版本过渡到了目前的2.5版本,Spring MVC作为Spring的重要组成部分(子项目或者技术特性,版本号源自Spring),也已经从1.0版本发展到了如今的5.0版本,本书的主要角色Spring Boot则从1.0版本发展到了目前的2.1.6版本。与此同时,Java语言的JDK从第1版发展到了第14版,但现有的里程碑版本仍然是第6版、第8版和第10版。最新的版本并没有被大面积应用,这是因为做任何事情都是需要时间的,“欲速则不达”,大家仍然习惯使用稳定的里程碑版本来做项目。而在每年发布的编程语言排行榜上,Java总是名列前茅,经常处于第一的位置,其热门程度可见一斑。

回顾这几十年的发展,Java语言每次更新后提供的特性总是让Java变得越发“高端”且简单。当然,并不是所有的新特性都会很快在项目中应用起来,毕竟广大程序员需要一个学习和适应新特性的过程。无论如何,Java语言从JDK 5开始,就让程序员的编程习惯有了一定的固化,这是因为JDK 5引入了泛型、枚举、静态导入、可变参数、内省、注解等令人震惊的概念,让程序员的编程习惯、工作效率得到了巨大的改变,可以说是焕然一新。因此,JDK 6是一个跨时代的经典版本,这全仰仗于JDK 5在技术特性上的革新。当然,JDK 6本身也提供了一些新的特性,例如提供了Compiler API来动态编译Java源文件,使得程序员修改Java服务器页面(Java Server Pages,JSP)后,不用重启服务器(JSP本身就是基于Java代码的,第一次访问会被服务器编译成.java文件和.class文件,以后访问的时候直接调用.class文件)。虽然JDK 6提供的特性远没有JDK 5那么丰富,但是两者的特性叠加起来就厉害了,这些特性汇集成了一种成熟的开发模式。因此,JDK 6成为一个稳定、经典的里程碑版本,这也是很多Java图书固执地从JDK 6版本讲起的原因。只有从第一个里程碑版本JDK 6讲起,再过渡到第二个里程碑版本JDK 8,当有需要的时候再过渡到第三个里程碑版本JDK 10,才是正确、科学的教学方法,让读者真正做到从零开始学习和见证Java编程的完整过程。

如果说单从技术层面来理解JDK版本这件事情略显单薄的话,那么从市场的角度来理解JDK版本,我们会发现,上面的结论仍然是正确的。当下很多公司在项目中采用的JDK版本通常不是JDK 6就是JDK 8,而JDK 7只是一个过渡版本。当然,也有一些公司已经把JDK版本升级到了10,但这样的公司并不是特别多。从实际的项目开发来说,我们选择里程碑版本依然是正确的。至于JDK 7和JDK 8的新特性,这里就不赘述了,本书的某些合适的章节会讲解一些有用的特性。在这里,我们只需要明白,编程技术的发展是日新月异的,正确的做法就是,在分析完这些新技术之后,找出其中最合适的内容来完成项目的技术选型和框架搭建。当然,这也正是我们学习Spring Boot的一个重要原因,它已经逐渐代替或者同化了Spring MVC,集框架技术之大成,令人刮目相看。

前面说到了JDK的版本问题,接着,我们简单地介绍一下框架技术的发展历程,来说明必须学习Spring Boot框架的原因。在Struts1时代,程序员基本上使用JavaBean、JSP、Spring和Struts 1,在持久层中使用传统的JDBC或者Hibernate,通过这几种技术的叠加形成一个成型的框架技术组合。这样的局面持续几年后,进入了Struts 2时代,与此同时,技术圈里也出现了MyBatis这种ORM框架,只是还没有流行起来。不过,当时确实是“SSH框架的天下”,如果程序员不懂SSH,基本上是没法“混饭吃”的。这种局面又持续了几年,Java Web开发领域逐渐进入Spring MVC时代。技术更新换代,新技术比老技术更加具有优势,这些优势主要表现在安全性、易用性与执行效率上。举个典型的例子,Spring MVC框架本身就是属于Spring Framework平台的,我们在集成框架的时候,可以直接集成Spring的内容,再加上ORM框架,就可以完成整个框架的搭建,又何必多此一举来集成Struts呢?况且,Struts 2在安全性上的表现也不尽如人意,例如,2016年一些网站的数据泄露事件就是由于有人利用了Struts 2的漏洞,虽然Apache团队紧急发布了Struts 2的新版本来修复这些问题,但已经失去了很多使用者,用户纷纷投入Spring MVC的怀抱。再者就是Spring MVC在执行效率和开发效率上都要比Struts 2高,因此当时的情况就是Spring MVC框架逐渐代替了Struts 2。

那么Spring MVC和Spring Boot又有什么关系呢?这个问题会在本书的正文中展开讨论。在这里,我们只需要明白一点,那就是这两个框架系出同源,可以笼统地说Spring Boot是Spring MVC的升级版,也可以称Spring Boot是工具集成包。这两者的区别主要是,Spring MVC框架自身需要用户手动配置的内容过多,而Spring Boot框架通过各种工具集成,帮助用户做好了这些配置,甚至将Tomcat也内嵌到了框架之中。这样一来,程序员便可以更加安心地投入业务的开发,不用再为那些数不清的配置而烦恼。但是,从框架的技术使用方法来看,使用Spring Boot跟使用Spring MVC基本上是一样的。因此,我们在学习Spring Boot的时候,其实就已经在学习Spring MVC。不过,笔者还是建议把这两个框架分开来对待,不能把两者混淆,毕竟Spring Boot提供的新特性很多。纵观Java框架技术的发展历程,我们可以看到,不论是CGI还是EJB,又或者是SSH,都曾经扮演过重要的角色,而软件开发本身就是一个追求效率的事情,因此它们逐渐落后甚至被淘汰亦是客观规律。在学习的时候,读者应该保持清醒的头脑,重点学习当前迫切需要使用的知识技能,而对于那些逐渐落伍的东西浅尝辄止即可,切莫花费大量的时间去关注,否则得不偿失!

2014年4月,Spring Boot 1.0正式发布,从此,Java EE的开发又迎来了新的篇章。直到2020年,Spring Boot占领了大部分市场。Spring Boot诞生之初就受到了开源社区的持续关注,从企业陆续使用,到现在的遍地开花,短短的几年间便获得了广泛的关注度。这点通过搜索引擎的指数就能知道,Spring Boot的搜索指数居高不下。

说到底,虽然国内关于Spring Boot的图书不少,但它们的侧重点各不相同,有的重点讲知识概念,有的重点讲项目,而能够将两者结合起来,真正做到从入门到精通的图书却是凤毛麟角,这就造成了大家在学习上的困扰。因此,我开始思考如何写一本这样的书,我跟阿里巴巴的工程师赵伟取得了联系,我们各抒己见,讨论了很久,他很支持我的想法。而我思考再三,也总算是确定了这本书的大致内容,遂动笔写作。

最后,希望各位读者与我共勉,都能从技术中得到快乐,从阅读中汲取知识,真正把Spring Boot作为Java EE领域中的最佳实践来推广和开发,成长为一名优秀的架构师。也希望亲爱的读者朋友通过本书的内容,真正学习到Spring Boot这门令人耳目一新的技术。

本书结合实际,深入浅出,全书共10章。前9章着重讲解Spring Boot的各类知识技能,其中包括Spring的功能(如控制反转、依赖注入、面向切面编程等)和Spring MVC的相关知识(如常用的注解、核心类、执行过程等),重点讲解MyBatis、MySQL、JPA等数据库方面的内容,其他内容全部都是与Spring Boot相关的,通过科学的划分与梳理,更加方便读者学习和掌握。学完前9章,读者就掌握了本书的绝大部分内容,接着通过第10章,读者可以亲自开发一个汽车管理系统项目,就能把全书的知识串联起来,做到融会贯通。这样的安排可谓匠心独运,非常适合读者从入门到精通。

笔者总结了自己多年来在Java Web领域的开发经验,从宏观层面上梳理了Spring Boot的整个框架知识体系,对这些内容进行了科学的划分,还亲自编写了大量示例程序,以供读者参考。另外,本书讲解的源码全部是基于浏览器/服务器(Browser/Server,B/S)架构的,读者可以反复练习,这样不但对学习Spring Boot这个框架有很大的作用,还能大大提升搭建框架的能力,可谓一举多得。

本书通俗易懂、内容丰富,不但重点讲述Spring Boot的核心知识,还提供项目实战的源码,大幅度降低学习难度。在架构知识拓展方面,本书还详细讲解了Spring与Spring MVC的相关技术。当然,为了让读者能够最大程度上见证Java框架技术的发展历程,本书还加入了EJB的快速入门级的编程内容,让读者通过编写简单、少量的代码,就能完全明白EJB编程是怎么一回事。另外,读者在学习的时候需要学会阅读注释,首先要明白当前这段程序是怎么运行的,然后把整个程序调试一遍,才能掌握讲解的内容。如果读者需要全面掌握Java的核心知识技能,可以参考笔者的另一本图书——《Java架构师指南》,该书在知识的广度上更加突出,而本书则专注于新的框架技术Spring Boot。本书也适合刚步入职场的新手,因为每段代码中都有详细的注释,并配有代码解析,方便读者领会代码的含义。

本书的内容包含Spring Boot的核心技术,以及使用该技术时所需要掌握的其他必备技能,例如SSH、Spring MVC、前端视图技术、数据库、单点登录等实用技术。这样组织内容的作用非常明显,那就是读者通过阅读本书,便可能成为一名全栈工程师或者架构师。本书各章的主要内容如下。

第1章讲述Spring家族、Spring基础环境搭建,以及EJB编程快速入门等。通过搭建简单的环境,开发出本书第一个程序。

第2章从Spring Boot必备的基础知识入手,讲解Spring的常用技术,如依赖注入、面向切面编程开发模式、注解、控制反转等技能;还有一些Java的核心API知识点,如Servlet、数据类型、类与接口、多线程与JVM等。

第3章讲解SSH框架,虽然SSH框架的使用逐年减少,但它仍然不失为一个经典的框架,因此本章的目标在于培养程序员的架构师思维。

第4章重点讲解Spring MVC框架。众所周知,Spring MVC是Spring Boot的基础,只有学习好本章的内容,才能更好地学习后面的章节,而Spring MVC是当前框架领域中一个承上启下的节点,因此读者想真正掌握Spring Boot,是必须认真学习该框架的。

第5章正式进入Spring Boot框架核心技术的讲解,其中包括框架搭建、核心类、需求开发,还有整合JPA以及当前热门的前端视图技术(FreeMarker与Thymeleaf)。

第6章讲解数据库方面的知识,主要包括MySQL、Oracle、MongoDB等数据库的应用,还有Redis快速入门、数据库加锁、分布式事务等内容。

第 7 章详细讲解安全框架Apache Shiro的权限管理和单点登录技术,演示如何将它们集成到Spring Boot框架中,并讲解WebService技术。

第8章讲解Spring Boot程序部署,内容包括Docker部署、Jenkins自动化部署等。

第9章讲解Spring Cloud微服务,通过一个简单但全面的项目,深入讲解微服务的常用组件,让读者真正理解微服务Spring Cloud与Spring Boot的关系与区别。

第10章是项目实战,通过重点讲解汽车管理系统部分功能的开发过程,带领读者把本书所有的知识串联起来,真正意义上做到对Spring Boot从入门到精通。

约定优于配置是Spring Boot的核心思想之一,其重要意义在于,编程的时候,为了最大化地享受简单与高效,框架会把成百上千的配置都设置为默认值。程序员在编写代码的时候,只需要对一些独特的属性进行自定义配置,而其他属性可保持默认值。这样的话,程序员便会更加专心地投入业务的开发,彻底从烦琐的文件配置(如令人诟病的XML配置)中解脱出来。在本书中,我也正式引入约定优于配置的概念。具体表现在两个方面:第一,基本上所有的代码都有解析内容,希望读者可以认真阅读,这些内容是掌握技术的重点;第二,书中的部分代码并不是完整的。因为软件项目的代码量特别多,本书无法把完整代码写到书里(部分练习代码除外),所以建议读者在阅读本书的时候,最好从Spring Boot源码下载地址获取完整代码并搭建好环境来学习,以获得最好的学习体验。

本书讲解Spring Boot框架的搭建和需求开发,以及上线部署的完整过程,特别适合Java EE领域的开发人员以及正在学习Java EE的读者。通过阅读本书的内容,读者朋友能够在较短的时间内,真正做到对Spring Boot从入门到精通。

需要明白一点,如果读者想要成为一名Java架构师的话,是绕不开Spring Boot框架体系的。因此,本书适合每一个想要成为全栈工程师、架构师的程序员,希望本书能给你们的成长带来帮助。

本书得以顺利出版,离不开我的不懈努力。作为一名软件工程师,必须有不断学习的觉悟,如果故步自封,不用几年,自己原有的知识体系就会落伍,跟不上时代,更谈不上传道解惑。软件工程师要想保证自己的核心竞争力,不但需要主动学习,还需要善于把自己在工作当中遇到的问题归纳起来,及时形成文档,这是一些个人经验,与大家共勉。另外,还要感谢我的家人、朋友对我的帮助,感谢人民邮电出版社的杨海玲编辑对我的信任和支持。

由于我的水平有限,书中难免有不足之处,恳请读者批评指正。欢迎读者通过电子邮件(453621515@qq.com)与我交流。


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

本书提供配套源代码。要获得相关配套资源,请在异步社区本书页面中点击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,点击“提交”按钮即可。本书的作者和编辑会对您提交的勘误信息进行审核,确认并接受您的建议后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

扫描下方二维码,您将会在异步社区微信服务号中看到本书信息及相关的服务提示。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频或者参与图书技术审校等工作,可以直接发邮件给本书的责任编辑(liuyasi@ptpress.com.cn)。

如果您来自学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接通过邮件发给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端和网络技术等。

异步社区

微信服务号


Spring是一个家族,里面有很多的项目,如Spring Boot、Spring Data、Spring Security和Spring Cloud等,这些项目都有自己独特的功能和适应场景。Spring Framework体系适用于Web项目,它提供了很多经典的功能,如控制反转(Inversion of Control,IoC)、依赖注入(Dependency Injection,DI)、面向切面编程(Aspect Oriented Program,AOP)等。本书的主要内容Spring Boot的应用场景,则是快速构建Web应用程序,如构建以Spring MVC架构为主的项目。至于它的效率如何,我们会在后面的章节详细讲解,并且阐述它与其他框架之间的优劣。

从Spring官方网站可以看到Spring家族的主要项目。Spring家族是非常庞大的,项目非常多,图1-1中只展示了6个,而目前Spring官方网站上列出来的项目多达22个,当然这个数量仍然在慢慢增加。在Java EE软件开发中,我们经常使用的Spring家族中的项目大概只有几个,如常用的Spring、Spring Boot、Spring Data、Spring Security等。

图1-1 Spring家族的主要项目

这些项目在软件开发中扮演了不一样的角色,出场方式和出场时机也是不一样的。

Spring现在几乎已经成为Java项目的“标配”,Java项目几乎都需要集成Spring,这是因为需要使用Spring的依赖注入和控制反转功能来管理类,而不是每次都使用new关键字来新建Java类。当然,如何管理不同的逻辑层、业务层和持久层等层次之间的类的关系,也是Spring的主要功能之一。如果在项目中需要使用安全框架,我们的选择就不只有Apache Shiro了,也可以直接使用Spring Security,至于两者之间的优劣,就需要仔细讨论了,可谓仁者见仁,智者见智。如果需要页面流程控制,可以直接使用Spring Web Flow(SWF),当然Activiti也是不错的选择。最后,说说持久层方面的事情,我们可以直接使用传统的JDBC,也可以使用Hibernate,当然还可以使用Spring Data JPA,至于如何选择,就看项目初期的技术选型了。

Spring作为通用的Web框架技术,已经包含Spring MVC技术,而其他Spring项目中或多或少也会用到Spring Framework提供的技术支撑,这也就解释了一些Spring项目使用Spring MVC来开发的原因。例如,常见的SSM框架体系就是Spring、Spring MVC和MyBatis的集合。

Spring Boot是Spring家族最具代表性的产品之一。说到Spring家族,这里有必要介绍一下,该家族的成员非常多,活跃在软件开发领域的各个角落。在这里,我们只谈几个司空见惯的,例如Spring Cloud,它为开发者提供了微服务、分布式系统中所需要使用的工具包,包括配置管理、服务发现、断路器和负载均衡等工具,这些工具就跟Java开发者工具(Java Development Kit,JDK)里的各种API一样,可以开箱即用(直接拿来使用),可极大地提高企业构建分布式系统的效率。

Spring Data的作用是简化数据库的访问,包括关系数据库、非关系数据库等,如果使用关系数据库的话,Spring Data支持的存储技术包括Java数据库互连(Java Database Connectivity,JDBC)、Java持久化API(Java Persistence API,JPA)。

Spring Security是一个基于Spring企业应用的安全框架,能对用户进行可定制的身份验证和访问控制。它提供声明式的安全访问控制,主要包括用户认证和用户授权两个部分。用户认证指的是控制用户是否有登录权限,如对用户名和密码的验证;用户授权指的是控制用户是否拥有系统中某个功能的权限,以及是否拥有执行某个操作的权限。例如,常见的用户角色分配。在实现技术方面,主要使用了拦截器和面向切面编程。

SWF是建立在Spring MVC框架技术上的页面流引擎。如果项目中需要用到流程控制,例如办公自动化(Office Automation,OA)系统的请假审批,员工发起请假申请,先由项目经理审批,再由部门经理审批,最后由总经理审批,这样的一个过程就可以用SWF来实现。当然,SWF跟工作流还是有区别的,SWF是页面流,也就是控制页面的流转,它是一个通用的产品,而工作流则是紧贴工作的流程控制术语。当然,使用SWF来实现工作流是没有任何问题的,常见的工作流有Activiti、Java业务流程管理(Java Business Process Management,JBPM)等。

Spring MVC并不是Spring家族的项目,严格地说它是Spring Framework包含的一种框架技术,很多Spring的项目都是用Spring MVC来支撑的。简单地说,Spring MVC的作用就是处理和响应请求,获取前端参数、表单校验等,接着拦截前端请求,进行后端的业务逻辑处理,最后与数据库进行交互操作。Spring MVC是近年来逐渐流行起来的Java开发框架,其主要设计思想是抛弃Struts 2,直接利用Spring来实现MVC的设计理念,所以它被称作Spring MVC。在Spring MVC中,无须将Struts 2当作控制器来转发Action的请求,而是直接使用Spring自带的注解来实现方法级别的拦截。这样做的好处非常明显,可以不用集成Struts 2框架,直接使用Spring即可完成前后端交互,提高了性能和速度,也降低了开发难度。因为Spring的注解依靠它本身的拦截器机制,这项技术又依赖于面向切面编程设计理念,所以在代码可读性方面,Spring MVC也比Struts 2更有优势。为什么需要使用Spring MVC呢?一句话,Spring MVC简化了Web项目的开发流程,是用来处理Web方面问题的一个模块。因为Spring Framework的主要作用是管理类,所以在程序逻辑控制方面的技术,便直接统称为Spring MVC了,大家也习惯这个称呼了。如果在面试的时候,面试官问你项目中有没有使用到Spring,你可以回答使用过,用Spring来管理类,并且用Spring MVC来拦截请求。这样回答虽然简单,也是对的。虽然,我们也可以继续使用Struts 2、Servlet这些技术,但项目的整体性能便会下降很多,这个无须多言,就像CPU从i3升级到i7一样,性能肯定会大幅度提升。

本书的重点是讲述Spring Boot框架技术。想顺利、轻松地学习这一框架,并不是一件容易的事情,原因是虽然Spring Boot框架简化了Spring系列框架所需要的大量且烦琐的配置,并且集成了Tomcat服务器,但其开发细节仍然跟Spring MVC几乎无异。因此,在做Spring Boot项目的时候,我们可以省略配置服务器这个步骤,但仍然需要注意服务器的端口号冲突等问题。在需求开发方面,仍然需要编写大量代码。

Spring Boot框架当前的使用频率非常高,而针对它的介绍却非常简略——它就是一些开发工具的集合。这样的介绍虽然言简意赅,但不够形象、深入,让人无法窥一斑而知全豹。接下来我们从几个方面来阐述Spring Boot框架的核心功能和优势,让大家在宏观上对它有清晰的认识,知道它到底能做什么,它与其他框架又有何区别。

1.Spring Boot简化了哪些配置

首先,使用Spring Boot或者Spring MVC都需要加入Spring Framework,这是毋庸置疑的。我们需要使用Spring Framework来管理类,说白了就是使用它的控制反转、依赖注入、面向切面编程等技术。而使用这些技术,就需要在XML文件中编写大量的配置信息,来完成各种类关系的依赖配置。例如,“类B需要注入类A”这样的引入关系,且不说这些类具体的业务功能,相关的配置工作是必不可少的。如果项目中有成千上万的类都需要手动配置,那工作量会很庞大,极其耗费时间。Spring Boot就是为了省略这些步骤而出现的,它简化了Spring Framework的使用方法,所有的配置都有默认值,完全依赖于注解。在没有使用Spring Boot时,我们在做软件开发之前,经常需要写大量的配置信息,而自从使用了Spring Boot,便基本上不用去处理这些事情了。

2.Spring Boot能做什么

Spring Boot简化了框架配置,也让应用程序的部署变得非常简单,在启动的时候依赖Application主程序类,可以像调试Java代码一样,在集成开发环境(Integrated Development Environment,IDE)中点击鼠标右键,选择“Run As”→“Java Application”来启动整个项目。关于项目启动方面的配置,则在该类里通过注解完成。如果需要调试程序代码,则需要在IDE中点击鼠标右键,选择“Debug As”→“Java Application”。当然,你也可以使用外置的Tomcat来加载项目,这是可选择的一项配置。总之,Spring Boot可省去很多烦琐的配置,而且可以通过主程序类来启动,其他方面则与Spring MVC差不多。

3.Spring Boot项目的特点有哪些

构建一个Spring Boot项目非常简单,建议使用Maven方式,在pom.xml中输入必备的几条语句即可自动构建,如下面的语句:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>springloaded</artifactId>
</dependency>

除此之外,无须使用其他配置,如果要使用其他工具,如MySQL、POI、Swagger UI等,则需要在pom.xml中添加依赖,由程序自动加载依赖JAR包等配置文件。整个Spring Boot项目只有一个配置文件,这个配置文件基本囊括了所有的配置,包括服务器端口号、数据库连接地址、用户名、密码等,Spring Boot把所有的信息都放在一个配置文件里,最大程度简化了配置。可以想象,以前我们在做SSH、SSM项目的时候,动辄需要好几个配置文件,有时候想要更改某个特定的配置,却往往找不到所需的配置文件。

通过这3点,我们已经大致了解了Spring Boot的主要特点,其实它就是一个配置工具、整合工具和辅助工具的集合,核心作用是简化框架,降低使用难度,提高开发效率。那么,既然Spring Boot是一个工具集合,程序运行的核心类来自哪里呢?其实这个问题的答案很简单,那就是Spring家族的各种框架技术,如Spring、Spring MVC、Spring Security、Spring Data等。Spring Boot的最大的作用便是提供一个简单、便捷的环境,让大家能够快速开发项目,而真正运行程序的则是Spring自带的那些核心类,它们已经被极大程度地封装,保存在源码里。

了解了Spring Boot的优势之后,我们来学习一下MVC模式,只有真正理解了MVC模式,在今后的学习当中才不会迷茫。现在基本上所有的浏览器/服务器(Browser/Server,B/S)架构的项目,都是基于MVC模式来开发的。因此在这里需要重点讲解一下MVC的概念。没错,尽管这是一个老生常谈的问题,但必须认真讲解,它就像高楼大厦的地基似的,如果打不好地基,高楼大厦轻则倾斜,重则倒塌。

MVC是一种设计模式。以前的软件开发模式处于探索期,在很长的一段时间里,程序员的开发模式可能没有章法,但仍然潜意识地按照MVC模式去做,只不过没有形成概念。为什么这么说呢?MVC产生于1982年,M代表的是模型(model),V代表的是视图(view),C代表的是控制器(controller)。很明显MVC的意图就是把这三者结合起来,开发程序的时候遵守MVC规则。即便是最早期的Web软件开发,也会按照MVC来做,其中模型就是JavaBean。JavaBean是一个软件组件模型类,也可以称作POJO。这里需要简单说明一下JavaBean和POJO的区别。

POJO是Plain Ordinary Java Object的缩写,意思是简单、普通的 Java对象,它具有以下特征。

(1)拥有一些private修饰的属性。

(2)这些private修饰的属性都提供get方法和set方法。

具有以上两点特征的类称为 POJO类,使用POJO类实例化出来的对象称为 POJO,POJO类就是未经特殊加工的普通的Java类。而JavaBean是可复用的组件,从概念就可以看出来,JavaBean是一种组件,并且需要不断地重复使用。因此,说JavaBean是经过特殊处理过的POJO也是不为过的,它需要符合一些特定的标准。

(1)所有的属性都被private修饰。

(2)该类有一个无参构造器。

(3)所有的属性必须都提供get方法和set方法。

(4)该类是可序列化的,实现Serializable接口。

举一个典型的例子。POJO一般用来做数据库映射,例如,员工表Emp的POJO可以是Emp.java,而JavaBean的官方定义是一种可复用的工具,那么系统分页类便可以作为JavaBean的一种。在某些情况下,普通的POJO类也可以成为JavaBean,例如员工类Emp.java,如果对该类实现了Serializable接口,增加了无参构造器,那它不就成为JavaBean了吗?首先,我们需要明确一点,序列化的作用是将数据分解成字节流,以便存储在文件中或在网络上传输,等传输完毕还要进行反序列化来重构对象,很明显这种功能就是为了使对象成为可复用的组件。因此给员工类Emp.java实现Serializable接口,增加了无参构造器,使其成为可复用的JavaBean组件,是一件正确的事情,所以POJO类可以成为JavaBean这个说法是正确的。接下来,我们通过两个基本的实例代码(如代码清单1-1和代码清单1-2所示)来理解一下POJO与JavaBean的异同。

代码清单1-1 Emp.java

package com.example.pojo;

public class Emp {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

代码解析

这是一个典型的POJO类,拥有private修饰的name属性,并且实现了get方法和set方法。

代码清单1-2 EmpBean.java

package com.example.pojo;

import java.io.Serializable;

public class EmpBean implements Serializable {
    private String name;

    public EmpBean() {}

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

代码解析

这是一个典型的JavaBean类,拥有private修饰的name属性,并且实现了get方法和set方法。除此之外,该类还实现了Serializable接口,增加了一个无参构造器。

搞懂了POJO与JavaBean的区别之后,我们再回到MVC模式上来。如果没有MVC这个经典的设计模式,就好比在开发某一个项目的时候,从头到尾毫无规则地写代码。有些功能实现了,又被改坏了;有些功能明明很简单,却碍于整体架构的紊乱不好去开发,最后拆东墙补西墙,到头来什么都做不好。这就充分体现了一个道理:做什么都需要设计。很幸运,前辈们为我们踏过了荆棘覆盖的丛林,找到了MVC模式,让现在的我们不用走太多弯路。

MVC的具体规则就是,用一种业务逻辑、数据、界面等分离的方法来设计程序框架、组织程序代码。将业务逻辑聚集到一个部件里面,封装成一块,在定制用户界面(User Interface,UI)或者处理用户交互的时候,都不需要重新编写业务逻辑。简而言之,就是分块处理,把庞大的程序代码分成若干部件,虽互相依赖,却不会因为修改某处而造成不好的影响,进而破坏整体结构。在Java Web开发中,一些日常操作,如建立在用户界面上的“输入—处理—输出”这个完整的过程,也可以当作MVC的一种应用。

举个例子,当用户在提交某个表单的时候,控制器接收到了这个事件,会自动调用相应的模型和视图去完成整个需求。控制器本身不会去做具体的处理,而是将这种处理的需求转发给相应的模型和视图去完成。如此看来,它的作用就更加明显,它决定了调用哪些模型和视图的组合去完成任务,具体应该怎样完成任务。按照MVC的规则去开发项目,就算在前期没有把项目做好,但因为整体架构符合MVC模式,在后期也可以利用一些方法对项目进行改版、补救。例如,招聘水平更高的软件工程师。如果项目的前期就没有按照MVC的规则去做,后期也很难通过各种手段来弥补。所以,MVC模式也可以说是一个保障项目扩展性的安全模式。

MVC经过了长期的发展和大量的实践,被证明是可行的,也完全适用于Java Web开发领域。近些年来,MVC的定义被不断地延伸,但一般来说,模型主要指的是业务逻辑(不管该业务逻辑的实际载体是什么,只要明确模型是指业务逻辑);视图主要指的是界面显示,与之相关的技术如HTML、EasyUI、ExtJS、Avalon、Vue这样的前端插件,以及jQuery(虽然它是前端控制语言,但也可以笼统地归纳在这里);控制器主要是指对业务逻辑、前端插件、程序架构、数据库接口等的综合掌控,与之相关的技术如Struts、Spring、Hibernate等框架,注意,不用追求多么细致的划分,它们都可以归纳到控制器当中。说到这里,其实应该给这种情况定义一个更加准确的称呼,那就是MVC框架。

最典型的MVC应用场景是“JSP +Servlet +JavaBean”的模式,也是入门级的。JSP用于界面显示,Servlet承担了控制器的角色,JavaBean 自然就是业务逻辑的组件了。总之,在软件开发过程中,一些经验欠缺的程序员可能不具备大局观,他们的角色往往是某个模块的开发者。如果架构师采用MVC模式来设计项目,就不用担心程序员因为经验不足的问题而导致的一些错误。毕竟在MVC模式下,很多错误都是可以挽救的。

Struts 是一个不错的开源框架,在没有Struts之前,Java Web开发非常依赖于Servlet。在早期的软件项目中,Servlet扮演了重要的角色,但随着Java Web技术的发展,Servlet的缺点也逐渐暴露出来,因为Servlet从配置到处理客户端请求都显得力不从心,尤其是当项目逐渐变大的时候,这种弊端更加严重。举个非常简单的例子,web.xml里应该配置项目最基础的东西,把Servlet的标签放进去,会显得不合时宜。而Servlet在页面处理上面也没有自己的标签,使得程序员在写前端HTML代码的时候比较费劲。使用Servlet最大的好处就是可以轻松地和JSP结合起来,完成对项目的整体控制,但Servlet对项目的控制程度明显不如Struts。

Servlet的生命周期是从客户端请求开始的,当接收到客户端请求时,Servlet首先会调用init()方法进行初始化;接着,Servlet会调用service()方法来获得关于请求的信息,并且触发doGet()或doPost()方法,也可以调用程序员自己写的方法;最后,当这个请求处理完毕之后,Servlet会调用destroy()方法对请求进行销毁。这是一个完整的Servlet生命周期。如果有多个请求的话,Servlet仍然重复以上步骤,但不再调用init()方法。另外,Servlet的线程安全问题也让一些架构师比较担心,每一个Servlet对象在Tomcat服务器中都是单例模式生成的,如果出现高并发的情况,很多请求可能访问同一个Servlet,如访问管理系统的“发货城市统计”功能,因为该功能属于查询模块,即便在非线程安全的情况下也不会出什么问题;但是如果这些并发请求访问的是基础数据的录入模块,如“增加商品”功能,这就有可能产生巨大的隐患,因为它们会同时并发地调用Servlet的service()方法,当然也可以在这些方法里加入线程同步的技术,但这需要增加工作量,相应地人力成本也会上升。

Struts的一个特点就是融合了Servlet和JSP的优点,符合MVC标准。在配置上,Struts将配置内容放在web.xml文件中,涉及程序控制的业务逻辑则统一放在struts.xml文件中,该文件会在项目初始化运行的时候被加载。Struts采用了JSP的Model2。所谓的Model1和Model2,指的是JSP的应用架构:在Model1中,JSP直接处理客户端发送的请求,并且以JavaBean处理若干应用逻辑,JSP就要担任MVC中的视图和控制器的角色,可以勉强处理简单的用户请求;在Model2中,引入了一个控制器的概念,就是把客户端的请求集中发送给Servlet,由它统一管理这些请求,再把处理结果通过ServletResponse对象响应给客户端。

Struts采用了Model2,虽然增加了一些复杂度,却解决了很多棘手的问题。例如,使用struts.xml文件来集中管理请求,并将请求分发给对应的Action,由此做到了“接收请求—转发请求—处理请求”这样有条不紊的逻辑。这样的逻辑,不但方便了开发,也明显降低了维护成本。Struts 2引入了拦截器的机制来处理请求,在程序接口方面,基本上做到了完全脱离Servlet,逐步发展成了成熟的开源框架。在Struts 2的配置文件中,除了一些基本配置,剩下的都是关于Action的配置。举一个典型的例子:

<action name="SendCity" class="SendCityAction">
    <result type="json">
        <param name="root">dataMap</param>
    </result>
</action>

这段代码就是对一个Action的完整配置。在该配置中,Struts 2的拦截器会自动拦截SendCity的请求,并且将控制权交给SendCityAction,而SendCityAction对应的类在Spring的配置文件中,这就是Struts 2与Spring的一次完美结合。结果类型则指的是该Action的数据返回值类型,本例中返回JSON。基本上,Struts 2对应Action的配置都是这样的,对每一个请求配置一个对应的控制类,可以配置具体类路径,也可以交给Spring去管理。Struts 2最主要的特点是:它是线程安全的,因为在Tomcat服务器对请求进行处理的时候,Struts 2会对每一个请求都产生一个新的实例,每个线程分别处理它对应的模块代码,即从Action到持久层的数据通道,这样即便是高并发项目,也不会存在线程安全的问题。

Spring是一个轻量级的开源框架,致力于解决J2EE开发中的复杂问题。其实,如果软件项目应用了Struts,就已经将MVC思想发挥得淋漓尽致了,如果再融合Spring,那就称得上锦上添花了。和Struts一样,Spring相关的配置内容写在web.xml中,而applicationContext.xml文件是Spring的核心文件。在applicationContext.xml文件中,我们可以做很多事情。例如,将项目所使用的连接数据库的配置信息写在该文件中,配置信息包括驱动器、地址、用户名、密码、连接池等,并且使用Spring提供的<bean>元素来完成对组件的注解。如果不使用Spring,在struts.xml中,就需要在<action>元素中写明class所对应的完整路径,如果使用了Spring,就只需要写明applicationContext.xml文件中所对应的<bean>元素。这样的话,Spring就可以当作一个类管理工厂来使用,这是Spring最主要的作用。当然,Spring还有一些其他的作用,如面向切面编程、直接将Struts和Spring的优点结合起来的Spring MVC。

而如果在项目中使用Spring MVC,那就更省事了。在这种框架组合下,我们只需要引入Spring相关的JAR包即可,其他框架一律不要,就能完成对整个项目框架的搭建。这也正是Spring MVC可以取代Struts 2的原因。当然,在持久层上我们可以使用MyBatis,从而构成“Spring MVC+MyBatis”的技术架构,也就是当前常说的SSM架构。需要注意的是,每种技术架构的XML配置文件的内容不尽相同,但发展趋势都是越来越简单。而到了Spring Boot“独领风骚”的时代,我们甚至连这些XML配置文件都不用写了。

在本节中,我们来正式搭建一个Spring开发的基础环境。其实,不论是Java基础开发环境,还是Spring基础开发环境,需要配置的东西本来就不多。可以说相关步骤都是固定的,也是最基础的内容。即便如此,如果不学习它们,后面关于高级内容的学习将无从谈起。只有牢固掌握了基础环境的搭建,再从基础环境出发,在项目里不停地填充内容,并且做各种练习和实验,我们才能逐步地掌握软件开发的技能,所以掌握基础环境的搭建至关重要。

本节主要讲解Java的分类,为广大读者扫除知识障碍。读者的知识背景参差不齐,有些人可能根本分不清Java以及它的衍生概念。举个最典型的例子,不少读者分不清Java和Java EE分别是什么。因此,本节对学习后续章节所必备的知识做系统并且简单扼要的介绍,以方便读者透彻理解它们。想一想,如果我们分不清这些概念,便会有疑问:到底是应该学习Java EE还是学习Java ME?这样就麻烦了!

1.Java发展

Java是一种当前非常热门的编程语言,诞生于20世纪90年代,至今已经有几十年的发展历史了。关于具体的历史,读者可以自行了解,Java的故事读起来也挺有意思的。首先,Java的发展绝对是一波三折的,甚至一度进入了低谷,它的浪潮依靠互联网的发展而来。如果互联网发展滞后,Java不可能变得热门,当然PHP也不可能。试想,在单机时代,我们所接触的单机游戏和.exe可执行程序,大部分都是用C语言或者C++写的,就连Java的核心也是用C语言写的,只不过其自身的工具类是用Java语言写的。但是话说回来,每种语言都有自己的优势,C语言和C++的优势在于能直接和汇编语言、机器语言打交道,这种特性也决定了它们擅长写底层的内核。而Java的优势就在于开发互联网应用,典型的例子就是电商网站、内容管理系统(Content Management System,CMS)网站,电子政务网站、信息平台等。

随着互联网的飞速发展,各种应用“漫天皆是”。网上购物平台、手机App这些软件产品的开发中都可以找到Java的身影,而各行各业信息化的需求愈发增多,可谓“一发不可收拾”!一个典型的例子就是电子政务,以前我们做什么事情都需要“事必躬亲”,而现在只需要在互联网上输入地址,填一些表单就可以完成这些事情,这些软件的更新迭代同样也离不开Java。这就是Java语言备受欢迎,并且长期“称霸”编程语言排行榜的原因。2021年7月的TIOBE编程语言排行榜如图1-2所示。

图1-2 2021年7月的TIOBE编程语言排行榜

2.Java特性

下面,我们来介绍一下Java语言的特性。读者深入理解了这些特性,就能明白这门语言可以做什么,以及学习这门语言的意义。

(1)简单易学。在C++中,我们需要花费大量时间去处理内存指针的问题,而在Java中,指针实际上存在,只是被隐藏起来了,其实指针对应的就是内存中的地址。Java为什么要这样做?就是为了降低开发难度。还有C++里面的多继承概念,Java也去掉了。但在Java中,我们可以通过extends(继承)和implement(实现)关键字来完成类功能的扩展。

(2)面向对象和跨平台。Java是“纯”面向对象的编程语言,意味着在Java开发中,所有的需求开发都需要从现实世界中抽取对象。例如,在常见的信息系统中,我们需要处理“张三”和“李四”这类姓名信息,在Java中便可以把它统一设计成User(用户)类,在整个项目周期中,凡是需要涉及“用户”这个数据模型类(POJO类)的时候,我们都可以使用事先定义好的User类。当然,一个项目所需要的数据模型类是非常多的,例如我们还可以定义Teacher(教师)类,Student(学生)类等,这些POJO类组合起来便可以支撑起若干个复杂的业务。

在Java文件的运行方面,它采用的是“先编译,再解释”的运行方式。也就是说,我们需要把Java语言编写好的类文件编译成.class文件,然后项目在运行到具体节点的时候,再把.class文件的内容解释、运行,因此Java也被称作半编译、半解释的语言。这样说有些笼统,举个简单的例子,我们之前定义了Student类,那么在项目中这个类的体现就是,把Student类的Java文件编译成了.class文件,由Java虚拟机(Java Virtual Machine,JVM)负责加载运行。这样的话,当项目在执行查询学生成绩的操作的时候,这个类便由JVM进行解释并且运行了。.class文件是字节码文件,本身是二进制编码的,但是它不能被机器运行、识别,它需要由JVM进行解释。Java的跨平台性就体现在这里了,不同的平台,如Windows或Linux,只要有了JVM即可以解释、运行Java程序。

(3)安全性强。如果说Java语言的跨平台性是最受欢迎的,那么Java语言的安全性是最让人放心的,这主要得益于Java语言中设计的沙箱安全模型。Java代码的运行全部在类装载器、.class文件检验器、VM内置的安全特性、安全管理器这4个组件的安全策略下完成,极大地保障了程序运行的安全。

(4)跨平台。Java在企业级应用方面的优势则越来越大,以至于出现了“一枝独秀”的局面。如果使用Java语言开发项目,我们所关注的无非是在某个系统环境下完成代码的编写和调试。至于Java程序最终需要用在哪里,没有必要过多地关心,因为无论是在Windows系统还是在Linux系统中,Java程序都可以顺利地部署、流畅地运行。Java跨平台的优点得到了很多公司的青睐,它们纷纷把自己公司的核心技术确定为Java。

另外,Java语言还提供了抽象窗口工具集(Abstract Window Toolkit,AWT)和Swing方面的开发方法,这两者都是基于图形用户界面(Graphical User Interface,GUI)的,也就是我们常说的GUI层面的开发方法。但是,Java语言在GUI领域的优势并不那么明显,更多的开发人员仍然选择了C++,绕过了虚拟机,直接与操作系统交互。

3.Java生态环境

除了这些特性,Java语言“屹立不倒”还有一个很重要的原因:Java语言的“生态环境”。理解生态环境,其实并不难。试想,如果淘宝只做电商,做好订单方面的管理也完全可以维持日常的运转,可它为什么还要在首页融入那么多其他应用(例如聚划算、优酷、饿了么等)呢?答案很简单,淘宝做的就是生态环境。因为这些应用时时刻刻影响着人们的生活,我们离开一两个应用也许可行,但我们无法离开所有的这些应用。因此,“阿里系”的产品便成了“巨无霸”,用户的黏性越来越大,以至于人们的生活很难离开它们,这便是软件生态环境。别的语言咱们暂且不提,就单独来看看Java。它的生态环境不断发展,我们可以举一些例子:

Java EE、Java SE、Java ME自带的生态环境;

Tomcat、Jetty、WebLogic等服务器;

Struts、Spring、Spring Boot、Hibernate、MyBatis等框架;

Activity、Nginx、Redis、Solr、Elasticsearch等与Java关联的第三方生态环境;

互联网上成千上万的Java技术社区。

经过多年的发展,可以说Java生态环境已经形成了很大的规模,在这种形势下,Java语言可能会持续热门下去。因此,学习Java仍然是不错的选择。

4.Java EE

Java EE原来叫J2EE,就是Java为了解决企业级方案的开发、部署、管理等复杂问题而专门定制的一款技术结构。我们学习Java也正是通过企业级项目来入手的。企业级项目的需求太多了,例如,大部分企业都会需要一款人力资源管理系统,这款系统便可以使用Java语言来开发。而且,企业级需求的常规开发操作很多是报表的增、删、改、查等,这类需求开发起来也相对简单。当然,随着互联网技术的发展,企业级项目的涵盖范围越来越广。例如,淘宝、京东等都需要大量的Java程序员来完成它们平台的日常需求的开发,而相比之下,腾讯对Java的需求则不是很多,这个问题也很容易理解,因为腾讯相关的很多业务都是用C++开发的。

总的来说,世界上有那么多企业,它们基本上都有这样的、那样的需求,Java官方正是看到了这些需求,才提出了Java EE这样的针对性的解决方案,以方便我们使用Java语言来满足这类需求。有个不太确定的说法:“凡是带有‘××管理系统’的项目,基本上都属于企业级项目的范畴”,然而这类项目就太多了,简直数不胜数,这是因为信息化的趋势愈发严峻,任何公司都希望精简工作流程、提高办事效率,来节省人力成本。但这并不是说Java只能干这些事情,互联网公司的很多项目都是使用Java语言开发的,只是Java EE为企业级项目提供了一些额外的工具包、功能特性等,方便我们开发和处理不同的场景,这也体现在Eclipse的版本特性上。

5.Java SE

Java SE是Java平台的标准版,主要用于开发和部署桌面、服务器、嵌入式设备、实时环境中的Java应用程序等。其实,Java SE就是Java的基础,包括数据类型、循环、多线程、Socket编程等,还有Java AWT、Java Swing等GUI编程内容。因为GUI编程并不是Java的优势,所以我们不用花费太多时间去学习这部分内容,使用C#、C++、VB可以做得更好。我们学习Java EE时,实际上也要学习很多Java SE的内容,只是需要学习的内容太多,故而做了精简以达到速成的目的。笔者曾经跟一些朋友做过一些简单的统计,那就是Java的知识如果不精简,大概需要一本几千页的图书才能介绍完,相信这样的阅读量会让每个程序员都觉得不可思议,因此对Java知识进行精选是非常重要的一件事情。

6.Java ME

Java ME的主要作用就是开发移动设备,它所提供的工具包和特性也是根据移动设备的特性来定制的。如果想要学习Android开发,就需要从Java ME入手了。学习Java ME可以为日后学习Android打下坚实的基础。Android是一个完整的移动操作系统,而Java EE则是一个使用Java语言编写的移动开发包,目前Java ME的应用率相对较低。

7.JVM

Java的跨平台性就是依靠JVM来完成的,它的作用是解释字节码并执行字节码文件,也就是我们编译后的.class文件。众所周知,在不同平台上运行不同语言的程序是需要重新编译的,而虚拟机作为不同平台上的公共的桥梁,可以理解为“虚拟的计算机”。虚拟机和真实计算机一样,有处理器、堆和栈、寄存器、指令系统等,正因为具备这些特性,Java程序便可以在有虚拟机的环境下直接运行,真正实现了“一次编译,四处运行”。而运行过程是由虚拟机来完成的,运行内容则对程序员隐藏,以方便程序员实现业务逻辑。如果对虚拟机特别精通,则可以完成针对虚拟机的开发,一些大型企业甚至有虚拟机工程师的职位。目前应用最广的JVM是HotSpot VM。

8.JDK和JRE

经常有人搞不清楚JDK和JRE的区别,其实它们的区别并不复杂。JDK是 Java 语言的软件开发工具包(Software Development Kit,SDK),实际上JDK就是我们日常开发的时候,为我们提供工具包的东西。JDK里包含一个JRE,因为我们不但要使用Java编程,还需要运行程序,所以必须有一个JRE来运行程序。Java语言的运行时环境(Java Runtime Environment,JRE)包含JVM标准实现及Java核心类库。也就是说,如果我们想在自己的计算机上运行Java程序,就必须有JRE,但是JRE并不包括开发环境。因此,在学习Java的时候,一般需要在IDE中配置JDK,并且还需要把JDK配置在环境变量里。

其实,本节的内容完全是用来为读者今后的学习扫清障碍的。如果我们只求速成,却连基本概念都一知半解的话,头脑中的疑惑便会随着我们学习的深入变得越来越“不可收拾”,极有可能形成“症结”。因此,在学习写代码之前,我们需要分清楚这些Java中经常混淆的概念,并且保持清醒的头脑,这样才能真正实现我们速成Java EE的目标,再在实现这个目标的基础上,继续深入浅出地学习Spring Boot。等学会了所有的内容,便可以站在Java架构师的巅峰“一览众山小”了。

JDK是Java开发的核心,包含JRE、工具和基础类库。如果没有JDK,Java开发是无法进行的,Java项目也无法运行起来。所以要做任何项目的开发,第一件事情就是安装好JDK,接下来我们才可以做更多的事情。纵观Java的开发工具,只有MyEclipse自带了JDK,如MyEclipse 10.7自带的Sun JDK 1.6.0_13,但是IntelliJ IDEA并没有携带JDK,需要自行配置。在本书中,我们不以MyEclipse作为开发工具,而是使用Eclipse,这样就需要手动配置JDK了。

这里需要注意一点,在笔者的其他著作中,一般都是安装JDK 6的。关于这点,前文中已经有过详细的叙述,JDK 6是第一个里程碑版本,因此,一般情况下我建议大家从JDK 6开始学习。但是JDK 6是不支持Spring Boot的,也就是说,如果项目采用了Spring Boot,很多的程序在JDK 6环境下运行是会出现编译错误的。因此,在本书中我们使用JDK的第二个里程碑版本,也就是JDK 8,再从该版本开始学习,逐步过渡升级。

首先,需要在Oracle官方网站上下载JDK 8。Oracle官方网站经常更新,具体的下载地址会经常改变,因此没有一个确切的下载地址。但是,可以在Oracle官方网站找到“Downloads”菜单,基本上Oracle公司所有的产品都可以通过“Downloads”菜单找到对应的下载界面。另一种方法是可以在其他的网站下载JDK 8,例如国内的一些网站,下载速度也相对比较快。在Oracle官方网站下载JDK的界面如图1-3所示。

图1-3 在Oracle官方网站下载JDK

下载JDK 8之后,最好将它安装在非系统盘里。接着,需要对刚才安装好的JDK进行环境变量的配置,以方便我们在DOS系统下使用JDK命令。例如,最常用的编译命令javac、显示JDK版本的命令java –version。这些命令的使用都依赖于环境变量的配置,如果没有配置,这些命令是不会生效的。

首先,打开Windows的“环境变量”对话框(见图1-4),新建系统变量“JAVA_HOME”和“CLASSPATH”。编辑“JAVA_HOME”变量,在变量值里输入JDK 8的安装地址,如“D:\Program Files\ Java\jdk1.8.0_202”,点击“确定”保存。接着,编辑“CLASSPATH”变量,在变量值里输入“.;%JAVA_ HOME%\lib;%JAVA_HOME%\lib\tools.jar”,点击“确定”保存。最后,选择系统变量名为“Path”的环境变量,在原有变量值的基础上追加“%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin”,点击“确定”保存。

图1-4 Windows的“环境变量”对话框

为了验证Java环境变量是否配置成功,可以运行cmd程序,打开Windows的命令行模式,输入java -version命令,如果环境变量配置成功,会在下面输出当前JDK版本号等信息,如图1-5所示。

图1-5 输出JDK版本号等信息

配置好了环境变量,还需要在Eclipse中配置JDK,使其可以在开发工具中使用。打开Eclipse,在“Preferences”菜单中的“Java”选项下找到“Installed JREs”选项,就可以看到当前工作空间中的JDK配置。点击“Add”按钮,在弹出的“Add JRE”窗口中选择“Standard VM”,点击“Next”按钮进入下一步,在弹出的窗口中点击“Directory”按钮,选择JDK 8的安装目录后,点击“确定”,自动识别出的JDK的相关信息会在“JRE system libraries”列表框中显示出来,如图1-6所示。

点击“Finish”按钮完成配置。这时,Eclipse会自动回到“Installed JREs”对话框中,JDK配置列表中会多出一栏刚刚配置好的JDK选项,勾选对应的复选框,点击“OK”。至此,Eclipse下的JDK配置就成功了,在以后的开发工作中,我们将依赖这个JDK提供的基础JAR包来开发和运行项目。

图1-6 在Eclipse中配置JDK 8

在十多年前,Java软件开发的模式跟现在是有很大的不同的。那个时候,Java生态环境远远没有现在这么繁盛,很多程序和需求完全需要自己去写,没有第三方的参考资料,更不要说直接引用别人已经写好的插件了。而且那时候的网络也没有现在这么发达,网速也不够快。因此,十多年前的Java开发模式一般都是配置好JDK,就开始直接写代码了。如果遇见需要引入的第三方JAR包,就直接将其复制到项目的lib目录下,让其自动生效、完成编译。

而随着时代的发展,这种方式显然不再适用。其一,如果公司或者个人没有积累的话,很多JAR包都需要依赖于网络寻找,很多时候会找不到;其二,随着时间的流逝,一些保存JAR包的服务器地址失效了,以至于一些JAR包根本找不到地方下载。因此,最近几年,Java开发模式有了改变,表现为在搭建项目的时候使用Maven模式,直接从固定的地址来下载JAR包,并且只需要在pom.xml文件中进行简单的配置即可。这样的话,当下载好JAR包之后,它便能直接在项目中生效。举个典型的例子,导出Excel文件这个功能随处可见,但是如果项目中没有在pom.xml文件中配置POI的信息的话,那么运行与之相关的代码便会报错,而如果随后加入了如下POI的信息,保存、编译后,这段报错的代码便会正常运行。

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.9</version>
</dependency>

那么话说回来,Maven要怎么配置呢?要学习使用Maven工具构建项目,首先需要搭建一个Maven环境。打开浏览器,在地址栏输入Maven的官方网站地址,按“Enter”键,进入Maven官网,如图1-7所示。

显而易见,Maven的具体下载菜单是“Download”,点击“Download”,可以看到官方提供的Maven最新的几个版本。在本例中,我们使用之前的3.2.1版本,下载Maven压缩包并将其解压缩后,将Maven复制到E盘根目录下,如E:\apache-maven-3.2.1。Maven的主要作用是从网上“拉取”JAR包,它的各个安装文件版本的功能其实都差不多,并没有什么特别大的区别,总之不要选择太“古老”的版本就行。

接着,配置Maven的环境变量,具体的配置方法跟JDK的类似,主要是配置两个系统变量,它们分别是MAVEN_HOME(E:\apache-maven-3.2.1)和Path(%MAVEN_HOME%\bin),配置好之后,点击“确定”保存。接下来,在Windows的“运行”对话框中输入cmd,进入命令行模式,输入mvn -v,如果屏幕上显示出“Apache Maven 3.2.1”这段文字,便说明Maven安装成功,环境变量也配置成功了。

图1-7 Maven官网

搭建好了开发环境,接着我们通过一个简单的入门项目来快速构建采用Spring Boot框架结构的项目,并且通过一个十分简单的需求,来实际体验一下Spring Boot方便、快捷、高效的特性。平时搭建一个SSM或者SSH框架需要很多步骤,框架搭建完之后还需要做很多配置,大概的过程有:配置web.xml、连接数据库、加载配置文件、开启注解、在XML文件中注入类的依赖关系等。且不论项目的规模大小,这是一个完整的过程,每个环节都需要执行一遍,才能成功构建一个完整的、可运行的项目。

接下来,我们就快速构建一个Spring Boot项目,来体验一下Spring Boot的开发效率。打开Eclipse的“File”菜单,选择“New”菜单下的“Spring Starter Project”,填入项目的“Name”为“demo”,其他的“Group”“Artifact”“Version”“Type”等设置根据需要填入即可。其中,“Group”是组织的意思,一般对应的是公司名;“Artifact”指的是模式,一般对应的是项目名称(可以与Name不一致),“Group”和“Artifact”组合是为了保持项目的唯一性;注意“Type”选择“Maven”。

点击“Next”,会弹出一个新的界面,该界面列出了该项目的各种选项设置,其中包括很多可以继承进来的第三方框架,如NoSQL、Spring Cloud、Web等,这部分暂时不用选择,保持默认即可。在该界面中,可以设置Spring Boot的版本号,如2.4.0等,点击“Next”进入下一个对话框。在Site Info窗口中,可以看到Base Url、Full Url的设置,这两个地址是生成Spring Boot项目的官方地址,保持默认即可,点击“Finish”按钮完成设置。接着,IDE便可以自动构造Spring Boot项目,在IDE界面右下角可以看到进度条,等待编译结束后,便可以看到Spring Boot项目的基本结构,如图1-8所示。

图1-8 Spring Boot项目的基本结构

从图1-8可以看到,Spring Boot项目的结构并不复杂,和其他项目并没有多少差别,但这个结构是自动生成的基本结构。接着便可以使用这个项目来完成复杂的开发任务了。那么Spring Boot的方便、快捷体现在什么地方呢?我们应该如何往里面添加东西呢?实际上要解决这些问题也不难,我们可以继续重复刚才的步骤。

在新建项目的时候,把“Name”设置为“demo-1”,等到选择Spring Boot版本号的时候,就可以看到一个下拉列表,里面列出了Spring Boot支持的所有第三方框架,直接勾选复选框,便可以将相应框架加入当前的项目当中。第三方框架列表如图1-9所示。

图1-9 选择第三方框架

可以随便选择几个看看效果,例如选中“Web”选项下面的“Spring Web”,点击“Finish”。从项目架构上来看,demo与demo-1并没有什么区别,而当我们打开Maven Dependencies文件夹后,就可以发现两个项目的不同之处了。原来,之后新建的项目要比之前的项目多了好几个JAR包,比较典型的就是多了Spring Framework的几个包,即Spring-core、Spring-web、Spring-beans、Spring-aop、Spring-context等,这些包的作用是方便程序使用Spring特性和Spring MVC,而多出来的tomcat-embed-core、tomcat-embed-el、tomcat-embed-websocket包则内嵌了Tomcat服务器。因为我们选择的是Spring Web集成插件包,既然是Spring Web项目,那么Tomcat服务器和Spring相关的技术必然是不可少的,所以IDE帮我们自动集成了这些JAR包。当然,如果需要其他框架,如Spring Cloud框架技术,可以在这里集成进来。

在这里,我们编写一个简单的测试类来运行Spring Boot项目。在demo-1项目下,新建com.example. demo.controller包。注意,这个包必须建立在com.example.demo包之下,才能被内置程序扫描到,否则访问无法成功!接着,新建EmpController.java文件,如代码清单1-3所示。

代码清单1-3 EmpController.java

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EmpController {

    @RequestMapping("/findEmpName")
    public String findEmpName(){
        return "张三";
    }
}

代码解析

这段代码中,@RestController注解的意思是该控制器中运行的方法的返回数据会以JSON类型直接传递给浏览器,这样的话,浏览器接收到“张三”后会将其直接输出。而@RequestMapping注解的意思是拦截请求 ,在这里,拦截了findEmpName请求,如果输入其他非法路径,浏览器会报“There was an unexpected error (type=Not Found, status=404)”错误。

编码完成后,使用新建的Spring Boot项目的启动文件Demo1Application.java,点击鼠标右键,选择“Run As”下的“Java Application”,启动Spring Boot程序。这时,Console栏中会出现一连串启动信息,如果程序没有报错,就代表着项目启动成功了。启动信息中有一条信息请特别注意一下:

Tomcat initialized with port(s): 8080 (http)

这条信息表明了Spring Boot当前内置的服务器为Tomcat,端口号是8080,当然这一切都是可以配置的,具体的内容以后会详细讲解。最后,我们在地址栏输入http://localhost:8080/Controller,按“Enter”键,浏览器的界面中显示了文本“张三”,说明Spring Boot项目的运行是成功的!这里需要注意一点,我们使用IDE自动生成了两个Spring Boot项目,名字分别是demo和demo-1。Spring Boot程序运行结果如图1-10所示。

图1-10 Spring Boot程序运行结果

为什么要使用第二个项目来测试呢?这是因为第一个项目并没有加载Spring Web集成插件,项目里面也自然没有集成Tomcat和Spring相关的JAR包。这样会存在两个问题:第一,使用该项目编写和运行Spring代码会报错;第二,即便没有报错,项目启动后,也是无法正常运行的,因为项目里面没有集成Tomcat服务器。

在Spring框架诞生之前,有很多项目采用企业JavaBean(Enterprise JavaBean,EJB)框架来进行开发,而Spring在诞生之后,没有经过多长时间,便替代了EJB框架。直到现在,仍然有不少人将Spring和EJB框架进行对比。因此,在本节中我们通过一个简单的例子来让读者达到EJB编程快速入门的目的。掌握了EJB编程,便能更好地理解Spring带来的革新,另外,也可以拓宽自己的知识广度。

Spring家族有众多衍生产品,例如Spring Boot、Spring Security、Spring JPA等。但是,它们的很多技术并不是单独运行的,而是互相交叉使用的,典型的例子就是很多产品虽然由Spring MVC技术实现,但在运行的时候,还需要用到Spring框架的控制反转、依赖注入、面向切面编程等编程方法。总之,Spring家族的产品在技术上是互通的。至于后期出现的Spring Boot,它的作用归根到底就是一句话:“最大程度地简化了Java EE的过程,使得程序员可把更多的时间投入业务逻辑的开发。”它的目标就是解决企业级应用开发的复杂问题,例如让程序员不再手动设置XML文件里的Java类的依赖。

稍微回顾一下历史,在1997年初,IBM公司提出了EJB技术概念。因为IBM和Sun公司的极力推崇,所以很多公司都纷纷采用EJB来部署自己的系统,这也是EJB当时火爆的原因,就跟现在的程序员推崇Spring一样。而当大众开始普遍使用EJB技术的时候,又出现了很多问题,归根结底便是EJB的远程调用模式会影响应用的性能,现实是很多中小型应用根本就不需要分布式计算,让它们强行使用EJB模式开发反而会影响效率。具体的弊端如下。

使用EJB开发模式,需要编写大量的接口和配置文件。到了EJB 2.0时代,开发一个EJB还需要配置两个文件,其结果就是配置的工作量比开发的工作量还要大。

EJB需要运行在EJB容器中,而JSP和Servlet需要运行在Web容器中,使用EJB模式开发,就需要Web容器远程调用EJB容器的服务。这样的话,就需要开发两个服务器的内容和很多配置文件,再加上EJB的API开发难度很大,导致程序员开发效率较低。而且,远程调用特别依赖网络,使用远程方法调用(Remote Method Invocation,RMI)会降低性能。

EJB最初设计的应用场景就是分布式系统。说得通俗点,就是客户端在本地运行A接口,而A接口直接去远程服务器调用某些处理代码。接着,远程服务器把处理结果返回给A接口,然后把结果呈现给用户。最初,由于市场上只有EJB这一种开发模式,再加上IBM和Sun公司的极力推崇,大家才开始普遍使用EJB,尽管它的开发过程非常复杂。

而到了2004年,这一切都开始发生变化。这一年由Rod Johnson主导的Spring项目推出了1.0版本,这就意味着Spring正式诞生,这种轻量级的框架是通用的,并非专门面向分布式系统,它极大地满足了市场上的绝大部分技术需求。因此,程序员很快地抛弃了重量级的EJB,纷纷投入了Spring的怀抱,这种感觉就像找到了久违的春天。Sun公司也开始大力推广Spring,再加上诸多技术社区的推动,Spring便迅速地占领了市场,成了行业标准,迎来了属于自己的时代。

EJB一般用来开发分布式应用,而在Web端的分布式应用就是本地程序远程调用EJB服务器。举个形象的例子,我想做超级计算,需要把数据综合起来进行分析才能得出结果。要支撑这样庞大的计算量,靠我本地的计算机配置是难以完成的,因为计算周期太长。为了解决这个问题,我就可以把这个计算过程的业务类抽取出来,部署到远程EJB服务器上,而我在本地只需要通过RMI技术调用远程服务器的接口,便可以在远程服务器完成计算,再把计算结果返回给我的本地计算机,这就是EJB的远程调用和开发模式。

这样一看,EJB确实起到了分布式计算的作用,但由于并非现实生活中所有的业务都需要用分布式模式来完成,如果强行使用分布式模式,反而会使性能降低。这种情况就是典型的“概念看上去很美好、很正确,但实现起来却发现有诸多困难”。别的不说,就说说EJB服务器吧,如果它有不同的网段,这些网段的速度是不一样的,如何来平衡?即便勉强平衡了,那么对于数据库的并发访问问题又该如何解决?如果在EJB中使用分布式事务,又该如何控制?总之,实际操作起来困难很多,如果不能完美解决,反而不如单机结构或集群结构。举个典型的场景吧,如果有一家小型公司,它只需要一个简单的工资绩效管理系统,其需求通过一些简单的增、删、改、查操作就可以满足了,再把系统部署到一台普通的服务器上,就可以正常运行。如果针对这种简单的需求,也强行使用EJB的话,就会得不偿失!

因此,如果某个项目一开始就确定是分布式应用,需要跨平台协作,那它使用EJB是正确的。如果别的项目不需要使用分布式模式,那就不要用EJB这种重量级的框架,老老实实使用Spring这种轻量级的框架就可以满足需求了,这种情况下使用EJB有点画蛇添足。梳理清楚了这些问题,我们来正式开发一个简单的EJB程序,“实地体验”一下这个分布式框架的作用。

开发EJB程序需要一个完整的过程。首先,需要安装JBoss插件,选择Eclipse的“Help”菜单下的“Eclipse Marketplace”,弹出“Eclipse Marketplace”窗口,在“Find”文本框中输入“JBoss Tools”,点击搜索图标,找到JBoss Tools插件,点击“Install”进行安装,如图1-11所示。

当所有设置完毕后,选择“I accept the terms of the license agreements”,即同意开始安装,最后点击“Finish”结束安装,JBoss插件就正式安装好了。安装的时候需要从远程服务器下载插件,可能需要等待一会儿。等安装JBoss之后,便可以正式开始配置这个服务器。

图1-11 Eclipse Marketplace窗口

先新建EJB项目。选择“New”菜单下的“Other”菜单,在弹出框中选择“EJB Project”,接着点击“Next”,在弹出的菜单中,需要设置项目名称(ejbDemo)、工作空间目录(Location)、运行环境(Target Runtime)、运行环境版本(EJB Module Version)等配置信息,保持默认即可。

其他配置信息的设置相对简单,唯独Target runtime比较困难。如果之前配置了JBoss的运行服务器,那么在此处可以直接勾选配置好的服务器,如果没有就需要新建服务器,大体过程跟部署Tomcat(见1.5.3节)一样,但也有一些不同之处需要注意。点击“New Runtime”按钮,在弹出的对话框中选择“JBoss 6.x Runtime”,点击“Next”按钮,在弹出的对话框中,可以设置一些信息:运行时JDK使用“JDK 8”,而“Home Directory”则是服务器目录。如果已经手动下载JBoss并且已经将其安装到该目录的话,则可以直接选择;如果没有,也可以采取线上直接下载的方式来安装,但需要指定安装目录。可以直接点击“Download and install runtime”链接来进行在线安装。在弹出的对话框中选择“JBoss 6.0.0”,点击“Next”,在弹出的界面中,分别设置安装和下载目录,如图1-12所示。

图1-12 在线安装JBoss

然后点击“Finish”按钮,Eclipse自动完成下载和安装。安装完成后,Eclipse自动识别到了JBoss服务器,并且做了默认的配置。接着,新建ejbServer和ejbClient项目来实现EBJ分布式开发。

首先,需要开发EJB项目的服务器端。在工作空间里选择“File”菜单,再选择“New”,选择EJB项目类型,点击“Next”,在弹出的对话框中,找到“Project name”,输入“ejbServer”,点击“Finish”完成建立。这里需要注意一件事情,Target runtime选择JBoss 6.x Runtime即可,跟选择Tomcat6是一个道理,但需要使用JBoss来运行EJB项目。如果“Target runtime”里没有选项,则需要点击“New Runtime”来建立一个服务器。

例如,点击添加JBoss6,在弹出的最新对话框中,有这样几个选项。第一个“Name”可以随便填,而“Home Directory”则是JBoss服务器目录。如果手动安装好了JBoss服务器就可以选择安装目录,如“E:\JBoss6\jboss-6.0.0.Final”;如果没有则可以使用“Download and install runtime”在线下载JBoss服务器,具体过程刚才已经讲解过了。

在这里使用在线下载模式,选择“JBoss 6.0.0”,点击“Next”按钮,点击“Finish”完成安装。这样ejbServer项目便可以作为服务器端来运行了,它可以接受普通Java项目的远程调用。在ejbServer项目中新建目录ejbModule,在目录下新建com.ejb.server程序包,再在其下分别新建两个文件,分别表示EJB的接口和数据模型Bean。新建ModelEjb.java文件,如代码清单1-4所示。

代码清单1-4 ModelEjb.java

package com.ejb.server;

import javax.ejb.Remote;

@Remote
public interface ModelEjb {
    public String sayHello(String name);
}

代码解析

这里我们建立一个server服务器端,并且在该interface接口中定义一个名为ModelEjb的接口,再为该接口新建一个sayHello()方法。这个接口在EJB之中起到了远程服务的作用,跟接下来要讲述的WebService技术的作用是差不多的。

新建ModelEjbBean.java文件,如代码清单1-5所示。

代码清单1-5 ModelEjbBean.java

package com.ejb.server;

import javax.ejb.Remote;
import javax.ejb.Stateless;

@Stateless
@Remote
public class ModelEjbBean implements ModelEjb {

    @Override
    public String sayHello(String name) {
        return name + "你好!这是第一个EJB项目";
    }

}

代码解析

ModelEjbBean实现了ModelEjb接口,并且为sayHello()方法返回了姓名(name)和一句话。注意:我们需要拓展一下思路,那就是可以把这个接口当作一个通用的计算接口。例如,这里有一个典型的场景,客户端是一台功能简单的计算机,它的配置可能是只有2GB内存的赛扬CPU。如果我们在这台计算机上进行大量的数据计算,则速度会特别慢。那么,我们为什么不使用EJB,把数据交互这类重点计算放在一台性能强大(高配置)的服务器上进行呢?假如ModelEjb接口正好在这台高配置服务器上,那么便可以在接口中写入一个复杂运算的程序模块,对客户端传来的数据进行计算,而不是单纯地输出一句话。

还需要注意的是,EJB编程对于JavaBean的管理与Spring编程有一点区别。例如,该项目中ModelEjb接口就可以当作一个Bean,而ModelEjbBean类则实现了这个接口,这种思想的意思是把业务抽象出来,当作可复用的组件部署在服务器上,然后等待客户端去访问它们。而在传统的非EJB编程中,JavaBean有可能是一张用户表,也有可能是分页组件。

写完了服务器端的代码之后,接着新建一个ejbClient项目来作为客户端。注意:在阐述EJB的概念的时候我们已经讲得很清楚了,EJB是服务器端中部署EJB以提供服务的接口,也就是EJB项目。而客户端则是普通的Java项目,直接完成远程调用。本节的ejbClient便是一个简单的Java项目。

点击“File”,在“New”菜单中选择“Java Project”类型后点击“ok”,在“Project name”文本框中输入“ejbClient”作为项目名称,点击“Finish”完成该项目的建立。在src目录下新建com.ejb.client包,在该包下新建EJBTest.java文件,如代码清单1-6所示。

代码清单1-6 EJBTest.java

package com.ejb.client;

import java.io.IOException;
import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.ejb.server.ModelEjb;

public class EJBTest {

    public static void main(String[] args) throws NamingException, IOException {
        Properties props = new Properties();
        props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream
        ("jndi.properties"));
        InitialContext context = new InitialContext(props);
        ModelEjb modelEjb = (ModelEjb) context.lookup("ModelEjbBean/remote");
        String sb = modelEjb.sayHello("程序员");
        System.out.println(sb);
    }
}

代码解析

EJBTest是客户端的测试类,我们在本地运行main()方法,读取jndi.properties配置文件,该配置文件中的内容是EJB目标程序的信息,例如java.naming.provider.url就用于配置目标URL,可以设置为localhost,用来访问本地的EJB程序,如果服务器在其他机器上,填写目标IP地址即可,例如192.168.0.88这个目标机器。

其他设置基本上都是读取EJB项目的配置信息,而ModelEjb的sayHello()方法的作用是直接读取服务器的sayHello()方法,并且为它传入“程序员”这个字符串参数。在Eclipse的“Servers”工具栏下找到之前配置好的JBoss AS 6.x服务器,点击鼠标右键,选择“Start”命令,启动该服务器。服务器启动成功后,在EJBTest.java文件中,点击鼠标右键,选择“Run As”下的“Java Application”命令,就可以看到本地远程调用EJB项目的接口成功,“Console”中输出了“程序员你好!这是第一个EJB项目”。

在学习了EJB项目的相关技术之后,我们已经明白了EJB的核心用法,那就是通过在本地配置Java命名与目录接口(Java Naming and Directory Interface,JNDI)文件,直接远程访问服务器端的接口,让该接口计算并返回计算值给客户端,这点与WebService技术是一样的,但从整个开发流程上来看,它们的难度似乎都不大。下面,我们来学习如何使用最传统的方法,搭建一个Spring项目,为日后的学习打下基础。

搭建Spring项目的传统方法是使用Spring Framework。要使用Spring Framework,需要下载spring-framework包,如spring-framework-5.1.4.RELEASE-dist文件和commons-logging-1.1.jar。而从spring-framework包中,只需要引入4个核心JAR包,分别是spring-beans、spring-context、spring-core和spring-expression。

Spring Framework有许多版本,可以在官方网站下载。如果需要选择某个确定的版本,可以在其官方网站上检索。Spring不同版本之间的差异并不是特别大,可以查看官方API文档和特性介绍。下载完JAR包之后,把Spring Framework的压缩文件解压,打开libs文件夹,在里面找到4个JAR包,再加上 common-logging-1.1.jar包,把这5个JAR包复制到某个单独的文件夹里。

打开Eclipse的“File”菜单,选择“Java Project”,命名为“helloSpring”,然后新建一个“lib”文件夹,将这5个整理好的JAR包直接复制粘贴到“lib”文件夹中,如图1-13所示。

图1-13 Spring需要的JAR包

可以选定这5个JAR包,点击鼠标右键,选择“Build Path”菜单下的“Add to Build Path”,把这些JAR包添加到“Referenced Libraries”目录下即可。此时,Spring Framework的配置就完成了。是不是非常简单?接下来,我们需要在该项目下编写一些Java类文件,完成对Spring项目功能的简单使用,初步学习一下该框架的精髓。

打开helloSpring项目中的“src”目录,新建com.spring.beans包,众所周知,Spring的主要作用就是管理JavaBean,那么使用这样的一个包名是非常正确的。接着,在该包下新建一个HelloSpring.java学生类文件,作用是初始化实体Bean。接着再新建一个HelloSpringMain.java文件,作用是通过主程序入口对JavaBean进行实例化,并且对其常用属性进行赋值,HelloSpringMain.java如代码清单1-7所示。

代码清单1-7 HelloSpringMain.java

package com.spring.beans;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloSpringMain {

    public static void main(String[] args) {
        // 创建HelloWorld的一个对象
        HelloSpring helloSpring = new HelloSpring();
        helloSpring.setName("test");
        // 1. 创建Spring的IoC容器对象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 2. 从IoC容器中获取Bean实例HelloSpring
        HelloSpring helloSpring2 = (HelloSpring) ctx.getBean("helloSpring");
        // 3. 调用sayHello()方法
        helloSpring2.sayHello();
    }
}

代码解析

以上代码使用了Spring提供的一些经典用法。例如,使用new关键字创建HelloWorld的实例化对象,再为它的name属性赋值。接下来的几段代码的具体含义,在代码之中已经有了详细的注释,阅读即可明白。这些代码没有什么特别需要注意的地方,且使用的都是Java的固定语法。其中,ClassPathXmlApplicationContext的作用是读取src目录下的配置文件applicationContext.xml,这个配置文件可以说是Spring使用方法的核心,Spring本身就是依赖各种配置,把各类的关系根据自上而下,甚至从左往右的规律匹配起来的。

一般情况下,对applicationContext.xml配置文件的加载是写在web.xml里的,此处出于演示的目的,进行了显式调用。加载配置文件后,如果想使用HelloSpring类的sayHello()方法,就需要使用getBean()方法来获取配置文件里的实体Bean,在这里是通过ID来查找匹配的。最后,我们通过getBean()获取的HelloSpring实例helloSpring2来调用sayHello()方法,并且输出结果。

写完了主函数的程序运行代码还不够,接着还需要配置applicationContext.xml文件,对JavaBean进行可视化的配置,这段配置代码便真正意义上实现了Spring框架的控制反转和依赖注入的思想。applicationContext.xml如代码清单1-8所示。

代码清单1-8 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.
         springframework.org/schema/beans/spring-beans.xsd">

    <!-- 配置Bean -->
    <bean id="helloSpring" class="com.spring.beans.HelloSpring">
        <property name="name" value="张三"></property>
    </bean>
</beans>

代码解析

这段配置信息可以忽略头文件,头文件信息都是自动生成的。重点来看实体Bean的配置信息。首先,需要知道这段配置信息不论是使用代码来调用,还是使用其他的任何方式加载,它所依赖的类就是一个JavaBean,是com.spring.beans.HelloSpring这个类。而<property>元素则通过配置文件设置了name属性的值是“张三”。这样,当我们在使用该JavaBean的时候,它的name属性就会有一个初始值——“张三”。

这就是Spring在项目中最大的作用之一:管理项目中的组件模型(数据模型)类JavaBean。我们知道,Java是一门面向对象的编程语言,在Java的编程世界里,所有的事物都可以抽象为类。那么,成千上万的类该怎么高效管理呢?如果每次使用该类的时候都使用new关键字,就太麻烦了,也增加了很多无谓的代码量,使得程序的可读性大幅度下降。

因此,可以使用applicationContext.xml文件来管理一个项目中所有组件模型类JavaBean。在这个小项目中,我们只使用了HelloSpring这个类,但在实际的项目开发当中却不是如此,可能要在applicationContext.xml文件中增加成百上千的JavaBean配置信息,并且通过各种各样的元素来最大程度上扩展它的功能,具体的内容将在以后的章节中详细讲解。

组件模型类JavaBean的代码如代码清单1-9所示。

代码清单1-9 HelloSpring.java

package com.spring.beans;

public class HelloSpring {

    private String name;
    private int studentId;

    public void setName(String name){
        System.out.println("setName:"+name);
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void sayHello(){
        System.out.println("hello:"+name);
    }
    public HelloSpring(){
        System.out.println("HelloSpring你好春天!");
    }
}

代码解析

这个类是一个典型的组件模型类JavaBean,它设置了两个属性,一个是name,另一个是studentId,并且为name属性生成了set方法。该类如果要更规范,应该叫作Student类,但这是一个入门级Demo,所以就叫作HelloSpring类,当然这并不是什么硬性规定。

编码结束后,打开HelloSpringMain.java文件,点击鼠标右键,选择“Run As”下的“Java Application”,可以看到如下输出结果:

HelloSpring你好春天!
setName:test
HelloSpring你好春天!
setName:张三
hello:张三

阅读输出结果,可以明白通过手动引入JAR包的Spring项目正常运行了,并没有发生什么异常。接下来,我们用Maven方式来引入Spring,看看这两种方式孰优孰劣。

新建一个Maven项目,并且选择“Maven Project”,勾选“Create a simple project(skip archetype selection)”,跳过选择模板的界面,将“Group Id”设置为“com.spring”,将“Artifact Id”设置为“helloSpring2”,其他保持不变,点击“Finish”完成设置。接下来的工作非常简单,把helloSpring项目的Java代码完全复制到helloSpring2,看看能否识别。项目运行时报错,说明第二个项目根本找不到Spring的JAR包,那么接下来,我们要做的就是使用项目对象模型(Project Object Model,POM)方式引入Spring的JAR包,并且使项目正常运行。

打开helloSpring2项目的pom.xml文件,修改为新的内容,如代码清单1-10所示。

代码清单1-10 pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.
            org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.spring</groupId>
    <artifactId>helloSpring2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.1.7.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!-- 添加Spring支持 -->
        <!-- 核心包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Spring控制反转的实现 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</project>

保存后,Eclipse会出现“User Operation is Waiting”对话框,提示IDE正在下载JAR包。等JAR包下载结束后,可以运行程序,看看两个项目的输出结果是否一致。如果一致,就说明两种Spring框架的搭建方式都是正确的。打开HelloSpringMain.java文件,点击鼠标右键,选择“Run As”下的“Java Application”,可以看到如下输出结果:

HelloSpring你好春天!
setName:test
HelloSpring你好春天!
setName:张三
hello:张三

前面几节对Java的知识点进行了全面的梳理,配置了基础开发环境,还快速开发了EJB和Spring的入门级项目。通过对这些内容的学习,可以说读者已经完全入门了,为以后的Spring Boot框架学习打下了坚实的基础。可是,即便Spring Boot并不需要配置服务器,我们仍然需要学习Tomcat服务器的部署和常用设置。

在学习前,我来介绍一下软件公司对开发工具的选择。开发工具又称作IDE,IntelliJ IDEA、Eclipse、EditPlus、UltraEdit等都是IDE,都是用来写程序代码的,“牛人”甚至可以使用记事本来写程序。当然,好的IDE自身集成了很多实用的功能。举个典型的例子,MyEclipse就是Eclipse的定制版,专门为Java EE增加了不少内容,例如它可以直接使用菜单方式为项目集成Spring、Struts 2等框架。因此,选择合适的IDE可以提高开发效率。本书选择Eclipse Neon作为开发工具,在必要的时候也会选择其他工具来演示。

至于开发环境,既然选择了Eclipse Neon作为开发工具,就要为之匹配一套合适的开发环境,如搭配JDK 1.8、Tomcat 8等。另外,软件公司把项目部署到服务器上,还会有开发环境和测试环境之分,开发环境是指开发人员使用的环境,测试环境是指测试人员使用的环境。

孔子曰:“工欲善其事,必先利其器。”这是流传千古的哲理——工匠要想做好他的工作,一定要先让工具“锋利”,这样才能发挥出最大的效率。这个哲理告诉我们,不管做什么事情,都要选择合适的工具。在软件开发的道路上,选择一个合适的开发工具也是极其重要的事情。Java的开发工具有多少种,这里不赘述,我们只需要对比它们的特点,即可从中选择一款最适合自己的开发工具。Java中常用的开发工具有NetBeans、JBuilder、Eclipse、MyEclipse、IntelliJ IDEA等。至于如何选择,其实很简单,一般情况下,Eclipse和IntelliJ IDEA都是可以的,并没有好坏之分,只取决于个人的操作习惯。而其他选择因素就是开发工具集成的插件数量,例如Eclipse和MyEclipse的区别,就是MyEclipse定制了很多Java EE的插件,可以方便日常开发,提高效率。

其中一些常用的开发工具的稳定版本有MyEclipse 10.7、Eclipse Neon、IntelliJ IDEA 2016等。SVN和GIT的不同版本的差别并不大,所以不对它们的版本做具体的规定,只要不使用特别古老的版本就能满足日常的开发需要了。

MyEclipse 10.7的界面如图1-14所示。

图1-14 MyEclipse 10.7的界面

Eclipse Neon的界面如图1-15所示。

图1-15 Eclipse Neon的界面

IntelliJ IDEA 2016的界面如图1-16所示。

图1-16 IntelliJ IDEA 2016的界面

另外,如果你经常开发Spring项目的话,也可以下载Spring Tool Suite这个集成平台开发工具,它就是在Eclipse Neon平台上的工具,使用它可以省去很多Spring相关的配置,具体的下载方法很简单,网上有很多教程,这里不赘述。本书后面的工程基本上都采用Spring Tool Suite来开发,该工具最大的特点便是帮助开发人员做了很多Spring相关的配置,也可以轻易地生成Spring项目,并且生成项目里的配置文件。

安装好了JDK,我们就可以在Eclipse中进行一系列代码编写工作了。例如,可以在开发工具中练习写一些类。对于包含main()函数的Java类,我们可以通过“Run As”菜单下的“Java Application”命令来运行,输出程序结果。例如,我在工作空间下新建一个Java Web项目“practise”,具体的过程如下:选择“File”菜单下的“New”选项,在右侧弹出的菜单中选择“Java Project”,在对话框的“Project name”文本框中输入“practise”,其他保持不变,把“JDK”选择为“8”即可,点击“Finish”,practise项目就建立好了。

选中practise项目的“src”目录,点击鼠标右键,选择新建“Package”,在对话框的“Name”文本框中输入“com.manage.practise”,点击“Finish”,就可以给这个项目建立一个空包。接下来,就可以在这个空包里新建类。选中Java包,点击鼠标右键,选择“New”下的“Class”,在弹出的对话框中的“Name”处输入类名“Test”,并且勾选“public static void main(String[] args)”,点击“Finish”。这样,在practise包下的第一个Test类就建立成功了。

打开Test类,在main()函数中输入第一行Java语句System.out.println("Hello World"),使用“Java Application”来运行。此时,Console中输出Hello World。理论上来说,我们的第一个Java程序就这样诞生了,尽管这个程序非常简单!

如果只在Eclipse下安装了JDK,这款开发工具能做的事情无非是编写类,利用“Java Application”来运行,并且进行程序的测试。在这种情况下,我们的代码中所设定的数值均是由自己输入的参数,然后根据程序中的处理逻辑,做一些简单的运算,最后输出正确的结果。可是,程序开发远远不是这么简单的事情,我们需要做的是开发一个具有交互能力的项目,而不仅仅是写一个简单的程序。要达成这个目标,就必须在Eclipse中安装Web服务器来运行项目。在这里,我们选择使用Tomcat服务器,这是因为Tomcat服务器具有简单、易用的优点。

首先,打开Apache的官方网站,在下载Tomcat 8的界面找到对应的软件,在“Core”列表中选择“64-bit Windows zip”的版本,将Tomcat 8压缩文件保存到本地,并且解压到本地的非系统盘(如E盘)的根目录。

打开Eclipse的“Preferences”对话框,在Eclipse的列表中选择“Servers”,再选择“Runtime Environment”功能,点击右侧的“Add”按钮。这时,会出现一个列表,列出了Eclipse支持的服务器,选择“Tomcat”,再选择“Tomcat 8”,点击“Next”。这时窗口中会列出几个功能项,我们点击“Browse”,选择“E:\apache-tomcat-8.0.43”目录,再把JRE选择为刚才安装好的JDK 8,点击“Finish”结束安装。

接着点击“Servers”,这里还没有配置Tomcat,点击提示文字,在弹出的窗口中选择之前配置好的Tomcat 8,点击“Finish”。这时,在Eclipse的“Package Explorer”栏目中会出现“Servers”项目,实际上就是配置好的服务器,这里列出了Tomcat 8的配置文件,其中web.xml用于进行服务器的全局配置,如配置欢迎界面;server.xml用于修改服务器环境,如修改端口号等内容。

我们要如何把项目发布到服务器中来实际观测一下呢?在“Servers”下的服务器的名称上点击鼠标右键,选择“Add and Remove”,系统会提示“There are no resources that can be added or removed from the server.”这是因为,刚才新建的practise项目本身没有服务器运行的环境,所以无法发布!

若要发布项目,就会涉及开发工具版本不同而使操作方法不同的问题。例如,如果Eclipse Neon需要新建服务器程序的话,就需要使用“Dynamic Web Project”来增加把项目发布到Web服务器的支持环境;MyEclipse 10.7使用“New Web Project”来新建Java EE项目,新建后将项目发布到Tomcat服务器中,便可以直接访问(开发环境的配置与Eclipse差不多)。

本节详细讲述了如何使用Eclipse、MyEclipse搭建开发环境,以及选择开发工具的一些常见准则。其实,在实际工作中,如果项目组的成员都做同一个项目,那么最好用统一的开发工具,包括版本控制工具。这样的话,即便是出现了某些环境问题,也可以统一处理。随着项目版本的迭代,项目中加入的程序代码越多,Eclipse、MyEclipse、IntelliJ IDEA所呈现的项目目录结构的差异就会越来越明显,即便这些开发工具所构建的项目可以互相转换,在这种情况下也很容易出现由开发环境不一致导致的问题。

我们通过工具栏运行Tomcat 8,运行成功后,点击工具栏的“Open MyEclipse Web Browser”图标,在地址栏中输入“http://localhost:8080/”,按“Enter”键,就可以看到Tomcat 8运行成功的画面,如图1-17所示。接下来,就可以在Tomcat服务器里部署Web项目,进行正式的编码工作了。

图1-17 Tomcat 8运行成功

前文对Java IDE的选择以及开发环境的搭建进行了系统介绍,相信读者在阅读了以上内容之后,一定迫不及待地想要投入项目的开发中。但是,凡事都要讲究循序渐进,Java EE项目的开发本身并不难,困难之处在于我们需要用架构师的思维来看待整个项目。

开发Java EE项目,说得形象一点就是一个搭积木的过程,我们需要把各种开源框架及代码都融入软件项目之中。因此,在学习方面通常要从零开始,也就是从细小的组成元素开始学起,最终实现整个项目的融合。下面,我们来学习使用Eclipse开发Hello World程序,并把它部署到Tomcat服务器中,然后讲解项目的初始结构的组成部分,只有明白了初始结构,才能有条不紊地推进学习的过程。其实,很多编程语言的学习都是从最基础的内容入手的,如果连最基础的内容都无法掌握,自己可能会失去学习的兴趣。

打开Eclipse的工作空间e:\workspace,在前文中我们新建的practise项目是一个纯粹的Java项目,它只支持使用“Run As”下的“Java Application”命令来输出结果。可以将这类项目简单理解为代码计算型的项目,只要我们写了相应的代码逻辑,就能输出结果。

而在Eclipse中新建带有服务器属性的Java EE项目(可发布到服务器)需要这样来做:选择“File”菜单下的“New”,再选择“Dynamic Web Project”;在弹出的界面中,输入项目名“chapter4”,在“Target runtime”中选择“Apache Tomcat 8”,表示我们的运行环境是该服务器,其他选项保持不变,点击“Next”;这时,在新的界面中,我们可以看到“Source folders on build path”(它的意思是项目的编译目录)的默认值是“src”,这个值保持默认即可;下面的选项是“Default output folder”,默认值是“build\classes”,也保持不变。

以上的设置是什么意思呢?大家都知道Java这门语言是需要把.java文件编译成.class二进制字节码文件来运行的。src目录就是指.java文件的位置,当我们把项目发布到Tomcat中之后,服务器只要一运行,就会把.java文件编译成.class文件,而服务器在整个运行周期中会一边加载这些类,一边解释执行它们,build\classes目录就是指.class文件的输出目录。理解了这些内容后,我们保持默认值不变,点击“Next”进入下一个设置环节。

接下来设置“Web Module”,“Context root”是上下文环境的根目录,保持默认即可,而“Content directory”指该Java EE项目的JSP文件的保存位置,默认值是“WebContent”,最后是“Generate web.xml deployment descriptor”这个选项,表示是否需要web.xml文件,勾选它,点击“Finish”按钮。此时,这个Java EE项目已经建立好了,它的结构如图1-18所示。

图1-18 Java EE项目结构

让我们来分析一下这个Java EE项目的主要组成部分。

(1)chapter4是项目名称。

(2)Deployment Descriptor是指该项目的web.xml文件的快捷建立方法。

(3)JAX-WS Web Services是指WebService方面的内容,本小节暂时不涉及。

(4)build就是刚才设置的输出.class文件的目录。

(5)WebContent就是前端文件所在的目录。其中,MANIFEST.MF文件用于记录一些项目扩展方面的内容,一般是自动生成的;web.xml包含整个项目在运行周期内全局的、服务器级别的配置,如Servlet、欢迎文件、错误跳转文件、过滤器、监听器、拦截器等的配置。

经过上述分析,我们应该大概明白了Java EE项目的初始化结构的意思,其实不论是Eclipse、MyEclipse,还是IDEA,它们的项目结构都是不完全相同的,但表述的意思是一致的,因此只要搞懂了这些基本配置的意思,就不用担心开发工具不同的问题了。选中“WebContent”,点击鼠标右键,选择“New”,再选择“JSP File”,在该前端文件目录下新建一个JSP文件。接着打开NewFile.jsp,做几处简单的修改,方便我们查看代码的运行效果。

修改第一行的编码方式,以支持中文,记住将编码方式修改为UTF-8即可:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

修改< body >元素为:

<body>
    笨鸟先飞!
</body>

这样,第一个简单的界面就做好了!接着,我们把这个项目发布到Tomcat 8里面,来看一下运行效果。

在“Servers”中,选中Tomcat 8服务器,点击鼠标右键,选择“Add and Remove”,这时,IDE自动识别到了工作空间中的Java EE项目chapter4,把它选中,点击“Add”,保存到“Configured”栏,勾选“If server is started,publish changes immediately”(它的意思是如果服务器启动,那么立即发布最新的改动,也就是热部署的意思!),点击“Finish”完成设置。这时,我们可以看到chapter4项目已经发布到了服务器下,如图1-19所示。

图1-19 项目发布

接着,我们选中服务器,点击快捷工具栏中的“Start the server”按钮。在“Console”中查看服务器启动日志,如果没有报错,那就说明一切顺利,它的最后一行日志信息类似“Server startup in 1287 ms”。打开浏览器,在地址栏中输入“http://localhost:8080/chapter4/ NewFile.jsp”,按“Enter”键,即可查看该项目的运行界面,如图1-20所示。

图1-20 项目运行

此时,我们在JSP中的修改都会及时反馈到浏览器中,只要刷新页面即可看到。虽然该项目很简单,但仍然是一个动态交互的网站,因为它使用了服务器技术。如果想要让这个项目丰富起来,就可以在原有项目的结构里,不断地增加符合需求的内容,直到这个项目的功能强大起来!这就是一个完整的项目开发过程,一切跟着需求走,如果需求就是使用一个JSP显示“笨鸟先飞”这4个字,那么我这个项目做到这里就可以顺利交付了。但是,实际项目中的需求肯定不会这么简单。

web.xml包含整个项目在运行周期内全局的、服务器级别的配置,如Servlet、欢迎文件、错误跳转文件、过滤器、监听器、拦截器等的配置。之前讲过这个概念,也许读者虽然理解了,但还是无法深入领悟“什么是服务器全局配置”,下面我们通过实例来讲解它。

之前我们通过http://localhost:8080/chapter4/NewFile.jsp这个地址来访问页面是可以的,我们直接访问http://localhost:8080/chapter4/却是不行的。大家都知道,Java EE项目的根目录节点一般都是域名加上项目名称,用于访问默认的首页,而通过这种方式访问,浏览器会报404错误,这是为什么呢?此时我们就需要有架构师的思想,因为项目中的任何节点都需要配置,如果没有配置,是访问不到的!接下来,就为该项目配置首页,也就是欢迎界面,看看能否达到我们需要的效果。

打开web.xml,可以看到<welcome-file-list>元素中已经默认生成了欢迎界面,分别对应index.html、index.htm、index.jsp等,那么我们在WebContent下新建welcome.jsp,看服务器是否能加载它。把index.jsp复制一份,改名为welcome.jsp,修改<body>元素内容为“欢迎界面!”,<title>元素内容为“全局配置”。最后,在web.xml文件中,把index.jsp修改成welcome.jsp。

接着访问http://localhost:8080/chapter4/,可以看到浏览器已经加载这个JSP文件了,如图1-21所示。

图1-21 欢迎界面

这时,大家可以再次发散思维,既然有了欢迎界面,是否还会需要一个错误界面呢?因为刚才只配置了根目录节点,没有设置错误界面。这时,如果在地址栏输入http://localhost:8080/chapter4/test.jsp,按“Enter”键,浏览器仍然会报404错误。

打开web.xml,在<web-app></web-app>之间输入以下代码,并且新建一个JSP文件,把名称修改为404.jsp。

<error-page>
  <error-code>404</error-code>
  <location>/404.jsp</location>
</error-page>

接着重启Tomcat,如果新配置了全局元素,就需要重启Tomcat,如果元素已经存在,就不需要重启了。输入“http://localhost:8080/chapter4/test.jsp”,发现浏览器已经不再报404错误,而是跳转到了错误界面,如图1-22所示。

图1-22 错误界面

至此,简单的web.xml配置就完成了,至于其他元素的修改,其实网上有很多资料,读者多试试,就可以很轻易地加强项目的完整性了。

在开发项目的过程中,往往需要同时启动多个Tomcat,在部署项目的时候,有时也需要同时部署多个服务器。鉴于这种场景,我们很有必要学习多个Tomcat的部署方法。

之前我们已经安装了Tomcat 8,为了模拟这种场景,可以把E:\apache-tomcat-8.5(01服务器)再复制、粘贴一份,重命名为E:\apache-tomcat-8.5-02(02服务器)。接着,按照之前学习的方法,在工作空间的Servers下再部署一个Tomcat,值得注意的是,选择Tomcat目录的时候必须选择02服务器,否则肯定是不对的!这时,启动两个Tomcat会报端口号已经占用的错误。这时,需要修改02服务器的端口号,否则它们无法同时启动。

打开02服务器的server.xml,找到端口8080,修改为8081;找到端口8005,修改为8006;找到端口8009,修改为8010。这样一来,两个服务器的端口号就不一致了。如果有03服务器,也要分配其他端口号给它。这时,再同时启动原来的01服务器和02服务器就没有任何问题了。

那么这样做的意义在哪里呢?不论是开发还是部署,在实际工作中,经常会有这样的情况存在:一种情况是,你的代码有两个不同的版本,你需要把分支代码的某个功能迁移到主版本上,最好的办法就是同时启动两个Tomcat,然后对比页面来迁移代码;另一种情况是,我们通过Redis保证Session一致性的时候,也需要同时部署两台服务器来验证。例如,我们在A服务器上登录了用户,这时访问B服务器,就不应该进入登录界面,而应该直接访问登录后的欢迎界面,因为A服务器和B服务器的Session需要共享。当然,要实现这个功能比较麻烦,需要在后面逐步学习。

本章全面阐述了Spring家族的产品和功能,详细介绍了Spring Boot与Spring MVC的功能和特点,还对两者的区别进行了阐述。为什么要这样做呢?这是因为很多人在学习和工作的时候,往往搞不清楚Spring Boot与Spring MVC究竟有什么关系。清除了这个知识盲点后,我们通过最基础的入门例子学习了Spring的核心作用和基本用法。在学习Spring 的时候,我们会遇见一个司空见惯的问题:Spring与EJB的关系究竟是什么样的?不论是网上的资料还是各种技术图书,大多都会把Spring当作EJB的替代品或者升级品,这种说法过于武断,也没有详细的论证,尽管EJB如今已经很少有人用了,但这种说法会让很多读者陷入一种“奇怪的迷茫”之中。

明明知道应该使用Spring替代EJB,却说不出具体原因,这会让人很“抓狂”。因此,本章使用两个经典的例子,分别是Hello EJB和helloSpring来开发对应的项目,呈现出它们的用法和区别。结果令人大吃一惊,原来EJB是做分布式调用的,类似WebService,而Spring是用来管理数据模型类JavaBean的。

而EJB之所以那么流行,一方面是因为大公司的极力推崇;另一方面是因为当时并没有其他解决方案,广大程序员不得不一边使用EJB,一边抱怨它的晦涩难懂。之后,Spring和Hibernate横空出世,以简单、便捷的特性“闻名于世”,并且它们不是针对分布式而开发出来的框架,具有通用性。这样,大家便抱着尝试的态度开始使用Spring,后来发现这个尝试是无比正确的,这也造就了如今Spring无法替代的地位。在使用EJB技术开发很多非分布式项目的时候,会出现框架技术不匹配的问题(所谓“驴唇不对马嘴”)。当年Spring横空出世,大家纷纷抛弃EJB而使用Spring,才有了“Spring是EJB的替代品”的这种说法。实际上,更加严谨的说法应该是:大家纷纷使用Struts、Spring、Spring MVC等框架来代替EJB。


相关图书

Effective Java中文版(原书第3版)
Effective Java中文版(原书第3版)
Java核心技术速学版(第3版)
Java核心技术速学版(第3版)
Java编程动手学
Java编程动手学
Java研发自测入门与进阶
Java研发自测入门与进阶
Java开发坑点解析:从根因分析到最佳实践
Java开发坑点解析:从根因分析到最佳实践
Java EE企业级应用开发实战(Spring Boot+Vue+Element)
Java EE企业级应用开发实战(Spring Boot+Vue+Element)

相关文章

相关课程