Java 实现 URL 转二维码功能:完整教程(含图片压缩与实战案例)

在日常开发中,二维码作为信息快速传递的载体被广泛应用,比如通过 URL 生成二维码实现网页快速访问、文件下载等场景。本文将基于 Java 语言,结合成熟的二维码生成库,实现从 URL 到二维码的完整流程,包括二维码生成、图片尺寸调整(等比例压缩),并提供可直接复用的实战代码。

一、技术选型

核心依赖库

生成二维码的核心是 ZXing(Zebra Crossing)库,它是 Google 开源的多格式 1D/2D 条码图像处理库,支持 QR Code、Data Matrix 等多种条码类型,且使用简单、兼容性强。

依赖引入(Maven/Gradle)

Maven 依赖
<!-- ZXing 核心依赖 -->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.4.1</version>
</dependency>

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.4.1</version>
</dependency>
Gradle 依赖
implementation 'com.google.zxing:core:3.4.1'
implementation 'com.google.zxing:javase:3.4.1'

二、核心功能实现

本文将实现两个核心功能:

  1. URL 生成二维码:将指定 URL 编码为二维码图片并保存到本地;
  2. 二维码图片压缩:支持等比例/固定尺寸调整二维码图片大小,保证图片清晰度。

1. 工具类完整代码

import com.google.zxing.*;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Java URL 转二维码工具类(含图片压缩功能)
 * @author 开发者名称
 * @date 2025-11-06
 */
public class QrCodeUtils {

    /**
     * 生成二维码核心方法
     * @param content 二维码内容(支持 URL、文本等)
     * @param savePath 二维码图片保存路径(含文件名,如:D:/qrcode/test.png)
     */
    public static void generateQrCode(String content, String savePath) {
        // 1. 配置二维码参数
        int width = 400; // 原始二维码宽度(像素)
        int height = 400; // 原始二维码高度(像素)
        String format = "png"; // 二维码图片格式(支持 png、jpg 等)

        // 2. 二维码高级配置(容错级别、编码格式、边框宽度)
        Map<EncodeHintType, Object> hints = new HashMap<>();
        // 容错级别:L(7%) < M(15%) < Q(25%) < H(30%),M 级别平衡容错与密度
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        // 字符编码:避免中文/特殊字符乱码
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 边框宽度:0-4(0 表示无边框)
        hints.put(EncodeHintType.MARGIN, 2);

        try {
            // 3. 生成二维码矩阵(核心步骤)
            BitMatrix bitMatrix = new MultiFormatWriter().encode(
                content, 
                BarcodeFormat.QR_CODE, 
                width, 
                height, 
                hints
            );

            // 4. 保存二维码到指定路径
            File qrCodeFile = new File(savePath);
            // 确保父目录存在(避免路径不存在报错)
            if (!qrCodeFile.getParentFile().exists()) {
                qrCodeFile.getParentFile().mkdirs();
            }
            MatrixToImageWriter.writeToPath(bitMatrix, format, qrCodeFile.toPath());
            System.out.println("二维码生成成功!保存路径:" + savePath);

        } catch (WriterException | IOException e) {
            System.err.println("二维码生成失败!");
            e.printStackTrace();
        }
    }

