I created a spring boot application with a parent context (services) and child context (spring-webmvc controllers):
@Configuration public class MainApiApplication { public static void main(String[] args) { new SpringApplicationBuilder() .parent(Services.class) .child(ApiOne.class, MainApiApplication.class) .run(args); } @Bean public EmbeddedServletContainerFactory servletContainer() { return new TomcatEmbeddedServletContainerFactory(); } }
Now I want to add another client context (and DispatcherServlet) for my ApiTwo.class
configuration. I think I have to do two things:
servletContainer
(thus the MainApiApplication.class configuration) out of the child context and/one/ -> ApiOne.class
and /two/ ApiTwo.class
What is the spring boot way to do it?
You can have as many DispatcherServlets as you want. Basically what you need to do is duplicate the configuration and give the servlet a different name (else it will overwrite the previous one), and have some separate configuration classes (or xml files) for it.
A web application can define any number of DispatcherServlet instances. Each servlet will operate in its own namespace, loading its own application context with mappings, handlers, etc. Only the root application context as loaded by ContextLoaderListener, if any, will be shared.
In order to have multiple context paths, you're limited to deploying the application multiple times with that convenient property set to what you want for each deployment. However, this is resource expensive because you're spinning up two applications for every one application you would normally spin up.
We can have multiple application contexts that share a parent-child relationship. A context hierarchy allows multiple child contexts to share beans which reside in the parent context. Each child context can override configuration inherited from the parent context.
As @josh-ghiloni already said, you need to register a ServletRegistrationBean
for every isolated web context you want to create. You need to create an application context from a xml or java config class. You can use @Import
and @ComponentScan
annotation to add shared services to the parent context. Here is an example:
import org.springframework.boot.SpringApplication; import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.XmlWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; //@ComponentScan({"..."}) //@Import({}) public class Starter { public static void main(String[] args) throws Exception { SpringApplication.run(Starter.class, args); } @Bean public ServletRegistrationBean apiV1() { DispatcherServlet dispatcherServlet = new DispatcherServlet(); XmlWebApplicationContext applicationContext = new XmlWebApplicationContext(); applicationContext.setConfigLocation("classpath:/META-INF/spring/webmvc-context.xml"); dispatcherServlet.setApplicationContext(applicationContext); ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/api/1/*"); servletRegistrationBean.setName("api-v1"); return servletRegistrationBean; } @Bean public ServletRegistrationBean apiV2() { DispatcherServlet dispatcherServlet = new DispatcherServlet(); AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(); applicationContext.register(ResourceConfig.class); dispatcherServlet.setApplicationContext(applicationContext); ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/api/2/*"); servletRegistrationBean.setName("api-v2"); return servletRegistrationBean; } }
Create a ServletRegistrationBean
that declares the servlet and its mappings. You will probably also want to exclude DispatcherServletAutoConfiguration
from the autoconfigurations called, because it will register a DispatcherServlet
at /
and override yours
EDIT Despite my comment below saying you might not need this, unless you need your APIs running on separate ports (and it doesn't sound like you do), Dave Syer, one of the authors of Spring Boot, answered a very similar question here: Configure multiple servletcontainers/servlets with spring boot
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With