开发中业务操作相关的记录-Java生成二维码-《Java笔记》

admin 2025-10-19 03:23:02 编程 来源:ZONE.CI 全球网 0 阅读模式

Java 二维码

一、介绍

说到二维码,相信大家每天都会用到,尤其是在手机支付的场景,使用频率极广。实际上二维码在1994年的时候就已经诞生了,由 Denso 公司研制而成,只是那个时候使用范围还不是很大。早期的二维码由于很容易通过技术方式进行伪造,因此很少有企业愿意去使用他,随着技术的不断迭代和更新,二维码的安全性更进一步得到了提升,从而使得更多的企业愿意使用这项新技术,例如当下的移动支付,还有微信互推,扫码出行等等,极大的方便了网民们的购物、社交和出行!在实际的业务开发过程中,二维码的使用场景开发也会经常出现在开发人员的面前,应该如何去处理呢?

二、代码实践

在 Java 生态体系里面,操作二维码的开源项目很多,如 SwetakeQRCode、BarCode4j、Zxing 等等。介绍下简单易用的 google 公司的 zxing,zxing 不仅使用方便,而且可以还操作条形码或者二维码等,不仅有 java 版本,还有 Android 版。开源库地址:

通过 Maven 仓库,可以很轻松的将其依赖包添加到自己的项目。

2.1、添加依赖包

开发中如果是非 web 应用则导入 core 包即可,如果是 web 应用,则 core 与 javase 一起导入。

  1. <!-- 如果是非 web 应用则导入 core 包即可,如果是 web 应用,则 core 与 javase 一起导入。-->
  2. <dependency>
  3. <groupId>com.google.zxing</groupId>
  4. <artifactId>core</artifactId>
  5. <version>3.3.3</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.google.zxing</groupId>
  9. <artifactId>javase</artifactId>
  10. <version>3.3.3</version>
  11. </dependency>

2.2、生成二维码

