Spring Boot 集成 zxing 生成條形碼與二維碼

目錄

前面我們知道了怎么通過 使用 zxing 生成二維碼以及條形碼, 由于我們現在都是 web 端的項目了,那么我們看下怎么使用 Spring Boot 集成然后返回給前端展示:

工程源碼

對應的工程源碼我放到了這里:github源碼路徑,點擊這里查看

開始搭建

這里的整個過程就很簡單了,引入依賴包還是和之前一樣,另外搭建就兩部分:

  • controller 層
  • utils 層

引入依賴

<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>

生成二維碼

對應的 controller 代碼示例:

@RestController
@RequestMapping(path = "/qrcode")
public class QrCodeController {// http://localhost:8080/qrcode/create?content=www.baidu.com@GetMapping(path = "/createQrCode")public void createQrCode(HttpServletResponse response, @RequestParam("content") String content) {try {// 創建二維碼BufferedImage bufferedImage = QrCodeUtils.createImage(content, null, false);// 通過流的方式返回給前端responseImage(response, bufferedImage);} catch (Exception e) {e.printStackTrace();}}/*** 設置 可通過 postman 或者瀏覽器直接瀏覽** @param response      response* @param bufferedImage bufferedImage* @throws Exception e*/public void responseImage(HttpServletResponse response, BufferedImage bufferedImage) throws Exception {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ImageOutputStream imageOutput = ImageIO.createImageOutputStream(byteArrayOutputStream);ImageIO.write(bufferedImage, "jpeg", imageOutput);InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());OutputStream outputStream = response.getOutputStream();response.setContentType("image/jpeg");response.setCharacterEncoding("UTF-8");IOUtils.copy(inputStream, outputStream);outputStream.flush();}
}

對應的 工具類 QrCodeUtils

