2015-06-05 12 views
13

Về cơ bản tôi muốn chia ứng dụng của mình thành 2 phần. Mỗi phần đều có nội dung bảo mật riêng và sở hữu số @Controller s. Bạn có thể truy cập @Services từ cả hai phần.Khởi động mùa xuân với nhiều DispatcherServlet, mỗi bộ phận có @Controllers của riêng mình

Vì vậy, tôi nghĩ, tôi sẽ nhận được 2 DispatcherServlet. Một người nghe /admin/* và người thứ hai lắng nghe mọi thứ khác (/). Mỗi người trong số đó sẽ có AnnotationConfigWebApplicationContext riêng của mình để tôi có thể quét riêng thành phần cho số @Controller s.

Và bởi vì mùa xuân Boot cung cấp một DispatcherServlet nghe trên / ra khỏi hộp, tôi nghĩ, tôi có thể chỉ cần thêm một giây một:

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

Các MyConfig2 lớp, chỉ có @Configuration@ComponentScan. Trong cùng một gói là @Controller.

Khi khởi động ứng dụng, tôi có thể thấy, bản đồ servlet thứ hai đang được đăng ký, nhưng @Controller thì không. Ngoài ra, tôi hiện có thể truy cập tất cả@Controllers từ //admin.


Bất kỳ ý tưởng nào tôi có thể làm việc này?

Trả lời

26

Tôi nhận được nó hoạt động bằng cách nào đó!

Dưới đây là Layout trọn gói của tôi:

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; 
    } 
} 
  • Các exclude không ngăn chặn Xuân Boot từ việc tạo riêng của mình DispatcherServlet với / lập bản đồ. Bạn có thể xóa dòng đó, nếu bạn muốn ánh xạ đó hoặc xác định bản đồ của riêng bạn.
  • Bạn có thể thêm servletRegistrationBean.setLoadOnStartup(1) nếu bạn muốn Servlets của bạn được khởi chạy khi bắt đầu ứng dụng. Khác nó sẽ đợi yêu cầu đầu tiên cho servlet đó.
  • Điều quan trọng là đặt servletRegistrationBean.setName(...), nếu không các servlet sẽ ghi đè lên nhau.

FooConfig.java & BarConfig.java:

@Configuration @ComponentScan @EnableWebMvc 
public class FooConfig { } 
  • @EnableWebMvc sẽ cho phép quá trình quét phần. Không có nó, nó sẽ không tìm thấy lớp học @Controller.

Bộ điều khiển và mã dịch vụ không quan trọng. Bạn chỉ cần biết rằng nếu bạn có @RequestMapping("/foo") bên trong FooController, yêu cầu phải là GET /foo/foo vì ánh xạ URL của Servlet là /foo/*.Không thể gọi URL GET /foo vì ánh xạ URL Servlet cần / ở cuối đường dẫn của nó (nói cách khác: GET /foo sẽ tìm Servlet với ánh xạ /!), Mặc dù @RequestMapping("") phải được gọi qua số GET /foo/. Và tất nhiên nó không thể sử dụng /foo hoặc /foo* như lập bản đồ Servlet (hoặc tôi chỉ không tìm thấy các thiết lập chính xác cho rằng)

Phạm vi: Các bộ điều khiển có thể không thấy nhau, mặc dù nó là không phải có thể là @Autowired chúng với nhau. Ngoài ra, Dịch vụ không thể @Autowired bất kỳ Bộ điều khiển nào. Nhưng Bộ điều khiển có thể @Autowired Dịch vụ.

Mặc dù đó là cấu trúc phân cấp ngữ cảnh của bố mẹ con cổ điển.

Điều "xấu" duy nhất là chúng tôi cần @EnableMvcConfig và không lấy đường được định cấu hình tự động từ khởi động Mùa xuân trong ngữ cảnh. Ngữ cảnh gốc sẽ tự động được cấu hình. Tôi đặt một số nội dung cơ sở dữ liệu trong số application.properties và đã thực hiện truy vấn bên trong MyService được gọi bởi FooController và nó hoạt động hoàn hảo! :)

Tôi hy vọng điều này có thể giúp một số người!

+0

Cảm ơn bạn đã trả lời. Thực sự hữu ích. Tôi có thêm một thách thức để vượt qua. Làm thế nào tôi có thể xác thực + ủy quyền (dựa trên DB) các điểm cuối/foo nhưng chỉ xác thực các điểm cuối/thanh? Tôi có một cấu hình từ đây [0]. http://stackoverflow.com/questions/36909226/how-to-configure-waffle-in-spring-using-java-configuration – JHS

+0

Cảm ơn Benjamin, tôi đã đấu tranh với cùng một vấn đề và thấy rằng @EnableMvcConfig là cần thiết sau khi đọc câu trả lời của bạn . – jatanp

+0

Cảm ơn bạn đã giải thích kỹ lưỡng! Nó đã giúp tôi giải quyết hai vấn đề khác nhau. Tôi có nghĩa là nó phổ biến để tự trả lời với "công trình này:" cộng với các bit mã mà không giải thích ... – sjngm

Các vấn đề liên quan