Spring Boot构建Fat JAR遇Jersey资源扫描文件不存在错误
嘿,我一眼就看出问题出在哪了——你用的Jersey版本(2.25.1)根本不兼容Spring Boot Fat Jar的目录结构!Spring Boot把编译好的类都塞在BOOT-INF/classes下面,但旧版Jersey的资源扫描器完全搞不懂这种嵌套在Jar里的路径,所以才会报找不到文件的错。
下面给你几个靠谱的解决办法,按优先级来:
1. 优先升级Jersey到兼容版本
Spring Boot 1.5.12.RELEASE对应的Jersey,只要升级到2.26-b03及以上版本,这个问题就直接解决了——这个版本专门修复了Fat Jar资源扫描的bug。你只需要在POM里加个版本属性统一覆盖就行:
<properties> <jersey.version>2.26-b03</jersey.version> </properties>
2. 要是没法升级,就换个扫描器
如果因为项目限制不能升级Jersey,那咱们就手动接管Jersey的资源注册,用Spring的扫描器代替Jersey自带的。写个配置类就行:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ServerProperties; @Configuration public class JerseyConfig { @Bean public ResourceConfig jerseyResourceConfig() { ResourceConfig config = new ResourceConfig(); // 先关掉Jersey自己的自动扫描 config.property(ServerProperties.PROVIDER_SCANNING_RECURSIVE, false); // 用Spring的扫描器手动找所有Jersey资源和提供者 PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); try { // 把这里换成你自己的Jersey资源包路径 String[] packages = {"com.yourteam.resources", "com.yourteam.providers"}; for (String pkg : packages) { String pattern = "classpath*:" + pkg.replace('.', '/') + "/**/*.class"; org.springframework.core.io.Resource[] resources = resolver.getResources(pattern); for (org.springframework.core.io.Resource resource : resources) { String className = resource.getFilename().replace(".class", ""); String fullClassName = pkg + "." + className; config.register(Class.forName(fullClassName)); } } } catch (Exception e) { throw new RuntimeException("注册Jersey资源失败", e); } return config; } }
3. 清理一下Maven插件的多余配置
看你的POM里spring-boot-maven-plugin加了requiresUnpack配置,除非那个my.com:myArtifact依赖真的需要解压才能用,不然这个配置可以删掉——Jersey本身不需要解压,留着反而可能添乱:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin>
4. 顺便解决依赖版本不一致的问题
看你的依赖树里,jersey-apache-connector用的是2.17版本,和其他Jersey组件的2.25.1不统一,这很容易出兼容性问题。建议在POM里加个dependencyManagement统一所有Jersey的版本:
<dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey</groupId> <artifactId>jersey-bom</artifactId> <version>${jersey.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
最后说下为啥会出这问题
Spring Boot的Fat Jar是嵌套结构:应用类在BOOT-INF/classes,依赖Jar在BOOT-INF/lib。但旧版Jersey(2.25.1及以下)的扫描器只能识别传统的Jar路径(比如file:/xxx.jar!/),根本看不懂file:/xxx.jar!/BOOT-INF/classes这种嵌套路径,所以才会报找不到文件的错。
内容的提问来源于stack exchange,提问作者Chad Van De Hey

