最近在工作中使用了freemarker来进行pdf模板导出,看似一帆风顺的在本地完美运行后,部署到生产环境上却出现了许多问题,先是找不到模板之后又是中文字符无法显示。历尽万难之后终于成功导出,下面就来对这次freemaker的使用中遇到的一些问题来进行一次总结。
1.idea可以导出,但打成jar包部署后却提示找不到模板
这段话的大体意思是“找不到模板:因为无法找到配置的资源路径,所以自动去系统的根目录'/root'下寻找。”而我的模板在"/resources/templates"下,我添加日志发现创建configuration时传入的地址为null,此时我的地址获取方式为:
ClassLoader classLoader = this.getClass().getClassLoader();
URL resource = classLoader.getResource("templates");
/*通过uri获取路径*/
String templateDirectory = resource.toURI().getPath();
/*通过url获取路径*/
//String templateDirectory = resource.getPath();
通过uri获得的路径为null,传入configuration为的路径为空自然无法获取到资源。经过查询资料原于是我改成用下面的url直接获取,成功获取了文件路径,但依然报错。原来之所以传入地址为空,是因为uri的getPath()获得的地址不符合规范,因此自动返回了空值。
其根本原因在于JAR包内的资源无法通过地址直接导出,只能通过文件流获取。只需要将configuration获取模板的方式改一下就好了:
//旧方法获取模板
String templateDirectory="aaa/bb/cc/";
Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
configuration.setDirectoryForTemplateLoading(new File(templateDirectory));
Template template = configuration.getTemplate(templateName,"UTF-8");
//新方法获取模板(可读取jar包中的资源)
Configuration ftlConifg = new Configuration(Configuration.VERSION_2_3_29);
ftlConifg.setClassForTemplateLoading(PdfUtil.class, "/templates");
Template template = ftlConifg.getTemplate(templateName, StandardCharsets.UTF_8.toString());
2.导出中文为乱码问题
这个问题是因为在Linux服务器上没有中文字体,在Linux上安装字体后根据地址进行导入就可以了。
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setCharset("UTF-8");
FontProvider fontProvider = new FontProvider();
//添加系统字体
fontProvider.addSystemFonts();
//根据地址添加导入字体
FontProgram fontProgram1 = FontProgramFactory.createFont("/usr/share/fonts/chinese/MSYH.TTC,0");
FontProgram fontProgram2 = FontProgramFactory.createFont("/usr/share/fonts/chinese/MSYHBD.TTC,0");
FontProgram fontProgram3 = FontProgramFactory.createFont("/usr/share/fonts/chinese/MSYHL.TTC,0");
fontProvider.addFont(fontProgram1);
fontProvider.addFont(fontProgram2);
fontProvider.addFont(fontProgram3);
converterProperties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(content,outputStream,converterProperties);