使用 Spring Boot 構建應用程式

本指南展示了 Spring Boot 如何幫助您加速應用程式開發。隨著您閱讀更多 Spring 入門指南,您將看到更多 Spring Boot 的用例。本指南旨在讓您快速體驗 Spring Boot。如果您想建立自己的基於 Spring Boot 的專案,請訪問 Spring Initializr,填寫您的專案詳細資訊,選擇您的選項,然後下載一個打包好的專案作為 zip 檔案。

您將構建什麼

您將使用 Spring Boot 構建一個簡單的 Web 應用程式,併為其新增一些有用的服務。

你需要什麼

如何完成本指南

與大多數 Spring 入門指南一樣,您可以從頭開始並完成每個步驟,也可以跳過您已熟悉的基本設定步驟。無論哪種方式,您最終都會得到可工作的程式碼。

從頭開始,請轉到從 Spring Initializr 開始

跳過基礎知識,請執行以下操作

完成後,您可以將您的結果與 gs-spring-boot/complete 中的程式碼進行核對。

瞭解您可以使用 Spring Boot 做些什麼

Spring Boot 提供了一種快速構建應用程式的方法。它會檢查您的類路徑和您配置的 bean,對您缺少的部分做出合理的假設,並新增這些項。使用 Spring Boot,您可以更專注於業務功能,而不是基礎設施。

以下示例展示了 Spring Boot 可以為您做些什麼

  • Spring MVC 是否在類路徑上?您幾乎總是需要一些特定的 bean,Spring Boot 會自動新增它們。Spring MVC 應用程式還需要一個 servlet 容器,因此 Spring Boot 會自動配置嵌入式 Tomcat。

  • Jetty 是否在類路徑上?如果是,您可能不想要 Tomcat,而是想要嵌入式 Jetty。Spring Boot 會為您處理這個問題。

  • Thymeleaf 是否在類路徑上?如果是,那麼您的應用程式上下文中必須始終新增一些 bean。Spring Boot 會為您新增它們。

這些只是 Spring Boot 提供的自動配置的幾個示例。同時,Spring Boot 不會妨礙您。例如,如果 Thymeleaf 在您的路徑上,Spring Boot 會自動將一個 SpringTemplateEngine 新增到您的應用程式上下文中。但是,如果您定義自己的 SpringTemplateEngine 並使用您自己的設定,Spring Boot 就不會新增一個。這使您可以在不費吹灰之力的情況下進行控制。

Spring Boot 不會生成程式碼或編輯您的檔案。相反,當您啟動應用程式時,Spring Boot 會動態地連線 bean 和設定,並將它們應用於您的應用程式上下文。

從 Spring Initializr 開始

您可以使用這個預初始化專案並點選生成下載 ZIP 檔案。此專案已配置為符合本教程中的示例。

手動初始化專案

  1. 導航到 https://start.spring.io。此服務會為您拉取應用程式所需的所有依賴項,併為您完成大部分設定。

  2. 選擇 Gradle 或 Maven 以及您想要使用的語言。

  3. 點選 Dependencies 並選擇 Spring Web

  4. 單擊生成

  5. 下載生成的 ZIP 檔案,這是一個已根據您的選擇配置好的 Web 應用程式存檔。

如果您的 IDE 集成了 Spring Initializr,您可以從 IDE 中完成此過程。
您還可以從 GitHub fork 專案,並在您的 IDE 或其他編輯器中開啟它。

建立簡單的 Web 應用程式

現在您可以為簡單的 Web 應用程式建立一個 Web 控制器,如以下清單所示

Java
package com.example.springboot;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

	@GetMapping("/")
	public String index() {
		return "Greetings from Spring Boot!";
	}

}
Kotlin
package com.example.springboot

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class HelloController {
    @GetMapping("/")
    fun index(): String = "Greetings from Spring Boot!"
}

該類被標記為 @RestController,這意味著它已準備好供 Spring MVC 處理 Web 請求。@GetMapping/ 對映到 index() 方法。當從瀏覽器或使用命令列上的 curl 呼叫時,該方法返回純文字。這是因為 @RestController 結合了 @Controller@ResponseBody,這兩個註解導致 Web 請求返回資料而不是檢視。

建立應用程式類

Spring Initializr 為您建立了一個簡單的應用程式類。但是,在這種情況下,它過於簡單。您需要修改應用程式類以匹配以下清單

Java
package com.example.springboot;

