1、描述

在系统中生成一个二维码,用户可以选择下载保存到本地;或生成的二维码以流的形式传输给前端工程展示(只生成流,不保存到本地)

2、实现

两种方法实现,①使用google的zxing实现。②使用hutool工具实现

1、引入依赖

<!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
 <dependency>
   <groupId>com.google.zxing</groupId>
   <artifactId>core</artifactId>
   <version>3.5.2</version>
 </dependency>
<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
<dependency>
  <groupId>com.google.zxing</groupId>
  <artifactId>javase</artifactId>
  <version>3.5.1</version>
</dependency>

2、在项目的工具包中创建一个QrCodeGenerator的工具类,代码如下:

@SneakyThrows
public static BufferedImage generateQrCodeImage(String qrCodeData) {
        // 设置二维码的宽度和高度
        int size = 250;
        // 设置二维码的参数
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8.name());
        // 生成二维码
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(qrCodeData, BarcodeFormat.QR_CODE, size, size, hints);
        // 创建一个空的BufferedImage来绘制二维码
        BufferedImage qrCodeImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
        qrCodeImage.createGraphics();
        // 设置二维码的颜色和背景颜色
        Graphics2D graphics = (Graphics2D) qrCodeImage.getGraphics();
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, size, size);
        graphics.setColor(Color.BLACK);
        // 在BufferedImage上绘制二维码的内容
        for (int x = 0; x < size; x++) {
            for (int y = 0; y < size; y++) {
                if (bitMatrix.get(x, y)) {
                    graphics.fillRect(x, y, 1, 1);
                }
            }
        }
        return qrCodeImage;
    }
@SneakyThrows
    public static String generateQRCodeBase64(String text, int width, int height) {
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0x000000 : 0xFFFFFF);
            }
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", baos);
        baos.flush();
        byte[] imageBytes = baos.toByteArray();
        baos.close();
        return "data:image/png;base64," + java.util.Base64.getEncoder().encodeToString(imageBytes);
    }

    @SneakyThrows
    public static String generateQRCodeByHutool(String text, int width, int height) {
        QrConfig config = new QrConfig(width, height);
        // 设置边距,既二维码和背景之间的边距
        config.setMargin(3);
        // 设置前景色,既二维码颜色(青色)
        config.setForeColor(Color.CYAN);
        // 设置背景色(灰色)
        config.setBackColor(Color.GRAY);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        BufferedImage generate = QrCodeUtil.generate(text, config);

        ImageIO.write(generate, "png", baos);

        baos.flush();

        byte[] imageBytes = baos.toByteArray();

        baos.close();

        return "data:image/png;base64," + java.util.Base64.getEncoder().encodeToString(imageBytes);
    }

3、测试调用

@SneakyThrows
@GetMapping("/qr")
public void generateQrCode(HttpServletResponse response){
        // 生成二维码的内容
        String qrCodeData = "https://yanyuplus.cn";
        // 调用Zxing生成二维码
        BufferedImage qrCodeImage = QrCodeGenerator.generateQrCodeImage(qrCodeData);
        // 将图片转换为字节数组
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(qrCodeImage, "png", baos);
        // 设置响应头信息
        response.setHeader("Content-Type", "image/png");
        response.setHeader("Content-Disposition", "attachment; filename=" + UUID.randomUUID().toString() + ".png");
        // 将字节数组写入响应输出流
        StreamUtils.copy(baos.toByteArray(), response.getOutputStream());
    }
    @GetMapping("/qr64")
    public String getQRCodeBase64(){
        String url = "https://yanyuplus.cn"; // 需要生成二维码的URL
        int width = 250; // 图片的宽度
        int height = 250; // 图片的高度
        return QrCodeGenerator.generateQRCodeBase64(url,width,height);
    }

    @GetMapping("/qrhu")
    public String getQRCodeHuTool(){
        String url = "https://yanyuplus.cn"; // 需要生成二维码的URL
        int width = 250; // 图片的宽度
        int height = 250; // 图片的高度
        return QrCodeGenerator.generateQRCodeByHutool(url,width,height);
    }

当调用controller层的第一个方法时,由于我们设置了response.setHeader("Content-Type", "image/png");的响应头,此时会直接将图片下载到本地。而后面两个方法只会返回一个字符串类型的数据流。