Spring Boot实践

978-7-115-63421-4
作者: [印]索姆纳特·穆西布(Somnath Musib)
译者: 陈德伟
编辑: 郭泳泽
分类: Spring

图书目录:

详情

本书是一本实战导向的Spring Boot开发教程。全书以现实问题为导向,从基本功能到技巧,全面地介绍Spring Boot开发技术,包括引导应用程序、数据库通信、微服务等内容,以及Spring Boot与RESTful API、WebSocket、RSocket、Kubernetes、Kotlin、GraalVM配合使用的方法。本书凝结了作者多年的Spring Boot开发经验,可以在Spring数据、Spring安全性,以及其他有关Spring的核心技术与技巧方面为读者提供指导。

图书摘要

版权信息

书名:Spring Boot实践

ISBN:978-7-115-63421-4

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

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

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

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


版  权

著    [印] 索姆纳特·穆西布(Somnath Musib)

译    陈德伟

责任编辑 郭泳泽

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

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

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

读者服务热线:(010)81055410

反盗版热线:(010)81055315

版权声明

© 2026 Posts & Telecom Press. Authorized translation of the English edition © 2022 Manning Publications. This translation is published and sold by permission of Manning Publications, the owner of all rights to publish and sell the same.

本书中文简体字版由Manning Publications授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式复制本书内容。

版权所有,侵权必究。

内 容 提 要

本书是一本实战导向的Spring Boot开发教程。全书以现实问题为导向,从基本功能到技巧,全面地介绍Spring Boot开发技术,包括引导应用程序、数据库通信、微服务等内容,以及Spring Boot与RESTful API、WebSocket、RSocket、Kubernetes、Kotlin、GraalVM配合使用的方法。本书凝结了作者多年的Spring Boot开发经验,可以在Spring数据、Spring安全性,以及其他有关Spring的核心技术与技巧方面为读者提供指导。

本书适合具备一定Spring基础的Java开发者和软件工程师阅读。


献给我的父母——他们费尽心血养育了我 致我的儿子 

Abhirup——他给我的生活增添了新的意义和目标

推 荐 序

我们选择了正确的路

2015年,James Watters、Andrew Clay Shafer和我一起坐在美国加利福尼亚州圣莫尼卡的一家咖啡馆里。他们两个都是我的同事,也是云计算领域的专家。当时我们正处于事业的十字路口。Spring团队于2013年推出了Spring Boot,并在2014年正式发布。而到了2015年,Spring Boot就已经受到大量关注。我们知道人们对Spring Boot带来的可能性感到兴奋,也知道人们在热烈拥抱Spring Boot。Spring Boot涵盖的内容太多了,我们不知道什么时候能做到最好,也不知道在哪个领域能做到最好。写这篇文章的时候已经是2022年年初了,这个项目每天都在增长,而我仍然不知道我们是否做到了最好。

“我们选择了正确的路。”我们同意道。的确是这样的。

我知道,要做到这一点,就需要人们达成共识并熟悉整个体系。如果没有选对方向,就无法找到出路。本书给了我希望。关于服务器端应用程序和服务开发的很多讲解,都会给读者带来如同攀岩般的眩晕,而本书提供了翔实、可靠的帮助来避免这一点。

本书几乎开篇就直接进入应用程序构建主题。先快速讲解了一遍基础知识,然后“砰”的一下,就开始构建一些东西!我认为这是最好的方法。Spring Boot涵盖的内容太多了,我们能做的就是开始探索。无论怎样详细讲解,甚至画各种图表,都无关紧要,它们都不如动手实践的效果好。你需要自己来体验和探索!

入门之后,我们就可以沿着概念的阶梯持续前进了。先从构建基于Spring Boot的应用程序要用到的基础内容开始。随后,我们学习数据访问,了解基于Spring Boot执行器的应用程序的可观察性,使用Spring Security保护应用程序,使用Spring MVC和Spring WebFlux构建HTTP服务。到了这一步,我们并没有精通Spring Boot的所有内容,但已经能够知道去哪里学了。我们学会了如何掌握自己的学习方向。

对于下一步要学什么,每个人都有自己的看法,作者Somnath Musib在本书中做得就很好。在广阔而美妙的Spring世界中,他选择介绍一些新兴的技术,包括Kotlin、Spring GraphQL和GraalVM。Kotlin是一种不断变化且充满活力的语言,可以和Spring生态系统很好地结合在一起。Spring GraphQL是一个全新的项目,它将GraphQL Java项目带给了Spring开发人员。Spring Native可以将Spring Boot 2.x和Spring Framework 5.x的代码转换为GraalVM原生镜像。Spring GraphQL和Spring Native都是相对较新的项目,所以我很高兴在本书中看到它们,这是一本十分可靠的Spring指南。

在引导人们学习Spring Boot的路上,Somnath Musib做得非常出色,他的专业指导使我们更容易专注于重要的事情:完善你的应用程序,一直到生产就绪状态。当你在生产环境中成功发布应用程序时,以及当你做到最好时,我希望你也能看着你的朋友和同事,微笑着说:“我们选择了正确的路。”

Josh Long

Spring开发倡导者,就职于VMWare Tanzu

撰写本书时,Spring Boot仍然是最流行的Java框架,它的使用率和接受程度远远领先于竞争对手,如Dropwizard、Quarkus和Micronaut。随着全行业都开始采用微服务架构,Spring Boot的受欢迎程度直线上升,已成为开发人员最想学的Java框架。

Spring Boot很受欢迎,而新手遇到的最大挑战是不知道从哪里开始学。Spring和Spring Boot的参考文档都很庞大,对初学者并不友好。Spring Boot提供了一些指南,来演示如何使用Spring Boot执行某些操作。这些指南有助于初学者快速入门,但没有提供实际的示例,并不能让他们全面理解Spring Boot的功能。互联网上有许多教程、文章和博文,但都是分散的、不完整的,并且远不能描绘Spring Boot的完整图景。

本书试图解决其中的许多问题。当开始编写本书时,我有两个主要目标。第一个是让读者清楚地了解Spring Boot及其内部的许多概念,例如自动配置、执行器和安全性。第二个是用Spring Boot的实际例子来丰富读者的学习之旅,而不是使用传统教科书式的、理论导向的例子。本书一直专注于这两个目标,对此我非常有信心。

本书涵盖了Spring Boot的各种材料,主要面向初级和中级开发人员,旨在带领读者踏上Spring Boot的学习旅程,从基本概念开始,介绍如何有效地使用Spring Boot的各种功能,并通过大量现实世界的例子引出更高级的主题。虽然本书主要关注初级和中级开发人员,但也为经验丰富的开发人员提供了不少材料。诸如在Spring Boot中使用Kotlin、基于GraalVM的Spring Native Image、在Spring Boot中使用GraphQL、HashiCorp Vault和多因素身份验证(MFA)等,对高级开发人员来说都十分有用。

我衷心希望读者能够欣赏本书的内容,并认可本书对自己的 Spring Boot应用开发有所助益。对任何改进本书内容的评论或建议,我都非常欢迎,并热切期待。你可以在LinkedIn上联系我。

致  谢

虽然封面上只标明了我是作者,但这本书的出版得到了很多人的帮助,我要感谢这些人,他们让这本书成为优秀的Spring Boot指南。

首先,我要对我的妻子Jhinuk表示衷心的感谢。感谢你的耐心等待,让我花大量时间写这本书。感谢你在此过程中给予我的支持和鼓励。我爱你。

接下来,我要感谢我刚出生的孩子 Abhirup,是他给了我人生新的意义和目标。我还要感谢我的父母、我的兄弟 Sumanta 和姐姐 Supriya,他们一直相信我,并激励我在人生中达到新的高度。

