Java生成二维码底部带文字并且返回前端使用img接收

本文介绍如何使用Java生成带有文字的二维码,并提供了一个简单的web测试案例。文章详细解释了所需依赖及工具类的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.java生成二维码工具类

2.web测试

3.前端处理

4.测试结果


  • 背景

本demo主要针对jdk1.6版本的,但是高版本的同样可以用,如果觉得不舒服可以自行添加高版本的依赖包。

  • 准备工具

  1. 依赖包
   
    <!--谷歌的jar包 主要的依赖包 -->
		<dependency>
		    <groupId>com.google.zxing</groupId>
		    <artifactId>core</artifactId>
		    <version>2.2</version>
		</dependency>
		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>javase</artifactId>
			<version>2.2</version>
		</dependency>



<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<!-- 资源文件拷贝插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.7</version>
				<configuration>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
			<!-- java编译插件;解决每次更新版本变化为1.5的问题 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
		<pluginManagement>
			<plugins>
				<!-- 配置Tomcat插件 -->
				<plugin>
					<groupId>org.apache.tomcat.maven</groupId>
					<artifactId>tomcat7-maven-plugin</artifactId>
					<version>2.2</version>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

1.java生成二维码工具类

工具类的方法主要是用于二维码底部显示对应的文字,至于在二维码添加logo的没有做,因为本人的需求没有涉及到。但是实现的思路就是引入一个logo图片通过设置其大小小于二维码的尺寸,然后通过java的画图方式将logo画在二维码上面

package com.tecrun.utils.qrcode;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.util.Base64;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;


/**
 * 二维码工具类
 * @author tchzt
 *
 */
public class QRCodeUtil {
	//二维码的宽高
	private static final int WIDTH=200;
	private static final int HEIGHT=200;
	// 加文字二维码高
	private static final int WORDHEIGHT = 250; 
	
	/**
	 *  生成二维码图片
	 * @param content 二维码的内容
	 * @return
	 */
	public static BufferedImage createQRCode(String content) {
		
		Map<EncodeHintType, Object> hints= new HashMap<EncodeHintType, Object>();
		//容错级别L>M>Q>H(级别越高扫描时间越长)
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
		//字符编码
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		hints.put(EncodeHintType.MARGIN, 0);//白边的宽度,可取0~4
		BufferedImage image=null;									
		try {
			MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
			//生成矩阵数据
			BitMatrix bitMatrix=multiFormatWriter.encode(content, 
					BarcodeFormat.QR_CODE,WIDTH,HEIGHT,hints);	
			int w = bitMatrix.getWidth();
			int h = bitMatrix.getHeight();
			//生成二维码bufferedImage图片
			image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
			// 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色
			for (int x = 0; x < w; x++) {
				for (int y = 0; y < h; y++) {
					image.setRGB(x, y, bitMatrix.get(x, y) ? 
							MatrixToImageConfig.BLACK : MatrixToImageConfig.WHITE);
				}
			}
			
											
		} catch (Exception e) {
			throw new RuntimeException("生成二维码失败:"+e.getMessage());
	    }							
		return image;
		
	}
	
	/**
	 *  生成解析二维码
	 * @param content 二维码的内容
	 * @return
	 */
	public static Result parseQRCode(String filePath) {
		//二维码编码相关的参数
		Map<DecodeHintType, Object> hints= new HashMap<DecodeHintType, Object>();
		//字符编码
		hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");

		BufferedImage image=null;
		try {
			File file = new File(filePath);
			image = ImageIO.read(file);
			
			if (image == null) {
				System.out.println("the decode image may be not exit.");
			}
			LuminanceSource source = new BufferedImageLuminanceSource(image);
			BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
			//解析二维码
			Result result = new MultiFormatReader().decode(bitmap, hints);
			
			return result;
		} catch (Exception e) {
			throw new RuntimeException("解析二维码失败:"+e.getMessage());
	    }
		
	}
	
	/**
	 *  删除生成的二维码周围的白边,根据审美决定是否删除
	 * @param matrix BitMatrix对象
	 * @return BitMatrix对象
	 * */
	private static BitMatrix deleteWhite(BitMatrix matrix) {
	    int[] rec = matrix.getEnclosingRectangle();
	    int resWidth = rec[2] + 1;
	    int resHeight = rec[3] + 1;

	    BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
	    resMatrix.clear();
	    for (int i = 0; i < resWidth; i++) {
	        for (int j = 0; j < resHeight; j++) {
	            if (matrix.get(i + rec[0], j + rec[1]))
	                resMatrix.set(i, j);
	        }
	    }
	    return resMatrix;
	} 
	
