Spring Boot集成现有Spring Web应用时加载application.xml失败求助
首先明确一点:Spring Boot本身完全不要求application.xml——它默认只会加载application.properties或application.yml格式的配置文件。你遇到的这个异常,本质是项目的依赖或自定义逻辑修改了Spring Boot的配置加载行为,强制它去尝试读取XML格式的属性文件。
核心原因分析
从你的异常栈可以看到,ConfigFileApplicationListener(Spring Boot负责加载配置的核心组件)在尝试加载classpath:/application.xml作为属性源。而Java的Properties类虽然支持XML格式,但要求严格符合特定DTD(你异常里提到的http://java.sun.com/dtd/application_1_3.dtd其实是错误的目标DTD,正常应该是properties.dtd,这也说明加载逻辑被错误引导了)。
出现这个情况的常见诱因:
- 某个第三方依赖(尤其是老版本的Spring组件、企业级框架)修改了Spring Boot的配置加载规则,比如默认设置
spring.config.extensions包含xml; - 原有Spring Web项目的遗留代码中,存在自定义的
EnvironmentPostProcessor或ApplicationContextInitializer,强制添加了XML格式的配置源; - 项目的
spring.factories文件中,有自定义的ConfigFileApplicationListener实现,改变了默认的配置文件查找逻辑。
分步解决建议
1. 快速临时修复(应急用)
如果需要先让项目跑起来,可以创建一个符合规范的空XML属性文件放在src/main/resources下,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> </properties>
这个文件完全符合Java Properties XML的规范,Spring Boot加载后不会再抛出格式异常。
2. 排查并修复根源问题
(1)检查依赖树,找出触发XML加载的依赖
用你的构建工具生成依赖树,排查异常依赖:
- Maven:执行
mvn dependency:tree - Gradle:执行
./gradlew dependencies
重点查找:
- 是否有依赖引入了自定义的配置加载扩展;
- 是否有依赖默认设置了
spring.config.name或spring.config.extensions参数; - 是否有老版本的Spring组件(比如Spring 4.x之前的)与Spring Boot 1.5.x产生冲突。
(2)显式指定Spring Boot的配置文件格式
在启动类中强制指定只加载properties/yml格式的配置,直接阻止Spring Boot尝试读取XML:
@SpringBootApplication public class Application { public static void main(final String[] args) { SpringApplication app = new SpringApplication(Application.class); // 明确指定配置文件扩展名,排除xml格式 app.setDefaultProperties(Collections.singletonMap("spring.config.extensions", "properties,yml,yaml")); app.run(args); } }
也可以通过JVM启动参数直接设置:
-Dspring.config.extensions=properties,yml,yaml
(3)检查项目中的自定义配置逻辑
- 查看
src/main/resources/META-INF/spring.factories文件,是否有自定义的ConfigFileApplicationListener或EnvironmentPostProcessor条目; - 搜索项目中是否有实现
EnvironmentPostProcessor或ApplicationContextInitializer的类,这些类可能修改了配置加载行为; - 检查原有Spring Web项目的配置文件,是否有遗留的配置逻辑被Spring Boot继承。
为什么从零搭建的Spring Boot项目没这个问题?
纯Spring Boot初始化的项目没有额外的遗留依赖或自定义逻辑,完全遵循Spring Boot的默认配置加载规则,所以不会去寻找application.xml。而你当前的项目是在已有Spring Web应用上集成,难免会带入原有项目的依赖或配置逻辑,这就是两者的核心差异点。
内容的提问来源于stack exchange,提问作者Adomas

