java(spring boot)实现二维码生成(可以插入中间log和底部文字)

1.创建一个spring boot项目(非必须):

项目结构:
在这里插入图片描述
2.导入maven依赖:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>core</artifactId>
			<version>3.4.0</version>
		</dependency>
		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>javase</artifactId>
			<version>3.4.0</version>
		</dependency>

3.编码实现:

QrcodeUtil工具类:

/**
 * 二维码工具类
 * 
 * @author jinghx
 *
 */
public class QrcodeUtil {
	private QrcodeUtil() {

	}

	/**
	 * 默认编码方式
	 */
	public static final String DEFAULT_CHARSET = "UTF-8";
	/**
	 * 默认二维码图片格式
	 */
	public static final String DEFAULT_SUBFIX = "PNG";

	/**
	 * 生成二维码默认宽度
	 */
	public static final int DEFAULT_WIDTH = 250;
	/**
	 * 生成二维码默认高度
	 */
	public static final int DEFAULT_HEIGHT = 300;
	/**
	 * 默认二维码中间log宽度
	 */
	public static final int DEFAULT_LOG_WIDTH = 50;
	/**
	 * 默认二维码中间log高度
	 */
	public static final int DEFAULT_LOG_HEIGHT = 50;
	/**
	 * 生成二维码默认保存位置
	 */
	public static final String DEFAULT_QRCODE_PATH = System.getProperty("user.dir") + "\" + "qrCode." + DEFAULT_SUBFIX;
	/**
	 * log默认路径
	 */
	public static final String DEFAULT_LOG_PATH = QrcodeUtil.class.getClassLoader().getResource("log/log.jpg")
			.getPath();

