当前位置: 首页 > news >正文

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);}
}

测试

访问返回对应的条码

相关文章:

Spring Boot 集成 zxing 生成条形码与二维码

前面我们知道了怎么通过 使用 zxing 生成二维码以及条形码&#xff0c; 由于我们现在都是 web 端的项目了&#xff0c;那么我们看下怎么使用 Spring Boot 集成然后返回给前端展示&#xff1a; 工程源码 对应的工程源码我放到了这里&#xff1a;github源码路径&#xff0c;点击…...

C# 编程基础:注释、变量、常量、数据类型和自定义类型

C# 是一种功能强大的面向对象编程语言&#xff0c;它提供了丰富的特性来帮助开发者编写清晰、高效的代码。本文将介绍C#中的注释、变量、常量、基本数据类型以及如何创建和使用自定义类型。 注释 注释用于解释代码的目的&#xff0c;它们不会被程序执行。 单行注释使用 //。…...

网络原理-三

一、连接管理 建立连接,断开连接 建立连接,TCP有连接的. 客户端执行 socket new Socket(SeverIP,severPort); -> 这个操作就是在建立连接. 上述只是调用socket api,真正建立连接的过程,实在操作系统内核完成的. 内核是怎样完成上述的 " 建立连接 "过程的…...

使用Ollama搭建一个免费的聊天机器人

0 概述 Ollama是一个能在本机运行大语言模型的软件&#xff0c;它提供命令行和API的交互方式&#xff0c;对于需要考虑数据隐私的情景&#xff0c;可以方便的使用Ollama部署大语言模型&#xff0c;并在此基础上开发RAG等应用&#xff0c;而无需调用OpenAI等开放API。Ollama基本…...

计算机网络之快重传和快恢复以及TCP连接与释放的握手

快重传和快恢复 快重传可以让发送方尽早得知丢失消息&#xff0c; 当发送消息M1,M2&#xff0c;M3,M4,M5后,假如消息M2丢失&#xff0c;那么按照算法会发送对M2报文前一个报文M1的重复确认&#xff08;M1正常接受到&#xff0c;已经发送了确认),然后之后收到M4,M5,也会发送两…...

vue 引用第三方库 Swpier轮播图

本文全程干货&#xff0c;没有废话 1.使用 npm 安装 swiper&#xff0c;使用 save 保存到 packjson 中 npm install --save swiper 2、把 swiper看成是第三方库或者是组件&#xff0c;然后按照&#xff0c;引用&#xff0c;挂载组件&#xff0c;使用组件三步法。 3、在 script…...

RabbitMQ-直连交换机(direct)使用方法

RabbitMQ-默认读、写方式介绍 RabbitMQ-发布/订阅模式 目录 1、概述 2、直连交换机 3、多重绑定 4、具体代码实现 4.1 生产者部分 4.2 消费者部分 5、运行代码 6、总结 1、概述 直连交换机&#xff0c;可以实现类似路由的功能&#xff0c;消息从交换机发送到哪个队列…...

942. 增减字符串匹配 - 力扣

1. 题目 由范围 [0,n] 内所有整数组成的 n 1 个整数的排列序列可以表示为长度为 n 的字符串 s &#xff0c;其中: 如果 perm[i] < perm[i 1] &#xff0c;那么 s[i] I 如果 perm[i] > perm[i 1] &#xff0c;那么 s[i] D 给定一个字符串 s &#xff0c;重构排列 pe…...

2024华为OD机试真题-机器人搬砖-C++(C卷D卷)

题目描述 机器人搬砖,一共有N堆砖存放在N个不同的仓库中,第i堆砖中有bricks[i]块砖头, 要求在8小时内搬完。机器人每小时能搬砖的数量取决于有多少能量格, 机器人一个小时中只能在一个仓库中搬砖,机器人的能量格每小时补充一次且能量格只在这一个小时有效,为使得机器人损…...

【DevOps】深入了解RabbitMQ:AMQP协议基础、消息队列工作原理和应用场景

目录 一、核心功能 二、优势 三、核心概念 四、工作原理 五、交换机类型 六、消息确认 七、持久性和可靠性 八、插件和扩展 九、集群和镜像队列 十、客户端库 十一、管理界面 十二、应用场景 RabbitMQ是一个基于AMQP协议的消息队列中间件&#xff0c;提供高可用、可…...

Mysql 技术实战篇

命令行 导出 - -h localhost&#xff1a;指定MySQL服务器的主机地址为本地主机。如果MySQL服务器在其他主机上&#xff0c;请将localhost替换为相应的主机地址。 - -u username&#xff1a;指定连接MySQL服务器的用户名。将username替换为您的有效用户名。 - -p&#xff1a;提…...

App自动化测试_Python+Appium使用手册

一、Appium的介绍 Appium是一款开源的自动化测试工具&#xff0c;支持模拟器和真机上的原生应用、混合应用、Web应用&#xff1b;基于Selenium二次开发&#xff0c;Appium支持Selenium WebDriver支持的所有语言&#xff08;java、 Object-C 、 JavaScript 、p hp、 Python等&am…...

k8s-部署对象存储minio

环境信息 minio版本 :最新 k8s 版本1.22 使用nfs作为共享存储 一.单节点安装包部署 脚本部署&#xff0c;一键部署&#xff0c;单节点应用于数据量小&#xff0c;一些缓存存储&#xff0c;比如gitlab-runner的产物数据&#xff0c;maven的打包依赖数据 #!/bin/bash# 步骤…...

go常用命令

创建一个module(逻辑概念) #The go mod init command initializes and writes a new go.mod file in the current directory, in effect creating #a new module rooted at the current directory. #specify a module path that serves as the module’s name. go mod initclon…...

【中年危机】程序猿自救指南

中年危机&#xff0c;一个听起来就充满挑战的词汇&#xff0c;它不仅仅是一个年龄的标记&#xff0c;更是一个个人成长和职业发展的转折点。 构架个人品牌&#xff1a; 学会打造IP个人品牌是职业生涯中的重要资产。在中年时期&#xff0c;你已经积累了丰富的经验和知识&#x…...

vueRouter路由总结

https://blog.csdn.net/qq_24767091/article/details/119326884...

算法工程师需要学习C++的哪些知识?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;以下是算法工程师需要学习的一些…...

CTF网络安全大赛简单的web抓包题目:HEADache

题目来源于&#xff1a;bugku 题目难度&#xff1a;简单 题目 描  述: > Wanna learn about some types of headache? > Lets dig right into it! 下面是题目源代码&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8"&…...

Qt Creator创建Python界面工程并打包为可执行exe文件

Qt Creator创建Python界面工程并打包为可执行exe文件_qtcreator创建python工程-CSDN博客...

基于单片机的步进电机控制系统的研究

摘要: 步进电机控制作为一种电机控制系统的重要模式,属于现代数字化控制的重要手段,其应用已经相当广泛。步进电机属于感应电机类,利用电子电路将直流电分为分时供电、多相时序供电控制电流,利用这种电流为电机供电,驱使电机工作。步进电机不能够在常规模式下使用,必须通过双环…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

WebRTC调研

WebRTC是什么&#xff0c;为什么&#xff0c;如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...