@Component
public class QrCodeUtils {private static final String CHARSET = "UTF-8";private static final String FORMAT_NAME = "JPG";/*** 二維碼尺寸*/private static final int QRCODE_SIZE = 300;/*** LOGO寬度*/private static final int WIDTH = 60;/*** LOGO高度*/private static final int HEIGHT = 60;/*** 創建二維碼圖片** @param content    內容* @param logoPath   logo* @param isCompress 是否壓縮Logo* @return 返回二維碼圖片* @throws WriterException e* @throws IOException     BufferedImage*/public static BufferedImage createImage(String content, String logoPath, boolean isCompress) throws WriterException, IOException {Hashtable<EncodeHintType, Object> hints = new Hashtable<>();// 設置二維碼的錯誤糾正級別 高hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 設置字符集hints.put(EncodeHintType.CHARACTER_SET, CHARSET);// 設置邊距hints.put(EncodeHintType.MARGIN, 1);// 生成二維碼BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);int width = bitMatrix.getWidth();int height = bitMatrix.getHeight();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) ? 0xFF000000 : 0xFFFFFFFF);}}if (logoPath == null || "".equals(logoPath)) {return image;}// 在二維碼中增加 logoQrCodeUtils.insertImage(image, logoPath, isCompress);return image;}/*** 添加Logo** @param source     二維碼圖片* @param logoPath   Logo* @param isCompress 是否壓縮Logo* @throws IOException void*/private static void insertImage(BufferedImage source, String logoPath, boolean isCompress) throws IOException {File file = new File(logoPath);if (!file.exists()) {return;}Image src = ImageIO.read(new File(logoPath));int width = src.getWidth(null);int height = src.getHeight(null);// 壓縮LOGOif (isCompress) {if (width > WIDTH) {width = WIDTH;}if (height > HEIGHT) {height = HEIGHT;}Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g = tag.getGraphics();// 繪制縮小后的圖g.drawImage(image, 0, 0, null);g.dispose();src = image;}// 插入LOGOGraphics2D graph = source.createGraphics();int x = (QRCODE_SIZE - width) / 2;int y = (QRCODE_SIZE - height) / 2;graph.drawImage(src, x, y, width, height, null);Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);graph.setStroke(new BasicStroke(3f));graph.draw(shape);graph.dispose();}/*** 生成帶Logo的二維碼** @param content    二維碼內容* @param logoPath   Logo* @param destPath   二維碼輸出路徑* @param isCompress 是否壓縮Logo* @throws Exception void*/public static void create(String content, String logoPath, String destPath, boolean isCompress) throws Exception {BufferedImage image = QrCodeUtils.createImage(content, logoPath, isCompress);mkdirs(destPath);ImageIO.write(image, FORMAT_NAME, new File(destPath));}/*** 生成不帶Logo的二維碼** @param content  二維碼內容* @param destPath 二維碼輸出路徑*/public static void create(String content, String destPath) throws Exception {QrCodeUtils.create(content, null, destPath, false);}/*** 生成帶Logo的二維碼,并輸出到指定的輸出流** @param content    二維碼內容* @param logoPath   Logo* @param output     輸出流* @param isCompress 是否壓縮Logo*/public static void create(String content, String logoPath, OutputStream output, boolean isCompress) throws Exception {BufferedImage image = QrCodeUtils.createImage(content, logoPath, isCompress);ImageIO.write(image, FORMAT_NAME, output);}/*** 生成不帶Logo的二維碼,并輸出到指定的輸出流** @param content 二維碼內容* @param output  輸出流* @throws Exception void*/public static void create(String content, OutputStream output) throws Exception {QrCodeUtils.create(content, null, output, false);}/*** 二維碼解析** @param file 二維碼* @return 返回解析得到的二維碼內容* @throws Exception String*/public static String parse(File file) throws Exception {BufferedImage image;image = ImageIO.read(file);if (image == null) {return null;}BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));Result result;Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();hints.put(DecodeHintType.CHARACTER_SET, CHARSET);result = new MultiFormatReader().decode(bitmap, hints);return result.getText();}/*** 二維碼解析** @param path 二維碼存儲位置* @return 返回解析得到的二維碼內容* @throws Exception String*/public static String parse(String path) throws Exception {return QrCodeUtils.parse(new File(path));}/*** 判斷路徑是否存在,如果不存在則創建** @param dir 目錄*/public static void mkdirs(String dir) {if (dir != null && !"".equals(dir)) {File file = new File(dir);if (!file.isDirectory()) {file.mkdirs();}}}
}

測試

生成的二維碼

生成條形碼

對應的 controller 代碼示例:

@RestController
@RequestMapping(path = "/barcode")
public class BarCodeController {@AutowiredBarCodeUtils barCodeUtils;// http://localhost:8080/barcode/createCode?content=987654132&barCodeWord=123456789@GetMapping(path = "/createCode")public void createQrCode(HttpServletResponse response, @RequestParam("content") String content, @RequestParam("content") String barCodeWord) {try {// 創建二維碼ByteArrayOutputStream byteArrayOutputStream = barCodeUtils.barcodeGenerator(content, barCodeWord);// 通過流的方式返回給前端InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());OutputStream outputStream = response.getOutputStream();response.setContentType("image/jpeg");response.setCharacterEncoding("UTF-8");IOUtils.copy(inputStream, outputStream);outputStream.flush();} catch (Exception e) {e.printStackTrace();}}}

對應的 工具類 BarCodeUtils

@Component
public class BarCodeUtils {/*** 條形碼寬度*/private static final int WIDTH = 200;/*** 條形碼高度*/private static final int HEIGHT = 50;/*** 生成條形碼,并加文字,以流的方式返回** @param content     內容* @param barCodeWord 二維碼的文字* @return ByteArrayOutputStream*/public ByteArrayOutputStream barcodeGenerator(String content, String barCodeWord) {// 設置條形碼參數HashMap<EncodeHintType, Object> hints = new HashMap<>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); // 設置糾錯級別為L(低)hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 設置字符編碼為UTF-8try {// 生成條形碼的矩陣BitMatrix matrix = new MultiFormatWriter().encode(content, BarcodeFormat.CODE_128, WIDTH, HEIGHT, hints);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(matrix);//底部加單號BufferedImage image = this.insertWords(bufferedImage, barCodeWord);if (Objects.isNull(image)) {throw new RuntimeException("條形碼加文字失敗");}ImageIO.write(image, "png", outputStream);return outputStream;} catch (WriterException | IOException e) {throw new RuntimeException("條形碼生成失敗", e);}}private BufferedImage insertWords(BufferedImage image, String words) {// 新的圖片,把帶logo的二維碼下面加上文字if (StringUtils.hasLength(words)) {BufferedImage outImage = new BufferedImage(WIDTH, HEIGHT + 20, BufferedImage.TYPE_INT_RGB);Graphics2D g2d = outImage.createGraphics();// 抗鋸齒this.setGraphics2D(g2d);// 設置白色this.setColorWhite(g2d);// 畫條形碼到新的面板g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);// 畫文字到新的面板Color color = new Color(0, 0, 0);g2d.setColor(color);// 字體、字型、字號g2d.setFont(new Font("微軟雅黑", Font.PLAIN, 16));//文字長度int strWidth = g2d.getFontMetrics().stringWidth(words);//總長度減去文字長度的一半  (居中顯示)int wordStartX = (WIDTH - strWidth) / 2;//height + (outImage.getHeight() - height) / 2 + 12int wordStartY = HEIGHT + 20;// time 文字長度// 畫文字g2d.drawString(words, wordStartX, wordStartY);g2d.dispose();outImage.flush();return outImage;}return null;}/*** 設置 Graphics2D 屬性  (抗鋸齒)** @param g2d Graphics2D提供對幾何形狀、坐標轉換、顏色管理和文本布局更為復雜的控制*/private void setGraphics2D(Graphics2D g2d) {// 消除畫圖鋸齒g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 消除文字鋸齒g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);g2d.setStroke(s);}private void setColorWhite(Graphics2D g2d) {g2d.setColor(Color.WHITE);//填充整個屏幕g2d.fillRect(0, 0, WIDTH, HEIGHT + 20);//設置筆刷g2d.setColor(Color.BLACK);}
}

測試

訪問返回對應的條碼

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21674.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21674.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21674.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

d2-crud-plus 使用小技巧(六)—— 表單下拉選擇 行樣式 溢出時顯示異常優化

問題 vue2 elementUI d2-crud-plus&#xff0c;數據類型為select時&#xff0c;行樣式顯示為tag樣式&#xff0c;但是如果選擇內容過長就會出現下面這種bug&#xff0c;顯然用戶體驗不夠友好。 期望 代碼 js export const crudOptions (vm) > {return {...columns:…

圖書管理系統(https://github.com/plusmultiply0/bookmanagesystem)

特意去github找了一個用flask框架的項目&#xff0c;一起來學習它吧 這個系統包括很多功能&#xff1a;用戶權限管理模塊&#xff08;管理員和普通用戶&#xff09;&#xff0c;注冊登錄模塊&#xff08;滑塊驗證碼功能&#xff09;&#xff0c;圖書有關信息模塊&#xff08;借…

毫米級精度3D人臉掃描設備,助推打造元宇宙虛擬分身

在元宇宙中&#xff0c;虛擬分身對應的是一個三維模型&#xff0c;數字化的過程則是三維重建過程&#xff0c;通過3D人臉掃描可以通過多相機同步采集人臉部&#xff0c;可快速、準確地重建出真人地臉部模型及貼圖&#xff0c;通過3D人臉掃描設備可快速重建出高逼真的虛擬分身。…

Linux系統下+jmeter分布式壓測

一.配置jdk&#xff08;Linux機都需配置同一個版本&#xff09; 下載Linux系統的jdk&#xff0c;下載地址&#xff1a;https://repo.huaweicloud.com/java/jdk/ 下載后的jdk文件上傳到 /opt目錄下 進入opt目錄&#xff0c;查看jdk文件 cd /opt ll 1.解壓文件 tar xzvf jd…

真國色碼上贊,科技流量雙劍合璧,商家獲客新紀元開啟

在數字化浪潮洶涌的今天,真國色研發團隊依托紅玉房網絡科技公司的雄厚實力,憑借科技領先的核心競爭力,推出了創新性的商家曝光引流工具——碼上贊。這款工具借助微信支付與視頻號已有功能,為實體商家提供了一種全新的引流獲客方式,實現了科技與商業的完美融合。 科技領先,流量黑…

CSS 空間轉換 動畫

目錄 1. 空間轉換1.1 視距 - perspective1.2 空間轉換 - 旋轉1.3 立體呈現 - transform-style1.4 空間轉換 - 縮放 2. 動畫 - animation2.1 動畫的基本用法2.1 animation 復合屬性2.2 animation 拆分屬性2.3 多組動畫 正文開始 1. 空間轉換 空間&#xff1a;是從坐標軸角度定義…

Paddle實現單目標檢測

單目標檢測 單目標檢測&#xff08;Single Object Detection&#xff09;是人工智能領域中的一個重要研究方向&#xff0c;旨在通過計算機視覺技術&#xff0c;識別和定位圖像中的特定目標物體。單目標檢測可以應用于各種場景&#xff0c;如智能監控、自動駕駛、醫療影像分析等…

短視頻矩陣系統搭建開發,ai智能剪輯系統,矩陣發布,一鍵管理多個賬戶

前言&#xff1a; 企業短視頻矩陣是企業通過搭建多個短視頻平臺賬號&#xff0c;形成一個多元化的內容傳播網絡。它旨在通過多平臺內容的同步傳播&#xff0c;實現企業品牌價值的最大化。短視頻矩陣包括抖音、快手、視頻號、小紅書、百家號等熱門短視頻平臺&#xff0c;其核心…

LeetCode 每日一題 數學篇 2520.統計能整除數字的位數

給你一個整數 num &#xff0c;返回 num 中能整除 num 的數位的數目。 如果滿足 nums % val 0 &#xff0c;則認為整數 val 可以整除 nums 。 int countDigits(int num) {int t num, res 0;while (t) {if (num % (t % 10) 0) {res 1;}t / 10;}return res; }解題思路&…

AT_abc348_c [ABC348C] Colorful Beans 題解

題目傳送門 解題思路 對于每種顏色的豆子&#xff0c;我們先找到美味度最小的那個&#xff0c;最后找出這些不同種類的豆子中美味度最大的即可。 那我們怎么找到第 i i i 種豆子中美味度最小的那個呢&#xff1f;這里給出兩種思路&#xff1a; 使用桶的思想標記。對于每一…

向日葵抓住哪三個要點,幫助企業構建專業技術支持服務體系?

售后技術支持是銷售行為的延續&#xff0c;在存量時代企業是否能夠提供優質專業的售后技術支持服務顯得尤為重要&#xff0c;它直接關系到企業產品在市場中的口碑&#xff0c;進而影響企業的發展命運。 因此&#xff0c;企業勢必需要重視技術支持服務體系的搭建&#xff0c;引…

JavaScript 事件循環竟還能這樣玩!

JavaScript 是一種單線程的編程語言&#xff0c;這意味著它一次只能執行一個任務。為了能夠處理異步操作&#xff0c;JavaScript 使用了一種稱為事件循環&#xff08;Event Loop&#xff09;的機制。 本文將深入探討事件循環的工作原理&#xff0c;并展示如何基于這一原理實現一…

git-commit-id-plugin maven插件筆記(git commitId跟蹤工具)

文章目錄 maven依賴git.properties 例子 代碼版本管理比較混亂&#xff0c;如何記錄呢? 一種是手動記錄&#xff0c;也可以實現&#xff0c;顯得有點笨。 也可以通過插件。 maven依賴 <plugin><groupId>pl.project13.maven</groupId><artifactId>git…

面試題系列:Python是什么?使用Python有什么好處?你對 PEP 8 有什么理解?

###面試題系列:Python是什么?使用Python有什么好處?你對 PEP 8 有什么理解? 1、Python是什么? Python是一門動態的(dynamic)且強類型(strong)語言 延伸: 1)靜態類型語言和動態類型語言的判別的標準 如果類型檢查發生在編譯階段(compile time),那么是靜態類型語言(s…

【數據分享】水體分布與五級水系和流域矢量數據+2000-2022年植被指數(NDVI)數據(全國/分省/分市)

1. 數據介紹 數據分為3個層次結構&#xff0c;分別為省、地級市、縣。其中&#xff0c;省級水體31個&#xff08;不包含香港、臺灣等&#xff09;&#xff0c; 地級市水體366個&#xff0c;縣級市水體2847個。每一個文件夾中都包含該省、地級市或者縣的水體矢量數據、行政邊界…

數學建模 —— 灰色系統(4)

目錄 什么是灰色系統&#xff1f; 一、灰色關聯分析 1.1 灰色關聯分析模型 1.2 灰色關聯因素和關聯算子集 1.2.1 灰色關聯因素 1.2.2 關聯算子集 1.3 灰色關聯公理與灰色關聯度 1.3.1 灰色關聯度 1.3.2 灰色關聯度計算步驟 1.4 廣義關聯度 1.4.1 灰色絕對關聯…

一文讀懂GDPR

GDPR將對人們的網絡足跡、使用的APP和服務如何保護或利用這些數據產生重大影響。 下面我們將對有關GDPR人們最關心的問題進行解讀。 GDPR是什么&#xff1f; 一般數據保護條例&#xff08;General Data Protection Regulation&#xff09;是一項全面的法律&#xff0c;賦予了…

風電Weibull+隨機出力!利用ARMA模型隨機生成風速+風速Weibull分布程序代碼!

前言 隨著能源問題日益突出&#xff0c;風力發電等以可再生能源為基礎的發電技術越來越受到關注。建立能夠正確反映實際風速特性的風速模型是研究風力發電系統控制策略以及并網運行特性的重要基礎叫。由于風速的隨機性和波動性&#xff0c;系統中的機械設備和電氣設備以及電網…

計算機網絡⑩ —— Linux系統如何收發網絡包

轉載于小林coding&#xff1a;https://www.xiaolincoding.com/network/1_base/how_os_deal_network_package.html 1. OSI七層模型 應用層&#xff0c;負責給應用程序提供統一的接口&#xff1b;表示層&#xff0c;負責把數據轉換成兼容另一個系統能識別的格式&#xff1b;會話…

深度剖析云邊對接技術:探索開放API接口的價值與意義

在當今數字化時代的浪潮中&#xff0c;云邊對接與開放API接口成為了塑造行業生態的重要驅動力。隨著云計算、物聯網和邊緣計算等技術的快速發展&#xff0c;傳統產業正在邁向數字化轉型的關鍵時刻。而在這個過程中&#xff0c;云邊對接技術以及開放的應用程序接口(API)扮演著舉…