使用自动配置创建多个(功能)webmvc应用程序的Spring Boot
使用自动配置创建多个(功能)webmvc应用程序的Spring Boot
我的问题是如何在Spring Boot中初始化一个孤立的Spring WebMVC Web应用程序。这个孤立的Web应用程序应该具备以下特点:
- 不应该在应用程序类中初始化自己。我们希望通过自动配置在starter pom中完成这些操作。我们有多个这样的Web应用程序,需要自动配置的灵活性。
- 能够使用接口进行自定义,例如:WebSecurityConfigurer(每个Web应用程序都以自己的方式进行安全性配置)和EmbeddedServletContainerCustomizer(用于设置Servlet的上下文路径)。
- 我们需要隔离特定于某些Web应用程序的bean,并且不希望它们进入父上下文。
我的META-INF/spring.factories中列出了以下配置类。
以下策略无法生成一个正常工作的Web-MVC servlet。上下文路径和安全性都没有被自定义。我的猜想是我需要包含某些处理上下文并根据存在的bean进行自动配置的webmvc bean,类似于我通过包含PropertySourcesPlaceholderConfigurer.class来使基于属性的占位符配置工作的方式。
@Configuration
@AutoConfigureAfter(DaoServicesConfiguration.class)
public class MyServletConfiguration {
@Autowired
ApplicationContext parentApplicationContext;
@Bean
public ServletRegistrationBean myApi() {
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.setParent(parentApplicationContext);
applicationContext.register(PropertySourcesPlaceholderConfigurer.class);
// 还注册了一些其他类。这些类不能添加到父应用程序上下文中。
// 包括WebSecurityConfigurerAdapter和EmbeddedServletContainerCustomizer的实现
applicationContext.scan(
// 一些包
);
DispatcherServlet ds = new DispatcherServlet();
ds.setApplicationContext(applicationContext);
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(ds, true, "/my_api/*");
servletRegistrationBean.setName("my_api");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}
}
Spring Boot创建多个(功能性)WebMVC应用程序的原因是无法找到一种使用自动配置来使用多个Servlet的方法。然而,可以使用ServletRegistrationBean为应用程序注册多个Servlet。可以使用AnnotationConfigWebApplicationContext来初始化上下文,这样可以使用默认的Spring配置工具(而不是Spring Boot工具)来配置Servlet。使用这种类型的上下文,只需要注册一个配置类。
如果要处理多部分请求,应该为注册Bean设置多部分配置。可以通过自动装配注册来解析这个配置,并从父上下文中解析。
作者还创建了一个小的GitHub示例项目,可以在这里找到。
需要注意的是,作者通过Java包设置了Servlet配置,但也可以为此目的定义自定义注解。
Spring Boot创建多个(功能)WebMVC应用程序使用自动配置的原因是为了实现在同一个项目中使用不同的配置和功能,并且能够通过不同的URL访问这些应用程序。以下是解决方法的代码示例:
public class JettyConfiguration { public ServletContextHandler servletContext() throws IOException { ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS); // 创建根WebApplicationContext AnnotationConfigWebApplicationContext rootWebApplicationContext = new AnnotationConfigWebApplicationContext(); rootWebApplicationContext.setParent(applicationContext); rootWebApplicationContext.refresh(); rootWebApplicationContext.getEnvironment().setActiveProfiles(applicationContext.getEnvironment().getActiveProfiles()); // 设置根WebApplicationContext属性和路径 handler.setAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, rootWebApplicationContext); handler.setContextPath("/my-root"); handler.setResourceBase(new ClassPathResource("webapp").getURI().toString()); // 添加自定义的Servlet和配置文件 handler.addServlet(AdminServlet.class, "/metrics/*");//DROPWIZARD // 添加默认的DispatcherServlet DispatcherServlet dispatcherServlet = new DispatcherServlet(); handler.addServlet(new ServletHolder("dispatcherServlet", dispatcherServlet), "/"); // 添加第一个Web应用程序 DispatcherServlet webMvcDispatcherServlet1 = new DispatcherServlet(); webMvcDispatcherServlet1.setContextConfigLocation("classpath*:/META-INF/spring/webmvc-config1.xml"); webMvcDispatcherServlet1.setDetectAllHandlerAdapters(true); webMvcDispatcherServlet1.setDetectAllHandlerMappings(true); webMvcDispatcherServlet1.setDetectAllViewResolvers(true); webMvcDispatcherServlet1.setEnvironment(applicationContext.getEnvironment()); handler.addServlet(new ServletHolder("webMvcDispatcherServlet1",webMvcDispatcherServlet1), "/web1/*"); // 添加第二个Web应用程序 DispatcherServlet webMvcDispatcherServlet2 = new DispatcherServlet(); webMvcDispatcherServlet2.setContextConfigLocation("classpath*:/META-INF/spring/web-yp-config.xml"); webMvcDispatcherServlet2.setDetectAllHandlerAdapters(true); webMvcDispatcherServlet2.setDetectAllHandlerMappings(true); webMvcDispatcherServlet2.setDetectAllViewResolvers(false); webMvcDispatcherServlet2.setEnvironment(applicationContext.getEnvironment()); handler.addServlet(new ServletHolder("webMvcDispatcherServlet2",webMvcDispatcherServlet2), "/web2/*"); // 添加第一个Web Services应用程序 MessageDispatcherServlet wsDispatcherServlet1 = new MessageDispatcherServlet(); wsDispatcherServlet1.setContextConfigLocation("classpath*:/META-INF/spring/ws-config1.xml"); wsDispatcherServlet1.setEnvironment(applicationContext.getEnvironment()); handler.addServlet(new ServletHolder("wsDispatcherServlet1", wsDispatcherServlet1), "/ws1/*"); // 添加第二个Web Services应用程序 MessageDispatcherServlet wsDispatcherServlet2 = new MessageDispatcherServlet(); wsDispatcherServlet2.setContextConfigLocation("classpath*:/META-INF/spring/ws-siteconnect-config.xml"); wsDispatcherServlet2.setEnvironment(applicationContext.getEnvironment()); handler.addServlet(new ServletHolder("wsDispatcherServlet2", wsDispatcherServlet2), "/ws2/*"); // 添加Spring Security过滤器 handler.addFilter(new FilterHolder( new DelegatingFilterProxy("springSecurityFilterChain")), "/*", null); return handler; } public Server jettyServer() throws IOException { // 创建Jetty服务器 Server server = new Server(); // 创建基本连接器 ServerConnector httpConnector = new ServerConnector(server); httpConnector.setPort(9083); server.addConnector(httpConnector); // 设置处理程序 server.setHandler(servletContext()); return server; } }
以上代码使用Jetty服务器创建了一个Web应用程序,该应用程序包含了多个功能,并通过不同的URL进行访问。通过使用不同的DispatcherServlet和配置文件,可以实现在同一个项目中创建多个独立的WebMVC应用程序。
Spring Boot可以创建多个(功能)WebMVC应用程序的原因是因为它使用了自动配置。解决这个问题的方法是创建一个父Spring配置,其中包含所有要共享的父bean。然后创建一个确定特定应用程序模块类型的类型,并在其中指定所需的上下文路径或其他应用程序特定数据。接下来创建一个整个应用程序的Boot应用程序初始化器,并在其中注册ServletRegistrationBean。此外,创建一个抽象配置类,其中包含子特定的bean和无法通过父上下文共享的内容。最后,创建一个入口点类来编译整个应用程序。通过初始化子应用程序并准备入口点,可以启动多个应用程序。
以上是解决Spring Boot创建多个(功能)WebMVC应用程序使用自动配置的问题的方法。这种方法可以帮助开发人员在一个应用程序中创建多个WebMVC应用程序,并共享父bean和特定于子应用程序的bean。通过这种方法,开发人员可以更好地组织和管理他们的应用程序,并实现更好的代码重用和可维护性。
参考链接:
- https://dzone.com/articles/what-servlet-container
- https://stackoverflow.com/questions/33163441
- https://stackoverflow.com/questions/11815339