用Java生成二維碼并附帶文字信息
更新時(shí)間:2021年04月29日 16:14:19 作者:超級(jí)蓄電池
這篇文章主要介紹了用Java生成二維碼并附帶文字信息,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
一、引入依賴
<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>
二、生成二維碼
2.1 創(chuàng)建實(shí)體類
代碼如下:
@Data
public class QRCodeUser {
private String userName;
private String userCode;
private String url; //二維碼跳轉(zhuǎn)的鏈接
}
2.2 創(chuàng)建QRCodeUtil
代碼如下:
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.*;
import java.util.List;
import javax.imageio.ImageIO;
import com.demo.demo.mapper.AssetsVo;
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 org.apache.commons.lang3.StringUtils;
public class QRCodeUtil {
//設(shè)置默認(rèn)參數(shù),可以根據(jù)需要進(jìn)行修改
private static final int QRCOLOR = 0xFF000000; // 默認(rèn)是黑色
private static final int BGWHITE = 0xFFFFFFFF; // 背景顏色
private static final int WIDTH = 180; // 二維碼寬
private static final int HEIGHT = 180; // 二維碼高
//設(shè)置高度常量
private static final int userNameHigh = 10;
private static final int userCodehigh = -20;
//設(shè)置字體寬度
private static final int strWidth = 130;
/**用于設(shè)置QR二維碼參數(shù)
* com.google.zxing.EncodeHintType:編碼提示類型,枚舉類型
* EncodeHintType.CHARACTER_SET:設(shè)置字符編碼類型
* EncodeHintType.ERROR_CORRECTION:設(shè)置誤差校正
* ErrorCorrectionLevel:誤差校正等級(jí),L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
* 不設(shè)置時(shí),默認(rèn)為 L 等級(jí),等級(jí)不一樣,生成的圖案不同,但掃描的結(jié)果是一樣的
* EncodeHintType.MARGIN:設(shè)置二維碼邊距,單位像素,值越小,二維碼距離四周越近
* */
private static Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>() {
private static final long serialVersionUID = 1L;
{
put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 設(shè)置QR二維碼的糾錯(cuò)級(jí)別(H為最高級(jí)別)具體級(jí)別信息
put(EncodeHintType.CHARACTER_SET, "utf-8");// 設(shè)置編碼方式
put(EncodeHintType.MARGIN, 0);
}
};
/**
* 生成二維碼和附帶字體參數(shù)
*/
private static BufferedImage createQr(QRCodeUser qrCodeUser, Font font) throws WriterException{
//設(shè)置二維碼旁邊的文字信息
String userName = "員工姓名:"+qrCodeUser.getUserName();
String userCode = "員工工號(hào):"+qrCodeUser.getUserName();
String qrurl = qrCodeUser.getUrl(); //這里以百度為例
/**
* MultiFormatWriter:多格式寫入,這是一個(gè)工廠類,里面重載了兩個(gè) encode 方法,用于寫入條形碼或二維碼
* encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
* contents:條形碼/二維碼內(nèi)容
* format:編碼類型,如 條形碼,二維碼 等
* width:碼的寬度
* height:碼的高度
* hints:碼內(nèi)容的編碼類型
* BarcodeFormat:枚舉該程序包已知的條形碼格式,即創(chuàng)建何種碼,如 1 維的條形碼,2 維的二維碼 等
* BitMatrix:位(比特)矩陣或叫2D矩陣,也就是需要的二維碼
*/
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
/**參數(shù)順序分別為:編碼內(nèi)容,編碼類型,生成圖片寬度,生成圖片高度,設(shè)置參數(shù)
* BitMatrix 的 get(int x, int y) 獲取比特矩陣內(nèi)容,指定位置有值,則返回true,將其設(shè)置為前景色,否則設(shè)置為背景色
* BufferedImage 的 setRGB(int x, int y, int rgb) 方法設(shè)置圖像像素
* x:像素位置的橫坐標(biāo),即列
* y:像素位置的縱坐標(biāo),即行
* rgb:像素的值,采用 16 進(jìn)制,如 0xFFFFFF 白色
*/
BitMatrix bm = multiFormatWriter.encode(qrurl, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);
//創(chuàng)建一個(gè)圖片緩沖區(qū)存放二維碼圖片
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
// 開始利用二維碼數(shù)據(jù)創(chuàng)建Bitmap圖片,分別設(shè)為黑(0xFFFFFFFF)白(0xFF000000)兩色
for (int x = 0; x < WIDTH; x++) {
for (int y = 0; y < HEIGHT; y++) {
image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
}
}
int height = image.getHeight();
// ------------------------------------------自定義文本描述-------------------------------------------------
if (StringUtils.isNotEmpty(qrCodeUser.getUserCode())) {
//在內(nèi)存創(chuàng)建圖片緩沖區(qū) 這里設(shè)置畫板的寬高和類型
BufferedImage outImage = new BufferedImage(600, 350, BufferedImage.TYPE_4BYTE_ABGR);
//創(chuàng)建畫布
Graphics2D outg = outImage.createGraphics();
// 在畫布上畫上二維碼 X軸Y軸,寬度高度
outg.drawImage(image, 10, 30, image.getWidth(), image.getHeight(), null);
// 畫文字到新的面板
outg.setColor(Color.BLACK);
// 字體、字型、字號(hào)
outg.setFont(font);
//獲取字體寬度
int userNameWidth = outg.getFontMetrics().stringWidth(userName);
int userCodeWidth = outg.getFontMetrics().stringWidth(userCode);
//drawString(文字信息、x軸、y軸)方法根據(jù)參數(shù)設(shè)置文字的坐標(biāo)軸 ,根據(jù)需要來進(jìn)行調(diào)整
outg.drawString(userName, 300 - userNameWidth / 2, height - userNameHigh); // 員工名字
outg.drawString(userCode, 300 - userCodeWidth / 2, height - userCodehigh); // 員工工號(hào)
// 例: outg.drawString(depatmentName, 65 - strWidth / 2, height + (outImage.getHeight() - height) / 2 - h3); 根據(jù)需求自行計(jì)算需要的寬高
outg.dispose();
outImage.flush();
image = outImage;
}
image.flush();
return image;
}
}
此時(shí)二維碼已經(jīng)可以生成
2.3 生成單條二維碼
/**
* @author: zyf
* @date: 2021/4/27
* Description: 生成單條二維碼附帶文字信息,導(dǎo)出到指定路徑
**/
public void drawLogoQRCode(QRCodeUser qrCodeUser) {
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream("D:"+ File.separator+"二維碼" + qrCodeUser.getUserCode() + ".png"); //保存路徑輸出流,將圖片輸出到指定路徑
Font fontChinese = new Font("黑體", Font.BOLD, 28);
BufferedImage image = QRCodeUtil.createQr(qrCodeUser,fontChinese);
boolean crateQRCode = ImageIO.write(image, "png", fileOutputStream);
}catch (WriterException | IOException e) {
log.error("二維碼寫入IO流異常",e);
}finally {
try {
if (null != fileOutputStream){
fileOutputStream.flush();
fileOutputStream.close();
}
}catch (IOException ioe){
log.error("二維碼關(guān)流異常",ioe);
}
}
}

