使用 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 提供了一種快速構建應用的方式。它檢視您的 classpath 和您配置的 bean,對您缺失的部分做出合理的假設,並新增這些項。使用 Spring Boot,您可以更專注於業務功能,而無需過多關注基礎設施。

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

  • Spring MVC 在 classpath 中嗎?有幾個特定的 bean 您幾乎總是需要,Spring Boot 會自動新增它們。Spring MVC 應用也需要一個 servlet 容器,因此 Spring Boot 會自動配置嵌入式 Tomcat。

  • Jetty 在 classpath 中嗎?如果是,您可能不想要 Tomcat,而是想要嵌入式 Jetty。Spring Boot 會為您處理好這一點。

  • Thymeleaf 在 classpath 中嗎?如果是,有幾個 bean 必須始終新增到您的應用上下文中。Spring Boot 會為您新增它們。

這些只是 Spring Boot 提供自動配置的一些示例。同時,Spring Boot 不會妨礙您。例如,如果 Thymeleaf 在您的路徑中,Spring Boot 會自動向您的應用上下文新增一個 SpringTemplateEngine。但是,如果您使用自己的設定定義了自己的 SpringTemplateEngine,Spring Boot 則不會新增。這讓您只需少量努力即可保持控制。

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

從 Spring Initializr 開始

您可以使用這個 預先初始化的專案,然後點選 Generate 下載一個 ZIP 檔案。這個專案已配置好以適配本教程中的示例。

手動初始化專案

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

  2. 選擇 Gradle 或 Maven,以及您想要使用的語言。本指南假設您選擇了 Java。

  3. 點選 Dependencies(依賴),然後選擇 Spring Web

  4. 點選 Generate(生成)。

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

如果您的 IDE 集成了 Spring Initializr,您可以在 IDE 中完成此過程。
您也可以從 Github Fork 該專案並在您的 IDE 或其他編輯器中開啟。
對於 Spring 3.0,無論您是否使用 Spring Initializr,都需要 Java 17 或更高版本。

建立一個簡單的 Web 應用

現在您可以為簡單的 Web 應用建立一個 Web 控制器,如以下列表所示(來自 src/main/java/com/example/springboot/HelloController.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!";
	}

}

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

建立一個 Application 類

Spring Initializr 為您建立了一個簡單的應用類。然而,在這個例子中,它過於簡單。您需要修改應用類以匹配以下列表(來自 src/main/java/com/example/springboot/Application.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);
			}

		};
	}

}

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

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

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

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

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

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

執行應用

要執行應用,請在終端視窗(在 complete 目錄下)執行以下命令

./gradlew bootRun

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

./mvnw spring-boot:run

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

Let's inspect the beans provided by Spring Boot:
application
beanNameHandlerMapping
defaultServletHandlerMapping
dispatcherServlet
embeddedServletContainerCustomizerBeanPostProcessor
handlerExceptionResolver
helloController
httpRequestHandlerAdapter
messageSource
mvcContentNegotiationManager
mvcConversionService
mvcValidator
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration$DispatcherServletConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration$EmbeddedTomcat
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration
org.springframework.boot.context.embedded.properties.ServerProperties
org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
propertySourcesBinder
propertySourcesPlaceholderConfigurer
requestMappingHandlerAdapter
requestMappingHandlerMapping
resourceHandlerMapping
simpleControllerHandlerAdapter
tomcatEmbeddedServletContainerFactory
viewControllerHandlerMapping

您可以清楚地看到 org.springframework.boot.autoconfigure bean。還有一個 tomcatEmbeddedServletContainerFactory

現在使用 curl 執行服務(在另一個終端視窗中),執行以下命令(及其輸出)

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

新增單元測試

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

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

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 請求和響應,如以下列表所示(來自 src/test/java/com/example/springboot/HelloControllerTest.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!")));
	}
}

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

除了模擬 HTTP 請求生命週期外,您還可以使用 Spring Boot 編寫一個簡單的全棧整合測試。例如,除了(或代替)前面展示的模擬測試,我們可以建立以下測試(來自 src/test/java/com/example/springboot/HelloControllerITest.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!");
    }
}

由於設定了 webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,嵌入式伺服器會在一個隨機埠上啟動,實際埠會自動配置到 TestRestTemplate 的基礎 URL 中。

新增生產級服務

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

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

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,請在終端視窗(在 complete 目錄下)執行以下命令

./gradlew bootRun

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

./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 暴露了以下端點

還有一個 /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 的 Starter

JAR 支援

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

然而,Spring Boot 的功能不止於此。它不僅支援傳統的 WAR 檔案部署,還藉助 Spring Boot 的 loader 模組讓您能夠打包成可執行的 JAR 檔案。各種指南透過 spring-boot-gradle-pluginspring-boot-maven-plugin 展示了這種雙重支援。

總結

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

另請參閱

以下指南也可能有所幫助

想編寫新的指南或為現有指南貢獻內容?請查閱我們的貢獻指南

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

獲取程式碼

免費

在雲端工作

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

前往 Spring 學院