概述
前后端都方便做的时候,交给前端来做
后端可以用java生成二维码,前端可以用js生成二维码,如果要保存到服务器,那就后端生成二维码;如果是一次性的、图片不需要保存到服务器,那就前端生成二维码。
后端实现,多个用户同时操作时会加重服务器的负担;前段实现,由用户浏览器完成操作,可以减轻服务器压力。前端生成二维码也比后端要简单一些。最好是前端传递参数,后端做相应处理返回给前端数据,前端拿到数据后生成对应的二维码。
要在多个模块中使用的功能,最好写成单独的一个模块
eg. 支付模块,二维码,短信通知
好处:1、解耦,好维护;2、方便复用
前端生成二维码
qrcode.js
qrcode.js 是一个用于生成二维码的 js 库,获取dom标签后使用canvas 绘制二维码,不依赖其它库。
<!-- 二维码容器 -->
<div id="qrcode"></div>
<!-- 引入qrcode.js -->
<script src="https://cdn.bootcdn.net/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<script type="text/javascript">
// 容器
let qrcodeEle = document.getElementById("qrcode");
// 内容
let text = "xxxxxxxxxxxxx";
// 生成二维码
let qrcode1= new QRCode(qrcodeEle,text);
// 可以指定宽高、颜色、纠错等级
let qrcode2 = new QRCode(qrcodeEle, {
text: text,
width: 128,
height: 128,
colorDark: "#ff0000",
correctLevel: QRCode.CorrectLevel.H
}
);
//清空二维码,容器还在
qrcode1.clear();
// 修改二维码的内容
qrcode1.makeCode("xxxxx");
</script>
jquery.qrcode.js
jquery.qrcode.js是jq用于生成二维码的一个插件,依赖jq。
<!-- 二维码容器 -->
<div id="qrcode1"></div>
<div id="qrcode2"></div>
<!-- 引入jq -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- 引入jquery.qrcode.js -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
<script>
// 生成二维码
$('#qrcode1').qrcode("xxxxxxxxxxxxxx");
// 可以设置宽高
$('#qrcode2').qrcode({width: 128, height: 128, text: "xxxxxxxxxxxxx"});
</script>
后端生成、解析二维码(zxing)
后端常用google的ZXing生成二维码。
依赖
<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>
前端
<!-- 上传二维码图片 -->
<form action="./qrcodeHandler" method="post" enctype="multipart/form-data">
请选择二维码图片:<input name="qrcodeFile" type="file" /><br />
<button type="submit">上传</button>
</form>
<br />
<!-- 从后端获取二维码 -->
<img id="qrcode" src="./getQrcode" />
<button onclick="flushQrcode()">刷新二维码</button>
<script>
// 刷新验证码
function flushQrcode() {
let img = document.getElementById("qrcode");
img.src = './getQrcode?' + new Date().getTime();
}
</script>
后端
工具类
public class QrcodeUtil {
// 生成的二维码格式
public static final String QRCODE_FORMAT = "PNG";
// 二维码的宽高
private static final int QRCODE_SIZE = 300;
// 内嵌图片的宽高
private static final int INNER_SIZE = 80;
/**
* 生成普通二维码
*
* @param text 二维码内容
* @return BufferedImage 生成的二维码
*/
public static BufferedImage generateQrcode(String text){
HashMap<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = null;
BufferedImage bufferedImage = null;
MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
try {
bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig);
} catch (WriterException e) {
e.printStackTrace();
}
return bufferedImage;
}
/**
* 生成内嵌图片的二维码
*
* @param text 二维码内容
* @param innerImagePath 内嵌图片的路径
* @return BufferedImage 生成的二维码
*/
public static BufferedImage generateQrcode(String text, String innerImagePath) {
HashMap<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = null;
try {
bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
} catch (WriterException e) {
e.printStackTrace();
}
BufferedImage image=null;
if (bitMatrix!=null){
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
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);
}
}
// 插入图片
insertImage(image, innerImagePath);
}
return image;
}
/**
* 内嵌图片
*
* @param qrCodeImage 二维码图片
* @param innerImagePath 内嵌图片的路径
*/
private static void insertImage(BufferedImage qrCodeImage, String innerImagePath) {
File file = new File(innerImagePath);
if (file.exists()) {
Image innerImage = null;
try {
innerImage = ImageIO.read(file);
} catch (IOException e) {
e.printStackTrace();
}
if (innerImage!=null){
int width = innerImage.getWidth(null);
int height = innerImage.getHeight(null);
// 缩放LOGO
if (width > INNER_SIZE) {
width = INNER_SIZE;
}
if (height > INNER_SIZE) {
height = INNER_SIZE;
}
Image image = innerImage.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();
innerImage = image;
// 插入LOGO
Graphics2D graph = qrCodeImage.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
graph.drawImage(innerImage, 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();
}
}
}
/**
* 解析上传的二维码
*
* @param file 上传的二维码图片
* @return 二维码中的文本
*/
public static String resolveQrcode(MultipartFile file) {
HashMap<DecodeHintType, Object> hints = new HashMap<>(2);
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
String resultStr = null;
try {
BufferedImage image = ImageIO.read(file.getInputStream());
BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result = new MultiFormatReader().decode(bitmap, hints);
resultStr = result.getText();
} catch (IOException | NotFoundException e) {
e.printStackTrace();
}
return resultStr;
}
}
controller
@Controller
public class QRCodeController {
/**
* 解析上传的二维码图片
*/
@PostMapping("/qrcodeHandler")
@ResponseBody
public String excelHandler(@RequestParam("qrcodeFile") MultipartFile file) {
String text = QrcodeUtil.resolveQrcode(file);
return "二维码中的文本:" + text;
}
/**
* 获取二维码图片
*/
@GetMapping("/getQrcode")
public void getQrcodeImage(HttpServletResponse response) {
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
//如果是jpg,此处改成jpeg
response.setContentType("image/png");
//二维码内容
String text = Math.random() + "";
//内嵌图片
String innerImagePath = "C:/Users/chy/Desktop/1.jpg";
//生成普通二维码
BufferedImage bufferedImage = QrcodeUtil.generateQrcode(text);
//生成内嵌图片的二维码
// BufferedImage bufferedImage = QrcodeUtil.generateQrcode(text,innerImagePath);
//输出到浏览器
OutputStream os = null;
try {
os = response.getOutputStream();
ImageIO.write(bufferedImage, QrcodeUtil.QRCODE_FORMAT, os);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}