2.4 批量生產(chǎn)二維碼
/**
* @author: zyf
* @date: 2021/4/27
* Description: 批量生產(chǎn)二維碼,導(dǎo)出到指定路徑
**/
public void drawLogoQRCode(List<QRCodeUser> qrCodeUserList) {
FileOutputStream fileOutputStream = null;
//咱們簡(jiǎn)單一點(diǎn),直接循環(huán)調(diào)用
try {
for(QRCodeUser qrCodeUser:qrCodeUserList){
fileOutputStream = new FileOutputStream("D:"+ File.separator+"二維碼" + qrCodeUser.getUserCode() + ".png"); //保存路徑輸出流,將圖片輸出到指定路徑
Font fontChinese = new Font("黑體", Font.BOLD, 28);
//返回的image就是二維碼圖片,可以根據(jù)需要進(jìn)行后續(xù)的處理,比如全都寫入指定文件夾進(jìn)行壓縮或者寫入PDF文件
BufferedImage image = QRCodeUtil.createQr(qrCodeUser,fontChinese);
//寫出到指定路徑
boolean crateQRCode = ImageIO.write(image, "png", fileOutputStream);
}
}catch (WriterException | IOException e) {
log.error("二維碼寫入IO流異常",e);
}finally {
try {
if (null != fileOutputStream){
fileOutputStream.flush();
fileOutputStream.close();
}
}catch (IOException ioe){
log.error("二維碼關(guān)流異常",ioe);
}
}
}
三、生成二維碼寫入PDF文件
3.1 引入依賴
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
3.2 替換工具類中的drawLogoQRCode方法
public static void drawLogoQRCode(OutputStream outputStream, QrCodeUser qrCodeUser) {
try {
Font fontChinese = new Font("黑體", Font.BOLD, 28);
BufferedImage image = createQr(qrCodeUser,fontChinese);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); //字節(jié)數(shù)組輸出流
boolean createQRCode = ImageIO.write(image, "png", byteArrayOutputStream);
if(!createQRCode){
log.error("二維碼寫入輸出流失敗");
}
/*生成pdf*/
Document document = new Document(PageSize.A4, 0, 0, 0, 0);
PdfWriter.getInstance(document, outputStream); //寫出pdf
document.open(); //打開文件
/*pdf寫入圖片*/
com.lowagie.text.Image image2 = com.lowagie.text.Image.getInstance(byteArrayOutputStream.toByteArray());
float documentWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();
float documentHeight = documentWidth / 300 * 80;// 重新設(shè)置寬高
image2.scaleAbsolute(documentWidth, documentHeight);// 重新設(shè)置寬高
document.add(image2);
document.close(); //關(guān)閉文件
byteArrayOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
3.3 PDF中文亂碼解決
Linux系統(tǒng)或者docker發(fā)布的項(xiàng)目中,不包含中文字體,會(huì)導(dǎo)致中文亂碼,所以PDF中的中文不能顯示 Linux系統(tǒng)中路徑 /usr/share/fonts/ 下是字體文件,復(fù)制windows本地的字體文件到這里面就可以,一般使用宋體 Docker系統(tǒng)中,需要配置 
到此這篇關(guān)于用Java生成二維碼并附帶文字信息的文章就介紹到這了,更多相關(guān)Java生成二維碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java操作Jenkins操作憑證(Credential)信息方式
這篇文章主要介紹了Java操作Jenkins操作憑證(Credential)信息方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-05-05
spring-boot-autoconfigure模塊用法詳解
autoconfigure就是自動(dòng)配置的意思,spring-boot通過spring-boot-autoconfigure體現(xiàn)了"約定優(yōu)于配置"這一設(shè)計(jì)原則,而spring-boot-autoconfigure主要用到了spring.factories和幾個(gè)常用的注解條件來實(shí)現(xiàn)自動(dòng)配置,思路很清晰也很簡(jiǎn)單,感興趣的朋友跟隨小編一起看看吧2022-11-11
Java中List轉(zhuǎn)Map List實(shí)現(xiàn)的幾種姿勢(shì)
本文主要介紹了Java中List轉(zhuǎn)Map List實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
java 中的instanceof用法詳解及instanceof是什么意思(推薦)
instanceof 是 Java 的保留關(guān)鍵字。它的作用是測(cè)試它左邊的對(duì)象是否是它右邊的類的實(shí)例,返回 boolean 的數(shù)據(jù)類型。接下來通過本文給大家介紹java 中的instanceof用法詳解及instanceof是什么意思,需要的朋友參考下吧2017-11-11
Java獲取當(dāng)前時(shí)間的時(shí)間戳(13位和10位)
本文主要介紹了Java獲取當(dāng)前時(shí)間的時(shí)間戳(13位和10位),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07

