SpringBoot 加载本地字体资源
1. 前言
近期遇到了项目在服务器部署后中文字体乱码的问题,而本地开发环境正常,经排查原因是服务器没有支持中文的字体。于是想到了两种解决方案,一是在服务器安装中文字体,优点为不用修改代码,缺点为需要了解服务器字体安装(不同服务器发行版安装方式可能不同);二是将字体放进项目中在代码中动态加载,优点是适配各种部署环境,缺点为需要修改代码(一劳永逸)。笔者选择了方案二,下文将记录如何在 SpringBoot 框架中加载 resources 资源目录下的字体文件。
2. 字体工具类
package com.xiaoqqya.font;
import java.awt.*;
import java.io.InputStream;
import java.util.Objects;
/**
* 字体工具类.
*
* @author <a href="mailto:xiaoQQya@126.com">xiaoQQya</a>
* @since 2023/03/30
*/
public class FontUtils {
private FontUtils() {
}
/**
* 从资源文件加载本地字体.
*
* @param fontPath 字体路径, 相对 resources 目录的相对路径, 如 fonts/simsun.ttc
* @param fontStyle 字体风格, 可选值: Font.PLAIN, Font.BOLD, Font.ITALIC
* @param fontSize 字体大小
* @return 字体
*/
public static Font loadLocalFont(String fontPath, int fontStyle, float fontSize) {
Font font;
try (InputStream fontStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fontPath)) {
if (Objects.isNull(fontStream)) {
throw new FontException("Font resource is null.");
}
font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
font = font.deriveFont(fontStyle, fontSize);
} catch (Exception e) {
throw new FontException(e.getMessage(), e.getCause());
}
return font;
}
/**
* 字体异常.
*
* @author <a href="mailto:xiaoQQya@126.com">xiaoQQya</a>
* @since 2023/03/30
*/
static class FontException extends RuntimeException {
public FontException(String message) {
super(message);
}
public FontException(String message, Throwable cause) {
super(message, cause);
}
}
}
注:Font.deriveFont 方法不会修改原 font 对象, 而是复制并应用设置的 style 与 size 返回新的 font 对象。
2. 测试
-
字体资源;
src ├── main │ ├── java │ └── resources │ └── fonts │ └── simsun.ttc └── test └── java └── com └── xiaoqqya └── font └── LoadLocalFontTests.java
-
测试代码;
package com.xiaoqqya.font; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @SpringBootTest class LoadLocalFontTests { @Test void chineseFontTest() throws IOException { Font font = FontUtils.loadLocalFont("fonts/simsun.ttc", Font.PLAIN, 400); BufferedImage image = new BufferedImage(1920, 1080, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = image.createGraphics(); graphics.setColor(Color.GREEN); graphics.setFont(font); graphics.drawString("中文测试", 100, 740); graphics.dispose(); ImageIO.write(image, "PNG", new File("chinese.png")); } }