转--记一次服务发布之后,图形验证码乱码的服务排查

由于业务拓展,新买了台系统为centOS7的服务器,配置完jdk和nginx之后,将服务发布到服务器上并部署启动,然后刷新页面,神奇的事情就出现了:

第一个想到的问题,就是进行本地调试,发现一切正常;于是在生成验证码文本的地方加上了logger输出,再次发布程序到服务器上,确定是否是文本生成时产生的问题,附上代码:

//        String vcode = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String vcode = "0123456789";
        codeImg = new BufferedImage(74, 30, BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D g = codeImg.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(Color.white);
        g.fillRect(0, 0, 74, 30);
        for (int i = 0; i < 100; i++) {
            int x = (int) Math.round((Math.random() * 74));
            int y = (int) Math.round((Math.random() * 30));
            Color color = new Color((float) (Math.random() * 0.7) + 0.3F, (float) (Math.random() * 0.7) + 0.3F,
                (float) (Math.random() * 0.7) + 0.3F);
            g.setColor(color);
            g.drawRect(x, y, 1, 1);
        }
        code = "";
        for (int i = 0; i < 4; i++) {
            int fontsize = (int) Math.round(Math.random() * 3 + 20);
            Font font = new Font("", (int) Math.round(Math.random() * 3), fontsize);
            Color color = new Color((float) (Math.random() * 0.7), (float) (Math.random() * 0.7), (float) (Math.random() * 0.7));
            g.setColor(color);
            g.setFont(font);
//            Character c = vcode.charAt(Math.round((float) Math.random() * 35));
            Character c = vcode.charAt(Math.round((float) Math.random() * 9));
            code += c;
            g.drawString(c + "", 18 * i + (int) (Math.random() * 10 - 5) + 2, 24 + (int) (Math.random() * 10 - 5));
        }
        logger.info("code:{}",code);
    }

运行服务之后,通过日志,发现文本生成输出正常,开始怀疑是否是jdk版本不一致导致的问题。因为我们开发环境装的是jdk7,服务器上装的是jdk8,难道是jdk做向下兼容的时候出现的问题;于是将项目发到另一台也是jdk8的服务器上,启动测试,发现一切正常,排除jdk版本问题。此时,再次查看代码,发现Graphics2D在生成文本的时候,其实调用了Font组件

 

进入font源码:

    public Font(String name, int style, int size) {
        this.name = (name != null) ? name : "Default";
        this.style = (style & ~0x03) == 0 ? style : 0;
        this.size = size;
        this.pointSize = size;
    }

发现用的是系统的默认字体,windows平台默认是微软雅黑,查看对应服务器上的系统字体:

以及系统的字体列表:

发现并没有我们需要的字体,于是基本可以确定问题点是出在系统字体上面。

解决方法很直接,就是直接到windows的字体目录下

选择 微软雅黑 字体,直接上传到服务器的字体文件目录下( /usr/share/fonts/),可以创建自定义目录:(我是新建了micro的目录,将拷贝出来的字体放在了此目录下)

然后利用命令:fc-cache 重新载入字体配置,清除字体缓存。然后重启项目,发现验证码正常。

由于自己也遇到了类似的问题,遂转载记录下。

转自:https://blog.csdn.net/zs296332478/article/details/78144460

猜你喜欢

转载自www.cnblogs.com/operationhome/p/9240318.html