我要感谢我的导师、同事和朋友,他们的教导让我在职业生涯中收获了许多宝贵的经验。这个名单很长,我必须提及的是以下人员:Amit Chitnis、Ashwani Singh、Midhuna Babu、Kiran N.S.、Sandeep Salian、Priya Ponnekanti、Minal Barve、Shravan Kumar Singh、Suhasini C.H.、Ramya S.和Parijat Pathak。

我要感谢Manning出版社的技术编辑Jennifer Stout,她与我一起工作,让我相信自己可以写这本书,并让本书的创作过程变得更轻松。我还要感谢本书的组稿编辑Mike Stephens、评审Mihaela Batinić、生产负责人Andy Marinkovich、文字编辑Christian Berk和校对Jason Everett。谢谢你们给我机会为Manning出版社写这本书。还有Manning出版社的其他人员,他们和我一起制作并推广本书。这确实是团队协作的成果。

在本书出版过程中的各个阶段,有很多审稿人花时间阅读稿件并提出了宝贵的反馈意见,在此表示感谢。感谢Ajit Malleri、Al Pezewski、Alain Lompo、Alex Saez、Amrah Umudlu、Andres Sacco、Anindya Bandopadhyay、Ashley Eatly、Asif Iqbal、Becky Huett、Chad Johnston、Fernando Bernardino、Gabriele Bassi、Giampiero Granatella、Harinath Kuntamukkala、Ilya Sakayev、Javid Asgarov、Jean-François Morin、João Miguel Pires Dias、John Guthrie、Kent R. Spillner、Krzysztof Kamyczek、Lachman Dhalliwal、Maqbool Patel、Mladen Knežić、Mohamed Sanaulla、Najeeb Arif、Neil Croll、Rafał Gorzkowski、Raffaella Ventaglio、Raghunath Nedumpurath、Raymond Cheung、Richard Meinsen、Ruslan Vidzert、Sambaran Hazra、Satej Sahu、Sergio Britos Arevalo、Søren Dines Jensen、Tan Wee、Tiziano Bezzi和William Fly,你们的帮助使这本书变得更好。

特别感谢本书的技术审校Ubaldo Pescatore,感谢你的审阅和反馈。非常感谢技术校对Giampiero Granatella,在本书出版前,他仔细审查了所有的代码。

最后,我还要感谢Spring和Spring Boot团队。感谢你们创造出了一个如此有用的框架,让世界各地开发人员的工作变得更轻松。

前  言

本书是为想要学习Spring Boot并在应用程序开发中使用它的Java开发人员编写的。本书隶属Manning出版社的“In Practice”系列,侧重于Spring Boot的实际应用,并附有大量的真实示例。本书按照“问题—解决方案—讨论”的模式编写,首先介绍一个问题,然后为它提供解决方案,最后在“讨论”部分对每个功能进行深入探究。

谁应该读这本书

本书是为初级和中级应用程序开发人员编写的,书中提供了大量使用Spring Boot的真实示例。本书着重介绍了Spring Boot内部概念以及新出现的功能,例如使用GraalVM Native Image、GraphQL和响应式应用开发的Spring Boot。因此,高级Spring Boot应用程序开发人员也能通过本书学到足够的内容。任何希望学习Spring Boot或复习Spring Boot知识的人都会发现这本书很有用。

本书的组织方式:路线图

本书分成5部分,共10章,还包含2个附录。

第1部分介绍了Spring Boot及其各种功能。

第1章从整体上介绍了Spring Boot、它的特性以及它提供的各种功能。

第2部分涵盖了开发Spring Boot应用程序时用到的概念和技术。

第2章讨论了如何使用Spring Boot来执行常见的应用程序任务。其中包括使用不同方式来管理配置、操作日志、验证数据等。

第3章介绍了Spring Boot应用程序访问数据库的技术。

第4章深入讨论了Spring Boot自动配置和执行器。在本章中,我们讨论了自动配置是如何设计的,它的内部结构是什么样的。我们还深入介绍了Spring Boot执行器、自定义端点的创建和Prometheus监控。

第5章介绍了Spring Security和保护Spring Boot应用程序的技术,包括Spring Security的工作原理、各种重要的过滤器,以及如何在Spring Boot应用程序中自定义各种安全参数。

第6章介绍了如何在Spring Boot应用程序中实现多个生产级别的安全特性,这些高级特性将第5章介绍的概念提升到了一个新的水平。

第7章介绍了如何使用Spring Boot开发RESTful API,讨论了RESTful API开发中的异常处理、文档API、版本API,最后还介绍了如何保护RESTful API。

第3部分讨论了如何使用Spring Boot来开发响应式应用程序。

第8章介绍了如何使用Spring Boot来开发响应式应用程序,还介绍了如何在Spring Boot中使用WebSocket和RSocket。

第4部分重点介绍了将Spring Boot应用程序部署到各个平台的技术。

第9章讨论了如何在各个平台上部署Spring Boot应用程序,从Spring Boot应用程序最基本的JAR和WAR部署开始,随后讨论了如何在Cloud Foundry和Heroku中部署Spring Boot应用程序,最后演示了如何将Spring Boot应用程序作为容器运行并部署在Kubernetes集群和Red Hat OpenShift中。

第5部分介绍了在Spring Boot项目中使用Kotlin、GraalVM和GraphQL的方法和技巧。

第10章讨论了如何使用Kotlin来开发Spring Boot应用程序,还讨论了如何使用buildpacks生成Spring Boot应用程序的原生镜像,最后介绍了如何在Spring Boot项目中使用GraphQL。

关于代码

本书包含许多源代码示例,有的出现在代码清单中。有时代码会用粗体来突出,以显示与前面步骤不同的代码,例如当添加新功能到现有代码行时。

原始代码在许多情况下会被重新格式化,添加换行符并重新设计缩进以适应书中可用的页面空间。在极少数情况下,即使做了这些也不够,代码清单中还包含行继续标记符()。此外,很多代码清单中都有注释,用来突出重要的概念,在文本中描述代码时,通常会移除里面的注释。

本书示例的完整代码可从Manning网站和GitHub存储库中下载。

关 于 作 者

 索姆纳特·穆西布(Somnath Musib)是一位拥有十多年开发经验的多语言开发人员。他从2015年开始使用Spring Boot,并积极参与Spring Boot应用程序的开发。Somnath热爱教学,喜欢以通俗易懂的方式向人们解释复杂的话题。在业余时间,他喜欢在Medium博客上撰写一些关于技术的文章。

关于封面插图

本书封面人物是“Femme de Navarre”,即来自纳瓦拉的女人,取自Jacques Grasset de Saint- Sauveur于1797年出版的作品集。此作品集中的每幅画作均由手工精心绘制和着色。

那个年代很容易就能通过着装来识别人们住在哪里,以及他们的职业或生活地位。此作品集中所展示的许多画作都还原了几个世纪前地区文化的丰富多样性。Manning出版社使用这幅画作作为图书封面插图,以此来赞扬计算机行业的创造性和主动性。

资源与支持

资源获取

本书提供如下资源:

配套代码文件;

本书思维导图;

异步社区7天VIP会员。

要获得以上资源,您可以扫描下方二维码,根据指引领取。

提交勘误信息

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

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

与我们联系

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

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

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们。

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

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

关于异步社区和异步图书

“异步社区”是由人民邮电出版社创办的IT专业图书社区,于2015年8月上线运营,致力于优质内容的出版和分享,为读者提供高品质的学习内容,为作译者提供专业的出版服务,实现作者与读者在线交流互动,以及传统出版与数字出版的融合发展。

“异步图书”是异步社区策划出版的精品IT图书的品牌,依托于人民邮电出版社在计算机图书领域30余年的发展与积淀。异步图书面向IT行业以及各行业使用IT的用户。

第1部分

本 书的第1部分只包含第1章,介绍了Spring Boot和它的一些重要特性。第1章对Spring Boot进行了概述,介绍了它的各个组件和一些重要功能,比如Spring Boot启动器、自动配置、执行器和故障分析器。我们还探讨了Spring Boot应用程序的项目结构和组成元素。第1章还讨论了如何在Spring Boot应用程序中创建可执行的JAR文件,并探索了JAR文件的组成部分。

