问题
使用Docker部署Jar包,登录的时候发现生成验证码失败,但是本地却没有问题。查看日志,报错:


java.lang.NullPointerException: null
at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219)
at sun.awt.FontConfiguration.init(FontConfiguration.java:107)
at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774)
at sun.font.SunFontManager$2.run(SunFontManager.java:431)
at java.security.AccessController.doPrivileged(Native Method)
at sun.font.SunFontManager.<init>(SunFontManager.java:376)
at sun.awt.FcFontManager.<init>(FcFontManager.java:35)
at sun.awt.X11FontManager.<init>(X11FontManager.java:57)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83)
at java.security.AccessController.doPrivileged(Native Method)
at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
at java.awt.Font.getFont2D(Font.java:491)
at java.awt.Font.access$000(Font.java:224)
at java.awt.Font$FontAccessImpl.getFont2D(Font.java:228)
at sun.font.FontUtilities.getFont2D(FontUtilities.java:180)
at sun.java2d.SunGraphics2D.checkFontInfo(SunGraphics2D.java:669)
at sun.java2d.SunGraphics2D.getFontInfo(SunGraphics2D.java:830)
at sun.java2d.pipe.GlyphListPipe.drawString(GlyphListPipe.java:50)
at sun.java2d.SunGraphics2D.drawString(SunGraphics2D.java:2928)
………………

分析
这个问题网上答案已经非常多了——

OpenJDK比OracleJDK简化了一些功能,所以后端绘制验证码所要用到Java的AWT组件就被简化了,结果报出空指针。

问题出现了,现在有三种解决思路:

1、修改代码,后端只生成验证码内容,具体绘制交给前端
2、更换Docker镜像为 OracleJDK
3、基于操作系统安装FontConfig组件
综合比较快捷的是第三种方式:

1、在centos7系统安装FontConfig
yum install fontconfig

2、修改dockerfile ,添加一行,安装字体 ttf-dejavu
RUN apk add --update font-adobe-100dpi ttf-dejavu fontconfig

3、重启docker容器
docker restart 容器ID或容器名

但是由于博主的服务器是内网环境,所以没有办法,只能用离线安装的方式。


解决
1、离线安装 fontconfig
下载 fontconfig离线包:fontconfig-2.13.0-4.3.el7.x86_64.rpm

上传到服务器,执行命令:

rpm -ivh fontconfig-2.13.0-4.3.el7.x86_64.rpm  --nodeps --force


在 /usr/share 下多出 fontconfig 和 fonts 目录。

2、安装字体 ttf-dejavu
下载字体 ttf-dejavu : https://packages.msys2.org/package/mingw-w64-x86_64-ttf-dejavu (失效自行查找)

上传字体:将 字体文件打包上传到服务器 /usr/share/fonts 目录,解压

刷新字体:fc-cache --force , 刷新完成之后可以使用 fc-list 查看安装的字体


3、容器中安装字体
将上传的 ttf-dejavu 字体文件夹拷贝到容器/usr/share/fonts 目录中
docker cp -a TTF/  [容器id]:/usr/share/fonts

进入容器 ,刷新字体
# 进入容器
docker exec -it [容器id] bash
# 刷新字体
fc-cache --force

fc-list 就可以看到安装的 ttf-dejavu 字体


4、重启容器
最后重启容器:

docker restart [容器id]

OK,问题解决

问题使用Docker部署Jar包,登录的时候发现生成验证码失败,但是本地却没有问题。查看日志,报错:java.lang.NullPointerException: null at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219) at sun.a...
docker 中OpenJDK excel无法导出 java .lang. NullPointerException at sun . awt . Font Configuration .get Version 1.背景说明: 本地使用的是jdk1.8版本功能可正常使用,当通过 docker 打包镜像部署到linux环境下(openJDK1.8)后无法导出excel,报初始化是否,空指针异常, 报错 如下: 2.原因: openjdk比jdk1.8简化了一些功能,所以用 docker 打包的时候更小。excel导出时初始化失败就是因为f
OpenJDK验证码无法显示( java .lang. NullPointerException at sun . awt . Font Configuration .get Version
之前开发的应用都是基于OracleJDK 1.8来做的,图片验证码显示正常,但是更换成OpenJDK1.8后,验证码无法显示,后台代码抛出异常,异常内容如下, java .lang. NullPointerException at sun . awt . Font Configuration .get Version Font Configuration . java 1264) 可以看到,猜测是因为验证码的API用到了...
java .lang. NullPointerException : null 2020/5/29 上午8:40:11 at sun . awt . Font Configuration .get Version ( Font Configuration . java :1264) 2020/5/29 上午8:40:11 at sun . awt . Font Configuration . read Font Config File ( Font Configuration . java :219) Caused by: java .lang. NullPointerException at sun . awt . Font Configuration .get Version ( Font Configuration . java :1264) at sun . awt . Font Configuration . read Font Config File ( Font Configuration . java :2 nginx响应超时upstream timed out (110: Connection timed out) while reading response header from upstream 33546