我用 Java 把二维码玩出花了

来源:juejin.cn/post/7527881245239001126
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战(多个项目) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
-
新项目:《Spring AI 项目实战》正在更新中..., 基于 Spring AI + Spring Boot 3.x + JDK 21;
-
《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;演示地址:http://116.62.199.48:7070/
-
《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;
-
专栏阅读地址:https://www.quanxiaoha.com/column
截止目前,累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有4000+小伙伴加入

-
前言:二维码是怎么悄悄“支配”我们的?
-
一、业务分析:二维码到底有几种玩法?
-
二、技术选型:选对工具,事半功倍
-
三、实战演示:Java 手把手教你生成各种二维码
-
四、最佳实践 & 踩坑总结(摸鱼人血泪经验)
-
五、后记:二维码虽小,五脏俱全
前言:二维码是怎么悄悄“支配”我们的?
你有没有发现:
现在任何东西都能整出个二维码?
-
微信支付?扫码。
-
加好友?扫码。
-
点菜?扫码。
-
领优惠券?扫码。
-
连 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 工程师出品
* 通用二维码生成工具类
*/
publicclass 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 高级多了。
记住一句老话:
“二维码是连接线下与线上最朴素、最强大的桥梁。 ”
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战(多个项目) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
-
新项目:《Spring AI 项目实战》正在更新中..., 基于 Spring AI + Spring Boot 3.x + JDK 21;
-
《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;演示地址:http://116.62.199.48:7070/
-
《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;
-
专栏阅读地址:https://www.quanxiaoha.com/column
截止目前,累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有4000+小伙伴加入


1. 我的私密学习小圈子,从0到1手撸企业实战项目~ 2. 8.8k Star,一款简单高效的MySQL审核平台 3. 百度二面,MySQL 怎么做权重搜索? 4. SpringBoot + Tesseract 异步 OCR:发票识别流水线深度解析
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。 获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。 点“在看”支持小哈呀,谢谢啦
更多推荐

所有评论(0)