    /**
     * 调整 BufferedImage 大小(支持等比例压缩/固定尺寸)
     * @param source 原始图片 BufferedImage 对象
     * @param targetW 目标宽度(像素)
     * @param targetH 目标高度(像素)
     * @param keepRatio 是否保持等比例(true:等比例,false:固定尺寸)
     * @return 调整后的 BufferedImage 对象
     */
    public static BufferedImage resizeBufferedImage(BufferedImage source, int targetW, int targetH, boolean keepRatio) {
        // 1. 计算缩放比例
        double scaleX = (double) targetW / source.getWidth(); // 宽度缩放比例
        double scaleY = (double) targetH / source.getHeight(); // 高度缩放比例

        // 2. 若保持等比例,取最小缩放比例(避免图片拉伸)
        if (keepRatio) {
            scaleX = Math.min(scaleX, scaleY);
            scaleY = scaleX;
            // 重新计算目标尺寸(等比例后的实际尺寸)
            targetW = (int) Math.round(source.getWidth() * scaleX);
            targetH = (int) Math.round(source.getHeight() * scaleY);
        }

        // 3. 创建目标图片 BufferedImage 对象
        BufferedImage targetImage;
        int imageType = source.getType();

        // 处理自定义图片类型(避免类型不兼容)
        if (imageType == BufferedImage.TYPE_CUSTOM) {
            ColorModel colorModel = source.getColorModel();
            WritableRaster raster = colorModel.createCompatibleWritableRaster(targetW, targetH);
            boolean alphaPremultiplied = colorModel.isAlphaPremultiplied();
            targetImage = new BufferedImage(colorModel, raster, alphaPremultiplied, null);
        } else {
            targetImage = new BufferedImage(targetW, targetH, imageType);
        }

        // 4. 高质量缩放图片(使用 Graphics2D 保证清晰度)
        Graphics2D graphics2D = targetImage.createGraphics();
        // 设置渲染提示:抗锯齿、高质量缩放
        graphics2D.setRenderingHint(
            RenderingHints.KEY_RENDERING, 
            RenderingHints.VALUE_RENDER_QUALITY
        );
        graphics2D.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING, 
            RenderingHints.VALUE_ANTIALIAS_ON
        );
        // 执行缩放绘制
        graphics2D.drawRenderedImage(
            source, 
            AffineTransform.getScaleInstance(scaleX, scaleY)
        );
        graphics2D.dispose(); // 释放资源

        return targetImage;
    }

    /**
     * 读取本地图片为 BufferedImage 对象
     * @param imagePath 图片本地路径
     * @return BufferedImage 对象
     * @throws IOException 图片读取异常
     */
    public static BufferedImage readImage(String imagePath) throws IOException {
        return ImageIO.read(new FileInputStream(imagePath));
    }

    /**
     * 保存 BufferedImage 为本地图片
     * @param image 要保存的 BufferedImage 对象
     * @param savePath 保存路径(含文件名)
     * @param format 图片格式(png/jpg 等)
     * @throws IOException 图片保存异常
     */
    public static void saveImage(BufferedImage image, String savePath, String format) throws IOException {
        File saveFile = new File(savePath);
        if (!saveFile.getParentFile().exists()) {
            saveFile.getParentFile().mkdirs();
        }
        ImageIO.write(image, format, saveFile);
        System.out.println("图片保存成功!路径:" + savePath);
    }
}

2. 关键方法解析

(1)二维码生成 generateQrCode 方法
  • 参数配置:通过 Map<EncodeHintType, Object> 配置二维码的容错级别、编码格式、边框宽度,其中:
    • ERROR_CORRECTION:容错级别越高,二维码越抗污损,但密度越大(推荐 M 级别);
    • CHARACTER_SET:指定 UTF-8 编码,避免 URL 中含特殊字符(如中文、参数符号)时乱码;
    • MARGIN:边框宽度,0 表示无白边,2-4 为常用值。
  • 核心逻辑:通过 MultiFormatWriter.encode() 生成 BitMatrix(二维码矩阵),再通过 MatrixToImageWriter.writeToPath() 将矩阵写入本地文件。
(2)图片压缩 resizeBufferedImage 方法
  • 等比例压缩:当 keepRatio=true 时,取宽度和高度缩放比例的最小值,确保图片不会拉伸,同时计算实际目标尺寸;
  • 高质量渲染:使用 Graphics2D 并设置 RenderingHints,保证缩放后的图片清晰度,避免出现模糊、锯齿等问题;
  • 类型兼容:处理 TYPE_CUSTOM 类型图片,避免因图片类型不兼容导致的报错。

三、实战案例:URL 生成二维码并压缩

场景需求

