Spring Boot con mĂșltiples DispatcherServlet, cada uno con sus propios @Controllers
spring-mvc servlets (1)
¡Lo tengo funcionando de alguna manera!
Aquí está mi diseño del paquete:
test.foo.
FooConfig.java
FooController.java
test.bar.
BarConfig.java
BarController.java
test.app.
Application.java
MyService.java
src/main/resources/application.properties
Aplicación.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;
}
}
- La
excludeimpide que Spring Boot cree su propioDispatcherServletcon/mapping. Puede eliminar esa línea, si desea que la asignación o definir su propia. - Puede agregar
servletRegistrationBean.setLoadOnStartup(1)si desea que sus Servlets se inicialicen al iniciar la aplicación. De lo contrario, esperará la primera solicitud de ese servlet. - Es importante establecer
servletRegistrationBean.setName(...), de lo contrario, los servlets se anularán entre sí.
FooConfig.java & BarConfig.java:
@Configuration @ComponentScan @EnableWebMvc
public class FooConfig { }
-
@EnableWebMvchabilitará la exploración de componentes. Sin él, no encontrará la clase@Controller.
El código de Controlador y Servicio no es importante. Solo debes saber que si tienes @RequestMapping("/foo") dentro de FooController , la solicitud debe ser GET /foo/foo porque la asignación de URL del Servlet es /foo/* . No es posible llamar a la URL GET /foo porque la asignación de la URL del Servlet necesita un / al final de su ruta (en otras palabras: GET /foo buscará un Servlet con / mapping), aunque @RequestMapping("") debe ser llamado a través de GET /foo/ . Y, por supuesto, no fue posible usar /foo o /foo* como asignación de Servlet (o simplemente no encontré la configuración correcta para eso)
Ámbito: los controladores no pueden verse entre sí, aunque no es posible que @Autowired los haya @Autowired . Además, el Servicio no puede @Autowired ninguno de los Controladores. Pero los Controladores pueden @Autowired el Servicio.
Aunque es una jerarquía de contexto padre-hijo clásica.
Lo único "malo" es que necesitamos @EnableMvcConfig y no obtenemos el azúcar configurado automáticamente desde Spring boot dentro del contexto. El contexto padre se está configurando automáticamente. Puse algunas cosas de la base de datos dentro de application.properties e hice una consulta dentro de MyService que MyService llamó y ¡funcionó a la perfección! :)
Espero que esto pueda ayudar a algunas personas!
Básicamente quiero dividir mi aplicación en 2 partes. Cada parte tiene su propio material de seguridad y el propio @Controller s. Los @Services deben ser accesibles desde ambas partes.
Así que pensé, debería obtener 2 DispatcherServlet . Uno escucha /admin/* y el segundo escucha todo lo demás ( / ). Cada uno de ellos tendrá su propio AnnotationConfigWebApplicationContext para que pueda tener una exploración de componentes separada para los @Controller s.
Y como Spring Boot proporciona un DispatcherServlet escucha dentro / fuera de la caja, pensé, solo puedo agregar una segunda:
@Configuration
public class MyConfig {
@Bean(name="myDS")
public DispatcherServlet myDS(ApplicationContext applicationContext) {
AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
webContext.setParent(applicationContext);
webContext.register(MyConfig2.class);
// webContext.refresh();
return new DispatcherServlet(webContext);
}
@Bean
public ServletRegistrationBean mySRB(@Qualifier("myDS") DispatcherServlet dispatcherServlet) {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet);
servletRegistrationBean.addUrlMappings("/admin/*");
servletRegistrationBean.setName("adminServlet");
return servletRegistrationBean;
}
}
La clase MyConfig2 , solo tiene @Configuration y @ComponentScan . Dentro del mismo paquete hay un @Controller .
Al iniciar la aplicación, puedo ver que se está registrando el segundo mapeo de servlet, pero no el @Controller . Además, ahora puedo acceder a todos los @Controllers desde / y /admin .
¿Alguna idea de cómo puedo hacer que esto funcione?