如何快速生成二维码呢?请看下面的测试代码!

  1. import com.google.zxing.BarcodeFormat;
  2. import com.google.zxing.EncodeHintType;
  3. import com.google.zxing.MultiFormatWriter;
  4. import com.google.zxing.common.BitMatrix;
  5. import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
  6. import javax.imageio.ImageIO;
  7. import javax.swing.filechooser.FileSystemView;
  8. import java.awt.image.BufferedImage;
  9. import java.io.File;
  10. import java.util.Date;
  11. import java.util.HashMap;
  12. import java.util.Map;
  13. /**
  14. *
  15. * 二维码、条形码工具类
  16. */
  17. public class QRCodeWriteUtil {
  18. /**
  19. * CODE_WIDTH:二维码宽度,单位像素
  20. * CODE_HEIGHT:二维码高度,单位像素
  21. * FRONT_COLOR:二维码前景色,0x000000 表示黑色
  22. * BACKGROUND_COLOR:二维码背景色,0xFFFFFF 表示白色
  23. * 演示用 16 进制表示,和前端页面 CSS 的取色是一样的,注意前后景颜色应该对比明显,如常见的黑白
  24. */
  25. private static final int CODE_WIDTH = 400;
  26. private static final int CODE_HEIGHT = 400;
  27. private static final int FRONT_COLOR = 0x000000;
  28. private static final int BACKGROUND_COLOR = 0xFFFFFF;
  29. /**
  30. * 生成二维码 并 保存为图片
  31. * @param codeContent
  32. */
  33. public static void createCodeToFile(String codeContent) {
  34. try {
  35. //获取系统目录
  36. String filePathDir = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath();
  37. //随机生成 png 格式图片
  38. String fileName = new Date().getTime() + ".png";
  39. /**com.google.zxing.EncodeHintType:编码提示类型,枚举类型
  40. * EncodeHintType.CHARACTER_SET:设置字符编码类型
  41. * EncodeHintType.ERROR_CORRECTION:设置误差校正
  42. * ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
  43. * 不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
  44. * EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近
  45. * */
  46. Map<EncodeHintType, Object> hints = new HashMap();
  47. hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
  48. hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
  49. hints.put(EncodeHintType.MARGIN, 1);
  50. /**
  51. * MultiFormatWriter:多格式写入,这是一个工厂类,里面重载了两个 encode 方法,用于写入条形码或二维码
  52. * encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
  53. * contents:条形码/二维码内容
  54. * format:编码类型,如 条形码,二维码 等
  55. * width:码的宽度
  56. * height:码的高度
  57. * hints:码内容的编码类型
  58. * BarcodeFormat:枚举该程序包已知的条形码格式,即创建何种码,如 1 维的条形码,2 维的二维码 等
  59. * BitMatrix:位(比特)矩阵或叫2D矩阵,也就是需要的二维码
  60. */
  61. MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
  62. BitMatrix bitMatrix = multiFormatWriter.encode(codeContent, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);
  63. /**java.awt.image.BufferedImage:具有图像数据的可访问缓冲图像,实现了 RenderedImage 接口
  64. * BitMatrix 的 get(int x, int y) 获取比特矩阵内容,指定位置有值,则返回true,将其设置为前景色,否则设置为背景色
  65. * BufferedImage 的 setRGB(int x, int y, int rgb) 方法设置图像像素
  66. * x:像素位置的横坐标,即列
  67. * y:像素位置的纵坐标,即行
  68. * rgb:像素的值,采用 16 进制,如 0xFFFFFF 白色
  69. */
  70. BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
  71. for (int x = 0; x < CODE_WIDTH; x++) {
  72. for (int y = 0; y < CODE_HEIGHT; y++) {
  73. bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
  74. }
  75. }
  76. /**javax.imageio.ImageIO java 扩展的图像IO
  77. * write(RenderedImage im,String formatName,File output)
  78. * im:待写入的图像
  79. * formatName:图像写入的格式
  80. * output:写入的图像文件,文件不存在时会自动创建
  81. *
  82. * 即将保存的二维码图片文件*/
  83. File codeImgFile = new File(filePathDir, fileName);
  84. ImageIO.write(bufferedImage, "png", codeImgFile);
  85. System.out.println("二维码图片生成成功:" + codeImgFile.getPath());
  86. } catch (Exception e) {
  87. e.printStackTrace();
  88. }
  89. }
  90. public static void main(String[] args) {
  91. String codeContent1 = "Hello World";
  92. createCodeToFile(codeContent1);
  93. String codeContent2 = "https://www.baidu.com/";
  94. createCodeToFile(codeContent2);
  95. }
  96. }

先创建一个内容为Hello World的二维码,然后在创建一个内容为https://www.baidu.com/链接地址的二维码。运行程序之后,输出内容如下:

  1. 二维码图片生成成功:/Users/Desktop/1632403131016.png
  2. 二维码图片生成成功:/Users/Desktop/1632403131233.png

打开图片内容!用微信扫一扫,结果如下:

2.3、读取二维码

创建很容易,那么如何读取二维码内容呢?请看下面的测试代码:

