基礎篇 SpringBoot基礎入門
1.1 SpringBoot入門
1.1.1 系統要求
- Java8+
- Maven3.3+
- idea2019.2+
1.1.2 maven設定
- 配置為阿里云的倉庫
- 設定jdk版本為1.8
1.1.3 SpringBoot常見注解
@RequestMapping:映射請求,
@ResponseBody:表明回傳的是字串,而不是跳轉頁面,
@RestController:輕量級的標注,為@ResponseBody和@RequestMapping的合體,
1.1.4 創建SpringBoot專案
- 創建maven專案
- 匯入父工程
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
</parent>
- 添加場景依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 寫主程式,在主程式上標注 @SpringBootApplication,表示這是一個SpringBoot應用,在主程式中運用run()把應用跑起來
@SpringBootApplication
public static void main(String[] args) {
SpringApplication.run(Example.class, args);
}
- 撰寫業務
- 測驗
- 簡化配置,所有的配置內容,都可以在application.properties中配置,
server.port=8080
- 簡化部署【添加插件】,把專案打成jar包,直接在目標服務器運行,
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
1.2 了解自動配置
1.2.1 依賴管理
- 父專案做依賴管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
</parent>
- 開發匯入starter場景啟動器
1.spring-boot-starter-*表示各種型別的場景,
2.只要引入starter,這個場景的各種依賴我們都能自動引入,
3.SpringBoot支持的各種場景:https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/using-spring-boot.html#using-boot-starter
4.見到的*-spring-boot-starter-*為第三方的場景,
- 無需關注版本,自動仲裁版本【引入依賴基本不用寫版本號,但引入非版本仲裁的要寫版本號】,
- 可以自定義依賴版本號,在pom.xml中修改< properties><\properties>,
1.2.2 自動配置
- 自動配好Tomcat,
1.引入Tomcat組件
2.自動配好Tomcat依賴
- 自動配好SpringMVC,
1.引入SpringMVC全套組件
2.自動配好SpringMVC常用組件
- 自動配好Web常見功能,如:字符編碼問題,
- 默認的包結構,
1.主程式下所在包下及其下的所有子包里面的組件都會被默認掃描,以前的包掃描不用配置,
2.若想掃描主程式之上的包則需要如下配置:@SpringBootApplication(scanBasePackages="xxx.xxx")或通過@Component("xxx.xxx"),
- 各種配置擁有默認值
- 按需加載各種配置項
非常多的starter
引入哪個場景這個場景的自動配置才會開啟
SpringBoot的所有自動配置功能都在spring-boot-autoConfigure包里
1.2.3 組件添加
@Configuration
- 用@Configuration標注的配置類本身也是組件,
- 配置類里面使用@Bean標注在方法上給容器注冊組件,默認也是單實體,
- full模式:@Configuration(proxyBeanMethods=true),
- lite模式:@Configuration(proxyBeanMethods=false),
- 最佳實戰:
- 配置類組件之間沒有依賴關系,使用lite模式,加快容器啟動程序,減少判斷,
- 配置類組件之間有依賴關系,會使用到之前的單實體組件,使用full模式,但容器啟動會變慢,
@Import({User.class,DBHelper.class}):給容器中創建出這兩個型別的組件,默認組件就是全類名,
@ImportResource:匯入資源檔案
1.2.4 配置系結
把組態檔中的值系結在容器中,
- @Component+@ConfigurationProperties【只有在容器中,才能使用SpringBoot的功能】
@Component
@ConfigurationProperties(preifx="myCar")
public class Car{
}
- @EnableConfigurationProperties+ @ConfigurationProperties【在配置類中加入@EnableConfigurationProperties,來開啟配置系結功能,并把組件自動注冊到容器中】
1.2.5 自動配置入門
- 引導加載自動配置類
//注解@SpringBootApplication拆分
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
@SpringBootConfiguration:代表當前是一個配置類,
@ComponentScan:開啟包掃描,
@EnableAutoConfiguration:
//@EnableAutoConfiguration的注解
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {}
@AutoConfigurationPackage:
@Import({Registrar.class})//給容器中匯入一個組件
public @interface AutoConfigurationPackage {}
//利用Registrar給容器匯入一系列組件
//將主程式所在的包下的所有組件都導進來
- 按需開啟自動配置項:雖然127個場景的所有自動配置啟動時默認全部加載,但是要按照條件裝配原則,最侄訓按需加載【@Conditional】,
\META-INF\spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
......
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
- 修改默認配置,SpringBoot會在底層配置好所有組件,但是如果用戶自己配置了,以用戶配置的優先,
總結:
- SpringBoot先加載所有的自動配置類:xxxxAutoConfiguration,
- 每個自動配置類按照條件自動生效,默認都會系結組態檔指定的值,xxxProperties里面拿,xxxProperties和組態檔進行了系結,
- 生效的配置類會在容器中裝配很多組件,
- 只要容器中這些組件有了,就相當于這些功能有了,
- 定制化配置:用戶自己用@Bean替換底層的組件,用戶去看這個組件系結了組態檔中的什么值就去修改,xxxxAutoConfiguration---->組件---->xxxxProperties里面拿值---->application.properties
1.2.6 最佳實踐
- 引入場景依賴
- 查看有哪些自動配置了【選做】
1.自己分析,引入場景對應的自動配置一般都生效了
2.組態檔中debug=true開啟自動配置報告,Negative(不生效)\Positive(生效)
- 是否需要修改
參照檔案修改配置項
自定義加入或替換組件
自定義器xxxxCustomizer
1.2.7 開發小技巧
1.2.7.1 Lombok
簡化Java Bean的開發,
- 引入依賴
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
- 安裝插件【在idea中安裝】
- 相關注解,
@Data:注解在類上, 為類提供讀寫屬性, 此外還提供了 equals()、hashCode()、toString() 方法,
@ToString:重寫tostring(),
@NoArgsConstructor:無參構造器,
@AllArgsConstructor:全參構造器,
@EqualsAndHashCode:重寫equals()和hashCode(),
@Slf4j:開啟日志功能,
1.2.7.2 dev-tools
Ctrl+F9:重新編譯,自動重啟,利于修改靜態頁面,
//引入依賴,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
1.2.7.3 Spring Initailizr
專案初始化向導,幫助開發SpringBoot專案,
- 創建專案時選擇開發所需要的場景,
- 自動創建主程式類,
- 自動匯入專案所需的依賴,
- 自動創建場景開發所需的檔案夾,

