傳統部署
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 容器依賴項標記為 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 依賴項不在測試 classpath 中,因此任何基於 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。
要透過擴充套件 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 提供自己的預設配置,但在這樣做之前,應該可以先讓一些東西跑起來。
靜態資源可以移動到 classpath 根目錄下的 /public
(或 /static
、/resources
或 /META-INF/resources
)中。messages.properties
也同樣適用(Spring Boot 會自動檢測 classpath 根目錄下的該檔案)。
Spring DispatcherServlet
和 Spring Security 的普通用法不需要進一步更改。如果你的應用程式中有其他特性(例如,使用其他 servlet 或 filter),你可能需要在 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>