1. 概述
条形码(Barcode)是一种通过视觉方式传递信息的技术,广泛应用于网页、邮件或可打印文档中。作为后端开发者,你可能在生成电子发票、物流单、会员卡或支付凭证时,都需要动态生成条码。
本文将带你掌握在 Java 中生成主流条形码和二维码的实战技巧。我们会:
✅ 解析常见条码类型的技术特点
✅ 对比主流 Java 条码库的优劣
✅ 实现基于 Spring Boot 的 RESTful 条码服务接口
✅ 踩坑提醒:校验位、文本显示、Maven 依赖等细节
目标是让你快速选出最适合项目的方案,避免掉进“生成出来扫不了”这种低级但致命的坑。
2. 条码类型详解
条码本质是将数字、文本等信息编码成机器可读的图形。按结构可分为两大类:
- 线性条码(Linear Barcode):一维码,横向排列
- 二维条码(2D Barcode):信息密度高,可存储更多内容
2.1 UPC 码(Universal Product Code)
主要用于北美地区,最常见的是一维码 UPC-A:
- ✅ 固定 12 位纯数字
- ✅ 前 6 位:厂商代码,中间 5 位:商品编号,最后 1 位:校验位
- ⚠️ 小包装可用 UPC-E(8 位)
2.2 EAN 码(European / International Article Number)
全球通用的商品条码标准,最常见的是 EAN-13:
- ✅ 13 位数字,结构与 UPC-A 类似
- ✅ 本质是 “0” + UPC-A(即 EAN-13 是 UPC-A 的超集)
- ✅ 广泛用于零售、图书(ISBN-13 实际就是 EAN-13 的一种)
2.3 Code 128
物流、仓储行业常用的一维高密度条码:
- ✅ 支持完整的 ASCII 128 个字符
- ✅ 变长编码,压缩率高
- ✅ 常用于快递单、资产标签
2.4 PDF417
一种“堆叠式”二维条码,由多个一维条码垂直堆叠而成:
- ✅ 兼容传统线性扫描仪
- ✅ 常见于登机牌、身份证、驾照、物流单据
- ✅ 使用 Reed-Solomon 纠错算法,轻微破损仍可读
- ❌ 体积较大,通常是 QR 码的 4 倍左右
2.5 QR 码(Quick Response Code)
目前最流行的二维条码,优势明显:
- ✅ 存储容量大(最多可存 7089 个数字或 4296 个字母)
- ✅ 支持四种编码模式:数字、字母、字节(二进制)、汉字(Kanji)
- ✅ 手机扫码识别快,容错能力强(L/M/Q/H 四级纠错)
- ✅ 可嵌入 Logo、变色、加文字说明,适合营销场景
3. Java 条码库选型对比
Java 生态中有多个成熟的条码生成库,以下是主流选项的横向对比:
库名 | 支持类型 | 特点 | 推荐场景 |
---|---|---|---|
Barbecue | 1D 为主 | API 极简,EAN/UPC 自动生成校验位 | 快速生成商品条码 |
Barcode4j | 1D + 2D(PDF417) | 功能全,支持 SVG 输出 | 生成 PDF417 登机牌 |
ZXing(核心库) | 全格式(含 QR) | Google 出品,社区活跃,扫码+生成一体 | 需要扫码或生成 QR 码 |
QRGen | 仅 QR | 基于 ZXing 封装,API 更友好 | 简单生成二维码 |
QR Code Generator(Nayuki) | 仅 QR | 代码清晰,纠错精准 | 对 QR 码正确性要求极高 |
Okapi Barcode | 超 50 种 | 纯 Java,持续维护 | 需要支持冷门条码 |
✅ 结论:
- 生成 QR 码 → 优先选 ZXing 或 QRGen
- 生成 EAN/UPC → Barbecue 最省心
- 需要 PDF417 → Barcode4j 或 ZXing
4. 生成线性条码(1D)
4.1 使用 Barbecue 库
特点:API 简单粗暴,自动处理校验位,适合快速上手。
添加依赖:
<dependency>
<groupId>net.sourceforge.barbecue</groupId>
<artifactId>barbecue</artifactId>
<version>1.5-beta1</version>
</dependency>
生成 EAN-13 示例:
public static BufferedImage generateEAN13BarcodeImage(String barcodeText) throws Exception {
Barcode barcode = BarcodeFactory.createEAN13(barcodeText);
barcode.setFont(new Font("Arial", Font.PLAIN, 12)); // 可选:设置下方文字字体
return BarcodeImageHandler.getImage(barcode);
}
⚠️ 注意:
barcodeText
传 12 位即可,第 13 位(校验位)会自动计算- 默认显示下方文本,无需额外配置
4.2 使用 Barcode4j 库
特点:支持更多格式,但 API 稍复杂。
添加依赖:
<dependency>
<groupId>net.sf.barcode4j</groupId>
<artifactId>barcode4j</artifactId>
<version>2.1</version>
</dependency>
生成 EAN-13 示例:
public static BufferedImage generateEAN13BarcodeImage(String barcodeText) {
EAN13Bean barcodeGenerator = new EAN13Bean();
BitmapCanvasProvider canvas =
new BitmapCanvasProvider(160, BufferedImage.TYPE_BYTE_BINARY, false, 0);
barcodeGenerator.generateBarcode(canvas, barcodeText);
return canvas.getBufferedImage();
}
参数说明:
160
:DPI(分辨率)TYPE_BYTE_BINARY
:黑白图像false
:关闭抗锯齿0
:旋转角度
✅ 文本默认显示在条码下方,无需额外设置。
4.3 使用 ZXing 库
特点:功能强大,但需手动处理细节。
添加依赖:
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
生成 EAN-13 示例:
public static BufferedImage generateEAN13BarcodeImage(String barcodeText) throws Exception {
EAN13Writer barcodeWriter = new EAN13Writer();
BitMatrix bitMatrix = barcodeWriter.encode(barcodeText, BarcodeFormat.EAN_13, 300, 150);
return MatrixToImageWriter.toBufferedImage(bitMatrix);
}
⚠️ 踩坑提醒:
- 必须传 13 位完整编码,包括校验位(ZXing 不自动计算)
- 生成的图像不带下方文本,需自行叠加
- 尺寸需明确指定(宽度、高度)
5. 生成二维条码(2D)
5.1 使用 ZXing 生成 QR 码
ZXing 是 Java 中生成 QR 码的事实标准。
public static BufferedImage generateQRCodeImage(String barcodeText) throws Exception {
QRCodeWriter barcodeWriter = new QRCodeWriter();
BitMatrix bitMatrix =
barcodeWriter.encode(barcodeText, BarcodeFormat.QR_CODE, 200, 200);
return MatrixToImageWriter.toBufferedImage(bitMatrix);
}
✅ 支持中文、URL、JSON 等任意文本
✅ 纠错级别可通过 EncodeHintType.ERROR_CORRECTION
设置(L/M/Q/H)
5.2 使用 QRGen 库
QRGen 是 ZXing 的封装,API 更简洁,但已不在 Maven Central,需从 JitPack 引入。
添加仓库和依赖:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.kenglxn.qrgen</groupId>
<artifactId>javase</artifactId>
<version>2.6.0</version>
</dependency>
生成 QR 码:
public static BufferedImage generateQRCodeImage(String barcodeText) throws Exception {
ByteArrayOutputStream stream = QRCode
.from(barcodeText)
.withSize(250, 250)
.stream();
ByteArrayInputStream bis = new ByteArrayInputStream(stream.toByteArray());
return ImageIO.read(bis);
}
✅ Builder 风格 API,链式调用,清爽
✅ 支持直接输出到文件或流
5.3 使用 QR Code Generator(Nayuki)
追求极致正确性和清晰代码结构时可选。
添加依赖:
<dependency>
<groupId>io.nayuki</groupId>
<artifactId>qrcodegen</artifactId>
<version>1.8.0</version>
</dependency>
生成 QR 码:
public static BufferedImage generateQrcode(String barcodeText) throws Exception {
QrCode qrCode = QrCode.encodeText(barcodeText, QrCode.Ecc.MEDIUM);
return toImage(qrCode, 4, 10); // scale=4, border=10
}
自定义图像渲染方法:
public static BufferedImage toImage(QrCode qr, int scale, int border, int lightColor, int darkColor) {
Objects.requireNonNull(qr);
if (scale <= 0 || border < 0) {
throw new IllegalArgumentException("Value out of range");
}
int size = (qr.size + border * 2) * scale;
BufferedImage result = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < result.getHeight(); y++) {
for (int x = 0; x < result.getWidth(); x++) {
boolean color = qr.getModule(x / scale - border, y / scale - border);
result.setRGB(x, y, color ? darkColor : lightColor);
}
}
return result;
}
✅ 可精确控制颜色、边框、缩放
✅ 适合定制化需求(如彩色 QR 码)
5.4 使用 Okapi Barcode 生成 Code 128
Okapi 支持超过 50 种条码格式,适合复杂场景。
添加依赖:
<dependency>
<groupId>uk.org.okapibarcode</groupId>
<artifactId>okapibarcode</artifactId>
<version>0.4.6</version>
</dependency>
生成 Code 128 示例:
public static BufferedImage generateOkapiBarcode(String barcodeText) throws Exception {
Code128 barcode = new Code128();
barcode.setFontName("Monospaced");
barcode.setFontSize(16);
barcode.setModuleWidth(2);
barcode.setBarHeight(50);
barcode.setHumanReadableLocation(HumanReadableLocation.BOTTOM);
barcode.setContent(barcodeText);
int width = barcode.getWidth();
int height = barcode.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2d = image.createGraphics();
Java2DRenderer renderer = new Java2DRenderer(g2d, 1, Color.WHITE, Color.BLACK);
renderer.render(barcode);
g2d.dispose();
return image;
}
✅ 配置项丰富,控制精细
✅ 适合生成工业级条码标签
6. 生成带文字的 QR 码
有时需要在 QR 码上下添加说明文字,提升用户体验(比如“扫码访问官网”)。
ZXing 原生不支持,需手动合成图像。
public static BufferedImage createQRwithText(String data, String topText, String bottomText)
throws WriterException, IOException {
QRCodeWriter barcodeWriter = new QRCodeWriter();
BitMatrix matrix = barcodeWriter.encode(data, BarcodeFormat.QR_CODE, 200, 200);
return modifiedQRCode(matrix, topText, bottomText);
}
图像合成核心逻辑:
private static BufferedImage modifiedQRCode(BitMatrix matrix, String topText, String bottomText) {
int matrixWidth = matrix.getWidth();
int matrixHeight = matrix.getHeight();
// 1. 先绘制原始 QR 码
BufferedImage image = new BufferedImage(matrixWidth, matrixHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = image.createGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, matrixWidth, matrixHeight);
graphics.setColor(Color.BLACK);
for (int i = 0; i < matrixWidth; i++) {
for (int j = 0; j < matrixHeight; j++) {
if (matrix.get(i, j)) {
graphics.fillRect(i, j, 1, 1);
}
}
}
graphics.dispose();
// 2. 计算最终图像尺寸(含文字区域)
Font font = new Font("SansSerif", Font.PLAIN, 14);
graphics = image.createGraphics();
graphics.setFont(font);
FontMetrics fontMetrics = graphics.getFontMetrics();
int topTextWidth = fontMetrics.stringWidth(topText);
int bottomTextWidth = fontMetrics.stringWidth(bottomText);
int textHeight = fontMetrics.getHeight();
int ascent = fontMetrics.getAscent();
int finalWidth = Math.max(matrixWidth, Math.max(topTextWidth, bottomTextWidth)) + 10;
int finalHeight = matrixHeight + textHeight * 2 + 10;
// 3. 创建最终图像并绘制
BufferedImage finalImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D finalGraphics = finalImage.createGraphics();
finalGraphics.setColor(Color.WHITE);
finalGraphics.fillRect(0, 0, finalWidth, finalHeight);
finalGraphics.setColor(Color.BLACK);
finalGraphics.setFont(font);
// 居中绘制 QR 码
int qrX = (finalWidth - matrixWidth) / 2;
int qrY = textHeight + 5;
finalGraphics.drawImage(image, qrX, qrY, null);
// 绘制上下文字
finalGraphics.drawString(topText, (finalWidth - topTextWidth) / 2, ascent + 5);
finalGraphics.drawString(bottomText, (finalWidth - bottomTextWidth) / 2, finalHeight - 5);
finalGraphics.dispose();
return finalImage;
}
✅ 效果:文字居中,QR 码自动对齐
✅ 可扩展支持 Logo 叠加、背景色设置等
7. 构建 REST 接口服务
将条码生成功能暴露为 HTTP 接口,便于前端或移动端调用。
基础配置
Spring Boot 需注册 BufferedImage
的消息转换器:
@Bean
public HttpMessageConverter<BufferedImage> createImageHttpMessageConverter() {
return new BufferedImageHttpMessageConverter();
}
控制器示例
@RestController
@RequestMapping("/barcodes")
public class BarcodesController {
@GetMapping(value = "/barbecue/ean13/{barcode}", produces = MediaType.IMAGE_PNG_VALUE)
public ResponseEntity<BufferedImage> barbecueEAN13Barcode(@PathVariable String barcode) throws Exception {
BufferedImage image = BarbecueBarcodeGenerator.generateEAN13BarcodeImage(barcode);
return ResponseEntity.ok(image);
}
}
接口测试示例
7.1 生成 UPC-A 条码
GET http://localhost:8080/barcodes/barbecue/upca/12345678901
7.2 生成 EAN-13 条码
GET http://localhost:8080/barcodes/barbecue/ean13/012345678901
7.3 生成 Code128 条码(POST)
POST http://localhost:8080/barcodes/barbecue/code128
Content-Type: text/plain
长文本内容,如:Lorem ipsum dolor sit amet...
7.4 生成 PDF417 条码
POST http://localhost:8080/barcodes/barbecue/pdf417
Content-Type: text/plain
长文本内容...
7.5 生成 QR 码
POST http://localhost:8080/barcodes/zxing/qrcode
Content-Type: text/plain
任意长文本、URL、JSON...
7.6 生成带文字的 QR 码
GET http://localhost:8080/barcodes/zxing/qrcode/text?barcode=https://example.com&toptext=访问官网&bottomtext=扫码立即体验
8. 总结
本文系统梳理了 Java 条码生成的核心技术方案:
选型建议:
- 商品条码(EAN/UPC)→ Barbecue(省心)
- 二维码(QR Code)→ ZXing 或 QRGen(主流)
- PDF417 → Barcode4j
- 高定制需求 → Okapi 或 Nayuki
关键踩坑点:
- 校验位是否自动生成(Barbecue ✅,ZXing ❌)
- 文本是否默认显示
- Maven 依赖是否可用(QRGen 需 JitPack)
生产建议:
- 封装统一的
BarcodeService
- 接口支持多种格式、尺寸、纠错级别
- 增加缓存避免重复生成
- 封装统一的
所有示例代码已托管至 GitHub:https://github.com/your-repo/barcode-demo
实际项目中可根据业务需求灵活组合使用。