Spring Boot 带有多个 DispatcherServlet,每个都有自己的 @Controllers
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30670327/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Boot with multiple DispatcherServlet, each having their own @Controllers
提问by Benjamin M
Basically I want to split my application into 2 parts. Each part has it's own security stuff and own @Controller
s. The @Services
should be accessible from both parts.
基本上我想将我的应用程序分成两部分。每个部分都有自己的安全内容和自己的@Controller
s。本@Services
应该从两个部分进行访问。
So I thought, I should get 2 DispatcherServlet
. One listening to /admin/*
and the second listening to everything else ( /
). Each of those will have its own AnnotationConfigWebApplicationContext
so I can have separate component scan for the @Controller
s.
所以我想,我应该得到 2 DispatcherServlet
。一个听,/admin/*
第二个听其他一切(/
)。每个都有自己的,AnnotationConfigWebApplicationContext
所以我可以对@Controller
s进行单独的组件扫描。
And because Spring Boot provides one DispatcherServlet
listening on /
out of the box, I thought, I can just add a second one:
因为 Spring Boot 提供了一个开箱即用的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;
}
}
The MyConfig2
class, only has @Configuration
and @ComponentScan
. Within the same package is a @Controller
.
该MyConfig2
班,只有@Configuration
和@ComponentScan
。在同一个包中是一个@Controller
.
When starting the application, I can see, that the second servlet mapping is getting registered, but the @Controller
is not. Additionally I can now access all@Controllers
from /
and/admin
.
启动应用程序时,我可以看到第二个 servlet 映射正在注册,但@Controller
没有注册。此外,我现在可以从和访问所有内容。@Controllers
/
/admin
Any idea how I can get this working?
知道如何让这个工作吗?
回答by Benjamin M
I got it working somehow!
我以某种方式让它工作了!
Here's my Package Layout:
这是我的包布局:
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:
应用程序.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.
- 这
exclude
确实会阻止 Spring Boot 创建自己DispatcherServlet
的/
映射。如果您想要该映射或定义您自己的映射,您可以删除该行。 servletRegistrationBean.setLoadOnStartup(1)
如果您希望在应用程序启动时初始化 Servlet,您可以添加。否则,它将等待对该 servlet 的第一个请求。- 设置 很重要
servletRegistrationBean.setName(...)
,否则 servlet 将相互覆盖。
FooConfig.java & BarConfig.java:
FooConfig.java 和 BarConfig.java:
@Configuration @ComponentScan @EnableWebMvc
public class FooConfig { }
@EnableWebMvc
will enable the component scan. Without it, it won't find the@Controller
class.
@EnableWebMvc
将启用组件扫描。没有它,它就找不到@Controller
类。
The Controller and Service codeis 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)
控制器和服务代码并不重要。你只需要知道,如果你在@RequestMapping("/foo")
里面FooController
,请求一定是GET /foo/foo
因为 Servlet 的 URL 映射是/foo/*
. 无法调用 URL,GET /foo
因为 Servlet URL 映射需要/
在其路径的末尾(换句话说:GET /foo
将查找具有/
映射的 Servlet !),但@RequestMapping("")
必须通过GET /foo/
. 当然,不可能使用/foo
或/foo*
作为 Servlet 映射(或者我只是没有找到正确的设置)
Scope:The Controllers can't seeeach other, though it's notpossible to @Autowired
them in each other. Also the Service can't @Autowired
any of the Controllers. Butthe Controllers can @Autowired
the Service.
适用范围:该控制器无法看到对方,虽然它没有可能@Autowired
他们彼此。此外,服务不能使用@Autowired
任何控制器。但是控制器可以@Autowired
服务。
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! :)
唯一“不好”的事情是,我们需要@EnableMvcConfig
并且不从上下文中的 Spring boot 获取自动配置的糖。父上下文正在自动配置。我在application.properties
里面放了一些数据库的东西,并在里面做了一个查询,MyService
它被调用了FooController
,它工作得很好!:)
I hope this may help some people!
我希望这可以帮助一些人!