springboot 概述
SpringBoot能夠快速開發(fā),簡化部署,適用于微服務(wù)
1. 什么是SpringBoot??
SpringBoot是一個基于Spring4而產(chǎn)生的一個微框架;Spring Boot并不是要成為Spring IO平臺里面眾多“Foundation”層項目的替代者。Spring Boot的目標(biāo)不在于為已解決的問題域提供新的解決方案,而是為平臺帶來另一種開發(fā)體驗,從而簡化對這些已有技術(shù)的使用。對于已經(jīng)熟悉Spring生態(tài)系統(tǒng)的開發(fā)人員來說,Boot是一個很理想的選擇,不過對于采用Spring技術(shù)的新人來說,Boot提供一種更簡潔的方式來使用這些技術(shù);SpringBoot也是使用微服務(wù)架構(gòu)的最好選擇。
SpringBoot能解決那些問題?
SpringBoot使編碼更簡單,使配置更簡單,使部署更簡單,使監(jiān)控更簡單
2.SpringBoot 精要
Spring將很多魔法帶入了Spring應(yīng)用程序的開發(fā)之中,其中最重要的是以下四個核心。
自動配置:針對很多Spring應(yīng)用程序常見的應(yīng)用功能,Spring Boot能自動提供相關(guān)配置
起步依賴:告訴Spring Boot需要什么功能,它就能引入需要的庫。
命令行界面:這是Spring Boot的可選特性,借此你只需寫代碼就能完成完整的應(yīng)用程序,無需傳統(tǒng)項目構(gòu)建。
Actuator:讓你能夠深入運行中的Spring Boot應(yīng)用程序,一探究竟。
3.SpringBoot能帶給我們什么?
從字面意思理解,Boot是引導(dǎo),SpringBoot能夠幫助開發(fā)者快速搭建Spring框架;
SpringBoot能夠幫助開發(fā)者快速啟動一個Web容器;
SpringBoot繼承了Spring框架的原有優(yōu)秀基因;
SpringBoot簡化了Spring的開發(fā)過程;
SpringBoot更多的是使用了Java Config的方式,對Spring進行配置;
SpringBoot更是一個微服務(wù)的起點。
配置文件的優(yōu)先級
application.properties和application.yml文件可以放在以下四個位置(優(yōu)先級由高到低):
外置,在相對于應(yīng)用程序運行目錄的/congfig子目錄里。
外置,在應(yīng)用程序運行的目錄里
內(nèi)置,在config包內(nèi)
內(nèi)置,在Classpath根目錄
同樣,這個列表按照優(yōu)先級排序,也就是說,src/main/resources/config下application.properties覆蓋src/main/resources下application.properties中相同的屬性,如圖:

此外,如果你在相同優(yōu)先級位置同時有application.properties和application.yml,那么application.properties里的屬性里面的屬性就會覆蓋application.yml。
Profile-多環(huán)境配置
在Spring Boot中多環(huán)境配置文件名需要滿足application-{profile}.properties的格式(或者.yml),其中{profile}對應(yīng)你的環(huán)境標(biāo)識,比如:
application-dev.properties:開發(fā)環(huán)境
application-pro.properties:生產(chǎn)環(huán)境
想要使用對應(yīng)的環(huán)境,只需要在application.properties中使用spring.profiles.active屬性來設(shè)置,值對應(yīng)上面提到的{profile},這里就是指dev、prod這2個。除了spring.profiles.active來激活一個或者多個profile之外,還可以用spring.profiles.include來疊加profile
spring.profiles.active: dev
spring.profiles.include: prodb,promq
除了可以用profile的配置文件來分區(qū)配置我們的環(huán)境變量,在代碼里,我們還可以直接用@Profile注解來進行配置
啟動原理解析
SpringBoot的啟動類會用到@SpringBootApplication這個注解
@SpringBootApplication由以下三個注解組成:
@Configuration(@SpringBootConfiguration點開查看發(fā)現(xiàn)里面還是應(yīng)用了@Configuration)
@EnableAutoConfiguration
@ComponentScan
?@Configuration
@Configuration就是JavaConfig形式的Spring Ioc容器的配置類使用的那個@Configuration,SpringBoot社區(qū)推薦使用基于JavaConfig的配置形式,所以,這里的啟動類標(biāo)注了@Configuration之后,本身其實也是一個IoC容器的配置類。
XML跟config配置方式的區(qū)別:



