Spring Boot支持传统部署以及更现代的部署形式。本节回答有关传统部署的常见问题。
17.1. 创建可部署的战争文件
| 由于Spring WebFlux不严格依赖Servlet API,并且默认情况下将应用程序部署在嵌入式Reactor Netty服务器上,因此WebFlux应用程序不支持War部署。 | |
|---|---|
产生可部署war文件的第一步是提供一个SpringBootServletInitializer子类并覆盖其configure方法。这样做利用了Spring Framework的Servlet 3.0支持,并允许您在由Servlet容器启动应用程序时对其进行配置。通常,应将应用程序的主类更新为extend SpringBootServletInitializer,如以下示例所示:
@SpringBootApplicationpublic class Application extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(Application.class);}public static void main(String[] args) {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'// …}
providedRuntime比Gradle的compileOnly配置更可取。除其他限制外,compileOnly依赖项不在测试类路径上,因此任何基于Web的集成测试都将失败。 | 
|
|---|---|
如果您使用Spring Boot构建工具,则将提供的嵌入式servlet容器依赖关系标记为提供,将生成可执行的war文件,并将提供的依赖关系打包在lib-provided目录中。这意味着,除了可以部署到servlet容器之外,还可以通过java -jar在命令行上使用运行应用程序。
17.2. 将现有应用程序转换为Spring Boot
要将现有的非Web Spring应用程序转换为Spring Boot应用程序,请替换创建您的代码ApplicationContext并将其替换为SpringApplication或的调用SpringApplicationBuilder。Spring MVC Web应用程序通常适合首先创建可部署的war应用程序,然后再将其迁移到可执行的war或jar。请参阅有关将罐子转换为战争的入门指南。
要通过扩展SpringBootServletInitializer(例如,在名为的类中Application)并添加Spring Boot@SpringBootApplication注释来创建可部署的战争,请使用类似于以下示例中所示的代码:
@SpringBootApplicationpublic class Application extends SpringBootServletInitializer {@Overrideprotected 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;}}
请记住,无论您放置什么,sources都仅是Spring ApplicationContext。通常,任何已经起作用的东西都应该在这里工作。也许有些bean可以稍后删除,然后让Spring Boot为它们提供自己的默认值,但是应该可以使某些东西工作,然后再执行此操作。
可以将静态资源移至类路径根目录中/public(或/static或/resources或/META-INF/resources)。这同样适用于messages.properties(Spring Boot自动在类路径的根目录中检测到)。
SpringDispatcherServlet和Spring Security的香草用法应该不需要进一步更改。如果您的应用程序具有其他功能(例如,使用其他servlet或过滤器),则可能需要Application通过从中替换这些元素来向上下文中添加一些配置web.xml,如下所示:
- 甲
@Bean类型的Servlet或ServletRegistrationBean将安装豆在容器中,好像它是一个<servlet/>与<servlet-mapping/>在web.xml。 - 甲
@Bean型的Filter或FilterRegistrationBean表现得类似(作为<filter/>和<filter-mapping/>)。 - 一个
ApplicationContextXML文件可以通过添加@ImportResource在你的Application。或者,可以在几行中重新创建已经大量使用注释配置的情况作为@Bean定义。 
war文件运行后,可以通过向中添加main方法来使其可执行Application,如以下示例所示:
public static void main(String[] args) {SpringApplication.run(Application.class, args);}
|  | 如果打算以战争或可执行应用程序的形式启动应用程序,则需要使用对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);}
}
|| :---: | --- |应用程序可以分为多个类别:- 没有的Servlet 3.0+应用程序`web.xml`。<br />- 带有的应用程序`web.xml`。<br />- 具有上下文层次结构的应用程序。<br />- 没有上下文层次结构的应用程序。<br />所有这些都应该适合翻译,但是每种可能都需要稍微不同的技术。<br />如果Servlet 3.0+应用程序已经使用了Spring Servlet 3.0+初始化程序支持类,那么它们可能会很容易转换。通常,来自现有代码的所有代码`WebApplicationInitializer`都可以移入`SpringBootServletInitializer`。如果您现有的应用程序有多个`ApplicationContext`(例如,如果使用`AbstractDispatcherServletInitializer`),则可以将所有上下文源组合为一个`SpringApplication`。您可能遇到的主要并发症是,如果合并不起作用,并且您需要维护上下文层次结构。有关示例,请参见[有关构建层次结构](https://docs.spring.io/spring-boot/docs/2.4.0-SNAPSHOT/reference/html/howto.html#howto-build-an-application-context-hierarchy)的[条目](https://docs.spring.io/spring-boot/docs/2.4.0-SNAPSHOT/reference/html/howto.html#howto-build-an-application-context-hierarchy)。通常需要分解包含特定于Web的功能的现有父上下文,以便所有`ServletContextAware`组件都在子上下文中。<br />还不是Spring应用程序的应用程序可以转换为Spring Boot应用程序,前面提到的指南可能会有所帮助。但是,您可能仍然遇到问题。在这种情况下,建议您[使用标记来在Stack Overflow上提问`spring-boot`](https://stackoverflow.com/questions/tagged/spring-boot)。<a name="howto-weblogic"></a>### 17.3. 将WAR部署到WebLogic要将Spring Boot应用程序部署到WebLogic,必须确保servlet初始化程序**直接**实现`WebApplicationInitializer`(即使从已经实现它的基类扩展)。<br />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”?>
<a name="howto-use-jedis-instead-of-lettuce"></a>### 17.4. 使用Jedis代替生菜默认情况下,Spring Boot入门(`spring-boot-starter-data-redis`)使用[Lettuce](https://github.com/lettuce-io/lettuce-core/)。您需要排除该依赖性,而改为包含[Jedis](https://github.com/xetorthio/jedis/)。Spring Boot管理这两个依赖关系,因此您无需指定版本即可切换到Jedis。<br />以下示例显示了如何在Maven中执行此操作:
以下示例显示了如何在Gradle中执行此操作:
dependencies { implementation(‘org.springframework.boot:spring-boot-starter-data-redis’) { exclude group: ‘io.lettuce’, module: ‘lettuce-core’ } implementation ‘redis.clients:jedis’ // … }
<a name="howto-testcontainers"></a>### 17.5. 使用Testcontainer进行集成测试该[Testcontainers](https://www.testcontainers.org/)库提供了一种方法来管理Docker容器中运行的服务。它与JUnit集成,允许您编写一个测试类,该类可以在运行任何测试之前启动容器。Testcontainers在编写与真实的后端服务(例如MySQL,MongoDB,Cassandra等)进行通信的集成测试时特别有用。Testcontainers可以在Spring Boot测试中使用,如下所示:
@SpringBootTest @Testcontainers class ExampleIntegrationTests { @Container static Neo4jContainer<?> neo4j = new Neo4jContainer<>(); }
在运行任何测试之前,这将启动运行Neo4j的Docker容器(如果Docker在本地运行)。在大多数情况下,您将需要使用正在运行的容器中的详细信息(例如容器IP或端口)来配置应用程序。<br />这可以通过`@DynamicPropertySource`允许将动态属性值添加到Spring Environment的静态方法来完成。
@SpringBootTest @Testcontainers class ExampleIntegrationTests { @Container static Neo4jContainer<?> neo4j = new Neo4jContainer<>(); @DynamicPropertySource static void neo4jProperties(DynamicPropertyRegistry registry) { registry.add(“spring.neo4j.uri”, neo4j::getBoltUrl); } } ``` 上面的配置允许应用程序中与Neo4j相关的Bean与在Testcontainers管理的Docker容器中运行的Neo4j通信。
