如何在XML和Java配置的Spring Web应用程序的WebApplicationContext中加载其他bean和配置文件?

时间:2019-07-12 09:35:29

标签: java spring servlets servlet-3.0 applicationcontext

我正在构建一个库,该库通过实现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个问题:

  1. AnnotationConfigWebApplicationContext类似乎是在初始化此类应用程序的根Web应用程序上下文之前加载的。因此@WebListener总是返回异常。
    getRequiredWebApplicationContext事件上调用@WebListener,而不是在拥有根Web上下文的ApplicationContextFacade事件上调用。

  2. 我删除了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应用程序实现相同的目标?有没有更好的方法来做我想做的事情?使用我的库使它对应用程序尽可能透明。

0 个答案:

没有答案