傳統部署
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
將 packaging 改為 war,如下所示:
<packaging>war</packaging>
如果您使用 Gradle,您需要修改 build.gradle
以將 war 外掛程式套用至專案,如下所示:
apply plugin: 'war'
此過程的最後一步是確保嵌入式 servlet 容器不會干擾部署 war 檔案的 servlet 容器。要做到這一點,您需要將嵌入式 servlet 容器的相依性標記為 provided。
如果您使用 Maven,以下範例將 servlet 容器(在本例中為 Tomcat)標記為 provided:
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- ... -->
</dependencies>
如果您使用 Gradle,以下範例將 servlet 容器(在本例中為 Tomcat)標記為 provided:
dependencies {
// ...
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
// ...
}
建議使用 providedRuntime 而不是 Gradle 的 compileOnly 設定。除了其他限制之外,compileOnly 相依性不在測試類別路徑上,因此任何基於 Web 的整合測試都會失敗。 |
如果您使用 Spring Boot 建置工具,將內嵌 Servlet 容器依賴項標記為「provided」,將會產生一個可執行的 war 檔案,其中「provided」的依賴項會被打包到 lib-provided
目錄中。這表示除了可以部署到 Servlet 容器之外,您也可以使用命令列上的 java -jar
來執行您的應用程式。
將現有應用程式轉換為 Spring Boot 應用程式
要將現有的非 Web Spring 應用程式轉換為 Spring Boot 應用程式,請將建立 ApplicationContext
的程式碼替換為呼叫 SpringApplication
或 SpringApplicationBuilder
。Spring MVC Web 應用程式通常適合先建立可部署的 war 應用程式,然後再將其遷移到可執行的 war 或 jar。請參閱 將 jar 轉換為 war 的入門指南。
要透過繼承 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
中的這些元素替換如下:
-
類型為
Servlet
或ServletRegistrationBean
的@Bean
會將該 bean 安裝到容器中,如同它是web.xml
中的<servlet/>
和<servlet-mapping/>
一樣。 -
類型為
Filter
或FilterRegistrationBean
的@Bean
的行為類似(如同<filter/>
和<filter-mapping/>
)。 -
XML 檔案中的
ApplicationContext
可以透過Application
中的@ImportResource
新增。或者,已經大量使用註釋設定的情況可以透過幾行程式碼重新建立為@Bean
定義。
一旦 war 檔案可以運作,您就可以透過在 Application
中新增 main
方法來使其可執行,如下例所示:
-
Java
-
Kotlin
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}
如果您打算將應用程式作為 war 或可執行應用程式啟動,則需要在一個方法中共享 builder 的客製化設定,該方法同時適用於
|
應用程式可以屬於多個類別:
-
沒有
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>