最近在在使用 @Value 注入文件碰到如下问题: 工程在在 IntelliJ IDEA 开发环境里正常运行, 但是一旦将工程打包成 jar 包运行, 就报 java.io.FileNotFoundException: class path resource 错
代码如下: 通过 @Value 将 resource 目录下 test/billingconfig-file.xml 目录注入到 Resource 上
- @Value("classpath:test/billingconfig-file.xml")
- private Resource resourceFile; // 注入计费点文件资源
- JAXBContext context = JAXBContext.newInstance(BillingModelList.class);
- Unmarshaller unmarshaller = context.createUnmarshaller();
- BillingModelList billingModelList = (BillingModelList) unmarshaller.unmarshal(resourceFile.getFile());
代码在 IntelliJ IDEA 开发环境里正常运行, 但是一旦将工程打包成 jar 包运行, 就提示如下错误:
- java.io.FileNotFoundException: class path resource [test/billingconfig-file.xml] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/C:/Users/Administrator/Desktop/tmp/other/sp-bap-simulator-1.5.17.RELEASE.jar!/BOOT-INF/classes!/test/billingconfig-file.xml
- at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:215)
- at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52)
- at im.yixin.spbap.logic.support.PayContext.init(PayContext.java:63)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
- at java.lang.reflect.Method.invoke(Method.java:497)
- at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366)
- at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311)
原因是因为 unmarshaller.unmarshal 传入的参数是 File, 在 IntelliJ IDEA 里运行时, billingconfig-file.xml 是个独立的文件, 可以被 File 访问到, 但是将工程打包成 jar 包运行, billingconfig-file.xml 被封装到 jar 包中了, 不是一个独立文件了, 此时肯定无法使用 File 访问到. 了解了原因, 我们可以将传递 unmarshaller.unmarshal() 方法的参数从 File 变成 InputStream 就可以了
将
unmarshaller.unmarshal(resourceFile.getFile());
修改为:
unmarshaller.unmarshal(resourceFile.getInputStream());
完整代码如下:
- @Value("classpath:test/billingconfig-file.xml")
- private Resource resourceFile; // 注入计费点文件资源
- JAXBContext context = JAXBContext.newInstance(BillingModelList.class);
- Unmarshaller unmarshaller = context.createUnmarshaller();
- BillingModelList billingModelList = (BillingModelList) unmarshaller.unmarshal(resourceFile.getInputStream())
来源: https://juejin.im/post/5bf2ba00f265da61715df225