基本的に、アプリケーションを2つの部分に分割します。各部分には、独自のセキュリティと独自の@Controller
sがあります。 @Services
は、両方の部分からアクセスできる必要があります。
だから、2 DispatcherServlet
を取得する必要があると思いました。 1つは/admin/*
をリッスンし、2つ目は他のすべてをリッスンします(/
)。これらはそれぞれ独自のAnnotationConfigWebApplicationContext
を持つため、@Controller
sの個別のコンポーネントスキャンを実行できます。
また、Spring BootはDispatcherServlet
をすぐに/
でリッスンするので、2つ目を追加できると思いました。
@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;
}
}
MyConfig2
クラスには、@Configuration
と@ComponentScan
のみがあります。同じパッケージ内には@Controller
があります。
アプリケーションを起動すると、2番目のサーブレットマッピングが登録されていることがわかりますが、@Controller
は登録されていません。さらに、@Controllers
からall/
にアクセスできるようになりましたおよび/admin
。
これをどのように機能させることができますか?
なんとか機能しました!
これが私のパッケージレイアウトです。
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;
}
}
exclude
は、Spring Bootが/
マッピングで独自のDispatcherServlet
を作成することを防ぎます。マッピングが必要な場合、または独自に定義する場合は、その行を削除できます。servletRegistrationBean.setLoadOnStartup(1)
を追加できます。それ以外の場合は、そのサーブレットの最初のリクエストを待ちます。servletRegistrationBean.setName(...)
を設定することが重要です。そうしないと、サーブレットが互いにオーバーライドします。FooConfig.JavaおよびBarConfig.Java:
@Configuration @ComponentScan @EnableWebMvc
public class FooConfig { }
@EnableWebMvc
は、コンポーネントスキャンを有効にします。これがないと、@Controller
クラスが見つかりません。コントローラーおよびサービスコードは重要ではありません。 FooController
内に@RequestMapping("/foo")
がある場合、サーブレットのURLマッピングはGET /foo/foo
であるため、リクエストは/foo/*
でなければなりません。サーブレットURLマッピングのパスの最後にGET /foo
が必要なため、URL /
を呼び出すことはできません(つまり、GET /foo
は、/
マッピングでサーブレットを探します!)。ただし、@RequestMapping("")
はGET /foo/
。そしてもちろん、/foo
または/foo*
をサーブレットマッピングとして使用することはできませんでした(または、そのための正しい設定が見つかりませんでした)
Scope:コントローラーは相互に参照することはできませんが、お互いに@Autowired
することは可能です not 。また、サービスはどのコントローラも@Autowired
できません。 しかし/コントローラーはサービスを@Autowired
できます。
それは古典的な親子コンテキスト階層ですが。
唯一の「悪い」ことは、@EnableMvcConfig
が必要であり、コンテキスト内のSpringブートから自動構成されたシュガーを取得しないことです。親コンテキストは自動構成されています。私はapplication.properties
内にいくつかのデータベースを配置し、MyService
によって呼び出されたFooController
内でクエリを実行しましたが、問題なく動作しました! :)
これが一部の人々に役立つことを願っています!