2015-06-05 12 views
13

Fondamentalmente voglio dividere la mia applicazione in 2 parti. Ogni parte ha le proprie caratteristiche di sicurezza e possiede @Controller s. Il @Services dovrebbe essere accessibile da entrambe le parti.Avvio a molla con DispatcherServlet multipli, ciascuno con i propri @Controllers

Quindi ho pensato, dovrei ottenere 2 DispatcherServlet. Uno che ascolta /admin/* e il secondo ascolta tutto il resto (/). Ognuno di questi avrà il suo AnnotationConfigWebApplicationContext così posso avere una scansione dei componenti separata per il @Controller s.

E perché la primavera di avvio fornisce un DispatcherServlet ascolto su / fuori dalla scatola, ho pensato, posso solo aggiungere un secondo:

@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; 
    } 
} 

Il MyConfig2 di classe, ha solo @Configuration e @ComponentScan. All'interno dello stesso pacchetto è un @Controller.

All'avvio dell'applicazione, posso vedere che la seconda mappatura servlet viene registrata, ma lo @Controller non lo è. Inoltre ora posso accedere a all@Controllers da /e/admin.


Qualche idea su come posso farlo funzionare?

risposta

26

Ho capito che funziona in qualche modo!

Ecco il mio layout pacchetto:

test.foo. 
     FooConfig.java 
     FooController.java 
test.bar. 
     BarConfig.java 
     BarController.java 
test.app. 
     Application.java 
     MyService.java 
src/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; 
    } 
} 
  • Il exclude impedisce Primavera avvio di creare un proprio DispatcherServlet con / mappatura. Puoi rimuovere quella linea, se vuoi quella mappatura o definirne la tua.
  • È possibile aggiungere servletRegistrationBean.setLoadOnStartup(1) se si desidera inizializzare i servlet all'avvio dell'applicazione. Altrimenti aspetterà la prima richiesta per quel servlet.
  • È importante impostare servletRegistrationBean.setName(...), altrimenti i servlet si sovrascriveranno.

FooConfig.java & BarConfig.java:

@Configuration @ComponentScan @EnableWebMvc 
public class FooConfig { } 
  • @EnableWebMvc permetterà la scansione dei componenti. Senza di esso, non troverà la classe @Controller.

Il codice controller e servizio non è importante. Devi solo sapere che se hai @RequestMapping("/foo") all'interno di FooController, la richiesta deve essere GET /foo/foo perché la mappatura dell'URL della servlet è /foo/*.Non è possibile chiamare l'URL GET /foo perché la mappatura dell'URL servlet ha bisogno di un / alla fine del suo percorso (in altre parole: GET /foo si cercherà un servlet con la mappatura /!), Anche se @RequestMapping("") deve essere chiamato tramite GET /foo/. E, naturalmente, non è stato possibile utilizzare /foo o /foo* la mappatura Servlet (o io non ho trovato le impostazioni corrette per questo)

Ambito: i controllori possono non vedere l'altro, anche se è non possibile a @Autowired l'uno nell'altro. Inoltre, il servizio non può @Autowired uno dei controller. Ma i Controller possono @Autowired il servizio.

Sebbene sia una classica gerarchia di contesto figlio secondario.

L'unica cosa "cattiva" è che abbiamo bisogno di @EnableMvcConfig e non si ottiene lo zucchero configurato automaticamente da avvio Spring nel contesto. Il contesto genitore viene automaticamente configurato. Ho inserito alcuni file di database all'interno dello application.properties e ho effettuato una query all'interno di MyService che è stata chiamata da FooController e ha funzionato in modo impeccabile! :)

Spero che questo possa aiutare alcune persone!

+0

Grazie per la risposta. Aiuta davvero Ho ancora una sfida da superare. Come posso autenticare + autorizzare (basato su DB) gli endpoint/foo ma solo autenticare gli endpoint/bar? Ho una configurazione da qui [0]. http://stackoverflow.com/questions/36909226/how-to-configure-waffle-in-spring-using-java-configuration – JHS

+0

Grazie Benjamin, ero alle prese con lo stesso problema e ho scoperto che @EnableMvcConfig è richiesto dopo aver letto la tua risposta . – jatanp

+0

Grazie per questa spiegazione approfondita! Mi ha aiutato a risolvere due diversi problemi. Voglio dire, è normale auto-rispondere con "questo funziona:" più i bit del codice senza spiegazione ... – sjngm

Problemi correlati