Spring MVC

Spring Boot 有許多包含 Spring MVC 的 Starter。請注意,有些 Starter 包含對 Spring MVC 的依賴,而不是直接包含它。本節回答了關於 Spring MVC 和 Spring Boot 的常見問題。

編寫 JSON REST 服務

只要 Jackson 3 在類路徑上,任何 Spring Boot 應用程式中的 Spring @RestController 都應預設呈現 JSON 響應,如以下示例所示:

  • Java

  • Kotlin

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

@RestController
public class MyController {

	@RequestMapping("/thing")
	public MyThing thing() {
		return new MyThing();
	}

}
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class MyController {

	@RequestMapping("/thing")
	fun thing(): MyThing {
		return MyThing()
	}

}

只要 MyThing 可以被 Jackson 3 序列化(對於普通 POJO 或 Groovy 物件來說是如此),那麼 localhost:8080/thing 就會預設提供其 JSON 表示。請注意,在瀏覽器中,您有時可能會看到 XML 響應,因為瀏覽器傾向於傳送優先使用 XML 的 Accept Header。

編寫 XML REST 服務

如果您的類路徑上有 Jackson XML 擴充套件 (jackson-dataformat-xml),您可以使用它來呈現 XML 響應。我們用於 JSON 的上一個示例也將適用。要使用 Jackson XML 渲染器,請將以下依賴項新增到您的專案中:

<dependency>
	<groupId>tools.jackson.dataformat</groupId>
	<artifactId>jackson-dataformat-xml</artifactId>
</dependency>

如果 Jackson 的 XML 擴充套件不可用且 JAXB 可用,則可以使用 XML 渲染,但需要額外要求將 MyThing 註釋為 @XmlRootElement,如以下示例所示:

  • Java

  • Kotlin

import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class MyThing {

	private String name;

	// getters/setters ...

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

}
import jakarta.xml.bind.annotation.XmlRootElement

@XmlRootElement
class MyThing {

	var name: String? = null

}

您需要確保 JAXB 庫是專案的一部分,例如透過新增:

<dependency>
	<groupId>org.glassfish.jaxb</groupId>
	<artifactId>jaxb-runtime</artifactId>
</dependency>
要使伺服器呈現 XML 而不是 JSON,您可能需要傳送一個 Accept: text/xml 頭(或使用瀏覽器)。

自定義 Jackson JsonMapper

您可以透過使用環境來配置 JsonMapper。Jackson 提供了一套廣泛的開/關功能,可用於配置其處理的各個方面。這些功能在 Jackson 的幾個列舉中進行了描述,這些列舉對映到環境中的屬性:

列舉 財產

DateTimeFeature

spring.jackson.datatype.datetime.<feature_name>

true, false

EnumFeature

spring.jackson.datatype.enum.<feature_name>

true, false

JsonNodeFeature

spring.jackson.datatype.json-node.<feature_name>

true, false

JsonInclude.Include

spring.jackson.default-property-inclusion

always, non_null, non_absent, non_default, non_empty

DeserializationFeature

spring.jackson.deserialization.<feature_name>

true, false

JsonReadFeature

spring.jackson.json.read.<feature_name>

true, false

JsonWriteFeature

spring.jackson.json.write.<feature_name>

true, false

MapperFeature

spring.jackson.mapper.<feature_name>

true, false

SerializationFeature

spring.jackson.serialization.<feature_name>

true, false

例如,要啟用美觀列印,請設定 spring.jackson.serialization.indent_output=true。請注意,由於使用了寬鬆繫結indent_output 的大小寫不必與相應的列舉常量 INDENT_OUTPUT 的大小寫匹配。

這種基於環境的配置應用於自動配置的 Builder Bean,並應用於使用構建器建立的任何對映器,包括自動配置的 JsonMapper Bean。

為了方便之前使用 Jackson 2 的應用程式的遷移,自動配置的 JsonMapper 可以配置為使用盡可能接近 Spring Boot 用於 Jackson 2 的預設值。要啟用這些預設值,請將 spring.jackson.use-jackson2-defaults 設定為 true

上下文的 Builder 可以透過一個或多個 JsonMapperBuilderCustomizer Bean 進行自定義。此類自定義器 Bean 可以排序(Boot 自己的自定義器排序為 0),允許在 Boot 的自定義之前和之後應用額外的自定義。

任何 JacksonModule 型別的 Bean 都會自動註冊到自動配置的 Builder 中,並應用於它建立的任何 JsonMapper 例項。當您嚮應用程式新增新功能時,這提供了一種在應用程式範圍內貢獻自定義模組的機制。

預設情況下,任何參與 Java ServiceLoader 機制的模組都會被發現並新增到自動配置的 Builder 中。要停用此行為,請將 spring.jackson.find-and-add-modules 設定為 false