第1章 启动Spring Boot

本章内容:

介绍Spring Boot;

项目结构和生成项目的各种元素;

创建可执行的JAR文件以及JAR文件的结构;

Spring Boot启动器、自动配置、故障分析器和执行器概述;

介绍Spring Boot开发人员工具,提高开发人员生产力。

欢迎使用Spring Boot——流行的Java框架!它彻底改变了Spring应用程序(或者更具体地说是Java应用程序)的开发方式。Spring Boot是Spring框架的开源扩展,旨在简化Spring应用程序的开发。Spring Boot的流行主要归功于它能够立即创建独立的、生产就绪的、基于Spring的应用程序,我们可以直接运行这些应用程序而不必担心配置问题。

本章对Spring Boot进行了概述,讨论了Spring Boot是什么、它的用途、项目结构,以及一些关键的Spring Boot特性。准备好了吗?现在就开启我们的旅程吧!

1.1 Spring Boot介绍

在本节中,我们会介绍Spring Boot框架,并简要回答一些有关Spring Boot的常见问题。我们将讨论为什么选择Spring Boot框架,也将解释该框架是什么、它提供的各种功能以及该框架的各种组件。

1.1.1 为什么选择Spring Boot

当我们踏上学习Spring Boot的美好旅程时,脑海中浮现的第一个问题是:为什么要学习它?为了找到这个问题的答案,我们需要了解一下Spring Boot承诺解决的问题。

Spring框架从一开始就致力于简化Java企业级应用程序的开发,它秉承这个理念,帮开发人员处理繁重的任务,这让Spring框架变得非常流行。而随着Spring框架越来越流行,开发人员又希望进一步简化Spring应用程序的开发过程。

尽管Spring框架为开发人员提供了大量支持,让他们专注于解决自己的业务问题,但在Spring Boot出现之前,开发人员仍然需要完成大量工作才能进入正式业务开发流程。例如,如果想要开发基于Spring的Web应用程序,会面临下面这些问题。

需要理解Servlet以及与之相关的部署描述文件web.xml中的一些概念。

需要熟悉WAR和EAR文件的目录结构,它们用于打包应用程序组件。

在部署应用程序时,需要了解与应用服务器相关的一些概念,例如域、端口、线程和数据源。

需要处理复杂的类加载策略、监控应用程序、熟悉应用管理相关的概念以及使用日志记录工具。

这里涉及很多术语。与之相对的是,只为应用程序编写业务逻辑,生成一个可执行文件,然后在命令行中运行它。如果我们无须定义复杂的XML配置,也不用在应用服务器上进行部署,或者做任何炫技杂耍,只需将这些问题留给一位经验丰富的魔法师解决,那该有多好啊,对吧?你很快就会发现,Spring Boot就是这样一位魔法师。

Spring Boot是作为Spring框架下的子项目引入的,旨在为开发人员提供快速启动体验,并消除大多数的配置问题。当继续Spring Boot的学习旅程时,我们会了解到Spring Boot是如何完美地解决这些配置和集成问题的。例如,在Spring Boot项目中,我们不需要定义部署描述文件web.xml。如果我们不打算在应用服务器上运行Spring Boot应用程序,则不会强制使用应用服务器运行应用程序。大多数时候,Spring Boot的默认配置就可以轻松满足我们的需求。

1.1.2 什么是Spring Boot

Spring Boot于2014年4月发布,旨在减轻Java Web应用程序开发的负担。它允许开发人员更多地关注业务逻辑,而不是样板代码和相关配置。Spring Boot能够帮助开发人员创建基于Spring的、生产就绪的、独立的应用程序,几乎不需要修改配置信息。它对Spring框架采用了约定的处理方式,因此应用程序开发人员可以快速使用他们需要的东西。Spring Boot在Spring框架之上提供了一个附加层,供用户来简化配置信息。

图1.1显示了Spring Boot如何将自己夹在应用程序开发人员和Spring框架之间。作为中间层,Spring Boot替我们管理着许多配置,如果开发人员直接与Spring框架交互,就需要自己进行配置。

图1.1 Spring Boot的开发人员视图。它将自己夹在开发人员和Spring框架之间。Spring Boot会检测开发人员使用的Spring组件并进行自动配置

1.1.3 Spring Boot的核心特性

Spring Boot具有5个显著的特性,这使它在众多框架中脱颖而出。

快速启动——Spring Boot的主要目标之一是在Spring应用开发中提供快速启动体验。假设我们想用传统方法来构建基于Spring的Web应用程序,一般需要遵循以下步骤。

(1)配置带Spring MVC依赖的Maven或Gradle项目。

(2)配置带Spring MVC的DispatcherServlet。

(3)将应用程序组件打包成WAR文件。

(4)将WAR文件部署到servlet容器(例如Apache Tomcat)中。

使用Spring Boot,你可以在应用程序中指定所需的依赖项,然后直接创建应用程序,其余的工作由Spring Boot处理。

自动配置——Spring Boot会自动为我们配置Spring应用程序所需的最少组件。它基于类路径中存在的JAR文件或各种属性文件中配置的属性来执行此操作。例如,如果Spring Boot检测到类路径中存在数据库驱动程序文件(比如内存数据库H2的JAR文件),它会自动配置相应的数据源来连接数据库。

约定——Spring Boot是基于约定的。它会自动配置相关组件来启动Spring应用程序。Spring Boot通过启动器依赖项(starter dependency)来实现这一点。每个启动器依赖项对应应用程序开发的一个特定领域,提供相关的依赖项处理。例如,需要开发Web应用时,可以配置spring-boot-starter-web依赖项,它能保证所有和Web应用开发相关的依赖项都在这个应用程序的类路径中,包括spring-web、spring-webmvc等。

独立——Spring Boot应用程序内嵌了一个Web服务器,因此它们可以独立运行,而不需要外部的Web服务器或应用服务器。这使得Spring Boot应用程序可以打包为可执行的JAR文件,然后使用java -jar命令运行。这也使得Spring Boot应用程序可以轻松容器化,从而很方便地用于云原生应用程序的开发。

生产就绪——Spring Boot提供了一些开箱即用且很有价值的生产就绪特性,在应用程序投入生产后,可用于对其进行监控和管理,例如健康检查、线程转储(thread dump)以及其他一些有用的指标。

1.1.4 Spring Boot组件

Spring Boot由多个组件组成,每个组件都专注于应用程序开发的某个特定领域。其中一些是核心组件,对于每个Spring Boot项目都不可或缺。例如,spring-boot组件是每个Spring Boot项目都会使用的主要组件。图1.2展示了相关的Spring Boot组件,下面我们进行简要介绍。

spring-boot——这是主要的Spring Boot组件,能为其他组件提供支持。它包含SpringApplication类,可以使用该类提供的静态方法来创建独立的Spring Boot应用程序。这个组件还提供了对嵌入式Web服务器(例如,Tomcat)的支持,并支持外化应用配置(例如,应用的数据库详细信息)等。

spring-boot-autoconfigure——该组件为Spring Boot应用程序的自动配置提供了必要的支持。Spring Boot自动配置会根据类路径中存在的依赖项和配置的属性来猜测并配置spring bean。但是,如果检测到用户配置了自定义的bean,则不再使用默认的配置。

spring-boot-starters——启动器描述了一组预先打包好的依赖项,能为开发人员提供方便。Spring Boot启动器旨在帮助开发人员使用Spring以及与之相关的技术,如果没有启动器,开发人员就需要自行处理这些工作。

spring-boot-CLI——该组件是一个对开发人员友好的命令行实用工具,可以编译并运行Groovy代码。它还可以监控文件的更改,这样就不需要在文件修改后重新启动应用程序。这个CLI工具免除了我们对Maven或Gradle等依赖项管理工具的需要。此外,它还能让我们快速构建Spring应用程序原型,而不必担心依赖项管理和其他与构建相关的问题。请参阅附录A了解如何使用Spring Boot CLI。

