要了解Spring Boot的發(fā)展背景,還得從2004年Spring Framework1.0版本發(fā)布開始說起,不過大家都是從開始學(xué)習(xí)Java就使用Spring Framework了,所以就不做過多展開。

隨著使用Spring Framework進(jìn)行開發(fā)的企業(yè)和個人越來越多,Spring 也慢慢從一個單一簡潔的小框架編程了一個大而全的開源軟件,Spring Framework的邊界不斷進(jìn)行擴張,到了現(xiàn)在Spring 幾乎可以做任何事情。目前市面上絕大部分的開源組件和中間件,都有Spring對應(yīng)組件的支持,

你們?nèi)绻リP(guān)注Spring目前的官網(wǎng),你會發(fā)現(xiàn)他的slogan是:Spring makes Java Simple。它讓Java的開發(fā)變得更加簡單。

雖然Spring的組件代碼是輕量級的,但是它的配置卻是重量級的,Spring 每集成一個開源軟件,就需要增加一些基礎(chǔ)配置,慢慢的隨著我們開發(fā)的項目越來越龐大,往往需要集成很多開源軟件,因此后期使用 Spirng 開發(fā)大型項目需要引入很多配置文件,太多的配置非常難以理解,并容易配置出錯,這個給開發(fā)人員帶來了不少的負(fù)擔(dān)。

大家想象一個場景,就是假如你需要用spring開發(fā)一個簡單的Hello World Web應(yīng)用程序,應(yīng)該要做哪些動作呢?

  • 創(chuàng)建一個項目結(jié)構(gòu),必然包含依賴Maven或者Gradle的構(gòu)建文件。
  • 至少需要添加spring mvc和servlet api的依賴
  • 一個web.xml,聲明spring的DispatcherServlet
  • 一個啟用了Spring MVC的spring 配置
  • 一個控制器類,“以HelloWord”為響應(yīng)的http請求
  • 一個用于部署應(yīng)用程序的web應(yīng)用服務(wù)器,比如Tomcat

在整個過程中,我們發(fā)現(xiàn)只有一個東西和Hello Word功能相關(guān),那就是控制器(controller),剩下的都是Spring 開發(fā)的Web應(yīng)用程序必須要的通用模版,既然所有Spring Web應(yīng)用程序都要用到他們,那為什么還要你來提供這些東西呢?

所以,直到2012年10月份,一個叫Mike Youngstrom(揚斯特羅姆)在Spring Jira中創(chuàng)建了一個功能請求,要求在Spring Framework中支持無容器Web應(yīng)用程序體系結(jié)構(gòu),他談到了在主容器引導(dǎo) spring 容器內(nèi)配置 Web 容器服務(wù)。

https://jira.spring.io/browse/SPR-9888

I think that Springs web application architecture can be significantly simplified if it were to provided tools and a reference architecture that leveraged the Spring component and configuration model from top to bottom. Embedding and unifying the configuration of those common web container services within a Spring Container bootstrapped from a simple main() method.我認(rèn)為,如果要提供從上到下充分利用Spring組件和配置模型的工具和參考體系結(jié)構(gòu),則可以大大簡化Spring的Web應(yīng)用程序體系結(jié)構(gòu)。在通過簡單main()方法引導(dǎo)的Spring容器中嵌入和統(tǒng)一那些通用Web容器服務(wù)的配置。

而且Spring 開發(fā)團(tuán)隊也意識到了這些問題,急需要一套軟件來解決這個問題,而這個時候微服務(wù)的概念也慢慢的起來,快速開發(fā)微小獨立的應(yīng)用也變得很急迫。

而Spring恰好處在這樣一個交叉點上,所以順勢而為在2013年初的時候,開始投入Spring Boot項目的研發(fā),直到2014年4月,Spring Boot1.0版本發(fā)布。從那以后,Spring Boot開啟了一些列的迭代和升級的過程。

經(jīng)過7年時間的發(fā)展,到目前為止,Spring Boot最新穩(wěn)定版為2.6.0版本。

Spring Boot的發(fā)展

Spring Boot剛出生的時候,引起了很多開源社區(qū)的關(guān)注,并且也有個人和企業(yè)開始嘗試使用Spring Boot。 其實直到2016年,Spring Boot才真正在國內(nèi)被使用起來。我之前在挖財?shù)臅r候,2015年公司就開始采用Spring Boot來構(gòu)建基于Dubbo的微服務(wù)架構(gòu)。到現(xiàn)在,Spring Boot幾乎是所有公司的第一選擇。

Build Anything

