当前位置: 首页 > 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博客...

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

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

BioPorto胰高血糖素样肽-1抗体(GLP-1)

丹麦BioPorto Diadnostics公司致力于提供世界领先的GLP-1抗体。基于结合GLP-1位点的不同&#xff0c;他们筛选出了不同的抗GLP-1抗体。有的抗体可以同时结合GLP-1的活性形式和非活性形式&#xff0c;有的专门结合生物活性形式的GLP-1。在开发和检测GLP-1相关治疗的过程中&#…...

Go 语言字符串及 strings 和 strconv 包

在 Go 语言编程中&#xff0c;字符串是最基本、最常用的数据类型之一。无论是处理用户输入、读取文件内容&#xff0c;还是生成输出&#xff0c;字符串操作无处不在。为了方便开发者对字符串进行各种操作&#xff0c;Go 语言提供了强大的 strings 包和 strconv 包。strings 包包…...

政府窗口服务第三方评估报告如何写

撰写政府窗口服务第三方评估报告需要结构清晰、内容详实&#xff0c;并包含对评估过程和结果的详细描述以及改进建议。以下是第三方评估机构民安智库&#xff08;第三方社会评估调研公司&#xff09;给出的一个政府窗口服务第三方评估报告简单的示例&#xff1a; 一、封面 报…...

若依前后端分离Spring Security新增手机号登录

备忘贴 转自&#xff1a;【若依RuoYi短信验证码登录】汇总_数据库_z_xiao_qiang-RuoYi 若依 配置Security: 按照Security的流程图可知&#xff0c;实现多种方式登录&#xff0c;只需要重写三个主要的组件&#xff0c;第一个用户认证处理过滤器&#xff0c;第二个用户认证tok…...

Oracle操作扩可变字符长度交易影响分析-较小

使用AI帮助学习知识 以下知识来至AI oracle 一张大表&#xff0c;对可变字符串长度从10扩到20位&#xff0c;oracle底层存储是否会发生变化&#xff0c;先锁表&#xff0c;更新表字典信息&#xff0c;然后会不会重新整理表&#xff0c;在有交易的情况下导致大量交易失效&#…...

全栈工程师需要具备哪些技能?

概论&#xff1a; 全栈工程师是一位能够从头到尾构建 Web 应用程序的工程师&#xff0c;能独立完成产品。技术包括前端部分、后端部分和应用程序所在的基础架构。他们在整个技术栈中工作&#xff0c;并了解其中的每个部分。从需求分析开始&#xff0c;到概要设计&#xff0c;详…...

用java实现客服聊天+网络爬虫下载音乐(java网络编程,io,多线程)

一 灵感&#xff1a; 在2022年的暑假&#xff0c;也就是我即将迈进高三的那个暑假&#xff0c;我并没有察觉自己应该要学习了&#xff0c;还是和过往的暑假一样玩着王者荣耀&#xff0c;凌晨2点睡觉&#xff0c;中午12点起床。我依稀记得这种状态一直持续到8月19。然而离开学还…...

基于springboot+vue的医院信息管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…...

乡村振兴与农业科技创新:加大农业科技研发投入,推动农业科技创新,促进农业现代化和美丽乡村建设

一、引言 在当代中国&#xff0c;乡村振兴已成为国家发展的重要战略之一。作为国民经济的基础&#xff0c;农业的发展直接关系到国家的稳定和人民的福祉。随着科技的不断进步&#xff0c;农业科技创新在推动农业现代化和美丽乡村建设中发挥着越来越重要的作用。本文旨在探讨如…...

Java 雪花算法:分布式唯一ID生成的魔法秘籍

欢迎来到本次博客的旅程&#xff0c;今天我们要揭开一个神秘算法的面纱&#xff0c;它就是在分布式系统中广受欢迎的——雪花算法&#xff08;Snowflake&#xff09;。这个算法不是用来预测雪花的形状&#xff0c;而是用来生成唯一的ID&#xff0c;保证在分布式系统中&#xff…...