@ComponentScan
@ComponentScan這個注解在Spring中很重要,它對應(yīng)XML配置中的元素,@ComponentScan的功能其實就是自動掃描并加載符合條件的組件(比如@Component和@Repository等)或者bean定義,最終將這些bean定義加載到IoC容器中。
我們可以通過basePackages等屬性來細粒度的定制@ComponentScan自動掃描的范圍,如果不指定,則默認Spring框架實現(xiàn)會從聲明@ComponentScan所在類的package進行掃描。
注:所以SpringBoot的啟動類最好是放在root package下,因為默認不指定basePackages。
@EnableAutoConfiguration
@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration的理念和做事方式其實一脈相承,簡單概括一下就是,借助@Import的支持,收集和注冊特定場景相關(guān)的bean定義。
@EnableScheduling是通過@Import將Spring調(diào)度框架相關(guān)的bean定義都加載到IoC容器。
@EnableMBeanExport是通過@Import將JMX相關(guān)的bean定義加載到IoC容器。
而@EnableAutoConfiguration也是借助@Import的幫助,將所有符合自動配置條件的bean定義加載到IoC容器,僅此而已!

SpringFactoriesLoader從指定的配置文件META-INF/spring.factories加載配置。配合@EnableAutoConfiguration使用的話,它更多是提供一種配置查找的功能支持,即根據(jù)@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作為查找的Key,獲取對應(yīng)的一組@Configuration類。? ?
所以,@EnableAutoConfiguration自動配置的魔法騎士就變成了:從classpath中搜尋所有的META-INF/spring.factories配置文件,并將其中org.springframework.boot.autoconfigure.EnableutoConfiguration對應(yīng)的配置項通過反射(Java Refletion)實例化為對應(yīng)的標(biāo)注了@Configuration的JavaConfig形式的IoC容器配置類,然后匯總為一個并加載到IoC容器。
SpringApplication執(zhí)行流程
SpringApplication的run方法的主要流程大體可以歸納如下:
1) 如果我們使用的是SpringApplication的靜態(tài)run方法,那么,這個方法里面首先要創(chuàng)建一個SpringApplication對象實例,然后調(diào)用這個創(chuàng)建好的SpringApplication的實例方法。在SpringApplication實例初始化的時候,它會提前做幾件事情:
根據(jù)classpath里面是否存在某個特征類(org.springframework.web.context.ConfigurableWebApplicationContext)來決定是否應(yīng)該創(chuàng)建一個為Web應(yīng)用使用的ApplicationContext類型。
使用SpringFactoriesLoader在應(yīng)用的classpath中查找并加載所有可用的ApplicationContextInitializer。
使用SpringFactoriesLoader在應(yīng)用的classpath中查找并加載所有可用的ApplicationListener。
推斷并設(shè)置main方法的定義類。
2) SpringApplication實例初始化完成并且完成設(shè)置后,就開始執(zhí)行run方法的邏輯了,方法執(zhí)行伊始,首先遍歷執(zhí)行所有通過SpringFactoriesLoader可以查找到并加載的SpringApplicationRunListener。調(diào)用它們的started()方法,告訴這些SpringApplicationRunListener,“嘿,SpringBoot應(yīng)用要開始執(zhí)行咯!”。
3) 創(chuàng)建并配置當(dāng)前Spring Boot應(yīng)用將要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4) 遍歷調(diào)用所有SpringApplicationRunListener的environmentPrepared()的方法,告訴他們:“當(dāng)前SpringBoot應(yīng)用使用的Environment準(zhǔn)備好了咯!”。
5) 如果SpringApplication的showBanner屬性被設(shè)置為true,則打印banner。
6) 根據(jù)用戶是否明確設(shè)置了applicationContextClass類型以及初始化階段的推斷結(jié)果,決定該為當(dāng)前SpringBoot應(yīng)用創(chuàng)建什么類型的ApplicationContext并創(chuàng)建完成,然后根據(jù)條件決定是否添加ShutdownHook,決定是否使用自定義的BeanNameGenerator,決定是否使用自定義的ResourceLoader,當(dāng)然,最重要的,將之前準(zhǔn)備好的Environment設(shè)置給創(chuàng)建好的ApplicationContext使用。
7) ApplicationContext創(chuàng)建好之后,SpringApplication會再次借助Spring-FactoriesLoader,查找并加載classpath中所有可用的ApplicationContext-Initializer,然后遍歷調(diào)用這些ApplicationContextInitializer的initialize(applicationContext)方法來對已經(jīng)創(chuàng)建好的ApplicationContext進行進一步的處理。
8) 遍歷調(diào)用所有SpringApplicationRunListener的contextPrepared()方法。
9) 最核心的一步,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置加載到已經(jīng)準(zhǔn)備完畢的ApplicationContext。
10) 遍歷調(diào)用所有SpringApplicationRunListener的contextLoaded()方法。
11) 調(diào)用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
12) 查找當(dāng)前ApplicationContext中是否注冊有CommandLineRunner,如果有,則遍歷執(zhí)行它們。
13) 正常情況下,遍歷執(zhí)行SpringApplicationRunListener的finished()方法、(如果整個過程出現(xiàn)異常,則依然調(diào)用所有SpringApplicationRunListener的finished()方法,只不過這種情況下會將異常信息一并傳入處理)
Spring MVC自動配置
Spring Boot為Spring MVC提供適用于多數(shù)應(yīng)用的自動配置功能。在Spring默認基礎(chǔ)上,自動配置添加了以下特性:
1)引入ContentNegotiatingViewResolver和BeanNameViewResolver beans。
2)對靜態(tài)資源的支持,包括對WebJars的支持。
3)自動注冊Converter,GenericConverter,F(xiàn)ormatter beans。
4)對HttpMessageConverters的支持。
5)自動注冊MessageCodeResolver。
6)對靜態(tài)index.html的支持。
7)對自定義Favicon的支持。
如果想全面控制Spring MVC,你可以添加自己的@Configuration,并使用@EnableWebMvc對其注解。如果想保留Spring Boot MVC的特性,并只是添加其他的MVC配置(攔截器,formatters,視圖控制器等),你可以添加自己的WebMvcConfigurerAdapter類型的@Bean(不使用@EnableWebMvc注解)
默認資源映射
Spring Boot 默認為我們提供了靜態(tài)資源處理,使用 WebMvcAutoConfiguration 中的配置各種屬性。
建議大家使用Spring Boot的默認配置方式,提供的靜態(tài)資源映射如下(優(yōu)先級由高到低):
classpath:/META-INF/resources
classpath:/resources
classpath:/static
classpath:/public

