java - 如何从 WEB-INF 加载 'mini' spring 上下文以初始化真实的应用程序上下文

标签 java spring spring-mvc applicationcontext

我有一个遗留的 Spring 3 Web 应用程序,它使用配置数据库来加载配置值,例如 url、超时等。

目前,配置数据库中的值以编程方式使用。

当前有一个应用程序上下文,其中配置数据库访问器代码与所有其他组件一起初始化(Spring 存储库)。

由于这个单一上下文,来自配置数据库的配置值不能在“@Value”注释中使用。当我可以访问这些值时,上下文已初始化,bean 已创建。

目标是允许通过 bean 中的“@Value”注释使用基于 config-db 的值。

所以我的想法是将 config-db 访问器 bean(数据源、实体管理器等)分离到“迷你”上下文中,并且:

  1. 从一开始就加载该迷你上下文,
  2. 然后将配置数据库中的值加载到属性中
  3. 然后将该属性插入“真实”上下文的 PropertySource

我几乎在所有事情上都成功了,但我只能从类路径初始化这个“迷你上下文”,而不是从 WEB-INF (WEB-INF 不在类路径上,只有 WEB-INF/classes 在)。我当前的初始化如下所示:

注册 Spring 调度程序 servlet 的上下文监听器:

<servlet>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextInitializerClasses</param-name>
        <param-value>xxx.xxx.ContextInitializer</param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/application-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

然后在ContextInitializer中:

public void initialize(ConfigurableApplicationContext applicationContext) {
    ClassPathXmlApplicationContext miniContext = 
            new ClassPathXmlApplicationContext("jpa-context-for-config-db.xml");
    ParameterDao parameterDao = miniContext.getBean(ParameterDao.class);
    Properties propertiesFromConfigDb = getPropertiesFromConfigDb(parameterDao);
    applicationContext.getEnvironment().getPropertySources().addFirst(
            new PropertiesPropertySource("parameterDaoBasedProperties", propertiesFromConfigDb));
    miniContext.close();
}

这是有效的,但是

  1. 我必须将迷你上下文 xml 放入/WEB-INF/classes 中,这不是其他上下文文件所在的位置(其他上下文文件位于/WEB-INF 中)

  2. 我无法在“location="/WEB-INF/....”的小型上下文中使用 property-placeholders 或 util:properties。

我尝试使用 GenericXmlApplicationContext 并使用它的 setResourceLoader 但尚未成功。

那么有没有办法以编程方式从 WEB-INF 而不是从类路径加载 spring context.xml?

最佳答案

在 Spring Web 应用程序中,可以通过 org.springframework.web.context.support.ServletContextResourceLoader 访问 WEB-INF 的内容。该类可以从 WEB-INF 加载资源。

所以初始化方法应该如下所示:

public void initialize(ConfigurableApplicationContext applicationContext) {
    ServletContext servletContext = ContextLoaderListener.getCurrentWebApplicationContext().getServletContext();
    GenericXmlApplicationContext miniContext = new GenericXmlApplicationContext();
    miniContext.setResourceLoader(new ServletContextResourceLoader(servletContext));
    miniContext.load("/WEB-INF/jpa-context-for-config-db.xml");
    miniContext.refresh();
    ParameterDao parameterDao = miniContext.getBean(ParameterDao.class);
    Properties propertiesFromConfigDb = getPropertiesFromConfigDb(parameterDao);
    applicationContext.getEnvironment().getPropertySources().addFirst(
            new PropertiesPropertySource("parameterDaoBasedProperties", propertiesFromConfigDb));
    miniContext.close();
}

关于java - 如何从 WEB-INF 加载 'mini' spring 上下文以初始化真实的应用程序上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55965937/

相关文章:

java - DAOImpl接口(interface)

java - 使用 Xpath 读取节点列表

java - 如何在 Swagger 中忽略类属性

java - 如何在 Spring MVC 中进行休息服务?

java - 我正在使用 Spring-Boot,使用类名字符串动态初始化类并获取返回值

java - 为什么我的 'transparent' 叠加 View 不透明?

java - xml 资源或 sqlite

java - 如何在同一行上使用 map 和 orElseThrow?

java - 为什么 HTTPServlet 是一个抽象类?任何功能原因?

java - "add non-palette componente"的 Intellij 错误