java生成二维码工具类
POM依赖
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
工具类代码
package com.common.util;
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 com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URLDecoder;
import java.nio.file.Paths;
import java.util.*;
import java.util.List;
/**
* @program: dict-uomp_git
* @description: 二维码工具类
* @author: huang wei
* @create: 2025-12-11 17:11
*/
@Slf4j
public class QrCodeUtil {
/**
* 默认编码方式
*/
private static final String DEFAULT_CHARSET = "UTF-8";
/**
* 默认二维码图片格式
*/
private static final String DEFAULT_SUBFIX = "png";
/**
* 生成二维码默认宽度
*/
private static final int DEFAULT_WIDTH = 260;
/**
* 生成二维码默认高度
*/
private static final int DEFAULT_HEIGHT = 300;
/**
* 默认二维码中间log宽度
*/
private static final int DEFAULT_LOG_WIDTH = 50;
/**
* 默认二维码中间log高度
*/
private static final int DEFAULT_LOG_HEIGHT = 50;
/**
* log默认路径
*/
private static final String DEFAULT_LOG_PATH = QrCodeUtil.class.getClassLoader().getResource("uomp-logo.png").getPath();
/**
* @Description: 获取base64格式简单二维码
* @author: hw
* @date: 2025/12/12 10:20
*/
public static String getQRCode(String data) {
BufferedImage bufferedImage = generateQRCode(data,DEFAULT_WIDTH,DEFAULT_HEIGHT);
return trans2Base64(bufferedImage);
}
/**
* @Description: 获取base64格式二维码,带LOGO图标
* @author: hw
* @date: 2025/12/12 10:20
*/
public static String getQRCodeWithLogo(String data) {
BufferedImage bufferedImage = generateQRCode(data,DEFAULT_WIDTH,DEFAULT_HEIGHT);
generateQRCodeWithLogo(bufferedImage, DEFAULT_WIDTH, DEFAULT_HEIGHT);
return trans2Base64(bufferedImage);
}
/**
* @Description: 获取base64格式二维码,带底部文字
* @author: hw
* @date: 2025/12/12 10:20
*/
public static String getQRCodeWithText(String data, String text) {
BufferedImage bufferedImage = generateQRCode(data,DEFAULT_WIDTH,DEFAULT_HEIGHT);
generateQRCodeWithText(bufferedImage, DEFAULT_WIDTH, DEFAULT_HEIGHT, text);
return trans2Base64(bufferedImage);
}
/**
* @Description: 获取base64格式二维码,带LOGO图标+底部文字
* @author: hw
* @date: 2025/12/12 10:21
*/
public static String getQRCodeWithLogoAndText(String data, String text) {
BufferedImage bufferedImage = generateQRCode(data,DEFAULT_WIDTH,DEFAULT_HEIGHT);
generateQRCodeWithLogo(bufferedImage, DEFAULT_WIDTH, DEFAULT_HEIGHT);
generateQRCodeWithText(bufferedImage, DEFAULT_WIDTH, DEFAULT_HEIGHT, text);
return trans2Base64(bufferedImage);
}
/**
* @Description: 生成base64格式的二维码
* @Param:
* @return:
* @author: hw
* @date: 2025/12/12 10:06
*/
private static String trans2Base64(BufferedImage bufferedImage) {
if (bufferedImage == null) {
return null;
}
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, DEFAULT_SUBFIX, stream);
String base64 = new String(Base64.getEncoder().encode(stream.toByteArray()));
stream.close();
return "data:image/"+DEFAULT_SUBFIX+";base64," + base64;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 生成简单二维码BufferedImage对象
* @param data 二维码内容(文本/URL/WiFi配置等)
* @param width 二维码宽度(像素)
* @param height 二维码高度(像素)
* @return
*/
private static BufferedImage generateQRCode(String data, int width, int height) {
if (StringUtils.isEmpty(data)) {
return null;
}
try {
//1.设置二维码生成参数
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, DEFAULT_CHARSET);
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.MARGIN, 1);
//2.生成二维码矩阵数据
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.QR_CODE, width, height, hints);
//3.转换为图像对象
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, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
}
}
return image;
} catch (Exception e) {
log.error("生成简单二维码BufferedImage对象异常", e);
}
return null;
}
/**
* @Description: 二维码BufferedImage添加logo图片
* @Param:
* @return:
* @author: hw
* @date: 2025/12/12 16:07
*/
private static void generateQRCodeWithLogo(BufferedImage bufferedImage, Integer width, Integer height){
try {
// LOGO处理
String logoPath = URLDecoder.decode(DEFAULT_LOG_PATH, "UTF-8");
File file = new File(logoPath);
if (file.exists()) {
Image logoImage = ImageIO.read(file);
Image image = logoImage.getScaledInstance(DEFAULT_LOG_WIDTH, DEFAULT_LOG_HEIGHT, Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(DEFAULT_LOG_WIDTH, DEFAULT_LOG_HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
// 绘制缩小后的图
g.drawImage(image, 0, 0, null);
g.dispose();
// 插入LOGO
int x = (width - DEFAULT_LOG_WIDTH) / 2;
int y = (height - DEFAULT_LOG_HEIGHT) / 2;
Graphics2D graph = bufferedImage.createGraphics();
graph.drawImage(image, x, y, DEFAULT_LOG_WIDTH, DEFAULT_LOG_HEIGHT, null);
Shape shape = new RoundRectangle2D.Float(x, y, DEFAULT_LOG_WIDTH, DEFAULT_LOG_HEIGHT, 6, 6);
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
}
} catch (Exception e) {
log.error("二维码BufferedImage添加logo异常", e);
}
}
/**
* @Description: 二维码BufferedImage添加底部文字
* @Param:
* @return:
* @author: hw
* @date: 2025/12/12 16:10
*/
private static void generateQRCodeWithText(BufferedImage bufferedImage, Integer width, Integer height, String text){
try {
// 插入底部文本
if (!StringUtils.isEmpty(text)) {
int fontStyle = 1;
int fontSize = 14;
// 计算文字开始的位置(居中显示)
// x开始的位置:(图片宽度-字体大小*字的个数)/2
int startX = (width - (fontSize * text.length())) / 2;
// y开始的位置:图片高度-(图片高度-图片宽度)/2
// int startY = height - (height - width)/2;
int startY = height - fontSize;
Graphics2D graph = bufferedImage.createGraphics();
graph.setColor(Color.BLUE);
// 字体风格与字体大小
graph.setFont(new Font(null, fontStyle, fontSize));
graph.drawString(text, startX, startY);
graph.dispose();
}
} catch (Exception e) {
log.error("二维码BufferedImage添加底部文字异常", e);
}
}
/**
* @Description: 批量生成二维码
* @Param: batchData 底部文字(text):转成二维码的文本(data)
* @return:
* @author: hw
* @date: 2025/12/11 17:18
*/
private static List<BufferedImage> batchGenerateQRCodeWithLogoAndText(Map<String,String> batchData) {
return batchGenerateQRCodeWithLogoAndText(batchData, DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
private static List<BufferedImage> batchGenerateQRCodeWithLogoAndText(Map<String,String> batchData, int width, int height) {
//1.设置二维码生成参数
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.ERROR_CORRECTION, com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.M);
hints.put(EncodeHintType.MARGIN, 1);
List<BufferedImage> bufferedImageList = new ArrayList<>();
for (String text : batchData.keySet()){
try {
//2.生成二维码矩阵数据
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix bitMatrix = writer.encode(batchData.get(text), BarcodeFormat.QR_CODE, width, height, hints);
//3.转换为图像对象
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, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
}
}
// 4.写入logo
generateQRCodeWithLogo(image, width, height);
// 5.写入文本
generateQRCodeWithText(image, width, height, text);
bufferedImageList.add(image);
} catch (Exception e) {
log.error("生成二维码BufferedImage异常: {}", text, e);
}
}
return bufferedImageList;
}
/**
* @Description: 图片导出为PDF
* @Param:
* @return:
* @author: hw
* @date: 2025/12/15 9:00
*/
public static void saveImagesToPDF(List<BufferedImage> bufferedImageList, String outputPath){
Document document = new Document();
try {
PdfWriter.getInstance(document, new FileOutputStream(outputPath));
document.open();
for (BufferedImage bufferedImage : bufferedImageList) {
// 创建PDF图片对象
try {
com.itextpdf.text.Image pdfImage = com.itextpdf.text.Image.getInstance(bufferedImage, null);
pdfImage.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER);
document.add(pdfImage);
}catch (Exception e){
log.error("创建PDF图片对象失败", e);
}
}
} catch (Exception e){
log.error("图片导出为PDF异常", e);
} finally {
document.close();
}
}
public static void main(String[] args) {
// 生成二维码base64数据
// String data = "{\"msg\": \"d7572de94b9debc5b4d605697669c4c9\",\"keyNum\": 1,\"algType\": \"SM4\"}";
// String text = "校园安防-研发测试-大法师-003";
// System.out.println(getQRCode(data));
// System.out.println(getQRCodeWithLogo(data));
// System.out.println(getQRCodeWithText(data, text));
// System.out.println(getQRCodeWithLogoAndText(data, text));
// 批量生成二维码并导出为pdf
String path = Paths.get("").toAbsolutePath().toString();
String outputPath = path+File.separator+"output.pdf"; // PDF文件的输出路径
Map<String,String> map = new HashMap<>();
map.put("校园安防-研发测试-大法师-001","{\"msg\": \"d7572de94b9debc5b4d605697669c4c9\",\"keyNum\": 1,\"algType\": \"SM4\"}");
map.put("校园安防-研发测试-大法师-002","{\"msg\": \"d7572de94b9debc5b4d605697669c4c9\",\"keyNum\": 1,\"algType\": \"SM4\"}");
map.put("校园安防-研发测试-大法师-003","{\"msg\": \"d7572de94b9debc5b4d605697669c4c9\",\"keyNum\": 1,\"algType\": \"SM4\"}");
List<BufferedImage> images = batchGenerateQRCodeWithLogoAndText(map);
saveImagesToPDF(images, outputPath);
System.out.println("PDF文件已保存至:" + outputPath);
}
}
==========================================================================================
我希望每一篇文章的背后,都能看到自己对于技术、对于生活的态度。
我相信乔布斯说的,只有那些疯狂到认为自己可以改变世界的人才能真正地改变世界。面对压力,我可以挑灯夜战、不眠不休;面对困难,我愿意迎难而上、永不退缩。
其实我想说的是,我只是一个程序员,这就是我现在纯粹人生的全部。
==========================================================================================

浙公网安备 33010602011771号