Указание относительного пути к ресурсу через Spring XmlWebApplicationContext

Фактический вопрос: есть ли способ заставить XmlWebApplicationContext загружать ресурсы, используя пути относительно местоположения контекста? Для ясности предположим, что «местоположение контекста» — это расположение первого файла, указанного с помощью метода setConfigLocation().

Подробное объяснение приведено ниже:
Я использую Spring MVC на веб-уровне и Spring IOC на промежуточном уровне. Соответствующие контексты определяются иерархически, как описано в документации Spring.: веб-материалы определены в my-servlet.xml, а сервисы и др. определены в services.xml, которые загружаются через ContextLoaderListener. Средний уровень может быть развернут либо вместе с веб-уровнем (например, все это выполняется в ServletContainer), либо отдельно (в этом случае services.xml заменяется remote-services.xml, определяющим удаленные заглушки). Вся установка работает отлично, за исключением следующей проблемы:

У меня есть определенные ресурсы (дополнительные файлы XML, что у вас есть), расположенные в той же папке, что и services.xml, которые должны быть доступны указанным службам. Эти ресурсы указаны как зависимости в services.xml с использованием относительных путей. Когда средний уровень развернут автономно, это работает нормально, но не когда он развернут в контейнере сервлетов. В последнем случае контекст среднего уровня создается как XmlWebApplicationContext, который загружает все ресурсы, основанные на корневом контексте сервлета, что означает, что мне нужно добавлять ко всему префикс /WEB-INF/, чего я действительно хотел бы избежать. Аналогичная проблема возникает и при использовании PropertyPlaceholderConfigurer.

Я знаю, что могу обойти это, загрузив ресурсы из пути к классам, но это тоже не идеально - для автономного развертывания это означает, что мне нужно добавить папку конфигурации в путь к классам, а для веб-развертывания это означает, что все должно быть скопировано в WEB-INF/ классы.

Есть идеи?


person ChssPly76    schedule 14.07.2009    source источник


Ответы (3)


В итоге я расширил Spring XmlWebApplicationContext, чтобы разрешить относительные пути к ресурсам. Это делает то, что я хочу, то есть позволяет мне использовать один и тот же файл context.xml независимо от того, развернут ли он как часть веб-приложения или отдельно.

Для всех желающих источник доступен ниже. Он опубликован с использованием лицензии SOV (голосование за переполнение стека) :-), что означает, что вы можете делать с ним все, что хотите, пока вы голосуете за этот ответ :-)

import java.io.IOException;

import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;

/**
 * Extends Spring's default web application context to allow relative
 * resource paths. Resources without explicitly specified URL protocol
 * and / or leading slash are loaded relative to the first location
 * from getConfigLocations().
 */

public class SpringApplicationContext extends XmlWebApplicationContext {

  @Override
  protected Resource getResourceByPath(String path) {
    path = StringUtils.cleanPath(path);
    if (path.startsWith("/") || (path.indexOf(':')>0)) {
      return super.getResourceByPath(path);
    }
    try {
      return super.getResourceByPath(getConfigLocations()[0])
        .createRelative(path);
    } catch (IOException E) {
      // failed to create relative resource - default to standard implementation
      return super.getResourceByPath(path);
    }
  } // getResourceByPath()
}
person ChssPly76    schedule 17.07.2009

Я согласен, что это довольно раздражает. Я обхожу это, делая то, что вы предлагаете, то есть помещая мою конфигурацию spring в путь к классам, поэтому, хотя я все еще использую полностью квалифицированный импорт, они работают в любой среде.

Однако я не уверен, почему ваша конфигурация пути к классам должна быть такой сложной. Файлы могут находиться прямо в исходной папке Java вместе с файлами Java, поэтому они обрабатываются одинаково.

person skaffman    schedule 14.07.2009
comment
Спасибо за ответ. Размещение ресурсов вместе с java-файлами в некоторых случаях прекрасно подходит (я делаю это для запросов Hibernate и т. д.), но довольно неудобно для вещей, которые можно изменить во время развертывания (например, файл свойств, используемый PropertyPlaceholderConfigurer). Он должен быть доступен (например, не внутри jar и т. д.), поэтому я должен либо поместить его в /WEB-INF/classes, либо добавить папку «conf», в которой он находится, в путь к классам во время автономного развертывания. - person ChssPly76; 14.07.2009

Странный. Ваше решение не работает для меня. Вот мой:

package dmp.springframework.web.context;

import java.io.IOException;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;

public class RelativeResourceXmlWebApplicationContext extends XmlWebApplicationContext {

    @Override
    protected Resource getResourceByPath(String path) {
        path = StringUtils.cleanPath(path);
        if (path.startsWith("/") || (path.contains(":"))) {
            return super.getResourceByPath(path);
        }
        try {
            String newFilename = super.getResourceByPath(getConfigLocations()[0]).getFile().getParentFile().getAbsolutePath();
            newFilename = newFilename + "/" + path;
            return new FileSystemResource(newFilename);
        } catch (IOException E) {
            // failed to create relative resource - default to standard implementation
            return super.getResourceByPath(path);
        }
    } // getResourceByPath()
}
person Raigedas    schedule 08.11.2010