项目中我们经常会用到二维码,今天就来讲讲二维码的生成:
1, 二维码的概念:
二维条码/二维码(2-dimensional bar code)是用某种特定的集合图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的图形.(二维码的黑点代表二进制的1,空白代表二进制的0);
2, 一维码(条形码) 是由一组粗细不同,黑白(或彩色)相间的条,空及其相应的字符(数字字母)组成的标记,即传统条码.
3, 二维码分类:
二维码也有许多不同的码制,就码制的编码原理而言,通常分为三种类型:
(1), 线性堆叠式二维码;
编码原理: 建立在一维条形码基础之上,按需要堆积成两行或多行;
(2), 矩阵式二维码;
最常用的类型: 在一个矩形空间通过黑,白像素在矩阵中的不同分布进行编码. 在矩阵相应元素位置上, 用点(方点,圆点或其他形状)的出现表示二进制"1",点的不出现表示二进制的"0";
(3), 邮政码;
最少使用: 邮政码通过不同长度的条进行编码,主要用于邮件编码,如: POSTNET, BPO4-STATE.
4, 二维码的优缺点:
优点: (1), 高密度编码,信息容量大;
(2), 编码范围广;
(3), 容错能力强;
(4), 译码可靠性高;
(5), 可引入加密措施;
(6), 成本低,易制作,持久耐用;
缺点: (1), 二维码技术成为手机病毒,钓鱼网站传播的新渠道;
(2), 信息泄露
5, QR code:
目前流行的三大国际标准:
PDF417: 不支持中文;
DM: 专利未公开;
QR code: 专利公开,支持中文;相比其他二维码,具有识读速度快,数据密度大,占用空间小的优势;
QR code 是由日本Denso公司于1994年研制的一种矩阵二维码符号吗,全称是Quick Response Code.
6, Java生成二维码:
ZXing Project, QrCode等,这里主要来测试ZXing的用法:
package code;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.EncodeHintType;
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.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
/**
* Maven 仓库:
* <dependency>
* <groupId>com.google.zxing</groupId>
* <artifactId>javase</artifactId>
* <version>3.3.1</version>
* </dependency>
*
* Jar包:
* javase-3.3.1.jar;
* core-3.3.1.jar;
* */
/**
*@description TODO 二维码生成解析类
*@date 2018/1/22
*@author geYang
**/
public class QrCode {
/**
* @description TODO 生成QR_Code图片
* @param size 生成图片大小
* @param content 内容
* @param path 生成的地址
* @return String
* @date 2018年1月22日下午4:54:28
* @author geYang
**/
public static String generateQrCode(Integer size, String content, String path, boolean isQrCode) throws Exception{
String imageName = getNowDate()+".png";
BitMatrix matrix;
if(isQrCode){
matrix = generateQrCode(size, content);
} else {
matrix = generateEna13Code(content);
}
//生成二维码图片:
Path file = FileSystems.getDefault().getPath(path, imageName);
MatrixToImageWriter.writeToPath(matrix, "png", file);
return path+imageName;
}
/**
* @description TODO 生成图片流
* @author geYang
**/
public static void generateQrCode(Integer size, String content, HttpServletResponse response, boolean isQrCode) throws Exception{
BitMatrix matrix;
if(isQrCode){
matrix = generateQrCode(size, content);
} else {
matrix = generateEna13Code(content);
}
MatrixToImageWriter.writeToStream(matrix, "png", response.getOutputStream());
response.getOutputStream().flush();
response.getOutputStream().close();
}
public static BitMatrix generateQrCode(Integer size, String content) throws Exception{
size = (size==null || size<300) ? 300 : size;
//定义二维码参数:
HashMap<EncodeHintType, Object> hintType = new HashMap<>();
hintType.put(EncodeHintType.CHARACTER_SET, "utf-8");
//纠错等级
hintType.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
//二维码与图片边距
hintType.put(EncodeHintType.MARGIN, 2);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, size, size, hintType);
return bitMatrix;
}
/**
* 生成一维码(条形码)
* @author geYang
**/
public static BitMatrix generateEna13Code(String content) throws Exception{
HashMap<EncodeHintType, Object> hintType = new HashMap<>();
hintType.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.EAN_13, 105, 50, hintType);
return bitMatrix;
}
/**
* @description TODO 解析二维码/条形码
* @return String
* @date 2018年1月22日下午5:08:13
* @author geYang
* @throws Exception
**/
public static String decoder(String path) throws Exception{
MultiFormatReader formatReader = new MultiFormatReader();
File input = new File(path);
BufferedImage read = ImageIO.read(input);
BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(read)));
Result result = formatReader.decode(binaryBitmap);
return result.getText();
}
/**当前时间*/
private static String getNowDate(){
SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
return sf.format(new Date());
}
/**
* 百度百科: https://baike.baidu.com/item/%E6%9D%A1%E5%BD%A2%E7%A0%81/278988?fr=aladdin
* @description TODO 生成商品条形码数字内容
* @param 69838 地区代码:69838 代表中国大陆
* @param shopCode 商品代码(5位数字) 代表着生产厂商代码,由厂商申请,国家分配
* @param productCode 商品代码(4位数字) 代表着厂内商品代码,由厂商自行确定
* @return String
* @date 2018年1月23日下午2:25:40
* @author geYang
**/
public static String getEna13CodeContent(String productCode){
return getEna13CodeContent("69838", productCode);
}
public static String getEna13CodeContent(String shopCode, String productCode){
Pattern pattern = Pattern.compile("[0-9]*");
StringBuffer code = new StringBuffer("693");
if(shopCode==null || shopCode.trim().length()!=5 || !pattern.matcher(shopCode).matches()){
return null;
}
if(productCode==null || productCode.trim().length()!=4 || !pattern.matcher(productCode).matches()){
return null;
}
code.append(shopCode).append(productCode);
//奇数位和;偶数位和
int sumA=0, sumB = 0;
for(int i=0; i<code.length(); i++){
int j = Integer.parseInt(code.substring(i, i+1));
if((i+1)%2==1){
sumA = sumA + j;
} else {
sumB = sumB + j;
}
}
code.append((10-((sumA+(sumB*3))%10))%10);
return code.toString();
}
/**
* 测试
* */
public static void main(String[] args) throws Exception {
String content = getEna13CodeContent("0003");
System.out.println("生成的条形码内容:"+content);
String codeImage = generateQrCode(300, content, "C:/Users/yvdedu.com/Desktop/IMGS/code/", false);
System.out.println("解析的条形码内容:"+decoder(codeImage));
}
}
2, 在 Servlet 中使用:
package code;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/code")
public class QrCodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
QrCode.generateQrCode(300, "http://www.baidu.com", response, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3, jQuery生成二维码:
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>生成二维码</title>
<!-- 二维码生成工具 -->
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery.min.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery.qrcode.min.js"></script>
</head>
<body>
<!-- 生成二维码方法: -->
<div id="qrcode"></div>
<script type="text/javascript">
jQuery("#qrcode").qrcode("Hellow jQuery QR_Code")
</script>
</body>
</html>
Java生成二维码就这么简单,推荐使用jQuery来生成二维码(比较简单);