54 java生成QR二维码
2019-01-17 本文已影响58人
滔滔逐浪
引言
随着二维码(QR code)的普及,越来越多的项目中会设计一些产生二维码的交互页面,以便更好地和用户互动,以及方便用户的使用,传播app等操作。那么今天就来探究一下如何在项目中快速简单的生成QR二维码。
一.简易版本
首先
我们用到谷歌开源的zxing项目包,使用maven的同学可以轻易的导入。
<!--QRcode-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
<!--QRcode-->
第二步
我们来编写生成简单二维码的java代码。只要有一个content的输入,能把content的内容藏到二维码中即可。那么代码如下:
package com.yuqiyu.schoolcms.utils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.awt.image.BufferedImage;
import java.util.Hashtable;
public class QRCodeUtil {
private static final String CHARSET ="utf-8";
//二维码尺寸
private static final int QRCODE_SIZE=300;
public static BufferedImage createImage(String content){
Hashtable<EncodeHintType,Object> hints =new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET,CHARSET);
hints.put(EncodeHintType.MARGIN,1);
BitMatrix bitMatrix =null;
try{
bitMatrix =new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE,QRCODE_SIZE,QRCODE_SIZE,
hints );
}catch (Exception e){
e.printStackTrace();
}
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);
}
}
return image;
}
}
下面我们编写controller接口去进行测试
注意:对于有些二维码是扫了即用,扫完即走那种的,这个时候就不应该产生本地的缓存暂用服务器资源。禁止缓存的方式详见代码
package com.yuqiyu.schoolcms.controller;
import com.yuqiyu.schoolcms.utils.QRCodeUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
@RestController
public class QRController {
@RequestMapping("/generateQR")
public void generateQR(@RequestParam("content")String content, HttpServletResponse response){
BufferedImage image;
//禁止图像缓存
response.setHeader("pragma","No-cache");
response.setHeader("Cache-control","no-cache");
response.setDateHeader("Expires",0);
response.setContentType("image/jpeg");
image= QRCodeUtil.createImage(content);
//创建二进制的输出流
try(ServletOutputStream sos = response.getOutputStream()){
// 将图像输出到Servlet输出流中。
ImageIO.write(image, "jpeg", sos);
} catch (IOException e) {
e.printStackTrace();
}
}
访问网址 http://localhost:8084/generateQR?content=1
二.拓展版本
在实际中,我们常常会看见一些二维码中间会放置上企业的logo,显得更加的美观专业。接下来我们就如何在二维码中间增加图案进行说明。
首先
我们考虑增加两个变量,一个是插入图片的地址,一个压缩参数(主要用于过大logo情况下是否压缩)
// LOGO宽度
private static final int LOGO_WIDTH = 80;
// LOGO高度
private static final int LOGO_HEIGHT = 80;
/**
* 插入LOGO
*
* @param source 二维码图片
* @param logoPath LOGO图片地址
* @param needCompress 是否压缩
* @throws Exception
*/
public static void insertImage(BufferedImage source, InputStream logoPath, boolean needCompress) {
Image src = null;
try {
src = ImageIO.read(logoPath);
} catch (IOException e) {
e.printStackTrace();
}
int width = src.getWidth(null);
int height = src.getHeight(null);
if (needCompress) {
// 压缩LOGO
if (width > LOGO_WIDTH) {
width = LOGO_WIDTH;
}
if (height > LOGO_HEIGHT) {
height = LOGO_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;
}
// 插入LOGO
Graphics2D 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, 12, 12);
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
}
我们只要在一中生成图片的基础上调用该方法,即可在里面插入一个Logo。
接着
我们照样编写了controller去测试:
@RequestMapping("/generateQRzengqiang")
public void generateQRzengqiang(@RequestParam("content")String content, HttpServletResponse response){
BufferedImage image;
//禁止图像缓存
response.setHeader("pragma","No-cache");
response.setHeader("Cache-control","no-cache");
response.setDateHeader("Expires",0);
response.setContentType("image/jpeg");
image= QRCodeUtil.createImage(content);
InputStream inputStream=this.getClass().getResourceAsStream("/static/1.jpg"); //新增代码
QRCodeUtil.insertImage(image,inputStream,Boolean.TRUE);//新增代码
//创建二进制的输出流
try(ServletOutputStream sos = response.getOutputStream()){
// 将图像输出到Servlet输出流中。
ImageIO.write(image, "jpeg", sos);
} catch (IOException e) {
e.printStackTrace();
}
}