1. 程式人生 > >SpringBoot in Action——專案構建

SpringBoot in Action——專案構建

SpringBoot結構

通常情況下,你建立的spring boot的結構如下: 在這裡插入圖片描述

  • build.gradle:當然build.gradle也可以換為pom,xml。
  • Application.java:一個帶有main()方法的類,用於引導啟動應用程式。
  • ApplicationTest.java:一個空的JUnit測試類,它載入了一個使用Spring boot自動配置功能的Spring應用上下文。
  • application.properties:一個空的properties檔案,你可以根據需要新增配置屬性。
  • static目錄:放置Web應用程式的靜態內容(如javascript、樣式表css、圖片等等)。
  • templates目錄:用於呈現模型資料的模版。

開發第一個應用程式

在本書,我們會構建一個簡單的閱讀列表應用程式。在這個程式裡,使用者可以輸入想讀的圖書資訊,檢視列表,刪除已經讀過的書。我們將使用Spring boot來開發。 從技術角度來看,我們要使用Spring Mvc來處理Web請求,用Thymeleaf來定義Web檢視,用Spring Data JPA來把閱讀列表持久化到資料庫裡,姑且先用嵌入式的H2資料庫。

啟動引導Spring

package readinglist;
import org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ReadingListApplication { public static void main(String[] args) { SpringApplication.run(ReadingListApplication.class, args); } }

這裡的@SpringBootApplication開啟了元件掃描和自動配置功能,實際上,它糅合了三個有用的註解:

  • Spring的@Configuration
    :表示它是配置類。
  • Spring的@ComponentScan:開啟元件掃描
  • Spring Boot的@EnableAutoConfiguration:開啟自動配置,這個不起眼的註釋也可以稱為@Abracadabra,仔細念,就像魔咒一樣,讓你不用再寫成篇的配置了。

配置應用程式屬性 application.properties可以幫助你細粒度的調整Spring boot的自動配置,比如你可以新增一行: server.port=8000 加上這樣一行,你的嵌入式Tomcat的監聽埠就變成了8000,而不是預設的8080.

Spring Boot依賴

覆蓋起步依賴引入的傳遞依賴

以Spring Boot的Web起步依賴為例,它傳遞依賴了Jackson JSON庫。如果你正在構建一個生產或消費JSON資源表述的REST服務,那它會很有用。但是,要構建傳統的面向人類使用者的Web應用程式,你可能用不上Jackson。雖然把它加進來也不會有什麼壞處,但排除掉它的傳遞依賴,可以為你的專案瘦身。 如果在用Gradle,你可以這樣排除傳遞依賴:

compile("org.springframework.boot:spring-boot-starter-web") {
exclude group: 'com.fasterxml.jackson.core'
}

在Maven裡,可以用<exclusions>元素來排除傳遞依賴。下面這個引入Spring Boot的build.gradle的<dependency>增加了<exclusions>元素去除Jackson:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
		<exclusions>
			<exclusion>
				<groupId>com.fasterxml.jackson.core</groupId>
			</exclusion>
		</exclusions>
</dependency>

另一方面,也許專案需要Jackson,但你需要用另一個版本的Jackson來進行構建,而不是Web起步依賴裡的那個。假設Web起步依賴引用了Jackson 2.3.4,但你需要使用2.4.3。在Maven裡,你可以直接在pom.xml中表達訴求,就像這樣:

<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.4.3</version>
</dependency>

Maven總是會用最近的依賴,也就是說,你在專案的構建說明檔案裡增加的這個依賴,會覆蓋傳遞依賴引入的另一個依賴。與之類似,如果你用的是Gradle,可以在build.gradle檔案裡指明你要的Jackson的版本: compile("com.fasterxml.jackson.core:jackson-databind:2.4.3") 因為這個依賴的版本比Spring Boot的Web起步依賴引入的要新,所以在Gradle裡是生效的。

使用自動配置

Spring Boot的自動配置是一個執行時(更準確地說,是應用程式啟動時)的過程,考慮了眾多因素,才決定Spring配置應該用哪個,不該用哪個。

專注於應用程式功能

我們學習Spring和Spring mvc,往往需要在Configuration裡面配置一堆template、factory、datasource。而且要使用一堆@Bean進行顯示宣告。 顯然,如果我們不知道有Spring boot這種東西,我們還能忍受一堆和實際程式碼無關的配置,但是既然有這種自動配置,我們為什麼還要忍耐呢?

但是在沒有配置程式碼的情況下,很難描述自動配置。與其花時間討論那些你不用做的事情,不如在這一節裡關注一下你要做的事——寫程式碼。 在嚮應用程式加入Spring Boot時,有個名為spring-boot-autoconfigure的JAR檔案,其中包含了很多配置類。每個配置類都在應用程式的Classpath裡,都有機會為應用程式的配置添磚加瓦。 這些配置類裡有用於Thymeleaf的配置,有用於Spring Data JPA的配置,有用於Spiring MVC的配置,還有很多其他東西的配置,你可以自己選擇是否在Spring應用程式裡使用它們。

在Spring裡可以很方便地編寫你自己的條件,你所要做的就是實現Condition介面,覆蓋它的matches()方法。

舉例來說,下面這個簡單的條件類只有在Classpath裡存在JdbcTemplate時才會生效:

package readinglist;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class JdbcTemplateCondition implements Condition {
	@Override
	public boolean matches(ConditionContext context,
		AnnotatedTypeMetadata metadata) {
	try {
		context.getClassLoader().loadClass(
			"org.springframework.jdbc.core.JdbcTemplate");
		return true;
	} catch (Exception e) {
		return false;}
	}
}

當你用Java來宣告Bean的時候,可以使用這個自定義條件類:

@Conditional(JdbcTemplateCondition.class)
public MyService myService() {
...
}

在這個例子裡,只有當JdbcTemplateCondition類的條件成立時才會建立MyService這個Bean。也就是說MyService Bean建立的條件是Classpath裡有JdbcTemplate。否則,這個Bean的宣告就會被忽略掉。 在這裡插入圖片描述

我們來看看Spring boot自動配置的原始碼:

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {
...
}

如你所見,DataSourceAutoConfiguration添加了@Configuration註解,它從其他配置類裡匯入了一些額外配置,還自己定義了一些Bean。最重要的是,DataSourceAutoConfiguration上添加了@ConditionalOnClass註解,要求Classpath裡必須要有DataSource和EmbeddedDatabaseType。如果它們不存在,條件就不成立,DataSourceAutoConfiguration提供的配置都會被忽略掉。