Spring Boot with multiple DispatcherServlet, each having their own @Controllers Spring Boot with multiple DispatcherServlet, each having their own @Controllers spring spring

Spring Boot with multiple DispatcherServlet, each having their own @Controllers


I got it working somehow!

Here's my Package Layout:

test.foo.         FooConfig.java         FooController.javatest.bar.         BarConfig.java         BarController.javatest.app.         Application.java         MyService.javasrc/main/resources/application.properties

Application.java:

@SpringBootApplication(exclude=DispatcherServletAutoConfiguration.class)public class Application {    public static void main(String[] args) throws Exception {        SpringApplication.run(Application.class, args);    }    @Bean    public ServletRegistrationBean foo() {        DispatcherServlet dispatcherServlet = new DispatcherServlet();           AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();        applicationContext.register(FooConfig.class);        dispatcherServlet.setApplicationContext(applicationContext);        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/foo/*");        servletRegistrationBean.setName("foo");        return servletRegistrationBean;    }    @Bean    public ServletRegistrationBean bar() {        DispatcherServlet dispatcherServlet = new DispatcherServlet();        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();        applicationContext.register(BarConfig.class);        dispatcherServlet.setApplicationContext(applicationContext);        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/bar/*");        servletRegistrationBean.setName("bar");        return servletRegistrationBean;    }}
  • The exclude does prevent Spring Boot from creating its own DispatcherServlet with / mapping. You can remove that line, if you want that mapping or define your own.
  • You can add servletRegistrationBean.setLoadOnStartup(1) if you want to have your Servlets initialized on application start. Else it will wait for the first request for that servlet.
  • It's important to set servletRegistrationBean.setName(...), else the servlets will override each other.

FooConfig.java & BarConfig.java:

@Configuration @ComponentScan @EnableWebMvcpublic class FooConfig { }
  • @EnableWebMvc will enable the component scan. Without it, it won't find the @Controller class.

The Controller and Service code is not important. You just have to know, that if you have @RequestMapping("/foo") inside FooController, the request must be GET /foo/foo because the Servlet's URL mapping is /foo/*. It's not possible to call the URL GET /foo because the Servlet URL mapping needs a / at the end of its path (in other words: GET /foo will look for a Servlet with / mapping!), though @RequestMapping("") must be called via GET /foo/. And of course it was not possible to use /foo or /foo* as Servlet mapping (or I just did not find the correct settings for that)

Scope: The Controllers can't see each other, though it's not possible to @Autowired them in each other. Also the Service can't @Autowired any of the Controllers. But the Controllers can @Autowired the Service.

Though it's a classical parent child context hierarchy.

The only "bad" thing is, that we need @EnableMvcConfig and don't get the auto configured sugar from Spring boot within the context. The parent context is getting auto configured. I put some database stuff within the application.properties and did a query inside MyService which got called by FooController and it worked flawlessly! :)

I hope this may help some people!