如果您想完全替換預設的 JsonMapper,可以定義一個該型別的 @Bean,或者,如果您更喜歡基於構建器的方法,則定義一個 Builder @Bean。定義 JsonMapper Bean 時,建議將其標記為 @Primary,因為其將替換的自動配置的 JsonMapper 也是 @Primary。請注意,在這兩種情況下,這樣做都會停用 JsonMapper 的所有自動配置。

如果您提供了任何 JacksonJsonHttpMessageConverter 型別的 @Bean,它們將替換 MVC 配置中的預設值。此外,還提供了一個 HttpMessageConverters 型別的便捷 Bean(如果您使用預設 MVC 配置,則始終可用)。它有一些有用的方法可以訪問預設和使用者增強的訊息轉換器。

有關更多詳細資訊,請參閱自定義 @ResponseBody 渲染部分和 WebMvcAutoConfiguration 原始碼。

自定義 @ResponseBody 渲染

Spring 使用 HttpMessageConverters 來渲染 @ResponseBody(或 @RestController 的響應)。您可以透過在 Spring Boot 上下文中新增適當型別的 Bean 來貢獻額外的轉換器。如果您新增的 Bean 型別是無論如何都會預設包含的型別(例如用於 JSON 轉換的 JacksonJsonHttpMessageConverter),它將替換預設值。提供了一個 HttpMessageConverters 型別的便捷 Bean,如果您使用預設 MVC 配置,則始終可用。它有一些有用的方法可以訪問預設和使用者增強的訊息轉換器(例如,如果您想手動將它們注入自定義 RestTemplate,這將很有用)。

與正常的 MVC 用法一樣,您提供的任何 WebMvcConfigurer Bean 也可以透過覆蓋 configureMessageConverters 方法來貢獻轉換器。但是,與正常 MVC 不同,您只能提供您需要的額外轉換器(因為 Spring Boot 使用相同的機制來貢獻其預設值)。最後,如果您透過提供自己的 @EnableWebMvc 配置來選擇退出預設的 Spring Boot MVC 配置,您可以使用 WebMvcConfigurationSupport 中的 getMessageConverters 完全控制並手動完成所有操作。

有關更多詳細資訊,請參閱 WebMvcAutoConfiguration 原始碼。

處理多部分檔案上傳

Spring Boot 支援 servlet 5 Part API 來支援檔案上傳。預設情況下,Spring Boot 將 Spring MVC 配置為每個檔案最大 1MB,單個請求中檔案資料最大 10MB。您可以使用 MultipartProperties 類中公開的屬性來覆蓋這些值、中間資料儲存的位置(例如,到 /tmp 目錄)以及資料重新整理到磁碟的閾值。例如,如果您想指定檔案大小不受限制,請將 spring.servlet.multipart.max-file-size 屬性設定為 -1

當您希望在 Spring MVC 控制器處理方法中接收型別為 MultipartFile@RequestParam 註解引數作為多部分編碼檔案資料時,多部分支援很有用。

有關更多詳細資訊,請參閱 MultipartAutoConfiguration 原始碼。

建議使用容器內建的多部分上傳支援,而不是引入額外的依賴項,例如 Apache Commons File Upload。

關閉 Spring MVC DispatcherServlet

預設情況下,所有內容都從應用程式的根目錄 (/) 提供。如果您想對映到不同的路徑,可以按如下方式配置:

  • 屬性

  • YAML

spring.mvc.servlet.path=/mypath
spring:
  mvc:
    servlet:
      path: "/mypath"

如果您有額外的 Servlet,您可以為每個 Servlet 宣告一個 @Bean 型別的 ServletServletRegistrationBean,Spring Boot 將透明地將它們註冊到容器中。也可以使用 @ServletRegistration 作為 ServletRegistrationBean 的基於註解的替代方案。因為 Servlet 是以這種方式註冊的,所以它們可以對映到 DispatcherServlet 的子上下文,而無需呼叫它。

自行配置 DispatcherServletPath 是不尋常的,但如果您確實需要這樣做,則還必須提供一個 @Bean 型別的 DispatcherServletPath,以提供您的自定義 DispatcherServlet 的路徑。

關閉預設的 MVC 配置

完全控制 MVC 配置的最簡單方法是提供您自己的帶有 @EnableWebMvc 註解的 @Configuration。這樣做將所有 MVC 配置都交由您自己處理。

自定義檢視解析器

ViewResolver 是 Spring MVC 的核心元件,它將 @Controller 中的檢視名稱轉換為實際的 View 實現。請注意,檢視解析器主要用於 UI 應用程式,而不是 REST 風格服務(View 不用於渲染 @ResponseBody)。有許多 ViewResolver 實現可供選擇,Spring 本身並不對您應該使用哪種檢視解析器發表意見。另一方面,Spring Boot 會為您安裝一兩個,具體取決於它在類路徑和應用程式上下文中找到的內容。DispatcherServlet 會使用它在應用程式上下文中找到的所有解析器,依次嘗試每個解析器直到獲得結果。如果您新增自己的解析器,您必須瞭解其順序以及您的解析器新增到的位置。

