使用 hutool 工具类生成和识别二维码图片

实际工作中生成二维码,通过手机进行扫码查看的需求比较多。Hutool 工具包中有很多实用的工具类,其中就包含二维码生成和识别的 QrCodeUtil 工具类,默认生成白底黑色的二维码,也可以自定义二维码的样式,比如设置背景色、前景色、设置边距以及在二维码中心显示自定义的 logo 等等,使用起来非常方便。

本篇博客通过代码的方式,介绍常用的二维码操作方法,比如:生成二维码、识别二维码的方法,请求网站接口下载二维码、展示二维码的方法,识别二维码提取信息的方法。在博客的最后会提供源代码的下载。


一、搭建工程

搭建一个 SpringBoot 工程,其结构如下所示:

image

QrController 中主要编写了一些 http 接口,用于演示如何下载二维码以及在页面中展示二维码

test 包下的 QrCodeTest 编写了一些方法,用于演示如何生成二维码以及识别二维码

resources 下的 logo 目录存放了一些图片,用于展示在所生成的二维码图片中心

resources 下的 img 目录下存放了一张二维码图片,用于演示识别二维码,提取二维码信息

先看一下 pom 文件中的依赖包:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jobs</groupId>
    <artifactId>springboot_qrcode</artifactId>
    <version>1.0</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--引入码生成和识别依赖包-->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!--里面有很多非常实用的工具类-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.3</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.4.5</version>
            </plugin>
        </plugins>
    </build>
</project>

主要引入 hutool-all 依赖和 com.google.zxing 的 core 依赖。com.google.zxing 的 core 依赖是生成和识别二维码的核心依赖,hutool 里面提供了 QrCodeUtil 工具类,对其进行了封装,大大简化了二维码的生成和识别的代码实现。


二、代码实现

由于代码很简单,注释也很详细,这里就不详细介绍,首先看一下 QrCodeTest 类的代码:

package com.jobs;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.Base64Utils;
import org.springframework.util.ResourceUtils;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;

@SpringBootTest
public class QrCodeTest {


    //直接根据url生成二维码
    @Test
    void test1() {
        QrCodeUtil.generate("https://www.cnblogs.com/studyjobs",
                300, 300, FileUtil.file("D:\\qrcode1.jpg"));
    }

    //设置二维码前景色、背景色、中间的logo
    @Test
    void test2() throws FileNotFoundException {
        QrConfig config = new QrConfig(300, 300);
        // 设置边距,既二维码和背景之间的边距
        config.setMargin(1);
        // 设置前景色,二维码颜色(绿色)
        config.setForeColor(new Color(0, 139, 69));
        // 设置背景色(淡黄色)
        config.setBackColor(new Color(255, 255, 224));
        // 设置中间的 logo 图片
        String logoPath = ResourceUtils.getFile("classpath:logo/logo1.png").getPath();
        config.setImg(logoPath);
        // 设置容错级别
        config.setErrorCorrection(ErrorCorrectionLevel.H);
        // 生成二维码到文件,也可以到流
        QrCodeUtil.generate("https://www.cnblogs.com/studyjobs",
                config, FileUtil.file("D:/qrcode2.jpg"));
    }

    //生成二维码的base64字符串
    @Test
    void test3() {
        byte[] pngArr = QrCodeUtil.generatePng("https://www.cnblogs.com/studyjobs",
                300, 300);
        String base64 = Base64Utils.encodeToString(pngArr);
        System.out.println(base64);

        //将 base64 字符串,放入 html 的 image 标签中,打开 html 就可以看到二维码图片
        //格式为:<img src="data:image/png;base64,你的图片的base64写在这里"/>
        //我们可以让 http 接口返回图片的 base64 字符串到前端,相当于提供了二维码图片下载接口
    }

