Мне удалось воспроизвести проблему и найти обходной путь для перенаправления 301 на DTD.
Сначала я настроил тест, в котором AplicationContext создается на основе файла XMLсо ссылкой 301:
import org.junit.Test;
import org.springframework.context.ApplicationContext;
public class MovedDtdTest {
@Test
public void test()throws Exception {
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:test.xml");
}
}
test.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.nos.nl">
</beans>
Что привело к тому же исключению:
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException:
Line 2 in XML document from class path resource [test.xml] is invalid;
nested exception is org.xml.sax.SAXParseException; systemId: http://nos.nl/;
lineNumber: 2; columnNumber: 35; s4s-elt-character: Non-whitespace characters
are not allowed in schema elements other than 'xs:appinfo' and 'xs:documentation'.
Saw '301 Moved Permanently'.
...
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392)
Затем я начал отлаживать стекпроследите и заметили, что в файле XmlBeanDefinitionReader
присутствует следующий статический атрибут:
public static final int VALIDATION_NONE = XmlValidationModeDetector.VALIDATION_NONE;
, установленный в org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setValidating
:
public void setValidating(boolean validating) {
this.validationMode = (validating ? VALIDATION_AUTO : VALIDATION_NONE);
this.namespaceAware = !validating;
}
При желании вы можетедобавьте точку останова в методе выше и установите для validating
значение false, чтобы протестировать ее.
После поиска того, как переопределить XmlBeanDefinitionReader
, я наткнулся на старый пост StackOverflow о том, каксоздать и использовать пользовательский NamespaceHandlerResolver
Я изменил его, чтобы изменить поведение XmlBeanDefinitionReader вместо NamespaceHandlerResolver:
public class CustomClassPathXmlApplicationContext extends FileSystemXmlApplicationContext {
public CustomClassPathXmlApplicationContext(String... configLocations) throws BeansException {
super(configLocations, true, null);
}
@Override
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
super.initBeanDefinitionReader(reader);
reader.setValidating(false);
}
}
И отредактировал мой тест для загрузки ApplicationContextиспользуя CustomClassPathXmlApplicationContext
:
@Test
public void test()throws Exception {
ApplicationContext context = new CustomClassPathXmlApplicationContext("classpath:test.xml");
}
Теперь тест проходит с:
18:28:41.753 [main] DEBUG xxx.xx.xx.CustomClassPathXmlApplicationContext - Refreshing xx.xx.xx.x.CustomClassPathXmlApplicationContext@2bbf4b8b
18:28:42.014 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 0 bean definitions from class path resource [test.xml]
Я не знаю, как ApplicationContext загружается в ваше приложение, но, как вы упомянули «устаревшее» приложениеЯ использовал XmlConfig вместо JavaConfig.
Я надеюсь, что вы сможете найти способ изменить поведение XmlBeanDefinitionReader
в вашем ApplicationContext.Это должно произойти на ранней стадии жизненного цикла Spring, так как XML анализируется перед созданием bean-компонентов.