	 /**
	    * 二维码底部加上文字
	    * @param image 传入二维码对象
	    * @param words 显示的文字内容 
	    * @return
	    */
	   private static BufferedImage insertWords(BufferedImage image,String words){
		   BufferedImage outImage = null;
			if (  StringUtils.isNotBlank(words)){
				outImage= new BufferedImage(WIDTH, WORDHEIGHT, BufferedImage.TYPE_4BYTE_ABGR);
				Graphics2D outg = outImage.createGraphics();
				// 画二维码到新的面板
				outg.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
				// 画文字到新的面板
				outg.setColor(Color.BLACK);
				outg.setFont(new Font("微软雅黑", Font.PLAIN, 16)); // 字体、字型、字号
				
				int strWidth = outg.getFontMetrics().stringWidth(words);
				
				int singleFD=outg.getFontMetrics().stringWidth("2");
				int grow=WIDTH/singleFD-1;
				//长度过长就截取超出二维码宽度部分换行
				if (strWidth > WIDTH) {
					String serialnum1 = words.substring(0, grow);
					String serialnum2 = words.substring(grow, words.length());
					outg.drawString(serialnum1, 5, image.getHeight() + (outImage.getHeight() - image.getHeight()) / 2 );
					BufferedImage outImage2 = new BufferedImage(WIDTH, WORDHEIGHT, BufferedImage.TYPE_4BYTE_ABGR);
					Graphics2D outg2 = outImage2.createGraphics();
					outg2.drawImage(outImage, 0, 0, outImage.getWidth(), outImage.getHeight(), null);
					outg2.setColor(Color.BLACK);
					// 字体、字型、字号
					outg2.setFont(new Font("微软雅黑", Font.PLAIN, 16)); 
					//参数:显示的内容、起始位置x、起始的y
					outg2.drawString(serialnum2,5, outImage.getHeight() + (outImage2.getHeight() - outImage.getHeight()) / 2 );
					outg2.dispose();
					outImage2.flush();
					outImage = outImage2;
				} else {
					// 画文字
					outg.drawString(words, (WIDTH - strWidth) / 2, 
							image.getHeight() + (outImage.getHeight() - image.getHeight()) / 3 ); 
				}
				outg.dispose();
				outImage.flush();
				image.flush();
			}
		  
	      return outImage;
	}
	   
	   
	/**
	 * 生成二维码下方不带文字
	 * @return
	 */
	public static String getQRCode(String srialnum,String savePath) {
		BufferedImage image=createQRCode(srialnum);
		try {
			
			//字节数组流包装输出对象流
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ImageIO.write(image, "png", baos);//将图片写入到输出流
			ImageIO.write(image, "png", new File(savePath));//直接写入某路径
			return Base64.encodeBase64URLSafeString(baos.toByteArray());
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("写出图片流失败");
		}
		
	}
	
	/**
	 * 生成的二维码下方带文字
	 * @return
	 */
	public static String getQRCode(String srialnum,String words,String savePath) {
		
		BufferedImage image = insertWords(createQRCode(srialnum), words);
		try {
			
			//字节数组流包装输出对象流
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			image.flush();
			//将图片写入到输出流
			ImageIO.write(image, "png", baos);
			
			ImageIO.write(image, "png", new File(savePath));//直接写入某路径
			return Base64.encodeBase64URLSafeString(baos.toByteArray());
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("写出图片流失败!!!");
		}
		
	}
	
	public static void main(String[] args) {
		String srialnum="123726387628736581235";
		String words="987345972934723123123435234523452345";
		String savePath="E:\\桌面\\image\\03.jpg";
		getQRCode(srialnum,words,savePath);
//		getQRCode(srialnum,savePath);
		System.out.println("ok");
		
		//去掉固定长度字符串的空格问题
		String string= "       uiiuhi kkjsnf jkjk  ";		
		System.out.println(string.replace(" ", ""));
	}
}
	

2.web测试

创建一个简单web项目,引入对应的jar包,将二维码工具类放入到工具类包下,写一个简单的controller类进行web测试。

/**
	 * 
	* @Title: showQRCode 
	* @Description: 测试二维码输出到前端显示
	* @return String
	* @author tchzt
	 * @throws IOException 
	* @date 2021年9月17日下午6:02:32
	 */
	@RequestMapping("/qrcode")
	public void showQRCode(HttpServletResponse response) throws IOException {

	    String words="254352397459dfasdgvxdvser3453452sfsdg454353wtwegd82374";
	    
	    String code = QRCodeUtil.getQRCode(words, words);
	    //解析二维码的base64流
	    byte[] base64 = Base64.decodeBase64(code);
	    ByteArrayOutputStream baos= new ByteArrayOutputStream();
	    baos.write(base64);
	    //获取HttpServletResponse响应流,用于输出到前端
	    ServletOutputStream outputStream = response.getOutputStream();
	    baos.writeTo(outputStream);
	    outputStream.close();
	    baos.close();
	   	
	}

3.前端处理

        使用img接收服务器响应的图片流,由于考虑到服务地址的变化,首先通过js获取到服务器的地址,这样不会因为服务变化而导致不能使用

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>

</head>
<body>

<img id="qrcode" alt="#" src="">

<script type="text/javascript">
   /* 获取服务地址  */
   var curWPath = window.document.location.href;
   var pathname = window.document.location.pathname;
   var index = curWPath.indexOf(pathname);
   var serverpath = curWPath.substring(0,index);
   /* 设置二维码的服务URL */
   var qrcodeobj = document.getElementById("qrcode");
   qrcodeobj.src = serverpath+"/qrcode";
   console.log("imgsrc="+qrcodeobj.src);
   alert(qrcodeobj.src);
   
</script>
</body>
</html>

4.测试结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值