WebMvcAutoConfiguration 會將以下 ViewResolver Bean 新增到您的上下文中:

  • 一個名為“defaultViewResolver”的 InternalResourceViewResolver。它定位可以透過 DefaultServlet 渲染的物理資源(包括靜態資源和 JSP 頁面,如果您使用這些)。它將字首和字尾應用於檢視名稱,然後在 servlet 上下文中查詢具有該路徑的物理資源(預設值都為空,但可以透過 spring.mvc.view.prefixspring.mvc.view.suffix 進行外部配置)。您可以透過提供相同型別的 bean 來覆蓋它。

  • 一個名為“beanNameViewResolver”的 BeanNameViewResolver。這是檢視解析器鏈中一個有用的成員,它會拾取任何與正在解析的 View 同名的 bean。應該沒有必要覆蓋或替換它。

  • 僅當實際存在 View 型別的 Bean 時,才會新增一個名為“viewResolver”的 ContentNegotiatingViewResolver。這是一個複合解析器,它委託給所有其他解析器,並嘗試查詢與客戶端傳送的“Accept”HTTP 頭匹配的檢視。有一篇關於 內容協商的有用部落格,您可能希望閱讀以瞭解更多資訊,您也可以檢視原始碼以獲取詳細資訊。您可以透過定義一個名為“viewResolver”的 Bean 來關閉自動配置的 ContentNegotiatingViewResolver

  • 如果您使用 Thymeleaf,您還有一個名為“thymeleafViewResolver”的 ThymeleafViewResolver。它透過在檢視名稱前後加上字首和字尾來查詢資源。字首是 spring.thymeleaf.prefix,字尾是 spring.thymeleaf.suffix。字首和字尾的預設值分別為“classpath:/templates/”和“.html”。您可以透過提供相同名稱的 Bean 來覆蓋 ThymeleafViewResolver

  • 如果您使用 FreeMarker,您還有一個名為“freeMarkerViewResolver”的 FreeMarkerViewResolver。它透過在檢視名稱前後加上字首和字尾來在載入器路徑中查詢資源(該路徑外部化為 spring.freemarker.templateLoaderPath,預設值為“classpath:/templates/”)。字首外部化為 spring.freemarker.prefix,字尾外部化為 spring.freemarker.suffix。字首和字尾的預設值分別為“”(空字串)和“.ftlh”。您可以透過提供相同名稱的 Bean 來覆蓋 FreeMarkerViewResolver。FreeMarker 變數可以透過定義 FreeMarkerVariablesCustomizer 型別的 Bean 進行自定義。

  • 如果您使用 Groovy 模板(實際上,如果您的類路徑中有 groovy-templates),您還有一個名為“groovyMarkupViewResolver”的 GroovyMarkupViewResolver。它透過在檢視名稱前後加上字首和字尾(外部化為 spring.groovy.template.prefixspring.groovy.template.suffix)來在載入器路徑中查詢資源。字首和字尾的預設值分別為“classpath:/templates/”和“.tpl”。您可以透過提供相同名稱的 Bean 來覆蓋 GroovyMarkupViewResolver

  • 如果您使用 Mustache,您還有一個名為“mustacheViewResolver”的 MustacheViewResolver。它透過在檢視名稱前後加上字首和字尾來查詢資源。字首是 spring.mustache.prefix,字尾是 spring.mustache.suffix。字首和字尾的預設值分別為“classpath:/templates/”和“.mustache”。您可以透過提供相同名稱的 Bean 來覆蓋 MustacheViewResolver

有關更多詳細資訊,請參閱以下部分:

自定義“白標”錯誤頁面

Spring Boot 安裝了一個“白標”錯誤頁面,如果您遇到伺服器錯誤,您會在瀏覽器客戶端中看到它(使用 JSON 和其他媒體型別的機器客戶端應該會看到帶有正確錯誤程式碼的合理響應)。

spring.web.error.whitelabel.enabled 設定為 false 可關閉預設錯誤頁面。這樣做將恢復您正在使用的 servlet 容器的預設設定。請注意,Spring Boot 仍會嘗試解析錯誤檢視,因此您應該新增自己的錯誤頁面而不是完全停用它。

用您自己的錯誤頁面覆蓋錯誤頁面取決於您使用的模板技術。例如,如果您使用 Thymeleaf,您可以新增一個 error.html 模板。如果您使用 FreeMarker,您可以新增一個 error.ftlh 模板。通常,您需要一個以 error 命名的 View 或一個處理 /error 路徑的 @Controller。除非您替換了一些預設配置,否則您應該在 ApplicationContext 中找到一個 BeanNameViewResolver,因此名為 error@Bean 將是實現此目的的一種方式。有關更多選項,請參閱 ErrorMvcAutoConfiguration

另請參閱 錯誤處理部分,瞭解如何在 servlet 容器中註冊處理程式的詳細資訊。

© . This site is unofficial and not affiliated with VMware.