Spring Boot被官方定位為“BUILD ANYTHING”,Spring Boot官方的概述是這么描述Spring Boot的。

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".// 通過Spring Boot可以輕松的創(chuàng)建獨立的、生產(chǎn)級別的基于Spring 生態(tài)下的應(yīng)用,你只需要運行即可。We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration.//對于Spring平臺和第三方庫,我們提供了一個固化的視圖,這個視圖可以讓我們在構(gòu)建應(yīng)用是減少很多麻煩。大部分spring boot應(yīng)用只需要最小的Spring 配置即可。

如果大家不習(xí)慣看英文文檔,可能理解起來比較復(fù)雜,翻譯成人話就是:Spring Boot能夠幫助使用Spring Framework生態(tài)的開發(fā)者快速高效的構(gòu)建一個基于Spring以及spring 生態(tài)體系的應(yīng)用。

為了讓大家對這句話的理解更加深刻,我們來做兩個小實驗,一個是基于傳統(tǒng)的Spring MVC框架構(gòu)建一個項目、另一種是使用Spring Boot。

Spring MVC With Spring Boot

通過Spring MVC項目搭建過程來對比Spring Boot的差異和優(yōu)勢。

Spring MVC項目搭建過程

  • 創(chuàng)建一個maven-webapp項目

  • 添加jar包依賴

      org.springframework  spring-beans  5.2.5.RELEASE  commons-logging  commons-logging  1.2
    spring-contextspring-context-supportspring-corespring-expressionspring-webspring-webmvc
  • 修改web.xml文件

      contextConfigLocation  classpath:applicationContext.xml  org.springframework.web.context.ContextLoaderListener  org.springframework.web.util.IntrospectorCleanupListener  springmvc  org.springframework.web.servlet.DispatcherServlet        contextConfigLocation      classpath:dispatcher-servlet.xml    springmvc  /
  • 在resources目錄下添加dispatcher-servlet.xml文件

        
  • 創(chuàng)建一個Controller

    @Controllerpublic class HelloController {  @RequestMapping(method = RequestMethod.GET,path = "/index")  public String index(Model model){      model.addAttribute("key","Hello Gupao");      return "index";  }}
  • 修改默認(rèn)的index.jsp,設(shè)置el表達(dá)式的解析

    <%@ page language="java" contentType="text/html; charset=utf-8"       pageEncoding="utf-8" isELIgnored="false" %>${key}
  • 運行項目

Spring Boot搭建過程

直接基于start.spring.io這個腳手架搭建即可。

思考和總結(jié)

咱們再回到最開始Spring Boot的定義部分,Spring Boot能夠幫助使用Spring Framework生態(tài)的開發(fā)者快速高效的構(gòu)建一個基于Spring以及spring 生態(tài)體系的應(yīng)用。

再對比兩種構(gòu)建過程,似乎也能夠理解Spring Boot的作用了吧。當(dāng)然它的作用不僅于此,后續(xù)會逐步揭開它的真實面目。

通過上面這個案例我們發(fā)現(xiàn),如果沒有spring boot,要去構(gòu)建一個Spring MVC的web應(yīng)用,需要做的事情很多

  • 引入jar包
  • 修改web.xml,添加監(jiān)聽和攔截
  • 創(chuàng)建spring mvc核心配置文件dispatcher-servlet.xml
  • 創(chuàng)建controller
  • 部署到tomcat

這個過程如果不熟悉,很可能需要1~2個小時,如果是新手,可能需要更長時間。但是spring boot,不管是新手還是老手,都能夠分分鐘解決問題。

理解約定優(yōu)于配置

我們知道,Spring Boot是約定由于配置理念下的產(chǎn)物,那么什么是約定由于配置呢?

約定優(yōu)于配置是一種軟件設(shè)計的范式,主要是為了減少軟件開發(fā)人員需做決定的數(shù)量,獲得簡單的好處,而又不失靈活性。

簡單來說,就是你所使用的工具默認(rèn)會提供一種約定,如果這個約定和你的期待相符合,就可以省略那些基礎(chǔ)的配置,否則,你就需要通過相關(guān)配置來達(dá)到你所期待的方式。

約定優(yōu)于配置有很多地方體現(xiàn),舉個例子,比如交通信號燈,紅燈停、綠燈行,這個是一個交通規(guī)范。你可以在紅燈的時候不停,因為此時沒有一個障礙物阻礙你。但是如果大家都按照這個約定來執(zhí)行,那么不管是交通的順暢度還是安全性都比較好。

