摸鱼八年,我用 Java 把二维码玩出花


摸鱼八年,我用 Java 把二维码玩出花

------来自一位八年资深"摸鱼"工程师的实战总结

作者:天天摸鱼的 Java 工程师

发布日期:2025-07-18


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

你有没有发现:

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

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

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

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

我嘴上说着"简单",心里却在想:
你知道二维码有多少种花样吗?!

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

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

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

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


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

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

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

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

理由如下:

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

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

1. 引入 Maven 依赖

xml 复制代码
<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

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. 实战调用:生成一个带参数的推广码

arduino 复制代码
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("推广二维码生成成功,快去扫码看看!");
    }
}

ini 复制代码
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 高级多了。

记住一句老话:

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

希望本文对你有帮助,不管你是刚入门的 Java 菜鸟,还是像我一样的 八年资深摸鱼工程师

作者:天天摸鱼的 Java 工程师
口号:用最少的代码,干最多的活,摸最深的鱼 🐟

相关推荐
Full Stack Developme8 分钟前
java.nio 包详解
java·python·nio
零千叶24 分钟前
【面试】Java JVM 调优面试手册
java·开发语言·jvm
代码充电宝34 分钟前
LeetCode 算法题【简单】290. 单词规律
java·算法·leetcode·职场和发展·哈希表
li37149089038 分钟前
nginx报400bad request 请求头过大异常处理
java·运维·nginx
摇滚侠41 分钟前
Spring Boot 项目, idea 控制台日志设置彩色
java·spring boot·intellij-idea
helloworddm1 小时前
Orleans 流系统握手机制时序图
后端·c#
Aevget1 小时前
「Java EE开发指南」用MyEclipse开发的EJB开发工具(二)
java·ide·java-ee·eclipse·myeclipse
黄昏晓x2 小时前
C++----多态
java·jvm·c++
Brookty2 小时前
【算法】前缀和
java·学习·算法·前缀和·动态规划
开心-开心急了2 小时前
Flask入门教程——李辉 第三章 关键知识梳理
后端·python·flask