傳統部署

Spring Boot 支援傳統部署以及更現代的部署形式。本節回答關於傳統部署的常見問題。

建立可部署的 War 檔案

由於 Spring WebFlux 並不嚴格依賴 Servlet API,且應用程式預設部署在嵌入式 Reactor Netty 伺服器上,因此 WebFlux 應用程式不支援 War 部署。

產生可部署 war 檔案的第一步是提供 SpringBootServletInitializer 子類別並覆寫其 configure 方法。這樣做會使用 Spring Framework 的 Servlet 3.0 支援,並讓您在 Servlet 容器啟動應用程式時組態您的應用程式。通常,您應該更新應用程式的主要類別以擴展 SpringBootServletInitializer,如下列範例所示

  • Java

  • Kotlin

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(MyApplication.class);
	}

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

}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.runApplication
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer

@SpringBootApplication
class MyApplication : SpringBootServletInitializer() {

	override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder {
		return application.sources(MyApplication::class.java)
	}

}

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

下一步是更新您的建置組態,使您的專案產生 war 檔案而不是 jar 檔案。如果您使用 Maven 和 spring-boot-starter-parent (它為您組態 Maven 的 war 外掛程式),您只需修改 pom.xml 以將封裝變更為 war,如下所示

<packaging>war</packaging>

如果您使用 Gradle,您需要修改 build.gradle 以將 war 外掛程式應用於專案,如下所示

apply plugin: 'war'

此過程的最後一步是確保嵌入式 Servlet 容器不會干擾 war 檔案部署到的 Servlet 容器。為此,您需要將嵌入式 Servlet 容器依賴項標記為已提供。

如果您使用 Maven,下列範例將 Servlet 容器 (在本例中為 Tomcat) 標記為已提供

<dependencies>
	<!-- ... -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-tomcat</artifactId>
		<scope>provided</scope>
	</dependency>
	<!-- ... -->
</dependencies>

如果您使用 Gradle,下列範例將 Servlet 容器 (在本例中為 Tomcat) 標記為已提供

dependencies {
	// ...
	providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
	// ...
}
providedRuntime 優於 Gradle 的 compileOnly 組態。除其他限制外,compileOnly 依賴項不在測試類別路徑上,因此任何基於 Web 的整合測試都會失敗。

如果您使用 Spring Boot 建置工具外掛程式,將嵌入式 Servlet 容器依賴項標記為已提供會產生一個可執行 war 檔案,其中提供的依賴項封裝在 lib-provided 目錄中。這表示,除了可部署到 Servlet 容器之外,您也可以透過在命令列上使用 java -jar 來執行您的應用程式。

將現有應用程式轉換為 Spring Boot

若要將現有的非 Web Spring 應用程式轉換為 Spring Boot 應用程式,請取代建立 ApplicationContext 的程式碼,並將其替換為對 SpringApplicationSpringApplicationBuilder 的呼叫。Spring MVC Web 應用程式通常適合先建立可部署的 war 應用程式,然後稍後將其遷移到可執行 war 或 jar。

若要透過擴展 SpringBootServletInitializer (例如,在名為 Application 的類別中) 並新增 Spring Boot @SpringBootApplication 註解來建立可部署的 war,請使用類似於下列範例所示的程式碼

  • Java

  • Kotlin

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		// Customize the application or call application.sources(...) to add sources
		// Since our example is itself a @Configuration class (through
		// @SpringBootApplication)
		// we actually do not need to override this method.
		return application;
	}


}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.runApplication
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer

@SpringBootApplication
class MyApplication : SpringBootServletInitializer() {

	override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder {
		// Customize the application or call application.sources(...) to add sources
		// Since our example is itself a @Configuration class (through @SpringBootApplication)
		// we actually do not need to override this method.
		return application
	}

}

請記住,無論您在 sources 中放入什麼,都只是一個 Spring ApplicationContext。通常,任何已經運作的東西都應該在這裡運作。稍後可能會有一些 Bean 可以移除,並讓 Spring Boot 為它們提供自己的預設值,但應該可以在您需要執行該操作之前讓某些東西運作。

靜態資源可以移動到類別路徑根目錄中的 /public (或 /static/resources/META-INF/resources)。messages.properties 也適用 (Spring Boot 會自動在類別路徑的根目錄中偵測到它)。

