springboot 概述
SpringBoot能夠快速開發,簡化部署,適用于微服務
1. 什么是SpringBoot??
SpringBoot是一個基于Spring4而產生的一個微框架;Spring Boot并不是要成為Spring IO平臺里面眾多“Foundation”層項目的替代者。Spring Boot的目標不在于為已解決的問題域提供新的解決方案,而是為平臺帶來另一種開發體驗,從而簡化對這些已有技術的使用。對于已經熟悉Spring生態系統的開發人員來說,Boot是一個很理想的選擇,不過對于采用Spring技術的新人來說,Boot提供一種更簡潔的方式來使用這些技術;SpringBoot也是使用微服務架構的最好選擇。
SpringBoot能解決那些問題?
SpringBoot使編碼更簡單,使配置更簡單,使部署更簡單,使監控更簡單
2.SpringBoot 精要
Spring將很多魔法帶入了Spring應用程序的開發之中,其中最重要的是以下四個核心。
自動配置:針對很多Spring應用程序常見的應用功能,Spring Boot能自動提供相關配置
起步依賴:告訴Spring Boot需要什么功能,它就能引入需要的庫。
命令行界面:這是Spring Boot的可選特性,借此你只需寫代碼就能完成完整的應用程序,無需傳統項目構建。
Actuator:讓你能夠深入運行中的Spring Boot應用程序,一探究竟。
3.SpringBoot能帶給我們什么?
從字面意思理解,Boot是引導,SpringBoot能夠幫助開發者快速搭建Spring框架;
SpringBoot能夠幫助開發者快速啟動一個Web容器;
SpringBoot繼承了Spring框架的原有優秀基因;
SpringBoot簡化了Spring的開發過程;
SpringBoot更多的是使用了Java Config的方式,對Spring進行配置;
SpringBoot更是一個微服務的起點。
配置文件的優先級
application.properties和application.yml文件可以放在以下四個位置(優先級由高到低):
外置,在相對于應用程序運行目錄的/congfig子目錄里。
外置,在應用程序運行的目錄里
內置,在config包內
內置,在Classpath根目錄
同樣,這個列表按照優先級排序,也就是說,src/main/resources/config下application.properties覆蓋src/main/resources下application.properties中相同的屬性,如圖:
此外,如果你在相同優先級位置同時有application.properties和application.yml,那么application.properties里的屬性里面的屬性就會覆蓋application.yml。
Profile-多環境配置
在Spring Boot中多環境配置文件名需要滿足application-{profile}.properties的格式(或者.yml),其中{profile}對應你的環境標識,比如:
application-dev.properties:開發環境
application-pro.properties:生產環境
想要使用對應的環境,只需要在application.properties中使用spring.profiles.active屬性來設置,值對應上面提到的{profile},這里就是指dev、prod這2個。除了spring.profiles.active來激活一個或者多個profile之外,還可以用spring.profiles.include來疊加profile
spring.profiles.active: dev
spring.profiles.include: prodb,promq
除了可以用profile的配置文件來分區配置我們的環境變量,在代碼里,我們還可以直接用@Profile注解來進行配置
啟動原理解析
SpringBoot的啟動類會用到@SpringBootApplication這個注解
@SpringBootApplication由以下三個注解組成:
@Configuration(@SpringBootConfiguration點開查看發現里面還是應用了@Configuration)
@EnableAutoConfiguration
@ComponentScan
?@Configuration
@Configuration就是JavaConfig形式的Spring Ioc容器的配置類使用的那個@Configuration,SpringBoot社區推薦使用基于JavaConfig的配置形式,所以,這里的啟動類標注了@Configuration之后,本身其實也是一個IoC容器的配置類。
XML跟config配置方式的區別:
@ComponentScan
@ComponentScan這個注解在Spring中很重要,它對應XML配置中的元素,@ComponentScan的功能其實就是自動掃描并加載符合條件的組件(比如@Component和@Repository等)或者bean定義,最終將這些bean定義加載到IoC容器中。
我們可以通過basePackages等屬性來細粒度的定制@ComponentScan自動掃描的范圍,如果不指定,則默認Spring框架實現會從聲明@ComponentScan所在類的package進行掃描。
注:所以SpringBoot的啟動類最好是放在root package下,因為默認不指定basePackages。
@EnableAutoConfiguration
@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration的理念和做事方式其實一脈相承,簡單概括一下就是,借助@Import的支持,收集和注冊特定場景相關的bean定義。
@EnableScheduling是通過@Import將Spring調度框架相關的bean定義都加載到IoC容器。
@EnableMBeanExport是通過@Import將JMX相關的bean定義加載到IoC容器。
而@EnableAutoConfiguration也是借助@Import的幫助,將所有符合自動配置條件的bean定義加載到IoC容器,僅此而已!
SpringFactoriesLoader從指定的配置文件META-INF/spring.factories加載配置。配合@EnableAutoConfiguration使用的話,它更多是提供一種配置查找的功能支持,即根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作為查找的Key,獲取對應的一組@Configuration類。? ?
所以,@EnableAutoConfiguration自動配置的魔法騎士就變成了:從classpath中搜尋所有的META-INF/spring.factories配置文件,并將其中org.springframework.boot.autoconfigure.EnableutoConfiguration對應的配置項通過反射(Java Refletion)實例化為對應的標注了@Configuration的JavaConfig形式的IoC容器配置類,然后匯總為一個并加載到IoC容器。
SpringApplication執行流程
SpringApplication的run方法的主要流程大體可以歸納如下:
1) 如果我們使用的是SpringApplication的靜態run方法,那么,這個方法里面首先要創建一個SpringApplication對象實例,然后調用這個創建好的SpringApplication的實例方法。在SpringApplication實例初始化的時候,它會提前做幾件事情:
根據classpath里面是否存在某個特征類(org.springframework.web.context.ConfigurableWebApplicationContext)來決定是否應該創建一個為Web應用使用的ApplicationContext類型。
使用SpringFactoriesLoader在應用的classpath中查找并加載所有可用的ApplicationContextInitializer。
使用SpringFactoriesLoader在應用的classpath中查找并加載所有可用的ApplicationListener。
推斷并設置main方法的定義類。
2) SpringApplication實例初始化完成并且完成設置后,就開始執行run方法的邏輯了,方法執行伊始,首先遍歷執行所有通過SpringFactoriesLoader可以查找到并加載的SpringApplicationRunListener。調用它們的started()方法,告訴這些SpringApplicationRunListener,“嘿,SpringBoot應用要開始執行咯!”。
3) 創建并配置當前Spring Boot應用將要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4) 遍歷調用所有SpringApplicationRunListener的environmentPrepared()的方法,告訴他們:“當前SpringBoot應用使用的Environment準備好了咯!”。
5) 如果SpringApplication的showBanner屬性被設置為true,則打印banner。
6) 根據用戶是否明確設置了applicationContextClass類型以及初始化階段的推斷結果,決定該為當前SpringBoot應用創建什么類型的ApplicationContext并創建完成,然后根據條件決定是否添加ShutdownHook,決定是否使用自定義的BeanNameGenerator,決定是否使用自定義的ResourceLoader,當然,最重要的,將之前準備好的Environment設置給創建好的ApplicationContext使用。
7) ApplicationContext創建好之后,SpringApplication會再次借助Spring-FactoriesLoader,查找并加載classpath中所有可用的ApplicationContext-Initializer,然后遍歷調用這些ApplicationContextInitializer的initialize(applicationContext)方法來對已經創建好的ApplicationContext進行進一步的處理。
8) 遍歷調用所有SpringApplicationRunListener的contextPrepared()方法。
9) 最核心的一步,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置加載到已經準備完畢的ApplicationContext。
10) 遍歷調用所有SpringApplicationRunListener的contextLoaded()方法。
11) 調用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
12) 查找當前ApplicationContext中是否注冊有CommandLineRunner,如果有,則遍歷執行它們。
13) 正常情況下,遍歷執行SpringApplicationRunListener的finished()方法、(如果整個過程出現異常,則依然調用所有SpringApplicationRunListener的finished()方法,只不過這種情況下會將異常信息一并傳入處理)
Spring MVC自動配置
Spring Boot為Spring MVC提供適用于多數應用的自動配置功能。在Spring默認基礎上,自動配置添加了以下特性:
1)引入ContentNegotiatingViewResolver和BeanNameViewResolver beans。
2)對靜態資源的支持,包括對WebJars的支持。
3)自動注冊Converter,GenericConverter,Formatter beans。
4)對HttpMessageConverters的支持。
5)自動注冊MessageCodeResolver。
6)對靜態index.html的支持。
7)對自定義Favicon的支持。
如果想全面控制Spring MVC,你可以添加自己的@Configuration,并使用@EnableWebMvc對其注解。如果想保留Spring Boot MVC的特性,并只是添加其他的MVC配置(攔截器,formatters,視圖控制器等),你可以添加自己的WebMvcConfigurerAdapter類型的@Bean(不使用@EnableWebMvc注解)
默認資源映射
Spring Boot 默認為我們提供了靜態資源處理,使用 WebMvcAutoConfiguration 中的配置各種屬性。
建議大家使用Spring Boot的默認配置方式,提供的靜態資源映射如下(優先級由高到低):
classpath:/META-INF/resources
classpath:/resources
classpath:/static
classpath:/public
可以在上面4個路徑下都放一張同名的圖片,訪問一下即可驗證。
任意在上面一個路徑下面放上index.html,當訪問應用根目錄http://lcoalhost:8080時,會直接映射到index.html頁面。
對應的配置文件配置如下:
# 默認值為 /**
spring.mvc.static-path-pattern=
# 默認值為 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
spring.resources.static-locations=這里設置要指向的路徑,多個使用英文逗號隔開
我們可以通過修改spring.mvc.static-path-pattern來修改默認的映射,例如我改成/dudu/**,那運行的時候訪問?http://lcoalhost:8080/dudu/index.html?才對應到index.html頁面。
自定義資源映射addResourceHandlers
如果Spring Boot提供的Sping MVC不符合要求,則可以通過一個配置類(注解有@Configuration的類)加上@EnableWebMvc注解來實現完全自己控制的MVC配置。
當然,通常情況下,Spring Boot的自動配置是符合我們大多數需求的。在你既需要保留Spring Boot提供的便利,有需要增加自己的額外的配置的時候,可以定義一個配置類并繼承WebMvcConfigurerAdapter,無需使用@EnableWebMvc注解。
比如,我們想自定義靜態資源映射目錄的話,只需重寫addResourceHandlers方法即可。
通過addResourceHandler添加映射路徑,然后通過addResourceLocations來指定路徑。我們訪問自定義my文件夾中的elephant.jpg 圖片的地址為?http://localhost:8080/my/elephant.jpg
如果想指定外部的目錄也很簡單,直接addResourceLocations指定即可,代碼如下:
攔截器addInterceptors
要實現攔截器功能需要完成以下2個步驟:
1.創建我們自己的攔截器類并實現 HandlerInterceptor 接口
2.重寫WebMvcConfigurerAdapter中的addInterceptors方法把自定義的攔截器類添加進
首先,自定義攔截器代碼:
接著,重寫WebMvcConfigurerAdapter中的addInterceptors方法如下:
默認日志Logback
Logback是log4j框架的作者開發的新一代日志框架,它效率更高、能夠適應諸多的運行環境,同時天然支持SLF4J。
假如maven依賴中添加了spring-boot-starter-logging:
那么,我們的Spring Boot應用將自動使用logback作為應用日志框架
(但是呢,實際開發中我們不需要直接添加該依賴,你會發現spring-boot-starter其中包含了 spring-boot-starter-logging,該依賴內容就是 Spring Boot 默認的日志框架 logback。而Thymeleaf依賴包含了spring-boot-starter,最終我只要引入Thymeleaf即可)
文件輸出
默認情況下,Spring Boot將日志輸出到控制臺,不會寫到日志文件。如果要編寫除控制臺輸出之外的日志文件,則需在application.properties中設置logging.file或logging.path屬性。
logging.file,設置文件,可以是絕對路徑,也可以是相對路徑。如:logging.file=my.log
logging.path,設置目錄,會在該目錄下創建spring.log文件,并寫入日志內容,如:logging.path=/var/log
如果只配置 logging.file,會在項目的當前路徑下生成一個 xxx.log 日志文件。
如果只配置 logging.path,在 /var/log文件夾生成一個日志文件為 spring.log
注:二者不能同時使用,如若同時使用,則只有logging.file生效
JdbcTemplate的使用
這里需要添加spring-boot-starter-jdbc依賴跟mysql依賴
在src/main/resources/application.properties中配置數據源信息。
Spring的JdbcTemplate是自動配置的,你可以直接使用@Autowired來注入到你自己的bean中來使用。
在dao層的實現類,注入我們需要的JdbcTemplate。
MyBatis的使用
添加mybatis-spring-boot-starter依賴跟mysql依賴,mybatis-spring-boot-starter中已經包含了Jdbc依賴
MyBatis-Spring-Boot-Starter依賴將會提供如下:
自動檢測現有的DataSource
將創建并注冊SqlSessionFactory的實例,該實例使用SqlSessionFactoryBean將該DataSource作為輸入進行傳遞
將創建并注冊從SqlSessionFactory中獲取的SqlSessionTemplate的實例。
自動掃描您的mappers,將它們鏈接到SqlSessionTemplate并將其注冊到Spring上下文,以便將它們注入到您的bean中。
就是說,使用了該Starter之后,只需要定義一個DataSource即可(application.properties中可配置),它會自動創建使用該DataSource的SqlSessionFactoryBean以及SqlSessionTemplate。會自動掃描你的Mappers,連接到SqlSessionTemplate,并注冊到Spring上下文中。
注解方式(xml方式省略)
Mybatis注解的方式好簡單,只要定義一個dao接口,然后sql語句通過注解寫在接口方法上。最后給這個接口添加@Mapper注解或者在啟動類上添加@MapperScan(“com.dudu.dao”)注解都行。
這些可選的 SQL 注解允許你指定一個類名和一個方法在執行時來返回運行 允許創建動態 的 SQL。 基于執行的映射語句, MyBatis 會實例化這個類,然后執行由 provider 指定的方法. 該方法可以有選擇地接受參數對象.(In MyBatis 3.4 or later, it’s allow multiple parameters) 屬性: type,method。type 屬性是類。method 屬性是方法名。 注意: 這節之后是對 類的 討論,它可以幫助你以干凈,容于閱讀 的方式來構建動態 SQL。
通用Mapper插件
引入了mybatis相關的一些依賴以及generator的配置,這里generator配置文件指向src/main/resources/mybatis-generator.xml文件,mybatis-generator.xml文件用來自動生成表對應的Model,Mapper以及xml,一會兒會提到。(Mybatis Geneator 詳解)
通用Mapper都可以極大的方便開發人員,對單表封裝了許多通用方法,省掉自己寫增刪改查的sql。(通用Mapper插件網址)
對應的application.properties配置:
這里實現一個自己的接口,繼承通用的mapper,關鍵點就是這個接口不能被掃描到,mapper接口不能放在dao包里。
最后在啟動類中通過MapperScan注解指定掃描的mapper路徑(dao)
IDEA自動生成文件的方法:
根據mybatis-generator.xml文件,自動生成model,mapper,xml文件
MyBatis分頁插件
物理分頁插件pagehelper,引入依賴
只需在查詢list之前使用PageHelper.startPage(int pageNum, int pageSize)方法即可。pageNum是第幾頁,pageSize是每頁多少條。
業務邏輯層(service)的實現
正常情況下具體業務是每個模塊的service里面定義許多方法,然后mapper中實現。
但通用Mapper在Spring4中的最佳用法是通用的Service(具體了解)
定義一個通用接口:
具體實現通用接口類
到此基本的增刪改查通用service就寫好了,具體業務的service就直接繼承這個接口即可,也可以添加額外的方法
具體實現service(實現類extends BaseService),然后再mapper文件中(我覺得相當于dao)實現sevice自定義的方法。
在自動生成的xml文件中實現具體方法(相當于dao的實現類):
Spring Loaded 實現熱部署
Spring Loaded是一個用于在JVM運行時重新加載類文件更改的JVM代理,Spring Loaded允許你動態的新增/修改/刪除某個方法/字段/構造方法,同樣可以修改作用在類/方法/字段/構造方法上的注解.也可以新增/刪除/改變枚舉中的值。
Spring Loaded有兩種方式實現,分別是Maven引入依賴方式或者添加啟動參數方式
Maven依賴方式
如果用IDEA也可以這樣啟動
注意:maven依賴的方式只適合spring-boot:run的啟動方式,右鍵那種方式不行。
出現這個說明配置成功
[INFO] Attaching agents: [C:\Users\tengj\.m2\repository\org\springframework\springloaded\1.2.6.RELEASE\springloaded-1.2.6.RELEASE.jar]
還有種方式是右鍵運行啟動類
首先先下載對應的springloaded-1.2.6.RELEASE.jar,可以去上面提到的官網獲取(這里直接引用maven依賴已經下載好的路徑)
然后打開下圖所示的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種方式隨便選擇一種即可,當系統通過 mvn spring-boot:run啟動或者 右鍵application debug啟動Java文件時,系統會監視classes文件,當有classes文件被改動時,系統會重新加載類文件,不用重啟啟動服務。(注:IDEA下需要重新編譯文件 Ctrl+Shift+F9或者編譯項目 Ctrl+F9 )
還可以使用spring-boot-devtools 方式、JRebel插件方式實現熱部署
經過簡單的測試,發現大多數情況可以使用熱部署,不過還是有一些情況下需要重新啟動,不可用的情況如下:
1:對于一些第三方框架的注解的修改,不能自動加載,比如:spring mvc的@RequestMapping?
2:application.properties的修改也不行?
3:log4j的配置文件的修改不能即時生
單元測試
Spring Boot中單元測試類寫在在src/test/java目錄下,你可以手動創建具體測試類,如果是IDEA,則可以通過IDEA自動創建測試類
最簡單的單元測試寫法(Service層),頂部只要@RunWith(SpringRunner.class)和SpringBootTest即可,想要執行的時候,鼠標放在對應的方法,右鍵選擇run該方法即可。推薦大家使用該assertThat斷言。
有時候需要對Controller層(API)做測試,這時候就得用到MockMvc了,你可以不必啟動工程就能測試這些接口。MockMvc實現了對Http請求的模擬,能夠直接使用網絡的形式,轉換到Controller的調用,這樣可以使得測試速度快、不依賴網絡環境,而且提供了一套驗證的工具,這樣可以使得請求的驗證統一而且很方便。
使用MockMvc的時候需要先用MockMvcBuilders使用構建MockMvc對象,如下
MockMvc簡單的方法
1. mockMvc.perform執行一個請求
2. MockMvcRequestBuilders.get(“/user/1”)構造一個請求,Post請求就用.post方法
3. contentType(MediaType.APPLICATION_JSON_UTF8)代表發送端發送的數據格式是application/json;charset=UTF-8
4. accept(MediaType.APPLICATION_JSON_UTF8)代表客戶端希望接受的數據類型為application/json;charset=UTF-8
5. session(session)注入一個session,這樣攔截器才可以通過
6. ResultActions.andExpect添加執行完成后的斷言
7. ResultActions.andExpect(MockMvcResultMatchers.status().isOk())方法看請求的狀態響應碼是否為200如果不是則拋異常,測試不通過
8. andExpect(MockMvcResultMatchers.jsonPath(“$.author”).value(“嘟嘟MD獨立博客”))這里jsonPath用來獲取author字段比對是否為嘟嘟? ? ? MD獨立博客,不是就測試不通過
9. ResultActions.andDo添加一個結果處理器,表示要對結果做點什么事情,比如此處使用MockMvcResultHandlers.print()輸出整個響應結果信息
新斷言assertThat使用
JUnit 4.4 結合 Hamcrest 提供了一個全新的斷言語法——assertThat。只使用 assertThat 一個斷言語句,結合 Hamcrest 提供的匹配符,就可以表達全部的測試思想,。 JUnit 4.4 默認提供一些可讀的描述性錯誤信息
使用asserThat的兩個例子:
1.? assertThat( [value], [matcher statement] );
2.? assertThat(s, anyOf(containsString("a"), containsString("b")));? ? //表示s里面是否包含“”“a”或者“”“b”
單元測試回滾
單元個測試的時候如果不想造成垃圾數據,可以開啟事物功能,記在方法或者類頭部添加@Transactional注解即可,如下:
這樣測試完數據就會回滾了,不會造成垃圾數據。如果想關閉回滾,只要加上@Rollback(false)注解即可。傳入一個參數value,默認true即回滾,false不回滾。如果你使用的數據庫是Mysql,有時候會發現加了注解@Transactional?也不會回滾,那么你就要查看一下你的默認引擎是不是InnoDB,如果不是就要改成InnoDB,如下圖:
微服務
微服務是一種細粒度的SOA(面向服務架構)
SOA特性: 面向服務? ?松耦合? 模塊化? ?分布式計算? 平臺無關性? ?集中管理