在idea 里面springboot项目跑的好好得,resources 下面的.ftl文件和其他的图片啥的读取都好好的,没什么问题,但是打成jar包用命令跑就会出问题,报java.io.FileNotFoundException: 错误。我的解决方案目前来看可以解决,但是不完美,希望看到有更好的解决方案。
如图:resources 下面有.ftl 模板和.jpg 文件等
在idea里面跑的时候读取可能是这样的,没什么问题
Image image =Image.getInstance("src/main/resources/image/image.png");
但是打成jar 包后,这个路径是有问题的,会报文件找不到错误
或者这种获取.ftl文件的方式,在打成jar包后运行依旧报错。
File file = new File(ClassLoader.getSystemResource("templates/mytemplate.ftl").getPath());
解决方案:
先说原因吧,我的理解是文件打包后都在jar 文件里面,所以获取的时候路径有点问题,找到了一个方法就是把源文件复制出来io写入到指定的路径,然后利用复制出来的文件,下面是我的代码
package mybatisplus.google.freemaker;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 包: mybatisplus.google.freemaker
* 作者: climber.luo
* 时间:2020.08.29 15:19
*/
public class FreeMakerUtil {
// 临时目录 resource 文件只生成一次 这个路径可以换成虚拟机上的实际存在的路径
static String tempPath = "G:/study/templates/mytemplate.ftl";
static File f = new File(tempPath);
// 创建一个Configuration对象,直接new一个对象。构造方法的参数就是freemarker对于的版本号。
private static final Configuration configuration;
static {
configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
configuration.setDefaultEncoding("utf-8");
ClassPathResource resource = new ClassPathResource("templates/mytemplate.ftl");
if (!f.exists()) {
try {
new File(f.getParent()).mkdirs();
InputStream inputStream = resource.getInputStream();
FileOutputStream outputStream = new FileOutputStream(f);
IOUtils.copy(inputStream, outputStream);
// 关闭流
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
configuration.setDirectoryForTemplateLoading(new File(f.getParent()));
} catch (IOException e) {
e.printStackTrace();
}
}
public static Template getTemplate(String templateName) throws IOException {
return configuration.getTemplate(templateName);
}
}
这行代码我是很不喜欢的,固定死了,这个就是从jar 里面将文件复制出来保存的路径
static String tempPath = "G:/study/templates/mytemplate.ftl";
关键代码
// 临时目录 resource 文件只生成一次
static String tempPath = "G:/study/templates/mytemplate.ftl";
static File f = new File(tempPath);
// 这里是从jar包中读取文件 ,关键类
ClassPathResource resource = new ClassPathResource("templates/mytemplate.ftl");
if (!f.exists()) {
try {
// 创建文件夹
new File(f.getParent()).mkdirs();
// 将resources 里的文件都取成流
InputStream inputStream = resource.getInputStream();
FileOutputStream outputStream = new FileOutputStream(f);
// 这个就是将jar 包里的文件复制到指定的文件夹里面
IOUtils.copy(inputStream, outputStream);
// 关闭流
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
缺点是将读取到的文件带入到系统里面,这样就回产生垃圾文件或者说零时文件,不太好,最好时有方法可以直接读取而不用产生临时文件。当然通过打包方式可以避免这个问题,但是希望这里还是希望有通过jar包也能解决这个问题的更好的方法。
本来不会发现这个问题,我在虚拟机里测试的时候发现的,记录下来。