而相對于技術(shù)層面來說,約定有很多地方體現(xiàn),比如一個公司,會有專門的文檔格式、代碼提交規(guī)范、接口命名規(guī)范、數(shù)據(jù)庫規(guī)范等等。這些規(guī)定的意義都是讓整個項目的可讀性和可維護(hù)性更強。

Spring Boot Web應(yīng)用中約定優(yōu)于配置的體現(xiàn)

那么在前面的案例中,我們可以思考一下,Spring Boot為什么能夠把原本繁瑣又麻煩的工作省略掉呢? 實際上這些工作并不是真正意義上省略了,只是Spring Boot幫我們默認(rèn)實現(xiàn)了。

而這個時候我們反過來思考一下,Spring Boot Web應(yīng)用中,相對Spring MVC框架的構(gòu)建而言,它的約定由于配置體現(xiàn)在哪些方面呢?

  • Spring Boot的項目結(jié)構(gòu)約定,Spring Boot默認(rèn)采用Maven的目錄結(jié)構(gòu),其中

    src.main.java 存放源代碼文件

    src.main.resource 存放資源文件

    src.test.java 測試代碼

    src.test.resource 測試資源文件

    target 編譯后的class文件和jar文件

  • 內(nèi)置了嵌入式的Web容器,在Spring 2.2.6版本的官方文檔中3.9章節(jié)中,有說明Spring Boot支持四種嵌入式的Web容器

    Tomcat

    Jetty

    Undertow

    Reactor

  • Spring Boot默認(rèn)提供了兩種配置文件,一種是application.properties、另一種是application.yml。Spring Boot默認(rèn)會從該配置文件中去解析配置進(jìn)行加載。

  • Spring Boot通過starter依賴,來減少第三方j(luò)ar的依賴。

這些就是Spring Boot能夠方便快捷的構(gòu)建一個Web應(yīng)用的秘密。當(dāng)然Spring Boot的約定優(yōu)于配置還不僅體現(xiàn)在這些地方,在后續(xù)的分析中還會看到Spring Boot中約定優(yōu)于配置的體現(xiàn)。

Spring Boot整合Mybatis

實際上Spring Boot的本質(zhì)就是Spring,如果一定要從技術(shù)發(fā)展的過程中找到一些相似的對比的話,你們可以對比一下Jsp/Servlet和Spring MVC, 兩者都可以用來開發(fā)Web項目,但是在使用上,Spring MVC的使用會更加簡單。

而Spring Boot和Spring 就相當(dāng)于當(dāng)年的JSP/Servlet和Spring MVC的關(guān)系。所以它本身并沒有所謂新的技術(shù),接下來,我?guī)е蠹襾硗ㄟ^Spring Boot整合Mybatis實現(xiàn)數(shù)據(jù)的基本操作的案例,來繼續(xù)認(rèn)識一下Spring Boot。

創(chuàng)建Spring Boot 應(yīng)用

創(chuàng)建一個Web項目

引入項目中需要的starter依賴

    mysql    mysql-connector-java    org.mybatis.spring.boot    mybatis-spring-boot-starter    2.1.2    org.springframework.boot    spring-boot-starter-thymeleaf

創(chuàng)建數(shù)據(jù)庫表

DROP TABLE IF EXISTS `t_user`;CREATE TABLE `t_user` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  `name` varchar(20) DEFAULT NULL,  `address` varchar(80) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;

配置數(shù)據(jù)庫連接

spring:  datasource:    url: jdbc:mysql://192.168.13.106:3306/test_springboot    username: root    password: root    driver-class-name: com.mysql.cj.jdbc.Driver

開發(fā)數(shù)據(jù)庫訪問層

創(chuàng)建實體對象

public class User {    private int id;    private String name;    private String address;}

創(chuàng)建Mapper

//@Repository可以支持在你的持久層作為一個標(biāo)記,可以去自動處理數(shù)據(jù)庫操作產(chǎn)生的異常@Repository@Mapperpublic interface UserMapper {    User findById(int id);    List list();    int insert(User user);    int delete(int id);    int update(User user);}

編寫mapper文件

