最近在學習Spring Boot相關的課程,過程當中以筆記的形式記錄下來,方便之後回憶,同時也在這裏和你們探討探討,文章中有漏的或者有補充的、錯誤的都但願你們可以及時提出來,本人在此先謝謝了!java
開始以前呢,但願你們帶着幾個問題去學習:
一、SpringBoot Starter 是什麼?
二、這個功能有什麼用?
三、怎麼實現的?
四、這個功能能應用在工做中?
這是對自個人提問,我認爲帶着問題去學習,是一種更好的學習方式,有利於加深理解。好了,接下來進入主題。web
在 Spring
時代,搭建一個 Web 應用一般須要在 pom 文件中引入多個 Web 模塊相關的 Maven
依賴,如 SpringMvc
、Tomcat
等依賴,而 SpringBoot
則只需引入 spring-boot-starter-web
依賴便可。這就是 SpringBoot
的 Starter 特性,用來簡化項目初始搭建以及開發過程,它是一個功能模塊的全部 Maven 依賴集合體。接下來,咱們進行詳細討論。redis
注:本篇文章所用到的 Spring Boot版本是 2.0.3.RELEASEspring
SpringBoot
提供了很是多的 Starter,下面列出經常使用的幾個:數據庫
名稱 | 功能 |
---|---|
spring-boot-starter-web | 支持 Web 開發,包括 Tomcat 和 spring-webmvc |
spring-boot-starter-redis | 支持 Redis 鍵值存儲數據庫,包括 spring-redis |
spring-boot-starter-test | 支持常規的測試依賴,包括 JUnit、Hamcrest、Mockito 以及 spring-test 模塊 |
spring-boot-starter-aop | 支持面向切面的編程即 AOP,包括 spring-aop 和 AspectJ |
spring-boot-starter-data-elasticsearch | 支持 ElasticSearch 搜索和分析引擎,包括 spring-data-elasticsearch |
spring-boot-starter-jdbc | 支持JDBC數據庫 |
spring-boot-starter-data-jpa | 支持 JPA ,包括 spring-data-jpa、spring-orm、Hibernate |
能夠看到這些 Starter 的名稱都是以 spring-boot-starter 爲開頭,後面跟着具體的模塊名,全部官方的 Starter 遵循類似的命名模式。這些 Starter 其實不包含 Java 代碼,核心是它的 pom 文件。咱們以 spring-boot-starter-web
爲例,來看看該 Starter 的 pom 文件包含的內容。apache
先在項目中引入如下依賴:編程
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.0.3.RELEASE</version> </dependency>
而後找到引入的 spring-boot-starter-web 依賴的文件夾位置:json
打開該 pom 文件進行查看:tomcat
<?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starters</artifactId> <version>2.0.3.RELEASE</version> </parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.0.3.RELEASE</version> <name>Spring Boot Web Starter</name> ... <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.0.3.RELEASE</version> <scope>compile</scope> </dependency> <!-- 對 json 解析的支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.0.3.RELEASE</version> <scope>compile</scope> </dependency> <!-- 提供 Tomcat 容器。經過這能夠看到 ServletWeb 默認的容器是 Tomcat --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.0.3.RELEASE</version> <scope>compile</scope> </dependency> <!-- hibernate 的校驗框架 --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.10.Final</version> <scope>compile</scope> </dependency> <!-- 提供了核心 HTTP 集成,用於集成其它 web 框架的基礎結構 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.0.7.RELEASE</version> <scope>compile</scope> </dependency> <!-- 提供了對 Spring MVC 的支持 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.7.RELEASE</version> <scope>compile</scope> </dependency> </dependencies> </project>
能夠看到,在該 pom 文件中已經定義好了 Web 模塊須要的各個組件。以後,引入的 Starter 依賴能夠與 SpringBoot
的自動裝配特性、外部化配置特性進行無縫銜接,來達到快速開發的目的。關於 SpringBoot
自動裝配和外部化配置你們能夠分別參考《SpringBoot 自動裝配(二)》和《SpringBoot 外部化配置(二)》這兩篇文章。接下來,經過實現自定義的 Starter 來理解總體邏輯。
先建立一個項目,在該項目中定義 Starter 的內容,而後經過 Maven 將其打成 jar 包,以後在另外一個項目中使用該 Starter 。
一、建立一個 Maven 項目,在其 pom 文件中引入自動裝配的依賴,並定義好 Starter 的名稱。非官方的 Starter 命名需遵循 xxx-spring-boot-starter 的格式。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.loong</groupId> <artifactId>demo-spring-boot-starter</artifactId> <version>1.0.0.RELEASE</version> <name>demo</name> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.0.3.RELEASE</version> </dependency> </dependencies> </project>
二、新建一個 Properties
配置類,用於保存外部化配置文件中定義的配置數據,其中配置文件包括 properties 或 yml 。
// 定義配置文件中的屬性前綴 @ConfigurationProperties(prefix = "demo") public class DemoProperties { private String name; private String date; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } }
關於外部化配置底層實現,你們能夠參考《SpringBoot 外部化配置(二)》這篇文章。
三、新建一個功能類,主要用來返回 DemoProperties
中的 name 和 date 屬性。
public class DemoService { private DemoProperties demoProperties; public DemoService(DemoProperties demoProperties) { this.demoProperties = demoProperties; } public String getName() { return demoProperties.getName(); } public String getDate() { return demoProperties.getDate(); } }
四、建立自動配置類,在該配置類中完成 Starter 的功能。這裏,經過構造器注入 DemoProperties
配置類對象,並初始化 DemoService
功能類。
@Configuration @EnableConfigurationProperties(value = DemoProperties.class) public class DemoAutoConfiguration { private final DemoProperties demoProperties; public DemoAutoConfiguration(DemoProperties demoProperties) { this.demoProperties = demoProperties; } @Bean // 當前項目是否包含 DemoService Class @ConditionalOnMissingBean(DemoService.class) public DemoService demoService() { return new DemoService(demoProperties); } }
自動配置類是 SpringBoot
自動裝配特性不可或缺的一環,關於 SpringBoot
自動裝配底層實現,你們能夠參考《SpringBoot自動裝配(二)》這篇文章。
五、自定義初始化器和監聽器,這是 SpringBoot
提供的擴展點,主要在 SpringBoot
的不一樣生命週期執行相應操做。
public class DemoApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println(" DemoApplicationContextInitializer 初始化成功 "); } }
public class DemoApplicationListener implements ApplicationListener<SpringApplicationEvent> { @Override public void onApplicationEvent(SpringApplicationEvent springApplicationEvent) { if (springApplicationEvent instanceof ApplicationStartingEvent) { System.out.println(" DemoApplicationListener 監聽 ApplicationStartingEvent 事件"); } } }
關於初始化器和監聽器你們能夠參考《Spring Boot SpringApplication啓動類(一)》的 2.2 和 2.3 小節 。
六、在 src/main/resources 目錄下建立 META-INF 文件夾,並在文件夾中建立 spring.factories
文件,定義以下內容:
# Initializers org.springframework.context.ApplicationContextInitializer=\ com.loong.demo.context.DemoApplicationContextInitializer # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.loong.demo.configuration.DemoAutoConfiguration # Application Listeners org.springframework.context.ApplicationListener=\ com.loong.demo.listener.DemoApplicationListener
這是 SpringBoot
的規約,當咱們自定義的初始化器、監聽器及自動配置類須要被 SpringBoot
讀取時,必須定義成該格式。關於原理,在前幾篇文章說過,這裏再也不敘述。
最後,全部的類已經定義完成,項目結構以下:
打開經過右側的 Maven 工具欄,點擊 install 打包到本地的 Maven 庫。
以後,自定義的 Starter 就可使用,咱們來測試一下。
一、在另外一個項目中引入該 Starter 的 Maven 依賴:
<dependency> <groupId>com.loong</groupId> <artifactId>demo-spring-boot-starter</artifactId> <version>1.0.0.RELEASE</version> </dependency>
二、在 properties 文件中定義配置數據:
demo.name = loong demo.date = 2020.01.01
三、在啓動類中,獲取 DemoService
Bean ,並調用它的 getDate 和 getName 方法獲取配置文件中的數據:
@SpringBootApplication public class DiveInSpringBootApplication { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(DiveInSpringBootApplication.class, args); DemoService bean = run.getBean(DemoService.class); System.out.println(bean.getDate() + " === " + bean.getName()); } }
最後,查看控制檯的輸出:
/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/bin/java "-javaagent:/Applications/IntelliJ IDEA CE.app..." DemoApplicationListener 監聽 ApplicationStartingEvent 事件 . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.0.3.RELEASE) DemoApplicationContextInitializer 初始化成功 2020-01-01 13:14:02.023 INFO 55657 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2020-01-01 13:14:02.189 INFO 55657 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6b19b79: startup date [Wed Jan 01 13:13:59 CST 2020]; root of context hierarchy 2020-01-01 13:14:02.257 INFO 55657 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/hello],methods=[GET]}" onto public java.lang.String com.loong.diveinspringboot.Chapter1.controller.HelloWorldController.helloWorld(java.lang.String) 2020-01-01 13:14:02.260 INFO 55657 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2020-01-01 13:14:02.261 INFO 55657 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2020-01-01 13:14:02.296 INFO 55657 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2020-01-01 13:14:02.296 INFO 55657 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2020-01-01 13:14:02.341 WARN 55657 --- [ main] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration) 2020-01-01 13:14:02.718 INFO 55657 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator' 2020-01-01 13:14:02.726 INFO 55657 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>) 2020-01-01 13:14:02.727 INFO 55657 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>) 2020-01-01 13:14:02.728 INFO 55657 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto protected java.util.Map<java.lang.String, java.util.Map<java.lang.String, org.springframework.boot.actuate.endpoint.web.Link>> org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping.links(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2020-01-01 13:14:02.766 INFO 55657 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2020-01-01 13:14:02.822 INFO 55657 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2020-01-01 13:14:02.826 INFO 55657 --- [ main] c.l.d.C.DiveInSpringBootApplication : Started DiveInSpringBootApplication in 3.607 seconds (JVM running for 3.984) 2020.01.01 === loong
能夠看到,結果正確輸出,且初始化器和監聽器都已被加載。這裏只是一個簡單的演示,Starter 較爲簡單,你們能夠根據實際狀況實現一個更爲複雜的。
SpringBoot Starter
的內容就介紹到這,若是文章中有錯誤或者須要補充的請及時提出,本人感激涕零。