    //生成二维码的base64字符串
    @Test
    void test4() throws FileNotFoundException {
        QrConfig config = new QrConfig(300, 300);
        // 设置边距,既二维码和背景之间的边距
        config.setMargin(1);
        // 设置前景色,二维码颜色(绿色)
        config.setForeColor(new Color(0, 139, 69));
        // 设置背景色(淡黄色)
        config.setBackColor(new Color(255, 255, 224));
        // 设置中间的 logo 图片
        String logoPath = ResourceUtils.getFile("classpath:logo/logo2.png").getPath();
        config.setImg(logoPath);
        // 设置容错级别
        config.setErrorCorrection(ErrorCorrectionLevel.H);
        byte[] pngArr = QrCodeUtil.generatePng("https://www.cnblogs.com/studyjobs", config);
        String base64 = Base64Utils.encodeToString(pngArr);
        System.out.println(base64);

        //将 base64 字符串,放入 html 的 image 标签中,打开 html 就可以看到二维码图片
        //格式为:<img src="data:image/png;base64,你的图片的base64写在这里"/>
        //我们可以让 http 接口返回图片的 base64 字符串到前端,相当于提供了二维码图片下载接口
    }

    //识别二维码中的 url 信息
    @Test
    void test5() throws FileNotFoundException {
        File qrFile = ResourceUtils.getFile("classpath:img/QrCode.png");
        String decode = QrCodeUtil.decode(qrFile);
        System.out.println(decode);
    }