核心篇 SpringBoot核心技術
2.1 組態檔
常規的是properties檔案,也可以使用yaml,yaml非常適合以資料為中心的組態檔,是輕量級的,但按照優先級,SpringBoot會最終加載properties中的配置,
2.1.1 基本語法
- 使用key: value來儲存,kv之間有空格,
- 使用縮進來表示層級關系,
- 只可以使用空格來表示縮進,不可以使用tab,【但idea等設定了用空格代替縮進的IDE可以隨意使用空格或者tab】
- 縮進的空格數可以不同,只要相同的層級的元素左對齊就可以,
- '#'代表注釋,
- 大小寫敏感,
- 字串無需加引號,如果要加,’'與""表示字串內容,會被轉義/不轉義,
2.1.2 資料型別
- 字面量:單個不可再分的,data,Boolean,string,number,null,
k: v
- 物件:map,hash,set,object,
行內寫法: k: {k1: v1,k2: v2,k3: v3}
#或
k:
k1: v1
k2: v2
k3: v3
- 陣列:array,list,queue,
行內寫法: k: [v1,v2,v3]
#或
k:
- v1
- v2
- v3
2.1.3 配置提示
pom.xml在添加:
<dependencys>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencys>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<proc>none</proc>
</configuration>
</plugin>
2.2 Web開發
2.2.1 簡單功能分析
2.2.1.1 靜態資源訪問
靜態資源目錄:只要靜態資源放在類路徑下的/static、/public、/resources、/META-INF/resources,訪問當前專案根路徑/+靜態資源名,
原理:靜態資源/**,請求進來,先去找Controller看能不能處理,不能處理的請求又交給靜態資源處理器,靜態資源找不到就404,
靜態資源訪問前綴:默認無前綴,可在組態檔中修改,當前專案+static-path-pattern+靜態資源名=靜態資源檔案夾下找,
webjar:支持webjar,
2.2.1.2 歡迎頁訪問
- 靜態路徑下的index.html
- controller能處理/index
2.2.1.3 自定義Favicon
將favicon.ico圖示放在靜態資源路徑下即可以訪問,
2.2.1.4 靜態資源配置原理
- 專案啟動,SpringBoot加載xxxAutoConfiguration(自動配置類),
- SpringMVC的自動配置類大多在webMvcAutoConfiguration,
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {}
- 給容器中配了什么,
@Configuration(
proxyBeanMethods = false
)
@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}
- 組態檔的相關屬性和xxx進行了系結,WebMvcProperties跟spring.mvc進行了系結,ResourceProperties跟spring.resources進行了系結,
2.2.2 SpringMVC在底層可以處理的web請求
- 注解:@RequestParam
- Servlet API:HTTPSession
- 復雜引數:Map、Model
- 自定義物件引數:Person
@GetMapping:用于處理請求方法的GET型別,
@PathVariable:獲取路徑變數上的引數,可以單個獲取,也可以用Map<String,String>的方式集體獲取,
@RequestHeader:獲取請求頭資訊,可以單個獲取,也可以用Map<String,String>的方式集體獲取,
@RequestParam:獲取請求引數,可以單個獲取,也可以用Map<String,String>的方式集體獲取,
@CookieValue:獲取Cookie中的值,可以單個獲取,也可以用Cookie的方式整體獲取,
@RequestBody:獲取請求體【POST請求才有請求體】,
@RequestAttribute:獲取請求域屬性的值,
@MatrixVariable:獲取矩陣變數的值,但是SpringBoot默認禁用了矩陣變數的功能,需要手動開啟,原理:對于路徑處理,都是用UrlPathHelper決議的,UrlPathHelper中的removeSemicolonContent屬性是用來設定是否禁用分號內容【矩陣變數必須有路徑變數才可以被決議】,
/cars/{path}?xxx=xxx?xxx=xxx queryString 查詢字串,使用@RequestParam的方式獲取請求引數,
/cars/{path};xxx=xxx;yyy=aaa,bbb,ccc 矩陣變數,使用@MatrixVariable的方式獲取引數,
面試題:當Cookie禁用了,session中的值怎么使用?
【session.set(a,b)--->jsessionid--->cookie--->每次發請求攜帶】
通過URL重寫:/abc;jsessionid=xxx 把cookie的值用矩陣變數進行傳遞,
2.2.3 視圖決議
thymeleaf使用
- 引入依賴
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
- 自動配置好了thymeleaf
2.3 資料訪問
2.3.1 資料源的自動配置
- 匯入jdbc場景
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
自動配置的項:
因為官方不知道我們需要操作什么資料庫,所有缺少資料庫驅動,需要手動匯入,
<!--注意springboot的版本仲裁,需要查看本機中資料庫的版本號來修改版本,可以在<dependency>中加修改</version>,也可以在prom.xml檔案中修改version,-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
- 分析自動配置類,
- 修改配置項,在組態檔中配置資料庫連接地址、用戶名、密碼、資料庫驅動【spring.datasource】,配置資料庫相關的屬性【spring.jdbc】,
2.3.2 使用druid資料源
- 引入druid-starter,
- 分析自動配置,
1.擴展配置項spring.datasource.durid,
2.DruidSpringAopConfiguration.class:監控SpringBean的,配置項:spring.datasource.durid.aop-pattern,
3.DruidStatViewServletConfiguration.class:監控頁的配置:spring.datasource.durid.stat-view-servlet,默認開啟,
4.DruidWebStatFilterConfiguration.class:web監控的配置:spring.datasource.durid.web-stat-filter,默認開啟,
5.DruidFilterConfiguration.class:所有Druid都有自己filter的配置,
2.3.3 整合mybatis
- 引入第三方starter,
- 撰寫Mapper介面,標注@Mapper注解,
- 撰寫sql映射檔案并系結Mapper介面,
- 在application.yaml中指定Mapper組態檔的位置,以及指定全域組態檔的資訊,【建議全域組態檔的配置配置在application.yaml的mybatis.coniguration下就行】,
<!--第三方starter-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>

-
配置模式
1.全域組態檔,
2.SqlSessionFactory:自動配置好了,
3.SqlSession:自動配置了SqlSessionTemplate組合了SqlSession,
4.@Import(AutoConfiguredMapperScannerRegisterar.class)
5.Mapper:只要我們寫的操作Mybatis的介面標注了 @Mapper就會被自動掃描進來,【可以用 @MapperScan來掃描Mapper,代替@Mapper】#配置mybatis規則 #Mapper介面系結xml mybatis: config-location: #全域組態檔 mapper-location: #sql映射檔案位置 -
注解模式
@Select:寫查詢陳述句,
@Insert:寫插入陳述句,
@Options:寫陳述句的屬性項, -
混合模式
2.3.4 整合Mybatis-Plus完成CRUD
什么是Mybatis-Plus:是一個Mybatis的增強工具,為簡化開發提高效率而生,建議安裝MybatisX插件,
引入mybatis-plus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>Latest Version</version>
</dependency>
自動配置:
- MybatisPlusAutoConfiguration配置類,MybatisPlusProperties配置項系結,mybatis-plus:xxx就是對mybatis-plus的定制,
- SQLSessionFactory自動配置好,底層是容器中默認的資料源,
- mapperLocation自動配置好,有默認值,classpath*:/mapper/**/*.xml;任意包的類路徑下的所有Mapper檔案夾下的任意路徑的所有xml都是映射檔案,建議以后sql所有映射檔案都寫在mapper下,
- 容器中也自動配置好了SqlSessionTemplate,
- @Mapper標注的介面也會被自動掃描,建議寫@MapperScan批量掃描就行,
優點:
- 只要我們的Mapper繼承BaseMapper,就可以擁有crud能力,
- 使用 @TableField可以標注屬性是否存在于資料表中,
- 使用 @TableName可以指定資料庫中對應資料表名字,
- 在Service介面中繼承IService,
- 在ServiceImplement中繼承ServiceImpl,
2.3.5 NoSql(以Redis為例)
引入依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
自動配置:
- RedisAutoConfiguration自動配置類,RedisProperties屬性類—>spring.redis.xxx是對Redis的配置,
- 連接工廠是準備好的,LettuceConnectConfiguration、JedisConnectConfiguration,
- 自動注入了RedisTemplate<Object,Object>:xxxTemplate,
- 自動注入了StringRedisTemplate;k,v都是String,
- key:value,
- 底層只要我們使用RedisTemplate或者StringRedisTemplate就可以操作Redis,
Redis環境搭建:
- 使用阿里云按量付費Redis,經典網路,
- 申請Redis的公網連接地址,
- 修改Redis白名單【0.0.0.0/0】,
RedisTemplate與Lettuce:
application.yaml中配置spring.redis.host、spring.redis.port、spring.redis.password,
切換到jedis:
- 添加redis和jedis的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
- application.yaml中配置spring.redis.host、spring.redis.port、spring.redis.password、spring.redis.client-type:jedis,
2.4 單元測驗
2.4.1 JUnit變化及與SpringBoot整合
JUnit5:
- JUnit Platform:是在JVM啟動測驗框架的基礎,不僅支持JUnit自制的測驗引擎,其他測驗引擎也可以接入,
- JUnit Jupiter:提供了JUnit5的新的編程模型,是JUnit5新特性的核心,內部包含了一個測驗引擎在JUnit Platform運行,
- JUnit Vintage:提供了兼容JUnit4.x,JUnit3.x的測驗引擎,
注意:
- SpringBoot2.4及其以上版本移除了默認對Vintage的依賴,如果需要使用JUnit4需要自行引入,(不能使用JUnit4的功能 @Test),
- 在SpringBoot使用Junit4及以前版本需要在測驗類標注 @SpringBootTest和 @RunWith(SpringTest.class),
- 在SpringBoot使用JUnit5只需要在測驗類中標注 @SpringBootTest,
SpringBoot整合JUnit后:
- 撰寫測驗方法:@Test標注(注意需要使用Junit5版本的注解),
- Junit類具有Spring功能,可以使用@Autowired、@Transaction【測驗完成后會自動回滾】注解,
2.4.2 JUnit5常用注解
@DisplayName:為測驗類或者測驗方法展示名稱,
@DisplayName("測驗displayName方法")
@Test
void testDisplayName(){
System.out.println(1);
}
@BeforeEach:在每個測驗單元測驗之前執行,
@BeforeEach
void testBeforeEach(){
System.out.println("當前測驗之前執行");
}
@AfterEach:在每個測驗單元測驗之后執行,
@BeforeEach
void testAfterEach(){
System.out.println("當前測驗之后執行");
}
@BeforeAll:在所有測驗單元測驗之前執行,
//因為只執行一次,所有方法之前要加上static
@BeforeAll
static void testBeforeAll(){
System.out.println("所有測驗之前執行");
}
@AfterAll:在所有測驗單元測驗之后執行,
//因為只執行一次,所有方法之前要加上static
@AfterAll
static void testAfterAll(){
System.out.println("所有測驗之后執行");
}
@Tag:表示單元測驗類別,相當于JUnit4的 @Categories,
@Disable:表示測驗類或測驗方法不執行,類似于JUnit4的 @Ignore,
@Timeout:表示測驗方法運行如果超過了指定時間將會回傳錯誤,
@RepeatedTest:測驗重復測驗的次數,
2.4.3 斷言
斷言是測驗中的核心部分,用來測驗需要滿足的條件進行驗證,這些斷言方法都是靜態方法,用來檢查業務邏輯回傳的資料是否合理,所有測驗運行結束后會有一個詳細的測驗報告,
斷言失敗后,后面的代碼都不會執行,
斷言有以下分類:
- 簡單斷言
- assertEquals:判斷兩個物件或兩個原始型別是否相等,
@Test
@DisplayName("測驗簡單斷言")
void testSimpleAssertions(){
int cal=cal(2,3);
//可以自定義失敗資訊
assertEquals(5,cal,"業務邏輯計算失敗");
}
int cal(int a,int b){
return a+b;
}
- assertNotEquals:判斷兩個物件或兩個原始型別是否不相等,
- assertSame:判斷兩個物件參考是否指向同一個物件,
- assertNotSame:判斷兩個物件參考是否指向不同物件,
- assertTrue:判斷給定的布林值是否為True,
- assertFalse:判斷給定的布林值是否為False,
- assertNull:判斷給定的物件參考是否為Null,
- assertNotNull:判斷給定的物件參考是否不為Null,
- 陣列斷言
- assertArrayEquals:判斷兩個物件或者原始型別陣列是否相等,
- 組合斷言
- assertAll:只有組合斷言中的所有斷言都成功,才算成功,
@Test
@DisplayName("測驗組合斷言")
void testAll(){
assertAll(
"testAll";
()->assertEquals(5,5,"結果不是5"),
()->assertTrue(true,true,"結果不為True"));
}
- 例外斷言
- assertThrows:斷定業務邏輯一定出現例外,
@Test
@DisplayName("測驗例外斷言")
void testException(){
assertThrows(
ArithmeticException.class,
()->{
int i=10/0;
},
"業務邏輯居然正常");
}
//結果為:測驗通過
- 超時例外
- assertTimeout:測驗方法有無超時,
@Test
@DisplayName("測驗超時斷言")
void testTimeout(){
assertTimeout(
Duration.ofMillis(1000),
()->Thread.sleep(500)
);
}
- 快速失敗
- fail:直接使得測驗失敗,
@Test
@DisplayName("測驗快速斷言")
void testFail(){
fail("is should fail");
}
2.4.4 前置條件(assumption)
前置條件:assumption【假設】類似于斷言,不同之處是在于不滿足的斷言會使得測驗方法失效,而不滿足的前置條件只會使得測驗方法的執行終止,前置方法可以看作測驗方法的前提,當該前提不滿足時,沒有繼續的必要,
2.4.5 嵌套測驗
- 通過Java中的內部類和 @Nested注解實作嵌套測驗,
- 嵌套測驗情況下,外層的的Test不能驅動內層的Before(After)All/Each之類的方法運行,而內層的可以驅動外層的,
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.EmptyStackException;
import java.util.Stack;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@DisplayName("A stack")
class TestingAStackDemo {
Stack<Object> stack;
@Test
@DisplayName("is instantiated with new Stack()")
void isInstantiatedWithNew() {
new Stack<>();
}
@Nested
@DisplayName("when new")
class WhenNew {
@BeforeEach
void createNewStack() {
stack = new Stack<>();
}
@Test
@DisplayName("is empty")
void isEmpty() {
assertTrue(stack.isEmpty());
}
@Test
@DisplayName("throws EmptyStackException when popped")
void throwsExceptionWhenPopped() {
assertThrows(EmptyStackException.class, stack::pop);
}
@Test
@DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() {
assertThrows(EmptyStackException.class, stack::peek);
}
@Nested
@DisplayName("after pushing an element")
class AfterPushing {
String anElement = "an element";
@BeforeEach
void pushAnElement() {
stack.push(anElement);
}
@Test
@DisplayName("it is no longer empty")
void isNotEmpty() {
assertFalse(stack.isEmpty());
}
@Test
@DisplayName("returns the element when popped and is empty")
void returnElementWhenPopped() {
assertEquals(anElement, stack.pop());
assertTrue(stack.isEmpty());
}
@Test
@DisplayName("returns the element when peeked but remains not empty")
void returnElementWhenPeeked() {
assertEquals(anElement, stack.peek());
assertFalse(stack.isEmpty());
}
}
}
}
2.4.6 引數化測驗
- 引數化測驗時Junit5的一個很重要的特性,它使得使用不用的引數多次運行測驗成為了可能,給單元測驗帶來了遍歷,
- 利用@ValueSource等注解指定入參,我們就可以使用不同的引數進行多次測驗,不用每新增一個引數就多寫一個方法,就省去很多的冗余代碼,
- 使用 @ParamsterizedTest表明該方法為引數化測驗的方法,
- @ValueSource:為引數測驗指定入參,支持八大基礎型別、String型別及class型別,
@ParamsterizedTest
@DisplayName("引數化測驗1")
@ValueSource(ints={1,2,3,4,5})
void testParamsterizedTest1(int i){
System.out.println(i);
}
- @NullSource:表示為引數化測驗提供一個Null的入參,
- @EnumSource:表示為引數化測驗提供一個列舉入參,
- @CsvFileSource:表示讀取指定CSV檔案內容作為引數化測驗入參,
- @MethodSource:表示讀取指定函式的回傳值作為引數化測驗入參,
@ParamsterizedTest
@DisplayName("引數化測驗2")
@MethodSource("stringProvider")
void testParamsterizedTest2(String i){
System.out.println(i);
}
static Stream<String> stringProvider(){
return Stream.of("apple","pear","cry");
}
2.4.7 Junit5遷移到JUnit4
參照JUnit官方檔案:https://junit.org/junit5/docs/current/user-guide/#migrating-from-junit4
2.5 指標控制
2.5.1 SpringBoot Actuator
2.5.1.1 簡介
SpringBoot Actuator:SpringBoot抽取Actuator場景,使得我們每個微服務都可以快速應用應用監控、審計等功能,
匯入starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2.5.1.2 1.x與2.x的不同

