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 ownDispatcherServlet
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!