spring-boot-actuator——该组件提供了执行器端点来和Spring Boot应用程序进行交互,还能监控并审计Spring Boot应用程序。Spring Boot中的执行器可以通过JMX或HTTP端点进行管理。Spring Boot提供了一个预定义的执行器端点列表,涵盖了应用程序的各个方面。如果还不能满足需求,我们也可以针对自己的应用程序来自定义执行器端点。Spring Boot执行器还能让我们配置要启用哪些执行器端点,并提供多种方法来保护这些端点免受未经授权的访问。

spring-boot-actuator-autoconfigure——该组件支持基于类路径来自动配置执行器端点。例如,如果类路径中存在Micrometer依赖项,那么Spring Boot会自动配置MetricsEndpoint。

spring-boot-test——这个组件包含了一些注解和方法,可以用来为Spring Boot应用程序编写测试用例。

spring-boot-test-autoconfigure——该组件支持应用程序测试用例的自动配置。

spring-boot-loader——该组件允许将Spring Boot应用程序打包为单个JAR文件,这个JAR文件中包含所有依赖项以及可以独立运行的嵌入式Web服务器。我们并不独立使用这个组件;相反,它与Maven或Gradle插件一起使用。

spring-boot-devtools——该组件包含一个额外的开发人员工具包,用于提升Spring Boot应用程序的开发体验。该工具包提供了多个功能,可以自动检测应用程序代码的变更,并且内嵌了LiveReload服务器来让浏览器自动刷新更改后的HTML页面。这个开发人员工具包旨在提高开发人员的工作效率。

图1.2 Spring Boot组件

1.2 代码示例

本节讨论代码示例以及开发这些示例时用到的相关技术。这包括书中用到的构建系统、编程语言和数据库。我们还会介绍Lombok,它可以通过简单的注解来简化POJO类的定义。

1.2.1 Maven与Gradle

我们可以使用Apache Maven或Gradle等构建工具来创建Spring Boot项目。在Spring Initializr工具上,可以选择想要使用的构建系统来生成项目。在本书中,我们将使用Apache Maven作为首选的构建系统,因为大多数读者比较熟悉Apache Maven。但是,对于Gradle用户来说,将代码示例无缝移植到Gradle上也非常容易。

1.2.2 Java与Kotlin

在Spring Boot项目中可以同时使用Java和Kotlin编程语言。Spring Framework 5.0已经加入了对Kotlin的支持,从那时起,Spring框架一直努力为Kotlin提供更好的支持。例如,在Spring Security 5.3中,Spring Security支持的领域特定语言(DSL)就包含了Kotlin版本。可以在本书配套的GitHub wiki页面上获得有关Spring框架对Kotlin支持的更多信息。

在本书中,大多数代码示例优先使用了Java。在第10章中,我们将通过Spring Boot来介绍Spring框架中的主要Kotlin特性。

1.2.3 数据库支持

本书中的一些代码示例需要访问数据库来演示相关概念。Spring Boot支持多个SQL和NoSQL数据库。为了便于运行示例,我们将在几乎所有代码示例中使用H2内存SQL数据库(有一些例外)。

1.2.4 Lombok

Lombok是一个Java库,它可以根据普通Java对象类(POJO类)中的注解来自动生成构造器、getter、setter、toString和其他一些方法。我们需要做的就是在POJO类中使用适当的注解。例如,要为POJO类中的所有成员变量生成getter方法,可以在类中指定@Getter注解。我们在本书代码示例中使用了Lombok。

如果你对使用Lombok不感兴趣,可以通过代码来直接提供相应的getter、setter和构造器。代码示例应该也能按预期运行。

Record

Java 14引入了Record的概念。Record是不可变的数据类,只需要指定字段的类型和名称即可。Java编译器会帮我们生成equals、hashCode和toString方法。另外,还会生成私有的final字段、getter方法和公共构造器。如果不想使用Lombok之类的第三方库,可以考虑使用Record。

Record定义如下:

Public record Course(int id, String name, String description, int rating) {}

编译器会生成一个含有所有定义字段的公共构造器,并提供与字段名称相同的 getter 方法(例如 id()、name()等)、equals方法和hashCode方法。可以在本书配套的GitHub wiki页面上找到有关Record的更多信息。

1.3 Spring Boot入门

现在我们已经对Spring Boot有了一个大概的了解,也知道了它的用途。在本节中,我们将学习如何生成Spring Boot项目,并讲解Spring Boot项目的结构。

1.3.1 第一个Spring Boot项目

Spring Boot提供了一个名为Spring Initializr的工具,可以用来生成Spring Boot项目骨架。此外,Spring Boot还提供了API供主流IDE供应商集成Spring Initializr,这样就可以将该功能内置到IDE中来生成Spring Boot项目。如果对Spring Initializr不熟悉,请参阅附录A了解创建Spring Boot项目的各种方法。我们已经在本书的配套GitHub库中生成了一个Spring Boot项目供参考。

1.3.2 Spring Boot项目的结构

生成的Spring Boot项目结构相对简单,仅包含Spring Boot应用程序开发所需的基本组件。

pom.xml文件:里面包含项目生成期间选择的依赖项。

Maven包装器(wrapper)文件:让我们无须在本地机器上安装Maven即可构建项目。[1]

[1] wrapper只是帮我们封装了Maven的安装脚本,避免了自己选择版本和下载的麻烦,但执行wrapper时Maven还是会安装到本机的。详情参见官方文档中的说明。——译者注

Java文件的包结构:分为源码包(source package)和测试包。源码包内有一个带有main方法的Java类,而测试包内有一个空的测试类。

资源文件夹:含有一个空的application.properties文件,以及一些提供额外配置的内容。

下面详细讨论这个项目的关键组件。

Maven pom.xml文件

Spring Boot项目的pom.xml文件如代码清单1.1所示。

代码清单1.1 Spring Boot项目的pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<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
 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>                                                       ❶
        <groupId>org.springframework.boot</groupId>                ❶
        <artifactId>spring-boot-starter-parent</artifactId>        ❶
        <version>2.6.3</version>                                   ❶
        <relativePath/> <!-- lookup parent from repository -->     ❶
    </parent>                                                      ❶
    <groupId>com.manning.sbip.ch01</groupId>                       ❷
    <artifactId>spring-boot-app-demo</artifactId>                  ❷
    <version>1.0.0</version>                                       ❷
    <name>spring-boot-app-demo</name>
    <description>Spring Boot Demo Application</description>
    <properties>
        <java.version>17</java.version>
    </properties>
 
    <dependencies>                                                 ❸
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>                                              ❹
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>                                               ❺
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

❶ 当前项目将Spring Boot starter parent声明为父项目,以表明该项目是Spring Boot子项目。这样应用程序的插件和依赖项管理等功能就可以自动由Spring Boot提供。

❷ 当前项目的工件(artifact)信息。

❸ 声明的Maven依赖项列表:Spring Boot starter web和Spring Boot starter test。

❹ Spring Boot starter test提供了流行的测试库(例如JUnit、Hamcrest和Mockito)依赖项,可以用来测试Spring Boot应用程序。依赖项里不包括junit-vintage-engine,这样就可以通过junit-jupiter-engine来使用JUnit 5的功能。

❺ Spring Boot Maven插件通过目标(goal)来执行应用程序的管理活动。这些目标很好用,例如,我们可以使用这个插件执行mvn spring-boot:run命令来快速启动Spring Boot应用程序。

pom.xml文件的内容可分为3部分:

(1)parent标签;

(2)dependencies标签块;

(3)Spring Boot Maven插件。

spring-boot-starter-parent是所有Spring Boot启动器依赖项的父依赖项。它还表明当前项目是一个Spring Boot子项目,只是对父项目做了一些扩展。