    //识别 base64 图片中的 url 信息
    @Test
    void test6() {
        String base64 = "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAIAAAD2HxkiAAAR/0lEQVR42u3de1BU1x3A8fzRmFi1SXxMYtR0Wp2xTsyjOlaT6PiKBqcqSSaxraYZ83DUOk3tpD5RooJPYlQUfCGI4gsERZCHCOyyuDx3FYRFEIkYRa1EQ1SMAtqfe3W7hGcSde+9fH/zm3VdLpd93M/+ztlzz9nH7tw5TZKkC/MxngKSBCFJgpAkSRCSJAhJkgQhSYKQJEkQkiQISZIEIUmCkCRJEJIkCEmSBCFJgpAkSRCSJAhJklQlwsd8RmgiH9T9f9jPj1ae54d9P/V6vIEQhCAEIQhBCEIQghCEIAQhCEEIQhCCEIQgBCEIQQhCEOodocuGOzWCUCtoXfWmo9fjDYQgBCEIQQhCEIIQhCAEIQhBCEIQghCEIAQhCEEIQhCCsKUidNVgrl4f18N+fvS6vdqONxCCEIQgBCEIQQhCEIIQhCAEIQhBCEIQghCEIAQhCEEIQhCq4yDTymTQRzPZ9NEfDyAEIQhBCEIQghCEIAQhCEEIQhCCEIQgBCEIQQhCEIIQhCAEoZpeVL0u/qu2kwRACEIQghCEIAQhCEEIQhCCEIQgBCEIQQhCEIIQhCAEIQhBqC+EWh8s1joSrS/Oy+K/IAQhCEEIQhCCEIQgBCEIQQhCEIIQhCAEIQhBCEIQghCE6kaolcmybN8yF/NV25sXCNkehCAEIduDEIRsD0IQgpDtQQhCtgchCEHI9iAEIduDUGsI9ZotbTKx2u5/Cz3qeApACEIQghCEICRBCEIQghCEICRBCEIQghCEICRBCMIWh1Ark0q18ni1PsiulTcdXQ3WgxCEIAQhCEEIQhCCEIQgBCEIQQhCEIIQhCAEIQhBCEIQauBg0vqXTqptkVy9Pi6tvJmCkIMVhCAEIQhBCEIQghCEIAQhCEEIQhCCEIQgBCEIQQhCrSFU24Nvaam2ScN6nbQNQhCCEIQgBCEIQQhCEIIQhCAEIQhBCEIQghCEIAQhCEEIQnUPIrvq/mjlzUhtrwuD/iAEIQhBCEIQghCEIAQhCEEIQhCCEIQgBCEIQQhCEIIQhNpE6KoXQ68Hn9bfRNR20oJWigEIQQhCEIIQhCAEIQhBCEIQghCEIAQhCEEIQhCCEIQgBKHWEKpt0Fmvkz61clKBq94E9TG5GYQgBCEIQQhCEILQ1XjO3XFZnAMhCEF4+47rA4QgbLkImxu37VFVVVVZWVlRUXHlypXy8vL/2uPixYtyKf+9fPmy/Oj69euymWz8KB2CEIQaRVi/E+Fks9kOHTqUkJBgMpmOHj1aUFDwtT1ONyNks5MnT544cUJ+KycnJzs7OzIyMiAgIDg42Gw2C9eH4RCEINQiwnN1a11xcXFMTIzBYBB4DlEPJBw409PTQ0JCzpw5Ux/CMhDqAaHa8Kh2kL2ugPj4+Nzc3K8fSWRkZERHR/+MYqiVydlamWQMQnUhzM/Plybo7t27U1JSpDFZWlr6YCuhhPwJ2bkU26ioKIvFAkIQgrBWpKWlSQ/w6tWrp06dMhqNgYGB27Zt279/f2pqqrROpaUqt9fbA6zbV5RbZGP5FavVmpmZKX3LuLg4uTxy5Ij8V/jJbkUjCEEIwlohXUGx8f3331++fLm8vPz8+fPffPONWMrLy8u6H0JIWpLSr0u7H2azWbmSbg/5qWyjbJydnS16pYlrs9mktEoZzMnJkVsUhFJ1QQhCENYKMZOUlFQXoRDK+llRVlYme5BmreykqKjIgVD+kICX6yAEIQhrhWCT5mJdhAUFBQ8cofy0pKQEhCAEYa2orKzMz8uTPqED4ZkzZ8SPtCQfLEL5kbRRb9y4AUIQgrBWVFdXHz9+3IFQCP1yhLKHehHK5c8brwehihBqZTKr2iahNoJQIiUlpaKi4kcIpTmqNCB/UsivyK/LlcjIyJUrV3p7e0fsi1AQSqPXaDTWewd0M6laW19mCkIVIUxMTBQ5ynmhzggtFksz4RkMhuCtwT7LV3gtWrRwwcJZM2au9V0rZfDkyZNSCaUVKgiTkpIOHz4MQhCCsJ7IzMy02fLrIrRarc0RuHjx4mVLlvqv8/v000/+Mm7cvz77rOTUqf83R/Py7tbBo0ejo6NFIwhBCML6OmSnTyckJNRFeOzYsSYFCjmPuXNGjhw5aNDASZMmmc3mex/MnDlTFB+VH+Cbs3GVUgn37dt34cIFEIIQhPXEzZs3pQtXF6HgaURgVNSBTz76SPj16NGjV69e6enpyu3nSk+fWr2wcMWc/P9MtYXuybfZFIQREeFVVVUgBCEI6496K+Hx48cbqYHj//ZXNze39h06vD9u3P0bLRmRe0/Nn1L4zw8KJn18d8R/R4jNvh97nzCxob8OQhCC8G630IFQGaw/ceKE85lrzhEREeE+ZkyrVk9KJicnKybNa5amjH8raezgkjW+pdbswgUzct8ba31jkM1mUxDKNiAEIQgbRCjdP0H47bffpqamOiphvQh37tzZu3fvxx9vtWiRl9VqzbZYTNMmGoa9ur1PT0N4eFaK8eTEt4v+Pib/7TctXV4otFoVhLKl/AkQ6gGhVlYZU/GLXX9YLBalEvbp21f4NYJwwIABv3q81fjx4+8WQIvFMLh/4ks9vHp1T09LM037OHlI3xN/Hji4c8fsri8cGzT4ZHGxglDKoBTbB45Qr6vOaXLxXxD+QoRJSUmX7DHXw2P4m2+WlJRkZmTs3r1bcGbfjy88v+jZs2fr1q3vFkCrNar3Kwee6zK5+++EotnHJ7FLN7OXV3ZWlvuLvTZ2fj6j629P3R8nlBqYnp5uMBhACEIQNogwxWgsKiwUhBcuXPh99x79+vWTPuGGjRv79/+Tj4+PUHR3d3/iySf+2KeP8Nvy+sB1nZ57u1u3/WFhoYu9/EePMsUcdJTKfk+1i37+BSHqXD8FuclkAiEIQdggQilZUt8EYVlZWWlpaetft/GY5yEt0jZt2z79zNNt2rXr2LHjP6ZNO3r06Kr+r3l26OTWvbts7zNtSlzonmxHtbRYPD6Y8O+OncI6d02LiMh2iri4uOLiYhCCEIQNIqyoqDh48KCCUPlgZtPmzS++9PL4CRPa/qbdM+3br169etNn06c+9cyQDu2lsiUeOmSRRmnt8Hzv/eFt24R07mbw81fOO5VLaYvm5OSEh4dfvXoVhCAEYYMIq6urY2NjHeOEUrWkDBYWFubm5nbv0b1v375hK3ymP93eu/fLR7Zvl9apzWZT4CnneUukpaZOf/0Nv2e7BD3XNSc3V26XnUiBlS0FYVRUVE1NDQhBCMLGlv1NTEx0VEIFYbH9s00/P7+x7mNtBQXpBkP07LnbBg/f3Kff2l4vbhg1apWb247Zs1dNmDD9lVcmd++xc+SoVc92OVdaqswnLCkpURAqZ2838qdBCEIQ3lvn4vz5885nzCgnzUgxlNI34PXX5NJqb4LKP+lHzCELF3m/5bZ05FveQ4ZO6dBJLtdN+CAjLc0xqdeBUNqlDSyyBsIWjFDri/z+gv03GBkZGWLGGWFeXp5c5tsjIiIiMChIOaFUWWBbrsjlicLC7MzMHKs1NdmgNE1/hFBuNJlMjQwSOk/q5VulHuXgPghVh9BoNIpDZ4TSHJWWpJQyZXb8sWPHbPazsR1FUuqbMu1QQlk2X67IHs6ePeuMMD4+voGVDkEIQhA6RWpqamRk5I8qocCzNBrWuwMTtcK5Eip9y7179xobHqkHIQhBeC+OHDkSGxurjBM2H2HdqNscjY6ONpmohCAEYVMIBU9SUlK9lVB6eocPHw4JCfHz81u1apWvr6+/v39AQMD27dv37NkTFhYmJdRgMDgQOpqjSiVMTk6WW0AIQhA2gbCmpiYzM1OphIJH+oHSlxNvXvaYZw9PT88lS5asWbNm/fr1QUFBO3bsCA8PP2CPiIiIMHtIp7GoqMi5EmZlZd28eROEIARhEwiVbqGC0Gq17ty5c8uWLeLtpyJUBgbT0tKUj3bk0mw2N/OrQkEIwpaOMCEhQbpzRqNRenG7du0KDAxsCOGGDRu2bt3qjFCuOCPMyMhITEyU/ch/Zbcg1D9CrQzKu2rQv5kITSaT4ElJSVEQSiV0NEcXLlwoCBcsWODt7b169WqlEkovUQqgoxLu3btXEEpPUhCmp6cLwpiYGLmxgS+BeZBfXq/RdO2kYRCqEWFOTk5SUpIzQvEm6pYvX7527Vqpfhs3btxwPzZt2hQQECAUA+0hhVFasHv27HEglF0Jwm3btsl1EIIQhM1CeOnSJSloDoRS6MTYhvpi8+bNQjSoTohG6U9aLBZHJZRbpGfYzA9mQAjClo6wpqZm9uzZkZGRBw8elGakdPnqRSiughoOqz2kWSuVUPYjfcjCwsLy8vJGZlGAEIQgvBe3b9+eOXPm/Pnzly5dutMegsrRBN1kj633Izg4WJqayhUlFIRZWVlmszk0NHTWrFkeHh7SmrXal3tq4PuYQAhCEDrFrVu35s6dKwgdH4Eq4xASQtHX13e1PeSK0j9UfMqlv7//V1999fnnn3/44YfvvvvuxIkTp06dOmPGjHnz5glCaZdK67SRSb0gBCEI70VVVZWnp6eCUJEmCKUehoWFRUVFxcfHx8XF7du3TzqEy5cvl0I3ZcoUd3f3ESNGDBs2zM3NbZQ93nnnHUEoPxKEUgm9vLykZyit08rKShCCEIRNN0dDQkIUhOvWrVMGA3ft2iUIDxw4IALFofQYReaXX345Z84ckTZmzJhRtUOphJMnT1YQrlixwmg0lpaW0ifUCULXrZmrbfyODf6w5ePGHUrPbdmyZYJQGZNwRhgbG1sX4ejRowWemz2cK6HSHBWExuTk8vLyhr6FQuLV4Cm6eb009hYAQlfN3L96q7KpUbs7oaGh0veTzl5zKqE0R4cMGTJ8+PAfNUcFsykl5eLFi9XV1Q02gGuq9fR6gRCEzd3PnWaEyLl27VpaTMzmTZuCg4Mj7QgPHTokCAMDA1euXOmohEOHDh04cKBcjh07dtKkScHr1yuT9L/77rumhgfv6Oz1AiEIf8J+blTdbA5F6SVKS/KHH364cuVKWVmZMtfebDabTCaDwSCdvdTU1KysLGXmxNmzZ6XlWVlZKYDlF5v4EOjh1EAQglBLC0n1Dpp0p9khqISWAlKYXb9+/dr9kP/Kjbdu3aqpqWnS3sPrB4IQhLpazU1tq4mBEIQgBCEIQQhCEKocodoOYrV9iaQGTyp4pK+72rA9mvsDQhCCEIQgBCEIQQhCEIIQhCAEIQhBCEIQghCEIAQhCEGoHYRaf1LAyUkC6jlOQAhCEIIQhCAEIQhBCEIQghCEIAQhCEEIQhCCEIQgBCEItYNQbYPFajvIXHUQu+qkC1cd9K5CC0IQghCEIAQhCEEIQhCCEIQgBCEIQQhCEIIQhCAEIQhB2FIRqg2n1ifRauXNSG2pzkm6IAQhCEEIQhCCEIQgBCEIQQhCEIIQhCAEIQhBCEIQghCE+kWo9UVmebzqfNNRG+YWsQI3CEEIQhDyeEEIQhCCEIQg5PGCEIQgBCEIOSh5vCAEIQhBCMIWlGqblOyqNwV9LJ6r/pMrQAhCEIIQhCAEIQhBCEIQghCEIAQhCEEIQhCCEIQgBCEI9YJQr5M+9TqJVq9vIlqZFA5CEIIQhCAEIQhBCEIQghCEIAQhCEEIQhCCEIQgBCEIQah3hGobfNfrosZaed60/no9mvsPQhCCEIQgBCEIQQhCEIIQhCAEIQhBCEIQghCEIAQhCEGoX4RaWaRV6wel1gf9tXLyhiYH60EIQhCCEIQgBCEIQQhCEIIQhCAEIQhBCEIQghCEIAQhCEGomUnJajvIXLV4rlb+LghBCEIQghCEIAQhCEEIQhCCEIQgBCEIQQhCEIIQhCAEIQi1OVivlcmjWn9+9IochCAEIQhBCEIQghCEIAQhCEEIQhCCEIQgBCEIQQhCEIIQhNpcxFbrJwmo7fnXyptUi5jUC0IQghCEIAQhCEEIQhCCEIQgBCEIQQhCEIIQhCAEIQhB+BAR6nWSq6sOJle9Cbrq5Aq1HQ+anNQLQhCCEIQgBCEIQQhCEIIQhCAEIQhBCEIQghCEIAQhCEH4EBGSJAlCkgQhSZIgJEkQkiQJQpIEIUmSICRJEJIkCUKSBCFJkiAkSRCSJAlCkgQhSZIgJEkQkiQJQpLUSP4P+J3wjePIbYwAAAAASUVORK5CYII=";
        byte[] bytes = Base64Utils.decodeFromString(base64);
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        String decode = QrCodeUtil.decode(bis);
        System.out.println(decode);
    }
}

