背景
因平台升级需要重构老系统报表打印服务,整合成 springboot+ireport 打印及预览 pdf 文件,并使用 docker 方式部署到 Linux 服务器。
现象
在本地 Windows 上测试通过后,将代码提交并打包 Docker 运行,点击打印提示如下错误:
net.sf.jasperreports.engine.util.JRFontNotFoundException: Font '仿宋' is not available to the JVM. See the Javadoc for more details...
问题
经检查发现是因为原框架中 ireport 的 jar 包中可默认从系统中获取字体环境,因此在 Windows 下若有该字体,就不会报错。而在 Linux 系统下往往缺乏一些中文字体环境,因此使用 ireport 导出或打印将会出现字体未在 JVM 编译等问题
解决
经研究,有两种解决方法:
1、方法一:可以对 Linux 安装相应字体库解决,具体根据系统版本参考网上资料。但该解决方式,需要每次部署Linux 时候都需要进行字体的安装,不利于部署。
2、方法二:将字体打进 jar 包,加载到项目中。使用该方法,在以后实施时,即便系统未安装字体,只要项目有该 jar 包即可保证程序字体环境正常运行。
由于此服务使用 Docker 部署,基础镜像为 alpine3.8 ,安装字体再重新打包复杂且不经济。这里采用第二种方法解决。
操作
1、找到自己本地的 jasperreports-fonts-4.0.0.jar 包(找到自己版本的jar包,我是使用的4.0.0版本),没有可以去 maven 仓库中下一个(链接)。
2、在本地 C:\Windows\Fonts 目录下,找到 simfang.ttf 文件(如果本地没有,在网上下一个)
3、打开 jar 包,或者解压后再打开,将 simfang.ttf 复制到目录 \net\sf\jasperreports\fonts\dejavu 下
4、修改 \net\sf\jasperreports\fonts 目录中的 fonts.xml,追加 fontFamily 元素,并配置宋体信息:
<!-- Linux fonts. -->
<fontFamily name="仿宋">
<normal>net/sf/jasperreports/fonts/dejavu/simfang.ttf</normal>
<bold>net/sf/jasperreports/fonts/dejavu/simfang.ttf</bold>
<italic>net/sf/jasperreports/fonts/dejavu/simfang.ttf</italic>
<boldItalic>net/sf/jasperreports/fonts/dejavu/simfang.ttf</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding>
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'仿宋', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'仿宋', Arial, Helvetica, sans-serif</export>
</exportFonts>
</fontFamily>
5、*如果修改的是 maven 上获取的 jar ,可修改 jar 包中的 jasperreports_extension.properties 文件,添加:
net.sf.jasperreports.awt.ignore.missing.font=true
6、完成以上操作后,保存或重新打 jar 包(命令:jar cvfm jasperreport-fonts-extra-4.0.0.jar test\META-INF\MANIFEST.MF -C test\ .)。普通 web 项目直接在 lib 依赖下添加 jar ,maven 需要重新修改 pom 再引入。重启项目,问题解决。