com.sun.image.codec.jpeg包引发的战争


今天,公司测试人员在C端测试环境注册账号时发现验证码图片显示不出来,报500。“又是以前程序员遗留下来的bug等着我们来收拾烂摊子了?” 。我在本地启动项目打着断点一步一步的边走边看,没有问题啊!“是不是谁动服务器了”, 我重新打包项目到服务器重启之后很自信的告诉测试人员,“没问题了哈”。“还是不显示验证码图片!”测试又开枪了。“咦,本地没问题怎么上服务器就有问题了呢,有鬼!”。于是我开始把它当一回事了,我解决问题的步骤如下:

一、发现问题

1.定位问题

通过F12我找到了报错的问题是找不到com.sun.image.codec.jpeg.JPEGCodec这个类。

String mobile = uuid;
		byte[] b = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
        	String imgCode = utilsAPI.getImgCode(null);
            captchaImageService.setCaptchaCodeText(mobile, imgCode);
            System.out.println("key=" + mobile + "||验证码="+imgCode);
            BufferedImage challenge = ImgVerifyCode.images(imgCode);
            
            //问题定位,就是下面这两行
            JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(baos);
			jpegEncoder.encode(challenge);
        } catch (IllegalArgumentException e) {
        	resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            return null;
        } catch (CaptchaServiceException e) {
        	resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        	return null;
        }
        b = baos.toByteArray();
        resp.setHeader("Cache-Control", "no-store");
        resp.setHeader("Pragma", "no-cache");
        resp.setDateHeader("Expires", 0);
        resp.setContentType("image/jpeg");
        ServletOutputStream sos = resp.getOutputStream();
        sos.write(b);
        sos.flush();
        sos.close();
        return null;

2.分析问题

通过看包名“com.sun.image.codec.jpeg.JPEGCodec”,这明显是sun公司的包,那么除了sun公司的jdk,我们常用的还有主要由java社区提供支持的openjdk,所以他们在虚拟机层面的很多包的实现是不同的。

3.假设

我猜想应该就是jdk的不同openjdk不存在这个包导致这个问题的发生!

4.证明

连接服务器查看jdk版本。果然是openjdk
在这里插入图片描述

二、解决问题

1 分析解决方案有两种

1)切换服务器jdk为sun公司的jdk
2)改虚拟机层面的包为语言成面的包

最终我选择了第二种方案,毕竟代码可移植性更高。

2.替代方案:

String mobile = uuid;
		byte[] b = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
        	String imgCode = utilsAPI.getImgCode(null);
            captchaImageService.setCaptchaCodeText(mobile, imgCode);
            System.out.println("key=" + mobile + "||验证码="+imgCode);
            BufferedImage challenge = ImgVerifyCode.images(imgCode);
            
            //替代方案
			ImageIO.write(challenge ,"png",baos); 
        } catch (IllegalArgumentException e) {
        	resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            return null;
        } catch (CaptchaServiceException e) {
        	resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        	return null;
        }
        b = baos.toByteArray();
        resp.setHeader("Cache-Control", "no-store");
        resp.setHeader("Pragma", "no-cache");
        resp.setDateHeader("Expires", 0);
        resp.setContentType("image/jpeg");
        ServletOutputStream sos = resp.getOutputStream();
        sos.write(b);
        sos.flush();
        sos.close();
        return null;

3. 测试

更新服务器应用并访问:
在这里插入图片描述
问题已经解决了!

4.反思

尽量不要用虚拟机层面的包!

发布了62 篇原创文章 · 获赞 23 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Z_Vivian/article/details/104315658