所需依赖
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.3</version>
</dependency>
生成一个带颜色的图片
- 参数一:可以是网址或者文本信息
- 参数二:图片尺寸
public static BufferedImage generate(String content, int size) {
// 创建参数容器
Map<EncodeHintType, Object> hints = new HashMap<>();
// 设置容错等级(允许 logo 覆盖),就是高,扫一半也可以扫出来
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 设置白边(0 = 无白边)
hints.put(EncodeHintType.MARGIN, 0);
// ZXing 的编码器工厂
// 参数一:内容,参数二:生成的类型是二维码
// 参数三和四:宽高,参数五:规则配置。
BitMatrix matrix;
try {
matrix = new MultiFormatWriter().encode(
content, BarcodeFormat.QR_CODE, size, size, hints
);
} catch (WriterException e) {
throw new RuntimeException(e);
}
int width = matrix.getWidth();
int height = matrix.getHeight();
// 创建图片画布,参数三是:带颜色的画布RGB
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 绘制二维码
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, matrix.get(x, y) ? 0x000000 : 0xFFFFFF);
}
}
return image;
}
增加logo
public static BufferedImage addLogo(BufferedImage qr, String logoPath) throws Exception {
// 读取 logo 图片
BufferedImage logo = ImageIO.read(new File(logoPath));
// 根据二维码大小,动态计算 logo 要占多少空间
int qrSize = qr.getWidth();
// 除以 5,logo 占二维码的 1/5
int logoSize = qrSize / 5;
// 1px像素边框
int border = 1;
int boxSize = logoSize + border * 2;
// 把原始 logo 压缩/缩放成 logoSize × logoSize 的图片
// 图片缩小 / 放大
// SCALE_SMOOTH = 平滑缩放、清晰、速度稍慢
Image scaledLogo = logo.getScaledInstance(
logoSize, logoSize,
Image.SCALE_SMOOTH);
// 开启高质量模式
// 绘画器
Graphics2D g = qr.createGraphics();
// KEY_ANTIALIASING = 抗锯齿
// VALUE_ANTIALIAS_ON = 开启
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// KEY_RENDERING = 渲染策略
// VALUE_RENDER_QUALITY = 高质量模式
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// 把 logo 放到二维码正中间
int x = (qrSize - logoSize) / 2;
int y = (qrSize - logoSize) / 2;
// 1. 先画像素边框(矩形框)
g.setColor(Color.BLACK); // 你也可以换成品牌色
g.fillRect(x, y, boxSize, boxSize);
// 2. 再在中间画 logo(留1px边框)
g.drawImage(scaledLogo, x + border, y + border, null);
g.dispose();
return qr;
}
知识扩展
在 Java 中生成二维码,目前最主流的解决方案是使用 Google 开源的 ZXing(Zebra Crossing) 库。它功能强大、稳定可靠,支持生成和解码多种格式的二维码。另一个备选是 QRGen,它基于 ZXing 但提供了更简化的 API。
方案一:使用 ZXing(推荐,功能最全面)
1. 添加 Maven 依赖
在你的 pom.xml 文件中添加以下依赖:
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.5.3</version>
</dependency>
2. 基础二维码生成(保存为图片文件)
这是最基础的用法,几行代码即可将文本内容生成为二维码图片。
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import java.nio.file.Paths;
public class QRCodeGenerator {
public static void main(String[] args) throws Exception {
String content = "https://www.example.com"; // 二维码内容
String path = "qrcode.png"; // 输出路径
int width = 300;
int height = 300;
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height);
MatrixToImageWriter.writeToPath(bitMatrix, "PNG", Paths.get(path));
System.out.println("二维码生成成功:" + path);
}
}
3. 生成内存中的二维码图片(BufferedImage)
如果你的项目需要将二维码用于 Web 展示、邮件附件或进一步图像处理,可以直接生成 BufferedImage 对象,而无需保存为文件。
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
public class QRCodeToBufferedImage {
public static BufferedImage generateQRCodeImage(String content, int width, int height) throws Exception {
// 配置参数:字符编码和纠错级别
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 最高纠错级别
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
// 将 BitMatrix 转换为 BufferedImage
BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
qrImage.setRGB(x, y, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
}
}
return qrImage;
}
}
4. 高级配置
在生成二维码时,可以通过 EncodeHintType 配置多种参数:
Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 字符编码 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 纠错级别(L/M/Q/H) hints.put(EncodeHintType.MARGIN, 2); // 白边宽度(默认4)
方案二:生成带 Logo 的二维码
在二维码中心嵌入 Logo 图标,需要在生成基础二维码后,用 Java AWT 将 Logo 图片绘制到二维码中心位置。
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
public class QRCodeWithLogo {
public static BufferedImage addLogoToQRCode(BufferedImage qrImage, String logoPath) throws Exception {
Graphics2D graphics = qrImage.createGraphics();
// 读取 Logo 图片
BufferedImage logoImage = ImageIO.read(new File(logoPath));
// Logo 大小设为二维码的 1/5(兼顾识别率与美观)
int logoWidth = qrImage.getWidth() / 5;
int logoHeight = qrImage.getHeight() / 5;
// 居中计算
int x = (qrImage.getWidth() - logoWidth) / 2;
int y = (qrImage.getHeight() - logoHeight) / 2;
// 绘制 Logo(带白色背景框,避免干扰二维码识别)
graphics.setColor(Color.WHITE);
graphics.fillRect(x - 5, y - 5, logoWidth + 10, logoHeight + 10);
graphics.drawImage(logoImage, x, y, logoWidth, logoHeight, null);
graphics.dispose();
return qrImage;
}
public static void main(String[] args) throws Exception {
BufferedImage qrImage = QRCodeToBufferedImage.generateQRCodeImage("https://www.example.com", 400, 400);
BufferedImage qrWithLogo = addLogoToQRCode(qrImage, "logo.png");
// 保存到文件
ImageIO.write(qrWithLogo, "PNG", new File("qrcode_with_logo.png"));
System.out.println("带 Logo 的二维码生成成功");
}
}
方案三:使用 QRGen(更简洁的 API)
如果你的需求仅限于生成二维码(不需要解析功能),QRGen 提供了更简洁的 API。
1. 添加 Maven 依赖
<dependency>
<groupId>net.glxn.qrgen</groupId>
<artifactId>javase</artifactId>
<version>2.0</version>
</dependency>
2. 生成二维码
import net.glxn.qrgen.QRCode;
import net.glxn.qrgen.image.ImageType;
import java.io.File;
public class QRGenExample {
public static void main(String[] args) {
// 生成二维码并保存为图片文件
QRCode.from("https://www.example.com")
.withSize(300, 300)
.to(ImageType.PNG)
.writeTo(new File("qrcode_qrgen.png"));
// 生成二维码并转为字节数组(适合 Web 响应)
byte[] qrBytes = QRCode.from("Hello QRGen")
.withSize(200, 200)
.to(ImageType.PNG)
.stream()
.toByteArray();
System.out.println("二维码生成成功");
}
}
常用工具类封装(Spring Boot 场景)
在实际项目中,通常会将二维码生成逻辑封装为工具类,方便复用。
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.io.ByteArrayOutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class QRCodeUtil {
public static void generateQRCode(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.ERROR_CORRECTION, ErrorCorrectionLevel.H);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
Path path = Paths.get(filePath);
MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);
}
public static byte[] generateQRCodeBytes(String content, int width, int height) throws Exception {
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", outputStream);
return outputStream.toByteArray();
}
}
在 Spring Boot Controller 中直接返回二维码图片:
@GetMapping("/qrcode")
public ResponseEntity<byte[]> generateQRCode(@RequestParam String content) throws Exception {
byte[] qrBytes = QRCodeUtil.generateQRCodeBytes(content, 300, 300);
return ResponseEntity.ok()
.contentType(MediaType.IMAGE_PNG)
.body(qrBytes);
}













