步驟
1尘喝、創(chuàng)建一個普通maven項目:SpringBootDemo
2、在pom.xml文件設置項目打包方式
<packaging>jar</packaging>
3、在pom.xml文件導入SpringBoot父項目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/>
</parent>
4、在pom.xml文件導入Web項目依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
5玄呛、編寫普通Controller類
/**
* 控制層
*/
@Controller
public class HelloController {
@RequestMapping("hello")
public Object hellp(){
return "Hello SpringBoot!";
}
}
6、編寫啟動類和二,啟動SpringBoot項目
/**
* SpringBoot項目啟動類
*/
@SpringBootApplication
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class,args);
}
}
7徘铝、瀏覽器訪問測試: http://localhost:8080/hello
問題
Web打包不應該是war,為什么是jar?
pom.xml文件中繼承的spring-boot-starter-parent有什么用惯吕?
pom.xml文件中導入的依賴spring-boot-starter-web又有什么用惕它?
啟動類SpringBootDemoApplication頭頂上的@SpringBootApplication注解做了什么?
沒有配置tomcat废登,沒有設置端口服務器怎么來怠缸,又怎么啟動的?
main方法中SpringApplication.run(..)又是什么情況钳宪?
分析
問題1:Web打包不應該是war,為什么是jar
SpringBoot默認的打包方式就是jar,傳統(tǒng)的外接tomcat或插件式tomcat與web項目是相互獨立,相互對接時必須滿足一定規(guī)則吏颖,war包結構項目就是規(guī)則約定之一搔体。而SpringBoot項目采用的是內嵌式(簡單理解為編碼方式)tomcat,項目與tomcat融為一體半醉,部署疚俱,啟動,運行一體化缩多,就沒有各種條條框框的約束了呆奕。
問題2:pom.xml文件中繼承的spring-boot-starter-parent有啥用
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/>
</parent>
spring-boot-starter-parent其實是SpringBoot提供了工具工程,工程收集了市面上常用各種第三方jar依賴衬吆,并對這些jar依賴進行了版本管理梁钾。當我們的項目繼承這個項目工程,就自動成為SpringBoot項目逊抡,并無償繼承了這些第三方jar依賴姆泻。后續(xù)項目中需要某個第三方依賴,只需要引入依賴坐標即可冒嫡, 不需要關系依賴版本拇勃。比如:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
一個拓展:
繼承是 Maven 中很強大的一種功能,繼承可以使得子POM可以獲得 parent 中的部分配置(groupId,version,dependencies,build,dependencyManagement等)孝凌,可以對子pom進行統(tǒng)一的配置和依賴管理方咆。
parent項目中的dependencyManagement里的聲明的依賴 , 只具有聲明的作用,并不實現(xiàn)引入蟀架,因此子項目需要顯式的聲明需要用的依賴瓣赂。如果不在子項目中聲明依賴,是不會從父項目中繼承下來的辜窑;只有在子項目中寫了該依賴項钩述,可以不指定具體版本,會從父項目中繼承該項穆碎,并且version和scope都讀取自父pom;另外如果子項目中指定了版本號牙勘,那么會使用子項目中指定的jar版本
parent項目中的dependencies里聲明的依賴會被所有的子項目繼承
問題3:pom.xml文件中導入的依賴spring-boot-starter-web又有啥用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
問題2中說了,SpringBoot收集了很多常用的第三方jar依賴所禀,為了進一步提高用戶體驗感方面,SpringBoot根據jar依賴特點,對這些依賴進一步分類色徘,整合恭金,再封裝,形成一個新的依賴工具集褂策, 每個工具集都解決特定領域的依賴問題横腿。SpringBoot將這些依賴工具稱為:啟動器(組件)颓屑,命名規(guī)則: spring-boot-starter-xxx。 如果是非SpringBoot定制的啟動器耿焊, 一般命名規(guī)則:xxx-spring-boot-starter
入門案例中導入的spring-boot-starter-web 就是用于解決web項目依賴的工具集(啟動器)
常用的啟動器(starter)還有很多:
spring-boot-starter: 核心啟動器 , 提供了自動配置,日志和YAML配置支持
spring-boot-starter-aop: 支持使用
Spring AOP
和AspectJ
進行切面編程揪惦。spring-boot-starter-freemarker: 支持使用
FreeMarker
視圖構建Web 應用spring-boot-starter-test: 支持使用
JUnit
, 測試Spring Boot
應用spring-boot-starter-web: 支持使用
Spring MVC
構建 Web 應用罗侯,包括RESTful
應用器腋,使用Tomcat
作為默認的嵌入式容器。spring-boot-starter-actuator: 支持使用 Spring Boot Actuator 提供生產級別的應用程序監(jiān)控和管理功能钩杰。
spring-boot-starter-logging: 提供了對日志的支持 , 默認使用Logback
問題4:啟動類App頭頂上的@SpringBootApplication注解做了什么
要回答這個問題纫塌, 就必須講清楚springboot的自動配置原理(也稱自動裝配)
springboot的精髓就在這個注解里。
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
先回顧一下以前使用SpringMVC搭建web項目時讲弄, 我們是怎么做的
1>導入Web措左, Spring, SpringMVC依賴
2>在web.xml文件配置前端控制器:DispatcherServlet
3>編寫controller類
4>配置controller掃描包路徑
5>部署到tomcat并啟動
從上面步驟上看垂睬,剛剛入門案例不需要我們去做的有幾步媳荒?
1:不需要配置前端控制器
2:不需要配置包掃描路徑
3:不需要部署tomcat這步
這些步驟我們都沒做,項目卻跑起來驹饺,那肯定有人幫我們做了钳枕,那會是誰?所有問題關鍵就是這個:@SpringBootApplication注解赏壹。
@SpringBootApplication源碼解析
點擊進入鱼炒,查看源碼:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters =
{
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
}
)
public @interface SpringBootApplication {
......
}
注解上面又有一堆注解,核心的有3個:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
這里注意:注解頭頂又貼有注解(非元注解)蝌借,表示當前注解為復合注解昔瞧,當前注解也擁有所貼注解功能。
@ComponentScan
功能:spring組件掃描注解菩佑,掃描所貼的類所在包及其子包所有貼有版型注解的類自晰,并創(chuàng)建對象交給spring容器管理。
入門案例中稍坯, 我們將@SpringBootApplication 注解貼在App類里面酬荞,那么它會掃描App類所有包及其子包里面所有貼有版型注解的類,并創(chuàng)建實例瞧哟, 那么controller包下的HelloController類就可以被掃描到混巧。
一個注意點: 一般貼有@SpringBootApplication注解的類稱之為啟動類,建議放置在根包下勤揩。
@SpringBootConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
....
}
該注解頭頂貼了@Configuration
注解咧党, 前面Javaconfig講過貼有@Configuration
類為配置類
<pre>@SpringBootApplication 頭頂貼有 @SpringBootConfiguration
@SpringBootConfiguration 頭頂貼有 @Configuration </pre>
根據上面注解關系推導下:入門案例中貼有@SpringBootApplication注解的App類就是一個項目配置類。
一個注意點:一般springboot項目只有唯一一個啟動類陨亡,啟動類都是配置類傍衡。
@EnableAutoConfiguration
@EnableAutoConfiguration
的作用深员,告訴SpringBoot基于你所添加的依賴,去“猜測”你想要如何配置Spring蛙埂。比如當我們引入了spring-boot-starter-web
這個啟動器辨液,spring會解析這個啟動器,推測當前項目為web項目箱残,根據啟動器默認配置要求自動配置web及SpringMVC相關對象創(chuàng)建與管理。比如:前端控制的創(chuàng)建止吁,比如前端控制的路徑映射等被辑。
SpringBoot對自帶啟動器與第三方啟動器進行了大量的默認配置,這些配置是否生效敬惦,是否加載到spring容器中使用盼理,取決于我們項目是否引入了對啟動器依賴,如果有那么默認配置就會生效俄删。
那么
這些默認配置是在哪里定義的呢宏怔?
為何依賴引入就會觸發(fā)配置生效呢?
看源碼:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...
}
@EnableAutoConfiguration注解import導入了一個AutoConfigurationImportSelector自動配置類選擇器畴椰,該類可以實現(xiàn)配置類批量載入 spring容器臊诊。其核心方法是getCandidateConfigurations
protected List<String> getCandidateConfigurations(
AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(),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;
}
getCandidateConfigurations方法作用是委托SpringFactoriesLoader去讀取jar包中的META-INF/spring.factories文件, 并加載里面配置的自動配置對象,其中包括: AOP / PropertyPlaceholder / FreeMarker / HttpMessageConverter / Jackson / DataSource / DataSourceTransactionManager / DispatcherServlet / WebMvc 等等斜脂。
一個注意點:不管是spring定制的啟動器抓艳,還是第三方定制的啟動器,都需要編寫META-INF/spring.factories帚戳,里面指定啟動器的自動配置類
接上面分析玷或, spring.factories文件中配置很多自動配置類,哪些會生效(加載到Spring容器并跑起來)呢, 此時需要滿足這些啟動類生效條件才會自動裝配片任。
以我們熟悉SpringMVC為例子:
在spring.factories找WebMvcAutoConfiguration自動配置類
<pre>org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration</pre>
點進去看源碼
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({
DispatcherServletAutoConfiguration.class,
TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
...
}
我們看到這個類上的4個注解:
@Configuration
:聲明這個類是一個配置類-
@ConditionalOnWebApplication(type = Type.SERVLET)
ConditionalOn偏友,翻譯就是在某個條件下,此處就是滿足項目的類是是Type.SERVLET類型对供,我們現(xiàn)在的項目就滿足了, 就是一個web服務(web項目)
-
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
這里的條件是OnClass位他,也就是滿足以下類存在:Servlet、DispatcherServlet犁钟、WebMvcConfigurer棱诱。這里就是判斷你是否引入了SpringMVC相關依賴,引入依賴后該條件成立涝动,當前類的配置才會生效迈勋!
-
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
這個條件與上面不同,OnMissingBean醋粟,是說環(huán)境中沒有指定的Bean這個才生效靡菇。其實這就是自定義配置的入口重归,也就是說,如果我們自己配置了一個WebMVCConfigurationSupport的bean, 代表容器里已經存在該bean了厦凤,那么這個默認配置就會失效鼻吮!這里允許我們定制自己的bean替換spring默認的。
接著较鼓,我們查看WebMvcAutoConfiguration該類中定義了什么:(如果它生效了椎木,會創(chuàng)建什么對象并載入容器進行管理)
視圖解析器:
@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix(this.mvcProperties.getView().getPrefix());
resolver.setSuffix(this.mvcProperties.getView().getSuffix());
return resolver;
}
@Bean
@ConditionalOnBean(View.class)
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver resolver = new BeanNameViewResolver();
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
return resolver;
}
WebMvcAutoConfiguration中使用了@AutoConfigureAfter注解, 意為指定的類加載完了后,再加載本類
<pre>@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })</pre>
而DispatcherServletAutoConfiguration中又做了很多事情, 比如配置了前端控制器
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.
isThrowExceptionIfNoHandlerFound());
dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
return dispatcherServlet;
}
總結:
@SpringBootApplication注解內部是3大注解功能的集成
@ComponentScan: 開啟組件掃描
@SpringBootConfiguration: 作用等同于@Configuration注解,也是用于標記配置類
@EnableAutoConfiguration: 內部導入AutoConfigurationImportSelector,該類中有個getCandidateConfigurations方法, 讀取jar包中META-INF/spring.factories文件中配置類, , 再根據條件進行加載和配置, 比如: AOP / PropertyPlaceholder / FreeMarker / HttpMessageConverter / Jackson / DataSource / DataSourceTransactionManager / DispatcherServlet / WebMvc 等等
問題5:沒有配置tomcat博烂,沒有設置端口服務器怎么來香椎,又怎么啟動的
SpringBoot使用嵌入式tomcat,編程實現(xiàn)禽篱,默認端口是8080畜伐,后續(xù)可以通過application.properties文件進行修改
問題6:main方法中SpringApplication.run(..)又是什么情況
SpringApplication.run(..)的作用:
啟動SpringBoot應用
加載自定義的配置類,完成自動配置功能
把當前項目部署到嵌入的Tomcat服務器
啟動Tomcat服務器跑項目
總結
SpringBoot項目完整結構
SpringBoot優(yōu)缺點
優(yōu)點:
創(chuàng)建獨立運行的Spring應用程序 ;
嵌入的Tomcat,無需部署war文件;
簡化Maven配置 ;
自動配置Spring ;
提供生產就緒型功能,如:日志,健康檢查和外部配置等;
不要求配置 XML;
非常容易和第三方框架集成起來。
缺點:
版本更新較快,可能出現(xiàn)較大變化;
因為約定大于配置,所以經常會出現(xiàn)一些很難解決的問題躺率。