传统部署

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。请参阅 入门指南:将 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 或过滤器),您可能需要通过从 web.xml 中替换这些元素,向 Application 上下文添加一些配置,如下所示

  • 类型为 ServletServletRegistrationBean@Bean 将该 bean 安装到容器中,就好像它是 web.xml 中的 <servlet/><servlet-mapping/> 一样。

  • 类型为 FilterFilterRegistrationBean@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 或可执行应用程序的形式启动应用程序,则需要在以下类似类中的 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>