⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 juejin.cn/post/7527881245239001126 「天天摸鱼的java工程师」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

前言:二维码是怎么悄悄“支配”我们的?

你有没有发现:

现在任何东西都能整出个二维码?

  • 微信支付?扫码。
  • 加好友?扫码。
  • 点菜?扫码。
  • 领优惠券?扫码。
  • 连 Wi-Fi?扫码。
  • 打开厕所门?也扫码……(别问我怎么知道的)

二维码已经彻底渗透到我们生活的每个角落。作为一名干了八年 Java 的程序员(主要在摸鱼,但也干活),我最近接到一个需求:

“我们要给用户生成动态的登录二维码,另外还要支持活动海报、带 logo 的分享码、临时访客二维码、带参数的推广码……你搞一下,应该不难吧?”

我嘴上说着“简单”,心里却在想:

你知道二维码有多少种花样吗?!

一、业务分析:二维码到底有几种玩法?

我们先冷静分析一下业务需求,把“二维码”拆解成几个典型的应用场景:

场景名称 特点描述
登录二维码 临时有效,常变化,内容是一个 token 或 URL
活动海报二维码 嵌入图片中,需高颜值,对清晰度有要求
带 logo 的二维码 中间加 logo 图标,用户更容易识别品牌
参数推广二维码 携带用户 ID、推广码等参数,可用于追踪来源
临时访客二维码 时间敏感,可能加密,甚至设定失效时间

简而言之,二维码不仅是一个图,还要“有脑子” 。

二、技术选型:选对工具,事半功倍

在 Java 世界,要生成二维码,主流有两个选择:

  • ZXing(Zebra Crossing):Google 出品,经典老牌,稳定可靠。
  • QrCode(来自 com.google.zxing.qrcode):轻量级,适合快速开发。
  • QRCodeUtils(封装工具类):自己撸一点封装,方便复用。

我选的是 ZXing + 自定义封装。

理由如下:

  • 社区活跃,有问题能搜到;
  • 支持二维码 + 条形码;
  • 可配置参数多,能满足各种奇葩需求;
  • 最重要的:依赖不重,摸鱼时也能快速搞定!

三、实战演示:Java 手把手教你生成各种二维码

1. 引入 Maven 依赖

<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.5.2</version>
</dependency>

2. 封装一个二维码工具类 QrCodeUtils.java

package com.moyu.qr;

import com.google.zxing.*;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

/**
* 天天摸鱼的 Java 工程师出品
* 通用二维码生成工具类
*/
public class QrCodeUtils {

/**
* 生成普通二维码并保存为图片文件
*
* @param content 二维码内容
* @param filePath 保存路径(绝对路径)
* @param width 宽度
* @param height 高度
* @throws Exception
*/
public static void generateSimpleQrCode(String content, String filePath, int width, int height) throws Exception {
// 编码参数设置
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 编码类型
hints.put(EncodeHintType.MARGIN, 1); // 边距

BitMatrix bitMatrix = new MultiFormatWriter().encode(
content,
BarcodeFormat.QR_CODE,
width,
height,
hints
);

Path path = new File(filePath).toPath();
MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);
}

/**
* 生成带 Logo 的二维码
*
* @param content 二维码内容
* @param logoPath logo 图片路径
* @param outputPath 输出二维码路径
*/
public static void generateQrCodeWithLogo(String content, String logoPath, String outputPath) throws Exception {
int width = 300;
int height = 300;

Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 1);
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 容错率高,避免 logo 遮挡

BitMatrix bitMatrix = new MultiFormatWriter().encode(
content, BarcodeFormat.QR_CODE, width, height, hints
);

// 生成二维码图像
BufferedImage qrImage = MatrixToImageWriter.toBufferedImage(bitMatrix, new MatrixToImageConfig());

// 加载 logo 图片
BufferedImage logo = ImageIO.read(new File(logoPath));

int logoWidth = qrImage.getWidth() / 5;
int logoHeight = qrImage.getHeight() / 5;

// 计算 logo 放置位置(居中)
int x = (qrImage.getWidth() - logoWidth) / 2;
int y = (qrImage.getHeight() - logoHeight) / 2;

// 合并图片
Graphics2D g = qrImage.createGraphics();
g.drawImage(logo, x, y, logoWidth, logoHeight, null);
g.dispose();

ImageIO.write(qrImage, "PNG", new File(outputPath));
}
}

3. 实战调用:生成一个带参数的推广码

public class Main {
public static void main(String[] args) throws Exception {
String content = "https://yourdomain.com/register?ref=userid_123456";
String savePath = "D:/qrcode/promo.png";

QrCodeUtils.generateSimpleQrCode(content, savePath, 300, 300);
System.out.println("推广二维码生成成功,快去扫码看看!");
}
}

4. 再来一个更骚的:带 Logo 的品牌码

public class LogoDemo {
public static void main(String[] args) throws Exception {
String content = "https://yourapp.com/share?id=abc123";
String logo = "D:/logo/logo.png";
String output = "D:/qrcode/share_with_logo.png";

QrCodeUtils.generateQrCodeWithLogo(content, logo, output);
System.out.println("带 Logo 的二维码已生成!");
}
}

四、最佳实践 & 踩坑总结(摸鱼人血泪经验)

✅ 推荐做法:

  • 高容错 + logo:记得设置 ErrorCorrectionLevel.H,否则 logo 会导致识别失败。
  • 二维码尺寸:建议大于 250x250,避免在海报中模糊。
  • 内容长度:控制长度,避免生成失败(尤其是带参数 URL)。

❌ 踩过的坑:

  • 设置边距为 0 会导致大部分扫码器识别失败(别问怎么知道的)。
  • Logo 太大?二维码直接“失忆”。
  • 文件路径拼错?OutputStream 直接挂。

五、后记:二维码虽小,五脏俱全

别看二维码只有黑白小格子,其背后能承载的业务逻辑、营销策略、用户行为追踪,可比你写的 if else 高级多了。

记住一句老话:

“二维码是连接线下与线上最朴素、最强大的桥梁。 ”

文章目录
  1. 1. 前言:二维码是怎么悄悄“支配”我们的?
  2. 2. 一、业务分析:二维码到底有几种玩法?
  3. 3. 二、技术选型:选对工具,事半功倍
  4. 4. 三、实战演示:Java 手把手教你生成各种二维码
    1. 4.0.1. 1. 引入 Maven 依赖
    2. 4.0.2. 2. 封装一个二维码工具类 QrCodeUtils.java
    3. 4.0.3. 3. 实战调用:生成一个带参数的推广码
    4. 4.0.4. 4. 再来一个更骚的:带 Logo 的品牌码
  • 5. 四、最佳实践 & 踩坑总结(摸鱼人血泪经验)
    1. 5.0.1. ✅ 推荐做法:
    2. 5.0.2. ❌ 踩过的坑:
  • 6. 五、后记:二维码虽小,五脏俱全