将 URL(如 https://www.baidu.com/DocxView?entrustMsgId=xxx)生成二维码,保存到本地后,将图片压缩为 100x100 像素(等比例),用于网页展示或小程序使用。

测试代码

public class QrCodeTest {
    public static void main(String[] args) {
        // 1. 配置基础参数
        String entrustMsgId = "MSG20251106001"; // 业务ID(示例)
        String otherDatabaseName = "doc_db"; // 数据库名称(示例)
        String baseImagePath = "D:/qrcode/"; // 图片保存根路径
        String urlPrefix = "https://www.baidu.com/DocxView?entrustMsgId=";
        String fullUrl = urlPrefix + entrustMsgId; // 完整 URL

        // 2. 生成二维码文件名(避免重复)
        String qrCodeFileName = entrustMsgId + "-" + otherDatabaseName + ".png";
        String qrCodeSavePath = baseImagePath + qrCodeFileName; // 二维码保存路径
        String compressedSavePath = baseImagePath + "compressed_" + qrCodeFileName; // 压缩后保存路径

        try {
            // 步骤1:生成原始二维码
            QrCodeUtils.generateQrCode(fullUrl, qrCodeSavePath);

            // 步骤2:读取原始二维码图片
            BufferedImage originalImage = QrCodeUtils.readImage(qrCodeSavePath);

            // 步骤3:等比例压缩为 100x100 像素
            BufferedImage compressedImage = QrCodeUtils.resizeBufferedImage(originalImage, 100, 100, true);

            // 步骤4:保存压缩后的图片
            QrCodeUtils.saveImage(compressedImage, compressedSavePath, "png");

        } catch (Exception e) {
            System.err.println("URL 转二维码并压缩失败!");
            e.printStackTrace();
        }
    }
}

执行结果

  1. 本地路径 D:/qrcode/ 下会生成两个文件:
    • MSG20251106001-doc_db.png:原始 400x400 像素二维码;
    • compressed_MSG20251106001-doc_db.png:压缩后 100x100 像素二维码(等比例,无拉伸)。
  2. 扫描二维码可直接跳转到目标 URL(https://www.baidu.com/DocxView?entrustMsgId=MSG20251106001)。

四、常见问题与注意事项

1. 二维码生成失败?

  • 检查 savePath 路径是否合法(如是否有权限写入),工具类已添加 mkdirs() 自动创建父目录;
  • 确保 URL 格式正确,避免含非法字符(可通过 URLEncoder.encode() 对 URL 编码后再生成二维码);
  • 检查 ZXing 依赖是否引入成功,版本是否兼容(推荐 3.5.0+)。

2. 压缩后图片模糊?

  • 避免将小尺寸图片放大(如 100x100 放大到 400x400),会导致像素拉伸;
  • 生成原始二维码时可适当增大尺寸(如 600x600),再压缩到目标尺寸,清晰度更高;
  • 确保 resizeBufferedImage 方法中启用了 RenderingHints.KEY_RENDERINGKEY_ANTIALIASING

3. 中文 URL 乱码?

  • 生成二维码前,对中文 URL 进行 UTF-8 编码:
    String fullUrl = urlPrefix + URLEncoder.encode(entrustMsgId, "UTF-8");
    
  • 确保 generateQrCode 方法中 CHARACTER_SET 配置为 UTF-8

五、功能扩展建议

  1. 添加 Logo:在二维码中心添加企业/产品 Logo,增强品牌识别度(需处理 Logo 大小,避免遮挡二维码信息);
  2. 内存流生成:不保存本地文件,直接生成 InputStreamBase64 编码,用于网络传输(如接口返回二维码图片);
  3. 自定义颜色:修改二维码的前景色(默认黑色)和背景色(默认白色),通过 MatrixToImageConfig 实现;
  4. 批量生成:支持多 URL 批量生成二维码,通过循环调用 generateQrCode 方法实现。

六、总结

本文基于 Java + ZXing 库实现了 URL 转二维码的完整流程,包含二维码生成、等比例压缩、图片读写等核心功能,代码可直接复用在实际项目中。通过灵活配置二维码参数和图片压缩策略,可满足不同场景(如网页展示、打印、移动端识别)的需求。如果需要进一步扩展功能(如添加 Logo、Base64 编码),可基于本文工具类进行二次开发。

希望本文对你有所帮助,如有问题或优化建议,欢迎在评论区交流!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