微服務:Spring Boot第二篇——執行原理和HelloWorld
這次來通過一個DEMO程式來學習Spring Boot的執行原理,參考的書為《Spring Cloud與Docker 微服務架構實戰》,採用的版本為Java 1.8,Spring Boot 1.5.6(後改為1.5.4),IDE是STS(Spring Tool Suite).
首先以網頁的形式來生成自己需要的一個Spring Boot初始目錄,這是Spring官方提供的生成工具,各項選擇如下。
Group和Artifact的輸入會生成com.movie.example_1的目錄,右側是選擇依賴項,這裡選擇了Web,因為這是Web應用;JAP用來做資料持久化;H2為一個內嵌的小型資料庫用來儲存資料。這裡如果不選擇的話,後面需要自己在pom.xml中配置。點Generate Project,下載並解壓檔案,在STS中選擇匯入Existing Maven Project,就可以開始編寫了。
先來學習一下Maven,在上面的圖片裡,我們在Generate a後面選擇了Maven Project,就是選擇以Maven作為這個專案的管理工具。Maven的主要作用就是統一開發規範和簡化配置,先來看一下匯入後的目錄。
匯入專案過幾秒鐘之後,會自動形成入上圖所示的目錄結構,如果之前做過Java類的開發,會發現這和一般的Java工程目錄結構不太一樣,一般的工程只有一個src,自己需要
來定義哪種檔案放在哪裡,Mave自動生成了儲存原始碼和資源的目錄,進行單元測試的目錄,統一了目錄結構。
最下面有一個pom.xml,pom是Project Object Model 的縮寫,用於描述整個Maven專案,是Maven的核心檔案,其簡化配置的功能也是通過該檔案實現。下面羅列一下里面各種
標籤的作用。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.movie</groupId> <artifactId>example_1</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>example_1</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
- groupId, artifactId, version這三個東西組成了我們這個專案的座標,比如XXX公司的一個電影商業專案,可以這樣命名,groupId為com.XXX,artifactId為Movie.
- packing:專案釋出時的打包方式,預設為jar
- name和description都是使用者自己新增的專案描述
- parent,整合的父專案的標識
- property中說明了專案編碼為UTF-8,java版本為1.8
- dependency標籤中都標識了我們的專案所依賴的jar包,Maven在本地倉庫中有一些包,如果找不到就會去遠端下載。
- build用於專案配置,plugin中指定了我們使用的外掛。
package com.movie.example_1.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MovieHelloController {
@RequestMapping("/hello")
public String Hello(){
return "Hello there";
}
}
然後右鍵在自動生成的Example1Application.java上run as JavaApplication,等控制檯輸出完畢,在瀏覽器頁面輸入http://localhost:8080/hello,應該就可以看到hello there的顯示了。
(我在這裡遇見一個問題,在Example1Application.java中import spring時報錯,在stackflow上找了半天才發現是版本問題,剛開始我還以為是maven的版本衝突。我看了下昨天的程式碼,
昨天Spring Boot還是1.5.4版本,今天就變成1.5.6了,估計其他的外掛還都沒更新吧)
下面來詳細學習一下Spring Boot的執行過程,先從程式入口開始。
package com.movie.example_1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Example1Application {
public static void main(String[] args) {
SpringApplication.run(Example1Application.class, args);
}
}
@SpringBootApplication是一系列註解的組合,其中最主要的是@Configuration,@EnableAutoConfiguration,@ComponentScan三個,因為這是所謂的最佳實踐,最經常被一起這樣使用,所以Spring Boot將其合併為一個SpringBootApplication.按照我的理解,@Configuration標註一個類為配置類,建立了一個Spring IOC容器,而這個註解被建議新增到main方法上,而@EnableAutoConfiguration被建議新增到主@Configuration類上,這個註解可以根據你新增的依賴來自動判斷你的應用型別並相應的對Spring設定,@ComponentScan自動收集sub-package下有@component @service @Responsitory @controller註解的所有類,並將它們註冊為spring beans,這也是為什麼我們建立的controller和entity包和主函式同級。
SpringApplication.run的啟動非常複雜,總體來講有這幾步:
- 建立SpringApplication物件,在該物件初始化的時候根據專案裡面的某個特徵類來決定建立什麼型別的ApplicationContext,在建立的時候還會查詢和載入所有可用的ApplicationContextInitializer,查詢載入所有可用的ApplicationListener
- 執行run()方法,查詢所有SpringApplicationRunListener,呼叫他們的started()方法
- 建立並配置當前Spring Boot應用需要的Environment,然後呼叫所有SpringApplicationRunListener的environmentPrepared()方法
- 將準備好的環境設定給建立好的Applicationcontext使用,呼叫ApplicationContextInitializer的initialize方法對建立好的ApplicationContext進行進一步處理
- 呼叫所有SpringApplicationRunListener的contextPrepared方法通知他們ApplicationContext已經準備好
- 將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IOC容器載入到已經準備完畢的ApplicationContext中
- 呼叫所有SpringApplicationRunListener的contextLoaded()方法
- 呼叫所有ApplicationContext的refresh()方法
- 查詢ApplicationContext中是否有註冊CommandLineRunner(),如果有則遍歷執行它們
- 呼叫ApplicationRunListener的finished()方法
接下來看在com.movie.example_1.controller目錄下的MovieHelloController檔案,先看第一個註解@RestController,這是@Controller和@ResponseBody的一個結合體。當實現一個RESTful web services的時候,response將一直通過response body傳送。為了簡化開發,Spring 4.0提供了一個專門版本的controller就是RestController. RequestMapping是一個用來處理請求地址對映的註解,在這裡我們映射了/hello這個頁面。
寫的也不短了,作為一個HelloWorld程式就先學習這麼多,下一節學習資料庫和相關配置的原理。