可以在上面4個路徑下都放一張同名的圖片,訪問一下即可驗證。
任意在上面一個路徑下面放上index.html,當(dāng)訪問應(yīng)用根目錄http://lcoalhost:8080時,會直接映射到index.html頁面。
對應(yīng)的配置文件配置如下:
# 默認值為 /**
spring.mvc.static-path-pattern=
# 默認值為 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
spring.resources.static-locations=這里設(shè)置要指向的路徑,多個使用英文逗號隔開
我們可以通過修改spring.mvc.static-path-pattern來修改默認的映射,例如我改成/dudu/**,那運行的時候訪問?http://lcoalhost:8080/dudu/index.html?才對應(yīng)到index.html頁面。
自定義資源映射addResourceHandlers
如果Spring Boot提供的Sping MVC不符合要求,則可以通過一個配置類(注解有@Configuration的類)加上@EnableWebMvc注解來實現(xiàn)完全自己控制的MVC配置。
當(dāng)然,通常情況下,Spring Boot的自動配置是符合我們大多數(shù)需求的。在你既需要保留Spring Boot提供的便利,有需要增加自己的額外的配置的時候,可以定義一個配置類并繼承WebMvcConfigurerAdapter,無需使用@EnableWebMvc注解。
比如,我們想自定義靜態(tài)資源映射目錄的話,只需重寫addResourceHandlers方法即可。

通過addResourceHandler添加映射路徑,然后通過addResourceLocations來指定路徑。我們訪問自定義my文件夾中的elephant.jpg 圖片的地址為?http://localhost:8080/my/elephant.jpg
如果想指定外部的目錄也很簡單,直接addResourceLocations指定即可,代碼如下:

攔截器addInterceptors
要實現(xiàn)攔截器功能需要完成以下2個步驟:
1.創(chuàng)建我們自己的攔截器類并實現(xiàn) HandlerInterceptor 接口
2.重寫WebMvcConfigurerAdapter中的addInterceptors方法把自定義的攔截器類添加進
首先,自定義攔截器代碼:

接著,重寫WebMvcConfigurerAdapter中的addInterceptors方法如下:

默認日志Logback
Logback是log4j框架的作者開發(fā)的新一代日志框架,它效率更高、能夠適應(yīng)諸多的運行環(huán)境,同時天然支持SLF4J。
假如maven依賴中添加了spring-boot-starter-logging:

那么,我們的Spring Boot應(yīng)用將自動使用logback作為應(yīng)用日志框架
(但是呢,實際開發(fā)中我們不需要直接添加該依賴,你會發(fā)現(xiàn)spring-boot-starter其中包含了 spring-boot-starter-logging,該依賴內(nèi)容就是 Spring Boot 默認的日志框架 logback。而Thymeleaf依賴包含了spring-boot-starter,最終我只要引入Thymeleaf即可)
文件輸出
默認情況下,Spring Boot將日志輸出到控制臺,不會寫到日志文件。如果要編寫除控制臺輸出之外的日志文件,則需在application.properties中設(shè)置logging.file或logging.path屬性。
logging.file,設(shè)置文件,可以是絕對路徑,也可以是相對路徑。如:logging.file=my.log
logging.path,設(shè)置目錄,會在該目錄下創(chuàng)建spring.log文件,并寫入日志內(nèi)容,如:logging.path=/var/log
如果只配置 logging.file,會在項目的當(dāng)前路徑下生成一個 xxx.log 日志文件。
如果只配置 logging.path,在 /var/log文件夾生成一個日志文件為 spring.log
注:二者不能同時使用,如若同時使用,則只有l(wèi)ogging.file生效
JdbcTemplate的使用
這里需要添加spring-boot-starter-jdbc依賴跟mysql依賴

在src/main/resources/application.properties中配置數(shù)據(jù)源信息。

Spring的JdbcTemplate是自動配置的,你可以直接使用@Autowired來注入到你自己的bean中來使用。
在dao層的實現(xiàn)類,注入我們需要的JdbcTemplate。

MyBatis的使用
添加mybatis-spring-boot-starter依賴跟mysql依賴,mybatis-spring-boot-starter中已經(jīng)包含了Jdbc依賴

MyBatis-Spring-Boot-Starter依賴將會提供如下:
自動檢測現(xiàn)有的DataSource
將創(chuàng)建并注冊SqlSessionFactory的實例,該實例使用SqlSessionFactoryBean將該DataSource作為輸入進行傳遞
將創(chuàng)建并注冊從SqlSessionFactory中獲取的SqlSessionTemplate的實例。
自動掃描您的mappers,將它們鏈接到SqlSessionTemplate并將其注冊到Spring上下文,以便將它們注入到您的bean中。
就是說,使用了該Starter之后,只需要定義一個DataSource即可(application.properties中可配置),它會自動創(chuàng)建使用該DataSource的SqlSessionFactoryBean以及SqlSessionTemplate。會自動掃描你的Mappers,連接到SqlSessionTemplate,并注冊到Spring上下文中。
注解方式(xml方式省略)
Mybatis注解的方式好簡單,只要定義一個dao接口,然后sql語句通過注解寫在接口方法上。最后給這個接口添加@Mapper注解或者在啟動類上添加@MapperScan(“com.dudu.dao”)注解都行。


這些可選的 SQL 注解允許你指定一個類名和一個方法在執(zhí)行時來返回運行 允許創(chuàng)建動態(tài) 的 SQL。 基于執(zhí)行的映射語句, MyBatis 會實例化這個類,然后執(zhí)行由 provider 指定的方法. 該方法可以有選擇地接受參數(shù)對象.(In MyBatis 3.4 or later, it’s allow multiple parameters) 屬性: type,method。type 屬性是類。method 屬性是方法名。 注意: 這節(jié)之后是對 類的 討論,它可以幫助你以干凈,容于閱讀 的方式來構(gòu)建動態(tài) SQL。
通用Mapper插件
引入了mybatis相關(guān)的一些依賴以及generator的配置,這里generator配置文件指向src/main/resources/mybatis-generator.xml文件,mybatis-generator.xml文件用來自動生成表對應(yīng)的Model,Mapper以及xml,一會兒會提到。(Mybatis Geneator 詳解)

通用Mapper都可以極大的方便開發(fā)人員,對單表封裝了許多通用方法,省掉自己寫增刪改查的sql。(通用Mapper插件網(wǎng)址)
對應(yīng)的application.properties配置:

這里實現(xiàn)一個自己的接口,繼承通用的mapper,關(guān)鍵點就是這個接口不能被掃描到,mapper接口不能放在dao包里。
最后在啟動類中通過MapperScan注解指定掃描的mapper路徑(dao)

IDEA自動生成文件的方法:

根據(jù)mybatis-generator.xml文件,自動生成model,mapper,xml文件

MyBatis分頁插件
物理分頁插件pagehelper,引入依賴

只需在查詢list之前使用PageHelper.startPage(int pageNum, int pageSize)方法即可。pageNum是第幾頁,pageSize是每頁多少條。

業(yè)務(wù)邏輯層(service)的實現(xiàn)
正常情況下具體業(yè)務(wù)是每個模塊的service里面定義許多方法,然后mapper中實現(xiàn)。
但通用Mapper在Spring4中的最佳用法是通用的Service(具體了解)
定義一個通用接口:

具體實現(xiàn)通用接口類

到此基本的增刪改查通用service就寫好了,具體業(yè)務(wù)的service就直接繼承這個接口即可,也可以添加額外的方法

具體實現(xiàn)service(實現(xiàn)類extends BaseService),然后再mapper文件中(我覺得相當(dāng)于dao)實現(xiàn)sevice自定義的方法。

在自動生成的xml文件中實現(xiàn)具體方法(相當(dāng)于dao的實現(xiàn)類):

Spring Loaded 實現(xiàn)熱部署
Spring Loaded是一個用于在JVM運行時重新加載類文件更改的JVM代理,Spring Loaded允許你動態(tài)的新增/修改/刪除某個方法/字段/構(gòu)造方法,同樣可以修改作用在類/方法/字段/構(gòu)造方法上的注解.也可以新增/刪除/改變枚舉中的值。
Spring Loaded有兩種方式實現(xiàn),分別是Maven引入依賴方式或者添加啟動參數(shù)方式
Maven依賴方式

如果用IDEA也可以這樣啟動

注意:maven依賴的方式只適合spring-boot:run的啟動方式,右鍵那種方式不行。
出現(xiàn)這個說明配置成功
[INFO] Attaching agents: [C:\Users\tengj\.m2\repository\org\springframework\springloaded\1.2.6.RELEASE\springloaded-1.2.6.RELEASE.jar]
還有種方式是右鍵運行啟動類
首先先下載對應(yīng)的springloaded-1.2.6.RELEASE.jar,可以去上面提到的官網(wǎng)獲?。ㄟ@里直接引用maven依賴已經(jīng)下載好的路徑)
然后打開下圖所示的Edit Configurations配置,在VM options中輸入:
-javaagent:C:\Users\tengj\.m2\repository\org\springframework\springloaded\1.2.6.RELEASE\springloaded-1.2.6.RELEASE.jar -noverify
上面2種方式隨便選擇一種即可,當(dāng)系統(tǒng)通過 mvn spring-boot:run啟動或者 右鍵application debug啟動Java文件時,系統(tǒng)會監(jiān)視classes文件,當(dāng)有classes文件被改動時,系統(tǒng)會重新加載類文件,不用重啟啟動服務(wù)。(注:IDEA下需要重新編譯文件 Ctrl+Shift+F9或者編譯項目 Ctrl+F9 )
還可以使用spring-boot-devtools 方式、JRebel插件方式實現(xiàn)熱部署
經(jīng)過簡單的測試,發(fā)現(xiàn)大多數(shù)情況可以使用熱部署,不過還是有一些情況下需要重新啟動,不可用的情況如下:
1:對于一些第三方框架的注解的修改,不能自動加載,比如:spring mvc的@RequestMapping?
2:application.properties的修改也不行?
3:log4j的配置文件的修改不能即時生
單元測試
Spring Boot中單元測試類寫在在src/test/java目錄下,你可以手動創(chuàng)建具體測試類,如果是IDEA,則可以通過IDEA自動創(chuàng)建測試類
最簡單的單元測試寫法(Service層),頂部只要@RunWith(SpringRunner.class)和SpringBootTest即可,想要執(zhí)行的時候,鼠標(biāo)放在對應(yīng)的方法,右鍵選擇run該方法即可。推薦大家使用該assertThat斷言。
有時候需要對Controller層(API)做測試,這時候就得用到MockMvc了,你可以不必啟動工程就能測試這些接口。MockMvc實現(xiàn)了對Http請求的模擬,能夠直接使用網(wǎng)絡(luò)的形式,轉(zhuǎn)換到Controller的調(diào)用,這樣可以使得測試速度快、不依賴網(wǎng)絡(luò)環(huán)境,而且提供了一套驗證的工具,這樣可以使得請求的驗證統(tǒng)一而且很方便。
使用MockMvc的時候需要先用MockMvcBuilders使用構(gòu)建MockMvc對象,如下

MockMvc簡單的方法

1. mockMvc.perform執(zhí)行一個請求
2. MockMvcRequestBuilders.get(“/user/1”)構(gòu)造一個請求,Post請求就用.post方法
3. contentType(MediaType.APPLICATION_JSON_UTF8)代表發(fā)送端發(fā)送的數(shù)據(jù)格式是application/json;charset=UTF-8
4. accept(MediaType.APPLICATION_JSON_UTF8)代表客戶端希望接受的數(shù)據(jù)類型為application/json;charset=UTF-8
5. session(session)注入一個session,這樣攔截器才可以通過
6. ResultActions.andExpect添加執(zhí)行完成后的斷言
7. ResultActions.andExpect(MockMvcResultMatchers.status().isOk())方法看請求的狀態(tài)響應(yīng)碼是否為200如果不是則拋異常,測試不通過
8. andExpect(MockMvcResultMatchers.jsonPath(“$.author”).value(“嘟嘟MD獨立博客”))這里jsonPath用來獲取author字段比對是否為嘟嘟? ? ? MD獨立博客,不是就測試不通過
9. ResultActions.andDo添加一個結(jié)果處理器,表示要對結(jié)果做點什么事情,比如此處使用MockMvcResultHandlers.print()輸出整個響應(yīng)結(jié)果信息
新斷言assertThat使用
JUnit 4.4 結(jié)合 Hamcrest 提供了一個全新的斷言語法——assertThat。只使用 assertThat 一個斷言語句,結(jié)合 Hamcrest 提供的匹配符,就可以表達全部的測試思想,。 JUnit 4.4 默認提供一些可讀的描述性錯誤信息
使用asserThat的兩個例子:
1.? assertThat( [value], [matcher statement] );
2.? assertThat(s, anyOf(containsString("a"), containsString("b")));? ? //表示s里面是否包含“”“a”或者“”“b”
單元測試回滾
單元個測試的時候如果不想造成垃圾數(shù)據(jù),可以開啟事物功能,記在方法或者類頭部添加@Transactional注解即可,如下:

這樣測試完數(shù)據(jù)就會回滾了,不會造成垃圾數(shù)據(jù)。如果想關(guān)閉回滾,只要加上@Rollback(false)注解即可。傳入一個參數(shù)value,默認true即回滾,false不回滾。如果你使用的數(shù)據(jù)庫是Mysql,有時候會發(fā)現(xiàn)加了注解@Transactional?也不會回滾,那么你就要查看一下你的默認引擎是不是InnoDB,如果不是就要改成InnoDB,如下圖:

微服務(wù)
微服務(wù)是一種細粒度的SOA(面向服務(wù)架構(gòu))
SOA特性: 面向服務(wù)? ?松耦合? 模塊化? ?分布式計算? 平臺無關(guān)性? ?集中管理