On this page
92. Traditional Deployment
Spring Boot 支持传统部署以及更现代的部署形式。本节回答有关传统部署的常见问题。
92.1 创建可部署的 War 文件
Warning
由于 Spring WebFlux 不严格依赖 Servlet API,并且默认情况下将应用程序部署在嵌入式 Reactor Netty 服务器上,因此 WebFlux 应用程序不支持 War 部署。
生成可部署 war 文件的第一步是提供SpringBootServletInitializer
子类并覆盖其configure
方法。这样做利用了 Spring Framework 的 Servlet 3.0 支持,并允许您在由 Servlet 容器启动应用程序时对其进行配置。通常,应更新应用程序的主类以扩展SpringBootServletInitializer
,如以下示例所示:
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, 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'
// …
}
Tip
providedRuntime
比 Gradle 的compileOnly
配置更可取。除其他限制外,compileOnly
依赖项不在测试 Classpath 上,因此任何基于 Web 的集成测试都将失败。
如果使用Spring Boot 构建工具,则将嵌入式 servlet 容器的相关性标记为已提供将生成一个可执行的 war 文件,其中所提供的相关性打包在lib-provided
目录中。这意味着,除了可以部署到 Servlet 容器之外,还可以通过在命令行上使用java -jar
运行应用程序。
Tip
查看 Spring Boot 的示例应用程序中先前配置的Maven-based example。
92.2 将现有应用程序转换为 Spring Boot
对于非 Web 应用程序,将现有的 Spring 应用程序转换为 Spring Boot 应用程序应该很容易。为此,请丢弃创建您的ApplicationContext
的代码,并将其替换为对SpringApplication
或SpringApplicationBuilder
的调用。 Spring MVC Web 应用程序通常适合首先创建可部署的 war 应用程序,然后再将其迁移到可执行的 war 或 jar。参见将Jar子转换为 War 的 Starter 指南。
要通过扩展SpringBootServletInitializer
(例如,在名为Application
的类中)并添加 Spring Boot @SpringBootApplication
Comments 来创建可部署的 War,请使用类似于以下示例中所示的代码:
@SpringBootApplication
public class Application 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 (via @SpringBootApplication)
// we actually don't need to override this method.
return application;
}
}
请记住,无论您 Importingsources
只是一个 Spring ApplicationContext
。通常,任何已经起作用的东西都应该在这里工作。可能有些 bean 可以稍后删除,然后让 Spring Boot 为它们提供自己的默认值,但是应该可以使某些东西工作,然后再执行此操作。
可以将静态资源移至 Classpath 根目录中的/public
(或/static
或/resources
或/META-INF/resources
)。 messages.properties
同样适用(Spring Boot 会在 Classpath 的根目录中自动检测到)。
在 Spring DispatcherServlet
和 Spring Security 上使用 Vanilla 不需要进一步更改。如果您的应用程序具有其他功能(例如,使用其他 servlet 或过滤器),则可能需要通过替换web.xml
中的那些元素来向Application
上下文添加一些配置,如下所示:
类型为
Servlet
或ServletRegistrationBean
的@Bean
将该 bean 安装在容器中,就好像它是web.xml
中的<servlet/>
和<servlet-mapping/>
一样。Filter
或FilterRegistrationBean
类型的@Bean
的行为类似(如<filter/>
和<filter-mapping/>
)。可以通过
Application
中的@ImportResource
添加 XML 文件中的ApplicationContext
。或者,可以在几行中将@Bean
定义重新创建已经大量使用 Comments 配置的简单情况。
war 文件运行后,可以通过向Application
添加main
方法使其变为可执行文件,如以下示例所示:
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
Note
如果您打算以 War 或可执行应用程序的形式启动应用程序,则需要使用SpringBootServletInitializer
回调可用的方法和main
方法中的类(类似于以下类)共享构建器的自定义项:
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return configureApplication(builder);
}
public static void main(String[] args) {
configureApplication(new SpringApplicationBuilder()).run(args);
}
private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
return builder.sources(Application.class).bannerMode(Banner.Mode.OFF);
}
}
应用程序可以分为多个类别:
没有
web.xml
的 Servlet 3.0 应用程序。带有
web.xml
的应用程序。具有上下文层次结构的应用程序。
没有上下文层次结构的应用程序。
所有这些都应该适合翻译,但每种都可能需要稍微不同的技术。
如果 Servlet 3.0 应用程序已经使用了 Spring Servlet 3.0 初始化程序支持类,则它们可能很容易转换。通常,现有WebApplicationInitializer
中的所有代码都可以移到SpringBootServletInitializer
中。如果您现有的应用程序有多个ApplicationContext
(例如,如果使用AbstractDispatcherServletInitializer
),则您可以将所有上下文源组合为一个SpringApplication
。您可能遇到的主要并发症是,如果合并不起作用,并且您需要维护上下文层次结构。有关示例,请参见构建层次结构的 Starter。通常需要分解包含特定于 Web 的功能的现有父上下文,以便所有ServletContextAware
组件都位于子上下文中。
还不是 Spring 应用程序的应用程序可以转换为 Spring Boot 应用程序,前面提到的指南可能会有所帮助。但是,您可能仍然遇到问题。在这种情况下,我们建议用 spring-boot 标签在 Stack Overflow 上提问。
92.3 将 WAR 部署到 WebLogic
要将 Spring Boot 应用程序部署到 WebLogic,必须确保 Servlet 初始化程序直接实现WebApplicationInitializer
(即使您是从已经实现它的 Base Class 中扩展过来的)。
WebLogic 的典型初始化程序应类似于以下示例:
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 {
}
如果使用 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
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
http://xmlns.oracle.com/weblogic/weblogic-web-app
http://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>
92.4 使用 Jedis 代替 Lettuce
默认情况下,Spring Boot 启动器(spring-boot-starter-data-redis
)使用Lettuce。您需要排除该依赖性,而改为包含Jedis个。 Spring Boot Management 这些依赖关系,以帮助简化此过程。
以下示例显示了如何在 Maven 中执行此操作:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
以下示例显示了如何在 Gradle 中执行此操作:
configurations {
compile.exclude module: "lettuce"
}
dependencies {
compile("redis.clients:jedis")
// ...
}