Spring-Boot:6分鐘掌握SpringBoot開發
構建項目
從技術角度來看,我們要用Spring MVC來處理Web請求,用Thymeleaf來定義Web視圖,用Spring Data JPA來把閱讀列表持久化到數據庫裏,姑且先用嵌入式的H2數據庫。
1、項目搭建
Spring IO 官網搭建
我們可以進入到Spring 的官網:http://start.spring.io/
進入官網後,可以快速的構建Spring boot 的基礎項目,這裏可以選擇Maven 項目或者Gradle 項目,然後設置項目相關的配置。
在選擇Generate Project 進行項目下載後,會生成對應的zip 文件。後續只需要將Zip 文件解壓,添加到IDE 中即可。
IDEA 快速構建
除了在SpringIO 官網進行項目初始化外,還可以通過IDEA 進行項目的搭建。如下圖所示,項目的搭建也是引用了 http://start.spring.io/
在後續的頁面中,我們可以設置相關的配置信息,一些常用的依賴,也可以進行初始化。
Spring Boot CLI
除了以上常用的項目創建方法以外,我們還可以通過CLI 進行項目的創建:
spring init -dweb,data-jpa,h2,thymeleaf --build gradle readinglist
CLI的init命令是不能指定項目根包名和項目名的。包名默認是demo,項目名默認是Demo。
2、目錄結構
不管我們采用哪種方式進行項目的創建,在將項目導入IDE之後,我們可以看到整個項目結構遵循傳統Maven或Gradle項目的布局,即主要應用程序代碼位於src/main/java目錄裏,資源都在src/main/resources目錄裏,測試代碼則在src/test/java目錄裏。此刻還沒有測試資源,但如果有的話,要放在src/test/resources裏。
文件介紹:
- SpringBootWebApplication: 應用程序的啟動引導類(bootstrap class),也是主要的Spring 配置類。
- appliction.properties:用於配置應用程序和Spring boot 的屬性
- SpringBootWebApplicationTests:一個基本的集成測試類。
- pom.xml:項目依賴文件
3、文件介紹
SpringBootWebApplication
Application 類在Spring boot應用程序中有兩個作用:配置和啟動引導。
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication --開啟組件掃描和自動配置 public class SpringBootWebApplication { public static void main(String[] args) { SpringApplication.run(SpringBootWebApplication.class, args); -- 負責啟動引導應用程序 } }
我們在使用Spring boot 進行開發時,Application 類是我們啟動服務的入口,起到關鍵作用的是 **@SpringBootApplication** 這一註解,實際上 @SpringBootApplication 包含了三個有用的註解:
- @Configuration:標明該類使用Spring 基於Java 的配置。
- @ComponentScan:啟用組件掃描,這樣你寫的Web控制器類和其他組件才能被自動發現並註冊為Spring 應用程序上下文中的Bean。
- @EnableAutoConfiguration:這一個配置開啟了Spring boot 的自動配置。
這裏使用到main 方法是需要提供一個@EnableAutoConfiguration 註解的引導類,來引導整個應用程序的啟動。
SpringBootWebApplicationTests
項目創建時問我們創建了一個帶有上下文的測試類。
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest -- 通過SpringBoot 加載上下文 public class SpringBootWebApplicationTests { @Test public void contextLoads() { -- 測試加載的上下文 } }
application.properties
實際上,這個文件是可選的,你可以刪掉它而不影響應用程序的運行。
我們可以通過向application.properties 中添加變量,從而改變程序的默認配置。例如:
server.port=8000
server.contextPath=SpringBootWeb
在上述代碼中,我們將程序的默認端口(8080) 修改成為使用 8000 端口,並且將應用程序的項目名修改為 SpringBootWeb。
原訪問地址:
http://127.0.0.1:8080/
修改後:
http://127.0.0.1:8000/SpringBootWeb/
除此之外 還可以配置多環境的變量設置等一系列的設置:
spring.profiles.active = dev
pom.xml
在代碼清單中,我們引用了 spring-boot-starter-parent 作為上一級,這樣一來就能利用到Maven 的依賴管理功能,集成很多常用庫的依賴,並且不需要知道版本。除此之外,也使用到了開篇所提到過的起步依賴,我們只需要引入 spring-boot-starter-web 這一依賴,就可以使用到Web 中常用的包。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ... </dependencies>
如下圖所示,我們使用到的 spring-boot-starter-web 依賴中,已經集成了常用的mvc json 等相關依賴。
org.springframework.boot:spring-boot-starter-web:jar:1.5.7.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.5.7.RELEASE:compile
[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.20:compile
[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.20:compile
[INFO] | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.20:compile
[INFO] | +- org.hibernate:hibernate-validator:jar:5.3.5.Final:compile
[INFO] | | +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO] | | \- com.fasterxml:classmate:jar:1.3.4:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.10:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.0:compile
[INFO] | | \- com.fasterxml.jackson.core:jackson-core:jar:2.8.10:compile
[INFO] | +- org.springframework:spring-web:jar:4.3.11.RELEASE:compile
[INFO] | \- org.springframework:spring-webmvc:jar:4.3.11.RELEASE:compile
[INFO] | \- org.springframework:spring-expression:jar:4.3.11.RELEASE:compile
4、開發功能
4.1 定義實體類 Book
如你所見,Book類就是簡單的Java對象,其中有些描述書的屬性,還有必要的訪問方法。
@Entity註解表明它是一個JPA實體,id屬性加了@Id和@GeneratedValue註解,說明這個字段
是實體的唯一標識,並且這個字段的值是自動生成的。
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; /** * Created by weijie_huang on 2017/9/20. */ @Entity @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class Book { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String reader; private String isbn; private String title; private String author; private String description; }
4.2 定義倉庫接口 ReadRepository
通過擴展JpaRepository,ReadingListRepository直接繼承了18個執行常用持久化操作
的方法。JpaRepository是個泛型接口,有兩個參數:倉庫操作的領域對象類型,及其ID屬性的
類型。此外,我還增加了一個findByReader()方法,可以根據讀者的用戶名來查找閱讀列表。
import com.jaycekon.demo.domain.Book; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; /** * Created by weijie_huang on 2017/9/20. */ public interface ReadRepository extends JpaRepository<Book,Long> { List<Book> findByReader(String reader); }
4.3 定義控制層 ReadController
在定義好了應用程序的實體類,持久化接口後。我們還需要創建一個MVC 控制器來處理HTTP請求。
import com.jaycekon.demo.dao.ReadRepository; import com.jaycekon.demo.domain.Book; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import java.util.List; /** * Created by weijie_huang on 2017/9/20. */ @Controller public class ReadController { @Autowired private ReadRepository readRepository; @RequestMapping(value="/{reader}", method= RequestMethod.GET) public String readersBooks( @PathVariable("reader") String reader, Model model) { List<Book> readingList = readRepository.findByReader(reader); if (readingList != null) { model.addAttribute("books", readingList); } return "readingList"; } @RequestMapping(value="/{reader}", method=RequestMethod.POST) public String addToReadingList( @PathVariable("reader") String reader, Book book) { book.setReader(reader); readRepository.save(book); return "redirect:/{reader}"; } }
使用了@Controller註解,這樣組件掃描會自動將其註冊為
Spring應用程序上下文裏的一個Bean。通過@Autowired 將倉庫接口註入到控制類中。
4.4 啟動服務
在開發完成後,我們去到Application 類下,啟動main 方法。即可將應用程序啟動,然後進入到下述頁面(html 文件不細述,可通過查看源碼進行了解)。可以看到,我們的服務已經成功啟動。
4.5 流程分析
大家可能會很疑惑,為什麽我們沒有配置數據庫信息,卻沒有報異常。我們明明創建了 ReadRepository 數據庫接口,如果沒有DataSource 的話,應該是會報異常的。但是Spring boot 卻巧妙的避開了這種問題。
首先我們需要來了解一下Spring-boot-autoconfigure 這個依賴包。這個Jar包下包含了很多的配置類。例如Thymeleaf,JPA以及Mvc的相關配置。
這裏主要涉及到了Condition 接口,該接口的作用是,只有到某個條件達成後,才回對這個Bean 進行實例化。
註解:
- @ConditionalOnBean 配置了某個特定Bean
- @ConditionalOnMissingBean 沒有配置特定的Bean
- @ConditionalOnClass Classpath裏有指定的類
- @ConditionalOnMissingClass Classpath裏缺少指定的類
- @ConditionalOnExpression 給定的Spring Expression Language(SpEL)表達式計算結果為true
- @ConditionalOnJava Java的版本匹配特定值或者一個範圍值
- @ConditionalOnJndi 參數中給定的JNDI位置必須存在一個,如果沒有給參數,則要有JNDI
- @ConditionalOnProperty 指定的配置屬性要有一個明確的值
- @ConditionalOnResource Classpath裏有指定的資源
上述程序之所有沒有進行數據庫操作,主要可以參考 DataSourceAutoConfiguratio 這個類的相應配置。
@Configuration @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) @EnableConfigurationProperties({DataSourceProperties.class}) @Import({Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class}) public class DataSourceAutoConfiguration
可以看到,只有DataSource 這個類實例化之後,這個Bean才會進行實例化。我們再往下觀察可以看到 JdbcTemplateConfiguratio 也有想類似的情況。
此處看到的只是DataSourceAutoConfiguration的冰山一角,Spring Boot提供的其他自
動配置類也有很多知識沒有提到。但這已經足以說明SpringBoot如何利用條件化配置實現自動配置。
自動配置會做出以下配置決策,它們和之前的例子息息相關。
- 因為Classpath 裏有H2 , 所以會創建一個嵌入式的H2 數據庫Bean , 它的類型是
javax.sql.DataSource,JPA實現(Hibernate)需要它來訪問數據庫。
- 因為Classpath裏有Hibernate(Spring Data JPA傳遞引入的)的實體管理器,所以自動配置
會配置與Hibernate 相關的Bean , 包括Spring 的LocalContainerEntityManager-
FactoryBean和JpaVendorAdapter。
- 因為Classpath裏有Spring Data JPA,所以它會自動配置為根據倉庫的接口創建倉庫實現。
- 因為Classpath裏有Thymeleaf,所以Thymeleaf會配置為Spring MVC的視圖,包括一個
Thymeleaf的模板解析器、模板引擎及視圖解析器。視圖解析器會解析相對於Classpath根
目錄的/templates目錄裏的模板。
- 因為Classpath 裏有Spring MVC ( 歸功於Web 起步依賴), 所以會配置Spring 的
DispatcherServlet並啟用Spring MVC。
- 因為這是一個Spring MVC Web應用程序,所以會註冊一個資源處理器,把相對於Classpath
根目錄的/static目錄裏的靜態內容提供出來。(這個資源處理器還能處理/public、/resources
和/META-INF/resources的靜態內容。)
- 因為Classpath裏有Tomcat(通過Web起步依賴傳遞引用),所以會啟動一個嵌入式的Tomcat
容器,監聽8080端口。
總結
通過Spring Boot的起步依賴和自動配置,你可以更加快速、便捷地開發Spring應用程序。起步依賴幫助你專註於應用程序需要的功能類型,而非提供該功能的具體庫和版本。與此同時,自動配置把你從樣板式的配置中解放了出來。這些配置在沒有Spring Boot的Spring應用程序裏非常常見。
雖然自動配置很方便,但在開發Spring應用程序時其中的一些用法也有點武斷。要是你在配置Spring時希望或者需要有所不同,該怎麽辦?在第3章,我們將會看到如何覆蓋Spring Boot自動配置,借此達成應用程序的一些目標,還有如何運用類似的技術來配置自己的應用程序組件。
github 地址:https://github.com/jaycekon/SpringBoot
Spring-Boot:6分鐘掌握SpringBoot開發