import java.util.Arrays;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

	@Bean
	public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
		return args -> {

			System.out.println("Let's inspect the beans provided by Spring Boot:");

			String[] beanNames = ctx.getBeanDefinitionNames();
			Arrays.sort(beanNames);
			for (String beanName : beanNames) {
				System.out.println(beanName);
			}

		};
	}

}
Kotlin
package com.example.springboot

import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.Bean

@SpringBootApplication
class Application {

    @Bean
    fun commandLineRunner(ctx: ApplicationContext) = CommandLineRunner {
        println("Let's inspect the beans provided by Spring Boot:")
        val beanNames = ctx.beanDefinitionNames
        beanNames.sorted().forEach { println(it) }
    }
}

fun main(args: Array<String>) {
    runApplication<Application>(*args)
}

@SpringBootApplication 是一個方便的註解,它添加了以下所有內容

  • @Configuration:將類標記為應用程式上下文的 bean 定義源。

  • @EnableAutoConfiguration:告訴 Spring Boot 根據類路徑設定、其他 bean 和各種屬性設定開始新增 bean。例如,如果 spring-webmvc 在類路徑中,此註解會將應用程式標記為 Web 應用程式並激活關鍵行為,例如設定 DispatcherServlet

  • @ComponentScan:告訴 Spring 在 com/example 包中查詢其他元件、配置和服務,使其能夠找到控制器。

main() 方法使用 Spring Boot 的 SpringApplication.run() 方法啟動應用程式。您是否注意到沒有一行 XML?也沒有 web.xml 檔案。這個 Web 應用程式是 100% 純 Java,您不必處理任何管道或基礎設施的配置。

還有一個標記為 @BeanCommandLineRunner 方法,它在啟動時執行。它檢索由您的應用程式建立或由 Spring Boot 自動新增的所有 bean。它對它們進行排序並打印出來。

執行應用程式

要執行應用程式,請在終端視窗目錄中執行以下命令

./gradlew bootRun

如果您使用 Maven,請在終端視窗目錄中執行以下命令

./mvnw spring-boot:run

您應該會看到類似以下的輸出

Let's inspect the beans provided by Spring Boot:
application
applicationAvailability
applicationTaskExecutor
applicationTaskExecutorAsyncConfigurer
basicErrorController
beanNameHandlerMapping
beanNameViewResolver
...

您可以看到 org.springframework.boot.autoconfigure bean。還有一個 tomcatServletWebServerFactory

現在使用 curl(在單獨的終端視窗中)透過執行以下命令(顯示其輸出)來執行服務

$ curl https://:8080
Greetings from Spring Boot!

新增單元測試

您將希望為您新增的端點新增測試,Spring Test 為此提供了一些機制。

如果您使用 Gradle,請將以下依賴項新增到您的 build.gradle(.kts) 檔案中

Groovy
testImplementation('org.springframework.boot:spring-boot-starter-test')
Kotlin
testImplementation("org.springframework.boot:spring-boot-starter-test")

如果您使用 Maven,請將以下內容新增到您的 pom.xml 檔案中

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

現在編寫一個簡單的單元測試,透過您的端點模擬 servlet 請求和響應,如以下清單所示

Java
package com.example.springboot;

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {

	@Autowired
	private MockMvc mvc;

	@Test
	public void getHello() throws Exception {
		mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
				.andExpect(status().isOk())
				.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
	}
}
Kotlin
package com.example.springboot

import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.get

@SpringBootTest
@AutoConfigureMockMvc
class HelloControllerTest {

    @Autowired
    private lateinit var mvc: MockMvc

    @Test
    fun getHello() {
        mvc.get("/") {
            accept(MediaType.APPLICATION_JSON)
        }.andExpect {
            status { isOk() }
            content { string("Greetings from Spring Boot!") }
        }
    }
}

MockMvc 來自 Spring Test,它允許您透過一組方便的構建器類將 HTTP 請求傳送到 DispatcherServlet 並對結果進行斷言。請注意使用 @AutoConfigureMockMvc@SpringBootTest 注入 MockMvc 例項。使用 @SpringBootTest 後,我們要求建立整個應用程式上下文。另一種方法是使用 @WebMvcTest 讓 Spring Boot 只建立上下文的 Web 層。在這兩種情況下,Spring Boot 都會自動嘗試定位應用程式的主要應用程式類,但如果您想構建不同的東西,可以覆蓋它或縮小範圍。

除了模擬 HTTP 請求週期之外,您還可以使用 Spring Boot 編寫一個簡單的全棧整合測試。例如,除了(或同時)前面顯示的模擬測試之外,我們可以建立以下測試

