問題備忘: 將工程打包成jar包執行,就報java.io.FileNotFoundException: class path resource錯誤
最近在在使用@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()) 複製程式碼