然后再看一下 QrController 的代码内容:
package com.jobs.controller;

import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.springframework.util.Base64Utils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;

@RequestMapping("/qrcode")
@RestController
public class QrController {

    //下载二维码的 base64 字符串
    @GetMapping("/download1")
    public String download1(HttpServletResponse response) throws Exception {
        //生成默认的白底黑码,中间无logo的二维码
        byte[] pngArr = QrCodeUtil.generatePng("https://www.cnblogs.com/studyjobs",
                300,300);
        String base64 = Base64Utils.encodeToString(pngArr);
        return base64;
    }

    //下载二维码图片
    @GetMapping("/download2")
    public void download2(HttpServletResponse response) throws Exception {

        QrConfig config = new QrConfig(300, 300);
        // 设置边距,既二维码和背景之间的边距
        config.setMargin(1);
        // 设置前景色,二维码颜色(绿色)
        config.setForeColor(new Color(0, 139, 69));
        // 设置背景色(淡黄色)
        config.setBackColor(new Color(255, 255, 224));
        // 设置中间的 logo 图片
        String logoPath = ResourceUtils.getFile("classpath:logo/logo3.png").getPath();
        config.setImg(logoPath);
        // 设置容错级别
        config.setErrorCorrection(ErrorCorrectionLevel.H);
        byte[] pngArr = QrCodeUtil.generatePng("https://www.cnblogs.com/studyjobs", config);

        //下载文件的响应类型,这里统一设置成了文件流
        //你可以根据自己所提供下载的文件类型,使用不同的响应 mime 类型
        response.setContentType("application/octet-stream;charset=utf-8");
        //设置下载弹出框中默认显示的文件名称,如果指定中文名称的话,需要转成 iso8859-1 编码,解决乱码问题
        String fileName = new String("二维码图片.png".getBytes(), "iso8859-1");
        response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
        response.getOutputStream().write(pngArr, 0, pngArr.length);
    }

