在docker容器中运行springboot时,报错“文件找不到”, 代码如下:
File file = new File(jasperFileCommonBegin);
资源文件路径:
--src
----main
------java
------resource
--------jasper
----------COMMON_BEGIN.jasper
关键日志如下:
2023-02-28 09:20:50.903 ERROR 1 --- [ncBatchThreads3] o.s.batch.core.step.AbstractStep : Encountered an error executing step PN2000P-Job1Step2 in job PN2000P-Job1
net.sf.jasperreports.engine.JRException: java.io.FileNotFoundException: jasper/COMMON_BEGIN.jasper
at net.sf.jasperreports.engine.util.JRLoader.loadObject(JRLoader.java:128) ~[jasperreports-6.19.1.jar:6.19.1-867c00bf88cd4d784d404379d6c05e1b419e8a4c]
at net.sf.jasperreports.engine.util.JRLoader.loadObject(JRLoader.java:117) ~[jasperreports-6.19.1.jar:6.19.1-867c00bf88cd4d784d404379d6c05e1b419e8a4c]
at stb.op.batch.report.pn2000p.step2.Step2GeneratePdfTasklet.execute(Step2GeneratePdfTasklet.java:60) ~[classes/:na]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.6.jar:5.3.6]
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.3.2.jar:4.3.2]
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.3.2.jar:4.3.2]
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.3.2.jar:4.3.2]
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:68) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:68) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.job.flow.support.state.SplitState$1.call(SplitState.java:94) ~[spring-batch-core-4.3.2.jar:4.3.2]
at org.springframework.batch.core.job.flow.support.state.SplitState$1.call(SplitState.java:91) ~[spring-batch-core-4.3.2.jar:4.3.2]
at java.base/java.util.concurrent.FutureTask.run(Unknown Source) ~[na:na]
at org.springframework.core.task.SimpleAsyncTaskExecutor$ConcurrencyThrottlingRunnable.run(SimpleAsyncTaskExecutor.java:280) ~[spring-core-5.3.6.jar:5.3.6]
at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
Caused by: java.io.FileNotFoundException: jasper/COMMON_BEGIN.jasper
... 23 common frames omitted
分析:看上去正在加载src/main/resources/jasper/COMMON_BEGIN.jasper,该文件仅在应用程序源代码可用并且工作目录是源代码树的根目录时才存在,如果你在没有可用源的情况下运行 jar 文件,你会在 Docker 等容器中看到同样的报错异常。
方案:应该从类路径加载文,而不是从文件系统加载文件,src/main/resources
中的任何文件都可以从类路径的根目录中获得。您可以使用从ConfigurationReader.class.getClassLoader().getResourceAsStream("
jasper/COMMON_BEGIN.jasper")
返回的InputStream
加载。或者当使用 Spring Boot 时,改用 Spring Framework 的 ClasspathResource
。
具体代码如下:
// 因为Resouce是一个接口 所以我们可以使用它的实现类ClassPathResource来new一个对象。而构造方法的参数便是resources目录下的文件路径
//注意这里是使用的相对路径(相对于resouces目录而言)
Resource resource = new ClassPathResource("jasper/COMMON_BEGIN.jasper");
//我们获取到resource对象后,变可以调用resouce.getFile()方法来获取文件。
File file = resouce.getFile();
解决~~~