Spring DispatcherServlet 和 Spring Security 的基本用法應不需要進一步變更。如果您的應用程式中有其他功能 (例如,使用其他 Servlet 或篩選器),您可能需要將一些組態新增到您的 Application 內容中,方法是從 web.xml 中取代這些元素,如下所示

  • 類型為 ServletServletRegistrationBean@Bean 會將該 Bean 安裝到容器中,如同它是 <servlet/><servlet-mapping/>web.xml 中。

  • 類型為 FilterFilterRegistrationBean@Bean 行為類似 (作為 <filter/><filter-mapping/>)。

  • XML 檔案中的 ApplicationContext 可以透過您 Application 中的 @ImportResource 新增。或者,已經大量使用註解組態的情況可以在幾行程式碼中重新建立為 @Bean 定義。

一旦 war 檔案運作正常,您可以透過將 main 方法新增到您的 Application 來使其可執行,如下列範例所示

  • Java

  • Kotlin

	public static void main(String[] args) {
		SpringApplication.run(MyApplication.class, args);
	}
fun main(args: Array<String>) {
	runApplication<MyApplication>(*args)
}

如果您打算以 war 或可執行應用程式啟動您的應用程式,您需要在一個方法中共享建置器的自訂設定,該方法既可供 SpringBootServletInitializer 回呼使用,也可在類似於下列類別的 main 方法中使用

  • Java

  • Kotlin

import org.springframework.boot.Banner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
		return customizerBuilder(builder);
	}

	public static void main(String[] args) {
		customizerBuilder(new SpringApplicationBuilder()).run(args);
	}

	private static SpringApplicationBuilder customizerBuilder(SpringApplicationBuilder builder) {
		return builder.sources(MyApplication.class).bannerMode(Banner.Mode.OFF);
	}

}
import org.springframework.boot.Banner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer

@SpringBootApplication
class MyApplication : SpringBootServletInitializer() {

	override fun configure(builder: SpringApplicationBuilder): SpringApplicationBuilder {
		return customizerBuilder(builder)
	}

	companion object {

		@JvmStatic
		fun main(args: Array<String>) {
			customizerBuilder(SpringApplicationBuilder()).run(*args)
		}

		private fun customizerBuilder(builder: SpringApplicationBuilder): SpringApplicationBuilder {
			return builder.sources(MyApplication::class.java).bannerMode(Banner.Mode.OFF)
		}

	}

}

應用程式可以歸類為多個類別

  • 沒有 web.xml 的 Servlet 3.0+ 應用程式。

  • 具有 web.xml 的應用程式。

  • 具有內容階層的應用程式。

  • 沒有內容階層的應用程式。

所有這些都應該適合翻譯,但每個可能需要稍微不同的技術。

如果 Servlet 3.0+ 應用程式已經使用 Spring Servlet 3.0+ 初始化程式支援類別,則它們可能會相當容易地翻譯。通常,現有 WebApplicationInitializer 中的所有程式碼都可以移動到 SpringBootServletInitializer 中。如果您的現有應用程式有多個 ApplicationContext (例如,如果它使用 AbstractDispatcherServletInitializer),那麼您或許可以將所有內容來源組合到單個 SpringApplication 中。您可能遇到的主要複雜情況是,如果組合不起作用,並且您需要維護內容階層。請參閱關於建立階層的條目以取得範例。包含 Web 特定功能的現有父內容通常需要分解,以便所有 ServletContextAware 組件都位於子內容中。

尚未成為 Spring 應用程式的應用程式可能會轉換為 Spring Boot 應用程式,並且先前提及的指南可能會有所幫助。但是,您可能仍然會遇到問題。在這種情況下,我們建議在 Stack Overflow 上提出問題,並加上 spring-boot 標籤

將 WAR 部署到 WebLogic

若要將 Spring Boot 應用程式部署到 WebLogic,您必須確保您的 Servlet 初始化程式直接實作 WebApplicationInitializer (即使您從已經實作它的基底類別擴展而來)。

WebLogic 的典型初始化程式應類似於下列範例

  • Java

  • Kotlin

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.WebApplicationInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {

}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
import org.springframework.web.WebApplicationInitializer

@SpringBootApplication
class MyApplication : SpringBootServletInitializer(), WebApplicationInitializer

如果您使用 Logback,您還需要告知 WebLogic 優先使用封裝版本,而不是伺服器預先安裝的版本。您可以透過新增具有下列內容的 WEB-INF/weblogic.xml 檔案來執行此操作

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app
	xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		https://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
		http://xmlns.oracle.com/weblogic/weblogic-web-app
		https://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
	<wls:container-descriptor>
		<wls:prefer-application-packages>
			<wls:package-name>org.slf4j</wls:package-name>
		</wls:prefer-application-packages>
	</wls:container-descriptor>
</wls:weblogic-web-app>