spring-boot-starter-parent也是一个特殊类型的启动器依赖项,它提供了几个默认配置,比如Java版本,以及项目中的一些Maven插件配置。maven-war-plugin和maven-surefire-plugin会自动包含在这个启动器依赖项中。

此外,spring-boot-starter-parent还有助于依赖项管理。注意,代码清单1.1没有为任何依赖项指定版本号。这些依赖项的版本号是在spring-boot-starter-parent中指定的。

你的项目是否已经有了父pom

你可能已经有一个使用父pom设置的Maven项目,并且正在将这个项目升级到Spring Boot。在这种情况下,这个Spring Boot子项目已经自定义了自己的父pom,那么它如何扩展并利用Spring Boot的父pom呢?

可以通过添加以下依赖项来获得Spring Boot的父pom所提供的依赖项管理等功能。在pom.xml文件的dependencyManagement部分指定spring-boot-dependencies:

<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-dependencies</artifactId>
         <version>2.6.3</version>
         <type>pom</type>
         <scope>import</scope>
      </dependency>
   </dependencies>
</dependencyManagement>

pom.xml 文件的剩余部分声明了Spring Boot启动器依赖项。Spring Boot启动器依赖项是Spring Boot框架的关键特性之一。下文概述了这一特性。

Spring Boot启动器依赖项

Spring Boot启动器依赖项旨在使Spring Boot应用程序开发变得简单、快速和有效。如果你之前有使用Apache Maven或Gradle等构建工具来开发Java应用程序的经验,那应该会记得管理依赖项是应用程序开发人员面临的主要挑战之一。

第一个挑战是确定开发应用程序特定组件所需的库(依赖项)。识别它们后,我们还需要找到正确的版本。即使找到了正确的库和版本,在这个快节奏的应用程序开发世界中,版本不同步的问题也很容易发生。而使这个问题变得更复杂的是,我们选择的依赖项又有自己的依赖项,或者更准确地说,是传递依赖项。在某些情况下,我们也需要处理传递依赖项。而Spring Boot启动器依赖项是Spring Boot提供的一个解决方案,它可以帮助我们解决上述所有问题。

启动器依赖项将开发应用程序组件所需的依赖项组合在一起。如果使用Spring Boot开发Web应用,我们很可能会选择spring-boot-starter-web依赖项。它可以确保开发Web应用所需的依赖项在应用程序中可用。当然,这是一种约定,我们得到的这组依赖项来自Spring团队的建议。这里最重要的是,我们可以从依赖项版本控制、升级和许多其他问题中解脱出来。

一个启动器依赖项也可能依赖另一个启动器依赖项。例如,spring-boot-starter-web就需要一些常见的启动器依赖项,包括spring-boot-starter、spring-boot-starter-tomcat和spring-boot-starter-json等依赖项。这些启动器分别拉取另一组与Spring Boot、Tomcat和JSON相关的依赖项。可以参考Spring Boot文档来获取可用的Spring Boot启动器列表(参见本书配套的GitHub wiki页面)。

启动器依赖项的概念是可扩展的。Spring Boot允许我们构建可以在应用程序中使用的启动器。大型应用程序可以通过自定义启动器来进行模块化,管理依赖关系。本书后面将介绍如何创建自定义的启动器。

代码清单 1.1 对应的项目中有两个启动器依赖项:spring-boot-starter-web和spring-boot-starter- test。Web启动器依赖项包括构建Web应用所需的JAR文件,而测试依赖项则让我们能够为应用程序编写测试用例。

在代码清单1.1所示pom.xml文件的最后部分,可以看到spring-boot-maven-plugin。这个插件能帮助开发人员简化对应用程序活动的管理。例如,我们很容易就能构建出Spring Boot应用程序的可执行JAR或WAR文件。这是因为spring-boot-maven-plugin的repackage会获取Maven生成的原始的、不可执行的JAR或WAR文件,然后重新打包让它们变成可执行的。表1.1显示了spring-boot-maven-plugin的可用目标列表,里面有相关语法和简要说明。

表1.1 Spring Boot Maven插件的可用目标列表

目标名称

Maven命令语法

描述

构建镜像

spring-boot:build-image

将应用程序打包到一个开放容器倡议(Open Container Initiative,OCI)镜像中。第9章会讲解更多关于镜像及容器部署的内容

生成构建信息

spring-boot:build-info

根据当前Maven项目生成build-info.properties文件。路径为${project.build.outputDirectory}/META-INF/build-info.properties

显示帮助信息

spring-boot:help

显示spring-boot-maven-plugin的帮助内容。可以使用mvn spring-boot:help -Ddetail=true -Dgoal=<goal-name>查看目标提供的参数。例如,mvn spring-boot:help -Ddetail=true -Dstart显示目标start的详细信息

重新打包Spring Boot JAR或WAR

文件

spring-boot:repackage

该目标旨在重新打包现有的JAR或WAR文件,以使它们可以在命令行中执行(例如,java -jar somejar.jar)。默认情况下,此目标在Maven生命周期的package阶段绑定自身,并使生成的JAR或WAR文件变成可执行的。可以使用mvn clean install spring-boot:repackage来查看这个目标是如何工作的。或者,也可以使用mvn package生成相同的可执行文件

运行Spring Boot

应用程序

spring-boot:run

直接运行Spring Boot应用程序

启动Spring Boot

应用程序

spring-boot:start

启动Spring Boot应用程序

停止正在运行的Spring Boot应用程序

spring-boot:stop

停止通过spring-boot:start启动的应用程序

例如,如果想运行当前的Spring Boot应用程序,可在pom.xml文件所在目录的命令行或终端执行以下命令:mvn spring-boot:run。我们会看到应用程序在默认HTTP端口8080上启动并运行,如图1.3所示。

图1.3 在命令行中使用Spring Boot Maven插件运行Spring Boot应用程序

仔细观察命令行输出,我们会看到这个目标调用了其他Maven插件,例如使用maven- resources-plugin来复制资源(将Java源文件从src/main/java文件夹复制到输出目录),以及使用maven-compiler-plugin在启动应用程序之前编译源代码。spring-boot-maven-plugin帮开发人员抽象出了所有这些低级任务。

Spring Boot主类

在生成的项目中,我们会发现Spring Initializr生成了一个Java类,这个类包含了一个main()方法。代码清单1.2展示了这一点。

代码清单1.2 Spring Boot主类

package com.manning.sbip.ch01;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class SpringBootAppDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootAppDemoApplication.class, args);
    }
}

让我们看看这个Java文件中的以下内容:

(1)main()方法的使用;

(2)@SpringBootApplication注解的使用;

(3)SpringApplication类的作用。

一般来说,要运行Web应用程序,我们需要构建并打包应用程序组件到WAR或EAR文件中,然后将其部署到Web服务器(例如Apache Tomcat)或应用服务器(例如Red Hat JBoss)。Spring Boot在一定程度上简化了这个过程。它不强制我们构建应用程序的WAR或EAR文件。相反,它允许使用传统的main()方法来运行Spring Boot应用程序,就像运行普通的Java应用程序一样。

尽管Spring Boot遵循常规的方法来让开发人员方便入手,但它在幕后做了大量繁重的工作。例如,基于Servlet的Web应用程序只能在Apache Tomcat或Jetty这样的Servlet容器中运行。Spring Boot通过在应用程序中使用嵌入式Apache Tomcat服务器来实现这一点。因此,当我们使用main()方法启动Spring Boot应用程序时,Spring Boot会启动一个嵌入式Apache Tomcat服务器实例,然后在其中运行Web应用程序。

如果进一步观察spring-boot-starter-web依赖项,会发现它对spring-boot-starter-tomcat模块具有传递依赖性。可以在pom.xml文件所在的路径上执行mvn dependency:tree命令,从而获取应用程序的依赖关系树。

