关键字

简化、为微服务(spring-cloud)提供技术基础


1. 背景

任何一门新技术的诞生,通常都是为了解决某段时期内的某个问题。

选择学习或使用一门新技术时,最好首先了解它解决了什么问题,为何产生,后续是否选择这门新技术也能做到心中有数。下面我们就简单的聊聊spring boot有何特别之处。

spring 丰富的框架和组件大大简化了java项目开发过程,经过多年的实践,得到了很多人的认可。spring 全栈式功能组件已经足够丰富,那么spring boot的诞生是否多此一举?你是否有如下困惑?

  • 为什么又诞生一个新框架?
  • spring boot到底是一个全新的技术栈还是旧瓶装新酒?
  • 它解决了什么问题?
  • 带来了哪些新功能?
  • 我需不需要使用它?

如果想了解一门技术解决了什么问题,那么应该先了解我们是否遇到了问题,以及遇到了什么问题?下面我们用一个简单的例子说明问题。

对java开发者而言,如果从无到有的创建一个系统或项目,第一步通常就是搭建一个项目基础框架,以支撑后续业务功能的开发。

那么针对基于spring 框架的web项目而言,基本需要如下几步:
  • 创建一个java web项目
  • 下载第三方相关库(手动或maven下载jar)
  • 配置web.xml(dispatcherSevlet、log、编码、session、mapping等等)
  • 配置spring及MVC九大组件中需要的部分
  • 开发业务
  • 开发非业务功能(如:安全、健康检查)
  • 下载安装并配置tomcat
  • 构建war
  • 部署项目到tomcat


对于上面的步骤,想一想是否有改进的地方?

  • 下载jar
无论是手动下载还是通过maven等构建工具,都必须知道所依赖的jar包版本。当依赖的jar越来越多,特别是嵌套依赖时,很容易让人分不清所依赖的jar到底需要怎样的版本才能正常运行。通过查询官网或偿试虽然可以解决问题,但往往会耗费大量的时间和精力。

  •  spring配置

scan、converter、viewResolver等spring配置相对于普通web项目,基本是通用、一成不变的(相对而言)。但每次创建项目都必须重复配置(通过复制只是减少了工作量,并未减少工作内容)

  •  开发业务

与各种组件(redis、mybatis、kafka、mail、rabbitMq等等)集成复杂,需要下载大量jar,并配置复杂的bean。
  • 下载tomcat
为了运行一个项目,必须事先创建相应的基础服务。对于已成习惯的我们,似乎并没什么大不了的,可是如果能省掉这样的工作是不是更好。另外,如果是在生产环境或者对服务器管理严格的公司,配置tomcat这样需要运维参与的事情,可能会导致项目的搭建需要一个比更长的等待时间。

  • 部署war
 把打好的war包复制(手工或jenkins)到tomcat中。并启动tomcat

  • 非业务功能
如果每个项目都需要一些非业务功能,如健康检查、内存监控等,要么做一套这样的功能到处复制,要么打成jar包各个项目引用。

总之(问题):创建一个新项目要做很多重复性的繁锁的易出错的工作。

总结:依赖复杂编码复杂配置复杂部署复杂、监控复杂


可是,上面的问题对大部分人来说根本不是问题,我们不是一直这么做吗?不过,如果有一种更简单的方式,或者你一旦习惯了另一种简单的方式,原本需要你小半天才能做好的工作,现在只需要十几分钟甚至几分钟就做好,你是否还会继续坚守原来的做法。反之,也并没有什么不对。


2. spring boot是什么

spring boot是一个用来简化搭建Spring应用以及简化其开发过程的框架。
 
目的:是为了简化spring应用的搭建,以及简化开发(简化包含了太多内容,它的目的也是为了解决上面提到的问题)
 

目的分解:

  • 为spring开发人员提供一个从根本上更快,且随处可得的入门体验
  • 开箱即用(即:不需要配置可以直接启动使用-通过默认配置)
  • 提供一系列大型项目常用的非功能性特征,如:内嵌服务器、安全、指标、健康检查、外部配置)
  • 减少对xml配置的依赖

听起来好像还不错,但是这样的概念是不是仍然让人感觉似懂非懂:

  • 什么是简化?
  • 怎么样才算简化?
  • 到底简化了什么?
  • 怎么样才算更快?
  • 什么是开箱即用?
  • 提供了哪些非功能性特征?
  • 对我来说有什么用?

3. spring boot做了什么

所谓的简化顾名思义就是繁锁的、重复性的事情简单化。比如:下载安装tomcat的事情就可以通过把tomcat与程序打包到一块,从而减少这个步骤。

简化原理:通过一个(些)注解、一个(些)配置、一个(些)jar的引入、默认配置代替手工配置等就可完成原本复杂而繁锁的事情。

spring boot简化的内容整体大概为如下几块:

  • 简化依赖
  • 简化容器(简化部署)
  • 简化配置(简化配置、简化编码)
  • 提供通用组件(简化监控)

简化依赖:通过maven中一个spring-boot-starter-xxx就可以把需要的功能模块所有指定版本的依赖包全部引入。

简化容器:通过maven中一个spring-boot-starter-web配置就可以引入一个内置的tomcat 

简化配置:通过@EnableAutoConfiguration就可以让spring boot智能化自动配置相应模块(需要classPath引入对应模块的jar来配合);通过@Configuration来减少甚至完全消除对xml的依赖。

提供通用组件:提供常用的临控功能

下面详细说明

3.1 简化依赖

对java项目而言,丰富的第三方库极大的简小了开发量,也提高了工作质量,但是过于丰富的第三库同样也带来依赖管理的复杂性,特别是手动下载相应的依赖库。

