产生一个可部署war包的第一步是提供一个SpringBootServletInitializer
子类,并覆盖它的configure
方法,这充分利用了Spring框架对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容器。为了达到这个目的,你需要将内嵌容器的依赖标记为provided
。
如果使用Maven:
<dependencies>
<!-- … -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- … -->
</dependencies>
如果使用Gradle:
dependencies {
// …
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
// …
}
如果你使用Spring Boot构建工具,将内嵌容器依赖标记为provided
将产生一个可执行war包,在lib-provided
目录有该war包的provided
依赖。这意味着,除了部署到servlet容器,你还可以通过使用命令行java -jar
命令来运行应用。
注 查看Spring Boot基于以上配置的一个Maven示例应用。
老的Servlet容器不支持在Servlet 3.0中使用的ServletContextInitializer
启动处理。你仍旧可以在这些容器使用Spring和Spring Boot,但你需要为应用添加一个web.xml
,并将它配置为通过一个DispatcherServlet
加载一个ApplicationContext
。
对于一个非web项目,转换为Spring Boot应用很容易(抛弃创建ApplicationContext
的代码,取而代之的是调用SpringApplication
或SpringApplicationBuilder
)。Spring MVC web应用通常先创建一个可部署的war应用,然后将它迁移为一个可执行的war或jar,建议阅读Getting Started Guide on Converting a jar to a war.。
通过继承SpringBootServletInitializer
创建一个可执行war(比如,在一个名为Application
的类中),然后添加Spring Boot的@EnableAutoConfiguration
注解,示例:
@Configuration
@EnableAutoConfiguration
@ComponentScan
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 we actually don't
// need to override this method.
return application;
}
}
记住不管你往sources
放什么东西,它仅是一个Spring ApplicationContext
,正常情况下,任何生效的在这里也会起作用。有一些beans你可以先移除,然后让Spring Boot提供它的默认实现,不过有可能需要先完成一些事情。
静态资源可以移到classpath根目录下的/public
(或/static
,/resources
,/META-INF/resources
)。同样的方式也适合于messages.properties
(Spring Boot在classpath根目录下自动发现这些配置)。
美妙的(Vanilla usage of)Spring DispatcherServlet
和Spring Security不需要改变。如果你的应用有其他特性,比如使用其他servlets或filters,那你可能需要添加一些配置到你的Application
上下文中,按以下操作替换web.xml
的那些元素:
Servlet
或ServletRegistrationBean
类型的@Bean
,就好像web.xml
中的<servlet/>
和<servlet-mapping/>
。Filter
或FilterRegistrationBean
类型的@Bean
(类似于<filter/>
和<filter-mapping/>
)。ApplicationContext
可以通过@Import
添加到你的Application
中。简单的情况下,大量使用注解配置可以在几行内定义@Bean
定义。一旦war可以使用,我们就通过添加一个main方法到Application
来让它可以执行,比如:
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
应用可以划分为多个类别:
所有这些都可以进行适当的转化,但每个可能需要稍微不同的技巧。
Servlet 3.0+的应用转化的相当简单,如果它们已经使用Spring Servlet 3.0+初始化器辅助类。通常所有来自一个存在的WebApplicationInitializer
的代码可以移到一个SpringBootServletInitializer
中。如果一个存在的应用有多个ApplicationContext
(比如,如果它使用AbstractDispatcherServletInitializer
),那你可以将所有上下文源放进一个单一的SpringApplication
。你遇到的主要难题可能是如果那样不能工作,那你就要维护上下文层次。参考示例entry on building a hierarchy。一个存在的包含web相关特性的父上下文通常需要分解,这样所有的ServletContextAware
组件都处于子上下文中。
对于还不是Spring应用的应用来说,上面的指南有助于你把应用转换为一个Spring Boot应用,但你也可以选择其他方式。
想要将Spring Boot应用部署到Weblogic,你需要确保你的servlet初始化器直接实现WebApplicationInitializer
(即使你继承的基类已经实现了它)。
一个传统的Weblogic初始化器可能如下所示:
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.web.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>
Spring Boot使用 Servlet 3.0 APIs初始化ServletContext
(注册Servlets
等),所以你不能在一个Servlet 2.5的容器中原封不动的使用同样的应用。使用一些特定的工具也是可以在老的容器中运行Spring Boot应用的。如果添加了org.springframework.boot:spring-boot-legacy
依赖,你只需要创建一个web.xml
,声明一个用于创建应用上下文的上下文监听器,过滤器和servlets。上下文监听器是专用于Spring Boot的,其他的都是一个Servlet 2.5的Spring应用所具有的。示例:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
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/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>demo.Application</param-value>
</context-param>
<listener>
<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>metricFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>metricFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在该示例中,我们使用一个单一的应用上下文(通过上下文监听器创建的),然后使用一个init参数将它附加到DispatcherServlet
。这在一个Spring Boot应用中是很正常的(你通常只有一个应用上下文)。