你可能会注意到代码清单1.2中的类使用了@SpringBootApplication注解。这个注解很有用,它由3个注解组成:@EnableAutoConfiguration、@ComponentScan和@SpringBootConfiguration,每个注解都在应用程序中执行特定的任务。

让我们根据这些注解的行为来理解它们。

@EnableAutoConfiguration——Spring Boot提供了几个@Enable*注解来启用Spring Boot应用程序中的特定功能。Spring Boot可以根据应用类路径中存在的JAR依赖项来自动配置应用程序,而@EnableAutoConfiguration注解为这个功能提供了支持。第4章将提供有关自动配置的更多信息。

@ComponentScan——支持扫描应用程序中的Spring组件。Spring组件是由Spring管理的一种Java Bean,它使用@Component、@Bean或专用组件注解来表示。配置了@ComponentScan注解后,Spring Boot应用程序会扫描根包及其子包中存在的所有组件,以管理它们的生命周期。对包进行扫描的关键在于,扫描是从根包开始并覆盖到所有子包的。因此,任何位于根包层级结构之外的包,都不会被扫描到。

@SpringBootConfiguration——表明被注解的类提供了Spring Boot应用程序配置。它使用Spring的@Configuration注解对自身进行了注解,这就使得Spring Boot能够自动找到注解类中的配置。因此,定义在这个主类中的bean可以被Spring自动检测和加载。

另外,Spring Boot应用程序的主类需要在根包中,因为这个类里配置了@SpringBootApplication注解,而@SpringBootApplication注解使用根包作为基础包。这个基础包和所有其他子包会被Spring Boot扫描,这样Spring Boot就可以加载Spring组件(例如,使用@Component、@Configuration和其他Spring注解配置的类)和其他可识别类型。

下一个要介绍的是在这个项目主类里调用的SpringApplication类。这个类由Spring Boot提供,用于方便地引导Spring Boot应用程序。大多数时候,我们使用SpringApplication的静态run()方法来引导和运行应用程序。Spring Boot在执行run()方法时会做下面4件事情。

(1)基于类路径中存在的库创建ApplicationContext实例。

(2)注册一个CommandLinePropertySource来将命令行参数加载为Spring属性。

(3)刷新步骤(1)中创建的ApplicationContext实例来加载所有单例bean。

(4)触发应用程序中配置的ApplicationRunners和CommandRunners。

重温ApplicationContext

我们开发的大多数Java应用程序由对象组成。这些对象是交互的,它们之间存在着依赖关系。为了更有效地管理对象的创建和依赖关系,Spring引入了依赖注入(DI)。依赖注入或控制反转(IoC)能让Spring创建对象(或者更恰当地说,是Spring术语中的bean)并在外部注入依赖项。bean通过XML bean定义文件(例如applicationContext.xml)或基于注解的配置(@Configuration注解)呈现给Spring。Spring加载这些bean并让它们在Spring IoC容器中可用。

ApplicationContext接口充当Spring IoC容器。Spring根据应用程序类型(Servlet或Reactive应用程序)、bean定义配置(例如,从类路径或注解加载)等信息提供了多个不同的ApplicationContext实现。可以参考ApplicationContext接口的Java文档(参见本书配套的GitHub wiki页面)来了解关于它和它的子类的更多信息。

SpringApplication类会根据类路径中存在的JAR依赖项来创建ApplicationContext实例。Spring Boot Web应用程序可以是基于Servlet的,也可以是响应式的。利用Spring的类加载技术,并根据类路径中类的可用性,Spring就能推断出当前应用程序的类型。一旦知道了应用程序类型,Spring Boot就会通过以下策略来加载应用程序上下文。

(1)如果应用程序被识别为基于Servlet的Web应用程序,Spring Boot会尝试创建AnnotationConfigServletWebServerApplicationContext类的实例。

(2)如果应用程序是响应式的,Spring Boot会创建AnnotationConfigReactiveWebServer ApplicationContext类的实例。

(3)如果应用程序既不是基于 Servlet 的也不是响应式的,Spring Boot会尝试创建AnnotationConfigApplicationContext类的实例。

我们使用SpringApplication类的静态方法run()来启动Spring Boot应用程序。尽管run()方法很有用,但Spring Boot也允许我们创建SpringApplication类的实例来自定义应用程序引导模式。例如,如果知道应用程序类型,就可以直接在 SpringApplication 实例中设置它,如代码清单 1.3所示。

代码清单1.3 自定义SpringApplication并设置应用程序类型为响应式的

package com.manning.sbip.ch01;
 
//导入
 
@SpringBootApplication
public class BootstrappingSpringBootAppApplication {
 
    public static void main(String[] args) {
 
        SpringApplication springApplication = new
 SpringApplication(BootstrappingSpringBootAppApplication.class);            ❶
 
        springApplication.setWebApplicationType(WebApplicationType.REACTIVE); ❷
        springApplication.run(args);
    }
}

❶ 创建SpringApplication实例。

❷ 自定义SpringApplication并将应用程序类型设置为响应式的。

SpringApplication还提供了几个setter方法,因此我们可以控制Spring Boot的各种功能,例如设置额外的Spring配置文件,或设置资源加载器来加载应用程序资源。可以查看Spring Boot的最新参考手册来了解SpringApplication的更多信息。

应用程序属性文件的配置管理

Spring Initializr在src/main/resources文件夹下生成了一个空的application.properties文件。这个属性文件能够为应用程序外化各种配置(例如,服务器详细信息或数据库详细信息)。尽管有多种方法可以将Spring Boot应用程序中的属性外部化,但这是最常用的方法。application.properties文件以键值对格式指定配置,其中键与关联值用“=”字符分隔。代码清单1.4给出了application.properties文件的示例配置,这个示例用来配置Spring Boot应用程序的服务器地址和端口。

代码清单1.4 在application.properties文件中配置Spring Boot应用程序的服务器地址和端口

server.address=localhost                     ❶
server.port=8081                             ❷
management.endpoints.web.exposure.include=*  ❸

❶ 服务器绑定的网络地址。

❷ 服务器的HTTP端口。

❸ 通过HTTP公开暴露的所有执行器端点。

想要动手练习,可以在application.properties文件中将当前应用程序中的server.port值修改为不同的HTTP端口值(例如,修改为9090)。修改后启动应用程序,可以看到应用程序在更新后的HTTP端口上启动。

如果不喜欢properties文件格式,也可以使用YAML文件格式来配置应用程序属性。YAML文件格式允许分层定义属性。如果想使用YAML文件格式,可以将现有的application.properties文件重命名为application.yml并以YAML文件格式指定属性。代码清单1.5提供了和代码清单1.4等效的YAML配置。

代码清单1.5 在application.yml文件中配置Spring Boot应用程序的服务器地址和端口

server:
  address: localhost
  port: 8080
management:
  endpoints:
    web:
      exposure:
        include: '*'

可以参考Spring Boot网站上的应用程序常用属性,来获取application.properties文件支持的属性列表。随着本书的学习,你会惊讶地发现,通过简单地添加应用程序配置属性,就可以实现应用程序行为的巨大变化。

本小节探索了Spring Boot应用程序的核心组件。你现在应该熟悉了整个Spring Boot项目结构、pom.xml文件组件、@SpringBootApplication注解、SpringApplication类,还有功能强大的application.properties文件,它可以通过各种内置或自定义的属性来控制Spring Boot应用程序的行为。

1.3.3 创建可执行的JAR文件

从Spring Boot项目创建可执行JAR文件的最简单方法是使用mvn package命令。回想一下,我们在项目生成时选择了打包类型。根据选择,项目的target目录下会生成一个JAR文件。可以在命令行中通过命令java -jar来运行生成的JAR文件,从而启动应用程序。

默认情况下,Maven的package目标不会自行生成可执行的JAR或WAR文件。spring-boot- maven-plugin的repackage在打包阶段进行了绑定,从而为可执行文件的生成奠定了基础。