    //浏览器直接显示二维码图片
    @GetMapping("/download3")
    public void download3(HttpServletResponse response) throws Exception {

        QrConfig config = new QrConfig(300, 300);
        // 设置边距,既二维码和背景之间的边距
        config.setMargin(1);
        // 设置前景色,二维码颜色(绿色)
        config.setForeColor(new Color(0, 139, 69));
        // 设置背景色(淡黄色)
        config.setBackColor(new Color(255, 255, 224));
        // 设置中间的 logo 图片
        String logoPath = ResourceUtils.getFile("classpath:logo/logo2.png").getPath();
        config.setImg(logoPath);
        // 设置容错级别
        config.setErrorCorrection(ErrorCorrectionLevel.H);
        byte[] pngArr = QrCodeUtil.generatePng("https://www.cnblogs.com/studyjobs", config);

        response.setContentType("image/png");
        response.getOutputStream().write(pngArr, 0, pngArr.length);
    }
}

下面列出代码执行过程中,自定义生成的一张二维码图片,扫描后跳转到博客园中我的博客首页:

image


以上就是本篇博客内容的全部,非常简略,具体细节可以下载源代码运行和验证。

本篇博客的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/springboot_qrcode.zip

posted @ 2023-11-16 21:27  乔京飞  阅读(16164)  评论(0编辑  收藏  举报