SpringBoot Jar 无法加载 TrueType 字体。

3

当我想要使用springboot fat jar中包含的字体时,我发现了一个奇怪的行为。在本地机器上运行测试加载自 /resources 目录的字体时,它能够完美工作。但是如果我使用maven构建应用并从终端运行,则会收到以下错误信息:

java.io.IOException: Problem reading font data.
at java.awt.Font.createFont0(Font.java:1000)
at java.awt.Font.createFont(Font.java:877)

我尝试寻找解决方案并进行了以下操作:

  • 使用不同的字体(有时会出现关于损坏表格等问题的其他错误)
  • 构建各种版本的docker openjdk容器以测试行为
  • 构建一个ubuntu容器,安装openjdk
  • 使用debian镜像,安装fc-cache,并通过以下方式使字体可用
    • /usr/share/fonts/truetype/europlate
    • fc-cache -f -v
  • 创建一个临时文件,仅确保在jar内部没有访问问题。
  • 从终端运行应用程序,其中加载字体也失败了
  • 在编辑器中使用该字体,甚至当应用程序从IDE中运行时也可以正常使用(无测试)

方法:

     public Font getFont() throws IOException, FontFormatException {
        File f = File.createTempFile("dang", "tmp");
        assert f != null;
        f.delete();
        ClassLoader classLoader = getClass().getClassLoader();
        Font font = Font.createFont(Font.TRUETYPE_FONT, classLoader.getSystemResourceAsStream("EuroPlate.ttf"));
        font.deriveFont(105f);
        System.out.println(font.getFontName());
        return font;
    }

编辑:

集成开发环境(IDE)运行应用程序 -> 正常工作

终端运行应用程序 -> 失败

堆栈跟踪:

java.io.IOException: Problem reading font data.
    at java.desktop/java.awt.Font.createFont0(Font.java:1183)
    at java.desktop/java.awt.Font.createFont(Font.java:1052)
    at components.NumberPlateUtility.getFont(NumberPlateUtility.java:81)
    at components.NumberPlateUtility.completeImage(NumberPlateUtility.java:173)
    at main.NumberplateClientCommands.one(NumberplateClientCommands.java:63)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:223)
    at org.springframework.shell.Shell.evaluate(Shell.java:169)
    at org.springframework.shell.Shell.run(Shell.java:134)
    at org.springframework.shell.jline.InteractiveShellApplicationRunner.run(InteractiveShellApplicationRunner.java:84)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:783)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:773)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230)
    at main.Main.main(Main.java:20)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)

代码仓库:https://github.com/Semo/numberplate_generator.git


你在开发环境中使用的jdk openjdk是相同的吗? - Malathi
1
你想用这个字体做什么?在 Boot 应用程序中操作字体非常不常见(例如,将其提供给客户端在浏览器中使用)。 - chrylis -cautiouslyoptimistic-
你的意思是在没有使用Docker的情况下使用openjdk x,并且在使用相同版本的openjdk x进行Docker构建时出现了问题。而且这个问题只出现在Docker容器中,而在没有使用Docker的环境中没有出现过。是这样吗? - Malathi
@chrylis 使用后端字体将字符串渲染成图像并发送到Web服务以供进一步使用。 - Semo
你能解压缩这个jar文件并查看它是否有字体吗? - Malathi
显示剩余3条评论
1个回答

3

这段代码可以正常工作:

public Font getFont() throws IOException, FontFormatException {
        File f = File.createTempFile("dang", "tmp");
        assert f != null;
        f.delete();
        ClassLoader classLoader = getClass().getClassLoader();
        Font font = Font.createFont(Font.TRUETYPE_FONT, classLoader.getResourceAsStream("EuroPlate.ttf"));
        font.deriveFont(105f);
        System.out.println(font.getFontName());
        return font;
    }

注意classLoader.getResourceAsStream的变化。有关更多解释,请参见答案。最初的回答。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接