QR码(Quick Response Code) 是二维码的一种,在正方形二位矩阵内通过黑白标识编码二进制位从而编码数据,最早发明用于日本汽车制造业追踪零部件。下面先给出实现
页面:
![](https://img-blog.csdnimg.cn/20181123184123910.png)
触发:点击二维码时调用js中qrcodeAction()方法
//添加巡检计划二维码
function qrcodeAction(id,type){
var url = "/QrCode/qrCode";
var mapObj = {"id": id,"type": type};
$.ajax({
url:url,
data:mapObj,
dataType:"json",
contentType:"application/json",
success:function(res){
layer_index = layer.open({
type:1,
title: ['二维码', 'font-size:14px;'],
area: ['300px', '330px'],
content:"<div align='center'><img src='https://img-blog.csdnimg.cn/2022010612115569606.png"+res.content+"'></div>",
btn:["下载"],
yes:function(){
window.location.href='/QrCode/downloadQrCode?id='+id;
}
})
},
});
Controller接口生成二维码代码:
@RequestMapping(value="/qrCode")
@ResponseBody
public String encoderQRCoder(@RequestParam("id") String id,@RequestParam("type") String type,HttpServletRequest request,HttpServletResponse response,ModelMap model) throws IOException{
//生成二维码要存储的信息
String url="http://localhost:8080/app/qr?id="+id+"&type="+type;
//获得二维码内容的字节数组
byte[] d = url.getBytes();
//缓冲区,创建一个不带透明色的BufferedImage对象
BufferedImage bi = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
//绘图,此 Graphics2D 类扩展Graphics 类,以提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制。它是用于在Java(tm) 平台上呈现二维形状、文本和图像的基础类
Graphics2D g = bi.createGraphics();
//设置背景色
g.setBackground(Color.WHITE);
//通过使用当前绘图表面的背景色进行填充来清除指定的矩形, public abstract void clearRect(int x, int y, int width, int height) :x - 要清除矩形的 x 坐标。 y - 要清除矩形的 y 坐标。 width - 要清除矩形的宽度
g.clearRect(0, 0, 300, 300);
//设定图像颜色,即二维码颜色,应用程序应该使用 setColor,然后使用 fillRect,以确保离屏图像被清除为指定颜色
g.setColor(Color.BLACK);
if (dataLength > 0 && dataLength <= 2000) {
//设置二维码
Qrcode qrcode = new Qrcode();
// 设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小
qrcode.setQrcodeErrorCorrect('M');
//N代表数字,A代表a-Z,B代表其它字符,如果有中文,必须设置为B
qrcode.setQrcodeEncodeMode('B');
//设置二维码尺寸,取值范围1-40,值越大尺寸越大,可存储的信息越大 ,码越乱
qrcode.setQrcodeVersion(15);
//设置二维码像素,设置的版本是几这就写几,否则有空白,即15对应上面的版本号15,这是一个计算公式,第一版本型号为21*21的矩阵, 以后每增加一个版本号会增加4个模块,第二版本为25*25的矩阵
int width = 67 + 12 * (15 - 1);
int height = 67 + 12 * (15 - 1);
//让字符串数组生成二维码
boolean[][] b = qrcode.calQrcode(d);
//输出内容——>二维码,来控制生成二维码的大小。(只能控制大致范围(最主要的控制),生成的大小还与设置setQrcodeVersion,setOrcodeEncodeMode,setQrcodeErrorCorrect有关. 根据这几个的关系可以调试出适合的二维码
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b.length; j++) {
if (b[j][i]) {
//填充背景色,+后面是偏移量,在这设置就是2,不设置可能导致解析出错,填充矩形的原方法应该是:public void fillRect(int,int int,int );4个参数的意思分别为,起始X坐标,起始Y坐标,宽度,高度
g.fillRect(j * 3 + 2, i * 3 + 2, 3, 3);
}
}
}
} else {
Logger.getRootLogger().info( dataLength +"大于"+ MAX_DATA_LENGTH);
}
//释放对象
g.dispose();
//清除图片缓存
bi.flush();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//设置图片格式,并将图片写入输出流中
ImageIO.write(bi, "jpg", outputStream);
//设置图片格式,与输出路径
ImageIO.write(bi, "jpg", new File("C:/MyProject/nsbd/qr"+id+".png"));
byte[] byteArray = outputStream.toByteArray();
Base64 base64=new Base64();
//转换为base64编码格式,之所以转换为base64,是因为在jsp中<img src>src的编码格式设置的为base64,为什么要这样写,请看下面讲解
byte[] binary=base64.encode(byteArray);
String s=new String(binary);
return JSON.toJSONString(s);
}
BufferedImage
BufferedImage是Image的一个子类,BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便的操作这个图片,通常用来做图片修改操作如大小变换、图片变灰、设置图片透明或不透明等
Data URI scheme
jsp图片是这样写的: <img src='https://img-blog.csdnimg.cn/2022010612115569606.png"+res.content+"'>
图片显示后,url后面跟了好长好长的一大串字符,我这用。。。省略了,该字符串大小大概有44KB
<img src="https://img-blog.csdnimg.cn/2022010612115569606.png/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAg。。。sljfsdlifjsd==">
这是Data URI scheme,是在RFC2397中定义的,目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入。比如上面那串字符,其实是一张小图片,data表示取得数据的协定名称,image/png 是数据类型名称,base64 是数据的编码方法,逗号后面就是这个image/png文件base64编码后的数据
目前,Data URI scheme支持的类型有:
data:,文本数据
data:text/plain,文本数据
data:text/html,HTML代码
data:text/html;base64,base64编码的HTML代码
data:text/css,CSS代码
data:text/css;base64,base64编码的CSS代码
data:text/javascript,Javascript代码
data:text/javascript;base64,base64编码的Javascript代码
data:image/gif;base64,base64编码的gif图片数据
https://img-blog.csdnimg.cn/2022010612115569606.pngbase64编码的png图片数据
data:image/jpeg;base64,base64编码的jpeg图片数据
data:image/x-icon;base64,base64编码的icon图片数据
base64简单地说,它把一些 8-bit 数据翻译成标准 ASCII 字符,目前,IE8、Firfox、Chrome、Opera浏览器都支持这种小文件嵌入
举个图片的例子:
网页中一张图片可以这样显示:
<img src="http://mail.163.com/images/x.png" />
也可以这样显示:
<img src="https://img-blog.csdnimg.cn/2022010612115569606.pngiVBORw0KGgoAAAANSUhEUgAAAAkAAAAJAQMAAADaX5RTAAAAA3NCSVQICAjb4U/gAAAABlBMVEX///+ZmZmOUEqyAAAAAnRSTlMA/1uRIrUAAAAJcEhZcwAACusAAArrAYKLDVoAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDkvMjAvMTIGkKG+AAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAAB1JREFUCJljONjA8LiBoZyBwY6BQQZMAtlAkYMNAF1fBs/zPvcnAAAAAElFTkSuQmCC" />
把图像文件的内容直接写在了HTML 文件中,这样做的好处是,节省了一个HTTP 请求。坏处是浏览器不会缓存这种图像。
二维码的数据格式解析
二维码内容不一定是http格式,还可以其它格式,详解参见:https://blog.csdn.net/qq_23953793/article/details/51699813
二维码扫描原理
(以http格式为例)
首先生成二维码,该二维码的内容为一个http格式的路径,然后将生成的二维码图片显示在页面,扫描时就会识别二维码的内容,在此即为http格式的一个url,识别url后,就会去请求该url,我们的项目中该url就是一个controller中的一个接口,所以扫描后就紧接着来请求这个controller了,进行一系列的操作,最后返回结果给App,显示在App端