Use the SpringBootServletInitializer
base class, which is picked up by Spring’s
Servlet 3.0 support on deployment. Add an extension of that to your project and build a
war file as normal. For more detail, see the
‘Converting a jar Project to a war’ guide
on the spring.io website and the sample below.
The war file can also be executable if you use the Spring Boot build tools. In that case
the embedded container classes (to launch Tomcat for instance) have to be added to the
war in a lib-provided
directory. The tools will take care of that as long as the
dependencies are marked as ‘provided’ in Maven or Gradle. Here’s a Maven example
in the Boot Samples.
Older Servlet containers don’t have support for the ServletContextInitializer
bootstrap
process used in Servlet 3.0. You can still use Spring and Spring Boot in these containers
but you are going to need to add a web.xml
to your application and configure it to load
an ApplicationContext
via a DispatcherServlet
.
For a non-web application it should be easy (throw away the code that creates your
ApplicationContext
and replace it with calls to SpringApplication
or
SpringApplicationBuilder
). Spring MVC web applications are generally amenable to first
creating a deployable war application, and then migrating it later to an executable war
and/or jar. Useful reading is in the Getting
Started Guide on Converting a jar to a war.
Create a deployable war by extending SpringBootServletInitializer
(e.g. in a class
called Application
), and add the Spring Boot @EnableAutoConfiguration
annotation.
Example:
@Configuration @EnableAutoConfiguration @ComponentScan public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } }
Remember that whatever you put in the sources
is just a Spring ApplicationContext
and
normally anything that already works should work here. There might be some beans you can
remove later and let Spring Boot provide its own defaults for them, but it should be
possible to get something working first.
Static resources can be moved to /public
(or /static
or /resources
or
/META-INF/resources
) in the classpath root. Same for messages.properties
(Spring Boot
detects this automatically in the root of the classpath).
Vanilla usage of Spring DispatcherServlet
and Spring Security should require no further
changes. If you have other features in your application, using other servlets or filters
for instance, then you may need to add some configuration to your Application
context,
replacing those elements from the web.xml
as follows:
@Bean
of type Servlet
or ServletRegistrationBean
installs that bean in the
container as if it was a <servlet/>
and <servlet-mapping/>
in web.xml
.
@Bean
of type Filter
or FilterRegistrationBean
behaves similarly (like a
<filter/>
and <filter-mapping/>
.
ApplicationContext
in an XML file can be added to an @Import
in your
Application
. Or simple cases where annotation configuration is heavily used already
can be recreated in a few lines as @Bean
definitions.
Once the war is working we make it executable by adding a main
method to our
Application
, e.g.
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
Applications can fall into more than one category:
web.xml
.
web.xml
.
All of these should be amenable to translation, but each might require slightly different tricks.
Servlet 3.0 applications might translate pretty easily if they already use the Spring
Servlet 3.0 initializer support classes. Normally all the code from an existing
WebApplicationInitializer
can be moved into a SpringBootServletInitializer
. If your
existing application has more than one ApplicationContext
(e.g. if it uses
AbstractDispatcherServletInitializer
) then you might be able to squash all your context
sources into a single SpringApplication
. The main complication you might encounter is if
that doesn’t work and you need to maintain the context hierarchy. See the
entry on building a hierarchy for
examples. An existing parent context that contains web-specific features will usually
need to be broken up so that all the ServletContextAware
components are in the child
context.
Applications that are not already Spring applications might be convertible to a Spring Boot application, and the guidance above might help, but your mileage may vary.
Spring Boot uses Servet 3.0 APIs to initialize the ServletContext
(register Servlets
etc.) so you can’t use the same application out of the box in a Servlet 2.5 container.
It is however possible to run a Spring Boot application on an older container with some
special tools. If you include org.springframework.boot:spring-boot-legacy
as a
dependency (maintained separately to the
core of Spring Boot and currently available at 1.0.0.RELEASE), all you should need to do
is create a web.xml
and declare a context listener to create the application context and
your filters and servlets. The context listener is a special purpose one for Spring Boot,
but the rest of it is normal for a Spring application in Servlet 2.5. Example:
<?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> </filte>r <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>
In this example we are using a single application context (the one created by the context
listener) and attaching it to the DispatcherServlet
using an init parameter. This is
normal in a Spring Boot application (you normally only have one application context).