传统部署

Spring Boot 支持传统部署以及更现代的部署形式。本节解答有关传统部署的常见问题。

创建可部署的 War 文件

由于 Spring WebFlux 不严格依赖于 servlet API,并且应用默认部署在嵌入式 Reactor Netty 服务器上,因此 WebFlux 应用不支持 War 部署。

生成可部署的 war 文件的第一步是提供一个 SpringBootServletInitializer 子类并覆盖其 configure 方法。这样做利用了 Spring 框架的 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容器依赖项标记为provided会生成一个可执行的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安装到容器中,就像它是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>