在resource文件目錄下創(chuàng)建UserMapper.xml文件,內(nèi)容如下

                                                    insert into t_user(name,address) values(#{name,jdbcType=VARCHAR},#{address,jdbcType=VARCHAR})                delete from t_user where id=#{id}                update t_user set name=#{name,jdbcType=VARCHAR},address=#{address,jdbcType=VARCHAR} where id=#{id,jdbcType=INTEGER}    

定義service及實現(xiàn)

public interface IUserService {    User findById(int id);    List list();    int insert(User user);    int delete(int id);    int update(User user);}@Servicepublic class UserServiceImpl implements IUserService {    @Autowired    private UserMapper userMapper;}

創(chuàng)建Controller

@RestControllerpublic class Controller {    @Autowired    private IUserService userService;    @GetMapping("/user/{id}")    public User user(@PathVariable("id") int id){        return userService.findById(id);    }    @GetMapping("/users")    public List users(){        return userService.list();    }    @PostMapping("/user")    public String insertUser(User user){        int row=userService.insert(user);        return row>0?"SUCCESS":"FAILED";    }    @PutMapping("/user")    public String updateUser(User user){        int row=userService.update(user);        return row>0?"SUCCESS":"FAILED";    }    @DeleteMapping("/user/{id}")    public String deleteUser(@PathVariable("id") int id){        return userService.delete(id)>0?"SUCCESS":"FAILED";    }}

修改配置

  • 在Spring 的Main方法上增加以下注解,用來掃描Mybatis的Mapper文件

    @MapperScan("com.example.demo.mapper")
  • 配置Mapper配置文件的地址,在application.yml中

    mybatis:mapper-locations: classpath:*Mapper.xml

    id int,

    name varchar(20),

    address varchar(20)

)

項目打包

  • mvn -Dmaven.test.skip -U clean install
  • java -jar xxx.jar

簡單總結(jié)

這個代碼,我想,大家應(yīng)該寫過無數(shù)遍了,而在基于Spring Boot集成Mybatis這個案例中,核心的業(yè)務(wù)邏輯并沒有減少,它只減少了一些繁瑣的配置,使得我們更聚焦在業(yè)務(wù)開發(fā)層面。

簡單來說,基于Spring Boot的項目中,我們只需要寫Controlelr、Service、Dao即可。甚至很多情況下我們dao都不需要管,比如使用mybatis-plus這個插件,就可以省去很多固定的dao層邏輯。

所以實際上,Spring Boot并沒有新鮮的東西,因此你看到市面上大部分講spring boot的書,這些書我?guī)缀醵伎催^,基本上都是講解Spring Boot的應(yīng)用,以及Spring Boot的一些特性分析。因為一旦你想講Spring Boot的原理,就必然會回歸到Spring這塊的內(nèi)容上。比如小馬哥的Spring Boot編程思想著本書,大篇幅的都是在講Spring Framework。因為Spring Boot的內(nèi)核還是Spring Framework。

Spring Boot與微服務(wù)

接下來,給大家講講spring boot與微服務(wù)這塊的內(nèi)容。

什么是Spring Cloud

首先,我們要簡單了解一下什么是微服務(wù),按照我的理解來說,微服務(wù)就是微粒度的服務(wù),它是面向服務(wù)架構(gòu)(SOA)的進(jìn)一步優(yōu)化。如果大家不是很好理解,翻譯成白話就是

一個業(yè)務(wù)系統(tǒng),原本是在一個獨立的war包中?,F(xiàn)在為了更好的維護(hù)和提高性能,把這個war包按照業(yè)務(wù)緯度拆分成了一個個獨立的業(yè)務(wù)子系統(tǒng),每個子系統(tǒng)提供該業(yè)務(wù)領(lǐng)域相關(guān)的功能,并暴露API接口。

這些服務(wù)彼此之間進(jìn)行數(shù)據(jù)交換和通信來實現(xiàn)整個產(chǎn)品的功能。

而這些業(yè)務(wù)子系統(tǒng),實際上代表的就是一個服務(wù),那么所謂的微服務(wù),說的是這個服務(wù)的粒度。至于服務(wù)的粒度什么樣才叫微,其實沒有一個固定的衡量標(biāo)準(zhǔn)。更多的還是在每個公司具體的業(yè)務(wù)粒度的把控上。

微服務(wù)化遇到的問題

在為服務(wù)化之后,會面臨很多的問題,比如服務(wù)注冊、服務(wù)路由、負(fù)載均衡、服務(wù)監(jiān)控等等。這些問題都需要有相應(yīng)的技術(shù)來解決,這個時候,Spring Cloud就出現(xiàn)了。