2.5.1.3 如何使用
- 引入場景
- 訪問http://localhost:8080/actuator/**
- 暴露所有監控資訊為HTTP
management:
endpoints:
enable-by-default: true #暴露所有端點資訊
web:
exposure:
include: '*' #以web方式暴露
- 測驗【http://localhost:8080/actuator/監控端點名/詳細要監控的路徑】
http://localhost:8080/actuator/beans
http://localhost:8080/actuator/metrics
…
2.5.1.4 可視化
https://github.com/codecentric/spring-boot-admin
- 創建SpringBoot快速向導專案作為可視化平臺專案,引入場景,

- 在主入口類上標注 @EnableAdminServer
- 在客戶端【被監測微服務模塊】引入客戶端場景

- 在客戶端的application.yaml中配置spring.boot.admin.client.url=監控專案的地址
spring:
boot:
admin:
client:
url: http://localhost:8888 #此為監控端ip
instance:
prefer-ip: true #使用IP注冊進來,默認值為false
application:
name: boot-01-admin #設定專案名
2.5.2 Actuator Endpoint
2.5.2.1 最常用的端點


如果應用程式是Web應用程式,還可以使用以下:

最常用的Endpoint:
- Health:監控狀況,
- Metrics:運行時指標,
- Loggers:日志記錄,
2.5.2.2 Health Endpoint
健康檢查端點,用于云平臺,定時檢查應用的健康狀況,我們就需要Health Endpoint為平臺回傳當前應用的一些列組件健康狀況的集合,
注意:
- health Endpoint的回傳結果,應該是一系列健康檢查的匯總報告【up/down】,
- 很多健康檢查已經默認配置好了,如redis、資料庫,
- 可以添加自定義的健康檢查機制,
- 可以在application.yaml中配置展示health endpoint的詳細資訊,
#management.endpoints:對所有端點進行配置
#management.endpoint: 對某個端點進行配置
management:
endpoint:
health:
show-details: always
2.5.2.3 Metrics Endpoint
提供詳細的、層級的、空間指標資訊,這些資訊可以被pull(主動推送)或push(被動獲取)的方式獲得,
- 通過Metrics對接多種監控系統,
- 簡化核心Metrics開發,
- 添加自定義的Metrics或者擴展已有的Metrics,
- 需要獲取Metrics中的某項指標的詳細內容,還需要二次請求獲取,【http://localhost:8080/actuator/metrics/具體指標】
2.5.2.4 管理Endpoint
由于某些端點比較敏感,所有有時候要按需開啟端點,方法如下:
management:
endpoints:
enable-by-default: false #關閉所有端點資訊
web:
exposure:
include: '*' #以web方式暴露
endpoint:
health:
show-details: always
enable: true
info:
enable: true
beans:
enable: true
metrics:
enable: true
2.5.3 定制Endpoint
2.5.3.1 定制Health資訊
- 方式一:實作HealthIndicator介面
- 方式二:繼承AbstractHealthIndicator抽象類
//繼承AbstractHealthIndicator抽象類
@Component
public class MyComHealthIndicator extends AbstractHealthIndicator{
@Override
protect void doHealthCheck(Health.Builder builder) throws Exception{
//mongodb.進行連接測驗
//存盤詳細資料
Map<String,Object> map=new HashMap<>();
//進行檢查業務邏輯
if(1=1){
// builder.up(); //方式一:健康
builder.status(Stauts.UP); //方式二:取具體的狀態Stauts.UP
map.put("count",1);
map.put("ms",100);
}else{
// builder.down();
builder.status(Stauts.OUT_OF_SERVICE); //方式二:取具體的狀態Stauts.OUT_OF_SERVICE
map.put("err","連接超時");
map.put("ms",300);
}
//withDetail()放鍵值對
//withDetails()放Map<String,Object>
builder.withDetail("code",100)
.withDetails(map);
}
}
2.5.3.2 定制Info資訊
- 方式一:撰寫application.yaml組態檔
info:
##在application.yaml寫死
appName: boot-gul
version: 2.0.2
#使用@@獲取maven的pom檔案的值
mavenProjectName: @project.artifactId@
mavenProjectVersion: @project.version@
- 方式二:實作InfoContributor介面
//實作InfoContributor介面
@Component
public class AppInfoInfoContributor implements InfoContributor{
@Override
public void contribute(Info.Builder builder){
builder.withDetail("msg","hello")
.withDetails(Collections.singletonMap("time","20200000"));
}
}
2.5.3.3 定制Metrics資訊
- 方式一:在需要呼叫的類中創建一個構造武,傳入MeterRegistry引數,并呼叫meterRegistry的具體方法,
class MyService{
Counter counter;
public Myservice(MeterRegistry meterRegistry){
counter=meterRegistry.counter("myService.method.running.counter");
}
public void hello(){
counter.increament();
}
}
-方式二: 注冊Bean