1.3.4 探索JAR文件

如果浏览生成的JAR文件,我们会发现代码清单1.6所示的JAR文件结构。

代码清单1.6 Spring Boot生成的JAR文件结构

spring-boot-app-demo.jar
  |
  +-META-INF
  |  +-MANIFEST.MF
  +-org
  |  +-springframework
  |    +-boot
  |      +-loader
  |        +-<spring boot loader classes>
  +-BOOT-INF
    +-classes
      |  +-com
      |    +-manning
      |      +-sbip
      |        +-ch01
      |          +-SpringBootAppDemoApplication.class
      +-lib
      | +-dependency1.jar
      | +-dependency2.jar
      +-classpath.idx
      +-layers.idx

JAR文件结构大致分为4个部分。

META-INF——该部分包含MANIFEST.MF文件,里面含有执行JAR文件所需的许多关键信息。MANIFEST.MF文件提供了两个关键参数Main-Class和Start-Class的详细信息。

Spring Boot loader组件——Spring Boot loader组件提供了多个用于加载可执行文件的加载器实现。例如,JarLauncher加载JAR文件,WarLauncher加载WAR文件,PropertiesLauncher允许通过一组loader.*属性自定义类加载。

BOOT-INF\classes——所有应用程序类文件都打包到这个文件夹中。

BOOT-INF\lib——该文件夹包含应用程序的所有依赖项。

需要注意的一个关键点是MANIFEST.MF文件中配置的Main-Class和Start-Class参数。Main- Class包含了Launcher的类名,它使用Start-Class中指定的类来启动应用程序。在Spring Boot的可执行JAR文件中,Start-Class始终是Spring Boot主类。

classpath.idx是一个索引文件,它按照类加载器的加载顺序列出依赖项。layer.idx文件用来将JAR文件隔离到逻辑层,从而创建Docker或OCI镜像。第9章会介绍如何从Spring Boot应用程序创建Docker镜像,届时我们会继续探索layer.idx的用法。

1.3.5 关闭Spring Boot应用程序

关闭Spring Boot应用程序非常简单。如果通过命令行将JAR文件作为前台进程运行,则可以使用Ctrl+C终止Java进程(在Windows和Linux系统中)。同样,如果应用程序作为后台进程运行,则可以使用特定于操作系统的命令来终止Java进程。

如果没有任何额外的配置,上面讨论的方法会立即终止Spring Boot应用程序,并且如果有正在执行的请求,也会立即被丢弃。这影响了应用程序的用户体验。因此,我们需要实现应用程序的优雅停机功能,也就是说,在应用程序停止前,正在处理的请求仍然会继续处理,但不会再接收任何新的请求。

Spring Boot提供了额外的属性来启用应用程序中的优雅停机功能。我们可以在application.properties文件中配置这些属性,如代码清单1.7所示。

代码清单1.7 优雅停机配置

server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=1m

server.shutdown属性的默认值为immediate,表示立即关闭应用程序。优雅停机配置后,还可以配置应用程序等待当前请求完成的超时时间。请注意,spring.lifecycle.timeout-per-shutdown- phase属性的默认值为30秒。如果默认值不适合我们的应用,可以配置自定义的超时值。在代码清单1.7中,我们配置了一分钟作为超时时间。

注意

优雅停机功能是在Spring Boot的2.3.0版本中引入的。它不适用于早期的Spring Boot版本。

1.4 Spring Boot的附加概念

在本节中,我们将简要介绍一些有用的Spring Boot附加概念。其中一些是该框架的关键概念,我们将在后续章节中进行详细的讨论。

1.4.1 Spring Boot的启动事件

Spring框架的事件管理机制促进了应用程序中事件发布者和订阅者的解耦。我们可以订阅Spring框架的内置事件,也可以自定义想要的事件。

Spring Boot框架提供了几个内置事件,我们可以订阅这些事件来执行某些操作。例如,一旦Spring Boot应用程序完全初始化,我们就需要调用某个外部的REST API,这种情况就可以通过订阅事件来实现。本小节将介绍9个Spring Boot事件,这些事件在应用程序启动和初始化的各个阶段发布。

ApplicationStartingEvent——在监听器注册后、应用程序开始启动时发布。Spring Boot的LoggingSystem使用此事件在应用程序初始化之前完成需要执行的操作。

ApplicationEnvironmentPreparedEvent——在应用程序启动后、Environment准备好开始接受检查和修改时,这个事件会被发布。Spring Boot内部使用此事件来预初始化多个服务,例如MessageConverter、ConversionService,或者用它初始化Jackson及其他一些组件。

ApplicationContextInitializedEvent——ApplicationContext生成后,ApplicationContextInitializers会被执行,此时还没有开始加载任何bean,在这个时间点此事件被发布。此事件可用于在Spring容器初始化bean之前执行任务。

ApplicationPreparedEvent——在ApplicationContext准备好时发布,此时bean被加载但还没有刷新。在此阶段Environment已准备好可以使用了。

ContextRefreshedEvent——在ApplicationContext刷新时发布。此事件来自Spring而非Spring Boot。它没有扩展SpringApplicationEvent。Spring Boot的ConditionEvaluationReportLoggingListener监听此事件并在此事件发布后打印自动配置报告。

WebServerInitializedEvent——当Web服务器准备好后这个事件会被发布。此事件根据应用程序的类型有两种变体:基于Servlet的ServletWebServerInitializedEvent和响应式的ReactiveWebServerInitializedEvent。此事件没有扩展SpringApplicationEvent。

ApplicationStartedEvent——在 ApplicationContext 刷新后且 ApplicationRunner 和CommandLineRunners调用前发布。

ApplicationReadyEvent——由SpringApplication发布,表示应用程序已准备好为请求提供服务。此时不建议更改应用程序的内部状态,因为所有应用程序初始化步骤都已完成。

ApplicationFailedEvent——当应用程序出现异常启动失败时发布。此事件对于执行异常处理脚本或通知应用程序启动失败这样的任务很有用。

1.4.2 监听Spring Boot应用程序中的事件

Spring Boot应用程序启动时的事件提供了应用初始化各个阶段的信息。如果需要对应用启动行为进行编程控制,这些事件就很有用。最简单的方法是订阅这些事件并采取必要的措施。例如,如果需要修改Environment中的任何参数,可以订阅ApplicationEnvironmentPreparedEvent。Spring Boot在内部使用这些事件来初始化应用程序的多个组件。

这些事件的订阅有多种方法。使用Spring框架的@EventListener注解是最简单的。例如,要监听ApplicationReadyEvent,可以使用代码清单1.8中的代码片段。

代码清单1.8 使用@EventListener注解监听ApplicationReadyEvent

@EventListener(ApplicationReadyEvent.class)
public void applicationReadyEvent(ApplicationReadyEvent
 applicationReadyEvent) {
    System.out.println("Application Ready Event generated at "+new
 Date(applicationReadyEvent.getTimestamp()));
}

代码清单1.8中的代码片段打印了生成ApplicationReadyEvent的时间戳。尽管@EventListener在大多数情况下能正常工作,但它不适用于在应用程序启动早期发布的事件,例如ApplicationStartingEvent和ApplicationEnvironmentPreparedEvent。在本小节中,我们将讨论在Spring Boot应用程序中监听事件的另外两种方法。

使用SpringApplication

在Spring Boot项目中,应用程序类通常会调用SpringApplication的静态run()方法来启动应用程序。但是,SpringApplication类也提供了几个setter方法来自定义应用程序的启动行为。例如,我们可以使用这些setter方法来添加ApplicationContextInitializer、设置ApplicationListener,以及执行许多其他操作。要使用SpringApplication监听事件,可以创建一个对应的ApplicationListener类并实现onApplicationEvent()方法。代码清单1.9显示了一个自定义的监听器,用于监听Spring Boot的ApplicationStartingEvent。

代码清单1.9 创建一个自定义的ApplicationListener

