一、開發環境
ID | 環境 | 版本 |
1 | Windows 10 專業版 | x64 1803 |
2 | JDK | 1.8.0_191 |
3 | IntelliJ IDEA | 2018.3 x64 |
4 | Maven | 3.3.9 |
5 | Spring Boot | 2.1.3.RELEASE |
二、創建項目
這里使用Intellij IDEA和Maven來創建項目。有兩種起手的方式:
- 創建一個Maven項目,自己配置pom.xml
- 使用Spring Initializr向導創建項目
方案1配置方法可以參考[
基於Maven的Spring Boot項目配置],本文重點講第二種方案。
第一步:打開Intellij IDEA

第二步:單擊 "Create New Project",新建項目

第三步:單擊"Spring Initializr"選擇使用Spring初始化向導創建項目
默認情況下需要訪問初始化服務器[
https://start.spring.io],本文中我們不使用自定義的初始化服務器,所以點擊"
Next"按鈕進入下一步。
注意:在點擊"
Next"之前要確定你的網絡可以正常訪問初始化服務器

第四步:設置項目信息,默認的模板信息如下:

我這里修改了一下信息:
- Group:com.findman
- Artifact:hello-world
- Description:Create Demo project for Spring Boot
其他項會
自動修改,修改完成后如下:

第五步:單擊“Next”,進入依賴選擇頁面

第六步:這里我們在本項目中僅做一個簡單的Web示例,所以僅需選擇"Web"類中的"web"選項

第七步:單擊"Next",進入向導的最后一個頁面,設置項目名稱和項目存儲路徑。
這里我使用默認,單擊“
Finish”完成
Spring Boot向導。

第八步:Intellij IDEA會打開向導所生成的項目
這里需要注意Maven要選擇自動導入。
Maven Project need to be imported 中選擇
Enable Auto-Import

三、項目結構
我們展開項目如下:

- HelloWorldApplication.java為項目入口,其中有入口main函數
1 package com.findman.helloworld; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 6 @SpringBootApplication 7 public class HelloWorldApplication { 8 9 public static void main(String[] args) { 10 SpringApplication.run(HelloWorldApplication.class, args); 11 } 12 13 }
- HelloWorldApplicationTests為測試類,這里是一個空測試類
1 package com.findman.helloworld; 2 3 import org.junit.Test; 4 import org.junit.runner.RunWith; 5 import org.springframework.boot.test.context.SpringBootTest; 6 import org.springframework.test.context.junit4.SpringRunner; 7 8 @RunWith(SpringRunner.class) 9 @SpringBootTest 10 public class HelloWorldApplicationTests { 11 12 @Test 13 public void contextLoads() { 14 } 15 16 }
- mvnw.cmd為Maven執行腳本
- pom.xml為Maven配置文件,這里和[基於Maven的Spring Boot項目配置]手動配置相似
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 <parent> 7 <groupId>org.springframework.boot</groupId> 8 <artifactId>spring-boot-starter-parent</artifactId> 9 <version>2.1.3.RELEASE</version> 10 <relativePath/> <!-- lookup parent from repository --> 11 </parent> 12 <groupId>com.findman</groupId> 13 <artifactId>hello-world</artifactId> 14 <version>0.0.1-SNAPSHOT</version> 15 <name>hello-world</name> 16 <description>Create Demo project for Spring Boot</description> 17 18 <properties> 19 <java.version>1.8</java.version> 20 </properties> 21 22 <dependencies> 23 <dependency> 24 <groupId>org.springframework.boot</groupId> 25 <artifactId>spring-boot-starter-web</artifactId> 26 </dependency> 27 28 <dependency> 29 <groupId>org.springframework.boot</groupId> 30 <artifactId>spring-boot-starter-test</artifactId> 31 <scope>test</scope> 32 </dependency> 33 </dependencies> 34 35 <build> 36 <plugins> 37 <plugin> 38 <groupId>org.springframework.boot</groupId> 39 <artifactId>spring-boot-maven-plugin</artifactId> 40 </plugin> 41 </plugins> 42 </build> 43 44 </project>
四、創建Hello World控制器
1、新建"HelloWorldController"控制器

包路徑為
com.findman.helloworld.controller
代碼如下:
1 package com.findman.helloworld.controller; 2 3 import org.springframework.stereotype.Controller; 4 import org.springframework.web.bind.annotation.RequestMapping; 5 import org.springframework.web.bind.annotation.ResponseBody; 6 7 /** 8 * HelloWorldController HelloWorld 9 * 10 * @author:findman@gmail.com 11 * @create: 2019-02-17 01:52 12 * @version: 1.0 13 **/ 14 @Controller 15 public class HelloWorldController { 16 17 /** 18 * helloWorld路由響應函數 19 * @return 20 * 返回Hello World!字符串 21 */ 22 @ResponseBody 23 @RequestMapping("/helloWorld") 24 public String helloWorld() { 25 return "Hello World!"; 26 } 27 }
2、運行測試
- 點擊工具欄運行

- 打開HelloWorldApplication,在main函數上右鍵單擊選擇"Run"HelloWorldApplicatio..""

執行成功會在Console窗口看到如下執行結果:
1 . ____ _ __ _ _ 2 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ 3 ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ 4 \\/ ___)| |_)| | | | | || (_| | ) ) ) ) 5 ' |____| .__|_| |_|_| |_\__, | / / / / 6 =========|_|==============|___/=/_/_/_/ 7 :: Spring Boot :: (v2.1.3.RELEASE) 8 9 2019-02-17 02:05:35.811 INFO 15544 --- [ main] c.f.helloworld.HelloWorldApplication : Starting HelloWorldApplication on FINDMAN-HOME with PID 15544 (F:\Projects\2019\01\SpringBootStudy\hello-world\target\classes started by Administrator in F:\Projects\2019\01\SpringBootStudy\hello-world) 10 2019-02-17 02:05:35.814 INFO 15544 --- [ main] c.f.helloworld.HelloWorldApplication : No active profile set, falling back to default profiles: default 11 2019-02-17 02:05:36.627 INFO 15544 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 12 2019-02-17 02:05:36.645 INFO 15544 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 13 2019-02-17 02:05:36.645 INFO 15544 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.16] 14 ............ 15 2019-02-17 02:05:36.773 INFO 15544 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 16 2019-02-17 02:05:36.774 INFO 15544 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 924 ms 17 2019-02-17 02:05:36.939 INFO 15544 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 18 2019-02-17 02:05:37.084 INFO 15544 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 19 2019-02-17 02:05:37.086 INFO 15544 --- [ main] c.f.helloworld.HelloWorldApplication : Started HelloWorldApplication in 1.578 seconds (JVM running for 2.441)
從執行日志可知,啟動的Tomcat端口為8080,而我們所定義的路由為"helloWorld"。我們在瀏覽器輸入
http://localhost:8080/helloWorld 可查看到控制器所返回的結果:

至此第一個Spring Boot程序運行成功。
五、揭秘HelloWorldController的自動加載
為什么HelloWorldController創建后能夠被Spring Boot自動載入呢?
1、揭開@SpringBootApplication注解的面紗
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Inherited 5 @SpringBootConfiguration 6 @EnableAutoConfiguration 7 @ComponentScan(excludeFilters = { 8 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), 9 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) 10 public @interface SpringBootApplication {
查看@SpringBootApplication的源碼,我們發現它還自帶了一大串的其他注解。在這些注解中,可以很容易發現@EnableAutoConfiguration的注解。這里大膽的猜測這個注解和自動配置有關。
2、自動配置注解@EnableAutoConfiguration
又一個自動配置相關的注解@AutoConfigurationPackage
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Inherited 5 @AutoConfigurationPackage 6 @Import(AutoConfigurationImportSelector.class) 7 public @interface EnableAutoConfiguration {
3、自動配置包注解@AutoConfigurationPackage
看到Import導入類AutoConfigurationPackages.Registrar.class了。接近真相。
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Inherited 5 @Import(AutoConfigurationPackages.Registrar.class) 6 public @interface AutoConfigurationPackage { 7 8 }
4、AutoConfigurationPackages.Registrar.class
1 static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { 2 3 @Override 4 public void registerBeanDefinitions(AnnotationMetadata metadata, 5 BeanDefinitionRegistry registry) { 6 register(registry, new PackageImport(metadata).getPackageName()); 7 }
5、registerBeanDefinitions函數
我們debug一下看看它拿到什么包名。

計算一下:

由此可知SpringBoot啟動時會掃描main函數所在類包下的bean容器。
7、HelloWorldController是一個容器嗎?
1 @Controller 2 public class HelloWorldController {
8、@Controller注解
1 @Target({ElementType.TYPE}) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Component 5 public @interface Controller {
@Controller注解中包含@Component注解。它是個容器,所以能夠被SpringBoot掃描到。從而實現自動注冊。
Over!