2.5.3.4 定制Endpoint
@Compoment
@Endpoint(id="myservice")
public class DockerEndpoint{
@ReadOperation
public Map getDockerInfo(){
return Collection.singletonMap("info","docker start...");
}
@WriteOpertion
public void restartDocker(){
System.out.println("docker stop...");
}
}
2.6 原理決議
2.6.1 Profile
2.6.1.1 application-profile功能
- 默認配置環境application.yaml在任何時候都會加載,
- 指定環境組態檔命名規則:application-{env}.yaml,
- 激活指定環境:
1.默認的組態檔中激活:spring.profiles.active= yyy,
2.命令列激活【更靈活,在打包之后還可以激活,且組態檔中所有的配置項都可以改變】:java -jar xxx.jar --spring.profiles.active= yyy, - 默認配置和環境配置同時生效,
- 同名配置項,profile配置優先,
2.6.1.2 @Profile條件裝配功能
@Profile可以在類上或方法上使用,
@Profile("prod")
public class prodEnv(){
//...
}
2.6.1.3 profile配置分組
在默認配置的application.properties中配置分組,
<!--先宣告分組-->
spring.profiles.group.myprod[0]=prod0
spring.profiles.group.myprod[1]=prod1
<!--激活環境-->
spring.profiles.active=myprod
2.6.2 外部化配置
2.6.2.1 外部配置源
常用:Java屬性檔案、yaml檔案、環境變數、命令列引數,
1.Default properties (specified by setting SpringApplication.setDefaultProperties).
2.@PropertySource annotations on your @Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.
【3.Config data (such as application.properties files)】組態檔application.properties、application.yaml
4.A RandomValuePropertySource that has properties only in random.*.
5.OS environment variables.
6.Java System properties (System.getProperties()).
7.JNDI attributes from java:comp/env.
8.ServletContext init parameters.
9.ServletConfig init parameters.
10.Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
【11.Command line arguments.】命令列引數
- properties attribute on your tests. Available on @SpringBootTest and the test annotations for testing a particular slice of your application.
13.@TestPropertySource annotations on your tests.
14.Devtools global settings properties in the $HOME/.config/spring-boot directory when devtools is active.
2.6.2.2 組態檔查找順序
至上而下查找,后面的會覆寫前面的,
- classpath根路徑,
- classpath根路徑下的config目錄,
- jar包當前目錄,
- jar包當前目錄的config目錄,
- /config子目錄的直接子目錄,
【2.6.2總結:指定環境優先,外部配置優先】
總結篇
學習程序中難免會接觸到一些原始碼的決議,但也可以整體把握好SpringBoot的基本應用,回頭再來理解好原始碼,這樣便于減少枯燥,保持學習興趣,后續的SpringBoot一些核心技術的學習還包括虛擬化技術、安全控制、快取技術、訊息中間件、物件存盤、定時調度、異步任務、分布式系統等,以及SpringBoot的回應式編程,包括回應式編程基礎、Weflux開發web應用、回應式訪問持久層、回應式安全開發和回應式原理,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/266363.html
標籤:java
