日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

springboot+java生成二维码图片

發布時間:2024/1/18 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot+java生成二维码图片 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

接下來將從IDEA創建springboot項目到生成效果圖詳細地為大家展示二維碼的制作過程

1、首先是創建springboot項目





上面的圖有紅色標記的地方需要填寫的,比如項目存放的路徑,包名等,其他的一路next就可以了。

2、導入相關依賴

<!--這兩個依賴創建springboot項目會自動加載進來--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!--Swagger2一款RESTful接口的文檔在線自動生成、功能測試功能框架--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.8.0</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.8.0</version></dependency><!-- 條形碼、二維碼生成 --><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>

3、項目結構

4、具體的類和完整代碼

package com.example.demo.controller;import com.example.demo.service.QrCodeService; import com.example.demo.util.ResultBean; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; /*** @author ll* @version 1.0* @date 2019-11-25 15:13*/ @RestController @RequestMapping("/qrCode/") @Slf4j public class QrCodeController {@Autowiredprivate QrCodeService qrCodeService;/*** 生成帶logo的二維碼圖片* @return*/@RequestMapping(value = "createQrCodeImage", method = RequestMethod.GET)@ResponseBodypublic ResultBean createQrCodeImage(String contents) {try {return qrCodeService.createQrCodeImage(contents);} catch (Exception e) {log.error("創建二維碼圖片異常" + e.getMessage());e.printStackTrace();return ResultBean.error("創建二維碼圖片異常");}} } package com.example.demo.service;import com.example.demo.date20191125.QRCodeUtil; import com.example.demo.util.FileUtil; import com.example.demo.util.ResultBean; import org.springframework.stereotype.Service;import java.io.IOException; /*** @author ll* @version 1.0* @date 2019-11-25 15:16*/ @Service public class QrCodeService {/*** 創建二維碼* @return*/public ResultBean createQrCodeImage(String contents) throws IOException {String pathImages = FileUtil.pathFormat(FileUtil.getPathImages());try {QRCodeUtil.encode(contents, pathImages + "/hashiqi_1.jpg", "d:/EWM", true);} catch (Exception e) {e.printStackTrace();e.getMessage();}return ResultBean.ok();} } package com.example.demo.util;import com.sun.org.apache.xpath.internal.operations.And;import java.io.File; import java.io.IOException;/*** @author ll* @date 2019-11-25 16:55*/ public class FileUtil {/*** 獲取images下面的路徑* @return*/public static String getPathImages() throws IOException {// 獲取static下面images的路徑File directory = new File("src/main/resources/static/images");String filePath = directory.getCanonicalPath();return filePath;}/*** 格式化路徑* @param str* @return*/public static String pathFormat(String str) {// 將路徑的\\轉化為// 否則后續二維碼中間log圖片路徑會找不到String result = str.replaceAll("\\\\", "/");return result;}public static void main(String[] args) {try {System.err.println(getPathImages());} catch (IOException e) {e.printStackTrace();}} } package com.example.demo.util;import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty;import java.util.HashMap; import java.util.Map;/*** @author ll* @version 1.0* @date 2019-12-03 15:20*/ @ApiModel public class ResultBean<T> {@ApiModelProperty(value = "返回信息狀態碼")private int code = 101;@ApiModelProperty(value = "返回信息")private String msg = "";@ApiModelProperty(value = "數據")private Map<String, T> data = new HashMap<String, T>();public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Map<String, T> getData() {return data;}public void setData(Map<String, T> data) {this.data = data;}public static ResultBean ok() {return new ResultBean() {{setMsg("操作成功");setCode(100);}};}public static ResultBean ok(Map<String, Object> data) {return new ResultBean() {{setMsg("操作成功");setCode(100);setData((data == null) ? new HashMap<String, Object>() : data);}};}public static ResultBean okForStringMap(Map<String, String> data) {return new ResultBean() {{setMsg("操作成功");setCode(100);setData((data == null) ? new HashMap<String, String>() : data);}};}public static ResultBean error() {return new ResultBean() {{setCode(101);setMsg("未知的錯誤");}};}public static ResultBean error(int errorCode, String msg) {return new ResultBean() {{setCode(errorCode);setMsg(msg);}};}public static ResultBean error(String msg) {return new ResultBean() {{setCode(101);setMsg(msg);}};} }

下面兩個類是參考了https://blog.csdn.net/jam_fanatic/article/details/82818857

package com.example.demo.date20191125;import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import com.google.zxing.LuminanceSource;/*** LuminanceSource這類層次結構的目的是不同的位圖實現跨平臺為請求獲得灰度亮度值的標準接口。該接口只提供了抽象方法,* 因此可以生成和旋轉創建副本。這是為了確保一個讀者不修改原來的亮度源,并讓它在一個未知的狀態,在鏈中的其他讀者。* https://zxing.github.io/zxing/apidocs/com/google/zxing/LuminanceSource.html* @author ljheee**/ public class BufferedImageLuminanceSource extends LuminanceSource {private final BufferedImage image;private final int left;private final int top;public BufferedImageLuminanceSource(BufferedImage image) {this(image, 0, 0, image.getWidth(), image.getHeight());}/*** 構造方法* @param image* @param left* @param top* @param width* @param height*/public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) {super(width, height);int sourceWidth = image.getWidth();int sourceHeight = image.getHeight();if (left + width > sourceWidth || top + height > sourceHeight) {throw new IllegalArgumentException("Crop rectangle does not fit within image data.");}for (int y = top; y < top + height; y++) {for (int x = left; x < left + width; x++) {if ((image.getRGB(x, y) & 0xFF000000) == 0) {// = whiteimage.setRGB(x, y, 0xFFFFFFFF);}}}this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);this.image.getGraphics().drawImage(image, 0, 0, null);this.left = left;this.top = top;}/*** 從底層平臺的位圖提取一行(only one row)的亮度數據值* @param y* @param row* @return*/@Overridepublic byte[] getRow(int y, byte[] row) {int width = getWidth();if (row == null || row.length < width) {row = new byte[width];}if (y < 0 || y >= getHeight()) {throw new IllegalArgumentException("Requested row is outside the image: " + y);}image.getRaster().getDataElements(left, top + y, width, 1, row);return row;}/*** 從底層平臺的位圖提取亮度數據值* @return*/@Overridepublic byte[] getMatrix() {int height = getHeight();int width = getWidth();int area = width * height;byte[] matrix = new byte[area];image.getRaster().getDataElements(left, top, width, height, matrix);return matrix;}/*** 是否支持裁剪* @return*/@Overridepublic boolean isCropSupported() {return true;}/*** 返回一個新的對象與裁剪的圖像數據。實現可以保存對原始數據的引用,而不是復制。*/@Overridepublic LuminanceSource crop(int left, int top, int width, int height) {return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);}@Overridepublic boolean isRotateSupported() {//是否支持旋轉return true;}/*** 逆時針旋轉圖像數據的90度,返回一個新的對象。* @return*/@Overridepublic LuminanceSource rotateCounterClockwise() {int sourceWidth = image.getWidth();int sourceHeight = image.getHeight();AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);Graphics2D g = rotatedImage.createGraphics();g.drawImage(image, transform, null);g.dispose();int width = getWidth();return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);} } package com.example.demo.date20191125;import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Shape; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.OutputStream; import java.util.Hashtable; import java.util.Random; import javax.imageio.ImageIO;import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import com.google.zxing.DecodeHintType; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatWriter; import com.google.zxing.Result; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; /*** 二維碼生成工具* @author ll**/ public class QRCodeUtil {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 imgPath 生成二維碼保存的路徑* @param needCompress 是否要壓縮* @return 返回二維碼圖片* @throws Exception*/private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {Hashtable 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 (imgPath == null || "".equals(imgPath)) {return image;}// 插入圖片QRCodeUtil.insertImage(image, imgPath, needCompress);return image;}/*** 在生成的二維碼中插入圖片* @param source* @param imgPath* @param needCompress* @throws Exception*/private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {File file = new File(imgPath);if (!file.exists()) {System.err.println("" + imgPath + " 該文件不存在!");return;}Image src = ImageIO.read(new File(imgPath));int height = src.getHeight(null);int width = src.getWidth(null);// 壓縮LOGOif (needCompress) {if (height > HEIGHT) {height = HEIGHT;}if (width > WIDTH) {width = WIDTH;}BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);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 logoImgPath logo圖片* @param destPath* @param needCompress* @throws Exception*/public static void encode(String content, String logoImgPath, String destPath, boolean needCompress) throws Exception {BufferedImage image = QRCodeUtil.createImage(content, logoImgPath, needCompress);mkdirs(destPath);//生成隨機文件名String file = new Random().nextInt(99999999) + ".jpg";ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file));}public static void mkdirs(String destPath) {File file = new File(destPath);// 當文件夾不存在時,mkdirs會自動創建多層目錄,區別于mkdir。(mkdir如果父目錄不存在則會拋出異常)if (!file.exists() && !file.isDirectory()) {file.mkdirs();}}public static void encode(String content, String imgPath, String destPath) throws Exception {QRCodeUtil.encode(content, imgPath, destPath, false);}public static void encode(String content, String destPath, boolean needCompress) throws Exception {QRCodeUtil.encode(content, null, destPath, needCompress);}public static void encode(String content, String destPath) throws Exception {QRCodeUtil.encode(content, null, destPath, false);}public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)throws Exception {BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);ImageIO.write(image, FORMAT_NAME, output);}public static void encode(String content, OutputStream output) throws Exception {QRCodeUtil.encode(content, null, output, false);}/*** 從二維碼中,解析數據* @param file 二維碼圖片文件* @return 返回從二維碼中解析到的數據值* @throws Exception*/public static String decode(File file) throws Exception {Result result;BufferedImage image;image = ImageIO.read(file);if (image == null) {return null;}BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));Hashtable hints = new Hashtable();hints.put(DecodeHintType.CHARACTER_SET, CHARSET);result = new MultiFormatReader().decode(bitmap, hints);String resultStr = result.getText();return resultStr;}public static String decode(String path) throws Exception {return QRCodeUtil.decode(new File(path));} }

5、請求生成二維碼

項目地址最好別用8080,這個可以在application.properties文件里面配置server.port=8090
后面的參數contents是掃碼后出現的數據,如果放鏈接比如百度,掃出來的結果就是百度頁面,這里我們可以放其他的鏈接或能找到路徑的本地頁面

這里是生成的二維碼

有很多可以優化的地方,也可以存放更多的其它類型的數據,有興趣的小伙伴可以去了解一下com.google.zxing源碼或者其它可以生成二維碼的方法,有錯誤的地方請指正、包涵,共同進步!

總結

以上是生活随笔為你收集整理的springboot+java生成二维码图片的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。