public class ApplicationStartingEventListener implements
 ApplicationListener<ApplicationStartingEvent> {
 
    @Override
    public void onApplicationEvent(ApplicationStartingEvent
 applicationStartingEvent) {
        System.out.println("Application Starting Event logged at "+new
 Date(applicationStartingEvent.getTimestamp()));
    }
}

然后,在SpringApplication中添加此监听器,以便在ApplicationStartingEvent发布后调用关联的监听器。代码清单1.10提供了SpringApplication的实现。

代码清单1.10 在SpringApplication中添加应用程序监听器

@SpringBootApplication
public class SpringBootEventsApplication {
 
    public static void main(String[] args) {
        SpringApplication springApplication = new
 SpringApplication(SpringBootEventsApplication.class);
        springApplication.addListeners(new
 ApplicationStartingEventListener());
        springApplication.run(args);
    }
}

在代码清单1.10中,我们将自定义的监听器添加到SpringApplication实例中。addListeners()方法采用可变参数,因此可以使用此方法添加任意数量的监听器。

本部分介绍的方法要求更改Spring Boot应用程序类的代码。如果这不方便,Spring Boot还提供了另一种方法:通过spring.factories属性文件注册自定义的监听器。

使用spring.factories文件

spring.factories文件提供了Spring Boot框架的扩展点,用于配置和自定义某些应用程序功能。例如,Spring Boot广泛使用此文件来配置初始化程序、应用程序监听器、故障分析器、模板,以及实现自动配置等。spring.factories文件是一个由键值对组成的属性文件。

一般来说,spring.factories文件在Spring Boot之前就已经存在,它是Spring框架的核心特性之一。可以在Spring框架组件spring-beans的JAR文件中找到它。

Spring Boot提供了一种通过此文件配置某些自定义组件(例如ApplicationListener)的方法。spring.factories文件位于META-INF文件夹下,该文件夹位于src\main\resources目录下。代码清单1.11显示了一个spring.factories示例文件。

代码清单1.11 一个spring.factories示例文件

org.springframework.context.ApplicationListener=com.manning.sbip.ch01.liste
 ner.ApplicationStartingEventListener

在代码清单1.11中,键是要配置的组件类的类型,值是对应实现的全限定类名。例如,当我们配置ApplicationListener时,键是完全限定的类的类型org.springframework.context.ApplicationListener,值是自定义的监听器实现类com.manning.sbip.ch01.listener.ApplicationStartingEventListener。可以通过逗号分隔来配置多个监听器实现。等到后面章节讲解自定义自动配置、故障分析器配置时,还会详细介绍spring.factories文件的使用。

1.4.3 自定义Spring Boot启动器

在前面的示例中,我们使用了由Spring Boot开发和维护的官方启动器。启动器是Spring Boot的关键特性之一,能够简化Spring Boot应用程序中的依赖项管理。

启动器这个概念也可以扩展到专有代码和配置。Spring Boot扩展了它的基础设施,让我们可以自定义启动器,这样我们就可以像其他应用程序组件一样定义和维护启动器了。本书的后半部分将演示如何自定义启动器。

1.4.4 自定义自动配置

在本章开头我们提到了Spring Boot是基于约定的。在应用程序启动时,Spring Boot会根据可用的依赖项和配置等因素自动配置各种应用程序组件。自动配置策略使得 Spring Boot能够控制某些应用程序组件,这在Spring Boot应用程序初始化和执行中发挥了重要作用。在启动器中也可以扩展自动配置功能,因此我们可以定义自己的自动配置。本书后面会演示如何自定义自动配置。

1.4.5 故障分析器

Spring Boot使用故障分析器来分析应用程序故障,提供有关故障的详细诊断报告。FailureAnalyzer接收异常并提供详细的FailureAnalysis。图1.4显示了在控制台为PortInUseException打印的故障分析报告。如果用于启动Spring Boot应用程序的端口不可用,就会抛出此异常。

图1.4 端口不可用时故障分析器的诊断报告

我们可以扩展FailureAnalyzer的概念并自定义异常和故障分析器。例如,可以与自定义的自动配置一起,定义特定领域的异常,并实现自己的故障分析器来提供详细的故障分析报告,这非常有用。本书后面部分探索了如何创建自定义的FailureAnalyzer。

1.4.6 Spring Boot执行器

Spring Boot执行器让我们能够监视Spring Boot应用程序并与之交互。在生产应用程序中监视多个表示应用状态的参数是很常见的。例如,可以在应用程序中执行健康检查,以确定应用程序是否启动。此外,还可以捕获应用程序的线程转储或堆转储以执行各种分析。Spring Boot为执行器提供了大量的生产就绪功能。要启用Spring Boot执行器,需要在pom.xml中包含spring-boot- starter-actuator依赖项。代码清单1.12展示了这种依赖关系。

代码清单1.12 在pom.xml中添加Spring Boot starter执行器依赖项

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

默认情况下,Spring Boot将/actuator作为所有可访问端点的基本端点,且仅为HTTP启用/health和/info端点。如果访问http://localhost:8080/actuator,会看到代码清单1.13中设置的页面。

代码清单1.13 Spring Boot执行器端点

{
   "_links":{
      "self":{
         "href":"http://localhost:8080/actuator",
         "templated":false
      },
      "health":{
         "href":"http://localhost:8080/actuator/health",
         "templated":false
      },
      "health-path":{
         "href":"http://localhost:8080/actuator/health/{*path}",
         "templated":true
      },
      "info":{
         "href":"http://localhost:8080/actuator/info",
         "templated":false
      }
   }
}

如果应用程序正在运行,访问http://localhost:8080/actuator/health,可以发现应用程序状态为UP。第4章会详细讨论Spring Boot执行器。

1.4.7 Spring Boot开发人员工具

为了提高开发人员的工作效率,Spring Boot提供了一组工具,以使开发体验更好。例如,它监控类路径更改,发现有更改后就会自动构建应用程序。此外,它还提供了一个嵌入式LiveReload服务器,可用于在资源修改时触发浏览器刷新。要在Spring Boot项目中包含开发人员工具,需要在pom.xml中包含spring-boot-devtools依赖项,如代码清单1.14所示。

代码清单1.14 在Spring Boot项目中包含开发人员工具

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

小结

Spring Boot让我们能够创建独立的、生产就绪的应用程序。我们可以运行这些应用程序,而无须过多地担心配置。Spring Boot的自动配置和基于启动器的依赖项管理功能替我们承担了繁重的应用程序配置工作,让我们能够专注于应用程序的业务开发。

在本章中,我们首先概述了Spring Boot的各种特性和组件。下面是本章探讨的一些主要内容。

Spring Boot是什么,与传统的Spring应用程序相比优点有哪些。

Spring Boot的特性及其各种组件。

Spring Boot项目的结构和组成。

如何从Spring Boot项目中创建可执行的JAR文件以及JAR文件的结构。

如何优雅地关闭正在运行的Spring Boot应用程序。

Spring Boot的启动事件,以及监听事件的各种方式。

自定义启动器、自动配置、故障分析器和执行器概述。

能够提高开发效率的Spring Boot开发人员工具介绍。

本书的其余部分致力于介绍一些实用技术,以解决我们使用Spring Boot时遇到的各种问题。我们会学习到多个主题领域,包括Spring Boot应用程序开发、安全性、响应式应用程序开发和基于云的部署。

相关图书

Spring Boot 3:入门与应用实战
Spring Boot 3:入门与应用实战
Spring Boot 3:高级与架构设计
Spring Boot 3:高级与架构设计
深入浅出Spring Boot 3.x
深入浅出Spring Boot 3.x
云原生Spring实战Spring Boot与?Kubernetes实践
云原生Spring实战Spring Boot与?Kubernetes实践
Java研发自测入门与进阶
Java研发自测入门与进阶
Spring实战(第6版)
Spring实战(第6版)

相关文章

相关课程