	/**
	 * 由字符串生成二维码BufferedImage对象
	 * 
	 * @param content 字符串内容
	 * @param width   二维码宽度,如果为空或小于等于0采用默认宽度
	 * @param height  二维码高度,如果为空或小于等于0采用默认高度
	 * @return
	 */
	private static BufferedImage createQrCodeBufferedImage(String content, Integer width, Integer height)
			throws Exception {
		BufferedImage resultImage = null;
		if (!StringUtils.isEmpty(content)) {
			Map<EncodeHintType, Object> hints = new HashMap<>();
			hints.put(EncodeHintType.CHARACTER_SET, DEFAULT_CHARSET);// 指定字符编码为UTF-8
			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 指定二维码的纠错等级为中级
			hints.put(EncodeHintType.MARGIN, 2);// 设置图片的边距

			QRCodeWriter writer = new QRCodeWriter();
			width = width != null && width > 0 ? width : DEFAULT_WIDTH;
			height = height != null && height > 0 ? height : DEFAULT_HEIGHT;

			BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
			// 写到字节数据中
			// MatrixToImageWriter.writeToStream(bitMatrix, DEFAULT_SUBFIX, os);
			// resultImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
			// ImageIO.write(resultImage, DEFAULT_SUBFIX, os);

			// 写到文件中
			// MatrixToImageWriter.writeToPath(bitMatrix, DEFAULT_SUBFIX,
			// Paths.get(DEFAULT_PATH));

			resultImage = new BufferedImage(bitMatrix.getWidth(), bitMatrix.getHeight(), BufferedImage.TYPE_INT_RGB);
			for (int x = 0; x < width; x++) {
				for (int y = 0; y < height; y++) {
					resultImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF008000 : 0xFFFFFFFF);// 0xFF000000 黑色 0xFF008000 绿色
				}
			}
		}
		return resultImage;
	}

	/**
	 * 由字符串生成base64格式的简单二维码
	 * 
	 * @param content      字符串内容
	 * @param width        二维码宽度,如果为空或小于等于0采用默认宽度
	 * @param height       二维码高度,如果为空或小于等于0采用默认高度
	 * @param isSaveToPath 是否保存到文件中
	 * @return
	 */
	public static String productQrCodeString(String content, Integer width, Integer height, boolean isSaveToPath) {
		String resultImage = "";
		if (!StringUtils.isEmpty(content)) {
			try {
				BufferedImage image = createQrCodeBufferedImage(content, width, height);
				if (image != null) {
					ByteArrayOutputStream os = new ByteArrayOutputStream();
					ImageIO.write(image, DEFAULT_SUBFIX, os);
					resultImage = "data:image/" + DEFAULT_SUBFIX + ";base64,"
							+ new String(Base64.getEncoder().encode(os.toByteArray()));
					if (isSaveToPath) {
						ImageIO.write(image, DEFAULT_SUBFIX, new FileOutputStream(DEFAULT_QRCODE_PATH));
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return resultImage;
	}

	/**
	 * 由字符串生成base64格式的复杂二维码
	 * 
	 * @param content        字符串内容
	 * @param width          二维码宽度,如果为空或小于等于0采用默认宽度
	 * @param height         二维码高度,如果为空或小于等于0采用默认高度
	 * @param isSaveToPath   是否保存到文件中
	 * @param logPath        log图片的路径
	 * @param isFixedLogSize 是否固定log图片大小
	 * @param text           二维码底部文本内容
	 * @return
	 */
	public static String productQrCodeWithLog(String content, Integer width, Integer height, boolean isSaveToPath,
			String logPath, boolean isFixedLogSize, String text) {
		String resultImage = "";
		if (!StringUtils.isEmpty(content)) {
			try {
				width = width != null && width > 0 ? width : DEFAULT_WIDTH;
				height = height != null && height > 0 ? height : DEFAULT_HEIGHT;
				BufferedImage image = createQrCodeBufferedImage(content, width, height);
				if (image != null) {
					ByteArrayOutputStream os = new ByteArrayOutputStream();
					insertImageAndText(image, width, height, StringUtils.isEmpty(logPath) ? DEFAULT_LOG_PATH : logPath,
							isFixedLogSize, text);
					ImageIO.write(image, DEFAULT_SUBFIX, os);
					resultImage = "data:image/" + DEFAULT_SUBFIX + ";base64,"
							+ new String(Base64.getEncoder().encode(os.toByteArray()));
					if (isSaveToPath) {
						ImageIO.write(image, DEFAULT_SUBFIX, new FileOutputStream(DEFAULT_QRCODE_PATH));
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return resultImage;
	}

	/**
	 * 插入LOGO
	 *
	 * @param source         二维码图片
	 * @param width          二维码宽度,如果为空或小于等于0采用默认宽度
	 * @param height         二维码高度,如果为空或小于等于0采用默认高度
	 * @param imgPath        LOGO图片地址
	 * @param isFixedLogSize 是否固定二维码中间log图标大小
	 * @param text           二维码底部文本内容
	 * @throws Exception
	 */
	private static void insertImageAndText(BufferedImage source, Integer width, Integer height, String imgPath,
			boolean isFixedLogSize, String text) throws Exception {
		File file = new File(imgPath);
		if (!file.exists()) {
			System.err.println("" + imgPath + "   该文件不存在!");
			return;
		}
		Image src = ImageIO.read(new File(imgPath));
		int lwidth = src.getWidth(null);
		int lheight = src.getHeight(null);
		if (isFixedLogSize || lwidth >= width || lheight >= height) { // 固定LOGO大小
			if (lwidth > width) {
				lwidth = DEFAULT_LOG_WIDTH;
			}
			if (lheight > height) {
				lheight = DEFAULT_LOG_HEIGHT;
			}
			Image image = src.getScaledInstance(lwidth, lheight, Image.SCALE_SMOOTH);
			BufferedImage tag = new BufferedImage(lwidth, lheight, BufferedImage.TYPE_INT_RGB);
			Graphics g = tag.getGraphics();
			g.drawImage(image, 0, 0, null); // 绘制缩小后的图
			g.dispose();
			src = image;
		}
		// 插入LOGO
		Graphics2D graph = source.createGraphics();
		int x = (width - lwidth) / 2;
		int y = (height - lheight) / 2;
		graph.drawImage(src, x, y, lwidth, lheight, null);
		Shape shape = new RoundRectangle2D.Float(x, y, lwidth, lheight, 6, 6);
		graph.setStroke(new BasicStroke(3f));
		graph.draw(shape);

		if (!StringUtils.isEmpty(text)) {
			int fontStyle = 1;
			int fontSize = 12; //
			// 计算文字开始的位置(居中显示)
			// x开始的位置:(图片宽度-字体大小*字的个数)/2
			int startX = (width - (fontSize * text.length())) / 2;
			// y开始的位置:图片高度-(图片高度-图片宽度)/2
			int startY = height - (height - width) / 2;
			graph.setColor(Color.BLUE);
			graph.setFont(new Font(null, fontStyle, fontSize)); // 字体风格与字体大小 graph.drawString(text, startX, startY);
			graph.drawString(text, startX, startY);
		}

		graph.dispose();
	}

	/**
	 * 解码二维码内容
	 * 
	 * @param file
	 * @return
	 * @throws Exception
	 */
	public static String decode(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, DEFAULT_CHARSET);
		result = new MultiFormatReader().decode(bitmap, hints);
		String resultStr = result.getText();
		return resultStr;
	}

	public static void main(String[] args) throws Exception {
		System.out.println(decode(new File(DEFAULT_QRCODE_PATH)));
	}
}

编写一个测试用的Controller类:

@RestController
@RequestMapping("/qrcode")
public class QrCodeController {

	/**
	 * 生成简单的字符串二维码
	 * 
	 * @param content
	 * @return
	 */
	@PostMapping("/simpleCode")
	public String productQrCode(String content) {
		return QrcodeUtil.productQrCodeString(content, null, null, true);
	}

	/**
	 * 生成带有log和底部字符串的二维码
	 * 
	 * @param content
	 * @return
	 */
	@PostMapping("/codePlus")
	public String productQrCodeWithLogAndText(String content, String bottomText) {
		return QrcodeUtil.productQrCodeWithLog(content, null, null, true, null, true, bottomText);
	}

}

编写一个简单的html页面qrCode.html,实时查看二维码生成效果:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>生成二维码</title>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
</head>
<body>
	<div style="float: left">
		<div>
			<input id="strContent" type="text" width="500px"
				placeholder="输入二维码想显示的内容">
			<button onclick="getSimpleQrcode()">点击显示简单二维码</button>
		</div>
		<div>
			<img id="simpleQrCode" />
		</div>

	</div>
	<div style="float: left; padding-left: 20px;">
		<div>
			<input id="logContent" type="text" width="500px"
				placeholder="输入二维码想显示的内容"> <input id="bottomText"
				type="text" width="300px" placeholder="二维码底部文字,可不填">
			<button onclick="getComplexQrcode()">点击显示带log二维码</button>
		</div>
		<div>
			<img id="complexQrCode" />
		</div>
	</div>
</body>
<script type="text/javascript">
	/**
	 * 通过ajax请求获取base64编码格式的二维码
	 */
	function getpQrcode(url, param, imgId) {
		$.ajax({
			url : url,
			cache : false,
			type : 'POST',
			data : param,
			async : true,
			dataType : 'text',
			error : function(event, XMLHttpRequest, ajaxOptions, thrownError) {
				console.log(event);
				console.log(XMLHttpRequest);
				console.log(ajaxOptions);
				console.log(thrownError);
			},
			success : function(data) {
				$("#" + imgId).prop('src', data);
			}
		});
	}
	/**
	 *简单二维码
	 */
	function getSimpleQrcode() {
		let url = "qrcode/simpleCode";
		let param = {
			'content' : $("#strContent").prop('value')
		};
		let imgId = "simpleQrCode";
		getpQrcode(url, param, imgId);
	}
	/**
	 *复杂二维码
	 */
	function getComplexQrcode() {
		let url = "qrcode/codePlus";
		let param = {
			'content' : $("#logContent").prop('value'),
			'bottomText' : $("#bottomText").prop('value')
		};
		let imgId = "complexQrCode";
		getpQrcode(url, param, imgId);
	}
</script>
</html>

整个工程就是依赖google的二维码工具包来进行二维码的生成,代码的注释比较详细了,这里就不再做过多的赘述,运行工程:

访问:http://localhost:8080/qrcode.html
在这里插入图片描述
可以在对应的input框中输入你想要生成的二维码内容,点击旁边的按钮即可生成(二维码颜色可以参考 颜色名称 RGB 对照表 设置):
在这里插入图片描述
同时工程目录下会保存一张最新生成的二维码图片:
在这里插入图片描述

一颗安安静静的小韭菜。文中如果有什么错误,欢迎指出。
原文地址:https://www.cnblogs.com/c-Ajing/p/13448345.html