带有多个DispatcherServlet的Spring Boot,每个都有自己的@Controllers

Ben*_*n M 18 spring servlets spring-mvc spring-boot spring-4

基本上我想将我的应用程序分成两部分.每个部分都有自己的安全性和自己@Controller的安全性.本@Services应该从两个部分进行访问.

所以我想,我应该得到2 DispatcherServlet.一听,/admin/*第二听其他一切(/).每个都有自己的,AnnotationConfigWebApplicationContext所以我可以对@Controllers 进行单独的组件扫描.

而由于春季启动提供了一个DispatcherServlet监听/开箱,我想,我可以再补充的第二个:

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这个MyConfig2班,只有@Configuration@ComponentScan.在同一个包中是一个@Controller.

在启动应用程序时,我可以看到第二个servlet映射已经注册,但事实@Controller并非如此.另外,我现在可以从访问所有 .@Controllers/ /admin


知道如何让这个工作吗?

Ben*_*n M 36

我以某种方式工作了!

这是我的包布局:

test.foo.
         FooConfig.java
         FooController.java
test.bar.
         BarConfig.java
         BarController.java
test.app.
         Application.java
         MyService.java
src/main/resources/application.properties
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)
  • exclude确实阻止Spring Boot DispatcherServlet通过/映射创建自己的.如果您想要映射或定义自己的映射,可以删除该行.
  • servletRegistrationBean.setLoadOnStartup(1)如果要在应用程序启动时初始化Servlet,可以添加.否则它将等待该servlet的第一个请求.
  • 设置很重要servletRegistrationBean.setName(...),否则servlet会互相覆盖.

FooConfig.java和BarConfig.java:

@Configuration @ComponentScan @EnableWebMvc
public class FooConfig { }
Run Code Online (Sandbox Code Playgroud)
  • @EnableWebMvc将启用组件扫描.没有它,它将找不到@Controller类.

控制器和服务代码并不重要.你必须知道,如果你有@RequestMapping("/foo")内部FooController,请求必须是GET /foo/foo因为Servlet的URL映射/foo/*.调用URL GET /foo是不可能的,因为Servlet URL映射需要/在其路径的末尾(换句话说:GET /foo将查找带有/映射的Servlet !),但@RequestMapping("")必须通过调用GET /foo/.当然,不可能使用/foo/foo*作为Servlet映射(或者我只是找不到正确的设置)

适用范围:该控制器无法看到对方,虽然它没有可能@Autowired他们彼此.此外,服务不能@Autowired任何控制器.控制器可以@Autowired服务.

虽然它是一个经典的父子上下文层次结构.

唯一"坏"的是,我们需要@EnableMvcConfig并且不要在上下文中从Spring启动获取自动配置的糖.父上下文正在自动配置.我在其中放了一些数据库内容application.properties,并在MyService其中调用了一个查询FooController,它完美无缺!:)

我希望这可以帮助一些人!