之前只在項目中使用,這裏還是再總結一下:
文章目錄
SpringBoot 系列:
1. Spring Boot 入門、原理、日誌
2. Spring Boot中的Thymeleaf、自動配置、國際化、容器
3. SpringBoot 數據訪問、啓動配置原理以及自定義Starter
4. SpringBoot 與緩存並整合 Redis
5. SpringBoot 與消息隊列並整合 RabbitMQ
Spring Boot 入門
概述
Spring Boot 簡化了 Spring 應用開發:
- 由原來的 Spring 全家桶簡化成 SpringBoot 的 J2EE一站式解決方案
- 以及後來的 Spring Cloud 分佈式整體解決方案。
優點:
- 快速創建獨立運行的 Spring 項目並可以集成主流框架
- 使用嵌入式的 Servlet 容器,應用無需打成 WAR 包
- starters 自動依賴與版本控制
- 自動化配置,簡化開發
- 無需配置 XML,無代碼生成
單體應用與微服務:
單體應用,即所有的功能模塊都在一個應用中,使用複製形式實現水平擴展。
而微服務其實是一種架構風格,一個應用由一組小型服務組成,通過HTTP的方式進行互通;
每一個功能元素最終都是一個可獨立替換和獨立升級的軟件單元。
環境配置
1.在 pom.xml 中配置:
<!-- 指定父項目,由父項目管理Spring Boot 應用裏面的所有依賴版本 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<!-- 通過 starter 場景啓動器(其它 acvitmq 等),導入 web 模塊 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2.編寫啓動 Spring Boot 主程序:
/**
* @SpringBootApplication 來標註一個主程序類,說明這是一個Spring Boot應用
*/
@SpringBootApplication
public class SpringBootDemoApplication{
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class,args);//啓動應用
}
}
此時就配置完成可以編寫 Controller 了:
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "Hello World!";
}
}
只需要運行 Main 方法就可以啓動應用,打包也只需打成 JAR 可執行包,配置打包插件:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3.其實也可以使用 Spring Initializr 來快速創建
SpringBootApplication 註解
由前面可知 SpringBootApplication 註解用於標註一個主程序類,說明這是一個Spring Boot應用,而它其實是一個組合註解:
1.@SpringBootConfiguration:標註在某個類上,表示這是一個Spring Boot的配置類;
- @Configuration:使用的是 Spring 的註解來標註配置類,配置類其實是配置文件,使用的是 @Component 被標註成 Spring 的組件。
2.@EnableAutoConfiguration:開啓自動配置功能;以前我們需要配置的東西,Spring Boot幫我們自動配置,也是一個組合註解,如下:
- @AutoConfigurationPackage:自動配置包,使用 Spring 的底層註解@Import(AutoConfigurationPackages.Registrar.class) ,會將主配置類所在包及下面所有子包裏面的組件掃描到 Spring 容器。
- @Import(EnableAutoConfigurationImportSelector.class):將我們所需要的場景組件的自動配置類(xxxAutoConfiguration)導入到容器。從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration指定的值,將這些值作爲自動配置類導入到容器中,幫助我們自動配置。
配置文件
Spring Boot 全局配置文件可以對自動配置的默認配置值進行修改,而配置文件有兩種形式:
- application.properties:我們正常使用的配置文件
server.port = 8081
- application.yml:使用 YAML 標記語言的文件,以數據爲中心,比json、xml更適合作配置文件
server:
port: 8081
context-path: /
YAML 語法
基本語法
- k:(空格)v 表示一堆鍵值對(空格不能省略)
- 以空格縮進的形式來控制層級關係,即左對齊的一列是同一層級
- 屬性和值是大小寫敏感的
值的類型
- 字面量(數字,字符串,布爾):直接寫,字符串默認不用加上引號;加上雙引號則不會轉義特殊字符,而單引號會轉移特殊字符。
- 對象、Map:在下一行寫對象的屬性和值的關係
# 第一種
user:
name: moke
age: 22
# 第二種
user: {name: moke,age: 22}
- 數組、List、Set
# 第一種
myList:
- a
- b
# 第二種
myList: [a,b]
值的注入
比如上面我們配置了一個 user 對象的值,那麼如何注入到我們容器的對象中呢,如下:
- 配置文件處理器
<!--導入配置文件處理器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
- yml 配置值
user:
name: hello
age: 18
boss: false
birth: 2017/12/12
father:
name: moke
age: 30
- 注入值:@ConfigurationProperties 和 @Value
//使用 @ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "user")
public class User{...}
//使用 @Value
public class User{
@Value("${user.name}")
private String name;
...
}
區別:
@PropertySource、@ImportResource、@Bean 註解:
@PropertySource:加載指定的配置文件
@PropertySource(value = {"classpath: redis.yml"})
@ImportResource:導入 Spring 的配置文件,即使用我們原來在 Spring 中使用 xml 配置文件
@ImportResource(locations = {"classpath: beans.xml"})
但是 SpringBoot 不建議使用 xml 配置文件,而是使用配置類:
@Configuration
public class MyConfig{
//將方法的返回值添加到容器中,默認的 id 就是方法名
@Bean
public User user(){
return new User();
}
}
配置佔位符
person:
name: 張三${random.uuid}
age: ${random.int}
Profile 多環境
- 多 Profile 文件
比如在主配置文件編寫的時候,文件名:application.yml、application-test.yml、application-dev.yml,可以在住配置文件中激活環境所需要的配置文件:
spring:
profiles:
active: test
- 多文檔塊
不需要編寫多個配置文件,使用 — 來劃分不同的文檔塊,不同文檔塊指定不同的環境
spring:
profiles:
active: dev
---
spring:
profiles: test
server:
port: 8081
---
spring:
profiles: dev
server:
port: 8081
- 激活指定 profile
之前我們激活指定 profile 都是通過在配置文件中配置 spring.profiles.active 來激活,也可以使用命令行的方式激活,在啓動時添加參數:–spring.profiles.active=dev;或者使用虛擬機參數:Dspring.profiles.active=test。
加載配置文件
配置文件加載位置,優先級從高到低,配置會互補,而相同則覆蓋低優先級配置內容
- file:./config/
- file:./
- classpath:/config/
- classpath:/
或者通過 spring.config.location 來改變默認的配置文件位置(配置文件/命令行)
加載外部配置(由高到低)
1.命令行參數:所有的配置都可以在命令行上進行指定
2.來自java:comp/env的JNDI屬性
3.Java系統屬性(System.getProperties())
4.操作系統環境變量
5.RandomValuePropertySource配置的random.*屬性值
6.jar包外部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
7.jar包內部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
8.jar包外部的application.properties或application.yml(不帶spring.profile)配置文件
9.jar包內部的application.properties或application.yml(不帶spring.profile)配置文件
10.@Configuration註解類上的@PropertySource
11.通過SpringApplication.setDefaultProperties指定的默認屬性
自動配置原理
配置文件可以配置的屬性:官方文檔
之前有說 SpringBoot 啓動的時候使用 @EnableAutoConfiguration 開啓了自動配置功能,而 @EnableAutoConfiguration 是利用 EnableAutoConfigurationImportSelectort 向容器導入組件,相關的方法:
把從 spring.factories 中掃描到的文件內容封裝成 properties 對象,然後就可以從 properties 中獲取到 EnableAutoConfiguration.class 類中對應的值,然後把它們添加到容器中。
我們以 AciveMQautoConfiguration 爲例,這是 ActiveMQ 的自動配置類
而 Properties 類默認是通過 spring.factories 中的 url 獲取到的 Properties,而通過 @ConfigurationProperties 註解允許從我們自定義的配置文件中注入修改的值:
@Conditional 註解
在自動配置加載 Properties 類前,會先進行條件的判斷,自動配置類必須在一定的條件下才能生效;
而它們都是基於 Spring 的底層註解 @Conditional,如下:
這些由 @Conditional 派生出來的不同的條件註解,常見的如下:
@Conditional擴展註解 | 作用(判斷是否滿足當前指定條件) |
---|---|
@ConditionalOnJava | 系統的java版本是否符合要求 |
@ConditionalOnBean | 容器中存在指定Bean; |
@ConditionalOnMissingBean | 容器中不存在指定Bean; |
@ConditionalOnExpression | 滿足SpEL表達式指定 |
@ConditionalOnClass | 系統中有指定的類 |
@ConditionalOnMissingClass | 系統中沒有指定的類 |
@ConditionalOnSingleCandidate | 容器中只有一個指定的Bean,或者這個Bean是首選Bean |
@ConditionalOnProperty | 系統中指定的屬性是否有指定的值 |
@ConditionalOnResource | 類路徑下是否存在指定資源文件 |
@ConditionalOnWebApplication | 當前是web環境 |
@ConditionalOnNotWebApplication | 當前不是web環境 |
@ConditionalOnJndi | JNDI存在指定項 |
那我們如何知道那些自動配置類生效了呢?
配置 debug=true,會在啓動時打印自動配置報告:
日誌框架
Spring 框架默認使用的是 JCL,而 SpringBoot 改爲 SLF4J 和 logback。
SLF4J 的原理
我們只需要調用日誌門面 SLF4J 抽象層中的方法,而不是直接調用日誌的實現類,除了導入 SLF4J 還需要導入相應日誌的實現(可以不是默認的 logback,但是需要一箇中間層來適配),參考官方的圖片:
此外,在開發過程中,框架會使用自己的底層配置的日誌實現框架,那如何都通過 SLF4J 提供的方法進行統一的日誌輸出呢?將應用中其他 日誌實現 替換成調用 SLF4J 的中間包,參考官方圖片:
而這些中間包的引入,可以通過SpringBoot 的依賴關係,看到 SpringBoot 都幫我們完成了:
所以在引入其他框架時,我們只需要把這個框架本身的日誌框架排除,比如 SpringBoot 對 Spring 框架中 commons-logging 的排除:
SpringBoot 中使用 SLF4J
在 SpringBoot 中使用 SLF4J
Logger logger = LoggerFactory.getLogger(getClass());
//日誌的級別;
//由低到高 trace<debug<info<warn<error
//可以調整輸出的日誌級別;日誌就只會在這個級別以以後的高級別生效
logger.trace("這是trace日誌...");
logger.debug("這是debug日誌...");
//SpringBoot默認給我們使用的是info級別的,沒有指定級別的就用SpringBoot默認規定的級別;root級別
logger.info("這是info日誌...");
logger.warn("這是warn日誌...");
logger.error("這是error日誌...");
而我們可以在配置文件中配置級別,以及使用日誌的其他功能:
logging:
# 日誌打印級別
level: trace
# 可以指定完整的路徑,以及生成的日誌文件名
file: F:/springboot.log
# 在當前磁盤的根路徑下創建spring文件夾和裏面的log文件夾;使用 spring.log 作爲默認文件
path: /spring/log
pattern:
# 在控制檯輸出的日誌的格式
console: '%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n'
# 指定文件中日誌輸出的格式
file: '%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n'
# 日誌的格式
# %d表示日期時間,
# %thread表示線程名,
# %-5level:級別從左顯示5個字符寬度
# %logger{50} 表示logger名字最長50個字符,否則按照句點分割。
# %msg:日誌消息,
# %n是換行符
還可以自己定義配置文件
給類路徑下放上每個日誌框架自己的配置文件即可;SpringBoot就不會使用他默認配置的
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
帶 spring 和不帶 spring 是有區別的,比如:
- logback.xml:直接就被日誌框架識別了;
- logback-spring.xml:日誌框架就不直接加載日誌的配置項,由SpringBoot解析日誌配置,可以使用SpringBoot的高級Profile功能
SpringBoot Profile: 可以指定某段配置只在某個環境下生效
<springProfile name="dev">
<!-- dev環境下的輸出格式 -->
<pattern>%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n</pattern>
</springProfile>
切換日誌框架
可以按照slf4j的日誌適配圖,進行相關的切換,比如切換到 slf4j+log4j2,先排除再引入:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>