构建和部署WAR文件
在本书中,我们编写Taco Cloud应用所需的服务时,都是在IDE中运行,或者通过命令行以可执行文件的形式运行。不管使用哪种方式,都会有一个嵌入式的Tomcat服务器(在Spring WebFlux应用中则为Netty)来为应用的请求提供服务。
在很大程度上,借助Spring Boot的自动配置,我们不需要创建web.xml文件或Servlet initializer类声明Spring的DispatcherServlet来实现Spring MVC相关的功能。如果要将应用程序部署到Java应用服务器中,就需要构建一个WAR文件。此外,为了让应用服务器知道如何运行应用程序,我们还需要在WAR文件中包含一个Servlet initializer,以扮演web.xml文件的角色并声明DispatcherServlet。
实际上,要将Spring Boot应用构建为WAR文件并不困难。使用Initializr创建应用时,如果选择了WAR方案,就没有额外的事情要做了。
Initializr会确保生成的项目包含Servlet initializer类,构建文件会被调整为生成WAR文件。如果你在Initializr中选择了构建为JAR文件(或者只是想知道它们之间的差异),请继续向下阅读。
首先,我们需要一种配置Spring DispatcherServlet的方式。这虽然可以通过web.xml文件来实现,但是Spring Boot的SpringBootServletInitializer使这个过程变得更加简单了。SpringBootServletInitializer是一个能够感知Spring Boot环境的特殊Spring WebApplication Initializer实现。除了配置Spring的DispatcherServlet之外,SpringBootServletInitializer还会查找Spring应用上下文中所有Filter、Servlet或ServletContextInitializer类型的bean,并将它们绑定到Servlet容器中。
要使用SpringBootServletInitializer,需要创建一个子类并重写configure()方法来指明Spring配置类。程序清单18.1展现了TacoCloudServletInitializer,它是SpringBootServlet Initializer的子类,我们将会使用它来实现Taco Cloud应用。
package tacos;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
public class TacoCloudServletInitializer
extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder builder) {
return builder.sources(TacoCloudApplication.class);
}
}
可以看到,configure()方法以参数形式得到了一个SpringApplicationBuilder对象,并且将其作为结果返回。在中间的代码中,它调用sources()方法来注册Spring配置类。在本例中,它注册了TacoCloudApplication类,这个类同时作为(可执行JAR的)引导类和Spring配置类。
虽然应用还有其他的Spring配置类,但是我们没有必要将它们全部注册到sources()方法中。TacoCloudApplication类使用了@SpringBootApplication,这说明组件扫描将会启用。组件扫描功能会发现其他的配置类并将它们添加进来。
在大多数情况下,SpringBootServletInitializer的子类都是样板式的,它引用了应用的主配置类。除此之外,在构建WAR时,每个应用都是相同的。我们没有什么必要去修改它。
现在,我们已经编写完Servlet initializer类。接下来,必须要对项目的构建文件做一些修改。如果使用Maven进行构建,那么所需的变更非常简单,只需要确保pom.xml中的<packaging>元素设置成war:
<packaging>war</packaging>
Gradle构建所需的变更也很简单直接,我们需要在build.gradle文件中应用war插件:
apply plugin: 'war'
现在,我们就可以构建应用了。如果使用Maven,那么可以借助Initializr使用的Maven包装器来执行package goal:
$ mvnw package
如果构建成功,WAR文件会出现在“target”目录下。
如果使用Gradle来构建项目,那么可以使用Gradle包装器来执行build任务:
$ gradlew build
构建完成后,我们可以在“build/libs”目录下找到WAR文件。剩下的事情就是部署应用了。不同应用服务器的部署过程会有所差异,请参考应用服务器部署过程的相关文档。
比较有意思的事情是,虽然我们构建了适用于Servlet 3.0(或更高版本)部署的WAR文件,但是这个WAR文件依然可以像可执行JAR文件那样在命令行中执行:
$ java -jar target/taco-cloud-0.0.19-SNAPSHOT.war
实际上,我们使用一个部署制品,同时实现了两种部署方案。