Java
package com.example.springboot;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerITest {

	@Autowired
	private TestRestTemplate template;

    @Test
    public void getHello() throws Exception {
        ResponseEntity<String> response = template.getForEntity("/", String.class);
        assertThat(response.getBody()).isEqualTo("Greetings from Spring Boot!");
    }
}
Kotlin
package com.example.springboot

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.boot.test.web.client.getForEntity

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class HelloControllerITest {

    @Autowired
    private lateinit var template: TestRestTemplate

    @Test
    fun getHello() {
        val response = template.getForEntity<String>("/")
        assertThat(response.body).isEqualTo("Greetings from Spring Boot!")
    }
}

嵌入式伺服器在隨機埠上啟動,因為 webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,並且實際埠在 TestRestTemplate 的基本 URL 中自動配置。

新增生產級服務

如果您正在為您的業務構建網站,您可能需要新增一些管理服務。Spring Boot 透過其 actuator 模組提供了幾個此類服務(例如健康、審計、bean 等)。

如果您使用 Gradle,請將以下依賴項新增到您的 build.gradle(.kts) 檔案中

Groovy
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Kotlin
implementation("org.springframework.boot:spring-boot-starter-actuator")

如果您使用 Maven,請將以下依賴項新增到您的 pom.xml 檔案中

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

然後重新啟動應用程式。如果您使用 Gradle,請在終端視窗中執行以下命令

./gradlew bootRun

如果您使用 Maven,請在終端視窗中執行以下命令

./mvnw spring-boot:run

您應該會看到應用程式已添加了一組新的 RESTful 端點。這些是 Spring Boot 提供的管理服務。以下清單顯示了典型的輸出

management.endpoint.configprops-org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointProperties
management.endpoint.env-org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointProperties
management.endpoint.health-org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties
management.endpoint.logfile-org.springframework.boot.actuate.autoconfigure.logging.LogFileWebEndpointProperties
management.endpoints.jmx-org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointProperties
management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties
management.endpoints.web.cors-org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties
management.health.diskspace-org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthIndicatorProperties
management.info-org.springframework.boot.actuate.autoconfigure.info.InfoContributorProperties
management.metrics-org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties
management.metrics.export.simple-org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleProperties
management.server-org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties

執行器暴露以下內容

還有一個 /actuator/shutdown 端點,但預設情況下,它只能透過 JMX 可見。要將其作為 HTTP 端點啟用,請將 management.endpoint.shutdown.enabled=true 新增到您的 application.properties 檔案中,並透過 management.endpoints.web.exposure.include=health,info,shutdown 暴露它。但是,您可能不應為公開可用的應用程式啟用 shutdown 端點。

您可以透過執行以下命令檢查應用程式的健康狀況

$ curl https://:8080/actuator/health
{"status":"UP"}

您還可以嘗試透過 curl 呼叫 shutdown,以檢視當您未將必要的行(如前面的註釋所示)新增到 application.properties 時會發生什麼

$ curl -X POST https://:8080/actuator/shutdown
{"timestamp":1401820343710,"error":"Not Found","status":404,"message":"","path":"/actuator/shutdown"}

由於我們沒有啟用它,所以請求的端點不可用(因為該端點不存在)。

有關這些 REST 端點中的每一個的更多詳細資訊以及如何使用 application.properties 檔案(在 src/main/resources 中)調整其設定,請參閱有關端點的文件

檢視 Spring Boot 的啟動器

您已經看到了一些 Spring Boot 的“啟動器”。您可以在此處檢視所有啟動器。

JAR 支援

最後一個示例展示了 Spring Boot 如何讓您連線您可能不知道需要的 bean。它還展示瞭如何開啟方便的管理服務。

但是,Spring Boot 不僅僅如此。得益於 Spring Boot 的 loader 模組,它不僅支援傳統的 WAR 檔案部署,還允許您組合可執行 JAR。各種指南透過 spring-boot-gradle-pluginspring-boot-maven-plugin 展示了這種雙重支援。

總結

恭喜!您使用 Spring Boot 構建了一個簡單的 Web 應用程式,並瞭解了它如何加速您的開發程序。您還開啟了一些便捷的生產服務。這只是 Spring Boot 功能的一小部分。有關更多資訊,請參閱Spring Boot 的線上文件

另請參閱

以下指南也可能有所幫助

想寫新指南或為現有指南做貢獻嗎?請檢視我們的貢獻指南

所有指南的程式碼均採用 ASLv2 許可,文字內容採用署名-禁止演繹知識共享許可

獲取程式碼

免費

在雲端工作

在 Spring Academy 的雲端完成本指南。

前往 Spring Academy