maven和gradle等自动化构建工具很方便的解放了我们的双手,但是一个功能可能需要依赖一组多个jar,以及大量jar包版本,仍然需要人工维护。jar升级、版本冲突都会耗费过多的精力。

对于特定的版本:如spring 4,它依赖的spring-core、spring-context、spring-beans等与spring4相关的依赖都是指定的版本,而且需要同时存在才能正常运行。那么如果我们按功能模块,把一个功能所依赖的所有jar,以一个单独的pom.xml(maven)维护(相当于一个功能的最小依赖清单),那么下次需要此功能时,只要把这个pom.xml引入就可以了。

spring boot正是通过这种方式,按功能把一个大的pom.xml文件分隔成一个一个小的pom.xml文件即:spring-boot-starter-xxx; 如:spring-boot-starter-jdbc、spring-boot-starter-web,每个小的pom.xml文件包含了一个功能所需要的所有jar包。

这样的好处:只需要引用一个pom依赖,就可以把对应功能所有依赖的、相应版本的jar加载到项目中。不需要一个一个到官网或maven仓库中找,也不会因为此功能下的jar版本相互不匹配而导致冲突报错。

如下,仅仅在pom文件中加入以下引用,就可以把tomcat相关的多个jar,以及其它spring依赖包全部加载到项目,简单、省心。

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




3.2 简化容器

这里的容器指提是web容器,如:tomcat、jetty、weblogic等。

通常为了部署一个web项目,第一步就是要安装一个web容器。

下载、安装、配置这一系列动作对每一个项目,流程和步骤基本是完全一样。对于部署一个5分钟就写好的hello world,还要花10分钟安装tomcat是不是纯属浪费时间。如果hello world这种测试例子不足以说明问题,那些这种无需安装web容器,自身就是一个“绿色”软件的优点,会在微服务的自动化应用中发挥关键作用。

微服务架构中,为了满足不同时段下访问量波动而服务不变化的需求,会在访问量增大时自动(或手动)增加集群内节点数量,在访问量下降时自动(或手动)减少集群内节点数量,可以通过直接复制一份代码,直接启动或关闭,无需提前或现场安装web容器。

实现原理:spring把tomcat或jetty内嵌到业务代码中。通过依赖引用,与业务代码一起构建成一个fatJar。

注意事项:spring boot最终打成一个jar包(web项目也是)。这个fatJar内部嵌套了其它jar(jar中jar),以及包含web相关的静态文件(html、css、js)

构建后的jar内部结构如下:


3.3 简化配置

  • 简化配置之默认配置
编码、web容器、数据库连接池等组件的使用都必须设置相应配置。但对大部分应用推荐配置就可以满足需要。如:编码:大部分java应用都是utf-8。因此spring首先使用默认配置来减化配置。默认配置并不代表不能自定义配置,通常情况,这些配置都可以通过自定义配置来覆盖默认配置。如:通过yaml文件(后续会涉及)中的如下配置,就可以覆盖默认的web容器端口8080为9090
#端口
server:
  port: 9090


  • 简化配置之代码配置
spring中大量的xml配置文件诟病已久。大量的xml文件不仅繁锁而且混乱。得益于注解和自动配置,大部分bean的管理都不需要xml文件配置。少量需要特殊需求可以通过 @Configuration 和  @ConfigurationProperties注解,以编码的方式管理,最大限度的减少甚至消除对xml的依赖。使项目只有代码,干净整洁。

官方建议不要使用 xml配置,但并非限制使用。如果有特殊需要,仍然可以使用xml配置或者代码配置与xml配置混用。

  • 简化配置之自动配置
自动配置是简化项目集成的利器。非spring boot的web项目搭建时,需要下载相应的spring jar 包,并配置相应的spring Listener及spring MVC 9大组中相应bean。而自动化配置只需要把相关的jar(通过pom.xml 中的一个依赖)加载到项目,spring boot 会通过检查项目中是否存在对应的类,然后自动配置相应的bean。 对于hello world项目,你甚至可以一个配置都不用设置,就可以创建一个完整的web项目。其它如:redis、mybatis等组件,只需要把jar包加载到项目,然后配置少量初始值,就可以与spring boot无缝对接,大大简化了各组件的集成。

3.4 提供通用组件

任何项目对系统(cpu、内存)、项目状态及指标、请求跟踪等信息的监控功能都是通用并且必要的,因此spring boot提供了一整套现成的解决方案,只需要引入相应的jar包,通过相应的开关配置,就可以打开所需要的监控功能

4. spring boot 能做什么

    spring boot算不上新技术,而是一种新思想。以一些巧秒的方法,简化了从依赖、编码到部署、监控整个项目生命周期中各个重要环节的操作。本质上它仍然是一个spring框架,与手动搭建spring基本框架没有任何本质上的不同。它的目的很简单,就是:简化。简化到只需要配置相应的jar(pom.xml)和一个main方法类,就可以启动并部署一个完整的web项目,开箱即用。

    因此,spring boot能做到的基本上spring-core及相关核心组件都可以实现,所以spring boot 可以做普通spring项目的所有功能。


    5. spring boot 什么情况下需要使用

    当你想"偷懒"、省事、简单、快捷的开发项目,以及使用spring-cloud创建微服务项目时尽量使用spring boot。

    6. 接下来

    也许你对spring boot仍然一知半解,太多的概念和混乱的说明会让理解更加凌乱和无所适从。不过没关系,下一章,我们会通过一个国际惯例-hello world- 的简单例子,对spring boot有一个感性的认识。

    本节只需要记住一个关键字:简化 就可以了。


    Logo

    权威|前沿|技术|干货|国内首个API全生命周期开发者社区

    更多推荐