Spring Boot打包成Jar后ServiceLoader加载URLStreamHandlerProvider失败
问题原因
Spring Boot打包的Fat Jar使用LaunchedURLClassLoader加载BOOT-INF/classes下的应用类,而JDK的ServiceLoader默认会使用系统类加载器(无法访问BOOT-INF内部的类)或启动初期的上下文类加载器查找服务提供者,导致找不到你实现的ClasspathURLStreamHandlerProvider。另外URL.setURLStreamHandlerFactory已被嵌入式Tomcat调用,无法重复使用。
解决方案
方法一:手动指定类加载器加载服务提供者
在应用启动初期,用应用类加载器手动触发ServiceLoader加载你的Provider,确保服务能被正确注册:
import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import java.net.spi.URLStreamHandlerProvider; import java.util.ServiceLoader; @Component public class URLHandlerBootstrap implements CommandLineRunner { @Override public void run(String... args) { // 使用当前类的类加载器(即LaunchedURLClassLoader)加载服务提供者 ServiceLoader<URLStreamHandlerProvider> loader = ServiceLoader.load( URLStreamHandlerProvider.class, this.getClass().getClassLoader() ); // 遍历触发加载,完成注册 loader.iterator().forEachRemaining(provider -> {}); } }
方法二:确认服务配置文件正确性
确保META-INF/services/java.net.spi.URLStreamHandlerProvider文件被正确打包到BOOT-INF/classes下(Spring Boot Maven插件默认会处理),文件内容为你的Provider全类名:
com.example.springlog.ClasspathURLStreamHandlerProvider
验证方式
打包后运行Jar,检查是否不再抛出ServiceConfigurationError,同时测试类路径URL定位功能是否正常工作。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

