我正在构建一个库,该库通过实现ServletContextListener
接口来侦听Spring Web应用程序的根Web应用程序上下文的初始化。我正在使用Servlet API 3.0。
然后,该库在刷新上下文之前将一些必要的配置文件(主要是控制器bean和spring安全配置XML文件)加载到Web应用程序上下文中。
@WebListener
public class CustomListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
this.servletContext = sce.getServletContext();
WebApplicationContext wac = null;
try {
wac = WebApplicationContextUtils.getRequiredWebApplicationContext(this.servletContext);
} catch (IllegalStateException ise) {
logger.error("Could not retrieve the WebApplicationContext", ise);
} catch (Exception e) {
logger.error("Encountered an error while trying to retrieve the WebApplicationContext", e);
}
if (wac != null && wac instanceof XmlWebApplicationContext) {
wac.getEnvironment().getPropertySources().addFirst(CustomProperties.getInstance());
//configLocations will contain = ["classpath*:securityContext.xml", "classpath*:spring-controllers.xml"]
String[] configLocations = this.getCustomConfigFilesLocations();
wac.setConfigLocations(configLocations);
wac.refresh();
Optional<String> servletName = ContextInitializerUtils.getServletNameForClass(this.servletContext,
org.springframework.web.servlet.DispatcherServlet.class);
if (!servletName.isPresent()) {
DispatcherServlet serv = new DispatcherServlet(wac);
ServletRegistration.Dynamic servletDynamic = servletContext.addServlet("spring", servlet);
servletDynamic.addMapping("/customapi/*");
servletDynamic.setLoadOnStartup(1);
}
else {
this.servletContex.servletContext.getServletRegistrations().get(servletName).addMapping("/customapi/*");
}
}
else {
//What should I do in this case ?
}
}
}
这很好用,我可以使用在我的库中使用的应用程序访问我的控制器,并使用在文件中声明的Spring Security配置...,但仅适用于具有基于XML的配置并且声明了{{ 1}}在他们的web.xml中。
我希望能够对具有基于Java的配置的Spring应用程序以及最终的Spring Boot应用程序执行相同的操作。
使用Java配置的Spring应用程序,我尝试在同一类中使用ContextLoaderListener
做类似的事情,但是遇到了2个问题:
AnnotationConfigWebApplicationContext
类似乎是在初始化此类应用程序的根Web应用程序上下文之前加载的。因此@WebListener
总是返回异常。
在getRequiredWebApplicationContext
事件上调用@WebListener
,而不是在拥有根Web上下文的ApplicationContextFacade
事件上调用。
我删除了StandardContext$NoPluggabilityServletContext
批注,并尝试通过实现@WebListener
接口并在WebApplicationInitializer
方法中将侦听器添加到servletContext
来以编程方式加载侦听器。
似乎可行,我可以通过onStartup
事件访问Root Web应用程序上下文,但是当我尝试使用Servlet 3.0 API进行访问时。 StandardContext$NoPluggabilityServletContext
getFilterRegistrations
...
我遇到这个异常:
addServlet
addServlet java.lang.UnsupportedOperationException: Section 4.4 of the Servlet 3.0 specification does not permit this method to be called from a ServletContextListener that was not defined in web.xml
我做错了什么?如何为Java配置的Spring应用程序实现相同的目标?有没有更好的方法来做我想做的事情?使用我的库使它对应用程序尽可能透明。