import%20com.google.zxing.*;import%20com.google.zxing.client.j2se.BufferedImageLuminanceSource;import%20com.google.zxing.common.HybridBinarizer;import%20javax.imageio.ImageIO;import%20java.awt.image.BufferedImage;import%20java.io.File;import%20java.io.IOException;import%20java.net.URL;import%20java.util.HashMap;import%20java.util.Map;/**%20*%20二维码、条形码工具类%20*/public%20class%20QRCodeReadUtil%20{%20%20%20%20/**%20%20%20%20%20*%20解析二维码内容(文件)%20%20%20%20%20*%20@param%20file%20%20%20%20%20*%20@return%20%20%20%20%20*%20@throws%20IOException%20%20%20%20%20*/%20%20%20%20public%20static%20String%20parseQRCodeByFile(File%20file)%20throws%20IOException%20{%20%20%20%20%20%20%20%20BufferedImage%20bufferedImage%20=%20ImageIO.read(file);%20%20%20%20%20%20%20%20return%20parseQRCode(bufferedImage);%20%20%20%20}%20%20%20%20/**%20%20%20%20%20*%20解析二维码内容(网络链接)%20%20%20%20%20*%20@param%20url%20%20%20%20%20*%20@return%20%20%20%20%20*%20@throws%20IOException%20%20%20%20%20*/%20%20%20%20public%20static%20String%20parseQRCodeByUrl(URL%20url)%20throws%20IOException%20{%20%20%20%20%20%20%20%20BufferedImage%20bufferedImage%20=%20ImageIO.read(url);%20%20%20%20%20%20%20%20return%20parseQRCode(bufferedImage);%20%20%20%20}%20%20%20%20private%20static%20String%20parseQRCode(BufferedImage%20bufferedImage){%20%20%20%20%20%20%20%20try%20{%20%20%20%20%20%20%20%20%20%20%20%20/**%20%20%20%20%20%20%20%20%20%20%20%20%20*%20com.google.zxing.client.j2se.BufferedImageLuminanceSource:缓冲图像亮度源%20%20%20%20%20%20%20%20%20%20%20%20%20*%20将%20java.awt.image.BufferedImage%20转为%20zxing%20的%20缓冲图像亮度源%20%20%20%20%20%20%20%20%20%20%20%20%20*%20关键就是下面这几句:HybridBinarizer%20用于读取二维码图像数据,BinaryBitmap%20二进制位图%20%20%20%20%20%20%20%20%20%20%20%20%20*/%20%20%20%20%20%20%20%20%20%20%20%20LuminanceSource%20source%20=%20new%20BufferedImageLuminanceSource(bufferedImage);%20%20%20%20%20%20%20%20%20%20%20%20BinaryBitmap%20bitmap%20=%20new%20BinaryBitmap(new%20HybridBinarizer(source));%20%20%20%20%20%20%20%20%20%20%20%20Map<DecodeHintType,%20Object>%20hints%20=%20new%20HashMap<>();%20%20%20%20%20%20%20%20%20%20%20%20hints.put(DecodeHintType.CHARACTER_SET,%20"UTF-8");%20%20%20%20%20%20%20%20%20%20%20%20/**%20%20%20%20%20%20%20%20%20%20%20%20%20*%20如果图片不是二维码图片,则%20decode%20抛异常:com.google.zxing.NotFoundException%20%20%20%20%20%20%20%20%20%20%20%20%20*%20MultiFormatWriter%20的%20encode%20用于对内容进行编码成%202D%20矩阵%20%20%20%20%20%20%20%20%20%20%20%20%20*%20MultiFormatReader%20的%20decode%20用于读取二进制位图数据%20%20%20%20%20%20%20%20%20%20%20%20%20*/%20%20%20%20%20%20%20%20%20%20%20%20Result%20result%20=%20new%20MultiFormatReader().decode(bitmap,%20hints);%20%20%20%20%20%20%20%20%20%20%20%20return%20result.getText();%20%20%20%20%20%20%20%20}%20catch%20(Exception%20e)%20{%20%20%20%20%20%20%20%20%20%20%20%20e.printStackTrace();%20%20%20%20%20%20%20%20%20%20%20%20System.out.println("-----解析二维码内容失败-----");%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20return%20null;%20%20%20%20}%20%20%20%20public%20static%20void%20main(String[]%20args)%20throws%20IOException%20{%20%20%20%20%20%20%20%20File%20localFile%20=%20new%20File("/Users/Desktop/1632403131016.png");
  • String content1 = parseQRCodeByFile(localFile);
  • System.out.println(localFile + " 二维码内容:" + content1);
  • URL url = new URL("http://cdn.pzblog.cn/1951b6c4b40fd81630903bf6f7037156.png");
  • String content2 = parseQRCodeByUrl(url);
  • System.out.println(url + " 二维码内容:" + content2);
  • }
  • }
  • 运行程序,输出内容如下:

    1. /Users/Desktop/1632403131016.png 二维码内容:Hello World
    2. http://cdn.pzblog.cn/1951b6c4b40fd81630903bf6f7037156.png 二维码内容:https://www.baidu.com/

    2.4、web 二维码交互展示

    在实际的项目开发过程中,很多时候二维码都是根据参数实时输出到网页上进行显示的,它的实现原理类似验证码,例如下图,它们都是后台先生成内存图像BufferedImage,然后使用ImageIO.write写出来。Java生成二维码 - 图3在线生成二维码的功能,其实也类似于此!前端关键代码如下:

    1. <img src="http://xxxx/projectDemo/qrCode" alt="验证码,点击刷新!" onclick="this.src=this.src+'?temp='+Math.random();" class="content-code fl-r" />

    后端关键代码如下:

    1. @Controller
    2. public class SystemController {
    3. @GetMapping("qrCode")
    4. public void getQRCode(HttpServletResponse response) {
    5. String content = "Hello World";
    6. try {
    7. /**
    8. * 调用工具类生成二维码并输出到输出流中
    9. */
    10. QRCodeWriteUtil.createCodeToOutputStream(content, response.getOutputStream());
    11. } catch (IOException e) {
    12. e.printStackTrace();
    13. }
    14. }
    15. }

    其中createCodeToOutputStream方法,源码如下:

    1. /**
    2. * 生成二维码 并 保存为图片
    3. * @param codeContent
    4. */
    5. public static void createCodeToOutputStream(String codeContent, OutputStream outputStream) {
    6. try {
    7. /**com.google.zxing.EncodeHintType:编码提示类型,枚举类型
    8. * EncodeHintType.CHARACTER_SET:设置字符编码类型
    9. * EncodeHintType.ERROR_CORRECTION:设置误差校正
    10. * ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
    11. * 不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
    12. * EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近
    13. * */
    14. Map<EncodeHintType, Object> hints = new HashMap();
    15. hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    16. hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
    17. hints.put(EncodeHintType.MARGIN, 1);
    18. /**
    19. * MultiFormatWriter:多格式写入,这是一个工厂类,里面重载了两个 encode 方法,用于写入条形码或二维码
    20. * encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
    21. * contents:条形码/二维码内容
    22. * format:编码类型,如 条形码,二维码 等
    23. * width:码的宽度
    24. * height:码的高度
    25. * hints:码内容的编码类型
    26. * BarcodeFormat:枚举该程序包已知的条形码格式,即创建何种码,如 1 维的条形码,2 维的二维码 等
    27. * BitMatrix:位(比特)矩阵或叫2D矩阵,也就是需要的二维码
    28. */
    29. MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
    30. BitMatrix bitMatrix = multiFormatWriter.encode(codeContent, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);
    31. /**java.awt.image.BufferedImage:具有图像数据的可访问缓冲图像,实现了 RenderedImage 接口
    32. * BitMatrix 的 get(int x, int y) 获取比特矩阵内容,指定位置有值,则返回true,将其设置为前景色,否则设置为背景色
    33. * BufferedImage 的 setRGB(int x, int y, int rgb) 方法设置图像像素
    34. * x:像素位置的横坐标,即列
    35. * y:像素位置的纵坐标,即行
    36. * rgb:像素的值,采用 16 进制,如 0xFFFFFF 白色
    37. */
    38. BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
    39. for (int x = 0; x < CODE_WIDTH; x++) {
    40. for (int y = 0; y < CODE_HEIGHT; y++) {
    41. bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
    42. }
    43. }
    44. ImageIO.write(bufferedImage, "png", outputStream);
    45. System.out.println("二维码图片生成成功");
    46. } catch (Exception e) {
    47. e.printStackTrace();
    48. }
    49. }

    这种方式,如果是单体应用,其实没太大问题,在微服务开发的环境下有局限性。因此还有另外一种玩法,那就是将生成的图片流转成base64的格式,然后返回给前端进行展示。关键代码改造过程如下:

    1. //定义字节输出流,将bufferedImage写入
    2. ByteArrayOutputStream out = new ByteArrayOutputStream();
    3. ImageIO.write(bufferedImage, "png", out);
    4. //将输出流转换成base64
    5. String str64 = Base64.getEncoder().encodeToString(out.toByteArray());

    最后,把base64内容以json的形式返回给前端,进行展示!

    以太坊cppgolang区别 编程

    以太坊cppgolang区别

    以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
    progolang 编程

    progolang

    Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
    golangn个发送者 编程

    golangn个发送者

    Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
    golang技能图谱 编程

    golang技能图谱

    从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
    评论:0   参与:  8