簡單來說,Spring Cloud 提供了一些可以讓開發(fā)者快速構(gòu)建微服務(wù)應(yīng)用的工具,比如配置管理、服務(wù)發(fā)現(xiàn)、熔斷、智能路由等,這些服務(wù)可以在任何分布式環(huán)境下很好地工作。Spring Cloud 主要
致力于解決如下問題:

  • Distributed/versioned configuration,分布式及版本化配置。
  • Service registration and discovery,服務(wù)注冊與發(fā)現(xiàn)。
  • Routing,服務(wù)路由。
  • Service-to-service calls,服務(wù)調(diào)用。
  • Load balancing,負(fù)載均衡。
  • Circuit Breakers,斷路器。
  • Global locks,全局鎖。
  • Leadership election and cluster state,Leader 選舉及集群狀態(tài)。
  • Distributed messaging,分布式消息。

需要注意的是,Spring Cloud 并不是 Spring 團(tuán)隊全新研發(fā)的框架,它只是把一些比較優(yōu)秀的解決微服務(wù)架構(gòu)中常見問題的開源框架基于 Spring Cloud 規(guī)范進(jìn)行了整合,通過 Spring Boot 這個
框架進(jìn)行再次封裝后屏蔽掉了復(fù)雜的配置,給開發(fā)者提供良好的開箱即用的微服務(wù)開發(fā)體驗。不難看出,Spring Cloud 其實就是一套規(guī)范,而 Spring Cloud Netflix、Spring Cloud Consul、Spring CloudAlibaba 才是 Spring Cloud 規(guī)范的實現(xiàn)。

為什么Spring Cloud是基于Spring Boot

那為什么Spring Cloud會采用Spring Boot來作為基礎(chǔ)框架呢?原因很簡單

  1. Spring Cloud它是關(guān)注服務(wù)治理領(lǐng)域的解決方案,而服務(wù)治理是依托于服務(wù)架構(gòu)之上,所以它仍然需要一個承載框架
  2. Spring Boot 可以簡單認(rèn)為它是一套快速配置Spring應(yīng)用的腳手架,它可以快速開發(fā)單個微服務(wù)

在微服務(wù)架構(gòu)下,微服務(wù)節(jié)點越來越多,需要一套成熟高效的腳手架,而Spring Boot正好可以滿足這樣的需求,如下圖所示。

Spring Boot的四大核心機制

如果一定要基于Spring Boot的特性去說,那么只能去說Spring Boot的四大核心機制,分別是@EnableAutoConfiguration 、 Starter開箱即用組件、Actuator應(yīng)用監(jiān)控、Spring Boot CLI 命令行工具。

EnableAutoConfiguration

Starter

告訴Spring Boot需要什么功能,它就能引入需要的庫。

Actuator

讓你能夠深入運行中的Spring Boot應(yīng)用程序

Spring Boot CLI

Spring Boot CLI 為Spring Cloud 提供了Spring Boot 命令行功能。我們可以通過編寫groovy腳本來運行Spring Cloud 組件應(yīng)用程序。步驟如下、

  • 下載spring-boot-cli

    Spring Boot CLI:https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/2.2.6.RELEASE/spring-boot-cli-2.2.6.RELEASE-bin.zip

  • 配置環(huán)境變量

  • 在控制臺spring --version查看CLI版本

  • 使用CLI運行應(yīng)用。我們可以使用run命令編譯和運行Groovy源代碼。Spring Boot CLI中包含所有運行Groovy所需要的依賴。

  • 創(chuàng)建一個hello.groovy文件

    @RestControllerclass HelloController {@GetMapping("/hello")String hello(){    return "Hello World";}}
  • 在控制臺執(zhí)行spring run hello.groovy,如果需要傳遞參數(shù),比如端口,和JVM參數(shù)類似

    spring run hello.groovy -- --server.port=9000

Spring Boot的四大核心特性

  • EnableAutoConfiguration

  • Starter

  • Actuator

  • Spring Boot CLI

    Spring Boot CLI 為Spring Cloud 提供了Spring Boot 命令行功能。我們可以通過編寫groovy腳本來運行Spring Cloud 組件應(yīng)用程序。步驟如下、

    • 下載spring-boot-cli

    Spring Boot CLI:https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/2.2.6.RELEASE/spring-boot-cli-2.2.6.RELEASE-bin.zip

    • 配置環(huán)境變量

    • 在控制臺spring --version查看CLI版本

    • 使用CLI運行應(yīng)用。我們可以使用run命令編譯和運行Groovy源代碼。Spring Boot CLI中包含所有運行Groovy所需要的依賴。

    • 創(chuàng)建一個hello.groovy文件
    @RestControllerclass HelloController {    @GetMapping("/hello")    String hello(){        return "Hello World";    }}
    • 在控制臺執(zhí)行spring run hello.groovy,如果需要傳遞參數(shù),比如端口,和JVM參數(shù)類似
    spring run hello.groovy -- --server.port=9000