javascript
SpringBoot入门学习
SpringBoot入門學(xué)習(xí)
Spring再簡化:SpringBoot-jar:內(nèi)嵌tomcat;微服務(wù)架構(gòu)!
服務(wù)越來越多就出來了Springcloud
回顧什么是Spring
Spring是一個(gè)開源框架,2003 年興起的一個(gè)輕量級的Java 開發(fā)框架,作者:Rod Johnson 。
Spring是為了解決企業(yè)級應(yīng)用開發(fā)的復(fù)雜性而創(chuàng)建的,簡化開發(fā)。
Spring是如何簡化Java開發(fā)的
為了降低Java開發(fā)的復(fù)雜性,Spring采用了以下4種關(guān)鍵策略:
1、基于POJO的輕量級和最小侵入性編程,所有東西都是bean;
2、通過IOC,依賴注入(DI)和面向接口實(shí)現(xiàn)松耦合;
3、基于切面(AOP)和慣例進(jìn)行聲明式編程;
4、通過切面和模版減少樣式代碼,RedisTemplate,xxxTemplate;
什么是SpringBoot
學(xué)過javaweb的同學(xué)就知道,開發(fā)一個(gè)web應(yīng)用,從最初開始接觸Servlet結(jié)合Tomcat, 跑出一個(gè)Hello Wolrld程序,是要經(jīng)歷特別多的步驟;后來就用了框架Struts,再后來是SpringMVC,到了現(xiàn)在的SpringBoot,過一兩年又會(huì)有其他web框架出現(xiàn);你們有經(jīng)歷過框架不斷的演進(jìn),然后自己開發(fā)項(xiàng)目所有的技術(shù)也在不斷的變化、改造嗎?建議都可以去經(jīng)歷一遍;
言歸正傳,什么是SpringBoot呢,就是一個(gè)javaweb的開發(fā)框架,和SpringMVC類似,對比其他javaweb框架的好處,官方說是簡化開發(fā),約定大于配置, you can “just run”,能迅速的開發(fā)web應(yīng)用,幾行代碼開發(fā)一個(gè)http接口。
所有的技術(shù)框架的發(fā)展似乎都遵循了一條主線規(guī)律:從一個(gè)復(fù)雜應(yīng)用場景 衍生 一種規(guī)范框架,人們只需要進(jìn)行各種配置而不需要自己去實(shí)現(xiàn)它,這時(shí)候強(qiáng)大的配置功能成了優(yōu)點(diǎn);發(fā)展到一定程度之后,人們根據(jù)實(shí)際生產(chǎn)應(yīng)用情況,選取其中實(shí)用功能和設(shè)計(jì)精華,重構(gòu)出一些輕量級的框架;之后為了提高開發(fā)效率,嫌棄原先的各類配置過于麻煩,于是開始提倡“約定大于配置”,進(jìn)而衍生出一些一站式的解決方案。
是的這就是Java企業(yè)級應(yīng)用->J2EE->spring->springboot的過程。
隨著 Spring 不斷的發(fā)展,涉及的領(lǐng)域越來越多,項(xiàng)目整合開發(fā)需要配合各種各樣的文件,慢慢變得不那么易用簡單,違背了最初的理念,甚至人稱配置地獄。Spring Boot 正是在這樣的一個(gè)背景下被抽象出來的開發(fā)框架,目的為了讓大家更容易的使用 Spring 、更容易的集成各種常用的中間件、開源軟件;
Spring Boot 基于 Spring 開發(fā),Spirng Boot 本身并不提供 Spring 框架的核心特性以及擴(kuò)展功能,只是用于快速、敏捷地開發(fā)新一代基于 Spring 框架的應(yīng)用程序。也就是說,它并不是用來替代 Spring 的解決方案,而是和 Spring 框架緊密結(jié)合用于提升 Spring 開發(fā)者體驗(yàn)的工具。Spring Boot 以約定大于配置的核心思想,默認(rèn)幫我們進(jìn)行了很多設(shè)置,多數(shù) Spring Boot 應(yīng)用只需要很少的 Spring 配置。同時(shí)它集成了大量常用的第三方庫配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot 應(yīng)用中這些第三方庫幾乎可以零配置的開箱即用。
簡單來說就是SpringBoot其實(shí)不是什么新的框架,它默認(rèn)配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架 。
Spring Boot 出生名門,從一開始就站在一個(gè)比較高的起點(diǎn),又經(jīng)過這幾年的發(fā)展,生態(tài)足夠完善,Spring Boot 已經(jīng)當(dāng)之無愧成為 Java 領(lǐng)域最熱門的技術(shù)。
Spring Boot的主要優(yōu)點(diǎn):
- 為所有Spring開發(fā)者更快的入門
- 開箱即用,提供各種默認(rèn)配置來簡化項(xiàng)目配置
- 內(nèi)嵌式容器簡化Web項(xiàng)目
- 沒有冗余代碼生成和XML配置的要求
MVVM微服務(wù)架構(gòu)理解
高內(nèi)聚,低耦合
現(xiàn)在跑程序,把一切都放到war包中運(yùn)行很方便部署,如果負(fù)載能力不行,我們將整個(gè)應(yīng)用進(jìn)行水平復(fù)制,進(jìn)行擴(kuò)展,然后負(fù)載均衡
現(xiàn)在把里邊的功能分開成模塊,想要怎么組裝就怎么組裝,把所有獨(dú)立出來的元素動(dòng)態(tài)組合,需要的功能元素才去拿來組合。所以微服務(wù)架構(gòu)是對功能元素進(jìn)行復(fù)制,而沒有對整個(gè)應(yīng)用進(jìn)行復(fù)制
每個(gè)功能元素的服務(wù)都是一個(gè)可替換的,可獨(dú)立升級的軟件代碼
SpringBoot之旅先知
1.Hello,World之項(xiàng)目結(jié)構(gòu)
Spring官方提供了非常方便的工具讓我們快速構(gòu)建應(yīng)用
Spring Initializr:https://start.spring.io/
**項(xiàng)目創(chuàng)建方式一:**使用Spring Initializr 的 Web頁面創(chuàng)建項(xiàng)目
1、打開 https://start.spring.io/
2、填寫項(xiàng)目信息
3、點(diǎn)擊”Generate Project“按鈕生成項(xiàng)目;下載此項(xiàng)目
4、解壓項(xiàng)目包,并用IDEA以Maven項(xiàng)目導(dǎo)入,一路下一步即可,直到項(xiàng)目導(dǎo)入完畢。
5、如果是第一次使用,可能速度會(huì)比較慢,包比較多、需要耐心等待一切就緒。
**項(xiàng)目創(chuàng)建方式二:**使用 IDEA 直接創(chuàng)建項(xiàng)目
1、創(chuàng)建一個(gè)新項(xiàng)目
2、選擇spring initalizr , 可以看到默認(rèn)就是去官網(wǎng)的快速構(gòu)建工具那里實(shí)現(xiàn)
3、填寫項(xiàng)目信息
4、選擇初始化的組件(初學(xué)勾選 Web 即可)
5、填寫項(xiàng)目路徑
6、等待項(xiàng)目構(gòu)建成功
項(xiàng)目結(jié)構(gòu)分析:
通過上面步驟完成了基礎(chǔ)項(xiàng)目的創(chuàng)建。就會(huì)自動(dòng)生成以下文件。
1、程序的主啟動(dòng)類
2、一個(gè) application.properties 配置文件
3、一個(gè) 測試類
4、一個(gè) pom.xml
pom.xml分析
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-FwzKXMUz-1614595470344)(C:\Users\18335\AppData\Roaming\Typora\typora-user-images\image-20201116145758215.png)]
<!-- 父依賴 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> </parent> <dependencies> <!-- web場景啟動(dòng)器 --> <dependency> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- springboot單元測試 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <!-- 剔除依賴 --> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency></dependencies> <build> <plugins> <!-- 打包插件 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>在application.properties中更改端口號 server.port=8081
在同級目錄下創(chuàng)建banner.txt改banner
2.運(yùn)行初探
SpringBoot的所有自動(dòng)裝配,都是在啟動(dòng)的時(shí)候掃描spring.factories文件,這個(gè)里面寫了所有自動(dòng)配置的類,但是不一定生效,有一個(gè)判斷條件ConditionalOnXXX()必須滿足里邊的條件才能配置,所以我們一般Start導(dǎo)入對應(yīng)的啟動(dòng)器,自動(dòng)裝配就生效了,然后配置成功
1.pom.xml
父依賴是真正的所有依賴都已經(jīng)寫好了的
其中它主要是依賴一個(gè)父項(xiàng)目,主要是管理項(xiàng)目的資源過濾及插件!
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --></parent>點(diǎn)進(jìn)去,發(fā)現(xiàn)還有一個(gè)父依賴
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.5.RELEASE</version> <relativePath>../../spring-boot-dependencies</relativePath></parent>這里才是真正管理SpringBoot應(yīng)用里面所有依賴版本的地方,SpringBoot的版本控制中心;
以后我們導(dǎo)入依賴默認(rèn)是不需要寫版本;但是如果導(dǎo)入的包沒有在依賴中管理著就需要手動(dòng)配置版本了;
啟動(dòng)器 spring-boot-starter
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>springboot-boot-starter-xxx:就是spring-boot的場景啟動(dòng)器
spring-boot-starter-web:幫我們導(dǎo)入了web模塊正常運(yùn)行所依賴的組件;
SpringBoot將所有的功能場景都抽取出來,做成一個(gè)個(gè)的starter (啟動(dòng)器),只需要在項(xiàng)目中引入這些starter即可,所有相關(guān)的依賴都會(huì)導(dǎo)入進(jìn)來 , 我們要用什么功能就導(dǎo)入什么樣的場景啟動(dòng)器即可 ;我們未來也可以自己自定義 starter;
2. 主程序
//@SpringBootApplication 來標(biāo)注一個(gè)主程序類//說明這是一個(gè)Spring Boot應(yīng)用@SpringBootApplicationpublic class SpringbootApplication {public static void main(String[] args) { //以為是啟動(dòng)了一個(gè)方法,沒想到啟動(dòng)了一個(gè)服務(wù) SpringApplication.run(SpringbootApplication.class, args); } }注解
@SpringBootApplication :springboot的配置@Configuration spring配置類@Component 說明這是一個(gè)spring的組件@EnableAutoConfiguration 自動(dòng)配置@AutoConfigurationPackage 自動(dòng)配置包@Import({Registrar.class}) 自動(dòng)配置包注冊@Import({AutoConfigurationImportSelector.class}) 自動(dòng)配置導(dǎo)入選擇[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-4qgmbzta-1614595470347)(C:\Users\18335\AppData\Roaming\Typora\typora-user-images\image-20201116162511276.png)]
1.@SpringBootApplication
作用:標(biāo)注在某個(gè)類上說明這個(gè)類是SpringBoot的主配置類 , SpringBoot就應(yīng)該運(yùn)行這個(gè)類的main方法來啟動(dòng)SpringBoot應(yīng)用;
進(jìn)入這個(gè)注解:可以看到上面還有很多其他注解!
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class}), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class})})public @interface SpringBootApplication { // ......}2.@ComonentScan
這個(gè)注解在Spring中很重要 ,它對應(yīng)XML配置中的元素。
作用:自動(dòng)掃描并加載符合條件的組件或者bean , 將這個(gè)bean定義加載到IOC容器中
3.@SpringBootConfiguration
作用:SpringBoot的配置類 ,標(biāo)注在某個(gè)類上 , 表示這是一個(gè)SpringBoot的配置類;
我們繼續(xù)進(jìn)去這個(gè)注解查看
// 點(diǎn)進(jìn)去得到下面的 @Component @Configuration public @interfaceSpringBootConfiguration {} @Component public @interface Configuration {}這里的 @Configuration,說明這是一個(gè)配置類 ,配置類就是對應(yīng)Spring的xml 配置文件;
里面的 @Component 這就說明,啟動(dòng)類本身也是Spring中的一個(gè)組件而已,負(fù)責(zé)啟動(dòng)應(yīng)用!
我們回到 SpringBootApplication 注解中繼續(xù)看。
@EnbleAutoConfiguration
4. @EnableAutoConfiguration :開啟自動(dòng)配置功能
以前我們需要自己配置的東西,而現(xiàn)在SpringBoot可以自動(dòng)幫我們配置 ;@EnableAutoConfiguration告訴SpringBoot開啟自動(dòng)配置功能,這樣自動(dòng)配置才能生效;
點(diǎn)進(jìn)注解接續(xù)查看:
@AutoConfigurationPackage :自動(dòng)配置包
@Import({Registrar.class}) public @interface AutoConfigurationPackage {}@import :Spring底層注解@import , 給容器中導(dǎo)入一個(gè)組件
Registrar.class 作用:將主啟動(dòng)類的所在包及包下面所有子包里面的所有組件掃描到Spring容器 ;
這個(gè)分析完了,退到上一步,繼續(xù)看
@Import({AutoConfigurationImportSelector.class}) :給容器導(dǎo)入組件 ;
AutoConfigurationImportSelector :自動(dòng)配置導(dǎo)入選擇器,那么它會(huì)導(dǎo)入哪些組件的選擇器呢?我們點(diǎn)擊去這個(gè)類看源碼:
1、這個(gè)類中有一個(gè)這樣的方法
// 獲得候選的配置 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { //這里的getSpringFactoriesLoaderFactoryClass()方法 //返回的就是我們最開始看的啟動(dòng)自動(dòng)導(dǎo)入配置文件的注解類;EnableAutoConfiguration List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); return configurations;}2、這個(gè)方法又調(diào)用了 SpringFactoriesLoader 類的靜態(tài)方法!我們進(jìn)入SpringFactoriesLoader類loadFactoryNames() 方法
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); //這里它又調(diào)用了 loadSpringFactories 方法 return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());}3、我們繼續(xù)點(diǎn)擊查看 loadSpringFactories 方法
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { //獲得classLoader , 我們返回可以看到這里得到的就是EnableAutoConfiguration標(biāo)注的類本身 MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { //去獲取一個(gè)資源 "META-INF/spring.factories" Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); LinkedMultiValueMap result = new LinkedMultiValueMap();//將讀取到的資源遍歷,封裝成為一個(gè)Properties while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator();while(var6.hasNext()) { Entry<?, ?> entry = (Entry)var6.next(); String factoryClassName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length;for(int var11 = 0; var11 < var10; ++var11) { String factoryName = var9[var11]; result.add(factoryClassName,factoryName.trim()); } } }cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); } } }4、發(fā)現(xiàn)一個(gè)多次出現(xiàn)的文件:spring.factories,全局搜索它
spring.factories
我們根據(jù)源頭打開spring.factories , 看到了很多自動(dòng)配置的文件;這就是自動(dòng)配置根源所在!
WebMvcAutoConfiguration
我們在上面的自動(dòng)配置類隨便找一個(gè)打開看看,比如 :WebMvcAutoConfiguration
可以看到這些一個(gè)個(gè)的都是JavaConfig配置類,而且都注入了一些Bean,可以找一些自己認(rèn)識的類,看著熟悉一下!
所以,自動(dòng)配置真正實(shí)現(xiàn)是從classpath中搜尋所有的META-INF/spring.factories配置文件 ,并將其中對應(yīng)的 org.springframework.boot.autoconfigure. 包下的配置項(xiàng),通過反射實(shí)例化為對應(yīng)標(biāo)注了 @Configuration的JavaConfig形式的IOC容器配置類 , 然后將這些都匯總成為一個(gè)實(shí)例并加載到IOC容器中。
結(jié)論:
3.不簡單的方法
我最初以為就是運(yùn)行了一個(gè)main方法,沒想到卻開啟了一個(gè)服務(wù);
@SpringBootApplication public class SpringbootApplication { public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); }}SpringApplication.run分析
分析該方法主要分兩部分,一部分是SpringApplication的實(shí)例化,二是run方法的執(zhí)行;
SpringApplication
這個(gè)類主要做了以下四件事情:
1、推斷應(yīng)用的類型是普通的項(xiàng)目還是Web項(xiàng)目
2、查找并加載所有可用初始化器 , 設(shè)置到initializers屬性中
3、找出所有的應(yīng)用程序監(jiān)聽器,設(shè)置到listeners屬性中
4、推斷并設(shè)置main方法的定義類,找到運(yùn)行的主類
查看構(gòu)造器:
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) { // ...... this.webApplicationType = WebApplicationType.deduceFromClasspath(); this.setInitializers(this.getSpringFactoriesInstances(); this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = this.deduceMainApplicationClass();}run方法流程分析
SpringBoot的理解
- 自動(dòng)裝配
- run
3.yaml語法
1.yaml使用
SpringBoot使用一個(gè)全局的配置文件 , 配置文件名稱是固定的
-
application.properties
-
- 語法結(jié)構(gòu) :key=value
-
application.yml
-
- 語法結(jié)構(gòu) :key:空格 value
**配置文件的作用 :**修改SpringBoot自動(dòng)配置的默認(rèn)值,因?yàn)镾pringBoot在底層都給我們自動(dòng)配置好了;
1、在springboot項(xiàng)目中的resources目錄下新建一個(gè)文件 application.yml
2、編寫一個(gè)實(shí)體類 Dog
package com.kuang.springboot.pojo; @Component //注冊bean到容器中 public class Dog { private String name; private Integer age; //有參無參構(gòu)造、get、set方法、toString()方法 }3、思考,我們原來是如何給bean注入屬性值的!@Value,給狗狗類測試一下:
@Component //注冊bean public class Dog { @Value("阿黃") private String name; @Value("18") private Integer age;}4、在SpringBoot的測試類下注入狗狗輸出一下;
@SpringBootTestclass DemoApplicationTests {@Autowired //將狗狗自動(dòng)注入進(jìn)來 Dog dog;@Test public void contextLoads() { System.out.println(dog); //打印看下狗狗對象 } }結(jié)果成功輸出,@Value注入成功,這是我們原來的辦法對吧。
5、我們在編寫一個(gè)復(fù)雜一點(diǎn)的實(shí)體類:Person 類
@Component //注冊bean到容器中 public class Person { private String name; private Integer age; private Boolean happy; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Dog dog; //有參無參構(gòu)造、get、set方法、toString()方法 }6、我們來使用yaml配置的方式進(jìn)行注入,大家寫的時(shí)候注意區(qū)別和優(yōu)勢,我們編寫一個(gè)yaml配置!
person: name: qinjiang age: 3 happy: false birth: 2000/01/01 maps: {k1: v1,k2: v2} lists: - code - girl - music dog: name: 旺財(cái) age: 17、我們剛才已經(jīng)把person這個(gè)對象的所有值都寫好了,我們現(xiàn)在來注入到我們的類中
/*@ConfigurationProperties作用:將配置文件中配置的每一個(gè)屬性的值,映射到這個(gè)組件中;告訴SpringBoot將本類中的所有屬性和配置文件中相關(guān)的配置進(jìn)行綁定參數(shù) prefix = “person” : 將配置文件中的person下面的所有屬性一一對應(yīng)*/ @Component //注冊bean @ConfigurationProperties(prefix = "person") public class Person { private String name; private Integer age; private Boolean happy; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Dog dog;}8、IDEA 提示,springboot配置注解處理器沒有找到,讓我們看文檔,我們可以查看文檔,找到一個(gè)依賴!
<!-- 導(dǎo)入配置文件處理器,配置文件進(jìn)行綁定就會(huì)有提示,需要重啟 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional></dependency>9、確認(rèn)以上配置都OK之后,我們?nèi)y試類中測試一下:
@SpringBootTestclass DemoApplicationTests {@Autowired Person person; //將person自動(dòng)注入進(jìn)來@Test public void contextLoads() { System.out.println(person); //打印person信息 } }結(jié)果:所有值全部注入成功!
yaml配置注入到實(shí)體類完全OK!
課堂測試:
1、將配置文件的key 值 和 屬性的值設(shè)置為不一樣,則結(jié)果輸出為null,注入失敗
2、在配置一個(gè)person2,然后將 @ConfigurationProperties(prefix = “person2”) 指向我們的person2;
加載指定的配文件
**@PropertySource :**加載指定的配置文件;
@configurationProperties:默認(rèn)從全局配置文件中獲取值;
1、我們?nèi)ピ趓esources目錄下新建一個(gè)person.properties文件
name=kuangshen2、然后在我們的代碼中指定加載person.properties文件
@PropertySource(value = "classpath:person.properties") @Component //注冊bean public class Person {@Value("${name}") private String name;...... }3、再次輸出測試一下:指定配置文件綁定成功!
配置文件占位符
配置文件還可以編寫占位符生成隨機(jī)數(shù)
person: name: qinjiang${random.uuid} # 隨機(jī)uuid age: ${random.int} # 隨機(jī)int happy: false birth: 2000/01/01 maps: {k1: v1,k2: v2} lists: - code - girl - music dog: name: ${person.hello:other}_旺財(cái) age: 12. 回顧properties配置
我們上面采用的yaml方法都是最簡單的方式,開發(fā)中最常用的;也是springboot所推薦的!那我們來嘮嘮其他的實(shí)現(xiàn)方式,道理都是相同的;寫還是那樣寫;配置文件除了yml還有我們之前常用的properties , 我們沒有講,我們來嘮嘮!
【注意】properties配置文件在寫中文的時(shí)候,會(huì)有亂碼 , 我們需要去IDEA中設(shè)置編碼格式為UTF-8;
settings–>FileEncodings 中配置;
測試步驟:
1、新建一個(gè)實(shí)體類User
@Component //注冊bean public class User { private String name; private int age; private String sex;}2、編輯配置文件 user.properties
user1.name=kuangshen user1.age=18 user1.sex=男3、我們在User類上使用@Value來進(jìn)行注入!
@Component //注冊bean @PropertySource(value = "classpath:user.properties") public class User { //直接使用@value @Value("${user.name}") //從配置文件中取值 private String name; @Value("#{9*2}") // #{SPEL} Spring表達(dá)式 private int age; @Value("男") // 字面量 private String sex;}4、Springboot測試
@SpringBootTestclass DemoApplicationTests {@Autowired User user;@Test public void contextLoads() { System.out.println(user); } }結(jié)果正常輸出:
對比小結(jié)
@Value這個(gè)使用起來并不友好!我們需要為每個(gè)屬性單獨(dú)注解賦值,比較麻煩;我們來看個(gè)功能對比圖
1、@ConfigurationProperties只需要寫一次即可 , @Value則需要每個(gè)字段都添加
2、松散綁定:這個(gè)什么意思呢? 比如我的yml中寫的last-name,這個(gè)和lastName是一樣的, - 后面跟著的字母默認(rèn)是大寫的。這就是松散綁定。可以測試一下
3、JSR303數(shù)據(jù)校驗(yàn) , 這個(gè)就是我們可以在字段是增加一層過濾器驗(yàn)證 , 可以保證數(shù)據(jù)的合法性
4、復(fù)雜類型封裝,yml中可以封裝對象 , 使用value就不支持
結(jié)論:
配置yml和配置properties都可以獲取到值 , 強(qiáng)烈推薦 yml;
如果我們在某個(gè)業(yè)務(wù)中,只需要獲取配置文件中的某個(gè)值,可以使用一下 @value;
如果說,我們專門編寫了一個(gè)JavaBean來和配置文件進(jìn)行一一映射,就直接@configurationProperties,不要猶豫!
3.JSR303數(shù)據(jù)校驗(yàn)
Springboot中可以用@validated來校驗(yàn)數(shù)據(jù),如果數(shù)據(jù)異常則會(huì)統(tǒng)一拋出異常,方便異常中心統(tǒng)一處理。我們這里來寫個(gè)注解讓我們的name只能支持Email格式;
@Component //注冊bean @ConfigurationProperties(prefix = "person") @Validated //數(shù)據(jù)校驗(yàn) public class Person {@Email(message="郵箱格式錯(cuò)誤") //name必須是郵箱格式 private String name;}運(yùn)行結(jié)果 :default message [不是一個(gè)合法的電子郵件地址];
使用數(shù)據(jù)校驗(yàn),可以保證數(shù)據(jù)的正確性;
常見參數(shù)
@NotNull(message="名字不能為空") private String userName; @Max (value=120,message="年齡最大不能查過120") private int age; @Email(message="郵箱格式錯(cuò)誤") private String email; 空檢查@Null 驗(yàn)證對象是否為null@NotNull 驗(yàn)證對象是否不為null, 無法查檢長度為0的字符串@NotBlank 檢查約束字符串是不是Null還有被Trim的長度是否大于0,只對字符串,且會(huì)去掉前后空格.@NotEmpty 檢查約束元素是否為NULL或者是EMPTY. Booelan檢查@AssertTrue 驗(yàn)證 Boolean 對象是否為 true @AssertFalse 驗(yàn)證 Boolean 對象是否為 false 長度檢查@Size(min=, max=) 驗(yàn)證對象(Array,Collection,Map,String)長度是否在給定的范圍之內(nèi)@Length(min=, max=) string is between min and max included. 日期檢查@Past 驗(yàn)證 Date 和 Calendar 對象是否在當(dāng)前時(shí)間之前 @Future 驗(yàn)證 Date 和 Calendar 對象是否在當(dāng)前時(shí)間之后 @Pattern 驗(yàn)證 String 對象是否符合正則表達(dá)式的規(guī)則 .......等等除此以外,我們還可以自定義一些數(shù)據(jù)校驗(yàn)規(guī)則4多環(huán)境切換
不同位置優(yōu)先級不同
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-2b1vOmsl-1614595470372)(C:\Users\18335\AppData\Roaming\Typora\typora-user-images\image-20201117141503882.png)]
springboot 啟動(dòng)會(huì)掃描以下位置的application.properties或者application.yml文件作為Spring boot的默認(rèn)配置文件:
優(yōu)先級1:項(xiàng)目路徑下的config文件夾配置文件優(yōu)先級2:項(xiàng)目路徑下配置文件優(yōu)先級3:資源路徑下的config文件夾配置文件優(yōu)先級4:資源路徑下配置文件優(yōu)先級由高到底,高優(yōu)先級的配置會(huì)覆蓋低優(yōu)先級的配置;
SpringBoot會(huì)從這四個(gè)位置全部加載主配置文件;互補(bǔ)配置;
我們在最低級的配置文件中設(shè)置一個(gè)項(xiàng)目訪問路徑的配置來測試互補(bǔ)問題;
#配置項(xiàng)目的訪問路徑server.servlet.context-path=/kuangprofile是Spring對不同環(huán)境提供不同配置功能的支持,可以通過激活不同的環(huán)境版本,實(shí)現(xiàn)快速切換環(huán)境;
多配置文件
我們在主配置文件編寫的時(shí)候,文件名可以是 application-{profile}.properties/yml , 用來指定多個(gè)環(huán)境版本;
例如:
application-test.properties 代表測試環(huán)境配置
application-dev.properties 代表開發(fā)環(huán)境配置
但是Springboot并不會(huì)直接啟動(dòng)這些配置文件,它默認(rèn)使用application.properties主配置文件;
我們需要通過一個(gè)配置來選擇需要激活的環(huán)境:
#比如在配置文件中指定使用dev環(huán)境,我們可以通過設(shè)置不同的端口號進(jìn)行測試;#我們啟動(dòng)SpringBoot,就可以看到已經(jīng)切換到dev下的配置了;spring.profiles.active=devyaml的多文檔塊
和properties配置文件中一樣,但是使用yml去實(shí)現(xiàn)不需要?jiǎng)?chuàng)建多個(gè)配置文件,更加方便了 !
server: port: 8081#選擇要激活那個(gè)環(huán)境塊spring: profiles: active: prod ---server: port: 8083spring: profiles: dev #配置環(huán)境的名稱--- server: port: 8084spring: profiles: prod #配置環(huán)境的名稱注意:如果yml和properties同時(shí)都配置了端口,并且沒有激活其他環(huán)境 , 默認(rèn)會(huì)使用properties配置文件的!
4. 自動(dòng)配置深如
我們以**HttpEncodingAutoConfiguration(Http編碼自動(dòng)配置)**為例解釋自動(dòng)配置原理;
//表示這是一個(gè)配置類,和以前編寫的配置文件一樣,也可以給容器中添加組件; @Configuration //啟動(dòng)指定類的ConfigurationProperties功能; //進(jìn)入這個(gè)HttpProperties查看,將配置文件中對應(yīng)的值和HttpProperties綁定起來; //并把HttpProperties加入到ioc容器中 @EnableConfigurationProperties({HttpProperties.class}) //Spring底層 @Conditional注解 //根據(jù)不同的條件判斷,如果滿足指定的條件,整個(gè)配置類里面的配置就會(huì)生效; //這里的意思就是判斷當(dāng)前應(yīng)用是否是web應(yīng)用,如果是,當(dāng)前配置類生效 @ConditionalOnWebApplication( type = Type.SERVLET) //判斷當(dāng)前項(xiàng)目有沒有這個(gè)類CharacterEncodingFilter;SpringMVC中進(jìn)行亂碼解決的過濾器;@ConditionalOnClass({CharacterEncodingFilter.class}) //判斷配置文件中是否存在某個(gè)配置:spring.http.encoding.enabled; //如果不存在,判斷也是成立的 //即使我們配置文件中不配置pring.http.encoding.enabled=true,也是默認(rèn)生效的; @ConditionalOnProperty( prefix = "spring.http.encoding", value = {"enabled"}, matchIfMissing = true) public class HttpEncodingAutoConfiguration { //他已經(jīng)和SpringBoot的配置文件映射了 private final Encoding properties; //只有一個(gè)有參構(gòu)造器的情況下,參數(shù)的值就會(huì)從容器中拿 public HttpEncodingAutoConfiguration(HttpProperties properties) { this.properties = properties.getEncoding(); } //給容器中添加一個(gè)組件,這個(gè)組件的某些值需要從properties中獲取 @Bean @ConditionalOnMissingBean //判斷容器沒有這個(gè)組件? public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE)); return filter; } //。。。。。。。 }一句話總結(jié) :根據(jù)當(dāng)前不同的條件判斷,決定這個(gè)配置類是否生效!
- 一但這個(gè)配置類生效;這個(gè)配置類就會(huì)給容器中添加各種組件;
- 這些組件的屬性是從對應(yīng)的properties類中獲取的,這些類里面的每一個(gè)屬性又是和配置文件綁定的;
- 所有在配置文件中能配置的屬性都是在xxxxProperties類中封裝著;
- 配置文件能配置什么就可以參照某個(gè)功能對應(yīng)的這個(gè)屬性類
我們?nèi)ヅ渲梦募锩嬖囋嚽熬Y,看提示!
這就是自動(dòng)裝配的原理!
精髓
1、SpringBoot啟動(dòng)會(huì)加載大量的自動(dòng)配置類
2、我們看我們需要的功能有沒有在SpringBoot默認(rèn)寫好的自動(dòng)配置類當(dāng)中;
3、我們再來看這個(gè)自動(dòng)配置類中到底配置了哪些組件;(只要我們要用的組件存在在其中,我們就不需要再手動(dòng)配置了)
4、給容器中自動(dòng)配置類添加組件的時(shí)候,會(huì)從properties類中獲取某些屬性。我們只需要在配置文件中指定這些屬性的值即可;
**xxxxAutoConfigurartion:自動(dòng)配置類;**給容器中添加組件
xxxxProperties:封裝配置文件中相關(guān)屬性;
了解:@Conditional
了解完自動(dòng)裝配的原理后,我們來關(guān)注一個(gè)細(xì)節(jié)問題,自動(dòng)配置類必須在一定的條件下才能生效;
@Conditional派生注解(Spring注解版原生的@Conditional作用)
作用:必須是@Conditional指定的條件成立,才給容器中添加組件,配置配里面的所有內(nèi)容才生效;
那么多的自動(dòng)配置類,必須在一定的條件下才能生效;也就是說,我們加載了這么多的配置類,但不是所有的都生效了。
我們怎么知道哪些自動(dòng)配置類生效?
我們可以通過啟用 debug=true屬性;來讓控制臺打印自動(dòng)配置報(bào)告,這樣我們就可以很方便的知道哪些自動(dòng)配置類生效;
#開啟springboot的調(diào)試類debug=truePositive matches:(自動(dòng)配置類啟用的:正匹配)
Negative matches:(沒有啟動(dòng),沒有匹配成功的自動(dòng)配置類:負(fù)匹配)
Unconditional classes: (沒有條件的類)
【演示:查看輸出的日志】
掌握吸收理解原理,即可以不變應(yīng)萬變!
SpringBoot web
1.導(dǎo)入靜態(tài)資源
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) {if (!this.resourceProperties.isAddMappings()) {// 已禁用默認(rèn)資源處理logger.debug("Default resource handling disabled");return;}// 緩存控制Duration cachePeriod = this.resourceProperties.getCache().getPeriod();CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();// webjars 配置if (!registry.hasMappingForPattern("/webjars/**")) {customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));}// 靜態(tài)資源配置String staticPathPattern = this.mvcProperties.getStaticPathPattern();if (!registry.hasMappingForPattern(staticPathPattern)) {customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern).addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));} }使用webjars
Webjars本質(zhì)就是以jar包的方式引入我們的靜態(tài)資源 , 我們以前要導(dǎo)入一個(gè)靜態(tài)資源文件,直接導(dǎo)入即可。
使用SpringBoot需要使用Webjars,我們可以去搜索一下:
網(wǎng)站:https://www.webjars.org
要使用jQuery,我們只要要引入jQuery對應(yīng)版本的pom依賴即可!
<dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.4.1</version></dependency>導(dǎo)入完畢,查看webjars目錄結(jié)構(gòu),并訪問Jquery.js文件!
訪問:只要是靜態(tài)資源,SpringBoot就會(huì)去對應(yīng)的路徑尋找資源,我們這里訪問:http://localhost:8080/webjars/jquery/3.4.1/jquery.js
在目錄中
以下四個(gè)目錄存放的靜態(tài)資源可以被我們識別:
"classpath:/META-INF/resources/"“classpath:/resources/""classpath:/static/""classpath:/public/"原文
總結(jié)
以上是生活随笔為你收集整理的SpringBoot入门学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(1263):post方式的参数
- 下一篇: 前端学习(756):javascript